@deepseek-ai/dsh-subagent 0.1.1-rc.2 → 0.1.2-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/README.i18n.yaml +2 -2
- package/README.md +105 -75
- package/README.zh.md +110 -84
- package/lib/index.js +934 -434
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +925 -0
- package/lib/typert.remote-client.d.ts +27 -0
- package/lib/typert.remote-client.js +159 -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 +17 -2
- package/lib/types/continuation.js +174 -48
- package/lib/types/control-types.d.ts +144 -0
- package/lib/types/control-types.js +9 -0
- package/lib/types/control.d.ts +67 -0
- package/lib/types/control.js +115 -0
- package/lib/types/descriptor.d.ts +6 -1
- package/lib/types/descriptor.js +6 -2
- package/lib/types/index.d.ts +62 -26
- package/lib/types/index.js +444 -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/lib/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AttachmentError, admitPromptContent } from "@deepseek-ai/dsh-attachment";
|
|
2
2
|
import { scopeTarget } from "@deepseek-ai/dsh-scope";
|
|
3
3
|
import { assertObjectJsonSchema } from "@deepseek-ai/dsh-tools";
|
|
4
|
-
import {
|
|
4
|
+
import { canonicalClientTimeZone } from "@deepseek-ai/dsh-util-time";
|
|
5
|
+
import { Remote, RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { HarnessError, ReasoningEffortId, boundContextSummary, contentHasImage, createUserMessage, errorChain } from "@deepseek-ai/dsh-llm";
|
|
5
8
|
import { randomUUID } from "node:crypto";
|
|
6
9
|
import { foldConsumedWork } from "@deepseek-ai/dsh-agent";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
10
|
+
import { brandString } from "@deepseek-ai/dsh-brand";
|
|
11
|
+
import { snapshotJsonValue } from "@deepseek-ai/dsh-util-values";
|
|
12
|
+
import { Session } from "@deepseek-ai/dsh-session";
|
|
9
13
|
import { accessSync, constants, statSync } from "node:fs";
|
|
10
14
|
import { isAbsolute, resolve } from "node:path";
|
|
11
15
|
//#region lib/types/error.js
|
|
@@ -22,6 +26,101 @@ var SubagentError = class extends HarnessError {
|
|
|
22
26
|
}
|
|
23
27
|
};
|
|
24
28
|
//#endregion
|
|
29
|
+
//#region lib/types/control.js
|
|
30
|
+
/**
|
|
31
|
+
* Browser-facing subagent control assembly: the catalog view sampled against
|
|
32
|
+
* the live Agent registry, one browser zone's validation, and the stable
|
|
33
|
+
* failure codes the Remote surface answers with.
|
|
34
|
+
*
|
|
35
|
+
* @module @deepseek-ai/dsh-subagent
|
|
36
|
+
*/
|
|
37
|
+
const SESSION_ID_SCHEMA = z.string().min(1);
|
|
38
|
+
const CONTROL_ID_SCHEMAS = {
|
|
39
|
+
"subagent.list": z.object({ parentSessionId: SESSION_ID_SCHEMA }),
|
|
40
|
+
"subagent.prompt": z.object({
|
|
41
|
+
parentSessionId: SESSION_ID_SCHEMA,
|
|
42
|
+
childSessionId: SESSION_ID_SCHEMA,
|
|
43
|
+
mode: z.literal("continuable")
|
|
44
|
+
}),
|
|
45
|
+
"subagent.interrupt": z.object({
|
|
46
|
+
parentSessionId: SESSION_ID_SCHEMA,
|
|
47
|
+
childSessionId: SESSION_ID_SCHEMA,
|
|
48
|
+
mode: z.literal("continuable")
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Apply the subagent payload checks that are stricter than generated
|
|
53
|
+
* branded-string codecs.
|
|
54
|
+
* @param method - method name carried in the failure message.
|
|
55
|
+
* @param payload - decoded control fields to validate.
|
|
56
|
+
* @throws {RemoteError} `gateway/bad-request` with the original Zod issues.
|
|
57
|
+
*/
|
|
58
|
+
function validateControlRequest(method, payload) {
|
|
59
|
+
const parsed = CONTROL_ID_SCHEMAS[method].safeParse(payload);
|
|
60
|
+
if (!parsed.success) throw new RemoteError("gateway/bad-request", `invalid payload for ${method}`, { issues: parsed.error.issues });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Project one durable listing onto the catalog view, replacing each row's
|
|
64
|
+
* store-derived activity with the live Agent driver's status and reporting
|
|
65
|
+
* whether the exact parent Agent is live. Without an Agent registry no driver
|
|
66
|
+
* runs at all, so every row is inactive and the parent is unavailable.
|
|
67
|
+
* @param ctx - Host context that may carry the Agent registry.
|
|
68
|
+
* @param parentSessionId - the listed parent.
|
|
69
|
+
* @param entries - the durable direct-child listing.
|
|
70
|
+
* @returns the catalog view answered to one browser.
|
|
71
|
+
*/
|
|
72
|
+
function catalogView(ctx, parentSessionId, entries) {
|
|
73
|
+
const agents = ctx.get("agents");
|
|
74
|
+
return {
|
|
75
|
+
entries: entries.map((entry) => entry.kind === "child" ? {
|
|
76
|
+
...entry,
|
|
77
|
+
activity: agents?.get(entry.id)?.status === "running" ? "running" : "inactive"
|
|
78
|
+
} : entry),
|
|
79
|
+
parentAvailable: agents?.get(parentSessionId) !== void 0
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Refuse one catalog read while preserving cancellation and a missing
|
|
84
|
+
* projections registry as distinct failures.
|
|
85
|
+
* @param error - the thrown value.
|
|
86
|
+
* @param signal - the caller's cancellation.
|
|
87
|
+
* @returns Never — the refusal is thrown.
|
|
88
|
+
* @throws {RemoteError} always.
|
|
89
|
+
*/
|
|
90
|
+
function rejectCatalogRead(error, signal) {
|
|
91
|
+
if (isCancellation(error, signal)) throw new RemoteError("gateway/cancelled", "subagent catalog read was cancelled", {}, { cause: error });
|
|
92
|
+
if (error instanceof SubagentError && error.code === "SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE") throw new RemoteError("subagent/projections-unavailable", "subagent catalog is unavailable: this deployment does not mount the sessionProjections registry (load @deepseek-ai/dsh-session-projection)", {}, { cause: error });
|
|
93
|
+
throw new RemoteError("gateway/internal", "subagent catalog read failed", {}, { cause: error });
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Refuse one continuation prompt without exposing provider detail: admission
|
|
97
|
+
* failures the caller can act on keep their own code, everything else is
|
|
98
|
+
* internal.
|
|
99
|
+
* @param error - the thrown value.
|
|
100
|
+
* @param childSessionId - the addressed child.
|
|
101
|
+
* @param signal - the caller's cancellation.
|
|
102
|
+
* @returns Never — the refusal is thrown.
|
|
103
|
+
* @throws {RemoteError} always.
|
|
104
|
+
*/
|
|
105
|
+
function rejectPrompt(error, childSessionId, signal) {
|
|
106
|
+
if (isCancellation(error, signal)) throw new RemoteError("gateway/cancelled", "subagent prompt was cancelled", {}, { cause: error });
|
|
107
|
+
if (error instanceof AttachmentError) throw new RemoteError("subagent/attachment-invalid", error.message, { reason: error.code }, { cause: error });
|
|
108
|
+
if (error instanceof SubagentError) switch (error.code) {
|
|
109
|
+
case "MODEL_DOES_NOT_SUPPORT_IMAGES": throw new RemoteError("subagent/attachment-invalid", error.message, { reason: error.code }, { cause: error });
|
|
110
|
+
case "NOT_RESUMABLE": throw new RemoteError("subagent/not-resumable", "subagent cannot be resumed", { childSessionId }, { cause: error });
|
|
111
|
+
case "UNAUTHORIZED": throw new RemoteError("subagent/unauthorized", "subagent does not belong to this parent", { childSessionId }, { cause: error });
|
|
112
|
+
case "DRAINING":
|
|
113
|
+
case "ACTIVATION_CLOSING":
|
|
114
|
+
case "CONTINUATION_UNAVAILABLE":
|
|
115
|
+
case "PERSISTENCE_UNAVAILABLE": throw new RemoteError("subagent/delivery-unavailable", "subagent follow-up is temporarily unavailable", { childSessionId }, { cause: error });
|
|
116
|
+
default: break;
|
|
117
|
+
}
|
|
118
|
+
throw new RemoteError("gateway/internal", "subagent prompt failed", {}, { cause: error });
|
|
119
|
+
}
|
|
120
|
+
function isCancellation(error, signal) {
|
|
121
|
+
return signal.aborted || error instanceof SubagentError && error.code === "CANCELLED";
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
25
124
|
//#region lib/types/depth.js
|
|
26
125
|
/**
|
|
27
126
|
* Delegation-depth accounting: the recursion budget a parent passes to its
|
|
@@ -325,7 +424,7 @@ function renderThrown(value) {
|
|
|
325
424
|
* Supporting another composition input is a deliberate version change, never
|
|
326
425
|
* an implicit extra field.
|
|
327
426
|
*/
|
|
328
|
-
const SUBAGENT_DESCRIPTOR_VERSION =
|
|
427
|
+
const SUBAGENT_DESCRIPTOR_VERSION = 3;
|
|
329
428
|
const DESCRIPTOR_BASE_KEYS = [
|
|
330
429
|
"version",
|
|
331
430
|
"mode",
|
|
@@ -337,6 +436,7 @@ const CONTINUABLE_DESCRIPTOR_KEYS = new Set([
|
|
|
337
436
|
...DESCRIPTOR_BASE_KEYS,
|
|
338
437
|
"agentProvider",
|
|
339
438
|
"agentModel",
|
|
439
|
+
"agentReasoningEffort",
|
|
340
440
|
"persona",
|
|
341
441
|
"toolFilter"
|
|
342
442
|
]);
|
|
@@ -383,7 +483,7 @@ function parseSubagentDescriptor(value) {
|
|
|
383
483
|
if (!isRecord(value)) throw new Error("persisted subagent descriptor payload must be an object");
|
|
384
484
|
const version = value["version"];
|
|
385
485
|
if (typeof version !== "number") throw new Error("persisted subagent descriptor version must be a number");
|
|
386
|
-
if (version !==
|
|
486
|
+
if (version !== 3) return void 0;
|
|
387
487
|
const mode = value["mode"];
|
|
388
488
|
if (mode !== "one-shot" && mode !== "continuable") throw new Error("persisted subagent descriptor mode must be \"one-shot\" or \"continuable\"");
|
|
389
489
|
assertKnownKeys(value, mode === "one-shot" ? ONE_SHOT_DESCRIPTOR_KEYS : CONTINUABLE_DESCRIPTOR_KEYS, "payload");
|
|
@@ -392,7 +492,7 @@ function parseSubagentDescriptor(value) {
|
|
|
392
492
|
if (mode === "one-shot") {
|
|
393
493
|
const label = optionalString(value, "label");
|
|
394
494
|
return {
|
|
395
|
-
version:
|
|
495
|
+
version: 3,
|
|
396
496
|
mode,
|
|
397
497
|
provider,
|
|
398
498
|
...label !== void 0 ? { label } : {}
|
|
@@ -402,32 +502,35 @@ function parseSubagentDescriptor(value) {
|
|
|
402
502
|
if (typeof label !== "string") throw new Error("persisted subagent descriptor label must be a string");
|
|
403
503
|
const agentProvider = optionalString(value, "agentProvider");
|
|
404
504
|
const agentModel = optionalString(value, "agentModel");
|
|
505
|
+
const agentReasoningEffort = optionalString(value, "agentReasoningEffort");
|
|
405
506
|
const persona = optionalString(value, "persona");
|
|
406
507
|
const toolFilter = Object.hasOwn(value, "toolFilter") ? parseToolFilter(value["toolFilter"]) : void 0;
|
|
407
508
|
return {
|
|
408
|
-
version:
|
|
509
|
+
version: 3,
|
|
409
510
|
mode,
|
|
410
511
|
provider,
|
|
411
512
|
label,
|
|
412
513
|
...agentProvider !== void 0 ? { agentProvider } : {},
|
|
413
514
|
...agentModel !== void 0 ? { agentModel } : {},
|
|
515
|
+
...agentReasoningEffort !== void 0 ? { agentReasoningEffort } : {},
|
|
414
516
|
...persona !== void 0 ? { persona } : {},
|
|
415
517
|
...toolFilter !== void 0 ? { toolFilter } : {}
|
|
416
518
|
};
|
|
417
519
|
}
|
|
418
520
|
function snapshotSubagentDescriptor(input) {
|
|
419
521
|
const snapshot = snapshotJsonValue(input.mode === "one-shot" ? {
|
|
420
|
-
version:
|
|
522
|
+
version: 3,
|
|
421
523
|
mode: input.mode,
|
|
422
524
|
provider: input.provider,
|
|
423
525
|
...input.label !== void 0 ? { label: input.label } : {}
|
|
424
526
|
} : {
|
|
425
|
-
version:
|
|
527
|
+
version: 3,
|
|
426
528
|
mode: input.mode,
|
|
427
529
|
provider: input.provider,
|
|
428
530
|
label: input.label,
|
|
429
531
|
...input.agentProvider !== void 0 ? { agentProvider: input.agentProvider } : {},
|
|
430
532
|
...input.agentModel !== void 0 ? { agentModel: input.agentModel } : {},
|
|
533
|
+
...input.agentReasoningEffort !== void 0 ? { agentReasoningEffort: input.agentReasoningEffort } : {},
|
|
431
534
|
...input.persona !== void 0 ? { persona: input.persona } : {},
|
|
432
535
|
...input.toolFilter !== void 0 ? { toolFilter: input.toolFilter } : {}
|
|
433
536
|
});
|
|
@@ -490,25 +593,51 @@ function resolveChildDepth(parent, maxDepth) {
|
|
|
490
593
|
return childDepth;
|
|
491
594
|
}
|
|
492
595
|
/**
|
|
493
|
-
* Resolve the child
|
|
494
|
-
*
|
|
495
|
-
*
|
|
596
|
+
* Resolve the parent values inherited by a child. The latest request header
|
|
597
|
+
* owns provider, model, and reasoning effort after request-time selection;
|
|
598
|
+
* creation options remain the fallback before the first request and retain
|
|
599
|
+
* the configured output-token limit.
|
|
600
|
+
* @param parent - delegating parent Agent.
|
|
601
|
+
* @returns detached Agent options for child-option merging.
|
|
602
|
+
*/
|
|
603
|
+
function parentAgentOptionsForDelegation(parent) {
|
|
604
|
+
const requestConfig = parent.session.requestHeader()?.config;
|
|
605
|
+
if (requestConfig === void 0) return { ...parent.options };
|
|
606
|
+
const { provider: _createdProvider, model: _createdModel, reasoningEffort: _createdReasoningEffort, ...createdOptions } = parent.options;
|
|
607
|
+
return {
|
|
608
|
+
...createdOptions,
|
|
609
|
+
provider: requestConfig.provider,
|
|
610
|
+
model: requestConfig.model,
|
|
611
|
+
...requestConfig.reasoningEffort === void 0 ? {} : { reasoningEffort: requestConfig.reasoningEffort }
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Resolve the child's `AgentOptions`: the parent's provider/model,
|
|
616
|
+
* reasoning-effort, and maxTokens values unless the request overrides them,
|
|
617
|
+
* stamped with the child's own delegation depth. Changing the route without
|
|
618
|
+
* naming an effort clears the parent's route-owned effort so the selected
|
|
619
|
+
* model resolves its own default.
|
|
496
620
|
* @param parent - the delegating parent whose route the child inherits.
|
|
497
621
|
* @param requested - per-child overrides, if any.
|
|
498
622
|
* @param childDepth - the resolved delegation depth to stamp.
|
|
499
623
|
* @returns the resolved options for `ctx.agents.create()`.
|
|
500
624
|
*/
|
|
501
625
|
function resolveChildAgentOptions(parent, requested, childDepth) {
|
|
502
|
-
const
|
|
503
|
-
const
|
|
504
|
-
const
|
|
505
|
-
|
|
626
|
+
const parentOptions = parentAgentOptionsForDelegation(parent);
|
|
627
|
+
const parentProvider = parentOptions.provider;
|
|
628
|
+
const parentModel = parentOptions.model;
|
|
629
|
+
const parentReasoningEffort = parentOptions.reasoningEffort;
|
|
630
|
+
const parentMaxTokens = parentOptions.maxTokens;
|
|
631
|
+
const resolved = {
|
|
506
632
|
...parentProvider !== void 0 ? { provider: parentProvider } : {},
|
|
507
633
|
...parentModel !== void 0 ? { model: parentModel } : {},
|
|
634
|
+
...parentReasoningEffort !== void 0 ? { reasoningEffort: parentReasoningEffort } : {},
|
|
508
635
|
...parentMaxTokens !== void 0 ? { maxTokens: parentMaxTokens } : {},
|
|
509
636
|
...requested,
|
|
510
637
|
subagentDepth: childDepth
|
|
511
638
|
};
|
|
639
|
+
if ((resolved.provider !== parentProvider || resolved.model !== parentModel) && requested?.reasoningEffort === void 0) delete resolved.reasoningEffort;
|
|
640
|
+
return resolved;
|
|
512
641
|
}
|
|
513
642
|
/**
|
|
514
643
|
* Build the child session's durable creation metadata: the parent's workspace,
|
|
@@ -571,12 +700,12 @@ function applyChildComposition(childCtx, parent, composition) {
|
|
|
571
700
|
childCtx.get("agentPresets")?.composeFrom(childCtx, parent.ctx);
|
|
572
701
|
childCtx.systemPrompt.context({
|
|
573
702
|
name: "subagent:delegation",
|
|
574
|
-
order:
|
|
703
|
+
order: childCtx.systemPrompt.getContextOrder("SUBAGENT_DELEGATION"),
|
|
575
704
|
text: SUBAGENT_DELEGATION_CONTEXT
|
|
576
705
|
});
|
|
577
706
|
if (composition.persona !== void 0) childCtx.systemPrompt.section({
|
|
578
707
|
name: "deployment:persona",
|
|
579
|
-
order:
|
|
708
|
+
order: childCtx.systemPrompt.getSectionOrder("DEPLOYMENT_PERSONA"),
|
|
580
709
|
text: composition.persona
|
|
581
710
|
});
|
|
582
711
|
if (composition.toolFilter !== void 0) childCtx.tools.restrict(composition.toolFilter);
|
|
@@ -664,6 +793,64 @@ function seedDescriptorTurn(childId, seed, descriptor) {
|
|
|
664
793
|
*
|
|
665
794
|
* @module @deepseek-ai/dsh-subagent
|
|
666
795
|
*/
|
|
796
|
+
var __addDisposableResource$1 = function(env, value, async) {
|
|
797
|
+
if (value !== null && value !== void 0) {
|
|
798
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
799
|
+
var dispose, inner;
|
|
800
|
+
if (async) {
|
|
801
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
802
|
+
dispose = value[Symbol.asyncDispose];
|
|
803
|
+
}
|
|
804
|
+
if (dispose === void 0) {
|
|
805
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
806
|
+
dispose = value[Symbol.dispose];
|
|
807
|
+
if (async) inner = dispose;
|
|
808
|
+
}
|
|
809
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
810
|
+
if (inner) dispose = function() {
|
|
811
|
+
try {
|
|
812
|
+
inner.call(this);
|
|
813
|
+
} catch (e) {
|
|
814
|
+
return Promise.reject(e);
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
env.stack.push({
|
|
818
|
+
value,
|
|
819
|
+
dispose,
|
|
820
|
+
async
|
|
821
|
+
});
|
|
822
|
+
} else if (async) env.stack.push({ async: true });
|
|
823
|
+
return value;
|
|
824
|
+
};
|
|
825
|
+
var __disposeResources$1 = (function(SuppressedError) {
|
|
826
|
+
return function(env) {
|
|
827
|
+
function fail(e) {
|
|
828
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
829
|
+
env.hasError = true;
|
|
830
|
+
}
|
|
831
|
+
var r, s = 0;
|
|
832
|
+
function next() {
|
|
833
|
+
while (r = env.stack.pop()) try {
|
|
834
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
835
|
+
if (r.dispose) {
|
|
836
|
+
var result = r.dispose.call(r.value);
|
|
837
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
|
|
838
|
+
fail(e);
|
|
839
|
+
return next();
|
|
840
|
+
});
|
|
841
|
+
} else s |= 1;
|
|
842
|
+
} catch (e) {
|
|
843
|
+
fail(e);
|
|
844
|
+
}
|
|
845
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
846
|
+
if (env.hasError) throw env.error;
|
|
847
|
+
}
|
|
848
|
+
return next();
|
|
849
|
+
};
|
|
850
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
|
|
851
|
+
var e = new Error(message);
|
|
852
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
853
|
+
});
|
|
667
854
|
/**
|
|
668
855
|
* Read one Activation's current disposal transaction. This indirection exists
|
|
669
856
|
* because TypeScript would otherwise narrow repeated reads of the mutable field
|
|
@@ -774,17 +961,20 @@ var SubagentContinuationManager = class {
|
|
|
774
961
|
this.assertAdmitting(parent);
|
|
775
962
|
const persistence = this.requirePersistence();
|
|
776
963
|
assertSubagentMaxDepth(request.maxDepth);
|
|
777
|
-
const childId = spec.childId ??
|
|
964
|
+
const childId = spec.childId ?? brandString(randomUUID());
|
|
778
965
|
this.assertChildIdAvailable(childId);
|
|
779
966
|
const childDepth = resolveChildDepth(parent, request.maxDepth);
|
|
780
|
-
const
|
|
781
|
-
const
|
|
967
|
+
const agentOptions = resolveChildAgentOptions(parent, request.agentOptions, childDepth);
|
|
968
|
+
const agentProvider = agentOptions.provider;
|
|
969
|
+
const agentModel = agentOptions.model;
|
|
970
|
+
const agentReasoningEffort = agentOptions.reasoningEffort;
|
|
782
971
|
const descriptor = snapshotSubagentDescriptor({
|
|
783
972
|
mode: "continuable",
|
|
784
973
|
provider: spec.provider,
|
|
785
974
|
label: spec.label,
|
|
786
975
|
...agentProvider !== void 0 ? { agentProvider } : {},
|
|
787
976
|
...agentModel !== void 0 ? { agentModel } : {},
|
|
977
|
+
...agentReasoningEffort !== void 0 ? { agentReasoningEffort } : {},
|
|
788
978
|
...request.persona !== void 0 ? { persona: request.persona } : {},
|
|
789
979
|
...request.toolFilter !== void 0 ? { toolFilter: request.toolFilter } : {}
|
|
790
980
|
});
|
|
@@ -820,7 +1010,7 @@ var SubagentContinuationManager = class {
|
|
|
820
1010
|
meta: childSessionMeta(parent, childDepth, lineageSeedLength),
|
|
821
1011
|
delegatedPolicies
|
|
822
1012
|
},
|
|
823
|
-
agentOptions
|
|
1013
|
+
agentOptions,
|
|
824
1014
|
composition: {
|
|
825
1015
|
persona: request.persona,
|
|
826
1016
|
toolFilter: request.toolFilter
|
|
@@ -858,11 +1048,19 @@ var SubagentContinuationManager = class {
|
|
|
858
1048
|
const live = await this.locks.run(childId, async () => {
|
|
859
1049
|
const activation = this.activations.get(childId);
|
|
860
1050
|
if (activation === void 0) return this.coldResume(parent, childId, content, options);
|
|
1051
|
+
const disposal = activation.disposal;
|
|
861
1052
|
/* v8 ignore next 3 -- the send-versus-dispose cutoff: reaching this arm needs a
|
|
862
1053
|
* delivery to observe the transaction inside the same critical section that opened it,
|
|
863
1054
|
* which no test can schedule deterministically. The behavior is covered end-to-end by
|
|
864
1055
|
* "cold-resumes a delivery that lost the race with final disposal". */
|
|
865
|
-
if (
|
|
1056
|
+
if (disposal !== void 0) return disposal.then(() => void 0, () => void 0);
|
|
1057
|
+
if (contentHasImage(content)) {
|
|
1058
|
+
await this.assertImageCapable(activation.handle.agent, options.signal);
|
|
1059
|
+
if (activation.disposal !== void 0) {
|
|
1060
|
+
await Promise.allSettled([activation.disposal]);
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
866
1064
|
return this.submitAdmitted(activation, content, options.source, parent, options.signal);
|
|
867
1065
|
});
|
|
868
1066
|
/* v8 ignore start -- only the lost-cutoff arm above returns undefined, so only that
|
|
@@ -1135,48 +1333,61 @@ var SubagentContinuationManager = class {
|
|
|
1135
1333
|
return "settled";
|
|
1136
1334
|
}
|
|
1137
1335
|
/**
|
|
1138
|
-
* Cold-resume a persisted child:
|
|
1336
|
+
* Cold-resume a persisted child: retain and authorize its prepared Session, fold the
|
|
1139
1337
|
* generic descriptor, create the Activation through `ctx.agents.resume()`,
|
|
1140
1338
|
* and submit the waiting turn. This never dispatches through a subagent
|
|
1141
1339
|
* provider — the persisted Session already holds the initial prefix and the
|
|
1142
1340
|
* descriptor is the whole reconstruction input.
|
|
1143
1341
|
*/
|
|
1144
1342
|
async coldResume(parent, childId, content, options) {
|
|
1145
|
-
const
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
}
|
|
1150
|
-
options.signal.throwIfAborted();
|
|
1151
|
-
throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
|
|
1152
|
-
}
|
|
1153
|
-
options.signal.throwIfAborted();
|
|
1154
|
-
this.assertAdmitting(parent);
|
|
1155
|
-
this.authorizeLineage(parent, childId, loaded.meta.parentSession);
|
|
1156
|
-
const descriptor = foldSubagentDescriptor(loaded.events.slice(loaded.meta.seedLength ?? 0));
|
|
1157
|
-
if (descriptor === void 0 || descriptor.mode !== "continuable") throw new SubagentError(`subagent "${childId}" has no supported continuation state and cannot be resumed; do not retry send_message with this id`, "NOT_RESUMABLE");
|
|
1158
|
-
let activation;
|
|
1343
|
+
const env_1 = {
|
|
1344
|
+
stack: [],
|
|
1345
|
+
error: void 0,
|
|
1346
|
+
hasError: false
|
|
1347
|
+
};
|
|
1159
1348
|
try {
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1349
|
+
const query = this.requireSessionQuery();
|
|
1350
|
+
let observation;
|
|
1351
|
+
try {
|
|
1352
|
+
observation = await query.observeSession(childId, { signal: options.signal });
|
|
1353
|
+
} catch (error) {
|
|
1354
|
+
options.signal.throwIfAborted();
|
|
1355
|
+
throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
|
|
1356
|
+
}
|
|
1357
|
+
const source = __addDisposableResource$1(env_1, observation, false);
|
|
1358
|
+
this.assertAdmitting(parent);
|
|
1359
|
+
this.authorizeLineage(parent, childId, source.header.parentSession);
|
|
1360
|
+
const descriptor = foldSubagentDescriptor(source.events.slice(source.header.seedLength ?? 0));
|
|
1361
|
+
if (descriptor === void 0 || descriptor.mode !== "continuable") throw new SubagentError(`subagent "${childId}" has no supported continuation state and cannot be resumed; do not retry send_message with this id`, "NOT_RESUMABLE");
|
|
1362
|
+
let activation;
|
|
1363
|
+
try {
|
|
1364
|
+
activation = await this.materialize({
|
|
1365
|
+
childId,
|
|
1366
|
+
provider: descriptor.provider,
|
|
1367
|
+
parent,
|
|
1368
|
+
agentOptions: {
|
|
1369
|
+
...descriptor.agentProvider !== void 0 ? { provider: descriptor.agentProvider } : {},
|
|
1370
|
+
...descriptor.agentModel !== void 0 ? { model: descriptor.agentModel } : {},
|
|
1371
|
+
...descriptor.agentReasoningEffort !== void 0 ? { reasoningEffort: ReasoningEffortId(descriptor.agentReasoningEffort) } : {}
|
|
1372
|
+
},
|
|
1373
|
+
composition: {
|
|
1374
|
+
persona: descriptor.persona,
|
|
1375
|
+
toolFilter: descriptor.toolFilter
|
|
1376
|
+
},
|
|
1377
|
+
signal: options.signal
|
|
1378
|
+
});
|
|
1379
|
+
} catch (error) {
|
|
1380
|
+
options.signal.throwIfAborted();
|
|
1381
|
+
if (error instanceof SubagentError) throw error;
|
|
1382
|
+
throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
|
|
1383
|
+
}
|
|
1384
|
+
return await this.submitMaterialized(activation, content, options.source, parent, options.signal);
|
|
1385
|
+
} catch (e_1) {
|
|
1386
|
+
env_1.error = e_1;
|
|
1387
|
+
env_1.hasError = true;
|
|
1388
|
+
} finally {
|
|
1389
|
+
__disposeResources$1(env_1);
|
|
1178
1390
|
}
|
|
1179
|
-
return this.submitMaterialized(activation, content, options.source, parent, options.signal);
|
|
1180
1391
|
}
|
|
1181
1392
|
/**
|
|
1182
1393
|
* Submit to a freshly materialized Activation or roll it back completely.
|
|
@@ -1189,6 +1400,10 @@ var SubagentContinuationManager = class {
|
|
|
1189
1400
|
*/
|
|
1190
1401
|
async submitMaterialized(activation, content, source, parent, signal) {
|
|
1191
1402
|
try {
|
|
1403
|
+
if (contentHasImage(content)) {
|
|
1404
|
+
await this.assertImageCapable(activation.handle.agent, signal);
|
|
1405
|
+
if (activation.disposal !== void 0) throw new SubagentError(`subagent "${activation.childId}" is closing`, "ACTIVATION_CLOSING");
|
|
1406
|
+
}
|
|
1192
1407
|
return this.submitAdmitted(activation, content, source, parent, signal);
|
|
1193
1408
|
} catch (error) {
|
|
1194
1409
|
/* v8 ignore next -- rollback disposal failures must not mask the
|
|
@@ -1198,6 +1413,28 @@ var SubagentContinuationManager = class {
|
|
|
1198
1413
|
}
|
|
1199
1414
|
}
|
|
1200
1415
|
/**
|
|
1416
|
+
* Refuse image content addressed to a child whose model accepts text only.
|
|
1417
|
+
* Callers guard with `contentHasImage`, so text-only delivery never awaits.
|
|
1418
|
+
* The check runs inside the per-child delivery lock, before the message
|
|
1419
|
+
* exists, so a rejection leaves no partial user message. When the child's
|
|
1420
|
+
* route is not fixed by its options (a request-waterfall listener owns it)
|
|
1421
|
+
* or no LLM registry is composed, delivery proceeds and the LLM layer's
|
|
1422
|
+
* text-only projection replaces each image with its stable placeholder.
|
|
1423
|
+
* @param agent - the live or freshly materialized child agent.
|
|
1424
|
+
* @param signal - caller cancellation bounding the model-info read.
|
|
1425
|
+
* @throws {SubagentError} `MODEL_DOES_NOT_SUPPORT_IMAGES` when the child's resolved model declines image input.
|
|
1426
|
+
*/
|
|
1427
|
+
async assertImageCapable(agent, signal) {
|
|
1428
|
+
const { provider, model } = agent.options;
|
|
1429
|
+
if (provider === void 0 || model === void 0) return;
|
|
1430
|
+
const llm = this.ctx.get("llm");
|
|
1431
|
+
/* v8 ignore next -- a deployment without the LLM registry serves no model
|
|
1432
|
+
* to refuse against; delivery then defers to the text-only projection. */
|
|
1433
|
+
if (llm === void 0) return;
|
|
1434
|
+
const info = await llm.resolveModelInfo(provider, model, signal);
|
|
1435
|
+
if (info.inputModalities !== void 0 && !info.inputModalities.includes("image")) throw new SubagentError(`Model "${model}" does not support image input.`, "MODEL_DOES_NOT_SUPPORT_IMAGES");
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1201
1438
|
* Create or resume the child Agent through the private activation-owner
|
|
1202
1439
|
* scope, install the handle in a fresh Activation, and register ownership on
|
|
1203
1440
|
* a continuation-managed parent. Rejection leaves no Activation, no handle,
|
|
@@ -1541,6 +1778,12 @@ var SubagentContinuationManager = class {
|
|
|
1541
1778
|
if (persistence === void 0) throw new SubagentError("continuable subagents require session persistence (load a dsh-session-persistence backend)", "PERSISTENCE_UNAVAILABLE");
|
|
1542
1779
|
return persistence;
|
|
1543
1780
|
}
|
|
1781
|
+
/** Resolve the Session query service used for cold child observations. */
|
|
1782
|
+
requireSessionQuery() {
|
|
1783
|
+
const query = this.ctx.get("sessionQuery");
|
|
1784
|
+
if (query === void 0) throw new SubagentError("continuable subagents require session query (load @deepseek-ai/dsh-session-query)", "CONTINUATION_UNAVAILABLE");
|
|
1785
|
+
return query;
|
|
1786
|
+
}
|
|
1544
1787
|
};
|
|
1545
1788
|
//#endregion
|
|
1546
1789
|
//#region lib/types/activation-setup-registry.js
|
|
@@ -1674,14 +1917,14 @@ var SubagentActivationSetupRegistry = class {
|
|
|
1674
1917
|
//#region lib/types/list-children.js
|
|
1675
1918
|
/**
|
|
1676
1919
|
* Read-only enumeration of durable subagent children and descendant trees
|
|
1677
|
-
*
|
|
1678
|
-
*
|
|
1679
|
-
*
|
|
1920
|
+
* through the Session query service. Candidates come from one live-preferred
|
|
1921
|
+
* corpus; each child's mode/label is the registered `subagent` projection
|
|
1922
|
+
* unit's value, resolved
|
|
1680
1923
|
* down a three-rung ladder: the registry's watermark cache for a live child,
|
|
1681
1924
|
* a durable projection-cache row when it serves an own-suffix identity (the
|
|
1682
|
-
* seq gate), and one
|
|
1683
|
-
*
|
|
1684
|
-
*
|
|
1925
|
+
* seq gate), and one shared Session observation otherwise, validated against
|
|
1926
|
+
* the enumerated lifecycle. The projection fold is the single classification
|
|
1927
|
+
* authority — this module parses no descriptor
|
|
1685
1928
|
* itself. Absent persistence, enumeration is live-only: a cold child is
|
|
1686
1929
|
* unreachable for resume anyway, so its absence is capability absence, not an
|
|
1687
1930
|
* error. The module owns no catalog state and does not consult Activation,
|
|
@@ -1689,10 +1932,68 @@ var SubagentActivationSetupRegistry = class {
|
|
|
1689
1932
|
*
|
|
1690
1933
|
* @module @deepseek-ai/dsh-subagent
|
|
1691
1934
|
*/
|
|
1935
|
+
var __addDisposableResource = function(env, value, async) {
|
|
1936
|
+
if (value !== null && value !== void 0) {
|
|
1937
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
1938
|
+
var dispose, inner;
|
|
1939
|
+
if (async) {
|
|
1940
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
1941
|
+
dispose = value[Symbol.asyncDispose];
|
|
1942
|
+
}
|
|
1943
|
+
if (dispose === void 0) {
|
|
1944
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
1945
|
+
dispose = value[Symbol.dispose];
|
|
1946
|
+
if (async) inner = dispose;
|
|
1947
|
+
}
|
|
1948
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
1949
|
+
if (inner) dispose = function() {
|
|
1950
|
+
try {
|
|
1951
|
+
inner.call(this);
|
|
1952
|
+
} catch (e) {
|
|
1953
|
+
return Promise.reject(e);
|
|
1954
|
+
}
|
|
1955
|
+
};
|
|
1956
|
+
env.stack.push({
|
|
1957
|
+
value,
|
|
1958
|
+
dispose,
|
|
1959
|
+
async
|
|
1960
|
+
});
|
|
1961
|
+
} else if (async) env.stack.push({ async: true });
|
|
1962
|
+
return value;
|
|
1963
|
+
};
|
|
1964
|
+
var __disposeResources = (function(SuppressedError) {
|
|
1965
|
+
return function(env) {
|
|
1966
|
+
function fail(e) {
|
|
1967
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
1968
|
+
env.hasError = true;
|
|
1969
|
+
}
|
|
1970
|
+
var r, s = 0;
|
|
1971
|
+
function next() {
|
|
1972
|
+
while (r = env.stack.pop()) try {
|
|
1973
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
1974
|
+
if (r.dispose) {
|
|
1975
|
+
var result = r.dispose.call(r.value);
|
|
1976
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
|
|
1977
|
+
fail(e);
|
|
1978
|
+
return next();
|
|
1979
|
+
});
|
|
1980
|
+
} else s |= 1;
|
|
1981
|
+
} catch (e) {
|
|
1982
|
+
fail(e);
|
|
1983
|
+
}
|
|
1984
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
1985
|
+
if (env.hasError) throw env.error;
|
|
1986
|
+
}
|
|
1987
|
+
return next();
|
|
1988
|
+
};
|
|
1989
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
|
|
1990
|
+
var e = new Error(message);
|
|
1991
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1992
|
+
});
|
|
1692
1993
|
/**
|
|
1693
|
-
* Concurrent cold
|
|
1694
|
-
*
|
|
1695
|
-
*
|
|
1994
|
+
* Concurrent cold observations per explicit catalog listing. Current Session
|
|
1995
|
+
* persistence providers are local; a networked provider must promote this to
|
|
1996
|
+
* a validated deployment setting.
|
|
1696
1997
|
*/
|
|
1697
1998
|
const COLD_READ_CONCURRENCY = 4;
|
|
1698
1999
|
/**
|
|
@@ -1700,9 +2001,8 @@ const COLD_READ_CONCURRENCY = 4;
|
|
|
1700
2001
|
* live-preferred merge of `ctx.sessions` and optional session persistence,
|
|
1701
2002
|
* serving each identity from the `subagent` projection unit: the registry's
|
|
1702
2003
|
* watermark snapshot for a live child; for a cold one, a durable
|
|
1703
|
-
* projection-cache
|
|
1704
|
-
* else one bounded-concurrency
|
|
1705
|
-
* registry.
|
|
2004
|
+
* projection-cache read when it serves an own-suffix identity (the seq gate),
|
|
2005
|
+
* else one bounded-concurrency shared Session observation.
|
|
1706
2006
|
* @see SubagentRuntime.listChildren for the public cancellation and failure contract.
|
|
1707
2007
|
* @param ctx - context carrying the session store, the projection registry,
|
|
1708
2008
|
* optional persistence, and the optional projection cache.
|
|
@@ -1751,32 +2051,30 @@ async function prepareListing(ctx, signal) {
|
|
|
1751
2051
|
const sessions = ctx.get("sessions");
|
|
1752
2052
|
if (sessions === void 0) throw new SubagentError("listing subagents requires the session store (load @deepseek-ai/dsh-session)", "SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE");
|
|
1753
2053
|
assertListingNotCancelled(signal);
|
|
1754
|
-
const
|
|
2054
|
+
const query = ctx.get("sessionQuery");
|
|
2055
|
+
if (query === void 0) throw new SubagentError("listing subagents requires the sessionQuery service (load @deepseek-ai/dsh-session-query)", "SUBAGENT_CONTROL_QUERY_UNAVAILABLE");
|
|
1755
2056
|
const cache = ctx.get("sessionProjectionCache");
|
|
1756
|
-
let
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
} catch (error) {
|
|
1761
|
-
assertListingNotCancelled(signal);
|
|
1762
|
-
throw error;
|
|
1763
|
-
}
|
|
2057
|
+
let records;
|
|
2058
|
+
try {
|
|
2059
|
+
records = await query.listSessions(signal);
|
|
2060
|
+
} catch (error) {
|
|
1764
2061
|
assertListingNotCancelled(signal);
|
|
2062
|
+
throw error;
|
|
1765
2063
|
}
|
|
2064
|
+
assertListingNotCancelled(signal);
|
|
1766
2065
|
const corpus = /* @__PURE__ */ new Map();
|
|
1767
|
-
for (const
|
|
1768
|
-
header
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
});
|
|
2066
|
+
for (const record of records) {
|
|
2067
|
+
const live = sessions.get(record.header.id);
|
|
2068
|
+
corpus.set(record.header.id, {
|
|
2069
|
+
header: live?.header ?? record.header,
|
|
2070
|
+
live
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
1775
2073
|
const subagentParents = /* @__PURE__ */ new Set();
|
|
1776
2074
|
for (const record of corpus.values()) if (record.header.origin === "subagent" && record.header.parentSession !== void 0) subagentParents.add(record.header.parentSession);
|
|
1777
2075
|
return {
|
|
1778
2076
|
projections,
|
|
1779
|
-
|
|
2077
|
+
query,
|
|
1780
2078
|
cache,
|
|
1781
2079
|
corpus,
|
|
1782
2080
|
subagentParents
|
|
@@ -1784,7 +2082,7 @@ async function prepareListing(ctx, signal) {
|
|
|
1784
2082
|
}
|
|
1785
2083
|
/** Resolve projection-backed rows for aligned candidates with bounded cold reads. */
|
|
1786
2084
|
async function resolveCandidateRows(candidates, listing, signal) {
|
|
1787
|
-
const { projections,
|
|
2085
|
+
const { projections, query, cache, subagentParents } = listing;
|
|
1788
2086
|
const rows = Array.from({ length: candidates.length });
|
|
1789
2087
|
const coldReads = [];
|
|
1790
2088
|
candidates.forEach((candidate, index) => {
|
|
@@ -1798,7 +2096,7 @@ async function resolveCandidateRows(candidates, listing, signal) {
|
|
|
1798
2096
|
}
|
|
1799
2097
|
let identity;
|
|
1800
2098
|
try {
|
|
1801
|
-
identity = projections.snapshot(candidate.live).values.subagent;
|
|
2099
|
+
identity = projections.snapshot(candidate.live, ["subagent"]).values.subagent;
|
|
1802
2100
|
} catch {
|
|
1803
2101
|
rows[index] = {
|
|
1804
2102
|
kind: "diagnostic",
|
|
@@ -1807,13 +2105,13 @@ async function resolveCandidateRows(candidates, listing, signal) {
|
|
|
1807
2105
|
};
|
|
1808
2106
|
return;
|
|
1809
2107
|
}
|
|
1810
|
-
if (identity === void 0 || identity === null) return;
|
|
2108
|
+
if (identity === void 0 || identity === null || identity.seq < (candidate.header.seedLength ?? 0)) return;
|
|
1811
2109
|
rows[index] = childRow(childId, identity, "running", subagentParents.has(childId));
|
|
1812
2110
|
});
|
|
1813
|
-
if (
|
|
2111
|
+
if (coldReads.length > 0) {
|
|
1814
2112
|
const queue = [...coldReads];
|
|
1815
2113
|
await Promise.all(Array.from({ length: Math.min(COLD_READ_CONCURRENCY, queue.length) }, async () => {
|
|
1816
|
-
for (let job = queue.shift(); job !== void 0; job = queue.shift()) rows[job.index] = await resolveColdIdentity(
|
|
2114
|
+
for (let job = queue.shift(); job !== void 0; job = queue.shift()) rows[job.index] = await resolveColdIdentity(query, cache, job.header, subagentParents.has(job.header.id), signal);
|
|
1817
2115
|
}));
|
|
1818
2116
|
}
|
|
1819
2117
|
assertListingNotCancelled(signal);
|
|
@@ -1859,58 +2157,61 @@ function compareCorpusRecords(a, b) {
|
|
|
1859
2157
|
/**
|
|
1860
2158
|
* Resolve one cold candidate down the remaining ladder: a durable
|
|
1861
2159
|
* projection-cache row when it serves an own-suffix identity (the seq gate),
|
|
1862
|
-
* otherwise one
|
|
1863
|
-
*
|
|
1864
|
-
*
|
|
1865
|
-
* retried on the next listing; an inspection naming another lifecycle, and a
|
|
2160
|
+
* otherwise one shared Session observation. An absent or transiently failed
|
|
2161
|
+
* observation is one `unavailable` row retried on the next listing; an observation
|
|
2162
|
+
* source naming another lifecycle, and a
|
|
1866
2163
|
* settled log the fold cannot identify — or that makes any registered unit
|
|
1867
2164
|
* throw — are final, so they report `corrupt`.
|
|
1868
2165
|
*/
|
|
1869
|
-
async function resolveColdIdentity(
|
|
1870
|
-
const
|
|
1871
|
-
|
|
1872
|
-
|
|
2166
|
+
async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
|
|
2167
|
+
const env_1 = {
|
|
2168
|
+
stack: [],
|
|
2169
|
+
error: void 0,
|
|
2170
|
+
hasError: false
|
|
2171
|
+
};
|
|
2172
|
+
try {
|
|
2173
|
+
const childId = header.id;
|
|
2174
|
+
if (cache !== void 0) {
|
|
2175
|
+
let cached;
|
|
2176
|
+
try {
|
|
2177
|
+
cached = cache.cachedSnapshot(header, ["subagent"])?.values.subagent;
|
|
2178
|
+
} catch {
|
|
2179
|
+
cached = void 0;
|
|
2180
|
+
}
|
|
2181
|
+
if (cached !== void 0 && cached !== null && cached.seq >= (header.seedLength ?? 0)) return childRow(childId, cached, "inactive", hasChildren);
|
|
2182
|
+
}
|
|
2183
|
+
assertListingNotCancelled(signal);
|
|
2184
|
+
let observation;
|
|
1873
2185
|
try {
|
|
1874
|
-
|
|
1875
|
-
} catch {
|
|
1876
|
-
|
|
2186
|
+
observation = await query.observeSession(childId, { ...signal === void 0 ? {} : { signal } });
|
|
2187
|
+
} catch (error) {
|
|
2188
|
+
assertListingNotCancelled(signal);
|
|
2189
|
+
return {
|
|
2190
|
+
kind: "diagnostic",
|
|
2191
|
+
id: childId,
|
|
2192
|
+
reason: sessionQueryCode(error) === "SESSION_QUERY_CORRUPT_SESSION" || sessionQueryCode(error) === "SESSION_QUERY_SOURCE_CONFLICT" ? "corrupt" : "unavailable"
|
|
2193
|
+
};
|
|
1877
2194
|
}
|
|
1878
|
-
|
|
1879
|
-
}
|
|
1880
|
-
assertListingNotCancelled(signal);
|
|
1881
|
-
let inspected;
|
|
1882
|
-
try {
|
|
1883
|
-
inspected = await persistence.inspect(childId, signal);
|
|
1884
|
-
} catch {
|
|
2195
|
+
const ownedObservation = __addDisposableResource(env_1, observation, false);
|
|
1885
2196
|
assertListingNotCancelled(signal);
|
|
1886
|
-
return {
|
|
2197
|
+
if (!sameLifecycle(ownedObservation.header, header)) return {
|
|
1887
2198
|
kind: "diagnostic",
|
|
1888
2199
|
id: childId,
|
|
1889
|
-
reason: "
|
|
2200
|
+
reason: "corrupt"
|
|
1890
2201
|
};
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
if (!sameLifecycle(inspected.meta, header)) return {
|
|
1894
|
-
kind: "diagnostic",
|
|
1895
|
-
id: childId,
|
|
1896
|
-
reason: "corrupt"
|
|
1897
|
-
};
|
|
1898
|
-
let identity;
|
|
1899
|
-
try {
|
|
1900
|
-
identity = projections.restore({}, inspected.events, 0).snapshot.values.subagent;
|
|
1901
|
-
} catch {
|
|
1902
|
-
return {
|
|
2202
|
+
const identity = ownedObservation.projections?.values.subagent;
|
|
2203
|
+
if (identity === void 0 || identity === null || identity.seq < (header.seedLength ?? 0)) return {
|
|
1903
2204
|
kind: "diagnostic",
|
|
1904
2205
|
id: childId,
|
|
1905
2206
|
reason: "corrupt"
|
|
1906
2207
|
};
|
|
2208
|
+
return childRow(childId, identity, "inactive", hasChildren);
|
|
2209
|
+
} catch (e_1) {
|
|
2210
|
+
env_1.error = e_1;
|
|
2211
|
+
env_1.hasError = true;
|
|
2212
|
+
} finally {
|
|
2213
|
+
__disposeResources(env_1);
|
|
1907
2214
|
}
|
|
1908
|
-
if (identity === void 0 || identity === null) return {
|
|
1909
|
-
kind: "diagnostic",
|
|
1910
|
-
id: childId,
|
|
1911
|
-
reason: "corrupt"
|
|
1912
|
-
};
|
|
1913
|
-
return childRow(childId, identity, "inactive", hasChildren);
|
|
1914
2215
|
}
|
|
1915
2216
|
/** Materialize one served identity as its child row. */
|
|
1916
2217
|
function childRow(id, identity, activity, hasChildren) {
|
|
@@ -1938,7 +2239,9 @@ const LIFECYCLE_WITNESS_KEYS = [
|
|
|
1938
2239
|
"cwd",
|
|
1939
2240
|
"parentSession",
|
|
1940
2241
|
"seedLength",
|
|
1941
|
-
"delegationDepth"
|
|
2242
|
+
"delegationDepth",
|
|
2243
|
+
"origin",
|
|
2244
|
+
"agentPreset"
|
|
1942
2245
|
];
|
|
1943
2246
|
/** Whether an inspected log still belongs to the enumerated lifecycle. */
|
|
1944
2247
|
function sameLifecycle(meta, expected) {
|
|
@@ -1948,6 +2251,9 @@ function sameLifecycle(meta, expected) {
|
|
|
1948
2251
|
function assertListingNotCancelled(signal) {
|
|
1949
2252
|
if (signal?.aborted) throw new SubagentError("subagent listing was cancelled", "CANCELLED");
|
|
1950
2253
|
}
|
|
2254
|
+
function sessionQueryCode(error) {
|
|
2255
|
+
return error instanceof Error && "code" in error ? error.code : void 0;
|
|
2256
|
+
}
|
|
1951
2257
|
//#endregion
|
|
1952
2258
|
//#region lib/types/projection.js
|
|
1953
2259
|
/**
|
|
@@ -2127,13 +2433,21 @@ function limitSubagentDiagnostic(diagnostic) {
|
|
|
2127
2433
|
while ((bytes[prefixBytes] & 192) === 128) prefixBytes -= 1;
|
|
2128
2434
|
return utf8Decoder.decode(bytes.subarray(0, prefixBytes)) + DIAGNOSTIC_TRUNCATION_SUFFIX;
|
|
2129
2435
|
}
|
|
2436
|
+
/** Enforce the byte limit on a provider-returned diagnostic. */
|
|
2437
|
+
function normalizeSubagentDiagnostic(result) {
|
|
2438
|
+
return result.diagnostic === void 0 ? result : {
|
|
2439
|
+
...result,
|
|
2440
|
+
diagnostic: limitSubagentDiagnostic(result.diagnostic)
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2130
2443
|
/**
|
|
2131
2444
|
* The capability advertisement of an out-of-process backend: NONE. A child in
|
|
2132
2445
|
* another process cannot honor parent-enforced start features
|
|
2133
|
-
* (`outputSchema`/`maxDepth`/`toolFilter`/`persona`), so the service rejects a
|
|
2446
|
+
* (`agentOptions`/`outputSchema`/`maxDepth`/`toolFilter`/`persona`), so the service rejects a
|
|
2134
2447
|
* request needing any of them before `start` runs — never accepted-then-ignored.
|
|
2135
2448
|
*/
|
|
2136
2449
|
const NO_START_CAPABILITIES = Object.freeze({
|
|
2450
|
+
agentOptions: false,
|
|
2137
2451
|
outputSchema: false,
|
|
2138
2452
|
depthLimit: false,
|
|
2139
2453
|
toolFilter: false,
|
|
@@ -2221,7 +2535,8 @@ function toError(value) {
|
|
|
2221
2535
|
* rejects after publication. A normally completed or rejected attempt resolves
|
|
2222
2536
|
* as `aborted` when cancellation already settled locally; another rejection is
|
|
2223
2537
|
* flattened to `stopReason: 'error'` through the contained diagnostic sink.
|
|
2224
|
-
* The abort listener is
|
|
2538
|
+
* Provider-returned diagnostics use the same byte limit. The abort listener is
|
|
2539
|
+
* removed on every path.
|
|
2225
2540
|
* @param parts - the attempt, output snapshot, cancellation state, sink, and signal wiring.
|
|
2226
2541
|
* @returns the terminal result (never a rejection).
|
|
2227
2542
|
*/
|
|
@@ -2231,7 +2546,7 @@ async function settleRunResult(parts) {
|
|
|
2231
2546
|
return parts.cancelled() ? {
|
|
2232
2547
|
output: parts.collectOutput(),
|
|
2233
2548
|
stopReason: "aborted"
|
|
2234
|
-
} : result;
|
|
2549
|
+
} : normalizeSubagentDiagnostic(result);
|
|
2235
2550
|
} catch (error) {
|
|
2236
2551
|
if (parts.cancelled()) return {
|
|
2237
2552
|
output: parts.collectOutput(),
|
|
@@ -2293,8 +2608,10 @@ function failureDetail(result) {
|
|
|
2293
2608
|
return result.diagnostic === void 0 ? stopReason : `${stopReason}; diagnostic: ${result.diagnostic}`;
|
|
2294
2609
|
}
|
|
2295
2610
|
/**
|
|
2296
|
-
* Map a child result to the task outcome: completed carries final text,
|
|
2297
|
-
* aborted is killed, and
|
|
2611
|
+
* Map a child result to the task outcome: completed carries final text, local
|
|
2612
|
+
* cancellation (`aborted` without a diagnostic) is killed, and provider-
|
|
2613
|
+
* diagnosed remote aborts plus every other reason are failed without partial
|
|
2614
|
+
* output.
|
|
2298
2615
|
* @param result - child terminal result.
|
|
2299
2616
|
* @returns outcome for the `ctx.jobs` registration.
|
|
2300
2617
|
*/
|
|
@@ -2304,7 +2621,10 @@ function runOutcome(result) {
|
|
|
2304
2621
|
status: "completed",
|
|
2305
2622
|
output: finalText(result.output)
|
|
2306
2623
|
};
|
|
2307
|
-
case "aborted": return { status: "killed" }
|
|
2624
|
+
case "aborted": return result.diagnostic === void 0 ? { status: "killed" } : {
|
|
2625
|
+
status: "failed",
|
|
2626
|
+
detail: failureDetail(result)
|
|
2627
|
+
};
|
|
2308
2628
|
case "error":
|
|
2309
2629
|
case "max-tokens":
|
|
2310
2630
|
case "refusal": return {
|
|
@@ -2351,10 +2671,8 @@ async function settleRun(run) {
|
|
|
2351
2671
|
* child before returning its run, so fulfillment is the single publication and
|
|
2352
2672
|
* ownership-transfer boundary.
|
|
2353
2673
|
*
|
|
2354
|
-
*
|
|
2355
|
-
*
|
|
2356
|
-
* one by name. The shape mirrors the LLM adapter registry
|
|
2357
|
-
* (`LlmRuntime.registerAdapter`), not the single-service bash executor.
|
|
2674
|
+
* Multiple providers coexist: each registers under a unique name and callers
|
|
2675
|
+
* select one by name.
|
|
2358
2676
|
*
|
|
2359
2677
|
* This package owns the Service Definition role of the capability seam. Service Providers
|
|
2360
2678
|
* (`@deepseek-ai/dsh-subagent-spawn-in-process`, `-fork`, `-acp`) and the model-facing
|
|
@@ -2377,299 +2695,481 @@ async function settleRun(run) {
|
|
|
2377
2695
|
*
|
|
2378
2696
|
* @module @deepseek-ai/dsh-subagent
|
|
2379
2697
|
*/
|
|
2698
|
+
var __runInitializers = function(thisArg, initializers, value) {
|
|
2699
|
+
var useValue = arguments.length > 2;
|
|
2700
|
+
for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
2701
|
+
return useValue ? value : void 0;
|
|
2702
|
+
};
|
|
2703
|
+
var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2704
|
+
function accept(f) {
|
|
2705
|
+
if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
|
|
2706
|
+
return f;
|
|
2707
|
+
}
|
|
2708
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
2709
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
2710
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
2711
|
+
var _, done = false;
|
|
2712
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2713
|
+
var context = {};
|
|
2714
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
2715
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
2716
|
+
context.addInitializer = function(f) {
|
|
2717
|
+
if (done) throw new TypeError("Cannot add initializers after decoration has completed");
|
|
2718
|
+
extraInitializers.push(accept(f || null));
|
|
2719
|
+
};
|
|
2720
|
+
var result = (0, decorators[i])(kind === "accessor" ? {
|
|
2721
|
+
get: descriptor.get,
|
|
2722
|
+
set: descriptor.set
|
|
2723
|
+
} : descriptor[key], context);
|
|
2724
|
+
if (kind === "accessor") {
|
|
2725
|
+
if (result === void 0) continue;
|
|
2726
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
2727
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
2728
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
2729
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
2730
|
+
} else if (_ = accept(result)) if (kind === "field") initializers.unshift(_);
|
|
2731
|
+
else descriptor[key] = _;
|
|
2732
|
+
}
|
|
2733
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
2734
|
+
done = true;
|
|
2735
|
+
};
|
|
2380
2736
|
/** Named provider registry with one-shot runs, durable discovery, and continuable-child operations. */
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2737
|
+
let SubagentRuntime = (() => {
|
|
2738
|
+
let _classSuper = TypertRemoteService;
|
|
2739
|
+
let _instanceExtraInitializers = [];
|
|
2740
|
+
let _remoteExportList_decorators;
|
|
2741
|
+
let _prompt_decorators;
|
|
2742
|
+
let _interruptByParent_decorators;
|
|
2743
|
+
return class SubagentRuntime extends _classSuper {
|
|
2744
|
+
static {
|
|
2745
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2746
|
+
_remoteExportList_decorators = [Remote("list")];
|
|
2747
|
+
_prompt_decorators = [Remote("prompt")];
|
|
2748
|
+
_interruptByParent_decorators = [Remote("interruptByParent")];
|
|
2749
|
+
__esDecorate(this, null, _remoteExportList_decorators, {
|
|
2750
|
+
kind: "method",
|
|
2751
|
+
name: "remoteExportList",
|
|
2752
|
+
static: false,
|
|
2753
|
+
private: false,
|
|
2754
|
+
access: {
|
|
2755
|
+
has: (obj) => "remoteExportList" in obj,
|
|
2756
|
+
get: (obj) => obj.remoteExportList
|
|
2757
|
+
},
|
|
2758
|
+
metadata: _metadata
|
|
2759
|
+
}, null, _instanceExtraInitializers);
|
|
2760
|
+
__esDecorate(this, null, _prompt_decorators, {
|
|
2761
|
+
kind: "method",
|
|
2762
|
+
name: "prompt",
|
|
2763
|
+
static: false,
|
|
2764
|
+
private: false,
|
|
2765
|
+
access: {
|
|
2766
|
+
has: (obj) => "prompt" in obj,
|
|
2767
|
+
get: (obj) => obj.prompt
|
|
2768
|
+
},
|
|
2769
|
+
metadata: _metadata
|
|
2770
|
+
}, null, _instanceExtraInitializers);
|
|
2771
|
+
__esDecorate(this, null, _interruptByParent_decorators, {
|
|
2772
|
+
kind: "method",
|
|
2773
|
+
name: "interruptByParent",
|
|
2774
|
+
static: false,
|
|
2775
|
+
private: false,
|
|
2776
|
+
access: {
|
|
2777
|
+
has: (obj) => "interruptByParent" in obj,
|
|
2778
|
+
get: (obj) => obj.interruptByParent
|
|
2779
|
+
},
|
|
2780
|
+
metadata: _metadata
|
|
2781
|
+
}, null, _instanceExtraInitializers);
|
|
2782
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
2783
|
+
enumerable: true,
|
|
2784
|
+
configurable: true,
|
|
2785
|
+
writable: true,
|
|
2786
|
+
value: _metadata
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
providers = (__runInitializers(this, _instanceExtraInitializers), /* @__PURE__ */ new Map());
|
|
2790
|
+
continuations;
|
|
2791
|
+
/** Deployment contributions composed into unpublished continuable children. */
|
|
2792
|
+
setupRegistry = new SubagentActivationSetupRegistry();
|
|
2793
|
+
/**
|
|
2794
|
+
* The contained lifecycle-edge publisher. Built here because scoped dispatch
|
|
2795
|
+
* keys its carrier by this exact service instance, whose own context filter
|
|
2796
|
+
* composes into the carrier.
|
|
2797
|
+
*/
|
|
2798
|
+
emitLifecycle;
|
|
2799
|
+
constructor(ctx) {
|
|
2800
|
+
super(ctx, "subagents");
|
|
2801
|
+
this.emitLifecycle = createLifecycleEmitter(this.ctx, (parent) => scopeTarget(this, parent));
|
|
2802
|
+
ctx.inject(["agents"], (childCtx) => {
|
|
2803
|
+
const manager = new SubagentContinuationManager(childCtx, {
|
|
2804
|
+
prepareContinuable: (name, request) => this.prepareContinuable(name, request),
|
|
2805
|
+
observeActivation: (provider, childId, parent) => this.observeActivation(provider, childId, parent)
|
|
2806
|
+
}, this.setupRegistry);
|
|
2807
|
+
this.continuations = manager;
|
|
2808
|
+
childCtx.effect(() => () => {
|
|
2809
|
+
/* v8 ignore else -- one injected binding owns the slot until its fiber disposes. */
|
|
2810
|
+
if (this.continuations === manager) this.continuations = void 0;
|
|
2811
|
+
}, "subagents.continuationBinding()");
|
|
2812
|
+
});
|
|
2813
|
+
ctx.inject(["sessionProjections"], (projectionCtx) => {
|
|
2814
|
+
projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition);
|
|
2815
|
+
projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition);
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
/**
|
|
2819
|
+
* Establish one durable continuable child and deliver its initial prompt.
|
|
2820
|
+
* Resolves when the child's inbox accepts that prompt, without waiting for the
|
|
2821
|
+
* turn to start or for the message to reach the Session log; any earlier
|
|
2822
|
+
* failure rejects with no ids and rolls back the child entirely.
|
|
2823
|
+
* @param spec - provider, delegation request, and caller cancellation.
|
|
2824
|
+
* @returns the durable child id and the accepted prompt's message id.
|
|
2825
|
+
* @throws when continuation services are unavailable or materialization fails.
|
|
2826
|
+
*/
|
|
2827
|
+
async startContinuable(spec) {
|
|
2828
|
+
return this.requireContinuations().startContinuable(spec);
|
|
2829
|
+
}
|
|
2830
|
+
/**
|
|
2831
|
+
* Deliver one later message to a continuable child as its next FIFO turn. A
|
|
2832
|
+
* resident child's Agent inbox accepts it directly (waking a `waiting`
|
|
2833
|
+
* Activation), while an absent one is cold-resumed from its persisted
|
|
2834
|
+
* Session. The Agent inbox is the only queue, so every accepted message has
|
|
2835
|
+
* one observable order.
|
|
2836
|
+
* @param parent - the exact live direct parent authorizing this delivery.
|
|
2837
|
+
* @param childId - durable child session id.
|
|
2838
|
+
* @param content - user-role content to deliver.
|
|
2839
|
+
* @param options - the message source fields and caller cancellation, which stops the
|
|
2840
|
+
* operation only before inbox acceptance.
|
|
2841
|
+
* @returns the accepted message's inbox id.
|
|
2842
|
+
* @throws when continuation services are unavailable, parent authority is
|
|
2843
|
+
* rejected, or the message was not admitted.
|
|
2844
|
+
*/
|
|
2845
|
+
async followup(parent, childId, content, options) {
|
|
2846
|
+
return this.requireContinuations().followup(parent, childId, content, options);
|
|
2847
|
+
}
|
|
2848
|
+
/**
|
|
2849
|
+
* Interrupt one live continuable child's current turn under a human parent
|
|
2850
|
+
* address or an exact live ancestor Agent. Fire-and-return: the cancel
|
|
2851
|
+
* signal is issued before this returns, but the target may keep running
|
|
2852
|
+
* until it observes the signal. Unclaimed pending inbox work, the Activation,
|
|
2853
|
+
* and published descendants are preserved; claimed work is not requeued.
|
|
2854
|
+
* Once the interrupted driver is idle, a waking send resumes the parked FIFO
|
|
2855
|
+
* queue. An absent target — including a one-shot or unknown id —
|
|
2856
|
+
* is an accepted no-op, as is a manager-less composition, which cannot own a
|
|
2857
|
+
* live Activation.
|
|
2858
|
+
* @param targetSessionId - the durable child session id to interrupt.
|
|
2859
|
+
* @param authority - the human parent address or exact live ancestor Agent.
|
|
2860
|
+
* @throws {SubagentError} `UNAUTHORIZED` when the authority does not own the
|
|
2861
|
+
* live target.
|
|
2862
|
+
*/
|
|
2863
|
+
interrupt(targetSessionId, authority) {
|
|
2864
|
+
this.continuations?.interrupt(targetSessionId, authority);
|
|
2865
|
+
}
|
|
2866
|
+
/**
|
|
2867
|
+
* Deliver selected content from one live continuable child to its durable
|
|
2868
|
+
* direct parent. The child is the authority credential; callers cannot name a
|
|
2869
|
+
* recipient. Reporting does not conclude the child's turn or Activation.
|
|
2870
|
+
* @param child - exact live reporting child.
|
|
2871
|
+
* @param content - selected model-facing content.
|
|
2872
|
+
* @param options - parent scheduling and pre-acceptance cancellation.
|
|
2873
|
+
* @returns the stable identity of the parent-accepted message.
|
|
2874
|
+
* @throws when continuation services are unavailable, sender authorization
|
|
2875
|
+
* fails, or the direct parent is not live.
|
|
2876
|
+
*/
|
|
2877
|
+
async reportFrom(child, content, options) {
|
|
2878
|
+
return this.requireContinuations().reportFrom(child, content, options);
|
|
2879
|
+
}
|
|
2880
|
+
/**
|
|
2881
|
+
* Compose one deployment capability into every continuable child's
|
|
2882
|
+
* unpublished creation context on fresh creation and cold resume. Grants wait
|
|
2883
|
+
* for the next Activation; removing the contribution revokes every resident
|
|
2884
|
+
* installation immediately.
|
|
2885
|
+
* @param contribution - synchronous child-scope installer.
|
|
2886
|
+
* @returns the exact Cordis effect disposer.
|
|
2887
|
+
*/
|
|
2888
|
+
registerContinuableSetup(contribution) {
|
|
2889
|
+
return this.ctx.effect(() => this.setupRegistry.register(contribution), "subagents.registerContinuableSetup()");
|
|
2890
|
+
}
|
|
2891
|
+
/**
|
|
2892
|
+
* Close continuable admission below exact live parent Agents, stop only their
|
|
2893
|
+
* visible descendant Activations synchronously, then await admitted scoped
|
|
2894
|
+
* materializations and release those forests child-first. The scoped cutoff
|
|
2895
|
+
* lasts until each exact parent leaves the registry; unrelated parent trees
|
|
2896
|
+
* remain live.
|
|
2897
|
+
* @param parents - exact host-owned parent Agents entering teardown.
|
|
2898
|
+
* @returns once every retained descendant Activation released its `AgentHandle`.
|
|
2899
|
+
* @throws an aggregate error after all branches settle when any failed.
|
|
2900
|
+
*/
|
|
2901
|
+
async drainContinuableDescendants(parents) {
|
|
2902
|
+
const manager = this.continuations;
|
|
2903
|
+
if (manager === void 0) return;
|
|
2904
|
+
await manager.drainDescendants(parents);
|
|
2905
|
+
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Release selected resident continuable direct children of one exact live
|
|
2908
|
+
* parent. Other children of the same parent remain admitted and resident.
|
|
2909
|
+
* Absent targets and a manager-less composition are accepted no-ops.
|
|
2910
|
+
* @param parent - exact live direct parent authorizing the selected release.
|
|
2911
|
+
* @param childIds - durable direct-child ids to release when resident.
|
|
2912
|
+
* @returns once every selected Activation released its `AgentHandle`.
|
|
2913
|
+
* @throws {SubagentError} `UNAUTHORIZED` when a resident target belongs to a
|
|
2914
|
+
* different parent or the supplied parent identity is stale.
|
|
2915
|
+
*/
|
|
2916
|
+
async drainContinuableChildren(parent, childIds) {
|
|
2917
|
+
const manager = this.continuations;
|
|
2918
|
+
if (manager === void 0) return;
|
|
2919
|
+
await manager.drainChildren(parent, childIds);
|
|
2920
|
+
}
|
|
2921
|
+
/**
|
|
2922
|
+
* Enumerate the parent's direct session-backed subagents without loading or
|
|
2923
|
+
* resuming an Agent. The Session query service supplies one live-preferred
|
|
2924
|
+
* corpus and shared point observations; the projection cache supplies
|
|
2925
|
+
* immutable descriptor hits without opening cold logs. The registered
|
|
2926
|
+
* `subagent` projection remains the sole mode/label classifier.
|
|
2927
|
+
*
|
|
2928
|
+
* Every query receives `signal`, and the listing rechecks cancellation
|
|
2929
|
+
* around each await. Read rejections that settle
|
|
2930
|
+
* after an abort become a stable `SubagentError` with code `CANCELLED`.
|
|
2931
|
+
* @param parentSessionId - parent session whose direct children are listed.
|
|
2932
|
+
* @param signal - caller-owned cancellation forwarded to Session queries
|
|
2933
|
+
* and observed around every read await.
|
|
2934
|
+
* @returns children and per-child diagnostics ordered by `createdAt`, then id.
|
|
2935
|
+
* @throws {@link SubagentError} when the projection registry or the session
|
|
2936
|
+
* store is not mounted, or the caller cancels the listing.
|
|
2937
|
+
*/
|
|
2938
|
+
listChildren(parentSessionId, signal) {
|
|
2939
|
+
return listChildren(this.ctx, parentSessionId, signal);
|
|
2940
|
+
}
|
|
2941
|
+
/**
|
|
2942
|
+
* Enumerate the root's complete session-backed subagent tree in stable
|
|
2943
|
+
* pre-order from one live-preferred corpus, without loading or resuming an
|
|
2944
|
+
* Agent. Ordinary sessions and one-shot children remain traversal nodes so
|
|
2945
|
+
* continuable descendants below them are discovered; each returned entry
|
|
2946
|
+
* adds its durable `parentId` and root-relative `depth`. Identity resolution,
|
|
2947
|
+
* diagnostics, optional persistence, and cancellation follow the same
|
|
2948
|
+
* projection-backed contract as {@link listChildren}.
|
|
2949
|
+
* @param rootSessionId - session whose complete descendant tree is listed.
|
|
2950
|
+
* @param signal - caller-owned cancellation forwarded to persistence reads
|
|
2951
|
+
* and observed around every read await.
|
|
2952
|
+
* @returns children and per-candidate diagnostics with tree position, in
|
|
2953
|
+
* stable pre-order.
|
|
2954
|
+
* @throws {@link SubagentError} under the same conditions as {@link listChildren}.
|
|
2955
|
+
*/
|
|
2956
|
+
listDescendants(rootSessionId, signal) {
|
|
2957
|
+
return listDescendants(this.ctx, rootSessionId, signal);
|
|
2958
|
+
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Remote face of {@link listChildren} for one browser: the durable listing
|
|
2961
|
+
* plus live Agent activity and the delivery-time parent availability hint.
|
|
2962
|
+
* Parent availability is a hint; {@link prompt} performs the authoritative
|
|
2963
|
+
* check. Named apart from the provider-name {@link list}, which owns the
|
|
2964
|
+
* member.
|
|
2965
|
+
* @param parentSessionId - parent session whose direct children are listed.
|
|
2966
|
+
* @param signal - carrier cancellation forwarded to Session queries.
|
|
2967
|
+
* @returns the catalog view for that parent.
|
|
2968
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty parent id,
|
|
2969
|
+
* `gateway/cancelled` for an aborted read, `subagent/projections-unavailable` when
|
|
2970
|
+
* the deployment has no projection registry, otherwise `gateway/internal`.
|
|
2971
|
+
*/
|
|
2972
|
+
async remoteExportList(parentSessionId, signal) {
|
|
2973
|
+
validateControlRequest("subagent.list", { parentSessionId });
|
|
2974
|
+
try {
|
|
2975
|
+
return catalogView(this.ctx, parentSessionId, await this.listChildren(parentSessionId, signal));
|
|
2976
|
+
} catch (error) {
|
|
2977
|
+
return rejectCatalogRead(error, signal);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
/**
|
|
2981
|
+
* Deliver one browser-authored message to a continuable child through the
|
|
2982
|
+
* exact live direct parent, retaining the caller-minted request identity and
|
|
2983
|
+
* validated browser zone on the accepted message. Success identifies the
|
|
2984
|
+
* message the child's FIFO inbox accepted; later execution is independent of
|
|
2985
|
+
* this call.
|
|
2986
|
+
* Image parts are admitted and persisted through the attachment store
|
|
2987
|
+
* before delivery, and the child's model must accept image input.
|
|
2988
|
+
* @param request - durable address, minted identity, content, and optional browser zone.
|
|
2989
|
+
* @param signal - carrier cancellation, owning the call until inbox acceptance.
|
|
2990
|
+
* @returns the accepted message's inbox identity.
|
|
2991
|
+
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-invalid`,
|
|
2992
|
+
* `subagent/invalid-time-zone`, `subagent/parent-unavailable`,
|
|
2993
|
+
* `subagent/not-resumable`, `subagent/unauthorized`,
|
|
2994
|
+
* `subagent/delivery-unavailable`, `gateway/cancelled`, or `gateway/internal`.
|
|
2995
|
+
*/
|
|
2996
|
+
async prompt(request, signal) {
|
|
2997
|
+
const { parentSessionId, childSessionId, clientTimeZone } = request;
|
|
2998
|
+
validateControlRequest("subagent.prompt", request);
|
|
2999
|
+
const canonicalTimeZone = clientTimeZone === void 0 ? void 0 : canonicalClientTimeZone(clientTimeZone);
|
|
3000
|
+
if (clientTimeZone !== void 0 && canonicalTimeZone === void 0) throw new RemoteError("subagent/invalid-time-zone", "clientTimeZone must be UTC or a valid IANA Area/Location name", { value: clientTimeZone });
|
|
3001
|
+
const parent = this.ctx.get("agents")?.get(parentSessionId);
|
|
3002
|
+
if (parent === void 0) throw new RemoteError("subagent/parent-unavailable", `parent session "${parentSessionId}" is not live`, { parentSessionId });
|
|
3003
|
+
const source = {
|
|
3004
|
+
kind: "user",
|
|
3005
|
+
rpcId: request.requestId,
|
|
3006
|
+
...canonicalTimeZone === void 0 ? {} : { clientTimeZone: canonicalTimeZone }
|
|
2578
3007
|
};
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
}
|
|
2597
|
-
/**
|
|
2598
|
-
* Establish a published child on the named provider. Capability and semantic
|
|
2599
|
-
* checks run before delegation. Provider ownership lasts until its promise
|
|
2600
|
-
* fulfills; a rejection therefore has no run for the caller to dispose and
|
|
2601
|
-
* emits no run lifecycle events. Post-publication turn and infrastructure
|
|
2602
|
-
* failures settle through the returned run.
|
|
2603
|
-
* @param name - the provider to use.
|
|
2604
|
-
* @param request - child label, prompt, parent, signal, and optional capabilities.
|
|
2605
|
-
* @returns the published holder-owned run.
|
|
2606
|
-
*/
|
|
2607
|
-
async start(name, request) {
|
|
2608
|
-
const provider = this.expectProvider(name);
|
|
2609
|
-
this.assertCapabilities(provider, request);
|
|
2610
|
-
assertSubagentMaxDepth(request.maxDepth);
|
|
2611
|
-
if (request.outputSchema !== void 0) assertObjectJsonSchema(request.outputSchema);
|
|
2612
|
-
const descriptor = snapshotSubagentDescriptor({
|
|
2613
|
-
mode: "one-shot",
|
|
2614
|
-
provider: name,
|
|
2615
|
-
...request.label !== void 0 ? { label: request.label } : {}
|
|
2616
|
-
});
|
|
2617
|
-
const resolved = {
|
|
2618
|
-
...request,
|
|
2619
|
-
descriptor
|
|
2620
|
-
};
|
|
2621
|
-
return observeRun(this.emitLifecycle, name, request.parent, await provider.start(resolved));
|
|
2622
|
-
}
|
|
2623
|
-
/**
|
|
2624
|
-
* Resolve one provider's detached continuable-creation contribution. Method
|
|
2625
|
-
* presence on the provider IS the capability, so a provider without it is
|
|
2626
|
-
* rejected before the manager reserves any child resources.
|
|
2627
|
-
*/
|
|
2628
|
-
async prepareContinuable(name, request) {
|
|
2629
|
-
const provider = this.expectProvider(name);
|
|
2630
|
-
if (provider.prepareContinuable === void 0) throw new SubagentError(`subagent provider "${provider.name}" does not support continuable children (no prepareContinuable capability)`, "UNSUPPORTED_CAPABILITY");
|
|
2631
|
-
return provider.prepareContinuable(request);
|
|
2632
|
-
}
|
|
2633
|
-
/** Look up a provider for dispatch or fail loud. */
|
|
2634
|
-
expectProvider(name) {
|
|
2635
|
-
const provider = this.providers.get(name);
|
|
2636
|
-
if (provider === void 0) throw new SubagentError(`no subagent provider registered for "${name}"`, "NO_PROVIDER");
|
|
2637
|
-
return provider;
|
|
2638
|
-
}
|
|
2639
|
-
/** Resolve the optional continuable-subagent manager or fail loud. */
|
|
2640
|
-
requireContinuations() {
|
|
2641
|
-
if (this.continuations === void 0) throw new SubagentError("continuable subagents require the agents service", "CONTINUATION_UNAVAILABLE");
|
|
2642
|
-
return this.continuations;
|
|
2643
|
-
}
|
|
2644
|
-
/**
|
|
2645
|
-
* Build the lifecycle observer for one continuable Activation's residency
|
|
2646
|
-
* epoch, so the manager publishes its edges without owning event dispatch.
|
|
2647
|
-
*/
|
|
2648
|
-
observeActivation(provider, childId, parent) {
|
|
2649
|
-
return createActivationObserver(this.emitLifecycle, provider, childId, parent);
|
|
2650
|
-
}
|
|
2651
|
-
/** Reject the first requested capability that the provider lacks. */
|
|
2652
|
-
assertCapabilities(provider, request) {
|
|
2653
|
-
const needs = [
|
|
2654
|
-
{
|
|
2655
|
-
when: request.outputSchema !== void 0,
|
|
2656
|
-
cap: "outputSchema"
|
|
2657
|
-
},
|
|
2658
|
-
{
|
|
2659
|
-
when: request.maxDepth !== void 0,
|
|
2660
|
-
cap: "depthLimit"
|
|
2661
|
-
},
|
|
2662
|
-
{
|
|
2663
|
-
when: request.toolFilter !== void 0,
|
|
2664
|
-
cap: "toolFilter"
|
|
2665
|
-
},
|
|
2666
|
-
{
|
|
2667
|
-
when: request.persona !== void 0,
|
|
2668
|
-
cap: "persona"
|
|
3008
|
+
try {
|
|
3009
|
+
let content;
|
|
3010
|
+
if (request.content.every((part) => part.type === "text")) content = request.content.map((part) => ({
|
|
3011
|
+
type: "text",
|
|
3012
|
+
text: part.text
|
|
3013
|
+
}));
|
|
3014
|
+
else {
|
|
3015
|
+
const attachments = this.ctx.get("attachments");
|
|
3016
|
+
if (attachments === void 0) throw new Error("subagent image prompt requires an attachment store");
|
|
3017
|
+
content = await admitPromptContent(attachments, request.content);
|
|
3018
|
+
}
|
|
3019
|
+
return { messageId: await this.followup(parent, childSessionId, content, {
|
|
3020
|
+
source,
|
|
3021
|
+
signal
|
|
3022
|
+
}) };
|
|
3023
|
+
} catch (error) {
|
|
3024
|
+
return rejectPrompt(error, childSessionId, signal);
|
|
2669
3025
|
}
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
3026
|
+
}
|
|
3027
|
+
/**
|
|
3028
|
+
* Remote face of {@link interrupt} under one durable parent address. No
|
|
3029
|
+
* catalog, history, persistence, or parent Agent lookup runs: the core
|
|
3030
|
+
* primitive alone authorizes the address against the live Activation, which
|
|
3031
|
+
* is what keeps a live child interruptible while its parent Agent is offline.
|
|
3032
|
+
* Absent, idle, and already-completed targets are accepted no-ops there.
|
|
3033
|
+
* @param childSessionId - durable child session id to interrupt.
|
|
3034
|
+
* @param parentSessionId - durable direct parent whose authority is claimed.
|
|
3035
|
+
* @param mode - required continuable-address discriminator.
|
|
3036
|
+
* @returns acknowledgement that the cancel signal was admitted, not that the target is quiescent.
|
|
3037
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty id,
|
|
3038
|
+
* `subagent/unauthorized` when the address does not own the live target,
|
|
3039
|
+
* otherwise `gateway/internal`.
|
|
3040
|
+
*/
|
|
3041
|
+
interruptByParent(childSessionId, parentSessionId, mode) {
|
|
3042
|
+
validateControlRequest("subagent.interrupt", {
|
|
3043
|
+
childSessionId,
|
|
3044
|
+
parentSessionId,
|
|
3045
|
+
mode
|
|
3046
|
+
});
|
|
3047
|
+
try {
|
|
3048
|
+
this.interrupt(childSessionId, {
|
|
3049
|
+
kind: "user",
|
|
3050
|
+
parentSessionId
|
|
3051
|
+
});
|
|
3052
|
+
} catch (error) {
|
|
3053
|
+
if (error instanceof SubagentError && error.code === "UNAUTHORIZED") throw new RemoteError("subagent/unauthorized", "subagent does not belong to this parent", { childSessionId }, { cause: error });
|
|
3054
|
+
throw new RemoteError("gateway/internal", "subagent interrupt failed", {}, { cause: error });
|
|
3055
|
+
}
|
|
3056
|
+
return { accepted: true };
|
|
3057
|
+
}
|
|
3058
|
+
/**
|
|
3059
|
+
* Register a provider under its name. Registration is effect-scoped and HMR
|
|
3060
|
+
* safe; removing a provider blocks new starts but does not revoke runs that
|
|
3061
|
+
* were already returned to their holders.
|
|
3062
|
+
* @param provider - the trusted provider implementation.
|
|
3063
|
+
* @returns the exact Cordis effect disposer.
|
|
3064
|
+
*/
|
|
3065
|
+
registerProvider(provider) {
|
|
3066
|
+
const name = provider.name;
|
|
3067
|
+
return this.ctx.effect(function* () {
|
|
3068
|
+
if (this.providers.has(name)) throw new SubagentError(`a subagent provider named "${name}" is already registered`, "DUPLICATE_PROVIDER");
|
|
3069
|
+
this.providers.set(name, provider);
|
|
3070
|
+
yield () => {
|
|
3071
|
+
this.providers.delete(name);
|
|
3072
|
+
this.emitLifecycle("subagent/provider-removed", name);
|
|
3073
|
+
};
|
|
3074
|
+
this.ctx.emit("subagent/provider-added", provider);
|
|
3075
|
+
}.bind(this), "subagents.registerProvider()");
|
|
3076
|
+
}
|
|
3077
|
+
/**
|
|
3078
|
+
* Look up a provider by name.
|
|
3079
|
+
* @param name - the provider name.
|
|
3080
|
+
* @returns the provider, or undefined when absent.
|
|
3081
|
+
*/
|
|
3082
|
+
getProvider(name) {
|
|
3083
|
+
return this.providers.get(name);
|
|
3084
|
+
}
|
|
3085
|
+
/**
|
|
3086
|
+
* List registered provider names in insertion order.
|
|
3087
|
+
* @returns the registered names.
|
|
3088
|
+
*/
|
|
3089
|
+
list() {
|
|
3090
|
+
return [...this.providers.keys()];
|
|
3091
|
+
}
|
|
3092
|
+
/**
|
|
3093
|
+
* Establish a published child on the named provider. Capability and semantic
|
|
3094
|
+
* checks run before delegation. Provider ownership lasts until its promise
|
|
3095
|
+
* fulfills; a rejection therefore has no run for the caller to dispose and
|
|
3096
|
+
* emits no run lifecycle events. Post-publication turn and infrastructure
|
|
3097
|
+
* failures settle through the returned run.
|
|
3098
|
+
* @param name - the provider to use.
|
|
3099
|
+
* @param request - child label, prompt, parent, signal, and optional capabilities.
|
|
3100
|
+
* @returns the published holder-owned run.
|
|
3101
|
+
*/
|
|
3102
|
+
async start(name, request) {
|
|
3103
|
+
const provider = this.expectProvider(name);
|
|
3104
|
+
this.assertCapabilities(provider, request);
|
|
3105
|
+
assertSubagentMaxDepth(request.maxDepth);
|
|
3106
|
+
if (request.outputSchema !== void 0) assertObjectJsonSchema(request.outputSchema);
|
|
3107
|
+
const descriptor = snapshotSubagentDescriptor({
|
|
3108
|
+
mode: "one-shot",
|
|
3109
|
+
provider: name,
|
|
3110
|
+
...request.label !== void 0 ? { label: request.label } : {}
|
|
3111
|
+
});
|
|
3112
|
+
const resolved = {
|
|
3113
|
+
...request,
|
|
3114
|
+
descriptor
|
|
3115
|
+
};
|
|
3116
|
+
return observeRun(this.emitLifecycle, name, request.parent, await provider.start(resolved));
|
|
3117
|
+
}
|
|
3118
|
+
/**
|
|
3119
|
+
* Resolve one provider's detached continuable-creation contribution. Method
|
|
3120
|
+
* presence on the provider IS the capability, so a provider without it is
|
|
3121
|
+
* rejected before the manager reserves any child resources.
|
|
3122
|
+
*/
|
|
3123
|
+
async prepareContinuable(name, request) {
|
|
3124
|
+
const provider = this.expectProvider(name);
|
|
3125
|
+
if (provider.prepareContinuable === void 0) throw new SubagentError(`subagent provider "${provider.name}" does not support continuable children (no prepareContinuable capability)`, "UNSUPPORTED_CAPABILITY");
|
|
3126
|
+
return provider.prepareContinuable(request);
|
|
3127
|
+
}
|
|
3128
|
+
/** Look up a provider for dispatch or fail loud. */
|
|
3129
|
+
expectProvider(name) {
|
|
3130
|
+
const provider = this.providers.get(name);
|
|
3131
|
+
if (provider === void 0) throw new SubagentError(`no subagent provider registered for "${name}"`, "NO_PROVIDER");
|
|
3132
|
+
return provider;
|
|
3133
|
+
}
|
|
3134
|
+
/** Resolve the optional continuable-subagent manager or fail loud. */
|
|
3135
|
+
requireContinuations() {
|
|
3136
|
+
if (this.continuations === void 0) throw new SubagentError("continuable subagents require the agents service", "CONTINUATION_UNAVAILABLE");
|
|
3137
|
+
return this.continuations;
|
|
3138
|
+
}
|
|
3139
|
+
/**
|
|
3140
|
+
* Build the lifecycle observer for one continuable Activation's residency
|
|
3141
|
+
* epoch, so the manager publishes its edges without owning event dispatch.
|
|
3142
|
+
*/
|
|
3143
|
+
observeActivation(provider, childId, parent) {
|
|
3144
|
+
return createActivationObserver(this.emitLifecycle, provider, childId, parent);
|
|
3145
|
+
}
|
|
3146
|
+
/** Reject the first requested capability that the provider lacks. */
|
|
3147
|
+
assertCapabilities(provider, request) {
|
|
3148
|
+
const needs = [
|
|
3149
|
+
{
|
|
3150
|
+
when: request.agentOptions !== void 0,
|
|
3151
|
+
cap: "agentOptions"
|
|
3152
|
+
},
|
|
3153
|
+
{
|
|
3154
|
+
when: request.outputSchema !== void 0,
|
|
3155
|
+
cap: "outputSchema"
|
|
3156
|
+
},
|
|
3157
|
+
{
|
|
3158
|
+
when: request.maxDepth !== void 0,
|
|
3159
|
+
cap: "depthLimit"
|
|
3160
|
+
},
|
|
3161
|
+
{
|
|
3162
|
+
when: request.toolFilter !== void 0,
|
|
3163
|
+
cap: "toolFilter"
|
|
3164
|
+
},
|
|
3165
|
+
{
|
|
3166
|
+
when: request.persona !== void 0,
|
|
3167
|
+
cap: "persona"
|
|
3168
|
+
}
|
|
3169
|
+
];
|
|
3170
|
+
for (const { when, cap } of needs) if (when && !provider.capabilities[cap]) throw new SubagentError(`subagent provider "${provider.name}" does not support the "${cap}" capability`, "UNSUPPORTED_CAPABILITY");
|
|
3171
|
+
}
|
|
3172
|
+
};
|
|
3173
|
+
})();
|
|
2674
3174
|
//#endregion
|
|
2675
|
-
export { AssistantOutputFold, NO_START_CAPABILITIES, SUBAGENT_DESCRIPTOR_VERSION, SubagentDepthError, SubagentError, SubagentRunId, SubagentRuntime, SubagentRuntime as default, appendDelegatedPolicyOverrides, applyChildComposition, assertPositiveFinite, assertSubagentMaxDepth, assertUsableCwd, captureDelegatedPolicyOverrides, childSessionMeta, delegationDepthOf, finalAssistantOutput, foldSubagentDescriptor, resolveChildAgentOptions, resolveChildCwd, resolveChildDepth, seedDescriptorTurn, settleRun, settleRunResult, snapshotSubagentDescriptor, subprocessRunHandle, validateConfiguredCwd };
|
|
3175
|
+
export { AssistantOutputFold, NO_START_CAPABILITIES, SUBAGENT_DESCRIPTOR_VERSION, SubagentDepthError, SubagentError, SubagentRunId, SubagentRuntime, SubagentRuntime as default, appendDelegatedPolicyOverrides, applyChildComposition, assertPositiveFinite, assertSubagentMaxDepth, assertUsableCwd, captureDelegatedPolicyOverrides, childSessionMeta, delegationDepthOf, finalAssistantOutput, foldSubagentDescriptor, parentAgentOptionsForDelegation, resolveChildAgentOptions, resolveChildCwd, resolveChildDepth, seedDescriptorTurn, settleRun, settleRunResult, snapshotSubagentDescriptor, subprocessRunHandle, validateConfiguredCwd };
|