@deepseek-ai/dsh-subagent 0.1.7-alpha.2 → 0.1.7-rc.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/README.i18n.yaml CHANGED
@@ -1,6 +1,94 @@
1
- # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
- # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
- # after editing either side, bring the other along and re-record with:
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
3
+ # After editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/subagent/subagent/README.md
5
- README.md: adffd0edfdc55177afee0390c8d1c2f7fbee7999
6
- README.zh.md: 79d39ca879c8a15385e1e97c6556178b04897fca
5
+ /:
6
+ en: 384d01a27a111f49
7
+ zh: fbadc6917c3099c9
8
+ /deepseek-ai-dsh-subagent:
9
+ en: 425344cec61f5c70
10
+ zh: 48e8f2a2e3c1f418
11
+ /deepseek-ai-dsh-subagent/summary:
12
+ en: 300242b82e87aa3e
13
+ zh: a4a1319487072484
14
+ /deepseek-ai-dsh-subagent/table-of-contents:
15
+ en: d152484eb41ac6b4
16
+ zh: 09388d293f9be9cb
17
+ /deepseek-ai-dsh-subagent/use-this-package:
18
+ en: 4651aec03a1d2e21
19
+ zh: 7b6d1d604bdb1bf1
20
+ /deepseek-ai-dsh-subagent/use-this-package/enabling-delegation:
21
+ en: f66e74a5fa4e49b6
22
+ zh: 8c3a793cc29fcc1b
23
+ /deepseek-ai-dsh-subagent/use-this-package/delegation-settings:
24
+ en: 86c982223fab1a3a
25
+ zh: 3d220d8ed84eab9a
26
+ /deepseek-ai-dsh-subagent/use-this-package/continuable-capacity:
27
+ en: 8346a0de39204c1c
28
+ zh: 9dd1d926790e5e8c
29
+ /deepseek-ai-dsh-subagent/use-this-package/one-shot-and-continuable-children:
30
+ en: 10d0a7e0513bf04b
31
+ zh: 0cf2c2d81e85d7a9
32
+ /deepseek-ai-dsh-subagent/use-this-package/messaging-interrupting-and-discovering:
33
+ en: ff41ac0e770ed865
34
+ zh: 27dcf055badf217d
35
+ /deepseek-ai-dsh-subagent/use-this-package/failure-and-recovery:
36
+ en: 782aaaf8639c211c
37
+ zh: e2a873eece366e74
38
+ /deepseek-ai-dsh-subagent/understand-the-implementation:
39
+ en: 74d91b364b23f88d
40
+ zh: 19cc558105efe8df
41
+ /deepseek-ai-dsh-subagent/understand-the-implementation/design-concept:
42
+ en: 26c4eb7592b77d14
43
+ zh: c166fb6ee1a1c7d8
44
+ /deepseek-ai-dsh-subagent/understand-the-implementation/source-map:
45
+ en: d9afc0d9548afe58
46
+ zh: 0e11526b6c001dc6
47
+ /deepseek-ai-dsh-subagent/understand-the-implementation/one-shot-flow:
48
+ en: 9439bd15ee2129c9
49
+ zh: 6c275cf484efa0cf
50
+ /deepseek-ai-dsh-subagent/understand-the-implementation/continuable-flow:
51
+ en: 9703c868342826cc
52
+ zh: e300484cecf15835
53
+ /deepseek-ai-dsh-subagent/understand-the-implementation/ownership-and-invariants:
54
+ en: 7384d01be46a2f0a
55
+ zh: 83373486ad10d6d5
56
+ /deepseek-ai-dsh-subagent/further-exploration:
57
+ en: d1c1e87fc59ebfe5
58
+ zh: b7ec9b870b514911
59
+ /deepseek-ai-dsh-subagent/model-experience:
60
+ en: 215e7ba838619b7b
61
+ zh: a311da3843709f90
62
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice:
63
+ en: f7cec22ba9d3fb4f
64
+ zh: 67b1d40f9b136f71
65
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice/what-the-model-sees:
66
+ en: 44ba290ef9896de9
67
+ zh: 21d207c31228c0ce
68
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice/token-effect:
69
+ en: 45dc428c61f606f5
70
+ zh: 7e9a2587e98c8ca6
71
+ /deepseek-ai-dsh-subagent/model-experience/settlement-notice/kv-cache-effect:
72
+ en: d6b1d618083da79b
73
+ zh: 9a28942b7d53c382
74
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement:
75
+ en: dc8544657916e194
76
+ zh: b0feff0764b5d903
77
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/what-the-model-sees:
78
+ en: 61906b6a7b656eeb
79
+ zh: 2fa94349714efc9f
80
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/what-the-model-sees/the-delegation-scope-statement:
81
+ en: 960e4abc8393bcd1
82
+ zh: e125aa2bab1570d0
83
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/token-effect:
84
+ en: 4e0b922b186dc2a9
85
+ zh: 7453563417c5b9a2
86
+ /deepseek-ai-dsh-subagent/model-experience/child-delegation-scope-statement/kv-cache-effect:
87
+ en: 59e848fca82a46fb
88
+ zh: fcd6a8a2bb58609f
89
+ /deepseek-ai-dsh-subagent/known-limitations-and-deferred-work:
90
+ en: b2182809471f0780
91
+ zh: cfab217025442ae8
92
+ /deepseek-ai-dsh-subagent/known-limitations-and-deferred-work/dev-note:
93
+ en: 25cc0909348666bb
94
+ zh: 95517f12de100049
package/README.md CHANGED
@@ -60,7 +60,7 @@ One-shot children run once and settle with a single result, plus an optional str
60
60
 
