Files
deepseek-harness/examples/echo-agent
Yichen Jiang 815365dbbe Merge remote-tracking branch 'origin/master' into worktree/provider-routed-llm-adapters
# Conflicts:
#	docs/config-catalog.md
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.md
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.jsonl
#	examples/acp-agent/tests/snapshots/both-mode-turn/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl
#	examples/acp-agent/tests/snapshots/skill-load/session.jsonl
#	examples/acp-agent/tests/snapshots/text-turn/session.jsonl
#	examples/sandbox-acp-agent/cordis.yml
#	examples/sandbox-acp-agent/tests/snapshots/escalation-approved/session.jsonl
#	examples/sandbox-acp-agent/tests/snapshots/escalation-rejected/session.jsonl
#	examples/sandbox-acp-agent/tests/snapshots/mode-switching/session.jsonl
#	packages/compact/compact-basic/README.md
#	packages/compact/compact-basic/src/index.ts
#	packages/compact/compact-basic/tests/compact-basic.spec.ts
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/src/loop.ts
#	packages/core/agent-loop/tests/properties.spec.ts
#	packages/core/session/README.md
#	packages/core/session/src/types.ts
#	packages/core/session/tests/derived-cache.spec.ts
#	packages/llm/llm-deepseek/src/index.ts
#	packages/llm/llm-pi-ai/README.md
#	packages/llm/llm-pi-ai/src/adapter.ts
#	packages/llm/llm-pi-ai/src/convert.ts
#	packages/llm/llm-pi-ai/tests/adapter.spec.ts
#	packages/llm/llm/README.md
#	packages/llm/llm/src/call-config.ts
#	packages/llm/llm/src/index.ts
#	packages/ui/acp-agent/src/index.ts
#	packages/ui/acp/tests/harness.ts
#	packages/ui/jsonrpc/README.md
#	packages/ui/jsonrpc/src/server.ts
#	packages/ui/stdio-agent/README.md
#	packages/ui/stdio-agent/src/index.ts
#	python/sdk/README.i18n.yaml
2026-07-14 22:17:50 +08:00
..
2026-07-14 21:57:52 +08:00
2026-06-11 10:55:05 +08:00

echo-agent

Runnable demo: stdin chat with a scripted mock model and an echo tool. The all-mock skeleton — "swap the backend, keep the app".

What it shows

This example is just a leaf cordis.yml: it loads the @deepseek-ai/dsh-stdio-agent app (which bundles the whole @deepseek-ai/dsh-agent-core spine, the console logger, JSONL persistence, the readline UI, and a pre-created main agent), and swaps in two example-local backends plus hmr:

  • mock-llm.ts — a mock LlmAdapter that streams scripted responses and calls the echo tool when the user types "echo ". Registered with ctx.llm.registerAdapter(['mock-echo'], …).
  • echo-tool.ts — a tool registered via ctx.tools.register(defineTool(…)) with typed execute args; echoes text back uppercased.

Swapping mock-llm for the real llm-deepseek adapter is all that separates this from coding-agent — the same app, a different backend.

Plugin files

File Role Key patterns demonstrated
src/mock-llm.ts LlmAdapter registration ctx.llm.registerAdapter(['mock-echo'], …), streaming chunks with the proper block-start/block-end protocol
src/echo-tool.ts Tool registration ctx.tools.register(defineTool(…)) with typed execute args, returning ContentBlock[]
cordis.yml Leaf wiring the two backends + hmr + one @deepseek-ai/dsh-stdio-agent entry carrying the app config

The spine, UI, persistence, and boot glue all live in @deepseek-ai/dsh-stdio-agent and the bundle it loads — this folder holds only the demo-specific mocks and the leaf wiring.

Run

pnpm run demo:echo
# or:
node --expose-internals --import tsx packages/ui/stdio-agent/src/bin.ts examples/echo-agent/cordis.yml

Type a message and press Enter. "echo " triggers a tool call round-trip (the mock model requests the echo tool, which echoes the text uppercased, and the next model step acknowledges it).

The session is persisted under .sessions/ relative to the directory you launch the demo from. pnpm run demo:echo runs from the repo root, so the logs land in <repo-root>/.sessions/cwd-<hash>/ (one .jsonl log per session). Clean up with: rm -rf .sessions