@lmzhen/dsh-evolution-review 0.1.0-rc.1
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 +24 -0
- package/lib/index.js +239 -0
- package/lib/invariant.js +8 -0
- package/lib/types/index.d.ts +24 -0
- package/lib/types/invariant.d.ts +5 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @deepseek-ai/dsh-evolution-review
|
|
2
|
+
|
|
3
|
+
Background review orchestration
|
|
4
|
+
|
|
5
|
+
## Model Experience
|
|
6
|
+
|
|
7
|
+
### Indirect model surface
|
|
8
|
+
|
|
9
|
+
#### What the model sees
|
|
10
|
+
|
|
11
|
+
`@deepseek-ai/dsh-evolution-review` registers no direct prompt or tool schema itself. Model-visible effects are owned by the packages that consume this service.
|
|
12
|
+
|
|
13
|
+
#### Token effect
|
|
14
|
+
|
|
15
|
+
Zero direct token effect from this package; consumers add any model-visible tokens.
|
|
16
|
+
|
|
17
|
+
#### KV Cache effect
|
|
18
|
+
|
|
19
|
+
Independent of request-prefix construction. This package does not alter the assembled prompt or tool list.
|
|
20
|
+
|
|
21
|
+
## Known Limitations and Deferred Work
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
- - Review subagents inherit the host preset; Anchored Standard deployments rely on the default `skill_search`/`skill_load` allow-list.
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
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";
|
|
5
|
+
import { validateEvolutionPlan } from "@lmzhen/dsh-evolution-plan-validator";
|
|
6
|
+
//#region lib/types/index.js
|
|
7
|
+
/**
|
|
8
|
+
* Background review orchestration: signal gate → one-shot subagent → trusted plan execution.
|
|
9
|
+
* @module @lmzhen/dsh-evolution-review
|
|
10
|
+
*/
|
|
11
|
+
const name = "evolution-review";
|
|
12
|
+
const inject = ["agents", "tools"];
|
|
13
|
+
const Config = z.object({
|
|
14
|
+
reviewEnabled: z.boolean().default(true),
|
|
15
|
+
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
|
+
]),
|
|
23
|
+
reviewTimeoutMs: z.number().default(12e4),
|
|
24
|
+
executionTimeoutMs: z.number().default(3e4),
|
|
25
|
+
reviewContextMessages: z.number().default(60),
|
|
26
|
+
reviewMessageChars: z.number().default(2e3),
|
|
27
|
+
reviewMaxDepth: z.number().default(0)
|
|
28
|
+
});
|
|
29
|
+
function apply(ctx, rawConfig) {
|
|
30
|
+
if (!verifyPromptBundle(PROMPT_BUNDLE)) throw new Error("dsh-evolution prompt bundle integrity check failed; refusing to schedule review work");
|
|
31
|
+
const config = rawConfig;
|
|
32
|
+
const turnStarts = /* @__PURE__ */ new Map();
|
|
33
|
+
const policy = () => ctx.get("evolutionPolicy")?.get();
|
|
34
|
+
ctx.on("session/event", (session, event) => {
|
|
35
|
+
if (event.type === "turn/start") turnStarts.set(session.id, session.seq - 1);
|
|
36
|
+
if (event.type !== "turn/end") return;
|
|
37
|
+
onTurnEnd(session, event);
|
|
38
|
+
});
|
|
39
|
+
async function onTurnEnd(session, event) {
|
|
40
|
+
if (!config.reviewEnabled) return;
|
|
41
|
+
if (session.header.origin === "subagent") return;
|
|
42
|
+
const agent = ctx.agents.get(session.id);
|
|
43
|
+
if (!agent) return;
|
|
44
|
+
const signal = foldTurn(session, turnStarts.get(session.id) ?? Math.max(0, session.seq - 1));
|
|
45
|
+
turnStarts.delete(session.id);
|
|
46
|
+
const stateService = ctx.get("evolutionState");
|
|
47
|
+
const state = await stateService?.loadReviewState(session.id) ?? {
|
|
48
|
+
turnsSinceMemory: 0,
|
|
49
|
+
turnsSinceSkill: 0,
|
|
50
|
+
lastTurn: -1
|
|
51
|
+
};
|
|
52
|
+
const snapshot = policy();
|
|
53
|
+
const kind = advanceReview(state, event.data.turn, signal, {
|
|
54
|
+
memoryInterval: snapshot?.reviewMemoryInterval ?? config.memoryInterval,
|
|
55
|
+
skillInterval: snapshot?.reviewSkillInterval ?? config.skillInterval,
|
|
56
|
+
substantiveMinToolCalls: snapshot?.substantiveMinToolCalls ?? 3,
|
|
57
|
+
substantiveMinUserChars: snapshot?.substantiveMinUserChars ?? 200,
|
|
58
|
+
substantiveMinAgentChars: snapshot?.substantiveMinAgentChars ?? 500
|
|
59
|
+
});
|
|
60
|
+
await stateService?.saveReviewState(session.id, state);
|
|
61
|
+
if (!kind) return;
|
|
62
|
+
if (!await trySubagentReview(session, agent, kind, signal)) agent.inject(createUserMessage({
|
|
63
|
+
content: [{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: reviewPrompt(kind)
|
|
66
|
+
}],
|
|
67
|
+
source: {
|
|
68
|
+
kind: "plugin",
|
|
69
|
+
plugin: "dsh-evolution-review",
|
|
70
|
+
form: "notice",
|
|
71
|
+
summary: "auto-review"
|
|
72
|
+
}
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
async function trySubagentReview(session, agent, kind, signal) {
|
|
76
|
+
if ((policy()?.reviewMode ?? config.reviewMode) === "inject") return false;
|
|
77
|
+
const subagents = ctx.get("subagents");
|
|
78
|
+
if (!subagents) return false;
|
|
79
|
+
try {
|
|
80
|
+
const routingPolicy = ctx.get("evolutionPolicy");
|
|
81
|
+
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);
|
|
83
|
+
const run = await subagents.start("spawn", {
|
|
84
|
+
label: "dsh-evolution-review",
|
|
85
|
+
prompt: [{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: reviewText
|
|
88
|
+
}],
|
|
89
|
+
parent: agent,
|
|
90
|
+
signal: AbortSignal.timeout(config.reviewTimeoutMs),
|
|
91
|
+
maxDepth: config.reviewMaxDepth,
|
|
92
|
+
agentOptions: {
|
|
93
|
+
provider: "deepseek-official",
|
|
94
|
+
model
|
|
95
|
+
},
|
|
96
|
+
persona: reviewPrompt(kind),
|
|
97
|
+
toolFilter: { allow: [...config.reviewToolAllow] },
|
|
98
|
+
outputSchema: {
|
|
99
|
+
type: "object",
|
|
100
|
+
additionalProperties: false,
|
|
101
|
+
properties: {
|
|
102
|
+
memoryOps: {
|
|
103
|
+
type: "array",
|
|
104
|
+
items: { type: "json" }
|
|
105
|
+
},
|
|
106
|
+
skillOps: {
|
|
107
|
+
type: "array",
|
|
108
|
+
items: { type: "json" }
|
|
109
|
+
},
|
|
110
|
+
summary: { type: "string" }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
const result = await run.result;
|
|
115
|
+
await run.dispose();
|
|
116
|
+
if (!result.structured) return true;
|
|
117
|
+
const snapshot = policy();
|
|
118
|
+
const plan = result.structured;
|
|
119
|
+
const policyFingerprint = fingerprintPolicy(snapshot);
|
|
120
|
+
const validation = validateEvolutionPlan(plan, {
|
|
121
|
+
sessionSeq: session.seq - 1,
|
|
122
|
+
maxOpsPerPlan: snapshot?.maxOpsPerPlan ?? 32,
|
|
123
|
+
protectedSkillNames: new Set(snapshot?.protectedSkillNames ?? []),
|
|
124
|
+
maxMemoryChars: snapshot?.memoryChars ?? 2200,
|
|
125
|
+
maxUserChars: snapshot?.userChars ?? 1375,
|
|
126
|
+
maxSkillContentChars: snapshot?.skillContentChars ?? 1e5
|
|
127
|
+
});
|
|
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);
|
|
130
|
+
session.append("evolution/plan-applied", {
|
|
131
|
+
planId: randomUUID(),
|
|
132
|
+
policyFingerprint,
|
|
133
|
+
memoryApplied: actions.filter((action) => action.startsWith("Memory")).length,
|
|
134
|
+
skillApplied: actions.filter((action) => action.startsWith("Skill ")).length,
|
|
135
|
+
rejectedOps: validation.rejected.length,
|
|
136
|
+
evidenceQuotes,
|
|
137
|
+
estimatedInputChars: reviewText.length
|
|
138
|
+
});
|
|
139
|
+
if (actions.length > 0) agent.inject(createUserMessage({
|
|
140
|
+
content: [{
|
|
141
|
+
type: "text",
|
|
142
|
+
text: `💾 Self-improvement review: ${actions.join(" · ")}`
|
|
143
|
+
}],
|
|
144
|
+
source: {
|
|
145
|
+
kind: "plugin",
|
|
146
|
+
plugin: "dsh-evolution-review",
|
|
147
|
+
form: "notice",
|
|
148
|
+
summary: "self-improvement review"
|
|
149
|
+
}
|
|
150
|
+
}));
|
|
151
|
+
return true;
|
|
152
|
+
} catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async function executePlan(plan, parent) {
|
|
157
|
+
const memory = ctx.get("memory");
|
|
158
|
+
const approval = ctx.get("evolutionApproval");
|
|
159
|
+
const actions = [];
|
|
160
|
+
for (const op of plan.memoryOps ?? []) {
|
|
161
|
+
if (!Array.isArray(op.evidence) || op.evidence.length === 0) continue;
|
|
162
|
+
const normalized = {
|
|
163
|
+
target: op.target === "user" ? "user" : "memory",
|
|
164
|
+
action: op.action ?? "add",
|
|
165
|
+
facts: op.facts ?? op.content,
|
|
166
|
+
old_text: op.old_text
|
|
167
|
+
};
|
|
168
|
+
if ((approval ? await runApproved("memory", `memory ${normalized.target} ${normalized.action}`, normalized, normalized) : await memory?.applyBatch(normalized.target, [normalized]))?.ok) actions.push("Memory updated");
|
|
169
|
+
}
|
|
170
|
+
for (const op of plan.skillOps ?? []) {
|
|
171
|
+
if (!Array.isArray(op.evidence) || op.evidence.length === 0 || !op.name) continue;
|
|
172
|
+
const args = {
|
|
173
|
+
...op,
|
|
174
|
+
evidence: op.evidence
|
|
175
|
+
};
|
|
176
|
+
if ((approval ? await runApproved("skill", `skill ${op.action ?? "patch"} ${op.name}`, {
|
|
177
|
+
operation: args,
|
|
178
|
+
origin: "background_review"
|
|
179
|
+
}, args) : await executeSkillTool(parent, args))?.ok) actions.push(`Skill ${op.name} ${op.action ?? "patch"}`);
|
|
180
|
+
}
|
|
181
|
+
return actions;
|
|
182
|
+
async function runApproved(kind, summary, stored, runnerArgs) {
|
|
183
|
+
if (!approval) return void 0;
|
|
184
|
+
const decision = await approval.request({
|
|
185
|
+
kind,
|
|
186
|
+
summary,
|
|
187
|
+
args: stored,
|
|
188
|
+
origin: "background_review"
|
|
189
|
+
});
|
|
190
|
+
if (decision.action === "staged") return {
|
|
191
|
+
ok: false,
|
|
192
|
+
message: decision.message
|
|
193
|
+
};
|
|
194
|
+
return await approval.run(kind, runnerArgs);
|
|
195
|
+
}
|
|
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 ? {
|
|
204
|
+
ok: false,
|
|
205
|
+
message: "skill_manage execution failed"
|
|
206
|
+
} : {
|
|
207
|
+
ok: true,
|
|
208
|
+
message: "skill_manage executed"
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
ctx.effect(() => () => {
|
|
213
|
+
turnStarts.clear();
|
|
214
|
+
}, "dsh-evolution-review.cleanup");
|
|
215
|
+
}
|
|
216
|
+
function fingerprintPolicy(snapshot) {
|
|
217
|
+
try {
|
|
218
|
+
return createHash("sha256").update(JSON.stringify(snapshot)).digest("hex").slice(0, 12);
|
|
219
|
+
} catch {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function buildReviewRequest(session, kind, signal, maxMessages, maxMessageChars) {
|
|
224
|
+
const messages = [];
|
|
225
|
+
const surface = session.deriveMessages();
|
|
226
|
+
for (const message of surface.slice(-maxMessages)) if (message.role === "user" || message.role === "assistant") {
|
|
227
|
+
const text = message.content.map((block) => block.type === "text" ? block.text : "").join(" ").trim();
|
|
228
|
+
if (text) messages.push(`${message.role.toUpperCase()}: ${text.slice(0, maxMessageChars)}`);
|
|
229
|
+
}
|
|
230
|
+
return [
|
|
231
|
+
`Review kind: ${kind}`,
|
|
232
|
+
`Signals: ${signal.toolCalls} tool calls, ${signal.userChars} user chars, ${signal.assistantChars} assistant chars.`,
|
|
233
|
+
"Return ONLY the structured JSON plan. Evidence is mandatory for every op.",
|
|
234
|
+
"",
|
|
235
|
+
...messages
|
|
236
|
+
].join("\n");
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
export { Config, apply, inject, name };
|
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region lib/types/invariant.js
|
|
2
|
+
const PACKAGE_NAME = "@deepseek-ai/dsh-evolution-review";
|
|
3
|
+
const name = "evolution-review-invariant";
|
|
4
|
+
const inject = ["invariants"];
|
|
5
|
+
const install = () => {};
|
|
6
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
7
|
+
//#endregion
|
|
8
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background review orchestration: signal gate → one-shot subagent → trusted plan execution.
|
|
3
|
+
* @module @deepseek-ai/dsh-evolution-review
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
+
import z from '@deepseek-ai/schemastery';
|
|
7
|
+
export declare const name = "evolution-review";
|
|
8
|
+
export declare const inject: string[];
|
|
9
|
+
export interface Config {
|
|
10
|
+
reviewEnabled?: boolean;
|
|
11
|
+
reviewMode?: string;
|
|
12
|
+
memoryInterval?: number;
|
|
13
|
+
skillInterval?: number;
|
|
14
|
+
/** Tools the one-shot review subagent may use. Defaults include the Anchored Standard discovery pair. */
|
|
15
|
+
reviewToolAllow?: string[];
|
|
16
|
+
reviewTimeoutMs?: number;
|
|
17
|
+
executionTimeoutMs?: number;
|
|
18
|
+
reviewContextMessages?: number;
|
|
19
|
+
reviewMessageChars?: number;
|
|
20
|
+
reviewMaxDepth?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const Config: z<Config>;
|
|
23
|
+
export declare function apply(ctx: Context, rawConfig: Config): void;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lmzhen/dsh-evolution-review",
|
|
3
|
+
"description": "Background review orchestration (community build)",
|
|
4
|
+
"version": "0.1.0-rc.1",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/lmzhen/dsh-evolution.git",
|
|
11
|
+
"directory": "packages/dsh-evolution-review"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/types/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./invariant": {
|
|
22
|
+
"types": "./lib/types/invariant.d.ts",
|
|
23
|
+
"default": "./lib/invariant.js"
|
|
24
|
+
},
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"lib/index.js",
|
|
29
|
+
"lib/invariant.js",
|
|
30
|
+
"lib/types/**/*.d.ts",
|
|
31
|
+
"lib/types/invariant.d.ts"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
36
|
+
"@lmzhen/dsh-evolution-core": "^0.1.0-rc.1"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
40
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
|
|
41
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
|
|
42
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
43
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
44
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
45
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.1",
|
|
46
|
+
"@lmzhen/dsh-evolution-state": "^0.1.0-rc.1"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
|
|
50
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.0-rc.6",
|
|
51
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
|
|
52
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
53
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
54
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
55
|
+
"@lmzhen/dsh-evolution-core": "^0.1.0-rc.1",
|
|
56
|
+
"@lmzhen/dsh-evolution-plan-validator": "^0.1.0-rc.1",
|
|
57
|
+
"@lmzhen/dsh-evolution-state": "^0.1.0-rc.1"
|
|
58
|
+
}
|
|
59
|
+
}
|