61
61
  ### Messaging, interrupting, and discovering
62
62
 
63
- Every exact live Agent can use `sendMessage()` with a direct continuable child; a resident continuable child can also use it with its direct parent. A working target receives the Agent message through Steer at its nearest step; an idle target starts a turn, and only a direct child can be cold-resumed. The parent can also interrupt a running descendant or list its children at any time. A browser continuation prompt independently selects Queue or Steer and may carry image parts: the Host admits and persists each image batch through the attachment store before the child inbox accepts the message, and refuses delivery when the child's declared model does not accept image input. Direct-child discovery reads the parent-owned `subagentCatalog` projection. `listChildren(parentSessionId, signal?)` owns a live-preferred Session observation and returns the catalog asynchronously without reading child logs. It forwards cancellation and releases the observation after materialization. Materialization preserves parent event order in O(D) time for D facts. Complete descendant discovery retains the Session corpus and child identity projection; neither path loads or resumes a child Agent.
63
+ Every exact live Agent can use `sendMessage()` with a direct continuable child; a resident continuable child can also use it with its direct parent. A working target receives the Agent message through Steer at its nearest step; an idle target starts a turn, and only a direct child can be cold-resumed. The parent can also interrupt a running descendant or list its children at any time. A browser continuation prompt independently selects Queue or Steer and may carry image parts: the Host admits and persists each image batch through the attachment store before the child inbox accepts the message, and refuses delivery when the child's declared model does not accept image input. Direct-child discovery reads the parent-owned `subagentCatalog` projection. `listChildren(parentSessionId, signal?)` owns a live-preferred Session observation and returns the catalog asynchronously without reading child logs. It forwards cancellation and releases the observation after materialization. Materialization preserves parent event order in O(D) time for D facts. Descendant discovery recursively reads those child catalogs in parent event order, observing each reachable Session once. It skips branches whose catalogs cannot be read and returns diagnostics for them; neither path loads or resumes a child Agent.
64
64
 
65
65
  ### Failure and recovery
66
66
 
@@ -97,7 +97,7 @@ This section explains how the service is built and where the observable behavior
97
97
  | [`src/descriptor.ts`](src/descriptor.ts) | Versioned `subagent/descriptor` session-event vocabulary |
98
98
  | [`src/catalog.ts`](src/catalog.ts) | Parent-owned `subagent/catalog` event and chunked host projection |
99
99
  | [`src/child-agent.ts`](src/child-agent.ts) | Child composition, delegated policy, depth helpers |
