@deepseek-ai/dsh-subagent 0.1.6-alpha.1 → 0.1.7-alpha.1

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,9 +1,10 @@
1
+ import z from "@deepseek-ai/schemastery";
1
2
  import { scopeTarget } from "@deepseek-ai/dsh-scope";
2
3
  import { assertObjectJsonSchema } from "@deepseek-ai/dsh-tools";
3
4
  import { canonicalClientTimeZone } from "@deepseek-ai/dsh-util-time";
4
5
  import { Remote, RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
5
6
  import { AttachmentError } from "@deepseek-ai/dsh-attachment";
6
- import { z } from "zod";
7
+ import { z as z$1 } from "zod";
7
8
  import { HarnessError, ReasoningEffortId, boundContextSummary, contentHasImage, createUserMessage, errorChain, joinAssistantStreamText } from "@deepseek-ai/dsh-llm";
8
9
  import { randomUUID } from "node:crypto";
9
10
  import { foldConsumedWork } from "@deepseek-ai/dsh-agent";
@@ -29,25 +30,23 @@ var SubagentError = class extends HarnessError {
29
30
  //#endregion
30
31
  //#region lib/types/control.js
31
32
  /**
32
- * Browser-facing subagent control assembly: the catalog view sampled against
33
- * the live Agent registry, one browser zone's validation, and the stable
34
- * failure codes the Remote surface answers with.
33
+ * Browser-facing subagent prompt and interrupt request validation plus the
34
+ * stable prompt failure codes returned by the Remote surface.
35
35
  *
36
36
  * @module @deepseek-ai/dsh-subagent
37
37
  */
38
- const SESSION_ID_SCHEMA = z.string().min(1);
38
+ const SESSION_ID_SCHEMA = z$1.string().min(1);
39
39
  const CONTROL_ID_SCHEMAS = {
40
- "subagent.list": z.object({ parentSessionId: SESSION_ID_SCHEMA }),
41
- "subagent.prompt": z.object({
40
+ "subagent.prompt": z$1.object({
42
41
  parentSessionId: SESSION_ID_SCHEMA,
43
42
  childSessionId: SESSION_ID_SCHEMA,
44
- mode: z.literal("continuable"),
45
- delivery: z.enum(["queue", "steer"])
43
+ mode: z$1.literal("continuable"),
44
+ delivery: z$1.enum(["queue", "steer"])
46
45
  }),
47
- "subagent.interrupt": z.object({
46
+ "subagent.interrupt": z$1.object({
48
47
  parentSessionId: SESSION_ID_SCHEMA,
49
48
  childSessionId: SESSION_ID_SCHEMA,
50
- mode: z.literal("continuable")
49
+ mode: z$1.literal("continuable")
51
50
  })
52
51
  };
53
52
  /**
@@ -62,39 +61,6 @@ function validateControlRequest(method, payload) {
62
61
  if (!parsed.success) throw new RemoteError("gateway/bad-request", `invalid payload for ${method}`, { issues: parsed.error.issues });
63
62
  }
64
63
  /**
65
- * Project one durable listing onto the catalog view, replacing each row's
66
- * store-derived activity with the live Agent driver's status and reporting
67
- * whether the exact parent Agent is live. Without an Agent registry no driver
68
- * runs at all, so every row is inactive and the parent is unavailable.
69
- * @param ctx - Host context that may carry the Agent registry.
70
- * @param parentSessionId - the listed parent.
71
- * @param entries - the durable direct-child listing.
72
- * @returns the catalog view answered to one browser.
73
- */
74
- function catalogView(ctx, parentSessionId, entries) {
75
- const agents = ctx.get("agents");
76
- return {
77
- entries: entries.map((entry) => entry.kind === "child" ? {
78
- ...entry,
79
- activity: agents?.get(entry.id)?.status === "running" ? "running" : "inactive"
80
- } : entry),
81
- parentAvailable: agents?.get(parentSessionId) !== void 0
82
- };
83
- }
84
- /**
85
- * Refuse one catalog read while preserving cancellation and a missing
86
- * projections registry as distinct failures.
87
- * @param error - the thrown value.
88
- * @param signal - the caller's cancellation.
89
- * @returns Never — the refusal is thrown.
90
- * @throws {RemoteError} always.
91
- */
92
- function rejectCatalogRead(error, signal) {
93
- if (isCancellation(error, signal)) throw new RemoteError("gateway/cancelled", "subagent catalog read was cancelled", {}, { cause: error });
94
- 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 });
95
- throw new RemoteError("gateway/internal", "subagent catalog read failed", {}, { cause: error });
96
- }
97
- /**
98
64
  * Refuse one continuation prompt without exposing provider detail: admission
99
65
  * failures the caller can act on keep their own code, everything else is
100
66
  * internal.
@@ -113,6 +79,7 @@ function rejectPrompt(error, childSessionId, signal) {
113
79
  case "UNAUTHORIZED": throw new RemoteError("subagent/unauthorized", "subagent does not belong to this parent", { childSessionId }, { cause: error });
114
80
  case "DRAINING":
115
81
  case "ACTIVATION_CLOSING":
82
+ case "ACTIVATION_LIMIT_REACHED":
116
83
  case "CONTINUATION_UNAVAILABLE":
117
84
  case "PERSISTENCE_UNAVAILABLE": throw new RemoteError("subagent/delivery-unavailable", "subagent follow-up is temporarily unavailable", { childSessionId }, { cause: error });
118
85
  default: break;
@@ -383,9 +350,10 @@ function epochStopReason(events) {
383
350
  case "blocked": return "refusal";
384
351
  case void 0:
385
352
  case "completed": return droppedUnrun ? "aborted" : "completed";
386
- /* v8 ignore next 3 -- `TurnEndReason` is merge-extensible, so this arm needs a
387
- * backend that adds a variant; treating an unnameable reason as success would
388
- * report failed work as completed. */
353
+ /* v8 ignore next 4 -- `forked` appears only in constructor seed history, while
354
+ * this function reads an epoch-owned suffix. `TurnEndReason` is merge-extensible,
355
+ * so a backend-added variant cannot be listed; treating an unnameable reason as
356
+ * success would report failed work as completed. */
389
357
  default: return "error";
390
358
  }
391
359
  }
@@ -752,6 +720,19 @@ var SubagentInbox = class {
752
720
  *
753
721
  * @module @deepseek-ai/dsh-subagent/continuation-activation
754
722
  */
723
+ /** Process-local slots shared through uninterrupted continuable parent links. */
724
+ var ActivationPool = class {
725
+ slots = /* @__PURE__ */ new Set();
726
+ /** Reserve before reconstruction; the returned release also tolerates unpublished rollback. */
727
+ reserve(capacity) {
728
+ if (this.slots.size >= capacity) throw new SubagentError(`subagent limit reached (active child limit: ${capacity}); wait for an existing child to finish or complete this work with the current agents`, "ACTIVATION_LIMIT_REACHED");
729
+ const slot = Symbol();
730
+ this.slots.add(slot);
731
+ return () => {
732
+ this.slots.delete(slot);
733
+ };
734
+ }
735
+ };
755
736
  /** Serialize each durable child's delivery, release, and disposal. */
756
737
  var ChildLock = class {
757
738
  tails = /* @__PURE__ */ new Map();
@@ -775,8 +756,11 @@ var ChildLock = class {
775
756
  var ContinuableActivationRegistry = class {
776
757
  ctx;
777
758
  observeActivation;
759
+ maxActiveSubagents;
778
760
  /** Child session id → its live Activation. Process-local, never durable. */
779
761
  resident = /* @__PURE__ */ new Map();
762
+ /** Root identities retain their pool across child settlement without retaining dead roots. */
763
+ rootPools = /* @__PURE__ */ new WeakMap();
780
764
  /** Materializations admitted before drain, tracked through publication or rollback. */
781
765
  materializations = /* @__PURE__ */ new Set();
782
766
  /** Per-child serializer shared by delivery, release, and disposal. */
@@ -796,9 +780,10 @@ var ContinuableActivationRegistry = class {
796
780
  * @param ctx - context providing Agents, Sessions, and teardown ownership.
797
781
  * @param observeActivation - build the lifecycle observer for one residency epoch.
798
782
  */
799
- constructor(ctx, observeActivation) {
783
+ constructor(ctx, observeActivation, maxActiveSubagents) {
800
784
  this.ctx = ctx;
801
785
  this.observeActivation = observeActivation;
786
+ this.maxActiveSubagents = maxActiveSubagents;
802
787
  const scope = ctx.plugin(function activationOwner() {});
803
788
  this.ownerCtx = scope.ctx;
804
789
  ctx.on("agent/disposed", ({ agent }) => {
@@ -979,14 +964,20 @@ var ContinuableActivationRegistry = class {
979
964
  */
980
965
  materialize(inputs) {
981
966
  this.assertAdmitting(inputs.parent);
982
- const settled = Promise.withResolvers();
967
+ inputs.signal.throwIfAborted();
983
968
  const lineage = this.liveLineage(inputs.parent);
969
+ const pool = this.resident.get(inputs.parent.id)?.pool ?? this.rootPool(inputs.parent);
970
+ const releaseSlot = pool.reserve(this.maxActiveSubagents());
971
+ const settled = Promise.withResolvers();
984
972
  const materialization = {
985
973
  lineage,
986
974
  settled: settled.promise
987
975
  };
988
976
  this.materializations.add(materialization);
989
- return this.materializeTracked(inputs, lineage).finally(() => {
977
+ return this.materializeTracked(inputs, lineage, pool, releaseSlot).catch((error) => {
978
+ releaseSlot();
979
+ throw error;
980
+ }).finally(() => {
990
981
  this.materializations.delete(materialization);
991
982
  settled.resolve();
992
983
  });
@@ -1061,8 +1052,17 @@ var ContinuableActivationRegistry = class {
1061
1052
  const lineage = this.liveLineage(agent);
1062
1053
  for (const [root, members] of this.closingScopes) if (members.has(agent) || lineage.includes(root)) return root;
1063
1054
  }
1055
+ /** Resolve a root's pool once; descendants inherit their resident parent's pool directly. */
1056
+ rootPool(parent) {
1057
+ let pool = this.rootPools.get(parent);
1058
+ if (pool === void 0) {
1059
+ pool = new ActivationPool();
1060
+ this.rootPools.set(parent, pool);
1061
+ }
1062
+ return pool;
1063
+ }
1064
1064
  /** Perform one tracked materialization through publication or rollback. */
1065
- async materializeTracked(inputs, parentLineage) {
1065
+ async materializeTracked(inputs, parentLineage, pool, releaseSlot) {
1066
1066
  const { childId, provider, parent, create } = inputs;
1067
1067
  inputs.signal.throwIfAborted();
1068
1068
  const setup = (childCtx, child) => {
@@ -1090,6 +1090,8 @@ var ContinuableActivationRegistry = class {
1090
1090
  setup
1091
1091
  });
1092
1092
  const activation = {
1093
+ pool,
1094
+ releaseSlot,
1093
1095
  childId,
1094
1096
  parentSession: parent.id,
1095
1097
  provider,
@@ -1128,6 +1130,7 @@ var ContinuableActivationRegistry = class {
1128
1130
  await activation.handle.dispose();
1129
1131
  } finally {
1130
1132
  this.resident.delete(activation.childId);
1133
+ activation.releaseSlot();
1131
1134
  this.releaseOwnership(activation.childId);
1132
1135
  }
1133
1136
  });
@@ -1241,6 +1244,7 @@ var ContinuableActivationRegistry = class {
1241
1244
  if (failures.length === 1) failure = failures[0];
1242
1245
  else if (failures.length > 1) failure = new SubagentError(`subagent "${childId}" activation teardown failed at ${failures.length} boundaries: ` + failures.map((item) => errorChain(item)).join("; "), "ACTIVATION_TEARDOWN_FAILED", { cause: new AggregateError(failures) });
1243
1246
  this.resident.delete(childId);
1247
+ activation.releaseSlot();
1244
1248
  this.notifySettlement(activation, activation.observer.terminal(failure));
1245
1249
  this.releaseOwnership(childId);
1246
1250
  activation.observer.settle(failure);
@@ -1432,49 +1436,68 @@ function foldSubagentDescriptor(events) {
1432
1436
  if (event === void 0) return void 0;
1433
1437
  return parseSubagentDescriptor(event.data);
1434
1438
  }
1435
- const sessionIdSchema = z.string();
1436
- const oneShotCatalogSchema = z.object({
1437
- version: z.literal(0),
1439
+ const sessionIdSchema = z$1.string();
1440
+ const oneShotCatalogSchema = z$1.object({
1441
+ version: z$1.union([z$1.literal(0), z$1.literal(1)]),
1438
1442
  childId: sessionIdSchema,
1439
- childCreatedAt: z.number().int().nonnegative(),
1440
- mode: z.literal("one-shot"),
1441
- label: z.string().optional()
1443
+ childCreatedAt: z$1.number().int().nonnegative(),
1444
+ mode: z$1.literal("one-shot"),
1445
+ label: z$1.string().optional()
1442
1446
  }).strict();
1443
- const continuableCatalogSchema = z.object({
1444
- version: z.literal(0),
1447
+ const continuableCatalogSchema = z$1.object({
1448
+ version: z$1.union([z$1.literal(0), z$1.literal(1)]),
1445
1449
  childId: sessionIdSchema,
1446
- childCreatedAt: z.number().int().nonnegative(),
1447
- mode: z.literal("continuable"),
1448
- label: z.string()
1450
+ childCreatedAt: z$1.number().int().nonnegative(),
1451
+ mode: z$1.literal("continuable"),
1452
+ label: z$1.string()
1449
1453
  }).strict();
1450
- const eventDataSchema = z.union([oneShotCatalogSchema, continuableCatalogSchema]);
1451
- const viewSchema = z.array(z.union([oneShotCatalogSchema.omit({
1452
- version: true,
1453
- childId: true,
1454
- childCreatedAt: true
1455
- }).extend({
1456
- id: sessionIdSchema,
1457
- createdAt: oneShotCatalogSchema.shape.childCreatedAt
1458
- }), continuableCatalogSchema.omit({
1459
- version: true,
1460
- childId: true,
1461
- childCreatedAt: true
1462
- }).extend({
1463
- id: sessionIdSchema,
1464
- createdAt: continuableCatalogSchema.shape.childCreatedAt
1465
- })]));
1466
- const stateSchema = z.object({
1467
- inheritedEventCount: z.number().int().nonnegative(),
1454
+ const unknownCatalogSchema = oneShotCatalogSchema.extend({
1455
+ version: z$1.literal(1),
1456
+ mode: z$1.literal("unknown")
1457
+ });
1458
+ const eventDataSchema = z$1.union([
1459
+ oneShotCatalogSchema,
1460
+ continuableCatalogSchema,
1461
+ unknownCatalogSchema
1462
+ ]);
1463
+ const viewSchema = z$1.array(z$1.union([
1464
+ oneShotCatalogSchema.omit({
1465
+ version: true,
1466
+ childId: true,
1467
+ childCreatedAt: true
1468
+ }).extend({
1469
+ id: sessionIdSchema,
1470
+ createdAt: oneShotCatalogSchema.shape.childCreatedAt
1471
+ }),
1472
+ continuableCatalogSchema.omit({
1473
+ version: true,
1474
+ childId: true,
1475
+ childCreatedAt: true
1476
+ }).extend({
1477
+ id: sessionIdSchema,
1478
+ createdAt: continuableCatalogSchema.shape.childCreatedAt
1479
+ }),
1480
+ unknownCatalogSchema.omit({
1481
+ version: true,
1482
+ childId: true,
1483
+ childCreatedAt: true
1484
+ }).extend({
1485
+ id: sessionIdSchema,
1486
+ createdAt: unknownCatalogSchema.shape.childCreatedAt
1487
+ })
1488
+ ]));
1489
+ const stateSchema = z$1.object({
1490
+ inheritedEventCount: z$1.number().int().nonnegative(),
1468
1491
  head: chunkedListSchema(eventDataSchema).optional()
1469
1492
  }).strict();
1470
1493
  /**
1471
- * Materialize direct children from their parent's successful creation facts.
1494
+ * Materialize complete and unknown-mode child identities from parent catalog events.
1472
1495
  * @param state - parent catalog fold state.
1473
1496
  * @returns current direct-child rows in parent catalog event order.
1474
1497
  */
1475
1498
  function subagentCatalogEntries(state) {
1476
1499
  const entries = [];
1477
- for (const data of iterateChunkedList(state.head)) entries.push(data.mode === "one-shot" ? {
1500
+ for (const data of iterateChunkedList(state.head)) entries.push(data.mode !== "continuable" ? {
1478
1501
  id: data.childId,
1479
1502
  createdAt: data.childCreatedAt,
1480
1503
  mode: data.mode,
@@ -1499,7 +1522,7 @@ const subagentCatalogProjectionDefinition = {
1499
1522
  head: appendChunkedList(state.head, eventDataSchema.parse(event.data))
1500
1523
  };
1501
1524
  },
1502
- stateVersion: 2,
1525
+ stateVersion: 3,
1503
1526
  wire: {
1504
1527
  viewSchema,
1505
1528
  view: subagentCatalogEntries
@@ -1565,7 +1588,7 @@ const deliverSubagentPrompt = Symbol.for("dsh.subagent.deliverPrompt");
1565
1588
  *
1566
1589
  * @module @deepseek-ai/dsh-subagent
1567
1590
  */
1568
- var __addDisposableResource$1 = function(env, value, async) {
1591
+ var __addDisposableResource$2 = function(env, value, async) {
1569
1592
  if (value !== null && value !== void 0) {
1570
1593
  if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
1571
1594
  var dispose, inner;
@@ -1594,7 +1617,7 @@ var __addDisposableResource$1 = function(env, value, async) {
1594
1617
  } else if (async) env.stack.push({ async: true });
1595
1618
  return value;
1596
1619
  };
1597
- var __disposeResources$1 = (function(SuppressedError) {
1620
+ var __disposeResources$2 = (function(SuppressedError) {
1598
1621
  return function(env) {
1599
1622
  function fail(e) {
1600
1623
  env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
@@ -1633,10 +1656,10 @@ var SubagentContinuationManager = class {
1633
1656
  ctx;
1634
1657
  host;
1635
1658
  activations;
1636
- constructor(ctx, host) {
1659
+ constructor(ctx, host, maxActiveSubagents) {
1637
1660
  this.ctx = ctx;
1638
1661
  this.host = host;
1639
- this.activations = new ContinuableActivationRegistry(ctx, (provider, childId, parent) => host.observeActivation(provider, childId, parent));
1662
+ this.activations = new ContinuableActivationRegistry(ctx, (provider, childId, parent) => host.observeActivation(provider, childId, parent), maxActiveSubagents);
1640
1663
  }
1641
1664
  /**
1642
1665
  * Start one continuable background child and resolve at initial inbox acceptance.
@@ -1887,7 +1910,7 @@ var SubagentContinuationManager = class {
1887
1910
  options.signal.throwIfAborted();
1888
1911
  throw new SubagentError(`subagent "${childId}" is unavailable`, "NOT_RESUMABLE", { cause: error });
1889
1912
  }
1890
- const source = __addDisposableResource$1(env_1, observation, false);
1913
+ const source = __addDisposableResource$2(env_1, observation, false);
1891
1914
  this.activations.assertAdmitting(parent);
1892
1915
  this.activations.authorizeLineage(parent, childId, source.header.parentSession);
1893
1916
  const descriptor = foldSubagentDescriptor(source.events.slice(source.inheritedEventCount));
@@ -1919,7 +1942,7 @@ var SubagentContinuationManager = class {
1919
1942
  env_1.error = e_1;
1920
1943
  env_1.hasError = true;
1921
1944
  } finally {
1922
- __disposeResources$1(env_1);
1945
+ __disposeResources$2(env_1);
1923
1946
  }
1924
1947
  }
1925
1948
  /** Admit a materialized child, commit its creation fact, and release it on failure. */
@@ -1976,24 +1999,15 @@ var SubagentContinuationManager = class {
1976
1999
  //#endregion
1977
2000
  //#region lib/types/list-children.js
1978
2001
  /**
1979
- * Read-only enumeration of durable subagent children and descendant trees
1980
- * through the Session query service. Candidates come from one live-preferred
1981
- * corpus; each child's mode/label is the registered `subagent` projection
1982
- * unit's value, resolved
1983
- * down a three-rung ladder: the registry's watermark cache for a live child,
1984
- * an unseeded durable projection-cache row, and one shared Session observation
1985
- * otherwise. A seeded header deliberately lacks its exact inherited cut, so
1986
- * it takes the body-bearing observation path before classifying an identity.
1987
- * The projection fold is the single classification
1988
- * authority — this module parses no descriptor
1989
- * itself. Absent persistence, enumeration is live-only: a cold child is
1990
- * unreachable for resume anyway, so its absence is capability absence, not an
1991
- * error. The module owns no catalog state and does not consult Activation,
1992
- * Agent-registry, continuation-manager, or provider state.
2002
+ * Direct-child discovery from a parent-owned `subagent/catalog` projection,
2003
+ * plus complete descendant-tree enumeration from the Session corpus. A direct
2004
+ * listing owns one parent observation and reads no child log. Descendant
2005
+ * enumeration retains the complete corpus and the child identity projection
2006
+ * because ordinary Sessions and one-shot children remain traversal nodes.
1993
2007
  *
1994
2008
  * @module @deepseek-ai/dsh-subagent
1995
2009
  */
1996
- var __addDisposableResource = function(env, value, async) {
2010
+ var __addDisposableResource$1 = function(env, value, async) {
1997
2011
  if (value !== null && value !== void 0) {
1998
2012
  if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
1999
2013
  var dispose, inner;
@@ -2022,7 +2036,7 @@ var __addDisposableResource = function(env, value, async) {
2022
2036
  } else if (async) env.stack.push({ async: true });
2023
2037
  return value;
2024
2038
  };
2025
- var __disposeResources = (function(SuppressedError) {
2039
+ var __disposeResources$1 = (function(SuppressedError) {
2026
2040
  return function(env) {
2027
2041
  function fail(e) {
2028
2042
  env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
@@ -2058,37 +2072,43 @@ var __disposeResources = (function(SuppressedError) {
2058
2072
  */
2059
2073
  const COLD_READ_CONCURRENCY = 4;
2060
2074
  /**
2061
- * Enumerate one parent's origin-classified direct children from the
2062
- * live-preferred merge of `ctx.sessions` and optional session persistence,
2063
- * serving each identity from the `subagent` projection unit: the registry's
2064
- * watermark snapshot for a live child; for a cold one, a durable
2065
- * projection-cache read for an unseeded lifecycle, else one bounded-concurrency
2066
- * shared Session observation carrying the exact inherited cut.
2067
- * @see SubagentRuntime.listChildren for the public cancellation and failure contract.
2068
- * @param ctx - context carrying the session store, the projection registry,
2069
- * optional persistence, and the optional projection cache.
2070
- * @param parentSessionId - parent session whose direct children are listed.
2071
- * @param signal - caller-owned cancellation observed around every persistence read.
2072
- * @returns children and per-child diagnostics ordered by `createdAt`, then id.
2073
- * @throws {@link SubagentError} when the projection registry or the session
2074
- * store is not mounted, or the caller cancels the listing.
2075
+ * Read one parent's durable catalog through a live-preferred Session observation.
2076
+ * @param ctx - context carrying the Session query service.
2077
+ * @param parentSessionId - parent whose direct children are requested.
2078
+ * @param signal - cancellation forwarded to the Session observation.
2079
+ * @returns direct-child rows in parent catalog event order.
2080
+ * @throws {@link SubagentError} when query or catalog projection is unavailable.
2075
2081
  */
2076
2082
  async function listChildren(ctx, parentSessionId, signal) {
2077
- const listing = await prepareListing(ctx, signal);
2078
- return (await resolveCandidateRows([...listing.corpus.values()].filter((record) => record.header.parentSession === parentSessionId && record.header.origin === "subagent").sort(compareCorpusRecords), listing, signal)).filter((row) => row !== void 0);
2083
+ const env_1 = {
2084
+ stack: [],
2085
+ error: void 0,
2086
+ hasError: false
2087
+ };
2088
+ try {
2089
+ const query = ctx.get("sessionQuery");
2090
+ if (query === void 0) throw new SubagentError("listing subagents requires the sessionQuery service (load @deepseek-ai/dsh-session-query)", "SUBAGENT_CONTROL_QUERY_UNAVAILABLE");
2091
+ const entries = __addDisposableResource$1(env_1, await query.observeSession(parentSessionId, { ...signal === void 0 ? {} : { signal } }), false).projections?.values.subagentCatalog;
2092
+ if (entries === void 0) throw new SubagentError("listing subagents requires the registered subagentCatalog projection", "SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE");
2093
+ return entries;
2094
+ } catch (e_1) {
2095
+ env_1.error = e_1;
2096
+ env_1.hasError = true;
2097
+ } finally {
2098
+ __disposeResources$1(env_1);
2099
+ }
2079
2100
  }
2080
2101
  /**
2081
2102
  * Enumerate every session-backed subagent below one root in stable pre-order.
2082
2103
  * Ordinary sessions and one-shot children remain traversal nodes, so a
2083
2104
  * continuable child below either is still discovered. Classification uses the
2084
- * same projection-backed runtime as {@link listChildren}; no Agent is loaded or
2085
- * resumed.
2105
+ * registered child identity projection; no Agent is loaded or resumed.
2086
2106
  * @see SubagentRuntime.listDescendants for the public cancellation and failure contract.
2087
2107
  * @param ctx - context carrying the session store, projection registry, and optional persistence/cache.
2088
2108
  * @param rootSessionId - session whose complete descendant tree is listed.
2089
2109
  * @param signal - caller-owned cancellation observed around every persistence read.
2090
2110
  * @returns interpreted subagents with durable direct-parent and root-relative depth.
2091
- * @throws {@link SubagentError} under the same conditions as {@link listChildren}.
2111
+ * @throws {@link SubagentError} when listing dependencies are unavailable or the caller cancels.
2092
2112
  */
2093
2113
  async function listDescendants(ctx, rootSessionId, signal) {
2094
2114
  const listing = await prepareListing(ctx, signal);
@@ -2224,7 +2244,7 @@ function compareCorpusRecords(a, b) {
2224
2244
  * throw — are final, so they report `corrupt`.
2225
2245
  */
2226
2246
  async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
2227
- const env_1 = {
2247
+ const env_2 = {
2228
2248
  stack: [],
2229
2249
  error: void 0,
2230
2250
  hasError: false
@@ -2234,7 +2254,7 @@ async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
2234
2254
  if (cache !== void 0 && !header.isSeeded) {
2235
2255
  let cached;
2236
2256
  try {
2237
- cached = cache.cachedSnapshot(header, SessionLogOffset(0), ["subagent"])?.values.subagent;
2257
+ cached = cache.cachedSnapshot(header, ["subagent"])?.values.subagent;
2238
2258
  } catch {
2239
2259
  cached = void 0;
2240
2260
  }
@@ -2252,7 +2272,7 @@ async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
2252
2272
  reason: sessionQueryCode(error) === "SESSION_QUERY_CORRUPT_SESSION" || sessionQueryCode(error) === "SESSION_QUERY_SOURCE_CONFLICT" ? "corrupt" : "unavailable"
2253
2273
  };
2254
2274
  }
2255
- const ownedObservation = __addDisposableResource(env_1, observation, false);
2275
+ const ownedObservation = __addDisposableResource$1(env_2, observation, false);
2256
2276
  assertListingNotCancelled(signal);
2257
2277
  if (!sameLifecycle(ownedObservation.header, header)) return {
2258
2278
  kind: "diagnostic",
@@ -2266,11 +2286,11 @@ async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
2266
2286
  reason: "corrupt"
2267
2287
  };
2268
2288
  return childRow(childId, identity, "inactive", hasChildren);
2269
- } catch (e_1) {
2270
- env_1.error = e_1;
2271
- env_1.hasError = true;
2289
+ } catch (e_2) {
2290
+ env_2.error = e_2;
2291
+ env_2.hasError = true;
2272
2292
  } finally {
2273
- __disposeResources(env_1);
2293
+ __disposeResources$1(env_2);
2274
2294
  }
2275
2295
  }
2276
2296
  /** Materialize one served identity as its child row. */
@@ -2315,6 +2335,159 @@ function sessionQueryCode(error) {
2315
2335
  return error instanceof Error && "code" in error ? error.code : void 0;
2316
2336
  }
2317
2337
  //#endregion
2338
+ //#region lib/types/archive-admission.js
2339
+ /**
2340
+ * The `subagent` family of the Workspace registry's archive admission: which
2341
+ * subagent descendants of a Session are still inside a turn, and how they
2342
+ * stop when the Session is archived with its work.
2343
+ *
2344
+ * @module @deepseek-ai/dsh-subagent
2345
+ */
2346
+ var __addDisposableResource = function(env, value, async) {
2347
+ if (value !== null && value !== void 0) {
2348
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
2349
+ var dispose, inner;
2350
+ if (async) {
2351
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
2352
+ dispose = value[Symbol.asyncDispose];
2353
+ }
2354
+ if (dispose === void 0) {
2355
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
2356
+ dispose = value[Symbol.dispose];
2357
+ if (async) inner = dispose;
2358
+ }
2359
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
2360
+ if (inner) dispose = function() {
2361
+ try {
2362
+ inner.call(this);
2363
+ } catch (e) {
2364
+ return Promise.reject(e);
2365
+ }
2366
+ };
2367
+ env.stack.push({
2368
+ value,
2369
+ dispose,
2370
+ async
2371
+ });
2372
+ } else if (async) env.stack.push({ async: true });
2373
+ return value;
2374
+ };
2375
+ var __disposeResources = (function(SuppressedError) {
2376
+ return function(env) {
2377
+ function fail(e) {
2378
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
2379
+ env.hasError = true;
2380
+ }
2381
+ var r, s = 0;
2382
+ function next() {
2383
+ while (r = env.stack.pop()) try {
2384
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
2385
+ if (r.dispose) {
2386
+ var result = r.dispose.call(r.value);
2387
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
2388
+ fail(e);
2389
+ return next();
2390
+ });
2391
+ } else s |= 1;
2392
+ } catch (e) {
2393
+ fail(e);
2394
+ }
2395
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
2396
+ if (env.hasError) throw env.error;
2397
+ }
2398
+ return next();
2399
+ };
2400
+ })(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
2401
+ var e = new Error(message);
2402
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
2403
+ });
2404
+ /**
2405
+ * Answer `workspace/session-activity` with the running subagent descendants of
2406
+ * the asked Session, and `workspace/session-stop` by cancelling each of them
2407
+ * as their parent would. Both listeners live as long as `ctx`'s fiber.
2408
+ * @param ctx - context carrying the Agent registry; the Session query service is optional and only supplies labels.
2409
+ */
2410
+ function installSubagentArchiveAdmission(ctx) {
2411
+ ctx.on("workspace/session-activity", async ({ sessionId }, next) => {
2412
+ const running = runningDescendants(ctx, sessionId);
2413
+ const rest = await next();
2414
+ if (running.length === 0) return rest;
2415
+ return [{
2416
+ kind: "subagent",
2417
+ items: await Promise.all(running.map((child) => describe(ctx, child)))
2418
+ }, ...rest];
2419
+ });
2420
+ ctx.on("workspace/session-stop", ({ sessionId }) => {
2421
+ for (const child of runningDescendants(ctx, sessionId)) try {
2422
+ child.cancel({ kind: "parent" });
2423
+ } catch (error) {
2424
+ ctx.logger.warn(`subagent: cancelling "${child.id}" for an archived Session failed: ${String(error)}`);
2425
+ }
2426
+ });
2427
+ }
2428
+ /**
2429
+ * Live subagent descendants inside a turn, by durable lineage: a child whose
2430
+ * header names its parent and carries the subagent origin this package
2431
+ * records, at any depth. A fork shares the lineage field without the origin
2432
+ * and is an independent conversation, so it never holds its source. Lineage
2433
+ * is read as data, so a damaged header chain that loops is visited once.
2434
+ */
2435
+ function runningDescendants(ctx, rootId) {
2436
+ const childrenOf = /* @__PURE__ */ new Map();
2437
+ for (const agent of ctx.agents.list()) {
2438
+ const { parentSession, origin } = agent.session.header;
2439
+ if (parentSession === void 0 || origin !== "subagent") continue;
2440
+ const siblings = childrenOf.get(parentSession) ?? [];
2441
+ siblings.push(agent);
2442
+ childrenOf.set(parentSession, siblings);
2443
+ }
2444
+ const running = [];
2445
+ const pending = [rootId];
2446
+ const visited = /* @__PURE__ */ new Set();
2447
+ while (pending.length > 0) {
2448
+ const parentId = pending.shift();
2449
+ if (visited.has(parentId)) continue;
2450
+ visited.add(parentId);
2451
+ for (const child of childrenOf.get(parentId) ?? []) {
2452
+ if (child.status === "running") running.push(child);
2453
+ pending.push(child.id);
2454
+ }
2455
+ }
2456
+ return running;
2457
+ }
2458
+ /**
2459
+ * The child's activity item: its id, plus the durable creation label its
2460
+ * descriptor carries, read through a live Session observation. Without the
2461
+ * Session query service, or with a descriptor that is absent or unreadable,
2462
+ * the item names the child by id alone.
2463
+ */
2464
+ async function describe(ctx, child) {
2465
+ const query = ctx.get("sessionQuery");
2466
+ if (query === void 0) return { id: child.id };
2467
+ try {
2468
+ const env_1 = {
2469
+ stack: [],
2470
+ error: void 0,
2471
+ hasError: false
2472
+ };
2473
+ try {
2474
+ const observation = __addDisposableResource(env_1, await query.observeSession(child.id, { projectionMode: "none" }), false);
2475
+ const label = foldSubagentDescriptor(observation.events.slice(observation.inheritedEventCount))?.label;
2476
+ return label === void 0 ? { id: child.id } : {
2477
+ id: child.id,
2478
+ label
2479
+ };
2480
+ } catch (e_1) {
2481
+ env_1.error = e_1;
2482
+ env_1.hasError = true;
2483
+ } finally {
2484
+ __disposeResources(env_1);
2485
+ }
2486
+ } catch {
2487
+ return { id: child.id };
2488
+ }
2489
+ }
2490
+ //#endregion
2318
2491
  //#region lib/types/projection.js
2319
2492
  /**
2320
2493
  * Pure session projections for subagent identity (mode/label) and active-turn
@@ -2322,16 +2495,18 @@ function sessionQueryCode(error) {
2322
2495
  *
2323
2496
  * @module @deepseek-ai/dsh-subagent/projection
2324
2497
  */
2325
- const activeIntervalSchema = z.object({
2326
- since: z.number().int().nonnegative(),
2327
- through: z.number().int().nonnegative()
2498
+ const activeIntervalSchema = z$1.object({
2499
+ since: z$1.number().int().nonnegative(),
2500
+ through: z$1.number().int().nonnegative()
2328
2501
  }).strict();
2329
- const projectionSchema = z.object({
2330
- settledMs: z.number().int().nonnegative(),
2331
- active: activeIntervalSchema.optional()
2332
- }).strict().transform(({ settledMs, active }) => ({
2502
+ const projectionSchema = z$1.object({
2503
+ settledMs: z$1.number().int().nonnegative(),
2504
+ active: activeIntervalSchema.optional(),
2505
+ lastTurnCompleted: z$1.boolean().optional()
2506
+ }).strict().transform(({ settledMs, active, lastTurnCompleted }) => ({
2333
2507
  settledMs,
2334
- ...active === void 0 ? {} : { active }
2508
+ ...active === void 0 ? {} : { active },
2509
+ ...lastTurnCompleted === void 0 ? {} : { lastTurnCompleted }
2335
2510
  }));
2336
2511
  /**
2337
2512
  * Fold turn boundaries around the child's own durable descriptor.
@@ -2343,27 +2518,31 @@ const projectionSchema = z.object({
2343
2518
  */
2344
2519
  const subagentTimingProjectionDefinition = {
2345
2520
  key: "subagentTiming",
2346
- stateSchema: z.object({
2347
- settledMs: z.number().int().nonnegative(),
2521
+ stateSchema: z$1.object({
2522
+ settledMs: z$1.number().int().nonnegative(),
2348
2523
  active: activeIntervalSchema.optional(),
2349
- pendingTurnStart: z.number().int().nonnegative().optional(),
2350
- descriptorSeen: z.boolean()
2524
+ pendingTurnStart: z$1.number().int().nonnegative().optional(),
2525
+ descriptorSeen: z$1.boolean(),
2526
+ lastTurnCompleted: z$1.boolean().optional()
2351
2527
  }).strict(),
2352
2528
  init: () => ({
2353
2529
  descriptorSeen: false,
2354
2530
  settledMs: 0
2355
2531
  }),
2356
2532
  apply: (state, event) => {
2357
- if (event.type === "turn/start") return state.descriptorSeen ? {
2358
- ...state,
2359
- active: {
2360
- since: event.time,
2361
- through: event.time
2362
- }
2363
- } : {
2364
- ...state,
2365
- pendingTurnStart: event.time
2366
- };
2533
+ if (event.type === "turn/start") {
2534
+ const { lastTurnCompleted: _closed, ...openState } = state;
2535
+ return state.descriptorSeen ? {
2536
+ ...openState,
2537
+ active: {
2538
+ since: event.time,
2539
+ through: event.time
2540
+ }
2541
+ } : {
2542
+ ...openState,
2543
+ pendingTurnStart: event.time
2544
+ };
2545
+ }
2367
2546
  if (event.type === "subagent/descriptor") {
2368
2547
  const activeSince = state.active?.since ?? state.pendingTurnStart;
2369
2548
  return {
@@ -2385,7 +2564,8 @@ const subagentTimingProjectionDefinition = {
2385
2564
  const { active, ...rest } = state;
2386
2565
  return {
2387
2566
  ...rest,
2388
- settledMs: state.settledMs + Math.max(0, event.time - active.since)
2567
+ settledMs: state.settledMs + Math.max(0, event.time - active.since),
2568
+ lastTurnCompleted: event.data.reason.kind === "completed"
2389
2569
  };
2390
2570
  }
2391
2571
  if (state.active === void 0) return state;
@@ -2401,22 +2581,23 @@ const subagentTimingProjectionDefinition = {
2401
2581
  viewSchema: projectionSchema,
2402
2582
  view: (state) => ({
2403
2583
  settledMs: state.settledMs,
2404
- ...state.active === void 0 ? {} : { active: state.active }
2584
+ ...state.active === void 0 ? {} : { active: state.active },
2585
+ ...state.lastTurnCompleted === void 0 ? {} : { lastTurnCompleted: state.lastTurnCompleted }
2405
2586
  })
2406
2587
  },
2407
- stateVersion: 2
2588
+ stateVersion: 3
2408
2589
  };
2409
- const identityValueSchema = z.discriminatedUnion("mode", [z.object({
2410
- mode: z.literal("one-shot"),
2411
- label: z.string().optional(),
2412
- seq: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).transform(SessionSeq)
2413
- }).strict(), z.object({
2414
- mode: z.literal("continuable"),
2415
- label: z.string(),
2416
- seq: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).transform(SessionSeq)
2590
+ const identityValueSchema = z$1.discriminatedUnion("mode", [z$1.object({
2591
+ mode: z$1.literal("one-shot"),
2592
+ label: z$1.string().optional(),
2593
+ seq: z$1.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).transform(SessionSeq)
2594
+ }).strict(), z$1.object({
2595
+ mode: z$1.literal("continuable"),
2596
+ label: z$1.string(),
2597
+ seq: z$1.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).transform(SessionSeq)
2417
2598
  }).strict()]);
2418
2599
  const identitySchema = identityValueSchema.nullable();
2419
- const identityStateSchema = z.object({ identity: identityValueSchema.optional() }).strict();
2600
+ const identityStateSchema = z$1.object({ identity: identityValueSchema.optional() }).strict();
2420
2601
  /** Interpret one `subagent/descriptor` event's identity; no value when the payload cannot be trusted. */
2421
2602
  function descriptorIdentity(event) {
2422
2603
  let descriptor;
@@ -2679,7 +2860,7 @@ function runOutcome(result) {
2679
2860
  switch (result.stopReason) {
2680
2861
  case "completed": return {
2681
2862
  status: "completed",
2682
- output: finalText(result.output)
2863
+ result: finalText(result.output)
2683
2864
  };
2684
2865
  case "aborted": return result.diagnostic === void 0 ? { status: "killed" } : {
2685
2866
  status: "failed",
@@ -2725,36 +2906,6 @@ async function settleRun(run) {
2725
2906
  }
2726
2907
  //#endregion
2727
2908
  //#region lib/types/index.js
2728
- /**
2729
- * Service Definition for the subagent capability seam (`ctx.subagents`): a named-provider registry plus a
2730
- * capability-validating asynchronous start API. Providers establish a
2731
- * child before returning its run, so fulfillment is the single publication and
2732
- * ownership-transfer boundary.
2733
- *
2734
- * Multiple providers coexist: each registers under a unique name and callers
2735
- * select one by name.
2736
- *
2737
- * This package owns the Service Definition role of the capability seam. Service Providers
2738
- * (`@deepseek-ai/dsh-subagent-spawn-in-process`, `-fork`, `-acp`) and the model-facing
2739
- * consumer (`@deepseek-ai/dsh-tool-subagent`) are separate packages.
2740
- *
2741
- * Public operations express caller intent: `start` returns one published owned
2742
- * one-shot run, `startContinuable` establishes a durable continuable child, and
2743
- * `sendMessage` steers between adjacent Agents without exposing whether a child
2744
- * is resident. Continuable children never become a {@link SubagentRun}: the
2745
- * continuation manager holds their `AgentHandle` directly and orders every turn
2746
- * through the child's own inbox, so providers contribute only the detached
2747
- * creation spec and see no handle, turn, or teardown. Child and descendant
2748
- * discovery read the live session store and optional session persistence
2749
- * directly and do not require that continuation runtime.
2750
- *
2751
- * Same-process providers are trusted typed collaborators. Requests, provider
2752
- * descriptors, results, and lifecycle payloads are borrowed immutable values;
2753
- * serialization and hostile-input validation belong at real process, worker,
2754
- * persistence, and model boundaries.
2755
- *
2756
- * @module @deepseek-ai/dsh-subagent
2757
- */
2758
2909
  var __runInitializers = function(thisArg, initializers, value) {
2759
2910
  var useValue = arguments.length > 2;
2760
2911
  for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
@@ -2797,26 +2948,13 @@ var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializ
2797
2948
  let SubagentRuntime = (() => {
2798
2949
  let _classSuper = TypertRemoteService;
2799
2950
  let _instanceExtraInitializers = [];
2800
- let _remoteExportList_decorators;
2801
2951
  let _prompt_decorators;
2802
2952
  let _interruptByParent_decorators;
2803
2953
  return class SubagentRuntime extends _classSuper {
2804
2954
  static {
2805
2955
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2806
- _remoteExportList_decorators = [Remote("list")];
2807
2956
  _prompt_decorators = [Remote("prompt")];
2808
2957
  _interruptByParent_decorators = [Remote("interruptByParent")];
2809
- __esDecorate(this, null, _remoteExportList_decorators, {
2810
- kind: "method",
2811
- name: "remoteExportList",
2812
- static: false,
2813
- private: false,
2814
- access: {
2815
- has: (obj) => "remoteExportList" in obj,
2816
- get: (obj) => obj.remoteExportList
2817
- },
2818
- metadata: _metadata
2819
- }, null, _instanceExtraInitializers);
2820
2958
  __esDecorate(this, null, _prompt_decorators, {
2821
2959
  kind: "method",
2822
2960
  name: "prompt",
@@ -2846,7 +2984,12 @@ let SubagentRuntime = (() => {
2846
2984
  value: _metadata
2847
2985
  });
2848
2986
  }
2849
- providers = (__runInitializers(this, _instanceExtraInitializers), /* @__PURE__ */ new Map());
2987
+ config = __runInitializers(this, _instanceExtraInitializers);
2988
+ static Config = z.object({
2989
+ maxDepth: z.number().step(1).min(0).max(Number.MAX_SAFE_INTEGER).default(1).volatile(),
2990
+ maxActiveSubagents: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER).default(8).volatile()
2991
+ });
2992
+ providers = /* @__PURE__ */ new Map();
2850
2993
  continuations;
2851
2994
  /**
2852
2995
  * The contained lifecycle-edge publisher. Built here because scoped dispatch
@@ -2854,14 +2997,15 @@ let SubagentRuntime = (() => {
2854
2997
  * composes into the carrier.
2855
2998
  */
2856
2999
  emitLifecycle;
2857
- constructor(ctx) {
3000
+ constructor(ctx, config) {
2858
3001
  super(ctx, "subagents");
3002
+ this.config = config;
2859
3003
  this.emitLifecycle = createLifecycleEmitter(this.ctx, (parent) => scopeTarget(this, parent));
2860
3004
  ctx.inject(["agents"], (childCtx) => {
2861
3005
  const manager = new SubagentContinuationManager(childCtx, {
2862
3006
  prepareContinuable: (name, request) => this.prepareContinuable(name, request),
2863
3007
  observeActivation: (provider, childId, parent) => this.observeActivation(provider, childId, parent)
2864
- });
3008
+ }, () => this.config.maxActiveSubagents.get());
2865
3009
  this.continuations = manager;
2866
3010
  childCtx.effect(() => () => {
2867
3011
  /* v8 ignore else -- one injected binding owns the slot until its fiber disposes. */
@@ -2869,10 +3013,26 @@ let SubagentRuntime = (() => {
2869
3013
  }, "subagents.continuationBinding()");
2870
3014
  });
2871
3015
  ctx.inject(["sessionProjections"], (projectionCtx) => {
2872
- projectionCtx.sessionProjections.register(subagentCatalogProjectionDefinition);
2873
- projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition);
2874
- projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition);
3016
+ const projections = projectionCtx.sessionProjections;
3017
+ projections.register(subagentCatalogProjectionDefinition);
3018
+ projections.register(subagentTimingProjectionDefinition);
3019
+ projections.register(subagentIdentityProjectionDefinition);
2875
3020
  });
3021
+ ctx.inject(["agents"], (agentsCtx) => {
3022
+ installSubagentArchiveAdmission(agentsCtx);
3023
+ });
3024
+ }
3025
+ /**
3026
+ * Resolve a delegation tool's depth policy against the current user setting.
3027
+ * @param configured - Explicit tool limit, or provider-managed for external delegation.
3028
+ * @returns The numeric limit, or undefined when the provider owns depth enforcement.
3029
+ */
3030
+ resolveMaxDepth(configured) {
3031
+ if (configured === "provider-managed") return void 0;
3032
+ if (configured !== void 0) return configured;
3033
+ const depth = this.config.maxDepth.get();
3034
+ assertSubagentMaxDepth(depth);
3035
+ return depth;
2876
3036
  }
2877
3037
  /**
2878
3038
  * Establish one durable continuable child and deliver its initial prompt.
@@ -2967,21 +3127,13 @@ let SubagentRuntime = (() => {
2967
3127
  await manager.drainChildren(parent, childIds);
2968
3128
  }
2969
3129
  /**
2970
- * Enumerate the parent's direct session-backed subagents without loading or
2971
- * resuming an Agent. The Session query service supplies one live-preferred
2972
- * corpus and shared point observations; the projection cache supplies
2973
- * immutable descriptor hits without opening cold logs. The registered
2974
- * `subagent` projection remains the sole mode/label classifier.
2975
- *
2976
- * Every query receives `signal`, and the listing rechecks cancellation
2977
- * around each await. Read rejections that settle
2978
- * after an abort become a stable `SubagentError` with code `CANCELLED`.
2979
- * @param parentSessionId - parent session whose direct children are listed.
2980
- * @param signal - caller-owned cancellation forwarded to Session queries
2981
- * and observed around every read await.
2982
- * @returns children and per-child diagnostics ordered by `createdAt`, then id.
2983
- * @throws {@link SubagentError} when the projection registry or the session
2984
- * store is not mounted, or the caller cancels the listing.
3130
+ * Read the parent's durable direct-child catalog without loading or resuming an Agent.
3131
+ * The service owns and releases the live-preferred Session observation.
3132
+ * @param parentSessionId - parent whose direct children are requested.
3133
+ * @param signal - cancellation forwarded to the Session query.
3134
+ * @returns catalog children in parent event order.
3135
+ * @throws {@link SubagentError} when query or catalog projection is unavailable.
3136
+ * @throws SessionQueryError when the parent cannot be read or the query is cancelled.
2985
3137
  */
2986
3138
  listChildren(parentSessionId, signal) {
2987
3139
  return listChildren(this.ctx, parentSessionId, signal);
@@ -2992,40 +3144,19 @@ let SubagentRuntime = (() => {
2992
3144
  * Agent. Ordinary sessions and one-shot children remain traversal nodes so
2993
3145
  * continuable descendants below them are discovered; each returned entry
2994
3146
  * adds its durable `parentId` and root-relative `depth`. Identity resolution,
2995
- * diagnostics, optional persistence, and cancellation follow the same
2996
- * projection-backed contract as {@link listChildren}.
3147
+ * diagnostics, optional persistence, and cancellation use the registered
3148
+ * child identity projection and complete Session corpus.
2997
3149
  * @param rootSessionId - session whose complete descendant tree is listed.
2998
3150
  * @param signal - caller-owned cancellation forwarded to persistence reads
2999
3151
  * and observed around every read await.
3000
3152
  * @returns children and per-candidate diagnostics with tree position, in
3001
3153
  * stable pre-order.
3002
- * @throws {@link SubagentError} under the same conditions as {@link listChildren}.
3154
+ * @throws {@link SubagentError} when listing dependencies are unavailable or the caller cancels.
3003
3155
  */
3004
3156
  listDescendants(rootSessionId, signal) {
3005
3157
  return listDescendants(this.ctx, rootSessionId, signal);
3006
3158
  }
3007
3159
  /**
3008
- * Remote face of {@link listChildren} for one browser: the durable listing
3009
- * plus live Agent activity and the delivery-time parent availability hint.
3010
- * Parent availability is a hint; {@link prompt} performs the authoritative
3011
- * check. Named apart from the provider-name {@link list}, which owns the
3012
- * member.
3013
- * @param parentSessionId - parent session whose direct children are listed.
3014
- * @param signal - carrier cancellation forwarded to Session queries.
3015
- * @returns the catalog view for that parent.
3016
- * @throws {RemoteError} `gateway/bad-request` for an empty parent id,
3017
- * `gateway/cancelled` for an aborted read, `subagent/projections-unavailable` when
3018
- * the deployment has no projection registry, otherwise `gateway/internal`.
3019
- */
3020
- async remoteExportList(parentSessionId, signal) {
3021
- validateControlRequest("subagent.list", { parentSessionId });
3022
- try {
3023
- return catalogView(this.ctx, parentSessionId, await this.listChildren(parentSessionId, signal));
3024
- } catch (error) {
3025
- return rejectCatalogRead(error, signal);
3026
- }
3027
- }
3028
- /**
3029
3160
  * Deliver one browser-authored message to a continuable child through the
3030
3161
  * exact live direct parent, retaining the caller-minted request identity and
3031
3162
  * validated browser zone on the accepted message. Success identifies the
@@ -3034,6 +3165,7 @@ let SubagentRuntime = (() => {
3034
3165
  * nearest step and retains the Agent loop's best-effort fallback semantics.
3035
3166
  * Image parts are admitted and persisted through the attachment store
3036
3167
  * before delivery, and the child's model must accept image input.
3168
+ * Cold resume at capacity rejects with `subagent/delivery-unavailable`.
3037
3169
  * @param request - durable address, delivery, minted identity, content, and optional browser zone.
3038
3170
  * @param signal - carrier cancellation, owning the call until inbox acceptance.
3039
3171
  * @returns the accepted message's inbox identity.