@lmzhen/dsh-evolution-review 0.3.41 → 0.3.42

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.
Files changed (2) hide show
  1. package/lib/index.js +38 -47
  2. package/package.json +10 -10
package/lib/index.js CHANGED
@@ -66,12 +66,13 @@ function apply(ctx, rawConfig) {
66
66
  const pendingCadenceReviews = /* @__PURE__ */ new Map();
67
67
  const pendingCadenceWarned = /* @__PURE__ */ new Set();
68
68
  const skipNextCadenceFire = /* @__PURE__ */ new Map();
69
+ const cadenceResetWarned = /* @__PURE__ */ new Set();
69
70
  let reviewInFlight = false;
70
71
  const policy = () => ctx.get("evolutionPolicy")?.get();
71
72
  ctx.on("session/event", (session, event) => {
72
73
  if (event.type === "turn/start") turnStarts.set(session.id, session.seq - 1);
73
74
  if (event.type !== "turn/end") return;
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) {
75
+ 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) {
75
76
  const isAlive = (id) => ctx.agents.get(id) !== void 0;
76
77
  sweepDeadSessionEntries(turnStarts, isAlive);
77
78
  sweepDeadSessionEntries(cumulativeToolCalls, isAlive);
@@ -79,6 +80,7 @@ function apply(ctx, rawConfig) {
79
80
  sweepDeadSessionEntries(pendingCadenceReviews, isAlive);
80
81
  sweepDeadSessionEntries(pendingCadenceWarned, isAlive);
81
82
  sweepDeadSessionEntries(skipNextCadenceFire, isAlive);
83
+ sweepDeadSessionEntries(cadenceResetWarned, isAlive);
82
84
  }
83
85
  onTurnEnd(session, event);
84
86
  });
@@ -126,31 +128,12 @@ function apply(ctx, rawConfig) {
126
128
  await stateService?.saveReviewState(session.id, state);
127
129
  const cumulative = (cumulativeToolCalls.get(session.id) ?? 0) + signal.toolCalls;
128
130
  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
- };
148
131
  if (event.data.reason.kind === "completed") {
149
132
  const pendingKind = pendingCadenceReviews.get(session.id) ?? kind ?? void 0;
150
133
  if (pendingKind !== void 0) {
151
134
  pendingCadenceReviews.delete(session.id);
152
135
  if ((policy()?.reviewMode ?? config.reviewMode) === "inject") try {
153
- deliverReview(reviewPrompt(pendingKind));
136
+ deliverMessage(agent, reviewPrompt(pendingKind), "auto-review");
154
137
  } catch (injectError) {
155
138
  ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
156
139
  }
@@ -162,13 +145,20 @@ function apply(ctx, rawConfig) {
162
145
  assistantChars: signal.assistantChars
163
146
  });
164
147
  else try {
165
- deliverReview(reviewPrompt(pendingKind));
148
+ deliverMessage(agent, reviewPrompt(pendingKind), "auto-review");
166
149
  } catch (injectError) {
167
150
  ctx.logger.warn(`dsh-evolution-review: deferred review inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
168
151
  }
169
152
  state.turnsSinceMemory = 0;
170
153
  state.turnsSinceSkill = 0;
171
- await stateService?.saveReviewState(session.id, state);
154
+ try {
155
+ await stateService?.saveReviewState(session.id, state);
156
+ } catch (resetError) {
157
+ if (!cadenceResetWarned.has(session.id)) {
158
+ cadenceResetWarned.add(session.id);
159
+ ctx.logger.warn(`dsh-evolution-review: cadence counter reset could not be persisted after a delivered review (${resetError instanceof Error ? resetError.message : String(resetError)}) — a stateful reload may re-deliver this review`);
160
+ }
161
+ }
172
162
  }
173
163
  }
174
164
  if (kind && event.data.reason.kind !== "completed") {
@@ -210,6 +200,29 @@ function apply(ctx, rawConfig) {
210
200
  assistantChars: signal.assistantChars
211
201
  });
212
202
  }
203
+ /** V7-03 (0.3.42): shared waking delivery — review prompts AND result
204
+ * notices go through the same followup-first channel (skip the woken turn's
205
+ * cadence fire once, degrade to inject when reviewWakeInject is off or the
206
+ * host lacks followup). */
207
+ const deliverMessage = (agent, text, summary) => {
208
+ const message = createUserMessage({
209
+ content: [{
210
+ type: "text",
211
+ text
212
+ }],
213
+ source: {
214
+ kind: "plugin",
215
+ plugin: "dsh-evolution-review",
216
+ form: "notice",
217
+ summary
218
+ }
219
+ });
220
+ const followup = agent.followup;
221
+ if (config.reviewWakeInject && typeof followup === "function") {
222
+ followup(message);
223
+ skipNextCadenceFire.set(agent.session.id, true);
224
+ } else agent.inject(message);
225
+ };
213
226
  async function trySubagentReview(session, agent, kind, signal) {
214
227
  if ((policy()?.reviewMode ?? config.reviewMode) === "inject") return false;
215
228
  const subagents = ctx.get("subagents");
@@ -281,18 +294,7 @@ function apply(ctx, rawConfig) {
281
294
  const applied = actions.join(" · ");
282
295
  const note = executed.ok ? "" : "\n部分操作失败。以下操作已应用,请勿重复执行。";
283
296
  try {
284
- agent.inject(createUserMessage({
285
- content: [{
286
- type: "text",
287
- text: `💾 Self-improvement review: ${applied}${note}`
288
- }],
289
- source: {
290
- kind: "plugin",
291
- plugin: "dsh-evolution-review",
292
- form: "notice",
293
- summary: "self-improvement review"
294
- }
295
- }));
297
+ deliverMessage(agent, `💾 Self-improvement review: ${applied}${note}`, "self-improvement review");
296
298
  } catch (injectError) {
297
299
  ctx.logger.warn(`dsh-evolution-review: result notice inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
298
300
  }
@@ -305,18 +307,7 @@ function apply(ctx, rawConfig) {
305
307
  if (reasons.length === 0) reasons.push("the review plan contained nothing executable");
306
308
  let text = `💾 Self-improvement review: 0 ops landed. ${reasons.join(" ")}`;
307
309
  if (text.length > 500) text = `${text.slice(0, 497)}…`;
308
- agent.inject(createUserMessage({
309
- content: [{
310
- type: "text",
311
- text
312
- }],
313
- source: {
314
- kind: "plugin",
315
- plugin: "dsh-evolution-review",
316
- form: "notice",
317
- summary: "self-improvement review"
318
- }
319
- }));
310
+ deliverMessage(agent, text, "self-improvement review");
320
311
  } catch (injectError) {
321
312
  ctx.logger.warn(`dsh-evolution-review: zero-landing notice inject failed: ${injectError instanceof Error ? injectError.message : String(injectError)}`);
322
313
  }
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.41",
4
+ "version": "0.3.42",
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.41",
35
- "@lmzhen/dsh-evolution-core": "^0.3.41",
36
- "@lmzhen/dsh-evolution-plan-validator": "^0.3.41"
34
+ "@lmzhen/dsh-evolution-approval": "^0.3.42",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.42",
36
+ "@lmzhen/dsh-evolution-plan-validator": "^0.3.42"
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.41",
46
- "@lmzhen/dsh-evolution-policy": "^0.3.41"
45
+ "@lmzhen/dsh-evolution-state": "^0.3.42",
46
+ "@lmzhen/dsh-evolution-policy": "^0.3.42"
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.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"
57
+ "@lmzhen/dsh-evolution-approval": "^0.3.42",
58
+ "@lmzhen/dsh-evolution-core": "^0.3.42",
59
+ "@lmzhen/dsh-evolution-plan-validator": "^0.3.42",
60
+ "@lmzhen/dsh-evolution-state": "^0.3.42"
61
61
  }
62
62
  }