Skip to content

feat(localagent): 统一消息反馈、回传与平台入站授权 - #1476

Merged
haofeng0705 merged 39 commits into
mainfrom
codex/localagent-message-status
Oct 15, 2026
Merged

haofeng0705 merged 39 commits into
mainfrom
codex/localagent-message-status

Conversation

@haofeng0705

@haofeng0705 haofeng0705 commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

问题与结果

Fixes #1475

统一本地数字员工的消息反馈、引用与图片输入、chat 回传、A2UI 摘要和平台入站授权。平台保证 local_agent 私聊可见即可聊;撤销可见范围后,已有私聊也停止投递;群聊按原生 @ 触发,切换员工类型会停止原绑定投递并要求重新绑定。因此本地取消每条消息重复查询 published 详情、通讯录和部门,避免额外接口故障阻断正常对话。

实现

  • 原消息反馈区分排队、思考、完成、失败和送达待确认;执行结果与投递结果独立记录。引用正文结构化传给模型,图片以员工 Profile 下载并限制数量、格式、大小及准备时间。
  • 回传统一使用 chat +messages-reply / +messages-send,使用受限 stdin、绑定上下文、幂等键和等待回执;保留已发布的 channel reply / operator-private 兼容入口,新宿主使用通用 chat。A2UI 支持 --summary。Codex 保留会话、权限与工作目录,恢复失败不自动创建新会话。
  • 正式 bind_local_agent 回执确定 platform 入站策略;其他通道为 local_allowlist。channel binding 在启动时返回明确策略,channel capabilities 声明 bindingAccessPolicy=true。删除 sender 参数及旧逐消息 visibility 协商,平台路径仅订阅单聊和原生群 @。
  • 删除仅服务于 visibility 的主管身份迁移和启动阻断。新绑定不再写 supervisorProfile,历史字段仅兼容读取;管理操作仍使用当前主管登录身份,审批仍使用固定 operatorOpenDingTalkId。
  • 自消息过滤独立保留:优先读取与当前绑定一致的本地员工自身 ID;旧 DSH 配置缺少该 ID 时,仅在启动阶段以员工自身精确 Profile 查询自己一次。身份错误或歧义拒绝启动,不借用主管,不改写绑定。
  • 绑定身份、代数、状态、未完成服务端操作、lease、群 @、去重与审计门禁保留。私有 lease 正常释放返回统一成功结果,避免释放成功却报内部错误。
  • 回执只对结构化 1001,或 PARAM_ERROR 且详情精确为“消息不存在”重查原任务;间隔 250ms,最多 8 次,查询与等待共享 2 秒预算。超时返回 delivery_unknown,不重发正文或重跑模型。

DWS #1479、#1480 已整合到本分支。配套 dsh-dingtalk #29,基于已合并的插件 #28;两侧需配套升级。

本次 CI 修复

  • 当前修复 head:1e33e03e24035072459e1e53cfa8bbfd93e78842,已合并 main 794e7a376892dea7423edca824d832336badb05c。
  • 修复原运行 38506662050 的三项失败:更新过期合并快照;恢复已发布的 Channel 兼容入口及能力字段;补齐取消、绑定重读、stdin 失败和发送前重验的跨平台覆盖测试。新宿主仍使用通用 chat,兼容入口使用相同的有界回执实现。
  • 修正更新片段 category: Fixed;修复 Windows 路径 JSON 解析、平台权限断言、原生子进程参数夹具和导出路径逃逸模拟。修复 Windows Markdown 盘符/file URI 识别,为内嵌 A2UI JSON 固定 LF,保留原始字节摘要校验。
  • 27d51a429e5dc7d9f68fb532ab473812c77cc4be 的运行 38711691277 已通过 Windows 原生 Test/Coverage、macOS Test/Coverage 及其余八项主线检查;最后剩余 helpers race 因整包累计耗尽 12m 失败,随后 fail-fast 取消尚未完成的测试。日志没有数据竞争报警;命令矩阵及两个 GIF 压缩测试累计耗时约 8m46s。
  • 本次将 helpers 在 focused/full race 两条路径的包超时调整为现有 cli/smoke 使用的 18m,并更新 workflow 契约断言。job 总预算仍为 25m;全部测试选择、断言、race 检测、100% 增量覆盖率、兼容审批清单和九项 required checks 均保留。
精确验证范围 结果
当前 head 的 workflow、分片计划、fail-fast、覆盖率工作流及 GitHub Script 语法契约 通过,go test ./test/scripts -run 'Test(GitHubScriptWorkflowJavaScriptParses|CoverageWorkflow|CIAppRace|CIFailFastTripwires|CITestPackagePlan|ChangelogPRFastPathWorkflowContract)' -count=1
27d51a429 的完整本地平台覆盖率 通过,673 条变更可执行语句,100.0000%;当前提交仅改 workflow 和对应测试
27d51a429 的 Windows 原生及 macOS 检查 上述远端运行对应 job 已通过;不以此冒充当前 head 的完整准入
当前 head 的 helpers 全包 race 本机执行 go test -race -count=1 -timeout=18m ./internal/helpers;最终远端准入以本次 push 后的完整运行及精确 head 为准
当前 head 的九项主线准入 等待本次 push 后的完整运行;已取消的旧分片不视为通过

既有验证(对应下述历史提交)

最终 DWS 提交:a3c7d486c983da624404b999360235b13a88e388;插件提交:67b3fb870b5d07774a43742aceed8a2abc8ef9d2。

检查 结果
go test ./internal/helpers -count=1 通过,166.670s
go test -race ./internal/helpers ./internal/app -run 'TestCrossPlatformCoverage(Employee|DigitalEmployee|DingTalkTagConnect)' -count=1 通过
check-generated-drift.sh 生成一致性和 Schema 装配确定性通过;protobuf 工具依赖检查因未安装 libprotoc 35.1 跳过
check-schema-catalog.sh 通过,32 products / 1497 tools;包含 cli、homology、helpers、app 的契约检查
go test ./internal/auth -run '^TestCrossPlatformCoverageAcquireDualLock' -count=1 通过;已将 Windows 关闭句柄断言改为跨平台重复 Close 检查
Windows amd64 auth 测试包 交叉编译通过;Windows 执行以远端 CI 为准
最终 DWS binary + 插件 pnpm run ci 387 pass / 0 fail / 0 skip;secrets、lint、typecheck、pack 通过
差异与独立代码审查 git diff --check 通过;未发现阻断项

最终二进制为本提交独立构建;本地 Mac arm64 / SDK 15.4。联合回归实际执行 DWS CLI,验证旧受管绑定缺主管字段可获取/释放 lease、连续私聊与群 @ 不逐条查询、主管字段不提升非受管权限、自消息过滤、绑定不变、1001 回执恢复及故障通知。事件投递和 IM 接口使用受控夹具,未发送真实消息。

首次本地编译受默认 SDK 链接环境影响,固定 SDK 后通过;旧成功用例补齐自身 ID 夹具后 helpers 全包通过。Schema 首次测试因仓库内临时输出被隔离规则拒绝,调整至 worktree 旁的专用运行目录后通过。没有修改门禁或跳过失败断言。

平台关于撤权与类型切换停止投递的语义由平台方确认;本地测试不冒充服务端授权验证。此次新组合尚未替换既有真实员工运行入口或之前交付的固定测试包,未发布正式版本。

风险与回滚

涉及入站授权策略与机器协议。新版插件拒绝旧能力、未知策略和错误身份,不默认放行;非受管场景继续白名单。平台类型变更必须停止原绑定投递并重新绑定,不能把本地历史 ID 当成新的绑定。停止、换绑与回复的校验继续保留。

回滚前正常停止员工,保留 Profile、会话、账本及审计,再配套回退两端。已有 supervisorProfile 的历史绑定不应直接交给拒绝未知字段的旧版读取;不要手改绑定或恢复过期代数。远端 CI 与精确 SHA 的主线准入仍按仓库门禁执行。

@haofeng0705 haofeng0705 added the ai-generated Pull request contains AI-generated code and must pass AI behavior policy label Oct 9, 2026
@github-actions
github-actions Bot requested a review from wxianfeng October 9, 2026 06:20
@github-actions
github-actions Bot requested a review from typefield October 9, 2026 06:20
@haofeng0705 haofeng0705 changed the title fix(localagent): 增加数字员工原消息处理状态反馈 fix(localagent): 完善消息反馈、引用与图片输入 Oct 9, 2026
@haofeng0705 haofeng0705 changed the title fix(localagent): 完善消息反馈、引用与图片输入 feat(dingtalk-tag): 统一数字员工消息反馈、回传与可见范围授权 Oct 10, 2026
@haofeng0705 haofeng0705 removed the ai-generated Pull request contains AI-generated code and must pass AI behavior policy label Oct 13, 2026
@haofeng0705 haofeng0705 changed the title feat(dingtalk-tag): 统一数字员工消息反馈、回传与可见范围授权 feat(localagent): 统一消息反馈、回传与平台入站授权 Oct 13, 2026
@github-actions
github-actions Bot disabled auto-merge October 15, 2026 09:51
@haofeng0705
haofeng0705 merged commit 9795ccb into main Oct 15, 2026
60 checks passed
@haofeng0705
haofeng0705 deleted the codex/localagent-message-status branch October 15, 2026 12:00
@siyideng0331-haoxiao

Copy link
Copy Markdown
Contributor

补充 CR 与实包验证结果:本轮完整验证收口于 27d51a429e5dc7d9f68fb532ab473812c77cc4be,对照 main 794e7a376892dea7423edca824d832336badb05c。发布评论前确认 PR 已合并,最终 head 为 1e33e03e24035072459e1e53cfa8bbfd93e78842;两者增量仅涉及 CI 工作流和门禁测试,下面两处实现未变。以下是合并后的补充反馈,不代表对最终 head 重新执行了整套实测。

仍需跟进的两个 P2

1. [P2] custom 空输出绕过 no-reply 分支,仍发送占位文本并标记完成

deap_agent_runtime.go:373–377 只判断 strings.TrimSpace(answer) == "",但 custom 的 execForwarder 已把正常退出且无 stdout 转成 (本地 agent 无文本输出),导致此分支无法命中。

实际复现:custom 脚本收到指定测试文本后 exit 0,不写 stdout。main 和 PR 原生包都发出了上述占位文本;27d51a429 的真实 IM 回读还确认原消息被标记“已完成”,没有达到 PR 声明的“仅贴收到、不发占位正文”。建议让执行层显式表达 no-reply,或在员工适配层统一处理,并补一条真实 custom 子进程回归;仅使用返回空串的 forwarder 替身不足以覆盖该问题。

2. [P2] 终态反馈共享 5 秒预算,失败后直接退出,缺少运行期收敛

deap_agent_feedback.go:144–152 给整个 remove/create/add 投影链共用 5 秒截止时间,apply 返回错误时仍因 terminal 直接退出,删除该反馈 worker。

无网络探针可稳定复现:先持有“思考中”,令 remove/create/add 分别耗时 2 秒;约 5.015 秒后 add 被截止,账本留下 desired=已完成,status=failed,反馈 worker 数量归零。业务回合已经结束,后续没有运行期重试;重启恢复仍使用相同预算。

真实链路中,首轮 7 条消息的终态账本 failed,经后续三次恢复验证(含收口包)仍未收敛,正文和 Agent 均未重复执行。收口包新增两条消息可以正常 applied,因此并非反馈必然失败。部分 failed 记录对应的表情实际已被服务端接受,不能把 failed 视为“确定未写入”。建议增加独立于正文发送的有界异步恢复,保留结果未知语义。真实请求的逐步骤耗时未暴露,不能断言这 7 次失败全部由探针中的同一个原因造成。

实包与基线对照

macOS arm64 上实际执行 make build,附带原生 runtime payload 并签名。测试组织专用员工累计进行了 16 条真实钉钉消息往返,使用可控 custom 执行器;测试进程已停止。

场景 main PR 实包
执行器 exit 7 无回复提示 正确回复“本次处理失败,请稍后重试。”;收口包原消息有“处理失败”反馈
exit 0、无 stdout 发送占位文本 仍发送占位文本,并标记“已完成”
引用消息 执行器缺少引用正文 收到结构化引用正文
图片 仅收到 mediaId 文本 下载为本地附件,执行器确认可读,回合后清理
1001 后回执可见 首次查询即失败 再次查询后成功,正文仅发送一次
持续 1001 首次查询即失败 最多查询 8 次后返回 delivery_unknown,正文不重发

引用与图片在 33817f27f 实包执行,后续增量已审阅;空输出、失败回传和 1001 对照补测至 27d51a429。1001 使用真实二进制连接本机合成 MCP 注入故障,不是宣称在线上稳定触发了 1001。

验证结果:27d51a429 四个相关包的 252 个顶层测试通过(含子测试共 1117 个 pass 记录),0 fail;首轮 33817f27f 的定向 race 检查也通过。发布片段格式、Windows 路径夹具等历史问题已由后续提交修复,不再列作当前发现。实测覆盖消息、执行、回传与清理边界,未覆盖真模型回答质量、DSH 配套全链路及所有客户端画面。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 数字员工 localagent 增加原消息处理状态反馈

2 participants