@deepseek-ai/dsh-subagent 0.2.1-alpha.1 → 0.2.1-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.
Files changed (41) hide show
  1. package/README.i18n.yaml +34 -34
  2. package/README.md +32 -26
  3. package/README.zh.md +32 -26
  4. package/lib/index.js +1436 -1304
  5. package/lib/typert.host.js +59 -48
  6. package/lib/typert.remote-client.js +2 -2
  7. package/lib/types/activation.d.ts +114 -0
  8. package/lib/types/activation.js +112 -0
  9. package/lib/types/catalog.d.ts +14 -6
  10. package/lib/types/catalog.js +34 -30
  11. package/lib/types/child-agent.d.ts +1 -3
  12. package/lib/types/child-agent.js +1 -3
  13. package/lib/types/continuation-messages.d.ts +4 -3
  14. package/lib/types/continuation-messages.js +13 -5
  15. package/lib/types/control-types.d.ts +7 -0
  16. package/lib/types/descriptor.d.ts +7 -46
  17. package/lib/types/descriptor.js +20 -21
  18. package/lib/types/index.d.ts +52 -51
  19. package/lib/types/index.js +75 -95
  20. package/lib/types/internal.d.ts +1 -1
  21. package/lib/types/lifecycle.d.ts +28 -58
  22. package/lib/types/lifecycle.js +9 -74
  23. package/lib/types/list-children.js +1 -1
  24. package/lib/types/manager.d.ts +247 -0
  25. package/lib/types/manager.js +1294 -0
  26. package/lib/types/out-of-process.d.ts +2 -28
  27. package/lib/types/out-of-process.js +3 -44
  28. package/lib/types/projection-types.d.ts +3 -0
  29. package/lib/types/structured.d.ts +49 -0
  30. package/lib/types/structured.js +130 -0
  31. package/lib/types/types.d.ts +57 -81
  32. package/lib/types/types.js +1 -1
  33. package/package.json +50 -49
  34. package/lib/types/continuation-activation.d.ts +0 -267
  35. package/lib/types/continuation-activation.js +0 -700
  36. package/lib/types/continuation.d.ts +0 -124
  37. package/lib/types/continuation.js +0 -455
  38. package/lib/types/inbox.d.ts +0 -43
  39. package/lib/types/inbox.js +0 -61
  40. package/lib/types/run-settlement.d.ts +0 -17
  41. package/lib/types/run-settlement.js +0 -70
