deepseek-harness/examples/acp-agent
Tianyi Cui 464a57d3ca Merge commit 'refs/codex/pr1006/master' into worktree/pr1006-merge-20260731
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/config-catalog.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	examples/headless-agent/cordis.yml
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
#	packages/llm/llm-deepseek/src/adapter.ts
#	packages/llm/llm-deepseek/src/index.ts
#	packages/llm/llm-deepseek/tests/adapter.spec.ts
#	packages/llm/llm/README.i18n.yaml
#	packages/llm/llm/README.md
#	packages/llm/llm/README.zh.md
#	packages/subagent/subagent-dsh-sdk/README.i18n.yaml
#	packages/ui/jsonrpc/README.i18n.yaml
2026-07-31 01:55:19 +08:00
..
tests Merge commit 'refs/codex/pr1006/master' into worktree/pr1006-merge-20260731 2026-07-31 01:55:19 +08:00
advanced.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
advanced.cordis.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
both-mode.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
both-mode.cordis.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
code-mode-workspace-context.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
code-mode-workspace-context.cordis.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
code-mode.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
code-mode.cordis.yml Merge branch 'worktree-llm-dynamic-config' into worktree-llm-web-config 2026-07-30 20:15:40 +08:00
composition.md refactor(subprocess): rename the process seam to subprocess and address review 2026-07-26 12:43:59 +08:00
cordis-tools.cordis.yml feat(web): present Cordis lifecycle tools 2026-07-27 17:57:59 +08:00
cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
cordis.yml Merge commit 'refs/codex/pr1006/master' into worktree/pr1006-merge-20260731 2026-07-31 01:55:19 +08:00
depth-two.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
depth-two.cordis.yml fix(tool-subagent): enforce depth only at runtime 2026-07-20 17:58:57 +08:00
fs.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
fs.cordis.yml fix(session-query): keep model tools opt-in 2026-07-25 18:14:36 +08:00
package.json refactor(acp): reduce bridge to automation protocol 2026-07-24 01:40:25 +08:00
pty-snapshot-backend.mjs feat: add persistent PTY sessions 2026-07-21 16:01:00 +08:00
pty.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
pty.cordis.yml fix(pty): make the foreground-handoff grace a config field 2026-07-27 14:14:59 +08:00
README.i18n.yaml fix(cli): close shared config review gaps 2026-07-30 14:56:39 +08:00
README.md fix(cli): close shared config review gaps 2026-07-30 14:56:39 +08:00
README.zh.md fix(cli): close shared config review gaps 2026-07-30 14:56:39 +08:00
retry.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
retry.cordis.yml Merge commit 'refs/codex/pr1006/master' into worktree/pr1006-merge-20260731 2026-07-31 01:55:19 +08:00
session-query.cordis.snapshot.yml fix(session-query): keep model tools opt-in 2026-07-25 18:14:36 +08:00
session-query.cordis.yml fix(session-query): keep model tools opt-in 2026-07-25 18:14:36 +08:00
session-sandbox-root.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
session-sandbox-root.cordis.yml test(snapshot): cover session-scoped sandbox roots 2026-07-21 01:16:29 +08:00
session-title.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
session-title.cordis.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
web-fetch-fixture-server.mjs fix(tool-web): bound HTML conversion work 2026-07-27 16:40:02 +08:00
web.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
web.cordis.yml feat(tool-web): replace the regex HTML-to-markdown converter with turndown 2026-07-27 00:22:13 +08:00
workspace-context.cordis.snapshot.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00
workspace-context.cordis.yml refactor(llm-deepseek)!: rename the provider route to deepseek-official 2026-07-29 16:36:07 +08:00

acp-agent example

English | 中文

Automation-oriented Agent Client Protocol server over JSON-RPC stdio. It is intended for parent agents, subagent providers, and other programmatic clients, not as the product UI.

pnpm run demo:acp             # needs DEEPSEEK_API_KEY (repo-root .env or env)
pnpm run demo:code-mode       # same protocol with the Code Mode tool transport

The leaf loads the ACP app, DeepSeek adapter, sandboxed bash and filesystem stacks, one-shot approval policy, compaction, subagents, workflows, hooks, a derived session-query index, and repeat guard. The app creates one fresh agent per session/new, persists sessions to JSONL, and keeps stdout protocol-pure. session-query.cordis.yml explicitly opts into the workspace-authorized query tools and generic timeout/spill policies for their dedicated snapshot; fs.cordis.yml adds spill storage for filesystem scenarios, code-mode.cordis.yml adds run_code and its generated TypeScript SDK, and web.cordis.yml adds the web seam, the local fetch provider, web_fetch, and a loopback HTML fixture server for the web-fetch snapshot.

Protocol channel

Stdout carries only newline-delimited ACP JSON-RPC. @deepseek-ai/dsh-acp-demo installs no stdout logger; leaf additions must use stderr for diagnostics.

The automation contract — supported methods, baseline prompt content, committed-text output, and the intentionally absent UI surfaces — lives in @deepseek-ai/dsh-acp.

Session workspaces and permissions

Each session/new supplies an absolute cwd. Sandboxed bash and filesystem mutations resolve workspace-write against that session cwd, so concurrent sessions can use separate project roots; platform temporary roots remain shared writable scratch space (sandbox contract). DSH_PERMISSION_MODE selects workspace-write or danger-full-access for deployment and tests.

Under workspace-write, a model retry requesting wider sandbox access triggers session/request_permission with allow_once and reject_once. The client decides programmatically; dismissal or an unavailable answer fails closed. The selected outcome applies only to that retry and is recorded through the normal tool-result/audit path. The server never exposes a permission picker or persists client policy.

Snapshot tests

This example owns the ACP snapshot suite. It boots the real automation server, replays committed model streams through dsh-llm-replay, and compares both normalized protocol output and re-persisted session logs. Recording uses the real model; refresh reuses committed replay input. Overrides cover throw/hang behavior, and optional workspace/ fixtures seed world-state checks.

Most scenarios pin backend behavior rather than ACP-specific behavior; the automation-only ACP decision owns why that coverage remains transport-coupled.