100
- | [`src/list-children.ts`](src/list-children.ts) | Direct parent-catalog reads and complete descendant-corpus reads |
100
+ | [`src/list-children.ts`](src/list-children.ts) | Direct and recursive parent-catalog reads |
101
101
  | [`src/control.ts`](src/control.ts) | Browser control request validation and stable failure codes |
102
102
  | [`src/control-types.ts`](src/control-types.ts) | Client-safe catalog row, control requests, receipts, and failures |
103
103
  | [`src/archive-admission.ts`](src/archive-admission.ts) | The `subagent` family of the Workspace registry's archive admission: running descendants and their parent-cause cancel |
@@ -184,6 +184,7 @@ Prefix-stable within a child: the statement never changes during the child's lif
184
184
 
185
185
  These limits define when the seam is a poor fit or needs special operational care. They are current package constraints, not a general delegation comparison or a task backlog.
186
186
 
187
+ - **Descendant reads are sequential** — each reachable catalog, including one-shot children, takes one observation. A cold Session without a valid prepared observation requires a full-log read; large cold trees can accumulate storage latency.
187
188
  - **ACP children remain one-shot and are not trace-enumerable** — an ACP run has no local child session in the parent's session corpus, and remote providers need an Activation ownership contract before they can support continuable children.
188
189
  - **Adjacent model messaging only** — `sendMessage()` requires an exact live sender; every sender may target a direct continuable child, while only a sender with a resident continuable Activation may target its direct parent. Browser prompts use a separate human Queue-or-Steer control path.
189
190
  - **A direct parent must remain live for child-to-parent delivery** — the service has no durable parent mailbox; a missing parent rejects the message instead of accepting work it cannot wake.
package/README.zh.md CHANGED
@@ -44,7 +44,7 @@ kind: "package-reference"
44
44
 
45
45
  ### 委派设置
46
46
 
47
- **插件 → Subagent** 页面的限制部分编辑 Host 的 `subagent` 设置分节。用户值覆盖本插件的组合配置;恢复默认会删除用户覆盖。`maxDepth` 默认为 `1`,在委派工具自身未配置深度时提供默认值。工具显式指定的深度(包括 `provider-managed`)优先。深度 `0` 禁止继承此设置的工具委派;深度 `1` 只允许直接子代理。修改在下一次委派时生效。直接调用服务的调用方仍自行提供可选的请求深度。
47
+ **插件 → 子智能体**页面的限制部分编辑 Host 的 `subagent` 设置分节。用户值覆盖本插件的组合配置;恢复默认会删除用户覆盖。`maxDepth` 默认为 `1`,在委派工具自身未配置深度时提供默认值。工具显式指定的深度(包括 `provider-managed`)优先。深度 `0` 禁止继承此设置的工具委派;深度 `1` 只允许直接子代理。修改在下一次委派时生效。直接调用服务的调用方仍自行提供可选的请求深度。
48
48
 
49
49
  ### 可续接子代理容量
50
50
 
@@ -60,7 +60,7 @@ kind: "package-reference"
60
60
 
61
61
  ### 消息、中断与发现
62
62
 
