@deepseek-ai/dsh-subagent 0.1.5-alpha.1 → 0.1.5-rc.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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
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: 6b58f36fcd4d6e8a198ddc86e80ccc28491a0a34
6
- README.zh.md: be99e7c91f13c6d83a6375047ec5f21d55b21053
5
+ README.md: 5f9668fd7a14cdfca33ab72a217c07372a24502f
6
+ README.zh.md: 563ed06237088c4bc250ca3c4f5a863b6ffe8239
package/README.md CHANGED
@@ -96,6 +96,8 @@ A request is validated against the provider's advertised capabilities, a durable
96
96
 
97
97
  The manager reserves a child identity, resolves the durable descriptor, creates (or cold-resumes) the child Agent, installs it in an Activation, and submits the prompt. Model-authored messages cross one parent/child edge through fixed Steer scheduling; browser human prompts choose Queue or best-effort Steer through an internal adapter, while other host protocols may retain Queue for distinct turns. A Session queue command admits a live subagent-owned Agent only from its own continuable descriptor. Settlement waits for Agent activity to finish, an empty Inbox, and no owned children, then flushes final Session state with admission open. Under the child lock, the manager revalidates the wake generation, Session sequence, Inbox, and owned children; the synchronous task entry of `Agent.runMaintenance()` claims the idle phase and closes the private subagent Inbox in the same JavaScript turn before handle disposal. An absent direct-child Activation cold-resumes from the persisted session. When a resident Activation settles, the manager tells the child's direct parent in the parent's own turn stream.
98
98
 
99
+ Successful local child creation appends a `subagent/catalog` fact to the parent Session. One-shot creation records it after the provider returns; continuable creation records it after initial inbox admission and before returning the child id. Failure releases the child without publishing a compensating catalog event. A one-shot catalog append failure handles the run’s result rejection and preserves the catalog error; disposal failures are logged separately. The `subagentCatalog` projection excludes fork-inherited facts and exposes a direct-child list through `projections.values.subagentCatalog` in Session observations and client snapshots. Invalid own catalog payloads, including unsupported versions, reject projection restoration. Its immutable storage and checkpoint validation use [`dsh-chunked-list`](../../util/chunked-list/README.md). Its view preserves parent catalog event order in O(D) time for D facts. [The parent-catalog decision](../../../.agents/notes/implemented/architecture/2026-09-01-parent-owned-subagent-catalog.md) owns ordering, persistence costs, and alternatives.
100
+
99
101
  ### Ownership and invariants
100
102
 
101
103
  - **Publication is the boundary** — before it the provider owns the setup and must roll back on failure; after it the caller owns the run and must dispose it.
package/README.zh.md CHANGED
@@ -96,6 +96,8 @@ kind: "package-reference"
96
96
 
97
97
  管理器预留 child 身份、解析持久化描述符、创建(或冷恢复)child、把它安装进 Activation 并提交提示词。模型编写的消息通过固定 Steer 调度跨一条 parent/child 边;浏览器人类 prompt 通过内部适配器选择 Queue 或 best-effort Steer,其他 host 协议仍可保留 Queue 以创建独立轮次。Session queue command 仅根据 child 自身的 continuable descriptor 准入在线 subagent-owned Agent。Settlement 会等待 Agent 活动结束、Inbox 为空且没有所拥有子级,再在准入开放时 flush 最终 Session 状态。管理器随后在 child lock 内重新验证 wake generation、Session 序号、Inbox 与所拥有子级;`Agent.runMaintenance()` 的同步 task 入口会占用 idle 阶段,并在同一个 JavaScript turn 内关闭私有 subagent Inbox,然后才 dispose handle。直接 child 不存在 Activation 时会从持久化会话冷恢复。当驻留 Activation 结算时,管理器会在 parent 自身的轮次流中告知该 child 的直接 parent。
98
98
 
99
+ 本地子级创建成功时,父 Session 追加一条 `subagent/catalog` 事实。一次性创建在 provider 返回后记录;可继续创建在初始 inbox 准入后、返回子级 id 前记录。失败会释放子级,不发布补偿性目录事件。一次性目录追加失败时会处理 run 的结果拒绝,并保留目录错误;资源释放失败会单独记录。`subagentCatalog` projection 排除 fork 继承的事实,通过 Session 观察和客户端快照中的 `projections.values.subagentCatalog` 暴露直接子级列表。无效的自身 catalog payload(包括不支持的版本)会使 projection 恢复失败。其不可变存储和检查点校验使用 [`dsh-chunked-list`](../../util/chunked-list/README.zh.md)。其视图对 D 条事实以 O(D) 时间保留父目录事件顺序。[父目录决策](../../../.agents/notes/implemented/architecture/2026-09-01-parent-owned-subagent-catalog.zh.md) 说明排序、持久化成本和替代方案。
100
+
99
101
  ### 所有权与不变式
100
102
 
101
103
  - **发布即边界**——发布前提供方拥有设置并须在失败时回滚;发布后调用方拥有运行并须 dispose(资源释放)它。
package/lib/index.js CHANGED
@@ -10,6 +10,7 @@ import { foldConsumedWork } from "@deepseek-ai/dsh-agent";
10
10
  import { SessionLogOffset, SessionSeq } from "@deepseek-ai/dsh-session";
11
11
  import { brandString } from "@deepseek-ai/dsh-brand";
12
12
  import { snapshotJsonValue } from "@deepseek-ai/dsh-util-values";
13
+ import { appendChunkedList, chunkedListSchema, iterateChunkedList } from "@deepseek-ai/dsh-chunked-list";
13
14
  import { accessSync, constants, statSync } from "node:fs";
14
15
  import { isAbsolute, resolve } from "node:path";
15
16
  //#region lib/types/error.js
@@ -1004,7 +1005,6 @@ var ContinuableActivationRegistry = class {
1004
1005
  } finally {
1005
1006
  this.wake(activation);
1006
1007
  }
1007
- activation.announced = true;
1008
1008
  return message.id;
1009
1009
  }
