@lmzhen/dsh-evolution-review 0.1.0-rc.41 → 0.1.0-rc.43
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 +76 -44
- package/lib/types/index.d.ts +10 -0
- package/package.json +9 -7
package/lib/index.js
CHANGED
|
@@ -64,6 +64,12 @@ function apply(ctx, rawConfig) {
|
|
|
64
64
|
ctx.on("session/event", (session, event) => {
|
|
65
65
|
if (event.type === "turn/start") turnStarts.set(session.id, session.seq - 1);
|
|
66
66
|
if (event.type !== "turn/end") return;
|
|
67
|
+
if (turnStarts.size >= 128 || cumulativeToolCalls.size >= 128 || completionInjected.size >= 128) {
|
|
68
|
+
const isAlive = (id) => ctx.agents.get(id) !== void 0;
|
|
69
|
+
sweepDeadSessionEntries(turnStarts, isAlive);
|
|
70
|
+
sweepDeadSessionEntries(cumulativeToolCalls, isAlive);
|
|
71
|
+
sweepDeadSessionEntries(completionInjected, isAlive);
|
|
72
|
+
}
|
|
67
73
|
onTurnEnd(session, event);
|
|
68
74
|
});
|
|
69
75
|
async function onTurnEnd(session, event) {
|
|
@@ -91,7 +97,8 @@ function apply(ctx, rawConfig) {
|
|
|
91
97
|
const cumulative = (cumulativeToolCalls.get(session.id) ?? 0) + signal.toolCalls;
|
|
92
98
|
cumulativeToolCalls.set(session.id, cumulative);
|
|
93
99
|
if (kind) {
|
|
94
|
-
|
|
100
|
+
ctx.emit("evolution/review-scheduled", {
|
|
101
|
+
sessionId: session.id,
|
|
95
102
|
kind,
|
|
96
103
|
toolCalls: signal.toolCalls,
|
|
97
104
|
userChars: signal.userChars,
|
|
@@ -116,7 +123,8 @@ function apply(ctx, rawConfig) {
|
|
|
116
123
|
if (completionInjected.has(session.id)) return;
|
|
117
124
|
if (!shouldCompletionReview(event.data.reason, cumulative, config.skillReviewCompletionMinToolCalls)) return;
|
|
118
125
|
completionInjected.add(session.id);
|
|
119
|
-
|
|
126
|
+
ctx.emit("evolution/review-scheduled", {
|
|
127
|
+
sessionId: session.id,
|
|
120
128
|
kind: "skill",
|
|
121
129
|
toolCalls: signal.toolCalls,
|
|
122
130
|
userChars: signal.userChars,
|
|
@@ -173,48 +181,55 @@ function apply(ctx, rawConfig) {
|
|
|
173
181
|
}
|
|
174
182
|
}
|
|
175
183
|
});
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
184
|
+
try {
|
|
185
|
+
const childReads = run.localAgent ? collectReadSkillNames(run.localAgent.session) : /* @__PURE__ */ new Set();
|
|
186
|
+
const result = await run.result;
|
|
187
|
+
if (!result.structured) return true;
|
|
188
|
+
const snapshot = policy();
|
|
189
|
+
const plan = result.structured;
|
|
190
|
+
const policyFingerprint = fingerprintPolicy(snapshot);
|
|
191
|
+
const validation = validateEvolutionPlan(plan, {
|
|
192
|
+
sessionSeq: session.seq - 1,
|
|
193
|
+
maxOpsPerPlan: snapshot?.maxOpsPerPlan ?? DEFAULT_MAX_OPS_PER_PLAN,
|
|
194
|
+
protectedSkillNames: new Set(snapshot?.protectedSkillNames ?? []),
|
|
195
|
+
maxMemoryChars: snapshot?.memoryChars ?? DEFAULT_MEMORY_CHAR_LIMIT,
|
|
196
|
+
maxUserChars: snapshot?.userChars ?? DEFAULT_USER_CHAR_LIMIT,
|
|
197
|
+
maxSkillContentChars: snapshot?.skillContentChars ?? DEFAULT_SKILL_CONTENT_CHARS
|
|
198
|
+
});
|
|
199
|
+
const acceptedSkillOps = validation.accepted.skillOps ?? [];
|
|
200
|
+
const skippedUnread = filterUnreadSkillOps(acceptedSkillOps, new Set([...collectReadSkillNames(session), ...childReads]));
|
|
201
|
+
const actions = await executePlan(validation.accepted);
|
|
202
|
+
const evidenceQuotes = [...validation.accepted.memoryOps ?? [], ...acceptedSkillOps].reduce((total, op) => total + (Array.isArray(op.evidence) ? op.evidence.length : 0), 0);
|
|
203
|
+
ctx.emit("evolution/plan-applied", {
|
|
204
|
+
sessionId: session.id,
|
|
205
|
+
planId: randomUUID(),
|
|
206
|
+
policyFingerprint,
|
|
207
|
+
memoryApplied: actions.filter((action) => action.startsWith("Memory")).length,
|
|
208
|
+
skillApplied: actions.filter((action) => action.startsWith("Skill ")).length,
|
|
209
|
+
rejectedOps: validation.rejected.length + skippedUnread,
|
|
210
|
+
evidenceQuotes,
|
|
211
|
+
estimatedInputChars: reviewText.length
|
|
212
|
+
});
|
|
213
|
+
if (actions.length > 0) agent.inject(createUserMessage({
|
|
214
|
+
content: [{
|
|
215
|
+
type: "text",
|
|
216
|
+
text: `💾 Self-improvement review: ${actions.join(" · ")}`
|
|
217
|
+
}],
|
|
218
|
+
source: {
|
|
219
|
+
kind: "plugin",
|
|
220
|
+
plugin: "dsh-evolution-review",
|
|
221
|
+
form: "notice",
|
|
222
|
+
summary: "self-improvement review"
|
|
223
|
+
}
|
|
224
|
+
}));
|
|
225
|
+
return true;
|
|
226
|
+
} finally {
|
|
227
|
+
try {
|
|
228
|
+
await run.dispose();
|
|
229
|
+
} catch (disposeError) {
|
|
230
|
+
ctx.logger.warn(`dsh-evolution-review: subagent dispose failed: ${disposeError instanceof Error ? disposeError.message : String(disposeError)}`);
|
|
215
231
|
}
|
|
216
|
-
}
|
|
217
|
-
return true;
|
|
232
|
+
}
|
|
218
233
|
} catch (error) {
|
|
219
234
|
ctx.logger.warn(`dsh-evolution-review: subagent review failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
220
235
|
return false;
|
|
@@ -349,6 +364,23 @@ function collectReadSkillNames(session) {
|
|
|
349
364
|
}
|
|
350
365
|
return names;
|
|
351
366
|
}
|
|
367
|
+
/** Map/set size that triggers a dead-session counter sweep (bounded, not a hard cap). */
|
|
368
|
+
const COUNTER_SWEEP_THRESHOLD = 128;
|
|
369
|
+
/**
|
|
370
|
+
* Remove every entry whose session is no longer live (rc.42 audit P1-10):
|
|
371
|
+
* `turnStarts` / `cumulativeToolCalls` / `completionInjected` are keyed by
|
|
372
|
+
* SessionId with no platform session-end hook to prune against, so they grew
|
|
373
|
+
* unbounded over a long-lived host. Works for maps and sets; returns the
|
|
374
|
+
* number of removed entries.
|
|
375
|
+
*/
|
|
376
|
+
function sweepDeadSessionEntries(entries, isAlive) {
|
|
377
|
+
let removed = 0;
|
|
378
|
+
for (const id of [...entries.keys()]) if (!isAlive(id)) {
|
|
379
|
+
entries.delete(id);
|
|
380
|
+
removed += 1;
|
|
381
|
+
}
|
|
382
|
+
return removed;
|
|
383
|
+
}
|
|
352
384
|
/**
|
|
353
385
|
* Drop mutating ops whose target was not read this session, in place.
|
|
354
386
|
* Create is exempt (no read required to author a new skill). Covers the same
|
|
@@ -418,4 +450,4 @@ function buildReviewRequest(session, kind, signal, maxMessages, maxMessageChars)
|
|
|
418
450
|
].join("\n");
|
|
419
451
|
}
|
|
420
452
|
//#endregion
|
|
421
|
-
export { Config, apply, collectReadSkillNames, filterUnreadSkillOps, inject, name, shouldCompletionReview };
|
|
453
|
+
export { COUNTER_SWEEP_THRESHOLD, Config, apply, collectReadSkillNames, filterUnreadSkillOps, inject, name, shouldCompletionReview, sweepDeadSessionEntries };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -38,6 +38,16 @@ export declare function shouldCompletionReview(reason: {
|
|
|
38
38
|
} | undefined, sessionToolCalls: number, minToolCalls: number): boolean;
|
|
39
39
|
/** Skill names this session loaded (read-before-write source for the background review). */
|
|
40
40
|
export declare function collectReadSkillNames(session: Session): Set<string>;
|
|
41
|
+
/** Map/set size that triggers a dead-session counter sweep (bounded, not a hard cap). */
|
|
42
|
+
export declare const COUNTER_SWEEP_THRESHOLD = 128;
|
|
43
|
+
/**
|
|
44
|
+
* Remove every entry whose session is no longer live (rc.42 audit P1-10):
|
|
45
|
+
* `turnStarts` / `cumulativeToolCalls` / `completionInjected` are keyed by
|
|
46
|
+
* SessionId with no platform session-end hook to prune against, so they grew
|
|
47
|
+
* unbounded over a long-lived host. Works for maps and sets; returns the
|
|
48
|
+
* number of removed entries.
|
|
49
|
+
*/
|
|
50
|
+
export declare function sweepDeadSessionEntries<K>(entries: Map<K, unknown> | Set<K>, isAlive: (id: K) => boolean): number;
|
|
41
51
|
/**
|
|
42
52
|
* Drop mutating ops whose target was not read this session, in place.
|
|
43
53
|
* Create is exempt (no read required to author a new skill). Covers the same
|
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.1.0-rc.
|
|
4
|
+
"version": "0.1.0-rc.43",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
36
|
-
"@lmzhen/dsh-evolution-core": "^0.1.0-rc.
|
|
37
|
-
"@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.
|
|
36
|
+
"@lmzhen/dsh-evolution-core": "^0.1.0-rc.43",
|
|
37
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.43"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
44
44
|
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
45
45
|
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
46
|
-
"@lmzhen/dsh-evolution-state": "^0.1.0-rc.
|
|
46
|
+
"@lmzhen/dsh-evolution-state": "^0.1.0-rc.43"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
|
|
@@ -51,9 +51,11 @@
|
|
|
51
51
|
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
|
|
52
52
|
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
53
53
|
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
54
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6",
|
|
55
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.0-rc.6",
|
|
54
56
|
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
55
|
-
"@lmzhen/dsh-evolution-core": "^0.1.0-rc.
|
|
56
|
-
"@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.
|
|
57
|
-
"@lmzhen/dsh-evolution-state": "^0.1.0-rc.
|
|
57
|
+
"@lmzhen/dsh-evolution-core": "^0.1.0-rc.43",
|
|
58
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.43",
|
|
59
|
+
"@lmzhen/dsh-evolution-state": "^0.1.0-rc.43"
|
|
58
60
|
}
|
|
59
61
|
}
|