63
- 每个确切在线 Agent 都可以对直接可继续 child 使用 `sendMessage()`;驻留的可继续 child 还可以对自己的直接 parent 使用它。正在工作的目标通过 Steer 在最近 step 接收 Agent 消息;空闲目标启动轮次,且只有直接 child 可以冷恢复。parent 也可以随时中断正在运行的后代或列举自己的子级。浏览器发出的继续执行 prompt 会独立选择 Queue 或 Steer,并且可以携带图片部分:Host 先通过附件存储完成整批图片的准入与持久化,子级 inbox 才接受这条消息;当子级声明的模型不接受图片输入时拒绝投递。 直接子级发现读取 parent 自有的 `subagentCatalog` projection。`listChildren(parentSessionId, signal?)` 持有一次优先实时来源的 Session 观察,异步返回目录,不读取子级日志。它转发取消信号,并在物化后释放观察。物化以 O(D) 时间保留 D 条事实的父日志事件顺序。完整后代发现保留 Session 语料库与子级身份 projection;两条路径都不加载或恢复子级 Agent。
63
+ 每个确切在线 Agent 都可以对直接可继续 child 使用 `sendMessage()`;驻留的可继续 child 还可以对自己的直接 parent 使用它。正在工作的目标通过 Steer 在最近 step 接收 Agent 消息;空闲目标启动轮次,且只有直接 child 可以冷恢复。parent 也可以随时中断正在运行的后代或列举自己的子级。浏览器发出的继续执行 prompt 会独立选择 Queue 或 Steer,并且可以携带图片部分:Host 先通过附件存储完成整批图片的准入与持久化,子级 inbox 才接受这条消息;当子级声明的模型不接受图片输入时拒绝投递。 直接子级发现读取 parent 自有的 `subagentCatalog` projection。`listChildren(parentSessionId, signal?)` 持有一次优先实时来源的 Session 观察,异步返回目录,不读取子级日志。它转发取消信号,并在物化后释放观察。物化以 O(D) 时间保留 D 条事实的父日志事件顺序。后代发现按父事件顺序递归读取子级目录,每个可达 Session 观察一次。无法读取目录的分支会被跳过,并返回诊断;两条路径都不加载或恢复子级 Agent。
64
64
 
65
65
  ### 失败与恢复
66
66
 
@@ -97,7 +97,7 @@ kind: "package-reference"
97
97
  | [`src/descriptor.ts`](src/descriptor.ts) | 版本化的 `subagent/descriptor` 会话事件词汇 |
98
98
  | [`src/catalog.ts`](src/catalog.ts) | parent 自有的 `subagent/catalog` 事件与分块 host projection |
99
99
  | [`src/child-agent.ts`](src/child-agent.ts) | 子级组装、委派策略、深度辅助函数 |
100
- | [`src/list-children.ts`](src/list-children.ts) | 直接 parent 目录读取与完整后代语料读取 |
100
+ | [`src/list-children.ts`](src/list-children.ts) | 直接与递归的 parent 目录读取 |
101
101
  | [`src/control.ts`](src/control.ts) | 浏览器控制请求校验与稳定失败分码 |
102
102
  | [`src/control-types.ts`](src/control-types.ts) | client-safe 的目录行、控制面请求、回执与失败 |
103
103
  | [`src/archive-admission.ts`](src/archive-admission.ts) | Workspace 注册表归档准入中的 `subagent` 族:运行中的子孙及其父级取消 |
@@ -184,6 +184,7 @@ You are a delegated subagent: your permission scope was fixed when you were star
184
184
 
185
185
  这些限制说明该 seam 何时不合适,或何时需要特别的运维注意。它们是当前包约束,不是通用委派对比或任务积压。
186
186
 
187
+ - **后代读取串行执行**——每个可达目录(包括一次性子级)都需要一次观察。冷 Session 缺少有效的 prepared 观察时需要读取完整日志;大型冷会话树可能累积存储延迟。
187
188
  - **ACP 子级仍为一次性,且无法通过追踪枚举**——ACP 运行在父级会话语料中没有本地子会话,远程提供方需要 Activation 所有权约定才能支持可继续子级。
188
189
  - **仅允许相邻模型消息**——`sendMessage()` 要求确切在线 sender;每个 sender 都可以指定直接可继续 child,只有具备驻留可继续 Activation 的 sender 可以指定自己的直接 parent。浏览器提示使用独立的人类 Queue 或 Steer 控制路径。
189
190
  - **child 到 parent 的投递要求直接 parent 保持在线**——服务没有持久 parent mailbox;parent 缺失时会拒绝消息,而非接受无法唤醒的工作。