1010
1010
  /**
@@ -1427,6 +1427,100 @@ function foldSubagentDescriptor(events) {
1427
1427
  if (event === void 0) return void 0;
1428
1428
  return parseSubagentDescriptor(event.data);
1429
1429
  }
1430
+ const sessionIdSchema = z.string();
1431
+ const oneShotCatalogSchema = z.object({
1432
+ version: z.literal(0),
1433
+ childId: sessionIdSchema,
1434
+ childCreatedAt: z.number().int().nonnegative(),
1435
+ mode: z.literal("one-shot"),
1436
+ label: z.string().optional()
1437
+ }).strict();
1438
+ const continuableCatalogSchema = z.object({
1439
+ version: z.literal(0),
1440
+ childId: sessionIdSchema,
1441
+ childCreatedAt: z.number().int().nonnegative(),
1442
+ mode: z.literal("continuable"),
1443
+ label: z.string()
1444
+ }).strict();
1445
+ const eventDataSchema = z.union([oneShotCatalogSchema, continuableCatalogSchema]);
1446
+ const viewSchema = z.array(z.union([oneShotCatalogSchema.omit({
1447
+ version: true,
1448
+ childId: true,
1449
+ childCreatedAt: true
1450
+ }).extend({
1451
+ id: sessionIdSchema,
1452
+ createdAt: oneShotCatalogSchema.shape.childCreatedAt
1453
+ }), continuableCatalogSchema.omit({
1454
+ version: true,
1455
+ childId: true,
1456
+ childCreatedAt: true
1457
+ }).extend({
1458
+ id: sessionIdSchema,
1459
+ createdAt: continuableCatalogSchema.shape.childCreatedAt
1460
+ })]));
1461
+ const stateSchema = z.object({
1462
+ inheritedEventCount: z.number().int().nonnegative(),
1463
+ head: chunkedListSchema(eventDataSchema).optional()
1464
+ }).strict();
1465
+ /**
1466
+ * Materialize direct children from their parent's successful creation facts.
1467
+ * @param state - parent catalog fold state.
1468
+ * @returns current direct-child rows in parent catalog event order.
1469
+ */
1470
+ function subagentCatalogEntries(state) {
1471
+ const entries = [];
1472
+ for (const data of iterateChunkedList(state.head)) entries.push(data.mode === "one-shot" ? {
1473
+ id: data.childId,
1474
+ createdAt: data.childCreatedAt,
1475
+ mode: data.mode,
1476
+ ...data.label === void 0 ? {} : { label: data.label }
1477
+ } : {
1478
+ id: data.childId,
1479
+ createdAt: data.childCreatedAt,
1480
+ mode: data.mode,
1481
+ label: data.label
1482
+ });
1483
+ return entries;
1484
+ }
1485
+ /** Parent-owned direct-child catalog projection; invalid own facts reject restoration. */
1486
+ const subagentCatalogProjectionDefinition = {
1487
+ key: "subagentCatalog",
1488
+ stateSchema,
1489
+ init: (_header, inheritedEventCount) => ({ inheritedEventCount }),
1490
+ apply: (state, event) => {
1491
+ if (event.type !== "subagent/catalog" || event.seq < state.inheritedEventCount) return state;
1492
+ return {
1493
+ ...state,
1494
+ head: appendChunkedList(state.head, eventDataSchema.parse(event.data))
1495
+ };
1496
+ },
1497
+ stateVersion: 2,
1498
+ wire: {
1499
+ viewSchema,
1500
+ view: subagentCatalogEntries
1501
+ }
1502
+ };
1503
+ /**
1504
+ * Append a complete direct-child discovery fact to its parent Session.
1505
+ * @param parent - durable direct parent receiving the discovery fact.
1506
+ * @param child - established child's immutable Session metadata.
1507
+ * @param descriptor - mode-discriminated creation label frozen with the child.
1508
+ */
1509
+ function establishCatalogChild(parent, child, descriptor) {
1510
+ parent.append("subagent/catalog", descriptor.mode === "one-shot" ? {
1511
+ version: 0,
1512
+ childId: child.id,
1513
+ childCreatedAt: child.createdAt,
1514
+ mode: descriptor.mode,
1515
+ ...descriptor.label === void 0 ? {} : { label: descriptor.label }
1516
+ } : {
1517
+ version: 0,
1518
+ childId: child.id,
1519
+ childCreatedAt: child.createdAt,
1520
+ mode: descriptor.mode,
1521
+ label: descriptor.label
1522
+ });
1523
+ }
1430
1524
  //#endregion
1431
1525
  //#region lib/types/internal.js
1432
1526
  /**
@@ -1612,11 +1706,14 @@ var SubagentContinuationManager = class {
1612
1706
  },
1613
1707
  signal: spec.signal
1614
1708
  });
1615
- return this.submitMaterialized(activation, isAdjacentAgentSendMessageTool(this.ctx.get("tools")?.get("send_message", activation.handle.agent)) ? withContinuableReturnGuidance(parent.id, request.prompt) : request.prompt, {
1709
+ const childHeader = activation.handle.agent.session.header;
1710
+ return await this.submitMaterialized(activation, isAdjacentAgentSendMessageTool(this.ctx.get("tools")?.get("send_message", activation.handle.agent)) ? withContinuableReturnGuidance(parent.id, request.prompt) : request.prompt, {
1616
1711
  source: { kind: "user" },
1617
1712
  signal: spec.signal,
1618
1713
  delivery: "queue"
1619
- }, parent);
1714
+ }, parent, () => {
1715
+ establishCatalogChild(parent.session, childHeader, descriptor);
1716
+ });
1620
1717
  })
1621
1718
  };
1622
1719
  } catch (error) {
@@ -1708,7 +1805,9 @@ var SubagentContinuationManager = class {
1708
1805
  return;
1709
1806
  }
1710
1807
  }
1711
- return this.submitAdmitted(activation, content, options, parent);
1808
+ const messageId = this.submitAdmitted(activation, content, options, parent);
1809
+ activation.announced = true;
1810
+ return messageId;
1712
1811
  });
1713
1812
  /* v8 ignore start -- only a delivery that lost the disposal cutoff retries. */
1714
1813
  if (live !== void 0) return live;
@@ -1818,18 +1917,23 @@ var SubagentContinuationManager = class {
1818
1917
  __disposeResources$1(env_1);
1819
1918
  }
1820
1919
  }
1821
- /** Submit to a freshly materialized Activation or roll it back completely. */
1822
- async submitMaterialized(activation, content, options, parent) {
1920
+ /** Admit a materialized child, commit its creation fact, and release it on failure. */
1921
+ async submitMaterialized(activation, content, options, parent, commit) {
1823
1922
  try {
1824
1923
  if (contentHasImage(content)) {
1825
1924
  await this.assertImageCapable(activation.handle.agent, options.signal);
1826
1925
  if (activation.inbox.closing !== void 0) throw new SubagentError(`subagent "${activation.childId}" is closing`, "ACTIVATION_CLOSING");
1827
1926
  }
1828
- return this.submitAdmitted(activation, content, options, parent);
1927
+ const messageId = this.submitAdmitted(activation, content, options, parent);
1928
+ commit?.();
1929
+ activation.announced = true;
1930
+ return messageId;
1829
1931
  } catch (error) {
1830
- /* v8 ignore next -- rollback disposal failures must not mask the
1831
- * pre-acceptance signal, drain, or lifecycle failure. */
1832
- await this.activations.dispose(activation).catch(() => void 0);
1932
+ try {
1933
+ await this.activations.dispose(activation);
1934
+ } catch (cleanupError) {
1935
+ this.ctx.logger.warn(`subagent continuation: disposal after admission or catalog append failure also failed: ${String(cleanupError)}`);
1936
+ }
1833
1937
  throw error;
1834
1938
  }
1835
1939
  }
@@ -2760,6 +2864,7 @@ let SubagentRuntime = (() => {
2760
2864
  }, "subagents.continuationBinding()");
2761
2865
  });
