@fml-inc/fml 0.2.0 → 0.3.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/.claude-plugin/plugin.json +1 -1
- package/dist/{chunk-NFC24I3N.js → chunk-CFPXJT5Q.js} +2 -2
- package/dist/chunk-MUKYS4IB.js +93 -0
- package/dist/chunk-MUKYS4IB.js.map +1 -0
- package/dist/cli.js +53 -41
- package/dist/cli.js.map +1 -1
- package/dist/{daemon-WXE6FYZD.js → daemon-GM3WNS4Z.js} +3 -3
- package/dist/{daemon-utils-EUOTVCKL.js → daemon-utils-CJO4XVJQ.js} +2 -2
- package/dist/mcp/server.js +3 -3
- package/dist/postinstall.js +1 -1
- package/dist/postinstall.js.map +1 -1
- package/package.json +3 -2
- package/scripts/postinstall.cjs +25 -0
- package/dist/chunk-ZKHH6EYQ.js +0 -61
- package/dist/chunk-ZKHH6EYQ.js.map +0 -1
- /package/dist/{chunk-NFC24I3N.js.map → chunk-CFPXJT5Q.js.map} +0 -0
- /package/dist/{daemon-WXE6FYZD.js.map → daemon-GM3WNS4Z.js.map} +0 -0
- /package/dist/{daemon-utils-EUOTVCKL.js.map → daemon-utils-CJO4XVJQ.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
SYNC_PID_FILE,
|
|
3
3
|
isDaemonRunning,
|
|
4
4
|
panopticonExec
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MUKYS4IB.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/daemon.ts
|
|
8
8
|
function parsePanopticonRunning() {
|
|
@@ -30,4 +30,4 @@ export {
|
|
|
30
30
|
handleStart,
|
|
31
31
|
handleStop
|
|
32
32
|
};
|
|
33
|
-
//# sourceMappingURL=chunk-
|
|
33
|
+
//# sourceMappingURL=chunk-CFPXJT5Q.js.map
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FML_DATA_DIR,
|
|
3
|
+
FML_LOG_DIR
|
|
4
|
+
} from "./chunk-4YEAQJPF.js";
|
|
5
|
+
|
|
6
|
+
// src/daemon-utils.ts
|
|
7
|
+
import fs2 from "fs";
|
|
8
|
+
import path2 from "path";
|
|
9
|
+
|
|
10
|
+
// src/bin-utils.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { execFileSync, execSync } from "child_process";
|
|
14
|
+
var IS_WIN = process.platform === "win32";
|
|
15
|
+
var DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
|
|
16
|
+
function resolveBin(name) {
|
|
17
|
+
const pathDirs = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean);
|
|
18
|
+
const hasExt = path.extname(name) !== "";
|
|
19
|
+
const exts = !IS_WIN || hasExt ? [""] : (process.env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean);
|
|
20
|
+
for (const dir of pathDirs) {
|
|
21
|
+
for (const ext of exts) {
|
|
22
|
+
const candidate = path.join(dir, name + ext);
|
|
23
|
+
try {
|
|
24
|
+
if (fs.statSync(candidate).isFile()) return candidate;
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function isWinShim(bin) {
|
|
32
|
+
return IS_WIN && /\.(cmd|bat)$/i.test(bin);
|
|
33
|
+
}
|
|
34
|
+
function quoteWinArg(arg) {
|
|
35
|
+
if (arg.length === 0) return '""';
|
|
36
|
+
if (/^[A-Za-z0-9@\-_+=:/.,]+$/.test(arg)) return arg;
|
|
37
|
+
const crt = arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/, "$1$1");
|
|
38
|
+
const quoted = `"${crt}"`;
|
|
39
|
+
return quoted.replace(/([()%!^<>&|"])/g, "^$1");
|
|
40
|
+
}
|
|
41
|
+
function execBinSync(bin, args, opts = {}) {
|
|
42
|
+
const { timeout = 1e4, encoding = "utf-8", stdio = "pipe" } = opts;
|
|
43
|
+
if (isWinShim(bin)) {
|
|
44
|
+
const command = [bin, ...args].map(quoteWinArg).join(" ");
|
|
45
|
+
return execSync(command, { timeout, encoding, stdio });
|
|
46
|
+
}
|
|
47
|
+
return execFileSync(bin, args, { timeout, encoding, stdio });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/daemon-utils.ts
|
|
51
|
+
var SYNC_PID_FILE = path2.join(FML_DATA_DIR, "sync.pid");
|
|
52
|
+
var SYNC_LOG_FILE = path2.join(FML_LOG_DIR, "sync.log");
|
|
53
|
+
function isDaemonRunning(pidFile) {
|
|
54
|
+
if (!fs2.existsSync(pidFile)) return { running: false, pid: null };
|
|
55
|
+
const pid = parseInt(fs2.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
56
|
+
try {
|
|
57
|
+
process.kill(pid, 0);
|
|
58
|
+
return { running: true, pid };
|
|
59
|
+
} catch {
|
|
60
|
+
return { running: false, pid };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function resolvePanopticonBin() {
|
|
64
|
+
return resolveBin("panopticon");
|
|
65
|
+
}
|
|
66
|
+
function panopticonExec(...argsAndOpts) {
|
|
67
|
+
let timeout = 1e4;
|
|
68
|
+
const args = [];
|
|
69
|
+
for (const a of argsAndOpts) {
|
|
70
|
+
if (typeof a === "string") args.push(a);
|
|
71
|
+
else timeout = a.timeout ?? timeout;
|
|
72
|
+
}
|
|
73
|
+
const bin = resolvePanopticonBin();
|
|
74
|
+
if (!bin) return { ok: false, stdout: "panopticon binary not found" };
|
|
75
|
+
try {
|
|
76
|
+
const stdout = execBinSync(bin, args, { timeout });
|
|
77
|
+
return { ok: true, stdout };
|
|
78
|
+
} catch (err) {
|
|
79
|
+
const e = err;
|
|
80
|
+
return { ok: false, stdout: (e.stdout ?? "") + (e.stderr ?? "") };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
resolveBin,
|
|
86
|
+
execBinSync,
|
|
87
|
+
SYNC_PID_FILE,
|
|
88
|
+
SYNC_LOG_FILE,
|
|
89
|
+
isDaemonRunning,
|
|
90
|
+
resolvePanopticonBin,
|
|
91
|
+
panopticonExec
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=chunk-MUKYS4IB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/daemon-utils.ts","../src/bin-utils.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execBinSync, resolveBin } from \"./bin-utils.js\";\nimport { FML_DATA_DIR, FML_LOG_DIR } from \"./dirs.js\";\n\nexport const SYNC_PID_FILE = path.join(FML_DATA_DIR, \"sync.pid\");\nexport const SYNC_LOG_FILE = path.join(FML_LOG_DIR, \"sync.log\");\n\nexport function isDaemonRunning(pidFile: string): {\n running: boolean;\n pid: number | null;\n} {\n if (!fs.existsSync(pidFile)) return { running: false, pid: null };\n const pid = parseInt(fs.readFileSync(pidFile, \"utf-8\").trim(), 10);\n try {\n process.kill(pid, 0);\n return { running: true, pid };\n } catch {\n return { running: false, pid };\n }\n}\n\n/** Resolve the panopticon CLI binary from PATH (globally installed). */\nexport function resolvePanopticonBin(): string | null {\n return resolveBin(\"panopticon\");\n}\n\n/** Run a panopticon CLI command and return stdout. */\nexport function panopticonExec(...args: string[]): {\n ok: boolean;\n stdout: string;\n};\nexport function panopticonExec(\n ...argsAndOpts: [...string[], { timeout?: number }]\n): { ok: boolean; stdout: string };\nexport function panopticonExec(\n ...argsAndOpts: Array<string | { timeout?: number }>\n): {\n ok: boolean;\n stdout: string;\n} {\n let timeout = 10_000;\n const args: string[] = [];\n for (const a of argsAndOpts) {\n if (typeof a === \"string\") args.push(a);\n else timeout = a.timeout ?? timeout;\n }\n const bin = resolvePanopticonBin();\n if (!bin) return { ok: false, stdout: \"panopticon binary not found\" };\n try {\n const stdout = execBinSync(bin, args, { timeout });\n return { ok: true, stdout };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; status?: number };\n return { ok: false, stdout: (e.stdout ?? \"\") + (e.stderr ?? \"\") };\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execFileSync, execSync } from \"node:child_process\";\n\nconst IS_WIN = process.platform === \"win32\";\nconst DEFAULT_PATHEXT = \".COM;.EXE;.BAT;.CMD\";\n\n/**\n * Resolve a CLI binary by walking process.env.PATH. On Windows, probe each\n * process.env.PATHEXT extension. Returns an absolute path or null.\n *\n * Pass the bare command name (e.g. \"npm\", not \"npm.cmd\"); the extension is\n * applied via PATHEXT on Windows. If the caller does include an extension,\n * it's used as-is.\n *\n * Replaces `which`/`where`: avoids spawning a child process and works the\n * same on macOS, Linux, and Windows.\n */\nexport function resolveBin(name: string): string | null {\n const pathDirs = (process.env.PATH ?? \"\").split(path.delimiter).filter(Boolean);\n const hasExt = path.extname(name) !== \"\";\n const exts = !IS_WIN || hasExt\n ? [\"\"]\n : (process.env.PATHEXT ?? DEFAULT_PATHEXT).split(\";\").filter(Boolean);\n\n for (const dir of pathDirs) {\n for (const ext of exts) {\n const candidate = path.join(dir, name + ext);\n try {\n if (fs.statSync(candidate).isFile()) return candidate;\n } catch {}\n }\n }\n return null;\n}\n\n/** True for Windows shell shims that execFile cannot run directly. */\nfunction isWinShim(bin: string): boolean {\n return IS_WIN && /\\.(cmd|bat)$/i.test(bin);\n}\n\n/**\n * Quote a single argument for safe inclusion in a Windows command line that\n * will be parsed by cmd.exe and then re-parsed by a CRT program.\n *\n * Two layers:\n * 1. CRT (CommandLineToArgvW): wrap in `\"`, escape internal `\"` as `\\\"`,\n * double any backslashes that precede a quote.\n * 2. cmd.exe: escape its metacharacters with `^` so they aren't expanded\n * before the CRT layer sees them. `%` and `!` (delayed expansion) are\n * the dangerous ones inside quotes; the rest are safest belt-and-braces.\n */\nexport function quoteWinArg(arg: string): string {\n if (arg.length === 0) return '\"\"';\n\n // Fast path: bare-word args that need no quoting at all.\n // Backslash is intentionally excluded so `path\\` and similar still go\n // through the trailing-backslash doubling logic below.\n if (/^[A-Za-z0-9@\\-_+=:/.,]+$/.test(arg)) return arg;\n\n // CRT layer: double backslashes before quotes, escape quotes, double trailing backslashes.\n const crt = arg\n .replace(/(\\\\*)\"/g, '$1$1\\\\\"')\n .replace(/(\\\\+)$/, \"$1$1\");\n const quoted = `\"${crt}\"`;\n\n // cmd.exe layer: escape metacharacters (including the surrounding quotes)\n // so cmd's first pass passes them through verbatim.\n return quoted.replace(/([()%!^<>&|\"])/g, \"^$1\");\n}\n\nexport interface ExecBinOptions {\n timeout?: number;\n encoding?: BufferEncoding;\n stdio?: \"pipe\" | \"inherit\" | \"ignore\";\n}\n\n/**\n * Run a resolved binary path with the given args, handling Windows .cmd/.bat\n * shims correctly. Throws on non-zero exit (matching execFileSync).\n */\nexport function execBinSync(\n bin: string,\n args: string[],\n opts: ExecBinOptions = {},\n): string {\n const { timeout = 10_000, encoding = \"utf-8\", stdio = \"pipe\" } = opts;\n\n if (isWinShim(bin)) {\n // CVE-2024-27980: Node refuses to spawn .cmd/.bat without shell: true.\n // Build the command string ourselves so we control the quoting.\n const command = [bin, ...args].map(quoteWinArg).join(\" \");\n return execSync(command, { timeout, encoding, stdio });\n }\n\n return execFileSync(bin, args, { timeout, encoding, stdio });\n}\n"],"mappings":";;;;;;AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,cAAc,gBAAgB;AAEvC,IAAM,SAAS,QAAQ,aAAa;AACpC,IAAM,kBAAkB;AAajB,SAAS,WAAW,MAA6B;AACtD,QAAM,YAAY,QAAQ,IAAI,QAAQ,IAAI,MAAM,KAAK,SAAS,EAAE,OAAO,OAAO;AAC9E,QAAM,SAAS,KAAK,QAAQ,IAAI,MAAM;AACtC,QAAM,OAAO,CAAC,UAAU,SACpB,CAAC,EAAE,KACF,QAAQ,IAAI,WAAW,iBAAiB,MAAM,GAAG,EAAE,OAAO,OAAO;AAEtE,aAAW,OAAO,UAAU;AAC1B,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,KAAK,KAAK,KAAK,OAAO,GAAG;AAC3C,UAAI;AACF,YAAI,GAAG,SAAS,SAAS,EAAE,OAAO,EAAG,QAAO;AAAA,MAC9C,QAAQ;AAAA,MAAC;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,UAAU,KAAsB;AACvC,SAAO,UAAU,gBAAgB,KAAK,GAAG;AAC3C;AAaO,SAAS,YAAY,KAAqB;AAC/C,MAAI,IAAI,WAAW,EAAG,QAAO;AAK7B,MAAI,2BAA2B,KAAK,GAAG,EAAG,QAAO;AAGjD,QAAM,MAAM,IACT,QAAQ,WAAW,SAAS,EAC5B,QAAQ,UAAU,MAAM;AAC3B,QAAM,SAAS,IAAI,GAAG;AAItB,SAAO,OAAO,QAAQ,mBAAmB,KAAK;AAChD;AAYO,SAAS,YACd,KACA,MACA,OAAuB,CAAC,GAChB;AACR,QAAM,EAAE,UAAU,KAAQ,WAAW,SAAS,QAAQ,OAAO,IAAI;AAEjE,MAAI,UAAU,GAAG,GAAG;AAGlB,UAAM,UAAU,CAAC,KAAK,GAAG,IAAI,EAAE,IAAI,WAAW,EAAE,KAAK,GAAG;AACxD,WAAO,SAAS,SAAS,EAAE,SAAS,UAAU,MAAM,CAAC;AAAA,EACvD;AAEA,SAAO,aAAa,KAAK,MAAM,EAAE,SAAS,UAAU,MAAM,CAAC;AAC7D;;;AD3FO,IAAM,gBAAgBC,MAAK,KAAK,cAAc,UAAU;AACxD,IAAM,gBAAgBA,MAAK,KAAK,aAAa,UAAU;AAEvD,SAAS,gBAAgB,SAG9B;AACA,MAAI,CAACC,IAAG,WAAW,OAAO,EAAG,QAAO,EAAE,SAAS,OAAO,KAAK,KAAK;AAChE,QAAM,MAAM,SAASA,IAAG,aAAa,SAAS,OAAO,EAAE,KAAK,GAAG,EAAE;AACjE,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO,EAAE,SAAS,MAAM,IAAI;AAAA,EAC9B,QAAQ;AACN,WAAO,EAAE,SAAS,OAAO,IAAI;AAAA,EAC/B;AACF;AAGO,SAAS,uBAAsC;AACpD,SAAO,WAAW,YAAY;AAChC;AAUO,SAAS,kBACX,aAIH;AACA,MAAI,UAAU;AACd,QAAM,OAAiB,CAAC;AACxB,aAAW,KAAK,aAAa;AAC3B,QAAI,OAAO,MAAM,SAAU,MAAK,KAAK,CAAC;AAAA,QACjC,WAAU,EAAE,WAAW;AAAA,EAC9B;AACA,QAAM,MAAM,qBAAqB;AACjC,MAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,QAAQ,8BAA8B;AACpE,MAAI;AACF,UAAM,SAAS,YAAY,KAAK,MAAM,EAAE,QAAQ,CAAC;AACjD,WAAO,EAAE,IAAI,MAAM,OAAO;AAAA,EAC5B,SAAS,KAAc;AACrB,UAAM,IAAI;AACV,WAAO,EAAE,IAAI,OAAO,SAAS,EAAE,UAAU,OAAO,EAAE,UAAU,IAAI;AAAA,EAClE;AACF;","names":["fs","path","path","fs"]}
|
package/dist/cli.js
CHANGED
|
@@ -27,10 +27,12 @@ import {
|
|
|
27
27
|
handleStart,
|
|
28
28
|
handleStop,
|
|
29
29
|
parsePanopticonRunning
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-CFPXJT5Q.js";
|
|
31
31
|
import {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
execBinSync,
|
|
33
|
+
panopticonExec,
|
|
34
|
+
resolveBin
|
|
35
|
+
} from "./chunk-MUKYS4IB.js";
|
|
34
36
|
import {
|
|
35
37
|
FML_DATA_DIR,
|
|
36
38
|
FML_LOG_DIR
|
|
@@ -273,7 +275,6 @@ async function handleDoctor(opts) {
|
|
|
273
275
|
}
|
|
274
276
|
|
|
275
277
|
// src/commands/install.ts
|
|
276
|
-
import { execFileSync } from "child_process";
|
|
277
278
|
import fs from "fs";
|
|
278
279
|
import os from "os";
|
|
279
280
|
import path from "path";
|
|
@@ -369,7 +370,7 @@ async function handleInstall() {
|
|
|
369
370
|
const pluginRoot = getPluginRoot();
|
|
370
371
|
console.log("Installing fml...\n");
|
|
371
372
|
console.log("[1/5] Setting up panopticon...");
|
|
372
|
-
const { resolvePanopticonBin } = await import("./daemon-utils-
|
|
373
|
+
const { resolvePanopticonBin } = await import("./daemon-utils-CJO4XVJQ.js");
|
|
373
374
|
let freshInstall = false;
|
|
374
375
|
const bin = resolvePanopticonBin();
|
|
375
376
|
let needsInstall = !bin;
|
|
@@ -386,18 +387,22 @@ async function handleInstall() {
|
|
|
386
387
|
console.log(
|
|
387
388
|
bin ? " Upgrading @fml-inc/panopticon..." : " Installing @fml-inc/panopticon globally..."
|
|
388
389
|
);
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
timeout: 12e4,
|
|
393
|
-
stdio: "pipe"
|
|
394
|
-
});
|
|
395
|
-
freshInstall = true;
|
|
396
|
-
console.log(" Installed @fml-inc/panopticon");
|
|
397
|
-
} catch (err) {
|
|
398
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
399
|
-
console.error(` Failed to install panopticon: ${msg}`);
|
|
390
|
+
const npmBin = resolveBin("npm");
|
|
391
|
+
if (!npmBin) {
|
|
392
|
+
console.error(" Failed to install panopticon: npm not found on PATH");
|
|
400
393
|
console.error(" Install manually: npm install -g @fml-inc/panopticon@latest");
|
|
394
|
+
} else {
|
|
395
|
+
try {
|
|
396
|
+
execBinSync(npmBin, ["install", "-g", "@fml-inc/panopticon@latest"], {
|
|
397
|
+
timeout: 12e4
|
|
398
|
+
});
|
|
399
|
+
freshInstall = true;
|
|
400
|
+
console.log(" Installed @fml-inc/panopticon");
|
|
401
|
+
} catch (err) {
|
|
402
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
403
|
+
console.error(` Failed to install panopticon: ${msg}`);
|
|
404
|
+
console.error(" Install manually: npm install -g @fml-inc/panopticon@latest");
|
|
405
|
+
}
|
|
401
406
|
}
|
|
402
407
|
}
|
|
403
408
|
if (!freshInstall) {
|
|
@@ -481,21 +486,26 @@ async function handleInstall() {
|
|
|
481
486
|
settings.enabledPlugins["fml@local-plugins"] = true;
|
|
482
487
|
writeJsonFile(CLAUDE_SETTINGS_PATH, settings);
|
|
483
488
|
console.log(` Claude settings: ${CLAUDE_SETTINGS_PATH}`);
|
|
484
|
-
|
|
489
|
+
const claudeBin = resolveBin("claude");
|
|
490
|
+
if (!claudeBin) {
|
|
491
|
+
console.log(" warn: claude CLI not found, run 'claude plugin install fml@local-plugins' manually");
|
|
492
|
+
} else {
|
|
485
493
|
try {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
494
|
+
try {
|
|
495
|
+
execBinSync(claudeBin, ["plugin", "install", "fml@local-plugins"], {
|
|
496
|
+
timeout: 15e3
|
|
497
|
+
});
|
|
498
|
+
} catch {
|
|
499
|
+
execBinSync(claudeBin, ["plugin", "update", "fml@local-plugins"], {
|
|
500
|
+
timeout: 15e3
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
console.log(" Plugin registered via Claude Code CLI");
|
|
504
|
+
} catch (err) {
|
|
505
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
506
|
+
console.log(` warn: claude plugin install/update failed: ${msg}`);
|
|
507
|
+
console.log(" Run 'claude plugin install fml@local-plugins' manually");
|
|
495
508
|
}
|
|
496
|
-
console.log(" Plugin registered via Claude Code CLI");
|
|
497
|
-
} catch {
|
|
498
|
-
console.log(" warn: claude CLI not found, run 'claude plugin install fml@local-plugins' manually");
|
|
499
509
|
}
|
|
500
510
|
console.log();
|
|
501
511
|
console.log("[5/5] Configuring sync target...");
|
|
@@ -531,7 +541,6 @@ async function handleInstall() {
|
|
|
531
541
|
}
|
|
532
542
|
|
|
533
543
|
// src/commands/uninstall.ts
|
|
534
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
535
544
|
import fs2 from "fs";
|
|
536
545
|
import os2 from "os";
|
|
537
546
|
import path2 from "path";
|
|
@@ -568,14 +577,17 @@ function handleUninstall(opts) {
|
|
|
568
577
|
console.log("[1/5] Skipping plugin uninstall (target-specific uninstall)");
|
|
569
578
|
} else {
|
|
570
579
|
console.log("[1/5] Uninstalling MCP plugin...");
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
580
|
+
const claudeBin = resolveBin("claude");
|
|
581
|
+
if (claudeBin) {
|
|
582
|
+
try {
|
|
583
|
+
execBinSync(
|
|
584
|
+
claudeBin,
|
|
585
|
+
["plugin", "uninstall", "fml@local-plugins", "--scope", "user"],
|
|
586
|
+
{ timeout: 1e4 }
|
|
587
|
+
);
|
|
588
|
+
console.log(" Uninstalled (user scope)");
|
|
589
|
+
} catch {
|
|
590
|
+
}
|
|
579
591
|
}
|
|
580
592
|
const installedPluginsPath = path2.join(
|
|
581
593
|
CLAUDE_DIR2,
|
|
@@ -689,7 +701,7 @@ function handleUninstall(opts) {
|
|
|
689
701
|
// src/commands/update.ts
|
|
690
702
|
import { execSync as execSync2 } from "child_process";
|
|
691
703
|
async function handleUpdate() {
|
|
692
|
-
const currentVersion = true ? "0.
|
|
704
|
+
const currentVersion = true ? "0.3.0+3bdd3b3" : "unknown";
|
|
693
705
|
console.log(`Current: ${currentVersion}`);
|
|
694
706
|
console.log("Updating via npm...\n");
|
|
695
707
|
try {
|
|
@@ -1934,7 +1946,7 @@ async function handleConfigDetail(opts) {
|
|
|
1934
1946
|
// src/commands/tools.ts
|
|
1935
1947
|
import { readFileSync } from "fs";
|
|
1936
1948
|
import path3 from "path";
|
|
1937
|
-
var pluginVersion = true ? "0.
|
|
1949
|
+
var pluginVersion = true ? "0.3.0+3bdd3b3" : void 0;
|
|
1938
1950
|
async function getApi() {
|
|
1939
1951
|
const api = await getAuthenticatedClient();
|
|
1940
1952
|
if (!api) {
|
|
@@ -2066,7 +2078,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
2066
2078
|
printBanner();
|
|
2067
2079
|
}
|
|
2068
2080
|
var program = new Command().name("fml").description("FML agent tools for Claude Code").version(
|
|
2069
|
-
true ? "0.
|
|
2081
|
+
true ? "0.3.0+3bdd3b3" : "dev"
|
|
2070
2082
|
);
|
|
2071
2083
|
var tools = program.command("tools", { hidden: true }).description("List all available CLI commands (including hidden agent tools)").action(() => {
|
|
2072
2084
|
function formatCmd(cmd, prefix = "") {
|