@deepseek-ai/dsh-subagent 0.1.1-rc.2 → 0.1.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1,11 +1,14 @@
1
- import { Service } from "@deepseek-ai/cordis";
2
1
  import { scopeTarget } from "@deepseek-ai/dsh-scope";
3
2
  import { assertObjectJsonSchema } from "@deepseek-ai/dsh-tools";
4
- import { HarnessError, boundContextSummary, createUserMessage, errorChain } from "@deepseek-ai/dsh-llm";
3
+ import { canonicalClientTimeZone } from "@deepseek-ai/dsh-util-time";
4
+ import { Remote, RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
5
+ import { z } from "zod";
6
+ import { HarnessError, ReasoningEffortId, boundContextSummary, createUserMessage, errorChain } from "@deepseek-ai/dsh-llm";
5
7
  import { randomUUID } from "node:crypto";
6
8
  import { foldConsumedWork } from "@deepseek-ai/dsh-agent";
7
- import { Session, SessionId, snapshotJsonValue } from "@deepseek-ai/dsh-session";
8
- import { z } from "zod";
9
+ import { brandString } from "@deepseek-ai/dsh-brand";
10
+ import { snapshotJsonValue } from "@deepseek-ai/dsh-util-values";
11
+ import { Session } from "@deepseek-ai/dsh-session";
9
12
  import { accessSync, constants, statSync } from "node:fs";
10
13
  import { isAbsolute, resolve } from "node:path";
11
14
  //#region lib/types/error.js
@@ -22,6 +25,124 @@ var SubagentError = class extends HarnessError {
22
25
  }
23
26
  };
24
27
  //#endregion
28
+ //#region lib/types/control.js
29
+ /**
30
+ * Browser-facing subagent control assembly: the catalog view sampled against
31
+ * the live Agent registry, one browser zone's validation, and the stable
32
+ * failure codes the Remote surface answers with.
33
+ *
34
+ * @module @deepseek-ai/dsh-subagent
35
+ */
36
+ const SESSION_ID_SCHEMA = z.string().min(1);
37
+ const CONTROL_ID_SCHEMAS = {
38
+ "subagent.list": z.object({ parentSessionId: SESSION_ID_SCHEMA }),
39
+ "subagent.prompt": z.object({
40
+ parentSessionId: SESSION_ID_SCHEMA,
41
+ childSessionId: SESSION_ID_SCHEMA,
42
+ mode: z.literal("continuable")
43
+ }),
44
+ "subagent.interrupt": z.object({
45
+ parentSessionId: SESSION_ID_SCHEMA,
46
+ childSessionId: SESSION_ID_SCHEMA,
47
+ mode: z.literal("continuable")
48
+ })
49
+ };
50
+ /**
51
+ * Apply the subagent payload checks that are stricter than generated
52
+ * branded-string codecs.
53
+ * @param method - method name carried in the failure message.
54
+ * @param payload - decoded control fields to validate.
55
+ * @throws {RemoteError} `gateway/bad-request` with the original Zod issues.
56
+ */
57
+ function validateControlRequest(method, payload) {
58
+ const parsed = CONTROL_ID_SCHEMAS[method].safeParse(payload);
59
+ if (!parsed.success) throw new RemoteError("gateway/bad-request", `invalid payload for ${method}`, { issues: parsed.error.issues });
60
+ }
61
+ /**
62
+ * Admit the content one continuation may deliver, refusing every image.
63
+ *
64
+ * The blocks become the child's user message verbatim, and this surface admits
65
+ * no attachment: nothing here registers encoded bytes with the attachment
66
+ * service, so an image would reach the child as a reference nothing resolves.
67
+ * The wire accepts the encoded upload so this refusal — not a Client that
68
+ * strips the block — is what the caller is answered with. Other block types
69
+ * still cross unnarrowed.
70
+ * @param childSessionId - the addressed child, named by the refusal.
71
+ * @param content - blocks the caller asked to deliver.
72
+ * @returns the admitted blocks, in order, as the durable content vocabulary.
73
+ * @throws {RemoteError} `subagent/attachment-unsupported` when any block is an image.
74
+ */
75
+ function admitPromptContent(childSessionId, content) {
76
+ const admitted = [];
77
+ for (const block of content) {
78
+ if (block.type === "image") throw new RemoteError("subagent/attachment-unsupported", "subagent continuation does not accept images", {
79
+ childSessionId,
80
+ reason: "SUBAGENT_IMAGE_UNSUPPORTED"
81
+ });
82
+ admitted.push(block);
83
+ }
84
+ return admitted;
85
+ }
86
+ /**
87
+ * Project one durable listing onto the catalog view, replacing each row's
88
+ * store-derived activity with the live Agent driver's status and reporting
89
+ * whether the exact parent Agent is live. Without an Agent registry no driver
90
+ * runs at all, so every row is inactive and the parent is unavailable.
91
+ * @param ctx - Host context that may carry the Agent registry.
92
+ * @param parentSessionId - the listed parent.
93
+ * @param entries - the durable direct-child listing.
94
+ * @returns the catalog view answered to one browser.
95
+ */
96
+ function catalogView(ctx, parentSessionId, entries) {
97
+ const agents = ctx.get("agents");
98
+ return {
99
+ entries: entries.map((entry) => entry.kind === "child" ? {
100
+ ...entry,
101
+ activity: agents?.get(entry.id)?.status === "running" ? "running" : "inactive"
102
+ } : entry),
103
+ parentAvailable: agents?.get(parentSessionId) !== void 0
104
+ };
105
+ }
106
+ /**
107
+ * Refuse one catalog read while preserving cancellation and a missing
108
+ * projections registry as distinct failures.
109
+ * @param error - the thrown value.
110
+ * @param signal - the caller's cancellation.
111
+ * @returns Never — the refusal is thrown.
112
+ * @throws {RemoteError} always.
113
+ */
114
+ function rejectCatalogRead(error, signal) {
115
+ if (isCancellation(error, signal)) throw new RemoteError("gateway/cancelled", "subagent catalog read was cancelled", {}, { cause: error });
116
+ 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 });
117
+ throw new RemoteError("gateway/internal", "subagent catalog read failed", {}, { cause: error });
118
+ }
119
+ /**
120
+ * Refuse one continuation prompt without exposing provider detail: admission
121
+ * failures the caller can act on keep their own code, everything else is
122
+ * internal.
123
+ * @param error - the thrown value.
124
+ * @param childSessionId - the addressed child.
125
+ * @param signal - the caller's cancellation.
126
+ * @returns Never — the refusal is thrown.
127
+ * @throws {RemoteError} always.
128
+ */
129
+ function rejectPrompt(error, childSessionId, signal) {
130
+ if (isCancellation(error, signal)) throw new RemoteError("gateway/cancelled", "subagent prompt was cancelled", {}, { cause: error });
131
+ if (error instanceof SubagentError) switch (error.code) {
132
+ case "NOT_RESUMABLE": throw new RemoteError("subagent/not-resumable", "subagent cannot be resumed", { childSessionId }, { cause: error });
133
+ case "UNAUTHORIZED": throw new RemoteError("subagent/unauthorized", "subagent does not belong to this parent", { childSessionId }, { cause: error });
134
+ case "DRAINING":
135
+ case "ACTIVATION_CLOSING":
136
+ case "CONTINUATION_UNAVAILABLE":
137
+ case "PERSISTENCE_UNAVAILABLE": throw new RemoteError("subagent/delivery-unavailable", "subagent follow-up is temporarily unavailable", { childSessionId }, { cause: error });
138
+ default: break;
139
+ }
140
+ throw new RemoteError("gateway/internal", "subagent prompt failed", {}, { cause: error });
141
+ }
142
+ function isCancellation(error, signal) {
143
+ return signal.aborted || error instanceof SubagentError && error.code === "CANCELLED";
144
+ }
145
+ //#endregion
25
146
  //#region lib/types/depth.js
26
147
  /**
27
148
  * Delegation-depth accounting: the recursion budget a parent passes to its
@@ -325,7 +446,7 @@ function renderThrown(value) {
325
446
  * Supporting another composition input is a deliberate version change, never
326
447
  * an implicit extra field.
327
448
  */