2762
2866
  ctx.inject(["sessionProjections"], (projectionCtx) => {
2867
+ projectionCtx.sessionProjections.register(subagentCatalogProjectionDefinition);
2763
2868
  projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition);
2764
2869
  projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition);
2765
2870
  });
@@ -3031,6 +3136,8 @@ let SubagentRuntime = (() => {
3031
3136
  * fulfills; a rejection therefore has no run for the caller to dispose and
3032
3137
  * emits no run lifecycle events. Post-publication turn and infrastructure
3033
3138
  * failures settle through the returned run.
3139
+ * A catalog append failure disposes the run and handles its result rejection;
3140
+ * the caller receives the catalog error even if disposal also fails.
3034
3141
  * @param name - the provider to use.
3035
3142
  * @param request - child label, prompt, parent, signal, and optional capabilities.
3036
3143
  * @returns the published holder-owned run.
@@ -3049,7 +3156,20 @@ let SubagentRuntime = (() => {
3049
3156
  ...request,
3050
3157
  descriptor
3051
3158
  };
3052
- return observeRun(this.emitLifecycle, name, request.parent, await provider.start(resolved));
3159
+ const run = await provider.start(resolved);
3160
+ const child = run.localAgent?.session;
3161
+ if (child !== void 0) try {
3162
+ establishCatalogChild(request.parent.session, child.header, descriptor);
3163
+ } catch (error) {
3164
+ run.result.catch(() => void 0);
3165
+ try {
3166
+ await run.dispose();
3167
+ } catch (cleanupError) {
3168
+ this.ctx.logger.warn(`subagent: disposal after catalog append failure also failed: ${String(cleanupError)}`);
3169
+ }
3170
+ throw error;
3171
+ }
3172
+ return observeRun(this.emitLifecycle, name, request.parent, run);
3053
3173
  }
3054
3174
  /**
3055
3175
  * Resolve one provider's detached continuable-creation contribution. Method
@@ -102,7 +102,7 @@ export const TYPERT = {
102
102
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentInterruptReceipt',
103
103
  schema: _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema,
104
104
  },
105
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":477,"column":3},
105
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":480,"column":3},
106
106
  },
107
107
  {
108
108
  id: '@deepseek-ai/dsh-subagent#subagents/list',
@@ -129,7 +129,7 @@ export const TYPERT = {
129
129
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentCatalog',
130
130
  schema: _deepseek_ai_dsh_subagent_subagents_list_result$schema,
131
131
  },
132
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":383,"column":9},
132
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":386,"column":9},
133
133
  },
134
134
  {
135
135
  id: '@deepseek-ai/dsh-subagent#subagents/prompt',
@@ -155,7 +155,7 @@ export const TYPERT = {
155
155
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptReceipt',
156
156
  schema: _deepseek_ai_dsh_subagent_subagents_prompt_result$schema,
157
157
  },
158
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":410,"column":9},
158
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":413,"column":9},
159
159
  },
160
160
  ],
161
161
  model: {
@@ -264,7 +264,7 @@ export const TYPERT = {
264
264
  "name": "start",
265
265
  "signature": "async start(name: string, request: SubagentStartRequest): Promise<SubagentRun>",
266
266
  "summary": "Establish a published child on the named provider.",
267
- "jsDoc": "/**\n * Establish a published child on the named provider. Capability and semantic\n * checks run before delegation. Provider ownership lasts until its promise\n * fulfills; a rejection therefore has no run for the caller to dispose and\n * emits no run lifecycle events. Post-publication turn and infrastructure\n * failures settle through the returned run.\n * @param name - the provider to use.\n * @param request - child label, prompt, parent, signal, and optional capabilities.\n * @returns the published holder-owned run.\n */"
267
+ "jsDoc": "/**\n * Establish a published child on the named provider. Capability and semantic\n * checks run before delegation. Provider ownership lasts until its promise\n * fulfills; a rejection therefore has no run for the caller to dispose and\n * emits no run lifecycle events. Post-publication turn and infrastructure\n * failures settle through the returned run.\n * A catalog append failure disposes the run and handles its result rejection;\n * the caller receives the catalog error even if disposal also fails.\n * @param name - the provider to use.\n * @param request - child label, prompt, parent, signal, and optional capabilities.\n * @returns the published holder-owned run.\n */"
268
268
  }
269
269
  ],
