Files
deepseek-harness/examples/acp-agent/cordis.snapshot.yml
Tianyi Cui 46e31d8481 feat(tool-todo): add the model-facing todo_write tool
Add @deepseek-ai/dsh-tool-todo (a new packages/todo/ group): a model-facing
todo_write(todos: [{content, status}]) tool with whole-list-replace semantics.
Each call appends the full list as a todo/write event to the calling agent's
session log; the current list is the most recent such event (last-write-wins).
Single-owner — a non-agent caller is rejected. Beyond the schema's
type/required/enum checks, execute rejects empty/duplicate content and more than
one in_progress task, narrowing the loosely-typed args into a real TodoItem[].

Both UIs render off the existing session/event: the stdio UI prints a glyphed
checklist; the ACP bridge maps the list to a `plan` sessionUpdate (todosToPlan
synthesizes the priority ACP requires; status maps 1:1). Wired into the
coding-agent, acp-agent, and snapshot example configs with a system-prompt nudge.

Tests: unit (schema, validation, append/replace, no-agent rejection, presentCall,
HMR-safety, Loader export-shape guard), full-loop integration through the agent
loop, the ACP todosToPlan mapping + stream-update arm, the stdio render arm, and
a session/load replay that re-emits the plan. New-group TS wiring added to
tsconfig.base/json/build. RFC + a doc-inventory sweep (architecture, packages
README, AGENTS layout, cookbook group list, example READMEs) ship with it.

The todo-plan ACP snapshot scenario is recorded separately (needs an API key).
2026-06-29 10:30:52 +08:00

83 lines
3.3 KiB
YAML

# Snapshot-test REPLAY config: the acp-agent plugin tree with the model backend
# swapped to llm-replay (serves a recorded session JSONL — no API key, no
# network). The dsh-acp-agent bin selects this file for DSH_SNAPSHOT=replay.
#
# Same app as cordis.yml (@deepseek-ai/dsh-acp-agent: the agent-core spine +
# JSONL persistence + the ACP bridge) — only the LLM backend differs: llm-replay
# here, llm-deepseek there. It can't reuse the real adapter because llm-deepseek's
# apply() throws without DEEPSEEK_API_KEY, killing a keyless replay run at boot.
#
# stdout is reserved for the ACP JSON-RPC protocol — no stdout logger (the app
# package omits it). The replay fixture path comes from $DSH_SNAPSHOT_FILE (and
# an optional $DSH_SNAPSHOT_OVERRIDE sidecar), set by the snapshot harness.
# The replay adapter: short-circuits llm/stream with the recorded log's chunks,
# in place of llm-deepseek.
- id: llm-replay
name: '@deepseek-ai/dsh-llm-replay'
# Local bash executor (the agent's only tool, via agent-core's tool-bash schema).
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
timeoutMs: 60000
# The ACP server app — identical to cordis.yml's entry.
- id: acp-agent
name: '@deepseek-ai/dsh-acp-agent'
config:
model: deepseek-v4-flash
persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
systemPrompt: |
You are a coding assistant driven over the Agent Client Protocol.
Your tools are bash (plus bash_output/bash_kill for background tasks)
and subagent. Do ALL file operations through bash: read with
cat/sed/head, search with grep, write with heredocs (cat <<'EOF' >
file), edit with sed or a rewrite. Each bash call runs in a fresh
shell — pass workdir instead of cd. Check the [exit code: N] marker;
verify your work. Keep answers brief and factual.
Use the subagent tool to delegate a focused, self-contained subtask to
a fresh child agent (it works in its own context and returns only its
final result) — give it a complete, standalone instruction.
For multi-step work, use the todo_write tool to track a task list:
send the WHOLE list each call (it replaces the previous one), keep
exactly one task in_progress, and mark a task completed as soon as it
is done. Skip it for trivial single-step tasks.
# The subagent seam + both in-process backends + two model-facing tools —
# identical to cordis.yml's wiring (only the LLM backend differs above): spawn
# and fork are each reachable via a dsh-tool-subagent bound to it with a distinct
# toolName (subagent → spawn, subagent_fork → fork).
- id: subagent
name: '@deepseek-ai/dsh-subagent'
- id: subagent-spawn
name: '@deepseek-ai/dsh-subagent-spawn'
config:
providerName: spawn
- id: subagent-fork
name: '@deepseek-ai/dsh-subagent-fork'
config:
providerName: fork
- id: tool-subagent
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
toolName: subagent
- id: tool-subagent-fork
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: fork
toolName: subagent_fork
# The model-facing todo_write tool — identical to cordis.yml's wiring, so a
# replayed todo_write tool call resolves to a real tool during snapshot replay.
- id: tool-todo
name: '@deepseek-ai/dsh-tool-todo'