@lmzhen/dsh-evolution-commands 0.23.0 → 0.25.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 +115 -98
- package/package.json +6 -6
package/lib/index.js
CHANGED
|
@@ -273,10 +273,10 @@ function presetProfileTarget(ctx) {
|
|
|
273
273
|
* @returns the refusal text, or undefined when the base is usable here.
|
|
274
274
|
*/
|
|
275
275
|
function baseRefusalReason(entry, servicePresent) {
|
|
276
|
-
if (typeof entry.unsupported === "string" && entry.unsupported !== "") return
|
|
276
|
+
if (typeof entry.unsupported === "string" && entry.unsupported !== "") return `基底「${entry.name}」被登记为 UNSUPPORTED(不受支持):${entry.unsupported}`;
|
|
277
277
|
const service = entry.requires?.service;
|
|
278
278
|
if (typeof service !== "string" || service === "") return void 0;
|
|
279
|
-
return servicePresent(service) ? void 0 :
|
|
279
|
+
return servicePresent(service) ? void 0 : `基底 "${entry.name}" 需要 "${service}" 服务,而本部署没有提供它 —— 生成的预设会拒绝挂载。`;
|
|
280
280
|
}
|
|
281
281
|
/**
|
|
282
282
|
* Resolve the platform base preset patch one `--base` composes.
|
|
@@ -423,7 +423,7 @@ function profilePatchText(profileDir) {
|
|
|
423
423
|
function installExclusionTarget(mounted) {
|
|
424
424
|
if (mounted === void 0 || mounted.dir === "") return {
|
|
425
425
|
kind: "undecidable",
|
|
426
|
-
reason: "
|
|
426
|
+
reason: "本进程没有挂载 profile,因此无法在这里回答双挂载问题"
|
|
427
427
|
};
|
|
428
428
|
let manifestFailure;
|
|
429
429
|
const declared = profileBundles(mounted.dir, (error) => {
|
|
@@ -432,7 +432,7 @@ function installExclusionTarget(mounted) {
|
|
|
432
432
|
const manifestCode = manifestFailure?.code;
|
|
433
433
|
if (manifestFailure !== void 0 && manifestCode !== "ENOENT") return {
|
|
434
434
|
kind: "undecidable",
|
|
435
|
-
reason: "
|
|
435
|
+
reason: "读不出已挂载 profile 的清单"
|
|
436
436
|
};
|
|
437
437
|
return {
|
|
438
438
|
kind: "mounted",
|
|
@@ -522,7 +522,7 @@ function presetIssues(presets) {
|
|
|
522
522
|
* @returns one readable line per divergence, empty when there is nothing to compare.
|
|
523
523
|
*/
|
|
524
524
|
function paramDivergences(platform) {
|
|
525
|
-
if (platform.configuration === void 0) return ["
|
|
525
|
+
if (platform.configuration === void 0) return ["平台上没有挂载配置面(configEditor.configuration):参数差异没有被检查"];
|
|
526
526
|
const issues = [];
|
|
527
527
|
for (const row of platform.configuration) {
|
|
528
528
|
const override = asMapping(row.override);
|
|
@@ -539,7 +539,7 @@ function paramDivergences(platform) {
|
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
541
|
if (platform.plugins === void 0) {
|
|
542
|
-
issues.push("
|
|
542
|
+
issues.push("平台上没有挂载插件行面(pluginManager.listPlugins):已声明但不可达的参数没有被检查");
|
|
543
543
|
return issues;
|
|
544
544
|
}
|
|
545
545
|
const live = liveRowTails(platform.plugins);
|
|
@@ -921,7 +921,7 @@ async function diagnose(ctx, options = {}) {
|
|
|
921
921
|
const conflicts = [];
|
|
922
922
|
const bundles = collectEvolutionBundles(home, (error, scope) => {
|
|
923
923
|
const detail = error instanceof Error ? error.message : String(error);
|
|
924
|
-
conflicts.push(scope === "profiles-dir" ?
|
|
924
|
+
conflicts.push(scope === "profiles-dir" ? `本 home 的 profiles 目录无法枚举(${detail}):基于 bundle 的安装形态与冲突检查已降级(DEGRADED),可能漏掉已安装的 bundle` : `本 profile 清单读不出来或无法解析(${detail}):本 profile 的 bundle 行为未知,因此安装形态与冲突检查已降级(DEGRADED),可能漏掉已安装的 bundle`);
|
|
925
925
|
});
|
|
926
926
|
const has = (name) => ctx.get(name) !== void 0;
|
|
927
927
|
const capabilityAbsence = absentHostServices(has);
|
|
@@ -1079,7 +1079,7 @@ async function probeBounded(work, label) {
|
|
|
1079
1079
|
timer = setTimeout(() => {
|
|
1080
1080
|
resolve({
|
|
1081
1081
|
ok: false,
|
|
1082
|
-
message: `${label}
|
|
1082
|
+
message: `${label} 在 ${PROBE_TIMEOUT_MS}ms 内没有应答:语料被阻塞(并发写入方可能拖住观测),或服务卡死。请隔离最近写入的会话后重试。`
|
|
1083
1083
|
});
|
|
1084
1084
|
}, PROBE_TIMEOUT_MS);
|
|
1085
1085
|
});
|
|
@@ -1398,7 +1398,7 @@ const COMMAND_ENTRIES = [
|
|
|
1398
1398
|
{
|
|
1399
1399
|
readonly: false,
|
|
1400
1400
|
usage: "release <id>",
|
|
1401
|
-
summary: "
|
|
1401
|
+
summary: "把卡在执行中的写入放回待批窗口(先确认效果再批准或驳回)"
|
|
1402
1402
|
},
|
|
1403
1403
|
{
|
|
1404
1404
|
readonly: true,
|
|
@@ -1498,12 +1498,12 @@ const COMMAND_ENTRIES = [
|
|
|
1498
1498
|
{
|
|
1499
1499
|
readonly: false,
|
|
1500
1500
|
usage: "policy set <id> <value> [--expect <revision>]",
|
|
1501
|
-
summary: "通过设置服务写入一个你可改的参数
|
|
1501
|
+
summary: "通过设置服务写入一个你可改的参数 (仅 E3;E1/E2 仍留在 cordis.yml)"
|
|
1502
1502
|
},
|
|
1503
1503
|
{
|
|
1504
1504
|
readonly: true,
|
|
1505
1505
|
usage: "params [--group <name>] [--json]",
|
|
1506
|
-
summary: "列出全部参数:分组、档位、生效时机、来源与当前值(--json
|
|
1506
|
+
summary: "列出全部参数:分组、档位、生效时机、来源与当前值(--json 便于脚本处理)"
|
|
1507
1507
|
},
|
|
1508
1508
|
{
|
|
1509
1509
|
readonly: false,
|
|
@@ -1699,12 +1699,12 @@ function newestRun(registry) {
|
|
|
1699
1699
|
/** Sentence F, ONE wording for the three id-less forms (design `10` cell 13): an index that could
|
|
1700
1700
|
* not be read must never answer as "there is no recent run" (G2/0.20.0). */
|
|
1701
1701
|
function unreadableIndex(note) {
|
|
1702
|
-
return
|
|
1702
|
+
return `本 home 的运行索引读不出来(${note ?? "原因未知"}):这不等于「最近没有运行」。`;
|
|
1703
1703
|
}
|
|
1704
1704
|
/** The explicit-id twin of {@link unreadableIndex}, worded like `maintain status` so the four
|
|
1705
1705
|
* readers cannot drift (review P1-1). */
|
|
1706
1706
|
function unreadableForId(id, note) {
|
|
1707
|
-
return
|
|
1707
|
+
return `运行 ${id} 不在本进程的历史里,且本 home 的运行索引读不出来(${note ?? "原因未知"}):但这不能证明那次运行没发生过。`;
|
|
1708
1708
|
}
|
|
1709
1709
|
/** The reader-facing report path: the `.md` digest beside the run's `.json` result. */
|
|
1710
1710
|
function reportDigestPath(record) {
|
|
@@ -1849,7 +1849,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
1849
1849
|
});
|
|
1850
1850
|
runs = registry;
|
|
1851
1851
|
registry.load().then((loaded) => {
|
|
1852
|
-
if (!loaded.ok) ctx.logger.warn(`evolution-commands: the run index is not usable — ${loaded.note ?? "
|
|
1852
|
+
if (!loaded.ok) ctx.logger.warn(`evolution-commands: the run index is not usable — ${loaded.note ?? "原因未知"}`);
|
|
1853
1853
|
else if (loaded.note !== void 0) ctx.logger.warn(`evolution-commands: ${loaded.note}`);
|
|
1854
1854
|
}).catch((error) => {
|
|
1855
1855
|
ctx.logger.warn(`evolution-commands: could not read the run index (${error instanceof Error ? error.message : String(error)})`);
|
|
@@ -1888,8 +1888,8 @@ function apply(ctx, rawConfig = {}) {
|
|
|
1888
1888
|
const listed = [...await approval.list("pending"), ...await approval.list("executing")];
|
|
1889
1889
|
const pending = [...new Map(listed.map((row) => [row.id, row])).values()];
|
|
1890
1890
|
const ttlMs = typeof approval.ttlMs === "number" && Number.isFinite(approval.ttlMs) ? approval.ttlMs : 0;
|
|
1891
|
-
const ttlNote = ttlMs > 0 ? `\n
|
|
1892
|
-
if (pending.length === 0) return ok("
|
|
1891
|
+
const ttlNote = ttlMs > 0 ? `\n(暂存写入 ${ttlMs} 毫秒后过期:过期即关闭为 REJECTED,且永不执行。若仍需要,请重新暂存。)` : "\n(staged writes never expire — the window waits for a decision; set the evolution-approval row pendingTtlMs to bound it)";
|
|
1892
|
+
if (pending.length === 0) return ok("没有待批准的自进化写入。" + ttlNote);
|
|
1893
1893
|
const detailed = pendingParsed.flags.get("detail") === true;
|
|
1894
1894
|
const nowMs = Date.now();
|
|
1895
1895
|
const attribution = (p) => {
|
|
@@ -1931,22 +1931,22 @@ function apply(ctx, rawConfig = {}) {
|
|
|
1931
1931
|
const curator = ctx.get("evolutionCurator");
|
|
1932
1932
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
1933
1933
|
const result = await curator.run({ ignoreGates: true });
|
|
1934
|
-
if (result.skipped !== void 0) return ok(
|
|
1935
|
-
return ok(
|
|
1934
|
+
if (result.skipped !== void 0) return ok(`策展轮已跳过(${result.skipped}):未执行策展过程。\nrunId=${result.report.runId}`);
|
|
1935
|
+
return ok(`策展轮完成:${result.stale.length} 项过期,${result.archived.length} 项已归档,${result.errors.length} 项失败。\nrunId=${result.report.runId}${result.report.snapshotPath ? `\nsnapshot=${result.report.snapshotPath}` : ""}`);
|
|
1936
1936
|
}
|
|
1937
1937
|
if (input === "curator pause" || input === "curator resume") {
|
|
1938
1938
|
const curator = ctx.get("evolutionCurator");
|
|
1939
1939
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
1940
1940
|
const paused = input === "curator pause";
|
|
1941
1941
|
await curator.setPaused(paused);
|
|
1942
|
-
const notPersisted = ctx.get("evolutionState") !== void 0 ? "" : "\
|
|
1943
|
-
return ok((paused ? "
|
|
1942
|
+
const notPersisted = ctx.get("evolutionState") !== void 0 ? "" : "\n注意:没有挂载 evolution 状态服务 —— 该设置不会被持久化,也不会在此进程之后保留。";
|
|
1943
|
+
return ok((paused ? "策展自动轮已暂停。手动 /evolution curator run 不受影响;用 /evolution curator resume 恢复。" : "策展自动轮已恢复。下一次定时轮要等一个间隔(首轮延后语义)。") + notPersisted);
|
|
1944
1944
|
}
|
|
1945
1945
|
if (input === "curator status") {
|
|
1946
1946
|
const curator = ctx.get("evolutionCurator");
|
|
1947
1947
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
1948
1948
|
const state = await curator.status();
|
|
1949
|
-
if (!state) return ok("
|
|
1949
|
+
if (!state) return ok("还没有策展状态:首个自动轮次要等间隔到达后才会执行。");
|
|
1950
1950
|
const lastRun = typeof state.lastRunAt === "number" && Number.isFinite(state.lastRunAt) && state.lastRunAt > 0 ? new Date(state.lastRunAt).toISOString() : "unknown";
|
|
1951
1951
|
return ok([
|
|
1952
1952
|
`paused=${state.paused}`,
|
|
@@ -1960,9 +1960,9 @@ function apply(ctx, rawConfig = {}) {
|
|
|
1960
1960
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
1961
1961
|
const records = await curator.skills.listMutations();
|
|
1962
1962
|
const usable = Array.isArray(records) ? records.filter((row) => typeof row === "object" && row !== null && typeof row.at === "string" && typeof row.skillName === "string" && typeof row.action === "string" && typeof row.summary === "string") : [];
|
|
1963
|
-
if (usable.length === 0) return ok("
|
|
1963
|
+
if (usable.length === 0) return ok("还没有写入记录。");
|
|
1964
1964
|
const recent = usable.slice(-5).reverse().map((record) => `${record.at.slice(0, 19)} ${record.skillName} ${record.action} ${record.summary}`);
|
|
1965
|
-
return ok(
|
|
1965
|
+
return ok(`写入记录:已记录 ${usable.length} 条(最近 5 条):\n${recent.join("\n")}`);
|
|
1966
1966
|
}
|
|
1967
1967
|
if (input === "curator scope") {
|
|
1968
1968
|
const curator = ctx.get("evolutionCurator");
|
|
@@ -1982,8 +1982,8 @@ function apply(ctx, rawConfig = {}) {
|
|
|
1982
1982
|
const curator = ctx.get("evolutionCurator");
|
|
1983
1983
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
1984
1984
|
const report = await curator.latestReport();
|
|
1985
|
-
if (!report) return ok("
|
|
1986
|
-
if (typeof report !== "object" || typeof report.runId !== "string" || typeof report.startedAt !== "string" || !Array.isArray(report.archived) || !Array.isArray(report.failed)) return err("
|
|
1985
|
+
if (!report) return ok("暂无策展报告。");
|
|
1986
|
+
if (typeof report !== "object" || typeof report.runId !== "string" || typeof report.startedAt !== "string" || !Array.isArray(report.archived) || !Array.isArray(report.failed)) return err("报告文件读不出来。");
|
|
1987
1987
|
const reportAny = report;
|
|
1988
1988
|
const nameOf = (item) => typeof item === "object" && item !== null && typeof item.name === "string" ? item.name : "?";
|
|
1989
1989
|
const reasonOf = (item) => typeof item === "object" && item !== null && typeof item.reason === "string" ? item.reason : "?";
|
|
@@ -2000,7 +2000,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2000
2000
|
}
|
|
2001
2001
|
if (input === "restore" || input.startsWith("restore ")) {
|
|
2002
2002
|
const tail = input.slice(7).trim();
|
|
2003
|
-
if (tail !== "") return err(`\`restore\`
|
|
2003
|
+
if (tail !== "") return err(`\`restore\` 不接受参数(收到 "${tail}")。\`restore\` 做整树回滚,\`skill restore <name>\` 恢复单个技能。`);
|
|
2004
2004
|
const restoreRefusal = unreplayableWriteRefusal("restore");
|
|
2005
2005
|
if (restoreRefusal) return restoreRefusal;
|
|
2006
2006
|
const curator = ctx.get("evolutionCurator");
|
|
@@ -2016,7 +2016,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2016
2016
|
const planTail = /\s--plan\s+(\S+)\s*$/.exec(input) ?? null;
|
|
2017
2017
|
const planRunId = planTail?.[1] ?? void 0;
|
|
2018
2018
|
const [target, ...sources] = (planTail ? input.slice(0, planTail.index) : input).slice(12).trim().split(/\s+/).filter(Boolean);
|
|
2019
|
-
if (!target || sources.length === 0) return err("
|
|
2019
|
+
if (!target || sources.length === 0) return err("用法:/evolution consolidate <target> <source...>");
|
|
2020
2020
|
const curator = ctx.get("evolutionCurator");
|
|
2021
2021
|
const result = curator ? await curator.consolidate(target, sources) : {
|
|
2022
2022
|
ok: false,
|
|
@@ -2027,7 +2027,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2027
2027
|
}
|
|
2028
2028
|
if (input.startsWith("skill restore ")) {
|
|
2029
2029
|
const name = input.slice(14).trim();
|
|
2030
|
-
if (!name) return err("
|
|
2030
|
+
if (!name) return err("用法:/evolution skill restore <name>");
|
|
2031
2031
|
const skillRestoreRefusal = unreplayableWriteRefusal("skill restore");
|
|
2032
2032
|
if (skillRestoreRefusal) return skillRestoreRefusal;
|
|
2033
2033
|
const curator = ctx.get("evolutionCurator");
|
|
@@ -2039,22 +2039,22 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2039
2039
|
}
|
|
2040
2040
|
if (input.startsWith("skill history ")) {
|
|
2041
2041
|
const name = input.slice(14).trim();
|
|
2042
|
-
if (!name) return err("
|
|
2042
|
+
if (!name) return err("用法:/evolution skill history <name>");
|
|
2043
2043
|
const curator = ctx.get("evolutionCurator");
|
|
2044
2044
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
2045
2045
|
const versions = await curator.history(name);
|
|
2046
|
-
if (versions.length === 0) return ok(
|
|
2046
|
+
if (versions.length === 0) return ok(`技能 "${name}" 还没有内容版本:下一次经 skill_manage 写入后才会出现。`);
|
|
2047
2047
|
const groups = partitionVersions(versions);
|
|
2048
2048
|
const row = (entry) => `v${entry.v}\t${entry.at}\t${entry.action}\t${entry.chars} chars\t${entry.hash.slice(0, 12)}`;
|
|
2049
|
-
const lines = [
|
|
2050
|
-
if (groups.support.length > 0) lines.push("
|
|
2049
|
+
const lines = [`技能 "${name}" 的内容版本(由旧到新,${groups.content.length} 条,最多保留这么多):`, ...groups.content.map(row)];
|
|
2050
|
+
if (groups.support.length > 0) lines.push("支撑文件版本(仅在历史里 —— 撤销恢复的是 SKILL.md,不是这些字节):", ...groups.support.map(row));
|
|
2051
2051
|
return ok(lines.join("\n"));
|
|
2052
2052
|
}
|
|
2053
2053
|
if (input.startsWith("skill undo ")) {
|
|
2054
2054
|
const rest = input.slice(11).trim();
|
|
2055
2055
|
const toMatch = /--to\s+v?(\d+)\s*$/.exec(rest);
|
|
2056
2056
|
const name = (toMatch?.index === void 0 ? rest : rest.slice(0, toMatch.index)).trim();
|
|
2057
|
-
if (!name) return err("
|
|
2057
|
+
if (!name) return err("用法:/evolution skill undo <name> [--to v<N>]");
|
|
2058
2058
|
const skillUndoRefusal = unreplayableWriteRefusal("skill undo");
|
|
2059
2059
|
if (skillUndoRefusal) return skillUndoRefusal;
|
|
2060
2060
|
const curator = ctx.get("evolutionCurator");
|
|
@@ -2068,9 +2068,9 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2068
2068
|
if (input === "skill pin" || input.startsWith("skill pin ") || input === "skill unpin" || input.startsWith("skill unpin ")) {
|
|
2069
2069
|
const pinned = !input.startsWith("skill unpin");
|
|
2070
2070
|
const name = input.slice(pinned ? 10 : 12).trim();
|
|
2071
|
-
if (!name) return err(
|
|
2071
|
+
if (!name) return err(`用法:/evolution skill ${pinned ? "pin" : "unpin"} <name>`);
|
|
2072
2072
|
const ioRegistry = ctx.get("evolutionIo");
|
|
2073
|
-
if (!ioRegistry) return err("
|
|
2073
|
+
if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法固定或取消固定技能。");
|
|
2074
2074
|
const result = await newSkillLibrary({
|
|
2075
2075
|
config: { root: skillsRootValue },
|
|
2076
2076
|
io: preferProvider(ioRegistry, ["fs"]),
|
|
@@ -2086,14 +2086,31 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2086
2086
|
const curator = ctx.get("evolutionCurator");
|
|
2087
2087
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
2088
2088
|
const [rows, observed] = await Promise.all([curator.healthView(), curator.usageObserved()]);
|
|
2089
|
-
const banner = observed ? "" : "
|
|
2090
|
-
const line = (row) =>
|
|
2091
|
-
|
|
2092
|
-
|
|
2089
|
+
const banner = observed ? "" : "使用观测尚未建立 —— 频繁变动(写入幽灵)行已被抑制。";
|
|
2090
|
+
const line = (row) => {
|
|
2091
|
+
const detail = (row.findings ?? []).map((f) => f.rule + " x" + String(f.count)).join(", ");
|
|
2092
|
+
return row.verdict.padEnd(18) + " " + row.name + (detail === "" ? "" : " — " + detail);
|
|
2093
|
+
};
|
|
2094
|
+
const tally = /* @__PURE__ */ new Map();
|
|
2095
|
+
for (const row of rows) for (const f of row.findings ?? []) {
|
|
2096
|
+
const hit = tally.get(f.rule);
|
|
2097
|
+
if (hit === void 0) tally.set(f.rule, {
|
|
2098
|
+
count: 1,
|
|
2099
|
+
severity: f.severity
|
|
2100
|
+
});
|
|
2101
|
+
else hit.count += 1;
|
|
2102
|
+
}
|
|
2103
|
+
const aggregate = tally.size === 0 ? [] : ["Main causes: " + [...tally.entries()].sort((a, b) => b[1].count - a[1].count).map(([rule, v]) => `${rule} (${v.severity}) x${v.count}`).join(", ")];
|
|
2104
|
+
if (rows.length === 0) return ok(["Structure health: no degraded row was reported (this does NOT assert that every skill is readable).", banner].filter(Boolean).join(" "));
|
|
2105
|
+
return ok([
|
|
2106
|
+
banner ? `Structure health (${rows.length} degraded): ${banner}` : `Structure health (${rows.length} degraded):`,
|
|
2107
|
+
...aggregate,
|
|
2108
|
+
...rows.map(line)
|
|
2109
|
+
].join("\n"));
|
|
2093
2110
|
}
|
|
2094
2111
|
if (input === "skills refresh") {
|
|
2095
2112
|
ctx.emit("evolution/skills-refresh");
|
|
2096
|
-
return ok("
|
|
2113
|
+
return ok("已请求重读技能目录:缓存已丢弃,下次查询时重新读取。");
|
|
2097
2114
|
}
|
|
2098
2115
|
if (input === "learn" || input.startsWith("learn ")) {
|
|
2099
2116
|
const request = rawInputTrimmed === "learn" ? "" : rawInputTrimmed.slice(6).trim();
|
|
@@ -2125,12 +2142,12 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2125
2142
|
}).catch((error) => {
|
|
2126
2143
|
ctx.logger.warn(`evolution-commands: failed to record learn event: ${String(error)}`);
|
|
2127
2144
|
});
|
|
2128
|
-
return woke ? ok("
|
|
2145
|
+
return woke ? ok("已向本会话发送学习请求,请现在执行。") : ok("学习请求已排入本会话队列:本宿主没有唤醒通道,会在你下一条消息时读取。");
|
|
2129
2146
|
}
|
|
2130
2147
|
const factsParsed = parseSubcommand(input);
|
|
2131
2148
|
if (!isParseFailure(factsParsed) && factsParsed.name === "maintain" && factsParsed.flags.get("facts") === true && factsParsed.positionals.length === 0) {
|
|
2132
2149
|
const ioRegistry = ctx.get("evolutionIo");
|
|
2133
|
-
if (!ioRegistry) return err("
|
|
2150
|
+
if (!ioRegistry) return err("未挂载 evolution-io 注册表:维护事实不可用。");
|
|
2134
2151
|
const library = newSkillLibrary({
|
|
2135
2152
|
config: { root: skillsRootValue },
|
|
2136
2153
|
io: preferProvider(ioRegistry, ["fs"])
|
|
@@ -2144,31 +2161,31 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2144
2161
|
ctx.logger.warn(`evolution-maintenance: skipping unreadable skill "${name}": ${error instanceof Error ? error.message : String(error)}`);
|
|
2145
2162
|
}
|
|
2146
2163
|
});
|
|
2147
|
-
if (snapshots.length === 0 && readFailures.length > 0) return err(
|
|
2148
|
-
if (snapshots.length === 0 && skillsRootValue !== "" && !await preferProvider(ioRegistry, ["fs"]).exists(skillsRootValue)) return err(
|
|
2149
|
-
if (snapshots.length === 0) return ok("
|
|
2164
|
+
if (snapshots.length === 0 && readFailures.length > 0) return err(`维护扫描读不出 ${readFailures.length} 个已登记技能(${readFailures.slice(0, 10).join(", ")}${readFailures.length > 10 ? ", …" : ""}),且一个技能都没读到:技能库未被审计。请修好读不出的技能(或它们的目录名)后重新扫描`);
|
|
2165
|
+
if (snapshots.length === 0 && skillsRootValue !== "" && !await preferProvider(ioRegistry, ["fs"]).exists(skillsRootValue)) return err(`维护扫描发现技能库为空,但配置的技能根目录不存在(${skillsRootValue}):请把 skillsRoot 指向真实目录(字面量 \`~\` 不会被展开),然后重新扫描`);
|
|
2166
|
+
if (snapshots.length === 0) return ok("维护扫描:技能库为空,无需处理。");
|
|
2150
2167
|
const { facts } = buildMaintainFacts(snapshots, enrichment.usageObservedValue, void 0);
|
|
2151
|
-
return ok(
|
|
2168
|
+
return ok(`维护事实(零 token 预览):\n${facts}`);
|
|
2152
2169
|
}
|
|
2153
2170
|
const maintainParsed = parseSubcommand(input);
|
|
2154
2171
|
const maintainFlagsDeclared = [...isParseFailure(maintainParsed) ? [] : maintainParsed.flags.keys()].every((flag) => flagsOf("maintain").includes("--" + flag));
|
|
2155
2172
|
if (!isParseFailure(maintainParsed) && maintainParsed.name === "maintain" && maintainParsed.positionals.length === 0 && maintainFlagsDeclared) {
|
|
2156
2173
|
const timeoutFlag = maintainParsed.flags.get("timeout");
|
|
2157
2174
|
const runTimeoutMs = typeof timeoutFlag === "string" ? Number(timeoutFlag) : config.maintainTimeoutMs ?? 6e5;
|
|
2158
|
-
if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > MAX_TIMER_DELAY_MS) return err(timeoutFlag !== void 0 ?
|
|
2175
|
+
if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > MAX_TIMER_DELAY_MS) return err(timeoutFlag !== void 0 ? `--timeout 值不合法:应为不超过 ${MAX_TIMER_DELAY_MS} 的正整数毫秒(例如 /evolution maintain --timeout 600000)。` : `maintainTimeoutMs 配置不合法:应为不超过 ${MAX_TIMER_DELAY_MS} 的正整数毫秒。请修正 evolution-commands 行的配置(maintainTimeoutMs)后重试。`);
|
|
2159
2176
|
const registry = runs;
|
|
2160
|
-
if (!registry) return err("
|
|
2177
|
+
if (!registry) return err("未挂载 evolution-io 注册表:维护扫描不可用。");
|
|
2161
2178
|
const synced = await syncRuns(registry);
|
|
2162
2179
|
if (!synced.ok) ctx.logger.warn(`evolution-commands: ${synced.note ?? "run index unreadable"} — the in-flight guard cannot see other processes' runs`);
|
|
2163
2180
|
else if (synced.note !== void 0) ctx.logger.warn(`evolution-commands: ${synced.note}`);
|
|
2164
2181
|
const ioRegistry = ctx.get("evolutionIo");
|
|
2165
2182
|
const subagents = ctx.get("subagents");
|
|
2166
|
-
if (!ioRegistry) return err("
|
|
2167
|
-
if (!subagents) return err("
|
|
2183
|
+
if (!ioRegistry) return err("未挂载 evolution-io 注册表:维护扫描不可用。");
|
|
2184
|
+
if (!subagents) return err("未挂载子智能体服务:维护扫描不可用。");
|
|
2168
2185
|
const running = registry.inFlight();
|
|
2169
2186
|
if (running) {
|
|
2170
2187
|
const elapsed = Math.max(1, Math.round((Date.now() - running.startedAt) / 1e3));
|
|
2171
|
-
return err(
|
|
2188
|
+
return err(`维护运行 ${running.id} 已经在进行中(约 ${elapsed}s 前启动):现在重交会再开一次扫描。查看状态:/evolution maintain status ${running.id};停止它:/evolution maintain cancel ${running.id}。`);
|
|
2172
2189
|
}
|
|
2173
2190
|
const cooldownMs = clampedNumber(config.maintainCooldownMs, 3e4, { min: 0 });
|
|
2174
2191
|
const lastSettled = registry.lastSettledAt();
|
|
@@ -2176,7 +2193,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2176
2193
|
if (cooldownMs > 0 && sinceLast < cooldownMs) {
|
|
2177
2194
|
const remaining = Math.ceil((cooldownMs - sinceLast) / 1e3);
|
|
2178
2195
|
const latest = registry.runs().find((record) => record.state !== "running");
|
|
2179
|
-
return err(
|
|
2196
|
+
return err(`维护冷却中(${remaining}s)${latest === void 0 ? "" : `,最近一次运行 ${latest.id}`}:现在重跑会再消耗一次模型调用。`);
|
|
2180
2197
|
}
|
|
2181
2198
|
const runHome = evolutionHome();
|
|
2182
2199
|
const runRoot = evolutionRoot();
|
|
@@ -2267,7 +2284,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2267
2284
|
} catch (error) {
|
|
2268
2285
|
ctx.logger.warn(`evolution-commands: automatic report handoff failed (${String(error)})`);
|
|
2269
2286
|
}
|
|
2270
|
-
} else ctx.logger.warn(`evolution-commands: maintenance run ${handle.id} produced no plan (${outcome.error ?? "
|
|
2287
|
+
} else ctx.logger.warn(`evolution-commands: maintenance run ${handle.id} produced no plan (${outcome.error ?? "原因未知"})`);
|
|
2271
2288
|
} catch (error) {
|
|
2272
2289
|
const aborted = handle.signal.aborted;
|
|
2273
2290
|
const failure = aborted ? "cancelled: the scan was stopped before it settled" : `Maintenance scan failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -2288,20 +2305,20 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2288
2305
|
const maintainStatus = subcommandOf(input, "maintain", "status", flagsOf("maintain"));
|
|
2289
2306
|
if (maintainStatus !== null) {
|
|
2290
2307
|
const registry = runs;
|
|
2291
|
-
if (!registry) return err("
|
|
2308
|
+
if (!registry) return err("未挂载 evolution-io 注册表:无法查看运行状态。");
|
|
2292
2309
|
const synced = await syncRuns(registry);
|
|
2293
2310
|
const wanted = maintainStatus.positionals[1];
|
|
2294
2311
|
if (wanted !== void 0) {
|
|
2295
2312
|
const record = registry.find(wanted);
|
|
2296
2313
|
if (!record) {
|
|
2297
|
-
if (!synced.ok) return err(
|
|
2298
|
-
return err(
|
|
2314
|
+
if (!synced.ok) return err(`运行 ${wanted} 不在本进程的历史里,且本 home 的运行索引读不出来(${synced.note ?? "原因未知"}):但这不能证明那次运行没发生过。`);
|
|
2315
|
+
return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
|
|
2299
2316
|
}
|
|
2300
|
-
return ok(synced.ok ? renderRunRecord(record) : `${renderRunRecord(record)}\n(
|
|
2317
|
+
return ok(synced.ok ? renderRunRecord(record) : `${renderRunRecord(record)}\n(运行索引读不出来:${synced.note ?? "原因未知"} — only this process's view is shown)`);
|
|
2301
2318
|
}
|
|
2302
|
-
if (!synced.ok) return err(
|
|
2319
|
+
if (!synced.ok) return err(`本 home 的运行历史读不出来(${synced.note ?? "原因未知"}):这「不是」没有运行。要开始干净的历史,请修好或删除 <evolutionHome>/runs.json。`);
|
|
2303
2320
|
const all = registry.runs();
|
|
2304
|
-
if (all.length === 0) return ok("
|
|
2321
|
+
if (all.length === 0) return ok("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
|
|
2305
2322
|
const live = all.filter((record) => record.state === "running");
|
|
2306
2323
|
const recent = all.filter((record) => record.state !== "running").slice(0, 5);
|
|
2307
2324
|
return ok([live.length === 0 ? "No maintenance run in flight." : `In flight:\n${live.map(renderRunRecord).join("\n")}`, recent.length === 0 ? "" : `Recent:\n${recent.map(renderRunRecord).join("\n")}`].filter((part) => part !== "").join("\n"));
|
|
@@ -2309,7 +2326,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2309
2326
|
const maintainReport = subcommandOf(input, "maintain", "report", flagsOf("maintain"));
|
|
2310
2327
|
if (maintainReport !== null) {
|
|
2311
2328
|
const registry = runs;
|
|
2312
|
-
if (!registry) return err("
|
|
2329
|
+
if (!registry) return err("未挂载 evolution-io 注册表:无法查看运行结果。");
|
|
2313
2330
|
const synced = await syncRuns(registry);
|
|
2314
2331
|
const wanted = maintainReport.positionals[1];
|
|
2315
2332
|
if (wanted === void 0 && !synced.ok) return err(unreadableIndex(synced.note));
|
|
@@ -2317,22 +2334,22 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2317
2334
|
if (!record) {
|
|
2318
2335
|
if (wanted !== void 0) {
|
|
2319
2336
|
if (!synced.ok) return err(unreadableForId(wanted, synced.note));
|
|
2320
|
-
return err(
|
|
2337
|
+
return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
|
|
2321
2338
|
}
|
|
2322
|
-
return err("
|
|
2339
|
+
return err("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
|
|
2323
2340
|
}
|
|
2324
|
-
if (wanted === void 0 && record.state === "running") return err(
|
|
2341
|
+
if (wanted === void 0 && record.state === "running") return err(`最新一次运行 ${record.id} 仍在进行:它结束后才会出报告;用 /evolution maintain status ${record.id} 查看进度。`);
|
|
2325
2342
|
const ioRegistry = ctx.get("evolutionIo");
|
|
2326
|
-
if (!ioRegistry) return err("
|
|
2343
|
+
if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法查看运行结果。");
|
|
2327
2344
|
const probed = await readRunReport(preferProvider(ioRegistry, ["fs"]), record);
|
|
2328
|
-
if (probed.kind === "missing") return err(
|
|
2329
|
-
if (probed.kind === "unknown") return err(
|
|
2345
|
+
if (probed.kind === "missing") return err(`运行 ${record.id}(${record.state})没有结果:没有写出报告${record.failure === void 0 ? "" : `(${record.failure})`}。`);
|
|
2346
|
+
if (probed.kind === "unknown") return err(`运行 ${record.id} 有报告但读不出来(${probed.reason}):这「不是」没有结果。`);
|
|
2330
2347
|
return ok(probed.text);
|
|
2331
2348
|
}
|
|
2332
2349
|
const maintainCancel = subcommandOf(input, "maintain", "cancel", flagsOf("maintain"));
|
|
2333
2350
|
if (maintainCancel !== null) {
|
|
2334
2351
|
const registry = runs;
|
|
2335
|
-
if (!registry) return err("
|
|
2352
|
+
if (!registry) return err("未挂载 evolution-io 注册表:无法取消运行。");
|
|
2336
2353
|
const synced = await syncRuns(registry);
|
|
2337
2354
|
const wanted = maintainCancel.positionals[1];
|
|
2338
2355
|
if (wanted === void 0 && !synced.ok) return err(unreadableIndex(synced.note));
|
|
@@ -2340,21 +2357,21 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2340
2357
|
if (!record) {
|
|
2341
2358
|
if (wanted !== void 0) {
|
|
2342
2359
|
if (!synced.ok) return err(unreadableForId(wanted, synced.note));
|
|
2343
|
-
return err(
|
|
2360
|
+
return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
|
|
2344
2361
|
}
|
|
2345
|
-
return err("
|
|
2362
|
+
return err("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
|
|
2346
2363
|
}
|
|
2347
|
-
const idlessHint = wanted === void 0 ? "
|
|
2364
|
+
const idlessHint = wanted === void 0 ? " 要取消某次运行请带上 id:/evolution maintain status 会列出它们。" : "";
|
|
2348
2365
|
if (!registry.cancel(record.id)) {
|
|
2349
|
-
if (record.state === "running") return err(
|
|
2350
|
-
return err(
|
|
2366
|
+
if (record.state === "running") return err(`运行 ${record.id} 正在共享本 home 的另一个进程里运行:只能在那里取消。`);
|
|
2367
|
+
return err(`运行 ${record.id} 已经是 ${record.state}:没有可取消的东西。${idlessHint}`);
|
|
2351
2368
|
}
|
|
2352
|
-
return ok(
|
|
2369
|
+
return ok(`维护运行 ${record.id} 已取消:扫描会在下一个检查点停止。用 /evolution maintain status ${record.id} 查看终态。`);
|
|
2353
2370
|
}
|
|
2354
2371
|
const maintainHandoff = subcommandOf(input, "maintain", "handoff", flagsOf("maintain"));
|
|
2355
2372
|
if (maintainHandoff !== null) {
|
|
2356
2373
|
const registry = runs;
|
|
2357
|
-
if (!registry) return err("
|
|
2374
|
+
if (!registry) return err("未挂载 evolution-io 注册表:无法交付报告。");
|
|
2358
2375
|
const synced = await syncRuns(registry);
|
|
2359
2376
|
const wanted = maintainHandoff.positionals[1];
|
|
2360
2377
|
if (wanted === void 0 && !synced.ok) return err(unreadableIndex(synced.note));
|
|
@@ -2362,16 +2379,16 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2362
2379
|
if (!record) {
|
|
2363
2380
|
if (wanted !== void 0) {
|
|
2364
2381
|
if (!synced.ok) return err(unreadableForId(wanted, synced.note));
|
|
2365
|
-
return err(
|
|
2382
|
+
return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
|
|
2366
2383
|
}
|
|
2367
|
-
return err("
|
|
2384
|
+
return err("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
|
|
2368
2385
|
}
|
|
2369
|
-
if (wanted === void 0 && record.state === "running") return err(
|
|
2386
|
+
if (wanted === void 0 && record.state === "running") return err(`最新一次运行 ${record.id} 仍在进行:它结束后才会出报告;用 /evolution maintain status ${record.id} 查看进度。`);
|
|
2370
2387
|
const ioRegistry = ctx.get("evolutionIo");
|
|
2371
|
-
if (!ioRegistry) return err("
|
|
2388
|
+
if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法交付报告。");
|
|
2372
2389
|
const probed = await readRunReport(preferProvider(ioRegistry, ["fs"]), record);
|
|
2373
|
-
if (probed.kind === "missing") return err(
|
|
2374
|
-
if (probed.kind === "unknown") return err(
|
|
2390
|
+
if (probed.kind === "missing") return err(`运行 ${record.id}(${record.state})没有结果:没有写出报告${record.failure === void 0 ? "" : `(${record.failure})`}。`);
|
|
2391
|
+
if (probed.kind === "unknown") return err(`运行 ${record.id} 有报告但读不出来(${probed.reason}):这「不是」没有结果。`);
|
|
2375
2392
|
const missingAgent = agentMissing("handoff");
|
|
2376
2393
|
if (missingAgent) return missingAgent;
|
|
2377
2394
|
const woke = deliverHandoff(invocationAgent, createUserMessage({
|
|
@@ -2392,9 +2409,9 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2392
2409
|
}
|
|
2393
2410
|
}));
|
|
2394
2411
|
if (woke === void 0) return err(errorText("e-305-the-invocation-agent-exposes", { a1: "this maintenance handoff" }));
|
|
2395
|
-
return ok(woke ?
|
|
2412
|
+
return ok(woke ? `已把运行 ${record.id} 交给模型 —— 报告:${reportDigestPath(record)}。它会读取该文件并执行其中的行动项。` : `已把运行 ${record.id} 交给模型并排队 —— 本宿主没有唤醒通道,因此会在你下一条消息时被读取。`);
|
|
2396
2413
|
}
|
|
2397
|
-
if (/^maintain\b/.test(input)) return err("
|
|
2414
|
+
if (/^maintain\b/.test(input)) return err("未知的 maintain 参数:应为 `maintain`、`maintain --timeout <ms>` / `maintain --timeout=<ms>`、`maintain status [<id>]`、`maintain report [<id>]`、`maintain handoff [<id>]` 或 `maintain cancel [<id>]`。实际收到:" + input);
|
|
2398
2415
|
const presetParsed = parseSubcommand(input);
|
|
2399
2416
|
const presetInstall = isParseFailure(presetParsed) || presetParsed.name !== "preset" ? null : presetParsed.positionals[0] === "install" && presetParsed.positionals.length === 1 && [...presetParsed.flags.keys()].every((flag) => flagsOf("preset").includes("--" + flag)) ? presetParsed : false;
|
|
2400
2417
|
if (presetInstall !== null && presetInstall !== false) {
|
|
@@ -2405,11 +2422,11 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2405
2422
|
dir: mounted.profileDir,
|
|
2406
2423
|
bundles: mounted.bundles
|
|
2407
2424
|
});
|
|
2408
|
-
if (exclusion.kind === "undecidable") return err(
|
|
2425
|
+
if (exclusion.kind === "undecidable") return err(`拒绝安装分层 Evolution 预设:${exclusion.reason}:all/preset 双重挂载检查无法执行。请解决该 profile 的访问权限后重试,或改用分层安装器——它会在安装前就执行同一套排除检查。`);
|
|
2409
2426
|
const installedBundles = exclusion.bundles;
|
|
2410
2427
|
const allBundle = installedBundles.find((name) => name === "dsh-evolution-all" || name.endsWith("/dsh-evolution-all"));
|
|
2411
2428
|
const presetBundle = installedBundles.find((name) => name === "dsh-evolution-preset" || name.endsWith("/dsh-evolution-preset"));
|
|
2412
|
-
if (allBundle || presetBundle) return err(
|
|
2429
|
+
if (allBundle || presetBundle) return err(`拒绝安装分层 Evolution 预设:本 profile 里已安装「${allBundle ?? presetBundle}」:它的模型行(tool-memory / tool-skill-manage / tool-session-query / skill-catalog)会与预设的重复挂载,profile 启动时会直接报错。只保留一个:安装分层预设前先移除 ${allBundle ? "evolution-all bundle" : "evolution-preset bundle"}(见 /evolution doctor)。`);
|
|
2413
2430
|
}
|
|
2414
2431
|
try {
|
|
2415
2432
|
const source = resolveAgentPresetDir(import.meta.url);
|
|
@@ -2417,17 +2434,17 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2417
2434
|
const baseFlag = presetInstall.flags.get("base");
|
|
2418
2435
|
const requestedRaw = typeof baseFlag === "string" ? baseFlag : table.defaultBase;
|
|
2419
2436
|
const requested = [...new Set(requestedRaw.split(",").map((part) => part.trim()).filter((part) => part !== ""))];
|
|
2420
|
-
if (requested.length === 0) return err(
|
|
2437
|
+
if (requested.length === 0) return err(`没有指定 agent-preset 基名:${join(source, "bases.json")} 里列出的是 ${table.entries.map((entry) => entry.name).join(", ")}`);
|
|
2421
2438
|
const selected = [];
|
|
2422
2439
|
for (const name of requested) {
|
|
2423
2440
|
const entry = table.entries.find((candidate) => candidate.name === name);
|
|
2424
|
-
if (entry === void 0) return err(
|
|
2441
|
+
if (entry === void 0) return err(`未知的 agent-preset 基名「${name}」:${join(source, "bases.json")} 里列出的是 ${table.entries.map((candidate) => candidate.name).join(", ")}`);
|
|
2425
2442
|
selected.push(entry);
|
|
2426
2443
|
}
|
|
2427
2444
|
const deltaPath = join(source, "agent.cordis.yml");
|
|
2428
|
-
if (!existsSync(deltaPath)) return err(
|
|
2445
|
+
if (!existsSync(deltaPath)) return err(`预设文件在 ${source} 里缺失:是否装了 dsh-evolution-agent-preset 包?`);
|
|
2429
2446
|
const profile = presetProfileTarget(ctx);
|
|
2430
|
-
if (profile === void 0) return err("
|
|
2447
|
+
if (profile === void 0) return err("本进程没有挂载任何 profile,因此没有可写入预设行的 profile 补丁:请在由 `dsh --profile <name>` 启动的会话里执行该命令。");
|
|
2431
2448
|
const delta = readFileSync(deltaPath, "utf8");
|
|
2432
2449
|
const hmr = ctx.get("hmr");
|
|
2433
2450
|
const commit = () => {
|
|
@@ -2456,33 +2473,33 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2456
2473
|
}], void 0, (message) => {
|
|
2457
2474
|
ctx.logger.warn(message);
|
|
2458
2475
|
});
|
|
2459
|
-
return ok(
|
|
2476
|
+
return ok(`已写入 evolution agent preset 行(${written.join("; ")})。重启会话切换器后即可选中它。`);
|
|
2460
2477
|
};
|
|
2461
2478
|
const runExclusive = hmr?.runExclusive;
|
|
2462
2479
|
if (runExclusive === void 0) return commit();
|
|
2463
2480
|
return await runExclusive.call(hmr, commit);
|
|
2464
2481
|
} catch (error) {
|
|
2465
|
-
return err(
|
|
2482
|
+
return err(`预设安装失败:${error instanceof Error ? error.message : String(error)}`);
|
|
2466
2483
|
}
|
|
2467
2484
|
}
|
|
2468
2485
|
if (input.startsWith("restructure ")) {
|
|
2469
2486
|
const restParsed = parseSubcommand(rawInputTrimmed);
|
|
2470
|
-
if (isParseFailure(restParsed) || restParsed.name !== "restructure") return err("
|
|
2487
|
+
if (isParseFailure(restParsed) || restParsed.name !== "restructure") return err("用法:/evolution restructure <name> \"<## heading>\" <to_file>");
|
|
2471
2488
|
const name = restParsed.positionals[0] ?? "";
|
|
2472
2489
|
const heading = restParsed.positionals[1] ?? "";
|
|
2473
2490
|
const toFile = restParsed.positionals[2] ?? "";
|
|
2474
|
-
if (name === "" || heading === "" || toFile === "") return err("
|
|
2491
|
+
if (name === "" || heading === "" || toFile === "") return err("用法:/evolution restructure <name> \"<## heading>\" <to_file>");
|
|
2475
2492
|
const planFlag = restParsed.flags.get("plan");
|
|
2476
2493
|
const planRunId = typeof planFlag === "string" ? planFlag : void 0;
|
|
2477
|
-
if (!toFile.startsWith("references/")) return err("to_file
|
|
2494
|
+
if (!toFile.startsWith("references/")) return err("to_file 必须位于 references/ 之下(日志或明细的落地位置)。");
|
|
2478
2495
|
const ioRegistry = ctx.get("evolutionIo");
|
|
2479
|
-
if (!ioRegistry) return err("
|
|
2496
|
+
if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法重构。");
|
|
2480
2497
|
if (approval) {
|
|
2481
2498
|
const session = invocationAgent?.session;
|
|
2482
2499
|
const sessionPolicy = effectiveSessionPolicy(ctx, session);
|
|
2483
2500
|
const stagesForeground = approval.isEnabled !== false && sessionPolicy !== "never" && approval.stageForeground !== false;
|
|
2484
2501
|
if (stagesForeground && session === void 0) return err(errorText("e-306-this-deployment-stages-foreground-2"));
|
|
2485
|
-
if (stagesForeground && !approval.hasRunner("skill")) return err("
|
|
2502
|
+
if (stagesForeground && !approval.hasRunner("skill")) return err("无法暂存重构:没有注册技能回放运行器:请挂载 tool-skill-manage 行(evolution-agent 预设或 evolution-all),或禁用 evolution-approval。");
|
|
2486
2503
|
const decision = await approval.request({
|
|
2487
2504
|
kind: "skill",
|
|
2488
2505
|
summary: `/evolution restructure ${name}${planRunId ? ` (plan ${planRunId})` : ""}`,
|
|
@@ -2556,7 +2573,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2556
2573
|
return ok(renderParamRows(selected, { providerMounted: provider !== void 0 }));
|
|
2557
2574
|
}
|
|
2558
2575
|
const policyParsed = parseSubcommand(input);
|
|
2559
|
-
if (isParseFailure(policyParsed) && policyParsed.name === "policy" && policyParsed.kind === "missing-value") return err("/evolution policy set
|
|
2576
|
+
if (isParseFailure(policyParsed) && policyParsed.name === "policy" && policyParsed.kind === "missing-value") return err("/evolution policy set 需要在 --" + (policyParsed.flag ?? "") + ";用法:policy set <id> <value> [--expect <revision>]");
|
|
2560
2577
|
if (!isParseFailure(policyParsed) && policyParsed.name === "policy" && policyParsed.positionals[0] === "set") {
|
|
2561
2578
|
const provider = ctx.get("settings");
|
|
2562
2579
|
if (provider?.update === void 0 || provider.describe === void 0) return err(errorText("e-311-no-settings-service-is"));
|
|
@@ -2651,7 +2668,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2651
2668
|
return ok(renderDoctorText(report));
|
|
2652
2669
|
}
|
|
2653
2670
|
if (input === "" || input === "help") return ok(`自进化:记忆、技能、会话回顾、技能整理——状态、待批准写入与维护。\n${renderHelpText()}`);
|
|
2654
|
-
return err(`/evolution ${input}
|
|
2671
|
+
return err(`/evolution ${input} 不是本构建能应答的子命令(已知子命令但缺参数也会落到这里)。\n${renderHint()}`);
|
|
2655
2672
|
} };
|
|
2656
2673
|
/** The registered definition: declared members only (A46). */
|
|
2657
2674
|
const evolutionCommand = {
|
|
@@ -2660,7 +2677,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
2660
2677
|
input: { hint: renderHint() },
|
|
2661
2678
|
handler: (invocation) => commandBody.run(invocation).catch((error) => ({
|
|
2662
2679
|
kind: "error",
|
|
2663
|
-
text: `evolution
|
|
2680
|
+
text: `evolution:命令失败:${error instanceof Error ? error.message : String(error)}\n请运行 /evolution doctor 检查服务与状态文件;损坏的状态文件会被隔离为 <file> 以便检查。`
|
|
2664
2681
|
}))
|
|
2665
2682
|
};
|
|
2666
2683
|
commandCtx.effect(() => commands.register(evolutionCommand));
|
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.
|
|
4
|
+
"version": "0.25.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,18 +27,18 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
30
|
-
"@lmzhen/dsh-evolution-approval": "^0.
|
|
31
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
32
|
-
"@lmzhen/dsh-evolution-maintenance": "^0.
|
|
30
|
+
"@lmzhen/dsh-evolution-approval": "^0.25.0",
|
|
31
|
+
"@lmzhen/dsh-evolution-core": "^0.25.0",
|
|
32
|
+
"@lmzhen/dsh-evolution-maintenance": "^0.25.0"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@lmzhen/dsh-evolution-agent-preset": "^0.
|
|
35
|
+
"@lmzhen/dsh-evolution-agent-preset": "^0.25.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
39
39
|
"@deepseek-ai/dsh-commands": "^0.2.0-rc.1",
|
|
40
40
|
"@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
|
|
41
|
-
"@lmzhen/dsh-evolution-io": "^0.
|
|
41
|
+
"@lmzhen/dsh-evolution-io": "^0.25.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@deepseek-ai/dsh-commands": "^0.2.0-rc.1"
|