270
270
  "types": [
@@ -388,6 +388,14 @@ export const TYPERT = {
388
388
  "name": "EpochHeader",
389
389
  "declaration": "export interface EpochHeader {\n config: LlmCallConfig;\n adapterDefaults?: LlmCallConfigAdapterDefaults;\n tools?: ToolSchema[];\n}"
390
390
  },
391
+ {
392
+ "name": "FeedbackCategory",
393
+ "declaration": "export type FeedbackCategory = 'task-result' | 'instruction-following' | 'product-interaction' | 'service-stability' | 'resource-cost' | 'security-privacy-permission' | 'other';"
394
+ },
395
+ {
396
+ "name": "FeedbackRecord",
397
+ "declaration": "export interface FeedbackRecord {\n readonly text?: string;\n readonly category?: FeedbackCategory;\n}"
398
+ },
391
399
  {
392
400
  "name": "FileAttachmentRef",
393
401
  "declaration": "export interface FileAttachmentRef {\n attachmentId: AttachmentId;\n name: string;\n bytes: number;\n}"
@@ -502,7 +510,7 @@ export const TYPERT = {
502
510
  },
503
511
  {
504
512
  "name": "MessageFeedbackItem",
505
- "declaration": "export interface MessageFeedbackItem {\n readonly messageId: MessageId;\n readonly rating: MessageFeedbackRating;\n readonly note?: string;\n readonly version: MessageFeedbackVersion;\n readonly createdAt: number;\n readonly updatedAt: number;\n}"
513
+ "declaration": "export interface MessageFeedbackItem {\n readonly messageId: MessageId;\n readonly rating: MessageFeedbackRating;\n readonly note?: string;\n readonly category?: FeedbackCategory;\n readonly version: MessageFeedbackVersion;\n readonly createdAt: number;\n readonly updatedAt: number;\n}"
506
514
  },
507
515
  {
508
516
  "name": "MessageFeedbackPut",
@@ -602,7 +610,7 @@ export const TYPERT = {
602
610
  },
603
611
  {
604
612
  "name": "SessionEventMap",
605
- "declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'system/message': { turn: number; step: number; message: SystemMessage; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; stream: AssistantStreamRecord[]; usage?: TokenUsage; interrupted?: true; };\n 'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[]; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': { inherited?: true; };\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/ptc-dispatch-start': PtcDispatchStartEventData;\n 'tool/ptc-dispatch': PtcDispatchEventData;\n 'agent-preset/selected': { agentPreset: string; };\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'model/selection': ModelSelection;\n 'subagent/descriptor': SubagentDescriptorData;\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'team/member': { version: 2; teamId: TeamId; member: TeamMemberSnapshot; };\n 'team/task': { version: 2; teamId: TeamId; task: TeamTaskSnapshot; };\n 'team/message/queued': { version: 2; teamId: TeamId; message: TeamMessageSnapshot; };\n 'team/message/delivered': { version: 2; teamId: TeamId; messageId: TeamMessageId; targetId: SessionId; };\n 'goal/change': GoalChangeMeta;\n 'feedback/message-put': MessageFeedbackPut;\n 'feedback/message-delete': MessageFeedbackDelete;\n 'compaction/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; };\n 'compaction/summary': { compactionId: CompactionId; sourceCommandId?: CommandId; summary: ContentBlock[]; shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; provider: string; model: string; maxTokens?: number; usage?: TokenUsage; } & ({ rawOutput: ContentBlock[]; llmStreamCall: true; } | { rawOutput?: ContentBlock[]; llmStreamCall?: never; });\n 'compaction/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string; };\n 'compaction/prune': { shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; };\n}"
613
+ "declaration": "export interface SessionEventMap {\n 'turn/start': { turn: number; };\n 'turn/end': { turn: number; reason: TurnEndReason; };\n 'step/start': { turn: number; step: number; };\n 'step/end': { turn: number; step: number; };\n 'user/message': UserMessage;\n 'system/message': { turn: number; step: number; message: SystemMessage; };\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; stream: AssistantStreamRecord[]; usage?: TokenUsage; interrupted?: true; };\n 'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[]; };\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string; };\n 'tool/result': { turn: number; step: number; message: ToolResultMessage; error?: { name: string; code: string; }; meta?: JsonValue; };\n 'request/header': { header: EpochHeader; reason: RequestHeaderReason; startsSeries?: true; };\n 'request/context': RequestContext;\n 'session/end-seed': { inherited?: true; };\n 'agent/inbox/spliced': { target: InboxTarget; start: number; removedCount?: number; inserted: UserMessage[]; outcome?: 'canceled'; };\n 'approval/asked': { id: ApprovalRequestId; toolName: string; callId?: ToolCallId; reason?: string; };\n 'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome; };\n 'approval/policy': { policy: ApprovalPolicy; source?: 'delegation'; };\n 'tool/ptc-dispatch-start': PtcDispatchStartEventData;\n 'tool/ptc-dispatch': PtcDispatchEventData;\n 'agent-preset/selected': { agentPreset: string; };\n 'command/run': { commandId: CommandId; name: string; args?: string; source: CommandSource; };\n 'command/done': { commandId: CommandId; kind: 'success' | 'error'; text?: string; sourceEventSeq?: import('@deepseek-ai/dsh-session/types').SessionSeq; };\n 'session/title': SessionTitleEventData;\n 'todo/write': { todos: TodoItem[]; };\n 'model/selection': ModelSelection;\n 'subagent/descriptor': SubagentDescriptorData;\n 'sandbox/mode': { mode: SandboxMode; source?: 'delegation'; };\n 'subagent/catalog': SubagentCatalogEvent;\n 'feedback/record': FeedbackRecord;\n 'team/member': { version: 2; teamId: TeamId; member: TeamMemberSnapshot; };\n 'team/task': { version: 2; teamId: TeamId; task: TeamTaskSnapshot; };\n 'team/message/queued': { version: 2; teamId: TeamId; message: TeamMessageSnapshot; };\n 'team/message/delivered': { version: 2; teamId: TeamId; messageId: TeamMessageId; targetId: SessionId; };\n 'goal/change': GoalChangeMeta;\n 'feedback/message-put': MessageFeedbackPut;\n 'feedback/message-delete': MessageFeedbackDelete;\n 'compaction/start': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; };\n 'compaction/summary': { compactionId: CompactionId; sourceCommandId?: CommandId; summary: ContentBlock[]; shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; provider: string; model: string; maxTokens?: number; usage?: TokenUsage; } & ({ rawOutput: ContentBlock[]; llmStreamCall: true; } | { rawOutput?: ContentBlock[]; llmStreamCall?: never; });\n 'compaction/end': { compactionId: CompactionId; sourceCommandId?: CommandId; turn: number | null; error?: string; };\n 'compaction/prune': { shadowedRange: { start: SessionSeq; end: SessionSeq; }; shadowedSeqs: SessionSeq[]; shadowedTokenCount: number; };\n}"
606
614
  },
607
615
  {
608
616
  "name": "SessionEventType",
@@ -668,6 +676,10 @@ export const TYPERT = {
668
676
  "name": "SubagentCatalog",
669
677
  "declaration": "export interface SubagentCatalog {\n readonly entries: readonly SubagentListEntry[];\n readonly parentAvailable: boolean;\n}"
670
678
  },
679
+ {
680
+ "name": "SubagentCatalogEvent",
681
+ "declaration": "export type SubagentCatalogEvent = { readonly version: 0; readonly childId: SessionId; readonly childCreatedAt: number; } & ({ readonly mode: 'one-shot'; readonly label?: string; } | { readonly mode: 'continuable'; readonly label: string; });"
682
+ },
671
683
  {
672
684
  "name": "SubagentDescendantListEntry",
673
685
  "declaration": "export type SubagentDescendantListEntry = SubagentListEntry & { readonly parentId: SessionId; readonly depth: number; };"
@@ -99,7 +99,7 @@ export const TYPERT_REMOTE = {
99
99
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentInterruptReceipt',
100
100
  schema: _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema,
101
101
  },
102
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":477,"column":3},
102
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":480,"column":3},
103
103
  },
104
104
  {
105
105
  id: '@deepseek-ai/dsh-subagent#subagents/list',
@@ -126,7 +126,7 @@ export const TYPERT_REMOTE = {
126
126
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentCatalog',
127
127
  schema: _deepseek_ai_dsh_subagent_subagents_list_result$schema,
128
128
  },
129
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":383,"column":9},
129
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":386,"column":9},
130
130
  },
131
131
  {
132
132
  id: '@deepseek-ai/dsh-subagent#subagents/prompt',
@@ -152,7 +152,7 @@ export const TYPERT_REMOTE = {
152
152
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptReceipt',
153
153
  schema: _deepseek_ai_dsh_subagent_subagents_prompt_result$schema,
154
154
  },
155
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":410,"column":9},
155
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":413,"column":9},
156
156
  },
157
157
  ],
158
158
  }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Parent-owned durable subagent catalog events and their chunked projection.
3
+ *
4
+ * @module @deepseek-ai/dsh-subagent/catalog
5
+ */
6
+ import { z } from 'zod';
7
+ import type { ChunkedList } from '@deepseek-ai/dsh-chunked-list';
8
+ import type { Session, SessionEvent, SessionHeader, SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session';
9
+ import type { SubagentCatalogEntry } from './projection-types.ts';
10
+ /** Current payload version for `subagent/catalog` events. */
11
+ export declare const SUBAGENT_CATALOG_VERSION = 0;
12
+ /** One complete parent-owned catalog fact. */
13
+ export type SubagentCatalogEvent = {
14
+ readonly version: 0;
15
+ readonly childId: SessionId;
16
+ readonly childCreatedAt: number;
17
+ } & ({
18
+ readonly mode: 'one-shot';
19
+ readonly label?: string;
20
+ } | {
21
+ readonly mode: 'continuable';
22
+ readonly label: string;
23
+ });
24
+ declare module '@deepseek-ai/dsh-session/types' {
25
+ interface SessionEventMap {
26
+ /**
27
+ * A direct child's complete discovery fact.
28
+ * @param data - versioned parent-owned catalog entry.
29
+ */
30
+ 'subagent/catalog': SubagentCatalogEvent;
31
+ }
32
+ }
33
+ /** Host fold state for one parent catalog. */
34
+ export interface SubagentCatalogState {
35
+ readonly inheritedEventCount: SessionLogOffset;
36
+ readonly head?: ChunkedList<SubagentCatalogEvent> | undefined;
37
+ }
38
+ declare module '@deepseek-ai/dsh-session-projection/types' {
39
+ interface SessionProjectionStateMap {
40
+ subagentCatalog: SubagentCatalogState;
41
+ }
42
+ }
43
+ /**
44
+ * Materialize direct children from their parent's successful creation facts.
45
+ * @param state - parent catalog fold state.
46
+ * @returns current direct-child rows in parent catalog event order.
47
+ */
48
+ declare function subagentCatalogEntries(state: SubagentCatalogState): SubagentCatalogEntry[];
49
+ /** Parent-owned direct-child catalog projection; invalid own facts reject restoration. */
50
+ export declare const subagentCatalogProjectionDefinition: {
51
+ key: "subagentCatalog";
52
+ stateSchema: z.ZodType<SubagentCatalogState, unknown, z.core.$ZodTypeInternals<SubagentCatalogState, unknown>>;
53
+ init: (_header: SessionHeader, inheritedEventCount: SessionLogOffset) => {
54
+ inheritedEventCount: SessionLogOffset;
55
+ };
56
+ apply: (state: NoInfer<SubagentCatalogState>, event: SessionEvent) => SubagentCatalogState;
57
+ stateVersion: number;
58
+ wire: {
59
+ viewSchema: z.ZodType<SubagentCatalogEntry[], unknown, z.core.$ZodTypeInternals<SubagentCatalogEntry[], unknown>>;
60
+ view: typeof subagentCatalogEntries;
61
+ };
62
+ };
63
+ /**
64
+ * Append a complete direct-child discovery fact to its parent Session.
65
+ * @param parent - durable direct parent receiving the discovery fact.
66
+ * @param child - established child's immutable Session metadata.
67
+ * @param descriptor - mode-discriminated creation label frozen with the child.
68
+ */
69
+ export declare function establishCatalogChild(parent: Session, child: SessionHeader, descriptor: {
70
+ readonly mode: 'one-shot';
71
+ readonly label?: string;
72
+ } | {
73
+ readonly mode: 'continuable';
74
+ readonly label: string;
75
+ }): void;
76
+ export {};
77
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Parent-owned durable subagent catalog events and their chunked projection.
3
+ *
4
+ * @module @deepseek-ai/dsh-subagent/catalog
5
+ */
6
+ import { z } from 'zod';
7
+ import { appendChunkedList, chunkedListSchema, iterateChunkedList } from '@deepseek-ai/dsh-chunked-list';
8
+ /** Current payload version for `subagent/catalog` events. */
9
+ export const SUBAGENT_CATALOG_VERSION = 0;
10
+ const sessionIdSchema = z.string();
11
+ const oneShotCatalogSchema = z.object({
12
+ version: z.literal(SUBAGENT_CATALOG_VERSION),
13
+ childId: sessionIdSchema,
14
+ childCreatedAt: z.number().int().nonnegative(),
15
+ mode: z.literal('one-shot'),
16
+ label: z.string().optional(),
17
+ }).strict();
18
+ const continuableCatalogSchema = z.object({
19
+ version: z.literal(SUBAGENT_CATALOG_VERSION),
20
+ childId: sessionIdSchema,
21
+ childCreatedAt: z.number().int().nonnegative(),
22
+ mode: z.literal('continuable'),
23
+ label: z.string(),
24
+ }).strict();
25
+ const eventDataSchema = z.union([
26
+ oneShotCatalogSchema,
27
+ continuableCatalogSchema,
28
+ ]);
29
+ const viewSchema = z.array(z.union([
30
+ oneShotCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
31
+ id: sessionIdSchema,
32
+ createdAt: oneShotCatalogSchema.shape.childCreatedAt,
33
+ }),
34
+ continuableCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
35
+ id: sessionIdSchema,
36
+ createdAt: continuableCatalogSchema.shape.childCreatedAt,
37
+ }),
38
+ ]));
39
+ const stateSchema = z.object({
40
+ inheritedEventCount: z.number().int().nonnegative(),
41
+ head: chunkedListSchema(eventDataSchema).optional(),
42
+ }).strict();
43
+ /**
44
+ * Materialize direct children from their parent's successful creation facts.
45
+ * @param state - parent catalog fold state.
46
+ * @returns current direct-child rows in parent catalog event order.
47
+ */
48
+ function subagentCatalogEntries(state) {
49
+ const entries = [];
50
+ for (const data of iterateChunkedList(state.head)) {
51
+ entries.push(data.mode === 'one-shot'
52
+ ? {
53
+ id: data.childId,
54
+ createdAt: data.childCreatedAt,
55
+ mode: data.mode,
56
+ ...data.label === undefined ? {} : { label: data.label },
57
+ }
58
+ : {
59
+ id: data.childId,
60
+ createdAt: data.childCreatedAt,
61
+ mode: data.mode,
62
+ label: data.label,
63
+ });
64
+ }
65
+ return entries;
66
+ }
67
+ /** Parent-owned direct-child catalog projection; invalid own facts reject restoration. */
68
+ export const subagentCatalogProjectionDefinition = {
69
+ key: 'subagentCatalog',
70
+ stateSchema,
71
+ init: (_header, inheritedEventCount) => ({ inheritedEventCount }),
72
+ apply: (state, event) => {
73
+ if (event.type !== 'subagent/catalog' || event.seq < state.inheritedEventCount)
74
+ return state;
75
+ return { ...state, head: appendChunkedList(state.head, eventDataSchema.parse(event.data)) };
76
+ },
77
+ stateVersion: 2,
78
+ wire: { viewSchema, view: subagentCatalogEntries },
79
+ };
80
+ /**
81
+ * Append a complete direct-child discovery fact to its parent Session.
82
+ * @param parent - durable direct parent receiving the discovery fact.
83
+ * @param child - established child's immutable Session metadata.
84
+ * @param descriptor - mode-discriminated creation label frozen with the child.
85
+ */
86
+ export function establishCatalogChild(parent, child, descriptor) {
87
+ parent.append('subagent/catalog', descriptor.mode === 'one-shot'
88
+ ? {
89
+ version: SUBAGENT_CATALOG_VERSION,
90
+ childId: child.id,
91
+ childCreatedAt: child.createdAt,
92
+ mode: descriptor.mode,
93
+ ...descriptor.label === undefined ? {} : { label: descriptor.label },
94
+ }
95
+ : {
96
+ version: SUBAGENT_CATALOG_VERSION,
97
+ childId: child.id,
98
+ childCreatedAt: child.createdAt,
99
+ mode: descriptor.mode,
100
+ label: descriptor.label,
101
+ });
102
+ }
103
+ //# sourceMappingURL=catalog.js.map
@@ -4,5 +4,5 @@
4
4
  * @module @deepseek-ai/dsh-subagent/client
