@lmzhen/dsh-evolution-review 0.1.0-rc.3 → 0.1.0-rc.31

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/README.md CHANGED
@@ -21,4 +21,10 @@ Independent of request-prefix construction. This package does not alter the asse
21
21
  ## Known Limitations and Deferred Work
22
22
 
23
23
 
24
- - - Review subagents inherit the host preset; Anchored Standard deployments rely on the default `skill_search`/`skill_load` allow-list.
24
+ - Review subagents inherit the host preset; Anchored Standard deployments rely on the default `skill_search`/`skill_load` allow-list.
25
+ - Review subagents run as `spawn` children on the deployment default preset rather than inheriting the parent agent's composition (`fork`): a fork child is always promoted by the Anchored Standard bootstrap and its narrowed resident catalog would drop the plain `skill` tool from the review allow-list.
26
+ - The review request text is redacted for credential-shaped patterns before it reaches the subagent, but redaction is pattern-based and best-effort, not a security boundary.
27
+
28
+ ## Configuration
29
+
30
+ `reviewProvider` selects the LLM provider for review subagents. When omitted, the subagent inherits the deployment default route instead of a hardcoded provider name. Model selection stays on the policy (`memoryReviewModel` / `skillReviewModel`).
package/lib/index.js CHANGED
@@ -1,8 +1,37 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import z from "@deepseek-ai/schemastery";
3
- import { CallId, createUserMessage } from "@deepseek-ai/dsh-llm";
4
- import { PROMPT_BUNDLE, advanceReview, foldTurn, reviewPrompt, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
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_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_USER_CHAR_LIMIT, PROMPT_BUNDLE, SkillLibrary, advanceReview, evolutionIoAdapter, foldTurn, reviewPrompt, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
5
5
  import { validateEvolutionPlan } from "@lmzhen/dsh-evolution-plan-validator";
6
+ //#region lib/types/redact.js
7
+ /**
8
+ * Review-input redaction. Review/curator subagents are the one place where a
9
+ * cross-session conversation snapshot leaves the owning session's context, so
10
+ * credential-shaped text is masked before it is sent. Redaction is best-effort
11
+ * and conservative: it targets well-known secret shapes and inline
12
+ * assignment patterns, never wholesale content.
13
+ */
14
+ const SECRET_PATTERNS = [
15
+ ["openai-style key", /sk-[A-Za-z0-9_-]{16,}/g],
16
+ ["aws access key", /AKIA[0-9A-Z]{16}/g],
17
+ ["github token", /gh[pousr]_[A-Za-z0-9]{20,}/g],
18
+ ["gitlab token", /glpat-[A-Za-z0-9_-]{16,}/g],
19
+ ["slack token", /xox[baprs]-[A-Za-z0-9-]{10,}/g],
20
+ ["jwt", /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g],
21
+ ["bearer credential", /Bearer [A-Za-z0-9._~+/=\-]{16,}/g],
22
+ ["inline assignment", /(\b(?:token|api[_-]?key|secret|password|passwd)\b[\s]*[:=][\s]*[\"\x27]?)([A-Z0-9._~+/=\-]{12,})/gi]
23
+ ];
24
+ /**
25
+ * Mask credential-shaped text in a review request.
26
+ * @param text - the assembled review request text.
27
+ * @returns the text with matched secrets replaced by `<redacted>`.
28
+ */
29
+ function redactReviewSecrets(text) {
30
+ let out = text;
31
+ for (const [, pattern] of SECRET_PATTERNS) out = out.replace(pattern, (_match, p1) => p1 === void 0 ? "<redacted>" : `${p1}<redacted>`);
32
+ return out;
33
+ }
34
+ //#endregion
6
35
  //#region lib/types/index.js
7
36
  /**
8
37
  * Background review orchestration: signal gate → one-shot subagent → trusted plan execution.
@@ -13,23 +42,24 @@ const inject = ["agents", "tools"];
13
42
  const Config = z.object({
14
43
  reviewEnabled: z.boolean().default(true),
15
44
  reviewMode: z.string().default("subagent"),
16
- memoryInterval: z.number().default(10),
17
- skillInterval: z.number().default(10),
18
- reviewToolAllow: z.array(z.string()).default([
19
- "skill",
20
- "skill_search",
21
- "skill_load"
22
- ]),
45
+ memoryInterval: z.number().default(DEFAULT_REVIEW_MEMORY_INTERVAL),
46
+ skillInterval: z.number().default(DEFAULT_REVIEW_SKILL_INTERVAL),
47
+ reviewToolAllow: z.array(z.string()).default(["skill"]),
23
48
  reviewTimeoutMs: z.number().default(12e4),
24
49
  executionTimeoutMs: z.number().default(3e4),
25
50
  reviewContextMessages: z.number().default(60),
26
51
  reviewMessageChars: z.number().default(2e3),
27
- reviewMaxDepth: z.number().default(0)
52
+ reviewMaxDepth: z.number().default(0),
53
+ reviewProvider: z.string(),
54
+ skillReviewTrigger: z.string().default(DEFAULT_SKILL_REVIEW_TRIGGER),
55
+ skillReviewCompletionMinToolCalls: z.number().default(DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS)
28
56
  });
29
57
  function apply(ctx, rawConfig) {
30
58
  if (!verifyPromptBundle(PROMPT_BUNDLE)) throw new Error("dsh-evolution prompt bundle integrity check failed; refusing to schedule review work");
31
59
  const config = rawConfig;
32
60
  const turnStarts = /* @__PURE__ */ new Map();
61
+ const cumulativeToolCalls = /* @__PURE__ */ new Map();
62
+ const completionInjected = /* @__PURE__ */ new Set();
33
63
  const policy = () => ctx.get("evolutionPolicy")?.get();
34
64
  ctx.on("session/event", (session, event) => {
35
65
  if (event.type === "turn/start") turnStarts.set(session.id, session.seq - 1);
@@ -58,17 +88,50 @@ function apply(ctx, rawConfig) {
58
88
  substantiveMinAgentChars: snapshot?.substantiveMinAgentChars ?? 500
59
89
  });
60
90
  await stateService?.saveReviewState(session.id, state);
61
- if (!kind) return;
62
- if (!await trySubagentReview(session, agent, kind, signal)) agent.inject(createUserMessage({
91
+ const cumulative = (cumulativeToolCalls.get(session.id) ?? 0) + signal.toolCalls;
92
+ cumulativeToolCalls.set(session.id, cumulative);
93
+ if (kind) {
94
+ session.append("evolution/review-scheduled", {
95
+ kind,
96
+ toolCalls: signal.toolCalls,
97
+ userChars: signal.userChars,
98
+ assistantChars: signal.assistantChars
99
+ });
100
+ if (!await trySubagentReview(session, agent, kind, signal)) agent.inject(createUserMessage({
101
+ content: [{
102
+ type: "text",
103
+ text: reviewPrompt(kind)
104
+ }],
105
+ source: {
106
+ kind: "plugin",
107
+ plugin: "dsh-evolution-review",
108
+ form: "notice",
109
+ summary: "auto-review"
110
+ }
111
+ }));
112
+ return;
113
+ }
114
+ const trigger = config.skillReviewTrigger;
115
+ if (trigger !== "completion" && trigger !== "both") return;
116
+ if (completionInjected.has(session.id)) return;
117
+ if (!shouldCompletionReview(event.data.reason, cumulative, config.skillReviewCompletionMinToolCalls)) return;
118
+ completionInjected.add(session.id);
119
+ session.append("evolution/review-scheduled", {
120
+ kind: "skill",
121
+ toolCalls: signal.toolCalls,
122
+ userChars: signal.userChars,
123
+ assistantChars: signal.assistantChars
124
+ });
125
+ agent.inject(createUserMessage({
63
126
  content: [{
64
127
  type: "text",
65
- text: reviewPrompt(kind)
128
+ text: COMPLETION_SKILL_REVIEW_PROMPT
66
129
  }],
67
130
  source: {
68
131
  kind: "plugin",
69
132
  plugin: "dsh-evolution-review",
70
133
  form: "notice",
71
- summary: "auto-review"
134
+ summary: "completion review"
72
135
  }
73
136
  }));
74
137
  }
@@ -79,7 +142,9 @@ function apply(ctx, rawConfig) {
79
142
  try {
80
143
  const routingPolicy = ctx.get("evolutionPolicy");
81
144
  const model = kind === "memory" ? routingPolicy?.get().memoryReviewModel ?? "deepseek-v4-flash" : routingPolicy?.get().skillReviewModel ?? "deepseek-v4-pro";
82
- const reviewText = buildReviewRequest(session, kind, signal, config.reviewContextMessages, config.reviewMessageChars);
145
+ const reviewText = redactReviewSecrets(buildReviewRequest(session, kind, signal, config.reviewContextMessages, config.reviewMessageChars));
146
+ const agentOptions = { model };
147
+ if (config.reviewProvider) agentOptions.provider = config.reviewProvider;
83
148
  const run = await subagents.start("spawn", {
84
149
  label: "dsh-evolution-review",
85
150
  prompt: [{
@@ -89,10 +154,7 @@ function apply(ctx, rawConfig) {
89
154
  parent: agent,
90
155
  signal: AbortSignal.timeout(config.reviewTimeoutMs),
91
156
  maxDepth: config.reviewMaxDepth,
92
- agentOptions: {
93
- provider: "deepseek-official",
94
- model
95
- },
157
+ agentOptions,
96
158
  persona: reviewPrompt(kind),
97
159
  toolFilter: { allow: [...config.reviewToolAllow] },
98
160
  outputSchema: {
@@ -119,20 +181,23 @@ function apply(ctx, rawConfig) {
119
181
  const policyFingerprint = fingerprintPolicy(snapshot);
120
182
  const validation = validateEvolutionPlan(plan, {
121
183
  sessionSeq: session.seq - 1,
122
- maxOpsPerPlan: snapshot?.maxOpsPerPlan ?? 32,
184
+ maxOpsPerPlan: snapshot?.maxOpsPerPlan ?? DEFAULT_MAX_OPS_PER_PLAN,
123
185
  protectedSkillNames: new Set(snapshot?.protectedSkillNames ?? []),
124
- maxMemoryChars: snapshot?.memoryChars ?? 2200,
125
- maxUserChars: snapshot?.userChars ?? 1375,
126
- maxSkillContentChars: snapshot?.skillContentChars ?? 1e5
186
+ maxMemoryChars: snapshot?.memoryChars ?? DEFAULT_MEMORY_CHAR_LIMIT,
187
+ maxUserChars: snapshot?.userChars ?? DEFAULT_USER_CHAR_LIMIT,
188
+ maxSkillContentChars: snapshot?.skillContentChars ?? DEFAULT_SKILL_CONTENT_CHARS
127
189
  });
128
- const actions = await executePlan(validation.accepted, agent);
129
- const evidenceQuotes = [...validation.accepted.memoryOps ?? [], ...validation.accepted.skillOps ?? []].reduce((total, op) => total + (Array.isArray(op.evidence) ? op.evidence.length : 0), 0);
190
+ const acceptedSkillOps = validation.accepted.skillOps ?? [];
191
+ const skippedUnread = filterUnreadSkillOps(acceptedSkillOps, collectReadSkillNames(session));
192
+ validation.accepted.skillOps = acceptedSkillOps;
193
+ const actions = await executePlan(validation.accepted);
194
+ const evidenceQuotes = [...validation.accepted.memoryOps ?? [], ...acceptedSkillOps].reduce((total, op) => total + (Array.isArray(op.evidence) ? op.evidence.length : 0), 0);
130
195
  session.append("evolution/plan-applied", {
131
196
  planId: randomUUID(),
132
197
  policyFingerprint,
133
198
  memoryApplied: actions.filter((action) => action.startsWith("Memory")).length,
134
199
  skillApplied: actions.filter((action) => action.startsWith("Skill ")).length,
135
- rejectedOps: validation.rejected.length,
200
+ rejectedOps: validation.rejected.length + skippedUnread,
136
201
  evidenceQuotes,
137
202
  estimatedInputChars: reviewText.length
138
203
  });
@@ -149,11 +214,12 @@ function apply(ctx, rawConfig) {
149
214
  }
150
215
  }));
151
216
  return true;
152
- } catch {
217
+ } catch (error) {
218
+ ctx.logger.warn(`dsh-evolution-review: subagent review failed: ${error instanceof Error ? error.message : String(error)}`);
153
219
  return false;
154
220
  }
155
221
  }
156
- async function executePlan(plan, parent) {
222
+ async function executePlan(plan) {
157
223
  const memory = ctx.get("memory");
158
224
  const approval = ctx.get("evolutionApproval");
159
225
  const actions = [];
@@ -173,10 +239,11 @@ function apply(ctx, rawConfig) {
173
239
  ...op,
174
240
  evidence: op.evidence
175
241
  };
176
- if ((approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, {
242
+ const runnerArgs = {
177
243
  operation: args,
178
244
  origin: "background_review"
179
- }, args) : await executeSkillTool(parent, args))?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
245
+ };
246
+ if ((approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, runnerArgs, runnerArgs) : await executeSkillDirect(args))?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
180
247
  }
181
248
  return actions;
182
249
  async function runApproved(kind, summary, stored, runnerArgs) {
@@ -193,26 +260,92 @@ function apply(ctx, rawConfig) {
193
260
  };
194
261
  return await approval.run(kind, runnerArgs);
195
262
  }
196
- async function executeSkillTool(agent, args) {
197
- return (await ctx.tools.execute({
198
- callId: CallId(`evolution-${randomUUID()}`),
199
- name: "skill_manage",
200
- arguments: args,
201
- agent,
202
- signal: AbortSignal.timeout(config.executionTimeoutMs)
203
- })).isError ? {
263
+ /**
264
+ * Approval-disabled path: execute the skill op through SkillLibrary with an
265
+ * EXPLICIT background_review origin. Going through ctx.tools.execute would
266
+ * make tool-skill-manage infer origin from the parent agent's header
267
+ * (not 'subagent'), silently escaping the .hermes-managed marker and the
268
+ * pinned write guard.
269
+ */
270
+ async function executeSkillDirect(skillArgs) {
271
+ const io = ctx.get("evolutionIo");
272
+ if (!io) return {
204
273
  ok: false,
205
- message: "skill_manage execution failed"
206
- } : {
207
- ok: true,
208
- message: "skill_manage executed"
274
+ message: "evolution-io service not mounted"
275
+ };
276
+ const library = new SkillLibrary(void 0, evolutionIoAdapter(() => io.provider()));
277
+ const op = skillArgs;
278
+ const name = op.name ?? "";
279
+ const origin = "background_review";
280
+ if (op.action === "create") return await library.create(name, op.content ?? "", origin);
281
+ if (op.action === "edit" || op.action === "update") return await library.update(name, op.content ?? "", origin);
282
+ if (op.action === "patch") return await library.patch(name, op.old_string ?? "", op.new_string ?? "", op.file_path ?? "", false, origin);
283
+ if (op.action === "delete") return await library.archive(name, op.absorbed_into ? { absorbedInto: op.absorbed_into } : {});
284
+ if (op.action === "write_file") return await library.writeSupportFile(name, op.file_path ?? "", op.file_content ?? op.content ?? "", origin);
285
+ if (op.action === "remove_file") return await library.removeSupportFile(name, op.file_path ?? "", origin);
286
+ return {
287
+ ok: false,
288
+ message: `Unknown skill action "${op.action ?? ""}"`
209
289
  };
210
290
  }
211
291
  }
212
292
  ctx.effect(() => () => {
213
293
  turnStarts.clear();
294
+ cumulativeToolCalls.clear();
295
+ completionInjected.clear();
214
296
  }, "dsh-evolution-review.cleanup");
215
297
  }
298
+ /** Completion-channel decision: task finished normally AND the session is proven long. */
299
+ function shouldCompletionReview(reason, sessionToolCalls, minToolCalls) {
300
+ return reason?.kind === "completed" && sessionToolCalls >= minToolCalls;
301
+ }
302
+ /** Skill names this session loaded (read-before-write source for the background review). */
303
+ function collectReadSkillNames(session) {
304
+ const names = /* @__PURE__ */ new Set();
305
+ for (const event of session.events) {
306
+ if (event.type !== "tool/call") continue;
307
+ if (event.data.name !== "skill" && event.data.name !== "skill_load") continue;
308
+ const raw = event.data.arguments;
309
+ let parsed = {};
310
+ if (typeof raw === "string") try {
311
+ parsed = JSON.parse(raw);
312
+ } catch {
313
+ continue;
314
+ }
315
+ else parsed = raw ?? {};
316
+ const name = typeof parsed.name === "string" ? parsed.name : typeof parsed.skill === "string" ? parsed.skill : "";
317
+ if (name) names.add(name);
318
+ }
319
+ return names;
320
+ }
321
+ /**
322
+ * Drop mutating ops whose target was not read this session, in place.
323
+ * Create is exempt (no read required to author a new skill). Covers the same
324
+ * mutating surface Hermes guards (edit/patch/write_file/remove_file), so a
325
+ * background review cannot blind-touch support files or edits of skills it
326
+ * never loaded. Returns the count of dropped ops so the plan event can report
327
+ * them as rejected.
328
+ */
329
+ function filterUnreadSkillOps(ops, readNames) {
330
+ const READ_REQUIRED = [
331
+ "edit",
332
+ "update",
333
+ "patch",
334
+ "delete",
335
+ "write_file",
336
+ "remove_file"
337
+ ];
338
+ let dropped = 0;
339
+ for (let index = ops.length - 1; index >= 0; index -= 1) {
340
+ const op = ops[index];
341
+ if (!op) continue;
342
+ if (op.action !== void 0 && READ_REQUIRED.includes(op.action) && op.name && !readNames.has(op.name)) {
343
+ ops.splice(index, 1);
344
+ dropped += 1;
345
+ }
346
+ }
347
+ return dropped;
348
+ }
216
349
  function fingerprintPolicy(snapshot) {
217
350
  try {
218
351
  return createHash("sha256").update(JSON.stringify(snapshot)).digest("hex").slice(0, 12);
@@ -236,4 +369,4 @@ function buildReviewRequest(session, kind, signal, maxMessages, maxMessageChars)
236
369
  ].join("\n");
237
370
  }
238
371
  //#endregion
239
- export { Config, apply, inject, name };
372
+ export { Config, apply, collectReadSkillNames, filterUnreadSkillOps, inject, name, shouldCompletionReview };
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import type { Context } from '@deepseek-ai/cordis';
6
6
  import z from '@deepseek-ai/schemastery';
7
+ import type { Session } from '@deepseek-ai/dsh-session';
7
8
  export declare const name = "evolution-review";
8
9
  export declare const inject: string[];
9
10
  export interface Config {
@@ -11,14 +12,42 @@ export interface Config {
11
12
  reviewMode?: string;
12
13
  memoryInterval?: number;
13
14
  skillInterval?: number;
14
- /** Tools the one-shot review subagent may use. Defaults include the Anchored Standard discovery pair. */
15
+ /**
16
+ * Tools the one-shot review subagent may use. Only actually-existing tools
17
+ * may be listed (the DSH tool catalog has `skill`; the `skill_search` /
18
+ * `skill_load` discovery pair does not exist on this platform).
19
+ */
15
20
  reviewToolAllow?: string[];
16
21
  reviewTimeoutMs?: number;
17
22
  executionTimeoutMs?: number;
18
23
  reviewContextMessages?: number;
19
24
  reviewMessageChars?: number;
20
25
  reviewMaxDepth?: number;
26
+ /** LLM provider for review subagents. Omit to inherit the deployment default route. */
27
+ reviewProvider?: string;
28
+ /** Skill-review trigger: cadence (interval) | completion (once after a proven-long task) | both. */
29
+ skillReviewTrigger?: string;
30
+ /** Cumulative session tool calls before a session counts as proven-long for the completion channel. */
31
+ skillReviewCompletionMinToolCalls?: number;
21
32
  }
22
33
  export declare const Config: z<Config>;
23
34
  export declare function apply(ctx: Context, rawConfig: Config): void;
35
+ /** Completion-channel decision: task finished normally AND the session is proven long. */
36
+ export declare function shouldCompletionReview(reason: {
37
+ kind?: string;
38
+ } | undefined, sessionToolCalls: number, minToolCalls: number): boolean;
39
+ /** Skill names this session loaded (read-before-write source for the background review). */
40
+ export declare function collectReadSkillNames(session: Session): Set<string>;
41
+ /**
42
+ * Drop mutating ops whose target was not read this session, in place.
43
+ * Create is exempt (no read required to author a new skill). Covers the same
44
+ * mutating surface Hermes guards (edit/patch/write_file/remove_file), so a
45
+ * background review cannot blind-touch support files or edits of skills it
46
+ * never loaded. Returns the count of dropped ops so the plan event can report
47
+ * them as rejected.
48
+ */
49
+ export declare function filterUnreadSkillOps(ops: Array<{
50
+ action?: string;
51
+ name?: string;
52
+ }>, readNames: ReadonlySet<string>): number;
24
53
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Review-input redaction. Review/curator subagents are the one place where a
3
+ * cross-session conversation snapshot leaves the owning session's context, so
4
+ * credential-shaped text is masked before it is sent. Redaction is best-effort
5
+ * and conservative: it targets well-known secret shapes and inline
6
+ * assignment patterns, never wholesale content.
7
+ */
8
+ /**
9
+ * Mask credential-shaped text in a review request.
10
+ * @param text - the assembled review request text.
11
+ * @returns the text with matched secrets replaced by `<redacted>`.
12
+ */
13
+ export declare function redactReviewSecrets(text: string): string;
14
+ //# sourceMappingURL=redact.d.ts.map
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.3",
4
+ "version": "0.1.0-rc.31",
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.3",
37
- "@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.3"
36
+ "@lmzhen/dsh-evolution-core": "^0.1.0-rc.31",
37
+ "@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.31"
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.3"
46
+ "@lmzhen/dsh-evolution-state": "^0.1.0-rc.31"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
@@ -52,8 +52,8 @@
52
52
  "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
53
53
  "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
54
54
  "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
55
- "@lmzhen/dsh-evolution-core": "^0.1.0-rc.3",
56
- "@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.3",
57
- "@lmzhen/dsh-evolution-state": "^0.1.0-rc.3"
55
+ "@lmzhen/dsh-evolution-core": "^0.1.0-rc.31",
56
+ "@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.31",
57
+ "@lmzhen/dsh-evolution-state": "^0.1.0-rc.31"
58
58
  }
59
59
  }