dsh-continual-evolve 0.11.0 → 0.12.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 +42 -115
- package/README.zh.md +33 -93
- package/client/client.js +253 -0
- package/cordis.patch.yml +2 -2
- package/lib/card-routes.d.ts +32 -0
- package/lib/card-routes.js +92 -0
- package/lib/index.d.ts +65 -217
- package/lib/index.js +74 -234
- package/lib/known-workspaces.d.ts +22 -0
- package/lib/known-workspaces.js +42 -0
- package/lib/memory-guide.d.ts +13 -14
- package/lib/memory-guide.js +34 -21
- package/lib/memory-section.d.ts +77 -0
- package/lib/memory-section.js +189 -0
- package/lib/memory-snapshot.d.ts +54 -0
- package/lib/memory-snapshot.js +125 -0
- package/package.json +8 -17
- package/lib/apply.d.ts +0 -22
- package/lib/apply.js +0 -157
- package/lib/approval.d.ts +0 -73
- package/lib/approval.js +0 -127
- package/lib/audit-log.d.ts +0 -19
- package/lib/audit-log.js +0 -52
- package/lib/auto.d.ts +0 -236
- package/lib/auto.js +0 -773
- package/lib/autocase.d.ts +0 -38
- package/lib/autocase.js +0 -76
- package/lib/benchmark-command.d.ts +0 -9
- package/lib/benchmark-command.js +0 -357
- package/lib/benchmark.d.ts +0 -151
- package/lib/benchmark.js +0 -250
- package/lib/command-util.d.ts +0 -70
- package/lib/command-util.js +0 -123
- package/lib/command.d.ts +0 -13
- package/lib/command.js +0 -134
- package/lib/consolidate.d.ts +0 -90
- package/lib/consolidate.js +0 -180
- package/lib/copy.d.ts +0 -37
- package/lib/copy.js +0 -58
- package/lib/declines.d.ts +0 -103
- package/lib/declines.js +0 -179
- package/lib/evaluate.d.ts +0 -74
- package/lib/evaluate.js +0 -271
- package/lib/evolve-event.d.ts +0 -40
- package/lib/evolve-event.js +0 -60
- package/lib/extraction-phase.d.ts +0 -132
- package/lib/extraction-phase.js +0 -236
- package/lib/failures.d.ts +0 -42
- package/lib/failures.js +0 -171
- package/lib/fate.d.ts +0 -130
- package/lib/fate.js +0 -350
- package/lib/goal-command.d.ts +0 -7
- package/lib/goal-command.js +0 -37
- package/lib/goal.d.ts +0 -72
- package/lib/goal.js +0 -72
- package/lib/inject.d.ts +0 -90
- package/lib/inject.js +0 -164
- package/lib/injection-caps.d.ts +0 -4
- package/lib/injection-caps.js +0 -4
- package/lib/injection-directory.d.ts +0 -29
- package/lib/injection-directory.js +0 -78
- package/lib/injection-rank.d.ts +0 -85
- package/lib/injection-rank.js +0 -161
- package/lib/listener.d.ts +0 -45
- package/lib/listener.js +0 -199
- package/lib/llm-text.d.ts +0 -104
- package/lib/llm-text.js +0 -140
- package/lib/logfile.d.ts +0 -71
- package/lib/logfile.js +0 -159
- package/lib/maintenance-commands.d.ts +0 -23
- package/lib/maintenance-commands.js +0 -136
- package/lib/memory-agent.d.ts +0 -93
- package/lib/memory-agent.js +0 -300
- package/lib/memory-apply.d.ts +0 -44
- package/lib/memory-apply.js +0 -202
- package/lib/memory-benchmark.d.ts +0 -76
- package/lib/memory-benchmark.js +0 -170
- package/lib/memory-index.d.ts +0 -114
- package/lib/memory-index.js +0 -197
- package/lib/memory-manifest.d.ts +0 -16
- package/lib/memory-manifest.js +0 -70
- package/lib/message-source.d.ts +0 -23
- package/lib/message-source.js +0 -12
- package/lib/mount-command.d.ts +0 -10
- package/lib/mount-command.js +0 -48
- package/lib/mount.d.ts +0 -42
- package/lib/mount.js +0 -212
- package/lib/notify.d.ts +0 -48
- package/lib/notify.js +0 -57
- package/lib/plan-command.d.ts +0 -12
- package/lib/plan-command.js +0 -38
- package/lib/plan.d.ts +0 -16
- package/lib/plan.js +0 -126
- package/lib/planner.d.ts +0 -61
- package/lib/planner.js +0 -144
- package/lib/pool.d.ts +0 -7
- package/lib/pool.js +0 -25
- package/lib/prefix-cache.d.ts +0 -79
- package/lib/prefix-cache.js +0 -168
- package/lib/project.d.ts +0 -28
- package/lib/project.js +0 -66
- package/lib/projection.d.ts +0 -22
- package/lib/projection.js +0 -112
- package/lib/promotion.d.ts +0 -94
- package/lib/promotion.js +0 -171
- package/lib/recall.d.ts +0 -85
- package/lib/recall.js +0 -142
- package/lib/record-language.d.ts +0 -85
- package/lib/record-language.js +0 -152
- package/lib/render.d.ts +0 -13
- package/lib/render.js +0 -80
- package/lib/review-scheduler.d.ts +0 -38
- package/lib/review-scheduler.js +0 -183
- package/lib/review.d.ts +0 -60
- package/lib/review.js +0 -145
- package/lib/rollback.d.ts +0 -9
- package/lib/rollback.js +0 -68
- package/lib/rubric.d.ts +0 -29
- package/lib/rubric.js +0 -119
- package/lib/runtime-commands.d.ts +0 -14
- package/lib/runtime-commands.js +0 -115
- package/lib/runtime.d.ts +0 -24
- package/lib/runtime.js +0 -87
- package/lib/score.d.ts +0 -64
- package/lib/score.js +0 -191
- package/lib/search.d.ts +0 -83
- package/lib/search.js +0 -136
- package/lib/service.d.ts +0 -63
- package/lib/service.js +0 -253
- package/lib/skill-render.d.ts +0 -23
- package/lib/skill-render.js +0 -69
- package/lib/skill.d.ts +0 -15
- package/lib/skill.js +0 -80
- package/lib/skillquality.d.ts +0 -85
- package/lib/skillquality.js +0 -320
- package/lib/source.d.ts +0 -30
- package/lib/source.js +0 -43
- package/lib/state.d.ts +0 -26
- package/lib/state.js +0 -151
- package/lib/store.d.ts +0 -61
- package/lib/store.js +0 -164
- package/lib/token-usage.d.ts +0 -68
- package/lib/token-usage.js +0 -211
- package/lib/tool.d.ts +0 -34
- package/lib/tool.js +0 -320
- package/lib/turn-snapshot.d.ts +0 -78
- package/lib/turn-snapshot.js +0 -252
- package/lib/types.d.ts +0 -218
- package/lib/types.js +0 -133
- package/lib/usage.d.ts +0 -36
- package/lib/usage.js +0 -98
- package/lib/validate.d.ts +0 -28
- package/lib/validate.js +0 -181
- package/lib/wrapup-candidates.d.ts +0 -127
- package/lib/wrapup-candidates.js +0 -161
- package/lib/wrapup-command.d.ts +0 -10
- package/lib/wrapup-command.js +0 -243
- package/lib/wrapup-proposals.d.ts +0 -101
- package/lib/wrapup-proposals.js +0 -281
- package/lib/wrapup.d.ts +0 -56
- package/lib/wrapup.js +0 -105
package/lib/review-scheduler.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Serial latest-boundary scheduler for automatic memory+review snapshots.
|
|
3
|
-
*
|
|
4
|
-
* One runner exists per session. A burst is coalesced by durable cursor rather
|
|
5
|
-
* than promise arrival: once multiple pending captures settle, the highest
|
|
6
|
-
* comparable boundary runs first. A cursor advances only after success/no-op;
|
|
7
|
-
* errors, aborts, and stale boundaries leave it unchanged.
|
|
8
|
-
*/
|
|
9
|
-
/** Bound unresolved acquisitions; actual auto capture is serialized per session. */
|
|
10
|
-
const MAX_PENDING_ACQUISITIONS = 16;
|
|
11
|
-
/**
|
|
12
|
-
* Create a scheduler with ZCode-compatible serial/coalescing semantics.
|
|
13
|
-
*
|
|
14
|
-
* @param execute - one serial extraction/review operation
|
|
15
|
-
* @param cursorOf - extracts the durable boundary from a snapshot
|
|
16
|
-
*/
|
|
17
|
-
export function createReviewScheduler(execute, cursorOf) {
|
|
18
|
-
let cursor;
|
|
19
|
-
let running;
|
|
20
|
-
let shuttingDown = false;
|
|
21
|
-
let wakePending;
|
|
22
|
-
const pending = [];
|
|
23
|
-
const shutdownController = new AbortController();
|
|
24
|
-
const signal = shutdownController.signal;
|
|
25
|
-
const trackPending = (acquisition) => {
|
|
26
|
-
const entry = {};
|
|
27
|
-
entry.promise = acquisition.then((result) => {
|
|
28
|
-
entry.result = result;
|
|
29
|
-
wakePending?.();
|
|
30
|
-
return result;
|
|
31
|
-
});
|
|
32
|
-
pending.push(entry);
|
|
33
|
-
while (pending.length > MAX_PENDING_ACQUISITIONS)
|
|
34
|
-
pending.shift();
|
|
35
|
-
};
|
|
36
|
-
const takeHighestPending = async () => {
|
|
37
|
-
while (!signal.aborted) {
|
|
38
|
-
for (let index = pending.length - 1; index >= 0; index -= 1) {
|
|
39
|
-
if (pending[index]?.result?.status === "error")
|
|
40
|
-
pending.splice(index, 1);
|
|
41
|
-
}
|
|
42
|
-
if (pending.length === 0)
|
|
43
|
-
return undefined;
|
|
44
|
-
const settled = pending.filter((entry) => entry.result !== undefined);
|
|
45
|
-
if (settled.length > 0) {
|
|
46
|
-
let bestIndex = -1;
|
|
47
|
-
let bestCursor;
|
|
48
|
-
for (let index = 0; index < settled.length; index += 1) {
|
|
49
|
-
const entry = settled[index];
|
|
50
|
-
if (!entry || entry.result?.status !== "acquired")
|
|
51
|
-
continue;
|
|
52
|
-
const candidate = cursorOf(entry.result.snapshot);
|
|
53
|
-
const order = bestCursor === undefined || candidate === undefined
|
|
54
|
-
? 1
|
|
55
|
-
: compareReviewCursors(candidate, bestCursor);
|
|
56
|
-
if (bestIndex < 0 || order === undefined || order > 0) {
|
|
57
|
-
bestIndex = pending.indexOf(entry);
|
|
58
|
-
bestCursor = candidate;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// bestIndex is always set here: the error purge above leaves only
|
|
62
|
-
// acquired snapshots in `settled` (SnapshotAcquisition has exactly
|
|
63
|
-
// two variants), so the first settled entry takes the slot.
|
|
64
|
-
const chosen = pending[bestIndex];
|
|
65
|
-
pending.splice(bestIndex, 1);
|
|
66
|
-
for (let index = pending.length - 1; index >= 0; index -= 1) {
|
|
67
|
-
if (pending[index]?.result !== undefined)
|
|
68
|
-
pending.splice(index, 1);
|
|
69
|
-
}
|
|
70
|
-
return chosen?.result;
|
|
71
|
-
}
|
|
72
|
-
await new Promise((resolve) => {
|
|
73
|
-
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
74
|
-
const onAbort = () => {
|
|
75
|
-
cleanup();
|
|
76
|
-
resolve();
|
|
77
|
-
};
|
|
78
|
-
wakePending = () => {
|
|
79
|
-
cleanup();
|
|
80
|
-
wakePending = undefined;
|
|
81
|
-
resolve();
|
|
82
|
-
};
|
|
83
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
return undefined;
|
|
87
|
-
};
|
|
88
|
-
const processSnapshot = async (snapshot) => {
|
|
89
|
-
if (shuttingDown || signal.aborted)
|
|
90
|
-
return;
|
|
91
|
-
const nextCursor = cursorOf(snapshot);
|
|
92
|
-
if (cursor !== undefined && nextCursor !== undefined) {
|
|
93
|
-
const order = compareReviewCursors(nextCursor, cursor);
|
|
94
|
-
if (order !== undefined && order <= 0)
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
let status;
|
|
98
|
-
try {
|
|
99
|
-
status = await execute({ snapshot, signal });
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (!shuttingDown && (status === "success" || status === "no-op") && nextCursor !== undefined) {
|
|
105
|
-
const order = cursor === undefined ? 1 : compareReviewCursors(nextCursor, cursor);
|
|
106
|
-
if (order === undefined || order > 0)
|
|
107
|
-
cursor = nextCursor;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
const run = async (first) => {
|
|
111
|
-
try {
|
|
112
|
-
let acquisition = await waitForSnapshotAcquisitionOrShutdown(first, signal);
|
|
113
|
-
while (acquisition.status !== "shutdown" && !shuttingDown) {
|
|
114
|
-
if (acquisition.status === "acquired")
|
|
115
|
-
await processSnapshot(acquisition.snapshot);
|
|
116
|
-
const next = await takeHighestPending();
|
|
117
|
-
if (!next)
|
|
118
|
-
break;
|
|
119
|
-
acquisition = next;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
finally {
|
|
123
|
-
if (shuttingDown) {
|
|
124
|
-
pending.length = 0;
|
|
125
|
-
wakePending?.();
|
|
126
|
-
wakePending = undefined;
|
|
127
|
-
}
|
|
128
|
-
running = undefined;
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
return {
|
|
132
|
-
async drain() {
|
|
133
|
-
while (running)
|
|
134
|
-
await running;
|
|
135
|
-
},
|
|
136
|
-
getCursor() {
|
|
137
|
-
return cursor;
|
|
138
|
-
},
|
|
139
|
-
hasPendingWork() {
|
|
140
|
-
return running !== undefined || pending.length > 0;
|
|
141
|
-
},
|
|
142
|
-
schedule(snapshot) {
|
|
143
|
-
if (shuttingDown)
|
|
144
|
-
return;
|
|
145
|
-
const acquisition = acquireSnapshot(snapshot);
|
|
146
|
-
if (running)
|
|
147
|
-
trackPending(acquisition);
|
|
148
|
-
else
|
|
149
|
-
running = run(acquisition);
|
|
150
|
-
},
|
|
151
|
-
shutdown() {
|
|
152
|
-
if (shuttingDown)
|
|
153
|
-
return;
|
|
154
|
-
shuttingDown = true;
|
|
155
|
-
pending.length = 0;
|
|
156
|
-
shutdownController.abort();
|
|
157
|
-
wakePending?.();
|
|
158
|
-
wakePending = undefined;
|
|
159
|
-
},
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
function acquireSnapshot(snapshot) {
|
|
163
|
-
return Promise.resolve(snapshot).then((value) => ({ status: "acquired", snapshot: value }), () => ({ status: "error" }));
|
|
164
|
-
}
|
|
165
|
-
function waitForSnapshotAcquisitionOrShutdown(acquisition, signal) {
|
|
166
|
-
if (signal.aborted)
|
|
167
|
-
return Promise.resolve({ status: "shutdown" });
|
|
168
|
-
return new Promise((resolve) => {
|
|
169
|
-
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
170
|
-
const onAbort = () => {
|
|
171
|
-
cleanup();
|
|
172
|
-
resolve({ status: "shutdown" });
|
|
173
|
-
};
|
|
174
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
175
|
-
void acquisition.then((result) => {
|
|
176
|
-
cleanup();
|
|
177
|
-
resolve(result);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
export { compareReviewCursors } from "./turn-snapshot.js";
|
|
182
|
-
import { compareReviewCursors } from "./turn-snapshot.js";
|
|
183
|
-
//# sourceMappingURL=review-scheduler.js.map
|
package/lib/review.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The automatic /evolve review gate: a cheap model call that decides whether
|
|
3
|
-
* the current trajectory justifies running the planner. Runs on a turn
|
|
4
|
-
* interval (and, in a later step, at compaction). The gate is deliberately
|
|
5
|
-
* small (bounded input, small output budget) — it only answers
|
|
6
|
-
* "should we refine?", never "what should we edit?".
|
|
7
|
-
*/
|
|
8
|
-
import type { Context } from "@deepseek-ai/cordis";
|
|
9
|
-
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
10
|
-
import type { HarnessState, RefinementResult } from "./types.js";
|
|
11
|
-
import { type PrefixCacheOptions } from "./prefix-cache.js";
|
|
12
|
-
import { type TokenUsageTarget } from "./token-usage.js";
|
|
13
|
-
import { type RecordLanguage } from "./record-language.js";
|
|
14
|
-
export interface AutoRefineReview {
|
|
15
|
-
shouldRefine: boolean;
|
|
16
|
-
rationale: string;
|
|
17
|
-
instructions?: string;
|
|
18
|
-
}
|
|
19
|
-
export type AutoRefineReason = "turn_snapshot" | "turn_interval" | "compact" | "goal_blocked";
|
|
20
|
-
export interface AutoRefineReviewContext {
|
|
21
|
-
reason: AutoRefineReason;
|
|
22
|
-
turnsSinceLastReview: number;
|
|
23
|
-
}
|
|
24
|
-
export interface ReviewOptions {
|
|
25
|
-
agent: Agent;
|
|
26
|
-
state: HarnessState;
|
|
27
|
-
history: readonly RefinementResult[];
|
|
28
|
-
context: AutoRefineReviewContext;
|
|
29
|
-
/** Serialized trajectory text; when absent the gate is skipped by the caller. */
|
|
30
|
-
trajectory?: string;
|
|
31
|
-
/** Incremental surface rows captured for this turn snapshot. */
|
|
32
|
-
trajectoryEvents?: readonly unknown[];
|
|
33
|
-
signal?: AbortSignal;
|
|
34
|
-
budgetTokens?: number;
|
|
35
|
-
/** Gap C1: optional provider/model override for the review gate (cheaper model). */
|
|
36
|
-
overrideProvider?: string;
|
|
37
|
-
overrideModel?: string;
|
|
38
|
-
/**
|
|
39
|
-
* Prefix-cache routing for the gate input. Route A prepends a
|
|
40
|
-
* session-derived message prefix and drops the flat `<conversation>`
|
|
41
|
-
* block (same source, structured form); Route B keeps it. Absent →
|
|
42
|
-
* auto-detect with the default budget.
|
|
43
|
-
*/
|
|
44
|
-
prefixCache?: PrefixCacheOptions;
|
|
45
|
-
/** Direct-call token ledger destination; the review phase is fixed by this module. */
|
|
46
|
-
tokenUsage?: TokenUsageTarget;
|
|
47
|
-
/**
|
|
48
|
-
* Authoring language for the rationale. Absent → resolved per call
|
|
49
|
-
* (explicit config upstream, else durable client preference, else
|
|
50
|
-
* trajectory detection, else `en`).
|
|
51
|
-
*/
|
|
52
|
-
language?: RecordLanguage;
|
|
53
|
-
}
|
|
54
|
-
export declare const AUTO_REVIEW_SYSTEM_PROMPT = "You are the automatic /evolve review gate.\n\nDecide whether this checkpoint should continue the non-memory /evolve path.\nA dedicated memory extraction agent has already processed the same snapshot\nwith a frozen memory manifest, so do NOT approve solely to create, update,\narchive, or delete a memory entry. Decline with a rationale that the memory\nphase owns that evidence. For the remaining kinds, approve ONLY when the\ntrajectory shows repeated evidence: the same failure, tactic, delegation\nrole, or behavioral policy recurs at least twice across turns. A single\none-off interaction defaults to decline no matter how useful it looks for\nfuture turns \u2014 one data point is never enough to generalize. When approving,\ncite the repeated spans in the instructions so the planner can ground its\nedits.\n\nThe current harness state below includes GLOBAL entries (scope=global) plus\nthis session's local entries (scope=local). When a topic is already covered\nby a global entry, do NOT approve a local duplicate of it \u2014 decline and say\nin the rationale that the topic is already covered globally.\n\nReject one-off noise, unsupported hypotheses, transient tool outputs, and\nrequests that carry no reusable content.\n\nStale local entries (superseded, long-unused, obsolete facts) are a valid\nrefine target: approve with instructions naming the entry ids, and tell the\nplanner to archive them (archive hides from injection, data stays restorable)\nrather than delete.\n\nSkill-related trajectories (the evidence concerns creating or improving a\nskill entry) are judged against the DSH skill quality standard (skill-audit\ndimensions: frontmatter routing, the 7 structural features, paragraph\nskeleton, no duplication of the official 11 skills or covered skills).\nApprove only when the trajectory shows a REAL trigger scenario and the\nresulting skill would meet the standard; otherwise decline and say in the\nrationale what must improve \u2014 drafting follows skill-creator, and the\nplanner receives the standard as its <skill_quality_standard> block.\n\nRepeated multi-step workflows (session start/end routines, recurring\nwrap-up or handoff procedures) are a valid refine target: approve with\ninstructions telling the planner to propose a guidance skill (kind=skill,\nskill_kind=guidance \u2014 a SKILL.md document, no python reference). Only\npropose when the same workflow recurs in the trajectory \u2014 never for\none-off flows. Auto-created skills are always offered to the user for a\ndecision before they land; the gate never writes a skill silently.\n\nReturn JSON only:\n{\n \"shouldRefine\": true|false,\n \"rationale\": \"short reason\",\n \"instructions\": \"optional concise instructions for /evolve if shouldRefine is true\"\n}";
|
|
55
|
-
/** Parse the gate's JSON reply. */
|
|
56
|
-
export declare function parseAutoRefineReview(text: string): AutoRefineReview;
|
|
57
|
-
/** Serialize surface events to bounded role-prefixed text. */
|
|
58
|
-
export declare function serializeSurface(events: readonly unknown[], maxChars: number): string;
|
|
59
|
-
export declare function reviewAutoRefine(ctx: Context, options: ReviewOptions): Promise<AutoRefineReview>;
|
|
60
|
-
//# sourceMappingURL=review.d.ts.map
|
package/lib/review.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { extractJsonObject } from "./plan.js";
|
|
2
|
-
import { formatHarnessStateForPrompt, historyForPrompt } from "./render.js";
|
|
3
|
-
import { sessionEventsOf } from "./inject.js";
|
|
4
|
-
import { buildPrefixMessages, detectPlannerRoute, resolvePrefixCache } from "./prefix-cache.js";
|
|
5
|
-
import { asLlmSessionId, streamText } from "./llm-text.js";
|
|
6
|
-
import { createTokenUsageObserver } from "./token-usage.js";
|
|
7
|
-
import { recordLanguageInstruction, resolveRecordLanguage } from "./record-language.js";
|
|
8
|
-
export const AUTO_REVIEW_SYSTEM_PROMPT = `You are the automatic /evolve review gate.
|
|
9
|
-
|
|
10
|
-
Decide whether this checkpoint should continue the non-memory /evolve path.
|
|
11
|
-
A dedicated memory extraction agent has already processed the same snapshot
|
|
12
|
-
with a frozen memory manifest, so do NOT approve solely to create, update,
|
|
13
|
-
archive, or delete a memory entry. Decline with a rationale that the memory
|
|
14
|
-
phase owns that evidence. For the remaining kinds, approve ONLY when the
|
|
15
|
-
trajectory shows repeated evidence: the same failure, tactic, delegation
|
|
16
|
-
role, or behavioral policy recurs at least twice across turns. A single
|
|
17
|
-
one-off interaction defaults to decline no matter how useful it looks for
|
|
18
|
-
future turns — one data point is never enough to generalize. When approving,
|
|
19
|
-
cite the repeated spans in the instructions so the planner can ground its
|
|
20
|
-
edits.
|
|
21
|
-
|
|
22
|
-
The current harness state below includes GLOBAL entries (scope=global) plus
|
|
23
|
-
this session's local entries (scope=local). When a topic is already covered
|
|
24
|
-
by a global entry, do NOT approve a local duplicate of it — decline and say
|
|
25
|
-
in the rationale that the topic is already covered globally.
|
|
26
|
-
|
|
27
|
-
Reject one-off noise, unsupported hypotheses, transient tool outputs, and
|
|
28
|
-
requests that carry no reusable content.
|
|
29
|
-
|
|
30
|
-
Stale local entries (superseded, long-unused, obsolete facts) are a valid
|
|
31
|
-
refine target: approve with instructions naming the entry ids, and tell the
|
|
32
|
-
planner to archive them (archive hides from injection, data stays restorable)
|
|
33
|
-
rather than delete.
|
|
34
|
-
|
|
35
|
-
Skill-related trajectories (the evidence concerns creating or improving a
|
|
36
|
-
skill entry) are judged against the DSH skill quality standard (skill-audit
|
|
37
|
-
dimensions: frontmatter routing, the 7 structural features, paragraph
|
|
38
|
-
skeleton, no duplication of the official 11 skills or covered skills).
|
|
39
|
-
Approve only when the trajectory shows a REAL trigger scenario and the
|
|
40
|
-
resulting skill would meet the standard; otherwise decline and say in the
|
|
41
|
-
rationale what must improve — drafting follows skill-creator, and the
|
|
42
|
-
planner receives the standard as its <skill_quality_standard> block.
|
|
43
|
-
|
|
44
|
-
Repeated multi-step workflows (session start/end routines, recurring
|
|
45
|
-
wrap-up or handoff procedures) are a valid refine target: approve with
|
|
46
|
-
instructions telling the planner to propose a guidance skill (kind=skill,
|
|
47
|
-
skill_kind=guidance — a SKILL.md document, no python reference). Only
|
|
48
|
-
propose when the same workflow recurs in the trajectory — never for
|
|
49
|
-
one-off flows. Auto-created skills are always offered to the user for a
|
|
50
|
-
decision before they land; the gate never writes a skill silently.
|
|
51
|
-
|
|
52
|
-
Return JSON only:
|
|
53
|
-
{
|
|
54
|
-
"shouldRefine": true|false,
|
|
55
|
-
"rationale": "short reason",
|
|
56
|
-
"instructions": "optional concise instructions for /evolve if shouldRefine is true"
|
|
57
|
-
}`;
|
|
58
|
-
/** Parse the gate's JSON reply. */
|
|
59
|
-
export function parseAutoRefineReview(text) {
|
|
60
|
-
const value = extractJsonObject(text);
|
|
61
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
62
|
-
throw new Error("auto-refine review JSON must be an object");
|
|
63
|
-
}
|
|
64
|
-
const record = value;
|
|
65
|
-
const review = {
|
|
66
|
-
shouldRefine: record["shouldRefine"] === true,
|
|
67
|
-
rationale: typeof record["rationale"] === "string" ? record["rationale"] : "No rationale provided.",
|
|
68
|
-
};
|
|
69
|
-
if (typeof record["instructions"] === "string" && record["instructions"].length > 0) {
|
|
70
|
-
review.instructions = record["instructions"];
|
|
71
|
-
}
|
|
72
|
-
return review;
|
|
73
|
-
}
|
|
74
|
-
/** Serialize surface events to bounded role-prefixed text. */
|
|
75
|
-
export function serializeSurface(events, maxChars) {
|
|
76
|
-
const lines = [];
|
|
77
|
-
for (const raw of events) {
|
|
78
|
-
if (typeof raw !== "object" || raw === null)
|
|
79
|
-
continue;
|
|
80
|
-
const event = raw;
|
|
81
|
-
const role = event.type === "user/message" ? "user" : event.type === "assistant/message" ? "assistant" : null;
|
|
82
|
-
if (role === null)
|
|
83
|
-
continue;
|
|
84
|
-
const content = event.data?.content;
|
|
85
|
-
if (!Array.isArray(content))
|
|
86
|
-
continue;
|
|
87
|
-
const text = content
|
|
88
|
-
.filter((block) => typeof block === "object" && block !== null && block.type === "text")
|
|
89
|
-
.map((block) => block.text ?? "")
|
|
90
|
-
.filter(Boolean)
|
|
91
|
-
.join(" ");
|
|
92
|
-
if (text.length > 0) {
|
|
93
|
-
lines.push(`${role}: ${text}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const joined = lines.join("\n");
|
|
97
|
-
return joined.length <= maxChars ? joined : joined.slice(-maxChars);
|
|
98
|
-
}
|
|
99
|
-
export async function reviewAutoRefine(ctx, options) {
|
|
100
|
-
const { agent, state, history } = options;
|
|
101
|
-
const provider = options.overrideProvider ?? agent.options.provider;
|
|
102
|
-
const model = options.overrideModel ?? agent.options.model;
|
|
103
|
-
if (!provider || !model) {
|
|
104
|
-
throw new Error("evolve: no provider/model route for the review gate");
|
|
105
|
-
}
|
|
106
|
-
if (!options.trajectory || options.trajectory.length === 0) {
|
|
107
|
-
throw new Error("evolve: review gate has no trajectory to judge");
|
|
108
|
-
}
|
|
109
|
-
// Route A carries the judged conversation as a session-derived message
|
|
110
|
-
// prefix and drops the flat block; an empty prefix falls back to B.
|
|
111
|
-
const events = options.trajectoryEvents ?? sessionEventsOf(agent);
|
|
112
|
-
const routing = resolvePrefixCache(options.prefixCache);
|
|
113
|
-
const route = detectPlannerRoute(events, routing.mode);
|
|
114
|
-
let prefixMessages = [];
|
|
115
|
-
if (route === "A") {
|
|
116
|
-
prefixMessages = buildPrefixMessages(events, {
|
|
117
|
-
...(provider ? { provider } : {}),
|
|
118
|
-
...(model ? { model } : {}),
|
|
119
|
-
maxChars: routing.maxChars,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
const conversationBlock = prefixMessages.length > 0 ? "" : `<conversation>\n${options.trajectory}\n</conversation>`;
|
|
123
|
-
const userPrompt = [
|
|
124
|
-
`<trigger>\n${options.context.reason}; ${options.context.turnsSinceLastReview} turns since the last review\n</trigger>`,
|
|
125
|
-
`<current_harness_state>\n${formatHarnessStateForPrompt(state)}\n</current_harness_state>`,
|
|
126
|
-
`<refinement_history>\n${historyForPrompt(history)}\n</refinement_history>`,
|
|
127
|
-
conversationBlock,
|
|
128
|
-
"Return shouldRefine=true only when the trajectory shows repeated evidence (>=2 occurrences) useful to this session's future turns. A single one-off interaction defaults to shouldRefine=false. Prefer local edits; do not ask for global refinement here.",
|
|
129
|
-
]
|
|
130
|
-
.filter(Boolean)
|
|
131
|
-
.join("\n\n");
|
|
132
|
-
const text = await streamText(ctx, {
|
|
133
|
-
provider,
|
|
134
|
-
model,
|
|
135
|
-
sessionId: asLlmSessionId(agent.id),
|
|
136
|
-
system: `${AUTO_REVIEW_SYSTEM_PROMPT}\n\n${recordLanguageInstruction(options.language ?? resolveRecordLanguage({ ctx, trajectoryText: options.trajectory }))}`,
|
|
137
|
-
prompt: userPrompt,
|
|
138
|
-
maxTokens: options.budgetTokens ?? 8000,
|
|
139
|
-
signal: options.signal,
|
|
140
|
-
...(prefixMessages.length > 0 ? { prefixMessages } : {}),
|
|
141
|
-
...(options.tokenUsage ? { onUsage: createTokenUsageObserver(options.tokenUsage, "review", provider, model) } : {}),
|
|
142
|
-
});
|
|
143
|
-
return parseAutoRefineReview(text);
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=review.js.map
|
package/lib/rollback.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic rollback: rebuild the inverse edit list from the applied
|
|
3
|
-
* result, in reverse order. Rollback is pure data transformation — no LLM
|
|
4
|
-
* is asked to "guess" the previous state.
|
|
5
|
-
*/
|
|
6
|
-
import type { RefinementProposal, RefinementResult } from "./types.js";
|
|
7
|
-
/** Build the inverse proposal for an applied refinement. */
|
|
8
|
-
export declare function rollbackProposal(target: RefinementResult): RefinementProposal;
|
|
9
|
-
//# sourceMappingURL=rollback.d.ts.map
|
package/lib/rollback.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/** Build the inverse proposal for an applied refinement. */
|
|
2
|
-
export function rollbackProposal(target) {
|
|
3
|
-
const edits = [];
|
|
4
|
-
for (const edit of [...target.appliedEdits].reverse()) {
|
|
5
|
-
if (!edit.applied)
|
|
6
|
-
continue;
|
|
7
|
-
const inverse = inverseEdit(edit, target.id);
|
|
8
|
-
if (inverse) {
|
|
9
|
-
edits.push(inverse);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
summary: `Rollback refinement ${target.id}`,
|
|
14
|
-
rationale: `Restores harness state to the snapshot recorded before refinement ${target.id}.`,
|
|
15
|
-
expectedOutcome: "Faulty refinement edits are reverted.",
|
|
16
|
-
edits,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
function inverseEdit(edit, refinementId) {
|
|
20
|
-
if (edit.before && edit.after) {
|
|
21
|
-
// Forward action was an update: restore the before snapshot.
|
|
22
|
-
// skill_kind rides along (review audit 2026-08-28 B4): without it a
|
|
23
|
-
// rollback could flip the skill form or fail validation on re-apply.
|
|
24
|
-
return {
|
|
25
|
-
action: "update",
|
|
26
|
-
kind: edit.kind,
|
|
27
|
-
id: edit.id,
|
|
28
|
-
title: edit.before.title,
|
|
29
|
-
content: edit.before.content,
|
|
30
|
-
path: edit.before.path,
|
|
31
|
-
reference: edit.before.reference,
|
|
32
|
-
arguments: edit.before.arguments,
|
|
33
|
-
...(edit.before.skill_kind !== undefined ? { skill_kind: edit.before.skill_kind } : {}),
|
|
34
|
-
metadata: edit.before.metadata,
|
|
35
|
-
reason: `Rollback ${refinementId}`,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
if (edit.before) {
|
|
39
|
-
// Forward action was a delete: re-create the entry from the snapshot.
|
|
40
|
-
// skill_kind is required for the re-created skill to pass the same
|
|
41
|
-
// contract validation as the original create (B4: a deleted guidance
|
|
42
|
-
// skill was previously unrecoverable via rollback).
|
|
43
|
-
return {
|
|
44
|
-
action: "create",
|
|
45
|
-
kind: edit.kind,
|
|
46
|
-
id: edit.id,
|
|
47
|
-
title: edit.before.title,
|
|
48
|
-
content: edit.before.content,
|
|
49
|
-
path: edit.before.path,
|
|
50
|
-
reference: edit.before.reference,
|
|
51
|
-
arguments: edit.before.arguments,
|
|
52
|
-
...(edit.before.skill_kind !== undefined ? { skill_kind: edit.before.skill_kind } : {}),
|
|
53
|
-
metadata: edit.before.metadata,
|
|
54
|
-
reason: `Rollback ${refinementId}`,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
if (edit.after) {
|
|
58
|
-
// Forward action was a create: delete the created entry.
|
|
59
|
-
return {
|
|
60
|
-
action: "delete",
|
|
61
|
-
kind: edit.kind,
|
|
62
|
-
id: edit.id,
|
|
63
|
-
reason: `Rollback ${refinementId}`,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
//# sourceMappingURL=rollback.js.map
|
package/lib/rubric.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/** The development fallback key — reachable only when the local key file is unusable. */
|
|
2
|
-
export declare const DEV_RUBRIC_KEY = "dsh-continual-evolve-dev-key";
|
|
3
|
-
/** Name of the per-installation key file under `<baseDir>/evolve/`. */
|
|
4
|
-
export declare const RUBRIC_KEY_FILE_NAME = "rubric.key";
|
|
5
|
-
/** Full path of the per-installation rubric key file. */
|
|
6
|
-
export declare function rubricKeyFilePath(baseDir: string): string;
|
|
7
|
-
export interface RubricCipher {
|
|
8
|
-
iv: string;
|
|
9
|
-
tag: string;
|
|
10
|
-
data: string;
|
|
11
|
-
}
|
|
12
|
-
export declare const RUBRIC_PREFIX = "v1:";
|
|
13
|
-
/** Derive a 32-byte AES-256 key from any passphrase. */
|
|
14
|
-
export declare function deriveKey(passphrase: string): Buffer;
|
|
15
|
-
/** Resolve the effective rubric key with the documented precedence. */
|
|
16
|
-
export declare function resolveRubricKey(baseDir: string, configKey: string | undefined, env?: NodeJS.ProcessEnv, warn?: (message: string) => void): Buffer;
|
|
17
|
-
/** Encrypt rubric plaintext into the `v1:` envelope (never written raw). */
|
|
18
|
-
export declare function encryptRubric(plaintext: string, key: Buffer): string;
|
|
19
|
-
/**
|
|
20
|
-
* Decrypt a `v1:` envelope. Legacy plaintext (no prefix) passes through
|
|
21
|
-
* unchanged so pre-ACL benchmark files keep working. Throws on tampered
|
|
22
|
-
* data, a wrong key, or a malformed envelope.
|
|
23
|
-
*/
|
|
24
|
-
export declare function decryptRubric(payload: string, key: Buffer): string;
|
|
25
|
-
/** True when a stored rubric is an encrypted envelope rather than legacy plaintext. */
|
|
26
|
-
export declare function isEncryptedRubric(payload: string): boolean;
|
|
27
|
-
/** Shape helper for tests and callers that inspect envelopes. */
|
|
28
|
-
export declare function parseEnvelope(payload: string): RubricCipher | undefined;
|
|
29
|
-
//# sourceMappingURL=rubric.d.ts.map
|
package/lib/rubric.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rubric ACL: rubric plaintext never touches the disk. The evaluation runner
|
|
3
|
-
* is the ONLY consumer that decrypts — the optimizer (planner) and the model
|
|
4
|
-
* (with its bash tools) can read benchmark files and see ciphertext only, so
|
|
5
|
-
* rubric isolation is enforced by code, not by prompt construction.
|
|
6
|
-
*
|
|
7
|
-
* Format: `v1:<base64(iv) | base64(tag) | base64(ciphertext)>` — each part is
|
|
8
|
-
* URL-safe base64 without padding, joined by `|`. A value without the `v1:`
|
|
9
|
-
* prefix is treated as legacy plaintext (pre-ACL files) and passes through.
|
|
10
|
-
*
|
|
11
|
-
* Key resolution (first match wins):
|
|
12
|
-
* 1. plugin config `rubricKey`
|
|
13
|
-
* 2. environment `DSH_EVOLVE_RUBRIC_KEY`
|
|
14
|
-
* 3. a per-installation local key file at `<baseDir>/evolve/rubric.key`
|
|
15
|
-
* (auto-generated with 0600 permissions on first use — every install
|
|
16
|
-
* gets its own random key, so no user setup is needed and no publicly
|
|
17
|
-
* known key protects anyone's rubrics)
|
|
18
|
-
* 4. a fixed development key as a last-resort fallback when the key file
|
|
19
|
-
* can neither be read nor written (warns; only reachable in
|
|
20
|
-
* pathological environments, since the plugin's stores live under the
|
|
21
|
-
* same directory)
|
|
22
|
-
* The key string is derived to 32 bytes with SHA-256, so any passphrase works.
|
|
23
|
-
*/
|
|
24
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
25
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
26
|
-
import { dirname, join } from "node:path";
|
|
27
|
-
/** The development fallback key — reachable only when the local key file is unusable. */
|
|
28
|
-
export const DEV_RUBRIC_KEY = "dsh-continual-evolve-dev-key";
|
|
29
|
-
/** Name of the per-installation key file under `<baseDir>/evolve/`. */
|
|
30
|
-
export const RUBRIC_KEY_FILE_NAME = "rubric.key";
|
|
31
|
-
/** Full path of the per-installation rubric key file. */
|
|
32
|
-
export function rubricKeyFilePath(baseDir) {
|
|
33
|
-
return join(baseDir, "evolve", RUBRIC_KEY_FILE_NAME);
|
|
34
|
-
}
|
|
35
|
-
export const RUBRIC_PREFIX = "v1:";
|
|
36
|
-
/** Derive a 32-byte AES-256 key from any passphrase. */
|
|
37
|
-
export function deriveKey(passphrase) {
|
|
38
|
-
return createHash("sha256").update(passphrase, "utf8").digest();
|
|
39
|
-
}
|
|
40
|
-
/** Resolve the effective rubric key with the documented precedence. */
|
|
41
|
-
export function resolveRubricKey(baseDir, configKey, env = process.env, warn) {
|
|
42
|
-
if (configKey && configKey.length > 0) {
|
|
43
|
-
return deriveKey(configKey);
|
|
44
|
-
}
|
|
45
|
-
const envKey = env["DSH_EVOLVE_RUBRIC_KEY"];
|
|
46
|
-
if (envKey && envKey.length > 0) {
|
|
47
|
-
return deriveKey(envKey);
|
|
48
|
-
}
|
|
49
|
-
return loadOrCreateLocalKey(baseDir, warn);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Load the per-installation key file, generating a fresh random key (0600)
|
|
53
|
-
* on first use. Falls back to the development key with a warning when the
|
|
54
|
-
* file can neither be read nor written.
|
|
55
|
-
*/
|
|
56
|
-
function loadOrCreateLocalKey(baseDir, warn) {
|
|
57
|
-
const path = rubricKeyFilePath(baseDir);
|
|
58
|
-
try {
|
|
59
|
-
if (existsSync(path)) {
|
|
60
|
-
const content = readFileSync(path, "utf8").trim();
|
|
61
|
-
if (content.length > 0) {
|
|
62
|
-
return deriveKey(content);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const key = randomBytes(32).toString("hex");
|
|
66
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
67
|
-
writeFileSync(path, `${key}\n`, { encoding: "utf8", mode: 0o600 });
|
|
68
|
-
return deriveKey(key);
|
|
69
|
-
}
|
|
70
|
-
catch (cause) {
|
|
71
|
-
warn?.(`rubric encryption: cannot read/write the local key file (${path}): ${cause instanceof Error ? cause.message : String(cause)} — using the development key`);
|
|
72
|
-
return deriveKey(DEV_RUBRIC_KEY);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/** Encrypt rubric plaintext into the `v1:` envelope (never written raw). */
|
|
76
|
-
export function encryptRubric(plaintext, key) {
|
|
77
|
-
const iv = randomBytes(12);
|
|
78
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
79
|
-
const data = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
80
|
-
const tag = cipher.getAuthTag();
|
|
81
|
-
return `${RUBRIC_PREFIX}${[iv, tag, data].map((part) => part.toString("base64url")).join("|")}`;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Decrypt a `v1:` envelope. Legacy plaintext (no prefix) passes through
|
|
85
|
-
* unchanged so pre-ACL benchmark files keep working. Throws on tampered
|
|
86
|
-
* data, a wrong key, or a malformed envelope.
|
|
87
|
-
*/
|
|
88
|
-
export function decryptRubric(payload, key) {
|
|
89
|
-
if (!payload.startsWith(RUBRIC_PREFIX)) {
|
|
90
|
-
return payload; // legacy plaintext file
|
|
91
|
-
}
|
|
92
|
-
const raw = payload.slice(RUBRIC_PREFIX.length);
|
|
93
|
-
const parts = raw.split("|");
|
|
94
|
-
if (parts.length !== 3) {
|
|
95
|
-
throw new Error("rubric: malformed encrypted envelope");
|
|
96
|
-
}
|
|
97
|
-
const [ivText, tagText, dataText] = parts;
|
|
98
|
-
const iv = Buffer.from(ivText, "base64url");
|
|
99
|
-
const tag = Buffer.from(tagText, "base64url");
|
|
100
|
-
const data = Buffer.from(dataText, "base64url");
|
|
101
|
-
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
102
|
-
decipher.setAuthTag(tag);
|
|
103
|
-
return Buffer.concat([decipher.update(data), decipher.final()]).toString("utf8");
|
|
104
|
-
}
|
|
105
|
-
/** True when a stored rubric is an encrypted envelope rather than legacy plaintext. */
|
|
106
|
-
export function isEncryptedRubric(payload) {
|
|
107
|
-
return payload.startsWith(RUBRIC_PREFIX);
|
|
108
|
-
}
|
|
109
|
-
/** Shape helper for tests and callers that inspect envelopes. */
|
|
110
|
-
export function parseEnvelope(payload) {
|
|
111
|
-
if (!isEncryptedRubric(payload))
|
|
112
|
-
return undefined;
|
|
113
|
-
const parts = payload.slice(RUBRIC_PREFIX.length).split("|");
|
|
114
|
-
if (parts.length !== 3)
|
|
115
|
-
return undefined;
|
|
116
|
-
const [iv, tag, data] = parts;
|
|
117
|
-
return { iv, tag, data };
|
|
118
|
-
}
|
|
119
|
-
//# sourceMappingURL=rubric.js.map
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { EvolutionEngine } from "./service.js";
|
|
2
|
-
import { type CommandRuntimeOptions, type CommandTextResult } from "./command-util.js";
|
|
3
|
-
/** `/evolve pause|resume` — the runtime switch is independent of registration. */
|
|
4
|
-
export declare function executePauseResumeCommand(engine: EvolutionEngine, sub: "pause" | "resume", runtime: CommandRuntimeOptions): CommandTextResult;
|
|
5
|
-
/** `/evolve status` — listener wiring plus per-store entry counts and retention. */
|
|
6
|
-
export declare function executeStatusCommand(engine: EvolutionEngine, sessionId: string, projectKey: string | undefined, runtime: CommandRuntimeOptions): CommandTextResult;
|
|
7
|
-
/**
|
|
8
|
-
* `/evolve usage` — injection counts per entry across the stores the human
|
|
9
|
-
* can see (global + this session + this project), plus the exact direct-call
|
|
10
|
-
* token report. Counts are per-session since the v2 usage shape — "in how
|
|
11
|
-
* many sessions did this entry surface".
|
|
12
|
-
*/
|
|
13
|
-
export declare function executeUsageCommand(engine: EvolutionEngine, sessionId: string, projectKey: string | undefined): CommandTextResult;
|
|
14
|
-
//# sourceMappingURL=runtime-commands.d.ts.map
|