5
5
  */
6
6
  export type * from './control-types.ts';
7
- export type { SubagentIdentityProjection, SubagentTimingProjection } from './projection-types.ts';
7
+ export type { SubagentCatalogEntry, SubagentIdentityProjection, SubagentTimingProjection } from './projection-types.ts';
8
8
  //# sourceMappingURL=client.d.ts.map
@@ -337,7 +337,6 @@ export class ContinuableActivationRegistry {
337
337
  finally {
338
338
  this.wake(activation);
339
339
  }
340
- activation.announced = true;
341
340
  return message.id;
342
341
  }
343
342
  /**
@@ -109,7 +109,7 @@ export declare class SubagentContinuationManager {
109
109
  * supplies every reconstruction input; no subagent provider is dispatched.
110
110
  */
111
111
  private coldResume;
112
- /** Submit to a freshly materialized Activation or roll it back completely. */
112
+ /** Admit a materialized child, commit its creation fact, and release it on failure. */
113
113
  private submitMaterialized;
114
114
  /** Build and submit one message across the final synchronous admission cutoff. */
115
115
  private submitAdmitted;
@@ -73,6 +73,7 @@ import { ContinuableActivationRegistry, } from "./continuation-activation.js";
73
73
  import { createAgentMessage, withContinuableReturnGuidance, } from "./continuation-messages.js";
