feat: 接入微信 ClawBot IM - #44
LIghtJUNction wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fbd6f3c47c
ℹ️ 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".
| if !input.IsActive && s.revokeOwner != nil { | ||
| if err := s.revokeOwner(ctx, userID); err != nil { | ||
| return common.User{}, err | ||
| } | ||
| } |
There was a problem hiding this comment.
Serialize IM revocation with user deactivation
When a user starts a new ClawBot login after revokeOwner returns but before the subsequent user update commits, the login still sees an active owner and can eventually persist a new account/runtime after the user has been disabled. This leaves the supposedly revoked credentials and worker attached to an inactive account; coordinate the state change and revocation under the same owner-level operation, or perform a final revocation after the inactive update succeeds.
Useful? React with 👍 / 👎.
| if item.Type == 1 && item.Text != nil { | ||
| textItems++ | ||
| text = item.Text.Text |
There was a problem hiding this comment.
Reject incomplete ClawBot text items
When iLink returns a finished message whose text item has is_completed: false, this condition still accepts the item because IsCompleted is never checked, and a normal text value can consequently complete the selected ChatAPI turn with partial content. Require the sole text item to have IsCompleted set before exposing its text to the coordinator.
Useful? React with 👍 / 👎.
| current := s.logins[sessionID] | ||
| if current == nil || current.ownerID != ownerID || current.generation != generation || s.loginGen[ownerID] != generation { | ||
| s.mu.Unlock() | ||
| return LoginView{}, ErrLoginNotFound |
There was a problem hiding this comment.
Recheck login expiry after the long poll
When a poll starts just before challenge.ExpiresAt, provider.PollLogin can remain in flight for up to 38 seconds and return a confirmed account after the five-minute session has expired. The completion path only validates the session generation here, so it persists that late confirmation; include the current challenge expiry in the post-poll validation before accepting the account.
Useful? React with 👍 / 👎.
变更内容
可扩展 IM 层
internal/service/im.Provider契约与 coordinator,Provider 负责登录、长轮询、发送和私有状态;coordinator 负责账号生命周期、owner 鉴权、pending 选择、通知合并和 turn controlturn.waitingobserver 不阻塞请求线程;按 owner 合并最新通知,发送前再次校验 authoritativePendingRegistry微信 ClawBot Provider
notifystart/notifystop、getupdates长轮询和文本发送ret/errcode == -14标记需要重新扫码;sendmessage -2在 runtime barrier 内标记发送所用 generation 为失效,cursor-only checkpoint 不会误恢复,只有更新的入站 context generation 才重新可用;网络错误采用有界退避weixin.qq.comHTTPS 域,拒绝 userinfo、非默认端口、path/query/fragment 和 hostname 边界绕过;生产 client 使用 fail-closed SafeDialer 拒绝私网/混合 DNS 且不跟随 HTTP 3xx;限制 HTTP body、二维码、cursor/context 和文本大小操作员工作流
/list:查看实时 pending 列表/use <编号>:切换请求/abort [原因]:中止请求/bind、/help:刷新绑定/查看帮助control.SourceIM,IM 手动操作继续参与 automation recorder 的人工录制语义配置与 UI
secretbox+CHATAPI_MASTER_KEY加密后存入独立 user config;秘密不进入日志、状态或 HTTP 响应;二维码请求只携带当前 owner 的 local tokenbackend/docs/im-clawbot-design.md说明一致性、安全边界、恢复行为和多副本限制首版语义说明
该接入把微信作为 ChatAPI 操作员端:ChatAPI 请求推送到扫码者本人,微信回复控制已有 turn。它不会把微信联系人消息转换成新的模型请求。
验证
go test ./...go test -race ./internal/service/im/...httptest:headers、QR 状态、redirect、notify start/stop、updates/send、超大响应、stale token、SSRF/URL 边界npm test(11 tests)npm run lintnpm run build官方协议参考