328
- const SUBAGENT_DESCRIPTOR_VERSION = 2;
449
+ const SUBAGENT_DESCRIPTOR_VERSION = 3;
329
450
  const DESCRIPTOR_BASE_KEYS = [
330
451
  "version",
331
452
  "mode",
@@ -337,6 +458,7 @@ const CONTINUABLE_DESCRIPTOR_KEYS = new Set([
337
458
  ...DESCRIPTOR_BASE_KEYS,
338
459
  "agentProvider",
339
460
  "agentModel",
461
+ "agentReasoningEffort",
340
462
  "persona",
341
463
  "toolFilter"
342
464
  ]);
@@ -383,7 +505,7 @@ function parseSubagentDescriptor(value) {
383
505
  if (!isRecord(value)) throw new Error("persisted subagent descriptor payload must be an object");
384
506
  const version = value["version"];
385
507
  if (typeof version !== "number") throw new Error("persisted subagent descriptor version must be a number");
386
- if (version !== 2) return void 0;
508
+ if (version !== 3) return void 0;
387
509
  const mode = value["mode"];
388
510
  if (mode !== "one-shot" && mode !== "continuable") throw new Error("persisted subagent descriptor mode must be \"one-shot\" or \"continuable\"");
389
511
  assertKnownKeys(value, mode === "one-shot" ? ONE_SHOT_DESCRIPTOR_KEYS : CONTINUABLE_DESCRIPTOR_KEYS, "payload");
@@ -392,7 +514,7 @@ function parseSubagentDescriptor(value) {
392
514
  if (mode === "one-shot") {
393
515
  const label = optionalString(value, "label");
394
516
  return {
395
- version: 2,
517
+ version: 3,
396
518
  mode,
397
519
  provider,
398
520
  ...label !== void 0 ? { label } : {}
@@ -402,32 +524,35 @@ function parseSubagentDescriptor(value) {
402
524
  if (typeof label !== "string") throw new Error("persisted subagent descriptor label must be a string");
403
525
  const agentProvider = optionalString(value, "agentProvider");
404
526
  const agentModel = optionalString(value, "agentModel");
527
+ const agentReasoningEffort = optionalString(value, "agentReasoningEffort");
405
528
  const persona = optionalString(value, "persona");
406
529
  const toolFilter = Object.hasOwn(value, "toolFilter") ? parseToolFilter(value["toolFilter"]) : void 0;
407
530
  return {
408
- version: 2,
531
+ version: 3,
409
532
  mode,
410
533
  provider,
411
534
  label,
412
535
  ...agentProvider !== void 0 ? { agentProvider } : {},
413
536
  ...agentModel !== void 0 ? { agentModel } : {},
537
+ ...agentReasoningEffort !== void 0 ? { agentReasoningEffort } : {},
414
538
  ...persona !== void 0 ? { persona } : {},
415
539
  ...toolFilter !== void 0 ? { toolFilter } : {}
416
540
  };
417
541
  }
418
542
  function snapshotSubagentDescriptor(input) {
419
543
  const snapshot = snapshotJsonValue(input.mode === "one-shot" ? {
420
- version: 2,
544
+ version: 3,
421
545
  mode: input.mode,
422
546
  provider: input.provider,
423
547
  ...input.label !== void 0 ? { label: input.label } : {}
424
548
  } : {
425
- version: 2,
549
+ version: 3,
426
550
  mode: input.mode,
427
551
  provider: input.provider,
428
552
  label: input.label,
429
553
  ...input.agentProvider !== void 0 ? { agentProvider: input.agentProvider } : {},
430
554
  ...input.agentModel !== void 0 ? { agentModel: input.agentModel } : {},
555
+ ...input.agentReasoningEffort !== void 0 ? { agentReasoningEffort: input.agentReasoningEffort } : {},
431
556
  ...input.persona !== void 0 ? { persona: input.persona } : {},
432
557
  ...input.toolFilter !== void 0 ? { toolFilter: input.toolFilter } : {}
433
558
  });
@@ -490,25 +615,51 @@ function resolveChildDepth(parent, maxDepth) {
490
615
  return childDepth;
491
616
  }
492
617
  /**
493
- * Resolve the child's `AgentOptions`: the parent's provider/model/maxTokens
494
- * route unless the request overrides it, stamped with the child's own
495
- * delegation depth.
618
+ * Resolve the parent values inherited by a child. The latest request header
619
+ * owns provider, model, and reasoning effort after request-time selection;
620
+ * creation options remain the fallback before the first request and retain
621
+ * the configured output-token limit.
622
+ * @param parent - delegating parent Agent.
623
+ * @returns detached Agent options for child-option merging.
624
+ */
625
+ function parentAgentOptionsForDelegation(parent) {
626
+ const requestConfig = parent.session.requestHeader()?.config;
627
+ if (requestConfig === void 0) return { ...parent.options };
628
+ const { provider: _createdProvider, model: _createdModel, reasoningEffort: _createdReasoningEffort, ...createdOptions } = parent.options;
629
+ return {
630
+ ...createdOptions,
631
+ provider: requestConfig.provider,
632
+ model: requestConfig.model,
633
+ ...requestConfig.reasoningEffort === void 0 ? {} : { reasoningEffort: requestConfig.reasoningEffort }
634
+ };
635
+ }
636
+ /**
637
+ * Resolve the child's `AgentOptions`: the parent's provider/model,
638
+ * reasoning-effort, and maxTokens values unless the request overrides them,
639
+ * stamped with the child's own delegation depth. Changing the route without
640
+ * naming an effort clears the parent's route-owned effort so the selected
641
+ * model resolves its own default.
496
642
  * @param parent - the delegating parent whose route the child inherits.
497
643
  * @param requested - per-child overrides, if any.
498
644
  * @param childDepth - the resolved delegation depth to stamp.
499
645
  * @returns the resolved options for `ctx.agents.create()`.
500
646
  */
501
647
  function resolveChildAgentOptions(parent, requested, childDepth) {
502
- const parentProvider = parent.options.provider;
503
- const parentModel = parent.options.model;
504
- const parentMaxTokens = parent.options.maxTokens;
505
- return {
648
+ const parentOptions = parentAgentOptionsForDelegation(parent);
649
+ const parentProvider = parentOptions.provider;
650
+ const parentModel = parentOptions.model;
651
+ const parentReasoningEffort = parentOptions.reasoningEffort;
652
+ const parentMaxTokens = parentOptions.maxTokens;
653
+ const resolved = {
506
654
  ...parentProvider !== void 0 ? { provider: parentProvider } : {},
507
655
  ...parentModel !== void 0 ? { model: parentModel } : {},
656
+ ...parentReasoningEffort !== void 0 ? { reasoningEffort: parentReasoningEffort } : {},
508
657
  ...parentMaxTokens !== void 0 ? { maxTokens: parentMaxTokens } : {},
509
658
  ...requested,
510
659
  subagentDepth: childDepth
511
660
  };
661
+ if ((resolved.provider !== parentProvider || resolved.model !== parentModel) && requested?.reasoningEffort === void 0) delete resolved.reasoningEffort;
662
+ return resolved;
512
663
  }
513
664
  /**
514
665
  * Build the child session's durable creation metadata: the parent's workspace,
@@ -571,12 +722,12 @@ function applyChildComposition(childCtx, parent, composition) {
571
722
  childCtx.get("agentPresets")?.composeFrom(childCtx, parent.ctx);
572
723
  childCtx.systemPrompt.context({
573
724
  name: "subagent:delegation",
574
- order: 120,
725
+ order: childCtx.systemPrompt.getContextOrder("SUBAGENT_DELEGATION"),
575
726
  text: SUBAGENT_DELEGATION_CONTEXT
576
727
  });
577
728
  if (composition.persona !== void 0) childCtx.systemPrompt.section({
578
729
  name: "deployment:persona",
579
- order: 0,
730
+ order: childCtx.systemPrompt.getSectionOrder("DEPLOYMENT_PERSONA"),
580
731
  text: composition.persona
581
732
  });
582
733
  if (composition.toolFilter !== void 0) childCtx.tools.restrict(composition.toolFilter);
@@ -664,6 +815,64 @@ function seedDescriptorTurn(childId, seed, descriptor) {
664
815
  *
665
816
  * @module @deepseek-ai/dsh-subagent
666
817
  */
818
+ var __addDisposableResource$1 = function(env, value, async) {
819
+ if (value !== null && value !== void 0) {
820
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
821
+ var dispose, inner;
822
+ if (async) {
823
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
824
+ dispose = value[Symbol.asyncDispose];
825
+ }
826
+ if (dispose === void 0) {
827
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
828
+ dispose = value[Symbol.dispose];
829
+ if (async) inner = dispose;
830
+ }
831
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
832
+ if (inner) dispose = function() {
833
+ try {
834
+ inner.call(this);
835
+ } catch (e) {
836
+ return Promise.reject(e);
837
+ }
838
+ };
839
+ env.stack.push({
840
+ value,
841
+ dispose,
842
+ async
843
+ });
844
+ } else if (async) env.stack.push({ async: true });
845
+ return value;
846
+ };
847
+ var __disposeResources$1 = (function(SuppressedError) {
848
+ return function(env) {
849
+ function fail(e) {
850
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
851
+ env.hasError = true;
852
+ }
853
+ var r, s = 0;
854
+ function next() {
855
+ while (r = env.stack.pop()) try {
856
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
857
+ if (r.dispose) {
858
+ var result = r.dispose.call(r.value);
859
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
860
+ fail(e);
861
+ return next();
862
+ });
863
+ } else s |= 1;
864
+ } catch (e) {
865
+ fail(e);
866
+ }
867
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
868
+ if (env.hasError) throw env.error;
869
+ }
870
+ return next();
871
+ };
872
+ })(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
873
+ var e = new Error(message);
874
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
875
+ });
667
876
  /**
668
877
  * Read one Activation's current disposal transaction. This indirection exists
669
878
  * because TypeScript would otherwise narrow repeated reads of the mutable field
@@ -774,17 +983,20 @@ var SubagentContinuationManager = class {
774
983
  this.assertAdmitting(parent);
775
984
  const persistence = this.requirePersistence();
776
985
  assertSubagentMaxDepth(request.maxDepth);
777
- const childId = spec.childId ?? SessionId(randomUUID());
986
+ const childId = spec.childId ?? brandString(randomUUID());
778
987
  this.assertChildIdAvailable(childId);
779
988
  const childDepth = resolveChildDepth(parent, request.maxDepth);
780
- const agentProvider = request.agentOptions?.provider ?? parent.options.provider;
781
- const agentModel = request.agentOptions?.model ?? parent.options.model;
989
+ const agentOptions = resolveChildAgentOptions(parent, request.agentOptions, childDepth);
990
+ const agentProvider = agentOptions.provider;
991
+ const agentModel = agentOptions.model;
992
+ const agentReasoningEffort = agentOptions.reasoningEffort;
782
993
  const descriptor = snapshotSubagentDescriptor({
783
994
  mode: "continuable",
784
995
  provider: spec.provider,
785
996
  label: spec.label,
786
997
  ...agentProvider !== void 0 ? { agentProvider } : {},
787
998
  ...agentModel !== void 0 ? { agentModel } : {},
999
+ ...agentReasoningEffort !== void 0 ? { agentReasoningEffort } : {},
788
1000
  ...request.persona !== void 0 ? { persona: request.persona } : {},
789
1001
  ...request.toolFilter !== void 0 ? { toolFilter: request.toolFilter } : {}
790
1002
  });
@@ -820,7 +1032,7 @@ var SubagentContinuationManager = class {
820
1032
  meta: childSessionMeta(parent, childDepth, lineageSeedLength),
821
1033
  delegatedPolicies
822
1034
  },
823
- agentOptions: resolveChildAgentOptions(parent, request.agentOptions, childDepth),
1035
+ agentOptions,
824
1036
  composition: {
825
1037
  persona: request.persona,
826
1038
  toolFilter: request.toolFilter
@@ -1135,48 +1347,61 @@ var SubagentContinuationManager = class {
1135
1347
  return "settled";
1136
1348
  }
1137
1349
  /**
1138
- * Cold-resume a persisted child: inspect and authorize its Session, fold the
1350
+ * Cold-resume a persisted child: retain and authorize its prepared Session, fold the
1139
1351
  * generic descriptor, create the Activation through `ctx.agents.resume()`,
1140
1352
  * and submit the waiting turn. This never dispatches through a subagent
1141
1353
  * provider — the persisted Session already holds the initial prefix and the
1142
1354
  * descriptor is the whole reconstruction input.
1143
1355
  */
1144
1356
  async coldResume(parent, childId, content, options) {
1145
- const persistence = this.requirePersistence();
1146
- let loaded;
1147
- try {
1148
- loaded = await persistence.inspect(childId, options.signal);
1149
- } catch (error) {
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;
1357
+ const env_1 = {
1358
+ stack: [],
1359
+ error: void 0,
1360
+ hasError: false
1361
+ };
1159
1362
  try {
1160
- activation = await this.materialize({
1161
- childId,
1162
- provider: descriptor.provider,
1163
- parent,
1164
- agentOptions: {
1165
- ...descriptor.agentProvider !== void 0 ? { provider: descriptor.agentProvider } : {},
1166
- ...descriptor.agentModel !== void 0 ? { model: descriptor.agentModel } : {}
1167
- },
1168
- composition: {
1169
- persona: descriptor.persona,
1170
- toolFilter: descriptor.toolFilter
1171
- },
1172
- signal: options.signal
1173
- });
1174
- } catch (error) {
1175
- options.signal.throwIfAborted();
1176
- if (error instanceof SubagentError) throw error;
1177
- throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
1363
+ const query = this.requireSessionQuery();
1364
+ let observation;
1365
+ try {
1366
+ observation = await query.observeSession(childId, { signal: options.signal });
1367
+ } catch (error) {
1368
+ options.signal.throwIfAborted();
1369
+ throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
1370
+ }
1371
+ const source = __addDisposableResource$1(env_1, observation, false);
1372
+ this.assertAdmitting(parent);
1373
+ this.authorizeLineage(parent, childId, source.header.parentSession);
1374
+ const descriptor = foldSubagentDescriptor(source.events.slice(source.header.seedLength ?? 0));
1375
+ 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");
1376
+ let activation;
1377
+ try {
1378
+ activation = await this.materialize({
1379
+ childId,
1380
+ provider: descriptor.provider,
1381
+ parent,
1382
+ agentOptions: {
1383
+ ...descriptor.agentProvider !== void 0 ? { provider: descriptor.agentProvider } : {},
1384
+ ...descriptor.agentModel !== void 0 ? { model: descriptor.agentModel } : {},
1385
+ ...descriptor.agentReasoningEffort !== void 0 ? { reasoningEffort: ReasoningEffortId(descriptor.agentReasoningEffort) } : {}
1386
+ },
1387
+ composition: {
1388
+ persona: descriptor.persona,
1389
+ toolFilter: descriptor.toolFilter
1390
+ },
1391
+ signal: options.signal
1392
+ });
1393
+ } catch (error) {
1394
+ options.signal.throwIfAborted();
1395
+ if (error instanceof SubagentError) throw error;
1396
+ throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
1397
+ }
1398
+ return await this.submitMaterialized(activation, content, options.source, parent, options.signal);
1399
+ } catch (e_1) {
1400
+ env_1.error = e_1;
1401
+ env_1.hasError = true;
1402
+ } finally {
1403
+ __disposeResources$1(env_1);
1178
1404
  }
1179
- return this.submitMaterialized(activation, content, options.source, parent, options.signal);
1180
1405
  }
1181
1406
  /**
1182
1407
  * Submit to a freshly materialized Activation or roll it back completely.
@@ -1541,6 +1766,12 @@ var SubagentContinuationManager = class {
1541
1766
  if (persistence === void 0) throw new SubagentError("continuable subagents require session persistence (load a dsh-session-persistence backend)", "PERSISTENCE_UNAVAILABLE");
1542
1767
  return persistence;
1543
1768
  }
1769
+ /** Resolve the Session query service used for cold child observations. */
1770
+ requireSessionQuery() {
1771
+ const query = this.ctx.get("sessionQuery");
1772
+ if (query === void 0) throw new SubagentError("continuable subagents require session query (load @deepseek-ai/dsh-session-query)", "CONTINUATION_UNAVAILABLE");
1773
+ return query;
1774
+ }
1544
1775
  };
1545
1776
  //#endregion
1546
1777
  //#region lib/types/activation-setup-registry.js
@@ -1674,14 +1905,14 @@ var SubagentActivationSetupRegistry = class {
1674
1905
  //#region lib/types/list-children.js
1675
1906
  /**
1676
1907
  * Read-only enumeration of durable subagent children and descendant trees
1677
- * straight from the live session store and optional session persistence — no
1678
- * query service. Candidates come from one live-preferred corpus; each child's
1679
- * mode/label is the registered `subagent` projection unit's value, resolved
1908
+ * through the Session query service. Candidates come from one live-preferred
1909
+ * corpus; each child's mode/label is the registered `subagent` projection
1910
+ * unit's value, resolved
1680
1911
  * down a three-rung ladder: the registry's watermark cache for a live child,
1681
1912
  * a durable projection-cache row when it serves an own-suffix identity (the
1682
- * seq gate), and one persistence inspection folded through the registry
1683
- * otherwise, validated against the enumerated lifecycle. The projection fold
1684
- * is the single classification authority — this module parses no descriptor
1913
+ * seq gate), and one shared Session observation otherwise, validated against
1914
+ * the enumerated lifecycle. The projection fold is the single classification
1915
+ * authority — this module parses no descriptor
1685
1916
  * itself. Absent persistence, enumeration is live-only: a cold child is
1686
1917
  * unreachable for resume anyway, so its absence is capability absence, not an
1687
1918
  * error. The module owns no catalog state and does not consult Activation,
@@ -1689,10 +1920,68 @@ var SubagentActivationSetupRegistry = class {
1689
1920
  *
1690
1921
  * @module @deepseek-ai/dsh-subagent
1691
1922
  */
1923
+ var __addDisposableResource = function(env, value, async) {
1924
+ if (value !== null && value !== void 0) {
1925
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
1926
+ var dispose, inner;
1927
+ if (async) {
1928
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
1929
+ dispose = value[Symbol.asyncDispose];
1930
+ }
1931
+ if (dispose === void 0) {
1932
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
1933
+ dispose = value[Symbol.dispose];
1934
+ if (async) inner = dispose;
1935
+ }
1936
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
1937
+ if (inner) dispose = function() {
1938
+ try {
1939
+ inner.call(this);
1940
+ } catch (e) {
1941
+ return Promise.reject(e);
1942
+ }
1943
+ };
1944
+ env.stack.push({
1945
+ value,
1946
+ dispose,
1947
+ async
1948
+ });
1949
+ } else if (async) env.stack.push({ async: true });
1950
+ return value;
1951
+ };
1952
+ var __disposeResources = (function(SuppressedError) {
1953
+ return function(env) {
1954
+ function fail(e) {
1955
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
1956
+ env.hasError = true;
1957
+ }
1958
+ var r, s = 0;
1959
+ function next() {
1960
+ while (r = env.stack.pop()) try {
1961
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
1962
+ if (r.dispose) {
1963
+ var result = r.dispose.call(r.value);
1964
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
1965
+ fail(e);
1966
+ return next();
1967
+ });
1968
+ } else s |= 1;
1969
+ } catch (e) {
1970
+ fail(e);
1971
+ }
1972
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
1973
+ if (env.hasError) throw env.error;
1974
+ }
1975
+ return next();
1976
+ };
1977
+ })(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
1978
+ var e = new Error(message);
1979
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1980
+ });
1692
1981
  /**
1693
- * Concurrent cold inspections per listing; a constant because it bounds one
1694
- * read-only scan of local media, not deployment behavior. Should a networked
1695
- * persistence backend appear, promote it to a validated `Config` field.
1982
+ * Concurrent cold observations per explicit catalog listing. Current Session
1983
+ * persistence providers are local; a networked provider must promote this to
1984
+ * a validated deployment setting.
1696
1985
  */
1697
1986
  const COLD_READ_CONCURRENCY = 4;
1698
1987
  /**
@@ -1700,9 +1989,8 @@ const COLD_READ_CONCURRENCY = 4;
1700
1989
  * live-preferred merge of `ctx.sessions` and optional session persistence,
1701
1990
  * serving each identity from the `subagent` projection unit: the registry's
1702
1991
  * watermark snapshot for a live child; for a cold one, a durable
1703
- * projection-cache row when it serves an own-suffix identity (the seq gate),
1704
- * else one bounded-concurrency persistence inspection folded through the
1705
- * registry.
1992
+ * projection-cache read when it serves an own-suffix identity (the seq gate),
1993
+ * else one bounded-concurrency shared Session observation.
1706
1994
  * @see SubagentRuntime.listChildren for the public cancellation and failure contract.
1707
1995
  * @param ctx - context carrying the session store, the projection registry,
1708
1996
  * optional persistence, and the optional projection cache.
@@ -1751,32 +2039,30 @@ async function prepareListing(ctx, signal) {
1751
2039
  const sessions = ctx.get("sessions");
1752
2040
  if (sessions === void 0) throw new SubagentError("listing subagents requires the session store (load @deepseek-ai/dsh-session)", "SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE");
1753
2041
  assertListingNotCancelled(signal);
1754
- const persistence = ctx.get("sessionPersistence");
2042
+ const query = ctx.get("sessionQuery");
2043
+ if (query === void 0) throw new SubagentError("listing subagents requires the sessionQuery service (load @deepseek-ai/dsh-session-query)", "SUBAGENT_CONTROL_QUERY_UNAVAILABLE");
1755
2044
  const cache = ctx.get("sessionProjectionCache");
1756
- let persistedHeaders = [];
1757
- if (persistence !== void 0) {
1758
- try {
1759
- persistedHeaders = await persistence.list(signal);
1760
- } catch (error) {
1761
- assertListingNotCancelled(signal);
1762
- throw error;
1763
- }
2045
+ let records;
2046
+ try {
2047
+ records = await query.listSessions(signal);
2048
+ } catch (error) {
1764
2049
  assertListingNotCancelled(signal);
2050
+ throw error;
1765
2051
  }
2052
+ assertListingNotCancelled(signal);
1766
2053
  const corpus = /* @__PURE__ */ new Map();
1767
- for (const header of persistedHeaders) corpus.set(header.id, {
1768
- header,
1769
- live: void 0
1770
- });
1771
- for (const session of sessions.list()) corpus.set(session.header.id, {
1772
- header: session.header,
1773
- live: session
1774
- });
2054
+ for (const record of records) {
2055
+ const live = sessions.get(record.header.id);
2056
+ corpus.set(record.header.id, {
2057
+ header: live?.header ?? record.header,
2058
+ live
2059
+ });
2060
+ }
1775
2061
  const subagentParents = /* @__PURE__ */ new Set();
1776
2062
  for (const record of corpus.values()) if (record.header.origin === "subagent" && record.header.parentSession !== void 0) subagentParents.add(record.header.parentSession);
1777
2063
  return {
1778
2064
  projections,
1779
- persistence,
2065
+ query,
1780
2066
  cache,
1781
2067
  corpus,
1782
2068
  subagentParents
@@ -1784,7 +2070,7 @@ async function prepareListing(ctx, signal) {
1784
2070
  }
1785
2071
  /** Resolve projection-backed rows for aligned candidates with bounded cold reads. */
1786
2072
  async function resolveCandidateRows(candidates, listing, signal) {
1787
- const { projections, persistence, cache, subagentParents } = listing;
2073
+ const { projections, query, cache, subagentParents } = listing;
1788
2074
  const rows = Array.from({ length: candidates.length });
1789
2075
  const coldReads = [];
1790
2076
  candidates.forEach((candidate, index) => {
@@ -1798,7 +2084,7 @@ async function resolveCandidateRows(candidates, listing, signal) {
1798
2084
  }
1799
2085
  let identity;
1800
2086
  try {
1801
- identity = projections.snapshot(candidate.live).values.subagent;
2087
+ identity = projections.snapshot(candidate.live, ["subagent"]).values.subagent;
1802
2088
  } catch {
1803
2089
  rows[index] = {
1804
2090
  kind: "diagnostic",
@@ -1807,13 +2093,13 @@ async function resolveCandidateRows(candidates, listing, signal) {
1807
2093
  };
1808
2094
  return;
1809
2095
  }
1810
- if (identity === void 0 || identity === null) return;
2096
+ if (identity === void 0 || identity === null || identity.seq < (candidate.header.seedLength ?? 0)) return;
1811
2097
  rows[index] = childRow(childId, identity, "running", subagentParents.has(childId));
1812
2098
  });
1813
- if (persistence !== void 0 && coldReads.length > 0) {
2099
+ if (coldReads.length > 0) {
1814
2100
  const queue = [...coldReads];
1815
2101
  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(persistence, projections, cache, job.header, subagentParents.has(job.header.id), signal);
2102
+ 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
2103
  }));
1818
2104
  }
1819
2105
  assertListingNotCancelled(signal);
@@ -1859,58 +2145,61 @@ function compareCorpusRecords(a, b) {
1859
2145
  /**
1860
2146
  * Resolve one cold candidate down the remaining ladder: a durable
1861
2147
  * projection-cache row when it serves an own-suffix identity (the seq gate),
1862
- * otherwise one persistence inspection folded through the projection
1863
- * registry (the same detached recipe the API proxy uses for detached session
1864
- * projections). A failed inspection is one transient `unavailable` row
1865
- * retried on the next listing; an inspection naming another lifecycle, and a
2148
+ * otherwise one shared Session observation. An absent or transiently failed
2149
+ * observation is one `unavailable` row retried on the next listing; an observation
2150
+ * source naming another lifecycle, and a
1866
2151
  * settled log the fold cannot identify — or that makes any registered unit
1867
2152
  * throw — are final, so they report `corrupt`.
1868
2153
  */
1869
- async function resolveColdIdentity(persistence, projections, cache, header, hasChildren, signal) {
1870
- const childId = header.id;
1871
- if (cache !== void 0) {
1872
- let cached;
2154
+ async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
2155
+ const env_1 = {
2156
+ stack: [],
2157
+ error: void 0,
2158
+ hasError: false
2159
+ };
2160
+ try {
2161
+ const childId = header.id;
2162
+ if (cache !== void 0) {
2163
+ let cached;
2164
+ try {
2165
+ cached = cache.cachedSnapshot(header, ["subagent"])?.values.subagent;
2166
+ } catch {
2167
+ cached = void 0;
2168
+ }
2169
+ if (cached !== void 0 && cached !== null && cached.seq >= (header.seedLength ?? 0)) return childRow(childId, cached, "inactive", hasChildren);
2170
+ }
2171
+ assertListingNotCancelled(signal);
2172
+ let observation;
1873
2173
  try {
1874
- cached = cache.cachedSnapshot(header)?.values.subagent;
1875
- } catch {
1876
- cached = void 0;
2174
+ observation = await query.observeSession(childId, { ...signal === void 0 ? {} : { signal } });
2175
+ } catch (error) {
2176
+ assertListingNotCancelled(signal);
2177
+ return {
2178
+ kind: "diagnostic",
2179
+ id: childId,
2180
+ reason: sessionQueryCode(error) === "SESSION_QUERY_CORRUPT_SESSION" || sessionQueryCode(error) === "SESSION_QUERY_SOURCE_CONFLICT" ? "corrupt" : "unavailable"
2181
+ };
1877
2182
  }
1878
- if (cached !== void 0 && cached !== null && cached.seq >= (header.seedLength ?? 0)) return childRow(childId, cached, "inactive", hasChildren);
1879
- }
1880
- assertListingNotCancelled(signal);
1881
- let inspected;
1882
- try {
1883
- inspected = await persistence.inspect(childId, signal);
1884
- } catch {
2183
+ const ownedObservation = __addDisposableResource(env_1, observation, false);
1885
2184
  assertListingNotCancelled(signal);
1886
- return {
2185
+ if (!sameLifecycle(ownedObservation.header, header)) return {
1887
2186
  kind: "diagnostic",
1888
2187
  id: childId,
1889
- reason: "unavailable"
2188
+ reason: "corrupt"
1890
2189
  };
1891
- }
1892
- assertListingNotCancelled(signal);
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 {
2190
+ const identity = ownedObservation.projections?.values.subagent;
2191
+ if (identity === void 0 || identity === null || identity.seq < (header.seedLength ?? 0)) return {
1903
2192
  kind: "diagnostic",
1904
2193
  id: childId,
1905
2194
  reason: "corrupt"
1906
2195
  };
2196
+ return childRow(childId, identity, "inactive", hasChildren);
2197
+ } catch (e_1) {
2198
+ env_1.error = e_1;
2199
+ env_1.hasError = true;
2200
+ } finally {
2201
+ __disposeResources(env_1);
1907
2202
  }
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
2203
  }
1915
2204
  /** Materialize one served identity as its child row. */
1916
2205
  function childRow(id, identity, activity, hasChildren) {
@@ -1938,7 +2227,9 @@ const LIFECYCLE_WITNESS_KEYS = [
1938
2227
  "cwd",
1939
2228
  "parentSession",
1940
2229
  "seedLength",
1941
- "delegationDepth"
2230
+ "delegationDepth",
2231
+ "origin",
2232
+ "agentPreset"
1942
2233
  ];
1943
2234
  /** Whether an inspected log still belongs to the enumerated lifecycle. */
1944
2235
  function sameLifecycle(meta, expected) {
@@ -1948,6 +2239,9 @@ function sameLifecycle(meta, expected) {
1948
2239
  function assertListingNotCancelled(signal) {
1949
2240
  if (signal?.aborted) throw new SubagentError("subagent listing was cancelled", "CANCELLED");
1950
2241
  }
2242
+ function sessionQueryCode(error) {
2243
+ return error instanceof Error && "code" in error ? error.code : void 0;
2244
+ }
1951
2245
  //#endregion
1952
2246
  //#region lib/types/projection.js
1953
2247
  /**
@@ -2127,13 +2421,21 @@ function limitSubagentDiagnostic(diagnostic) {
2127
2421
  while ((bytes[prefixBytes] & 192) === 128) prefixBytes -= 1;
2128
2422
  return utf8Decoder.decode(bytes.subarray(0, prefixBytes)) + DIAGNOSTIC_TRUNCATION_SUFFIX;
2129
2423
  }
2424
+ /** Enforce the byte limit on a provider-returned diagnostic. */
2425
+ function normalizeSubagentDiagnostic(result) {
2426
+ return result.diagnostic === void 0 ? result : {
2427
+ ...result,
2428
+ diagnostic: limitSubagentDiagnostic(result.diagnostic)
2429
+ };
2430
+ }
2130
2431
  /**
2131
2432
  * The capability advertisement of an out-of-process backend: NONE. A child in
2132
2433
  * another process cannot honor parent-enforced start features
2133
- * (`outputSchema`/`maxDepth`/`toolFilter`/`persona`), so the service rejects a
2434
+ * (`agentOptions`/`outputSchema`/`maxDepth`/`toolFilter`/`persona`), so the service rejects a
2134
2435
  * request needing any of them before `start` runs — never accepted-then-ignored.
2135
2436
  */
2136
2437
  const NO_START_CAPABILITIES = Object.freeze({
2438
+ agentOptions: false,
2137
2439
  outputSchema: false,
2138
2440
  depthLimit: false,
2139
2441
  toolFilter: false,
@@ -2221,7 +2523,8 @@ function toError(value) {
2221
2523
  * rejects after publication. A normally completed or rejected attempt resolves
2222
2524
  * as `aborted` when cancellation already settled locally; another rejection is
2223
2525
  * flattened to `stopReason: 'error'` through the contained diagnostic sink.
2224
- * The abort listener is removed on every path.
2526
+ * Provider-returned diagnostics use the same byte limit. The abort listener is
2527
+ * removed on every path.
2225
2528
  * @param parts - the attempt, output snapshot, cancellation state, sink, and signal wiring.
2226
2529
  * @returns the terminal result (never a rejection).
2227
2530
  */
@@ -2231,7 +2534,7 @@ async function settleRunResult(parts) {
2231
2534
  return parts.cancelled() ? {
2232
2535
  output: parts.collectOutput(),
2233
2536
  stopReason: "aborted"
2234
- } : result;
2537
+ } : normalizeSubagentDiagnostic(result);
2235
2538
  } catch (error) {
2236
2539
  if (parts.cancelled()) return {
2237
2540
  output: parts.collectOutput(),
@@ -2293,8 +2596,10 @@ function failureDetail(result) {
2293
2596
  return result.diagnostic === void 0 ? stopReason : `${stopReason}; diagnostic: ${result.diagnostic}`;
2294
2597
  }
2295
2598
  /**
2296
- * Map a child result to the task outcome: completed carries final text,
2297
- * aborted is killed, and every other reason is failed without partial output.
2599
+ * Map a child result to the task outcome: completed carries final text, local
2600
+ * cancellation (`aborted` without a diagnostic) is killed, and provider-
2601
+ * diagnosed remote aborts plus every other reason are failed without partial
2602
+ * output.
2298
2603
  * @param result - child terminal result.
2299
2604
  * @returns outcome for the `ctx.jobs` registration.
2300
2605
  */
@@ -2304,7 +2609,10 @@ function runOutcome(result) {
2304
2609
  status: "completed",
2305
2610
  output: finalText(result.output)
2306
2611
  };
2307
- case "aborted": return { status: "killed" };
2612
+ case "aborted": return result.diagnostic === void 0 ? { status: "killed" } : {
2613
+ status: "failed",
2614
+ detail: failureDetail(result)
2615
+ };
2308
2616
  case "error":
2309
2617
  case "max-tokens":
2310
2618
  case "refusal": return {
@@ -2351,10 +2659,8 @@ async function settleRun(run) {
2351
2659
  * child before returning its run, so fulfillment is the single publication and
2352
2660
  * ownership-transfer boundary.
2353
2661
  *
2354
- * Unlike the bash seam (one executor per context, second load throws), MULTIPLE
2355
- * providers coexist here: each registers under a unique name and a caller picks
2356
- * one by name. The shape mirrors the LLM adapter registry
2357
- * (`LlmRuntime.registerAdapter`), not the single-service bash executor.
2662
+ * Multiple providers coexist: each registers under a unique name and callers
2663
+ * select one by name.
2358
2664
  *
2359
2665
  * This package owns the Service Definition role of the capability seam. Service Providers
2360
2666
  * (`@deepseek-ai/dsh-subagent-spawn-in-process`, `-fork`, `-acp`) and the model-facing
@@ -2377,299 +2683,470 @@ async function settleRun(run) {
2377
2683
  *
2378
2684
  * @module @deepseek-ai/dsh-subagent
2379
2685
  */
2686
+ var __runInitializers = function(thisArg, initializers, value) {
2687
+ var useValue = arguments.length > 2;
2688
+ for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
2689
+ return useValue ? value : void 0;
2690
+ };
2691
+ var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2692
+ function accept(f) {
2693
+ if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
2694
+ return f;
2695
+ }
2696
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
2697
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
2698
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
2699
+ var _, done = false;
2700
+ for (var i = decorators.length - 1; i >= 0; i--) {
2701
+ var context = {};
2702
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
2703
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
2704
+ context.addInitializer = function(f) {
2705
+ if (done) throw new TypeError("Cannot add initializers after decoration has completed");
2706
+ extraInitializers.push(accept(f || null));
2707
+ };
2708
+ var result = (0, decorators[i])(kind === "accessor" ? {
2709
+ get: descriptor.get,
2710
+ set: descriptor.set
2711
+ } : descriptor[key], context);
2712
+ if (kind === "accessor") {
2713
+ if (result === void 0) continue;
2714
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
2715
+ if (_ = accept(result.get)) descriptor.get = _;
2716
+ if (_ = accept(result.set)) descriptor.set = _;
2717
+ if (_ = accept(result.init)) initializers.unshift(_);
2718
+ } else if (_ = accept(result)) if (kind === "field") initializers.unshift(_);
2719
+ else descriptor[key] = _;
2720
+ }
2721
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
2722
+ done = true;
2723
+ };
2380
2724
  /** Named provider registry with one-shot runs, durable discovery, and continuable-child operations. */
2381
- var SubagentRuntime = class extends Service {
2382
- providers = /* @__PURE__ */ new Map();
2383
- continuations;
2384
- /** Deployment contributions composed into unpublished continuable children. */
2385
- setupRegistry = new SubagentActivationSetupRegistry();
2386
- /**
2387
- * The contained lifecycle-edge publisher. Built here because scoped dispatch
2388
- * keys its carrier by this exact service instance, whose own context filter
2389
- * composes into the carrier.
2390
- */
2391
- emitLifecycle;
2392
- constructor(ctx) {
2393
- super(ctx, "subagents");
2394
- this.emitLifecycle = createLifecycleEmitter(this.ctx, (parent) => scopeTarget(this, parent));
2395
- ctx.inject(["agents"], (childCtx) => {
2396
- const manager = new SubagentContinuationManager(childCtx, {
2397
- prepareContinuable: (name, request) => this.prepareContinuable(name, request),
2398
- observeActivation: (provider, childId, parent) => this.observeActivation(provider, childId, parent)
2399
- }, this.setupRegistry);
2400
- this.continuations = manager;
2401
- childCtx.effect(() => () => {
2402
- /* v8 ignore else -- one injected binding owns the slot until its fiber disposes. */
2403
- if (this.continuations === manager) this.continuations = void 0;
2404
- }, "subagents.continuationBinding()");
2405
- });
2406
- ctx.inject(["sessionProjections"], (projectionCtx) => {
2407
- projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition);
2408
- projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition);
2409
- });
2410
- }
2411
- /**
2412
- * Establish one durable continuable child and deliver its initial prompt.
2413
- * Resolves when the child's inbox accepts that prompt, without waiting for the
2414
- * turn to start or for the message to reach the Session log; any earlier
2415
- * failure rejects with no ids and rolls back the child entirely.
2416
- * @param spec - provider, delegation request, and caller cancellation.
2417
- * @returns the durable child id and the accepted prompt's message id.
2418
- * @throws when continuation services are unavailable or materialization fails.
2419
- */
2420
- async startContinuable(spec) {
2421
- return this.requireContinuations().startContinuable(spec);
2422
- }
2423
- /**
2424
- * Deliver one later message to a continuable child as its next FIFO turn. A
2425
- * resident child's Agent inbox accepts it directly (waking a `waiting`
2426
- * Activation), while an absent one is cold-resumed from its persisted
2427
- * Session. The Agent inbox is the only queue, so every accepted message has
2428
- * one observable order.
2429
- * @param parent - the exact live direct parent authorizing this delivery.
2430
- * @param childId - durable child session id.
2431
- * @param content - user-role content to deliver.
2432
- * @param options - the message source fields and caller cancellation, which stops the
2433
- * operation only before inbox acceptance.
2434
- * @returns the accepted message's inbox id.
2435
- * @throws when continuation services are unavailable, parent authority is
2436
- * rejected, or the message was not admitted.
2437
- */
2438
- async followup(parent, childId, content, options) {
2439
- return this.requireContinuations().followup(parent, childId, content, options);
2440
- }
2441
- /**
2442
- * Interrupt one live continuable child's current turn under a human parent
2443
- * address or an exact live ancestor Agent. Fire-and-return: the cancel
2444
- * signal is issued before this returns, but the target may keep running
2445
- * until it observes the signal. Unclaimed pending inbox work, the Activation,
2446
- * and published descendants are preserved; claimed work is not requeued.
2447
- * Once the interrupted driver is idle, a waking send resumes the parked FIFO
2448
- * queue. An absent target — including a one-shot or unknown id —
2449
- * is an accepted no-op, as is a manager-less composition, which cannot own a
2450
- * live Activation.
2451
- * @param targetSessionId - the durable child session id to interrupt.
2452
- * @param authority - the human parent address or exact live ancestor Agent.
2453
- * @throws {SubagentError} `UNAUTHORIZED` when the authority does not own the
2454
- * live target.
2455
- */
2456
- interrupt(targetSessionId, authority) {
2457
- this.continuations?.interrupt(targetSessionId, authority);
2458
- }
2459
- /**
2460
- * Deliver selected content from one live continuable child to its durable
2461
- * direct parent. The child is the authority credential; callers cannot name a
2462
- * recipient. Reporting does not conclude the child's turn or Activation.
2463
- * @param child - exact live reporting child.
2464
- * @param content - selected model-facing content.
2465
- * @param options - parent scheduling and pre-acceptance cancellation.
2466
- * @returns the stable identity of the parent-accepted message.
2467
- * @throws when continuation services are unavailable, sender authorization
2468
- * fails, or the direct parent is not live.
2469
- */
2470
- async reportFrom(child, content, options) {
2471
- return this.requireContinuations().reportFrom(child, content, options);
2472
- }
2473
- /**
2474
- * Compose one deployment capability into every continuable child's
2475
- * unpublished creation context on fresh creation and cold resume. Grants wait
2476
- * for the next Activation; removing the contribution revokes every resident
2477
- * installation immediately.
2478
- * @param contribution - synchronous child-scope installer.
2479
- * @returns the exact Cordis effect disposer.
2480
- */
2481
- registerContinuableSetup(contribution) {
2482
- return this.ctx.effect(() => this.setupRegistry.register(contribution), "subagents.registerContinuableSetup()");
2483
- }
2484
- /**
2485
- * Close continuable admission below exact live parent Agents, stop only their
2486
- * visible descendant Activations synchronously, then await admitted scoped
2487
- * materializations and release those forests child-first. The scoped cutoff
2488
- * lasts until each exact parent leaves the registry; unrelated parent trees
2489
- * remain live.
2490
- * @param parents - exact host-owned parent Agents entering teardown.
2491
- * @returns once every retained descendant Activation released its `AgentHandle`.
2492
- * @throws an aggregate error after all branches settle when any failed.
2493
- */
2494
- async drainContinuableDescendants(parents) {
2495
- const manager = this.continuations;
2496
- if (manager === void 0) return;
2497
- await manager.drainDescendants(parents);
2498
- }
2499
- /**
2500
- * Release selected resident continuable direct children of one exact live
2501
- * parent. Other children of the same parent remain admitted and resident.
2502
- * Absent targets and a manager-less composition are accepted no-ops.
2503
- * @param parent - exact live direct parent authorizing the selected release.
2504
- * @param childIds - durable direct-child ids to release when resident.
2505
- * @returns once every selected Activation released its `AgentHandle`.
2506
- * @throws {SubagentError} `UNAUTHORIZED` when a resident target belongs to a
2507
- * different parent or the supplied parent identity is stale.
2508
- */
2509
- async drainContinuableChildren(parent, childIds) {
2510
- const manager = this.continuations;
2511
- if (manager === void 0) return;
2512
- await manager.drainChildren(parent, childIds);
2513
- }
2514
- /**
2515
- * Enumerate the parent's direct session-backed subagents without loading or
2516
- * resuming an Agent and without any query service: the listing merges the live
2517
- * session store with optional session persistence (live-preferred) and
2518
- * serves each child's durable mode/label from the registered `subagent`
2519
- * projection unit down a three-rung ladder — the registry's watermark
2520
- * snapshot for a live child; for a cold one, a durable projection-cache
2521
- * row when the optional cache serves an own-suffix identity (its `seq`
2522
- * gate proves the value postdates the fork seed, where a child's own
2523
- * descriptor is immutable once appended), else one persistence inspection
2524
- * folded through the registry. The
2525
- * projection fold is the single classification authority; per-child
2526
- * diagnostics relay a fold that served no identity or a failed inspection,
2527
- * never a list-time descriptor parse. Absent persistence, enumeration is
2528
- * live-only (a cold child cannot be resumed then either, so its absence is
2529
- * capability absence, not an error). This service consults no Agent
2530
- * registrations, Activations, or providers.
2531
- *
2532
- * Every persistence read receives `signal`, and the listing rechecks
2533
- * cancellation around each of those awaits. Read rejections that settle
2534
- * after an abort become a stable `SubagentError` with code `CANCELLED`.
2535
- * @param parentSessionId - parent session whose direct children are listed.
2536
- * @param signal - caller-owned cancellation forwarded to persistence reads
2537
- * and observed around every read await.
2538
- * @returns children and per-child diagnostics ordered by `createdAt`, then id.
2539
- * @throws {@link SubagentError} when the projection registry or the session
2540
- * store is not mounted, or the caller cancels the listing.
2541
- */
2542
- listChildren(parentSessionId, signal) {
2543
- return listChildren(this.ctx, parentSessionId, signal);
2544
- }
2545
- /**
2546
- * Enumerate the root's complete session-backed subagent tree in stable
2547
- * pre-order from one live-preferred corpus, without loading or resuming an
2548
- * Agent. Ordinary sessions and one-shot children remain traversal nodes so
2549
- * continuable descendants below them are discovered; each returned entry
2550
- * adds its durable `parentId` and root-relative `depth`. Identity resolution,
2551
- * diagnostics, optional persistence, and cancellation follow the same
2552
- * projection-backed contract as {@link listChildren}.
2553
- * @param rootSessionId - session whose complete descendant tree is listed.
2554
- * @param signal - caller-owned cancellation forwarded to persistence reads
2555
- * and observed around every read await.
2556
- * @returns children and per-candidate diagnostics with tree position, in
2557
- * stable pre-order.
2558
- * @throws {@link SubagentError} under the same conditions as {@link listChildren}.
2559
- */
2560
- listDescendants(rootSessionId, signal) {
2561
- return listDescendants(this.ctx, rootSessionId, signal);
2562
- }
2563
- /**
2564
- * Register a provider under its name. Registration is effect-scoped and HMR
2565
- * safe; removing a provider blocks new starts but does not revoke runs that
2566
- * were already returned to their holders.
2567
- * @param provider - the trusted provider implementation.
2568
- * @returns the exact Cordis effect disposer.
2569
- */
2570
- registerProvider(provider) {
2571
- const name = provider.name;
2572
- return this.ctx.effect(function* () {
2573
- if (this.providers.has(name)) throw new SubagentError(`a subagent provider named "${name}" is already registered`, "DUPLICATE_PROVIDER");
2574
- this.providers.set(name, provider);
2575
- yield () => {
2576
- this.providers.delete(name);
2577
- this.emitLifecycle("subagent/provider-removed", name);
2725
+ let SubagentRuntime = (() => {
2726
+ let _classSuper = TypertRemoteService;
2727
+ let _instanceExtraInitializers = [];
2728
+ let _remoteExportList_decorators;
2729
+ let _prompt_decorators;
2730
+ let _interruptByParent_decorators;
2731
+ return class SubagentRuntime extends _classSuper {
2732
+ static {
2733
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2734
+ _remoteExportList_decorators = [Remote("list")];
2735
+ _prompt_decorators = [Remote("prompt")];
2736
+ _interruptByParent_decorators = [Remote("interruptByParent")];
2737
+ __esDecorate(this, null, _remoteExportList_decorators, {
2738
+ kind: "method",
2739
+ name: "remoteExportList",
2740
+ static: false,
2741
+ private: false,
2742
+ access: {
2743
+ has: (obj) => "remoteExportList" in obj,
2744
+ get: (obj) => obj.remoteExportList
2745
+ },
2746
+ metadata: _metadata
2747
+ }, null, _instanceExtraInitializers);
2748
+ __esDecorate(this, null, _prompt_decorators, {
2749
+ kind: "method",
2750
+ name: "prompt",
2751
+ static: false,
2752
+ private: false,
2753
+ access: {
2754
+ has: (obj) => "prompt" in obj,
2755
+ get: (obj) => obj.prompt
2756
+ },
2757
+ metadata: _metadata
2758
+ }, null, _instanceExtraInitializers);
2759
+ __esDecorate(this, null, _interruptByParent_decorators, {
2760
+ kind: "method",
2761
+ name: "interruptByParent",
2762
+ static: false,
2763
+ private: false,
2764
+ access: {
2765
+ has: (obj) => "interruptByParent" in obj,
2766
+ get: (obj) => obj.interruptByParent
2767
+ },
2768
+ metadata: _metadata
2769
+ }, null, _instanceExtraInitializers);
2770
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, {
2771
+ enumerable: true,
2772
+ configurable: true,
2773
+ writable: true,
2774
+ value: _metadata
2775
+ });
2776
+ }
2777
+ providers = (__runInitializers(this, _instanceExtraInitializers), /* @__PURE__ */ new Map());
2778
+ continuations;
2779
+ /** Deployment contributions composed into unpublished continuable children. */
2780
+ setupRegistry = new SubagentActivationSetupRegistry();
2781
+ /**
2782
+ * The contained lifecycle-edge publisher. Built here because scoped dispatch
2783
+ * keys its carrier by this exact service instance, whose own context filter
2784
+ * composes into the carrier.
2785
+ */
2786
+ emitLifecycle;
2787
+ constructor(ctx) {
2788
+ super(ctx, "subagents");
2789
+ this.emitLifecycle = createLifecycleEmitter(this.ctx, (parent) => scopeTarget(this, parent));
2790
+ ctx.inject(["agents"], (childCtx) => {
2791
+ const manager = new SubagentContinuationManager(childCtx, {
2792
+ prepareContinuable: (name, request) => this.prepareContinuable(name, request),
2793
+ observeActivation: (provider, childId, parent) => this.observeActivation(provider, childId, parent)
2794
+ }, this.setupRegistry);
2795
+ this.continuations = manager;
2796
+ childCtx.effect(() => () => {
2797
+ /* v8 ignore else -- one injected binding owns the slot until its fiber disposes. */
2798
+ if (this.continuations === manager) this.continuations = void 0;
2799
+ }, "subagents.continuationBinding()");
2800
+ });
2801
+ ctx.inject(["sessionProjections"], (projectionCtx) => {
2802
+ projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition);
2803
+ projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition);
2804
+ });
2805
+ }
2806
+ /**
2807
+ * Establish one durable continuable child and deliver its initial prompt.
2808
+ * Resolves when the child's inbox accepts that prompt, without waiting for the
2809
+ * turn to start or for the message to reach the Session log; any earlier
2810
+ * failure rejects with no ids and rolls back the child entirely.
2811
+ * @param spec - provider, delegation request, and caller cancellation.
2812
+ * @returns the durable child id and the accepted prompt's message id.
2813
+ * @throws when continuation services are unavailable or materialization fails.
2814
+ */
2815
+ async startContinuable(spec) {
2816
+ return this.requireContinuations().startContinuable(spec);
2817
+ }
2818
+ /**
2819
+ * Deliver one later message to a continuable child as its next FIFO turn. A
2820
+ * resident child's Agent inbox accepts it directly (waking a `waiting`
2821
+ * Activation), while an absent one is cold-resumed from its persisted
2822
+ * Session. The Agent inbox is the only queue, so every accepted message has
2823
+ * one observable order.
2824
+ * @param parent - the exact live direct parent authorizing this delivery.
2825
+ * @param childId - durable child session id.
2826
+ * @param content - user-role content to deliver.
2827
+ * @param options - the message source fields and caller cancellation, which stops the
2828
+ * operation only before inbox acceptance.
2829
+ * @returns the accepted message's inbox id.
2830
+ * @throws when continuation services are unavailable, parent authority is
2831
+ * rejected, or the message was not admitted.
2832
+ */
2833
+ async followup(parent, childId, content, options) {
2834
+ return this.requireContinuations().followup(parent, childId, content, options);
2835
+ }
2836
+ /**
2837
+ * Interrupt one live continuable child's current turn under a human parent
2838
+ * address or an exact live ancestor Agent. Fire-and-return: the cancel
2839
+ * signal is issued before this returns, but the target may keep running
2840
+ * until it observes the signal. Unclaimed pending inbox work, the Activation,
2841
+ * and published descendants are preserved; claimed work is not requeued.
2842
+ * Once the interrupted driver is idle, a waking send resumes the parked FIFO
2843
+ * queue. An absent target — including a one-shot or unknown id —
2844
+ * is an accepted no-op, as is a manager-less composition, which cannot own a
2845
+ * live Activation.
2846
+ * @param targetSessionId - the durable child session id to interrupt.
2847
+ * @param authority - the human parent address or exact live ancestor Agent.
2848
+ * @throws {SubagentError} `UNAUTHORIZED` when the authority does not own the
2849
+ * live target.
2850
+ */
2851
+ interrupt(targetSessionId, authority) {
2852
+ this.continuations?.interrupt(targetSessionId, authority);
2853
+ }
2854
+ /**
2855
+ * Deliver selected content from one live continuable child to its durable
2856
+ * direct parent. The child is the authority credential; callers cannot name a
2857
+ * recipient. Reporting does not conclude the child's turn or Activation.
2858
+ * @param child - exact live reporting child.
2859
+ * @param content - selected model-facing content.
2860
+ * @param options - parent scheduling and pre-acceptance cancellation.
2861
+ * @returns the stable identity of the parent-accepted message.
2862
+ * @throws when continuation services are unavailable, sender authorization
2863
+ * fails, or the direct parent is not live.
2864
+ */
2865
+ async reportFrom(child, content, options) {
2866
+ return this.requireContinuations().reportFrom(child, content, options);
2867
+ }
2868
+ /**
2869
+ * Compose one deployment capability into every continuable child's
2870
+ * unpublished creation context on fresh creation and cold resume. Grants wait
2871
+ * for the next Activation; removing the contribution revokes every resident
2872
+ * installation immediately.
2873
+ * @param contribution - synchronous child-scope installer.
2874
+ * @returns the exact Cordis effect disposer.
2875
+ */
2876
+ registerContinuableSetup(contribution) {
2877
+ return this.ctx.effect(() => this.setupRegistry.register(contribution), "subagents.registerContinuableSetup()");
2878
+ }
2879
+ /**
2880
+ * Close continuable admission below exact live parent Agents, stop only their
2881
+ * visible descendant Activations synchronously, then await admitted scoped
2882
+ * materializations and release those forests child-first. The scoped cutoff
2883
+ * lasts until each exact parent leaves the registry; unrelated parent trees
2884
+ * remain live.
2885
+ * @param parents - exact host-owned parent Agents entering teardown.
2886
+ * @returns once every retained descendant Activation released its `AgentHandle`.
2887
+ * @throws an aggregate error after all branches settle when any failed.
2888
+ */
2889
+ async drainContinuableDescendants(parents) {
2890
+ const manager = this.continuations;
2891
+ if (manager === void 0) return;
2892
+ await manager.drainDescendants(parents);
2893
+ }
2894
+ /**
2895
+ * Release selected resident continuable direct children of one exact live
2896
+ * parent. Other children of the same parent remain admitted and resident.
2897
+ * Absent targets and a manager-less composition are accepted no-ops.
2898
+ * @param parent - exact live direct parent authorizing the selected release.
2899
+ * @param childIds - durable direct-child ids to release when resident.
2900
+ * @returns once every selected Activation released its `AgentHandle`.
2901
+ * @throws {SubagentError} `UNAUTHORIZED` when a resident target belongs to a
2902
+ * different parent or the supplied parent identity is stale.
2903
+ */
2904
+ async drainContinuableChildren(parent, childIds) {
2905
+ const manager = this.continuations;
2906
+ if (manager === void 0) return;
2907
+ await manager.drainChildren(parent, childIds);
2908
+ }
2909
+ /**
2910
+ * Enumerate the parent's direct session-backed subagents without loading or
2911
+ * resuming an Agent. The Session query service supplies one live-preferred
2912
+ * corpus and shared point observations; the projection cache supplies
2913
+ * immutable descriptor hits without opening cold logs. The registered
2914
+ * `subagent` projection remains the sole mode/label classifier.
2915
+ *
2916
+ * Every query receives `signal`, and the listing rechecks cancellation
2917
+ * around each await. Read rejections that settle
2918
+ * after an abort become a stable `SubagentError` with code `CANCELLED`.
2919
+ * @param parentSessionId - parent session whose direct children are listed.
2920
+ * @param signal - caller-owned cancellation forwarded to Session queries
2921
+ * and observed around every read await.
2922
+ * @returns children and per-child diagnostics ordered by `createdAt`, then id.
2923
+ * @throws {@link SubagentError} when the projection registry or the session
2924
+ * store is not mounted, or the caller cancels the listing.
2925
+ */
2926
+ listChildren(parentSessionId, signal) {
2927
+ return listChildren(this.ctx, parentSessionId, signal);
2928
+ }
2929
+ /**
2930
+ * Enumerate the root's complete session-backed subagent tree in stable
2931
+ * pre-order from one live-preferred corpus, without loading or resuming an
2932
+ * Agent. Ordinary sessions and one-shot children remain traversal nodes so
2933
+ * continuable descendants below them are discovered; each returned entry
2934
+ * adds its durable `parentId` and root-relative `depth`. Identity resolution,
2935
+ * diagnostics, optional persistence, and cancellation follow the same
2936
+ * projection-backed contract as {@link listChildren}.
2937
+ * @param rootSessionId - session whose complete descendant tree is listed.
2938
+ * @param signal - caller-owned cancellation forwarded to persistence reads
2939
+ * and observed around every read await.
2940
+ * @returns children and per-candidate diagnostics with tree position, in
2941
+ * stable pre-order.
2942
+ * @throws {@link SubagentError} under the same conditions as {@link listChildren}.
2943
+ */
2944
+ listDescendants(rootSessionId, signal) {
2945
+ return listDescendants(this.ctx, rootSessionId, signal);
2946
+ }
2947
+ /**
2948
+ * Remote face of {@link listChildren} for one browser: the durable listing
2949
+ * plus live Agent activity and the delivery-time parent availability hint.
2950
+ * Parent availability is a hint; {@link prompt} performs the authoritative
2951
+ * check. Named apart from the provider-name {@link list}, which owns the
2952
+ * member.
2953
+ * @param parentSessionId - parent session whose direct children are listed.
2954
+ * @param signal - carrier cancellation forwarded to Session queries.
2955
+ * @returns the catalog view for that parent.
2956
+ * @throws {RemoteError} `gateway/bad-request` for an empty parent id,
2957
+ * `gateway/cancelled` for an aborted read, `subagent/projections-unavailable` when
2958
+ * the deployment has no projection registry, otherwise `gateway/internal`.
2959
+ */
2960
+ async remoteExportList(parentSessionId, signal) {
2961
+ validateControlRequest("subagent.list", { parentSessionId });
2962
+ try {
2963
+ return catalogView(this.ctx, parentSessionId, await this.listChildren(parentSessionId, signal));
2964
+ } catch (error) {
2965
+ return rejectCatalogRead(error, signal);
2966
+ }
2967
+ }
2968
+ /**
2969
+ * Deliver one browser-authored message to a continuable child through the
2970
+ * exact live direct parent, retaining the caller-minted request identity and
2971
+ * validated browser zone on the accepted message. Success identifies the
2972
+ * message the child's FIFO inbox accepted; later execution is independent of
2973
+ * this call.
2974
+ * @param request - durable address, minted identity, content, and optional browser zone.
2975
+ * @param signal - carrier cancellation, owning the call until inbox acceptance.
2976
+ * @returns the accepted message's inbox identity.
2977
+ * @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-unsupported`,
2978
+ * `subagent/invalid-time-zone`, `subagent/parent-unavailable`,
2979
+ * `subagent/not-resumable`, `subagent/unauthorized`,
2980
+ * `subagent/delivery-unavailable`, `gateway/cancelled`, or `gateway/internal`.
2981
+ */
2982
+ async prompt(request, signal) {
2983
+ const { parentSessionId, childSessionId, clientTimeZone } = request;
2984
+ validateControlRequest("subagent.prompt", request);
2985
+ const content = admitPromptContent(childSessionId, request.content);
2986
+ const canonicalTimeZone = clientTimeZone === void 0 ? void 0 : canonicalClientTimeZone(clientTimeZone);
2987
+ 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 });
2988
+ const parent = this.ctx.get("agents")?.get(parentSessionId);
2989
+ if (parent === void 0) throw new RemoteError("subagent/parent-unavailable", `parent session "${parentSessionId}" is not live`, { parentSessionId });
2990
+ const source = {
2991
+ kind: "user",
2992
+ rpcId: request.requestId,
2993
+ ...canonicalTimeZone === void 0 ? {} : { clientTimeZone: canonicalTimeZone }
2578
2994
  };
2579
- this.ctx.emit("subagent/provider-added", provider);
2580
- }.bind(this), "subagents.registerProvider()");
2581
- }
2582
- /**
2583
- * Look up a provider by name.
2584
- * @param name - the provider name.
2585
- * @returns the provider, or undefined when absent.
2586
- */
2587
- getProvider(name) {
2588
- return this.providers.get(name);
2589
- }
2590
- /**
2591
- * List registered provider names in insertion order.
2592
- * @returns the registered names.
2593
- */
2594
- list() {
2595
- return [...this.providers.keys()];
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"
2995
+ try {
2996
+ return { messageId: await this.followup(parent, childSessionId, content, {
2997
+ source,
2998
+ signal
2999
+ }) };
3000
+ } catch (error) {
3001
+ return rejectPrompt(error, childSessionId, signal);
2669
3002
  }
2670
- ];
2671
- 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");
2672
- }
2673
- };
3003
+ }
3004
+ /**
3005
+ * Remote face of {@link interrupt} under one durable parent address. No
3006
+ * catalog, history, persistence, or parent Agent lookup runs: the core
3007
+ * primitive alone authorizes the address against the live Activation, which
3008
+ * is what keeps a live child interruptible while its parent Agent is offline.
3009
+ * Absent, idle, and already-completed targets are accepted no-ops there.
3010
+ * @param childSessionId - durable child session id to interrupt.
3011
+ * @param parentSessionId - durable direct parent whose authority is claimed.
3012
+ * @param mode - required continuable-address discriminator.
3013
+ * @returns acknowledgement that the cancel signal was admitted, not that the target is quiescent.
3014
+ * @throws {RemoteError} `gateway/bad-request` for an empty id,
3015
+ * `subagent/unauthorized` when the address does not own the live target,
3016
+ * otherwise `gateway/internal`.
3017
+ */
3018
+ interruptByParent(childSessionId, parentSessionId, mode) {
3019
+ validateControlRequest("subagent.interrupt", {
3020
+ childSessionId,
3021
+ parentSessionId,
3022
+ mode
3023
+ });
3024
+ try {
3025
+ this.interrupt(childSessionId, {
3026
+ kind: "user",
3027
+ parentSessionId
3028
+ });
3029
+ } catch (error) {
3030
+ if (error instanceof SubagentError && error.code === "UNAUTHORIZED") throw new RemoteError("subagent/unauthorized", "subagent does not belong to this parent", { childSessionId }, { cause: error });
3031
+ throw new RemoteError("gateway/internal", "subagent interrupt failed", {}, { cause: error });
3032
+ }
3033
+ return { accepted: true };
3034
+ }
3035
+ /**
3036
+ * Register a provider under its name. Registration is effect-scoped and HMR
3037
+ * safe; removing a provider blocks new starts but does not revoke runs that
3038
+ * were already returned to their holders.
3039
+ * @param provider - the trusted provider implementation.
3040
+ * @returns the exact Cordis effect disposer.
3041
+ */
3042
+ registerProvider(provider) {
3043
+ const name = provider.name;
3044
+ return this.ctx.effect(function* () {
3045
+ if (this.providers.has(name)) throw new SubagentError(`a subagent provider named "${name}" is already registered`, "DUPLICATE_PROVIDER");
3046
+ this.providers.set(name, provider);
3047
+ yield () => {
3048
+ this.providers.delete(name);
3049
+ this.emitLifecycle("subagent/provider-removed", name);
3050
+ };
3051
+ this.ctx.emit("subagent/provider-added", provider);
3052
+ }.bind(this), "subagents.registerProvider()");
3053
+ }
3054
+ /**
3055
+ * Look up a provider by name.
3056
+ * @param name - the provider name.
3057
+ * @returns the provider, or undefined when absent.
3058
+ */
3059
+ getProvider(name) {
3060
+ return this.providers.get(name);
3061
+ }
3062
+ /**
3063
+ * List registered provider names in insertion order.
3064
+ * @returns the registered names.
3065
+ */
3066
+ list() {
3067
+ return [...this.providers.keys()];
3068
+ }
3069
+ /**
3070
+ * Establish a published child on the named provider. Capability and semantic
3071
+ * checks run before delegation. Provider ownership lasts until its promise
3072
+ * fulfills; a rejection therefore has no run for the caller to dispose and
3073
+ * emits no run lifecycle events. Post-publication turn and infrastructure
3074
+ * failures settle through the returned run.
3075
+ * @param name - the provider to use.
3076
+ * @param request - child label, prompt, parent, signal, and optional capabilities.
3077
+ * @returns the published holder-owned run.
3078
+ */
3079
+ async start(name, request) {
3080
+ const provider = this.expectProvider(name);
3081
+ this.assertCapabilities(provider, request);
3082
+ assertSubagentMaxDepth(request.maxDepth);
3083
+ if (request.outputSchema !== void 0) assertObjectJsonSchema(request.outputSchema);
3084
+ const descriptor = snapshotSubagentDescriptor({
3085
+ mode: "one-shot",
3086
+ provider: name,
3087
+ ...request.label !== void 0 ? { label: request.label } : {}
3088
+ });
3089
+ const resolved = {
3090
+ ...request,
3091
+ descriptor
3092
+ };
3093
+ return observeRun(this.emitLifecycle, name, request.parent, await provider.start(resolved));
3094
+ }
3095
+ /**
3096
+ * Resolve one provider's detached continuable-creation contribution. Method
3097
+ * presence on the provider IS the capability, so a provider without it is
3098
+ * rejected before the manager reserves any child resources.
3099
+ */
3100
+ async prepareContinuable(name, request) {
3101
+ const provider = this.expectProvider(name);
3102
+ if (provider.prepareContinuable === void 0) throw new SubagentError(`subagent provider "${provider.name}" does not support continuable children (no prepareContinuable capability)`, "UNSUPPORTED_CAPABILITY");
3103
+ return provider.prepareContinuable(request);
3104
+ }
3105
+ /** Look up a provider for dispatch or fail loud. */
3106
+ expectProvider(name) {
3107
+ const provider = this.providers.get(name);
3108
+ if (provider === void 0) throw new SubagentError(`no subagent provider registered for "${name}"`, "NO_PROVIDER");
3109
+ return provider;
3110
+ }
3111
+ /** Resolve the optional continuable-subagent manager or fail loud. */
3112
+ requireContinuations() {
3113
+ if (this.continuations === void 0) throw new SubagentError("continuable subagents require the agents service", "CONTINUATION_UNAVAILABLE");
3114
+ return this.continuations;
3115
+ }
3116
+ /**
3117
+ * Build the lifecycle observer for one continuable Activation's residency
3118
+ * epoch, so the manager publishes its edges without owning event dispatch.
3119
+ */
3120
+ observeActivation(provider, childId, parent) {
3121
+ return createActivationObserver(this.emitLifecycle, provider, childId, parent);
3122
+ }
3123
+ /** Reject the first requested capability that the provider lacks. */
3124
+ assertCapabilities(provider, request) {
3125
+ const needs = [
3126
+ {
3127
+ when: request.agentOptions !== void 0,
3128
+ cap: "agentOptions"
3129
+ },
3130
+ {
3131
+ when: request.outputSchema !== void 0,
3132
+ cap: "outputSchema"
3133
+ },
3134
+ {
3135
+ when: request.maxDepth !== void 0,
3136
+ cap: "depthLimit"
3137
+ },
3138
+ {
3139
+ when: request.toolFilter !== void 0,
3140
+ cap: "toolFilter"
3141
+ },
3142
+ {
3143
+ when: request.persona !== void 0,
3144
+ cap: "persona"
3145
+ }
3146
+ ];
3147
+ 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");
3148
+ }
3149
+ };
3150
+ })();
2674
3151
  //#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 };
3152
+ 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 };