74
74
  import { assertSubagentMaxDepth } from "./depth.js";
75
75
  import { foldSubagentDescriptor, snapshotSubagentDescriptor } from "./descriptor.js";
76
+ import { establishCatalogChild } from "./catalog.js";
76
77
  import { SubagentError } from "./error.js";
77
78
  import { isAdjacentAgentSendMessageTool } from "./internal.js";
78
79
  /**
@@ -167,9 +168,10 @@ export class SubagentContinuationManager {
167
168
  composition: { persona: request.persona, toolFilter: request.toolFilter },
168
169
  signal: spec.signal,
169
170
  });
170
- return this.submitMaterialized(activation, isAdjacentAgentSendMessageTool(this.ctx.get('tools')?.get('send_message', activation.handle.agent))
171
+ const childHeader = activation.handle.agent.session.header;
172
+ return await this.submitMaterialized(activation, isAdjacentAgentSendMessageTool(this.ctx.get('tools')?.get('send_message', activation.handle.agent))
171
173
  ? withContinuableReturnGuidance(parent.id, request.prompt)
172
- : request.prompt, { source: { kind: 'user' }, signal: spec.signal, delivery: 'queue' }, parent);
174
+ : request.prompt, { source: { kind: 'user' }, signal: spec.signal, delivery: 'queue' }, parent, () => { establishCatalogChild(parent.session, childHeader, descriptor); });
173
175
  });
174
176
  return { childId, messageId };
175
177
  }
@@ -264,7 +266,9 @@ export class SubagentContinuationManager {
264
266
  return undefined;
265
267
  }
266
268
  }
267
- return this.submitAdmitted(activation, content, options, parent);
269
+ const messageId = this.submitAdmitted(activation, content, options, parent);
270
+ activation.announced = true;
271
+ return messageId;
268
272
  });
269
273
  /* v8 ignore start -- only a delivery that lost the disposal cutoff retries. */
270
274
  if (live !== undefined)
@@ -385,8 +389,8 @@ export class SubagentContinuationManager {
385
389
  __disposeResources(env_1);
386
390
  }
387
391
  }
