@fishwithcat/dsh-subagent 0.2.2-alpha.2 → 0.2.2-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.
@@ -3,22 +3,16 @@ import { z } from 'zod'
3
3
 
4
4
  import { createTypertRemoteInfo } from '@deepseek-ai/dsh-typert-protocol/remote-info'
5
5
 
6
- let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema$value
7
- const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema$value ??= z.string())
8
- let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema$value
9
- const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_1$schema$value ??= z.string())
10
- let _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema$value
11
- const _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_2$schema$value ??= z.literal("continuable"))
12
- let _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema$value
13
- const _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema$value ??= z.object({
6
+ let _deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0$schema$value
7
+ const _deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0$schema$value ??= z.string())
8
+ let _deepseek_ai_dsh_subagent_subagents_interruptByUser_result$schema$value
9
+ const _deepseek_ai_dsh_subagent_subagents_interruptByUser_result$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByUser_result$schema$value ??= z.object({
14
10
  'accepted': z.literal(true).readonly(),
15
11
  }))
16
12
  let _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema$value
17
13
  const _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema = () => (_deepseek_ai_dsh_subagent_subagents_prompt_parameter_0$schema$value ??= z.object({
18
14
  'requestId': z.string().readonly().describe('Identity persisted on the accepted message, minted before the call.'),
19
- 'parentSessionId': z.string().readonly(),
20
15
  'childSessionId': z.string().readonly(),
21
- 'mode': z.literal("continuable").readonly().describe('Required discriminator retained from the browser control address.'),
22
16
  'delivery': z.union([z.literal("queue"), z.literal("steer")]).readonly().describe('Whether this message queues a later turn or targets the nearest step.'),
23
17
  'content': z.array(z.union([z.object({
24
18
  'type': z.literal("text").readonly(),
@@ -35,18 +29,12 @@ let _deepseek_ai_dsh_subagent_subagents_prompt_result$schema$value
35
29
  const _deepseek_ai_dsh_subagent_subagents_prompt_result$schema = () => (_deepseek_ai_dsh_subagent_subagents_prompt_result$schema$value ??= z.object({
36
30
  'messageId': z.string().readonly(),
37
31
  }))
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"))
32
+ let _deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0_strict$schema$value
33
+ const _deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0_strict$schema = () => (_deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0_strict$schema$value ??= z.string())
44
34
  let _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0_strict$schema$value
45
35
  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
36
  'requestId': z.string().readonly().describe('Identity persisted on the accepted message, minted before the call.'),
47
- 'parentSessionId': z.string().readonly(),
48
37
  'childSessionId': z.string().readonly(),
49
- 'mode': z.literal("continuable").readonly().describe('Required discriminator retained from the browser control address.'),
50
38
  'delivery': z.union([z.literal("queue"), z.literal("steer")]).readonly().describe('Whether this message queues a later turn or targets the nearest step.'),
51
39
  'content': z.array(z.union([z.strictObject({
52
40
  'type': z.literal("text").readonly(),
@@ -63,9 +51,9 @@ const _deepseek_ai_dsh_subagent_subagents_prompt_parameter_0_strict$schema = ()
63
51
  export const TYPERT_REMOTE = createTypertRemoteInfo({
64
52
  package: '@fishwithcat/dsh-subagent',
65
53
  methods: {
66
- 'subagents/interruptByParent': {
54
+ 'subagents/interruptByUser': {
67
55
  service: 'subagents',
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.',
56
+ description: 'Remote face of {@link interrupt}, authorized on the target Session by the Gateway. No catalog, history, persistence, or parent Agent lookup runs. Absent, idle, and already-completed targets are accepted no-ops there.',
69
57
  invocation: { kind: 'direct' },
70
58
  parameters: [
71
59
  {
@@ -75,80 +63,46 @@ export const TYPERT_REMOTE = createTypertRemoteInfo({
75
63
  codec: {
76
64
  mode: 'strict',
77
65
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
78
- create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0$schema,
66
+ create: _deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0$schema,
79
67
  jsonSchema: {"type":"string"},
80
68
  },
81
69
  strictCodec: {
82
70
  mode: 'strict',
83
71
  typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
84
- create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_parameter_0_strict$schema,
72
+ create: _deepseek_ai_dsh_subagent_subagents_interruptByUser_parameter_0_strict$schema,
85
73
  jsonSchema: {"type":"string"},
86
74
  },
87
75
  },
88
- {
89
- name: 'parentSessionId',
90
- description: 'durable direct parent whose authority is claimed.',
91
- source: 'json',
92
- codec: {
93
- mode: 'strict',
94
- typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',
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"},
103
- },
104
- },
105
- {
106
- name: 'mode',
107
- description: 'required continuable-address discriminator.',
108
- source: 'json',
109
- codec: {
110
- mode: 'strict',
111
- typeSymbol: '@deepseek-ai/dsh-subagent#subagents/interruptByParent:mode',
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"},
120
- },
121
- },
122
76
  ],
123
77
  result: {
124
78
  mode: 'strict',
125
79
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentInterruptReceipt',
126
- create: _deepseek_ai_dsh_subagent_subagents_interruptByParent_result$schema,
80
+ create: _deepseek_ai_dsh_subagent_subagents_interruptByUser_result$schema,
127
81
  description: 'acknowledgement that the cancel signal was admitted, not that the target is quiescent.',
128
82
  jsonSchema: {"type":"object","properties":{"accepted":{"type":"boolean","const":true}},"required":["accepted"],"additionalProperties":true},
129
83
  },
130
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":529,"column":3},
84
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":467,"column":3},
131
85
  },
132
86
  'subagents/prompt': {
133
87
  service: 'subagents',
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`.',
88
+ description: 'Deliver one browser-authored message to a continuable child through its live subagent tree root, 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`. Access is checked on the target Session before attachment admission or restoration.',
135
89
  invocation: { kind: 'direct' },
136
90
  parameters: [
137
91
  {
138
92
  name: 'request',
139
- description: 'durable address, delivery, minted identity, content, and optional browser zone.',
93
+ description: 'target id, delivery, minted identity, content, and optional browser zone.',
140
94
  source: 'json',
141
95
  codec: {
142
96
  mode: 'strict',
143
97
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptRequest',
144
98
  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},
99
+ jsonSchema: {"type":"object","properties":{"requestId":{"type":"string","description":"Identity persisted on the accepted message, minted before the call."},"childSessionId":{"type":"string"},"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","childSessionId","delivery","content"],"additionalProperties":true},
146
100
  },
147
101
  strictCodec: {
148
102
  mode: 'strict',
149
103
  typeSymbol: '@deepseek-ai/dsh-subagent/client#SubagentPromptRequest',
150
104
  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},
105
+ jsonSchema: {"type":"object","properties":{"requestId":{"type":"string","description":"Identity persisted on the accepted message, minted before the call."},"childSessionId":{"type":"string"},"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","childSessionId","delivery","content"],"additionalProperties":false},
152
106
  },
153
107
  },
154
108
  ],
@@ -160,7 +114,7 @@ export const TYPERT_REMOTE = createTypertRemoteInfo({
160
114
  description: 'the accepted message\'s inbox identity.',
161
115
  jsonSchema: {"type":"object","properties":{"messageId":{"type":"string"}},"required":["messageId"],"additionalProperties":true},
162
116
  },
163
- sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":460,"column":9},
117
+ sourceLocation: {"file":"packages/subagent/subagent/src/index.ts","line":414,"column":9},
164
118
  },
165
119
  },
166
120
  }, z)
@@ -3,10 +3,9 @@
3
3
  */
4
4
  import type { Agent, AgentHandle } from '@deepseek-ai/dsh-agent';
5
5
  import type { SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session';
6
- import type { ActivationObserver } from './lifecycle.ts';
7
6
  import type { StructuredAttachment } from './structured.ts';
8
- import type { SubagentResult, SubagentRun } from './types.ts';
9
- /** Process-local slots shared through uninterrupted continuable parent links. */
7
+ import type { SubagentResult, SubagentRun, SubagentRunId } from './types.ts';
8
+ /** Process-local capacity shared by every member of a subagent tree. */
10
9
  export declare class ActivationPool {
11
10
  private readonly slots;
12
11
  /**
@@ -21,37 +20,28 @@ export declare class ActivationPool {
21
20
  * The manager owns admission, execution handles, and resource release.
22
21
  */
23
22
  interface ActivationBase {
24
- /** Shared capacity for this Activation and all its managed descendants. */
25
- readonly pool: ActivationPool;
26
23
  /** Return this epoch's slot after its handle has finished disposal. */
27
24
  readonly releaseSlot: () => void;
28
25
  /** The durable child this Activation is an epoch of. */
29
26
  readonly childId: SessionId;
30
- readonly parent: Agent;
27
+ /** Unique identity shared by this residency epoch's start/end event pair. */
28
+ readonly runId: SubagentRunId;
29
+ /** Provider recorded at creation, retained across cold resumes. */
30
+ readonly provider: string;
31
+ /** Exact live subagent tree root owning this instance and its shared capacity. */
32
+ readonly root: Agent;
33
+ /** Verified creation ancestors, from subagent tree root to direct creator. */
34
+ readonly ancestors: readonly SessionId[];
31
35
  readonly delivery: 'parent' | 'caller';
32
36
  readonly result: PromiseWithResolvers<SubagentResult>;
33
37
  /** Published synchronously before teardown; subsequent callers share this transaction. */
34
38
  closing: Promise<void> | undefined;
35
39
  /**
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.
40
+ * Whether local input was accepted or external startup completed, including
41
+ * any required catalog publication. Until then, teardown owes the parent no
42
+ * settlement notice, even if this epoch's start event was already published.
39
43
  */
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;
44
+ accepted: boolean;
55
45
  }
56
46
  /** Resources retained only for the selected execution kind. */
57
47
  export type ActivationResource = {
@@ -61,7 +51,7 @@ export type ActivationResource = {
61
51
  readonly structured: StructuredAttachment | undefined;
62
52
  /** Latest live failure not superseded by a later committed turn ending. */
63
53
  failureAt: SessionLogOffset | undefined;
64
- /** Renewed when local settlement must recheck input or owned children. */
54
+ /** Renewed when local settlement must recheck input. */
65
55
  poke: PromiseWithResolvers<void>;
66
56
  /**
67
57
  * Whether this child's settlement notice omits its closing text: true while
@@ -5,7 +5,7 @@ import { assertNever } from '@deepseek-ai/dsh-util-values';
5
5
  import { finalAssistantOutput } from "./assistant-output.js";
6
6
  import { epochStopReason } from "./lifecycle.js";
7
7
  import { SubagentError } from "./error.js";
8
- /** Process-local slots shared through uninterrupted continuable parent links. */
8
+ /** Process-local capacity shared by every member of a subagent tree. */
9
9
  export class ActivationPool {
10
10
  slots = new Set();
11
11
  /**
@@ -1,16 +1,23 @@
1
1
  /**
2
2
  * The `subagent` family of the Workspace registry's archive admission: which
3
3
  * subagent descendants of a Session are still inside a turn, and how they
4
- * stop when the Session is archived with its work.
4
+ * stop when the Session is archived with its work. Archived ancestors also
5
+ * block later model steps, including when their Sessions have been released.
5
6
  *
6
7
  * @module @deepseek-ai/dsh-subagent
7
8
  */
8
9
  import type { Context } from '@deepseek-ai/cordis';
10
+ import type { Agent } from '@deepseek-ai/dsh-agent';
11
+ import type { Session, SessionId } from '@deepseek-ai/dsh-session';
12
+ import type { SubagentIdentityProjection } from './projection-types.ts';
9
13
  /**
10
14
  * Answer `workspace/session-activity` with the running subagent descendants of
11
15
  * the asked Session, and `workspace/session-stop` by cancelling each of them
12
- * as their parent would. Both listeners live as long as `ctx`'s fiber.
13
- * @param ctx - context carrying the Agent registry; the Session query service is optional and only supplies labels.
16
+ * as their parent would. Reject subsequent steps beneath archived ancestors.
17
+ * All listeners live as long as `ctx`'s fiber.
18
+ * @param ctx - context carrying the Agent registry.
19
+ * @param residentAncestors - verified creation ancestors for an exact managed Agent, absent before publication or for unmanaged Agents.
20
+ * @param identityOf - ready service-owned descriptor identity reader; absent or invalid descriptors yield no identity.
14
21
  */
15
- export declare function installSubagentArchiveAdmission(ctx: Context): void;
22
+ export declare function installSubagentArchiveAdmission(ctx: Context, residentAncestors: (agent: Agent) => readonly SessionId[] | undefined, identityOf: (session: Session) => SubagentIdentityProjection | undefined): void;
16
23
  //# sourceMappingURL=archive-admission.d.ts.map
@@ -1,80 +1,34 @@
1
1
  /**
2
2
  * The `subagent` family of the Workspace registry's archive admission: which
3
3
  * subagent descendants of a Session are still inside a turn, and how they
4
- * stop when the Session is archived with its work.
4
+ * stop when the Session is archived with its work. Archived ancestors also
5
+ * block later model steps, including when their Sessions have been released.
5
6
  *
6
7
  * @module @deepseek-ai/dsh-subagent
7
8
  */
8
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
9
- if (value !== null && value !== void 0) {
10
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
11
- var dispose, inner;
12
- if (async) {
13
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
14
- dispose = value[Symbol.asyncDispose];
15
- }
16
- if (dispose === void 0) {
17
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
18
- dispose = value[Symbol.dispose];
19
- if (async) inner = dispose;
20
- }
21
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
22
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
23
- env.stack.push({ value: value, dispose: dispose, async: async });
24
- }
25
- else if (async) {
26
- env.stack.push({ async: true });
27
- }
28
- return value;
29
- };
30
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
31
- return function (env) {
32
- function fail(e) {
33
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
34
- env.hasError = true;
35
- }
36
- var r, s = 0;
37
- function next() {
38
- while (r = env.stack.pop()) {
39
- try {
40
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
41
- if (r.dispose) {
42
- var result = r.dispose.call(r.value);
43
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
44
- }
45
- else s |= 1;
46
- }
47
- catch (e) {
48
- fail(e);
49
- }
50
- }
51
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
52
- if (env.hasError) throw env.error;
53
- }
54
- return next();
55
- };
56
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
57
- var e = new Error(message);
58
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
59
- });
60
- import { foldSubagentDescriptor } from "./descriptor.js";
61
9
  /**
62
10
  * Answer `workspace/session-activity` with the running subagent descendants of
63
11
  * the asked Session, and `workspace/session-stop` by cancelling each of them
64
- * as their parent would. Both listeners live as long as `ctx`'s fiber.
65
- * @param ctx - context carrying the Agent registry; the Session query service is optional and only supplies labels.
12
+ * as their parent would. Reject subsequent steps beneath archived ancestors.
13
+ * All listeners live as long as `ctx`'s fiber.
14
+ * @param ctx - context carrying the Agent registry.
15
+ * @param residentAncestors - verified creation ancestors for an exact managed Agent, absent before publication or for unmanaged Agents.
16
+ * @param identityOf - ready service-owned descriptor identity reader; absent or invalid descriptors yield no identity.
66
17
  */
67
- export function installSubagentArchiveAdmission(ctx) {
18
+ export function installSubagentArchiveAdmission(ctx, residentAncestors, identityOf) {
19
+ const ancestorsOf = (agent) => residentAncestors(agent) ?? headerAncestors(ctx, agent);
20
+ const runningDescendants = (sessionId) => ctx.agents.list()
21
+ .filter(agent => agent.status === 'running' && ancestorsOf(agent).includes(sessionId));
68
22
  ctx.on('workspace/session-activity', async ({ sessionId }, next) => {
69
- const running = runningDescendants(ctx, sessionId);
23
+ const running = runningDescendants(sessionId);
70
24
  const rest = await next();
71
25
  if (running.length === 0)
72
26
  return rest;
73
- const own = { kind: 'subagent', items: await Promise.all(running.map(child => describe(ctx, child))) };
27
+ const own = { kind: 'subagent', items: running.map(child => describe(child, identityOf(child.session))) };
74
28
  return [own, ...rest];
75
29
  });
76
30
  ctx.on('workspace/session-stop', ({ sessionId }) => {
77
- for (const child of runningDescendants(ctx, sessionId)) {
31
+ for (const child of runningDescendants(sessionId)) {
78
32
  try {
79
33
  child.cancel({ kind: 'parent' });
80
34
  }
@@ -84,68 +38,38 @@ export function installSubagentArchiveAdmission(ctx) {
84
38
  }
85
39
  }
86
40
  });
41
+ ctx.on('agent/pre-step', ({ agent }, next) => {
42
+ const archived = ctx.get('workspaceRegistry')?.archivedSessionIds;
43
+ return archived !== undefined && ancestorsOf(agent).some(id => archived.includes(id))
44
+ ? Promise.resolve({ kind: 'reject' })
45
+ : next();
46
+ });
87
47
  }
88
48
  /**
89
- * Live subagent descendants inside a turn, by durable lineage: a child whose
90
- * header names its parent and carries the subagent origin this package
91
- * records, at any depth. A fork shares the lineage field without the origin
92
- * and is an independent conversation, so it never holds its source. Lineage
93
- * is read as data, so a damaged header chain that loops is visited once.
49
+ * Header-only ancestry for Agents without a published Activation. Include an
50
+ * offline direct creator; ordinary forks stop the chain and cycles terminate.
94
51
  */
95
- function runningDescendants(ctx, rootId) {
96
- const childrenOf = new Map();
97
- for (const agent of ctx.agents.list()) {
98
- const { parentSession, origin } = agent.session.header;
99
- if (parentSession === undefined || origin !== 'subagent')
100
- continue;
101
- const siblings = childrenOf.get(parentSession) ?? [];
102
- siblings.push(agent);
103
- childrenOf.set(parentSession, siblings);
104
- }
105
- const running = [];
106
- const pending = [rootId];
107
- const visited = new Set();
108
- while (pending.length > 0) {
109
- const parentId = pending.shift();
110
- if (visited.has(parentId))
111
- continue;
52
+ function headerAncestors(ctx, agent) {
53
+ const ancestors = [];
54
+ const visited = new Set([agent.id]);
55
+ let header = agent.session.header;
56
+ while (header.origin === 'subagent' && header.parentSession !== undefined && !visited.has(header.parentSession)) {
57
+ const parentId = header.parentSession;
58
+ ancestors.push(parentId);
112
59
  visited.add(parentId);
113
- for (const child of childrenOf.get(parentId) ?? []) {
114
- if (child.status === 'running')
115
- running.push(child);
116
- pending.push(child.id);
117
- }
60
+ const parent = ctx.agents.get(parentId)?.session;
61
+ if (parent === undefined)
62
+ break;
63
+ header = parent.header;
118
64
  }
119
- return running;
65
+ return ancestors;
120
66
  }
121
67
  /**
122
- * The child's activity item: its id, plus the durable creation label its
123
- * descriptor carries, read through a live Session observation. Without the
124
- * Session query service, or with a descriptor that is absent or unreadable,
125
- * the item names the child by id alone.
68
+ * Report the child's current projected label only when its descriptor belongs
69
+ * to the child's own log; inherited, absent, or invalid identities yield the id alone.
126
70
  */
127
- async function describe(ctx, child) {
128
- const query = ctx.get('sessionQuery');
129
- if (query === undefined)
130
- return { id: child.id };
131
- try {
132
- const env_1 = { stack: [], error: void 0, hasError: false };
133
- try {
134
- const observation = __addDisposableResource(env_1, await query.observeSession(child.id, { projectionMode: 'none' }), false);
135
- const label = foldSubagentDescriptor(observation.events.slice(observation.inheritedEventCount))?.label;
136
- return label === undefined ? { id: child.id } : { id: child.id, label };
137
- }
138
- catch (e_1) {
139
- env_1.error = e_1;
140
- env_1.hasError = true;
141
- }
142
- finally {
143
- __disposeResources(env_1);
144
- }
145
- }
146
- catch {
147
- // A damaged descriptor is data damage in the child; the report still names the child.
148
- return { id: child.id };
149
- }
71
+ function describe(child, identity) {
72
+ const label = identity !== undefined && child.session.isOwnSeq(identity.seq) ? identity.label : undefined;
73
+ return label === undefined ? { id: child.id } : { id: child.id, label };
150
74
  }
151
75
  //# sourceMappingURL=archive-admission.js.map
@@ -8,7 +8,7 @@
8
8
  import type { Context } from '@deepseek-ai/cordis';
9
9
  import type { Agent, AgentOptions, CreateAgentOptions } from '@deepseek-ai/dsh-agent';
10
10
  import type { SandboxMode } from '@deepseek-ai/dsh-sandbox';
11
- import type { Session, SessionId } from '@deepseek-ai/dsh-session';
11
+ import type { Session } from '@deepseek-ai/dsh-session';
12
12
  import type { ToolRestriction } from '@deepseek-ai/dsh-tools';
13
13
  import type { ApprovalPolicy } from '@deepseek-ai/dsh-user-approval';
14
14
  /** Thrown when starting a child would exceed the requested depth cap. */
@@ -66,7 +66,7 @@ export declare function resolveChildAgentOptions(parent: Agent, requested: Agent
66
66
  export declare function childSessionMeta(parent: Agent, childDepth: number, isSeeded: boolean, selectedPreset?: string): NonNullable<CreateAgentOptions['meta']>;
67
67
  /** The scoped composition a child agent's creation window applies. */
68
68
  export interface ChildComposition {
69
- /** Independently mounted preset; omission shares the parent's standing generation. */
69
+ /** Preset to mount; omission shares a supplied creator or uses host composition. */
70
70
  readonly agentPreset?: string | undefined;
71
71
  /** Historical descriptor persona reapplied only during cold resume. */
72
72
  readonly persona?: string | undefined;
@@ -88,15 +88,16 @@ export declare const SUBAGENT_DELEGATION_CONTEXT: string;
88
88
  export declare const SUBAGENT_DELEGATION_INTERACTIVE_CONTEXT: string;
89
89
  /**
90
90
  * Compose a child before publication and restore historical descriptor overrides.
91
- * Explicit selection mounts the named preset; omission synchronously joins the
92
- * parent's current generation. Registrations belong to the child's scope.
91
+ * Explicit selection mounts the named preset. Omission joins a supplied creator's
92
+ * current generation; a restored child without a saved preset uses host composition.
93
+ * Registrations belong to the child's scope.
93
94
  * @param childCtx - the child agent's scoped creation context.
94
- * @param parent - the delegating parent used when no preset is selected.
95
+ * @param parent - creator for fresh delegation; absent during target-only restoration.
95
96
  * @param composition - independent preset and any overrides read from a historical descriptor.
96
97
  * @param approvalPolicy - the child's effective approval policy, selecting its delegation statement.
97
98
  * @returns A promise when mounting an independent preset; otherwise completes synchronously.
98
99
  */
99
- export declare function applyChildComposition(childCtx: Context, parent: Agent, composition: ChildComposition, approvalPolicy: ApprovalPolicy | undefined): void | Promise<void>;
100
+ export declare function applyChildComposition(childCtx: Context, parent: Agent | undefined, composition: ChildComposition, approvalPolicy: ApprovalPolicy | undefined): void | Promise<void>;
100
101
  /** How a delegated child's approval policy is seeded at creation. */
101
102
  export type DelegatedApprovalPolicy = 'never' | 'inherit';
102
103
  /** Policy seeded onto a child session's log at the delegation boundary. */
@@ -141,15 +142,4 @@ export declare function captureDelegatedPolicyOverrides(parent: Agent, delegated
141
142
  * @param overrides - the policy captured at delegation.
142
143
  */
143
144
  export declare function appendDelegatedPolicyOverrides(childSession: Session, overrides: DelegatedPolicyOverrides): void;
144
- /** Identity and lineage inputs shared by every in-process child creation. */
145
- export interface ChildCreateInputs {
146
- /** The child's reserved session id. */
147
- readonly sessionId: SessionId;
148
- /** The delegating parent agent. */
149
- readonly parent: Agent;
150
- /** The resolved delegation depth. */
151
- readonly childDepth: number;
152
- /** How many leading seed events came from the parent's log. */
153
- readonly lineageSeedLength: number;
154
- }
155
145
  //# sourceMappingURL=child-agent.d.ts.map
@@ -140,10 +140,11 @@ export const SUBAGENT_DELEGATION_INTERACTIVE_CONTEXT = 'You are a delegated suba
140
140
  + 'state the limitation in your reply so the delegating agent can handle it.';
141
141
  /**
142
142
  * Compose a child before publication and restore historical descriptor overrides.
143
- * Explicit selection mounts the named preset; omission synchronously joins the
144
- * parent's current generation. Registrations belong to the child's scope.
143
+ * Explicit selection mounts the named preset. Omission joins a supplied creator's
144
+ * current generation; a restored child without a saved preset uses host composition.
145
+ * Registrations belong to the child's scope.
145
146
  * @param childCtx - the child agent's scoped creation context.
146
- * @param parent - the delegating parent used when no preset is selected.
147
+ * @param parent - creator for fresh delegation; absent during target-only restoration.
147
148
  * @param composition - independent preset and any overrides read from a historical descriptor.
148
149
  * @param approvalPolicy - the child's effective approval policy, selecting its delegation statement.
149
150
  * @returns A promise when mounting an independent preset; otherwise completes synchronously.
@@ -158,7 +159,8 @@ export function applyChildComposition(childCtx, parent, composition, approvalPol
158
159
  applyChildOverrides(childCtx, composition, approvalPolicy);
159
160
  });
160
161
  }
161
- childCtx.get('agentPresets')?.composeFrom(childCtx, parent.ctx);
162
+ if (parent !== undefined)
163
+ childCtx.get('agentPresets')?.composeFrom(childCtx, parent.ctx);
162
164
  applyChildOverrides(childCtx, composition, approvalPolicy);
163
165
  }
164
166
  function applyChildOverrides(childCtx, composition, approvalPolicy) {
@@ -29,6 +29,8 @@ export interface SubagentSettledMessageSource {
29
29
  readonly form: 'notice';
30
30
  /** One-line account of how the child ended. */
31
31
  readonly summary: string;
32
+ /** Exact execution stop reason; absent on historical notices. Writers always include it. */
33
+ readonly stopReason?: SubagentResult['stopReason'];
32
34
  /** Session id of the child that settled. */
33
35
  readonly senderSessionId: SessionId;
34
36
  }
@@ -39,26 +41,25 @@ declare module '@deepseek-ai/dsh-llm' {
39
41
  }
40
42
  }
41
43
  /**
42
- * Build the model-visible and durable representation of one adjacent-Agent message.
44
+ * Build the model-visible and durable representation of one Agent message.
43
45
  * @param sender - exact live Agent that authored the message.
44
46
  * @param content - model-visible message blocks supplied by the sender.
45
47
  * @returns the durable user-message representation delivered to the recipient.
46
48
  */
47
49
  export declare function createAgentMessage(sender: Agent, content: ContentBlock[]): ReturnType<typeof createUserMessage>;
48
50
  /**
49
- * Append adjacent-Agent return guidance to a continuable child's initial task.
50
- * @param parentId - durable parent session id named in the guidance.
51
+ * Append automatic result-delivery guidance to a parent-delivered child's initial task.
51
52
  * @param prompt - initial model-visible task blocks.
52
- * @returns task blocks followed by the continuable return guidance.
53
+ * @returns task blocks followed by the result-delivery guidance.
53
54
  */
54
- export declare function withContinuableReturnGuidance(parentId: SessionId, prompt: ContentBlock[]): ContentBlock[];
55
+ export declare function withResultDeliveryGuidance(prompt: ContentBlock[]): ContentBlock[];
55
56
  /**
56
57
  * Build the runtime-owned settlement notice from the child's nonempty closing text.
57
58
  * @param childId - durable child session id named in the notice.
58
59
  * @param terminal - recorded terminal state for the settled Activation.
59
60
  * @param continuable - whether the child can accept another task.
60
- * @param omitClosingText - replace the closing text with a note that the child's
61
- * last message to the parent already carries it.
61
+ * @param omitClosingText - replace the closing text when the child's last action
62
+ * was a message to its direct parent.
62
63
  * @returns the durable user-message representation delivered to the parent.
63
64
  */
64
65
  export declare function createSettlementMessage(childId: SessionId, terminal: SubagentResult, continuable?: boolean, omitClosingText?: boolean): ReturnType<typeof createUserMessage>;