Skip to content

fix(weixin): wait for gemini tool continuations#1946

Merged
piorpua merged 3 commits intoiOfficeAI:mainfrom
JerryLiu369:fix/weixin-gemini-tool-continuation
Mar 30, 2026
Merged

fix(weixin): wait for gemini tool continuations#1946
piorpua merged 3 commits intoiOfficeAI:mainfrom
JerryLiu369:fix/weixin-gemini-tool-continuation

Conversation

@JerryLiu369
Copy link
Copy Markdown
Member

Summary

  • keep channel streams open briefly when Gemini ends a turn on a tool status message
  • allow the follow-up Gemini continuation turn to deliver the final text back to WeChat
  • add a regression test for tool-call continuation timing

Testing

  • bunx vitest run tests/unit/channels/channelMessageService.test.ts tests/unit/channels/weixinPlugin.test.ts

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 30, 2026

Codecov Report

❌ Patch coverage is 73.91304% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...rc/process/channels/agent/ChannelMessageService.ts 73.91% 5 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72099cd0e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +134 to +136
stream.finishTimer = setTimeout(() => {
if (this.activeStreams.get(conversationId) === stream) {
this.resolveStream(conversationId, stream);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Settle superseded streams during continuation wait

When a finish arrives after a tool_group, this path defers resolution for 15s; if another message for the same conversation starts in that window, sendMessage replaces activeStreams with a new entry, and this guard skips resolving the old stream forever. That leaves the first sendMessage() promise permanently pending (no resolve/reject path), which can stall downstream cleanup in callers that still await it (for example, overlapping channel chats with supersede behavior).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@piorpua piorpua added the bot:reviewing Review in progress (mutex) label Mar 30, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 30, 2026

CI 检查未通过

以下 job 在本次自动化 review 时未通过,请修复:

Job 结论
Unit Tests (windows-2022) ❌ FAILURE

本次自动化 review 暂缓,待 CI 全部通过后将重新处理。

@piorpua piorpua removed the bot:reviewing Review in progress (mutex) label Mar 30, 2026
@piorpua piorpua added bot:reviewing Review in progress (mutex) and removed bot:reviewing Review in progress (mutex) labels Mar 30, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 30, 2026

Code Review:fix(weixin): wait for gemini tool continuations (#1946)

变更概述

本 PR 修复了 WeChat channel 与 Gemini agent 集成时的一个时序问题:当 Gemini 在 tool_group 消息后结束一轮对话(而非直接发送文字回复),由于流提前关闭,后续的 continuation turn(含最终文字回复)无法送达 WeChat。主要改动集中在 ChannelMessageService.ts,通过在 tool_group 类型的 finish 后引入 15 秒等待窗口来允许 continuation 到达。


方案评估

结论:✅ 方案合理

方案通过跟踪最后一个可见消息类型(lastVisibleMessageType)并在 tool-only finish 后设置延迟解析 timer,正确解决了 Gemini continuation 时序问题。逻辑清晰,与已有的 turnCount/finishCount 多轮追踪机制协调一致。当新的 start 事件到达时取消 timer 的设计是正确的;resolveStream 辅助方法统一了 timer 清理逻辑,避免了遗漏。无明显设计盲点,未引入过度复杂度。


问题清单

🔵 LOW — 缺少超时兜底路径的测试覆盖

文件src/process/channels/agent/ChannelMessageService.ts,第 134–138 行

问题代码

stream.finishTimer = setTimeout(() => {
  if (this.activeStreams.get(conversationId) === stream) {
    this.resolveStream(conversationId, stream);
  }
}, TOOL_CONTINUATION_WAIT_MS);

问题说明:Codecov 报告本次 patch 覆盖率为 73.91%(5 行 missing,1 行 partial)。核心场景——当 Gemini 确实在 tool_group 后不发送任何 continuation、15 秒 timer 触发兜底解析——未被任何测试覆盖。这是方案的重要回退路径,缺少测试意味着如果 timer 逻辑存在 bug(如 closure 引用错误)将无法被捕获。

修复建议:补充一个测试用例,验证超时兜底行为:

it('resolves via timeout when no continuation arrives after a tool-only finish', async () => {
  const service = new ChannelMessageService() as any;
  const resolve = vi.fn();
  const reject = vi.fn();

  service.activeStreams.set('conv-4', {
    msgId: 'msg-4',
    callback: vi.fn(),
    buffer: '',
    resolve,
    reject,
    turnCount: 0,
    finishCount: 0,
    lastVisibleMessageType: undefined,
    finishTimer: undefined,
  });

  service.handleAgentMessage({ conversation_id: 'conv-4', type: 'start', msg_id: 'msg-4', data: '' });
  service.handleAgentMessage({ conversation_id: 'conv-4', type: 'tool_group', msg_id: 'msg-4', data: [] });
  service.handleAgentMessage({ conversation_id: 'conv-4', type: 'finish', msg_id: 'msg-4', data: '' });

  expect(resolve).not.toHaveBeenCalled();

  await vi.advanceTimersByTimeAsync(15_000);

  expect(resolve).toHaveBeenCalledWith('msg-4');
});

🔵 LOW — TOOL_CONTINUATION_WAIT_MS = 15_000 对实时消息场景偏长

文件src/process/channels/agent/ChannelMessageService.ts,第 40 行

问题代码

const TOOL_CONTINUATION_WAIT_MS = 15_000;

问题说明:15 秒是较长的等待时间。若 Gemini 真的在 tool_group 后不发送任何 continuation(例如 tool 调用失败或 Gemini 确实以工具调用结束对话),WeChat 用户将面临 15 秒无响应,体验较差。PR 说明称其为 briefly,但 15 秒在实时消息场景中并不短暂。考虑是否可以根据实际 Gemini continuation 响应时间(通常在 1-3 秒内)适当缩短该值,或添加注释说明选择 15 秒的具体依据。


汇总

# 严重级别 文件 问题
1 🔵 LOW ChannelMessageService.ts:134-138 缺少超时兜底路径的测试覆盖
2 🔵 LOW ChannelMessageService.ts:40 15 秒等待常量对实时消息场景偏长

结论

批准合并 — 无阻塞性问题

方案设计正确,代码质量良好,主要测试场景覆盖到位。两个 LOW 级别问题均不阻塞合并,建议后续跟进补充超时兜底测试。


本报告由本地 pr-review skill 生成,包含完整项目上下文,无截断限制。

@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 30, 2026

✅ 已自动 review,无阻塞性问题,正在触发自动合并。

@piorpua piorpua merged commit b20f9c5 into iOfficeAI:main Mar 30, 2026
14 checks passed
@piorpua piorpua added bot:done Auto-merged by bot and removed bot:reviewing Review in progress (mutex) labels Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:done Auto-merged by bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants