fix(goal): close human command surface gaps

This commit is contained in:
Tianyi Cui
2026-07-20 12:11:06 +08:00
parent 79d41dfaa9
commit 491dafc785
12 changed files with 47 additions and 28 deletions
@@ -14,7 +14,7 @@ Status: implemented
位于 `packages/goal/command-goal/` 的 `@deepseek-ai/dsh-command-goal` 是构建在 `ctx.commands` 与 `ctx.goals` 之上的命令生产方。它为 TUI 和 ACP 表面注册一个全局 `goal` 定义。处理器从命令分发接收准确的目标 agent(智能体),通过领域服务读取或改变该 agent 的目标,并返回直接的纯文本 UI 输出。它不导入任何适配器或具体 agent loop(智能体循环)。
该命令遵循[官方开发者命令参考](https://learn.chatgpt.com/docs/developer-commands?surface=cli)所记录的当前 Codex 紧凑形态:无参数状态查询、自由形式目标描述,以及 `clear`、`edit`、`pause` 或 `resume` 控制。本仓库保留自身的事件溯源状态、回合计数策略与恢复后激活规则,而不复制 Codex 的 SQLite、token 预算或自动恢复行为。
该命令遵循 [OpenAI Codex 公共仓库 `678157a` 提交中的 TUI 分发实现](https://github.com/openai/codex/blob/678157acaa819d5510adfe359abb5d0392cfe461/codex-rs/tui/src/chatwidget/slash_dispatch.rs#L750-L805)所呈现的紧凑形态:无参数状态查询、自由形式目标描述,以及 `clear`、`edit`、`pause` 或 `resume` 控制。固定到提交的链接使调研所得语法在 Codex 后续演进时仍可核验。本仓库保留自身的事件溯源状态、回合计数策略与恢复后激活规则,而不复制 Codex 的 SQLite、token 预算或自动恢复行为。
### 语法与生命周期动词
@@ -30,9 +30,9 @@ Status: implemented
### 输出与失败边界
状态输出省略品牌化 id 与比较并交换修订号,因为它们属于模型/插件协调细节,而不是人类控制项。输出包含激活态,因为该事实会改变工作是否继续。命令提示从准确状态派生:已激活的活跃目标提供暂停,未激活的活跃目标或可恢复的停止目标提供恢复,受预算限制和已完成状态不会宣传非法的恢复操作。
状态输出省略品牌化 id 与比较并交换修订号,因为它们属于模型/插件协调细节,而不是人类控制项。输出包含激活态,因为该事实会改变工作是否继续。命令提示从准确状态派生:已激活的活跃目标提供暂停,未激活的活跃目标或可恢复的停止目标提供恢复,受预算限制的目标说明 agent 必须先提高 `maxGoalRounds` 才能恢复,已完成目标则提供替换或清除。
预期的 `GoalError` 失败会变为 `CommandResult.error`,因此非法人类操作会收到稳定的直接响应,且绝不会进入模型历史。其他异常仍是适配器可见的命令失败;若把程序缺陷当成普通领域错误,就会隐藏问题。命令处理器只执行同步领域变更,因此请求取消会在变更开始前由命令注册表决定,不存在需要回滚的外逸异步副作用。
预期的 `GoalError` 失败会变为一个稳定且不含品牌化 id 的 `CommandResult.error`,使领域诊断不会向人类表面泄露比较并交换内部细节,非法操作也绝不会进入模型历史。当前状态负责提供针对具体状态且可执行的恢复路径。其他异常仍是适配器可见的命令失败;若把程序缺陷当成普通领域错误,就会隐藏问题。命令处理器只执行同步领域变更,因此请求取消会在变更开始前由命令注册表决定,不存在需要回滚的外逸异步副作用。
通用斜杠输入、状态文本与错误不会持久化。成功的目标变更使用现有 `Agent.inject()` 路径,产出持久化本就拥有的原始模型可见目标快照或清除墓碑。因此该命令不会改变会话格式,也不会引入可能与领域事件不一致的第二份审计记录。
@@ -40,11 +40,11 @@ Status: implemented
`agent-spine-demo` 接受可选的 `goals` 组合对象,其中包含目标领域与模型工具的所有者配置。省略或设为 `false` 时不会挂载该栈。对无头单次调用方而言,明确选择加入非常重要:它们的结果 API 会在一个相关物理轮次后结束,不能静默变成长时间运行的逻辑目标操作。
终端和 ACP 应用包作出相反的产品选择。它们默认让 `goals` 使用所有者默认值,挂载目标领域、模型工具、同会话驱动器、命令注册表与本生产方,并接受 `goals: false` 作为一致的整体退出选项。随后,TUI 与 ACP 桥通过通用注册表发现同一个定义。行式 stdio 模式不消费命令平面;在那里输入的 `/goal` 仍是普通人类提示词,模型可以通过独立授权的目标工具解释它。
交互式应用包作出相反的产品选择。ACP 默认让 `goals` 使用所有者默认值,并挂载目标领域、模型工具、同会话驱动器、命令注册表与本生产方。终端应用默认启用相同目标栈,但只在 TUI 模式挂载本生产方;行式 stdio 不消费命令平面,因此在那里输入的 `/goal` 仍是普通人类提示词,模型可以通过独立授权的目标工具解释它。两个应用都接受 `goals: false` 作为一致的整体退出选项。Python SDK 运行时闭包把本生产方与 ACP、命令及目标栈一并交付,使外部 `cordis.yml` 能组合相同命令表面。
## 测试
生产方测试套件使用真实命令注册表、目标服务、agent 注册表与会话日志。它覆盖 Loader 安全导出、两个表面的发现、资源释放、空状态、目标描述解析、拒绝未完成目标替换、行内编辑、已完成目标替换、所有缺失状态控制、暂停/恢复/清除、每个持久阶段、已激活/未激活展示、回合预算展示、预期领域错误、意外失败与持久变更记录。应用组合测试覆盖显式主干选择加入、终端/ACP 默认值、一致退出、转发的领域/工具配置、命令发现与扩展后的模型工具组装。无密钥 ACP 快照固定了交付应用组合中的 `/goal` 发现元数据和目标工具 schema。
生产方测试套件使用真实命令注册表、目标服务、agent 注册表与会话日志。它覆盖 Loader 安全导出、两个表面的发现、资源释放、空状态、目标描述解析、拒绝未完成目标替换、行内编辑、已完成目标替换、所有缺失状态控制、暂停/恢复/清除、每个持久阶段、已激活/未激活展示、预算耗尽恢复提示、经净化的领域错误、意外失败与持久变更记录。应用组合测试覆盖显式主干选择加入、TUI/ACP 默认值、readline 不挂载生产方、一致退出、转发的领域/工具配置、命令发现、打包运行时闭包与扩展后的模型工具组装。无密钥 ACP 快照固定了交付应用组合中的 `/goal` 发现元数据和目标工具 schema。
## 考虑过的替代方案