@toddzheng024/dscode-bundle 0.4.0 → 0.5.0
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/THIRD_PARTY_NOTICES.md +15 -0
- package/cordis.patch.yml +3 -3
- package/package.json +7 -1
- package/plugins/clipboard-image/clipboard-image.swift +56 -0
- package/plugins/clipboard-image/index.mjs +70 -0
- package/plugins/code-review/git.mjs +95 -0
- package/plugins/code-review/index.mjs +88 -0
- package/plugins/dscode/index.mjs +17 -3
- package/plugins/session-metrics/index.mjs +6 -2
- package/plugins/session-metrics/rate.mjs +62 -0
- package/plugins/session-metrics/view.mjs +15 -9
- package/plugins/tui-tools/doctor-cli.mjs +22 -0
- package/plugins/tui-tools/doctor.mjs +141 -0
- package/plugins/tui-tools/index.mjs +14 -6
- package/plugins/ultra/policy.mjs +12 -1
- package/plugins/worktree-subagent/worktree.mjs +50 -0
- package/presets/dscode/agent.cordis.yml +7 -2
- package/vendor/deepseek/index.js +12 -2
- package/vendor/subagent/index.js +29 -9
- package/vendor/subagent-core/LICENSE +21 -0
- package/vendor/subagent-core/index.js +3232 -0
- package/vendor/subagent-core/invariant.js +76 -0
- package/vendor/subagent-core/typert.host.d.ts +3 -0
- package/vendor/subagent-core/typert.host.js +964 -0
- package/vendor/subagent-core/typert.remote-client.d.ts +27 -0
- package/vendor/subagent-core/typert.remote-client.js +160 -0
- package/vendor/subagent-core/types/assistant-output.d.ts +48 -0
- package/vendor/subagent-core/types/assistant-output.js +73 -0
- package/vendor/subagent-core/types/catalog.d.ts +77 -0
- package/vendor/subagent-core/types/catalog.js +103 -0
- package/vendor/subagent-core/types/child-agent.d.ts +150 -0
- package/vendor/subagent-core/types/child-agent.js +207 -0
- package/vendor/subagent-core/types/client.d.ts +8 -0
- package/vendor/subagent-core/types/client.js +7 -0
- package/vendor/subagent-core/types/continuation-activation.d.ts +251 -0
- package/vendor/subagent-core/types/continuation-activation.js +663 -0
- package/vendor/subagent-core/types/continuation-messages.d.ts +62 -0
- package/vendor/subagent-core/types/continuation-messages.js +102 -0
- package/vendor/subagent-core/types/continuation.d.ts +124 -0
- package/vendor/subagent-core/types/continuation.js +455 -0
- package/vendor/subagent-core/types/control-types.d.ts +146 -0
- package/vendor/subagent-core/types/control-types.js +9 -0
- package/vendor/subagent-core/types/control.d.ts +71 -0
- package/vendor/subagent-core/types/control.js +116 -0
- package/vendor/subagent-core/types/depth.d.ts +31 -0
- package/vendor/subagent-core/types/depth.js +39 -0
- package/vendor/subagent-core/types/descriptor.d.ts +144 -0
- package/vendor/subagent-core/types/descriptor.js +193 -0
- package/vendor/subagent-core/types/error.d.ts +11 -0
- package/vendor/subagent-core/types/error.js +14 -0
- package/vendor/subagent-core/types/inbox.d.ts +43 -0
- package/vendor/subagent-core/types/inbox.js +61 -0
- package/vendor/subagent-core/types/index.d.ts +316 -0
- package/vendor/subagent-core/types/index.js +511 -0
- package/vendor/subagent-core/types/internal.d.ts +58 -0
- package/vendor/subagent-core/types/internal.js +58 -0
- package/vendor/subagent-core/types/invariant.d.ts +13 -0
- package/vendor/subagent-core/types/invariant.js +91 -0
- package/vendor/subagent-core/types/lifecycle.d.ts +113 -0
- package/vendor/subagent-core/types/lifecycle.js +178 -0
- package/vendor/subagent-core/types/list-children.d.ts +65 -0
- package/vendor/subagent-core/types/list-children.js +381 -0
- package/vendor/subagent-core/types/out-of-process.d.ts +118 -0
- package/vendor/subagent-core/types/out-of-process.js +219 -0
- package/vendor/subagent-core/types/projection-types.d.ts +74 -0
- package/vendor/subagent-core/types/projection-types.js +7 -0
- package/vendor/subagent-core/types/projection.d.ts +95 -0
- package/vendor/subagent-core/types/projection.js +151 -0
- package/vendor/subagent-core/types/run-settlement.d.ts +17 -0
- package/vendor/subagent-core/types/run-settlement.js +70 -0
- package/vendor/subagent-core/types/types.d.ts +377 -0
- package/vendor/subagent-core/types/types.js +19 -0
- package/vendor/subagent-driver/LICENSE +21 -0
- package/vendor/subagent-driver/index.js +255 -0
- package/vendor/subagent-driver/types/index.d.ts +33 -0
- package/vendor/subagent-driver/types/structured.d.ts +42 -0
- package/vendor/subagent-fork/LICENSE +21 -0
- package/vendor/subagent-fork/index.js +61 -0
- package/vendor/subagent-fork/types/index.d.ts +20 -0
- package/vendor/subagent-spawn/LICENSE +21 -0
- package/vendor/subagent-spawn/index.js +45 -0
- package/vendor/subagent-spawn/types/index.d.ts +19 -0
- package/vendor/terminal/LICENSE +21 -0
- package/vendor/terminal/index.js +1013 -0
- package/vendor/terminal/types/config.d.ts +71 -0
- package/vendor/terminal/types/index.d.ts +36 -0
- package/vendor/terminal/types/sanitize.d.ts +47 -0
- package/vendor/terminal/types/session.d.ts +87 -0
- package/vendor/tui/dscode-clipboard-image/clipboard-image.swift +56 -0
- package/vendor/tui/dscode-clipboard-image/index.mjs +70 -0
- package/vendor/tui/index.mjs +301 -78
|
@@ -0,0 +1,116 @@
|
|
|
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 { AttachmentError } from '@deepseek-ai/dsh-attachment';
|
|
9
|
+
import { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { SubagentError } from "./error.js";
|
|
12
|
+
const SESSION_ID_SCHEMA = z.string().min(1);
|
|
13
|
+
const CONTROL_ID_SCHEMAS = {
|
|
14
|
+
'subagent.list': z.object({ parentSessionId: SESSION_ID_SCHEMA }),
|
|
15
|
+
'subagent.prompt': z.object({
|
|
16
|
+
parentSessionId: SESSION_ID_SCHEMA,
|
|
17
|
+
childSessionId: SESSION_ID_SCHEMA,
|
|
18
|
+
mode: z.literal('continuable'),
|
|
19
|
+
delivery: z.enum(['queue', 'steer']),
|
|
20
|
+
}),
|
|
21
|
+
'subagent.interrupt': z.object({
|
|
22
|
+
parentSessionId: SESSION_ID_SCHEMA,
|
|
23
|
+
childSessionId: SESSION_ID_SCHEMA,
|
|
24
|
+
mode: z.literal('continuable'),
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Apply the subagent payload checks that are stricter than generated
|
|
29
|
+
* branded-string codecs.
|
|
30
|
+
* @param method - method name carried in the failure message.
|
|
31
|
+
* @param payload - decoded control fields to validate.
|
|
32
|
+
* @throws {RemoteError} `gateway/bad-request` with the original Zod issues.
|
|
33
|
+
*/
|
|
34
|
+
export function validateControlRequest(method, payload) {
|
|
35
|
+
const parsed = CONTROL_ID_SCHEMAS[method].safeParse(payload);
|
|
36
|
+
if (!parsed.success) {
|
|
37
|
+
throw new RemoteError('gateway/bad-request', `invalid payload for ${method}`, { issues: parsed.error.issues });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Project one durable listing onto the catalog view, replacing each row's
|
|
42
|
+
* store-derived activity with the live Agent driver's status and reporting
|
|
43
|
+
* whether the exact parent Agent is live. Without an Agent registry no driver
|
|
44
|
+
* runs at all, so every row is inactive and the parent is unavailable.
|
|
45
|
+
* @param ctx - Host context that may carry the Agent registry.
|
|
46
|
+
* @param parentSessionId - the listed parent.
|
|
47
|
+
* @param entries - the durable direct-child listing.
|
|
48
|
+
* @returns the catalog view answered to one browser.
|
|
49
|
+
*/
|
|
50
|
+
export function catalogView(ctx, parentSessionId, entries) {
|
|
51
|
+
const agents = ctx.get('agents');
|
|
52
|
+
return {
|
|
53
|
+
entries: entries.map((entry) => entry.kind === 'child'
|
|
54
|
+
? { ...entry, activity: agents?.get(entry.id)?.status === 'running' ? 'running' : 'inactive' }
|
|
55
|
+
: entry),
|
|
56
|
+
parentAvailable: agents?.get(parentSessionId) !== undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Refuse one catalog read while preserving cancellation and a missing
|
|
61
|
+
* projections registry as distinct failures.
|
|
62
|
+
* @param error - the thrown value.
|
|
63
|
+
* @param signal - the caller's cancellation.
|
|
64
|
+
* @returns Never — the refusal is thrown.
|
|
65
|
+
* @throws {RemoteError} always.
|
|
66
|
+
*/
|
|
67
|
+
export function rejectCatalogRead(error, signal) {
|
|
68
|
+
if (isCancellation(error, signal)) {
|
|
69
|
+
throw new RemoteError('gateway/cancelled', 'subagent catalog read was cancelled', {}, { cause: error });
|
|
70
|
+
}
|
|
71
|
+
if (error instanceof SubagentError && error.code === 'SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE') {
|
|
72
|
+
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 });
|
|
73
|
+
}
|
|
74
|
+
throw new RemoteError('gateway/internal', 'subagent catalog read failed', {}, { cause: error });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Refuse one continuation prompt without exposing provider detail: admission
|
|
78
|
+
* failures the caller can act on keep their own code, everything else is
|
|
79
|
+
* internal.
|
|
80
|
+
* @param error - the thrown value.
|
|
81
|
+
* @param childSessionId - the addressed child.
|
|
82
|
+
* @param signal - the caller's cancellation.
|
|
83
|
+
* @returns Never — the refusal is thrown.
|
|
84
|
+
* @throws {RemoteError} always.
|
|
85
|
+
*/
|
|
86
|
+
export function rejectPrompt(error, childSessionId, signal) {
|
|
87
|
+
if (isCancellation(error, signal)) {
|
|
88
|
+
throw new RemoteError('gateway/cancelled', 'subagent prompt was cancelled', {}, { cause: error });
|
|
89
|
+
}
|
|
90
|
+
if (error instanceof AttachmentError) {
|
|
91
|
+
throw new RemoteError('subagent/attachment-invalid', error.message, { reason: error.code }, { cause: error });
|
|
92
|
+
}
|
|
93
|
+
if (error instanceof SubagentError) {
|
|
94
|
+
switch (error.code) {
|
|
95
|
+
case 'MODEL_DOES_NOT_SUPPORT_IMAGES':
|
|
96
|
+
throw new RemoteError('subagent/attachment-invalid', error.message, { reason: error.code }, { cause: error });
|
|
97
|
+
case 'NOT_RESUMABLE':
|
|
98
|
+
throw new RemoteError('subagent/not-resumable', 'subagent cannot be resumed', { childSessionId }, { cause: error });
|
|
99
|
+
case 'UNAUTHORIZED':
|
|
100
|
+
throw new RemoteError('subagent/unauthorized', 'subagent does not belong to this parent', { childSessionId }, { cause: error });
|
|
101
|
+
case 'DRAINING':
|
|
102
|
+
case 'ACTIVATION_CLOSING':
|
|
103
|
+
case 'CONTINUATION_UNAVAILABLE':
|
|
104
|
+
case 'PERSISTENCE_UNAVAILABLE':
|
|
105
|
+
throw new RemoteError('subagent/delivery-unavailable', 'subagent follow-up is temporarily unavailable', { childSessionId }, { cause: error });
|
|
106
|
+
// A code outside the admission vocabulary is not the caller's move to make.
|
|
107
|
+
default:
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
throw new RemoteError('gateway/internal', 'subagent prompt failed', {}, { cause: error });
|
|
112
|
+
}
|
|
113
|
+
function isCancellation(error, signal) {
|
|
114
|
+
return signal.aborted || (error instanceof SubagentError && error.code === 'CANCELLED');
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=control.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation-depth accounting: the recursion budget a parent passes to its
|
|
3
|
+
* children. Kept apart from the service so composition helpers can read it
|
|
4
|
+
* without importing the registry.
|
|
5
|
+
*
|
|
6
|
+
* @module @deepseek-ai/dsh-subagent/depth
|
|
7
|
+
*/
|
|
8
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
9
|
+
declare module '@deepseek-ai/dsh-agent' {
|
|
10
|
+
interface AgentOptions {
|
|
11
|
+
/** Delegation depth: zero for a top-level agent and parent depth + 1 for a child. */
|
|
12
|
+
subagentDepth?: number;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read an agent's delegation depth, treating absence as top-level depth zero.
|
|
17
|
+
* The persisted session header is authoritative and monotone: runtime
|
|
18
|
+
* `AgentOptions.subagentDepth` may DEEPEN the count but can never lower it —
|
|
19
|
+
* a resumed child arrives with fresh options, and counting it from zero would
|
|
20
|
+
* let it delegate as if it were top-level.
|
|
21
|
+
* @param agent - the agent whose header and options carry the depth.
|
|
22
|
+
* @returns its non-negative safe-integer depth.
|
|
23
|
+
* @throws if the runtime `AgentOptions.subagentDepth` is not a non-negative safe integer.
|
|
24
|
+
*/
|
|
25
|
+
export declare function delegationDepthOf(agent: Agent): number;
|
|
26
|
+
/**
|
|
27
|
+
* Reject a recursion cap that cannot represent an exact delegation depth.
|
|
28
|
+
* @param maxDepth - the optional runtime value to validate.
|
|
29
|
+
*/
|
|
30
|
+
export declare function assertSubagentMaxDepth(maxDepth: unknown): void;
|
|
31
|
+
//# sourceMappingURL=depth.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation-depth accounting: the recursion budget a parent passes to its
|
|
3
|
+
* children. Kept apart from the service so composition helpers can read it
|
|
4
|
+
* without importing the registry.
|
|
5
|
+
*
|
|
6
|
+
* @module @deepseek-ai/dsh-subagent/depth
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Read an agent's delegation depth, treating absence as top-level depth zero.
|
|
10
|
+
* The persisted session header is authoritative and monotone: runtime
|
|
11
|
+
* `AgentOptions.subagentDepth` may DEEPEN the count but can never lower it —
|
|
12
|
+
* a resumed child arrives with fresh options, and counting it from zero would
|
|
13
|
+
* let it delegate as if it were top-level.
|
|
14
|
+
* @param agent - the agent whose header and options carry the depth.
|
|
15
|
+
* @returns its non-negative safe-integer depth.
|
|
16
|
+
* @throws if the runtime `AgentOptions.subagentDepth` is not a non-negative safe integer.
|
|
17
|
+
*/
|
|
18
|
+
export function delegationDepthOf(agent) {
|
|
19
|
+
const runtime = agent.options.subagentDepth;
|
|
20
|
+
if (runtime !== undefined && (!Number.isSafeInteger(runtime) || runtime < 0 || Object.is(runtime, -0))) {
|
|
21
|
+
throw new TypeError('agent subagentDepth must be a non-negative safe integer');
|
|
22
|
+
}
|
|
23
|
+
// The header value was validated at the session boundary (creation and
|
|
24
|
+
// persistence load both construct through the store).
|
|
25
|
+
return Math.max(agent.session.header.delegationDepth ?? 0, runtime ?? 0);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Reject a recursion cap that cannot represent an exact delegation depth.
|
|
29
|
+
* @param maxDepth - the optional runtime value to validate.
|
|
30
|
+
*/
|
|
31
|
+
export function assertSubagentMaxDepth(maxDepth) {
|
|
32
|
+
if (maxDepth !== undefined && (typeof maxDepth !== 'number'
|
|
33
|
+
|| !Number.isSafeInteger(maxDepth)
|
|
34
|
+
|| maxDepth < 0
|
|
35
|
+
|| Object.is(maxDepth, -0))) {
|
|
36
|
+
throw new TypeError('subagent maxDepth must be a non-negative safe integer');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=depth.js.map
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The durable subagent-child descriptor: the versioned, model-hidden
|
|
3
|
+
* `subagent/descriptor` session event that identifies every session-backed
|
|
4
|
+
* subagent and records whether it is one-shot or continuable. Continuable
|
|
5
|
+
* descriptors additionally preserve the declared composition required for
|
|
6
|
+
* cold resume. Providers append it turn-enclosed in the child's initial turn.
|
|
7
|
+
*
|
|
8
|
+
* The descriptor deliberately snapshots explicit fields rather than the
|
|
9
|
+
* merge-extensible `AgentOptions` object: an unrelated extension value cannot
|
|
10
|
+
* make continuation fail merely because it is not JSON, and later composition
|
|
11
|
+
* inputs require a deliberate {@link SUBAGENT_DESCRIPTOR_VERSION} change. It
|
|
12
|
+
* omits `subagentDepth` — cold resume trusts the persisted header's
|
|
13
|
+
* `delegationDepth` as the monotone floor — and `outputSchema`, which belongs
|
|
14
|
+
* to one activation's result contract rather than durable child composition.
|
|
15
|
+
* Per-activation knobs such as `maxTokens` are omitted for the same reason as
|
|
16
|
+
* `outputSchema`: they budget one activation. Cold resume requires the exact
|
|
17
|
+
* live parent for authorization but reconstructs child options only from the
|
|
18
|
+
* durable descriptor, so it neither restores the prior budget nor inherits
|
|
19
|
+
* the parent's current one; the resumed route's defaults apply instead.
|
|
20
|
+
*
|
|
21
|
+
* @module @deepseek-ai/dsh-subagent/descriptor
|
|
22
|
+
*/
|
|
23
|
+
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
24
|
+
import type { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
25
|
+
import type { ToolRestriction } from '@deepseek-ai/dsh-tools';
|
|
26
|
+
declare module '@deepseek-ai/dsh-session/types' {
|
|
27
|
+
interface SessionEventMap {
|
|
28
|
+
/**
|
|
29
|
+
* Durable identity and lifecycle mode of a session-backed subagent child,
|
|
30
|
+
* appended once by the establishing provider inside the child's initial
|
|
31
|
+
* turn, before its first request. Continuable records also carry their
|
|
32
|
+
* resumable composition. Log-only: it carries no `surfaceOp`, never enters
|
|
33
|
+
* model history, and survives compaction.
|
|
34
|
+
*/
|
|
35
|
+
'subagent/descriptor': SubagentDescriptorData;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The current descriptor format version, stamped into every appended
|
|
40
|
+
* `subagent/descriptor` event and required verbatim by {@link foldSubagentDescriptor}.
|
|
41
|
+
* Supporting another composition input is a deliberate version change, never
|
|
42
|
+
* an implicit extra field.
|
|
43
|
+
*/
|
|
44
|
+
export declare const SUBAGENT_DESCRIPTOR_VERSION = 3;
|
|
45
|
+
/** Fields shared by every supported `subagent/descriptor` payload. */
|
|
46
|
+
interface SubagentDescriptorBase {
|
|
47
|
+
/** Descriptor format version ({@link SUBAGENT_DESCRIPTOR_VERSION}). */
|
|
48
|
+
readonly version: number;
|
|
49
|
+
/** Whether the child is a terminal one-shot run or a resumable conversation. */
|
|
50
|
+
readonly mode: 'one-shot' | 'continuable';
|
|
51
|
+
/** The `ctx.subagents` provider name that established the child. */
|
|
52
|
+
readonly provider: string;
|
|
53
|
+
}
|
|
54
|
+
/** A session-backed subagent that cannot be cold-resumed after its run. */
|
|
55
|
+
export interface OneShotSubagentDescriptorData extends SubagentDescriptorBase {
|
|
56
|
+
readonly mode: 'one-shot';
|
|
57
|
+
/**
|
|
58
|
+
* The initial delegation's short `description`, kept as the child's durable
|
|
59
|
+
* creation label so enumeration can identify the conversation without
|
|
60
|
+
* replaying parent tool results or exposing the child prompt.
|
|
61
|
+
*/
|
|
62
|
+
readonly label?: string;
|
|
63
|
+
}
|
|
64
|
+
/** A session-backed subagent whose declared composition supports cold resume. */
|
|
65
|
+
export interface ContinuableSubagentDescriptorData extends SubagentDescriptorBase {
|
|
66
|
+
readonly mode: 'continuable';
|
|
67
|
+
/** The initial delegation's short `description`, used for durable enumeration. */
|
|
68
|
+
readonly label: string;
|
|
69
|
+
/** Resolved child `agentOptions.provider`, when one was declared. */
|
|
70
|
+
readonly agentProvider?: string;
|
|
71
|
+
/** Resolved child `agentOptions.model`, when one was declared. */
|
|
72
|
+
readonly agentModel?: string;
|
|
73
|
+
/** Resolved child `agentOptions.reasoningEffort`, when one was declared. */
|
|
74
|
+
readonly agentReasoningEffort?: ReasoningEffortId;
|
|
75
|
+
/** Per-child persona that shadows the deployment persona on resume. */
|
|
76
|
+
readonly persona?: string;
|
|
77
|
+
/** Child tool scoping reapplied on resume. */
|
|
78
|
+
readonly toolFilter?: ToolRestriction;
|
|
79
|
+
}
|
|
80
|
+
/** The supported durable subagent identity and optional continuation composition. */
|
|
81
|
+
export type SubagentDescriptorData = OneShotSubagentDescriptorData | ContinuableSubagentDescriptorData;
|
|
82
|
+
/** Fields shared by descriptor snapshot inputs. */
|
|
83
|
+
interface SubagentDescriptorInputBase {
|
|
84
|
+
/** Whether the child is a terminal one-shot run or a resumable conversation. */
|
|
85
|
+
readonly mode: 'one-shot' | 'continuable';
|
|
86
|
+
/** The `ctx.subagents` provider name that will establish the child. */
|
|
87
|
+
readonly provider: string;
|
|
88
|
+
}
|
|
89
|
+
/** Input for a one-shot child's durable identity. */
|
|
90
|
+
export interface OneShotSubagentDescriptorInput extends SubagentDescriptorInputBase {
|
|
91
|
+
readonly mode: 'one-shot';
|
|
92
|
+
/** Optional initial delegation `description` used as the durable creation label. */
|
|
93
|
+
readonly label?: string;
|
|
94
|
+
}
|
|
95
|
+
/** Input for a continuable child's durable identity and resumable composition. */
|
|
96
|
+
export interface ContinuableSubagentDescriptorInput extends SubagentDescriptorInputBase {
|
|
97
|
+
readonly mode: 'continuable';
|
|
98
|
+
/** Initial delegation `description` used for durable enumeration. */
|
|
99
|
+
readonly label: string;
|
|
100
|
+
/** Requested child `agentOptions.provider`. */
|
|
101
|
+
readonly agentProvider?: string;
|
|
102
|
+
/** Requested child `agentOptions.model`. */
|
|
103
|
+
readonly agentModel?: string;
|
|
104
|
+
/** Requested child `agentOptions.reasoningEffort`. */
|
|
105
|
+
readonly agentReasoningEffort?: ReasoningEffortId;
|
|
106
|
+
/** Requested per-child persona. */
|
|
107
|
+
readonly persona?: string;
|
|
108
|
+
/** Requested child tool scoping. */
|
|
109
|
+
readonly toolFilter?: ToolRestriction;
|
|
110
|
+
}
|
|
111
|
+
/** Inputs {@link snapshotSubagentDescriptor} validates and detaches. */
|
|
112
|
+
export type SubagentDescriptorInput = OneShotSubagentDescriptorInput | ContinuableSubagentDescriptorInput;
|
|
113
|
+
/**
|
|
114
|
+
* Validate and detach descriptor inputs into the durable payload, before any
|
|
115
|
+
* Task or provider work begins — the same detached lossless-JSON boundary the
|
|
116
|
+
* session log itself enforces, applied early so a synchronous validation
|
|
117
|
+
* failure rejects the tool call without creating a Task.
|
|
118
|
+
* @param input - the caller-collected composition fields.
|
|
119
|
+
* @returns the versioned, detached descriptor payload.
|
|
120
|
+
* @throws when a field is not losslessly JSON-serializable.
|
|
121
|
+
*/
|
|
122
|
+
export declare function snapshotSubagentDescriptor(input: OneShotSubagentDescriptorInput): OneShotSubagentDescriptorData;
|
|
123
|
+
/**
|
|
124
|
+
* Validate and detach a continuable descriptor input.
|
|
125
|
+
* @param input - the caller-collected continuable composition fields.
|
|
126
|
+
* @returns the versioned, detached continuable descriptor payload.
|
|
127
|
+
* @throws when a field is not losslessly JSON-serializable.
|
|
128
|
+
*/
|
|
129
|
+
export declare function snapshotSubagentDescriptor(input: ContinuableSubagentDescriptorInput): ContinuableSubagentDescriptorData;
|
|
130
|
+
/**
|
|
131
|
+
* Fold a persisted child log to its supported descriptor. The first
|
|
132
|
+
* `subagent/descriptor` event is authoritative — the establishing provider
|
|
133
|
+
* appends exactly one, so a later same-type event cannot rewrite the declared
|
|
134
|
+
* composition.
|
|
135
|
+
* @param events - the loaded child session events.
|
|
136
|
+
* @returns the descriptor, or `undefined` when the log has none or its
|
|
137
|
+
* version is not {@link SUBAGENT_DESCRIPTOR_VERSION} (the child cannot be
|
|
138
|
+
* classified by this runtime).
|
|
139
|
+
* @throws when a current-version persisted payload does not match its complete
|
|
140
|
+
* declared schema.
|
|
141
|
+
*/
|
|
142
|
+
export declare function foldSubagentDescriptor(events: readonly SessionEvent[]): SubagentDescriptorData | undefined;
|
|
143
|
+
export {};
|
|
144
|
+
//# sourceMappingURL=descriptor.d.ts.map
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The durable subagent-child descriptor: the versioned, model-hidden
|
|
3
|
+
* `subagent/descriptor` session event that identifies every session-backed
|
|
4
|
+
* subagent and records whether it is one-shot or continuable. Continuable
|
|
5
|
+
* descriptors additionally preserve the declared composition required for
|
|
6
|
+
* cold resume. Providers append it turn-enclosed in the child's initial turn.
|
|
7
|
+
*
|
|
8
|
+
* The descriptor deliberately snapshots explicit fields rather than the
|
|
9
|
+
* merge-extensible `AgentOptions` object: an unrelated extension value cannot
|
|
10
|
+
* make continuation fail merely because it is not JSON, and later composition
|
|
11
|
+
* inputs require a deliberate {@link SUBAGENT_DESCRIPTOR_VERSION} change. It
|
|
12
|
+
* omits `subagentDepth` — cold resume trusts the persisted header's
|
|
13
|
+
* `delegationDepth` as the monotone floor — and `outputSchema`, which belongs
|
|
14
|
+
* to one activation's result contract rather than durable child composition.
|
|
15
|
+
* Per-activation knobs such as `maxTokens` are omitted for the same reason as
|
|
16
|
+
* `outputSchema`: they budget one activation. Cold resume requires the exact
|
|
17
|
+
* live parent for authorization but reconstructs child options only from the
|
|
18
|
+
* durable descriptor, so it neither restores the prior budget nor inherits
|
|
19
|
+
* the parent's current one; the resumed route's defaults apply instead.
|
|
20
|
+
*
|
|
21
|
+
* @module @deepseek-ai/dsh-subagent/descriptor
|
|
22
|
+
*/
|
|
23
|
+
import { snapshotJsonValue } from '@deepseek-ai/dsh-util-values';
|
|
24
|
+
/**
|
|
25
|
+
* The current descriptor format version, stamped into every appended
|
|
26
|
+
* `subagent/descriptor` event and required verbatim by {@link foldSubagentDescriptor}.
|
|
27
|
+
* Supporting another composition input is a deliberate version change, never
|
|
28
|
+
* an implicit extra field.
|
|
29
|
+
*/
|
|
30
|
+
export const SUBAGENT_DESCRIPTOR_VERSION = 3;
|
|
31
|
+
const DESCRIPTOR_BASE_KEYS = [
|
|
32
|
+
'version',
|
|
33
|
+
'mode',
|
|
34
|
+
'provider',
|
|
35
|
+
'label',
|
|
36
|
+
];
|
|
37
|
+
const ONE_SHOT_DESCRIPTOR_KEYS = new Set(DESCRIPTOR_BASE_KEYS);
|
|
38
|
+
const CONTINUABLE_DESCRIPTOR_KEYS = new Set([
|
|
39
|
+
...DESCRIPTOR_BASE_KEYS,
|
|
40
|
+
'agentProvider',
|
|
41
|
+
'agentModel',
|
|
42
|
+
'agentReasoningEffort',
|
|
43
|
+
'persona',
|
|
44
|
+
'toolFilter',
|
|
45
|
+
]);
|
|
46
|
+
const TOOL_FILTER_KEYS = new Set(['allow', 'deny']);
|
|
47
|
+
/** Whether a persisted JSON value is an object record. */
|
|
48
|
+
function isRecord(value) {
|
|
49
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
/** Reject fields outside one versioned record's declared schema. */
|
|
52
|
+
function assertKnownKeys(value, keys, path) {
|
|
53
|
+
const unknown = Object.keys(value).find(key => !keys.has(key));
|
|
54
|
+
if (unknown !== undefined) {
|
|
55
|
+
throw new Error(`persisted subagent descriptor ${path} has unknown field "${unknown}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Read one optional string field from a persisted descriptor record. */
|
|
59
|
+
function optionalString(value, key) {
|
|
60
|
+
if (!Object.hasOwn(value, key))
|
|
61
|
+
return undefined;
|
|
62
|
+
const field = value[key];
|
|
63
|
+
if (typeof field !== 'string') {
|
|
64
|
+
throw new Error(`persisted subagent descriptor ${key} must be a string`);
|
|
65
|
+
}
|
|
66
|
+
return field;
|
|
67
|
+
}
|
|
68
|
+
/** Read one optional string-array field from a persisted tool restriction. */
|
|
69
|
+
function optionalStringArray(value, key) {
|
|
70
|
+
if (!Object.hasOwn(value, key))
|
|
71
|
+
return undefined;
|
|
72
|
+
const field = value[key];
|
|
73
|
+
if (!Array.isArray(field)) {
|
|
74
|
+
throw new Error(`persisted subagent descriptor toolFilter.${key} must be an array of strings`);
|
|
75
|
+
}
|
|
76
|
+
const items = field;
|
|
77
|
+
if (items.some(item => typeof item !== 'string')) {
|
|
78
|
+
throw new Error(`persisted subagent descriptor toolFilter.${key} must be an array of strings`);
|
|
79
|
+
}
|
|
80
|
+
return items;
|
|
81
|
+
}
|
|
82
|
+
/** Validate and reconstruct a persisted tool restriction. */
|
|
83
|
+
function parseToolFilter(value) {
|
|
84
|
+
if (!isRecord(value)) {
|
|
85
|
+
throw new Error('persisted subagent descriptor toolFilter must be an object');
|
|
86
|
+
}
|
|
87
|
+
assertKnownKeys(value, TOOL_FILTER_KEYS, 'toolFilter');
|
|
88
|
+
const allow = optionalStringArray(value, 'allow');
|
|
89
|
+
const deny = optionalStringArray(value, 'deny');
|
|
90
|
+
if (allow === undefined && deny === undefined) {
|
|
91
|
+
throw new Error('persisted subagent descriptor toolFilter must declare allow and/or deny');
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
...allow !== undefined ? { allow } : {},
|
|
95
|
+
...deny !== undefined ? { deny } : {},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** Validate one persisted descriptor payload for the current runtime. */
|
|
99
|
+
function parseSubagentDescriptor(value) {
|
|
100
|
+
if (!isRecord(value)) {
|
|
101
|
+
throw new Error('persisted subagent descriptor payload must be an object');
|
|
102
|
+
}
|
|
103
|
+
const version = value['version'];
|
|
104
|
+
if (typeof version !== 'number') {
|
|
105
|
+
throw new Error('persisted subagent descriptor version must be a number');
|
|
106
|
+
}
|
|
107
|
+
if (version !== SUBAGENT_DESCRIPTOR_VERSION)
|
|
108
|
+
return undefined;
|
|
109
|
+
const mode = value['mode'];
|
|
110
|
+
if (mode !== 'one-shot' && mode !== 'continuable') {
|
|
111
|
+
throw new Error('persisted subagent descriptor mode must be "one-shot" or "continuable"');
|
|
112
|
+
}
|
|
113
|
+
assertKnownKeys(value, mode === 'one-shot' ? ONE_SHOT_DESCRIPTOR_KEYS : CONTINUABLE_DESCRIPTOR_KEYS, 'payload');
|
|
114
|
+
const provider = value['provider'];
|
|
115
|
+
if (typeof provider !== 'string') {
|
|
116
|
+
throw new Error('persisted subagent descriptor provider must be a string');
|
|
117
|
+
}
|
|
118
|
+
if (mode === 'one-shot') {
|
|
119
|
+
const label = optionalString(value, 'label');
|
|
120
|
+
return {
|
|
121
|
+
version: SUBAGENT_DESCRIPTOR_VERSION,
|
|
122
|
+
mode,
|
|
123
|
+
provider,
|
|
124
|
+
...label !== undefined ? { label } : {},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const label = value['label'];
|
|
128
|
+
if (typeof label !== 'string') {
|
|
129
|
+
throw new Error('persisted subagent descriptor label must be a string');
|
|
130
|
+
}
|
|
131
|
+
const agentProvider = optionalString(value, 'agentProvider');
|
|
132
|
+
const agentModel = optionalString(value, 'agentModel');
|
|
133
|
+
const agentReasoningEffort = optionalString(value, 'agentReasoningEffort');
|
|
134
|
+
const persona = optionalString(value, 'persona');
|
|
135
|
+
const toolFilter = Object.hasOwn(value, 'toolFilter')
|
|
136
|
+
? parseToolFilter(value['toolFilter'])
|
|
137
|
+
: undefined;
|
|
138
|
+
return {
|
|
139
|
+
version: SUBAGENT_DESCRIPTOR_VERSION,
|
|
140
|
+
mode,
|
|
141
|
+
provider,
|
|
142
|
+
label,
|
|
143
|
+
...agentProvider !== undefined ? { agentProvider } : {},
|
|
144
|
+
...agentModel !== undefined ? { agentModel } : {},
|
|
145
|
+
...agentReasoningEffort !== undefined ? { agentReasoningEffort } : {},
|
|
146
|
+
...persona !== undefined ? { persona } : {},
|
|
147
|
+
...toolFilter !== undefined ? { toolFilter } : {},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function snapshotSubagentDescriptor(input) {
|
|
151
|
+
const candidate = input.mode === 'one-shot'
|
|
152
|
+
? {
|
|
153
|
+
version: SUBAGENT_DESCRIPTOR_VERSION,
|
|
154
|
+
mode: input.mode,
|
|
155
|
+
provider: input.provider,
|
|
156
|
+
...input.label !== undefined ? { label: input.label } : {},
|
|
157
|
+
}
|
|
158
|
+
: {
|
|
159
|
+
version: SUBAGENT_DESCRIPTOR_VERSION,
|
|
160
|
+
mode: input.mode,
|
|
161
|
+
provider: input.provider,
|
|
162
|
+
label: input.label,
|
|
163
|
+
...input.agentProvider !== undefined ? { agentProvider: input.agentProvider } : {},
|
|
164
|
+
...input.agentModel !== undefined ? { agentModel: input.agentModel } : {},
|
|
165
|
+
...input.agentReasoningEffort !== undefined ? { agentReasoningEffort: input.agentReasoningEffort } : {},
|
|
166
|
+
...input.persona !== undefined ? { persona: input.persona } : {},
|
|
167
|
+
...input.toolFilter !== undefined ? { toolFilter: input.toolFilter } : {},
|
|
168
|
+
};
|
|
169
|
+
const snapshot = snapshotJsonValue(candidate);
|
|
170
|
+
if (snapshot === undefined) {
|
|
171
|
+
throw new Error('subagent descriptor is not losslessly JSON-serializable');
|
|
172
|
+
}
|
|
173
|
+
return snapshot;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Fold a persisted child log to its supported descriptor. The first
|
|
177
|
+
* `subagent/descriptor` event is authoritative — the establishing provider
|
|
178
|
+
* appends exactly one, so a later same-type event cannot rewrite the declared
|
|
179
|
+
* composition.
|
|
180
|
+
* @param events - the loaded child session events.
|
|
181
|
+
* @returns the descriptor, or `undefined` when the log has none or its
|
|
182
|
+
* version is not {@link SUBAGENT_DESCRIPTOR_VERSION} (the child cannot be
|
|
183
|
+
* classified by this runtime).
|
|
184
|
+
* @throws when a current-version persisted payload does not match its complete
|
|
185
|
+
* declared schema.
|
|
186
|
+
*/
|
|
187
|
+
export function foldSubagentDescriptor(events) {
|
|
188
|
+
const event = events.find((candidate) => candidate.type === 'subagent/descriptor');
|
|
189
|
+
if (event === undefined)
|
|
190
|
+
return undefined;
|
|
191
|
+
return parseSubagentDescriptor(event.data);
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=descriptor.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed failures shared by subagent service and provider operations.
|
|
3
|
+
*
|
|
4
|
+
* @module @deepseek-ai/dsh-subagent
|
|
5
|
+
*/
|
|
6
|
+
import { HarnessError } from '@deepseek-ai/dsh-llm';
|
|
7
|
+
/** Typed failure for the subagent seam. */
|
|
8
|
+
export declare class SubagentError extends HarnessError {
|
|
9
|
+
constructor(message: string, code: string, options?: ErrorOptions);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed failures shared by subagent service and provider operations.
|
|
3
|
+
*
|
|
4
|
+
* @module @deepseek-ai/dsh-subagent
|
|
5
|
+
*/
|
|
6
|
+
import { HarnessError } from '@deepseek-ai/dsh-llm';
|
|
7
|
+
/** Typed failure for the subagent seam. */
|
|
8
|
+
export class SubagentError extends HarnessError {
|
|
9
|
+
constructor(message, code, options) {
|
|
10
|
+
super(message, code, options);
|
|
11
|
+
this.name = 'SubagentError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activation-local admission around one continuable subagent's Agent inbox.
|
|
3
|
+
*
|
|
4
|
+
* @module @deepseek-ai/dsh-subagent/inbox
|
|
5
|
+
*/
|
|
6
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
7
|
+
import type { UserMessage } from '@deepseek-ai/dsh-session';
|
|
8
|
+
import type { SubagentPromptRequest } from './control-types.ts';
|
|
9
|
+
/** One Agent inbox destination, as the wire request selects it. */
|
|
10
|
+
export type SubagentDelivery = SubagentPromptRequest['delivery'];
|
|
11
|
+
/** Delegate Queue and Steer to one live Agent until its Activation starts closing. */
|
|
12
|
+
export declare class SubagentInbox {
|
|
13
|
+
private readonly agent;
|
|
14
|
+
private closingPromise;
|
|
15
|
+
/**
|
|
16
|
+
* Wrap one live continuable Agent.
|
|
17
|
+
* @param agent - the Agent whose inbox receives accepted deliveries.
|
|
18
|
+
*/
|
|
19
|
+
constructor(agent: Agent);
|
|
20
|
+
/**
|
|
21
|
+
* Read the Activation's close transaction.
|
|
22
|
+
* @returns the memoized transaction, or `undefined` while delivery remains open.
|
|
23
|
+
*/
|
|
24
|
+
get closing(): Promise<void> | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Read whether the underlying Agent still has accepted work to claim.
|
|
27
|
+
* @returns whether either Agent inbox destination is non-empty.
|
|
28
|
+
*/
|
|
29
|
+
get hasPending(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Submit through the Agent only while its Activation remains resident.
|
|
32
|
+
* @param message - the accepted input to submit.
|
|
33
|
+
* @param delivery - whether to queue a distinct turn or steer the nearest step.
|
|
34
|
+
*/
|
|
35
|
+
deliver(message: UserMessage, delivery: SubagentDelivery): void;
|
|
36
|
+
/**
|
|
37
|
+
* Close delivery synchronously and share one asynchronous release.
|
|
38
|
+
* @param release - the one release operation to start after closing admission.
|
|
39
|
+
* @returns the memoized release transaction.
|
|
40
|
+
*/
|
|
41
|
+
close(release: () => Promise<void>): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=inbox.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activation-local admission around one continuable subagent's Agent inbox.
|
|
3
|
+
*
|
|
4
|
+
* @module @deepseek-ai/dsh-subagent/inbox
|
|
5
|
+
*/
|
|
6
|
+
import { SubagentError } from "./error.js";
|
|
7
|
+
/** Delegate Queue and Steer to one live Agent until its Activation starts closing. */
|
|
8
|
+
export class SubagentInbox {
|
|
9
|
+
agent;
|
|
10
|
+
closingPromise;
|
|
11
|
+
/**
|
|
12
|
+
* Wrap one live continuable Agent.
|
|
13
|
+
* @param agent - the Agent whose inbox receives accepted deliveries.
|
|
14
|
+
*/
|
|
15
|
+
constructor(agent) {
|
|
16
|
+
this.agent = agent;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Read the Activation's close transaction.
|
|
20
|
+
* @returns the memoized transaction, or `undefined` while delivery remains open.
|
|
21
|
+
*/
|
|
22
|
+
get closing() {
|
|
23
|
+
return this.closingPromise;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read whether the underlying Agent still has accepted work to claim.
|
|
27
|
+
* @returns whether either Agent inbox destination is non-empty.
|
|
28
|
+
*/
|
|
29
|
+
get hasPending() {
|
|
30
|
+
return this.agent.inbox.nextTurn.length > 0 || this.agent.inbox.nextStep.length > 0;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Submit through the Agent only while its Activation remains resident.
|
|
34
|
+
* @param message - the accepted input to submit.
|
|
35
|
+
* @param delivery - whether to queue a distinct turn or steer the nearest step.
|
|
36
|
+
*/
|
|
37
|
+
deliver(message, delivery) {
|
|
38
|
+
if (this.closingPromise !== undefined) {
|
|
39
|
+
throw new SubagentError(`subagent "${this.agent.id}" activation is being disposed; the message was not accepted`, 'ACTIVATION_CLOSING');
|
|
40
|
+
}
|
|
41
|
+
if (delivery === 'steer')
|
|
42
|
+
this.agent.steer(message);
|
|
43
|
+
else
|
|
44
|
+
this.agent.followup(message);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Close delivery synchronously and share one asynchronous release.
|
|
48
|
+
* @param release - the one release operation to start after closing admission.
|
|
49
|
+
* @returns the memoized release transaction.
|
|
50
|
+
*/
|
|
51
|
+
close(release) {
|
|
52
|
+
const existing = this.closingPromise;
|
|
53
|
+
if (existing !== undefined)
|
|
54
|
+
return existing;
|
|
55
|
+
const completion = Promise.withResolvers();
|
|
56
|
+
this.closingPromise = completion.promise;
|
|
57
|
+
void release().then(completion.resolve, completion.reject);
|
|
58
|
+
return completion.promise;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=inbox.js.map
|