@deepseek-ai/dsh-subagent 0.0.1-rc.1
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/LICENSE +28 -0
- package/README.i18n.yaml +6 -0
- package/README.md +132 -0
- package/README.zh.md +132 -0
- package/lib/index.js +2392 -0
- package/lib/invariant.js +76 -0
- package/lib/types/activation-setup-registry.d.ts +57 -0
- package/lib/types/activation-setup-registry.js +148 -0
- package/lib/types/child-agent.d.ts +139 -0
- package/lib/types/child-agent.js +169 -0
- package/lib/types/client.d.ts +7 -0
- package/lib/types/client.js +7 -0
- package/lib/types/continuation.d.ts +375 -0
- package/lib/types/continuation.js +951 -0
- package/lib/types/depth.d.ts +31 -0
- package/lib/types/depth.js +39 -0
- package/lib/types/descriptor-seed.d.ts +21 -0
- package/lib/types/descriptor-seed.js +24 -0
- package/lib/types/descriptor.d.ts +139 -0
- package/lib/types/descriptor.js +189 -0
- package/lib/types/error.d.ts +11 -0
- package/lib/types/error.js +14 -0
- package/lib/types/index.d.ts +278 -0
- package/lib/types/index.js +338 -0
- package/lib/types/invariant.d.ts +13 -0
- package/lib/types/invariant.js +91 -0
- package/lib/types/lifecycle.d.ts +93 -0
- package/lib/types/lifecycle.js +169 -0
- package/lib/types/list-children.d.ts +112 -0
- package/lib/types/list-children.js +316 -0
- package/lib/types/out-of-process.d.ts +115 -0
- package/lib/types/out-of-process.js +181 -0
- package/lib/types/projection-types.d.ts +60 -0
- package/lib/types/projection-types.js +7 -0
- package/lib/types/projection.d.ts +48 -0
- package/lib/types/projection.js +135 -0
- package/lib/types/run-settlement.d.ts +17 -0
- package/lib/types/run-settlement.js +59 -0
- package/lib/types/types.d.ts +293 -0
- package/lib/types/types.js +19 -0
- package/package.json +106 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** Package-owned subagent registry and lifecycle invariants. @module @deepseek-ai/dsh-subagent/invariant */
|
|
2
|
+
const PACKAGE_NAME = '@deepseek-ai/dsh-subagent';
|
|
3
|
+
/** Cordis companion plugin name. */
|
|
4
|
+
export const name = 'subagent-invariant';
|
|
5
|
+
/** Service required before the companion can reserve package ownership. */
|
|
6
|
+
export const inject = ['invariants'];
|
|
7
|
+
/** Assert that a terminal lifecycle payload matches its start identity. */
|
|
8
|
+
function validateRunEnd(start, end, fail) {
|
|
9
|
+
if (start.provider !== end.provider || start.id !== end.id || start.local !== end.local) {
|
|
10
|
+
fail(`subagent/end identity diverges from subagent/start for run ${JSON.stringify(end.runId)}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Install provider-registry and start/end pairing checks. */
|
|
14
|
+
const install = Object.assign((ctx, fail) => {
|
|
15
|
+
const providers = new Set(ctx.subagents.list());
|
|
16
|
+
const runs = new Map();
|
|
17
|
+
const stagedProviders = new WeakSet();
|
|
18
|
+
const stagedRemovals = new Set();
|
|
19
|
+
const stagedStarts = new WeakSet();
|
|
20
|
+
const stagedEnds = new WeakSet();
|
|
21
|
+
ctx.on('internal/dispatch', (_mode, eventName, args) => {
|
|
22
|
+
if (eventName === 'subagent/provider-added') {
|
|
23
|
+
const provider = args[0];
|
|
24
|
+
if (provider.name.length === 0)
|
|
25
|
+
fail('subagent provider names must be non-empty');
|
|
26
|
+
if (providers.has(provider.name))
|
|
27
|
+
fail(`subagent/provider-added repeated ${JSON.stringify(provider.name)}`);
|
|
28
|
+
stagedProviders.add(provider);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (eventName === 'subagent/provider-removed') {
|
|
32
|
+
const providerName = args[0];
|
|
33
|
+
if (!providers.has(providerName))
|
|
34
|
+
fail(`subagent/provider-removed names unknown provider ${JSON.stringify(providerName)}`);
|
|
35
|
+
stagedRemovals.add(providerName);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (eventName === 'subagent/start') {
|
|
39
|
+
const info = args[0];
|
|
40
|
+
// Provider availability is an admission-time relationship. A published
|
|
41
|
+
// one-shot run may outlive provider removal, and a cold-resumed Activation
|
|
42
|
+
// records the initial provider name without dispatching through it.
|
|
43
|
+
if (info.provider.length === 0 || String(info.runId).length === 0 || String(info.id).length === 0) {
|
|
44
|
+
fail('subagent/start provider, runId, and child id must be non-empty');
|
|
45
|
+
}
|
|
46
|
+
if (runs.has(info.runId))
|
|
47
|
+
fail(`subagent/start repeated run id ${JSON.stringify(info.runId)}`);
|
|
48
|
+
stagedStarts.add(info);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (eventName !== 'subagent/end')
|
|
52
|
+
return;
|
|
53
|
+
const info = args[0];
|
|
54
|
+
const start = runs.get(info.runId);
|
|
55
|
+
if (start === undefined)
|
|
56
|
+
fail(`subagent/end has no matching subagent/start for run ${JSON.stringify(info.runId)}`);
|
|
57
|
+
validateRunEnd(start, info, fail);
|
|
58
|
+
stagedEnds.add(info);
|
|
59
|
+
}, { global: true });
|
|
60
|
+
ctx.on('subagent/provider-added', (provider) => {
|
|
61
|
+
/* v8 ignore next -- internal/dispatch stages the same provider object */
|
|
62
|
+
if (!stagedProviders.delete(provider))
|
|
63
|
+
return;
|
|
64
|
+
providers.add(provider.name);
|
|
65
|
+
}, { global: true });
|
|
66
|
+
ctx.on('subagent/provider-removed', (providerName) => {
|
|
67
|
+
/* v8 ignore next -- internal/dispatch stages the same provider name */
|
|
68
|
+
if (!stagedRemovals.delete(providerName))
|
|
69
|
+
return;
|
|
70
|
+
providers.delete(providerName);
|
|
71
|
+
}, { global: true });
|
|
72
|
+
ctx.on('subagent/start', (info) => {
|
|
73
|
+
/* v8 ignore next -- internal/dispatch stages the same lifecycle object */
|
|
74
|
+
if (!stagedStarts.delete(info))
|
|
75
|
+
return;
|
|
76
|
+
runs.set(info.runId, info);
|
|
77
|
+
}, { global: true });
|
|
78
|
+
ctx.on('subagent/end', (info) => {
|
|
79
|
+
/* v8 ignore next -- internal/dispatch stages the same lifecycle object */
|
|
80
|
+
if (!stagedEnds.delete(info))
|
|
81
|
+
return;
|
|
82
|
+
runs.delete(info.runId);
|
|
83
|
+
}, { global: true });
|
|
84
|
+
}, { inject: ['subagents'] });
|
|
85
|
+
/**
|
|
86
|
+
* Register the subagent invariant companion.
|
|
87
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
88
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
89
|
+
*/
|
|
90
|
+
export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
91
|
+
//# sourceMappingURL=invariant.js.map
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle-edge publication for both subagent shapes: the contained emitter,
|
|
3
|
+
* the one-shot run observer, and the continuable Activation observer.
|
|
4
|
+
*
|
|
5
|
+
* The public payload contracts ({@link SubagentRunInfo},
|
|
6
|
+
* {@link SubagentRunEndInfo}) live in `./types.ts` with the rest of the seam's
|
|
7
|
+
* consumer-facing types; this module owns only the implementation and the
|
|
8
|
+
* package-private {@link ActivationObserver} the continuation manager consumes.
|
|
9
|
+
* Keeping the internal control interface out of the published surface is
|
|
10
|
+
* deliberate: the observer's `start`/`capture`/`settle` ordering is a contract
|
|
11
|
+
* between this module and one in-package caller, not something a plugin may
|
|
12
|
+
* depend on.
|
|
13
|
+
*
|
|
14
|
+
* @module @deepseek-ai/dsh-subagent/lifecycle
|
|
15
|
+
*/
|
|
16
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
17
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
18
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
19
|
+
import type { SubagentRun, SubagentRunEndInfo, SubagentRunInfo } from './types.ts';
|
|
20
|
+
/**
|
|
21
|
+
* Lifecycle observer for one Activation's residency epoch, so continuable
|
|
22
|
+
* children emit the same start/end pair as one-shot runs. Package-private: the
|
|
23
|
+
* continuation manager is the only consumer, and its call ordering is an
|
|
24
|
+
* in-package contract rather than a published extension point.
|
|
25
|
+
*/
|
|
26
|
+
export interface ActivationObserver {
|
|
27
|
+
/**
|
|
28
|
+
* Publish the start edge once the epoch is resident.
|
|
29
|
+
* @param child - the resident child agent, whose log suffix bounds this epoch.
|
|
30
|
+
*/
|
|
31
|
+
start(child: Agent): void;
|
|
32
|
+
/**
|
|
33
|
+
* Snapshot the child-dependent terminal facts while the child is still
|
|
34
|
+
* registered, because handle disposal unregisters it and consumers resolve it
|
|
35
|
+
* to read the child's own log and scope.
|
|
36
|
+
* @param child - the quiescent child agent about to be released.
|
|
37
|
+
*/
|
|
38
|
+
capture(child: Agent): void;
|
|
39
|
+
/**
|
|
40
|
+
* Publish the terminal edge exactly once, pairing this epoch's {@link start},
|
|
41
|
+
* after the disposal outcome is known. Called only for a resident epoch: a
|
|
42
|
+
* failure before residency publishes no edge, because inventing one would
|
|
43
|
+
* report a lifecycle the child never had.
|
|
44
|
+
* @param failure - the teardown or durability failure, or `undefined` on success.
|
|
45
|
+
*/
|
|
46
|
+
settle(failure: unknown): void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Publish one lifecycle edge with per-listener exception containment. Run edges
|
|
50
|
+
* carry the delegating parent that keys scoped dispatch; provider removal has no
|
|
51
|
+
* parent carrier and reaches listeners unscoped.
|
|
52
|
+
*
|
|
53
|
+
* The service owns this closure because scoped dispatch keys its carrier by the
|
|
54
|
+
* exact service instance, whose own context filter composes into the carrier;
|
|
55
|
+
* a narrowed stand-in would silently change scope filtering.
|
|
56
|
+
*/
|
|
57
|
+
export type LifecycleEmitter = {
|
|
58
|
+
(name: 'subagent/start', info: SubagentRunInfo, parent: Agent): void;
|
|
59
|
+
(name: 'subagent/end', info: SubagentRunEndInfo, parent: Agent): void;
|
|
60
|
+
(name: 'subagent/provider-removed', info: string): void;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Build the contained lifecycle emitter this seam publishes every edge through.
|
|
64
|
+
* Every listener is independently contained: a synchronous throw or a rejected
|
|
65
|
+
* returned promise is logged without starving peer listeners, changing the run,
|
|
66
|
+
* or — for provider removal, which fires from a disposer — breaking teardown.
|
|
67
|
+
* @param ctx - the service's own context, owning dispatch and the logger.
|
|
68
|
+
* @param carrier - resolve the scoped dispatch carrier for one delegating parent.
|
|
69
|
+
* @returns the emitter both observers and the provider registry publish through.
|
|
70
|
+
*/
|
|
71
|
+
export declare function createLifecycleEmitter(ctx: Context, carrier: (parent: Agent) => object): LifecycleEmitter;
|
|
72
|
+
/**
|
|
73
|
+
* Emit the start/end lifecycle pair for one accepted one-shot run.
|
|
74
|
+
* @param emit - the contained lifecycle emitter.
|
|
75
|
+
* @param provider - the provider that established the run.
|
|
76
|
+
* @param parent - the delegating parent keying scoped dispatch.
|
|
77
|
+
* @param run - the published run whose settlement closes the pair.
|
|
78
|
+
* @returns the same run, unchanged.
|
|
79
|
+
*/
|
|
80
|
+
export declare function observeRun(emit: LifecycleEmitter, provider: string, parent: Agent, run: SubagentRun): SubagentRun;
|
|
81
|
+
/**
|
|
82
|
+
* Build the observer for one continuable Activation's residency epoch. Observers
|
|
83
|
+
* see the same vocabulary as a one-shot run, so a child's start and settlement
|
|
84
|
+
* remain observable without exposing whether the manager materialized, woke, or
|
|
85
|
+
* cold-resumed it. Creation failure before residency emits no lifecycle edge.
|
|
86
|
+
* @param emit - the contained lifecycle emitter.
|
|
87
|
+
* @param provider - the provider name recorded in the durable descriptor.
|
|
88
|
+
* @param childId - the durable child session id.
|
|
89
|
+
* @param parent - the exact live direct parent keying scoped dispatch.
|
|
90
|
+
* @returns the observer whose edges this epoch publishes.
|
|
91
|
+
*/
|
|
92
|
+
export declare function createActivationObserver(emit: LifecycleEmitter, provider: string, childId: SessionId, parent: Agent): ActivationObserver;
|
|
93
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle-edge publication for both subagent shapes: the contained emitter,
|
|
3
|
+
* the one-shot run observer, and the continuable Activation observer.
|
|
4
|
+
*
|
|
5
|
+
* The public payload contracts ({@link SubagentRunInfo},
|
|
6
|
+
* {@link SubagentRunEndInfo}) live in `./types.ts` with the rest of the seam's
|
|
7
|
+
* consumer-facing types; this module owns only the implementation and the
|
|
8
|
+
* package-private {@link ActivationObserver} the continuation manager consumes.
|
|
9
|
+
* Keeping the internal control interface out of the published surface is
|
|
10
|
+
* deliberate: the observer's `start`/`capture`/`settle` ordering is a contract
|
|
11
|
+
* between this module and one in-package caller, not something a plugin may
|
|
12
|
+
* depend on.
|
|
13
|
+
*
|
|
14
|
+
* @module @deepseek-ai/dsh-subagent/lifecycle
|
|
15
|
+
*/
|
|
16
|
+
import { randomUUID } from 'node:crypto';
|
|
17
|
+
import { findLastMessageTurnEnd } from '@deepseek-ai/dsh-session';
|
|
18
|
+
import { SubagentRunId } from "./types.js";
|
|
19
|
+
/**
|
|
20
|
+
* Build the contained lifecycle emitter this seam publishes every edge through.
|
|
21
|
+
* Every listener is independently contained: a synchronous throw or a rejected
|
|
22
|
+
* returned promise is logged without starving peer listeners, changing the run,
|
|
23
|
+
* or — for provider removal, which fires from a disposer — breaking teardown.
|
|
24
|
+
* @param ctx - the service's own context, owning dispatch and the logger.
|
|
25
|
+
* @param carrier - resolve the scoped dispatch carrier for one delegating parent.
|
|
26
|
+
* @returns the emitter both observers and the provider registry publish through.
|
|
27
|
+
*/
|
|
28
|
+
export function createLifecycleEmitter(ctx, carrier) {
|
|
29
|
+
return (name, info, parent) => {
|
|
30
|
+
const dispatchArgs = parent === undefined
|
|
31
|
+
? [name, info]
|
|
32
|
+
: [carrier(parent), name, info];
|
|
33
|
+
for (const callback of ctx.events.dispatch('emit', dispatchArgs)) {
|
|
34
|
+
try {
|
|
35
|
+
const returned = callback(info);
|
|
36
|
+
void Promise.resolve(returned).catch((error) => {
|
|
37
|
+
ctx.logger.warn(`subagent: ${name} listener rejected: ${renderThrown(error)}`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
ctx.logger.warn(`subagent: ${name} listener threw: ${renderThrown(error)}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Emit the start/end lifecycle pair for one accepted one-shot run.
|
|
48
|
+
* @param emit - the contained lifecycle emitter.
|
|
49
|
+
* @param provider - the provider that established the run.
|
|
50
|
+
* @param parent - the delegating parent keying scoped dispatch.
|
|
51
|
+
* @param run - the published run whose settlement closes the pair.
|
|
52
|
+
* @returns the same run, unchanged.
|
|
53
|
+
*/
|
|
54
|
+
export function observeRun(emit, provider, parent, run) {
|
|
55
|
+
const identity = {
|
|
56
|
+
runId: SubagentRunId(randomUUID()),
|
|
57
|
+
provider,
|
|
58
|
+
id: run.id,
|
|
59
|
+
local: run.localAgent !== undefined,
|
|
60
|
+
};
|
|
61
|
+
// Attach the terminal observer before dispatching start. Promise reactions
|
|
62
|
+
// still run after this synchronous start emission, preserving start → end.
|
|
63
|
+
void run.result.then((result) => {
|
|
64
|
+
emit('subagent/end', {
|
|
65
|
+
...identity,
|
|
66
|
+
stopReason: result.stopReason,
|
|
67
|
+
lastAssistantMessage: result.output,
|
|
68
|
+
}, parent);
|
|
69
|
+
}, () => {
|
|
70
|
+
emit('subagent/end', { ...identity, stopReason: 'error' }, parent);
|
|
71
|
+
});
|
|
72
|
+
emit('subagent/start', identity, parent);
|
|
73
|
+
return run;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the observer for one continuable Activation's residency epoch. Observers
|
|
77
|
+
* see the same vocabulary as a one-shot run, so a child's start and settlement
|
|
78
|
+
* remain observable without exposing whether the manager materialized, woke, or
|
|
79
|
+
* cold-resumed it. Creation failure before residency emits no lifecycle edge.
|
|
80
|
+
* @param emit - the contained lifecycle emitter.
|
|
81
|
+
* @param provider - the provider name recorded in the durable descriptor.
|
|
82
|
+
* @param childId - the durable child session id.
|
|
83
|
+
* @param parent - the exact live direct parent keying scoped dispatch.
|
|
84
|
+
* @returns the observer whose edges this epoch publishes.
|
|
85
|
+
*/
|
|
86
|
+
export function createActivationObserver(emit, provider, childId, parent) {
|
|
87
|
+
const identity = { runId: SubagentRunId(randomUUID()), provider, id: childId, local: true };
|
|
88
|
+
// A cold resume replays earlier turns, so this epoch's telemetry must come
|
|
89
|
+
// from the suffix it actually produced — never the whole session, which
|
|
90
|
+
// would report a previous epoch's answer when this one opened no turn.
|
|
91
|
+
let boundary = 0;
|
|
92
|
+
// Assigned by `capture()`, which the disposal path always runs before
|
|
93
|
+
// `settle()`; a resident epoch therefore always has its facts by then.
|
|
94
|
+
let captured = {
|
|
95
|
+
stopReason: 'completed',
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
start: (child) => {
|
|
99
|
+
boundary = child.session.events.length;
|
|
100
|
+
emit('subagent/start', identity, parent);
|
|
101
|
+
},
|
|
102
|
+
capture: (child) => {
|
|
103
|
+
const own = child.session.events.slice(boundary);
|
|
104
|
+
const output = lastAssistantOutput(own);
|
|
105
|
+
captured = {
|
|
106
|
+
stopReason: epochStopReason(own),
|
|
107
|
+
...output === undefined ? {} : { output },
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
settle: (failure) => {
|
|
111
|
+
const output = failure === undefined ? captured.output : undefined;
|
|
112
|
+
emit('subagent/end', {
|
|
113
|
+
...identity,
|
|
114
|
+
stopReason: failure === undefined ? captured.stopReason : 'error',
|
|
115
|
+
...output === undefined ? {} : { lastAssistantMessage: output },
|
|
116
|
+
}, parent);
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Why this child's last ordinary turn ended, for the terminal lifecycle edge.
|
|
122
|
+
* The child's own `turn/end` is authoritative: teardown succeeding says nothing
|
|
123
|
+
* about whether the model errored, hit its token ceiling, or was cancelled, so
|
|
124
|
+
* deriving the reason from disposal would report failed work as completed.
|
|
125
|
+
* @param events - this epoch's own event suffix.
|
|
126
|
+
* @returns its terminal stop reason; `completed` when no ordinary turn closed.
|
|
127
|
+
*/
|
|
128
|
+
function epochStopReason(events) {
|
|
129
|
+
const reason = findLastMessageTurnEnd(events)?.data.reason;
|
|
130
|
+
// No ordinary turn closed, so nothing failed either.
|
|
131
|
+
if (reason === undefined)
|
|
132
|
+
return 'completed';
|
|
133
|
+
switch (reason.kind) {
|
|
134
|
+
case 'max-tokens':
|
|
135
|
+
return 'max-tokens';
|
|
136
|
+
case 'aborted':
|
|
137
|
+
case 'interrupted':
|
|
138
|
+
return 'aborted';
|
|
139
|
+
case 'error':
|
|
140
|
+
return 'error';
|
|
141
|
+
case 'completed':
|
|
142
|
+
return 'completed';
|
|
143
|
+
/* v8 ignore next 3 -- `TurnEndReason` is merge-extensible, so this arm needs a
|
|
144
|
+
* backend that adds a variant; treating an unnameable reason as success would
|
|
145
|
+
* report failed work as completed. */
|
|
146
|
+
default:
|
|
147
|
+
return 'error';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The child's last assistant message content, for one Activation's terminal
|
|
152
|
+
* lifecycle edge. Absent when no assistant message reached the log.
|
|
153
|
+
* @param events - this epoch's own event suffix.
|
|
154
|
+
* @returns its final assistant content, or `undefined` when it produced none.
|
|
155
|
+
*/
|
|
156
|
+
function lastAssistantOutput(events) {
|
|
157
|
+
const message = events.findLast((event) => event.type === 'assistant/message');
|
|
158
|
+
return message?.data.message.content;
|
|
159
|
+
}
|
|
160
|
+
/** Render any listener-thrown value without letting coercion escape containment. */
|
|
161
|
+
function renderThrown(value) {
|
|
162
|
+
try {
|
|
163
|
+
return value instanceof Error ? `${value.name}: ${value.message}` : String(value);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return '<unrenderable thrown value>';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only enumeration of durable subagent children and descendant trees
|
|
3
|
+
* straight from the live session store and optional session persistence — no
|
|
4
|
+
* query service. Candidates come from one live-preferred corpus; each child's
|
|
5
|
+
* mode/label is the registered `subagent` projection unit's value, resolved
|
|
6
|
+
* down a three-rung ladder: the registry's watermark cache for a live child,
|
|
7
|
+
* a durable projection-cache row when it serves an own-suffix identity (the
|
|
8
|
+
* seq gate), and one persistence inspection folded through the registry
|
|
9
|
+
* otherwise, validated against the enumerated lifecycle. The projection fold
|
|
10
|
+
* is the single classification authority — this module parses no descriptor
|
|
11
|
+
* itself. Absent persistence, enumeration is live-only: a cold child is
|
|
12
|
+
* unreachable for resume anyway, so its absence is capability absence, not an
|
|
13
|
+
* error. The module owns no catalog state and does not consult Activation,
|
|
14
|
+
* Agent-registry, continuation-manager, or provider state.
|
|
15
|
+
*
|
|
16
|
+
* @module @deepseek-ai/dsh-subagent
|
|
17
|
+
*/
|
|
18
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
19
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
20
|
+
/**
|
|
21
|
+
* One entry of a {@link listChildren} result, ordered by header `createdAt`
|
|
22
|
+
* with ties broken on id. Only a candidate whose durable header has
|
|
23
|
+
* `origin: 'subagent'` is interpreted. A served `subagent` projection value
|
|
24
|
+
* produces a `child`; a settled candidate whose fold served no identity
|
|
25
|
+
* produces a `diagnostic`; a running candidate without one is omitted — its
|
|
26
|
+
* descriptor may not be appended yet (the creation window). Diagnostics
|
|
27
|
+
* relay the projection fold's outcome or a failed read, never a per-child
|
|
28
|
+
* event scan, and never expose model-hidden descriptor content.
|
|
29
|
+
*/
|
|
30
|
+
export type SubagentListEntry = {
|
|
31
|
+
readonly kind: 'child';
|
|
32
|
+
/** The durable child session id, stable across Activations. */
|
|
33
|
+
readonly id: SessionId;
|
|
34
|
+
/**
|
|
35
|
+
* Store snapshot activity: `running` means the logical record is live in
|
|
36
|
+
* `ctx.sessions`; `inactive` means it exists only in persistence. Neither
|
|
37
|
+
* encodes a durable outcome, and a continuable child may still reject
|
|
38
|
+
* delivery as an ownership conflict.
|
|
39
|
+
*/
|
|
40
|
+
readonly activity: 'running' | 'inactive';
|
|
41
|
+
/** Whether a direct descendant has durable `origin: 'subagent'`. */
|
|
42
|
+
readonly hasChildren: boolean;
|
|
43
|
+
} & ({
|
|
44
|
+
/** A terminal one-shot child. */
|
|
45
|
+
readonly mode: 'one-shot';
|
|
46
|
+
/** Optional durable creation label from the child's descriptor. */
|
|
47
|
+
readonly label?: string;
|
|
48
|
+
} | {
|
|
49
|
+
/** A resumable conversation. */
|
|
50
|
+
readonly mode: 'continuable';
|
|
51
|
+
/** Durable creation label from the child's descriptor. */
|
|
52
|
+
readonly label: string;
|
|
53
|
+
}) | {
|
|
54
|
+
readonly kind: 'diagnostic';
|
|
55
|
+
/** The candidate's session id. */
|
|
56
|
+
readonly id: SessionId;
|
|
57
|
+
/**
|
|
58
|
+
* Why the candidate has no `child` row: `corrupt` for a settled candidate
|
|
59
|
+
* whose projection fold served no identity (a missing, malformed, or
|
|
60
|
+
* unrecognized-version descriptor — deliberately undistinguished), and
|
|
61
|
+
* for any candidate whose log makes a registered unit's fold or schema
|
|
62
|
+
* throw (deterministic data damage, contained per child); `unavailable`
|
|
63
|
+
* when the candidate's persistence inspection failed (retried on the
|
|
64
|
+
* next listing). `unsupported` is never produced; it remains in the
|
|
65
|
+
* union for consumers that route on it.
|
|
66
|
+
*/
|
|
67
|
+
readonly reason: 'corrupt' | 'unsupported' | 'unavailable';
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* One entry of a descendant listing: the interpreted subagent facts plus its
|
|
71
|
+
* position in the complete session tree. `parentId` is the durable direct
|
|
72
|
+
* parent from the enumerated header, and `depth` counts edges from the root.
|
|
73
|
+
*/
|
|
74
|
+
export type SubagentDescendantListEntry = SubagentListEntry & {
|
|
75
|
+
/** Durable direct parent of this candidate in the enumerated tree. */
|
|
76
|
+
readonly parentId: SessionId;
|
|
77
|
+
/** Edge distance from the requested root; direct children are `1`. */
|
|
78
|
+
readonly depth: number;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Enumerate one parent's origin-classified direct children from the
|
|
82
|
+
* live-preferred merge of `ctx.sessions` and optional session persistence,
|
|
83
|
+
* serving each identity from the `subagent` projection unit: the registry's
|
|
84
|
+
* watermark snapshot for a live child; for a cold one, a durable
|
|
85
|
+
* projection-cache row when it serves an own-suffix identity (the seq gate),
|
|
86
|
+
* else one bounded-concurrency persistence inspection folded through the
|
|
87
|
+
* registry.
|
|
88
|
+
* @see SubagentService.listChildren for the public cancellation and failure contract.
|
|
89
|
+
* @param ctx - context carrying the session store, the projection registry,
|
|
90
|
+
* optional persistence, and the optional projection cache.
|
|
91
|
+
* @param parentSessionId - parent session whose direct children are listed.
|
|
92
|
+
* @param signal - caller-owned cancellation observed around every persistence read.
|
|
93
|
+
* @returns children and per-child diagnostics ordered by `createdAt`, then id.
|
|
94
|
+
* @throws {@link SubagentError} when the projection registry or the session
|
|
95
|
+
* store is not mounted, or the caller cancels the listing.
|
|
96
|
+
*/
|
|
97
|
+
export declare function listChildren(ctx: Context, parentSessionId: SessionId, signal?: AbortSignal): Promise<SubagentListEntry[]>;
|
|
98
|
+
/**
|
|
99
|
+
* Enumerate every session-backed subagent below one root in stable pre-order.
|
|
100
|
+
* Ordinary sessions and one-shot children remain traversal nodes, so a
|
|
101
|
+
* continuable child below either is still discovered. Classification uses the
|
|
102
|
+
* same projection-backed runtime as {@link listChildren}; no Agent is loaded or
|
|
103
|
+
* resumed.
|
|
104
|
+
* @see SubagentService.listDescendants for the public cancellation and failure contract.
|
|
105
|
+
* @param ctx - context carrying the session store, projection registry, and optional persistence/cache.
|
|
106
|
+
* @param rootSessionId - session whose complete descendant tree is listed.
|
|
107
|
+
* @param signal - caller-owned cancellation observed around every persistence read.
|
|
108
|
+
* @returns interpreted subagents with durable direct-parent and root-relative depth.
|
|
109
|
+
* @throws {@link SubagentError} under the same conditions as {@link listChildren}.
|
|
110
|
+
*/
|
|
111
|
+
export declare function listDescendants(ctx: Context, rootSessionId: SessionId, signal?: AbortSignal): Promise<SubagentDescendantListEntry[]>;
|
|
112
|
+
//# sourceMappingURL=list-children.d.ts.map
|