返回源码地图

packages/subagent/subagent/src/types.ts

main snapshot · da00f7f5358f · 正文引用章节 13 / 13;完整原文可核对,不声称全文件人工逐行审计

完整原文供逐行核对;页面收录不代表每行都经过人工语义审核。MIT 许可见 许可证。

1/**
2 * The seam's consumer-facing contracts: request, result, and capability types
3 * for {@link SubagentProvider}, plus the `subagent/start` and `subagent/end`
4 * payloads that plugins and hosts observe. Internal control interfaces belong
5 * with their implementation — the lifecycle observer in `./lifecycle.ts`, the
6 * continuation host in `./continuation.ts` — so this module stays the published
7 * surface rather than a bag of everything type-shaped.
8 *
9 * @module @deepseek-ai/dsh-subagent/types
10 */
11
12import type { Agent, AgentOptions } from '@deepseek-ai/dsh-agent'
13import type { Branded } from '@deepseek-ai/dsh-brand'
14import type { ContentBlock, MessageId } from '@deepseek-ai/dsh-llm'
15import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
16import type { ObjectJsonSchema, ToolRestriction } from '@deepseek-ai/dsh-tools'
17import type { SubagentDescriptorData } from './descriptor.ts'
18
19/** Identifies one accepted subagent run across its lifecycle event pair. */
20export type SubagentRunId = Branded<'SubagentRunId'>
21
22/**
23 * Brand a string as a {@link SubagentRunId}.
24 * @param id - the raw run id.
25 * @returns the same string, branded.
26 */
27export function SubagentRunId(id: string): SubagentRunId {
28 return id as SubagentRunId
29}
30
31/** What a caller asks for when starting a continuable background child. */
32export interface ContinuableStartSpec {
33 /** The `ctx.subagents` provider whose continuable-creation capability establishes the child. */
34 readonly provider: string
35 /** The initial delegation's short `description`, persisted as the child's creation label. */
36 readonly label: string
37 /**
38 * Optional caller-reserved child identity. Omission preserves the manager's
39 * UUID allocation; supplying one lets a durable parent record provisioning
40 * before child materialization without a second identity handshake.
41 */
42 readonly childId?: SessionId
43 /**
44 * The delegation request. The manager reserves the stable child id, resolves
45 * the durable descriptor, and composes the child itself.
46 */
47 readonly request: Omit<SubagentStartRequest, 'label' | 'signal' | 'outputSchema'>
48 /** Caller cancellation, owning the operation only until inbox acceptance. */
49 readonly signal: AbortSignal
50}
51
52/** Identities returned once a continuable child accepted its initial prompt. */
53export interface ContinuableStart {
54 /** The durable child session id, stable across activations. */
55 readonly childId: SessionId
56 /** The accepted initial prompt's inbox message id. */
57 readonly messageId: MessageId
58}
59
60/**
61 * Authority under which one interrupt request is admitted. `user` carries the
62 * durable direct-parent address a human client presented; `ancestor` carries
63 * the exact live Agent object whose recorded lineage must contain the caller.
64 */
65export type SubagentInterruptAuthority =
66 | { readonly kind: 'user'; readonly parentSessionId: SessionId }
67 | { readonly kind: 'ancestor'; readonly agent: Agent }
68
69/** Options for one model-authored message between adjacent Agents. */
70export interface SubagentSendMessageOptions {
71 /** Caller cancellation, owning the operation only until inbox acceptance. */
72 readonly signal: AbortSignal
73}
74
75/**
76 * Observe-only identifying detail for a published subagent run, carried by
77 * `subagent/start`. One-shot runs and continuable Activation epochs share this
78 * payload, so an observer sees the same vocabulary for both.
79 */
80export interface SubagentRunInfo {
81 /** Unique identity shared with the paired terminal event. */
82 readonly runId: SubagentRunId
83 /**
84 * Provider name recorded when the child was first created. The provider may
85 * be absent when an accepted one-shot run becomes ready or a persisted
86 * Activation cold-resumes, because neither lifecycle depends on continued
87 * registration.
88 */
89 readonly provider: string
90 /** The child agent's id. */
91 readonly id: SessionId
92 /** Snapshot of whether `SubagentRun.localAgent` was present when start fulfilled. */
93 readonly local: boolean
94}
95
96/**
97 * Observe-only outcome detail for a settled subagent run, carried by
98 * `subagent/end` and paired with one {@link SubagentRunInfo} by `runId`.
99 */
100export interface SubagentRunEndInfo {
101 /** Unique identity shared with the paired start event. */
102 readonly runId: SubagentRunId
103 /** The same provider name carried by the paired start event. */
104 readonly provider: string
105 /** The child agent's id. */
106 readonly id: SessionId
107 /** Snapshot of whether `SubagentRun.localAgent` was present when start fulfilled. */
108 readonly local: boolean
109 /** The terminal stop reason. */
110 readonly stopReason: SubagentResult['stopReason']
111 /**
112 * The child's final assistant output, selected by the same rule as
113 * {@link SubagentResult.output}; absent on infrastructure rejection or when
114 * the child produced none.
115 */
116 readonly lastAssistantMessage?: readonly ContentBlock[]
117}
118
119/**
120 * Which START-TIME features a provider supports. Checked by the service before delegating to
121 * {@link SubagentProvider.start}: a request that needs a capability the chosen provider lacks
122 * is rejected with a typed error rather than accepted-then-ignored (the "fail loud, no silent
123 * degradation" rule). These flags describe the ONE-SHOT
124 * {@link SubagentProvider.start} path, where the provider composes the child;
125 * continuable children are composed by the continuation manager itself and are
126 * gated by {@link SubagentProvider.prepareContinuable} instead. Each flag
127 * corresponds one-to-one to a {@link SubagentStartRequest} option: `depthLimit`
128 * to `maxDepth`; the other names match.
129 */
130export interface SubagentCapabilities {
131 readonly agentOptions: boolean
132 readonly outputSchema: boolean
133 readonly depthLimit: boolean
134 readonly toolFilter: boolean
135 readonly persona: boolean
136}
137
138/**
139 * What a caller asks for when starting a ONE-SHOT subagent. The tool layer
140 * builds this from the model's `{ description, prompt }` plus its own config;
141 * the service validates {@link SubagentCapabilities} against the named provider
142 * and resolves the durable descriptor before dispatching to
143 * {@link SubagentProvider.start}.
144 */
145export interface SubagentStartRequest {
146 /** Optional short display label persisted with a session-backed child. */
147 readonly label?: string
148 /** Content delivered as the child's user message. */
149 readonly prompt: ContentBlock[]
150 /**
151 * The spawning agent. In-process providers derive workspace, lineage, and
152 * delegation depth from its durable session state. ACP reads only its cwd,
153 * and only when no deployment `cwd` override is configured.
154 */
155 readonly parent: Agent
156 /**
157 * Cancellation signal from the spawning context (the tool's `exec.signal`).
158 * This is the canonical cancellation channel both before and after startup:
159 * a provider rejects `start()` after cleaning partial resources when it
160 * fires before the run is published, and cancels the published run's
161 * remaining turn work when it fires afterward.
162 */
163 readonly signal: AbortSignal
164 /**
165 * Optional host-Agent provider, model, reasoning-effort, and output-token
166 * overrides. Requires {@link SubagentCapabilities.agentOptions}; in-process
167 * providers merge them over the parent Agent's options when they create the
168 * child, while the DSH SDK provider merges them over its instance defaults
169 * before initializing the separate child runtime.
170 */
171 readonly agentOptions?: AgentOptions
172 /**
173 * Object-rooted JSON Schema within `assertObjectJsonSchema`'s enforced subset. Start rejects
174 * unsupported schemas or providers without the capability. Data must be plain host-realm JSON;
175 * a successful child returns the matching value as {@link SubagentResult.structured}.
176 */
177 readonly outputSchema?: ObjectJsonSchema
178 /**
179 * Optional absolute delegation-depth cap for the child being started: its
180 * computed depth must be less than or equal to this non-negative safe
181 * integer. Requires {@link SubagentCapabilities.depthLimit}; rejected at
182 * start otherwise.
183 */
184 readonly maxDepth?: number
185 /**
186 * Optional child tool scoping. Requires {@link SubagentCapabilities.toolFilter};
187 * rejected at start otherwise. In-process backends apply it as a scoped
188 * `tools.restrict()` in the child's creation window: the named tools vanish
189 * from the child's prompt AND refuse to execute (one visibility), with loud
190 * unknown-name validation.
191 */
192 readonly toolFilter?: ToolRestriction
193 /**
194 * Optional per-child persona. Requires {@link SubagentCapabilities.persona};
195 * rejected at start otherwise. In-process backends register it as a scoped
196 * `deployment:persona-prefix` section on the child, SHADOWING the deployment's
197 * persona for this child alone — same template semantics as the deployment
198 * persona (strict `{{…}}` interpolation against the registered variables).
199 */
200 readonly persona?: string
201}
202
203/**
204 * Provider-facing one-shot request after {@link SubagentRuntime.start} resolves
205 * the durable child descriptor.
206 */
207export interface ResolvedSubagentStartRequest extends SubagentStartRequest {
208 /** Detached descriptor a session-backed provider persists in the child log. */
209 readonly descriptor: SubagentDescriptorData
210}
211
212/**
213 * What the continuation manager asks a provider for while materializing one
214 * continuable child's FIRST activation. The manager has already reserved the
215 * durable child identity and owns every later operation, so this request
216 * carries only what distinguishes a fresh child from one seeded with parent
217 * history.
218 */
219export interface ContinuableCreateRequest {
220 /** The reserved durable child session id, for provider diagnostics. */
221 readonly sessionId: SessionId
222 /** The delegating parent agent whose history a seeding provider reads. */
223 readonly parent: Agent
224 /**
225 * Caller cancellation, which owns preparation only until the manager accepts
226 * the initial prompt into the child's inbox.
227 */
228 readonly signal: AbortSignal
229}
230
231/**
232 * A provider's detached contribution to one continuable child's creation. This
233 * is DATA, never a capability: it carries no Agent, `AgentHandle`, prompt
234 * delivery, result, disposal, or resume operation, because the continuation
235 * manager owns the child's whole lifecycle after preparation.
236 */
237export interface ContinuableCreateSpec {
238 /**
239 * Completed-turn prefix of the parent's log to seed the child session with,
240 * or absent for a fresh child. Same durable contract as
241 * `CreateAgentOptions.seed`: contiguous from seq 0, lossless JSON, balanced.
242 */
243 readonly seed?: readonly SessionEvent[]
244}
245
246/**
247 * Why a subagent run ended. Merge-extensible (a backend may add variants);
248 * consumers branch on the known cases and fall through `default`. The known
249 * cases mirror the harness turn-end vocabulary so the tool layer can map a
250 * non-`completed` result to an `isError` tool result.
251 */
252export interface SubagentStopReasonMap {
253 /** The child finished its turn normally. */
254 completed: 'completed'
255 /** Cancelled through the request signal or disposal. */
256 aborted: 'aborted'
257 /** Model or transport failure. */
258 error: 'error'
259 /** The child hit its token ceiling before finishing. */
260 'max-tokens': 'max-tokens'
261 /** The child declined the task. */
262 refusal: 'refusal'
263}
264
265/** The union over {@link SubagentStopReasonMap} — widens automatically as backends merge in variants. */
266export type SubagentStopReason = SubagentStopReasonMap[keyof SubagentStopReasonMap]
267
268/**
269 * The terminal outcome of a subagent run, resolved by {@link SubagentRun.result}.
270 */
271export interface SubagentResult {
272 /**
273 * The child's final assistant output is the content of its last non-empty
274 * assistant message. Empty-content messages, including usage-only messages,
275 * are skipped. Without a non-empty message, the output is its accumulated
276 * assistant text stream, or `[]` when the child produced neither.
277 */
278 readonly output: readonly ContentBlock[]
279 /**
280 * The structured result after a requested `outputSchema` was successfully
281 * satisfied. Requesting a schema does not guarantee presence: a provider can
282 * end with `stopReason: 'error'` when the child fails or finishes without a
283 * valid capture. The structured value is validated against the requested
284 * output schema by the provider; `unknown` here because the seam is
285 * schema-agnostic.
286 */
287 readonly structured?: unknown
288 /**
289 * Provider-authored, non-assistant failure detail for a non-`completed`
290 * result. Providers keep this text free of tool inputs, file contents,
291 * environment values, credentials, and raw protocol payloads, and limit it
292 * to 4096 UTF-8 bytes. Consumers present it separately from {@link output}.
293 */
294 readonly diagnostic?: string
295 /** Why the run ended. A non-`completed` reason means `output` may be partial. */
296 readonly stopReason: SubagentStopReason
297}
298
299/**
300 * ONE-SHOT child handle returned after publication. Prompt submission, turn
301 * work, and infrastructure faults after that boundary belong to {@link result}.
302 * Consumers await that result and must always {@link dispose} to cancel
303 * remaining work and reach quiescence. A run is one disposable foreground
304 * delegation with one result; continuable conversations have no run — the
305 * continuation manager holds their `AgentHandle` directly and orders every
306 * turn through the child's own inbox.
307 */
308export interface SubagentRun {
309 /**
310 * Parent-scoped run id. For a local run, this MUST equal the published child
311 * session id, whose `parentSession` records `request.parent.session.id`; a
312 * remote provider mints an id unique in the parent namespace.
313 */
314 readonly id: SessionId
315 /**
316 * The exact published in-process child, or `undefined` for a remote run.
317 * When present, its id is {@link id}; the provider retains no ownership
318 * implication beyond the run's ordinary {@link dispose} contract.
319 */
320 readonly localAgent: Agent | undefined
321 /**
322 * Resolves with the child's terminal {@link SubagentResult} when the run
323 * settles. Does NOT reject on a child-level failure — a model/transport
324 * failure resolves with `stopReason: 'error'` so the consumer maps it to an
325 * `isError` tool result. Rejects on an infrastructure fault the seam cannot
326 * represent as a stop reason.
327 */
328 readonly result: Promise<SubagentResult>
329 /**
330 * Cancel remaining work, reach child quiescence, and release resources.
331 * Idempotent.
332 */
333 dispose(): Promise<void>
334}
335
336/**
337 * One registered transport for running child agents. Providers are trusted
338 * same-process implementations; callers treat descriptors and returned values
339 * as borrowed immutable data. The service may call one provider concurrently
340 * for distinct children. Providers isolate operation-local mutable state; a
341 * shared capacity controller may delay an operation but must not couple its
342 * settlement or cleanup to a sibling.
343 */
344export interface SubagentProvider {
345 /** Unique registry name (e.g. `spawn`, `fork`, `acp`). */
346 readonly name: string
347 /** The start-time features this provider supports (see {@link SubagentCapabilities}). */
348 readonly capabilities: SubagentCapabilities
349 /**
350 * Whether the child sees the parent's completed-turn prefix. This is descriptive, not a
351 * service-validated start capability: the model-facing tool derives truthful wording from it.
352 * It says nothing about tool registration, injected services, or authority inheritance.
353 */
354 readonly inheritsParentContext: boolean
355 /**
356 * Optional static provider-owned provider/model route for one-shot Agent
357 * options. Consumers merge tool/model overrides over these values before
358 * preflight; providers whose route derives from the parent omit it. The value
359 * is detached immutable data and requires `agentOptions` support.
360 */
361 readonly agentRouteDefaults?: Readonly<{ provider: string; model: string }>
362 /**
363 * Establish a ONE-SHOT child and return its handle after publication.
364 * The service has already validated that every requested start-time
365 * capability is supported and resolved `request.descriptor`, so a
366 * session-backed implementation appends that descriptor inside the child's
367 * initial turn. Before fulfillment, the provider owns setup and cleans any
368 * unpublished partial resources before rejecting. Ownership transfers on
369 * fulfillment; subsequent turn or infrastructure failure settles through
370 * the returned run. Distinct starts may overlap; cancellation, failure,
371 * result settlement, and disposal remain independent for each run.
372 */
373 start(request: ResolvedSubagentStartRequest): Promise<SubagentRun>
374 /**
375 * OPTIONAL (continuable-creation capability): contribute the detached
376 * creation inputs that distinguish this provider's continuable children —
377 * only whether the child session is seeded with parent history. Method
378 * presence IS the capability: the service rejects continuable starts on
379 * providers without it, while a provider that has it may still serve
380 * ordinary one-shot delegations.
381 *
382 * This is the provider's ONLY participation in a continuable child. The
383 * continuation manager owns identity reservation, composition, Agent
384 * creation, prompt delivery, cold resume, ownership, and disposal, so a
385 * provider never sees the child's Agent, handle, turns, or teardown.
386 * Distinct preparations may overlap; each follows its own signal and returns
387 * data belonging only to `request.sessionId`.
388 */
389 prepareContinuable?(request: ContinuableCreateRequest): Promise<ContinuableCreateSpec>
390}