@lmzhen/dsh-evolution-review 0.3.39 → 0.3.41
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 +44 -35
- package/lib/types/index.d.ts +5 -0
- package/package.json +10 -10
package/lib/index.js
CHANGED
|
@@ -23,6 +23,7 @@ const Config = z.object({
|
|
|
23
23
|
reviewMaxDepth: z.number().min(1).default(1),
|
|
24
24
|
reviewProvider: z.string(),
|
|
25
25
|
skillReviewTrigger: z.string().default(DEFAULT_SKILL_REVIEW_TRIGGER),
|
|
26
|
+
reviewWakeInject: z.boolean().default(true),
|
|
26
27
|
skillReviewCompletionMinToolCalls: z.number().min(1).default(DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS)
|
|
27
28
|
});
|
|
28
29
|
let statelessReviewStateWarned = false;
|
|
@@ -64,18 +65,20 @@ function apply(ctx, rawConfig) {
|
|
|
64
65
|
const completionInjected = /* @__PURE__ */ new Set();
|
|
65
66
|
const pendingCadenceReviews = /* @__PURE__ */ new Map();
|
|
66
67
|
const pendingCadenceWarned = /* @__PURE__ */ new Set();
|
|
68
|
+
const skipNextCadenceFire = /* @__PURE__ */ new Map();
|
|
67
69
|
let reviewInFlight = false;
|
|
68
70
|
const policy = () => ctx.get("evolutionPolicy")?.get();
|
|
69
71
|
ctx.on("session/event", (session, event) => {
|
|
70
72
|
if (event.type === "turn/start") turnStarts.set(session.id, session.seq - 1);
|
|
71
73
|
if (event.type !== "turn/end") return;
|
|
72
|
-
if (turnStarts.size >= COUNTER_SWEEP_THRESHOLD || cumulativeToolCalls.size >= COUNTER_SWEEP_THRESHOLD || completionInjected.size >= COUNTER_SWEEP_THRESHOLD || pendingCadenceReviews.size >= COUNTER_SWEEP_THRESHOLD) {
|
|
74
|
+
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) {
|
|
73
75
|
const isAlive = (id) => ctx.agents.get(id) !== void 0;
|
|
74
76
|
sweepDeadSessionEntries(turnStarts, isAlive);
|
|
75
77
|
sweepDeadSessionEntries(cumulativeToolCalls, isAlive);
|
|
76
78
|
sweepDeadSessionEntries(completionInjected, isAlive);
|
|
77
79
|
sweepDeadSessionEntries(pendingCadenceReviews, isAlive);
|
|
78
80
|
sweepDeadSessionEntries(pendingCadenceWarned, isAlive);
|
|
81
|
+
sweepDeadSessionEntries(skipNextCadenceFire, isAlive);
|
|
79
82
|
}
|
|
80
83
|
onTurnEnd(session, event);
|
|
81
84
|
});
|
|
@@ -109,33 +112,45 @@ function apply(ctx, rawConfig) {
|
|
|
109
112
|
lastTurn: -1
|
|
110
113
|
};
|
|
111
114
|
const snapshot = policy();
|
|
112
|
-
const
|
|
115
|
+
const skipFire = skipNextCadenceFire.get(session.id) ?? false;
|
|
116
|
+
if (skipFire) skipNextCadenceFire.delete(session.id);
|
|
117
|
+
const rawKind = advanceReview(state, event.data.turn, signal, {
|
|
113
118
|
memoryInterval: snapshot?.reviewMemoryInterval ?? config.memoryInterval,
|
|
114
119
|
skillInterval: snapshot?.reviewSkillInterval ?? config.skillInterval,
|
|
115
120
|
substantiveMinToolCalls: snapshot?.substantiveMinToolCalls ?? 3,
|
|
116
121
|
substantiveMinUserChars: snapshot?.substantiveMinUserChars ?? 200,
|
|
117
|
-
substantiveMinAgentChars: snapshot?.substantiveMinAgentChars ?? 500
|
|
122
|
+
substantiveMinAgentChars: snapshot?.substantiveMinAgentChars ?? 500,
|
|
123
|
+
resetOnFire: false
|
|
118
124
|
});
|
|
125
|
+
const kind = skipFire ? null : rawKind;
|
|
119
126
|
await stateService?.saveReviewState(session.id, state);
|
|
120
127
|
const cumulative = (cumulativeToolCalls.get(session.id) ?? 0) + signal.toolCalls;
|
|
121
128
|
cumulativeToolCalls.set(session.id, cumulative);
|
|
129
|
+
const deliverReview = (text) => {
|
|
130
|
+
const message = createUserMessage({
|
|
131
|
+
content: [{
|
|
132
|
+
type: "text",
|
|
133
|
+
text
|
|
134
|
+
}],
|
|
135
|
+
source: {
|
|
136
|
+
kind: "plugin",
|
|
137
|
+
plugin: "dsh-evolution-review",
|
|
138
|
+
form: "notice",
|
|
139
|
+
summary: "auto-review"
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
const followup = agent.followup;
|
|
143
|
+
if (config.reviewWakeInject && typeof followup === "function") {
|
|
144
|
+
followup(message);
|
|
145
|
+
skipNextCadenceFire.set(session.id, true);
|
|
146
|
+
} else agent.inject(message);
|
|
147
|
+
};
|
|
122
148
|
if (event.data.reason.kind === "completed") {
|
|
123
|
-
const pendingKind = pendingCadenceReviews.get(session.id);
|
|
149
|
+
const pendingKind = pendingCadenceReviews.get(session.id) ?? kind ?? void 0;
|
|
124
150
|
if (pendingKind !== void 0) {
|
|
125
151
|
pendingCadenceReviews.delete(session.id);
|
|
126
152
|
if ((policy()?.reviewMode ?? config.reviewMode) === "inject") try {
|
|
127
|
-
|
|
128
|
-
content: [{
|
|
129
|
-
type: "text",
|
|
130
|
-
text: reviewPrompt(pendingKind)
|
|
131
|
-
}],
|
|
132
|
-
source: {
|
|
133
|
-
kind: "plugin",
|
|
134
|
-
plugin: "dsh-evolution-review",
|
|
135
|
-
form: "notice",
|
|
136
|
-
summary: "auto-review"
|
|
137
|
-
}
|
|
138
|
-
}));
|
|
153
|
+
deliverReview(reviewPrompt(pendingKind));
|
|
139
154
|
} catch (injectError) {
|
|
140
155
|
ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
|
|
141
156
|
}
|
|
@@ -147,24 +162,16 @@ function apply(ctx, rawConfig) {
|
|
|
147
162
|
assistantChars: signal.assistantChars
|
|
148
163
|
});
|
|
149
164
|
else try {
|
|
150
|
-
|
|
151
|
-
content: [{
|
|
152
|
-
type: "text",
|
|
153
|
-
text: reviewPrompt(pendingKind)
|
|
154
|
-
}],
|
|
155
|
-
source: {
|
|
156
|
-
kind: "plugin",
|
|
157
|
-
plugin: "dsh-evolution-review",
|
|
158
|
-
form: "notice",
|
|
159
|
-
summary: "auto-review"
|
|
160
|
-
}
|
|
161
|
-
}));
|
|
165
|
+
deliverReview(reviewPrompt(pendingKind));
|
|
162
166
|
} catch (injectError) {
|
|
163
167
|
ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
|
|
164
168
|
}
|
|
169
|
+
state.turnsSinceMemory = 0;
|
|
170
|
+
state.turnsSinceSkill = 0;
|
|
171
|
+
await stateService?.saveReviewState(session.id, state);
|
|
165
172
|
}
|
|
166
173
|
}
|
|
167
|
-
if (kind) {
|
|
174
|
+
if (kind && event.data.reason.kind !== "completed") {
|
|
168
175
|
pendingCadenceReviews.set(session.id, kind);
|
|
169
176
|
if (!pendingCadenceWarned.has(session.id)) {
|
|
170
177
|
pendingCadenceWarned.add(session.id);
|
|
@@ -267,7 +274,7 @@ function apply(ctx, rawConfig) {
|
|
|
267
274
|
});
|
|
268
275
|
const acceptedSkillOps = validation.accepted.skillOps ?? [];
|
|
269
276
|
const skippedUnread = filterUnreadSkillOps(acceptedSkillOps, new Set([...collectReadSkillNames(session), ...childReads]));
|
|
270
|
-
const executed = await executePlan(validation.accepted, session
|
|
277
|
+
const executed = await executePlan(validation.accepted, session);
|
|
271
278
|
const actions = executed.actions;
|
|
272
279
|
const evidenceQuotes = [...validation.accepted.memoryOps ?? [], ...acceptedSkillOps].reduce((total, op) => total + (Array.isArray(op.evidence) ? op.evidence.length : 0), 0);
|
|
273
280
|
if (actions.length > 0) {
|
|
@@ -345,7 +352,8 @@ function apply(ctx, rawConfig) {
|
|
|
345
352
|
reviewInFlight = false;
|
|
346
353
|
}
|
|
347
354
|
}
|
|
348
|
-
async function executePlan(plan,
|
|
355
|
+
async function executePlan(plan, session) {
|
|
356
|
+
const sessionId = session?.id;
|
|
349
357
|
const memory = ctx.get("memory");
|
|
350
358
|
const approval = ctx.get("evolutionApproval");
|
|
351
359
|
const origins = resolveOrigins(void 0, true);
|
|
@@ -361,7 +369,7 @@ function apply(ctx, rawConfig) {
|
|
|
361
369
|
facts: op.facts ?? op.content,
|
|
362
370
|
old_text: op.old_text
|
|
363
371
|
};
|
|
364
|
-
const result = approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized) : await memory?.applyBatch(normalized.target, [normalized]);
|
|
372
|
+
const result = approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized, session) : await memory?.applyBatch(normalized.target, [normalized]);
|
|
365
373
|
if (result?.ok) actions.push("Memory updated");
|
|
366
374
|
else {
|
|
367
375
|
ok = false;
|
|
@@ -378,7 +386,7 @@ function apply(ctx, rawConfig) {
|
|
|
378
386
|
operation: args,
|
|
379
387
|
origin: origins.library
|
|
380
388
|
};
|
|
381
|
-
const result = approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs) : await executeSkillDirect(args);
|
|
389
|
+
const result = approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs, session) : await executeSkillDirect(args);
|
|
382
390
|
if (result?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
|
|
383
391
|
else {
|
|
384
392
|
ok = false;
|
|
@@ -401,7 +409,7 @@ function apply(ctx, rawConfig) {
|
|
|
401
409
|
aborted: reason
|
|
402
410
|
};
|
|
403
411
|
}
|
|
404
|
-
async function runApproved(kind, summary, stored, runnerArgs) {
|
|
412
|
+
async function runApproved(kind, summary, stored, runnerArgs, approvalSession) {
|
|
405
413
|
if (!approval) return void 0;
|
|
406
414
|
if (approval.isEnabled === true && !approval.hasRunner(kind)) {
|
|
407
415
|
ctx.logger.warn(`dsh-evolution-review: approval enabled but no replay runner registered for kind "${kind}" - skipping write (${summary})`);
|
|
@@ -415,7 +423,8 @@ function apply(ctx, rawConfig) {
|
|
|
415
423
|
summary,
|
|
416
424
|
args: stored,
|
|
417
425
|
origin: origins.approval,
|
|
418
|
-
...sessionId ? { sessionId } : {}
|
|
426
|
+
...sessionId ? { sessionId } : {},
|
|
427
|
+
...approvalSession ? { session: approvalSession } : {}
|
|
419
428
|
});
|
|
420
429
|
if (decision.action === "staged") return {
|
|
421
430
|
ok: false,
|
package/lib/types/index.d.ts
CHANGED
|
@@ -32,6 +32,11 @@ export interface Config {
|
|
|
32
32
|
skillReviewTrigger?: string;
|
|
33
33
|
/** Cumulative session tool calls before a session counts as proven-long for the completion channel. */
|
|
34
34
|
skillReviewCompletionMinToolCalls?: number;
|
|
35
|
+
/** 0.3.40: deliver the deferred review with a WAKING inject for a summary the
|
|
36
|
+
* model starts immediately (agent.followup — same send() queue, wakeup bit
|
|
37
|
+
* differs). Default true; false degrades to the non-waking inject (the
|
|
38
|
+
* summary then waits for the next driver wake). */
|
|
39
|
+
reviewWakeInject?: boolean;
|
|
35
40
|
}
|
|
36
41
|
export declare const Config: z<Config>;
|
|
37
42
|
/**
|
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.41",
|
|
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.41",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.41",
|
|
36
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.3.41"
|
|
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.41",
|
|
46
|
+
"@lmzhen/dsh-evolution-policy": "^0.3.41"
|
|
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.41",
|
|
58
|
+
"@lmzhen/dsh-evolution-core": "^0.3.41",
|
|
59
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.3.41",
|
|
60
|
+
"@lmzhen/dsh-evolution-state": "^0.3.41"
|
|
61
61
|
}
|
|
62
62
|
}
|