@deepseek-ai/dsh-subagent 0.2.1-alpha.1 → 0.2.1-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.i18n.yaml +40 -34
  2. package/README.md +43 -26
  3. package/README.zh.md +43 -26
  4. package/lib/index.js +1480 -1349
  5. package/lib/typert.host.js +230 -76
  6. package/lib/typert.remote-client.d.ts +6 -2
  7. package/lib/typert.remote-client.js +82 -28
  8. package/lib/types/activation.d.ts +114 -0
  9. package/lib/types/activation.js +112 -0
  10. package/lib/types/catalog.d.ts +14 -6
  11. package/lib/types/catalog.js +34 -30
  12. package/lib/types/child-agent.d.ts +16 -32
  13. package/lib/types/child-agent.js +25 -30
  14. package/lib/types/continuation-messages.d.ts +4 -3
  15. package/lib/types/continuation-messages.js +13 -5
  16. package/lib/types/control-types.d.ts +7 -0
  17. package/lib/types/descriptor.d.ts +7 -46
  18. package/lib/types/descriptor.js +20 -21
  19. package/lib/types/index.d.ts +52 -51
  20. package/lib/types/index.js +81 -98
  21. package/lib/types/internal.d.ts +1 -1
  22. package/lib/types/lifecycle.d.ts +28 -58
  23. package/lib/types/lifecycle.js +9 -74
  24. package/lib/types/list-children.js +1 -1
  25. package/lib/types/manager.d.ts +247 -0
  26. package/lib/types/manager.js +1316 -0
  27. package/lib/types/out-of-process.d.ts +3 -29
  28. package/lib/types/out-of-process.js +5 -47
  29. package/lib/types/projection-types.d.ts +3 -0
  30. package/lib/types/structured.d.ts +49 -0
  31. package/lib/types/structured.js +130 -0
  32. package/lib/types/types.d.ts +66 -100
  33. package/lib/types/types.js +1 -1
  34. package/locale/en.json +5 -0
  35. package/locale/zh.json +6 -0
  36. package/package.json +56 -53
  37. package/lib/types/continuation-activation.d.ts +0 -267
  38. package/lib/types/continuation-activation.js +0 -700
  39. package/lib/types/continuation.d.ts +0 -124
  40. package/lib/types/continuation.js +0 -455
  41. package/lib/types/inbox.d.ts +0 -43
  42. package/lib/types/inbox.js +0 -61
  43. package/lib/types/run-settlement.d.ts +0 -17
  44. package/lib/types/run-settlement.js +0 -70
@@ -1,7 +1,8 @@
1
1
  /* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */
2
2
  import type {
3
3
  RemoteResult,
4
- TypertRemoteContribution,
4
+ TypertRemoteInfo,
5
+ TypertRemoteMethod,
5
6
  } from '@deepseek-ai/dsh-typert-protocol'
6
7
  import type { SessionId } from '@deepseek-ai/dsh-session/types'
7
8
  import type { SubagentInterruptReceipt, SubagentPromptReceipt, SubagentPromptRequest } from '@deepseek-ai/dsh-subagent/client'
@@ -20,6 +21,9 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
20
21
  }
21
22
  }
22
23
 
23
- export declare const TYPERT_REMOTE: TypertRemoteContribution
24
+ export declare const TYPERT_REMOTE: TypertRemoteInfo<{
25
+ readonly 'subagents/interruptByParent': TypertRemoteMethod<{ readonly 'childSessionId': SessionId; readonly 'parentSessionId': SessionId; readonly 'mode': 'continuable' }, SubagentInterruptReceipt>
26
+ readonly 'subagents/prompt': TypertRemoteMethod<{ readonly 'request': SubagentPromptRequest }, SubagentPromptReceipt>
27
+ }>
24
28
  export default TYPERT_REMOTE
25
29
  //# sourceMappingURL=typert.remote-client.d.ts.map
@@ -1,10 +1,12 @@
1
1
  /* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */
2
2
  import { z } from 'zod'
3
3
 
4
+ import { createTypertRemoteInfo } from '@deepseek-ai/dsh-typert-protocol/remote-info'
5
+
4
6
  let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema$value
5
- const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema$value ??= z.intersection(z.string(), z.unknown()))
7
+ const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema$value ??= z.string())
6
8
  let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema$value
