Skip to content

fix(wechat): detect repeated iLink send rejection - #3299

Open
fico-hub wants to merge 9 commits into
makecindy:mainfrom
fico-hub:fix/issue-3285-wechat-ilink-rejection-health
Open

fix(wechat): detect repeated iLink send rejection#3299
fico-hub wants to merge 9 commits into
makecindy:mainfrom
fico-hub:fix/issue-3285-wechat-ilink-rejection-health

Conversation

@fico-hub

@fico-hub fico-hub commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

微信 iLink 在凭证仍看似有效、但发送端持续返回确定性拒绝时,原先会一直把消息留在重试队列,界面却仍显示已连接。本 PR 为发送失败增加稳定、无敏感信息的分类,并仅在同一绑定连续出现 3 次确定性拒绝时进入现有的 needs_reauth 状态;单次未知拒绝仍可重试,成功发送会重置计数。媒体上传仍参与鉴权失效判断;直接发送只在实际消息成功后清除证据,outbox 则只在同一 item 的文本和全部媒体都投递成功后统一清除,避免中间成功掩盖后续媒体拒绝。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护
  • 其他:

范围

UI 变化

不涉及:仅修改桌面主进程中的微信连接健康判断与协议错误分类,没有视觉、交互布局或文案改动。

  • 引用的设计规范:不涉及。

怎么验证的

自动验证

pnpm --filter @cindy/wechat-ilink test
结果:通过,25/25

pnpm --filter @cindy/wechat-ilink typecheck
结果:通过

pnpm --filter desktop exec vitest run src/main/im/wechat/__tests__/WechatIM.test.ts
结果:通过,33/33

pnpm --filter desktop typecheck
结果:通过

pnpm --filter desktop exec eslint src/main/im/wechat/WechatIM.ts src/main/im/wechat/__tests__/WechatIM.test.ts
结果:通过

git diff --check
结果:通过

pnpm test:unit:related
结果:WeChat 相关 workspace 通过;maker-core 的 Pi provenance 既有测试漂移导致 3 项失败。相同失败已在干净 PR base 148735f4 上用原测试文件完整复现,确认不由本 PR 引入。

手工验证

不涉及:问题需要 iLink 服务端拒绝态,已用 API client 与 WechatIM 单元测试覆盖。

未执行的验证

未执行真实微信账号的服务端拒绝复现,避免触碰真实绑定;使用确定性响应 fixture 验证。

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:

影响与回滚

  • 影响范围:仅微信 iLink 发送路径;显式认证失效立即进入 needs_reauth,其他确定性拒绝需在同一绑定 5 分钟内累计 3 次。
  • 回滚 / 降级方式:回滚本提交即可恢复原有的单次发送失败重试行为;待发送 outbox 记录不会被删除。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI 则跳过)
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档
  • 已确认测试结果或说明未执行原因

Signed-off-by: fico-hub <fico@xd.com>
@greptile-apps

greptile-apps Bot commented Aug 23, 2026

Copy link
Copy Markdown

Greptile Summary

本 PR 为微信 iLink 出站操作增加稳定错误分类和连续拒绝健康检测,在同一绑定五分钟内连续三次确定性拒绝后进入 needs_reauth

  • 文本发送、媒体上传和媒体发送统一经过发送健康检查
  • outbox 以整条记录完成作为清除拒绝证据的成功边界
  • epoch 停止、轮询和任务派发增加失效检查,避免旧连接覆盖重认证状态
  • 补充协议分类、直接发送、媒体发送、outbox 和生命周期竞态测试

Confidence Score: 5/5

当前没有仍需阻止合并的已确认故障,PR 看起来可以安全合并。

未发现仍然存在的阻塞性故障。

Important Files Changed

Filename Overview
apps/desktop/src/main/im/wechat/WechatIM.ts 增加按绑定和时间窗累计发送拒绝的健康状态,并将其接入直接发送、媒体、outbox 与 epoch 生命周期。
packages/wechat-ilink/src/apiClient.ts 将 iLink 发送拒绝分类为稳定的 SEND_REJECTED,并识别发送及上传响应中的 AUTH_REPLACED。
packages/wechat-ilink/src/errors.ts 扩展安全错误码联合类型以包含 SEND_REJECTED。
apps/desktop/src/main/im/wechat/tests/WechatIM.test.ts 覆盖拒绝阈值、成功重置、媒体与 outbox 成功边界,以及 epoch 失效后的状态和任务收口。
packages/wechat-ilink/src/tests/protocol.test.ts 覆盖文本、媒体及上传接口的新错误分类和 retryable 属性。

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[执行 iLink 发送或媒体上传] --> B{操作结果}
  B -->|成功| C{是否达到完整成功边界}
  C -->|是| D[清除当前 binding 的拒绝证据]
  C -->|否| E[保留拒绝证据]
  B -->|AUTH_EXPIRED 或 AUTH_REPLACED| F[立即进入 needs_reauth]
  B -->|SEND_REJECTED| G[记录当前 binding 的窗口内拒绝]
  G --> H{五分钟内累计三次?}
  H -->|否| I[保留重试路径]
  H -->|是| F
  F --> J[中止当前 epoch 并收口交互与活跃任务]
Loading

Reviews (9): Last reviewed commit: "fix(wechat): release lease when pump los..." | Re-trigger Greptile

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

Copy link
Copy Markdown

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: 3b3d192c6d

ℹ️ 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 thread apps/desktop/src/main/im/wechat/WechatIM.ts Outdated
@MagicLizi MagicLizi added awaiting-discussion 等待维护者讨论(review-pr) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) and removed awaiting-discussion 等待维护者讨论(review-pr) labels Aug 23, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