388
- /** Submit to a freshly materialized Activation or roll it back completely. */
389
- async submitMaterialized(activation, content, options, parent) {
392
+ /** Admit a materialized child, commit its creation fact, and release it on failure. */
393
+ async submitMaterialized(activation, content, options, parent, commit) {
390
394
  try {
391
395
  if (contentHasImage(content)) {
392
396
  await this.assertImageCapable(activation.handle.agent, options.signal);
@@ -394,12 +398,18 @@ export class SubagentContinuationManager {
394
398
  throw new SubagentError(`subagent "${activation.childId}" is closing`, 'ACTIVATION_CLOSING');
395
399
  }
396
400
  }
397
- return this.submitAdmitted(activation, content, options, parent);
401
+ const messageId = this.submitAdmitted(activation, content, options, parent);
402
+ commit?.();
403
+ activation.announced = true;
404
+ return messageId;
398
405
  }
399
406
  catch (error) {
400
- /* v8 ignore next -- rollback disposal failures must not mask the
401
- * pre-acceptance signal, drain, or lifecycle failure. */
402
- await this.activations.dispose(activation).catch(() => undefined);
407
+ try {
408
+ await this.activations.dispose(activation);
409
+ }
410
+ catch (cleanupError) {
411
+ this.ctx.logger.warn(`subagent continuation: disposal after admission or catalog append failure also failed: ${String(cleanupError)}`);
412
+ }
403
413
  throw error;
404
414
  }
405
415
  }
@@ -38,6 +38,7 @@ import type { SubagentCatalog, SubagentInterruptReceipt, SubagentPromptReceipt,
38
38
  import type { ContinuableStart, ContinuableStartSpec, SubagentInterruptAuthority, SubagentProvider, SubagentRun, SubagentRunEndInfo, SubagentRunInfo, SubagentSendMessageOptions, SubagentStartRequest } from './types.ts';
39
39
  import type { SubagentDescendantListEntry, SubagentListEntry } from './list-children.ts';
40
40
  import { deliverSubagentPrompt } from './internal.ts';
41
+ export type {} from './catalog.ts';
41
42
  export * from './out-of-process.ts';
42
43
  export { AssistantOutputFold, finalAssistantOutput } from './assistant-output.ts';
43
44
  export { SubagentRunId } from './types.ts';
@@ -286,6 +287,8 @@ export declare class SubagentRuntime extends TypertRemoteService {
286
287
  * fulfills; a rejection therefore has no run for the caller to dispose and
287
288
  * emits no run lifecycle events. Post-publication turn and infrastructure
288
289
  * failures settle through the returned run.
290
+ * A catalog append failure disposes the run and handles its result rejection;
291
+ * the caller receives the catalog error even if disposal also fails.
289
292
  * @param name - the provider to use.
290
293
  * @param request - child label, prompt, parent, signal, and optional capabilities.
291
294
  * @returns the published holder-owned run.
@@ -74,6 +74,7 @@ import SubagentContinuationManager from "./continuation.js";
74
74
  import { listChildren as listSubagentChildren, listDescendants as listSubagentDescendants } from "./list-children.js";
75
75
  import { snapshotSubagentDescriptor } from "./descriptor.js";
76
76
  import { subagentIdentityProjectionDefinition, subagentTimingProjectionDefinition } from "./projection.js";
77
+ import { establishCatalogChild, subagentCatalogProjectionDefinition } from "./catalog.js";
77
78
  import { deliverSubagentPrompt } from "./internal.js";
78
79
  export * from "./out-of-process.js";
79
80
  export { AssistantOutputFold, finalAssistantOutput } from "./assistant-output.js";
@@ -125,6 +126,7 @@ let SubagentRuntime = (() => {
125
126
  }, 'subagents.continuationBinding()');
126
127
  });
127
128
  ctx.inject(['sessionProjections'], (projectionCtx) => {
129
+ projectionCtx.sessionProjections.register(subagentCatalogProjectionDefinition);
128
130
  projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition);
129
131
  projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition);
130
132
  });