7
- const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema$value ??= z.intersection(z.string(), z.unknown()))
9
+ const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema$value ??= z.string())
8
10
  let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema$value
9
11
  const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema$value ??= z.literal("continuable"))
10
12
  let _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema$value
@@ -13,11 +15,11 @@ const _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema = () =
13
15
  }))
14
16
  let _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema$value
15
17
  const _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema = () => (_deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema$value ??= z.object({
16
- 'requestId': z.intersection(z.string(), z.unknown()).readonly(),
17
- 'parentSessionId': z.intersection(z.string(), z.unknown()).readonly(),
18
- 'childSessionId': z.intersection(z.string(), z.unknown()).readonly(),
19
- 'mode': z.literal("continuable").readonly(),
20
- 'delivery': z.union([z.literal("queue"), z.literal("steer")]).readonly(),
18
+ 'requestId': z.string().readonly().describe('Identity persisted on the accepted message, minted before the call.'),
19
+ 'parentSessionId': z.string().readonly(),
20
+ 'childSessionId': z.string().readonly(),
21
+ 'mode': z.literal("continuable").readonly().describe('Required discriminator retained from the browser control address.'),
22
+ 'delivery': z.union([z.literal("queue"), z.literal("steer")]).readonly().describe('Whether this message queues a later turn or targets the nearest step.'),
21
23
  'content': z.array(z.union([z.object({
22
24
  'type': z.literal("text").readonly(),
23
25
  'text': z.string().readonly(),
@@ -26,52 +28,95 @@ const _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema = () => (_de
26
28
  'mediaType': z.union([z.literal("image/png"), z.literal("image/jpeg"), z.literal("image/webp"), z.literal("image/gif")]).readonly(),
27
29
  'data': z.string().readonly(),
28
30
  'name': z.string().readonly().optional(),
29
- })])).readonly(),
30
- 'clientTimeZone': z.string().readonly().optional(),
31
+ })])).readonly().describe('Browser prompt parts delivered as the child\'s user message. The Host admits and persists image parts before delivery, so the wire never carries a durable attachment reference the caller could fabricate.'),
32
+ 'clientTimeZone': z.string().readonly().optional().describe('Optional browser zone sampled for this exact human prompt.'),
31
33
  }))
32
34
  let _deepseek_ai_dsh_subagent_subagents_prompt_result$schema$value
33
35
  const _deepseek_ai_dsh_subagent_subagents_prompt_result$schema = () => (_deepseek_ai_dsh_subagent_subagents_prompt_result$schema$value ??= z.object({
34
- 'messageId': z.intersection(z.string(), z.unknown()).readonly(),
36
+ 'messageId': z.string().readonly(),
37
+ }))
38
+ let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0_strict$schema$value
39
+ const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0_strict$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0_strict$schema$value ??= z.string())
40
+ let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1_strict$schema$value
41
+ const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1_strict$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1_strict$schema$value ??= z.string())
42
+ let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2_strict$schema$value
43
+ const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2_strict$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2_strict$schema$value ??= z.literal("continuable"))
44
+ let _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0_strict$schema$value
45
+ const _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0_strict$schema = () => (_deepseek_ai_dsh_subagent_subagents_prompt_parameter_0_strict$schema$value ??= z.strictObject({
46
+ 'requestId': z.string().readonly().describe('Identity persisted on the accepted message, minted before the call.'),
47
+ 'parentSessionId': z.string().readonly(),
48
+ 'childSessionId': z.string().readonly(),
49
+ 'mode': z.literal("continuable").readonly().describe('Required discriminator retained from the browser control address.'),
50
+ 'delivery': z.union([z.literal("queue"), z.literal("steer")]).readonly().describe('Whether this message queues a later turn or targets the nearest step.'),
51
+ 'content': z.array(z.union([z.strictObject({
52
+ 'type': z.literal("text").readonly(),
53
+ 'text': z.string().readonly(),
54
+ }), z.strictObject({
55
+ 'type': z.literal("image").readonly(),
56
+ 'mediaType': z.union([z.literal("image/png"), z.literal("image/jpeg"), z.literal("image/webp"), z.literal("image/gif")]).readonly(),
57
+ 'data': z.string().readonly(),
58
+ 'name': z.string().readonly().optional(),
59
+ })])).readonly().describe('Browser prompt parts delivered as the child\'s user message. The Host admits and persists image parts before delivery, so the wire never carries a durable attachment reference the caller could fabricate.'),
60
+ 'clientTimeZone': z.string().readonly().optional().describe('Optional browser zone sampled for this exact human prompt.'),
35
61
  }))
