`dsh` shipped two config trees that were 43 rows the same: apps/cli/cordis.yml composed web as 74 flat rows, while the TUI booted examples/tui-agent/cordis.yml whose single `@deepseek-ai/dsh-tui-demo` row mounted twelve plugins behind a twenty-key pass-through Config. Neither file was what its location claimed — apps/cli hardcoded the "example" as the product default and the "demo" bundle was the application — and every capability change had to be made twice. - apps/cli/base.cordis.yml holds the 43 shared rows; tui.cordis.yml and web.cordis.yml are patch lists stating only what differs per surface - overlays apply as SIBLING patch lists at one include level, because include patches never cross an include boundary. Precedence: base < surface < (--config | personal ~/.dsh/config.yaml) < launcher flag/profile patches - `--config` now applies an overlay INSTEAD OF the personal one, so a demo or test tree never inherits the user's route; new `--config-replace` boots a file as the entire tree (the old `--config` behaviour). Both survive /resume - vendor/include: index each `insert`ed row as it is added so a later patch can configure or disable it. Upstream built the id index once before the patch loop, leaving every surface-only row — the whole TUI front door — silently unpatchable from user config. Logged as local modification 8 - session identity moves to dsh-agent-loop's CONFIGURED_AGENT_IDENTITIES_KEY; dsh-tui's MAIN_SESSION_ID_KEY is deleted (only the bundle read it) - delete examples/tui-agent, examples/cordis-agent, packages/examples/tui-demo; TUI tests → apps/cli/tests, cordis e2e → packages/cordis/tool-cordis/tests, examples/code-mode survives as an overlay leaf - `dsh web` gains --config, threaded into AppCLIEntry as an extra overlay Three latent defects surfaced and are fixed here: the TUI captured the optional sessionQuery service once at construction and could permanently disable /resume when it won the mount race; the session-store root silently reverted to a project-local ./.sessions; --config-replace was dropped by the resume handoff. Verified by booting each tree through the real Loader (TUI 55 entries, web 75, zero unsettled) rather than reading YAML. All eight terminal snapshots replay byte-identically; 14/14 PTY smoke, 112/112 snapshots, 25/25 doc-sync, hygiene and lint clean.
5.7 KiB
@deepseek-ai/dsh-tool-todo
English | 中文
面向模型的 todo_write 工具:agent(智能体)的完整任务列表,每次调用都会整体替换。
功能
注册一个工具 todo_write(todos: [{ content, status }]) 到 ctx.tools。模型每次调用都会发送完整列表,不存在部分更新或单项编辑。每次调用都会向调用 agent 的会话日志追加 todo/write 事件(完整列表快照),具体调用 agent.session.append('todo/write', { todos });当前列表是最新的该类事件(回放时后写覆盖先写)。
status 是 pending、in_progress 或 completed 之一。
单一所有者
该列表属于调用工具的唯一 agent 会话。不存在 subagent/共享/swarm scope:非 agent 调用方(没有 exec.agent)无处写入列表,因此会被拒绝。这是有意设置的 scope 限制,详见 Agent Note(agent 决策记录)。
验证
除 schema 的类型/必填/枚举检查外,execute 还会拒绝空或重复的 content、同时存在多个 in_progress 任务的情况(连贯计划最多只有一个活跃任务),以及 content/status 之外的任何条目键——扩展条目形状(id、嵌套)会明确报错而不是被静默压平,保证落日志的快照与模型自认为写入的内容一致。列表的顺序及及时更新由模型依照工具描述负责。
渲染
<<<<<<< HEAD
规范结果为 { todos, counts: { pending, inProgress, completed } };其 Native 渲染器返回精简的更新确认。工具还会写入完整 todo/write 会话事件。UI 订阅事件流,并自行渲染该持久化列表:TUI 应用与 web 客户端基于当前有效计划(其后没有更晚 turn/start 的最近一次 todo/write)显示计划条(web 另有专属工具行)(展示、生命周期)。
规范结果为 { todos, counts: { pending, inProgress, completed } };其 Native 渲染器返回精简的更新确认。工具还会写入完整 todo/write 会话事件。UI 订阅事件流,并自行渲染该持久列表:TUI 前端入口与 web 客户端基于站立计划(其后没有更晚 turn/start 的最近一次 todo/write)显示计划条(web 另有专属工具行)(展示、生命周期)。
a1c6a2c3f (refactor(cli)!: one shared base config with per-surface overlays)
会话投影
当组合挂载了 ctx.sessionProjections(@deepseek-ai/dsh-session-projection)时,本包在一个注入的子插件中注册 todos 投影单元:init = null(尚无写入)、apply = 从每个 todo/write 取整表,并在每个 turn/start 清为 null(当前有效计划;turn/end 保留刚完成的清单;其余事件都返回同一个状态引用)、view = 恒等、stateVersion = 2。该键在本包中合并进 SessionProjectionMap(经接口包的 /types 出口);框架驱动该单元,载体通过历史尾页与 session/projection 推送帧提供该值。未挂载注册表的组合不受影响。生命周期理由见 在下一轮次清空 todo 计划。
导出形状
函数/命名空间插件:导出 name/inject/apply,不提供默认导出。意外的 export default 会被 Loader 的 unwrapExports 折叠为默认导出,并导致 inject 丢失(参见 docs/postmortem/0001)。
模型体验
工具 schema
模型看到的内容
模型会看到生成的 todo_write schema。
Token 影响
工具可见的每个请求都有固定的 schema token 开销。
KV Cache 影响
只要定义和可见性不变,前缀就保持稳定。插件生命周期或 scope 限制可能会使从此 schema 起的缓存复用失效。
工具调用历史与结果
模型看到的内容
每个 assistant 工具调用都会在参数中保留整个替换列表。成功时原样返回 Updated todo list: <pending> pending, <inProgress> in progress, <completed> completed.。稳定失败文本为 Error: invalid todo: `content` must be a non-empty string、Error: invalid todos: duplicate content "<content>"、Error: invalid todos: at most one task may be in_progress, got <count> 和 Error: todo_write requires an owning agent session。完整 todo/write 会话事件是 UI 与回放状态,而非第二条模型消息。
Token 影响
token 用量会随模型每次提交的完整列表增长,且这些调用参数会保留到压缩(compaction)。结果本身很小,且形状固定。
KV Cache 影响
仅追加;新可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
已知限制与暂缓事项
- 仅单一所有者 scope:列表属于唯一调用 agent 会话;subagent/共享/swarm scope 是有意设置的限制(参见「单一所有者」一节),非 agent 调用方会被拒绝。
- 条目形状有意保持最小:
content加三态status;整表替换不需要稳定 id、优先级或 active-form 字段。 - 整表替换是唯一操作:没有部分更新,也没有回读工具;模型每次调用都必须重新发送完整列表。