@fenglimg/fabric-cli 2.2.0-rc.3 → 2.2.0-rc.4
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-5LQIHYFC.js → chunk-5JG4QJLO.js} +1 -1
- package/dist/{chunk-5ZUMLCD5.js → chunk-5SSNE5GM.js} +55 -2
- package/dist/{doctor-J4O3X54I.js → doctor-U5W4CX5I.js} +1 -1
- package/dist/index.js +6 -6
- package/dist/{install-BULNDUIM.js → install-7XJ64WSC.js} +119 -192
- package/dist/{status-PANEGKU2.js → status-7UFLWRX7.js} +2 -2
- package/dist/store-ZEZMQVG7.js +817 -0
- package/dist/{whoami-66YKY5DZ.js → whoami-3FRWYGML.js} +2 -2
- package/package.json +3 -3
- package/dist/store-66NK2FTQ.js +0 -443
|
@@ -14,11 +14,14 @@ import { existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, rmSync, sy
|
|
|
14
14
|
import { join } from "path";
|
|
15
15
|
import {
|
|
16
16
|
addMountedStore,
|
|
17
|
+
addStoreProject,
|
|
17
18
|
bindRequiredStore,
|
|
18
19
|
detachMountedStore,
|
|
19
20
|
explainStore,
|
|
20
21
|
initStore,
|
|
22
|
+
readStoreProjects,
|
|
21
23
|
STORES_ROOT_DIR,
|
|
24
|
+
storeHasProject,
|
|
22
25
|
storeRelativePath
|
|
23
26
|
} from "@fenglimg/fabric-shared";
|
|
24
27
|
var NO_GLOBAL_CONFIG = "no global Fabric config found \u2014 run `fabric install --global <url>` first";
|
|
@@ -193,11 +196,58 @@ function requireProjectConfig(projectRoot) {
|
|
|
193
196
|
}
|
|
194
197
|
return config;
|
|
195
198
|
}
|
|
196
|
-
function
|
|
199
|
+
function resolveStoreDir(aliasOrUuid, globalRoot = resolveGlobalRoot()) {
|
|
200
|
+
const config = loadGlobalConfig(globalRoot);
|
|
201
|
+
if (config === null) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const store = config.stores.find(
|
|
205
|
+
(s) => s.alias === aliasOrUuid || s.store_uuid === aliasOrUuid
|
|
206
|
+
);
|
|
207
|
+
if (store === void 0) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
return join(globalRoot, storeRelativePath(store.store_uuid));
|
|
211
|
+
}
|
|
212
|
+
function storeProjectList(aliasOrUuid, globalRoot = resolveGlobalRoot()) {
|
|
213
|
+
const storeDir = resolveStoreDir(aliasOrUuid, globalRoot);
|
|
214
|
+
if (storeDir === null) {
|
|
215
|
+
throw new Error(`no mounted store '${aliasOrUuid}' \u2014 run \`fabric store list\` to see mounts`);
|
|
216
|
+
}
|
|
217
|
+
return readStoreProjects(storeDir);
|
|
218
|
+
}
|
|
219
|
+
function storeProjectCreate(aliasOrUuid, id, now, options = {}) {
|
|
220
|
+
const globalRoot = options.globalRoot ?? resolveGlobalRoot();
|
|
221
|
+
const storeDir = resolveStoreDir(aliasOrUuid, globalRoot);
|
|
222
|
+
if (storeDir === null) {
|
|
223
|
+
throw new Error(`no mounted store '${aliasOrUuid}' \u2014 run \`fabric store list\` to see mounts`);
|
|
224
|
+
}
|
|
225
|
+
const project = options.name === void 0 ? { id, created_at: now } : { id, name: options.name, created_at: now };
|
|
226
|
+
addStoreProject(storeDir, project);
|
|
227
|
+
return project;
|
|
228
|
+
}
|
|
229
|
+
function storeBind(projectRoot, entry, options = {}) {
|
|
197
230
|
const config = requireProjectConfig(projectRoot);
|
|
231
|
+
let activeProject = config.active_project;
|
|
232
|
+
if (options.project !== void 0) {
|
|
233
|
+
const globalRoot = options.globalRoot ?? resolveGlobalRoot();
|
|
234
|
+
const storeDir = resolveStoreDir(entry.id, globalRoot);
|
|
235
|
+
if (storeDir === null) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`cannot bind project '${options.project}': store '${entry.id}' is not mounted \u2014 mount it first (\`fabric store add\` / \`fabric install --global --url <remote>\`)`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
if (!storeHasProject(storeDir, options.project)) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
`cannot bind to project '${options.project}': not registered in store '${entry.id}' \u2014 create it first with \`fabric store project create ${entry.id} ${options.project}\``
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
activeProject = options.project;
|
|
246
|
+
}
|
|
198
247
|
const next = {
|
|
199
248
|
...config,
|
|
200
|
-
required_stores: bindRequiredStore(config.required_stores ?? [], entry)
|
|
249
|
+
required_stores: bindRequiredStore(config.required_stores ?? [], entry),
|
|
250
|
+
...activeProject === void 0 ? {} : { active_project: activeProject }
|
|
201
251
|
};
|
|
202
252
|
saveProjectConfig(next, projectRoot);
|
|
203
253
|
return next;
|
|
@@ -241,6 +291,9 @@ export {
|
|
|
241
291
|
assertStoreMountable,
|
|
242
292
|
storeRemove,
|
|
243
293
|
storeExplain,
|
|
294
|
+
resolveStoreDir,
|
|
295
|
+
storeProjectList,
|
|
296
|
+
storeProjectCreate,
|
|
244
297
|
storeBind,
|
|
245
298
|
storeSwitchWrite,
|
|
246
299
|
missingRequiredStores,
|
package/dist/index.js
CHANGED
|
@@ -11,16 +11,16 @@ 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-7XJ64WSC.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-ZEZMQVG7.js").then((module) => module.default),
|
|
17
17
|
// v2.1.0-rc.1 P3 (S9/S17/S37): multi-store pull --rebase + push, conflict resume.
|
|
18
18
|
sync: () => import("./sync-EA5HZMXM.js").then((module) => module.default),
|
|
19
19
|
// v2.1.0-rc.1 P3 (F5): read-only identity/status info commands.
|
|
20
|
-
whoami: () => import("./whoami-
|
|
21
|
-
status: () => import("./status-
|
|
20
|
+
whoami: () => import("./whoami-3FRWYGML.js").then((module) => module.default),
|
|
21
|
+
status: () => import("./status-7UFLWRX7.js").then((module) => module.default),
|
|
22
22
|
"scope-explain": () => import("./scope-explain-BWRWBCCP.js").then((module) => module.default),
|
|
23
|
-
doctor: () => import("./doctor-
|
|
23
|
+
doctor: () => import("./doctor-U5W4CX5I.js").then((module) => module.default),
|
|
24
24
|
uninstall: () => import("./uninstall-F75MPKQC.js").then((module) => module.default),
|
|
25
25
|
config: () => import("./config-VJMXCLXW.js").then((module) => module.default),
|
|
26
26
|
"plan-context-hint": () => import("./plan-context-hint-CHVZGOZ5.js").then((module) => module.default),
|
|
@@ -55,7 +55,7 @@ function renderTopLevelError(err, stream = process.stderr) {
|
|
|
55
55
|
var main = defineCommand({
|
|
56
56
|
meta: {
|
|
57
57
|
name: "fabric",
|
|
58
|
-
version: "2.2.0-rc.
|
|
58
|
+
version: "2.2.0-rc.4",
|
|
59
59
|
description: t("cli.main.description")
|
|
60
60
|
},
|
|
61
61
|
subCommands: allCommands
|
|
@@ -40,29 +40,36 @@ import {
|
|
|
40
40
|
import {
|
|
41
41
|
detectClientSupports
|
|
42
42
|
} from "./chunk-XC5RUHLK.js";
|
|
43
|
+
import {
|
|
44
|
+
regenerateBindingsSnapshot
|
|
45
|
+
} from "./chunk-H3FE6VIK.js";
|
|
46
|
+
import "./chunk-EOT63RDH.js";
|
|
43
47
|
import {
|
|
44
48
|
getProjectTranslator,
|
|
45
49
|
t
|
|
46
50
|
} from "./chunk-2CY4BMTH.js";
|
|
47
51
|
import {
|
|
52
|
+
storeBind,
|
|
53
|
+
storeCreate,
|
|
54
|
+
storeList,
|
|
55
|
+
storeSwitchWrite,
|
|
48
56
|
syncStoreAliasLinks,
|
|
49
57
|
unboundAvailableStores
|
|
50
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-5SSNE5GM.js";
|
|
51
59
|
import {
|
|
52
60
|
globalConfigPath,
|
|
53
61
|
loadGlobalConfig,
|
|
62
|
+
loadProjectConfig,
|
|
54
63
|
resolveGlobalRoot,
|
|
55
64
|
saveGlobalConfig
|
|
56
65
|
} from "./chunk-XCBVSGCS.js";
|
|
57
66
|
|
|
58
67
|
// src/commands/install.ts
|
|
59
68
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
60
|
-
import { homedir } from "os";
|
|
61
69
|
import * as childProcess from "child_process";
|
|
62
|
-
import { appendFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2,
|
|
70
|
+
import { appendFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, rmSync as rmSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
63
71
|
import { dirname, isAbsolute as isAbsolute3, join as join7, resolve as resolve3 } from "path";
|
|
64
|
-
import { cancel, confirm, group, intro, isCancel, log, note, outro, select } from "@clack/prompts";
|
|
65
|
-
import { defaultAgentsMetaCounters } from "@fenglimg/fabric-shared";
|
|
72
|
+
import { cancel, confirm, group, intro, isCancel, log, note, outro, select, text } from "@clack/prompts";
|
|
66
73
|
import { atomicWriteJson } from "@fenglimg/fabric-shared/node/atomic-write";
|
|
67
74
|
import { defineCommand } from "citty";
|
|
68
75
|
|
|
@@ -413,6 +420,7 @@ function mountStoreFromRemote(url, globalRoot) {
|
|
|
413
420
|
globalRoot
|
|
414
421
|
);
|
|
415
422
|
console.log(`mounted store '${alias}' (${identity.store_uuid}) from ${url}`);
|
|
423
|
+
return { store_uuid: identity.store_uuid, alias };
|
|
416
424
|
}
|
|
417
425
|
async function runGlobalInstall(options = {}, globalRoot = resolveGlobalRoot()) {
|
|
418
426
|
const uid = options.uid ?? deriveUid();
|
|
@@ -1593,7 +1601,7 @@ function readProjectName(target) {
|
|
|
1593
1601
|
return basename(target);
|
|
1594
1602
|
}
|
|
1595
1603
|
function getCliVersion() {
|
|
1596
|
-
return true ? "2.2.0-rc.
|
|
1604
|
+
return true ? "2.2.0-rc.4" : "unknown";
|
|
1597
1605
|
}
|
|
1598
1606
|
function sortRecord(record) {
|
|
1599
1607
|
return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -1631,16 +1639,6 @@ var installCommand = defineCommand({
|
|
|
1631
1639
|
description: t("cli.install.args.yes.description"),
|
|
1632
1640
|
default: false
|
|
1633
1641
|
},
|
|
1634
|
-
"force-skills-only": {
|
|
1635
|
-
type: "boolean",
|
|
1636
|
-
description: t("cli.install.args.force-skills-only.description"),
|
|
1637
|
-
default: false
|
|
1638
|
-
},
|
|
1639
|
-
"force-hooks-only": {
|
|
1640
|
-
type: "boolean",
|
|
1641
|
-
description: t("cli.install.args.force-hooks-only.description"),
|
|
1642
|
-
default: false
|
|
1643
|
-
},
|
|
1644
1642
|
global: {
|
|
1645
1643
|
type: "boolean",
|
|
1646
1644
|
description: "Set up global Fabric (~/.fabric: uid + personal store + config)",
|
|
@@ -1648,7 +1646,7 @@ var installCommand = defineCommand({
|
|
|
1648
1646
|
},
|
|
1649
1647
|
url: {
|
|
1650
1648
|
type: "string",
|
|
1651
|
-
description: "
|
|
1649
|
+
description: "Clone + mount a shared store remote. In a project install: also binds it to this project and sets it as the write target. With --global: mounts it machine-wide only."
|
|
1652
1650
|
},
|
|
1653
1651
|
"enable-embed": {
|
|
1654
1652
|
type: "boolean",
|
|
@@ -1665,83 +1663,6 @@ var installCommand = defineCommand({
|
|
|
1665
1663
|
}
|
|
1666
1664
|
});
|
|
1667
1665
|
var install_default = installCommand;
|
|
1668
|
-
async function runSkillsOnlyRefresh(targetInput) {
|
|
1669
|
-
const target = normalizeTarget3(targetInput);
|
|
1670
|
-
const metaPath = join7(target, ".fabric", "agents.meta.json");
|
|
1671
|
-
if (!existsSync5(metaPath)) {
|
|
1672
|
-
const message = t("cli.install.force-skills-only.uninitialised.message");
|
|
1673
|
-
const hint = t("cli.install.force-skills-only.uninitialised.hint");
|
|
1674
|
-
process.stderr.write(`${message}
|
|
1675
|
-
${hint}
|
|
1676
|
-
`);
|
|
1677
|
-
process.exitCode = 1;
|
|
1678
|
-
return;
|
|
1679
|
-
}
|
|
1680
|
-
console.log(formatInitStageHeader(t("cli.install.force-skills-only.banner")));
|
|
1681
|
-
const results = [];
|
|
1682
|
-
results.push(...await cleanupDeprecatedSkills(target));
|
|
1683
|
-
results.push(...await installFabricArchiveSkill(target));
|
|
1684
|
-
results.push(...await installFabricReviewSkill(target));
|
|
1685
|
-
results.push(...await installFabricImportSkill(target));
|
|
1686
|
-
results.push(...await installFabricSyncSkill(target));
|
|
1687
|
-
results.push(...await installFabricStoreSkill(target));
|
|
1688
|
-
results.push(...await installFabricAuditSkill(target));
|
|
1689
|
-
results.push(...await installFabricConnectSkill(target));
|
|
1690
|
-
results.push(...await installSharedSkillLib(target));
|
|
1691
|
-
let written = 0;
|
|
1692
|
-
let skipped = 0;
|
|
1693
|
-
let errors = 0;
|
|
1694
|
-
for (const r of results) {
|
|
1695
|
-
if (r.status === "written") written += 1;
|
|
1696
|
-
else if (r.status === "skipped") skipped += 1;
|
|
1697
|
-
else if (r.status === "error") errors += 1;
|
|
1698
|
-
}
|
|
1699
|
-
console.log(
|
|
1700
|
-
t("cli.install.force-skills-only.summary", {
|
|
1701
|
-
written: String(written),
|
|
1702
|
-
skipped: String(skipped),
|
|
1703
|
-
errors: String(errors)
|
|
1704
|
-
})
|
|
1705
|
-
);
|
|
1706
|
-
if (errors > 0) {
|
|
1707
|
-
for (const r of results) {
|
|
1708
|
-
if (r.status === "error") {
|
|
1709
|
-
process.stderr.write(` ${r.step} ${r.path}: ${r.message ?? "error"}
|
|
1710
|
-
`);
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
process.exitCode = 1;
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
async function runHooksOnlyRefresh(targetInput) {
|
|
1717
|
-
const target = normalizeTarget3(targetInput);
|
|
1718
|
-
const metaPath = join7(target, ".fabric", "agents.meta.json");
|
|
1719
|
-
if (!existsSync5(metaPath)) {
|
|
1720
|
-
const message = t("cli.install.force-hooks-only.uninitialised.message");
|
|
1721
|
-
const hint = t("cli.install.force-hooks-only.uninitialised.hint");
|
|
1722
|
-
process.stderr.write(`${message}
|
|
1723
|
-
${hint}
|
|
1724
|
-
`);
|
|
1725
|
-
process.exitCode = 1;
|
|
1726
|
-
return;
|
|
1727
|
-
}
|
|
1728
|
-
console.log(formatInitStageHeader(t("cli.install.force-hooks-only.banner")));
|
|
1729
|
-
const result = await installHooks(target);
|
|
1730
|
-
console.log(
|
|
1731
|
-
t("cli.install.force-hooks-only.summary", {
|
|
1732
|
-
written: String(result.installed.length),
|
|
1733
|
-
skipped: String(result.skipped.length),
|
|
1734
|
-
errors: String(result.errors.length)
|
|
1735
|
-
})
|
|
1736
|
-
);
|
|
1737
|
-
if (result.errors.length > 0) {
|
|
1738
|
-
for (const err of result.errors) {
|
|
1739
|
-
process.stderr.write(` ${err}
|
|
1740
|
-
`);
|
|
1741
|
-
}
|
|
1742
|
-
process.exitCode = 1;
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
1666
|
async function runInitCommand(args) {
|
|
1746
1667
|
const logger = createDebugLogger(args.debug);
|
|
1747
1668
|
if (args.global === true) {
|
|
@@ -1749,14 +1670,6 @@ async function runInitCommand(args) {
|
|
|
1749
1670
|
return;
|
|
1750
1671
|
}
|
|
1751
1672
|
const resolution = resolveDevMode(args.target, process.cwd());
|
|
1752
|
-
if (args["force-skills-only"] === true) {
|
|
1753
|
-
await runSkillsOnlyRefresh(resolution.target);
|
|
1754
|
-
return;
|
|
1755
|
-
}
|
|
1756
|
-
if (args["force-hooks-only"] === true) {
|
|
1757
|
-
await runHooksOnlyRefresh(resolution.target);
|
|
1758
|
-
return;
|
|
1759
|
-
}
|
|
1760
1673
|
const intent = resolveInitCliIntent(args, resolution.target);
|
|
1761
1674
|
logger(`init target source: ${resolution.source}`);
|
|
1762
1675
|
for (const step of resolution.chain) {
|
|
@@ -1786,6 +1699,11 @@ async function runInitCommand(args) {
|
|
|
1786
1699
|
console.log(t("cli.install.next-steps"));
|
|
1787
1700
|
console.log("");
|
|
1788
1701
|
console.log(paint.muted("More: docs/surfaces.md explains when to use CLI vs Skill vs MCP."));
|
|
1702
|
+
if (typeof args.url === "string" && args.url.length > 0) {
|
|
1703
|
+
bindRemoteStoreToProject(resolution.target, args.url);
|
|
1704
|
+
} else if (intent.wizardEnabled) {
|
|
1705
|
+
await promptStoreOnboarding(resolution.target);
|
|
1706
|
+
}
|
|
1789
1707
|
const unboundStores = unboundAvailableStores(resolution.target);
|
|
1790
1708
|
if (unboundStores.length > 0) {
|
|
1791
1709
|
console.log("");
|
|
@@ -1797,19 +1715,105 @@ async function runInitCommand(args) {
|
|
|
1797
1715
|
);
|
|
1798
1716
|
}
|
|
1799
1717
|
if (args["enable-embed"] === true) {
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
console.log(paint.muted(`\u8BED\u4E49\u641C\u7D22\u5DF2\u662F\u542F\u7528\u72B6\u6001 (embed_model=${enabled.model})\uFF0C\u672A\u6539\u52A8 ${enabled.configPath}\u3002`));
|
|
1804
|
-
} else {
|
|
1805
|
-
for (const line of renderSemanticSearchInstructions(enabled.model)) {
|
|
1806
|
-
console.log(line);
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1718
|
+
enableSemanticSearchAndReport(resolution.target, args["embed-model"]);
|
|
1719
|
+
} else if (intent.wizardEnabled) {
|
|
1720
|
+
await promptSemanticSearch(resolution.target);
|
|
1809
1721
|
}
|
|
1810
1722
|
}
|
|
1811
1723
|
return result;
|
|
1812
1724
|
}
|
|
1725
|
+
function enableSemanticSearchAndReport(projectRoot, model) {
|
|
1726
|
+
const enabled = enableSemanticSearch(projectRoot, model === void 0 ? {} : { model });
|
|
1727
|
+
console.log("");
|
|
1728
|
+
if (enabled.alreadyEnabled) {
|
|
1729
|
+
console.log(paint.muted(`\u8BED\u4E49\u641C\u7D22\u5DF2\u662F\u542F\u7528\u72B6\u6001 (embed_model=${enabled.model})\uFF0C\u672A\u6539\u52A8 ${enabled.configPath}\u3002`));
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
for (const line of renderSemanticSearchInstructions(enabled.model)) {
|
|
1733
|
+
console.log(line);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
async function promptSemanticSearch(projectRoot) {
|
|
1737
|
+
const enable = await confirm({
|
|
1738
|
+
message: "Enable vector semantic search? (downloads an embedding model on first use)",
|
|
1739
|
+
initialValue: false
|
|
1740
|
+
});
|
|
1741
|
+
if (isCancel(enable) || !enable) {
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
enableSemanticSearchAndReport(projectRoot);
|
|
1745
|
+
}
|
|
1746
|
+
function bindRemoteStoreToProject(projectRoot, url, globalRoot = resolveGlobalRoot()) {
|
|
1747
|
+
const already = storeList(globalRoot).find((store) => store.remote === url);
|
|
1748
|
+
const mounted = already ?? mountStoreFromRemote(url, globalRoot);
|
|
1749
|
+
storeBind(projectRoot, { id: mounted.alias, suggested_remote: url });
|
|
1750
|
+
storeSwitchWrite(projectRoot, mounted.alias);
|
|
1751
|
+
regenerateBindingsSnapshot(projectRoot, { now: (/* @__PURE__ */ new Date()).toISOString(), globalRoot });
|
|
1752
|
+
console.log("");
|
|
1753
|
+
console.log(
|
|
1754
|
+
paint.success(
|
|
1755
|
+
`bound store '${mounted.alias}' to this project and set it as the write target.`
|
|
1756
|
+
)
|
|
1757
|
+
);
|
|
1758
|
+
}
|
|
1759
|
+
function bindCreatedStoreToProject(projectRoot, alias, options = {}) {
|
|
1760
|
+
const globalRoot = options.globalRoot ?? resolveGlobalRoot();
|
|
1761
|
+
storeCreate(alias, (/* @__PURE__ */ new Date()).toISOString(), {
|
|
1762
|
+
...options.remote === void 0 ? {} : { remote: options.remote },
|
|
1763
|
+
globalRoot
|
|
1764
|
+
});
|
|
1765
|
+
storeBind(
|
|
1766
|
+
projectRoot,
|
|
1767
|
+
options.remote === void 0 ? { id: alias } : { id: alias, suggested_remote: options.remote }
|
|
1768
|
+
);
|
|
1769
|
+
storeSwitchWrite(projectRoot, alias);
|
|
1770
|
+
regenerateBindingsSnapshot(projectRoot, { now: (/* @__PURE__ */ new Date()).toISOString(), globalRoot });
|
|
1771
|
+
console.log("");
|
|
1772
|
+
console.log(
|
|
1773
|
+
paint.success(
|
|
1774
|
+
`created store '${alias}', bound it to this project, and set it as the write target.`
|
|
1775
|
+
)
|
|
1776
|
+
);
|
|
1777
|
+
}
|
|
1778
|
+
async function promptStoreOnboarding(projectRoot) {
|
|
1779
|
+
const config = loadProjectConfig(projectRoot);
|
|
1780
|
+
if (typeof config?.active_write_store === "string" && config.active_write_store.length > 0) {
|
|
1781
|
+
return;
|
|
1782
|
+
}
|
|
1783
|
+
const choice = await select({
|
|
1784
|
+
message: "Set up a team / shared knowledge store for this project?",
|
|
1785
|
+
initialValue: "skip",
|
|
1786
|
+
options: [
|
|
1787
|
+
{ value: "skip", label: "skip", hint: "personal store only (default)" },
|
|
1788
|
+
{ value: "join", label: "join existing", hint: "clone + bind a shared store from a git remote" },
|
|
1789
|
+
{ value: "create", label: "create new", hint: "start a fresh local store (optionally remote-backed)" }
|
|
1790
|
+
]
|
|
1791
|
+
});
|
|
1792
|
+
if (isCancel(choice) || choice === "skip") {
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
if (choice === "join") {
|
|
1796
|
+
const url = await text({
|
|
1797
|
+
message: "Shared store git remote (url):",
|
|
1798
|
+
placeholder: "git@github.com:org/knowledge.git"
|
|
1799
|
+
});
|
|
1800
|
+
if (isCancel(url) || typeof url !== "string" || url.length === 0) {
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1803
|
+
bindRemoteStoreToProject(projectRoot, url);
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
const alias = await text({ message: "Local alias for the new store:", initialValue: "team" });
|
|
1807
|
+
if (isCancel(alias) || typeof alias !== "string" || alias.length === 0) {
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
const remote = await text({
|
|
1811
|
+
message: "Git remote to back it (optional \u2014 leave blank to skip):",
|
|
1812
|
+
placeholder: "git@github.com:org/knowledge.git"
|
|
1813
|
+
});
|
|
1814
|
+
const remoteStr = !isCancel(remote) && typeof remote === "string" && remote.length > 0 ? remote : void 0;
|
|
1815
|
+
bindCreatedStoreToProject(projectRoot, alias, remoteStr === void 0 ? {} : { remote: remoteStr });
|
|
1816
|
+
}
|
|
1813
1817
|
var FABRIC_GITIGNORE_CONTENT = [
|
|
1814
1818
|
"# Fabric per-dev activity ledgers & caches \u2014 auto-generated, not shared.",
|
|
1815
1819
|
"# Managed by `fabric install`; edit freely (re-install never overwrites this).",
|
|
@@ -1955,7 +1959,6 @@ async function executeInitExecutionPlan(plan) {
|
|
|
1955
1959
|
printInitPlanSummary(plan.target, plan.options, plan.mcpInstallMode, plan.supports);
|
|
1956
1960
|
}
|
|
1957
1961
|
const scaffoldStates = [
|
|
1958
|
-
{ path: plan.scaffold.metaPath, state: plan.scaffold.metaState },
|
|
1959
1962
|
{ path: plan.scaffold.eventsPath, state: plan.scaffold.eventsState },
|
|
1960
1963
|
{ path: plan.scaffold.forensicPath, state: plan.scaffold.forensicState }
|
|
1961
1964
|
];
|
|
@@ -2016,26 +2019,16 @@ async function executeInitExecutionPlan(plan) {
|
|
|
2016
2019
|
finalSupports
|
|
2017
2020
|
};
|
|
2018
2021
|
}
|
|
2019
|
-
var KNOWLEDGE_SUBDIRS = ["decisions", "pitfalls", "guidelines", "models", "processes", "pending"];
|
|
2020
|
-
function resolvePersonalFabricRoot() {
|
|
2021
|
-
return process.env.FABRIC_HOME ?? homedir();
|
|
2022
|
-
}
|
|
2023
2022
|
async function buildInitFabricPlan(target, options) {
|
|
2024
2023
|
assertExistingDirectory3(target);
|
|
2025
2024
|
const fabricDir = join7(target, ".fabric");
|
|
2026
2025
|
const agentsMdPath = join7(target, "AGENTS.md");
|
|
2027
2026
|
const agentsMdAction = existsSync5(agentsMdPath) ? "preserved" : "created";
|
|
2028
|
-
const knowledgeDir = join7(fabricDir, "knowledge");
|
|
2029
|
-
const personalKnowledgeDir = join7(resolvePersonalFabricRoot(), ".fabric", "knowledge");
|
|
2030
2027
|
const forensicPath = join7(fabricDir, "forensic.json");
|
|
2031
2028
|
const eventsPath = join7(fabricDir, "events.jsonl");
|
|
2032
|
-
const metaPath = join7(fabricDir, "agents.meta.json");
|
|
2033
2029
|
const replaceFabricDir = shouldReplaceWritableDirectory(fabricDir, options);
|
|
2034
|
-
const knowledgeDirAction = existsSync5(knowledgeDir) ? "overwritten" : "created";
|
|
2035
|
-
const metaClassification = classifyFreshPath(metaPath, "structural");
|
|
2036
2030
|
const eventsClassification = classifyFreshPath(eventsPath, "presence");
|
|
2037
2031
|
const forensicClassification = classifyFreshPath(forensicPath, "always-rewrite");
|
|
2038
|
-
const metaAction = diffStateToWriteAction(metaClassification.state);
|
|
2039
2032
|
const eventsAction = diffStateToWriteAction(eventsClassification.state);
|
|
2040
2033
|
const forensicAction = diffStateToWriteAction(forensicClassification.state);
|
|
2041
2034
|
const showScanProgress = process.stderr.isTTY === true;
|
|
@@ -2048,7 +2041,6 @@ async function buildInitFabricPlan(target, options) {
|
|
|
2048
2041
|
process.stderr.write(`${t("cli.install.scan-complete")}
|
|
2049
2042
|
`);
|
|
2050
2043
|
}
|
|
2051
|
-
const meta = createInitialMeta();
|
|
2052
2044
|
return {
|
|
2053
2045
|
target,
|
|
2054
2046
|
options,
|
|
@@ -2056,18 +2048,11 @@ async function buildInitFabricPlan(target, options) {
|
|
|
2056
2048
|
replaceFabricDir,
|
|
2057
2049
|
agentsMdPath,
|
|
2058
2050
|
agentsMdAction,
|
|
2059
|
-
knowledgeDir,
|
|
2060
|
-
knowledgeDirAction,
|
|
2061
|
-
personalKnowledgeDir,
|
|
2062
|
-
metaPath,
|
|
2063
|
-
metaAction,
|
|
2064
|
-
meta,
|
|
2065
2051
|
eventsPath,
|
|
2066
2052
|
eventsAction,
|
|
2067
2053
|
forensicPath,
|
|
2068
2054
|
forensicAction,
|
|
2069
2055
|
forensicReport,
|
|
2070
|
-
metaState: metaClassification.state,
|
|
2071
2056
|
eventsState: eventsClassification.state,
|
|
2072
2057
|
forensicState: forensicClassification.state
|
|
2073
2058
|
};
|
|
@@ -2079,19 +2064,6 @@ async function executeInitFabricPlan(plan) {
|
|
|
2079
2064
|
mkdirSync2(plan.fabricDir, { recursive: true });
|
|
2080
2065
|
writeDefaultFabricConfig(plan.fabricDir, plan.target);
|
|
2081
2066
|
writeDefaultGitignore(plan.fabricDir);
|
|
2082
|
-
mkdirSync2(plan.knowledgeDir, { recursive: true });
|
|
2083
|
-
for (const sub of KNOWLEDGE_SUBDIRS) {
|
|
2084
|
-
const teamSubDir = join7(plan.knowledgeDir, sub);
|
|
2085
|
-
mkdirSync2(teamSubDir, { recursive: true });
|
|
2086
|
-
const teamGitkeep = join7(teamSubDir, ".gitkeep");
|
|
2087
|
-
if (!existsSync5(teamGitkeep)) {
|
|
2088
|
-
writeFileSync2(teamGitkeep, "", "utf8");
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
if (plan.metaState === "missing") {
|
|
2092
|
-
preparePlannedPath(plan.metaPath, plan.metaAction);
|
|
2093
|
-
await atomicWriteJson(plan.metaPath, plan.meta);
|
|
2094
|
-
}
|
|
2095
2067
|
if (plan.eventsState === "missing") {
|
|
2096
2068
|
preparePlannedPath(plan.eventsPath, plan.eventsAction);
|
|
2097
2069
|
mkdirSync2(dirname(plan.eventsPath), { recursive: true });
|
|
@@ -2104,7 +2076,6 @@ async function executeInitFabricPlan(plan) {
|
|
|
2104
2076
|
const canonical = [];
|
|
2105
2077
|
const drifted = [];
|
|
2106
2078
|
for (const entry of [
|
|
2107
|
-
{ path: plan.metaPath, state: plan.metaState },
|
|
2108
2079
|
{ path: plan.eventsPath, state: plan.eventsState },
|
|
2109
2080
|
{ path: plan.forensicPath, state: plan.forensicState }
|
|
2110
2081
|
]) {
|
|
@@ -2121,11 +2092,6 @@ async function executeInitFabricPlan(plan) {
|
|
|
2121
2092
|
return {
|
|
2122
2093
|
agentsMdPath: plan.agentsMdPath,
|
|
2123
2094
|
agentsMdAction: plan.agentsMdAction,
|
|
2124
|
-
knowledgeDir: plan.knowledgeDir,
|
|
2125
|
-
knowledgeDirAction: plan.knowledgeDirAction,
|
|
2126
|
-
personalKnowledgeDir: plan.personalKnowledgeDir,
|
|
2127
|
-
metaPath: plan.metaPath,
|
|
2128
|
-
metaAction: plan.metaAction,
|
|
2129
2095
|
eventsPath: plan.eventsPath,
|
|
2130
2096
|
eventsAction: plan.eventsAction,
|
|
2131
2097
|
forensicPath: plan.forensicPath,
|
|
@@ -2175,8 +2141,6 @@ function exhaustiveInitStagePlan(value) {
|
|
|
2175
2141
|
}
|
|
2176
2142
|
function printInitScaffoldResult(created) {
|
|
2177
2143
|
console.log(formatAgentsMdAction(created.agentsMdPath, created.agentsMdAction));
|
|
2178
|
-
console.log(formatInitPathAction(created.knowledgeDir, created.knowledgeDirAction));
|
|
2179
|
-
console.log(formatInitPathAction(created.metaPath, created.metaAction));
|
|
2180
2144
|
console.log(formatInitPathAction(created.eventsPath, created.eventsAction));
|
|
2181
2145
|
console.log(formatInitPathAction(created.forensicPath, created.forensicAction));
|
|
2182
2146
|
}
|
|
@@ -2223,11 +2187,6 @@ function buildPlanOnlyScaffoldResult(plan) {
|
|
|
2223
2187
|
return {
|
|
2224
2188
|
agentsMdPath: plan.agentsMdPath,
|
|
2225
2189
|
agentsMdAction: plan.agentsMdAction,
|
|
2226
|
-
knowledgeDir: plan.knowledgeDir,
|
|
2227
|
-
knowledgeDirAction: plan.knowledgeDirAction,
|
|
2228
|
-
personalKnowledgeDir: plan.personalKnowledgeDir,
|
|
2229
|
-
metaPath: plan.metaPath,
|
|
2230
|
-
metaAction: plan.metaAction,
|
|
2231
2190
|
eventsPath: plan.eventsPath,
|
|
2232
2191
|
eventsAction: plan.eventsAction,
|
|
2233
2192
|
forensicPath: plan.forensicPath,
|
|
@@ -2325,7 +2284,7 @@ function shouldReplaceWritableDirectory(path, _options) {
|
|
|
2325
2284
|
}
|
|
2326
2285
|
return false;
|
|
2327
2286
|
}
|
|
2328
|
-
function classifyFreshPath(path,
|
|
2287
|
+
function classifyFreshPath(path, _strategy) {
|
|
2329
2288
|
if (!existsSync5(path)) {
|
|
2330
2289
|
return { path, state: "missing" };
|
|
2331
2290
|
}
|
|
@@ -2342,30 +2301,7 @@ function classifyFreshPath(path, strategy) {
|
|
|
2342
2301
|
if (!stat.isFile()) {
|
|
2343
2302
|
return { path, state: "user-modified", reason: "expected a file" };
|
|
2344
2303
|
}
|
|
2345
|
-
|
|
2346
|
-
return { path, state: "present-canonical" };
|
|
2347
|
-
}
|
|
2348
|
-
try {
|
|
2349
|
-
const raw = readFileSync4(path, "utf8");
|
|
2350
|
-
const parsed = JSON.parse(raw);
|
|
2351
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
2352
|
-
return { path, state: "user-modified", reason: "not a JSON object" };
|
|
2353
|
-
}
|
|
2354
|
-
const record = parsed;
|
|
2355
|
-
const hasRevision = typeof record["revision"] === "string";
|
|
2356
|
-
const hasNodes = record["nodes"] !== void 0 && record["nodes"] !== null && typeof record["nodes"] === "object" && !Array.isArray(record["nodes"]);
|
|
2357
|
-
const hasCounters = record["counters"] !== void 0 && record["counters"] !== null && typeof record["counters"] === "object" && !Array.isArray(record["counters"]);
|
|
2358
|
-
if (!hasRevision || !hasNodes || !hasCounters) {
|
|
2359
|
-
return { path, state: "drifted", reason: "missing required AgentsMeta fields" };
|
|
2360
|
-
}
|
|
2361
|
-
return { path, state: "present-canonical" };
|
|
2362
|
-
} catch (error) {
|
|
2363
|
-
return {
|
|
2364
|
-
path,
|
|
2365
|
-
state: "user-modified",
|
|
2366
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
2367
|
-
};
|
|
2368
|
-
}
|
|
2304
|
+
return { path, state: "present-canonical" };
|
|
2369
2305
|
}
|
|
2370
2306
|
function diffStateToWriteAction(_state) {
|
|
2371
2307
|
return "created";
|
|
@@ -2554,13 +2490,6 @@ function installLocalFabricServer(target, manager) {
|
|
|
2554
2490
|
shell: process.platform === "win32"
|
|
2555
2491
|
});
|
|
2556
2492
|
}
|
|
2557
|
-
function createInitialMeta() {
|
|
2558
|
-
return {
|
|
2559
|
-
revision: "sha256:initial",
|
|
2560
|
-
nodes: {},
|
|
2561
|
-
counters: defaultAgentsMetaCounters()
|
|
2562
|
-
};
|
|
2563
|
-
}
|
|
2564
2493
|
function appendInstallDiffLedgerEvent(eventsPath, payload) {
|
|
2565
2494
|
const event = {
|
|
2566
2495
|
kind: "fabric-event",
|
|
@@ -2652,8 +2581,6 @@ function printInitPlanSummary(target, options, mcpInstallMode, supports) {
|
|
|
2652
2581
|
})
|
|
2653
2582
|
);
|
|
2654
2583
|
console.log(t("cli.install.plan.writes"));
|
|
2655
|
-
console.log(` - ${target}/.fabric/knowledge/{decisions,pitfalls,guidelines,models,processes,pending}/`);
|
|
2656
|
-
console.log(` - ${target}/.fabric/agents.meta.json`);
|
|
2657
2584
|
console.log(` - ${target}/.fabric/events.jsonl`);
|
|
2658
2585
|
console.log(` - ${target}/.fabric/forensic.json`);
|
|
2659
2586
|
console.log(` - ${target}/.fabric/fabric-config.json`);
|
|
@@ -2799,6 +2726,8 @@ function writeStderr(message) {
|
|
|
2799
2726
|
`);
|
|
2800
2727
|
}
|
|
2801
2728
|
export {
|
|
2729
|
+
bindCreatedStoreToProject,
|
|
2730
|
+
bindRemoteStoreToProject,
|
|
2802
2731
|
buildInitExecutionPlan,
|
|
2803
2732
|
buildInitFabricPlan,
|
|
2804
2733
|
createDefaultInitWizardAdapter,
|
|
@@ -2809,8 +2738,6 @@ export {
|
|
|
2809
2738
|
initFabric,
|
|
2810
2739
|
installCommand,
|
|
2811
2740
|
resolveInitExecutionPlanWithWizard,
|
|
2812
|
-
runHooksOnlyRefresh,
|
|
2813
2741
|
runInitCommand,
|
|
2814
|
-
runSkillsOnlyRefresh,
|
|
2815
2742
|
shouldUseInitWizard
|
|
2816
2743
|
};
|