36
62
 
37
- export const TYPERT_REMOTE = {
63
+ export const TYPERT_REMOTE = createTypertRemoteInfo({
38
64
  package: '@deepseek-ai/dsh-subagent',
39
- descriptors: [
40
- {
41
- id: '@deepseek-ai/dsh-subagent#subagents/interruptByParent',
65
+ methods: {
66
+ 'subagents/interruptByParent': {
42
67
  service: 'subagents',
43
- namespace: 'subagents',
44
- method: 'interruptByParent',
68
+ description: 'Remote face of {@link interrupt} under one durable parent address. No catalog, history, persistence, or parent Agent lookup runs: the core primitive alone authorizes the address against the live Activation, which is what keeps a live child interruptible while its parent Agent is offline. Absent, idle, and already-completed targets are accepted no-ops there.',
45
69
  invocation: { kind: 'direct' },
46
70
  parameters: [
47
71
  {
48
72
  name: 'childSessionId',
49
- wire: 'childSessionId',
73
+ description: 'durable child session id to interrupt.',
50
74
  source: 'json',
51
75
  codec: {
52
76
  mode: 'strict',
53
77
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
54
78
  create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema,
79
+ jsonSchema: {"type":"string"},
80
+ },
81
+ strictCodec: {
82
+ mode: 'strict',
83
+ typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
84
+ create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0_strict$schema,
85
+ jsonSchema: {"type":"string"},
55
86
  },
56
87
  },
57
88
  {
58
89
  name: 'parentSessionId',
59
- wire: 'parentSessionId',
90
+ description: 'durable direct parent whose authority is claimed.',
60
91
  source: 'json',
61
92
  codec: {
62
93
  mode: 'strict',
63
94
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
64
95
  create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema,
96
+ jsonSchema: {"type":"string"},
97
+ },
98
+ strictCodec: {
99
+ mode: 'strict',
100
+ typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
101
+ create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1_strict$schema,
102
+ jsonSchema: {"type":"string"},
65
103
  },
66
104
  },
67
105
  {
68
106
  name: 'mode',
69
- wire: 'mode',
107
+ description: 'required continuable-address discriminator.',
70
108
  source: 'json',
71
109
  codec: {
72
110
  mode: 'strict',
73
111
  typeSymbol: '@deepseek-ai/dsh-subagent#subagents/interruptByParent:mode',
74
112
  create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema,
113
+ jsonSchema: {"type":"string","const":"continuable"},
114
+ },
115
+ strictCodec: {
116
+ mode: 'strict',
117
+ typeSymbol: '@deepseek-ai/dsh-subagent#subagents/interruptByParent:mode',
118
+ create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2_strict$schema,
119
+ jsonSchema: {"type":"string","const":"continuable"},
75
120
  },
76
121
  },
77
122
  ],
@@ -79,24 +124,31 @@ export const TYPERT_REMOTE = {
79
124
  mode: 'strict',
80
125
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentInterruptReceipt',
81
126
  create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema,
127
+ description: 'acknowledgement that the cancel signal was admitted, not that the target is quiescent.',
128
+ jsonSchema: {"type":"object","properties":{"accepted":{"type":"boolean","const":true}},"required":["accepted"],"additionalProperties":true},
82
129
  },
83
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":481,"column":3},
130
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":517,"column":3},
84
131
  },
85
- {
86
- id: '@deepseek-ai/dsh-subagent#subagents/prompt',
132
+ 'subagents/prompt': {
87
133
  service: 'subagents',
88
- namespace: 'subagents',
89
- method: 'prompt',
134
+ description: 'Deliver one browser-authored message to a continuable child through the exact live direct parent, retaining the caller-minted request identity and validated browser zone on the accepted message. Success identifies the message the child\'s inbox accepted; later execution is independent of this call. Queue delivery targets a later turn; steer delivery targets the nearest step and retains the Agent loop\'s best-effort fallback semantics. Image parts are admitted and persisted through the attachment store before delivery, and the child\'s model must accept image input. Cold resume at capacity rejects with `subagent/delivery-unavailable`.',
90
135
  invocation: { kind: 'direct' },
91
136
  parameters: [
92
137
  {
93
138
  name: 'request',
94
- wire: 'request',
139
+ description: 'durable address, delivery, minted identity, content, and optional browser zone.',
95
140
  source: 'json',
96
141
  codec: {
97
142
  mode: 'strict',
98
143
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptRequest',
99
144
  create: _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema,
145
+ jsonSchema: {"type":"object","properties":{"requestId":{"type":"string","description":"Identity persisted on the accepted message, minted before the call."},"parentSessionId":{"type":"string"},"childSessionId":{"type":"string"},"mode":{"type":"string","const":"continuable","description":"Required discriminator retained from the browser control address."},"delivery":{"type":"string","enum":["queue","steer"],"description":"Whether this message queues a later turn or targets the nearest step."},"content":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"}},"required":["type","text"],"additionalProperties":true},{"type":"object","properties":{"type":{"type":"string","const":"image"},"mediaType":{"type":"string","enum":["image/png","image/jpeg","image/webp","image/gif"]},"data":{"type":"string"},"name":{"type":"string"}},"required":["type","mediaType","data"],"additionalProperties":true}]},"description":"Browser prompt parts delivered as the child's user message. The Host admits and persists image parts before delivery, so the wire never carries a durable attachment reference the caller could fabricate."},"clientTimeZone":{"type":"string","description":"Optional browser zone sampled for this exact human prompt."}},"required":["requestId","parentSessionId","childSessionId","mode","delivery","content"],"additionalProperties":true},
146
+ },
147
+ strictCodec: {
148
+ mode: 'strict',
149
+ typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptRequest',
150
+ create: _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0_strict$schema,
151
+ jsonSchema: {"type":"object","properties":{"requestId":{"type":"string","description":"Identity persisted on the accepted message, minted before the call."},"parentSessionId":{"type":"string"},"childSessionId":{"type":"string"},"mode":{"type":"string","const":"continuable","description":"Required discriminator retained from the browser control address."},"delivery":{"type":"string","enum":["queue","steer"],"description":"Whether this message queues a later turn or targets the nearest step."},"content":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"text":{"type":"string"}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"image"},"mediaType":{"type":"string","enum":["image/png","image/jpeg","image/webp","image/gif"]},"data":{"type":"string"},"name":{"type":"string"}},"required":["type","mediaType","data"],"additionalProperties":false}]},"description":"Browser prompt parts delivered as the child's user message. The Host admits and persists image parts before delivery, so the wire never carries a durable attachment reference the caller could fabricate."},"clientTimeZone":{"type":"string","description":"Optional browser zone sampled for this exact human prompt."}},"required":["requestId","parentSessionId","childSessionId","mode","delivery","content"],"additionalProperties":false},
100
152
  },
101
153
  },
102
154
  ],
@@ -105,10 +157,12 @@ export const TYPERT_REMOTE = {
105
157
  mode: 'strict',
106
158
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptReceipt',
107
159
  create: _deepseek_ai_dsh_subagent_subagents_prompt_result$schema,
160
+ description: 'the accepted message\'s inbox identity.',
161
+ jsonSchema: {"type":"object","properties":{"messageId":{"type":"string"}},"required":["messageId"],"additionalProperties":true},
108
162
  },
109
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":414,"column":9},
163
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":448,"column":9},
110
164
  },
111
- ],
112
- }
165
+ },
166
+ }, z)
113
167
 
