@deepseek-ai/dsh-subagent 0.1.2-alpha.2 → 0.1.2-alpha.4
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 +12 -11
- package/README.zh.md +12 -11
- package/lib/index.js +238 -324
- package/lib/typert.host.js +52 -157
- package/lib/typert.remote-client.js +8 -91
- package/lib/types/child-agent.d.ts +2 -2
- package/lib/types/child-agent.js +3 -3
- package/lib/types/continuation.d.ts +50 -69
- package/lib/types/continuation.js +173 -105
- package/lib/types/control-types.d.ts +11 -27
- package/lib/types/control.d.ts +1 -17
- package/lib/types/control.js +6 -24
- package/lib/types/descriptor-seed.d.ts +1 -1
- package/lib/types/descriptor-seed.js +1 -1
- package/lib/types/index.d.ts +32 -43
- package/lib/types/index.js +51 -50
- package/lib/types/internal.d.ts +46 -0
- package/lib/types/internal.js +45 -0
- package/lib/types/lifecycle.js +4 -3
- package/lib/types/list-children.d.ts +6 -5
- package/lib/types/list-children.js +23 -22
- package/lib/types/projection-types.d.ts +4 -3
- package/lib/types/projection.js +3 -2
- package/package.json +48 -44
- package/lib/types/activation-setup-registry.d.ts +0 -57
- package/lib/types/activation-setup-registry.js +0 -148
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module @deepseek-ai/dsh-subagent/control-types
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
8
|
+
import type { PromptContentPart } from '@deepseek-ai/dsh-attachment/types';
|
|
9
9
|
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
10
10
|
import type { MessageId } from '@deepseek-ai/dsh-llm/brand';
|
|
11
|
-
import type { ContentBlock } from '@deepseek-ai/dsh-llm/types';
|
|
12
11
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
13
12
|
/**
|
|
14
13
|
* Client-minted identity of one browser prompt, persisted on the exact accepted
|
|
@@ -83,19 +82,6 @@ export type SubagentAddress = {
|
|
|
83
82
|
} | {
|
|
84
83
|
readonly mode: 'continuable';
|
|
85
84
|
});
|
|
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
85
|
/** One human message addressed to a continuable direct child. */
|
|
100
86
|
export interface SubagentPromptRequest {
|
|
101
87
|
/** Identity persisted on the accepted message, minted before the call. */
|
|
@@ -104,8 +90,12 @@ export interface SubagentPromptRequest {
|
|
|
104
90
|
readonly childSessionId: SessionId;
|
|
105
91
|
/** Required discriminator retained from the browser control address. */
|
|
106
92
|
readonly mode: 'continuable';
|
|
107
|
-
/**
|
|
108
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Browser prompt parts delivered as the child's user message. The Host
|
|
95
|
+
* admits and persists image parts before delivery, so the wire never
|
|
96
|
+
* carries a durable attachment reference the caller could fabricate.
|
|
97
|
+
*/
|
|
98
|
+
readonly content: readonly PromptContentPart[];
|
|
109
99
|
/** Optional browser zone sampled for this exact human prompt. */
|
|
110
100
|
readonly clientTimeZone?: string;
|
|
111
101
|
}
|
|
@@ -118,10 +108,8 @@ export interface SubagentInterruptReceipt {
|
|
|
118
108
|
readonly accepted: true;
|
|
119
109
|
}
|
|
120
110
|
/**
|
|
121
|
-
* Failure details the control surface answers with.
|
|
122
|
-
*
|
|
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.
|
|
111
|
+
* Failure details the control surface answers with. Catalog reads, prompts,
|
|
112
|
+
* and interrupts share this vocabulary with the Client Remote result.
|
|
125
113
|
*/
|
|
126
114
|
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
127
115
|
interface RemoteErrorDetailsMap {
|
|
@@ -141,12 +129,8 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
|
141
129
|
'subagent/unauthorized': {
|
|
142
130
|
readonly childSessionId: SessionId;
|
|
143
131
|
};
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
* for the caller's copy, as the Session prompt's attachment refusals do.
|
|
147
|
-
*/
|
|
148
|
-
'subagent/attachment-unsupported': {
|
|
149
|
-
readonly childSessionId: SessionId;
|
|
132
|
+
/** Image admission or model image-capability refusal. */
|
|
133
|
+
'subagent/attachment-invalid': {
|
|
150
134
|
readonly reason: string;
|
|
151
135
|
};
|
|
152
136
|
/** The child exists but its inbox cannot admit the message now. */
|
package/lib/types/control.d.ts
CHANGED
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
* @module @deepseek-ai/dsh-subagent
|
|
7
7
|
*/
|
|
8
8
|
import type { Context } from '@deepseek-ai/cordis';
|
|
9
|
-
import type { ContentBlock } from '@deepseek-ai/dsh-llm';
|
|
10
9
|
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
11
10
|
import { z } from 'zod';
|
|
12
|
-
import type { SubagentCatalog, SubagentListEntry
|
|
11
|
+
import type { SubagentCatalog, SubagentListEntry } from './control-types.ts';
|
|
13
12
|
declare const CONTROL_ID_SCHEMAS: {
|
|
14
13
|
readonly 'subagent.list': z.ZodObject<{
|
|
15
14
|
parentSessionId: z.ZodString;
|
|
@@ -33,21 +32,6 @@ declare const CONTROL_ID_SCHEMAS: {
|
|
|
33
32
|
* @throws {RemoteError} `gateway/bad-request` with the original Zod issues.
|
|
34
33
|
*/
|
|
35
34
|
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
35
|
/**
|
|
52
36
|
* Project one durable listing onto the catalog view, replacing each row's
|
|
53
37
|
* store-derived activity with the live Agent driver's status and reporting
|
package/lib/types/control.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module @deepseek-ai/dsh-subagent
|
|
7
7
|
*/
|
|
8
|
+
import { AttachmentError } from '@deepseek-ai/dsh-attachment';
|
|
8
9
|
import { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
|
|
9
10
|
import { z } from 'zod';
|
|
10
11
|
import { SubagentError } from "./error.js";
|
|
@@ -35,30 +36,6 @@ export function validateControlRequest(method, payload) {
|
|
|
35
36
|
throw new RemoteError('gateway/bad-request', `invalid payload for ${method}`, { issues: parsed.error.issues });
|
|
36
37
|
}
|
|
37
38
|
}
|
|
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
39
|
/**
|
|
63
40
|
* Project one durable listing onto the catalog view, replacing each row's
|
|
64
41
|
* store-derived activity with the live Agent driver's status and reporting
|
|
@@ -109,8 +86,13 @@ export function rejectPrompt(error, childSessionId, signal) {
|
|
|
109
86
|
if (isCancellation(error, signal)) {
|
|
110
87
|
throw new RemoteError('gateway/cancelled', 'subagent prompt was cancelled', {}, { cause: error });
|
|
111
88
|
}
|
|
89
|
+
if (error instanceof AttachmentError) {
|
|
90
|
+
throw new RemoteError('subagent/attachment-invalid', error.message, { reason: error.code }, { cause: error });
|
|
91
|
+
}
|
|
112
92
|
if (error instanceof SubagentError) {
|
|
113
93
|
switch (error.code) {
|
|
94
|
+
case 'MODEL_DOES_NOT_SUPPORT_IMAGES':
|
|
95
|
+
throw new RemoteError('subagent/attachment-invalid', error.message, { reason: error.code }, { cause: error });
|
|
114
96
|
case 'NOT_RESUMABLE':
|
|
115
97
|
throw new RemoteError('subagent/not-resumable', 'subagent cannot be resumed', { childSessionId }, { cause: error });
|
|
116
98
|
case 'UNAUTHORIZED':
|
|
@@ -17,5 +17,5 @@ import type { SubagentDescriptorData } from './descriptor.ts';
|
|
|
17
17
|
* @param descriptor - the snapshotted composition record to persist.
|
|
18
18
|
* @returns the complete seed events, contiguous from sequence zero.
|
|
19
19
|
*/
|
|
20
|
-
export declare function seedDescriptorTurn(childId: SessionId, seed: readonly SessionEvent[] | undefined, descriptor: SubagentDescriptorData): SessionEvent[];
|
|
20
|
+
export declare function seedDescriptorTurn(childId: SessionId, seed: readonly SessionEvent[] | undefined, descriptor: SubagentDescriptorData): readonly SessionEvent[];
|
|
21
21
|
//# sourceMappingURL=descriptor-seed.d.ts.map
|
|
@@ -19,6 +19,6 @@ import { Session } from '@deepseek-ai/dsh-session';
|
|
|
19
19
|
export function seedDescriptorTurn(childId, seed, descriptor) {
|
|
20
20
|
const staged = Session.create(childId, seed);
|
|
21
21
|
staged.append('subagent/descriptor', descriptor);
|
|
22
|
-
return
|
|
22
|
+
return staged.snapshotEvents();
|
|
23
23
|
}
|
|
24
24
|
//# sourceMappingURL=descriptor-seed.js.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Public operations express caller intent: `start` returns one published owned
|
|
15
15
|
* one-shot run, `startContinuable` establishes a durable continuable child, and
|
|
16
|
-
* `
|
|
17
|
-
* resident. Continuable children never become a {@link SubagentRun}: the
|
|
16
|
+
* `sendMessage` steers between adjacent Agents without exposing whether a child
|
|
17
|
+
* is resident. Continuable children never become a {@link SubagentRun}: the
|
|
18
18
|
* continuation manager holds their `AgentHandle` directly and orders every turn
|
|
19
19
|
* through the child's own inbox, so providers contribute only the detached
|
|
20
20
|
* creation spec and see no handle, turn, or teardown. Child and descendant
|
|
@@ -36,9 +36,9 @@ import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
|
36
36
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
37
37
|
import type { SubagentCatalog, SubagentInterruptReceipt, SubagentPromptReceipt, SubagentPromptRequest } from './control-types.ts';
|
|
38
38
|
import type { SubagentProvider, SubagentRun, SubagentRunEndInfo, SubagentRunInfo, SubagentStartRequest } from './types.ts';
|
|
39
|
-
import type { ContinuableStart, ContinuableStartSpec,
|
|
40
|
-
import type { ContinuableSetupContribution } from './activation-setup-registry.ts';
|
|
39
|
+
import type { ContinuableStart, ContinuableStartSpec, SubagentInterruptAuthority, SubagentSendMessageOptions } from './continuation.ts';
|
|
41
40
|
import type { SubagentDescendantListEntry, SubagentListEntry } from './list-children.ts';
|
|
41
|
+
import { queueSubagentPrompt } from './internal.ts';
|
|
42
42
|
export * from './out-of-process.ts';
|
|
43
43
|
export { AssistantOutputFold, finalAssistantOutput } from './assistant-output.ts';
|
|
44
44
|
export { SubagentRunId } from './types.ts';
|
|
@@ -51,8 +51,7 @@ export { settleRun } from './run-settlement.ts';
|
|
|
51
51
|
export { assertSubagentMaxDepth, delegationDepthOf } from './depth.ts';
|
|
52
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
|
-
export type { ContinuableStart, ContinuableStartSpec,
|
|
55
|
-
export type { ContinuableSetupContribution } from './activation-setup-registry.ts';
|
|
54
|
+
export type { AgentMessageSource, ContinuableStart, ContinuableStartSpec, SubagentInterruptAuthority, SubagentSendMessageOptions, SubagentSettledMessageSource, } from './continuation.ts';
|
|
56
55
|
export type * from './control-types.ts';
|
|
57
56
|
export type { SubagentDescendantListEntry } from './list-children.ts';
|
|
58
57
|
export type { SubagentRunEndInfo, SubagentRunInfo } from './types.ts';
|
|
@@ -100,8 +99,6 @@ declare module '@deepseek-ai/cordis' {
|
|
|
100
99
|
export declare class SubagentRuntime extends TypertRemoteService {
|
|
101
100
|
private providers;
|
|
102
101
|
private continuations;
|
|
103
|
-
/** Deployment contributions composed into unpublished continuable children. */
|
|
104
|
-
private readonly setupRegistry;
|
|
105
102
|
/**
|
|
106
103
|
* The contained lifecycle-edge publisher. Built here because scoped dispatch
|
|
107
104
|
* keys its carrier by this exact service instance, whose own context filter
|
|
@@ -120,21 +117,32 @@ export declare class SubagentRuntime extends TypertRemoteService {
|
|
|
120
117
|
*/
|
|
121
118
|
startContinuable(spec: ContinuableStartSpec): Promise<ContinuableStart>;
|
|
122
119
|
/**
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* @param
|
|
129
|
-
* @param
|
|
130
|
-
* @param content -
|
|
131
|
-
* @param options -
|
|
132
|
-
* operation only before inbox acceptance.
|
|
120
|
+
* Steer one model-authored message to the sender's direct parent or direct
|
|
121
|
+
* continuable child. A running target admits it at the nearest step boundary;
|
|
122
|
+
* an idle target starts a turn, and an absent direct child cold-resumes from
|
|
123
|
+
* persistence. The service derives durable sender attribution from the exact
|
|
124
|
+
* live sender. Caller cancellation stops only pre-acceptance work.
|
|
125
|
+
* @param sender - exact live Agent authorizing and originating the message.
|
|
126
|
+
* @param targetId - durable direct-parent or direct-child session id.
|
|
127
|
+
* @param content - model-authored content to deliver.
|
|
128
|
+
* @param options - caller cancellation before inbox acceptance.
|
|
133
129
|
* @returns the accepted message's inbox id.
|
|
134
|
-
* @throws when continuation services are unavailable,
|
|
135
|
-
*
|
|
130
|
+
* @throws when continuation services are unavailable, adjacency is rejected,
|
|
131
|
+
* or the message was not admitted.
|
|
136
132
|
*/
|
|
137
|
-
|
|
133
|
+
sendMessage(sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions): Promise<MessageId>;
|
|
134
|
+
/**
|
|
135
|
+
* Queue one host-protocol message as a distinct direct-child turn.
|
|
136
|
+
* Symbol-keyed so host adapters can preserve their own provenance without
|
|
137
|
+
* widening the public Service Definition or impersonating an Agent sender.
|
|
138
|
+
* @param parent - exact live direct parent authorizing delivery.
|
|
139
|
+
* @param childId - durable direct-child session id.
|
|
140
|
+
* @param content - host-authored content to deliver.
|
|
141
|
+
* @param source - durable host-protocol provenance.
|
|
142
|
+
* @param signal - caller cancellation before inbox acceptance.
|
|
143
|
+
* @returns the accepted message's inbox id.
|
|
144
|
+
*/
|
|
145
|
+
private [queueSubagentPrompt];
|
|
138
146
|
/**
|
|
139
147
|
* Interrupt one live continuable child's current turn under a human parent
|
|
140
148
|
* address or an exact live ancestor Agent. Fire-and-return: the cancel
|
|
@@ -151,27 +159,6 @@ export declare class SubagentRuntime extends TypertRemoteService {
|
|
|
151
159
|
* live target.
|
|
152
160
|
*/
|
|
153
161
|
interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void;
|
|
154
|
-
/**
|
|
155
|
-
* Deliver selected content from one live continuable child to its durable
|
|
156
|
-
* direct parent. The child is the authority credential; callers cannot name a
|
|
157
|
-
* recipient. Reporting does not conclude the child's turn or Activation.
|
|
158
|
-
* @param child - exact live reporting child.
|
|
159
|
-
* @param content - selected model-facing content.
|
|
160
|
-
* @param options - parent scheduling and pre-acceptance cancellation.
|
|
161
|
-
* @returns the stable identity of the parent-accepted message.
|
|
162
|
-
* @throws when continuation services are unavailable, sender authorization
|
|
163
|
-
* fails, or the direct parent is not live.
|
|
164
|
-
*/
|
|
165
|
-
reportFrom(child: Agent, content: ContentBlock[], options: SubagentReportOptions): Promise<MessageId>;
|
|
166
|
-
/**
|
|
167
|
-
* Compose one deployment capability into every continuable child's
|
|
168
|
-
* unpublished creation context on fresh creation and cold resume. Grants wait
|
|
169
|
-
* for the next Activation; removing the contribution revokes every resident
|
|
170
|
-
* installation immediately.
|
|
171
|
-
* @param contribution - synchronous child-scope installer.
|
|
172
|
-
* @returns the exact Cordis effect disposer.
|
|
173
|
-
*/
|
|
174
|
-
registerContinuableSetup(contribution: ContinuableSetupContribution): () => void;
|
|
175
162
|
/**
|
|
176
163
|
* Close continuable admission below exact live parent Agents, stop only their
|
|
177
164
|
* visible descendant Activations synchronously, then await admitted scoped
|
|
@@ -248,10 +235,12 @@ export declare class SubagentRuntime extends TypertRemoteService {
|
|
|
248
235
|
* validated browser zone on the accepted message. Success identifies the
|
|
249
236
|
* message the child's FIFO inbox accepted; later execution is independent of
|
|
250
237
|
* this call.
|
|
238
|
+
* Image parts are admitted and persisted through the attachment store
|
|
239
|
+
* before delivery, and the child's model must accept image input.
|
|
251
240
|
* @param request - durable address, minted identity, content, and optional browser zone.
|
|
252
241
|
* @param signal - carrier cancellation, owning the call until inbox acceptance.
|
|
253
242
|
* @returns the accepted message's inbox identity.
|
|
254
|
-
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-
|
|
243
|
+
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-invalid`,
|
|
255
244
|
* `subagent/invalid-time-zone`, `subagent/parent-unavailable`,
|
|
256
245
|
* `subagent/not-resumable`, `subagent/unauthorized`,
|
|
257
246
|
* `subagent/delivery-unavailable`, `gateway/cancelled`, or `gateway/internal`.
|
package/lib/types/index.js
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Public operations express caller intent: `start` returns one published owned
|
|
15
15
|
* one-shot run, `startContinuable` establishes a durable continuable child, and
|
|
16
|
-
* `
|
|
17
|
-
* resident. Continuable children never become a {@link SubagentRun}: the
|
|
16
|
+
* `sendMessage` steers between adjacent Agents without exposing whether a child
|
|
17
|
+
* is resident. Continuable children never become a {@link SubagentRun}: the
|
|
18
18
|
* continuation manager holds their `AgentHandle` directly and orders every turn
|
|
19
19
|
* through the child's own inbox, so providers contribute only the detached
|
|
20
20
|
* creation spec and see no handle, turn, or teardown. Child and descendant
|
|
@@ -62,19 +62,20 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
62
62
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
63
63
|
done = true;
|
|
64
64
|
};
|
|
65
|
+
import { admitPromptContent } from '@deepseek-ai/dsh-attachment';
|
|
65
66
|
import { scopeTarget } from '@deepseek-ai/dsh-scope';
|
|
66
67
|
import { assertObjectJsonSchema } from '@deepseek-ai/dsh-tools';
|
|
67
68
|
import { canonicalClientTimeZone } from '@deepseek-ai/dsh-util-time';
|
|
68
69
|
import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
69
|
-
import {
|
|
70
|
+
import { catalogView, rejectCatalogRead, rejectPrompt, validateControlRequest, } from "./control.js";
|
|
70
71
|
import { SubagentError } from "./error.js";
|
|
71
72
|
import { assertSubagentMaxDepth } from "./depth.js";
|
|
72
73
|
import { createActivationObserver, createLifecycleEmitter, observeRun } from "./lifecycle.js";
|
|
73
74
|
import SubagentContinuationManager from "./continuation.js";
|
|
74
|
-
import SubagentActivationSetupRegistry from "./activation-setup-registry.js";
|
|
75
75
|
import { listChildren as listSubagentChildren, listDescendants as listSubagentDescendants } from "./list-children.js";
|
|
76
76
|
import { snapshotSubagentDescriptor } from "./descriptor.js";
|
|
77
77
|
import { subagentIdentityProjectionDefinition, subagentTimingProjectionDefinition } from "./projection.js";
|
|
78
|
+
import { queueSubagentPrompt } from "./internal.js";
|
|
78
79
|
export * from "./out-of-process.js";
|
|
79
80
|
export { AssistantOutputFold, finalAssistantOutput } from "./assistant-output.js";
|
|
80
81
|
export { SubagentRunId } from "./types.js";
|
|
@@ -104,8 +105,6 @@ let SubagentRuntime = (() => {
|
|
|
104
105
|
}
|
|
105
106
|
providers = (__runInitializers(this, _instanceExtraInitializers), new Map());
|
|
106
107
|
continuations;
|
|
107
|
-
/** Deployment contributions composed into unpublished continuable children. */
|
|
108
|
-
setupRegistry = new SubagentActivationSetupRegistry();
|
|
109
108
|
/**
|
|
110
109
|
* The contained lifecycle-edge publisher. Built here because scoped dispatch
|
|
111
110
|
* keys its carrier by this exact service instance, whose own context filter
|
|
@@ -119,7 +118,7 @@ let SubagentRuntime = (() => {
|
|
|
119
118
|
const manager = new SubagentContinuationManager(childCtx, {
|
|
120
119
|
prepareContinuable: (name, request) => this.prepareContinuable(name, request),
|
|
121
120
|
observeActivation: (provider, childId, parent) => this.observeActivation(provider, childId, parent),
|
|
122
|
-
}
|
|
121
|
+
});
|
|
123
122
|
this.continuations = manager;
|
|
124
123
|
childCtx.effect(() => () => {
|
|
125
124
|
/* v8 ignore else -- one injected binding owns the slot until its fiber disposes. */
|
|
@@ -145,22 +144,35 @@ let SubagentRuntime = (() => {
|
|
|
145
144
|
return this.requireContinuations().startContinuable(spec);
|
|
146
145
|
}
|
|
147
146
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* @param
|
|
154
|
-
* @param
|
|
155
|
-
* @param content -
|
|
156
|
-
* @param options -
|
|
157
|
-
* operation only before inbox acceptance.
|
|
147
|
+
* Steer one model-authored message to the sender's direct parent or direct
|
|
148
|
+
* continuable child. A running target admits it at the nearest step boundary;
|
|
149
|
+
* an idle target starts a turn, and an absent direct child cold-resumes from
|
|
150
|
+
* persistence. The service derives durable sender attribution from the exact
|
|
151
|
+
* live sender. Caller cancellation stops only pre-acceptance work.
|
|
152
|
+
* @param sender - exact live Agent authorizing and originating the message.
|
|
153
|
+
* @param targetId - durable direct-parent or direct-child session id.
|
|
154
|
+
* @param content - model-authored content to deliver.
|
|
155
|
+
* @param options - caller cancellation before inbox acceptance.
|
|
158
156
|
* @returns the accepted message's inbox id.
|
|
159
|
-
* @throws when continuation services are unavailable,
|
|
160
|
-
*
|
|
157
|
+
* @throws when continuation services are unavailable, adjacency is rejected,
|
|
158
|
+
* or the message was not admitted.
|
|
161
159
|
*/
|
|
162
|
-
async
|
|
163
|
-
return this.requireContinuations().
|
|
160
|
+
async sendMessage(sender, targetId, content, options) {
|
|
161
|
+
return this.requireContinuations().sendMessage(sender, targetId, content, options);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Queue one host-protocol message as a distinct direct-child turn.
|
|
165
|
+
* Symbol-keyed so host adapters can preserve their own provenance without
|
|
166
|
+
* widening the public Service Definition or impersonating an Agent sender.
|
|
167
|
+
* @param parent - exact live direct parent authorizing delivery.
|
|
168
|
+
* @param childId - durable direct-child session id.
|
|
169
|
+
* @param content - host-authored content to deliver.
|
|
170
|
+
* @param source - durable host-protocol provenance.
|
|
171
|
+
* @param signal - caller cancellation before inbox acceptance.
|
|
172
|
+
* @returns the accepted message's inbox id.
|
|
173
|
+
*/
|
|
174
|
+
[queueSubagentPrompt](parent, childId, content, source, signal) {
|
|
175
|
+
return this.requireContinuations().queuePrompt(parent, childId, content, source, signal);
|
|
164
176
|
}
|
|
165
177
|
/**
|
|
166
178
|
* Interrupt one live continuable child's current turn under a human parent
|
|
@@ -180,32 +192,6 @@ let SubagentRuntime = (() => {
|
|
|
180
192
|
interrupt(targetSessionId, authority) {
|
|
181
193
|
this.continuations?.interrupt(targetSessionId, authority);
|
|
182
194
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Deliver selected content from one live continuable child to its durable
|
|
185
|
-
* direct parent. The child is the authority credential; callers cannot name a
|
|
186
|
-
* recipient. Reporting does not conclude the child's turn or Activation.
|
|
187
|
-
* @param child - exact live reporting child.
|
|
188
|
-
* @param content - selected model-facing content.
|
|
189
|
-
* @param options - parent scheduling and pre-acceptance cancellation.
|
|
190
|
-
* @returns the stable identity of the parent-accepted message.
|
|
191
|
-
* @throws when continuation services are unavailable, sender authorization
|
|
192
|
-
* fails, or the direct parent is not live.
|
|
193
|
-
*/
|
|
194
|
-
async reportFrom(child, content, options) {
|
|
195
|
-
return this.requireContinuations().reportFrom(child, content, options);
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Compose one deployment capability into every continuable child's
|
|
199
|
-
* unpublished creation context on fresh creation and cold resume. Grants wait
|
|
200
|
-
* for the next Activation; removing the contribution revokes every resident
|
|
201
|
-
* installation immediately.
|
|
202
|
-
* @param contribution - synchronous child-scope installer.
|
|
203
|
-
* @returns the exact Cordis effect disposer.
|
|
204
|
-
*/
|
|
205
|
-
registerContinuableSetup(contribution) {
|
|
206
|
-
// oxlint-disable-next-line typescript/no-misused-promises -- synchronous disposer
|
|
207
|
-
return this.ctx.effect(() => this.setupRegistry.register(contribution), 'subagents.registerContinuableSetup()');
|
|
208
|
-
}
|
|
209
195
|
/**
|
|
210
196
|
* Close continuable admission below exact live parent Agents, stop only their
|
|
211
197
|
* visible descendant Activations synchronously, then await admitted scoped
|
|
@@ -305,10 +291,12 @@ let SubagentRuntime = (() => {
|
|
|
305
291
|
* validated browser zone on the accepted message. Success identifies the
|
|
306
292
|
* message the child's FIFO inbox accepted; later execution is independent of
|
|
307
293
|
* this call.
|
|
294
|
+
* Image parts are admitted and persisted through the attachment store
|
|
295
|
+
* before delivery, and the child's model must accept image input.
|
|
308
296
|
* @param request - durable address, minted identity, content, and optional browser zone.
|
|
309
297
|
* @param signal - carrier cancellation, owning the call until inbox acceptance.
|
|
310
298
|
* @returns the accepted message's inbox identity.
|
|
311
|
-
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-
|
|
299
|
+
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-invalid`,
|
|
312
300
|
* `subagent/invalid-time-zone`, `subagent/parent-unavailable`,
|
|
313
301
|
* `subagent/not-resumable`, `subagent/unauthorized`,
|
|
314
302
|
* `subagent/delivery-unavailable`, `gateway/cancelled`, or `gateway/internal`.
|
|
@@ -316,7 +304,6 @@ let SubagentRuntime = (() => {
|
|
|
316
304
|
async prompt(request, signal) {
|
|
317
305
|
const { parentSessionId, childSessionId, clientTimeZone } = request;
|
|
318
306
|
validateControlRequest('subagent.prompt', request);
|
|
319
|
-
const content = admitPromptContent(childSessionId, request.content);
|
|
320
307
|
const canonicalTimeZone = clientTimeZone === undefined
|
|
321
308
|
? undefined
|
|
322
309
|
: canonicalClientTimeZone(clientTimeZone);
|
|
@@ -333,7 +320,21 @@ let SubagentRuntime = (() => {
|
|
|
333
320
|
...(canonicalTimeZone === undefined ? {} : { clientTimeZone: canonicalTimeZone }),
|
|
334
321
|
};
|
|
335
322
|
try {
|
|
336
|
-
|
|
323
|
+
// Admission precedes delivery: image parts become durable references
|
|
324
|
+
// here, so the child inbox only ever accepts Host-persisted attachments.
|
|
325
|
+
let content;
|
|
326
|
+
if (request.content.every((part) => part.type === 'text')) {
|
|
327
|
+
content = request.content.map(part => ({ type: 'text', text: part.text }));
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const attachments = this.ctx.get('attachments');
|
|
331
|
+
if (attachments === undefined)
|
|
332
|
+
throw new Error('subagent image prompt requires an attachment store');
|
|
333
|
+
content = await admitPromptContent(attachments, request.content);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
messageId: await this[queueSubagentPrompt](parent, childSessionId, content, source, signal),
|
|
337
|
+
};
|
|
337
338
|
}
|
|
338
339
|
catch (error) {
|
|
339
340
|
return rejectPrompt(error, childSessionId, signal);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation integration markers and host adapters outside the public
|
|
3
|
+
* Service Definition and model-facing Agent messaging contract.
|
|
4
|
+
* @module @deepseek-ai/dsh-subagent/internal
|
|
5
|
+
*/
|
|
6
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
7
|
+
import type { ContentBlock, MessageId, MessageSource } from '@deepseek-ai/dsh-llm';
|
|
8
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
9
|
+
import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
|
|
10
|
+
import type SubagentRuntime from './index.ts';
|
|
11
|
+
/** Process-stable identity carried only by the standard adjacent-Agent messaging tool. */
|
|
12
|
+
export declare const adjacentAgentSendMessageTool: unique symbol;
|
|
13
|
+
/**
|
|
14
|
+
* Mark the standard adjacent-Agent messaging tool without changing its model-visible schema.
|
|
15
|
+
* @param definition - the standard `send_message` definition.
|
|
16
|
+
* @returns the same definition with its internal identity installed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function markAdjacentAgentSendMessageTool(definition: ToolDefinition): ToolDefinition;
|
|
19
|
+
/**
|
|
20
|
+
* Test whether one visible definition is the standard adjacent-Agent messaging tool.
|
|
21
|
+
* @param definition - the scope-resolved `send_message` candidate.
|
|
22
|
+
* @returns whether the definition carries the internal standard-tool identity.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isAdjacentAgentSendMessageTool(definition: ToolDefinition | undefined): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Process-stable symbol-keyed Queue delivery shared by the bundled runtime
|
|
27
|
+
* entry and this unbundled internal subpath.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare const queueSubagentPrompt: unique symbol;
|
|
31
|
+
/** Runtime face required by the host-only Queue adapter. */
|
|
32
|
+
export interface HostPromptQueue {
|
|
33
|
+
[queueSubagentPrompt](parent: Agent, childId: SessionId, content: ContentBlock[], source: MessageSource, signal: AbortSignal): Promise<MessageId>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Queue one host-protocol message without exposing another Service operation.
|
|
37
|
+
* @param runtime - subagent runtime owning continuation residency.
|
|
38
|
+
* @param parent - exact live direct parent authorizing delivery.
|
|
39
|
+
* @param childId - durable direct-child session id.
|
|
40
|
+
* @param content - host-authored content to deliver.
|
|
41
|
+
* @param source - durable host-protocol provenance.
|
|
42
|
+
* @param signal - caller cancellation before inbox acceptance.
|
|
43
|
+
* @returns the accepted message's inbox id.
|
|
44
|
+
*/
|
|
45
|
+
export declare function queueHostSubagentPrompt(runtime: SubagentRuntime, parent: Agent, childId: SessionId, content: ContentBlock[], source: MessageSource, signal: AbortSignal): Promise<MessageId>;
|
|
46
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation integration markers and host adapters outside the public
|
|
3
|
+
* Service Definition and model-facing Agent messaging contract.
|
|
4
|
+
* @module @deepseek-ai/dsh-subagent/internal
|
|
5
|
+
*/
|
|
6
|
+
/** Process-stable identity carried only by the standard adjacent-Agent messaging tool. */
|
|
7
|
+
export const adjacentAgentSendMessageTool = Symbol.for('dsh.subagent.adjacentAgentSendMessageTool');
|
|
8
|
+
/**
|
|
9
|
+
* Mark the standard adjacent-Agent messaging tool without changing its model-visible schema.
|
|
10
|
+
* @param definition - the standard `send_message` definition.
|
|
11
|
+
* @returns the same definition with its internal identity installed.
|
|
12
|
+
*/
|
|
13
|
+
export function markAdjacentAgentSendMessageTool(definition) {
|
|
14
|
+
Object.defineProperty(definition, adjacentAgentSendMessageTool, { value: true });
|
|
15
|
+
return definition;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Test whether one visible definition is the standard adjacent-Agent messaging tool.
|
|
19
|
+
* @param definition - the scope-resolved `send_message` candidate.
|
|
20
|
+
* @returns whether the definition carries the internal standard-tool identity.
|
|
21
|
+
*/
|
|
22
|
+
export function isAdjacentAgentSendMessageTool(definition) {
|
|
23
|
+
return definition !== undefined
|
|
24
|
+
&& definition[adjacentAgentSendMessageTool] === true;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Process-stable symbol-keyed Queue delivery shared by the bundled runtime
|
|
28
|
+
* entry and this unbundled internal subpath.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export const queueSubagentPrompt = Symbol.for('dsh.subagent.queuePrompt');
|
|
32
|
+
/**
|
|
33
|
+
* Queue one host-protocol message without exposing another Service operation.
|
|
34
|
+
* @param runtime - subagent runtime owning continuation residency.
|
|
35
|
+
* @param parent - exact live direct parent authorizing delivery.
|
|
36
|
+
* @param childId - durable direct-child session id.
|
|
37
|
+
* @param content - host-authored content to deliver.
|
|
38
|
+
* @param source - durable host-protocol provenance.
|
|
39
|
+
* @param signal - caller cancellation before inbox acceptance.
|
|
40
|
+
* @returns the accepted message's inbox id.
|
|
41
|
+
*/
|
|
42
|
+
export function queueHostSubagentPrompt(runtime, parent, childId, content, source, signal) {
|
|
43
|
+
return runtime[queueSubagentPrompt](parent, childId, content, source, signal);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=internal.js.map
|
package/lib/types/lifecycle.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { randomUUID } from 'node:crypto';
|
|
17
17
|
import { foldConsumedWork } from '@deepseek-ai/dsh-agent';
|
|
18
|
+
import { SessionLogOffset } from '@deepseek-ai/dsh-session';
|
|
18
19
|
import { finalAssistantOutput } from "./assistant-output.js";
|
|
19
20
|
import { SubagentRunId } from "./types.js";
|
|
20
21
|
/**
|
|
@@ -90,7 +91,7 @@ export function createActivationObserver(emit, provider, childId, parent) {
|
|
|
90
91
|
// A cold resume replays earlier turns, so this epoch's telemetry must come
|
|
91
92
|
// from the suffix it actually produced — never the whole session, which
|
|
92
93
|
// would report a previous epoch's answer when this one opened no turn.
|
|
93
|
-
let boundary = 0;
|
|
94
|
+
let boundary = SessionLogOffset(0);
|
|
94
95
|
// Assigned by `capture()`, which the disposal path always runs before
|
|
95
96
|
// `settle()`; a resident epoch therefore always has its facts by then.
|
|
96
97
|
let captured = { stopReason: 'completed' };
|
|
@@ -101,11 +102,11 @@ export function createActivationObserver(emit, provider, childId, parent) {
|
|
|
101
102
|
: { stopReason: 'error' };
|
|
102
103
|
return {
|
|
103
104
|
start: (child) => {
|
|
104
|
-
boundary = child.session.
|
|
105
|
+
boundary = child.session.seq;
|
|
105
106
|
emit('subagent/start', identity, parent);
|
|
106
107
|
},
|
|
107
108
|
capture: (child) => {
|
|
108
|
-
const own = child.session.
|
|
109
|
+
const own = child.session.snapshotEvents(boundary);
|
|
109
110
|
const output = finalAssistantOutput(own);
|
|
110
111
|
captured = {
|
|
111
112
|
stopReason: epochStopReason(own),
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* corpus; each child's mode/label is the registered `subagent` projection
|
|
5
5
|
* unit's value, resolved
|
|
6
6
|
* down a three-rung ladder: the registry's watermark cache for a live child,
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* an unseeded durable projection-cache row, and one shared Session observation
|
|
8
|
+
* otherwise. A seeded header deliberately lacks its exact inherited cut, so
|
|
9
|
+
* it takes the body-bearing observation path before classifying an identity.
|
|
10
|
+
* The projection fold is the single classification
|
|
10
11
|
* authority — this module parses no descriptor
|
|
11
12
|
* itself. Absent persistence, enumeration is live-only: a cold child is
|
|
12
13
|
* unreachable for resume anyway, so its absence is capability absence, not an
|
|
@@ -35,8 +36,8 @@ export type SubagentDescendantListEntry = SubagentListEntry & {
|
|
|
35
36
|
* live-preferred merge of `ctx.sessions` and optional session persistence,
|
|
36
37
|
* serving each identity from the `subagent` projection unit: the registry's
|
|
37
38
|
* watermark snapshot for a live child; for a cold one, a durable
|
|
38
|
-
* projection-cache read
|
|
39
|
-
*
|
|
39
|
+
* projection-cache read for an unseeded lifecycle, else one bounded-concurrency
|
|
40
|
+
* shared Session observation carrying the exact inherited cut.
|
|
40
41
|
* @see SubagentRuntime.listChildren for the public cancellation and failure contract.
|
|
41
42
|
* @param ctx - context carrying the session store, the projection registry,
|
|
42
43
|
* optional persistence, and the optional projection cache.
|