feat(weixin): support channel file send protocol#1993
feat(weixin): support channel file send protocol#1993piorpua merged 7 commits intoiOfficeAI:mainfrom
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0b8d044803
ℹ️ 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 (workspace && !isPathInsideWorkspace(resolvedPath, workspace) && resolvedPath !== path.resolve(workspace)) { | ||
| continue; |
There was a problem hiding this comment.
Canonicalize media path before workspace boundary check
The workspace restriction currently relies on lexical path comparison, so a symlink inside the workspace can bypass it. For example, if workspace/leak points to /etc/passwd, isPathInsideWorkspace still passes and statSync follows the symlink, allowing files outside the workspace to be sent. This is a data-exfiltration risk for channel conversations; resolve the candidate with realpath (or reject symlinks with lstat) before enforcing the workspace boundary.
Useful? React with 👍 / 👎.
| const fileData = fs.readFileSync(action.path); | ||
| if (fileData.length > UPLOADS_MAX_BYTES) { | ||
| throw new Error(`file too large: ${fileData.length}`); |
There was a problem hiding this comment.
Enforce upload size limit before reading file into memory
uploadMediaAction reads the whole file with fs.readFileSync and only then checks UPLOADS_MAX_BYTES. If a media action points to a very large file, the process can consume excessive memory (or OOM) before the guard runs. This can be triggered by model output paths in normal channel flows, so the size should be validated via stat (or a bounded stream) before reading file contents.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd6b2a476f
ℹ️ 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".
| await callSendMediaMessage(baseUrl, token, wechatUin, conversationId, uploaded, msg.context_token); | ||
| } catch (sendErr) { | ||
| const failedName = mediaAction.fileName || path.basename(mediaAction.path); | ||
| fallbackNotices.push(`Failed to send ${failedName}`); |
There was a problem hiding this comment.
Localize media-send failure notice
When a media upload/send fails, this hardcoded English fallback is appended to the user-visible reply (Failed to send ...). /workspace/AionUi/AGENTS.md explicitly requires that all user-facing text use i18n keys, so this introduces a non-localized runtime message that will leak English text to non-English chats whenever file delivery fails.
Useful? React with 👍 / 👎.
| const resolvedPath = path.isAbsolute(action.path) | ||
| ? path.resolve(action.path) | ||
| : workspace | ||
| ? path.resolve(workspace, action.path) | ||
| : ''; |
There was a problem hiding this comment.
Reject protocol paths when conversation workspace is missing
If getConversation(conversationId) fails (for example, stale/deleted conversation records or transient DB read failures), workspace becomes undefined, but absolute protocol paths are still accepted and only checked for existence/size. In that state, a model-emitted block like /etc/passwd bypasses workspace confinement entirely and can be uploaded to chat; this code should fail closed unless a valid workspace root is available.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eee9eee910
ℹ️ 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 (!resolvedPath) continue; | ||
| if (!existsSync(resolvedPath)) continue; | ||
|
|
There was a problem hiding this comment.
Emit failure notice when protocol actions are discarded
This branch silently drops unresolved protocol actions (continue) before they reach the upload loop, but no fallback text is generated for those drops. In the common “file-only” skill output (no visible text, only [AIONUI_CHANNEL_SEND]), an invalid/missing/out-of-workspace path results in mediaActions becoming empty and response.text staying empty, so WeixinMonitor sends nothing at all (its fallback notices are only added inside the upload/send catch path). This makes user requests appear to be ignored instead of reporting a failed send.
Useful? React with 👍 / 👎.
Code Review:feat(weixin): support channel file send protocol (#1993)变更概述本 PR 为微信渠道新增文件/图片发送能力。核心改动包括:(1) 新增 方案评估结论:✅ 方案合理 方案整体设计清晰:通过 skill 文件引导 AI 在回复中嵌入结构化协议块,由 问题清单🟡 MEDIUM —
|
| # | 严重级别 | 文件 | 问题 |
|---|---|---|---|
| 1 | 🟡 MEDIUM | channelSendProtocol.ts:105-109 |
statSync 重复调用,可复用 lstatSync 结果 |
| 2 | 🟡 MEDIUM | WeixinMonitor.ts:390 |
同步读取大文件阻塞事件循环 |
| 3 | 🔵 LOW | channelSendProtocol.ts:12 |
模块级 /g 正则潜在状态问题(当前安全) |
| 4 | 🔵 LOW | WeixinMonitor.ts |
Patch 覆盖率偏低,上传逻辑测试不足 |
结论
本报告由本地 pr-review skill 生成,包含完整项目上下文,无截断限制。
CONCLUSION: CONDITIONAL
IS_CRITICAL_PATH: false
CRITICAL_PATH_FILES: (none)
PR_NUMBER: 1993
- Reuse lstatSync result instead of redundant statSync call in channelSendProtocol - Replace sync readFileSync with async fs.promises.readFile in WeixinMonitor Review follow-up for iOfficeAI#1993
PR Fix 验证报告原始 PR: #1993
总结: ✅ 已修复 2 个 | ❌ 未能修复 0 个
|
* feat(weixin): support channel file send protocol * fix(weixin): align media upload with openclaw * fix(weixin): align media send ordering * fix(weixin): broaden file send skill triggers * fix(weixin): simplify file send skill description * fix(weixin): harden channel file send * fix(weixin): address review issues from PR iOfficeAI#1993 - Reuse lstatSync result instead of redundant statSync call in channelSendProtocol - Replace sync readFileSync with async fs.promises.readFile in WeixinMonitor Review follow-up for iOfficeAI#1993 --------- Co-authored-by: zynx <>
Summary
Test plan