114
168
  export default TYPERT_REMOTE
@@ -0,0 +1,114 @@
1
+ /** Execution-period records, capacity slots, child serialization, and local output capture.
2
+ * @module @deepseek-ai/dsh-subagent/activation
3
+ */
4
+ import type { Agent, AgentHandle } from '@deepseek-ai/dsh-agent';
5
+ import type { SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session';
6
+ import type { ActivationObserver } from './lifecycle.ts';
7
+ import type { StructuredAttachment } from './structured.ts';
8
+ import type { SubagentResult, SubagentRun } from './types.ts';
9
+ /** Process-local slots shared through uninterrupted continuable parent links. */
10
+ export declare class ActivationPool {
11
+ private readonly slots;
12
+ /**
13
+ * Reserve before reconstruction; release also tolerates unpublished rollback.
14
+ * @param capacity - the maximum simultaneous activations in this pool.
15
+ * @returns an idempotent slot release.
16
+ */
17
+ reserve(capacity: number): () => void;
18
+ }
19
+ /**
20
+ * One residency epoch for a local child or an external execution.
21
+ * The manager owns admission, execution handles, and resource release.
22
+ */
23
+ interface ActivationBase {
24
+ /** Shared capacity for this Activation and all its managed descendants. */
25
+ readonly pool: ActivationPool;
26
+ /** Return this epoch's slot after its handle has finished disposal. */
27
+ readonly releaseSlot: () => void;
28
+ /** The durable child this Activation is an epoch of. */
29
+ readonly childId: SessionId;
30
+ readonly parent: Agent;
31
+ readonly delivery: 'parent' | 'caller';
32
+ readonly result: PromiseWithResolvers<SubagentResult>;
33
+ /** Published synchronously before teardown; subsequent callers share this transaction. */
34
+ closing: Promise<void> | undefined;
35
+ /**
36
+ * Exact live Agent ancestry observed when this Activation materialized.
37
+ * Weak membership preserves host-scope identity across an intermediate
38
+ * ancestor leaving the registry without retaining that ancestor's runtime.
39
+ */
40
+ readonly ancestry: WeakSet<Agent>;
41
+ /**
42
+ * Session ids of the child Activations this one owns. Because one Session has
43
+ * at most one live Activation, the id identifies the live child without
44
+ * another runtime-incarnation reference. Non-empty blocks settlement.
45
+ */
46
+ readonly ownedChildren: Set<SessionId>;
47
+ /** The lifecycle observer that emits this epoch's start and terminal edges. */
48
+ readonly observer: ActivationObserver;
49
+ /**
50
+ * Whether any delivery to this child was ever accepted. A materialization
51
+ * rolled back before its first acceptance is a child the caller was told does
52
+ * not exist, so its teardown owes the parent no settlement account.
53
+ */
54
+ announced: boolean;
55
+ }
56
+ /** Resources retained only for the selected execution kind. */
57
+ export type ActivationResource = {
58
+ readonly kind: 'local';
59
+ readonly handle: AgentHandle;
60
+ readonly outputStart: SessionLogOffset;
61
+ readonly structured: StructuredAttachment | undefined;
62
+ /** Latest live failure not superseded by a later committed turn ending. */
63
+ failureAt: SessionLogOffset | undefined;
64
+ /** Renewed when local settlement must recheck input or owned children. */
65
+ poke: PromiseWithResolvers<void>;
66
+ } | {
67
+ readonly kind: 'external';
68
+ readonly run: SubagentRun;
69
+ readonly controller: AbortController;
70
+ };
71
+ /** One managed execution period with its provider-specific resources. */
72
+ export type Activation = ActivationBase & ActivationResource;
73
+ /** Local residency with input admission and Session-backed result capture. */
74
+ export type LocalActivation = Extract<Activation, {
75
+ kind: 'local';
76
+ }>;
77
+ /**
78
+ * Read the live Agent retained by local execution.
79
+ * @param activation - the managed local or external execution.
80
+ * @returns the local Agent, absent for an external run.
81
+ */
82
+ export declare function activationAgent(activation: Activation): Agent | undefined;
83
+ /**
84
+ * Require local residency before accepting further input.
85
+ * @param activation - execution targeted by message delivery.
86
+ * @returns the local activation.
87
+ * @throws when the external backend cannot accept another message.
88
+ */
89
+ export declare function requireLocalActivation(activation: Activation): LocalActivation;
90
+ /**
91
+ * Retain local failures whose turn ending could not be committed.
92
+ * @param activation - exact local Agent and epoch receiving the scoped observers.
93
+ * @param wake - notify its settlement watcher when failure changes readiness.
94
+ */
95
+ export declare function observeLocalFailure(activation: LocalActivation, wake: () => void): void;
96
+ /**
97
+ * Capture local output and retain failures without a later committed turn ending.
98
+ * @param activation - the settled local execution and any structured result.
99
+ * @returns final output, stop reason, and committed structured value.
100
+ */
101
+ export declare function captureLocalResult(activation: LocalActivation): SubagentResult;
102
+ /** Serialize each durable child's delivery, release, and disposal. */
103
+ export declare class ChildLock {
104
+ private tails;
105
+ /**
106
+ * Run `operation` after every previously queued operation for `childId`.
107
+ * @param childId - the durable child whose operations are linearized.
108
+ * @param operation - the critical section to run in order.
109
+ * @returns the operation's own settlement.
110
+ */
111
+ run<T>(childId: SessionId, operation: () => Promise<T>): Promise<T>;
112
+ }
113
+ export {};
114
+ //# sourceMappingURL=activation.d.ts.map
@@ -0,0 +1,112 @@
1
+ /** Execution-period records, capacity slots, child serialization, and local output capture.
2
+ * @module @deepseek-ai/dsh-subagent/activation
3
+ */
4
+ import { assertNever } from '@deepseek-ai/dsh-util-values';
5
+ import { finalAssistantOutput } from "./assistant-output.js";
6
+ import { epochStopReason } from "./lifecycle.js";
7
+ import { SubagentError } from "./error.js";
8
+ /** Process-local slots shared through uninterrupted continuable parent links. */
9
+ export class ActivationPool {
10
+ slots = new Set();
11
+ /**
12
+ * Reserve before reconstruction; release also tolerates unpublished rollback.
13
+ * @param capacity - the maximum simultaneous activations in this pool.
14
+ * @returns an idempotent slot release.
15
+ */
16
+ reserve(capacity) {
17
+ if (this.slots.size >= capacity) {
18
+ throw new SubagentError(`subagent limit reached (active child limit: ${capacity}); wait for an existing child to finish `
19
+ + 'or complete this work with the current agents', 'ACTIVATION_LIMIT_REACHED');
20
+ }
21
+ const slot = Symbol();
22
+ this.slots.add(slot);
23
+ return () => { this.slots.delete(slot); };
24
+ }
25
+ }
26
+ /**
27
+ * Read the live Agent retained by local execution.
28
+ * @param activation - the managed local or external execution.
29
+ * @returns the local Agent, absent for an external run.
30
+ */
31
+ export function activationAgent(activation) {
32
+ return activation.kind === 'local' ? activation.handle.agent : undefined;
33
+ }
34
+ /**
35
+ * Require local residency before accepting further input.
36
+ * @param activation - execution targeted by message delivery.
37
+ * @returns the local activation.
38
+ * @throws when the external backend cannot accept another message.
39
+ */
40
+ export function requireLocalActivation(activation) {
41
+ switch (activation.kind) {
42
+ case 'local': return activation;
43
+ case 'external':
44
+ throw new SubagentError(`subagent "${activation.childId}" does not accept follow-up input`, 'NOT_CONTINUABLE');
45
+ /* v8 ignore next 2 -- Both execution kinds are handled above. */
46
+ default: return assertNever(activation);
47
+ }
48
+ }
49
+ /**
50
+ * Retain local failures whose turn ending could not be committed.
51
+ * @param activation - exact local Agent and epoch receiving the scoped observers.
52
+ * @param wake - notify its settlement watcher when failure changes readiness.
53
+ */
54
+ export function observeLocalFailure(activation, wake) {
55
+ const child = activation.handle.agent;
56
+ child.ctx.on('agent/error', ({ agent }) => {
57
+ if (agent !== child)
58
+ return;
59
+ activation.failureAt = child.session.seq;
60
+ wake();
61
+ });
62
+ child.ctx.on('session/event', (session, event) => {
63
+ if (session === child.session && event.type === 'turn/end'
64
+ && activation.failureAt !== undefined && event.seq >= activation.failureAt) {
65
+ activation.failureAt = undefined;
66
+ }
67
+ });
68
+ }
69
+ /**
70
+ * Capture local output and retain failures without a later committed turn ending.
71
+ * @param activation - the settled local execution and any structured result.
72
+ * @returns final output, stop reason, and committed structured value.
73
+ */
74
+ export function captureLocalResult(activation) {
75
+ // oxlint-disable-next-line typescript/no-deprecated -- Existing Session history read; migration deferred.
76
+ const events = activation.handle.agent.session.snapshotEvents(activation.outputStart);
77
+ const output = finalAssistantOutput(events) ?? [];
78
+ const stopReason = activation.failureAt === undefined ? epochStopReason(events) : 'error';
79
+ const structured = activation.structured;
80
+ if (structured !== undefined) {
81
+ const captured = structured.captured();
82
+ if (captured !== undefined)
83
+ return { output, stopReason, structured: captured.value };
84
+ if (stopReason === 'completed')
85
+ return { output, stopReason: 'error' };
86
+ }
87
+ return { output, stopReason };
88
+ }
89
+ /** Serialize each durable child's delivery, release, and disposal. */
90
+ export class ChildLock {
91
+ tails = new Map();
92
+ /**
93
+ * Run `operation` after every previously queued operation for `childId`.
94
+ * @param childId - the durable child whose operations are linearized.
95
+ * @param operation - the critical section to run in order.
96
+ * @returns the operation's own settlement.
97
+ */
98
+ run(childId, operation) {
99
+ const previous = this.tails.get(childId) ?? Promise.resolve();
100
+ const result = previous.then(operation, operation);
101
+ // Absorb rejections in the chaining tail so one failed critical section
102
+ // cannot reject an unrelated later caller.
103
+ const tail = result.then(() => undefined, () => undefined);
104
+ this.tails.set(childId, tail);
105
+ void tail.then(() => {
106
+ if (this.tails.get(childId) === tail)
107
+ this.tails.delete(childId);
108
+ });
109
+ return result;
110
+ }
111
+ }
112
+ //# sourceMappingURL=activation.js.map
@@ -7,7 +7,7 @@ import { z } from 'zod';
7
7
  import type { ChunkedList } from '@deepseek-ai/dsh-chunked-list';
8
8
  import type { Session, SessionEvent, SessionHeader, SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session';
9
9
  import type { SubagentCatalogEntry } from './projection-types.ts';
10
- /** Catalog payload version emitted by live child creation. */
10
+ /** Catalog payload version emitted by local child creation. */
11
11
  export declare const SUBAGENT_CATALOG_VERSION = 0;
12
12
  type KnownCatalogMode = {
13
13
  readonly mode: 'one-shot';
@@ -16,7 +16,7 @@ type KnownCatalogMode = {
16
16
  readonly mode: 'continuable';
17
17
  readonly label: string;
18
18
  };
19
- /** Parent catalog v0 records known modes; v1 also retains children with unknown mode. */
19
+ /** Parent catalog v0 records local modes, v1 adds unknown children, and v2 records external executions. */
20
20
  export type SubagentCatalogEvent = {
21
21
  readonly childId: SessionId;
22
22
  readonly childCreatedAt: number;
@@ -27,7 +27,11 @@ export type SubagentCatalogEvent = {
27
27
  } & (KnownCatalogMode | {
28
28
  readonly mode: 'unknown';
29
29
  readonly label?: string;
30
- })));
30
+ })) | {
31
+ readonly version: 2;
32
+ readonly mode: 'external';
33
+ readonly label?: string;
34
+ });
31
35
  declare module '@deepseek-ai/dsh-session/types' {
32
36
  interface SessionEventMap {
33
37
  /**
@@ -74,11 +78,15 @@ export declare const subagentCatalogProjectionDefinition: {
74
78
  * @param descriptor - mode-discriminated creation label frozen with the child.
75
79
  */
76
80
  export declare function establishCatalogChild(parent: Session, child: SessionHeader, descriptor: {
77
- readonly mode: 'one-shot';
78
- readonly label?: string;
79
- } | {
80
81
  readonly mode: 'continuable';
81
82
  readonly label: string;
82
83
  }): void;
84
+ /**
85
+ * Record an external execution without a local child Session.
86
+ * @param parent - durable direct parent receiving the discovery fact.
87
+ * @param childId - identity returned by the external provider.
88
+ * @param label - display label assigned by the caller.
89
+ */
90
+ export declare function establishExternalCatalogChild(parent: Session, childId: SessionId, label: string): void;
83
91
  export {};
84
92
  //# sourceMappingURL=catalog.d.ts.map
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { z } from 'zod';
7
7
  import { appendChunkedList, chunkedListSchema, iterateChunkedList } from '@deepseek-ai/dsh-chunked-list';
8
- /** Catalog payload version emitted by live child creation. */
8
+ /** Catalog payload version emitted by local child creation. */
9
9
  export const SUBAGENT_CATALOG_VERSION = 0;
10
10
  const sessionIdSchema = z.string();
11
11
  const oneShotCatalogSchema = z.object({
@@ -22,9 +22,11 @@ const continuableCatalogSchema = z.object({
22
22
  mode: z.literal('continuable'),
23
23
  label: z.string(),
24
24
  }).strict();
25
+ const externalCatalogSchema = oneShotCatalogSchema.extend({ version: z.literal(2), mode: z.literal('external') });
25
26
  const unknownCatalogSchema = oneShotCatalogSchema.extend({ version: z.literal(1), mode: z.literal('unknown') });
26
27
  const eventDataSchema = z.union([
27
28
  oneShotCatalogSchema,
29
+ externalCatalogSchema,
28
30
  continuableCatalogSchema,
29
31
  unknownCatalogSchema,
30
32
  ]);
@@ -33,6 +35,10 @@ const viewSchema = z.array(z.union([
33
35
  id: sessionIdSchema,
34
36
  createdAt: oneShotCatalogSchema.shape.childCreatedAt,
35
37
  }),
38
+ externalCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
39
+ id: sessionIdSchema,
40
+ createdAt: externalCatalogSchema.shape.childCreatedAt,
41
+ }),
36
42
  continuableCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
37
43
  id: sessionIdSchema,
38
44
  createdAt: continuableCatalogSchema.shape.childCreatedAt,
@@ -54,19 +60,8 @@ const stateSchema = z.object({
54
60
  function subagentCatalogEntries(state) {
55
61
  const entries = [];
56
62
  for (const data of iterateChunkedList(state.head)) {
57
- entries.push(data.mode !== 'continuable'
58
- ? {
59
- id: data.childId,
60
- createdAt: data.childCreatedAt,
61
- mode: data.mode,
62
- ...data.label === undefined ? {} : { label: data.label },
63
- }
64
- : {
65
- id: data.childId,
66
- createdAt: data.childCreatedAt,
67
- mode: data.mode,
68
- label: data.label,
69
- });
63
+ const { version: _version, childId, childCreatedAt, ...descriptor } = data;
64
+ entries.push({ id: childId, createdAt: childCreatedAt, ...descriptor });
70
65
  }
71
66
  return entries;
72
67
  }
@@ -80,7 +75,7 @@ export const subagentCatalogProjectionDefinition = {
80
75
  return state;
81
76
  return { ...state, head: appendChunkedList(state.head, eventDataSchema.parse(event.data)) };
82
77
  },
83
- stateVersion: 3,
78
+ stateVersion: 6,
84
79
  wire: { viewSchema, view: subagentCatalogEntries },
85
80
  };
86
81
  /**
@@ -90,20 +85,29 @@ export const subagentCatalogProjectionDefinition = {
90
85
  * @param descriptor - mode-discriminated creation label frozen with the child.
91
86
  */
92
87
  export function establishCatalogChild(parent, child, descriptor) {
93
- parent.append('subagent/catalog', descriptor.mode === 'one-shot'
94
- ? {
95
- version: SUBAGENT_CATALOG_VERSION,
96
- childId: child.id,
97
- childCreatedAt: child.createdAt,
98
- mode: descriptor.mode,
99
- ...descriptor.label === undefined ? {} : { label: descriptor.label },
100
- }
101
- : {
102
- version: SUBAGENT_CATALOG_VERSION,
103
- childId: child.id,
104
- childCreatedAt: child.createdAt,
105
- mode: descriptor.mode,
106
- label: descriptor.label,
107
- });
88
+ parent.append('subagent/catalog', {
89
+ version: SUBAGENT_CATALOG_VERSION,
90
+ childId: child.id,
91
+ childCreatedAt: child.createdAt,
92
+ mode: descriptor.mode,
93
+ label: descriptor.label,
94
+ });
95
+ }
96
+ /** Catalog payload version emitted by external execution creation. */
97
+ const EXTERNAL_SUBAGENT_CATALOG_VERSION = 2;
98
+ /**
99
+ * Record an external execution without a local child Session.
100
+ * @param parent - durable direct parent receiving the discovery fact.
101
+ * @param childId - identity returned by the external provider.
102
+ * @param label - display label assigned by the caller.
103
+ */
104
+ export function establishExternalCatalogChild(parent, childId, label) {
105
+ parent.append('subagent/catalog', {
106
+ version: EXTERNAL_SUBAGENT_CATALOG_VERSION,
107
+ childId,
108
+ childCreatedAt: Date.now(),
109
+ mode: 'external',
110
+ label,
111
+ });
108
112
  }
109
113
  //# sourceMappingURL=catalog.js.map