@fenglimg/fabric-cli 2.1.0-rc.2 → 2.2.0-rc.1
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/dist/{chunk-PWLW3B57.js → chunk-2CY4BMTH.js} +5 -1
- package/dist/{chunk-F46ORPOA.js → chunk-2R55HNVD.js} +82 -5
- package/dist/{chunk-HFQVXY6P.js → chunk-4R2CYEA4.js} +31 -1
- package/dist/{chunk-BATF4PEJ.js → chunk-AOE6AYI7.js} +2 -2
- package/dist/{chunk-WWNXR34K.js → chunk-BO4XIZWZ.js} +8 -1
- package/dist/{chunk-MF3OTILQ.js → chunk-XC5RUHLK.js} +29 -8
- package/dist/{config-XJIPZNUP.js → config-XYRBZJDU.js} +3 -3
- package/dist/{doctor-QVNPHLJK.js → doctor-YONYXDX6.js} +39 -26
- package/dist/index.js +54 -14
- package/dist/{install-2HDO5FTQ.js → install-74ANPCCP.js} +88 -34
- package/dist/{metrics-ACEQFPDU.js → metrics-RER6NLFC.js} +22 -9
- package/dist/{onboard-coverage-MFCAEBDO.js → onboard-coverage-JWQWDZW7.js} +1 -1
- package/dist/{scope-explain-2F2R5URO.js → scope-explain-CDIZESP5.js} +6 -2
- package/dist/{store-XTSE5TY6.js → store-XB3ADT65.js} +50 -11
- package/dist/{sync-BJCWDPNC.js → sync-UJ4BBCZJ.js} +18 -12
- package/dist/{uninstall-TAXSUSKH.js → uninstall-C3QXKOO6.js} +35 -4
- package/dist/{whoami-B6AEMSEV.js → whoami-2MLO4Y37.js} +10 -5
- package/package.json +3 -3
- package/templates/hooks/fabric-hint.cjs +99 -7
- package/templates/hooks/knowledge-hint-broad.cjs +164 -9
- package/templates/hooks/knowledge-hint-narrow.cjs +10 -4
- package/templates/hooks/lib/injection-log.cjs +91 -0
- package/templates/hooks/lib/state-store.cjs +30 -11
- package/templates/skills/fabric-audit/SKILL.md +53 -0
- package/templates/skills/fabric-connect/SKILL.md +48 -0
- package/templates/skills/fabric-review/SKILL.md +2 -0
- package/templates/skills/fabric-review/ref/cite-contract.md +56 -0
- package/templates/skills/fabric-store/SKILL.md +44 -0
|
@@ -8,11 +8,15 @@ import {
|
|
|
8
8
|
} from "@fenglimg/fabric-shared";
|
|
9
9
|
var locale = detectNodeLocale();
|
|
10
10
|
var t = createTranslator(locale);
|
|
11
|
-
function
|
|
11
|
+
function getProjectTranslator(projectRoot = process.cwd()) {
|
|
12
12
|
return createTranslator(resolveFabricLocale(projectRoot));
|
|
13
13
|
}
|
|
14
|
+
function getDoctorTranslator(projectRoot) {
|
|
15
|
+
return getProjectTranslator(projectRoot);
|
|
16
|
+
}
|
|
14
17
|
|
|
15
18
|
export {
|
|
16
19
|
t,
|
|
20
|
+
getProjectTranslator,
|
|
17
21
|
getDoctorTranslator
|
|
18
22
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
deepMerge
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XC5RUHLK.js";
|
|
5
5
|
|
|
6
6
|
// src/install/write-bootstrap-snapshot.ts
|
|
7
7
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -55,6 +55,9 @@ var SKILL_TEMPLATE_REL = "skills/fabric-archive/SKILL.md";
|
|
|
55
55
|
var SKILL_REVIEW_TEMPLATE_REL = "skills/fabric-review/SKILL.md";
|
|
56
56
|
var SKILL_IMPORT_TEMPLATE_REL = "skills/fabric-import/SKILL.md";
|
|
57
57
|
var SKILL_SYNC_TEMPLATE_REL = "skills/fabric-sync/SKILL.md";
|
|
58
|
+
var SKILL_STORE_TEMPLATE_REL = "skills/fabric-store/SKILL.md";
|
|
59
|
+
var SKILL_AUDIT_TEMPLATE_REL = "skills/fabric-audit/SKILL.md";
|
|
60
|
+
var SKILL_CONNECT_TEMPLATE_REL = "skills/fabric-connect/SKILL.md";
|
|
58
61
|
var HOOK_SCRIPT_TEMPLATE_REL = "hooks/fabric-hint.cjs";
|
|
59
62
|
var HOOK_BROAD_SCRIPT_TEMPLATE_REL = "hooks/knowledge-hint-broad.cjs";
|
|
60
63
|
var HOOK_NARROW_SCRIPT_TEMPLATE_REL = "hooks/knowledge-hint-narrow.cjs";
|
|
@@ -81,6 +84,23 @@ var SKILL_DESTINATIONS = {
|
|
|
81
84
|
fabricSync: [
|
|
82
85
|
".claude/skills/fabric-sync/SKILL.md",
|
|
83
86
|
".codex/skills/fabric-sync/SKILL.md"
|
|
87
|
+
],
|
|
88
|
+
// v2.1 ADJ-NEWN-1/#4: fabric-store knowledge-store ops skill, same 2-client
|
|
89
|
+
// coverage as the sibling skills.
|
|
90
|
+
fabricStore: [
|
|
91
|
+
".claude/skills/fabric-store/SKILL.md",
|
|
92
|
+
".codex/skills/fabric-store/SKILL.md"
|
|
93
|
+
],
|
|
94
|
+
// v2.2 SK1-audit (W2-T5): fabric-audit semantic-deprecation skill, same
|
|
95
|
+
// 2-client coverage as the sibling skills.
|
|
96
|
+
fabricAudit: [
|
|
97
|
+
".claude/skills/fabric-audit/SKILL.md",
|
|
98
|
+
".codex/skills/fabric-audit/SKILL.md"
|
|
99
|
+
],
|
|
100
|
+
// v2.2 SK2-connect (W3-T2): fabric-connect knowledge-graph relation skill.
|
|
101
|
+
fabricConnect: [
|
|
102
|
+
".claude/skills/fabric-connect/SKILL.md",
|
|
103
|
+
".codex/skills/fabric-connect/SKILL.md"
|
|
84
104
|
]
|
|
85
105
|
};
|
|
86
106
|
var DEPRECATED_SKILL_DIRS = [
|
|
@@ -128,7 +148,11 @@ var HOOK_CONFIG_TARGETS = {
|
|
|
128
148
|
cursor: ".cursor/hooks.json"
|
|
129
149
|
};
|
|
130
150
|
var HOOK_CONFIG_ARRAY_PATHS = {
|
|
131
|
-
|
|
151
|
+
// F2: "hooks.UserPromptSubmit" MUST be listed — the Claude Code template
|
|
152
|
+
// ships a UserPromptSubmit cite-policy hook, so without this path deepMerge
|
|
153
|
+
// array-REPLACEs (instead of append-with-dedupe) on re-install, silently
|
|
154
|
+
// clobbering any user-defined UserPromptSubmit hook.
|
|
155
|
+
claudeCode: ["hooks.Stop", "hooks.SessionStart", "hooks.PreToolUse", "hooks.UserPromptSubmit"],
|
|
132
156
|
codex: ["events.Stop", "events.SessionStart", "events.PreToolUse"],
|
|
133
157
|
cursor: ["hooks.stop", "hooks.sessionStart", "hooks.preToolUse"]
|
|
134
158
|
};
|
|
@@ -136,17 +160,22 @@ var FABRIC_HOOK_COMMAND_PATHS = {
|
|
|
136
160
|
claudeCode: {
|
|
137
161
|
fabricHint: "${CLAUDE_PROJECT_DIR}/.claude/hooks/fabric-hint.cjs",
|
|
138
162
|
knowledgeHintBroad: "${CLAUDE_PROJECT_DIR}/.claude/hooks/knowledge-hint-broad.cjs",
|
|
139
|
-
knowledgeHintNarrow: "${CLAUDE_PROJECT_DIR}/.claude/hooks/knowledge-hint-narrow.cjs"
|
|
163
|
+
knowledgeHintNarrow: "${CLAUDE_PROJECT_DIR}/.claude/hooks/knowledge-hint-narrow.cjs",
|
|
164
|
+
// F3: the UserPromptSubmit cite-policy-evict hook must be a known fabric
|
|
165
|
+
// command so uninstall prunes it (matches the literal in claude-code.json).
|
|
166
|
+
citePolicyEvict: "${CLAUDE_PROJECT_DIR}/.claude/hooks/cite-policy-evict.cjs"
|
|
140
167
|
},
|
|
141
168
|
codex: {
|
|
142
169
|
fabricHint: '"$(git rev-parse --show-toplevel)/.codex/hooks/fabric-hint.cjs"',
|
|
143
170
|
knowledgeHintBroad: '"$(git rev-parse --show-toplevel)/.codex/hooks/knowledge-hint-broad.cjs"',
|
|
144
|
-
knowledgeHintNarrow: '"$(git rev-parse --show-toplevel)/.codex/hooks/knowledge-hint-narrow.cjs"'
|
|
171
|
+
knowledgeHintNarrow: '"$(git rev-parse --show-toplevel)/.codex/hooks/knowledge-hint-narrow.cjs"',
|
|
172
|
+
citePolicyEvict: '"$(git rev-parse --show-toplevel)/.codex/hooks/cite-policy-evict.cjs"'
|
|
145
173
|
},
|
|
146
174
|
cursor: {
|
|
147
175
|
fabricHint: ".cursor/hooks/fabric-hint.cjs",
|
|
148
176
|
knowledgeHintBroad: ".cursor/hooks/knowledge-hint-broad.cjs",
|
|
149
|
-
knowledgeHintNarrow: ".cursor/hooks/knowledge-hint-narrow.cjs"
|
|
177
|
+
knowledgeHintNarrow: ".cursor/hooks/knowledge-hint-narrow.cjs",
|
|
178
|
+
citePolicyEvict: ".cursor/hooks/cite-policy-evict.cjs"
|
|
150
179
|
}
|
|
151
180
|
};
|
|
152
181
|
function readFabricLanguagePreference(projectRoot) {
|
|
@@ -257,6 +286,51 @@ async function installFabricSyncSkill(projectRoot, _options = {}) {
|
|
|
257
286
|
}
|
|
258
287
|
return results;
|
|
259
288
|
}
|
|
289
|
+
async function installFabricStoreSkill(projectRoot, _options = {}) {
|
|
290
|
+
const source = await readTemplate(SKILL_STORE_TEMPLATE_REL);
|
|
291
|
+
validateSkillCanonicalSize(source, "fabric-store");
|
|
292
|
+
const targets = SKILL_DESTINATIONS.fabricStore.map((rel) => join2(projectRoot, rel));
|
|
293
|
+
const results = [];
|
|
294
|
+
for (const target of targets) {
|
|
295
|
+
const staleMsg = inspectStaleInstall(target, source);
|
|
296
|
+
const result = await copyTextIdempotent("skill-store", source, target);
|
|
297
|
+
if (staleMsg && result.status === "written") {
|
|
298
|
+
result.message = result.message ? `${staleMsg}; ${result.message}` : staleMsg;
|
|
299
|
+
}
|
|
300
|
+
results.push(result);
|
|
301
|
+
}
|
|
302
|
+
return results;
|
|
303
|
+
}
|
|
304
|
+
async function installFabricAuditSkill(projectRoot, _options = {}) {
|
|
305
|
+
const source = await readTemplate(SKILL_AUDIT_TEMPLATE_REL);
|
|
306
|
+
validateSkillCanonicalSize(source, "fabric-audit");
|
|
307
|
+
const targets = SKILL_DESTINATIONS.fabricAudit.map((rel) => join2(projectRoot, rel));
|
|
308
|
+
const results = [];
|
|
309
|
+
for (const target of targets) {
|
|
310
|
+
const staleMsg = inspectStaleInstall(target, source);
|
|
311
|
+
const result = await copyTextIdempotent("skill-audit", source, target);
|
|
312
|
+
if (staleMsg && result.status === "written") {
|
|
313
|
+
result.message = result.message ? `${staleMsg}; ${result.message}` : staleMsg;
|
|
314
|
+
}
|
|
315
|
+
results.push(result);
|
|
316
|
+
}
|
|
317
|
+
return results;
|
|
318
|
+
}
|
|
319
|
+
async function installFabricConnectSkill(projectRoot, _options = {}) {
|
|
320
|
+
const source = await readTemplate(SKILL_CONNECT_TEMPLATE_REL);
|
|
321
|
+
validateSkillCanonicalSize(source, "fabric-connect");
|
|
322
|
+
const targets = SKILL_DESTINATIONS.fabricConnect.map((rel) => join2(projectRoot, rel));
|
|
323
|
+
const results = [];
|
|
324
|
+
for (const target of targets) {
|
|
325
|
+
const staleMsg = inspectStaleInstall(target, source);
|
|
326
|
+
const result = await copyTextIdempotent("skill-connect", source, target);
|
|
327
|
+
if (staleMsg && result.status === "written") {
|
|
328
|
+
result.message = result.message ? `${staleMsg}; ${result.message}` : staleMsg;
|
|
329
|
+
}
|
|
330
|
+
results.push(result);
|
|
331
|
+
}
|
|
332
|
+
return results;
|
|
333
|
+
}
|
|
260
334
|
async function cleanupDeprecatedSkills(projectRoot) {
|
|
261
335
|
const results = [];
|
|
262
336
|
for (const rel of DEPRECATED_SKILL_DIRS) {
|
|
@@ -887,6 +961,9 @@ export {
|
|
|
887
961
|
installFabricReviewSkill,
|
|
888
962
|
installFabricImportSkill,
|
|
889
963
|
installFabricSyncSkill,
|
|
964
|
+
installFabricStoreSkill,
|
|
965
|
+
installFabricAuditSkill,
|
|
966
|
+
installFabricConnectSkill,
|
|
890
967
|
cleanupDeprecatedSkills,
|
|
891
968
|
installSharedSkillLib,
|
|
892
969
|
installArchiveHintHook,
|
|
@@ -10,11 +10,16 @@ import {
|
|
|
10
10
|
} from "./chunk-RYAFBNES.js";
|
|
11
11
|
|
|
12
12
|
// src/store/store-ops.ts
|
|
13
|
+
import { randomUUID } from "crypto";
|
|
14
|
+
import { existsSync } from "fs";
|
|
15
|
+
import { join } from "path";
|
|
13
16
|
import {
|
|
14
17
|
addMountedStore,
|
|
15
18
|
bindRequiredStore,
|
|
16
19
|
detachMountedStore,
|
|
17
|
-
explainStore
|
|
20
|
+
explainStore,
|
|
21
|
+
initStore,
|
|
22
|
+
storeRelativePath
|
|
18
23
|
} from "@fenglimg/fabric-shared";
|
|
19
24
|
var NO_GLOBAL_CONFIG = "no global Fabric config found \u2014 run `fabric install --global <url>` first";
|
|
20
25
|
function requireConfig(globalRoot) {
|
|
@@ -32,6 +37,29 @@ function storeAdd(store, globalRoot = resolveGlobalRoot()) {
|
|
|
32
37
|
saveGlobalConfig(next, globalRoot);
|
|
33
38
|
return next;
|
|
34
39
|
}
|
|
40
|
+
function storeCreate(alias, now, options = {}) {
|
|
41
|
+
const globalRoot = options.globalRoot ?? resolveGlobalRoot();
|
|
42
|
+
const config = requireConfig(globalRoot);
|
|
43
|
+
const uuid = options.uuid ?? randomUUID();
|
|
44
|
+
const storeDir = join(globalRoot, storeRelativePath(uuid));
|
|
45
|
+
initStore(
|
|
46
|
+
storeDir,
|
|
47
|
+
{ store_uuid: uuid, created_at: now, canonical_alias: alias },
|
|
48
|
+
{ git: options.git }
|
|
49
|
+
);
|
|
50
|
+
const mounted = options.remote === void 0 ? { store_uuid: uuid, alias } : { store_uuid: uuid, alias, remote: options.remote };
|
|
51
|
+
const next = addMountedStore(config, mounted);
|
|
52
|
+
saveGlobalConfig(next, globalRoot);
|
|
53
|
+
return { config: next, store_uuid: uuid, storeDir };
|
|
54
|
+
}
|
|
55
|
+
function assertStoreMountable(uuid, globalRoot = resolveGlobalRoot()) {
|
|
56
|
+
const storeDir = join(globalRoot, storeRelativePath(uuid));
|
|
57
|
+
if (!existsSync(join(storeDir, "store.json"))) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`cannot mount store ${uuid}: no store tree at ${storeDir} \u2014 clone it first (\`fabric install --global --url <remote>\`) or create it locally, then re-run \`fabric store add\`. Refusing to register a phantom store.`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
35
63
|
function storeRemove(alias, globalRoot = resolveGlobalRoot()) {
|
|
36
64
|
const result = detachMountedStore(requireConfig(globalRoot), alias);
|
|
37
65
|
saveGlobalConfig(result.config, globalRoot);
|
|
@@ -78,6 +106,8 @@ function missingRequiredStores(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
78
106
|
export {
|
|
79
107
|
storeList,
|
|
80
108
|
storeAdd,
|
|
109
|
+
storeCreate,
|
|
110
|
+
assertStoreMountable,
|
|
81
111
|
storeRemove,
|
|
82
112
|
storeExplain,
|
|
83
113
|
storeBind,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveClients
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XC5RUHLK.js";
|
|
5
5
|
import {
|
|
6
6
|
t
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2CY4BMTH.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/config.ts
|
|
10
10
|
import { existsSync, statSync } from "fs";
|
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import stringWidth from "string-width";
|
|
6
6
|
function isColorEnabled() {
|
|
7
|
-
|
|
7
|
+
if (process.env.NO_COLOR) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const force = process.env.FORCE_COLOR;
|
|
11
|
+
if (force !== void 0) {
|
|
12
|
+
return force !== "0" && force.toLowerCase() !== "false";
|
|
13
|
+
}
|
|
14
|
+
return Boolean(process.stdout.isTTY) && Boolean(process.stderr.isTTY);
|
|
8
15
|
}
|
|
9
16
|
function colorize(painter) {
|
|
10
17
|
return (value) => isColorEnabled() ? painter(value) : value;
|
|
@@ -307,7 +307,7 @@ function serializeTomlInlineTable(values) {
|
|
|
307
307
|
const entries = Object.entries(values).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key} = ${escapeTomlString(value)}`);
|
|
308
308
|
return `{ ${entries.join(", ")} }`;
|
|
309
309
|
}
|
|
310
|
-
function serializeCodexServerBlock(serverName, serverEntry) {
|
|
310
|
+
function serializeCodexServerBlock(serverName, serverEntry, preservedUserLines = []) {
|
|
311
311
|
const lines = [
|
|
312
312
|
`[mcp_servers.${serverName}]`,
|
|
313
313
|
`command = ${escapeTomlString(serverEntry.command)}`,
|
|
@@ -316,9 +316,26 @@ function serializeCodexServerBlock(serverName, serverEntry) {
|
|
|
316
316
|
if (serverEntry.env !== void 0 && Object.keys(serverEntry.env).length > 0) {
|
|
317
317
|
lines.push(`env = ${serializeTomlInlineTable(serverEntry.env)}`);
|
|
318
318
|
}
|
|
319
|
+
lines.push(...preservedUserLines);
|
|
319
320
|
return `${lines.join("\n")}
|
|
320
321
|
`;
|
|
321
322
|
}
|
|
323
|
+
var CODEX_MANAGED_BLOCK_KEYS = /* @__PURE__ */ new Set(["command", "args", "env"]);
|
|
324
|
+
function extractCodexBlockUserLines(blockText) {
|
|
325
|
+
const out = [];
|
|
326
|
+
const lines = blockText.split("\n");
|
|
327
|
+
for (const line of lines) {
|
|
328
|
+
const trimmed = line.trim();
|
|
329
|
+
if (trimmed.length === 0) continue;
|
|
330
|
+
if (/^\[/.test(trimmed)) continue;
|
|
331
|
+
const keyMatch = /^([A-Za-z0-9_-]+)\s*=/.exec(trimmed);
|
|
332
|
+
if (keyMatch !== null && CODEX_MANAGED_BLOCK_KEYS.has(keyMatch[1])) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
out.push(trimmed);
|
|
336
|
+
}
|
|
337
|
+
return out;
|
|
338
|
+
}
|
|
322
339
|
function trimTrailingBlankLines(value) {
|
|
323
340
|
return value.replace(/\s+$/u, "");
|
|
324
341
|
}
|
|
@@ -341,13 +358,16 @@ function removeCodexServerBlock(rawConfig, serverName) {
|
|
|
341
358
|
return { text, changed };
|
|
342
359
|
}
|
|
343
360
|
function upsertCodexServerBlock(rawConfig, serverName, serverEntry) {
|
|
344
|
-
const block = serializeCodexServerBlock(serverName, serverEntry);
|
|
345
361
|
const normalized = rawConfig.replace(/\r\n/g, "\n");
|
|
346
|
-
const
|
|
362
|
+
const escaped = serverName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
363
|
+
const legacyPattern = new RegExp(String.raw`\n?\[mcp\.servers\.${escaped}\]\n[\s\S]*?(?=\n\[[^\n]+\]\n|$)`, "g");
|
|
347
364
|
const currentPattern = new RegExp(
|
|
348
|
-
String.raw`\n?\[mcp_servers\.${
|
|
365
|
+
String.raw`\n?\[mcp_servers\.${escaped}\]\n[\s\S]*?(?=\n\[[^\n]+\]\n|$)`,
|
|
349
366
|
"g"
|
|
350
367
|
);
|
|
368
|
+
const existingMatch = normalized.match(currentPattern);
|
|
369
|
+
const preservedUserLines = existingMatch !== null && existingMatch.length > 0 ? extractCodexBlockUserLines(existingMatch[0]) : [];
|
|
370
|
+
const block = serializeCodexServerBlock(serverName, serverEntry, preservedUserLines);
|
|
351
371
|
const withoutLegacy = normalized.replace(legacyPattern, "");
|
|
352
372
|
const withoutExisting = withoutLegacy.replace(currentPattern, "");
|
|
353
373
|
const trimmed = trimTrailingBlankLines(withoutExisting);
|
|
@@ -528,10 +548,11 @@ function detectClientSupports(workspaceRoot, fabricConfig = {}) {
|
|
|
528
548
|
},
|
|
529
549
|
installedCapabilities: {
|
|
530
550
|
hook: existsSync4(join4(workspaceRoot, ".codex", "hooks.json")),
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
|
|
551
|
+
// F6: the v2 skills (fabric-archive/review/import/…) DO install to
|
|
552
|
+
// `.codex/skills/` now, so probe that directory instead of the stale
|
|
553
|
+
// hardcoded `false` (which made `fabric install` always re-report Codex
|
|
554
|
+
// skills as uninstalled even right after installing them).
|
|
555
|
+
skill: existsSync4(join4(workspaceRoot, ".codex", "skills"))
|
|
535
556
|
}
|
|
536
557
|
}
|
|
537
558
|
];
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
configCmd,
|
|
4
4
|
config_default,
|
|
5
5
|
installMcpClients
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-AOE6AYI7.js";
|
|
7
|
+
import "./chunk-XC5RUHLK.js";
|
|
8
|
+
import "./chunk-2CY4BMTH.js";
|
|
9
9
|
export {
|
|
10
10
|
configCmd,
|
|
11
11
|
config_default as default,
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
import {
|
|
3
3
|
paint,
|
|
4
4
|
symbol
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BO4XIZWZ.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveDevMode
|
|
8
8
|
} from "./chunk-COI5VDFU.js";
|
|
9
|
+
import {
|
|
10
|
+
missingRequiredStores
|
|
11
|
+
} from "./chunk-4R2CYEA4.js";
|
|
9
12
|
import {
|
|
10
13
|
getDoctorTranslator,
|
|
11
14
|
t
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import {
|
|
14
|
-
missingRequiredStores
|
|
15
|
-
} from "./chunk-HFQVXY6P.js";
|
|
15
|
+
} from "./chunk-2CY4BMTH.js";
|
|
16
16
|
import {
|
|
17
17
|
loadProjectConfig
|
|
18
18
|
} from "./chunk-LFIKMVY7.js";
|
|
@@ -373,23 +373,30 @@ var doctorCommand = defineCommand({
|
|
|
373
373
|
if (fixKnowledge) {
|
|
374
374
|
const preReport = await runDoctorReport(resolution.target);
|
|
375
375
|
const plan = computeFixKnowledgePlan(preReport);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
if (args["dry-run"] === true) {
|
|
377
|
+
if (plan.totalCount > 0) {
|
|
378
|
+
renderFixKnowledgePlan(plan);
|
|
379
|
+
}
|
|
380
|
+
report = preReport;
|
|
379
381
|
} else {
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
plan
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
382
|
+
const yesFlag = args.yes === true;
|
|
383
|
+
const envBypass = process.env.FABRIC_NONINTERACTIVE === "1";
|
|
384
|
+
if (plan.totalCount === 0) {
|
|
385
|
+
} else {
|
|
386
|
+
renderFixKnowledgePlan(plan);
|
|
387
|
+
const decision = await resolveFixKnowledgeConsent({
|
|
388
|
+
yesFlag,
|
|
389
|
+
envBypass,
|
|
390
|
+
plan
|
|
391
|
+
});
|
|
392
|
+
if (decision === "abort") {
|
|
393
|
+
process.exitCode = 1;
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
389
396
|
}
|
|
397
|
+
fixKnowledgeReport = await runDoctorFixKnowledge(resolution.target);
|
|
398
|
+
report = fixKnowledgeReport.report;
|
|
390
399
|
}
|
|
391
|
-
fixKnowledgeReport = await runDoctorFixKnowledge(resolution.target);
|
|
392
|
-
report = fixKnowledgeReport.report;
|
|
393
400
|
} else if (fix) {
|
|
394
401
|
if (args["dry-run"] === true) {
|
|
395
402
|
report = await runDoctorReport(resolution.target);
|
|
@@ -418,7 +425,7 @@ var doctorCommand = defineCommand({
|
|
|
418
425
|
renderFixKnowledgeMutations(fixKnowledgeReport, dt);
|
|
419
426
|
} else if (fixReport !== null) {
|
|
420
427
|
writeStdout(fixReport.message);
|
|
421
|
-
} else if (fix && args["dry-run"] === true) {
|
|
428
|
+
} else if ((fix || fixKnowledge) && args["dry-run"] === true) {
|
|
422
429
|
writeStdout(dt("cli.doctor.fix-dry-run-banner"));
|
|
423
430
|
}
|
|
424
431
|
renderHumanReport(report, dt, args.verbose === true);
|
|
@@ -447,7 +454,7 @@ var doctorCommand = defineCommand({
|
|
|
447
454
|
var doctor_default = doctorCommand;
|
|
448
455
|
function renderHumanReport(report, dt, verbose) {
|
|
449
456
|
writeStdout(`${renderStatus(report.status)} ${paint.ai("fabric doctor")} ${paint.human(report.summary.target)}`);
|
|
450
|
-
renderTldrHeader(report);
|
|
457
|
+
renderTldrHeader(report, dt, verbose);
|
|
451
458
|
for (const check of report.checks) {
|
|
452
459
|
writeStdout(`${renderStatus(check.status)} ${check.name}: ${check.message}`);
|
|
453
460
|
}
|
|
@@ -520,16 +527,16 @@ function writeIssueSection(title, issues, options) {
|
|
|
520
527
|
}
|
|
521
528
|
}
|
|
522
529
|
}
|
|
523
|
-
function renderTldrHeader(report) {
|
|
530
|
+
function renderTldrHeader(report, dt, verbose) {
|
|
524
531
|
const ranked = [];
|
|
525
532
|
for (const issue of report.fixable_errors) {
|
|
526
|
-
ranked.push({ severity: "fixable", code: issue.code, message: issue.message });
|
|
533
|
+
ranked.push({ severity: "fixable", code: issue.code, message: issue.message, actionHint: issue.actionHint, audience: issue.audience });
|
|
527
534
|
}
|
|
528
535
|
for (const issue of report.manual_errors) {
|
|
529
|
-
ranked.push({ severity: "manual", code: issue.code, message: issue.message });
|
|
536
|
+
ranked.push({ severity: "manual", code: issue.code, message: issue.message, actionHint: issue.actionHint, audience: issue.audience });
|
|
530
537
|
}
|
|
531
538
|
for (const issue of report.warnings) {
|
|
532
|
-
ranked.push({ severity: "warn", code: issue.code, message: issue.message });
|
|
539
|
+
ranked.push({ severity: "warn", code: issue.code, message: issue.message, actionHint: issue.actionHint, audience: issue.audience });
|
|
533
540
|
}
|
|
534
541
|
if (ranked.length === 0) {
|
|
535
542
|
writeStdout(`${symbol.ok} TL;DR: all 48 checks green \u2014 nothing to fix.`);
|
|
@@ -543,6 +550,11 @@ function renderTldrHeader(report) {
|
|
|
543
550
|
const marker = item.severity === "fixable" ? symbol.error : item.severity === "manual" ? symbol.error : symbol.warn;
|
|
544
551
|
const truncated = item.message.length > 140 ? `${item.message.slice(0, 137)}...` : item.message;
|
|
545
552
|
writeStdout(` ${marker} ${item.code}: ${truncated}`);
|
|
553
|
+
if (item.actionHint !== void 0 && item.actionHint.length > 0) {
|
|
554
|
+
writeStdout(
|
|
555
|
+
item.audience === "maintainer" && !verbose ? ` \u2192 ${dt("doctor.maintainer-hint-folded")}` : ` \u2192 ${item.actionHint}`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
546
558
|
}
|
|
547
559
|
}
|
|
548
560
|
function renderStatus(status) {
|
|
@@ -916,5 +928,6 @@ function formatTimestampForTable(iso) {
|
|
|
916
928
|
export {
|
|
917
929
|
doctor_default as default,
|
|
918
930
|
doctorCommand,
|
|
919
|
-
parseSinceDuration
|
|
931
|
+
parseSinceDuration,
|
|
932
|
+
renderTldrHeader
|
|
920
933
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,47 +1,87 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
t
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2CY4BMTH.js";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
7
|
import { realpathSync } from "fs";
|
|
8
8
|
import { resolve } from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
|
-
import { defineCommand, runMain } from "citty";
|
|
10
|
+
import { defineCommand, runCommand, runMain } from "citty";
|
|
11
11
|
|
|
12
12
|
// src/commands/index.ts
|
|
13
13
|
var allCommands = {
|
|
14
|
-
install: () => import("./install-
|
|
14
|
+
install: () => import("./install-74ANPCCP.js").then((module) => module.default),
|
|
15
15
|
// v2.1.0-rc.1 P3: multi-store lifecycle command group (list/add/remove/explain).
|
|
16
|
-
store: () => import("./store-
|
|
16
|
+
store: () => import("./store-XB3ADT65.js").then((module) => module.default),
|
|
17
17
|
// v2.1.0-rc.1 P3 (S9/S17/S37): multi-store pull --rebase + push, conflict resume.
|
|
18
|
-
sync: () => import("./sync-
|
|
18
|
+
sync: () => import("./sync-UJ4BBCZJ.js").then((module) => module.default),
|
|
19
19
|
// v2.1.0-rc.1 P3 (F5): read-only identity/status info commands.
|
|
20
|
-
whoami: () => import("./whoami-
|
|
20
|
+
whoami: () => import("./whoami-2MLO4Y37.js").then((module) => module.default),
|
|
21
21
|
status: () => import("./status-GLQWLWH6.js").then((module) => module.default),
|
|
22
|
-
"scope-explain": () => import("./scope-explain-
|
|
23
|
-
doctor: () => import("./doctor-
|
|
24
|
-
uninstall: () => import("./uninstall-
|
|
25
|
-
config: () => import("./config-
|
|
22
|
+
"scope-explain": () => import("./scope-explain-CDIZESP5.js").then((module) => module.default),
|
|
23
|
+
doctor: () => import("./doctor-YONYXDX6.js").then((module) => module.default),
|
|
24
|
+
uninstall: () => import("./uninstall-C3QXKOO6.js").then((module) => module.default),
|
|
25
|
+
config: () => import("./config-XYRBZJDU.js").then((module) => module.default),
|
|
26
26
|
"plan-context-hint": () => import("./plan-context-hint-FC6P3WFE.js").then((module) => module.default),
|
|
27
27
|
// v2.0.0-rc.23 TASK-014 (F8c): S5 onboard-slot coverage. Used by the
|
|
28
28
|
// fabric-archive Skill's first-run phase to detect unclaimed slots.
|
|
29
|
-
"onboard-coverage": () => import("./onboard-coverage-
|
|
29
|
+
"onboard-coverage": () => import("./onboard-coverage-JWQWDZW7.js").then((module) => module.default),
|
|
30
30
|
// v2.0.0-rc.37 NEW-34: text dashboard over .fabric/metrics.jsonl.
|
|
31
|
-
metrics: () => import("./metrics-
|
|
31
|
+
metrics: () => import("./metrics-RER6NLFC.js").then((module) => module.default)
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
// src/lib/error-render.ts
|
|
35
|
+
function hasActionHint(err) {
|
|
36
|
+
if (err === null || typeof err !== "object") return false;
|
|
37
|
+
const candidate = err;
|
|
38
|
+
return typeof candidate.message === "string" && candidate.message.length > 0 && typeof candidate.actionHint === "string" && candidate.actionHint.length > 0;
|
|
39
|
+
}
|
|
40
|
+
function renderFabricError(err, stream = process.stderr) {
|
|
41
|
+
stream.write(`${err.message}
|
|
42
|
+
`);
|
|
43
|
+
stream.write(` -> ${err.actionHint}
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
function renderTopLevelError(err, stream = process.stderr) {
|
|
47
|
+
if (hasActionHint(err)) {
|
|
48
|
+
renderFabricError(err, stream);
|
|
49
|
+
return "fabric-error";
|
|
50
|
+
}
|
|
51
|
+
return "other";
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
// src/index.ts
|
|
35
55
|
var main = defineCommand({
|
|
36
56
|
meta: {
|
|
37
57
|
name: "fabric",
|
|
38
|
-
version: "2.
|
|
58
|
+
version: "2.2.0-rc.1",
|
|
39
59
|
description: t("cli.main.description")
|
|
40
60
|
},
|
|
41
61
|
subCommands: allCommands
|
|
42
62
|
});
|
|
43
63
|
async function run() {
|
|
44
|
-
|
|
64
|
+
const rawArgs = process.argv.slice(2);
|
|
65
|
+
const wantsHelp = rawArgs.some((arg) => arg === "--help" || arg === "-h");
|
|
66
|
+
const wantsVersion = rawArgs.length === 1 && (rawArgs[0] === "--version" || rawArgs[0] === "-v");
|
|
67
|
+
if (wantsHelp || wantsVersion) {
|
|
68
|
+
await runMain(main, { rawArgs });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await runCommand(main, { rawArgs });
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (renderTopLevelError(err) === "fabric-error") {
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
const code = err !== null && typeof err === "object" ? err.code : void 0;
|
|
78
|
+
if (typeof code === "string" && code.startsWith("E_")) {
|
|
79
|
+
await runMain(main, { rawArgs });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
console.error(err, "\n");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
45
85
|
}
|
|
46
86
|
var entrypoint = process.argv[1];
|
|
47
87
|
var currentFilePath = fileURLToPath(import.meta.url);
|