本项目遵循 Keep a Changelog 格式。
classifyFetchError— 网络错误分类:src/api/api.ts新增classifyFetchError工具函数,将 fetch 级错误分类为dns/tcp/tls/timeout/unknown。apiGetFetch与apiPostFetch在失败时输出结构化日志(type, description, code),便于排查网络问题。覆盖 ENOTFOUND、ECONNREFUSED、ETIMEDOUT、SSL/TLS、AbortError 等场景的完整测试。sendMessage返回值校验:sendMessage现在解析服务端返回的SendMessageResp(ret/errmsg),ret非零时抛错,避免消息发送静默失败。
SESSION_EXPIRED_ERRCODE→STALE_TOKEN_ERRCODE: 在src/api/session-guard.ts中重命名,更准确地描述 token 过期(-14 表示 token 失效,而非 session 过期)。monitor.ts与测试中所有引用同步更新。- 错误日志改进:
monitor.ts中getUpdates的错误日志使用classifyFetchError输出分类信息(type, description, code)。monitor.ts移除重复的errLog日志行,仅保留aLog.error。- CDN 上传失败日志(
cdn-upload.ts)增加脱敏 URL 和错误 cause 信息。 downloadRemoteImageToTemp(upload.ts)增加 fetch 网络错误详情日志。- API GET/POST fetch 失败日志(
api.ts)增加脱敏 URL、超时设置及错误分类信息。
- 最低宿主版本升级:
peerDependencies.openclaw和install.minHostVersion从>=2026.3.22升至>=2026.5.12。
outbound-hooks.test.ts: 新增测试文件,覆盖applyWeixinMessageSendingHook(无 hook、内容修改、取消、错误容错)和emitWeixinMessageSent(无 hook、成功、失败走 fire-and-forget)各场景。
pairing.test.tsmock 路径:vi.mock目标从"openclaw/plugin-sdk"修正为"openclaw/plugin-sdk/infra-runtime"。api.test.tssendMessage 测试 mock: 成功用例的 mock 返回值从""改为"{}",与sendMessage新增的响应解析逻辑一致。
- 工具调用进度消息: 模型执行 tool 时,发送
TOOL_CALL_START/TOOL_CALL_RESULT进度消息,可通过replyProgressMessages开关控制(默认开启)。 - 请求中断信号支持:
apiPostFetch/getUpdates现在接受外部的AbortSignal。当网关停止或热重载频道时,正在进行的 long-poll 请求会被立即取消,无需等待服务端超时。
iLink-App-Id/iLink-App-ClientVersion请求头在生产环境为空 /0。readPackageJson用固定的../../从import.meta.url推算package.json,但 TypeScript 构建(tsconfig.include同时包含index.ts和src/**/*.ts)实际产物是dist/src/api/api.js(多出一层src/),导致解析到不存在的dist/package.json,catch 返回{}。改为从当前模块所在目录向上逐级查找,并通过name包含openclaw-weixin或存在ilink_appid字段来确认是本插件自己的package.json,同时兼容开发态(src/api/)和发布态(dist/src/api/)布局。src/api/api.test.ts新增 5 个用例覆盖编译产物布局、开发布局、途经node_modules/<dep>/package.json不被误识别、找不到时返回{}、坏 JSON 容错继续向上查找。openclaw channels login在 "已连接过此 OpenClaw" 场景下被误判为失败。 服务端返回binded_redirect时本地凭据其实仍有效,但旧逻辑返回connected: false,channel.ts的auth.login据此throw,CLI 非零退出,导致openclaw-weixin-installer等自动化脚本误打印"首次连接未完成"。WeixinQrWaitResult新增alreadyConnected字段,QR 轮询在binded_redirect时置为true;auth.login据此仅记录消息、不抛错,CLI 以 0 退出。
- Node 24 / undici 兼容性——所有请求
TypeError: fetch failed。 从buildHeaders中移除手动设置的Content-Length。Node 24 自带的 undici 不允许调用方预设Content-Length,会以UND_ERR_INVALID_ARG: invalid content-length header拒绝整个请求,导致所有 CGI 调用失败。改由fetch根据请求体自动计算,恢复在 Node 24 下的网络调用。 - OpenClaw ≥ 2026.5.x——微信 runtime 初始化超时无限重启。 移除模块作用域的
pluginRuntime全局变量(同时删掉src/runtime.ts),改为按调用从网关 ctx 中读取ctx.channelRuntime。原先的全局是在插件注册阶段写入的,但较新宿主改为按调用注入 runtime surface,启动时拿不到/拿到旧值,channel 启动一直超时进而被反复重启。
- 冗余脚本与入口: 删除调试用的
scripts/test-full-upload.ts/scripts/test-upload-url.ts,以及遗留的index.ts转发文件。对调用方无行为变更。
- npm 包内携带 dist 产物作为 channel 入口:
package.json的files加入dist/,openclaw.runtimeExtensions设为["./dist/index.js"];宿主直接加载预编译的 JS 入口,不再依赖装包时的 TypeScript 源码,避免在较严格的宿主版本上出现requires compiled runtime output for TypeScript entry index.ts错误。 openclaw.plugin.json频道配置: 在openclaw.plugin.json中声明channels与channelConfigs,使较新宿主(≥ 2026.4.x)能直接渲染频道选择 UI,无需回退到package.json#openclaw。
bot_agent请求字段: 上行 CGI 现在携带由上层应用提供的bot_agent(类似 UA 的name/version (comment)语法,支持多个 product),按上层应用的 channel 配置传入;src/api/api.ts中的sanitizeBotAgent负责清洗与长度上限,缺失或不合法时回落为OpenClaw。- 扫码时上送
local_token_list:fetchQRCode现在带上本地最近 10 个bot_token,让服务端识别"已绑定到本端"的 bot 并下发binded_redirect,避免重复发会话。 - 配对码登录流程: 服务端要求二次校验时(
need_verifycode/verify_code_blocked),waitForWeixinLogin通过 stdin 提示用户输入verify_code并做有限次重试。 binded_redirect处理: QR 轮询新增分支,输出✅ 已连接过此 OpenClaw,无需重复连接。并优雅返回。- 连接状态通知(start/stop):
gateway.startAccount在 provider 注册后调用notifyStart,新增的gateway.stopAccounthook 调用notifyStop,便于上游微信服务端对账户在线状态进行对账。
- 扫码登录文案: 调整 QR / 扫码相关的提示文案;同时移除
fetchQRCode/startWeixinLoginWithQr的客户端超时,长轮询仅受服务端与网络栈限制。
- 连接状态通知(start/stop)首次引入: 账号启动时发送
notifyStart,关闭时通过新的gateway.stopAccounthook 发送notifyStop。该能力在后续 2.3.x 中保留。
- 外发 hook 支持: 为所有外发路径(
sendText、sendMedia、process-message中的入站回复deliver)接入message_sending(发送前拦截/修改)和message_sent(发送后通知)hook。hook 逻辑抽取至共享模块src/messaging/outbound-hooks.ts。
- 清理: 移除
sendWeixinOutbound签名中未使用的mediaUrl参数。
- Markdown 过滤器:
StreamingMarkdownFilter放开了更多 Markdown 格式的保留。
- 插件注册重入:
channel.ts中将monitorWeixinProvider改为在startAccount内部懒加载(await import(...)),避免插件注册阶段提前拉取 monitor → process-message → command-auth 依赖链,导致 plugin/provider registry 重入。 - 初始化副作用:
process-message.ts中将resolveSenderCommandAuthorizationWithRuntime/resolveDirectDmAuthorizationOutcome改为懒加载,避免模块初始化时触发宿主的ensureContextWindowCacheLoaded副作用,进而导致loadOpenClawPlugins重入。
- tool-call 外发路径:
sendWeixinOutbound现在对发送文本应用StreamingMarkdownFilter,与process-message中的 model-output 路径保持一致。
- 扫码登录: 移除
get_bot_qrcode的客户端超时,请求不再因固定时限被 abort(仍受服务端与网络栈限制)。
StreamingMarkdownFilter(src/messaging/markdown-filter.ts):外发文本由原先markdownToPlainText整段剥离 Markdown,改为流式逐字符过滤;对 Markdown 从完全不支持变为部分支持。
- 外发文本:
process-message在每次deliver时用StreamingMarkdownFilter(feed/flush)处理回复,替代markdownToPlainText。
- 从
src/messaging/send.ts删除markdownToPlainText(相关用例从send.test.ts迁至markdown-filter.test.ts)。
- 登录后配置刷新: 每次微信登录成功后,在
openclaw.json中更新channels.openclaw-weixin.channelConfigUpdatedAt(ISO 8601),让网关从磁盘重新加载配置;不再写入空的accounts: {}占位。 - 扫码登录:
get_bot_qrcode客户端超时由 5s 调整为 10s。 - 文档: 卸载说明改为使用
openclaw plugins uninstall @tencent-weixin/openclaw-weixin,与插件 CLI 一致。 - 日志:
debug-check日志不再输出stateDir/OPENCLAW_STATE_DIR。
openclaw-weixin子命令(删除src/weixin-cli.ts及index.ts中的注册)。请使用宿主自带的openclaw plugins uninstall …卸载流程。
- 解决在 OpenClaw 2026.3.31 及更新版本上安装插件时出现的 dangerous code pattern 提示(宿主插件安装 / 静态检查)。