@lmzhen/dsh-evolution-commands 0.3.63 → 0.3.65
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 +28 -14
- package/lib/types/index.d.ts +9 -4
- package/package.json +5 -5
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
4
|
-
import { SkillLibrary, appendEvolutionEvent, buildLearnPrompt, clampedNumber, composePresetComposition, eventsFile, evolutionRoot, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
|
|
4
|
+
import { SkillLibrary, appendEvolutionEvent, buildLearnPrompt, clampedNumber, composePresetComposition, eventsFile, evolutionRoot, resolveRootConfig, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
|
|
5
5
|
import { buildEnrichment, buildMaintainFacts, runMaintain, snapshotFromLibrary } from "@lmzhen/dsh-evolution-maintenance";
|
|
6
6
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { dirname, join } from "node:path";
|
|
@@ -16,6 +16,14 @@ import { fileURLToPath } from "node:url";
|
|
|
16
16
|
* services are actually mounted in this runtime. Always ends with suggested
|
|
17
17
|
* actions so any finding carries its next step.
|
|
18
18
|
*/
|
|
19
|
+
/** D-6 (v18): exact-segment tail match (the loose substring form matched a
|
|
20
|
+
* hypothetical `dsh-evolution-allowlist`). */
|
|
21
|
+
const tailOf = (name) => name.slice(name.lastIndexOf("/") + 1);
|
|
22
|
+
const EVOLUTION_BUNDLE_TAILS = new Set([
|
|
23
|
+
"dsh-evolution-all",
|
|
24
|
+
"dsh-evolution-host",
|
|
25
|
+
"dsh-evolution-preset"
|
|
26
|
+
]);
|
|
19
27
|
/** Profile bundle rows for evolution-family packages across all profiles. */
|
|
20
28
|
function collectEvolutionBundles(home) {
|
|
21
29
|
const profilesDir = join(home, "profiles");
|
|
@@ -25,7 +33,7 @@ function collectEvolutionBundles(home) {
|
|
|
25
33
|
if (!profile.isDirectory()) continue;
|
|
26
34
|
try {
|
|
27
35
|
const manifest = JSON.parse(readFileSync(join(profilesDir, profile.name, "package.json"), "utf8"));
|
|
28
|
-
for (const name of manifest.dsh?.profile?.bundles ?? []) if (
|
|
36
|
+
for (const name of manifest.dsh?.profile?.bundles ?? []) if (EVOLUTION_BUNDLE_TAILS.has(tailOf(name))) bundles.push(name);
|
|
29
37
|
} catch {}
|
|
30
38
|
}
|
|
31
39
|
return bundles;
|
|
@@ -50,9 +58,9 @@ async function diagnose(ctx, options = {}) {
|
|
|
50
58
|
const home = options.home ?? evolutionRoot();
|
|
51
59
|
const bundles = collectEvolutionBundles(home);
|
|
52
60
|
const has = (name) => ctx.get(name) !== void 0;
|
|
53
|
-
const full = bundles.some((name) =>
|
|
54
|
-
const host = bundles.some((name) =>
|
|
55
|
-
const preset = bundles.some((name) =>
|
|
61
|
+
const full = bundles.some((name) => tailOf(name) === "dsh-evolution-all");
|
|
62
|
+
const host = bundles.some((name) => tailOf(name) === "dsh-evolution-host");
|
|
63
|
+
const preset = bundles.some((name) => tailOf(name) === "dsh-evolution-preset");
|
|
56
64
|
const presetDir = join(home, ".agent-presets", "evolution");
|
|
57
65
|
const layered = host && existsSync(presetDir);
|
|
58
66
|
const conflicts = [];
|
|
@@ -191,6 +199,7 @@ function renderHelpText() {
|
|
|
191
199
|
/** Enrichment maps shared by the full scan and the `--facts` preview (v12). */
|
|
192
200
|
const name = "evolution-commands";
|
|
193
201
|
const Config = z.object({
|
|
202
|
+
root: z.string().default(""),
|
|
194
203
|
skillsRoot: z.string().default(""),
|
|
195
204
|
maintainCooldownMs: z.number().min(0).default(3e4),
|
|
196
205
|
maintainTimeoutMs: z.number().min(1).default(6e5),
|
|
@@ -198,6 +207,9 @@ const Config = z.object({
|
|
|
198
207
|
});
|
|
199
208
|
function apply(ctx, rawConfig = {}) {
|
|
200
209
|
const config = rawConfig;
|
|
210
|
+
const rootConfig = resolveRootConfig(rawConfig);
|
|
211
|
+
if (rootConfig.usedDeprecatedAlias) ctx.logger.warn("evolution-commands: config \"skillsRoot\" is deprecated (E-7); use \"root\" — the alias is honoured until 0.3.65");
|
|
212
|
+
const skillsRootValue = rootConfig.root;
|
|
201
213
|
let lastMaintainAt = 0;
|
|
202
214
|
let lastMaintainRunId = "";
|
|
203
215
|
let maintainInFlightSince = 0;
|
|
@@ -251,6 +263,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
251
263
|
const curator = ctx.get("evolutionCurator");
|
|
252
264
|
if (!curator) return err("E-302: curator service not mounted. Next: mount the evolution-curator row (evolution-host/evolution-all) and run /evolution doctor.");
|
|
253
265
|
const result = await curator.run({ ignoreGates: true });
|
|
266
|
+
if (result.skipped !== void 0) return ok(`Curator run skipped (${result.skipped}): no curation pass was executed.\nrunId=${result.report.runId}`);
|
|
254
267
|
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}` : ""}`);
|
|
255
268
|
}
|
|
256
269
|
if (input === "curator pause" || input === "curator resume") {
|
|
@@ -314,6 +327,8 @@ function apply(ctx, rawConfig = {}) {
|
|
|
314
327
|
].join("\n"));
|
|
315
328
|
}
|
|
316
329
|
if (input === "restore" || input.startsWith("restore ")) {
|
|
330
|
+
const tail = input.slice(7).trim();
|
|
331
|
+
if (tail !== "") return err(`\`restore\` takes no arguments (got "${tail}"). Use \`restore\` for a whole-tree rollback, or \`skill restore <name>\` for one skill.`);
|
|
317
332
|
const curator = ctx.get("evolutionCurator");
|
|
318
333
|
const result = curator ? await curator.restoreSnapshot() : {
|
|
319
334
|
ok: false,
|
|
@@ -384,7 +399,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
384
399
|
if (input === "maintain --facts") {
|
|
385
400
|
const ioRegistry = ctx.get("evolutionIo");
|
|
386
401
|
if (!ioRegistry) return err("Evolution IO registry not mounted — maintenance facts unavailable.");
|
|
387
|
-
const library = new SkillLibrary(resolveSkillsRoot({ root:
|
|
402
|
+
const library = new SkillLibrary(resolveSkillsRoot({ root: skillsRootValue }), ioRegistry.provider());
|
|
388
403
|
const enrichment = await buildEnrichment(ctx, library);
|
|
389
404
|
const { facts } = buildMaintainFacts(await snapshotFromLibrary(library, {
|
|
390
405
|
descriptions: enrichment.descriptions,
|
|
@@ -398,7 +413,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
398
413
|
const maintainArgs = /^maintain(?:\s+--timeout[ =](\d+))?\s*$/.exec(input);
|
|
399
414
|
if (maintainArgs) {
|
|
400
415
|
const runTimeoutMs = maintainArgs[1] ? Number(maintainArgs[1]) : config.maintainTimeoutMs ?? 6e5;
|
|
401
|
-
if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs >
|
|
416
|
+
if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > 2147483647) return err(maintainArgs[1] ? "Invalid --timeout value: expected a positive integer number of milliseconds up to 2147483647 (e.g. /evolution maintain --timeout 600000)." : "The maintainTimeoutMs config is invalid: expected a positive integer number of milliseconds up to 2147483647. Fix the evolution-commands row config (maintainTimeoutMs), then retry.");
|
|
402
417
|
if (maintainInFlightSince > 0) return err(`Maintenance scan is already running (since ~${Math.max(1, Math.round((Date.now() - maintainInFlightSince) / 1e3))}s ago) — re-submitting now would cancel it. Wait for it to settle; the result appears when it finishes.`);
|
|
403
418
|
const cooldownMs = clampedNumber(config.maintainCooldownMs, 3e4, { min: 0 });
|
|
404
419
|
const sinceLast = Date.now() - lastMaintainAt;
|
|
@@ -409,7 +424,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
409
424
|
if (!subagents) return err("Subagents service not mounted — maintenance scan unavailable.");
|
|
410
425
|
try {
|
|
411
426
|
maintainInFlightSince = Date.now();
|
|
412
|
-
const library = new SkillLibrary(resolveSkillsRoot({ root:
|
|
427
|
+
const library = new SkillLibrary(resolveSkillsRoot({ root: skillsRootValue }), ioRegistry.provider());
|
|
413
428
|
const enrichment = await buildEnrichment(ctx, library);
|
|
414
429
|
const outcome = await runMaintain({
|
|
415
430
|
library,
|
|
@@ -422,6 +437,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
422
437
|
} }
|
|
423
438
|
}, {
|
|
424
439
|
timeoutMs: runTimeoutMs,
|
|
440
|
+
signal: invocation.signal,
|
|
425
441
|
descriptions: () => enrichment.descriptions,
|
|
426
442
|
supportFiles: () => enrichment.supportFiles,
|
|
427
443
|
quality: () => enrichment.quality,
|
|
@@ -486,7 +502,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
486
502
|
if (!toFile.startsWith("references/")) return err("to_file must live under references/ (log/detail destination).");
|
|
487
503
|
const ioRegistry = ctx.get("evolutionIo");
|
|
488
504
|
if (!ioRegistry) return err("Evolution IO registry not mounted — restructure unavailable.");
|
|
489
|
-
const result = await new SkillLibrary(resolveSkillsRoot({ root:
|
|
505
|
+
const result = await new SkillLibrary(resolveSkillsRoot({ root: skillsRootValue }), ioRegistry.provider(), void 0, (event) => {
|
|
490
506
|
ctx.emit("evolution/skill-mutated", event);
|
|
491
507
|
}, void 0, config.threatExemptLabels ?? []).restructure(name, [{
|
|
492
508
|
heading,
|
|
@@ -520,14 +536,12 @@ function apply(ctx, rawConfig = {}) {
|
|
|
520
536
|
* dir≠name trap), so BOTH sibling shapes are probed.
|
|
521
537
|
*/
|
|
522
538
|
function resolveAgentPresetDir(importMetaUrl) {
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
const candidates = [siblingCandidate, join(dir, "..", "..", "evolution-agent")];
|
|
526
|
-
for (const candidate of candidates) if (existsSync(join(candidate, "agent.cordis.yml")) && existsSync(join(candidate, "preset.yml"))) return candidate;
|
|
539
|
+
const overlayCandidate = join(dirname(fileURLToPath(importMetaUrl)), "..", "..", "evolution-agent");
|
|
540
|
+
if (existsSync(join(overlayCandidate, "agent.cordis.yml")) && existsSync(join(overlayCandidate, "preset.yml"))) return overlayCandidate;
|
|
527
541
|
try {
|
|
528
542
|
return dirname(createRequire(importMetaUrl).resolve("@lmzhen/dsh-evolution-agent-preset/package.json"));
|
|
529
543
|
} catch {
|
|
530
|
-
return
|
|
544
|
+
return overlayCandidate;
|
|
531
545
|
}
|
|
532
546
|
}
|
|
533
547
|
const defaultFs = {
|
package/lib/types/index.d.ts
CHANGED
|
@@ -6,10 +6,13 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
6
6
|
import z from '@deepseek-ai/schemastery';
|
|
7
7
|
export declare const name = "evolution-commands";
|
|
8
8
|
export interface Config {
|
|
9
|
-
/** Skill-tree root for maintain/restructure; empty uses
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
/** Skill-tree root for maintain/restructure; empty uses the default tree.
|
|
10
|
+
* E-7 (v18): canonical key — the same `root` every other family row reads,
|
|
11
|
+
* resolved through resolveSkillsRoot() so an empty/whitespace value falls
|
|
12
|
+
* back to the default instead of a CWD-relative root. */
|
|
13
|
+
root?: string | undefined;
|
|
14
|
+
/** Deprecated alias of `root` (E-7, v18): honoured only while `root` is
|
|
15
|
+
* empty, with a warning; removed after 0.3.65. */
|
|
13
16
|
skillsRoot?: string | undefined;
|
|
14
17
|
/** Cooldown window for scan commands (ms) — misclick/rapid-trigger guard;
|
|
15
18
|
* secondary calls inside the window return the previous runId instead of
|
|
@@ -34,11 +37,13 @@ export interface Config {
|
|
|
34
37
|
threatExemptLabels?: string[] | undefined;
|
|
35
38
|
}
|
|
36
39
|
export declare const Config: z<Schemastery.ObjectS<{
|
|
40
|
+
root: z<string, string>;
|
|
37
41
|
skillsRoot: z<string, string>;
|
|
38
42
|
maintainCooldownMs: z<number, number>;
|
|
39
43
|
maintainTimeoutMs: z<number, number>;
|
|
40
44
|
threatExemptLabels: z<string[], string[]>;
|
|
41
45
|
}>, Schemastery.ObjectT<{
|
|
46
|
+
root: z<string, string>;
|
|
42
47
|
skillsRoot: z<string, string>;
|
|
43
48
|
maintainCooldownMs: z<number, number>;
|
|
44
49
|
maintainTimeoutMs: z<number, number>;
|
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 (/evolution pending|curator|maintain|doctor) (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.65",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-approval": "^0.3.
|
|
35
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
36
|
-
"@lmzhen/dsh-evolution-maintenance": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-approval": "^0.3.65",
|
|
35
|
+
"@lmzhen/dsh-evolution-core": "^0.3.65",
|
|
36
|
+
"@lmzhen/dsh-evolution-maintenance": "^0.3.65"
|
|
37
37
|
},
|
|
38
38
|
"optionalDependencies": {
|
|
39
|
-
"@lmzhen/dsh-evolution-agent-preset": "^0.3.
|
|
39
|
+
"@lmzhen/dsh-evolution-agent-preset": "^0.3.65"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@deepseek-ai/cordis": "^4.0.1",
|