@deepseek-ai/dsh-subagent 0.1.1-rc.2 → 0.1.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +105 -75
- package/README.zh.md +110 -84
- package/lib/index.js +910 -433
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1016 -0
- package/lib/typert.remote-client.d.ts +27 -0
- package/lib/typert.remote-client.js +242 -0
- package/lib/types/child-agent.d.ts +14 -3
- package/lib/types/child-agent.js +48 -10
- package/lib/types/client.d.ts +2 -1
- package/lib/types/client.js +1 -1
- package/lib/types/continuation.d.ts +4 -2
- package/lib/types/continuation.js +124 -46
- package/lib/types/control-types.d.ts +160 -0
- package/lib/types/control-types.js +9 -0
- package/lib/types/control.d.ts +83 -0
- package/lib/types/control.js +133 -0
- package/lib/types/descriptor.d.ts +6 -1
- package/lib/types/descriptor.js +6 -2
- package/lib/types/index.d.ts +60 -26
- package/lib/types/index.js +430 -299
- package/lib/types/list-children.d.ts +10 -58
- package/lib/types/list-children.js +161 -97
- package/lib/types/out-of-process.d.ts +3 -2
- package/lib/types/out-of-process.js +11 -3
- package/lib/types/run-settlement.js +7 -3
- package/lib/types/types.d.ts +18 -0
- package/package.json +63 -37
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/subagent/subagent/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 76df70351d711d580d3ab1a89d0f929b85eab172
|
|
6
|
+
README.zh.md: c4deb001c47435d29a5ca18cc0f8c0d26e48941e
|
package/README.md
CHANGED
|
@@ -1,112 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "The subagent delegation seam for users and maintainers choosing a provider backend, composing delegation tools, or debugging child-agent runs."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# @deepseek-ai/dsh-subagent
|
|
2
7
|
|
|
3
8
|
English | [中文](README.zh.md)
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The [subagent family overview](../README.md) maps implementations and model-facing consumers. This package owns the provider registry, shared request and result contracts, durable descriptors, and continuable-child orchestration. Multiple named providers may coexist behind that contract.
|
|
8
|
-
|
|
9
|
-
## Service API
|
|
10
|
-
|
|
11
|
-
`SubagentRuntime` has these operations:
|
|
12
|
-
|
|
13
|
-
| Member | Meaning |
|
|
14
|
-
|---|---|
|
|
15
|
-
| `registerProvider(provider)` | Register one trusted same-process implementation by name. Registration is effect-scoped; removing it prevents new starts but does not revoke runs already returned to callers. Duplicate names fail loud. |
|
|
16
|
-
| `getProvider(name)` | Return the provider, or `undefined` when absent. |
|
|
17
|
-
| `list()` | Return provider names in insertion order. |
|
|
18
|
-
| `start(name, request)` | Validate an ordinary caller request, resolve its detached `one-shot` descriptor, then await the provider until a real one-shot child is published. Fulfillment returns a holder-owned `SubagentRun`; rejection means the provider has already cleaned every unpublished startup resource, while post-publication turn or infrastructure faults settle through the run. Continuable children never enter through this operation. |
|
|
19
|
-
| `startContinuable(spec)` | Establish one durable continuable child and deliver its initial prompt. Resolves with `{ childId, messageId }` when the child's inbox accepts that prompt, without waiting for the turn to start or for the message to reach the Session log; any earlier failure rejects with no ids and rolls the child back entirely. A caller-reserved `childId` is rejected when the live registries or configured persistence already own it. Requires `ctx.agents`, session persistence, and a provider with the `prepareContinuable` capability. |
|
|
20
|
-
| `followup(parent, childId, content, { source, signal })` | Deliver one later message from the exact live direct parent as the child's next FIFO turn, matching `Agent.followup()` terminology, and return the accepted `MessageId`. A resident child's inbox accepts it directly (waking a waiting Activation); an absent one cold-resumes from its persisted Session. Requires `ctx.agents`; cold resume also requires session persistence. |
|
|
21
|
-
| `interrupt(targetSessionId, authority)` | Interrupt one live continuable child's current turn under a human durable parent address (`{ kind: 'user', parentSessionId }`) or an exact live ancestor Agent (`{ kind: 'ancestor', agent }`). Admission is synchronous and the effect asynchronous: it issues `Agent.cancel(cause, { keepInbox: true })` and returns without waiting for the target to observe the signal. Unclaimed pending inbox work, the Activation, and published descendants are preserved; work already claimed into the interrupted turn is not requeued. An absent target is an accepted no-op; a wrong parent address or a stale, self-targeting, or non-ancestor caller rejects with `UNAUTHORIZED`. |
|
|
22
|
-
| `reportFrom(child, content, { delivery, signal })` | Deliver one selected message from the exact live continuable child to its exact live direct parent and return the accepted stable `MessageId`. Quiet delivery injects next-step context without waking; next-step delivery steers and wakes the parent. |
|
|
23
|
-
| `registerContinuableSetup(contribution)` | Compose an optional deployment capability into each continuable child's unpublished scope, with immediate revocation from resident children. |
|
|
24
|
-
| `drainContinuableDescendants(parents)` | Close admission below exact live host-owned parent Agents, stop only their visible continuable descendants, await materializations admitted below those roots through publication or rollback, then release the selected forests child-first. The cutoff lasts until each exact parent leaves the registry; unrelated parent forests and manager-wide admission remain live. |
|
|
25
|
-
| `drainContinuableChildren(parent, childIds)` | Release only the named resident continuable direct children of one exact live parent, recursively and child-first. It does not close admission or touch siblings, accepts absent ids as no-ops, and rejects a resident child owned by another parent. This is teardown, so unlike `interrupt()` it does not preserve pending inbox work. |
|
|
26
|
-
| `listChildren(parentSessionId, signal?)` | List direct session-backed subagents with their `one-shot`/`continuable` mode, `running`/`inactive` activity, origin-classified one-level `hasChildren` hint, and per-child diagnostics, ordered by `createdAt` then id, without loading or resuming them. Reads the live session store and optional session persistence directly (live-only enumeration when persistence is absent) and requires the mounted `sessionProjections` registry; it does not require `ctx.agents`, the continuation manager, or any query service. |
|
|
27
|
-
| `listDescendants(rootSessionId, signal?)` | Flatten the root's complete session tree in stable pre-order from the same live-preferred corpus, adding each subagent entry's durable `parentId` and root-relative `depth`. Ordinary sessions and one-shot children remain traversal nodes so continuable descendants below them are discovered. Identity, diagnostics, dependencies, and cancellation follow `listChildren()`. |
|
|
28
|
-
|
|
29
|
-
`SubagentStartRequest.label` is an optional short durable display label for a session-backed one-shot child. Model-facing delegation supplies its existing `description`; lower-level callers need not invent presentation metadata. Continuable starts always carry their own required label. `signal` is required and is the canonical cancellation channel for a one-shot `start`. An abort before publication makes `start()` reject after rollback; an abort after publication cancels the returned run's remaining turn work without hiding its id. The request may also select a model, require structured output, cap delegation depth, restrict child tools, or set a child persona. For a continuable start or follow-up, the caller signal owns lookup, materialization, and admission only until inbox acceptance; afterward the manager owns the Activation independently, so later caller cancellation neither cancels the accepted turn nor disposes the child.
|
|
30
|
-
|
|
31
|
-
Follow-up authority comes from the exact live direct parent recorded in the child's durable header. Cold resume checks that authority before reconstruction and again in the final no-await inbox-admission span, so a parent unregistered or replaced during materialization cannot authorize delivery. The `source` on a follow-up records who supplied the delivered message and grants no authority.
|
|
10
|
+
## Summary
|
|
32
11
|
|
|
33
|
-
|
|
12
|
+
`dsh-subagent` is the service behind child-agent delegation: an agent hands a task to a named child, collects the finished result, and — for continuable children — keeps sending follow-up work across turns. Multiple providers coexist under one contract, so a single composition can offer in-process children, out-of-process ACP or SDK children, and real Codex or Claude Code children side by side. Children come in two shapes: one-shot runs that settle with a single result, and continuable children whose durable session accepts later messages and can be interrupted. The same service answers discovery questions — which children exist, their mode, activity, and lineage — without loading or resuming them. Mount it with at least one provider backend and a delegation tool; the backends and the model-facing tools live in sibling packages.
|
|
34
13
|
|
|
35
|
-
##
|
|
14
|
+
## Table of Contents
|
|
36
15
|
|
|
37
|
-
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
38
22
|
|
|
39
|
-
|
|
40
|
-
- `depthLimit` — enforce `maxDepth`.
|
|
41
|
-
- `toolFilter` — apply the requested child tool restriction.
|
|
42
|
-
- `persona` — apply a per-child persona.
|
|
23
|
+
-----
|
|
43
24
|
|
|
44
|
-
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
45
27
|
|
|
46
|
-
|
|
28
|
+
This package is the contract every delegation setup shares. You enable it by mounting the service together with one or more provider backends and the model-facing delegation tool; from then on, an agent can delegate work and the service routes each request to the named provider.
|
|
47
29
|
|
|
48
|
-
|
|
30
|
+
### Enabling delegation
|
|
49
31
|
|
|
50
|
-
|
|
32
|
+
Mount the service with a provider and the delegation tool. The provider registers under the name you configure (the in-process spawn backend defaults to `spawn`); the tool row names that provider so the model sees a static tool. A minimal one-shot setup:
|
|
51
33
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
```yaml
|
|
35
|
+
- name: '@deepseek-ai/dsh-subagent'
|
|
36
|
+
- name: '@deepseek-ai/dsh-subagent-spawn-in-process'
|
|
37
|
+
- name: '@deepseek-ai/dsh-tool-subagent'
|
|
38
|
+
config:
|
|
39
|
+
provider: spawn
|
|
40
|
+
toolName: subagent
|
|
41
|
+
```
|
|
55
42
|
|
|
56
|
-
|
|
43
|
+
An agent that calls the tool gets the child's final answer as the tool result. Mounting the service alone changes nothing: nothing can delegate until a provider and a tool are composed.
|
|
57
44
|
|
|
58
|
-
|
|
45
|
+
### One-shot and continuable children
|
|
59
46
|
|
|
60
|
-
|
|
47
|
+
One-shot children run once and settle with a single result, plus an optional structured output and a safe diagnostic on failure. A start request may override the child Agent's provider, model, reasoning effort, and output-token limit through `agentOptions`; every requested option requires the provider's matching capability. Continuable children keep a durable session and accept later messages in order: the caller receives a stable child id, sends follow-ups, and can interrupt the current turn without destroying the child. The tool row's `backgroundMode` picks the shape (`one-shot` by default, or `continuable` on providers that support it).
|
|
61
48
|
|
|
62
|
-
|
|
49
|
+
### Following up, interrupting, and discovering
|
|
63
50
|
|
|
64
|
-
|
|
51
|
+
Continuable children answer follow-up messages as their next turns, and the parent can interrupt a running turn or list its children at any time. Discovery covers both shapes: the service lists direct children and the full descendant tree — mode, activity, and lineage — reading live session state and optional persistence, without loading any child.
|
|
65
52
|
|
|
66
|
-
|
|
53
|
+
### Failure and recovery
|
|
67
54
|
|
|
68
|
-
|
|
55
|
+
Requests that need a capability the chosen provider lacks fail loudly at start rather than being silently ignored. A failed child run returns a stop reason, and provider backends add a safe diagnostic; a cancelled request settles as `aborted`. Children are isolated: a crashed or misbehaving child cannot corrupt the parent's session.
|
|
69
56
|
|
|
70
|
-
|
|
57
|
+
-----
|
|
71
58
|
|
|
72
|
-
|
|
59
|
+
<a id="understand-the-implementation"></a>
|
|
60
|
+
## Understand the implementation
|
|
73
61
|
|
|
74
|
-
|
|
62
|
+
<details>
|
|
63
|
+
<summary>Implementation internals — click to expand</summary>
|
|
75
64
|
|
|
76
|
-
|
|
65
|
+
This section explains how the service is built and where the observable behavior comes from; the full contract lives in [Use this package](#use-this-package).
|
|
77
66
|
|
|
78
|
-
|
|
67
|
+
### Design concept
|
|
79
68
|
|
|
80
|
-
|
|
69
|
+
- **One service, many providers.** The service is a named-provider registry; each backend registers under a unique name and a request picks one by name.
|
|
70
|
+
- **Two child shapes.** One-shot runs transfer ownership at publication; continuable children keep a durable Session and at most one process-local Activation.
|
|
71
|
+
- **Fulfillment is publication.** A provider's `start()` fulfills only after a real child exists, so the caller always owns a live run or nothing.
|
|
72
|
+
- **Trusted same-process values.** Requests, descriptors, and results are borrowed immutable; serialization and hostile-input validation belong at process and wire boundaries.
|
|
81
73
|
|
|
82
|
-
|
|
74
|
+
### Source map
|
|
83
75
|
|
|
84
|
-
|
|
76
|
+
| File | Role |
|
|
77
|
+
|---|---|
|
|
78
|
+
| [`src/index.ts`](src/index.ts) | Service entry: provider registry, start and continuation API, lifecycle events |
|
|
79
|
+
| [`src/continuation.ts`](src/continuation.ts) | Continuable children: identity reservation, Activation residency, follow-up, interrupt, settlement |
|
|
80
|
+
| [`src/types.ts`](src/types.ts) | Public request, result, and provider contracts |
|
|
81
|
+
| [`src/descriptor.ts`](src/descriptor.ts) | Versioned `subagent/descriptor` session-event vocabulary |
|
|
82
|
+
| [`src/child-agent.ts`](src/child-agent.ts) | Child composition, delegated policy, depth helpers |
|
|
83
|
+
| [`src/list-children.ts`](src/list-children.ts) | Discovery over the live session store and optional persistence |
|
|
84
|
+
| [`src/control.ts`](src/control.ts) | Browser control assembly: catalog activity sampling, browser-zone validation, failure codes |
|
|
85
|
+
| [`src/control-types.ts`](src/control-types.ts) | Client-safe catalog row, control requests, receipts, and failures |
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
### One-shot flow
|
|
87
88
|
|
|
88
|
-
A
|
|
89
|
+
A request is validated against the provider's advertised capabilities, a durable descriptor is snapshotted, and the provider builds the child. Both in-process providers advertise `agentOptions`: child creation merges requested fields over the provider, model, and reasoning effort in the parent's latest logged request, falls back to creation options before the first request, and retains the configured token limit. A route change without an explicit effort clears the inherited route-owned effort so the selected model resolves its default. DSH SDK also advertises this capability and publishes immutable `agentRouteDefaults`, which supply its instance provider/model defaults before exact-route preflight; `start()` still owns direct callers and the output cap. ACP, Codex, and Claude Code reject agent-route overrides rather than silently ignoring them. On success the run is published and ownership transfers to the caller; on failure the provider rolls back every unpublished resource. The result carries the child's final output, an optional structured value, a stop reason, and an optional safe diagnostic.
|
|
89
90
|
|
|
90
|
-
|
|
91
|
+
### Continuable flow
|
|
91
92
|
|
|
92
|
-
The
|
|
93
|
+
The manager reserves a child identity, resolves the durable descriptor, creates (or cold-resumes) the child Agent, installs it in an Activation, and submits the prompt. Later messages become FIFO turns through the child's own inbox; an absent Activation cold-resumes from the persisted session. When a resident Activation settles, the manager tells the child's direct parent in the parent's own turn stream.
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
### Ownership and invariants
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
- **Publication is the boundary** — before it the provider owns the setup and must roll back on failure; after it the caller owns the run and must dispose it.
|
|
98
|
+
- **Registration is effect-scoped** — removing a provider blocks new starts but never revokes accepted runs.
|
|
99
|
+
- **Continuation authority is exact identity** — follow-ups require the exact live direct parent; reports require the exact live child.
|
|
100
|
+
- **The descriptor is log-only** — a session event absent from model history and retained across compaction; a continuable descriptor records the resolved child provider, model, and reasoning effort explicitly for cold resume.
|
|
97
101
|
|
|
98
|
-
|
|
102
|
+
</details>
|
|
99
103
|
|
|
100
|
-
|
|
104
|
+
-----
|
|
101
105
|
|
|
102
|
-
|
|
106
|
+
<a id="further-exploration"></a>
|
|
107
|
+
## Further Exploration
|
|
103
108
|
|
|
104
|
-
|
|
109
|
+
Read these pages when the package-level contract is not enough. They move from the shared seam to the backends, the model-facing tools, and the design decisions.
|
|
105
110
|
|
|
106
|
-
|
|
111
|
+
- [Subagent subsystem](../../../docs/subsystems/subagent.md) — the service contract, provider contract, and terminal result semantics.
|
|
112
|
+
- [Subagent capability seam](../../../.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md) — the design record for the delegation capability family.
|
|
113
|
+
- [Continuable background subagents](../../../.agents/notes/implemented/feature/2026-07-21-continuable-background-subagents.md) — durable children that accept follow-up turns.
|
|
114
|
+
- [In-process spawn backend](../subagent-spawn-in-process/README.md) — the simplest provider to compose.
|
|
115
|
+
- [Out-of-process ACP backend](../subagent-acp/README.md) — children with their own runtime over the Agent Client Protocol.
|
|
116
|
+
- [Merged subagent control service](../../../.agents/notes/implemented/simplification/2026-07-26-merge-subagent-control-service.md) — the follow-up, interrupt, and listing surface.
|
|
107
117
|
|
|
108
|
-
|
|
118
|
+
-----
|
|
109
119
|
|
|
120
|
+
<a id="model-experience"></a>
|
|
110
121
|
## Model Experience
|
|
111
122
|
|
|
112
123
|
### Settlement notice
|
|
@@ -145,11 +156,30 @@ Prefix-stable within a child: the statement never changes during the child's lif
|
|
|
145
156
|
|
|
146
157
|
## Known Limitations and Deferred Work
|
|
147
158
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
- **
|
|
154
|
-
- **No
|
|
159
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
These limits define when the seam is a poor fit or needs special operational care. They are current package constraints, not a general delegation comparison or a task backlog.
|
|
163
|
+
|
|
164
|
+
- **ACP children remain one-shot and are not trace-enumerable** — an ACP run has no local child session in the parent's session corpus, and remote providers need an Activation ownership contract before they can support continuable children.
|
|
165
|
+
- **No host-user continuation** — `followup()` requires the exact live direct parent; only `interrupt()` accepts a durable human parent address.
|
|
166
|
+
- **Continuation messages never steer** — parent-to-child follow-ups enqueue later turns; they never redirect the child's current turn.
|
|
167
|
+
- **Wake gap during cancellation convergence** — a follow-up accepted after an interrupt signal but before the driver becomes idle stays queued until another waking send.
|
|
168
|
+
- **Process-local residency** — the Activation inbox and ownership graph do not coordinate two harness processes; concurrent access to one persistence store needs a durable mailbox and cross-process lease protocol.
|
|
169
|
+
- **No replay of accepted-but-unlogged messages** — a crash can lose an accepted prompt that never reached the child's session log; the lost message is not replayed automatically.
|
|
170
|
+
- **No durable report mailbox** — reports require a live direct parent and provide acceptance identity rather than exactly-once delivery.
|
|
155
171
|
- **Lifecycle events are observe-only** — a run-affecting `subagent/end` continuation or decision API waits for a concrete consumer.
|
|
172
|
+
|
|
173
|
+
<a id="dev-note"></a>
|
|
174
|
+
### Dev Note
|
|
175
|
+
|
|
176
|
+
<details>
|
|
177
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
178
|
+
|
|
179
|
+
This Dev Note is working context for maintainers: open questions and undecided directions. It is explicitly non-authoritative — shipped behavior and limits live in the sections above and in the package code.
|
|
180
|
+
|
|
181
|
+
- **Cross-process continuation** — a durable mailbox and lease protocol would let two harness processes share one persistence store.
|
|
182
|
+
- **Continuable ACP children** — requires persisting the remote session id and a per-child continuation advertisement.
|
|
183
|
+
- **Host-user delivery** — a future host adapter needs a concrete authenticated interaction before the seam gains a user delivery capability.
|
|
184
|
+
|
|
185
|
+
</details>
|