@lmzhen/dsh-evolution-commands 0.30.17 → 0.30.19
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 +137 -2
- package/lib/types/command-catalog.d.ts +87 -0
- package/lib/types/doctor.d.ts +8 -0
- package/lib/types/index.d.ts +1 -0
- package/package.json +5 -5
package/lib/index.js
CHANGED
|
@@ -1477,6 +1477,8 @@ async function diagnose(ctx, options = {}) {
|
|
|
1477
1477
|
actions.push(`Preset row for base "${row.base}" in ${row.destination} DIFFERS from a fresh generation — it is an install-time snapshot; re-run the installer (/evolution preset install) to regenerate`);
|
|
1478
1478
|
}
|
|
1479
1479
|
const view = buildDoctorView(await assembleDoctorInputs(ctx));
|
|
1480
|
+
const merge = await mergeDoctorLine(ctx);
|
|
1481
|
+
if (merge.status !== "ok" && merge.remedy !== void 0) actions.push("合并行:" + merge.remedy);
|
|
1480
1482
|
return {
|
|
1481
1483
|
installForm,
|
|
1482
1484
|
deploymentForm,
|
|
@@ -1500,7 +1502,35 @@ async function diagnose(ctx, options = {}) {
|
|
|
1500
1502
|
dormantBundles,
|
|
1501
1503
|
serviceSource: reviewRow === void 0 ? "bundles" : "platform",
|
|
1502
1504
|
actions,
|
|
1503
|
-
view
|
|
1505
|
+
view,
|
|
1506
|
+
merge
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Probe the merge plugin's global-doctor line. The plugin exposes `doctorFact()` (which composes
|
|
1511
|
+
* its wire DoctorView); this module never reads merge files itself, so core stays free of merge
|
|
1512
|
+
* rows and the two producers cannot drift.
|
|
1513
|
+
* @param ctx - the host service view.
|
|
1514
|
+
* @returns the one-line merge fact; unknown on absence or failure (doctor must answer).
|
|
1515
|
+
*/
|
|
1516
|
+
async function mergeDoctorLine(ctx) {
|
|
1517
|
+
const service = ctx.get("evolutionMerge");
|
|
1518
|
+
if (service?.doctorFact === void 0) return {
|
|
1519
|
+
status: "unknown",
|
|
1520
|
+
detail: "evolutionMerge 服务未挂载:本安装形态没有合并行",
|
|
1521
|
+
remedy: "安装含 evolution-merge 的 bundle 后重新运行 /evolution doctor"
|
|
1522
|
+
};
|
|
1523
|
+
const probed = await probeBounded(() => service.doctorFact(), "merge doctor");
|
|
1524
|
+
if (!probed.ok) return {
|
|
1525
|
+
status: "unknown",
|
|
1526
|
+
detail: "合并状态探测失败:" + probed.message,
|
|
1527
|
+
remedy: "运行 /evolution merge doctor 查看详情"
|
|
1528
|
+
};
|
|
1529
|
+
const value = probed.value;
|
|
1530
|
+
return {
|
|
1531
|
+
status: value.status === "ok" || value.status === "warn" || value.status === "fail" || value.status === "unknown" ? value.status : "unknown",
|
|
1532
|
+
detail: typeof value.detail === "string" && value.detail !== "" ? value.detail : "合并状态探测没有返回 detail",
|
|
1533
|
+
...typeof value.remedy === "string" && value.remedy !== "" ? { remedy: value.remedy } : {}
|
|
1504
1534
|
};
|
|
1505
1535
|
}
|
|
1506
1536
|
/**
|
|
@@ -1642,6 +1672,9 @@ function renderDoctorText(report) {
|
|
|
1642
1672
|
if (report.dormantBundles.length > 0) extras.push(`installed but not selected: ${report.dormantBundles.join(", ")} — the Plugins page lists them; this runtime mounts neither`);
|
|
1643
1673
|
extras.push(`bundles (all profiles): ${report.bundles.length > 0 ? report.bundles.join(", ") : "(none)"}`);
|
|
1644
1674
|
extras.push(`services: review=${report.services.review} (${report.serviceSource === "platform" ? "the live row, this runtime" : "inferred from bundles, all profiles"}) curator=${report.services.curator} approval=${report.services.approval} skillUsage=${report.services.skillUsage} io=${report.services.io}`);
|
|
1675
|
+
const mergeStatus = report.merge.status === "ok" ? "正常" : report.merge.status === "warn" ? "注意" : report.merge.status === "fail" ? "异常" : "未知";
|
|
1676
|
+
extras.push("merge: [" + mergeStatus + "] " + report.merge.detail + (report.merge.remedy === void 0 ? "" : ";下一步:" + report.merge.remedy));
|
|
1677
|
+
if (report.merge.status !== "ok" && report.merge.remedy !== void 0) extras.push(" → " + report.merge.remedy);
|
|
1645
1678
|
if (report.capabilityAbsence.length > 0) extras.push(`capability absence (${report.capabilityAbsence.length}): ${report.capabilityAbsence.map((entry) => `${entry.service} — ${entry.feature}`).join("; ")}`);
|
|
1646
1679
|
extras.push(scopedProbeLine(report.scopedProbe));
|
|
1647
1680
|
extras.push(legacyLine(report.legacy));
|
|
@@ -2178,6 +2211,108 @@ function parseSubcommand(input) {
|
|
|
2178
2211
|
};
|
|
2179
2212
|
}
|
|
2180
2213
|
//#endregion
|
|
2214
|
+
//#region lib/types/command-catalog.js
|
|
2215
|
+
function buildSurface(defs, prefix) {
|
|
2216
|
+
const defaults = (def) => Object.fromEntries(def.flags.flatMap((flag) => {
|
|
2217
|
+
if (flag.default !== void 0) return [[flag.name, flag.default]];
|
|
2218
|
+
return flag.kind === "boolean" ? [[flag.name, "false"]] : [];
|
|
2219
|
+
}));
|
|
2220
|
+
return {
|
|
2221
|
+
wireVersion: 1,
|
|
2222
|
+
prefix,
|
|
2223
|
+
commands: defs.filter((def) => def.surface !== false).map((def) => ({
|
|
2224
|
+
id: def.id,
|
|
2225
|
+
words: def.words,
|
|
2226
|
+
flags: def.flags,
|
|
2227
|
+
positional: def.positional,
|
|
2228
|
+
readOnly: def.readOnly,
|
|
2229
|
+
needsRun: def.needsRun,
|
|
2230
|
+
defaults: defaults(def),
|
|
2231
|
+
rowActions: (def.rowActions ?? []).map((action) => ({
|
|
2232
|
+
id: action.id,
|
|
2233
|
+
command: action.command,
|
|
2234
|
+
confirm: action.confirm === true
|
|
2235
|
+
})),
|
|
2236
|
+
fallback: def.fallback
|
|
2237
|
+
})),
|
|
2238
|
+
fallback: defs.filter((def) => def.surface !== false && (def.rowActions === void 0 || def.rowActions.length === 0)).map((def) => ({
|
|
2239
|
+
id: def.id,
|
|
2240
|
+
command: def.fallback
|
|
2241
|
+
}))
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
function parseCommand(defs, argv) {
|
|
2245
|
+
const [verb, ...rest] = argv;
|
|
2246
|
+
if (verb === void 0 || verb === "help" || verb === "--help" || verb === "-h") return {
|
|
2247
|
+
ok: true,
|
|
2248
|
+
id: "help",
|
|
2249
|
+
values: {},
|
|
2250
|
+
help: true
|
|
2251
|
+
};
|
|
2252
|
+
const candidates = defs.filter((item) => item.words.includes(verb));
|
|
2253
|
+
const def = candidates.find((item) => rest.filter((token) => token.startsWith("--")).every((token) => item.flags.some((flag) => flag.name === token.slice(2)))) ?? candidates[0];
|
|
2254
|
+
if (def === void 0) return {
|
|
2255
|
+
ok: false,
|
|
2256
|
+
code: "usage",
|
|
2257
|
+
message: "unknown command: " + verb
|
|
2258
|
+
};
|
|
2259
|
+
const values = {};
|
|
2260
|
+
const positional = [];
|
|
2261
|
+
for (let index = 0; index < rest.length; index += 1) {
|
|
2262
|
+
const token = rest[index];
|
|
2263
|
+
if (!token.startsWith("--")) {
|
|
2264
|
+
positional.push(token);
|
|
2265
|
+
continue;
|
|
2266
|
+
}
|
|
2267
|
+
const name = token.slice(2);
|
|
2268
|
+
const flag = def.flags.find((item) => item.name === name);
|
|
2269
|
+
if (flag === void 0) return {
|
|
2270
|
+
ok: false,
|
|
2271
|
+
code: "usage",
|
|
2272
|
+
message: "unknown flag: --" + name
|
|
2273
|
+
};
|
|
2274
|
+
if (flag.kind === "boolean") values[name] = true;
|
|
2275
|
+
else {
|
|
2276
|
+
const value = rest[index + 1];
|
|
2277
|
+
if (value === void 0 || value.startsWith("--")) return {
|
|
2278
|
+
ok: false,
|
|
2279
|
+
code: "usage",
|
|
2280
|
+
message: "missing value for --" + name
|
|
2281
|
+
};
|
|
2282
|
+
values[name] = value;
|
|
2283
|
+
index += 1;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
for (const flag of def.flags) if (flag.required === true && values[flag.name] === void 0) return {
|
|
2287
|
+
ok: false,
|
|
2288
|
+
code: "usage",
|
|
2289
|
+
message: "missing required flag: --" + flag.name
|
|
2290
|
+
};
|
|
2291
|
+
const required = def.positional.filter((item) => item.required).length;
|
|
2292
|
+
if (positional.length < required || positional.length > def.positional.length) return {
|
|
2293
|
+
ok: false,
|
|
2294
|
+
code: "usage",
|
|
2295
|
+
message: "usage: " + def.fallback
|
|
2296
|
+
};
|
|
2297
|
+
def.positional.forEach((item, index) => {
|
|
2298
|
+
const value = positional[index];
|
|
2299
|
+
if (value !== void 0) values[item.name] = value;
|
|
2300
|
+
});
|
|
2301
|
+
return {
|
|
2302
|
+
ok: true,
|
|
2303
|
+
id: def.id,
|
|
2304
|
+
values
|
|
2305
|
+
};
|
|
2306
|
+
}
|
|
2307
|
+
function aliasRegistration(version, def) {
|
|
2308
|
+
if (def.deprecatedAt === void 0) return "registered";
|
|
2309
|
+
const [major, minor] = version.split(".").map(Number);
|
|
2310
|
+
const [depMajor = 0, depMinor = 0] = def.deprecatedAt.split(".").map(Number);
|
|
2311
|
+
if ((major ?? 0) > depMajor || (major ?? 0) === depMajor && (minor ?? 0) >= depMinor + 1) return "removed";
|
|
2312
|
+
if ((major ?? 0) === depMajor && (minor ?? 0) === depMinor) return "deprecated";
|
|
2313
|
+
return "registered";
|
|
2314
|
+
}
|
|
2315
|
+
//#endregion
|
|
2181
2316
|
//#region lib/types/index.js
|
|
2182
2317
|
/**
|
|
2183
2318
|
* Human commands for the evolution family: /evolution learn|pending|curator|restore|consolidate|skills refresh.
|
|
@@ -3342,4 +3477,4 @@ function safeStagedArgs(args) {
|
|
|
3342
3477
|
}
|
|
3343
3478
|
}
|
|
3344
3479
|
//#endregion
|
|
3345
|
-
export { Config, apply, atomicWriteFiles, name };
|
|
3480
|
+
export { Config, aliasRegistration, apply, atomicWriteFiles, buildSurface, name, parseCommand };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** Family command catalog: one source for parser/help/surface/fallback. */
|
|
2
|
+
export interface CommandFlagDef {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly kind: 'boolean' | 'value';
|
|
5
|
+
readonly valueName?: string;
|
|
6
|
+
readonly repeatable?: boolean;
|
|
7
|
+
readonly values?: readonly string[];
|
|
8
|
+
readonly default?: string;
|
|
9
|
+
readonly required?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface CommandPositionalDef {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly kind: 'skill' | 'target' | 'runId' | 'id' | 'json' | 'text';
|
|
14
|
+
readonly required: boolean;
|
|
15
|
+
readonly variadic?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface RowActionDef {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly command: string;
|
|
20
|
+
readonly confirm?: boolean;
|
|
21
|
+
readonly enabledWhen?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface CommandDef {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly words: readonly string[];
|
|
26
|
+
readonly summaryKey: string;
|
|
27
|
+
readonly helpKey: string;
|
|
28
|
+
readonly flags: readonly CommandFlagDef[];
|
|
29
|
+
readonly positional: readonly CommandPositionalDef[];
|
|
30
|
+
readonly readOnly: boolean;
|
|
31
|
+
readonly needsRun: boolean;
|
|
32
|
+
readonly aliases?: readonly string[];
|
|
33
|
+
readonly rowActions?: readonly RowActionDef[];
|
|
34
|
+
readonly fallback: string;
|
|
35
|
+
readonly deprecatedAt?: '0.31' | '0.32';
|
|
36
|
+
readonly surface?: boolean;
|
|
37
|
+
readonly usage?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface CommandSurfaceCommand {
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly words: readonly string[];
|
|
42
|
+
readonly flags: readonly {
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly kind: 'boolean' | 'value';
|
|
45
|
+
readonly valueName?: string;
|
|
46
|
+
readonly repeatable?: boolean;
|
|
47
|
+
readonly values?: readonly string[];
|
|
48
|
+
}[];
|
|
49
|
+
readonly positional: readonly {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly kind: 'skill' | 'target' | 'runId' | 'id' | 'json' | 'text';
|
|
52
|
+
readonly required: boolean;
|
|
53
|
+
readonly variadic?: boolean;
|
|
54
|
+
}[];
|
|
55
|
+
readonly readOnly: boolean;
|
|
56
|
+
readonly needsRun: boolean;
|
|
57
|
+
readonly defaults: Readonly<Record<string, string>>;
|
|
58
|
+
readonly rowActions: readonly {
|
|
59
|
+
readonly id: string;
|
|
60
|
+
readonly command: string;
|
|
61
|
+
readonly confirm: boolean;
|
|
62
|
+
}[];
|
|
63
|
+
readonly fallback: string;
|
|
64
|
+
}
|
|
65
|
+
export interface CommandSurfaceView {
|
|
66
|
+
readonly wireVersion: 1;
|
|
67
|
+
readonly prefix: string;
|
|
68
|
+
readonly commands: readonly CommandSurfaceCommand[];
|
|
69
|
+
readonly fallback: readonly {
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly command: string;
|
|
72
|
+
}[];
|
|
73
|
+
}
|
|
74
|
+
export type ParsedCommand = {
|
|
75
|
+
readonly ok: true;
|
|
76
|
+
readonly id: string;
|
|
77
|
+
readonly values: Readonly<Record<string, string | true>>;
|
|
78
|
+
readonly help?: true;
|
|
79
|
+
} | {
|
|
80
|
+
readonly ok: false;
|
|
81
|
+
readonly code: 'usage';
|
|
82
|
+
readonly message: string;
|
|
83
|
+
};
|
|
84
|
+
export declare function buildSurface(defs: readonly CommandDef[], prefix: string): CommandSurfaceView;
|
|
85
|
+
export declare function parseCommand(defs: readonly CommandDef[], argv: readonly string[]): ParsedCommand;
|
|
86
|
+
export declare function aliasRegistration(version: string, def: CommandDef): 'registered' | 'deprecated' | 'removed';
|
|
87
|
+
//# sourceMappingURL=command-catalog.d.ts.map
|
package/lib/types/doctor.d.ts
CHANGED
|
@@ -60,6 +60,12 @@ export interface LegacyMigrationRow {
|
|
|
60
60
|
/** Keys still waiting for their row, as `rowId.key`. */
|
|
61
61
|
readonly pending: readonly string[];
|
|
62
62
|
}
|
|
63
|
+
/** The merge plugin's one-line contribution to the global doctor (cross-plugin read). */
|
|
64
|
+
export interface MergeDoctorLine {
|
|
65
|
+
readonly status: 'ok' | 'warn' | 'fail' | 'unknown';
|
|
66
|
+
readonly detail: string;
|
|
67
|
+
readonly remedy?: string;
|
|
68
|
+
}
|
|
63
69
|
export interface DoctorReport {
|
|
64
70
|
/** OPT-23 (2026-09): `preset-only` — the delivered Evolution preset
|
|
65
71
|
* artifact exists but NO profile carries an evolution bundle (e.g. the
|
|
@@ -144,6 +150,8 @@ export interface DoctorReport {
|
|
|
144
150
|
/** G6/W8 tail: the frozen DiagnosticsView (7 facts + 8 runtime rows) — the SAME object the
|
|
145
151
|
* diagnostics route and the client card render; `--json` emits it and the text renderer prints it. */
|
|
146
152
|
readonly view: DiagnosticsView;
|
|
153
|
+
/** The merge row: produced by the merge plugin's buildDoctorView consumer; absent service = unknown. */
|
|
154
|
+
readonly merge: MergeDoctorLine;
|
|
147
155
|
}
|
|
148
156
|
/** Profile bundle rows for evolution-family packages across all profiles.
|
|
149
157
|
*
|
package/lib/types/index.d.ts
CHANGED
|
@@ -73,4 +73,5 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
73
73
|
threatExemptLabels: z<string[], string[], "defined">;
|
|
74
74
|
}>>, "plain">;
|
|
75
75
|
export declare function apply(ctx: Context, rawConfig?: Config): void;
|
|
76
|
+
export * from './command-catalog.ts';
|
|
76
77
|
//# sourceMappingURL=index.d.ts.map
|
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.30.
|
|
4
|
+
"version": "0.30.19",
|
|
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.5",
|
|
30
|
-
"@lmzhen/dsh-evolution-approval": "^0.30.
|
|
31
|
-
"@lmzhen/dsh-evolution-core": "^0.30.
|
|
32
|
-
"@lmzhen/dsh-evolution-maintenance": "^0.30.
|
|
30
|
+
"@lmzhen/dsh-evolution-approval": "^0.30.19",
|
|
31
|
+
"@lmzhen/dsh-evolution-core": "^0.30.19",
|
|
32
|
+
"@lmzhen/dsh-evolution-maintenance": "^0.30.19"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@lmzhen/dsh-evolution-agent-preset": "^0.30.
|
|
35
|
+
"@lmzhen/dsh-evolution-agent-preset": "^0.30.19"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.5",
|