package/lib/index.js CHANGED
@@ -1999,12 +1999,8 @@ var SubagentContinuationManager = class {
1999
1999
  //#endregion
2000
2000
  //#region lib/types/list-children.js
2001
2001
  /**
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.
2007
- *
2002
+ * Direct-child and recursive descendant discovery from parent-owned catalogs.
2003
+ * Each catalog read releases its Session observation before the next branch.
2008
2004
  * @module @deepseek-ai/dsh-subagent
2009
2005
  */
2010
2006
  var __addDisposableResource$1 = function(env, value, async) {
@@ -2066,12 +2062,6 @@ var __disposeResources$1 = (function(SuppressedError) {
2066
2062
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
2067
2063
  });
2068
2064
  /**
2069
- * Concurrent cold observations per explicit catalog listing. Current Session
2070
- * persistence providers are local; a networked provider must promote this to
2071
- * a validated deployment setting.
2072
- */
2073
- const COLD_READ_CONCURRENCY = 4;
2074
- /**
2075
2065
  * Read one parent's durable catalog through a live-preferred Session observation.
2076
2066
  * @param ctx - context carrying the Session query service.
2077
2067
  * @param parentSessionId - parent whose direct children are requested.
@@ -2099,241 +2089,84 @@ async function listChildren(ctx, parentSessionId, signal) {
2099
2089
  }
2100
2090
  }
2101
2091
  /**
2102
- * Enumerate every session-backed subagent below one root in stable pre-order.
2103
- * Ordinary sessions and one-shot children remain traversal nodes, so a
2104
- * continuable child below either is still discovered. Classification uses the
2105
- * registered child identity projection; no Agent is loaded or resumed.
2106
- * @see SubagentRuntime.listDescendants for the public cancellation and failure contract.
2107
- * @param ctx - context carrying the session store, projection registry, and optional persistence/cache.
2108
- * @param rootSessionId - session whose complete descendant tree is listed.
2109
- * @param signal - caller-owned cancellation observed around every persistence read.
2110
- * @returns interpreted subagents with durable direct-parent and root-relative depth.
2111
- * @throws {@link SubagentError} when listing dependencies are unavailable or the caller cancels.
2092
+ * Walk reachable parent catalogs in stable pre-order without loading Agents.
2093
+ * @see SubagentRuntime.listDescendants for failure and cancellation semantics.
2094
+ * @param ctx - context carrying the Session store and query service.
2095
+ * @param rootSessionId - parent whose catalog starts the traversal.
2096
+ * @param signal - cancellation checked around each catalog read.
2097
+ * @returns children and branch diagnostics with catalog parent and depth.
2112
2098
  */
2113
2099
  async function listDescendants(ctx, rootSessionId, signal) {
2114
- const listing = await prepareListing(ctx, signal);
2115
- const positioned = descendantCandidates(listing.corpus, rootSessionId);
2116
- const rows = await resolveCandidateRows(positioned.map((candidate) => candidate.record), listing, signal);
2117
- const entries = [];
2118
- positioned.forEach((position, index) => {
2119
- const row = rows[index];
2120
- if (row !== void 0) entries.push({
2121
- ...row,
2122
- parentId: position.parentId,
2123
- depth: position.depth
2124
- });
2125
- });
2126
- return entries;
2127
- }
2128
- /** Resolve listing services once and build one live-preferred session corpus. */
2129
- async function prepareListing(ctx, signal) {
2130
- const projections = ctx.get("sessionProjections");
2131
- if (projections === void 0) throw new SubagentError("listing subagents requires the sessionProjections registry (load @deepseek-ai/dsh-session-projection)", "SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE");
2132
2100
  const sessions = ctx.get("sessions");
2133
2101
  if (sessions === void 0) throw new SubagentError("listing subagents requires the session store (load @deepseek-ai/dsh-session)", "SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE");
2134
- assertListingNotCancelled(signal);
2135
- const query = ctx.get("sessionQuery");
2136
- if (query === void 0) throw new SubagentError("listing subagents requires the sessionQuery service (load @deepseek-ai/dsh-session-query)", "SUBAGENT_CONTROL_QUERY_UNAVAILABLE");
2137
- const cache = ctx.get("sessionProjectionCache");
2138
- let records;
2139
- try {
2140
- records = await query.listSessions(signal);
2141
- } catch (error) {
2102
+ const readChildren = async (id) => {
2142
2103
  assertListingNotCancelled(signal);
2143
- throw error;
2144
- }
2145
- assertListingNotCancelled(signal);
2146
- const corpus = /* @__PURE__ */ new Map();
2147
- for (const record of records) {
2148
- const live = sessions.get(record.header.id);
2149
- corpus.set(record.header.id, {
2150
- header: live?.header ?? record.header,
2151
- live
2152
- });
2153
- }
2154
- const subagentParents = /* @__PURE__ */ new Set();
2155
- for (const record of corpus.values()) if (record.header.origin === "subagent" && record.header.parentSession !== void 0) subagentParents.add(record.header.parentSession);
2156
- return {
2157
- projections,
2158
- query,
2159
- cache,
2160
- corpus,
2161
- subagentParents
2162
- };
2163
- }
2164
- /** Resolve projection-backed rows for aligned candidates with bounded cold reads. */
2165
- async function resolveCandidateRows(candidates, listing, signal) {
2166
- const { projections, query, cache, subagentParents } = listing;
2167
- const rows = Array.from({ length: candidates.length });
2168
- const coldReads = [];
2169
- candidates.forEach((candidate, index) => {
2170
- const childId = candidate.header.id;
2171
- if (candidate.live === void 0) {
2172
- coldReads.push({
2173
- index,
2174
- header: candidate.header
2175
- });
2176
- return;
2177
- }
2178
- let identity;
2104
+ let children;
2179
2105
  try {
2180
- identity = projections.snapshot(candidate.live, ["subagent"]).values.subagent;
2181
- } catch {
2182
- rows[index] = {
2183
- kind: "diagnostic",
2184
- id: childId,
2185
- reason: "corrupt"
2186
- };
2187
- return;
2106
+ children = await listChildren(ctx, id, signal);
2107
+ } catch (error) {
2108
+ assertListingNotCancelled(signal);
2109
+ throw error;
2188
2110
  }
2189
- if (identity === void 0 || identity === null || !candidate.live.isOwnSeq(identity.seq)) return;
2190
- rows[index] = childRow(childId, identity, "running", subagentParents.has(childId));
2191
- });
2192
- if (coldReads.length > 0) {
2193
- const queue = [...coldReads];
2194
- await Promise.all(Array.from({ length: Math.min(COLD_READ_CONCURRENCY, queue.length) }, async () => {
2195
- 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);
2196
- }));
2197
- }
2198
- assertListingNotCancelled(signal);
2199
- return rows;
2200
- }
2201
- /** Build origin-classified candidates from the complete tree without recursion. */
2202
- function descendantCandidates(corpus, rootSessionId) {
2203
- const children = /* @__PURE__ */ new Map();
2204
- for (const record of corpus.values()) {
2205
- const parentId = record.header.parentSession;
2206
- if (parentId === void 0) continue;
2207
- const siblings = children.get(parentId);
2208
- if (siblings === void 0) children.set(parentId, [record]);
2209
- else siblings.push(record);
2210
- }
2211
- for (const siblings of children.values()) siblings.sort(compareCorpusRecords);
2212
- const positioned = [];
2213
- const stack = (children.get(rootSessionId) ?? []).map((record) => ({
2214
- record,
2111
+ assertListingNotCancelled(signal);
2112
+ return children;
2113
+ };
2114
+ const stack = (await readChildren(rootSessionId)).map((entry) => ({
2115
+ entry,
2215
2116
  parentId: rootSessionId,
2216
2117
  depth: 1
2217
2118
  })).reverse();
2218
2119
  const visited = new Set([rootSessionId]);
2219
- while (stack.length > 0) {
2220
- const position = stack.pop();
2221
- const id = position.record.header.id;
2222
- if (visited.has(id)) continue;
2223
- visited.add(id);
2224
- if (position.record.header.origin === "subagent") positioned.push(position);
2225
- const descendants = children.get(id) ?? [];
2226
- for (const record of [...descendants].reverse()) stack.push({
2227
- record,
2228
- parentId: id,
2229
- depth: position.depth + 1
2230
- });
2231
- }
2232
- return positioned;
2233
- }
2234
- /** Compare siblings by durable creation time, then id. */
2235
- function compareCorpusRecords(a, b) {
2236
- return a.header.createdAt - b.header.createdAt || a.header.id.localeCompare(b.header.id);
2237
- }
2238
- /**
2239
- * Resolve one cold candidate down the remaining ladder: an unseeded durable
2240
- * projection-cache row, otherwise one shared Session observation. An absent or transiently failed
2241
- * observation is one `unavailable` row retried on the next listing; an observation
2242
- * source naming another lifecycle, and a
2243
- * settled log the fold cannot identify — or that makes any registered unit
2244
- * throw — are final, so they report `corrupt`.
2245
- */
2246
- async function resolveColdIdentity(query, cache, header, hasChildren, signal) {
2247
- const env_2 = {
2248
- stack: [],
2249
- error: void 0,
2250
- hasError: false
2251
- };
2252
- try {
2253
- const childId = header.id;
2254
- if (cache !== void 0 && !header.isSeeded) {
2255
- let cached;
2256
- try {
2257
- cached = cache.cachedSnapshot(header, ["subagent"])?.values.subagent;
2258
- } catch {
2259
- cached = void 0;
2260
- }
2261
- if (cached !== void 0 && cached !== null) return childRow(childId, cached, "inactive", hasChildren);
2262
- }
2263
- assertListingNotCancelled(signal);
2264
- let observation;
2120
+ const result = [];
2121
+ for (let position = stack.pop(); position !== void 0; position = stack.pop()) {
2122
+ const { entry, parentId, depth } = position;
2123
+ if (visited.has(entry.id)) continue;
2124
+ visited.add(entry.id);
2125
+ let children;
2265
2126
  try {
2266
- observation = await query.observeSession(childId, { ...signal === void 0 ? {} : { signal } });
2127
+ children = await readChildren(entry.id);
2267
2128
  } catch (error) {
2268
- assertListingNotCancelled(signal);
2269
- return {
2129
+ if (error instanceof SubagentError) throw error;
2130
+ const code = error instanceof Error && "code" in error ? error.code : void 0;
2131
+ result.push({
2270
2132
  kind: "diagnostic",
2271
- id: childId,
2272
- reason: sessionQueryCode(error) === "SESSION_QUERY_CORRUPT_SESSION" || sessionQueryCode(error) === "SESSION_QUERY_SOURCE_CONFLICT" ? "corrupt" : "unavailable"
2273
- };
2133
+ id: entry.id,
2134
+ parentId,
2135
+ depth,
2136
+ reason: code === "SESSION_QUERY_CORRUPT_SESSION" || code === "SESSION_QUERY_SOURCE_CONFLICT" ? "corrupt" : "unavailable"
2137
+ });
2138
+ continue;
2274
2139
  }
2275
- const ownedObservation = __addDisposableResource$1(env_2, observation, false);
2276
- assertListingNotCancelled(signal);
2277
- if (!sameLifecycle(ownedObservation.header, header)) return {
2278
- kind: "diagnostic",
2279
- id: childId,
2280
- reason: "corrupt"
2281
- };
2282
- const identity = ownedObservation.projections?.values.subagent;
2283
- if (identity === void 0 || identity === null || identity.seq < ownedObservation.inheritedEventCount) return {
2140
+ if (entry.mode === "unknown") result.push({
2284
2141
  kind: "diagnostic",
2285
- id: childId,
2286
- reason: "corrupt"
2287
- };
2288
- return childRow(childId, identity, "inactive", hasChildren);
2289
- } catch (e_2) {
2290
- env_2.error = e_2;
2291
- env_2.hasError = true;
2292
- } finally {
2293
- __disposeResources$1(env_2);
2142
+ id: entry.id,
2143
+ parentId,
2144
+ depth,
2145
+ reason: "unsupported"
2146
+ });
2147
+ else {
2148
+ const { createdAt: _createdAt, ...identity } = entry;
2149
+ result.push({
2150
+ ...identity,
2151
+ kind: "child",
2152
+ parentId,
2153
+ depth,
2154
+ activity: sessions.get(entry.id) === void 0 ? "inactive" : "running",
2155
+ hasChildren: children.length > 0
2156
+ });
2157
+ }
2158
+ for (const child of [...children].reverse()) stack.push({
2159
+ entry: child,
2160
+ parentId: entry.id,
2161
+ depth: depth + 1
2162
+ });
2294
2163
  }
2164
+ return result;
2295
2165
  }
2296
- /** Materialize one served identity as its child row. */
2297
- function childRow(id, identity, activity, hasChildren) {
2298
- return identity.mode === "one-shot" ? {
2299
- kind: "child",
2300
- id,
2301
- mode: "one-shot",
2302
- ...identity.label !== void 0 ? { label: identity.label } : {},
2303
- activity,
2304
- hasChildren
2305
- } : {
2306
- kind: "child",
2307
- id,
2308
- mode: "continuable",
2309
- label: identity.label,
2310
- activity,
2311
- hasChildren
2312
- };
2313
- }
2314
- /** Immutable header fields that distinguish one session lifecycle from another under the same id. */
2315
- const LIFECYCLE_WITNESS_KEYS = [
2316
- "version",
2317
- "id",
2318
- "createdAt",
2319
- "cwd",
2320
- "parentSession",
2321
- "isSeeded",
2322
- "delegationDepth",
2323
- "origin",
2324
- "agentPreset"
2325
- ];
2326
- /** Whether an inspected log still belongs to the enumerated lifecycle. */
2327
- function sameLifecycle(meta, expected) {
2328
- return LIFECYCLE_WITNESS_KEYS.every((key) => meta[key] === expected[key]);
2329
- }
2330
- /** Stop a listing at its next cancellation checkpoint. */
2166
+ /** Stop the complete traversal when its caller cancels. */
2331
2167
  function assertListingNotCancelled(signal) {
2332
2168
  if (signal?.aborted) throw new SubagentError("subagent listing was cancelled", "CANCELLED");
2333
2169
  }
2334
- function sessionQueryCode(error) {
2335
- return error instanceof Error && "code" in error ? error.code : void 0;
2336
- }
2337
2170
  //#endregion
2338
2171
  //#region lib/types/archive-admission.js
2339
2172
  /**
@@ -3139,19 +2972,19 @@ let SubagentRuntime = (() => {
3139
2972
  return listChildren(this.ctx, parentSessionId, signal);
3140
2973
  }
3141
2974
  /**
3142
- * Enumerate the root's complete session-backed subagent tree in stable
3143
- * pre-order from one live-preferred corpus, without loading or resuming an
3144
- * Agent. Ordinary sessions and one-shot children remain traversal nodes so
3145
- * continuable descendants below them are discovered; each returned entry
3146
- * adds its durable `parentId` and root-relative `depth`. Identity resolution,
3147
- * diagnostics, optional persistence, and cancellation use the registered
3148
- * child identity projection and complete Session corpus.
3149
- * @param rootSessionId - session whose complete descendant tree is listed.
3150
- * @param signal - caller-owned cancellation forwarded to persistence reads
3151
- * and observed around every read await.
3152
- * @returns children and per-candidate diagnostics with tree position, in
3153
- * stable pre-order.
2975
+ * Recursively list reachable parent catalogs in stable pre-order, preserving
2976
+ * each catalog's event order. Each row carries its catalog parent and depth;
2977
+ * one-shot and unknown-mode children remain traversal nodes. Unknown modes
2978
+ * produce unsupported diagnostics. Unreadable child catalogs produce corrupt
2979
+ * or unavailable diagnostics and stop only that branch. Root read failures,
2980
+ * missing services or projections, and cancellation reject the whole listing.
2981
+ * Each catalog is observed once and released before the next read. No Agent
2982
+ * is loaded or resumed; Sessions absent from reachable catalogs are omitted.
2983
+ * @param rootSessionId - session whose catalog starts descendant discovery.
2984
+ * @param signal - cancellation forwarded to and checked around each catalog read.
2985
+ * @returns children and branch diagnostics in parent-catalog pre-order.
3154
2986
  * @throws {@link SubagentError} when listing dependencies are unavailable or the caller cancels.
2987
+ * @throws SessionQueryError when the root catalog cannot be read.
3155
2988
  */
3156
2989
  listDescendants(rootSessionId, signal) {
3157
2990
  return listDescendants(this.ctx, rootSessionId, signal);