@lmzhen/dsh-evolution-commands 0.8.0 → 0.10.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 +97 -31
- package/lib/types/params.d.ts +0 -6
- package/package.json +5 -5
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { effectiveSessionPolicy } from "@lmzhen/dsh-evolution-approval";
|
|
4
4
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
5
|
-
import { DEFAULT_SKILL_LIMITS, MAX_TIMER_DELAY_MS, PARAM_EXPOSURE, PARAM_NAMESPACES, appendEvolutionEvent, assertSkillsRootAliasRetired, buildLearnPrompt, canonicalWriteId, clampedNumber, composePresetComposition, errorText, eventsFile, evolutionRoot, isDeprecatedParamId, isMissingPath, newSkillLibrary, policyStageLimits, resolveParamId, resolveRootConfig, scopedProbeReport } from "@lmzhen/dsh-evolution-core";
|
|
5
|
+
import { DEFAULT_SKILL_LIMITS, MAX_TIMER_DELAY_MS, PARAM_EXPOSURE, PARAM_GROUP_LABELS, PARAM_NAMESPACES, appendEvolutionEvent, assertSkillsRootAliasRetired, buildLearnPrompt, canonicalWriteId, clampedNumber, composePresetComposition, errorText, eventsFile, evolutionRoot, isDeprecatedParamId, isMissingPath, newSkillLibrary, orderVersions, policyStageLimits, resolveParamId, resolveRootConfig, scopedProbeReport } from "@lmzhen/dsh-evolution-core";
|
|
6
6
|
import { buildEnrichment, buildMaintainFacts, runMaintain, snapshotFromLibrary } from "@lmzhen/dsh-evolution-maintenance";
|
|
7
7
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
@@ -643,15 +643,46 @@ function renderValue(value) {
|
|
|
643
643
|
if (typeof value === "string") return value;
|
|
644
644
|
return JSON.stringify(value);
|
|
645
645
|
}
|
|
646
|
+
const WIDE_CHAR = new RegExp("[" + [
|
|
647
|
+
"ᄀ-ᅟ",
|
|
648
|
+
"⺀-〾",
|
|
649
|
+
"ぁ-㏿",
|
|
650
|
+
"㐀-䶿",
|
|
651
|
+
"一-鿿",
|
|
652
|
+
"가-힣",
|
|
653
|
+
"豈-",
|
|
654
|
+
"︰-",
|
|
655
|
+
"-⦆",
|
|
656
|
+
"¢-₩"
|
|
657
|
+
].join("") + "]");
|
|
646
658
|
/**
|
|
647
|
-
*
|
|
648
|
-
* @param
|
|
649
|
-
* @param
|
|
650
|
-
* @returns the
|
|
659
|
+
* Pad one cell to a display width, counting CJK characters as two columns.
|
|
660
|
+
* @param text - the cell text.
|
|
661
|
+
* @param columns - the target width in terminal columns.
|
|
662
|
+
* @returns the text plus at least one space, so columns never touch.
|
|
651
663
|
*/
|
|
664
|
+
function pad(text, columns) {
|
|
665
|
+
let used = 0;
|
|
666
|
+
for (const char of text) used += WIDE_CHAR.test(char) ? 2 : 1;
|
|
667
|
+
return text + " ".repeat(Math.max(1, columns - used));
|
|
668
|
+
}
|
|
669
|
+
/** Settings timing, in the operator's words. */
|
|
670
|
+
const APPLIES_LABELS = Object.freeze({
|
|
671
|
+
live: "立即",
|
|
672
|
+
restart: "重启后",
|
|
673
|
+
none: "不生效"
|
|
674
|
+
});
|
|
675
|
+
/** Where a row's effective value comes from, in the operator's words. */
|
|
676
|
+
const SOURCE_LABELS = Object.freeze({
|
|
677
|
+
user: "我改过",
|
|
678
|
+
deployment: "默认",
|
|
679
|
+
unregistered: "不可改"
|
|
680
|
+
});
|
|
681
|
+
/** What the E-tiers mean, so the count line reads without the docs. */
|
|
682
|
+
const TIER_LEGEND = "档位:E0 固定/E1 只读/E2 安装时定/E3 你可改/E4 装完固化。";
|
|
652
683
|
function renderParamRows(rows, options) {
|
|
653
|
-
const header = "
|
|
654
|
-
const body = rows.map((row) => row.id
|
|
684
|
+
const header = pad("参数", 36) + pad("分组", 12) + pad("档位", 6) + pad("生效", 8) + pad("来源", 10) + "当前值";
|
|
685
|
+
const body = rows.map((row) => pad(row.id, 36) + pad(PARAM_GROUP_LABELS[row.group], 12) + pad(row.tier, 6) + pad(APPLIES_LABELS[row.applies] ?? row.applies, 8) + pad(SOURCE_LABELS[row.source] ?? row.source, 10) + renderValue(row.value));
|
|
655
686
|
const tiers = [
|
|
656
687
|
"E0",
|
|
657
688
|
"E1",
|
|
@@ -660,13 +691,14 @@ function renderParamRows(rows, options) {
|
|
|
660
691
|
"E4"
|
|
661
692
|
].map((tier) => `${tier} ${rows.filter((row) => row.tier === tier).length}`).join(" / ");
|
|
662
693
|
const userRows = rows.filter((row) => row.source === "user").length;
|
|
663
|
-
const
|
|
664
|
-
const note = options.providerMounted ? "
|
|
694
|
+
const counts = options.providerMounted ? `共 ${rows.length} 个参数:${tiers};你改过的:${userRows} 项。` : `共 ${rows.length} 个参数:${tiers};是否改过:未知(没有设置服务)。`;
|
|
695
|
+
const note = options.providerMounted ? "来源:我改过=你在设置里改的;默认=安装时的配置;不可改=该功能不提供用户可改项。" : "设置服务未挂载——读不到你改过的值,所以每行显示的都是安装时的配置(这不等于「你没改过」)。";
|
|
665
696
|
return [
|
|
666
697
|
header,
|
|
667
698
|
...body,
|
|
668
699
|
"",
|
|
669
|
-
|
|
700
|
+
counts,
|
|
701
|
+
TIER_LEGEND,
|
|
670
702
|
note
|
|
671
703
|
].join("\n");
|
|
672
704
|
}
|
|
@@ -709,79 +741,87 @@ function renderParamJson(rows) {
|
|
|
709
741
|
const COMMAND_ENTRIES = [
|
|
710
742
|
{
|
|
711
743
|
usage: "pending [--detail]",
|
|
712
|
-
summary: "
|
|
744
|
+
summary: "列出暂存的写入(--detail 显示参数)"
|
|
713
745
|
},
|
|
714
746
|
{
|
|
715
747
|
usage: "approve <id>",
|
|
716
|
-
summary: "
|
|
748
|
+
summary: "执行一条已批准的写入"
|
|
717
749
|
},
|
|
718
750
|
{
|
|
719
751
|
usage: "reject <id>",
|
|
720
|
-
summary: "
|
|
752
|
+
summary: "丢弃一条暂存写入,不执行"
|
|
721
753
|
},
|
|
722
754
|
{
|
|
723
755
|
usage: "release <id>",
|
|
724
|
-
summary: "
|
|
756
|
+
summary: "把卡在执行中的写入放回待批窗口(先确认效果再批准 or reject)"
|
|
725
757
|
},
|
|
726
758
|
{
|
|
727
759
|
usage: "doctor [--json]",
|
|
728
|
-
summary: "
|
|
760
|
+
summary: "只读自检:安装形态、冲突、环境、服务(--json 供脚本用)"
|
|
729
761
|
},
|
|
730
762
|
{
|
|
731
763
|
usage: "curator run|pause|resume|status|report|scope",
|
|
732
|
-
summary: "
|
|
764
|
+
summary: "立即运行一次自动整理,或暂停/恢复/查看状态"
|
|
733
765
|
},
|
|
734
766
|
{
|
|
735
767
|
usage: "mutations",
|
|
736
|
-
summary: "
|
|
768
|
+
summary: "列出技能改动记录"
|
|
737
769
|
},
|
|
738
770
|
{
|
|
739
771
|
usage: "restore",
|
|
740
|
-
summary: "
|
|
772
|
+
summary: "从最近的快照恢复技能"
|
|
741
773
|
},
|
|
742
774
|
{
|
|
743
775
|
usage: "consolidate <target> <sources...> [--plan <runId>]",
|
|
744
|
-
summary: "
|
|
776
|
+
summary: "把若干技能合并进一个总括技能"
|
|
745
777
|
},
|
|
746
778
|
{
|
|
747
779
|
usage: "skill restore <name>",
|
|
748
|
-
summary: "
|
|
780
|
+
summary: "按名字恢复一个已归档的技能"
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
usage: "skill history <name>",
|
|
784
|
+
summary: "列出某个技能的内容版本(含时间、动作、字符数、哈希前缀)"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
usage: "skill undo <name> [--to v<N>]",
|
|
788
|
+
summary: "把某个技能的内容回退到某一版(默认上一版;只动内容,撤销本身也记为一版)"
|
|
749
789
|
},
|
|
750
790
|
{
|
|
751
791
|
usage: "skills health",
|
|
752
|
-
summary: "
|
|
792
|
+
summary: "技能库结构体检"
|
|
753
793
|
},
|
|
754
794
|
{
|
|
755
795
|
usage: "skills refresh",
|
|
756
|
-
summary: "
|
|
796
|
+
summary: "丢弃目录缓存并重新读取技能树"
|
|
757
797
|
},
|
|
758
798
|
{
|
|
759
799
|
usage: "learn [request]",
|
|
760
|
-
summary: "
|
|
800
|
+
summary: "向本会话发一条学习请求"
|
|
761
801
|
},
|
|
762
802
|
{
|
|
763
803
|
usage: "maintain [--timeout=<ms> | --facts]",
|
|
764
|
-
summary: "
|
|
804
|
+
summary: "运行一次维护扫描(--facts 为 0 token 预览)"
|
|
765
805
|
},
|
|
766
806
|
{
|
|
767
807
|
usage: "policy set <id> <value> [--expect <revision>]",
|
|
768
|
-
summary: "
|
|
808
|
+
summary: "通过设置服务写入一个你可改的参数 (E3 only; E1/E2 stay in cordis.yml)"
|
|
769
809
|
},
|
|
770
810
|
{
|
|
771
811
|
usage: "params [--group <name>] [--json]",
|
|
772
|
-
summary: "
|
|
812
|
+
summary: "列出全部参数:分组、档位、生效时机、来源与当前值(--json feeds scripts)"
|
|
773
813
|
},
|
|
774
814
|
{
|
|
775
815
|
usage: "preset install [--base <name>[,<name>...]]",
|
|
776
|
-
summary: "
|
|
816
|
+
summary: "按指定基础生成自进化 Agent 预设到用户 root (bases from the agent package's bases.json)"
|
|
777
817
|
},
|
|
778
818
|
{
|
|
779
819
|
usage: "restructure <name> \"<heading>\" <to_file> [--plan <runId>]",
|
|
780
|
-
summary: "
|
|
820
|
+
summary: "把技能正文的一节移到 references 文件"
|
|
781
821
|
},
|
|
782
822
|
{
|
|
783
823
|
usage: "replay",
|
|
784
|
-
summary: "
|
|
824
|
+
summary: "比较不同会话与重启之间的计划结果(从活动记录回填)"
|
|
785
825
|
}
|
|
786
826
|
];
|
|
787
827
|
/** The input-declaration hint (single line, ` | `-separated). */
|
|
@@ -818,7 +858,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
818
858
|
const commands = commandCtx.commands;
|
|
819
859
|
const evolutionCommand = {
|
|
820
860
|
name: "evolution",
|
|
821
|
-
description: "
|
|
861
|
+
description: "自进化:状态与待批准写入",
|
|
822
862
|
recordInput: false,
|
|
823
863
|
input: { hint: renderHint() },
|
|
824
864
|
run: async (invocation) => {
|
|
@@ -989,6 +1029,32 @@ function apply(ctx, rawConfig = {}) {
|
|
|
989
1029
|
};
|
|
990
1030
|
return result.ok ? ok(result.message) : err(result.message);
|
|
991
1031
|
}
|
|
1032
|
+
if (input.startsWith("skill history ")) {
|
|
1033
|
+
const name = input.slice(14).trim();
|
|
1034
|
+
if (!name) return err("Usage: /evolution skill history <name>");
|
|
1035
|
+
const curator = ctx.get("evolutionCurator");
|
|
1036
|
+
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
1037
|
+
const versions = await curator.history(name);
|
|
1038
|
+
if (versions.length === 0) return ok(`No content versions are recorded for "${name}" yet — they appear after the next write through skill_manage.`);
|
|
1039
|
+
const ordered = orderVersions(versions);
|
|
1040
|
+
const rows = ordered.map((entry) => `v${entry.v}\t${entry.at}\t${entry.action}\t${entry.chars} chars\t${entry.hash.slice(0, 12)}`);
|
|
1041
|
+
return ok([`Content versions for "${name}" (oldest first, ${ordered.length} of at most the retained count):`, ...rows].join("\n"));
|
|
1042
|
+
}
|
|
1043
|
+
if (input.startsWith("skill undo ")) {
|
|
1044
|
+
const rest = input.slice(11).trim();
|
|
1045
|
+
const toMatch = /--to\s+v?(\d+)\s*$/.exec(rest);
|
|
1046
|
+
const name = (toMatch?.index === void 0 ? rest : rest.slice(0, toMatch.index)).trim();
|
|
1047
|
+
if (!name) return err("Usage: /evolution skill undo <name> [--to v<N>]");
|
|
1048
|
+
const skillUndoRefusal = unreplayableWriteRefusal("skill undo");
|
|
1049
|
+
if (skillUndoRefusal) return skillUndoRefusal;
|
|
1050
|
+
const curator = ctx.get("evolutionCurator");
|
|
1051
|
+
const target = toMatch?.[1] === void 0 ? void 0 : Number(toMatch[1]);
|
|
1052
|
+
const result = curator ? await (target === void 0 ? curator.undo(name) : curator.undo(name, target)) : {
|
|
1053
|
+
ok: false,
|
|
1054
|
+
message: errorText("e-302-curator-service-not-mounted")
|
|
1055
|
+
};
|
|
1056
|
+
return result.ok ? ok(result.message) : err(result.message);
|
|
1057
|
+
}
|
|
992
1058
|
if (input === "skills health") {
|
|
993
1059
|
const curator = ctx.get("evolutionCurator");
|
|
994
1060
|
if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
|
|
@@ -1341,7 +1407,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
1341
1407
|
if (input === "doctor --json") return ok(JSON.stringify(report, null, 2));
|
|
1342
1408
|
return ok(renderDoctorText(report));
|
|
1343
1409
|
}
|
|
1344
|
-
return ok(
|
|
1410
|
+
return ok(`自进化:记忆、技能、会话回顾、技能整理——状态、待批准写入与维护。\n${renderHelpText()}`);
|
|
1345
1411
|
},
|
|
1346
1412
|
handler: (invocation) => evolutionCommand.run(invocation).catch((error) => ({
|
|
1347
1413
|
kind: "error",
|
package/lib/types/params.d.ts
CHANGED
|
@@ -52,12 +52,6 @@ export declare function paramSurfaceRows(sections: ReadonlyMap<string, ParamSect
|
|
|
52
52
|
* @returns distinct group names.
|
|
53
53
|
*/
|
|
54
54
|
export declare function paramGroups(entries?: readonly ParamExposure[]): string[];
|
|
55
|
-
/**
|
|
56
|
-
* Render the rows as fixed-width text (one parameter per line, never truncated).
|
|
57
|
-
* @param rows - rows from {@link paramSurfaceRows}.
|
|
58
|
-
* @param options - whether the settings service answered at all.
|
|
59
|
-
* @returns the command text.
|
|
60
|
-
*/
|
|
61
55
|
export declare function renderParamRows(rows: readonly ParamSurfaceRow[], options: {
|
|
62
56
|
providerMounted: boolean;
|
|
63
57
|
}): string;
|
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.10.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
30
|
-
"@lmzhen/dsh-evolution-approval": "^0.
|
|
31
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
32
|
-
"@lmzhen/dsh-evolution-maintenance": "^0.
|
|
30
|
+
"@lmzhen/dsh-evolution-approval": "^0.10.0",
|
|
31
|
+
"@lmzhen/dsh-evolution-core": "^0.10.0",
|
|
32
|
+
"@lmzhen/dsh-evolution-maintenance": "^0.10.0"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@lmzhen/dsh-evolution-agent-preset": "^0.
|
|
35
|
+
"@lmzhen/dsh-evolution-agent-preset": "^0.10.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.1",
|