v3.7.0 发布说明
本次 minor 版本带来两项面向体验与安全的能力:AI 卡片长任务进度块与 Gateway RPC 能力开关 / 白名单;同时完成多轮安全加固(SecretInput 环境变量读取收敛、出站媒体本机读取边界)、引用与 mention 上下文修复,以及一次全仓领域目录迁移与格式化收口。
Important
本版本抬高了最低宿主版本:插件现在依赖 OpenClaw 2026.8.1 起公开导出的 openclaw/plugin-sdk/secret-ref-readonly。宿主低于 2026.8.1 时插件会因缺少该 SDK 子路径而加载失败,请先升级 OpenClaw 宿主。
最新版本入口:latest.md
⚠️ 破坏性变更
- 最低宿主版本从
2026.7.1-2抬升到2026.8.1PR #609(by @soimy)为隔离clientSecret的env引用读取,改用 OpenClaw2026.8.1起公开导出的openclaw/plugin-sdk/secret-ref-readonly。- 同步更新
peerDependencies.openclaw、openclaw.compat.pluginApi、openclaw.install.minHostVersion、openclaw.build.openclawVersion与开发依赖中的openclaw,均为2026.8.1。 - 连带适配 2026.8 类型面:移除宿主已删除的
ChannelGroupAdapter.resolveGroupIntroHint(core 从未消费,属死代码);历史会话扫描改为读取 canonicaldelivery状态,并保留对未执行openclaw doctor --fix迁移的旧字段(origin/lastChannel/lastTo/lastAccountId)的运行时兼容读取,避免历史群 peer 恢复能力丢失。
✨ 功能与体验改进
1. AI 卡片长任务进度块
- 长任务期间在同一张卡片顶部保留可替换的进度块
PR #612(by @soimy)让卡片在创建之后到最终答案之间的静默期(最长可达数分钟)不再"看起来卡住":进度块展示当前阶段、已完成步数与已耗时,任务超过 10 秒才出现(若已有可关联的工具调用则立即出现),之后按 30 秒心跳刷新,并在最终答案提交前清除。- 隐私安全:进度文本只由归一化后的工具名派生,绝不渲染命令参数、工具输出、URL、token 或凭据。
- 所有退出路径都释放控制器:
ReplyStrategy新增幂等dispose(),入站 dispatch 在finally中调用,覆盖既不 finalize 也不 abort 的 ask-user 接管早退分支;修复前接管后进度定时器与事件订阅会永久存活,recall 失败时用户会看到一张永远刷新"⏳ 任务处理中"的卡片。 - 可配置:
cardTaskProgress(true强制开启 /false强制关闭 / 未设置默认开启,但cardStreamingMode显式为"off"时默认关闭);cardTaskProgressRefresh(heartbeat默认,出现时 1 次 + 每 30 秒 1 次;interval每个可关联工具事件都推送,由cardStreamInterval节流)。两个字段均已写入openclaw.plugin.json的默认账号与 named account 两处 schema 并附 UI hint,且不注入 JSON-Schema / Zod 默认值,以保证 named account 能正确继承渠道级设置。 - 架构边界:新增
src/platform/runtime-events.ts,把通用 runtime 事件面(类型、引用计数 fan-out、字段访问器、run correlator)从ack-reaction/抽到platform/,card/不再依赖 ack-reaction 私有模块;fan-out 逐个隔离监听器异常。 - 真机验证驱动的修正(宿主 OpenClaw 2026.9.2):工具事件 phase 实际为
start/update/result,计步改为匹配result(此前匹配"end"导致步数恒为 0);钉钉客户端对同一 markdown block 内的多行只刷新尾行,进度块因此收敛为单行单 block。 - 文档更新:
docs/user/features/ai-card.md、docs/user/reference/api-usage-and-cost.md、docs/user/reference/configuration.md。
2. Gateway RPC 能力开关与白名单
- docs / 主动发送 RPC 可显式关闭,并支持空间与目标白名单
PR #611(by @soimy)新增gatewayCapabilities配置,回应 ClawHub 安全审核(Issue #608)对gateway-docs-and-send-rpc的 finding,并在用户文档中说明其信任模型与所需钉钉权限。gatewayCapabilities.tools.docs/gatewayCapabilities.tools.proactiveSend:能力开关,默认true;关闭后dingtalk.docs.*与dingtalk-connector.docs.*别名的全部 RPC 统一拒绝,能力开关走 fast-path(先于 required 参数解析),缺参时返回结构化 deny 而非参数错误。gatewayCapabilities.docs.allowedSpaceIds:文档空间白名单(未配置不限制;配置后至少一项,[]会被 schema 直接拒绝,运行时按 fail-closed 全部拒绝)。gatewayCapabilities.send.allowedTargets:发送目标白名单,每项必须为user:*/group:*。- 多账号按子键(
tools/docs/send)与渠道级合并,账号级同子键优先,因此账号级只覆盖局部子键时渠道级限制仍然生效。 - 拒绝日志统一
[DingTalk][GatewayRPC][Denied]前缀,reason 为静态文案,不泄露凭证;status/probe不受影响。 - 文档更新:
docs/user/reference/gateway-rpc.md新增"能力开关与白名单"章节,security-policies.md与configuration.md同步补充。
🛠 安全与修复
-
SecretInput 环境变量读取收敛到单个已授权变量(
PR #609,by @soimy)- 不再把整个
process.env透传给宿主 SecretInput 解析器:env引用改为"归一化引用 → 只读路径授权(canResolveEnvSecretRefInReadOnlyPath)→ 仅读取process.env[ref.id]",与 OpenClaw 官方频道的实现形态对齐,消除suspicious.env_credential_access静态指纹。 - 未授权引用在发起任何钉钉网络请求之前本地失败,并区分"未授权"/"已授权但变量未设置或为空"/"provider source 不匹配"三类原因,避免误导排查方向;
file引用行为不变(显式传env: {})。 scripts/verify-runtime-package.mjs新增构建产物守卫:命中env: process.env形态即失败。
- 不再把整个
-
出站媒体先校验本机根目录再读取(
PR #610,by @soimy)- 配置
mediaLocalRoots后,仅当媒体路径的 realpath 位于允许目录内才直接读取主机文件,越界路径统一交由受控 runtime media bridge 处理。 - 修复符号链接绕过(realpath + 打开后二次校验、
O_NOFOLLOW)、语音源文件绕过边界的外泄路径(改为先按边界取字节写入插件自有临时文件再供 ffmpeg/ffprobe 读取)、插件自有临时媒体被根目录误拦的回归,并将文件系统根/视为无效条目。 - 文档新增"出站媒体主机读取边界
mediaLocalRoots"章节。
- 配置
-
引用正文从真实
repliedMsg报文形态恢复(PR #599,by @BenGuanRan)message-context-store未命中时(群聊引用他人消息、超 TTL、插件安装前的消息),改为从content.content提取文本正文、递归提取cardContent中的 TEXT 节点,并保留 legacycontent.text等形态兼容,修复引用上下文丢失。- 文档更新:
docs/user/features/message-types.md。
-
上下文保留结构化 mention ID(
PR #603,by @huyua9)message-context-store新增mentionUserIds,入站消息把顶层atUsers与 richTextatUserId合并去重后持久化;群聊GroupSystemPrompt增加脱敏后的mentionedDingtalkIds。- 明确不从文本显示名反推 ID,只保留 payload 可证实的原始钉钉 ID。
🧩 架构与工程
- 完成领域目录迁移并全仓格式化收口(
PR #613,by @soimy)format/format:check的 glob 由src/*.ts扩展为"src/**/*.ts",并覆盖openclaw.plugin.json、vitest.config.ts与"scripts/**/*.mjs";此前src/card/、src/messaging/、src/targeting/等子目录长期未纳入 oxfmt(全仓 47 个源文件不合规)。src/根级遗留的 46 个模块按架构文档迁入gateway/、targeting/、messaging/、card/、command/、platform/、shared/与既有ack-reaction/,src/channel.ts保持为唯一根级装配层;不改变运行时行为。- CI 新增
format:check门禁步骤,避免格式再次漂移;AGENTS.md/CLAUDE.md/docs/contributor/architecture.*.md等文档同步为现状。
🤝 鸣谢
本版本 feat(card) 长任务进度功能源自 PR #605(by @jznrhnn)。该 PR 在 feat/live-task-progress-card 分支上提交了可替换进度块的原始实现,并完成了基于真实钉钉客户端的初步部署验证;因开发时基于 fix/openclaw-2026.8-sdk-compat,后由 PR #612 改基到 main 并完成两轮评审修复与真机验证后发布。感谢 @jznrhnn 的原始设计与实现。
同时感谢:
发布页面:https://github.com/soimy/openclaw-channel-dingtalk/releases/tag/v3.7.0
Full Changelog: v3.6.11...v3.7.0