@deepseek-ai/dsh-subagent 0.1.1-rc.2 → 0.1.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +105 -75
- package/README.zh.md +110 -84
- package/lib/index.js +910 -433
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1016 -0
- package/lib/typert.remote-client.d.ts +27 -0
- package/lib/typert.remote-client.js +242 -0
- package/lib/types/child-agent.d.ts +14 -3
- package/lib/types/child-agent.js +48 -10
- package/lib/types/client.d.ts +2 -1
- package/lib/types/client.js +1 -1
- package/lib/types/continuation.d.ts +4 -2
- package/lib/types/continuation.js +124 -46
- package/lib/types/control-types.d.ts +160 -0
- package/lib/types/control-types.js +9 -0
- package/lib/types/control.d.ts +83 -0
- package/lib/types/control.js +133 -0
- package/lib/types/descriptor.d.ts +6 -1
- package/lib/types/descriptor.js +6 -2
- package/lib/types/index.d.ts +60 -26
- package/lib/types/index.js +430 -299
- package/lib/types/list-children.d.ts +10 -58
- package/lib/types/list-children.js +161 -97
- package/lib/types/out-of-process.d.ts +3 -2
- package/lib/types/out-of-process.js +11 -3
- package/lib/types/run-settlement.js +7 -3
- package/lib/types/types.d.ts +18 -0
- package/package.json +63 -37
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-safe subagent catalog and control vocabulary: the durable direct-child
|
|
3
|
+
* row both the listing and the browser catalog answer with, plus the
|
|
4
|
+
* browser-facing control surface's prompt, receipts, and failures.
|
|
5
|
+
*
|
|
6
|
+
* @module @deepseek-ai/dsh-subagent/control-types
|
|
7
|
+
*/
|
|
8
|
+
import type { EncodedImageAttachment } from '@deepseek-ai/dsh-attachment/types';
|
|
9
|
+
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
10
|
+
import type { MessageId } from '@deepseek-ai/dsh-llm/brand';
|
|
11
|
+
import type { ContentBlock } from '@deepseek-ai/dsh-llm/types';
|
|
12
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
13
|
+
/**
|
|
14
|
+
* Client-minted identity of one browser prompt, persisted on the exact accepted
|
|
15
|
+
* message. It carries the Session Controller's `session-request-id` brand so a
|
|
16
|
+
* subagent prompt and an ordinary Session prompt share one identity
|
|
17
|
+
* vocabulary; that package depends on this one, so the brand is spelled here
|
|
18
|
+
* rather than imported.
|
|
19
|
+
*/
|
|
20
|
+
export type SubagentPromptRequestId = Branded<'session-request-id'>;
|
|
21
|
+
/**
|
|
22
|
+
* One durable direct-child row, ordered by header `createdAt` with ties broken
|
|
23
|
+
* on id. Only a candidate whose durable header has `origin: 'subagent'` is
|
|
24
|
+
* interpreted. A served `subagent` projection value produces a `child`; a
|
|
25
|
+
* settled candidate whose fold served no identity produces a `diagnostic`; a
|
|
26
|
+
* running candidate without one is omitted — its descriptor may not be
|
|
27
|
+
* appended yet (the creation window). Diagnostics relay the projection fold's
|
|
28
|
+
* outcome or a failed read, never a per-child event scan, and never expose
|
|
29
|
+
* model-hidden descriptor content.
|
|
30
|
+
*/
|
|
31
|
+
export type SubagentListEntry = {
|
|
32
|
+
readonly kind: 'child';
|
|
33
|
+
/** The durable child session id, stable across Activations. */
|
|
34
|
+
readonly id: SessionId;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the child is live at the moment its reader sampled it: the
|
|
37
|
+
* durable listing reads the Session store (`running` means the logical
|
|
38
|
+
* record is resident, `inactive` that it exists only in persistence),
|
|
39
|
+
* while the browser catalog re-samples the child's Agent driver. Neither
|
|
40
|
+
* encodes a durable outcome, and a continuable child may still reject
|
|
41
|
+
* delivery as an ownership conflict.
|
|
42
|
+
*/
|
|
43
|
+
readonly activity: 'running' | 'inactive';
|
|
44
|
+
/** Whether a direct descendant has durable `origin: 'subagent'`. */
|
|
45
|
+
readonly hasChildren: boolean;
|
|
46
|
+
} & ({
|
|
47
|
+
/** A terminal one-shot child. */
|
|
48
|
+
readonly mode: 'one-shot';
|
|
49
|
+
/** Optional durable creation label from the child's descriptor. */
|
|
50
|
+
readonly label?: string;
|
|
51
|
+
} | {
|
|
52
|
+
/** A resumable conversation. */
|
|
53
|
+
readonly mode: 'continuable';
|
|
54
|
+
/** Durable creation label from the child's descriptor. */
|
|
55
|
+
readonly label: string;
|
|
56
|
+
}) | {
|
|
57
|
+
readonly kind: 'diagnostic';
|
|
58
|
+
/** The candidate's session id. */
|
|
59
|
+
readonly id: SessionId;
|
|
60
|
+
/**
|
|
61
|
+
* Why the candidate has no `child` row: `corrupt` for a settled candidate
|
|
62
|
+
* whose projection fold served no identity (a missing, malformed, or
|
|
63
|
+
* unrecognized-version descriptor — deliberately undistinguished), and
|
|
64
|
+
* for any candidate whose log makes a registered unit's fold or schema
|
|
65
|
+
* throw (deterministic data damage, contained per child); `unavailable`
|
|
66
|
+
* when the candidate's Session observation was absent or transiently
|
|
67
|
+
* unreadable (retried on the next listing). `unsupported` is never produced; it remains in the
|
|
68
|
+
* union for consumers that route on it.
|
|
69
|
+
*/
|
|
70
|
+
readonly reason: 'corrupt' | 'unsupported' | 'unavailable';
|
|
71
|
+
};
|
|
72
|
+
/** Complete direct-child catalog plus the delivery-time parent availability hint. */
|
|
73
|
+
export interface SubagentCatalog {
|
|
74
|
+
readonly entries: readonly SubagentListEntry[];
|
|
75
|
+
readonly parentAvailable: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** Durable parent/child address that selects subagent transport in the client. */
|
|
78
|
+
export type SubagentAddress = {
|
|
79
|
+
readonly parentSessionId: SessionId;
|
|
80
|
+
readonly childSessionId: SessionId;
|
|
81
|
+
} & ({
|
|
82
|
+
readonly mode: 'one-shot';
|
|
83
|
+
} | {
|
|
84
|
+
readonly mode: 'continuable';
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* One browser-encoded upload as the Session prompt wire carries it: the shared
|
|
88
|
+
* attachment vocabulary under the content-block tag.
|
|
89
|
+
*/
|
|
90
|
+
export interface EncodedImagePromptBlock extends EncodedImageAttachment {
|
|
91
|
+
readonly type: 'image';
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* One block a browser prompt may carry. The encoded upload is accepted by the
|
|
95
|
+
* wire and refused by the Host, so the Client narrows nothing: a caller that
|
|
96
|
+
* attaches an image is answered, not silently stripped.
|
|
97
|
+
*/
|
|
98
|
+
export type SubagentPromptContentPart = ContentBlock | EncodedImagePromptBlock;
|
|
99
|
+
/** One human message addressed to a continuable direct child. */
|
|
100
|
+
export interface SubagentPromptRequest {
|
|
101
|
+
/** Identity persisted on the accepted message, minted before the call. */
|
|
102
|
+
readonly requestId: SubagentPromptRequestId;
|
|
103
|
+
readonly parentSessionId: SessionId;
|
|
104
|
+
readonly childSessionId: SessionId;
|
|
105
|
+
/** Required discriminator retained from the browser control address. */
|
|
106
|
+
readonly mode: 'continuable';
|
|
107
|
+
/** Content proposed as the child's user message; images are refused. */
|
|
108
|
+
readonly content: readonly SubagentPromptContentPart[];
|
|
109
|
+
/** Optional browser zone sampled for this exact human prompt. */
|
|
110
|
+
readonly clientTimeZone?: string;
|
|
111
|
+
}
|
|
112
|
+
/** Inbox identity returned once the continuation accepts one human message. */
|
|
113
|
+
export interface SubagentPromptReceipt {
|
|
114
|
+
readonly messageId: MessageId;
|
|
115
|
+
}
|
|
116
|
+
/** Uniform acknowledgement that one interrupt request was admitted. */
|
|
117
|
+
export interface SubagentInterruptReceipt {
|
|
118
|
+
readonly accepted: true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Failure details the control surface answers with. The catalog read, the
|
|
122
|
+
* prompt, and the interrupt produce these codes; a Client fabricates
|
|
123
|
+
* `subagent/not-resumable` and `subagent/delivery-unavailable` for a one-shot
|
|
124
|
+
* address it refuses before the call, so both planes read one vocabulary.
|
|
125
|
+
*/
|
|
126
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
127
|
+
interface RemoteErrorDetailsMap {
|
|
128
|
+
/** A browser-supplied zone is neither UTC nor a canonical IANA name. */
|
|
129
|
+
'subagent/invalid-time-zone': {
|
|
130
|
+
readonly value: string;
|
|
131
|
+
};
|
|
132
|
+
/** No live Agent carries the addressed parent session. */
|
|
133
|
+
'subagent/parent-unavailable': {
|
|
134
|
+
readonly parentSessionId: SessionId;
|
|
135
|
+
};
|
|
136
|
+
/** The addressed child cannot take a continuation. */
|
|
137
|
+
'subagent/not-resumable': {
|
|
138
|
+
readonly childSessionId: SessionId;
|
|
139
|
+
};
|
|
140
|
+
/** The claimed parent does not own the addressed child. */
|
|
141
|
+
'subagent/unauthorized': {
|
|
142
|
+
readonly childSessionId: SessionId;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* The continuation admits no attachment. `reason` names the refused plane
|
|
146
|
+
* for the caller's copy, as the Session prompt's attachment refusals do.
|
|
147
|
+
*/
|
|
148
|
+
'subagent/attachment-unsupported': {
|
|
149
|
+
readonly childSessionId: SessionId;
|
|
150
|
+
readonly reason: string;
|
|
151
|
+
};
|
|
152
|
+
/** The child exists but its inbox cannot admit the message now. */
|
|
153
|
+
'subagent/delivery-unavailable': {
|
|
154
|
+
readonly childSessionId: SessionId;
|
|
155
|
+
};
|
|
156
|
+
/** The deployment mounts no session-projection registry. */
|
|
157
|
+
'subagent/projections-unavailable': {};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=control-types.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-safe subagent catalog and control vocabulary: the durable direct-child
|
|
3
|
+
* row both the listing and the browser catalog answer with, plus the
|
|
4
|
+
* browser-facing control surface's prompt, receipts, and failures.
|
|
5
|
+
*
|
|
6
|
+
* @module @deepseek-ai/dsh-subagent/control-types
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=control-types.js.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-facing subagent control assembly: the catalog view sampled against
|
|
3
|
+
* the live Agent registry, one browser zone's validation, and the stable
|
|
4
|
+
* failure codes the Remote surface answers with.
|
|
5
|
+
*
|
|
6
|
+
* @module @deepseek-ai/dsh-subagent
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
9
|
+
import type { ContentBlock } from '@deepseek-ai/dsh-llm';
|
|
10
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import type { SubagentCatalog, SubagentListEntry, SubagentPromptContentPart } from './control-types.ts';
|
|
13
|
+
declare const CONTROL_ID_SCHEMAS: {
|
|
14
|
+
readonly 'subagent.list': z.ZodObject<{
|
|
15
|
+
parentSessionId: z.ZodString;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
readonly 'subagent.prompt': z.ZodObject<{
|
|
18
|
+
parentSessionId: z.ZodString;
|
|
19
|
+
childSessionId: z.ZodString;
|
|
20
|
+
mode: z.ZodLiteral<"continuable">;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
readonly 'subagent.interrupt': z.ZodObject<{
|
|
23
|
+
parentSessionId: z.ZodString;
|
|
24
|
+
childSessionId: z.ZodString;
|
|
25
|
+
mode: z.ZodLiteral<"continuable">;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Apply the subagent payload checks that are stricter than generated
|
|
30
|
+
* branded-string codecs.
|
|
31
|
+
* @param method - method name carried in the failure message.
|
|
32
|
+
* @param payload - decoded control fields to validate.
|
|
33
|
+
* @throws {RemoteError} `gateway/bad-request` with the original Zod issues.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateControlRequest(method: keyof typeof CONTROL_ID_SCHEMAS, payload: unknown): void;
|
|
36
|
+
/**
|
|
37
|
+
* Admit the content one continuation may deliver, refusing every image.
|
|
38
|
+
*
|
|
39
|
+
* The blocks become the child's user message verbatim, and this surface admits
|
|
40
|
+
* no attachment: nothing here registers encoded bytes with the attachment
|
|
41
|
+
* service, so an image would reach the child as a reference nothing resolves.
|
|
42
|
+
* The wire accepts the encoded upload so this refusal — not a Client that
|
|
43
|
+
* strips the block — is what the caller is answered with. Other block types
|
|
44
|
+
* still cross unnarrowed.
|
|
45
|
+
* @param childSessionId - the addressed child, named by the refusal.
|
|
46
|
+
* @param content - blocks the caller asked to deliver.
|
|
47
|
+
* @returns the admitted blocks, in order, as the durable content vocabulary.
|
|
48
|
+
* @throws {RemoteError} `subagent/attachment-unsupported` when any block is an image.
|
|
49
|
+
*/
|
|
50
|
+
export declare function admitPromptContent(childSessionId: SessionId, content: readonly SubagentPromptContentPart[]): ContentBlock[];
|
|
51
|
+
/**
|
|
52
|
+
* Project one durable listing onto the catalog view, replacing each row's
|
|
53
|
+
* store-derived activity with the live Agent driver's status and reporting
|
|
54
|
+
* whether the exact parent Agent is live. Without an Agent registry no driver
|
|
55
|
+
* runs at all, so every row is inactive and the parent is unavailable.
|
|
56
|
+
* @param ctx - Host context that may carry the Agent registry.
|
|
57
|
+
* @param parentSessionId - the listed parent.
|
|
58
|
+
* @param entries - the durable direct-child listing.
|
|
59
|
+
* @returns the catalog view answered to one browser.
|
|
60
|
+
*/
|
|
61
|
+
export declare function catalogView(ctx: Context, parentSessionId: SessionId, entries: readonly SubagentListEntry[]): SubagentCatalog;
|
|
62
|
+
/**
|
|
63
|
+
* Refuse one catalog read while preserving cancellation and a missing
|
|
64
|
+
* projections registry as distinct failures.
|
|
65
|
+
* @param error - the thrown value.
|
|
66
|
+
* @param signal - the caller's cancellation.
|
|
67
|
+
* @returns Never — the refusal is thrown.
|
|
68
|
+
* @throws {RemoteError} always.
|
|
69
|
+
*/
|
|
70
|
+
export declare function rejectCatalogRead(error: unknown, signal: AbortSignal): never;
|
|
71
|
+
/**
|
|
72
|
+
* Refuse one continuation prompt without exposing provider detail: admission
|
|
73
|
+
* failures the caller can act on keep their own code, everything else is
|
|
74
|
+
* internal.
|
|
75
|
+
* @param error - the thrown value.
|
|
76
|
+
* @param childSessionId - the addressed child.
|
|
77
|
+
* @param signal - the caller's cancellation.
|
|
78
|
+
* @returns Never — the refusal is thrown.
|
|
79
|
+
* @throws {RemoteError} always.
|
|
80
|
+
*/
|
|
81
|
+
export declare function rejectPrompt(error: unknown, childSessionId: SessionId, signal: AbortSignal): never;
|
|
82
|
+
export {};
|
|
83
|
+
//# sourceMappingURL=control.d.ts.map
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-facing subagent control assembly: the catalog view sampled against
|
|
3
|
+
* the live Agent registry, one browser zone's validation, and the stable
|
|
4
|
+
* failure codes the Remote surface answers with.
|
|
5
|
+
*
|
|
6
|
+
* @module @deepseek-ai/dsh-subagent
|
|
7
|
+
*/
|
|
8
|
+
import { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { SubagentError } from "./error.js";
|
|
11
|
+
const SESSION_ID_SCHEMA = z.string().min(1);
|
|
12
|
+
const CONTROL_ID_SCHEMAS = {
|
|
13
|
+
'subagent.list': z.object({ parentSessionId: SESSION_ID_SCHEMA }),
|
|
14
|
+
'subagent.prompt': z.object({
|
|
15
|
+
parentSessionId: SESSION_ID_SCHEMA,
|
|
16
|
+
childSessionId: SESSION_ID_SCHEMA,
|
|
17
|
+
mode: z.literal('continuable'),
|
|
18
|
+
}),
|
|
19
|
+
'subagent.interrupt': z.object({
|
|
20
|
+
parentSessionId: SESSION_ID_SCHEMA,
|
|
21
|
+
childSessionId: SESSION_ID_SCHEMA,
|
|
22
|
+
mode: z.literal('continuable'),
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Apply the subagent payload checks that are stricter than generated
|
|
27
|
+
* branded-string codecs.
|
|
28
|
+
* @param method - method name carried in the failure message.
|
|
29
|
+
* @param payload - decoded control fields to validate.
|
|
30
|
+
* @throws {RemoteError} `gateway/bad-request` with the original Zod issues.
|
|
31
|
+
*/
|
|
32
|
+
export function validateControlRequest(method, payload) {
|
|
33
|
+
const parsed = CONTROL_ID_SCHEMAS[method].safeParse(payload);
|
|
34
|
+
if (!parsed.success) {
|
|
35
|
+
throw new RemoteError('gateway/bad-request', `invalid payload for ${method}`, { issues: parsed.error.issues });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Admit the content one continuation may deliver, refusing every image.
|
|
40
|
+
*
|
|
41
|
+
* The blocks become the child's user message verbatim, and this surface admits
|
|
42
|
+
* no attachment: nothing here registers encoded bytes with the attachment
|
|
43
|
+
* service, so an image would reach the child as a reference nothing resolves.
|
|
44
|
+
* The wire accepts the encoded upload so this refusal — not a Client that
|
|
45
|
+
* strips the block — is what the caller is answered with. Other block types
|
|
46
|
+
* still cross unnarrowed.
|
|
47
|
+
* @param childSessionId - the addressed child, named by the refusal.
|
|
48
|
+
* @param content - blocks the caller asked to deliver.
|
|
49
|
+
* @returns the admitted blocks, in order, as the durable content vocabulary.
|
|
50
|
+
* @throws {RemoteError} `subagent/attachment-unsupported` when any block is an image.
|
|
51
|
+
*/
|
|
52
|
+
export function admitPromptContent(childSessionId, content) {
|
|
53
|
+
const admitted = [];
|
|
54
|
+
for (const block of content) {
|
|
55
|
+
if (block.type === 'image') {
|
|
56
|
+
throw new RemoteError('subagent/attachment-unsupported', 'subagent continuation does not accept images', { childSessionId, reason: 'SUBAGENT_IMAGE_UNSUPPORTED' });
|
|
57
|
+
}
|
|
58
|
+
admitted.push(block);
|
|
59
|
+
}
|
|
60
|
+
return admitted;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Project one durable listing onto the catalog view, replacing each row's
|
|
64
|
+
* store-derived activity with the live Agent driver's status and reporting
|
|
65
|
+
* whether the exact parent Agent is live. Without an Agent registry no driver
|
|
66
|
+
* runs at all, so every row is inactive and the parent is unavailable.
|
|
67
|
+
* @param ctx - Host context that may carry the Agent registry.
|
|
68
|
+
* @param parentSessionId - the listed parent.
|
|
69
|
+
* @param entries - the durable direct-child listing.
|
|
70
|
+
* @returns the catalog view answered to one browser.
|
|
71
|
+
*/
|
|
72
|
+
export function catalogView(ctx, parentSessionId, entries) {
|
|
73
|
+
const agents = ctx.get('agents');
|
|
74
|
+
return {
|
|
75
|
+
entries: entries.map((entry) => entry.kind === 'child'
|
|
76
|
+
? { ...entry, activity: agents?.get(entry.id)?.status === 'running' ? 'running' : 'inactive' }
|
|
77
|
+
: entry),
|
|
78
|
+
parentAvailable: agents?.get(parentSessionId) !== undefined,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Refuse one catalog read while preserving cancellation and a missing
|
|
83
|
+
* projections registry as distinct failures.
|
|
84
|
+
* @param error - the thrown value.
|
|
85
|
+
* @param signal - the caller's cancellation.
|
|
86
|
+
* @returns Never — the refusal is thrown.
|
|
87
|
+
* @throws {RemoteError} always.
|
|
88
|
+
*/
|
|
89
|
+
export function rejectCatalogRead(error, signal) {
|
|
90
|
+
if (isCancellation(error, signal)) {
|
|
91
|
+
throw new RemoteError('gateway/cancelled', 'subagent catalog read was cancelled', {}, { cause: error });
|
|
92
|
+
}
|
|
93
|
+
if (error instanceof SubagentError && error.code === 'SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE') {
|
|
94
|
+
throw new RemoteError('subagent/projections-unavailable', 'subagent catalog is unavailable: this deployment does not mount the sessionProjections registry (load @deepseek-ai/dsh-session-projection)', {}, { cause: error });
|
|
95
|
+
}
|
|
96
|
+
throw new RemoteError('gateway/internal', 'subagent catalog read failed', {}, { cause: error });
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Refuse one continuation prompt without exposing provider detail: admission
|
|
100
|
+
* failures the caller can act on keep their own code, everything else is
|
|
101
|
+
* internal.
|
|
102
|
+
* @param error - the thrown value.
|
|
103
|
+
* @param childSessionId - the addressed child.
|
|
104
|
+
* @param signal - the caller's cancellation.
|
|
105
|
+
* @returns Never — the refusal is thrown.
|
|
106
|
+
* @throws {RemoteError} always.
|
|
107
|
+
*/
|
|
108
|
+
export function rejectPrompt(error, childSessionId, signal) {
|
|
109
|
+
if (isCancellation(error, signal)) {
|
|
110
|
+
throw new RemoteError('gateway/cancelled', 'subagent prompt was cancelled', {}, { cause: error });
|
|
111
|
+
}
|
|
112
|
+
if (error instanceof SubagentError) {
|
|
113
|
+
switch (error.code) {
|
|
114
|
+
case 'NOT_RESUMABLE':
|
|
115
|
+
throw new RemoteError('subagent/not-resumable', 'subagent cannot be resumed', { childSessionId }, { cause: error });
|
|
116
|
+
case 'UNAUTHORIZED':
|
|
117
|
+
throw new RemoteError('subagent/unauthorized', 'subagent does not belong to this parent', { childSessionId }, { cause: error });
|
|
118
|
+
case 'DRAINING':
|
|
119
|
+
case 'ACTIVATION_CLOSING':
|
|
120
|
+
case 'CONTINUATION_UNAVAILABLE':
|
|
121
|
+
case 'PERSISTENCE_UNAVAILABLE':
|
|
122
|
+
throw new RemoteError('subagent/delivery-unavailable', 'subagent follow-up is temporarily unavailable', { childSessionId }, { cause: error });
|
|
123
|
+
// A code outside the admission vocabulary is not the caller's move to make.
|
|
124
|
+
default:
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
throw new RemoteError('gateway/internal', 'subagent prompt failed', {}, { cause: error });
|
|
129
|
+
}
|
|
130
|
+
function isCancellation(error, signal) {
|
|
131
|
+
return signal.aborted || (error instanceof SubagentError && error.code === 'CANCELLED');
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=control.js.map
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* @module @deepseek-ai/dsh-subagent/descriptor
|
|
22
22
|
*/
|
|
23
23
|
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
24
|
+
import type { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
24
25
|
import type { ToolRestriction } from '@deepseek-ai/dsh-tools';
|
|
25
26
|
declare module '@deepseek-ai/dsh-session/types' {
|
|
26
27
|
interface SessionEventMap {
|
|
@@ -40,7 +41,7 @@ declare module '@deepseek-ai/dsh-session/types' {
|
|
|
40
41
|
* Supporting another composition input is a deliberate version change, never
|
|
41
42
|
* an implicit extra field.
|
|
42
43
|
*/
|
|
43
|
-
export declare const SUBAGENT_DESCRIPTOR_VERSION =
|
|
44
|
+
export declare const SUBAGENT_DESCRIPTOR_VERSION = 3;
|
|
44
45
|
/** Fields shared by every supported `subagent/descriptor` payload. */
|
|
45
46
|
interface SubagentDescriptorBase {
|
|
46
47
|
/** Descriptor format version ({@link SUBAGENT_DESCRIPTOR_VERSION}). */
|
|
@@ -69,6 +70,8 @@ export interface ContinuableSubagentDescriptorData extends SubagentDescriptorBas
|
|
|
69
70
|
readonly agentProvider?: string;
|
|
70
71
|
/** Resolved child `agentOptions.model`, when one was declared. */
|
|
71
72
|
readonly agentModel?: string;
|
|
73
|
+
/** Resolved child `agentOptions.reasoningEffort`, when one was declared. */
|
|
74
|
+
readonly agentReasoningEffort?: ReasoningEffortId;
|
|
72
75
|
/** Per-child persona that shadows the deployment persona on resume. */
|
|
73
76
|
readonly persona?: string;
|
|
74
77
|
/** Child tool scoping reapplied on resume. */
|
|
@@ -98,6 +101,8 @@ export interface ContinuableSubagentDescriptorInput extends SubagentDescriptorIn
|
|
|
98
101
|
readonly agentProvider?: string;
|
|
99
102
|
/** Requested child `agentOptions.model`. */
|
|
100
103
|
readonly agentModel?: string;
|
|
104
|
+
/** Requested child `agentOptions.reasoningEffort`. */
|
|
105
|
+
readonly agentReasoningEffort?: ReasoningEffortId;
|
|
101
106
|
/** Requested per-child persona. */
|
|
102
107
|
readonly persona?: string;
|
|
103
108
|
/** Requested child tool scoping. */
|
package/lib/types/descriptor.js
CHANGED
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @module @deepseek-ai/dsh-subagent/descriptor
|
|
22
22
|
*/
|
|
23
|
-
import { snapshotJsonValue } from '@deepseek-ai/dsh-
|
|
23
|
+
import { snapshotJsonValue } from '@deepseek-ai/dsh-util-values';
|
|
24
24
|
/**
|
|
25
25
|
* The current descriptor format version, stamped into every appended
|
|
26
26
|
* `subagent/descriptor` event and required verbatim by {@link foldSubagentDescriptor}.
|
|
27
27
|
* Supporting another composition input is a deliberate version change, never
|
|
28
28
|
* an implicit extra field.
|
|
29
29
|
*/
|
|
30
|
-
export const SUBAGENT_DESCRIPTOR_VERSION =
|
|
30
|
+
export const SUBAGENT_DESCRIPTOR_VERSION = 3;
|
|
31
31
|
const DESCRIPTOR_BASE_KEYS = [
|
|
32
32
|
'version',
|
|
33
33
|
'mode',
|
|
@@ -39,6 +39,7 @@ const CONTINUABLE_DESCRIPTOR_KEYS = new Set([
|
|
|
39
39
|
...DESCRIPTOR_BASE_KEYS,
|
|
40
40
|
'agentProvider',
|
|
41
41
|
'agentModel',
|
|
42
|
+
'agentReasoningEffort',
|
|
42
43
|
'persona',
|
|
43
44
|
'toolFilter',
|
|
44
45
|
]);
|
|
@@ -129,6 +130,7 @@ function parseSubagentDescriptor(value) {
|
|
|
129
130
|
}
|
|
130
131
|
const agentProvider = optionalString(value, 'agentProvider');
|
|
131
132
|
const agentModel = optionalString(value, 'agentModel');
|
|
133
|
+
const agentReasoningEffort = optionalString(value, 'agentReasoningEffort');
|
|
132
134
|
const persona = optionalString(value, 'persona');
|
|
133
135
|
const toolFilter = Object.hasOwn(value, 'toolFilter')
|
|
134
136
|
? parseToolFilter(value['toolFilter'])
|
|
@@ -140,6 +142,7 @@ function parseSubagentDescriptor(value) {
|
|
|
140
142
|
label,
|
|
141
143
|
...agentProvider !== undefined ? { agentProvider } : {},
|
|
142
144
|
...agentModel !== undefined ? { agentModel } : {},
|
|
145
|
+
...agentReasoningEffort !== undefined ? { agentReasoningEffort } : {},
|
|
143
146
|
...persona !== undefined ? { persona } : {},
|
|
144
147
|
...toolFilter !== undefined ? { toolFilter } : {},
|
|
145
148
|
};
|
|
@@ -159,6 +162,7 @@ export function snapshotSubagentDescriptor(input) {
|
|
|
159
162
|
label: input.label,
|
|
160
163
|
...input.agentProvider !== undefined ? { agentProvider: input.agentProvider } : {},
|
|
161
164
|
...input.agentModel !== undefined ? { agentModel: input.agentModel } : {},
|
|
165
|
+
...input.agentReasoningEffort !== undefined ? { agentReasoningEffort: input.agentReasoningEffort } : {},
|
|
162
166
|
...input.persona !== undefined ? { persona: input.persona } : {},
|
|
163
167
|
...input.toolFilter !== undefined ? { toolFilter: input.toolFilter } : {},
|
|
164
168
|
};
|
package/lib/types/index.d.ts
CHANGED
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
* child before returning its run, so fulfillment is the single publication and
|
|
5
5
|
* ownership-transfer boundary.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* one by name. The shape mirrors the LLM adapter registry
|
|
10
|
-
* (`LlmRuntime.registerAdapter`), not the single-service bash executor.
|
|
7
|
+
* Multiple providers coexist: each registers under a unique name and callers
|
|
8
|
+
* select one by name.
|
|
11
9
|
*
|
|
12
10
|
* This package owns the Service Definition role of the capability seam. Service Providers
|
|
13
11
|
* (`@deepseek-ai/dsh-subagent-spawn-in-process`, `-fork`, `-acp`) and the model-facing
|
|
@@ -30,11 +28,13 @@
|
|
|
30
28
|
*
|
|
31
29
|
* @module @deepseek-ai/dsh-subagent
|
|
32
30
|
*/
|
|
33
|
-
import { Context
|
|
31
|
+
import { Context } from '@deepseek-ai/cordis';
|
|
34
32
|
import type { Scoped } from '@deepseek-ai/dsh-scope';
|
|
35
33
|
import type { ContentBlock, MessageId } from '@deepseek-ai/dsh-llm';
|
|
36
34
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
37
35
|
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
36
|
+
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
37
|
+
import type { SubagentCatalog, SubagentInterruptReceipt, SubagentPromptReceipt, SubagentPromptRequest } from './control-types.ts';
|
|
38
38
|
import type { SubagentProvider, SubagentRun, SubagentRunEndInfo, SubagentRunInfo, SubagentStartRequest } from './types.ts';
|
|
39
39
|
import type { ContinuableStart, ContinuableStartSpec, SubagentFollowupOptions, SubagentInterruptAuthority, SubagentReportOptions } from './continuation.ts';
|
|
40
40
|
import type { ContinuableSetupContribution } from './activation-setup-registry.ts';
|
|
@@ -49,11 +49,12 @@ export { seedDescriptorTurn } from './descriptor-seed.ts';
|
|
|
49
49
|
export { SubagentError } from './error.ts';
|
|
50
50
|
export { settleRun } from './run-settlement.ts';
|
|
51
51
|
export { assertSubagentMaxDepth, delegationDepthOf } from './depth.ts';
|
|
52
|
-
export { appendDelegatedPolicyOverrides, applyChildComposition, captureDelegatedPolicyOverrides, childSessionMeta, resolveChildAgentOptions, resolveChildDepth, SubagentDepthError, } from './child-agent.ts';
|
|
52
|
+
export { appendDelegatedPolicyOverrides, applyChildComposition, captureDelegatedPolicyOverrides, childSessionMeta, parentAgentOptionsForDelegation, resolveChildAgentOptions, resolveChildDepth, SubagentDepthError, } from './child-agent.ts';
|
|
53
53
|
export type { ChildComposition, DelegatedPolicyOverrides } from './child-agent.ts';
|
|
54
54
|
export type { ContinuableStart, ContinuableStartSpec, CoordinatorMessageSource, SubagentFollowupOptions, SubagentInterruptAuthority, SubagentReportDelivery, SubagentReportMessageSource, SubagentReportOptions, SubagentSettledMessageSource, } from './continuation.ts';
|
|
55
55
|
export type { ContinuableSetupContribution } from './activation-setup-registry.ts';
|
|
56
|
-
export type
|
|
56
|
+
export type * from './control-types.ts';
|
|
57
|
+
export type { SubagentDescendantListEntry } from './list-children.ts';
|
|
57
58
|
export type { SubagentRunEndInfo, SubagentRunInfo } from './types.ts';
|
|
58
59
|
export type { SubagentIdentityProjection, SubagentTimingProjection } from './projection-types.ts';
|
|
59
60
|
declare module '@deepseek-ai/cordis' {
|
|
@@ -96,7 +97,7 @@ declare module '@deepseek-ai/cordis' {
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
/** Named provider registry with one-shot runs, durable discovery, and continuable-child operations. */
|
|
99
|
-
export declare class SubagentRuntime extends
|
|
100
|
+
export declare class SubagentRuntime extends TypertRemoteService {
|
|
100
101
|
private providers;
|
|
101
102
|
private continuations;
|
|
102
103
|
/** Deployment contributions composed into unpublished continuable children. */
|
|
@@ -195,27 +196,16 @@ export declare class SubagentRuntime extends Service {
|
|
|
195
196
|
drainContinuableChildren(parent: Agent, childIds: readonly SessionId[]): Promise<void>;
|
|
196
197
|
/**
|
|
197
198
|
* Enumerate the parent's direct session-backed subagents without loading or
|
|
198
|
-
* resuming an Agent
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* projection
|
|
202
|
-
* snapshot for a live child; for a cold one, a durable projection-cache
|
|
203
|
-
* row when the optional cache serves an own-suffix identity (its `seq`
|
|
204
|
-
* gate proves the value postdates the fork seed, where a child's own
|
|
205
|
-
* descriptor is immutable once appended), else one persistence inspection
|
|
206
|
-
* folded through the registry. The
|
|
207
|
-
* projection fold is the single classification authority; per-child
|
|
208
|
-
* diagnostics relay a fold that served no identity or a failed inspection,
|
|
209
|
-
* never a list-time descriptor parse. Absent persistence, enumeration is
|
|
210
|
-
* live-only (a cold child cannot be resumed then either, so its absence is
|
|
211
|
-
* capability absence, not an error). This service consults no Agent
|
|
212
|
-
* registrations, Activations, or providers.
|
|
199
|
+
* resuming an Agent. The Session query service supplies one live-preferred
|
|
200
|
+
* corpus and shared point observations; the projection cache supplies
|
|
201
|
+
* immutable descriptor hits without opening cold logs. The registered
|
|
202
|
+
* `subagent` projection remains the sole mode/label classifier.
|
|
213
203
|
*
|
|
214
|
-
* Every
|
|
215
|
-
*
|
|
204
|
+
* Every query receives `signal`, and the listing rechecks cancellation
|
|
205
|
+
* around each await. Read rejections that settle
|
|
216
206
|
* after an abort become a stable `SubagentError` with code `CANCELLED`.
|
|
217
207
|
* @param parentSessionId - parent session whose direct children are listed.
|
|
218
|
-
* @param signal - caller-owned cancellation forwarded to
|
|
208
|
+
* @param signal - caller-owned cancellation forwarded to Session queries
|
|
219
209
|
* and observed around every read await.
|
|
220
210
|
* @returns children and per-child diagnostics ordered by `createdAt`, then id.
|
|
221
211
|
* @throws {@link SubagentError} when the projection registry or the session
|
|
@@ -238,6 +228,50 @@ export declare class SubagentRuntime extends Service {
|
|
|
238
228
|
* @throws {@link SubagentError} under the same conditions as {@link listChildren}.
|
|
239
229
|
*/
|
|
240
230
|
listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise<SubagentDescendantListEntry[]>;
|
|
231
|
+
/**
|
|
232
|
+
* Remote face of {@link listChildren} for one browser: the durable listing
|
|
233
|
+
* plus live Agent activity and the delivery-time parent availability hint.
|
|
234
|
+
* Parent availability is a hint; {@link prompt} performs the authoritative
|
|
235
|
+
* check. Named apart from the provider-name {@link list}, which owns the
|
|
236
|
+
* member.
|
|
237
|
+
* @param parentSessionId - parent session whose direct children are listed.
|
|
238
|
+
* @param signal - carrier cancellation forwarded to Session queries.
|
|
239
|
+
* @returns the catalog view for that parent.
|
|
240
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty parent id,
|
|
241
|
+
* `gateway/cancelled` for an aborted read, `subagent/projections-unavailable` when
|
|
242
|
+
* the deployment has no projection registry, otherwise `gateway/internal`.
|
|
243
|
+
*/
|
|
244
|
+
remoteExportList(parentSessionId: SessionId, signal: AbortSignal): Promise<SubagentCatalog>;
|
|
245
|
+
/**
|
|
246
|
+
* Deliver one browser-authored message to a continuable child through the
|
|
247
|
+
* exact live direct parent, retaining the caller-minted request identity and
|
|
248
|
+
* validated browser zone on the accepted message. Success identifies the
|
|
249
|
+
* message the child's FIFO inbox accepted; later execution is independent of
|
|
250
|
+
* this call.
|
|
251
|
+
* @param request - durable address, minted identity, content, and optional browser zone.
|
|
252
|
+
* @param signal - carrier cancellation, owning the call until inbox acceptance.
|
|
253
|
+
* @returns the accepted message's inbox identity.
|
|
254
|
+
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-unsupported`,
|
|
255
|
+
* `subagent/invalid-time-zone`, `subagent/parent-unavailable`,
|
|
256
|
+
* `subagent/not-resumable`, `subagent/unauthorized`,
|
|
257
|
+
* `subagent/delivery-unavailable`, `gateway/cancelled`, or `gateway/internal`.
|
|
258
|
+
*/
|
|
259
|
+
prompt(request: SubagentPromptRequest, signal: AbortSignal): Promise<SubagentPromptReceipt>;
|
|
260
|
+
/**
|
|
261
|
+
* Remote face of {@link interrupt} under one durable parent address. No
|
|
262
|
+
* catalog, history, persistence, or parent Agent lookup runs: the core
|
|
263
|
+
* primitive alone authorizes the address against the live Activation, which
|
|
264
|
+
* is what keeps a live child interruptible while its parent Agent is offline.
|
|
265
|
+
* Absent, idle, and already-completed targets are accepted no-ops there.
|
|
266
|
+
* @param childSessionId - durable child session id to interrupt.
|
|
267
|
+
* @param parentSessionId - durable direct parent whose authority is claimed.
|
|
268
|
+
* @param mode - required continuable-address discriminator.
|
|
269
|
+
* @returns acknowledgement that the cancel signal was admitted, not that the target is quiescent.
|
|
270
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty id,
|
|
271
|
+
* `subagent/unauthorized` when the address does not own the live target,
|
|
272
|
+
* otherwise `gateway/internal`.
|
|
273
|
+
*/
|
|
274
|
+
interruptByParent(childSessionId: SessionId, parentSessionId: SessionId, mode: 'continuable'): SubagentInterruptReceipt;
|
|
241
275
|
/**
|
|
242
276
|
* Register a provider under its name. Registration is effect-scoped and HMR
|
|
243
277
|
* safe; removing a provider blocks new starts but does not revoke runs that
|