@lmzhen/dsh-evolution-review 0.3.65 → 0.3.66
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 +62 -19
- 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, resolveRootConfig, 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, contentHash, 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
|
/**
|
|
@@ -94,7 +94,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
94
94
|
let reviewInFlight = false;
|
|
95
95
|
const policy = () => ctx.get("evolutionPolicy")?.get();
|
|
96
96
|
ctx.on("session/event", (session, event) => {
|
|
97
|
-
if (event.type === "turn/start") turnStarts.set(session.id, session.seq - 1);
|
|
97
|
+
if (event.type === "turn/start" && session.header.origin !== "subagent") turnStarts.set(session.id, session.seq - 1);
|
|
98
98
|
if (event.type !== "turn/end") return;
|
|
99
99
|
if (turnStarts.size >= COUNTER_SWEEP_THRESHOLD || cumulativeToolCalls.size >= COUNTER_SWEEP_THRESHOLD || completionInjected.size >= COUNTER_SWEEP_THRESHOLD || pendingCadenceReviews.size >= COUNTER_SWEEP_THRESHOLD || skipNextCadenceFire.size >= COUNTER_SWEEP_THRESHOLD || cadenceResetWarned.size >= COUNTER_SWEEP_THRESHOLD) {
|
|
100
100
|
const isAlive = (id) => ctx.agents.get(id) !== void 0;
|
|
@@ -161,21 +161,24 @@ function apply(ctx, rawConfig = {}) {
|
|
|
161
161
|
} catch (injectError) {
|
|
162
162
|
ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
|
|
163
163
|
}
|
|
164
|
-
else
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
164
|
+
else {
|
|
165
|
+
const reviewOutcome = await trySubagentReview(session, agent, pendingKind, signal);
|
|
166
|
+
if (reviewOutcome === true) try {
|
|
167
|
+
ctx.emit("evolution/review-scheduled", {
|
|
168
|
+
sessionId: session.id,
|
|
169
|
+
kind: pendingKind,
|
|
170
|
+
toolCalls: signal.toolCalls,
|
|
171
|
+
userChars: signal.userChars,
|
|
172
|
+
assistantChars: signal.assistantChars
|
|
173
|
+
});
|
|
174
|
+
} catch (emitError) {
|
|
175
|
+
ctx.logger.warn(`dsh-evolution-review: review-scheduled emit failed: ${emitError instanceof Error ? emitError.message : String(emitError)}`);
|
|
176
|
+
}
|
|
177
|
+
else if (reviewOutcome !== "deferred") try {
|
|
178
|
+
deliverMessage(agent, reviewPrompt(pendingKind), "auto-review");
|
|
179
|
+
} catch (injectError) {
|
|
180
|
+
ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
|
|
181
|
+
}
|
|
179
182
|
}
|
|
180
183
|
state.turnsSinceMemory = 0;
|
|
181
184
|
state.turnsSinceSkill = 0;
|
|
@@ -246,11 +249,35 @@ function apply(ctx, rawConfig = {}) {
|
|
|
246
249
|
skipNextCadenceFire.set(agent.session.id, true);
|
|
247
250
|
} else agent.inject(message);
|
|
248
251
|
};
|
|
252
|
+
const withTimeout = (promise, ms, label) => new Promise((resolve, reject) => {
|
|
253
|
+
const timer = setTimeout(() => {
|
|
254
|
+
reject(/* @__PURE__ */ new Error(`dsh-evolution-review: ${label} timed out after ${ms}ms`));
|
|
255
|
+
}, ms);
|
|
256
|
+
promise.then((value) => {
|
|
257
|
+
clearTimeout(timer);
|
|
258
|
+
resolve(value);
|
|
259
|
+
}, (error) => {
|
|
260
|
+
clearTimeout(timer);
|
|
261
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
const deferredFallbackReviews = [];
|
|
265
|
+
const DEFERRED_REVIEW_CAP = 16;
|
|
266
|
+
ctx.effect(() => () => {
|
|
267
|
+
deferredFallbackReviews.length = 0;
|
|
268
|
+
}, "dsh-evolution-review.deferred-drain");
|
|
249
269
|
async function trySubagentReview(session, agent, kind, signal) {
|
|
250
270
|
if ((policy()?.reviewMode ?? config.reviewMode) === "inject") return false;
|
|
251
271
|
const subagents = ctx.get("subagents");
|
|
252
272
|
if (!subagents) return false;
|
|
253
|
-
if (reviewInFlight)
|
|
273
|
+
if (reviewInFlight) {
|
|
274
|
+
if (deferredFallbackReviews.length < DEFERRED_REVIEW_CAP) deferredFallbackReviews.push({
|
|
275
|
+
agent,
|
|
276
|
+
kind
|
|
277
|
+
});
|
|
278
|
+
else ctx.logger.warn(`dsh-evolution-review: deferred-review queue at cap (${DEFERRED_REVIEW_CAP}) — dropping one fallback review prompt`);
|
|
279
|
+
return "deferred";
|
|
280
|
+
}
|
|
254
281
|
reviewInFlight = true;
|
|
255
282
|
try {
|
|
256
283
|
const snapshot = policy();
|
|
@@ -296,7 +323,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
296
323
|
});
|
|
297
324
|
const acceptedSkillOps = validation.accepted.skillOps ?? [];
|
|
298
325
|
const skippedUnread = filterUnreadSkillOps(acceptedSkillOps, new Set([...collectReadSkillNames(session), ...childReads]));
|
|
299
|
-
const executed = await executePlan(validation.accepted, session);
|
|
326
|
+
const executed = await withTimeout(executePlan(validation.accepted, session), config.reviewTimeoutMs, "review plan execution");
|
|
300
327
|
const actions = executed.actions;
|
|
301
328
|
const evidenceQuotes = [...validation.accepted.memoryOps ?? [], ...acceptedSkillOps].reduce((total, op) => total + (Array.isArray(op.evidence) ? op.evidence.length : 0), 0);
|
|
302
329
|
if (actions.length > 0) {
|
|
@@ -347,15 +374,27 @@ function apply(ctx, rawConfig = {}) {
|
|
|
347
374
|
}
|
|
348
375
|
} catch (error) {
|
|
349
376
|
ctx.logger.warn(`dsh-evolution-review: subagent review failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
377
|
+
if (error instanceof Error && error.message.includes("plan execution timed out")) ctx.logger.warn("dsh-evolution-review: plan execution abandoned on timeout — any late write it lands has NO plan-applied record and races the fallback inject; inspect the skill tree and usage sidecar");
|
|
350
378
|
return false;
|
|
351
379
|
} finally {
|
|
352
380
|
reviewInFlight = false;
|
|
381
|
+
const deferred = deferredFallbackReviews.splice(0);
|
|
382
|
+
for (const { agent: waitingAgent, kind: waitingKind } of deferred) try {
|
|
383
|
+
deliverMessage(waitingAgent, reviewPrompt(waitingKind), "auto-review");
|
|
384
|
+
} catch (injectError) {
|
|
385
|
+
ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
|
|
386
|
+
}
|
|
353
387
|
}
|
|
354
388
|
}
|
|
355
389
|
async function executePlan(plan, session) {
|
|
356
390
|
const sessionId = session?.id;
|
|
357
391
|
const memory = ctx.get("memory");
|
|
358
392
|
const approval = ctx.get("evolutionApproval");
|
|
393
|
+
const hashLibrary = (() => {
|
|
394
|
+
const io = ctx.get("evolutionIo");
|
|
395
|
+
if (!io) return null;
|
|
396
|
+
return new SkillLibrary(resolveSkillsRoot({ root: rootConfig.root }), evolutionIoAdapter(() => io.provider()));
|
|
397
|
+
})();
|
|
359
398
|
const origins = resolveOrigins(void 0, true);
|
|
360
399
|
const actions = [];
|
|
361
400
|
const failedOps = [];
|
|
@@ -390,6 +429,10 @@ function apply(ctx, rawConfig = {}) {
|
|
|
390
429
|
...op,
|
|
391
430
|
evidence: op.evidence
|
|
392
431
|
};
|
|
432
|
+
if ((args.action === "update" || args.action === "edit") && hashLibrary && typeof args.name === "string" && args.name !== "") {
|
|
433
|
+
const stageCurrent = await hashLibrary.read(args.name).catch(() => null);
|
|
434
|
+
if (stageCurrent !== null) args.staged_from_sha256 = contentHash(stageCurrent);
|
|
435
|
+
}
|
|
393
436
|
const runnerArgs = {
|
|
394
437
|
operation: args,
|
|
395
438
|
origin: origins.library
|
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.66",
|
|
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.66",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.66",
|
|
36
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.3.66"
|
|
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.66",
|
|
46
|
+
"@lmzhen/dsh-evolution-policy": "^0.3.66"
|
|
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.66",
|
|
58
|
+
"@lmzhen/dsh-evolution-core": "^0.3.66",
|
|
59
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.3.66",
|
|
60
|
+
"@lmzhen/dsh-evolution-state": "^0.3.66"
|
|
61
61
|
}
|
|
62
62
|
}
|