@lmzhen/dsh-evolution-commands 0.1.0-rc.9 → 0.1.0
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 +110 -22
- package/lib/types/index.d.ts +1 -1
- package/package.json +7 -5
package/lib/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import { appendEvolutionEvent, buildLearnPrompt, eventsFile } from "@lmzhen/dsh-evolution-core";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
1
5
|
//#region lib/types/index.js
|
|
2
6
|
/**
|
|
3
|
-
* Human commands for the evolution family: /evolution
|
|
7
|
+
* Human commands for the evolution family: /evolution learn|pending|curator|restore|consolidate.
|
|
4
8
|
* @module @lmzhen/dsh-evolution-commands
|
|
5
9
|
*/
|
|
6
10
|
const name = "evolution-commands";
|
|
@@ -12,69 +16,153 @@ function apply(ctx) {
|
|
|
12
16
|
recordInput: false,
|
|
13
17
|
async handler(invocation) {
|
|
14
18
|
const input = invocation.rawInput?.trim() ?? "";
|
|
19
|
+
const ok = (text) => ({
|
|
20
|
+
kind: "success",
|
|
21
|
+
text
|
|
22
|
+
});
|
|
23
|
+
const err = (text) => ({
|
|
24
|
+
kind: "error",
|
|
25
|
+
text
|
|
26
|
+
});
|
|
15
27
|
const approval = ctx.get("evolutionApproval");
|
|
16
28
|
if (input === "pending") {
|
|
17
29
|
const pending = approval ? await approval.list("pending") : [];
|
|
18
|
-
return
|
|
30
|
+
return ok(pending.length === 0 ? "No pending evolution writes." : pending.map((p) => `${p.id} ${p.kind} ${p.summary}`).join("\n"));
|
|
19
31
|
}
|
|
20
32
|
if (input.startsWith("approve ")) {
|
|
21
33
|
const id = input.slice(8).trim();
|
|
22
|
-
|
|
34
|
+
const result = approval ? await approval.approve(id) : {
|
|
23
35
|
ok: false,
|
|
24
36
|
message: "approval service not mounted"
|
|
25
|
-
}
|
|
37
|
+
};
|
|
38
|
+
return result.ok ? ok(result.message) : err(result.message);
|
|
26
39
|
}
|
|
27
40
|
if (input.startsWith("reject ")) {
|
|
28
41
|
const id = input.slice(7).trim();
|
|
29
|
-
|
|
42
|
+
const result = approval ? await approval.reject(id) : {
|
|
30
43
|
ok: false,
|
|
31
44
|
message: "approval service not mounted"
|
|
32
|
-
}
|
|
45
|
+
};
|
|
46
|
+
return result.ok ? ok(result.message) : err(result.message);
|
|
33
47
|
}
|
|
34
48
|
if (input === "curator run") {
|
|
35
49
|
const curator = ctx.get("evolutionCurator");
|
|
36
|
-
if (!curator) return
|
|
37
|
-
const result = await curator.run();
|
|
38
|
-
return
|
|
50
|
+
if (!curator) return err("Curator service not mounted.");
|
|
51
|
+
const result = await curator.run({ ignoreGates: true });
|
|
52
|
+
return ok(`Curator run complete: ${result.stale.length} stale, ${result.archived.length} archived, ${result.errors.length} failed.\nrunId=${result.report.runId}${result.report.snapshotPath ? `\nsnapshot=${result.report.snapshotPath}` : ""}`);
|
|
53
|
+
}
|
|
54
|
+
if (input === "curator pause" || input === "curator resume") {
|
|
55
|
+
const curator = ctx.get("evolutionCurator");
|
|
56
|
+
if (!curator) return err("Curator service not mounted.");
|
|
57
|
+
const paused = input === "curator pause";
|
|
58
|
+
await curator.setPaused(paused);
|
|
59
|
+
return ok(paused ? "Curator automatic curation paused. Manual /evolution curator run is unaffected; resume with /evolution curator resume." : "Curator automatic curation resumed. The next scheduled pass waits one interval (first-run defer semantics).");
|
|
60
|
+
}
|
|
61
|
+
if (input === "curator status") {
|
|
62
|
+
const curator = ctx.get("evolutionCurator");
|
|
63
|
+
if (!curator) return err("Curator service not mounted.");
|
|
64
|
+
const state = await curator.status();
|
|
65
|
+
if (!state) return ok("No curator state yet: the first automatic pass is deferred until the interval elapses.");
|
|
66
|
+
const lastRun = typeof state.lastRunAt === "number" && Number.isFinite(state.lastRunAt) && state.lastRunAt > 0 ? new Date(state.lastRunAt).toISOString() : "unknown";
|
|
67
|
+
return ok([
|
|
68
|
+
`paused=${state.paused}`,
|
|
69
|
+
`runs=${state.runCount}`,
|
|
70
|
+
`lastRun=${lastRun}`,
|
|
71
|
+
`summary=${state.lastSummary}`
|
|
72
|
+
].join("\n"));
|
|
73
|
+
}
|
|
74
|
+
if (input === "mutations") {
|
|
75
|
+
const curator = ctx.get("evolutionCurator");
|
|
76
|
+
if (!curator) return err("Curator service not mounted.");
|
|
77
|
+
const records = await curator.skills.listMutations();
|
|
78
|
+
if (records.length === 0) return ok("No mutation records yet.");
|
|
79
|
+
const recent = records.slice(-5).reverse().map((record) => `${record.at.slice(0, 19)} ${record.skillName} ${record.action} ${record.summary}`);
|
|
80
|
+
return ok(`Mutations: ${records.length} recorded (recent 5):\n${recent.join("\n")}`);
|
|
81
|
+
}
|
|
82
|
+
if (input === "curator scope") {
|
|
83
|
+
const curator = ctx.get("evolutionCurator");
|
|
84
|
+
if (!curator) return err("Curator service not mounted.");
|
|
85
|
+
const view = await curator.scopeView();
|
|
86
|
+
const line = (label, names) => `${label}: ${names.length}${names.length === 0 ? "" : `\n ${names.join(", ")}`}`;
|
|
87
|
+
return ok([
|
|
88
|
+
`Lifecycle scope at ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`,
|
|
89
|
+
line("Managed (may transition)", view.managed),
|
|
90
|
+
line("Watched (stale / quality-warned)", view.watched),
|
|
91
|
+
line("Quality-warned", view.qualityWarned),
|
|
92
|
+
line("Exempted (exclude / referenced)", view.exempted),
|
|
93
|
+
line("Protected (pinned / bundled / hub)", view.protected)
|
|
94
|
+
].join("\n"));
|
|
39
95
|
}
|
|
40
96
|
if (input === "curator report") {
|
|
41
97
|
const curator = ctx.get("evolutionCurator");
|
|
42
|
-
if (!curator) return
|
|
98
|
+
if (!curator) return err("Curator service not mounted.");
|
|
43
99
|
const report = await curator.latestReport();
|
|
44
|
-
if (!report) return
|
|
45
|
-
return
|
|
100
|
+
if (!report) return ok("No curator report available.");
|
|
101
|
+
return ok([
|
|
46
102
|
`runId=${report.runId}`,
|
|
47
103
|
`startedAt=${report.startedAt}`,
|
|
48
104
|
`archived=${report.archived.map((item) => item.name).join(", ") || "(none)"}`,
|
|
49
105
|
`failed=${report.failed.map((item) => `${item.name}: ${item.reason}`).join(", ") || "(none)"}`
|
|
50
|
-
].join("\n")
|
|
106
|
+
].join("\n"));
|
|
51
107
|
}
|
|
52
108
|
if (input.startsWith("restore ")) {
|
|
53
109
|
const curator = ctx.get("evolutionCurator");
|
|
54
|
-
|
|
110
|
+
const result = curator ? await curator.restoreSnapshot() : {
|
|
55
111
|
ok: false,
|
|
56
112
|
message: "Curator service not mounted."
|
|
57
|
-
}
|
|
113
|
+
};
|
|
114
|
+
return result.ok ? ok(result.message) : err(result.message);
|
|
58
115
|
}
|
|
59
116
|
if (input.startsWith("consolidate ")) {
|
|
60
117
|
const [target, ...sources] = input.slice(12).trim().split(/\s+/).filter(Boolean);
|
|
61
|
-
if (!target || sources.length === 0) return
|
|
118
|
+
if (!target || sources.length === 0) return err("Usage: /evolution consolidate <target> <source...>");
|
|
62
119
|
const curator = ctx.get("evolutionCurator");
|
|
63
|
-
|
|
120
|
+
const result = curator ? await curator.consolidate(target, sources) : {
|
|
64
121
|
ok: false,
|
|
65
122
|
message: "Curator service not mounted."
|
|
66
|
-
}
|
|
123
|
+
};
|
|
124
|
+
return result.ok ? ok(result.message) : err(result.message);
|
|
67
125
|
}
|
|
68
126
|
if (input.startsWith("skill restore ")) {
|
|
69
127
|
const name = input.slice(14).trim();
|
|
70
|
-
if (!name) return
|
|
128
|
+
if (!name) return err("Usage: /evolution skill restore <name>");
|
|
71
129
|
const curator = ctx.get("evolutionCurator");
|
|
72
|
-
|
|
130
|
+
const result = curator ? await curator.restore(name) : {
|
|
73
131
|
ok: false,
|
|
74
132
|
message: "Curator service not mounted."
|
|
75
|
-
}
|
|
133
|
+
};
|
|
134
|
+
return result.ok ? ok(result.message) : err(result.message);
|
|
135
|
+
}
|
|
136
|
+
if (input === "learn" || input.startsWith("learn ")) {
|
|
137
|
+
const request = input === "learn" ? "" : input.slice(6).trim();
|
|
138
|
+
invocation.agent.inject(createUserMessage({
|
|
139
|
+
content: [{
|
|
140
|
+
type: "text",
|
|
141
|
+
text: buildLearnPrompt(request)
|
|
142
|
+
}],
|
|
143
|
+
source: {
|
|
144
|
+
kind: "plugin",
|
|
145
|
+
plugin: "dsh-evolution-commands",
|
|
146
|
+
form: "notice",
|
|
147
|
+
summary: "learn request"
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
150
|
+
const eventIo = ctx.get("evolutionIo")?.provider();
|
|
151
|
+
if (eventIo) appendEvolutionEvent(eventIo, eventsFile(process.env.DSH_HOME ?? join(homedir(), ".dsh")), {
|
|
152
|
+
type: "learn",
|
|
153
|
+
source: "manual",
|
|
154
|
+
...request ? { request } : {}
|
|
155
|
+
}).catch((error) => {
|
|
156
|
+
ctx.logger.warn(`evolution-commands: failed to record learn event: ${String(error)}`);
|
|
157
|
+
});
|
|
158
|
+
return ok("Learning request sent to this session. Follow it now.");
|
|
159
|
+
}
|
|
160
|
+
if (input === "replay") {
|
|
161
|
+
const replay = ctx.get("evolutionReplay");
|
|
162
|
+
if (!replay) return err("Replay service not mounted.");
|
|
163
|
+
return ok(replay.compare().report);
|
|
76
164
|
}
|
|
77
|
-
return
|
|
165
|
+
return ok("Evolution: memory, skills, review, curator. Use /evolution pending | approve <id> | reject <id> | curator run | curator status | curator pause | curator resume | curator report | curator scope | restore | consolidate <target> <source...> | skill restore <name> | learn [request] | replay.");
|
|
78
166
|
}
|
|
79
167
|
});
|
|
80
168
|
});
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Human commands for the evolution family: /evolution
|
|
2
|
+
* Human commands for the evolution family: /evolution learn|pending|curator|restore|consolidate.
|
|
3
3
|
* @module @deepseek-ai/dsh-evolution-commands
|
|
4
4
|
*/
|
|
5
5
|
import type { Context } from '@deepseek-ai/cordis';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-commands",
|
|
3
3
|
"description": "Human commands for the evolution family (community build)",
|
|
4
|
-
"version": "0.1.0
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -32,13 +32,15 @@
|
|
|
32
32
|
],
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
35
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
36
|
+
"@lmzhen/dsh-evolution-core": "^0.1.0"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
|
-
"@deepseek-ai/
|
|
39
|
-
"@deepseek-ai/
|
|
39
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
40
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
41
|
+
"@deepseek-ai/dsh-llm": "^0.1.1-rc.2"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
|
-
"@deepseek-ai/dsh-invariants": "^0.1.
|
|
44
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2"
|
|
43
45
|
}
|
|
44
46
|
}
|