mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
59 lines
3.3 KiB
Markdown
59 lines
3.3 KiB
Markdown
# @deepseek-ai/dsh-subagent-acp
|
|
|
|
The ACP provider runs each subagent in a fresh subprocess and drives it as an Agent Client Protocol client. It is the out-of-process alternative to spawn and fork: the child has its own runtime, session, model configuration, and tools.
|
|
|
|
## Start and ownership
|
|
|
|
`start(request)` performs `spawn` → ACP `initialize` → `newSession` before it fulfills. Fulfillment therefore means a remote session is ready and ownership has transferred to the caller. A spawn, initialization, new-session, or pre-publication cancellation failure rejects only after the subprocess has been reaped.
|
|
|
|
After publication, the provider sends the prompt and collects streamed `agent_message_chunk` text into `SubagentResult.output`. A prompt/transport failure resolves with `stopReason: 'error'`, or `aborted` when the required request signal or disposal requested cancellation.
|
|
|
|
`dispose()` is idempotent. It removes the signal listener, requests ACP cancellation when possible, closes stdin, waits `disposeEofGraceMs`, escalates to SIGTERM, waits `disposeGraceMs`, and finally uses SIGKILL if necessary. Every run uses a fresh process; process pooling is not implemented.
|
|
|
|
## Capabilities and context
|
|
|
|
ACP advertises no start-time capabilities because this process cannot enforce the remote child's depth, tool filter, persona, or structured-output runtime. It also reports `inheritsParentContext: false`: the remote session starts fresh and ignores `request.parent` beyond the seam's required attribution field.
|
|
|
|
## Configuration
|
|
|
|
| Key | Default | Meaning |
|
|
|---|---|---|
|
|
| `providerName` | `acp` | Registry name on `ctx.subagents`. |
|
|
| `command` | required | Executable spawned for each run. |
|
|
| `args` | `[]` | Command arguments. |
|
|
| `cwd` | process cwd | Child process and ACP session working directory. |
|
|
| `permission` | `reject` | Auto-answer permission requests by rejecting or choosing the first allow-shaped option. |
|
|
| `env` | `{}` | Explicit child environment layered over a credential-scrubbed parent environment. |
|
|
| `disposeEofGraceMs` | `6000` | Grace after stdin EOF before SIGTERM. |
|
|
| `disposeGraceMs` | `3000` | Grace after SIGTERM before SIGKILL. |
|
|
|
|
```yaml
|
|
- id: subagent-acp
|
|
name: '@deepseek-ai/dsh-subagent-acp'
|
|
config:
|
|
providerName: acp
|
|
command: node
|
|
args: ['--import', 'tsx', './packages/ui/acp-agent/src/bin.ts', './examples/acp-agent/cordis.yml']
|
|
permission: reject
|
|
env:
|
|
DEEPSEEK_API_KEY: !!js process.env.DEEPSEEK_API_KEY
|
|
```
|
|
|
|
## Stop-reason mapping
|
|
|
|
| ACP | Harness |
|
|
|---|---|
|
|
| `end_turn` | `completed` |
|
|
| `max_tokens` | `max-tokens` |
|
|
| `refusal` | `refusal` |
|
|
| `cancelled` | `aborted` |
|
|
| `max_turn_requests` or unknown | `error` |
|
|
|
|
## Process boundary
|
|
|
|
The child environment is built by [`buildChildEnv`](../subagent-subprocess/README.md): credential-shaped ambient variables are removed, then explicit `config.env` values are applied. The ACP wire is the real serialization boundary; same-process subagent values are not defensively cloned.
|
|
|
|
The package has no default export. Cordis loader unwrapping would otherwise hide the named `inject` metadata; see [postmortem 0001](../../../docs/postmortem/0001-acp-default-export-drops-inject.md).
|
|
|
|
Keyless tests drive a scripted ACP subprocess over real stdio. The with-key e2e drives the repository's real ACP agent and self-skips without `DEEPSEEK_API_KEY`.
|