@@ -414,6 +416,8 @@ let SubagentRuntime = (() => {
414
416
  * fulfills; a rejection therefore has no run for the caller to dispose and
415
417
  * emits no run lifecycle events. Post-publication turn and infrastructure
416
418
  * failures settle through the returned run.
419
+ * A catalog append failure disposes the run and handles its result rejection;
420
+ * the caller receives the catalog error even if disposal also fails.
417
421
  * @param name - the provider to use.
418
422
  * @param request - child label, prompt, parent, signal, and optional capabilities.
419
423
  * @returns the published holder-owned run.
@@ -430,7 +434,25 @@ let SubagentRuntime = (() => {
430
434
  ...request.label !== undefined ? { label: request.label } : {},
431
435
  });
432
436
  const resolved = { ...request, descriptor };
433
- return observeRun(this.emitLifecycle, name, request.parent, await provider.start(resolved));
437
+ const run = await provider.start(resolved);
438
+ const child = run.localAgent?.session;
439
+ if (child !== undefined) {
440
+ try {
441
+ establishCatalogChild(request.parent.session, child.header, descriptor);
442
+ }
443
+ catch (error) {
444
+ // No caller receives this run; the catalog error owns the failed start.
445
+ void run.result.catch(() => undefined);
446
+ try {
447
+ await run.dispose();
448
+ }
449
+ catch (cleanupError) {
450
+ this.ctx.logger.warn(`subagent: disposal after catalog append failure also failed: ${String(cleanupError)}`);
451
+ }
452
+ throw error;
453
+ }
454
+ }
455
+ return observeRun(this.emitLifecycle, name, request.parent, run);
434
456
  }
435
457
  /**
436
458
  * Resolve one provider's detached continuable-creation contribution. Method
@@ -3,7 +3,18 @@
3
3
  *
4
4
  * @module @deepseek-ai/dsh-subagent/projection-types
5
5
  */
6
- import type { SessionSeq } from '@deepseek-ai/dsh-session/types';
6
+ import type { SessionId, SessionSeq } from '@deepseek-ai/dsh-session/types';
7
+ /** One current direct-child discovery row materialized from parent facts. */
8
+ export type SubagentCatalogEntry = {
9
+ readonly id: SessionId;
10
+ readonly createdAt: number;
11
+ } & ({
12
+ readonly mode: 'one-shot';
13
+ readonly label?: string;
14
+ } | {
15
+ readonly mode: 'continuable';
16
+ readonly label: string;
17
+ });
7
18
  /** Durable active-turn timing for one descriptor-backed child session. */
8
19
  export interface SubagentTimingProjection {
9
20
  /** Milliseconds accumulated across completed turns after the child's own descriptor. */
@@ -44,6 +55,8 @@ export type SubagentIdentityProjection = {
44
55
  };
45
56
  declare module '@deepseek-ai/dsh-session-projection/types' {
46
57
  interface SessionProjectionMap {
58
+ /** Direct children in parent catalog event order, excluding fork-inherited facts. */
59
+ subagentCatalog: SubagentCatalogEntry[];
47
60
  /** Active-turn duration for a descriptor-backed subagent session. */
48
61
  subagentTiming: SubagentTimingProjection;
49
62
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-subagent",
3
3
  "description": "Abstract subagent seam (ctx.subagents): named-provider registry for delegating to child agents",
4
- "version": "0.1.5-alpha.1",
4
+ "version": "0.1.5-rc.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -54,30 +54,31 @@
54
54
  "license": "MIT",
55
55
  "dependencies": {
56
56
  "zod": "^4.4.3",
57
- "@deepseek-ai/dsh-util-values": "^0.1.5-alpha.1",
58
- "@deepseek-ai/dsh-brand": "^0.1.5-alpha.1"
57
+ "@deepseek-ai/dsh-brand": "^0.1.5-rc.1",
58
+ "@deepseek-ai/dsh-chunked-list": "^0.1.5-rc.1",
59
+ "@deepseek-ai/dsh-util-values": "^0.1.5-rc.1"
59
60
  },
60
61
  "peerDependencies": {
61
- "@deepseek-ai/dsh-attachment": "^0.1.5-alpha.1",
62
- "@deepseek-ai/dsh-invariants": "^0.1.5-alpha.1",
63
- "@deepseek-ai/dsh-jobs": "^0.1.5-alpha.1",
64
- "@deepseek-ai/dsh-llm": "^0.1.5-alpha.1",
65
- "@deepseek-ai/dsh-sandbox": "^0.1.5-alpha.1",
66
- "@deepseek-ai/dsh-scope": "^0.1.5-alpha.1",
67
- "@deepseek-ai/dsh-sandbox-policy": "^0.1.5-alpha.1",
68
- "@deepseek-ai/dsh-session-persistence": "^0.1.5-alpha.1",
69
- "@deepseek-ai/dsh-session-projection": "^0.1.5-alpha.1",
70
- "@deepseek-ai/dsh-session-projection-cache": "^0.1.5-alpha.1",
71
- "@deepseek-ai/dsh-session-query": "^0.1.5-alpha.1",
72
- "@deepseek-ai/dsh-system-prompt": "^0.1.5-alpha.1",
73
- "@deepseek-ai/dsh-tools": "^0.1.5-alpha.1",
74
- "@deepseek-ai/dsh-session": "^0.1.5-alpha.1",
75
- "@deepseek-ai/dsh-agent": "^0.1.5-alpha.1",
76
- "@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.1",
77
- "@deepseek-ai/dsh-user-approval": "^0.1.5-alpha.1",
78
- "@deepseek-ai/dsh-util-time": "^0.1.5-alpha.1",
79
- "@deepseek-ai/dsh-agent-presets": "^0.1.5-alpha.1",
80
- "@deepseek-ai/cordis": "^4.0.2"
62
+ "@deepseek-ai/cordis": "^4.0.2",
63
+ "@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
64
+ "@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.1",
65
+ "@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
66
+ "@deepseek-ai/dsh-invariants": "^0.1.5-rc.1",
67
+ "@deepseek-ai/dsh-jobs": "^0.1.5-rc.1",
68
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
69
+ "@deepseek-ai/dsh-sandbox": "^0.1.5-rc.1",
70
+ "@deepseek-ai/dsh-sandbox-policy": "^0.1.5-rc.1",
71
+ "@deepseek-ai/dsh-scope": "^0.1.5-rc.1",
72
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.1",
73
+ "@deepseek-ai/dsh-session-persistence": "^0.1.5-rc.1",
74
+ "@deepseek-ai/dsh-session-projection": "^0.1.5-rc.1",
75
+ "@deepseek-ai/dsh-session-projection-cache": "^0.1.5-rc.1",
76
+ "@deepseek-ai/dsh-session-query": "^0.1.5-rc.1",
77
+ "@deepseek-ai/dsh-tools": "^0.1.5-rc.1",
78
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
79
+ "@deepseek-ai/dsh-user-approval": "^0.1.5-rc.1",
80
+ "@deepseek-ai/dsh-util-time": "^0.1.5-rc.1",
81
+ "@deepseek-ai/dsh-system-prompt": "^0.1.5-rc.1"
81
82
  },
82
83
  "peerDependenciesMeta": {
83
84
  "@deepseek-ai/dsh-agent-presets": {
@@ -110,28 +111,28 @@
110
111
  },
111
112
  "devDependencies": {
112
113
  "@deepseek-ai/cordis": "^4.0.2",
113
- "@deepseek-ai/dsh-agent": "^0.1.5-alpha.1",
114
- "@deepseek-ai/dsh-attachment": "^0.1.5-alpha.1",
115
- "@deepseek-ai/dsh-invariants": "^0.1.5-alpha.1",
116
- "@deepseek-ai/dsh-agent-presets": "^0.1.5-alpha.1",
117
- "@deepseek-ai/dsh-jobs": "^0.1.5-alpha.1",
118
- "@deepseek-ai/dsh-llm": "^0.1.5-alpha.1",
119
- "@deepseek-ai/dsh-sandbox-policy": "^0.1.5-alpha.1",
120
- "@deepseek-ai/dsh-sandbox": "^0.1.5-alpha.1",
121
- "@deepseek-ai/dsh-schedule": "^0.1.5-alpha.1",
122
- "@deepseek-ai/dsh-scope": "^0.1.5-alpha.1",
123
- "@deepseek-ai/dsh-session": "^0.1.5-alpha.1",
124
- "@deepseek-ai/dsh-session-persistence": "^0.1.5-alpha.1",
125
- "@deepseek-ai/dsh-session-projection": "^0.1.5-alpha.1",
126
- "@deepseek-ai/dsh-session-projection-cache": "^0.1.5-alpha.1",
127
- "@deepseek-ai/dsh-session-query": "^0.1.5-alpha.1",
128
- "@deepseek-ai/dsh-storage": "^0.1.5-alpha.1",
129
- "@deepseek-ai/dsh-storage-domain": "^0.1.5-alpha.1",
130
- "@deepseek-ai/dsh-system-prompt": "^0.1.5-alpha.1",
131
- "@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.1",
132
- "@deepseek-ai/dsh-user-approval": "^0.1.5-alpha.1",
133
- "@deepseek-ai/dsh-util-time": "^0.1.5-alpha.1",
134
- "@deepseek-ai/dsh-tools": "^0.1.5-alpha.1",
135
- "@deepseek-ai/dsh-storage-json": "^0.1.5-alpha.1"
114
+ "@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
115
+ "@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.1",
116
+ "@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
117
+ "@deepseek-ai/dsh-invariants": "^0.1.5-rc.1",
118
+ "@deepseek-ai/dsh-jobs": "^0.1.5-rc.1",
119
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
120
+ "@deepseek-ai/dsh-sandbox": "^0.1.5-rc.1",
121
+ "@deepseek-ai/dsh-sandbox-policy": "^0.1.5-rc.1",
122
+ "@deepseek-ai/dsh-schedule": "^0.1.5-rc.1",
123
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.1",
124
+ "@deepseek-ai/dsh-session-persistence": "^0.1.5-rc.1",
125
+ "@deepseek-ai/dsh-session-projection": "^0.1.5-rc.1",
126
+ "@deepseek-ai/dsh-session-projection-cache": "^0.1.5-rc.1",
127
+ "@deepseek-ai/dsh-session-query": "^0.1.5-rc.1",
128
+ "@deepseek-ai/dsh-scope": "^0.1.5-rc.1",
129
+ "@deepseek-ai/dsh-storage": "^0.1.5-rc.1",
130
+ "@deepseek-ai/dsh-storage-domain": "^0.1.5-rc.1",
131
+ "@deepseek-ai/dsh-storage-json": "^0.1.5-rc.1",
132
+ "@deepseek-ai/dsh-system-prompt": "^0.1.5-rc.1",
133
+ "@deepseek-ai/dsh-tools": "^0.1.5-rc.1",
134
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
135
+ "@deepseek-ai/dsh-user-approval": "^0.1.5-rc.1",
136
+ "@deepseek-ai/dsh-util-time": "^0.1.5-rc.1"
136
137
  }
137
138
  }