@fico-hub 👋 这个 PR 还有 1 条 review conversation 没 resolve(apps/desktop/src/main/im/wechat/WechatIM.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。

如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。

@MagicLizi

Copy link
Copy Markdown
Contributor

这条 PR 被维护者确认门拦住了(架构):@cindy/wechat-ilink 新增了导出错误码 SEND_REJECTED,并改变发送失败的处理语义,需要维护者确认后再合。

确认方式:维护者在本 PR 上 Approve;若要改,请 Request Changes,改完后再 Approve。
讨论 issue:#3303

Signed-off-by: fico-hub <fico@xd.com>

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

Copy link
Copy Markdown

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: 96e36d218c

ℹ️ 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 thread apps/desktop/src/main/im/wechat/WechatIM.ts Outdated
Comment thread apps/desktop/src/main/im/wechat/WechatIM.ts Outdated
@MagicLizi

Copy link
Copy Markdown
Contributor

@fico-hub 👋 这个 PR 还有 2 条 review conversation 没 resolve(apps/desktop/src/main/im/wechat/WechatIM.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。

如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。

Signed-off-by: fico-hub <fico@xd.com>

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

Copy link
Copy Markdown

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: 43450b15cb

ℹ️ 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 thread apps/desktop/src/main/im/wechat/WechatIM.ts
Signed-off-by: fico-hub <fico@xd.com>

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

Copy link
Copy Markdown

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: 4620a223c3

ℹ️ 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 thread packages/wechat-ilink/src/apiClient.ts
Signed-off-by: fico-hub <fico@xd.com>

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

Copy link
Copy Markdown

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: f2c434499e

ℹ️ 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 thread packages/wechat-ilink/src/apiClient.ts
Signed-off-by: fico-hub <fico@xd.com>

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

Copy link
Copy Markdown

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: b71baa97e6

ℹ️ 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 thread apps/desktop/src/main/im/wechat/WechatIM.ts
Signed-off-by: fico-hub <fico@xd.com>

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

Copy link
Copy Markdown

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: 1f41320ebd

ℹ️ 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 thread apps/desktop/src/main/im/wechat/WechatIM.ts
Signed-off-by: fico-hub <fico@xd.com>

@dashhuang dashhuang left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

发现一处需要先修的 P1 竞态:发送拒绝 abort 当前 epoch 后,#taskPump 可能正从 #pollBarrierleaseNextTask() 返回;这两个 await 后没有重新确认 binding/signal 仍属于当前 epoch,因此会继续为旧 binding 派发新的 Agent turn。现有清理发生时该任务尚未加入 #activeTasks,覆盖不到它。

请在 barrier 和 lease 返回后统一检查 current epoch;若 lease 已取得 task,则先 releaseDispatch 再退出,并补一条 abort × lease 的交错回归测试。修复前暂不 Approve。

After a send rejection aborts the current epoch, #taskPump can still be
awaiting the poll barrier or leaseNextTask(). When those resolve for the
dead binding the stale pump could dispatch an Agent turn that epoch cleanup
cannot cancel.

Re-check the send epoch after both awaits. Release any leased task before
returning so work is not lost, and cover the abort/lease interleaving with a
deterministic regression test.

Signed-off-by: fico-hub <fico@xd.com>
@fico-hub

Copy link
Copy Markdown
Contributor Author

@dashhuang 已在 0909f06 修复该 P1:#taskPump 在 poll barrier 与 leaseNextTask() 返回后统一重查当前 send epoch;若旧 epoch 已失效且已 lease 到任务,会先 releaseDispatch 再退出,避免为旧 binding 启动 Agent turn。新增 abort × lease 确定性交错回归,断言任务被释放且不发生 dispatch。

本机 qwen3.8-27b 验证:WechatIM 33/33、Desktop typecheck、targeted ESLint、DCO 与 git diff --check 均通过。pnpm test:unit:related 唯一红灯是 maker-core 的 3 个 Pi provenance 既有失败,已在干净 PR base 148735f 上原样复现,确认与本 PR 无关。

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

Copy link
Copy Markdown

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: 0909f06a4c

ℹ️ 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 +1057 to +1060
if (!this.#isSendEpochCurrent(binding.bindingEpoch, signal)) {
if (task) {
await this.#requireStore().releaseDispatch(task.bindingEpoch, task.id);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 在任务处理的异步边界后重新检查 epoch

leaseNextTask 返回后 epoch 仍有效、但 #processTask 中的命令或交互回复路径正在等待数据库操作时,并发的 outbox/直接发送可能触发第三次拒绝并中止 epoch;这里的检查已经通过,而这些路径尚未加入 #activeTasks,所以拒绝清理无法停止它们。随后 /new、权限命令等仍会修改会话并为已失效的 binding 提交回复,回复无法发送且会在重新认证清理旧 binding 时被删除;应在进入相关处理及其关键 await 后再次校验该任务仍属于当前 epoch,或让中止信号贯穿这些路径。

Useful? React with 👍 / 👎.

@MagicLizi

Copy link
Copy Markdown
Contributor

@fico-hub 👋 这个 PR 还有 1 条 review conversation 没 resolve(apps/desktop/src/main/im/wechat/WechatIM.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。

如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-discussion 等待维护者讨论(review-pr) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

微信 iLink 会话被静默失效,恢复需两次人工干预(重登 + 入站消息)——希望增加掉线检测与无人值守自愈能力

3 participants