@lmzhen/dsh-evolution-core 0.26.26 → 0.27.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/README.md +16 -1
- package/lib/composition/index.js +3 -0
- package/lib/composition-D8Y3-ROd.js +604 -0
- package/lib/ensure-MEYMj9jn.js +222 -0
- package/lib/errors-Br2-uUSK.js +57 -0
- package/lib/http-routes-BP-S3KV-.js +149 -0
- package/lib/http-routes.js +2 -0
- package/lib/index.js +66 -850
- package/lib/restrictor.js +37 -0
- package/lib/subagent/index.js +186 -0
- package/lib/types/citations.js +192 -0
- package/lib/types/{preset-composition.d.ts → composition/composer.d.ts} +1 -1
- package/lib/types/composition/composer.js +681 -0
- package/lib/types/composition/ensure.d.ts +10 -0
- package/lib/types/composition/ensure.js +95 -0
- package/lib/types/composition/index.d.ts +5 -0
- package/lib/types/composition/index.js +7 -0
- package/lib/types/composition/preset-ids.d.ts +17 -0
- package/lib/types/composition/preset-ids.js +21 -0
- package/lib/types/composition/restricted-preset.d.ts +36 -0
- package/lib/types/composition/restricted-preset.js +42 -0
- package/lib/types/constants.js +223 -0
- package/lib/types/cost.js +67 -0
- package/lib/types/curator.js +346 -0
- package/lib/types/diagnostics.d.ts +26 -0
- package/lib/types/diagnostics.js +23 -0
- package/lib/types/document-body.js +91 -0
- package/lib/types/drift-signals.js +319 -0
- package/lib/types/env.js +25 -0
- package/lib/types/errors.d.ts +4 -1
- package/lib/types/errors.js +59 -0
- package/lib/types/events.js +16 -0
- package/lib/types/evidence.js +65 -0
- package/lib/types/evolution-events.js +479 -0
- package/lib/types/fold-untrusted.js +44 -0
- package/lib/types/frontmatter.js +623 -0
- package/lib/types/fuzzy-match.js +135 -0
- package/lib/types/gates.js +51 -0
- package/lib/types/guards.js +27 -0
- package/lib/types/health-baseline.js +63 -0
- package/lib/types/http-routes.d.ts +67 -35
- package/lib/types/http-routes.js +135 -0
- package/lib/types/index.d.ts +7 -2
- package/lib/types/index.js +101 -0
- package/lib/types/instance-scope.js +69 -0
- package/lib/types/io.js +675 -0
- package/lib/types/learn-prompt.js +42 -0
- package/lib/types/limits.js +63 -0
- package/lib/types/live.js +107 -0
- package/lib/types/long-runs.js +96 -0
- package/lib/types/memory-store.d.ts +0 -16
- package/lib/types/memory-store.js +606 -0
- package/lib/types/mutations.js +95 -0
- package/lib/types/namespace-migration.js +156 -0
- package/lib/types/numeric.js +47 -0
- package/lib/types/opt-in.js +101 -0
- package/lib/types/package-identity.js +47 -0
- package/lib/types/params.js +328 -0
- package/lib/types/payload.js +36 -0
- package/lib/types/platform-line.generated.d.ts +10 -0
- package/lib/types/platform-line.generated.js +12 -0
- package/lib/types/platform-services.d.ts +2 -2
- package/lib/types/platform-services.js +52 -0
- package/lib/types/probe.js +122 -0
- package/lib/types/prompts.js +409 -0
- package/lib/types/quality.js +308 -0
- package/lib/types/reachability.js +122 -0
- package/lib/types/redact.js +257 -0
- package/lib/types/reference-rewrite.js +144 -0
- package/lib/types/reports.js +110 -0
- package/lib/types/restrictor.d.ts +11 -0
- package/lib/types/restrictor.js +48 -0
- package/lib/types/review-channel.js +59 -0
- package/lib/types/run-registry.js +345 -0
- package/lib/types/scope.js +7 -0
- package/lib/types/serial.js +17 -0
- package/lib/types/session-fold.d.ts +15 -0
- package/lib/types/session-fold.js +28 -0
- package/lib/types/session-projection.js +295 -0
- package/lib/types/signals.js +209 -0
- package/lib/types/skill-discovery.js +66 -0
- package/lib/types/skill-health.js +134 -0
- package/lib/types/skill-history.js +745 -0
- package/lib/types/skill-lint.js +112 -0
- package/lib/types/skill-reads.js +67 -0
- package/lib/types/skill-row-cells.js +123 -0
- package/lib/types/skill-store.js +3528 -0
- package/lib/types/state-store.js +60 -0
- package/lib/types/store-ledger.js +117 -0
- package/lib/types/subagent/channel.d.ts +4 -0
- package/lib/types/subagent/channel.js +131 -0
- package/lib/types/subagent/index.d.ts +4 -0
- package/lib/types/subagent/index.js +5 -0
- package/lib/types/subagent/readiness.d.ts +6 -0
- package/lib/types/subagent/readiness.js +35 -0
- package/lib/types/subagent/types.d.ts +58 -0
- package/lib/types/subagent/types.js +2 -0
- package/lib/types/threats.js +338 -0
- package/lib/types/tool-dispatch.d.ts +5 -0
- package/lib/types/tool-dispatch.js +535 -0
- package/lib/types/tree-write.js +40 -0
- package/lib/types/unit-members.js +121 -0
- package/lib/types/usage.js +474 -0
- package/lib/types/write-authority.js +23 -0
- package/lib/types/write-gates.js +344 -0
- package/lib/types/write-inventory.js +158 -0
- package/package.json +39 -11
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evolution home path helpers: the DSH root and `$DSH_HOME/evolution` for
|
|
3
|
+
* plugin-owned sidecar state (reports, activity store, feedback file,
|
|
4
|
+
* state-domain data).
|
|
5
|
+
*
|
|
6
|
+
* C-10: PATH HELPERS ONLY — despite the file name there is no store
|
|
7
|
+
* here. Durable evolution state lives in the state stack (evolution-state over
|
|
8
|
+
* evolution-state-json / -domain); skills and memories live in skill-store.ts
|
|
9
|
+
* / memory-store.ts. The file name is kept deliberately: renaming it would
|
|
10
|
+
* touch every family import for zero behavior change, and the audit records
|
|
11
|
+
* the mismatch as known naming debt.
|
|
12
|
+
*/
|
|
13
|
+
import { join, resolve } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
/**
|
|
16
|
+
* DSH home root: `$DSH_HOME` or `~/.dsh`. Single source of the empty-string
|
|
17
|
+
* fallback — an EMPTY or WHITESPACE-ONLY DSH_HOME resolves to the default
|
|
18
|
+
* home, never to a CWD-relative path (0.3.19 W1.3, 0.3.22 F-207);
|
|
19
|
+
* V8-06 (0.3.47) extends the guard to whitespace.
|
|
20
|
+
* C-11 correction (S2.2, PLAN 2026-09-16): upstream `resolveDshHome`
|
|
21
|
+
* (util/home-paths) uses `trim()` ONLY as the ADOPTION test and then uses the
|
|
22
|
+
* RAW env value — the earlier "same trimmed source" form returned the trimmed
|
|
23
|
+
* text, so `DSH_HOME=" /x "` produced `/x` where upstream produced the literal
|
|
24
|
+
* padded path. The value semantics now match upstream line for line:
|
|
25
|
+
* `const selected = configured ?? (fromEnv !== undefined &&
|
|
26
|
+
* fromEnv.trim().length > 0 ? fromEnv : defaultDshHome())`.
|
|
27
|
+
* OPT-27 (2026-09, plan D5 — accepted): the v10-era "no `~` expansion, no
|
|
28
|
+
* resolve" divergence from upstream `resolveDshHome` is RETIRED. It became
|
|
29
|
+
* load-bearing when the skill-catalog shadow made "same tree as the upstream
|
|
30
|
+
* `USER_DSH_RANK` provider" a hard contract: upstream watches the EXPANDED
|
|
31
|
+
* absolute `<home>/skills` while this value fed a literal `~/x` (a directory
|
|
32
|
+
* named `~` under the host CWD) or a CWD-relative path — split-brain skill
|
|
33
|
+
* trees, preset installs the platform never reads, doctor probes of a
|
|
34
|
+
* directory nothing serves.
|
|
35
|
+
* S2.2 (PLAN 2026-09-16), final correction: the result is ALWAYS
|
|
36
|
+
* `resolve(expandHomePath(selected))` — the earlier form returned an
|
|
37
|
+
* already-absolute value VERBATIM, so a trailing slash or `..` segment
|
|
38
|
+
* landed unnormalized while upstream normalizes every value. Relative
|
|
39
|
+
* `DSH_HOME` values change landing spot; a CLEAN absolute home stays
|
|
40
|
+
* byte-identical (resolve is a no-op on it).
|
|
41
|
+
*/
|
|
42
|
+
export function evolutionRoot(env = process.env) {
|
|
43
|
+
const fromEnv = env.DSH_HOME;
|
|
44
|
+
const selected = fromEnv !== undefined && fromEnv.trim().length > 0 ? fromEnv : join(homedir(), '.dsh');
|
|
45
|
+
// Mirror upstream expandHomePath (util/home-paths): `~` alone is the OS
|
|
46
|
+
// home; `~/` and `~\` prefix the OS home; anything else is taken literally
|
|
47
|
+
// — then resolved to an absolute path like upstream resolveDshHome.
|
|
48
|
+
const expanded = selected === '~'
|
|
49
|
+
? homedir()
|
|
50
|
+
: selected.startsWith('~/') || selected.startsWith('~\\')
|
|
51
|
+
? join(homedir(), selected.slice(2))
|
|
52
|
+
: selected;
|
|
53
|
+
return resolve(expanded);
|
|
54
|
+
}
|
|
55
|
+
/** Evolution home path helper: `$DSH_HOME/evolution` for plugin-owned sidecar
|
|
56
|
+
* state (reports, activity store, feedback file, state-domain data). */
|
|
57
|
+
export function evolutionHome(env = process.env) {
|
|
58
|
+
return join(evolutionRoot(env), 'evolution');
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=state-store.js.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* G3/3.2 (audit 06-performance.md 接缝 C): ONE declaration for every bounded store.
|
|
3
|
+
*
|
|
4
|
+
* Before this file the family had eight retention rules scattered across four packages and no place
|
|
5
|
+
* that could answer "how long does this record live under the current policy" (S1.md 4.3): six caps
|
|
6
|
+
* were named constants, three lived inline (snapshots 5, reports 20/20/10, archive 365d). Each entry
|
|
7
|
+
* below states its bound AND the code that declares it, so a gate can compare the two sets.
|
|
8
|
+
*
|
|
9
|
+
* `declare` is an ARRAY because one store may have several declaration sites (the report buckets are
|
|
10
|
+
* kept by two packages). The `inline` branch matches a CODE SNIPPET rather than a line number: line
|
|
11
|
+
* numbers rot on every edit above them, a snippet survives (and a snippet that stops matching is the
|
|
12
|
+
* detector the gate wants). No naming convention is assumed anywhere - that is the whole point of a
|
|
13
|
+
* ledger: the list IS the declaration.
|
|
14
|
+
*/
|
|
15
|
+
/** The one list. A new bounded store that is not registered here is what the G3 gate refuses. */
|
|
16
|
+
export const STORE_LEDGER = [
|
|
17
|
+
{
|
|
18
|
+
id: 'archive-entries',
|
|
19
|
+
owner: 'evolution-core',
|
|
20
|
+
unit: 'entries',
|
|
21
|
+
bound: '365 days, report-only by default (the removal policy is report, not delete)',
|
|
22
|
+
cutoff: 'archivedAt older than the retention window',
|
|
23
|
+
trigger: 'run-end',
|
|
24
|
+
artifact: 'count of .archive entries and their ages',
|
|
25
|
+
declare: [
|
|
26
|
+
// The window and the policy are two declarations on purpose: the bound is the window, and the
|
|
27
|
+
// policy decides whether crossing it deletes or only reports (audit S1-01: the message promised
|
|
28
|
+
// recoverability from a snapshot chain that is five deep).
|
|
29
|
+
{ kind: 'inline', file: 'packages/evolution-core/src/skill-store.ts', contains: 'ARCHIVE_RETENTION_DAYS = 365', value: '365 days' },
|
|
30
|
+
{ kind: 'named', module: 'evolution-core/src/limits.ts', name: 'DEFAULT_ARCHIVE_RETENTION_POLICY', value: 'report' },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'skill-snapshots',
|
|
35
|
+
owner: 'evolution-core',
|
|
36
|
+
unit: 'entries',
|
|
37
|
+
bound: '5 snapshots',
|
|
38
|
+
cutoff: 'oldest snapshot beyond the keep window',
|
|
39
|
+
trigger: 'run-end',
|
|
40
|
+
artifact: 'snapshot count and total bytes',
|
|
41
|
+
declare: [{ kind: 'inline', file: 'packages/evolution-core/src/skill-store.ts', contains: 'retainSnapshots(5)', value: '5' }],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'skill-versions',
|
|
45
|
+
owner: 'evolution-core',
|
|
46
|
+
unit: 'entries',
|
|
47
|
+
bound: '20 versions per skill',
|
|
48
|
+
cutoff: 'history index entries beyond versionKeep',
|
|
49
|
+
trigger: 'write',
|
|
50
|
+
artifact: 'history index length per skill',
|
|
51
|
+
declare: [{ kind: 'named', module: 'evolution-core/src/constants.ts', name: 'DEFAULT_SKILL_VERSION_KEEP', value: 20 }],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 'pending-resolved',
|
|
55
|
+
owner: 'evolution-state-storage',
|
|
56
|
+
unit: 'entries',
|
|
57
|
+
bound: '200 resolved pending records',
|
|
58
|
+
cutoff: 'resolved records beyond the cap',
|
|
59
|
+
trigger: 'write',
|
|
60
|
+
artifact: 'resolved record count',
|
|
61
|
+
declare: [{ kind: 'named', module: 'evolution-state-storage/src/constants.ts', name: 'PENDING_RESOLVED_CAP', value: 200 }],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'review-session',
|
|
65
|
+
owner: 'evolution-state-storage',
|
|
66
|
+
unit: 'entries',
|
|
67
|
+
bound: '500 review session rows',
|
|
68
|
+
cutoff: 'rows beyond the session cap',
|
|
69
|
+
trigger: 'write',
|
|
70
|
+
artifact: 'review state row count',
|
|
71
|
+
declare: [{ kind: 'named', module: 'evolution-state-storage/src/constants.ts', name: 'REVIEW_STATE_SESSION_CAP', value: 500 }],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'reports',
|
|
75
|
+
owner: 'evolution-commands',
|
|
76
|
+
unit: 'files',
|
|
77
|
+
bound: '20/20/10 files across the three report buckets',
|
|
78
|
+
cutoff: 'reports beyond each bucket keep',
|
|
79
|
+
trigger: 'run-end',
|
|
80
|
+
artifact: 'report file count per bucket',
|
|
81
|
+
declare: [
|
|
82
|
+
{ kind: 'inline', file: 'packages/evolution-commands/src/index.ts', contains: 'maintain-', value: '20' },
|
|
83
|
+
{ kind: 'inline', file: 'packages/evolution-curator/src/index.ts', contains: 'errorKeep', value: '10' },
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'event-archives',
|
|
88
|
+
owner: 'evolution-core',
|
|
89
|
+
unit: 'files',
|
|
90
|
+
bound: '10 archived event logs',
|
|
91
|
+
cutoff: 'archives beyond the retention count',
|
|
92
|
+
trigger: 'write',
|
|
93
|
+
artifact: 'event archive count',
|
|
94
|
+
declare: [{ kind: 'named', module: 'evolution-core/src/evolution-events.ts', name: 'EVENT_LOG_RETAIN_ARCHIVES', value: 10 }],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 'run-records',
|
|
98
|
+
owner: 'evolution-core',
|
|
99
|
+
unit: 'entries',
|
|
100
|
+
bound: '50 run records',
|
|
101
|
+
cutoff: 'runs beyond the record cap',
|
|
102
|
+
trigger: 'write',
|
|
103
|
+
artifact: 'runs.json record count',
|
|
104
|
+
declare: [{ kind: 'named', module: 'evolution-core/src/run-registry.ts', name: 'DEFAULT_RUN_RECORDS', value: 50 }],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'support-reads',
|
|
108
|
+
owner: 'evolution-core',
|
|
109
|
+
unit: 'entries',
|
|
110
|
+
bound: '200 support_reads keys',
|
|
111
|
+
cutoff: 'keys beyond the read-path cap',
|
|
112
|
+
trigger: 'write',
|
|
113
|
+
artifact: 'usage sidecar key count',
|
|
114
|
+
declare: [{ kind: 'named', module: 'evolution-core/src/usage.ts', name: 'MAX_SUPPORT_READ_PATHS', value: 200 }],
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
//# sourceMappingURL=store-ledger.js.map
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { ensureRestrictedPreset } from "../composition/ensure.js";
|
|
2
|
+
import { probeChannelState } from "./readiness.js";
|
|
3
|
+
function serviceOf(ctx, name) {
|
|
4
|
+
return ctx.get(name);
|
|
5
|
+
}
|
|
6
|
+
function messageOf(error) {
|
|
7
|
+
return error instanceof Error ? error.message : String(error);
|
|
8
|
+
}
|
|
9
|
+
export function createSubagentChannel(ctx) {
|
|
10
|
+
let lastKind = 'reviewer';
|
|
11
|
+
const channel = {
|
|
12
|
+
get state() {
|
|
13
|
+
return probeChannelState(ctx, lastKind);
|
|
14
|
+
},
|
|
15
|
+
prepare(spec) {
|
|
16
|
+
lastKind = spec.kind;
|
|
17
|
+
const state = probeChannelState(ctx, spec.kind);
|
|
18
|
+
if (state.kind === 'unavailable')
|
|
19
|
+
return Promise.resolve(state);
|
|
20
|
+
if (spec.allow.length === 0)
|
|
21
|
+
return Promise.resolve({ kind: 'unavailable', code: 'E-324', reason: 'allow set is empty' });
|
|
22
|
+
return Promise.resolve(state);
|
|
23
|
+
},
|
|
24
|
+
async run(spec) {
|
|
25
|
+
lastKind = spec.kind;
|
|
26
|
+
const probe = probeChannelState(ctx, spec.kind);
|
|
27
|
+
if (probe.kind === 'unavailable')
|
|
28
|
+
return probe;
|
|
29
|
+
const subagents = serviceOf(ctx, 'subagents');
|
|
30
|
+
const presets = serviceOf(ctx, 'agentPresets');
|
|
31
|
+
if (subagents === undefined || presets === undefined) {
|
|
32
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'subagents/agentPresets service unavailable' };
|
|
33
|
+
}
|
|
34
|
+
const parentPresetId = presets.composedPreset(spec.parent.ctx);
|
|
35
|
+
if (parentPresetId === undefined) {
|
|
36
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'parent preset could not be resolved' };
|
|
37
|
+
}
|
|
38
|
+
const ensured = await ensureRestrictedPreset(ctx, { kind: spec.kind, parentPresetId, allow: spec.allow });
|
|
39
|
+
if (ensured.kind === 'failed') {
|
|
40
|
+
return { kind: 'unavailable', code: 'E-324', reason: ensured.reason };
|
|
41
|
+
}
|
|
42
|
+
const controller = new AbortController();
|
|
43
|
+
const timer = setTimeout(() => { controller.abort(new Error('subagent timeout')); }, spec.timeoutMs);
|
|
44
|
+
const onAbort = () => { controller.abort(spec.signal?.reason); };
|
|
45
|
+
spec.signal?.addEventListener('abort', onAbort, { once: true });
|
|
46
|
+
let activation;
|
|
47
|
+
try {
|
|
48
|
+
activation = await subagents.startActivation({
|
|
49
|
+
provider: 'spawn',
|
|
50
|
+
label: spec.label,
|
|
51
|
+
delivery: 'caller',
|
|
52
|
+
request: {
|
|
53
|
+
parent: spec.parent,
|
|
54
|
+
prompt: [{ type: 'text', text: spec.promptText }],
|
|
55
|
+
agentPreset: ensured.presetId,
|
|
56
|
+
...(spec.outputSchema !== undefined ? { outputSchema: spec.outputSchema } : {}),
|
|
57
|
+
...(spec.maxDepth !== undefined ? { maxDepth: spec.maxDepth } : {}),
|
|
58
|
+
...(spec.agentOptions !== undefined ? { agentOptions: spec.agentOptions } : {}),
|
|
59
|
+
},
|
|
60
|
+
signal: controller.signal,
|
|
61
|
+
});
|
|
62
|
+
let result;
|
|
63
|
+
try {
|
|
64
|
+
result = await activation.result;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (controller.signal.aborted)
|
|
68
|
+
return { kind: 'aborted' };
|
|
69
|
+
return { kind: 'unavailable', code: 'E-323', reason: messageOf(error) };
|
|
70
|
+
}
|
|
71
|
+
let evidence;
|
|
72
|
+
if (spec.afterResult !== undefined) {
|
|
73
|
+
try {
|
|
74
|
+
const agents = serviceOf(ctx, 'agents');
|
|
75
|
+
const child = agents?.get(activation.childId);
|
|
76
|
+
if (child !== undefined)
|
|
77
|
+
evidence = spec.afterResult(child);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
evidence = undefined;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const stopReason = result.stopReason;
|
|
84
|
+
// W5 §3: OK requires BOTH a completed stop and a structured payload; a completed run that
|
|
85
|
+
// produced nothing must stay a no-structured outcome so the business layer cannot treat an
|
|
86
|
+
// empty result as a plan.
|
|
87
|
+
if (stopReason === 'completed' && result.structured !== undefined && result.structured !== null) {
|
|
88
|
+
return {
|
|
89
|
+
kind: 'ok',
|
|
90
|
+
structured: result.structured,
|
|
91
|
+
childId: activation.childId,
|
|
92
|
+
stopReason: 'completed',
|
|
93
|
+
...(evidence !== undefined ? { evidence } : {}),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (stopReason === 'aborted')
|
|
97
|
+
return { kind: 'aborted' };
|
|
98
|
+
return {
|
|
99
|
+
kind: 'no-structured',
|
|
100
|
+
childId: activation.childId,
|
|
101
|
+
stopReason,
|
|
102
|
+
...(result.diagnostic !== undefined ? { diagnostic: result.diagnostic } : {}),
|
|
103
|
+
...(evidence !== undefined ? { evidence } : {}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (controller.signal.aborted)
|
|
108
|
+
return { kind: 'aborted' };
|
|
109
|
+
return { kind: 'unavailable', code: 'E-323', reason: messageOf(error) };
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
clearTimeout(timer);
|
|
113
|
+
spec.signal?.removeEventListener('abort', onAbort);
|
|
114
|
+
if (activation !== undefined) {
|
|
115
|
+
try {
|
|
116
|
+
await activation.dispose();
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
// W5 §6: teardown failures are observable but must NOT replace the captured outcome.
|
|
120
|
+
try {
|
|
121
|
+
ctx.logger.warn('subagent channel: activation dispose failed: ' + messageOf(error));
|
|
122
|
+
}
|
|
123
|
+
catch { /* logging must not mask teardown */ }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
return channel;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { ChannelKind, ChannelState } from './types.ts';
|
|
3
|
+
/** Pure derivation (no side effects): the doctor reads this, the channel re-probes on every run. */
|
|
4
|
+
export declare function probeChannelState(ctx: Context, kind: ChannelKind): ChannelState;
|
|
5
|
+
export declare function subagentChannelState(ctx: Context, kind: ChannelKind): ChannelState;
|
|
6
|
+
//# sourceMappingURL=readiness.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { restrictedPresetState } from "../composition/ensure.js";
|
|
2
|
+
import { restrictedPresetId } from "../composition/preset-ids.js";
|
|
3
|
+
function serviceOf(ctx, name) {
|
|
4
|
+
return ctx.get(name);
|
|
5
|
+
}
|
|
6
|
+
function kindOf(kind) {
|
|
7
|
+
return kind === 'reviewer' ? 'reviewer' : 'maintainer';
|
|
8
|
+
}
|
|
9
|
+
/** Pure derivation (no side effects): the doctor reads this, the channel re-probes on every run. */
|
|
10
|
+
export function probeChannelState(ctx, kind) {
|
|
11
|
+
const subagents = serviceOf(ctx, 'subagents');
|
|
12
|
+
if (subagents === undefined || typeof subagents.getProvider !== 'function') {
|
|
13
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'subagents service unavailable' };
|
|
14
|
+
}
|
|
15
|
+
const provider = subagents.getProvider('spawn');
|
|
16
|
+
if (provider === undefined)
|
|
17
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'spawn provider unavailable' };
|
|
18
|
+
if (provider.capabilities?.agentPreset !== true) {
|
|
19
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'spawn provider lacks the agentPreset capability' };
|
|
20
|
+
}
|
|
21
|
+
if (provider.inheritsParentContext === true) {
|
|
22
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'spawn provider inherits the parent context (independent preset required)' };
|
|
23
|
+
}
|
|
24
|
+
const agentPresets = serviceOf(ctx, 'agentPresets');
|
|
25
|
+
if (agentPresets === undefined || typeof agentPresets.readDocument !== 'function' || typeof agentPresets.register !== 'function') {
|
|
26
|
+
return { kind: 'unavailable', code: 'E-323', reason: 'agentPresets service unavailable or incomplete' };
|
|
27
|
+
}
|
|
28
|
+
const id = restrictedPresetId(kindOf(kind));
|
|
29
|
+
const state = restrictedPresetState(ctx, kindOf(kind));
|
|
30
|
+
return { kind: 'available', provider: 'spawn', preset: { id, registered: state?.kind === 'ready' } };
|
|
31
|
+
}
|
|
32
|
+
export function subagentChannelState(ctx, kind) {
|
|
33
|
+
return probeChannelState(ctx, kind);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=readiness.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Agent, AgentOptions } from '@deepseek-ai/dsh-agent';
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
3
|
+
import type { SubagentStopReason } from '@deepseek-ai/dsh-subagent';
|
|
4
|
+
import type { ObjectJsonSchema } from '@deepseek-ai/dsh-tools';
|
|
5
|
+
export type ChannelCode = 'E-323' | 'E-324';
|
|
6
|
+
export type ChannelKind = 'reviewer' | 'maintainer';
|
|
7
|
+
export interface PresetStatus {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly registered: boolean;
|
|
10
|
+
readonly broken?: string;
|
|
11
|
+
}
|
|
12
|
+
export type ChannelState = {
|
|
13
|
+
readonly kind: 'available';
|
|
14
|
+
readonly provider: 'spawn';
|
|
15
|
+
readonly preset: PresetStatus;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: 'unavailable';
|
|
18
|
+
readonly code: ChannelCode;
|
|
19
|
+
readonly reason: string;
|
|
20
|
+
};
|
|
21
|
+
export type ChannelOutcome<T = undefined> = {
|
|
22
|
+
readonly kind: 'ok';
|
|
23
|
+
readonly structured: unknown;
|
|
24
|
+
readonly childId: SessionId;
|
|
25
|
+
readonly stopReason: 'completed';
|
|
26
|
+
readonly evidence?: T;
|
|
27
|
+
} | {
|
|
28
|
+
readonly kind: 'no-structured';
|
|
29
|
+
readonly childId?: SessionId;
|
|
30
|
+
readonly stopReason: SubagentStopReason;
|
|
31
|
+
readonly diagnostic?: string;
|
|
32
|
+
readonly evidence?: T;
|
|
33
|
+
} | {
|
|
34
|
+
readonly kind: 'aborted';
|
|
35
|
+
} | {
|
|
36
|
+
readonly kind: 'unavailable';
|
|
37
|
+
readonly code: ChannelCode;
|
|
38
|
+
readonly reason: string;
|
|
39
|
+
};
|
|
40
|
+
export interface ChannelSpec<T = undefined> {
|
|
41
|
+
readonly parent: Agent;
|
|
42
|
+
readonly label: string;
|
|
43
|
+
readonly promptText: string;
|
|
44
|
+
readonly kind: ChannelKind;
|
|
45
|
+
readonly allow: readonly string[];
|
|
46
|
+
readonly outputSchema?: ObjectJsonSchema;
|
|
47
|
+
readonly agentOptions?: AgentOptions;
|
|
48
|
+
readonly maxDepth?: number;
|
|
49
|
+
readonly timeoutMs: number;
|
|
50
|
+
readonly signal?: AbortSignal;
|
|
51
|
+
readonly afterResult?: (child: Agent) => T;
|
|
52
|
+
}
|
|
53
|
+
export interface SubagentChannel {
|
|
54
|
+
readonly state: ChannelState;
|
|
55
|
+
prepare(spec: Pick<ChannelSpec, 'kind' | 'allow'>): Promise<ChannelState>;
|
|
56
|
+
run<T = undefined>(spec: ChannelSpec<T>): Promise<ChannelOutcome<T>>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|