@@ -1,124 +0,0 @@
1
- /**
2
- * Continuable-subagent orchestration behind `ctx.subagents`: stable child ids,
3
- * descriptor persistence, provider preparation, cold resume, authorization,
4
- * and message routing. {@link ContinuableActivationRegistry} owns the mutable
5
- * process-local Activation graph and its settlement and disposal lifecycle.
6
- *
7
- * A continuable child has one durable Session and at most one process-local
8
- * Activation. The Agent inbox is the only turn queue, so this manager owns
9
- * durable orchestration while the Agent loop owns all turn ordering and
10
- * execution. No continuable path creates a Task or an intermediate
11
- * result-bearing wrapper.
12
- *
13
- * @module @deepseek-ai/dsh-subagent
14
- */
15
- import type { Context } from '@deepseek-ai/cordis';
16
- import type { Agent } from '@deepseek-ai/dsh-agent';
17
- import type { ContentBlock, MessageId, MessageSource } from '@deepseek-ai/dsh-llm';
18
- import type { SessionId } from '@deepseek-ai/dsh-session';
19
- import type { ActivationObserver } from './lifecycle.ts';
20
- import type { ContinuableCreateRequest, ContinuableCreateSpec, ContinuableStart, ContinuableStartSpec, SubagentInterruptAuthority, SubagentSendMessageOptions } from './types.ts';
21
- /** Package-private hooks supplied by the owning service. */
22
- interface ContinuationHost {
23
- /** Resolve one provider's detached continuable-creation contribution. */
24
- prepareContinuable(name: string, request: ContinuableCreateRequest): Promise<ContinuableCreateSpec>;
25
- /** Build the lifecycle observer for one Activation residency epoch. */
26
- observeActivation(provider: string, childId: SessionId, parent: Agent): ActivationObserver;
27
- }
28
- /**
29
- * The continuable-subagent orchestration service behind `ctx.subagents`. Tool
30
- * schema and host adapters are consumers of this one contract; foreground
31
- * one-shot delegation keeps calling `ctx.subagents.start()` and never enters
32
- * this lifecycle.
33
- */
34
- export declare class SubagentContinuationManager {
35
- private readonly ctx;
36
- private readonly host;
37
- private readonly activations;
38
- constructor(ctx: Context, host: ContinuationHost, maxActiveSubagents: () => number);
39
- /**
40
- * Start one continuable background child and resolve at initial inbox acceptance.
41
- * Every earlier failure disposes any created handle and rolls back Activation
42
- * and parent ownership without returning either id.
43
- * @param spec - provider, delegation request, and caller cancellation.
44
- * @returns the durable child id and accepted initial prompt message id.
45
- */
46
- startContinuable(spec: ContinuableStartSpec): Promise<ContinuableStart>;
47
- /**
48
- * Deliver one model-authored message to a direct continuable child or to the
49
- * sender's direct parent. A missing direct child cold-resumes through the
50
- * ordinary continuation lifecycle.
51
- * @param sender - exact live Agent authorizing and originating the message.
52
- * @param targetId - durable direct-parent or direct-child session id.
53
- * @param content - model-authored content to deliver.
54
- * @param options - caller cancellation before acceptance.
55
- * @returns the accepted message's inbox id.
56
- */
57
- sendMessage(sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions): Promise<MessageId>;
58
- /**
59
- * Queue one human-authored prompt as a distinct direct-child turn.
60
- * @param parent - exact live direct parent authorizing delivery.
61
- * @param childId - durable direct-child session id.
62
- * @param content - model-visible prompt blocks.
63
- * @param source - durable attribution for the human prompt.
64
- * @param signal - caller cancellation before inbox acceptance.
65
- * @returns the accepted durable message id.
66
- */
67
- queuePrompt(parent: Agent, childId: SessionId, content: ContentBlock[], source: MessageSource, signal: AbortSignal): Promise<MessageId>;
68
- /**
69
- * Steer one host-authored prompt to a direct continuable child.
70
- * @param parent - exact live direct parent authorizing delivery.
71
- * @param childId - durable direct-child session id.
72
- * @param content - model-visible prompt blocks.
73
- * @param source - durable attribution for the host prompt.
74
- * @param signal - caller cancellation before inbox acceptance.
75
- * @returns the accepted durable message id.
76
- */
77
- steerPrompt(parent: Agent, childId: SessionId, content: ContentBlock[], source: MessageSource, signal: AbortSignal): Promise<MessageId>;
78
- /** Route one parent-originated delivery through residency and cold resume. */
79
- private deliverToChild;
80
- /** The delivery loop behind {@link deliverToChild}, run under the parent hold. */
81
- private deliverFollowup;
82
- /**
83
- * Interrupt one live continuable child's current turn. Admission is
84
- * synchronous and the cancellation effect is asynchronous. An absent or
85
- * already-closing target is an accepted no-op after authority checks.
86
- * @param targetSessionId - the durable child session id to interrupt.
87
- * @param authority - the human parent address or exact live ancestor Agent.
88
- */
89
- interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void;
90
- /** Deliver one resident continuable child's message to its live direct parent. */
91
- private sendToParent;
92
- /** Send one Agent message while translating only the target's own rejection. */
93
- private sendAgentMessage;
94
- /** Close manager-wide admission and release every live Activation. */
95
- drain(): Promise<void>;
96
- /**
97
- * Stop only the continuable descendants of exact live host-owned parents.
98
- * @param parents - exact live roots whose continuable descendants must stop.
99
- */
100
- drainDescendants(parents: readonly Agent[]): Promise<void>;
101
- /**
102
- * Release selected resident direct children of one exact live parent.
103
- * @param parent - exact live direct parent authorizing the selected release.
104
- * @param childIds - durable direct-child ids to release when resident.
105
- */
106
- drainChildren(parent: Agent, childIds: readonly SessionId[]): Promise<void>;
107
- /**
108
- * Cold-resume a persisted child and submit the waiting turn. The descriptor
109
- * supplies every reconstruction input; no subagent provider is dispatched.
110
- */
111
- private coldResume;
112
- /** Admit a materialized child, commit its creation fact, and release it on failure. */
113
- private submitMaterialized;
114
- /** Build and submit one message across the final synchronous admission cutoff. */
115
- private submitAdmitted;
116
- /** Refuse image content for a child whose fixed model accepts text only. */
117
- private assertImageCapable;
118
- /** Resolve the persistence service continuable children require, or fail loud. */
119
- private requirePersistence;
120
- /** Resolve the Session query service used for cold child observations. */
121
- private requireSessionQuery;
122
- }
123
- export default SubagentContinuationManager;
124
- //# sourceMappingURL=continuation.d.ts.map
@@ -1,455 +0,0 @@
1
- /**
2
- * Continuable-subagent orchestration behind `ctx.subagents`: stable child ids,
3
- * descriptor persistence, provider preparation, cold resume, authorization,
4
- * and message routing. {@link ContinuableActivationRegistry} owns the mutable
5
- * process-local Activation graph and its settlement and disposal lifecycle.
6
- *
7
- * A continuable child has one durable Session and at most one process-local
8
- * Activation. The Agent inbox is the only turn queue, so this manager owns
9
- * durable orchestration while the Agent loop owns all turn ordering and
10
- * execution. No continuable path creates a Task or an intermediate
11
- * result-bearing wrapper.
12
- *
13
- * @module @deepseek-ai/dsh-subagent
14
- */
15
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
16
- if (value !== null && value !== void 0) {
17
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
18
- var dispose, inner;
19
- if (async) {
20
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
21
- dispose = value[Symbol.asyncDispose];
22
- }
23
- if (dispose === void 0) {
24
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
25
- dispose = value[Symbol.dispose];
26
- if (async) inner = dispose;
27
- }
28
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
29
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
30
- env.stack.push({ value: value, dispose: dispose, async: async });
31
- }
32
- else if (async) {
33
- env.stack.push({ async: true });
34
- }
35
- return value;
36
- };
37
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
38
- return function (env) {
39
- function fail(e) {
40
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
41
- env.hasError = true;
42
- }
43
- var r, s = 0;
44
- function next() {
45
- while (r = env.stack.pop()) {
46
- try {
47
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
48
- if (r.dispose) {
49
- var result = r.dispose.call(r.value);
50
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
51
- }
52
- else s |= 1;
53
- }
54
- catch (e) {
55
- fail(e);
56
- }
57
- }
58
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
59
- if (env.hasError) throw env.error;
60
- }
61
- return next();
62
- };
63
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
64
- var e = new Error(message);
65
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
66
- });
67
- import { randomUUID } from 'node:crypto';
68
- import { brandString } from '@deepseek-ai/dsh-brand';
69
- import { ReasoningEffortId, contentHasImage, createUserMessage } from '@deepseek-ai/dsh-llm';
70
- import { SessionLogOffset } from '@deepseek-ai/dsh-session';
71
- import { childSessionMeta, captureDelegatedPolicyOverrides, resolveChildAgentOptions, resolveChildDepth, } from "./child-agent.js";
72
- import { ContinuableActivationRegistry, } from "./continuation-activation.js";
73
- import { createAgentMessage, withContinuableReturnGuidance, } from "./continuation-messages.js";
74
- import { assertSubagentMaxDepth } from "./depth.js";
75
- import { foldSubagentDescriptor, snapshotSubagentDescriptor } from "./descriptor.js";
76
- import { establishCatalogChild } from "./catalog.js";
77
- import { SubagentError } from "./error.js";
78
- import { isAdjacentAgentSendMessageTool } from "./internal.js";
79
- /**
80
- * The continuable-subagent orchestration service behind `ctx.subagents`. Tool
81
- * schema and host adapters are consumers of this one contract; foreground
82
- * one-shot delegation keeps calling `ctx.subagents.start()` and never enters
83
- * this lifecycle.
84
- */
85
- export class SubagentContinuationManager {
86
- ctx;
87
- host;
88
- activations;
89
- constructor(ctx, host, maxActiveSubagents) {
90
- this.ctx = ctx;
91
- this.host = host;
92
- this.activations = new ContinuableActivationRegistry(ctx, (provider, childId, parent) => host.observeActivation(provider, childId, parent), maxActiveSubagents);
93
- }
94
- /**
95
- * Start one continuable background child and resolve at initial inbox acceptance.
96
- * Every earlier failure disposes any created handle and rolls back Activation
97
- * and parent ownership without returning either id.
98
- * @param spec - provider, delegation request, and caller cancellation.
99
- * @returns the durable child id and accepted initial prompt message id.
100
- */
101
- async startContinuable(spec) {
102
- const request = spec.request;
103
- const parent = request.parent;
104
- this.activations.assertAdmitting(parent);
105
- const persistence = this.requirePersistence();
106
- assertSubagentMaxDepth(request.maxDepth);
107
- const childId = spec.childId ?? brandString(randomUUID());
108
- this.activations.assertChildIdAvailable(childId);
109
- const childDepth = resolveChildDepth(parent, request.maxDepth);
110
- // Snapshot before any await: invalid descriptor JSON rejects the call
111
- // before a child exists, and the detached value is what reaches the log.
112
- const agentOptions = resolveChildAgentOptions(parent, request.agentOptions, childDepth);
113
- const agentProvider = agentOptions.provider;
114
- const agentModel = agentOptions.model;
115
- const agentReasoningEffort = agentOptions.reasoningEffort;
116
- const descriptor = snapshotSubagentDescriptor({
117
- mode: 'continuable',
118
- provider: spec.provider,
119
- label: spec.label,
120
- ...agentProvider !== undefined ? { agentProvider } : {},
121
- ...agentModel !== undefined ? { agentModel } : {},
122
- ...agentReasoningEffort !== undefined ? { agentReasoningEffort } : {},
123
- ...request.persona !== undefined ? { persona: request.persona } : {},
124
- ...request.toolFilter !== undefined ? { toolFilter: request.toolFilter } : {},
125
- });
126
- // Capture before the first await: a later parent switch belongs to the
127
- // parent's future, not to this child.
128
- const delegatedPolicies = captureDelegatedPolicyOverrides(parent);
129
- // An idle continuation-managed parent must not settle while a caller is
130
- // still creating its child. A turn-scoped delegation does not need this,
131
- // but the service is also callable outside a turn.
132
- const releaseHold = this.activations.holdOwnership(parent, childId);
133
- try {
134
- const prepared = await this.host.prepareContinuable(spec.provider, {
135
- sessionId: childId,
136
- parent,
137
- signal: spec.signal,
138
- });
139
- spec.signal.throwIfAborted();
140
- this.activations.assertAdmitting(parent);
141
- const inheritedEventCount = SessionLogOffset(prepared.seed?.length ?? 0);
142
- const seed = prepared.seed;
143
- const messageId = await this.activations.locks.run(childId, async () => {
144
- spec.signal.throwIfAborted();
145
- this.activations.assertAdmitting(parent);
146
- this.activations.assertChildIdAvailable(childId);
147
- if (spec.childId !== undefined) {
148
- const persisted = await persistence.stat(childId, { signal: spec.signal });
149
- spec.signal.throwIfAborted();
150
- this.activations.assertAdmitting(parent);
151
- this.activations.assertChildIdAvailable(childId);
152
- if (persisted !== undefined) {
153
- throw new SubagentError(`subagent "${childId}" already exists`, 'DUPLICATE_CHILD');
154
- }
155
- }
156
- const activation = await this.activations.materialize({
157
- childId,
158
- provider: spec.provider,
159
- parent,
160
- create: {
161
- seed,
162
- meta: childSessionMeta(parent, childDepth, prepared.seed !== undefined),
163
- inheritedEventCount,
164
- delegatedPolicies,
165
- descriptor,
166
- },
167
- agentOptions,
168
- composition: { persona: request.persona, toolFilter: request.toolFilter },
169
- signal: spec.signal,
170
- });
171
- const childHeader = activation.handle.agent.session.header;
172
- return await this.submitMaterialized(activation, isAdjacentAgentSendMessageTool(this.ctx.get('tools')?.get('send_message', activation.handle.agent))
173
- ? withContinuableReturnGuidance(parent.id, request.prompt)
174
- : request.prompt, { source: { kind: 'user' }, signal: spec.signal, delivery: 'queue' }, parent, () => { establishCatalogChild(parent.session, childHeader, descriptor); });
175
- });
176
- return { childId, messageId };
177
- }
178
- catch (error) {
179
- releaseHold();
180
- throw error;
181
- }
182
- }
183
- /**
184
- * Deliver one model-authored message to a direct continuable child or to the
185
- * sender's direct parent. A missing direct child cold-resumes through the
186
- * ordinary continuation lifecycle.
187
- * @param sender - exact live Agent authorizing and originating the message.
188
- * @param targetId - durable direct-parent or direct-child session id.
189
- * @param content - model-authored content to deliver.
190
- * @param options - caller cancellation before acceptance.
191
- * @returns the accepted message's inbox id.
192
- */
193
- async sendMessage(sender, targetId, content, options) {
194
- if (this.ctx.agents.get(sender.id) !== sender) {
195
- throw new SubagentError('message delivery requires the exact live sender agent', 'UNAUTHORIZED');
196
- }
197
- this.activations.assertAdmitting(sender);
198
- const senderActivation = this.activations.get(sender.id);
199
- if (senderActivation !== undefined
200
- && senderActivation.handle.agent === sender
201
- && senderActivation.parentSession === targetId) {
202
- options.signal.throwIfAborted();
203
- return this.sendToParent(senderActivation, sender, content);
204
- }
205
- if (sender.session.header.parentSession === targetId) {
206
- throw new SubagentError(`agent "${sender.id}" is not a resident continuable child and cannot send to parent "${targetId}"`, 'UNAUTHORIZED');
207
- }
208
- return this.deliverToChild(sender, targetId, content, {
209
- signal: options.signal,
210
- delivery: 'steer',
211
- });
212
- }
213
- /**
214
- * Queue one human-authored prompt as a distinct direct-child turn.
215
- * @param parent - exact live direct parent authorizing delivery.
216
- * @param childId - durable direct-child session id.
217
- * @param content - model-visible prompt blocks.
218
- * @param source - durable attribution for the human prompt.
219
- * @param signal - caller cancellation before inbox acceptance.
220
- * @returns the accepted durable message id.
221
- */
222
- async queuePrompt(parent, childId, content, source, signal) {
223
- return this.deliverToChild(parent, childId, content, { source, signal, delivery: 'queue' });
224
- }
225
- /**
226
- * Steer one host-authored prompt to a direct continuable child.
227
- * @param parent - exact live direct parent authorizing delivery.
228
- * @param childId - durable direct-child session id.
229
- * @param content - model-visible prompt blocks.
230
- * @param source - durable attribution for the host prompt.
231
- * @param signal - caller cancellation before inbox acceptance.
232
- * @returns the accepted durable message id.
233
- */
234
- async steerPrompt(parent, childId, content, source, signal) {
235
- return this.deliverToChild(parent, childId, content, { source, signal, delivery: 'steer' });
236
- }
237
- /** Route one parent-originated delivery through residency and cold resume. */
238
- async deliverToChild(parent, childId, content, options) {
239
- this.activations.assertAdmitting(parent);
240
- const releaseHold = this.activations.holdOwnership(parent, childId);
241
- try {
242
- return await this.deliverFollowup(parent, childId, content, options);
243
- }
244
- catch (error) {
245
- releaseHold();
246
- throw error;
247
- }
248
- }
249
- /** The delivery loop behind {@link deliverToChild}, run under the parent hold. */
250
- async deliverFollowup(parent, childId, content, options) {
251
- while (true) {
252
- const live = await this.activations.locks.run(childId, async () => {
253
- const activation = this.activations.get(childId);
254
- if (activation === undefined)
255
- return this.coldResume(parent, childId, content, options);
256
- const disposal = activation.inbox.closing;
257
- /* v8 ignore next 3 -- the send-versus-dispose cutoff needs a delivery to
258
- * observe the transaction inside the same critical section that opened it. */
259
- if (disposal !== undefined) {
260
- return disposal.then(() => undefined, () => undefined);
261
- }
262
- if (contentHasImage(content)) {
263
- await this.assertImageCapable(activation.handle.agent, options.signal);
264
- if (activation.inbox.closing !== undefined) {
265
- await Promise.allSettled([activation.inbox.closing]);
266
- return undefined;
267
- }
268
- }
269
- const messageId = this.submitAdmitted(activation, content, options, parent);
270
- activation.announced = true;
271
- return messageId;
272
- });
273
- /* v8 ignore start -- only a delivery that lost the disposal cutoff retries. */
274
- if (live !== undefined)
275
- return live;
276
- this.activations.assertAdmitting(parent);
277
- options.signal.throwIfAborted();
278
- /* v8 ignore stop */
279
- }
280
- }
281
- /**
282
- * Interrupt one live continuable child's current turn. Admission is
283
- * synchronous and the cancellation effect is asynchronous. An absent or
284
- * already-closing target is an accepted no-op after authority checks.
285
- * @param targetSessionId - the durable child session id to interrupt.
286
- * @param authority - the human parent address or exact live ancestor Agent.
287
- */
288
- interrupt(targetSessionId, authority) {
289
- this.activations.interrupt(targetSessionId, authority);
290
- }
291
- /** Deliver one resident continuable child's message to its live direct parent. */
292
- sendToParent(activation, sender, content) {
293
- /* v8 ignore next 6 -- only synchronous re-entrant teardown can open this
294
- * transaction between exact-agent authorization and this no-await span. */
295
- if (activation.inbox.closing !== undefined) {
296
- throw new SubagentError(`subagent "${sender.id}" activation is being disposed; the message was not delivered`, 'ACTIVATION_CLOSING');
297
- }
298
- const parent = this.ctx.agents.get(activation.parentSession);
299
- if (parent === undefined) {
300
- throw new SubagentError('direct parent is not live; the message was not delivered', 'PARENT_UNAVAILABLE');
301
- }
302
- const message = createAgentMessage(sender, content);
303
- this.sendAgentMessage(parent, message);
304
- return message.id;
305
- }
306
- /** Send one Agent message while translating only the target's own rejection. */
307
- sendAgentMessage(parent, message) {
308
- try {
309
- this.activations.sendWaking(parent, message, 'steer');
310
- }
311
- catch (error) {
312
- throw new SubagentError('direct parent is not live; the message was not delivered', 'PARENT_UNAVAILABLE', { cause: error });
313
- }
314
- }
315
- /** Close manager-wide admission and release every live Activation. */
316
- async drain() {
317
- await this.activations.drain();
318
- }
319
- /**
320
- * Stop only the continuable descendants of exact live host-owned parents.
321
- * @param parents - exact live roots whose continuable descendants must stop.
322
- */
323
- async drainDescendants(parents) {
324
- await this.activations.drainDescendants(parents);
325
- }
326
- /**
327
- * Release selected resident direct children of one exact live parent.
328
- * @param parent - exact live direct parent authorizing the selected release.
329
- * @param childIds - durable direct-child ids to release when resident.
330
- */
331
- async drainChildren(parent, childIds) {
332
- await this.activations.drainChildren(parent, childIds);
333
- }
334
- /**
335
- * Cold-resume a persisted child and submit the waiting turn. The descriptor
336
- * supplies every reconstruction input; no subagent provider is dispatched.
337
- */
338
- async coldResume(parent, childId, content, options) {
339
- const env_1 = { stack: [], error: void 0, hasError: false };
340
- try {
341
- const query = this.requireSessionQuery();
342
- let observation;
343
- try {
344
- observation = await query.observeSession(childId, {
345
- signal: options.signal,
346
- });
347
- }
348
- catch (error) {
349
- options.signal.throwIfAborted();
350
- throw new SubagentError(`subagent "${childId}" is unavailable`, 'NOT_RESUMABLE', { cause: error });
351
- }
352
- const source = __addDisposableResource(env_1, observation, false);
353
- this.activations.assertAdmitting(parent);
354
- this.activations.authorizeLineage(parent, childId, source.header.parentSession);
355
- const descriptor = foldSubagentDescriptor(source.events.slice(source.inheritedEventCount));
356
- if (descriptor === undefined || descriptor.mode !== 'continuable') {
357
- throw new SubagentError(`subagent "${childId}" has no supported continuation state and cannot be resumed; choose a different target`, 'NOT_RESUMABLE');
358
- }
359
- let activation;
360
- try {
361
- activation = await this.activations.materialize({
362
- childId,
363
- provider: descriptor.provider,
364
- parent,
365
- agentOptions: {
366
- ...descriptor.agentProvider !== undefined ? { provider: descriptor.agentProvider } : {},
367
- ...descriptor.agentModel !== undefined ? { model: descriptor.agentModel } : {},
368
- ...descriptor.agentReasoningEffort !== undefined
369
- ? { reasoningEffort: ReasoningEffortId(descriptor.agentReasoningEffort) }
370
- : {},
371
- },
372
- composition: { persona: descriptor.persona, toolFilter: descriptor.toolFilter },
373
- signal: options.signal,
374
- });
375
- }
376
- catch (error) {
377
- options.signal.throwIfAborted();
378
- if (error instanceof SubagentError)
379
- throw error;
380
- throw new SubagentError(`subagent "${childId}" is unavailable`, 'NOT_RESUMABLE', { cause: error });
381
- }
382
- return await this.submitMaterialized(activation, content, options, parent);
383
- }
384
- catch (e_1) {
385
- env_1.error = e_1;
386
- env_1.hasError = true;
387
- }
388
- finally {
389
- __disposeResources(env_1);
390
- }
391
- }
392
- /** Admit a materialized child, commit its creation fact, and release it on failure. */
393
- async submitMaterialized(activation, content, options, parent, commit) {
394
- try {
395
- if (contentHasImage(content)) {
396
- await this.assertImageCapable(activation.handle.agent, options.signal);
397
- if (activation.inbox.closing !== undefined) {
398
- throw new SubagentError(`subagent "${activation.childId}" is closing`, 'ACTIVATION_CLOSING');
399
- }
400
- }
401
- const messageId = this.submitAdmitted(activation, content, options, parent);
402
- commit?.();
403
- activation.announced = true;
404
- return messageId;
405
- }
406
- catch (error) {
407
- try {
408
- await this.activations.dispose(activation);
409
- }
410
- catch (cleanupError) {
411
- this.ctx.logger.warn(`subagent continuation: disposal after admission or catalog append failure also failed: ${String(cleanupError)}`);
412
- }
413
- throw error;
414
- }
415
- }
416
- /** Build and submit one message across the final synchronous admission cutoff. */
417
- submitAdmitted(activation, content, options, parent) {
418
- const message = options.source === undefined
419
- ? createAgentMessage(parent, content)
420
- : createUserMessage({ content, source: options.source });
421
- return this.activations.submitAdmitted(activation, message, options.delivery, parent, options.signal);
422
- }
423
- /** Refuse image content for a child whose fixed model accepts text only. */
424
- async assertImageCapable(agent, signal) {
425
- const { provider, model } = agent.options;
426
- if (provider === undefined || model === undefined)
427
- return;
428
- const llm = this.ctx.get('llm');
429
- /* v8 ignore next -- without an LLM registry, delivery defers to projection. */
430
- if (llm === undefined)
431
- return;
432
- const info = await llm.resolveModelInfo(provider, model, signal);
433
- if (info.inputModalities !== undefined && !info.inputModalities.includes('image')) {
434
- throw new SubagentError(`Model "${model}" does not support image input.`, 'MODEL_DOES_NOT_SUPPORT_IMAGES');
435
- }
436
- }
437
- /** Resolve the persistence service continuable children require, or fail loud. */
438
- requirePersistence() {
439
- const persistence = this.ctx.get('sessionPersistence');
440
- if (persistence === undefined) {
441
- throw new SubagentError('continuable subagents require session persistence (load a dsh-session-persistence backend)', 'PERSISTENCE_UNAVAILABLE');
442
- }
443
- return persistence;
444
- }
445
- /** Resolve the Session query service used for cold child observations. */
446
- requireSessionQuery() {
447
- const query = this.ctx.get('sessionQuery');
448
- if (query === undefined) {
449
- throw new SubagentError('continuable subagents require session query (load @deepseek-ai/dsh-session-query)', 'CONTINUATION_UNAVAILABLE');
450
- }
451
- return query;
452
- }
453
- }
454
- export default SubagentContinuationManager;
455
- //# sourceMappingURL=continuation.js.map
@@ -1,43 +0,0 @@
1
- /**
2
- * Activation-local admission around one continuable subagent's Agent inbox.
3
- *
4
- * @module @deepseek-ai/dsh-subagent/inbox
5
- */
6
- import type { Agent } from '@deepseek-ai/dsh-agent';
7
- import type { UserMessage } from '@deepseek-ai/dsh-session';
8
- import type { SubagentPromptRequest } from './control-types.ts';
9
- /** One Agent inbox destination, as the wire request selects it. */
10
- export type SubagentDelivery = SubagentPromptRequest['delivery'];
11
- /** Delegate Queue and Steer to one live Agent until its Activation starts closing. */
12
- export declare class SubagentInbox {
13
- private readonly agent;
14
- private closingPromise;
15
- /**
16
- * Wrap one live continuable Agent.
17
- * @param agent - the Agent whose inbox receives accepted deliveries.
18
- */
19
- constructor(agent: Agent);
20
- /**
21
- * Read the Activation's close transaction.
22
- * @returns the memoized transaction, or `undefined` while delivery remains open.
23
- */
24
- get closing(): Promise<void> | undefined;
25
- /**
26
- * Read whether the underlying Agent still has accepted work to claim.
27
- * @returns whether either Agent inbox destination is non-empty.
28
- */
29
- get hasPending(): boolean;
30
- /**
31
- * Submit through the Agent only while its Activation remains resident.
32
- * @param message - the accepted input to submit.
33
- * @param delivery - whether to queue a distinct turn or steer the nearest step.
34
- */
35
- deliver(message: UserMessage, delivery: SubagentDelivery): void;
36
- /**
37
- * Close delivery synchronously and share one asynchronous release.
38
- * @param release - the one release operation to start after closing admission.
39
- * @returns the memoized release transaction.
40
- */
41
- close(release: () => Promise<void>): Promise<void>;
42
- }
43
- //# sourceMappingURL=inbox.d.ts.map