@qlzt/dsh-subagent 0.0.0-stage → 0.2.1-alpha.3
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/LICENSE +21 -0
- package/README.i18n.yaml +94 -0
- package/README.md +215 -2
- package/README.zh.md +216 -0
- package/lib/index.js +3333 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +991 -0
- package/lib/typert.remote-client.d.ts +25 -0
- package/lib/typert.remote-client.js +114 -0
- package/lib/types/activation.d.ts +114 -0
- package/lib/types/activation.js +112 -0
- package/lib/types/archive-admission.d.ts +16 -0
- package/lib/types/archive-admission.js +151 -0
- package/lib/types/assistant-output.d.ts +48 -0
- package/lib/types/assistant-output.js +73 -0
- package/lib/types/catalog.d.ts +92 -0
- package/lib/types/catalog.js +113 -0
- package/lib/types/child-agent.d.ts +154 -0
- package/lib/types/child-agent.js +211 -0
- package/lib/types/client.d.ts +8 -0
- package/lib/types/client.js +7 -0
- package/lib/types/continuation-messages.d.ts +63 -0
- package/lib/types/continuation-messages.js +114 -0
- package/lib/types/control-types.d.ts +142 -0
- package/lib/types/control-types.js +8 -0
- package/lib/types/control.d.ts +45 -0
- package/lib/types/control.js +79 -0
- package/lib/types/depth.d.ts +31 -0
- package/lib/types/depth.js +39 -0
- package/lib/types/descriptor.d.ts +105 -0
- package/lib/types/descriptor.js +192 -0
- package/lib/types/error.d.ts +11 -0
- package/lib/types/error.js +14 -0
- package/lib/types/index.d.ts +319 -0
- package/lib/types/index.js +455 -0
- package/lib/types/internal.d.ts +58 -0
- package/lib/types/internal.js +58 -0
- package/lib/types/lifecycle.d.ts +83 -0
- package/lib/types/lifecycle.js +115 -0
- package/lib/types/list-children.d.ts +36 -0
- package/lib/types/list-children.js +166 -0
- package/lib/types/manager.d.ts +247 -0
- package/lib/types/manager.js +1294 -0
- package/lib/types/out-of-process.d.ts +92 -0
- package/lib/types/out-of-process.js +178 -0
- package/lib/types/projection-types.d.ts +85 -0
- package/lib/types/projection-types.js +7 -0
- package/lib/types/projection.d.ts +100 -0
- package/lib/types/projection.js +157 -0
- package/lib/types/structured.d.ts +49 -0
- package/lib/types/structured.js +130 -0
- package/lib/types/types.d.ts +353 -0
- package/lib/types/types.js +19 -0
- package/package.json +136 -4
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Child-scoped structured-output tool, prompt instruction, terminal guard, and authoritative
|
|
3
|
+
* result capture for in-process subagents. Each child registers its real schema on its own
|
|
4
|
+
* scope, so concurrent runs do not interact and disposal leaves no global residue. The prompt
|
|
5
|
+
* contribution is ordinary reconstructed request state.
|
|
6
|
+
*
|
|
7
|
+
* Capture commits only after the authoritative `tools/result` succeeds; PTC mode capture also
|
|
8
|
+
* waits for the enclosing `run_code` result. The terminal result marker and monotonic tool
|
|
9
|
+
* guard prevent later calls from reopening a completed structured run.
|
|
10
|
+
* @module @qlzt/dsh-subagent/structured
|
|
11
|
+
*/
|
|
12
|
+
import { ToolArgsError, validateJsonSchemaValue } from '@qlzt/dsh-tools';
|
|
13
|
+
/** The model-facing tool name a structured child must call to finish. */
|
|
14
|
+
export const STRUCTURED_OUTPUT_TOOL = 'structured_output';
|
|
15
|
+
/**
|
|
16
|
+
* The instruction registered as the child's trailing scoped prompt section:
|
|
17
|
+
* the demand travels with the
|
|
18
|
+
* tool, as ordinary prompt state of exactly one agent.
|
|
19
|
+
*/
|
|
20
|
+
export const STRUCTURED_OUTPUT_INSTRUCTION = 'When you have your final answer, you MUST report it by calling the '
|
|
21
|
+
+ `\`${STRUCTURED_OUTPUT_TOOL}\` tool with arguments matching its parameter schema exactly. `
|
|
22
|
+
+ 'Do not finish with a plain text answer: only the tool call counts as your result.';
|
|
23
|
+
/**
|
|
24
|
+
* Attach the scoped capture tool, instruction, and enforcement to a child during
|
|
25
|
+
* its creation window. Child disposal removes every registration.
|
|
26
|
+
* @param childCtx - the child agent's scope context (`setup`'s argument).
|
|
27
|
+
* @param schema - the trusted, already-asserted schema subset to enforce (see
|
|
28
|
+
* `assertObjectJsonSchema` in dsh-tools).
|
|
29
|
+
* @param canComplete - whether accepted input and owned child work have finished.
|
|
30
|
+
* @returns the attachment handle (read `captured()` after the child settles).
|
|
31
|
+
*/
|
|
32
|
+
export function attachStructuredRuntime(childCtx, schema, canComplete) {
|
|
33
|
+
/**
|
|
34
|
+
* Validated values staged by the capture tool body, awaiting THEIR OWN
|
|
35
|
+
* authoritative `tools/result` notification. The execution object's identity
|
|
36
|
+
* uniquely identifies a trip through the pipeline: adapter call ids may
|
|
37
|
+
* repeat across steps, but another execution can never reach this Map
|
|
38
|
+
* entry. This is distinct from the opaque `ToolExecutionToken` used to
|
|
39
|
+
* correlate nested transports. The final notification always deletes its own
|
|
40
|
+
* stage, whether the result succeeded or failed.
|
|
41
|
+
*/
|
|
42
|
+
const staged = new Map();
|
|
43
|
+
/** Successful nested capture waiting for its enclosing transport to commit. */
|
|
44
|
+
let pending;
|
|
45
|
+
let captured;
|
|
46
|
+
const schemaEntry = {
|
|
47
|
+
name: STRUCTURED_OUTPUT_TOOL,
|
|
48
|
+
description: 'Report your final structured result. Call this exactly once, when your answer is complete; '
|
|
49
|
+
+ 'the arguments must match this tool\'s parameter schema exactly.',
|
|
50
|
+
parameters: { ...schema },
|
|
51
|
+
};
|
|
52
|
+
childCtx.tools.register({
|
|
53
|
+
...schemaEntry,
|
|
54
|
+
output: {
|
|
55
|
+
schema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: { recorded: { type: 'boolean', const: true } },
|
|
58
|
+
required: ['recorded'],
|
|
59
|
+
additionalProperties: false,
|
|
60
|
+
},
|
|
61
|
+
render: () => [{ type: 'text', text: 'Structured output recorded.' }],
|
|
62
|
+
},
|
|
63
|
+
execute(args, exec) {
|
|
64
|
+
const violations = validateJsonSchemaValue(schema, args);
|
|
65
|
+
// ToolArgsError → isError result with INVALID_ARGS: the model retries
|
|
66
|
+
// within the same turn, exactly like a schema-validated defineTool call.
|
|
67
|
+
if (violations.length > 0)
|
|
68
|
+
throw new ToolArgsError(violations);
|
|
69
|
+
if (!canComplete())
|
|
70
|
+
throw new Error('Wait for all delegated child tasks to finish and process pending messages before submitting structured output.');
|
|
71
|
+
// Two-phase commit, keyed by THIS execution: later transformable
|
|
72
|
+
// waterfalls may still turn the success into an error. ToolRuntime has
|
|
73
|
+
// already frozen model-bound arguments at the actual input boundary.
|
|
74
|
+
staged.set(exec, { value: args });
|
|
75
|
+
exec.concludeTurn();
|
|
76
|
+
return Promise.resolve({ recorded: true });
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
childCtx.systemPrompt.section({
|
|
80
|
+
name: `tool:${STRUCTURED_OUTPUT_TOOL}`,
|
|
81
|
+
order: childCtx.systemPrompt.getSectionOrder('STRUCTURED_OUTPUT'),
|
|
82
|
+
text: STRUCTURED_OUTPUT_INSTRUCTION,
|
|
83
|
+
});
|
|
84
|
+
// Terminal WITHIN the step. Guards run after the whole pre-execute
|
|
85
|
+
// waterfall and compose monotonically (deny or abstain, never allow), so a
|
|
86
|
+
// later prepended listener cannot resurrect dispatch. Calls that precede
|
|
87
|
+
// capture in the same response remain untouched.
|
|
88
|
+
childCtx.tools.guard(exec => captured === undefined && pending === undefined
|
|
89
|
+
? undefined
|
|
90
|
+
: `structured output already recorded: the run is complete, so \`${exec.name}\` is not executed`);
|
|
91
|
+
// The capture COMMIT observes the immutable, authoritative result after the
|
|
92
|
+
// complete pipeline and outer error normalization. This notification cannot
|
|
93
|
+
// transform the outcome, so there is no wrapper outside the commit verdict.
|
|
94
|
+
childCtx.on('tools/result', function (exec, result) {
|
|
95
|
+
if (exec.name === STRUCTURED_OUTPUT_TOOL) {
|
|
96
|
+
const entry = staged.get(exec);
|
|
97
|
+
if (entry === undefined)
|
|
98
|
+
return;
|
|
99
|
+
staged.delete(exec);
|
|
100
|
+
if (result.isError)
|
|
101
|
+
return;
|
|
102
|
+
if (exec.parent === undefined) {
|
|
103
|
+
/* v8 ignore else -- sequential agent-loop dispatch lets the guard block every later supported call */
|
|
104
|
+
if (captured === undefined)
|
|
105
|
+
captured = { value: entry.value };
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
/* v8 ignore else -- PTC mode serializes sub-dispatches, so the guard blocks every later supported call */
|
|
109
|
+
if (captured === undefined && pending === undefined) {
|
|
110
|
+
pending = { parent: exec.parent, value: entry.value };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (pending?.parent !== exec.token)
|
|
116
|
+
return;
|
|
117
|
+
const entry = pending;
|
|
118
|
+
pending = undefined;
|
|
119
|
+
if (result.isError)
|
|
120
|
+
return;
|
|
121
|
+
/* v8 ignore else -- PTC mode serializes outer executions, so the guard blocks every later supported call */
|
|
122
|
+
if (captured === undefined)
|
|
123
|
+
captured = { value: entry.value };
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
captured: () => captured,
|
|
127
|
+
acceptsInput: () => staged.size === 0 && pending === undefined && captured === undefined,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=structured.js.map
|
|
@@ -0,0 +1,353 @@
|
|
|
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
|
+
* manager host in `./manager.ts` — so this module stays the published
|
|
7
|
+
* surface rather than a bag of everything type-shaped.
|
|
8
|
+
*
|
|
9
|
+
* @module @qlzt/dsh-subagent/types
|
|
10
|
+
*/
|
|
11
|
+
import type { Agent, AgentOptions } from '@qlzt/dsh-agent';
|
|
12
|
+
import type { Branded } from '@qlzt/dsh-brand';
|
|
13
|
+
import type { ContentBlock, MessageId } from '@qlzt/dsh-llm';
|
|
14
|
+
import type { SessionEvent, SessionId } from '@qlzt/dsh-session';
|
|
15
|
+
import type { ObjectJsonSchema, ToolRestriction } from '@qlzt/dsh-tools';
|
|
16
|
+
/** Identifies one accepted subagent run across its lifecycle event pair. */
|
|
17
|
+
export type SubagentRunId = Branded<'SubagentRunId'>;
|
|
18
|
+
/**
|
|
19
|
+
* Brand a string as a {@link SubagentRunId}.
|
|
20
|
+
* @param id - the raw run id.
|
|
21
|
+
* @returns the same string, branded.
|
|
22
|
+
*/
|
|
23
|
+
export declare function SubagentRunId(id: string): SubagentRunId;
|
|
24
|
+
/** One managed child execution and its result delivery policy. */
|
|
25
|
+
export interface SubagentActivationSpec {
|
|
26
|
+
/** Registered backend to use. */
|
|
27
|
+
readonly provider: string;
|
|
28
|
+
/** Short task label retained in cataloged child membership. */
|
|
29
|
+
readonly label: string;
|
|
30
|
+
/** Optional reserved identity for a local child; external backends allocate their own ids. */
|
|
31
|
+
readonly childId?: SessionId;
|
|
32
|
+
/** Task, parent, and backend-supported execution options. */
|
|
33
|
+
readonly request: Omit<SubagentStartRequest, 'label' | 'signal'>;
|
|
34
|
+
/** Cancellation before publication; callers own later cancellation through dispose. */
|
|
35
|
+
readonly signal: AbortSignal;
|
|
36
|
+
/** Parent delivery notifies the model; caller delivery only returns the result. Local children always enter the parent catalog. */
|
|
37
|
+
readonly delivery: 'parent' | 'caller';
|
|
38
|
+
}
|
|
39
|
+
/** A managed execution; disposal addresses this exact activation, never a later resume. */
|
|
40
|
+
export interface SubagentActivation {
|
|
41
|
+
/** Stable identity of the child. */
|
|
42
|
+
readonly childId: SessionId;
|
|
43
|
+
/** Accepted inbox message, when the backend has a local inbox. */
|
|
44
|
+
readonly messageId?: MessageId;
|
|
45
|
+
/**
|
|
46
|
+
* Execution result after teardown settles and notifications are sent; capture failures reject.
|
|
47
|
+
* Teardown failures are reported by dispose() without replacing a captured result.
|
|
48
|
+
*/
|
|
49
|
+
readonly result: Promise<SubagentResult>;
|
|
50
|
+
/** Stop and release this activation and its owned descendants; rejects on teardown failure. */
|
|
51
|
+
dispose(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Authority under which one interrupt request is admitted. `user` carries the
|
|
55
|
+
* durable direct-parent address a human client presented; `ancestor` carries
|
|
56
|
+
* the exact live Agent object whose recorded lineage must contain the caller.
|
|
57
|
+
*/
|
|
58
|
+
export type SubagentInterruptAuthority = {
|
|
59
|
+
readonly kind: 'user';
|
|
60
|
+
readonly parentSessionId: SessionId;
|
|
61
|
+
} | {
|
|
62
|
+
readonly kind: 'ancestor';
|
|
63
|
+
readonly agent: Agent;
|
|
64
|
+
};
|
|
65
|
+
/** Options for one model-authored message between adjacent Agents. */
|
|
66
|
+
export interface SubagentSendMessageOptions {
|
|
67
|
+
/** Caller cancellation, owning the operation only until inbox acceptance. */
|
|
68
|
+
readonly signal: AbortSignal;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Observe-only identifying detail for a published subagent run, carried by
|
|
72
|
+
* `subagent/start`. Local and external activations share this payload.
|
|
73
|
+
*/
|
|
74
|
+
export interface SubagentRunInfo {
|
|
75
|
+
/** Unique identity shared with the paired terminal event. */
|
|
76
|
+
readonly runId: SubagentRunId;
|
|
77
|
+
/**
|
|
78
|
+
* Provider name recorded when the child was first created, retained even
|
|
79
|
+
* after that provider is unregistered.
|
|
80
|
+
*/
|
|
81
|
+
readonly provider: string;
|
|
82
|
+
/** The child agent's id. */
|
|
83
|
+
readonly id: SessionId;
|
|
84
|
+
/** Whether this activation owns a local Agent, fixed at publication. */
|
|
85
|
+
readonly local: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Observe-only outcome detail for a settled subagent run, carried by
|
|
89
|
+
* `subagent/end` and paired with one {@link SubagentRunInfo} by `runId`.
|
|
90
|
+
*/
|
|
91
|
+
export interface SubagentRunEndInfo {
|
|
92
|
+
/** Unique identity shared with the paired start event. */
|
|
93
|
+
readonly runId: SubagentRunId;
|
|
94
|
+
/** The same provider name carried by the paired start event. */
|
|
95
|
+
readonly provider: string;
|
|
96
|
+
/** The child agent's id. */
|
|
97
|
+
readonly id: SessionId;
|
|
98
|
+
/** Whether this activation owns a local Agent, fixed at publication. */
|
|
99
|
+
readonly local: boolean;
|
|
100
|
+
/** The terminal stop reason. */
|
|
101
|
+
readonly stopReason: SubagentResult['stopReason'];
|
|
102
|
+
/**
|
|
103
|
+
* The child's final assistant output, selected by the same rule as
|
|
104
|
+
* {@link SubagentResult.output}; absent on infrastructure rejection or when
|
|
105
|
+
* the child produced none.
|
|
106
|
+
*/
|
|
107
|
+
readonly lastAssistantMessage?: readonly ContentBlock[];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Start-time options supported by a registered backend. The manager checks
|
|
111
|
+
* every requested option before preparing a local child or starting an external
|
|
112
|
+
* execution. depthLimit controls maxDepth; the remaining flag names match
|
|
113
|
+
* SubagentStartRequest fields.
|
|
114
|
+
*/
|
|
115
|
+
export interface SubagentCapabilities {
|
|
116
|
+
readonly agentOptions: boolean;
|
|
117
|
+
readonly outputSchema: boolean;
|
|
118
|
+
readonly depthLimit: boolean;
|
|
119
|
+
readonly toolFilter: boolean;
|
|
120
|
+
readonly persona: boolean;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Task and optional capabilities supplied to a backend. startActivation carries
|
|
124
|
+
* these fields in request while owning its label, cancellation, and delivery
|
|
125
|
+
* policy separately.
|
|
126
|
+
*/
|
|
127
|
+
export interface SubagentStartRequest {
|
|
128
|
+
/** Initial child directory; relative paths resolve against the parent's current directory. Omitted inherits that directory at start. */
|
|
129
|
+
readonly cwd?: string;
|
|
130
|
+
/** Optional short display label persisted with a session-backed child. */
|
|
131
|
+
readonly label?: string;
|
|
132
|
+
/** Content delivered as the child's user message. */
|
|
133
|
+
readonly prompt: ContentBlock[];
|
|
134
|
+
/**
|
|
135
|
+
* The spawning agent. Its effective directory supplies the default cwd;
|
|
136
|
+
* in-process children retain its origin, lineage, and delegation depth.
|
|
137
|
+
*/
|
|
138
|
+
readonly parent: Agent;
|
|
139
|
+
/**
|
|
140
|
+
* Cancellation signal from the spawning context (the tool's `exec.signal`).
|
|
141
|
+
* This is the canonical cancellation channel both before and after startup:
|
|
142
|
+
* a provider rejects `start()` after cleaning partial resources when it
|
|
143
|
+
* fires before the run is published, and cancels the published run's
|
|
144
|
+
* remaining turn work when it fires afterward.
|
|
145
|
+
*/
|
|
146
|
+
readonly signal: AbortSignal;
|
|
147
|
+
/**
|
|
148
|
+
* Optional host-Agent provider, model, reasoning-effort, and output-token
|
|
149
|
+
* overrides. Requires {@link SubagentCapabilities.agentOptions}; in-process
|
|
150
|
+
* providers merge them over the parent Agent's options when they create the
|
|
151
|
+
* child, while the DSH SDK provider merges them over its instance defaults
|
|
152
|
+
* before initializing the separate child runtime.
|
|
153
|
+
*/
|
|
154
|
+
readonly agentOptions?: AgentOptions;
|
|
155
|
+
/**
|
|
156
|
+
* Object-rooted JSON Schema within `assertObjectJsonSchema`'s enforced subset. Start rejects
|
|
157
|
+
* unsupported schemas or providers without the capability. Data must be plain host-realm JSON;
|
|
158
|
+
* a successful child returns the matching value as {@link SubagentResult.structured}.
|
|
159
|
+
*/
|
|
160
|
+
readonly outputSchema?: ObjectJsonSchema;
|
|
161
|
+
/**
|
|
162
|
+
* Optional absolute delegation-depth cap for the child being started: its
|
|
163
|
+
* computed depth must be less than or equal to this non-negative safe
|
|
164
|
+
* integer. Requires {@link SubagentCapabilities.depthLimit}; rejected at
|
|
165
|
+
* start otherwise.
|
|
166
|
+
*/
|
|
167
|
+
readonly maxDepth?: number;
|
|
168
|
+
/**
|
|
169
|
+
* Optional child tool scoping. Requires {@link SubagentCapabilities.toolFilter};
|
|
170
|
+
* rejected at start otherwise. In-process backends apply it as a scoped
|
|
171
|
+
* `tools.restrict()` in the child's creation window: the named tools vanish
|
|
172
|
+
* from the child's prompt AND refuse to execute (one visibility), with loud
|
|
173
|
+
* unknown-name validation.
|
|
174
|
+
*/
|
|
175
|
+
readonly toolFilter?: ToolRestriction;
|
|
176
|
+
/**
|
|
177
|
+
* Optional per-child persona. Requires {@link SubagentCapabilities.persona};
|
|
178
|
+
* rejected at start otherwise. In-process backends register it as a scoped
|
|
179
|
+
* `deployment:persona-prefix` section on the child, SHADOWING the deployment's
|
|
180
|
+
* persona for this child alone — same template semantics as the deployment
|
|
181
|
+
* persona (strict `{{…}}` interpolation against the registered variables).
|
|
182
|
+
*/
|
|
183
|
+
readonly persona?: string;
|
|
184
|
+
}
|
|
185
|
+
/** Provider-facing request with an absolute directory selected before startup. */
|
|
186
|
+
export interface ResolvedSubagentStartRequest extends SubagentStartRequest {
|
|
187
|
+
/** Absolute child directory captured from the parent or explicit request. */
|
|
188
|
+
readonly cwd: string;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* What the continuation manager asks a provider for while materializing one
|
|
192
|
+
* continuable child's FIRST activation. The manager has already reserved the
|
|
193
|
+
* durable child identity and owns every later operation, so this request
|
|
194
|
+
* carries only what distinguishes a fresh child from one seeded with parent
|
|
195
|
+
* history.
|
|
196
|
+
*/
|
|
197
|
+
export interface ContinuableCreateRequest {
|
|
198
|
+
/** Absolute initial directory captured before provider preparation. */
|
|
199
|
+
readonly cwd: string;
|
|
200
|
+
/** The reserved durable child session id, for provider diagnostics. */
|
|
201
|
+
readonly sessionId: SessionId;
|
|
202
|
+
/** The delegating parent agent whose history a seeding provider reads. */
|
|
203
|
+
readonly parent: Agent;
|
|
204
|
+
/**
|
|
205
|
+
* Caller cancellation, which owns preparation only until the manager accepts
|
|
206
|
+
* the initial prompt into the child's inbox.
|
|
207
|
+
*/
|
|
208
|
+
readonly signal: AbortSignal;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* A provider's detached contribution to one continuable child's creation. This
|
|
212
|
+
* is DATA, never a capability: it carries no Agent, `AgentHandle`, prompt
|
|
213
|
+
* delivery, result, disposal, or resume operation, because the continuation
|
|
214
|
+
* manager owns the child's whole lifecycle after preparation.
|
|
215
|
+
*/
|
|
216
|
+
export interface ContinuableCreateSpec {
|
|
217
|
+
/**
|
|
218
|
+
* Completed-turn prefix of the parent's log to seed the child session with,
|
|
219
|
+
* or absent for a fresh child. Same durable contract as
|
|
220
|
+
* `CreateAgentOptions.seed`: contiguous from seq 0, lossless JSON, balanced.
|
|
221
|
+
*/
|
|
222
|
+
readonly seed?: readonly SessionEvent[];
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Why a subagent run ended. Merge-extensible (a backend may add variants);
|
|
226
|
+
* consumers branch on the known cases and fall through `default`. The known
|
|
227
|
+
* cases mirror the harness turn-end vocabulary so the tool layer can map a
|
|
228
|
+
* non-`completed` result to an `isError` tool result.
|
|
229
|
+
*/
|
|
230
|
+
export interface SubagentStopReasonMap {
|
|
231
|
+
/** The child finished its turn normally. */
|
|
232
|
+
completed: 'completed';
|
|
233
|
+
/** Cancelled through the request signal or disposal. */
|
|
234
|
+
aborted: 'aborted';
|
|
235
|
+
/** Model or transport failure. */
|
|
236
|
+
error: 'error';
|
|
237
|
+
/** The child hit its token ceiling before finishing. */
|
|
238
|
+
'max-tokens': 'max-tokens';
|
|
239
|
+
/** The child declined the task. */
|
|
240
|
+
refusal: 'refusal';
|
|
241
|
+
}
|
|
242
|
+
/** The union over {@link SubagentStopReasonMap} — widens automatically as backends merge in variants. */
|
|
243
|
+
export type SubagentStopReason = SubagentStopReasonMap[keyof SubagentStopReasonMap];
|
|
244
|
+
/**
|
|
245
|
+
* The terminal outcome of a subagent run, resolved by {@link SubagentRun.result}.
|
|
246
|
+
*/
|
|
247
|
+
export interface SubagentResult {
|
|
248
|
+
/**
|
|
249
|
+
* The child's final assistant output is the content of its last non-empty
|
|
250
|
+
* assistant message. Empty-content messages, including usage-only messages,
|
|
251
|
+
* are skipped. Without a non-empty message, the output is its accumulated
|
|
252
|
+
* assistant text stream, or `[]` when the child produced neither.
|
|
253
|
+
*/
|
|
254
|
+
readonly output: readonly ContentBlock[];
|
|
255
|
+
/**
|
|
256
|
+
* The structured result after a requested `outputSchema` was successfully
|
|
257
|
+
* satisfied. Requesting a schema does not guarantee presence: a provider can
|
|
258
|
+
* end with `stopReason: 'error'` when the child fails or finishes without a
|
|
259
|
+
* valid capture. The structured value is validated against the requested
|
|
260
|
+
* output schema by the provider; `unknown` here because the seam is
|
|
261
|
+
* schema-agnostic.
|
|
262
|
+
*/
|
|
263
|
+
readonly structured?: unknown;
|
|
264
|
+
/**
|
|
265
|
+
* Provider-authored, non-assistant failure detail for a non-`completed`
|
|
266
|
+
* result. Providers keep this text free of tool inputs, file contents,
|
|
267
|
+
* environment values, credentials, and raw protocol payloads, and limit it
|
|
268
|
+
* to 4096 UTF-8 bytes. Consumers present it separately from {@link output}.
|
|
269
|
+
*/
|
|
270
|
+
readonly diagnostic?: string;
|
|
271
|
+
/** Why the run ended. A non-`completed` reason means `output` may be partial. */
|
|
272
|
+
readonly stopReason: SubagentStopReason;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Backend execution handle owned directly by the activation registry.
|
|
276
|
+
* A result may become available before resource release; the manager always
|
|
277
|
+
* disposes the handle and awaits cleanup. Backend startup failures clean up
|
|
278
|
+
* partial resources before rejecting, while accepted execution failures settle
|
|
279
|
+
* through result.
|
|
280
|
+
*/
|
|
281
|
+
export interface SubagentRun {
|
|
282
|
+
/** Provider-minted id, unique across all parents, providers, and local Sessions in this runtime. */
|
|
283
|
+
readonly id: SessionId;
|
|
284
|
+
/**
|
|
285
|
+
* Resolves with the child's terminal {@link SubagentResult} when the run
|
|
286
|
+
* settles. Does NOT reject on a child-level failure — a model/transport
|
|
287
|
+
* failure resolves with `stopReason: 'error'` so the consumer maps it to an
|
|
288
|
+
* `isError` tool result. Rejects on an infrastructure fault the seam cannot
|
|
289
|
+
* represent as a stop reason.
|
|
290
|
+
*/
|
|
291
|
+
readonly result: Promise<SubagentResult>;
|
|
292
|
+
/**
|
|
293
|
+
* Cancel remaining work, reach child quiescence, and release resources.
|
|
294
|
+
* Idempotent.
|
|
295
|
+
*/
|
|
296
|
+
dispose(): Promise<void>;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* One registered transport for running child agents. Providers are trusted
|
|
300
|
+
* same-process implementations; callers treat descriptors and returned values
|
|
301
|
+
* as borrowed immutable data. The service may call one provider concurrently
|
|
302
|
+
* for distinct children. Providers isolate operation-local mutable state; a
|
|
303
|
+
* shared capacity controller may delay an operation but must not couple its
|
|
304
|
+
* settlement or cleanup to a sibling.
|
|
305
|
+
*/
|
|
306
|
+
export interface SubagentProvider {
|
|
307
|
+
/** Unique registry name (e.g. `spawn`, `fork`, `acp`). */
|
|
308
|
+
readonly name: string;
|
|
309
|
+
/** The start-time features this provider supports (see {@link SubagentCapabilities}). */
|
|
310
|
+
readonly capabilities: SubagentCapabilities;
|
|
311
|
+
/**
|
|
312
|
+
* Whether the child sees the parent's completed-turn prefix. This is descriptive, not a
|
|
313
|
+
* service-validated start capability: the model-facing tool derives truthful wording from it.
|
|
314
|
+
* It says nothing about tool registration, injected services, or authority inheritance.
|
|
315
|
+
*/
|
|
316
|
+
readonly inheritsParentContext: boolean;
|
|
317
|
+
/**
|
|
318
|
+
* Optional static provider-owned provider/model route for child Agent
|
|
319
|
+
* options. Consumers merge tool/model overrides over these values before
|
|
320
|
+
* preflight; providers whose route derives from the parent omit it. The value
|
|
321
|
+
* is detached immutable data and requires `agentOptions` support.
|
|
322
|
+
*/
|
|
323
|
+
readonly agentRouteDefaults?: Readonly<{
|
|
324
|
+
provider: string;
|
|
325
|
+
model: string;
|
|
326
|
+
}>;
|
|
327
|
+
/**
|
|
328
|
+
* Establish one external execution and return its owned handle.
|
|
329
|
+
* The service has already validated that every requested start-time
|
|
330
|
+
* capability is supported. Before fulfillment, the provider owns setup and
|
|
331
|
+
* cleans any unpublished partial resources before rejecting. Ownership transfers on
|
|
332
|
+
* fulfillment; subsequent turn or infrastructure failure settles through
|
|
333
|
+
* the returned run. Distinct starts may overlap; cancellation, failure,
|
|
334
|
+
* result settlement, and disposal remain independent for each run.
|
|
335
|
+
*/
|
|
336
|
+
start?(request: ResolvedSubagentStartRequest): Promise<SubagentRun>;
|
|
337
|
+
/**
|
|
338
|
+
* OPTIONAL (continuable-creation capability): contribute the detached
|
|
339
|
+
* creation inputs that distinguish this provider's continuable children —
|
|
340
|
+
* only whether the child session is seeded with parent history. Method
|
|
341
|
+
* presence selects local activation execution. Providers without it execute
|
|
342
|
+
* through start and do not accept subsequent messages.
|
|
343
|
+
*
|
|
344
|
+
* This is the provider's ONLY participation in a continuable child. The
|
|
345
|
+
* continuation manager owns identity reservation, composition, Agent
|
|
346
|
+
* creation, prompt delivery, cold resume, ownership, and disposal, so a
|
|
347
|
+
* provider never sees the child's Agent, handle, turns, or teardown.
|
|
348
|
+
* Distinct preparations may overlap; each follows its own signal and returns
|
|
349
|
+
* data belonging only to `request.sessionId`.
|
|
350
|
+
*/
|
|
351
|
+
prepareContinuable?(request: ContinuableCreateRequest): Promise<ContinuableCreateSpec>;
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
* manager host in `./manager.ts` — so this module stays the published
|
|
7
|
+
* surface rather than a bag of everything type-shaped.
|
|
8
|
+
*
|
|
9
|
+
* @module @qlzt/dsh-subagent/types
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Brand a string as a {@link SubagentRunId}.
|
|
13
|
+
* @param id - the raw run id.
|
|
14
|
+
* @returns the same string, branded.
|
|
15
|
+
*/
|
|
16
|
+
export function SubagentRunId(id) {
|
|
17
|
+
return id;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,138 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qlzt/dsh-subagent",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"description": "Abstract subagent seam (ctx.subagents): named-provider registry for delegating to child agents",
|
|
4
|
+
"version": "0.2.1-alpha.3",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://gitee.com/zsping1989/deepseek-harness.git",
|
|
11
|
+
"directory": "packages/subagent/subagent"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/types/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./internal": {
|
|
22
|
+
"types": "./lib/types/internal.d.ts",
|
|
23
|
+
"default": "./lib/types/internal.js"
|
|
24
|
+
},
|
|
25
|
+
"./client": {
|
|
26
|
+
"types": "./lib/types/client.d.ts",
|
|
27
|
+
"default": "./lib/types/client.js"
|
|
28
|
+
},
|
|
29
|
+
"./typert": {
|
|
30
|
+
"types": "./lib/typert.host.d.ts",
|
|
31
|
+
"default": "./lib/typert.host.js"
|
|
32
|
+
},
|
|
33
|
+
"./remote": {
|
|
34
|
+
"types": "./lib/typert.remote-client.d.ts",
|
|
35
|
+
"default": "./lib/typert.remote-client.js"
|
|
36
|
+
},
|
|
37
|
+
"./src/*": "./src/*",
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"lib/index.js",
|
|
42
|
+
"lib/types/**/*.js",
|
|
43
|
+
"lib/types/**/*.d.ts",
|
|
44
|
+
"lib/typert.host.js",
|
|
45
|
+
"lib/typert.host.d.ts",
|
|
46
|
+
"lib/typert.remote-client.js",
|
|
47
|
+
"lib/typert.remote-client.d.ts"
|
|
48
|
+
],
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@qlzt/dsh-brand": "0.2.1-alpha.3",
|
|
52
|
+
"@qlzt/dsh-chunked-list": "0.2.1-alpha.3",
|
|
53
|
+
"@qlzt/dsh-util-values": "0.2.1-alpha.3",
|
|
54
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.1",
|
|
55
|
+
"zod": "^4.4.3"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
59
|
+
"@qlzt/dsh-agent": "0.2.1-alpha.3",
|
|
60
|
+
"@qlzt/dsh-agent-preset-registry": "0.2.1-alpha.3",
|
|
61
|
+
"@qlzt/dsh-attachment": "0.2.1-alpha.3",
|
|
62
|
+
"@qlzt/dsh-llm": "0.2.1-alpha.3",
|
|
63
|
+
"@qlzt/dsh-sandbox": "0.2.1-alpha.3",
|
|
64
|
+
"@qlzt/dsh-sandbox-policy": "0.2.1-alpha.3",
|
|
65
|
+
"@qlzt/dsh-scope": "0.2.1-alpha.3",
|
|
66
|
+
"@qlzt/dsh-session": "0.2.1-alpha.3",
|
|
67
|
+
"@qlzt/dsh-session-persistence": "0.2.1-alpha.3",
|
|
68
|
+
"@qlzt/dsh-session-projection": "0.2.1-alpha.3",
|
|
69
|
+
"@qlzt/dsh-session-query": "0.2.1-alpha.3",
|
|
70
|
+
"@qlzt/dsh-system-prompt": "0.2.1-alpha.3",
|
|
71
|
+
"@qlzt/dsh-tools": "0.2.1-alpha.3",
|
|
72
|
+
"@qlzt/dsh-typert-protocol": "0.2.1-alpha.3",
|
|
73
|
+
"@qlzt/dsh-user-approval": "0.2.1-alpha.3",
|
|
74
|
+
"@qlzt/dsh-util-time": "0.2.1-alpha.3",
|
|
75
|
+
"@qlzt/dsh-permission-presets": "0.2.1-alpha.3",
|
|
76
|
+
"@qlzt/dsh-workspace": "0.2.1-alpha.3",
|
|
77
|
+
"@qlzt/dsh-working-directory": "0.2.1-alpha.3"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"@deepseek-ai/dsh-agent-preset-registry": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"@deepseek-ai/dsh-permission-presets": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"@deepseek-ai/dsh-sandbox": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"@deepseek-ai/dsh-sandbox-policy": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@deepseek-ai/dsh-session-persistence": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@deepseek-ai/dsh-session-projection": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@deepseek-ai/dsh-session-query": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"@deepseek-ai/dsh-workspace": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"@deepseek-ai/dsh-user-approval": {
|
|
105
|
+
"optional": true
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"devDependencies": {
|
|
109
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
110
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.3",
|
|
111
|
+
"@deepseek-ai/dsh-agent-preset-registry": "0.2.1-alpha.3",
|
|
112
|
+
"@deepseek-ai/dsh-attachment": "0.2.1-alpha.3",
|
|
113
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.3",
|
|
114
|
+
"@deepseek-ai/dsh-sandbox": "0.2.1-alpha.3",
|
|
115
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.3",
|
|
116
|
+
"@deepseek-ai/dsh-scope": "0.2.1-alpha.3",
|
|
117
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.3",
|
|
118
|
+
"@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.3",
|
|
119
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.3",
|
|
120
|
+
"@deepseek-ai/dsh-session-query": "0.2.1-alpha.3",
|
|
121
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.3",
|
|
122
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.3",
|
|
123
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.3",
|
|
124
|
+
"@deepseek-ai/dsh-user-approval": "0.2.1-alpha.3",
|
|
125
|
+
"@deepseek-ai/dsh-util-time": "0.2.1-alpha.3",
|
|
126
|
+
"@deepseek-ai/dsh-permission-presets": "0.2.1-alpha.3",
|
|
127
|
+
"@deepseek-ai/dsh-workspace": "0.2.1-alpha.3",
|
|
128
|
+
"@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.1",
|
|
129
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
|
|
130
|
+
"@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.3",
|
|
131
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.3",
|
|
132
|
+
"@deepseek-ai/dsh-fs-sandbox": "0.2.1-alpha.3",
|
|
133
|
+
"@deepseek-ai/dsh-tool-fs": "0.2.1-alpha.3",
|
|
134
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.3",
|
|
135
|
+
"@deepseek-ai/dsh-working-directory": "0.2.1-alpha.3"
|
|
136
|
+
},
|
|
137
|
+
"dsh": {}
|
|
138
|
+
}
|