@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.
- package/README.i18n.yaml +39 -24
- package/README.md +41 -20
- package/README.zh.md +41 -20
- package/lib/index.js +573 -872
- package/lib/typert.host.js +64 -120
- package/lib/typert.remote-client.d.ts +3 -3
- package/lib/typert.remote-client.js +17 -63
- package/lib/types/activation.d.ts +15 -25
- package/lib/types/activation.js +1 -1
- package/lib/types/archive-admission.d.ts +11 -4
- package/lib/types/archive-admission.js +39 -115
- package/lib/types/child-agent.d.ts +7 -17
- package/lib/types/child-agent.js +6 -4
- package/lib/types/continuation-messages.d.ts +8 -7
- package/lib/types/continuation-messages.js +12 -14
- package/lib/types/control-types.d.ts +7 -28
- package/lib/types/control.d.ts +0 -4
- package/lib/types/control.js +1 -5
- package/lib/types/descriptor.d.ts +1 -1
- package/lib/types/descriptor.js +1 -1
- package/lib/types/index.d.ts +46 -95
- package/lib/types/index.js +83 -146
- package/lib/types/lifecycle.d.ts +9 -38
- package/lib/types/lifecycle.js +5 -31
- package/lib/types/manager.d.ts +74 -109
- package/lib/types/manager.js +394 -568
- package/lib/types/projection-types.d.ts +14 -6
- package/lib/types/projection.d.ts +2 -2
- package/lib/types/structured.d.ts +1 -1
- package/lib/types/structured.js +2 -2
- package/lib/types/types.d.ts +16 -28
- package/lib/types/types.js +2 -4
- package/package.json +53 -57
- package/lib/types/internal.d.ts +0 -58
- package/lib/types/internal.js +0 -58
|
@@ -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
|
|
7
|
-
const
|
|
8
|
-
let
|
|
9
|
-
const
|
|
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
|
|
39
|
-
const
|
|
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/
|
|
54
|
+
'subagents/interruptByUser': {
|
|
67
55
|
service: 'subagents',
|
|
68
|
-
description: 'Remote face of {@link interrupt}
|
|
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:
|
|
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:
|
|
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:
|
|
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":
|
|
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
|
|
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: '
|
|
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."},"
|
|
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."},"
|
|
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":
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
package/lib/types/activation.js
CHANGED
|
@@ -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
|
|
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.
|
|
13
|
-
*
|
|
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.
|
|
65
|
-
*
|
|
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(
|
|
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:
|
|
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(
|
|
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
|
-
*
|
|
90
|
-
*
|
|
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
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
60
|
+
const parent = ctx.agents.get(parentId)?.session;
|
|
61
|
+
if (parent === undefined)
|
|
62
|
+
break;
|
|
63
|
+
header = parent.header;
|
|
118
64
|
}
|
|
119
|
-
return
|
|
65
|
+
return ancestors;
|
|
120
66
|
}
|
|
121
67
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
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
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
92
|
-
*
|
|
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 -
|
|
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
|
package/lib/types/child-agent.js
CHANGED
|
@@ -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
|
|
144
|
-
*
|
|
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 -
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
53
|
+
* @returns task blocks followed by the result-delivery guidance.
|
|
53
54
|
*/
|
|
54
|
-
export declare function
|
|
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
|
|
61
|
-
*
|
|
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>;
|