@lmzhen/dsh-evolution-review 0.3.62 → 0.3.64
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/lib/index.js +33 -11
- package/lib/types/index.d.ts +5 -2
- package/package.json +10 -10
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
4
|
-
import { COMPLETION_SKILL_REVIEW_PROMPT, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_USER_CHAR_LIMIT, PROMPT_BUNDLE, SkillLibrary, advanceReview, clampedNumber, evolutionIoAdapter, foldTurn, redactSecrets, resolveOrigins, resolveSkillsRoot, reviewPrompt, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
4
|
+
import { COMPLETION_SKILL_REVIEW_PROMPT, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_REVIEW_CONTEXT_MESSAGES, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_MESSAGE_CHARS, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_REVIEW_TIMEOUT_MS, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_USER_CHAR_LIMIT, PROMPT_BUNDLE, SkillLibrary, advanceReview, clampedNumber, evolutionIoAdapter, foldTurn, redactSecrets, resolveOrigins, resolveRootConfig, resolveSkillsRoot, reviewPrompt, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
5
5
|
import { validateEvolutionPlan } from "@lmzhen/dsh-evolution-plan-validator";
|
|
6
6
|
//#region lib/types/index.js
|
|
7
7
|
/**
|
|
@@ -10,13 +10,20 @@ import { validateEvolutionPlan } from "@lmzhen/dsh-evolution-plan-validator";
|
|
|
10
10
|
*/
|
|
11
11
|
const name = "evolution-review";
|
|
12
12
|
const inject = ["agents"];
|
|
13
|
+
/** Node's 32-bit timer-delay ceiling (`AbortSignal.timeout`/`setTimeout`):
|
|
14
|
+
* a larger value throws RangeError. B-2 (v18): without a max, a misconfigured
|
|
15
|
+
* `reviewTimeoutMs` made `AbortSignal.timeout` throw inside the subagent
|
|
16
|
+
* start call; the outer catch logged it and silently degraded the review to
|
|
17
|
+
* the inject path. The schema and the assembly clamp both reject it (same
|
|
18
|
+
* bound as commands/maintenance). */
|
|
19
|
+
const MAX_TIMER_DELAY_MS = 4294967295;
|
|
13
20
|
const Config = z.object({
|
|
14
21
|
reviewEnabled: z.boolean().default(true),
|
|
15
22
|
reviewMode: z.union([z.const("subagent"), z.const("inject")]).default("subagent"),
|
|
16
23
|
memoryInterval: z.number().min(1).default(DEFAULT_REVIEW_MEMORY_INTERVAL),
|
|
17
24
|
skillInterval: z.number().min(1).default(DEFAULT_REVIEW_SKILL_INTERVAL),
|
|
18
25
|
reviewToolAllow: z.array(z.string()).default(["skill"]),
|
|
19
|
-
reviewTimeoutMs: z.number().min(1).default(DEFAULT_REVIEW_TIMEOUT_MS),
|
|
26
|
+
reviewTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS).default(DEFAULT_REVIEW_TIMEOUT_MS),
|
|
20
27
|
reviewContextMessages: z.number().min(1).default(DEFAULT_REVIEW_CONTEXT_MESSAGES),
|
|
21
28
|
reviewMessageChars: z.number().min(1).default(DEFAULT_REVIEW_MESSAGE_CHARS),
|
|
22
29
|
reviewMaxDepth: z.number().min(1).default(1),
|
|
@@ -28,6 +35,7 @@ const Config = z.object({
|
|
|
28
35
|
]).default(DEFAULT_SKILL_REVIEW_TRIGGER),
|
|
29
36
|
reviewWakeInject: z.boolean().default(true),
|
|
30
37
|
skillReviewCompletionMinToolCalls: z.number().min(1).default(DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS),
|
|
38
|
+
root: z.string().default(""),
|
|
31
39
|
skillsRoot: z.string().default("")
|
|
32
40
|
});
|
|
33
41
|
/** V8-01 (0.3.45): the review subagent's structured-output contract. The
|
|
@@ -48,18 +56,20 @@ const REVIEW_OUTPUT_SCHEMA = {
|
|
|
48
56
|
summary: { type: "string" }
|
|
49
57
|
}
|
|
50
58
|
};
|
|
51
|
-
let statelessReviewStateWarned = false;
|
|
52
59
|
function clampReviewConfig(rawConfig, ctx) {
|
|
53
60
|
const clamped = [];
|
|
54
|
-
const field = (name, value, fallback, min) => {
|
|
55
|
-
const result = clampedNumber(value, fallback, { min }
|
|
61
|
+
const field = (name, value, fallback, min, max) => {
|
|
62
|
+
const result = clampedNumber(value, fallback, max === void 0 ? { min } : {
|
|
63
|
+
min,
|
|
64
|
+
max
|
|
65
|
+
});
|
|
56
66
|
if (value !== void 0 && result !== value) clamped.push(name);
|
|
57
67
|
return result;
|
|
58
68
|
};
|
|
59
69
|
const config = Object.assign({}, rawConfig, {
|
|
60
70
|
memoryInterval: field("memoryInterval", rawConfig.memoryInterval, DEFAULT_REVIEW_MEMORY_INTERVAL, 1),
|
|
61
71
|
skillInterval: field("skillInterval", rawConfig.skillInterval, DEFAULT_REVIEW_SKILL_INTERVAL, 1),
|
|
62
|
-
reviewTimeoutMs: field("reviewTimeoutMs", rawConfig.reviewTimeoutMs, DEFAULT_REVIEW_TIMEOUT_MS, 1),
|
|
72
|
+
reviewTimeoutMs: field("reviewTimeoutMs", rawConfig.reviewTimeoutMs, DEFAULT_REVIEW_TIMEOUT_MS, 1, MAX_TIMER_DELAY_MS),
|
|
63
73
|
reviewContextMessages: field("reviewContextMessages", rawConfig.reviewContextMessages, DEFAULT_REVIEW_CONTEXT_MESSAGES, 1),
|
|
64
74
|
reviewMessageChars: field("reviewMessageChars", rawConfig.reviewMessageChars, DEFAULT_REVIEW_MESSAGE_CHARS, 1),
|
|
65
75
|
reviewMaxDepth: field("reviewMaxDepth", rawConfig.reviewMaxDepth, 1, 1),
|
|
@@ -68,10 +78,13 @@ function clampReviewConfig(rawConfig, ctx) {
|
|
|
68
78
|
if (clamped.length > 0) ctx.logger.warn(`dsh-evolution-review: ${clamped.join(", ")} provided an invalid value; falling back to the default`);
|
|
69
79
|
return config;
|
|
70
80
|
}
|
|
71
|
-
function apply(ctx, rawConfig) {
|
|
81
|
+
function apply(ctx, rawConfig = {}) {
|
|
72
82
|
if (!verifyPromptBundle(PROMPT_BUNDLE)) throw new Error("dsh-evolution prompt bundle integrity check failed; refusing to schedule review work");
|
|
73
83
|
const config = clampReviewConfig(rawConfig, ctx);
|
|
84
|
+
const rootConfig = resolveRootConfig(rawConfig);
|
|
85
|
+
if (rootConfig.usedDeprecatedAlias) ctx.logger.warn("evolution-review: config \"skillsRoot\" is deprecated (E-7); use \"root\" — the alias is honoured until 0.3.65");
|
|
74
86
|
const turnStarts = /* @__PURE__ */ new Map();
|
|
87
|
+
let statelessReviewStateWarned = false;
|
|
75
88
|
const cumulativeToolCalls = /* @__PURE__ */ new Map();
|
|
76
89
|
const completionInjected = /* @__PURE__ */ new Set();
|
|
77
90
|
const pendingCadenceReviews = /* @__PURE__ */ new Map();
|
|
@@ -185,6 +198,7 @@ function apply(ctx, rawConfig) {
|
|
|
185
198
|
}
|
|
186
199
|
return;
|
|
187
200
|
}
|
|
201
|
+
if (skipFire) return;
|
|
188
202
|
const trigger = config.skillReviewTrigger;
|
|
189
203
|
if (trigger !== "completion" && trigger !== "both") return;
|
|
190
204
|
if (completionInjected.has(session.id)) return;
|
|
@@ -348,7 +362,11 @@ function apply(ctx, rawConfig) {
|
|
|
348
362
|
let ok = true;
|
|
349
363
|
try {
|
|
350
364
|
for (const op of plan.memoryOps ?? []) {
|
|
351
|
-
if (!Array.isArray(op.evidence) || op.evidence.length === 0)
|
|
365
|
+
if (!Array.isArray(op.evidence) || op.evidence.length === 0) {
|
|
366
|
+
ok = false;
|
|
367
|
+
failedOps.push(`memory ${op.action ?? "add"} ${op.target}: missing evidence (defense-in-depth rejection)`);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
352
370
|
const normalized = {
|
|
353
371
|
target: op.target === "user" ? "user" : "memory",
|
|
354
372
|
action: op.action ?? "add",
|
|
@@ -363,7 +381,11 @@ function apply(ctx, rawConfig) {
|
|
|
363
381
|
}
|
|
364
382
|
}
|
|
365
383
|
for (const op of plan.skillOps ?? []) {
|
|
366
|
-
if (!Array.isArray(op.evidence) || op.evidence.length === 0 || !op.name)
|
|
384
|
+
if (!Array.isArray(op.evidence) || op.evidence.length === 0 || !op.name) {
|
|
385
|
+
ok = false;
|
|
386
|
+
failedOps.push(`skill ${op.action ?? "patch"} ${op.name ?? "<unnamed>"}: missing evidence or name (defense-in-depth rejection)`);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
367
389
|
const args = {
|
|
368
390
|
...op,
|
|
369
391
|
evidence: op.evidence
|
|
@@ -448,7 +470,7 @@ function apply(ctx, rawConfig) {
|
|
|
448
470
|
ok: false,
|
|
449
471
|
message: "evolution-io service not mounted"
|
|
450
472
|
};
|
|
451
|
-
const library = new SkillLibrary(resolveSkillsRoot({ root:
|
|
473
|
+
const library = new SkillLibrary(resolveSkillsRoot({ root: rootConfig.root }), evolutionIoAdapter(() => io.provider()), void 0, (event) => {
|
|
452
474
|
ctx.emit("evolution/skill-mutated", event);
|
|
453
475
|
});
|
|
454
476
|
const op = skillArgs;
|
|
@@ -471,7 +493,7 @@ function apply(ctx, rawConfig) {
|
|
|
471
493
|
if (archived.ok) await ctx.get("skillUsage")?.markArchived?.(name);
|
|
472
494
|
return archived;
|
|
473
495
|
}
|
|
474
|
-
if (op.action === "write_file") return await library.writeSupportFile(name, op.file_path ?? "", op.file_content ??
|
|
496
|
+
if (op.action === "write_file") return await library.writeSupportFile(name, op.file_path ?? "", op.file_content ?? "", origin);
|
|
475
497
|
if (op.action === "remove_file") return await library.removeSupportFile(name, op.file_path ?? "", origin);
|
|
476
498
|
if (op.action === "restructure") {
|
|
477
499
|
const moves = (op.restructure ?? []).filter((move) => move !== null).map((move) => ({
|
package/lib/types/index.d.ts
CHANGED
|
@@ -45,7 +45,10 @@ export interface Config {
|
|
|
45
45
|
* Empty (the default) resolves through `resolveSkillsRoot` to the shared
|
|
46
46
|
* default root — the historical behavior. A custom root keeps review-created
|
|
47
47
|
* skills in the SAME tree the catalog/tools read instead of writing a
|
|
48
|
-
* parallel tree the rest of the family cannot see. */
|
|
48
|
+
* parallel tree the rest of the family cannot see. E-7 (v18): canonical key. */
|
|
49
|
+
root?: string;
|
|
50
|
+
/** Deprecated alias of `root` (E-7, v18); honoured only while `root` is
|
|
51
|
+
* empty, with a warning; removed after 0.3.65. */
|
|
49
52
|
skillsRoot?: string;
|
|
50
53
|
}
|
|
51
54
|
export declare const Config: z<Config>;
|
|
@@ -97,7 +100,7 @@ type ClampedReviewConfig = Config & {
|
|
|
97
100
|
skillReviewCompletionMinToolCalls: number;
|
|
98
101
|
};
|
|
99
102
|
export declare function clampReviewConfig(rawConfig: Config, ctx: Context): ClampedReviewConfig;
|
|
100
|
-
export declare function apply(ctx: Context, rawConfig
|
|
103
|
+
export declare function apply(ctx: Context, rawConfig?: Config): void;
|
|
101
104
|
/** Completion-channel decision: task finished normally AND the session is proven long. */
|
|
102
105
|
export declare function shouldCompletionReview(reason: {
|
|
103
106
|
kind?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-review",
|
|
3
3
|
"description": "Background review orchestration (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.64",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-approval": "^0.3.
|
|
35
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
36
|
-
"@lmzhen/dsh-evolution-plan-validator": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-approval": "^0.3.64",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.64",
|
|
36
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.3.64"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
|
|
43
43
|
"@deepseek-ai/dsh-session": "^0.1.1-rc.2",
|
|
44
44
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
45
|
-
"@lmzhen/dsh-evolution-state": "^0.3.
|
|
46
|
-
"@lmzhen/dsh-evolution-policy": "^0.3.
|
|
45
|
+
"@lmzhen/dsh-evolution-state": "^0.3.64",
|
|
46
|
+
"@lmzhen/dsh-evolution-policy": "^0.3.64"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2",
|
|
55
55
|
"@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.1-rc.2",
|
|
56
56
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
57
|
-
"@lmzhen/dsh-evolution-approval": "^0.3.
|
|
58
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
59
|
-
"@lmzhen/dsh-evolution-plan-validator": "^0.3.
|
|
60
|
-
"@lmzhen/dsh-evolution-state": "^0.3.
|
|
57
|
+
"@lmzhen/dsh-evolution-approval": "^0.3.64",
|
|
58
|
+
"@lmzhen/dsh-evolution-core": "^0.3.64",
|
|
59
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.3.64",
|
|
60
|
+
"@lmzhen/dsh-evolution-state": "^0.3.64"
|
|
61
61
|
}
|
|
62
62
|
}
|