dsh-continual-evolve 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -7
- package/README.zh.md +44 -7
- package/lib/apply.js +1 -1
- package/lib/approval.d.ts +6 -0
- package/lib/approval.js +9 -1
- package/lib/auto.d.ts +38 -4
- package/lib/auto.js +58 -5
- package/lib/benchmark-command.d.ts +9 -0
- package/lib/benchmark-command.js +331 -0
- package/lib/benchmark.d.ts +70 -0
- package/lib/benchmark.js +107 -1
- package/lib/command.js +25 -442
- package/lib/evaluate.d.ts +7 -0
- package/lib/evaluate.js +22 -7
- package/lib/evolve-event.d.ts +38 -0
- package/lib/evolve-event.js +49 -0
- package/lib/failures.d.ts +39 -0
- package/lib/failures.js +170 -0
- package/lib/fate.d.ts +3 -1
- package/lib/fate.js +8 -4
- package/lib/goal-command.d.ts +7 -0
- package/lib/goal-command.js +37 -0
- package/lib/index.d.ts +29 -25
- package/lib/index.js +14 -0
- package/lib/inject.d.ts +8 -0
- package/lib/inject.js +51 -4
- package/lib/llm-text.d.ts +30 -0
- package/lib/llm-text.js +49 -0
- package/lib/mount-command.d.ts +10 -0
- package/lib/mount-command.js +48 -0
- package/lib/plan.js +5 -0
- package/lib/planner.d.ts +1 -1
- package/lib/planner.js +13 -39
- package/lib/render.d.ts +1 -3
- package/lib/render.js +0 -4
- package/lib/review.d.ts +4 -1
- package/lib/review.js +10 -38
- package/lib/rollback.d.ts +1 -3
- package/lib/rollback.js +0 -8
- package/lib/score.d.ts +15 -0
- package/lib/score.js +74 -5
- package/lib/service.d.ts +2 -2
- package/lib/service.js +5 -2
- package/lib/skill-render.d.ts +15 -0
- package/lib/skill-render.js +30 -0
- package/lib/skill.d.ts +2 -5
- package/lib/skill.js +2 -29
- package/lib/skillquality.d.ts +1 -2
- package/lib/skillquality.js +2 -2
- package/lib/store.d.ts +1 -3
- package/lib/store.js +0 -7
- package/lib/tool.js +22 -1
- package/lib/types.d.ts +8 -0
- package/lib/usage.d.ts +32 -0
- package/lib/usage.js +84 -0
- package/lib/validate.d.ts +12 -2
- package/lib/validate.js +26 -1
- package/lib/wrapup-command.d.ts +8 -0
- package/lib/wrapup-command.js +211 -0
- package/lib/wrapup.d.ts +14 -9
- package/lib/wrapup.js +24 -36
- package/package.json +8 -8
package/lib/wrapup.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { BlockAssembler, createUserMessage, ReasoningEffortId } from "@deepseek-ai/dsh-llm";
|
|
2
1
|
import { ARCHIVED_AT_KEY, PROMOTED_AT_KEY, PROMOTED_TO_KEY, SOURCE_SEQS_KEY, SOURCE_SESSION_KEY, SOURCED_FROM_KEY, isArchived } from "./types.js";
|
|
3
2
|
import { extractJsonObject } from "./plan.js";
|
|
4
3
|
import { compactText } from "./render.js";
|
|
4
|
+
import { streamText } from "./llm-text.js";
|
|
5
|
+
import { getUsageCount, loadUsage } from "./usage.js";
|
|
6
|
+
import { recencyScore } from "./inject.js";
|
|
5
7
|
export function candidateKey(kind, id) {
|
|
6
8
|
return `${kind}:${id}`;
|
|
7
9
|
}
|
|
@@ -71,7 +73,11 @@ export function globalHintsFor(globalState, kind, entry) {
|
|
|
71
73
|
* `coveredGlobally` flag so the assessor never wastes a promote on a topic
|
|
72
74
|
* the global store already owns.
|
|
73
75
|
*/
|
|
74
|
-
|
|
76
|
+
/** Staleness threshold: entries with recency below this AND zero usage are stale. */
|
|
77
|
+
const STALE_RECENCY_THRESHOLD = 0.1;
|
|
78
|
+
export function listLocalCandidates(state, globalState, baseDir) {
|
|
79
|
+
const usage = baseDir ? loadUsage(baseDir) : undefined;
|
|
80
|
+
const now = Date.now();
|
|
75
81
|
const candidates = [];
|
|
76
82
|
for (const kind of Object.keys(state.entries)) {
|
|
77
83
|
for (const entry of Object.values(state.entries[kind])) {
|
|
@@ -81,6 +87,8 @@ export function listLocalCandidates(state, globalState) {
|
|
|
81
87
|
continue;
|
|
82
88
|
if (typeof entry.metadata[PROMOTED_TO_KEY] === "string")
|
|
83
89
|
continue;
|
|
90
|
+
const injectionCount = usage ? getUsageCount(usage, kind, entry.id) : 0;
|
|
91
|
+
const stale = injectionCount === 0 && recencyScore(entry, now) < STALE_RECENCY_THRESHOLD;
|
|
84
92
|
candidates.push({
|
|
85
93
|
kind,
|
|
86
94
|
id: entry.id,
|
|
@@ -91,6 +99,8 @@ export function listLocalCandidates(state, globalState) {
|
|
|
91
99
|
metadata: entry.metadata,
|
|
92
100
|
coveredGlobally: globalCoverageDetected(globalState, kind, entry),
|
|
93
101
|
globalHints: globalHintsFor(globalState, kind, entry),
|
|
102
|
+
injectionCount,
|
|
103
|
+
stale,
|
|
94
104
|
});
|
|
95
105
|
}
|
|
96
106
|
}
|
|
@@ -342,12 +352,17 @@ listed entry exactly once:
|
|
|
342
352
|
procedure or skill. Future sessions would benefit from seeing it.
|
|
343
353
|
- "archive" — the content is session-specific task progress, one-off noise,
|
|
344
354
|
superseded or obsolete, or already covered by the global store (note
|
|
345
|
-
"covered globally" in the reason)
|
|
355
|
+
"covered globally" in the reason), or stale (old + never injected — note
|
|
356
|
+
"stale (injectionCount=0, recency low)" in the reason).
|
|
346
357
|
- "keep" — still actively useful to this session, or genuinely uncertain.
|
|
347
358
|
|
|
348
359
|
Rules:
|
|
349
360
|
- When an entry is marked "covered globally" in the listing, prefer "archive"
|
|
350
361
|
or "keep" over "promote" — promoting a duplicate gains nothing.
|
|
362
|
+
- When an entry is marked "stale" (injectionCount=0 and low recency), prefer
|
|
363
|
+
"archive" — the entry has never been used and is old, so it is unlikely to
|
|
364
|
+
be needed again. Only "keep" if the content is clearly valuable despite low
|
|
365
|
+
usage (e.g. a safety policy that rarely triggers but is critical).
|
|
351
366
|
- Do not promote local task state, work-in-progress notes, or content tied to
|
|
352
367
|
one session's ephemeral details.
|
|
353
368
|
- Skills: only "promote" a skill entry that is a genuinely reusable procedure
|
|
@@ -387,10 +402,11 @@ export async function assessLocalEntries(ctx, agent, candidates, options = {}) {
|
|
|
387
402
|
.map((candidate) => {
|
|
388
403
|
const key = candidateKey(candidate.kind, candidate.id);
|
|
389
404
|
const covered = candidate.coveredGlobally ? " (covered globally)" : "";
|
|
405
|
+
const stale = candidate.stale ? ` (stale: injectionCount=${candidate.injectionCount}, recency low)` : "";
|
|
390
406
|
const hints = candidate.globalHints.length > 0
|
|
391
407
|
? ` | global≈${candidate.globalHints.map((hint) => hint.id + ":" + hint.title).join(", ")}`
|
|
392
408
|
: "";
|
|
393
|
-
return `- ${key} [${candidate.path}, v${candidate.version}] "${candidate.title}"${covered}${hints}: ${compactText(candidate.content, 220)}`;
|
|
409
|
+
return `- ${key} [${candidate.path}, v${candidate.version}] "${candidate.title}"${covered}${stale}${hints}: ${compactText(candidate.content, 220)}`;
|
|
394
410
|
})
|
|
395
411
|
.join("\n");
|
|
396
412
|
const userPrompt = [
|
|
@@ -398,42 +414,14 @@ export async function assessLocalEntries(ctx, agent, candidates, options = {}) {
|
|
|
398
414
|
`<local_entries>\n${candidateText}\n</local_entries>`,
|
|
399
415
|
"Return only JSON. Every item must reference one of the keys above.",
|
|
400
416
|
].join("\n\n");
|
|
401
|
-
const
|
|
402
|
-
for await (const chunk of ctx.llm.stream({
|
|
417
|
+
const text = await streamText(ctx, {
|
|
403
418
|
provider: agent.options.provider,
|
|
404
419
|
model: agent.options.model,
|
|
405
420
|
system: WRAPUP_ASSESS_SYSTEM_PROMPT,
|
|
406
|
-
|
|
407
|
-
createUserMessage({
|
|
408
|
-
content: [{ type: "text", text: userPrompt }],
|
|
409
|
-
source: { kind: "plugin", plugin: "dsh-continual-evolve" },
|
|
410
|
-
}),
|
|
411
|
-
],
|
|
412
|
-
// Force non-reasoning output so the budget lands in the JSON verdicts.
|
|
413
|
-
reasoningEffort: ReasoningEffortId("off"),
|
|
421
|
+
prompt: userPrompt,
|
|
414
422
|
maxTokens: options.maxOutputTokens ?? 4096,
|
|
415
|
-
|
|
416
|
-
})
|
|
417
|
-
assembler.push(chunk);
|
|
418
|
-
}
|
|
419
|
-
const finish = assembler.finish;
|
|
420
|
-
if (finish.kind === "error") {
|
|
421
|
-
throw new Error(`evolve: wrap-up assessor call failed: ${finish.failure?.message ?? "unknown"}`);
|
|
422
|
-
}
|
|
423
|
-
if (finish.kind === "aborted") {
|
|
424
|
-
throw new Error("evolve: wrap-up assessor call aborted");
|
|
425
|
-
}
|
|
426
|
-
if (finish.kind === "max-tokens") {
|
|
427
|
-
throw new Error("evolve: wrap-up assessor output budget exhausted (max-tokens)");
|
|
428
|
-
}
|
|
429
|
-
const text = assembler
|
|
430
|
-
.blocks()
|
|
431
|
-
.filter((block) => block.type === "text")
|
|
432
|
-
.map((block) => block.text)
|
|
433
|
-
.join("\n");
|
|
434
|
-
if (text.length === 0) {
|
|
435
|
-
throw new Error("evolve: wrap-up assessor produced no text");
|
|
436
|
-
}
|
|
423
|
+
signal: options.signal,
|
|
424
|
+
});
|
|
437
425
|
return parseWrapupAssessment(text, candidates);
|
|
438
426
|
}
|
|
439
427
|
//# sourceMappingURL=wrapup.js.map
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-continual-evolve",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Continual self-evolution plugin for DeepSeek Harness: versioned, auditable, rollback-safe harness state (prompt notes, memories, skills, subagent specs) refined from session trajectories.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/ZK-Andy/dsh-continual-evolve.git"
|
|
8
|
+
"url": "git+https://github.com/ZK-Andy/dsh-continual-evolve.git"
|
|
9
9
|
},
|
|
10
10
|
"homepage": "https://github.com/ZK-Andy/dsh-continual-evolve",
|
|
11
11
|
"bugs": {
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
65
|
-
"@deepseek-ai/dsh-agent": "0.1.0-rc.
|
|
66
|
-
"@deepseek-ai/dsh-commands": "0.1.0-rc.
|
|
67
|
-
"@deepseek-ai/dsh-home-paths": "0.1.0-rc.
|
|
68
|
-
"@deepseek-ai/dsh-llm": "0.1.0-rc.
|
|
69
|
-
"@deepseek-ai/dsh-system-prompt": "0.1.0-rc.
|
|
70
|
-
"@deepseek-ai/dsh-tools": "0.1.0-rc.
|
|
65
|
+
"@deepseek-ai/dsh-agent": "0.1.0-rc.7",
|
|
66
|
+
"@deepseek-ai/dsh-commands": "0.1.0-rc.7",
|
|
67
|
+
"@deepseek-ai/dsh-home-paths": "0.1.0-rc.7",
|
|
68
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.7",
|
|
69
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.0-rc.7",
|
|
70
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.7",
|
|
71
71
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
72
72
|
"@types/node": "^22.10.0",
|
|
73
73
|
"oxlint": "^0.16.0",
|