@fml-inc/fml 0.8.0-rc.2 → 0.8.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/README.md +12 -10
- package/dist/{chunk-WZLLO563.js → chunk-7DWFJENY.js} +1 -1
- package/dist/{chunk-56TPYMNK.js → chunk-KBT5RMAU.js} +19 -3
- package/dist/cli.js +414 -209
- package/dist/hook-handler.js +10 -3
- package/dist/observer-server.js +3 -3
- package/dist/pi/extension.js +350 -0
- package/package.json +4 -2
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
isPidAlive,
|
|
11
11
|
readObserverStateStatus,
|
|
12
12
|
removeObserverStateIfOwned
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7DWFJENY.js";
|
|
14
14
|
import {
|
|
15
15
|
readJsonFile,
|
|
16
16
|
setHookCaptureDisabled,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
isObserverHealth,
|
|
25
25
|
readHookInboxStatus,
|
|
26
26
|
readObserverAuthToken
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-KBT5RMAU.js";
|
|
28
28
|
import "./chunk-7V7G7NVF.js";
|
|
29
29
|
import {
|
|
30
30
|
claudeConfigDirectory,
|
|
@@ -124,7 +124,7 @@ var POLL_INTERVAL_MS = 50;
|
|
|
124
124
|
var LOG_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
125
125
|
var LOG_ROTATE_FILES = 3;
|
|
126
126
|
function expectedObserverVersion() {
|
|
127
|
-
return true ? "0.8.0
|
|
127
|
+
return true ? "0.8.0+246af775" : "dev";
|
|
128
128
|
}
|
|
129
129
|
function delay(ms) {
|
|
130
130
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -1062,9 +1062,9 @@ async function handleDoctor(opts) {
|
|
|
1062
1062
|
}
|
|
1063
1063
|
|
|
1064
1064
|
// src/commands/install.ts
|
|
1065
|
-
import
|
|
1065
|
+
import fs10 from "fs";
|
|
1066
1066
|
import os5 from "os";
|
|
1067
|
-
import
|
|
1067
|
+
import path22 from "path";
|
|
1068
1068
|
import { fileURLToPath } from "url";
|
|
1069
1069
|
|
|
1070
1070
|
// ../../packages/agent-targets/src/install/claude/index.ts
|
|
@@ -1305,21 +1305,166 @@ var CLAUDE_PLUGIN_INSTALLER = Object.freeze({
|
|
|
1305
1305
|
})
|
|
1306
1306
|
});
|
|
1307
1307
|
|
|
1308
|
-
// src/
|
|
1308
|
+
// ../../packages/agent-targets/src/install/pi/index.ts
|
|
1309
1309
|
import fs3 from "fs";
|
|
1310
1310
|
import path4 from "path";
|
|
1311
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1312
|
+
var FML_PI_EXTENSION_MARKER = "__FML_PI_EXTENSION_V1__";
|
|
1313
|
+
var LEGACY_PI_EXTENSION_MARKER = "__panopticonPiExtensionTest";
|
|
1314
|
+
var LEGACY_PI_EXTENSION_SIGNATURES = Object.freeze([
|
|
1315
|
+
"PANOPTICON_PORT",
|
|
1316
|
+
'"/hooks"',
|
|
1317
|
+
"UserPromptSubmit",
|
|
1318
|
+
"PreToolUse",
|
|
1319
|
+
"PostToolUse",
|
|
1320
|
+
"SessionEnd"
|
|
1321
|
+
]);
|
|
1322
|
+
function pathApiFor(platform) {
|
|
1323
|
+
return platform === "win32" ? path4.win32 : path4.posix;
|
|
1324
|
+
}
|
|
1325
|
+
function resolvePiAgentDir(context, pathApi) {
|
|
1326
|
+
const configured = context.env.PI_CODING_AGENT_DIR?.trim();
|
|
1327
|
+
if (!configured) {
|
|
1328
|
+
return pathApi.join(context.homeDir, ".pi", "agent");
|
|
1329
|
+
}
|
|
1330
|
+
if (configured === "~") return context.homeDir;
|
|
1331
|
+
if (configured.startsWith("~/") || configured.startsWith("~\\")) {
|
|
1332
|
+
return pathApi.join(context.homeDir, configured.slice(2));
|
|
1333
|
+
}
|
|
1334
|
+
return pathApi.normalize(configured);
|
|
1335
|
+
}
|
|
1336
|
+
function readFileIfPresent(filePath) {
|
|
1337
|
+
try {
|
|
1338
|
+
return fs3.readFileSync(filePath, "utf8");
|
|
1339
|
+
} catch (error) {
|
|
1340
|
+
if (error.code === "ENOENT") return null;
|
|
1341
|
+
throw error;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function isOwnedExtension(source, legacy = false) {
|
|
1345
|
+
return source.includes(FML_PI_EXTENSION_MARKER) || legacy && (source.includes(LEGACY_PI_EXTENSION_MARKER) || LEGACY_PI_EXTENSION_SIGNATURES.every(
|
|
1346
|
+
(signature) => source.includes(signature)
|
|
1347
|
+
));
|
|
1348
|
+
}
|
|
1349
|
+
function removeLegacyExtension(filePath) {
|
|
1350
|
+
const source = readFileIfPresent(filePath);
|
|
1351
|
+
if (source === null) return { removed: false, preserved: false };
|
|
1352
|
+
if (!isOwnedExtension(source, true)) {
|
|
1353
|
+
return { removed: false, preserved: true };
|
|
1354
|
+
}
|
|
1355
|
+
fs3.rmSync(filePath);
|
|
1356
|
+
return { removed: true, preserved: false };
|
|
1357
|
+
}
|
|
1358
|
+
function writeExtensionAtomically(filePath, source) {
|
|
1359
|
+
fs3.mkdirSync(path4.dirname(filePath), { recursive: true, mode: 448 });
|
|
1360
|
+
const temporaryPath = path4.join(
|
|
1361
|
+
path4.dirname(filePath),
|
|
1362
|
+
`.${path4.basename(filePath)}.${process.pid}.${randomUUID2()}.tmp`
|
|
1363
|
+
);
|
|
1364
|
+
try {
|
|
1365
|
+
fs3.writeFileSync(temporaryPath, source, { encoding: "utf8", mode: 384 });
|
|
1366
|
+
if (process.platform === "win32" && fs3.existsSync(filePath)) {
|
|
1367
|
+
fs3.rmSync(filePath);
|
|
1368
|
+
}
|
|
1369
|
+
fs3.renameSync(temporaryPath, filePath);
|
|
1370
|
+
} finally {
|
|
1371
|
+
fs3.rmSync(temporaryPath, { force: true });
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
var PI_EXTENSION_INSTALLER = Object.freeze({
|
|
1375
|
+
resolvePaths(context) {
|
|
1376
|
+
const pathApi = pathApiFor(context.platform);
|
|
1377
|
+
const extensionsDir = pathApi.join(
|
|
1378
|
+
resolvePiAgentDir(context, pathApi),
|
|
1379
|
+
"extensions"
|
|
1380
|
+
);
|
|
1381
|
+
return {
|
|
1382
|
+
sourcePath: pathApi.join(
|
|
1383
|
+
context.packageRoot,
|
|
1384
|
+
"dist",
|
|
1385
|
+
"pi",
|
|
1386
|
+
"extension.js"
|
|
1387
|
+
),
|
|
1388
|
+
extensionsDir,
|
|
1389
|
+
destinationPath: pathApi.join(extensionsDir, "fml.js"),
|
|
1390
|
+
legacyDestinationPath: pathApi.join(extensionsDir, "panopticon.js")
|
|
1391
|
+
};
|
|
1392
|
+
},
|
|
1393
|
+
install(paths) {
|
|
1394
|
+
const source = fs3.readFileSync(paths.sourcePath, "utf8");
|
|
1395
|
+
if (!source.includes(FML_PI_EXTENSION_MARKER)) {
|
|
1396
|
+
throw new Error(
|
|
1397
|
+
`Packaged Pi extension is invalid: ${paths.sourcePath} does not contain the FML ownership marker`
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
const existing = readFileIfPresent(paths.destinationPath);
|
|
1401
|
+
if (existing !== null && !isOwnedExtension(existing)) {
|
|
1402
|
+
const legacy2 = removeLegacyExtension(paths.legacyDestinationPath);
|
|
1403
|
+
return {
|
|
1404
|
+
status: "preserved",
|
|
1405
|
+
destinationPath: paths.destinationPath,
|
|
1406
|
+
reason: "an extension not managed by FML already exists at this path",
|
|
1407
|
+
legacyRemoved: legacy2.removed,
|
|
1408
|
+
legacyPreserved: legacy2.preserved
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
const status = existing === null ? "installed" : existing === source ? "unchanged" : "updated";
|
|
1412
|
+
if (status !== "unchanged") {
|
|
1413
|
+
writeExtensionAtomically(paths.destinationPath, source);
|
|
1414
|
+
}
|
|
1415
|
+
const legacy = removeLegacyExtension(paths.legacyDestinationPath);
|
|
1416
|
+
return {
|
|
1417
|
+
status,
|
|
1418
|
+
destinationPath: paths.destinationPath,
|
|
1419
|
+
legacyRemoved: legacy.removed,
|
|
1420
|
+
legacyPreserved: legacy.preserved
|
|
1421
|
+
};
|
|
1422
|
+
},
|
|
1423
|
+
uninstall(paths) {
|
|
1424
|
+
const existing = readFileIfPresent(paths.destinationPath);
|
|
1425
|
+
const legacy = removeLegacyExtension(paths.legacyDestinationPath);
|
|
1426
|
+
if (existing === null) {
|
|
1427
|
+
return {
|
|
1428
|
+
status: "absent",
|
|
1429
|
+
destinationPath: paths.destinationPath,
|
|
1430
|
+
legacyRemoved: legacy.removed,
|
|
1431
|
+
legacyPreserved: legacy.preserved
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
if (!isOwnedExtension(existing)) {
|
|
1435
|
+
return {
|
|
1436
|
+
status: "preserved",
|
|
1437
|
+
destinationPath: paths.destinationPath,
|
|
1438
|
+
reason: "the existing extension is not managed by FML",
|
|
1439
|
+
legacyRemoved: legacy.removed,
|
|
1440
|
+
legacyPreserved: legacy.preserved
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
fs3.rmSync(paths.destinationPath);
|
|
1444
|
+
return {
|
|
1445
|
+
status: "removed",
|
|
1446
|
+
destinationPath: paths.destinationPath,
|
|
1447
|
+
legacyRemoved: legacy.removed,
|
|
1448
|
+
legacyPreserved: legacy.preserved
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
|
|
1453
|
+
// src/bin-utils.ts
|
|
1454
|
+
import fs4 from "fs";
|
|
1455
|
+
import path5 from "path";
|
|
1311
1456
|
import { execFileSync, execSync } from "child_process";
|
|
1312
1457
|
var IS_WIN = process.platform === "win32";
|
|
1313
1458
|
var DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
|
|
1314
1459
|
function resolveBin(name) {
|
|
1315
|
-
const pathDirs = (process.env.PATH ?? "").split(
|
|
1316
|
-
const hasExt =
|
|
1460
|
+
const pathDirs = (process.env.PATH ?? "").split(path5.delimiter).filter(Boolean);
|
|
1461
|
+
const hasExt = path5.extname(name) !== "";
|
|
1317
1462
|
const exts = !IS_WIN || hasExt ? [""] : (process.env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean);
|
|
1318
1463
|
for (const dir of pathDirs) {
|
|
1319
1464
|
for (const ext of exts) {
|
|
1320
|
-
const candidate =
|
|
1465
|
+
const candidate = path5.join(dir, name + ext);
|
|
1321
1466
|
try {
|
|
1322
|
-
if (
|
|
1467
|
+
if (fs4.statSync(candidate).isFile()) return candidate;
|
|
1323
1468
|
} catch {
|
|
1324
1469
|
}
|
|
1325
1470
|
}
|
|
@@ -1351,18 +1496,18 @@ function execBinSync(bin, args, opts = {}) {
|
|
|
1351
1496
|
}
|
|
1352
1497
|
|
|
1353
1498
|
// src/managed-directories.ts
|
|
1354
|
-
import
|
|
1499
|
+
import fs5 from "fs";
|
|
1355
1500
|
import os from "os";
|
|
1356
|
-
import
|
|
1501
|
+
import path6 from "path";
|
|
1357
1502
|
var FML_MANAGED_DIRECTORY_MARKER = ".fml-managed-root";
|
|
1358
1503
|
var FML_MANAGED_DIRECTORY_MARKER_CONTENT = "fml-managed-directory-v1\n";
|
|
1359
1504
|
function comparisonPathApi(platform, targetPaths) {
|
|
1360
1505
|
if (platform === "win32" && targetPaths.some(
|
|
1361
1506
|
(targetPath) => /^[A-Za-z]:[\\/]/u.test(targetPath) || targetPath.startsWith("\\\\") || targetPath.startsWith("//")
|
|
1362
1507
|
)) {
|
|
1363
|
-
return
|
|
1508
|
+
return path6.win32;
|
|
1364
1509
|
}
|
|
1365
|
-
return
|
|
1510
|
+
return path6;
|
|
1366
1511
|
}
|
|
1367
1512
|
function resolveComparisonPath(targetPath, platform) {
|
|
1368
1513
|
return comparisonPathApi(platform, [targetPath]).resolve(targetPath);
|
|
@@ -1435,7 +1580,7 @@ function configuredManagedRoots(platform = process.platform) {
|
|
|
1435
1580
|
);
|
|
1436
1581
|
}
|
|
1437
1582
|
function managedDirectoryMarker(directory) {
|
|
1438
|
-
return
|
|
1583
|
+
return path6.join(directory, FML_MANAGED_DIRECTORY_MARKER);
|
|
1439
1584
|
}
|
|
1440
1585
|
function ownershipStatus(stats, platform) {
|
|
1441
1586
|
if (platform === "win32") return "unverifiable";
|
|
@@ -1446,8 +1591,8 @@ function ownershipStatus(stats, platform) {
|
|
|
1446
1591
|
function hasManagedDirectoryMarkerContents(directory) {
|
|
1447
1592
|
const marker = managedDirectoryMarker(directory);
|
|
1448
1593
|
try {
|
|
1449
|
-
const stats =
|
|
1450
|
-
return stats.isFile() &&
|
|
1594
|
+
const stats = fs5.lstatSync(marker);
|
|
1595
|
+
return stats.isFile() && fs5.readFileSync(marker, "utf8") === FML_MANAGED_DIRECTORY_MARKER_CONTENT;
|
|
1451
1596
|
} catch {
|
|
1452
1597
|
return false;
|
|
1453
1598
|
}
|
|
@@ -1455,11 +1600,11 @@ function hasManagedDirectoryMarkerContents(directory) {
|
|
|
1455
1600
|
function hasManagedDirectoryMarker(directory, platform = process.platform) {
|
|
1456
1601
|
const marker = managedDirectoryMarker(directory);
|
|
1457
1602
|
try {
|
|
1458
|
-
const stats =
|
|
1603
|
+
const stats = fs5.lstatSync(marker);
|
|
1459
1604
|
if (!stats.isFile() || ownershipStatus(stats, platform) !== "owned") {
|
|
1460
1605
|
return false;
|
|
1461
1606
|
}
|
|
1462
|
-
return
|
|
1607
|
+
return fs5.readFileSync(marker, "utf8") === FML_MANAGED_DIRECTORY_MARKER_CONTENT;
|
|
1463
1608
|
} catch {
|
|
1464
1609
|
return false;
|
|
1465
1610
|
}
|
|
@@ -1467,7 +1612,7 @@ function hasManagedDirectoryMarker(directory, platform = process.platform) {
|
|
|
1467
1612
|
function writeManagedDirectoryMarker(directory, platform) {
|
|
1468
1613
|
const marker = managedDirectoryMarker(directory);
|
|
1469
1614
|
try {
|
|
1470
|
-
|
|
1615
|
+
fs5.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
|
|
1471
1616
|
encoding: "utf8",
|
|
1472
1617
|
flag: "wx",
|
|
1473
1618
|
mode: 384
|
|
@@ -1492,23 +1637,23 @@ function prepareManagedDirectory(root, platform = process.platform) {
|
|
|
1492
1637
|
let created = false;
|
|
1493
1638
|
let existingStats = null;
|
|
1494
1639
|
try {
|
|
1495
|
-
existingStats =
|
|
1640
|
+
existingStats = fs5.lstatSync(root.directory);
|
|
1496
1641
|
} catch (error) {
|
|
1497
1642
|
if (error.code !== "ENOENT") throw error;
|
|
1498
1643
|
existed = false;
|
|
1499
1644
|
}
|
|
1500
1645
|
if (!existed) {
|
|
1501
|
-
|
|
1646
|
+
fs5.mkdirSync(path6.dirname(root.directory), {
|
|
1502
1647
|
recursive: true,
|
|
1503
1648
|
mode: 448
|
|
1504
1649
|
});
|
|
1505
1650
|
try {
|
|
1506
|
-
|
|
1651
|
+
fs5.mkdirSync(root.directory, { mode: 448 });
|
|
1507
1652
|
created = true;
|
|
1508
1653
|
} catch (error) {
|
|
1509
1654
|
if (error.code !== "EEXIST") throw error;
|
|
1510
1655
|
existed = true;
|
|
1511
|
-
existingStats =
|
|
1656
|
+
existingStats = fs5.lstatSync(root.directory);
|
|
1512
1657
|
}
|
|
1513
1658
|
}
|
|
1514
1659
|
if (hasSymlinkedParentBelowTrustedAnchor(root.directory, platform)) {
|
|
@@ -1518,7 +1663,7 @@ function prepareManagedDirectory(root, platform = process.platform) {
|
|
|
1518
1663
|
markerCreated: false
|
|
1519
1664
|
};
|
|
1520
1665
|
}
|
|
1521
|
-
const directoryStats = existingStats ??
|
|
1666
|
+
const directoryStats = existingStats ?? fs5.lstatSync(root.directory);
|
|
1522
1667
|
const ownership = ownershipStatus(directoryStats, platform);
|
|
1523
1668
|
const recognizedWindowsMarker = platform === "win32" && hasManagedDirectoryMarkerContents(root.directory);
|
|
1524
1669
|
if (directoryStats.isSymbolicLink() || !directoryStats.isDirectory() || ownership === "foreign" || !root.nativeDefault && ownership !== "owned" && !(created && ownership === "unverifiable") && !recognizedWindowsMarker) {
|
|
@@ -1542,7 +1687,7 @@ function prepareManagedDirectory(root, platform = process.platform) {
|
|
|
1542
1687
|
markerCreated: false
|
|
1543
1688
|
};
|
|
1544
1689
|
}
|
|
1545
|
-
const mayClaim =
|
|
1690
|
+
const mayClaim = fs5.readdirSync(root.directory).length === 0;
|
|
1546
1691
|
if (!mayClaim) {
|
|
1547
1692
|
return {
|
|
1548
1693
|
directory: root.directory,
|
|
@@ -1601,7 +1746,7 @@ function hasSymlinkedParentBelowTrustedAnchor(targetPath, platform = process.pla
|
|
|
1601
1746
|
for (const component of relativeParent.split(pathApi.sep)) {
|
|
1602
1747
|
current = pathApi.join(current, component);
|
|
1603
1748
|
try {
|
|
1604
|
-
if (
|
|
1749
|
+
if (fs5.lstatSync(current).isSymbolicLink()) return true;
|
|
1605
1750
|
} catch (error) {
|
|
1606
1751
|
if (error.code === "ENOENT") return false;
|
|
1607
1752
|
return true;
|
|
@@ -1626,7 +1771,7 @@ function unsafePurgeRoots(roots, platform = process.platform) {
|
|
|
1626
1771
|
}
|
|
1627
1772
|
let stats;
|
|
1628
1773
|
try {
|
|
1629
|
-
stats =
|
|
1774
|
+
stats = fs5.lstatSync(root.directory);
|
|
1630
1775
|
} catch (error) {
|
|
1631
1776
|
if (error.code === "ENOENT") continue;
|
|
1632
1777
|
unsafe.push({
|
|
@@ -1675,14 +1820,14 @@ function unsafePurgeRoots(roots, platform = process.platform) {
|
|
|
1675
1820
|
}
|
|
1676
1821
|
|
|
1677
1822
|
// src/commands/hook-config.ts
|
|
1678
|
-
import
|
|
1823
|
+
import fs6 from "fs";
|
|
1679
1824
|
import os2 from "os";
|
|
1680
|
-
import
|
|
1825
|
+
import path11 from "path";
|
|
1681
1826
|
|
|
1682
1827
|
// ../../packages/agent-targets/src/install/hooks/codex.ts
|
|
1683
1828
|
import { createHash } from "crypto";
|
|
1684
1829
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
1685
|
-
import
|
|
1830
|
+
import path8 from "path";
|
|
1686
1831
|
import { parse as parse2 } from "smol-toml";
|
|
1687
1832
|
|
|
1688
1833
|
// ../../packages/agent-targets/src/toml.ts
|
|
@@ -1692,7 +1837,7 @@ function asRecord2(value) {
|
|
|
1692
1837
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1693
1838
|
}
|
|
1694
1839
|
function singlePath(value) {
|
|
1695
|
-
const
|
|
1840
|
+
const path30 = [];
|
|
1696
1841
|
let current = value;
|
|
1697
1842
|
while (true) {
|
|
1698
1843
|
if (Array.isArray(current) && current.length === 1) {
|
|
@@ -1700,13 +1845,13 @@ function singlePath(value) {
|
|
|
1700
1845
|
continue;
|
|
1701
1846
|
}
|
|
1702
1847
|
const record = asRecord2(current);
|
|
1703
|
-
if (!record) return
|
|
1848
|
+
if (!record) return path30;
|
|
1704
1849
|
const keys = Object.keys(record);
|
|
1705
|
-
if (keys.length === 0) return
|
|
1850
|
+
if (keys.length === 0) return path30;
|
|
1706
1851
|
if (keys.length !== 1) throw new Error("ambiguous TOML statement path");
|
|
1707
1852
|
const key = keys[0];
|
|
1708
1853
|
if (key === void 0) throw new Error("missing TOML statement key");
|
|
1709
|
-
|
|
1854
|
+
path30.push(key);
|
|
1710
1855
|
current = record[key];
|
|
1711
1856
|
}
|
|
1712
1857
|
}
|
|
@@ -1788,8 +1933,8 @@ function scanStatements(source) {
|
|
|
1788
1933
|
}
|
|
1789
1934
|
return statements;
|
|
1790
1935
|
}
|
|
1791
|
-
function startsWithPath(
|
|
1792
|
-
return prefix.every((part, index) =>
|
|
1936
|
+
function startsWithPath(path30, prefix) {
|
|
1937
|
+
return prefix.every((part, index) => path30[index] === part);
|
|
1793
1938
|
}
|
|
1794
1939
|
function pathsEqual(left, right) {
|
|
1795
1940
|
return left.length === right.length && left.every((part, index) => part === right[index]);
|
|
@@ -1815,9 +1960,9 @@ function appendToml(source, addition) {
|
|
|
1815
1960
|
function hasOwn(record, key) {
|
|
1816
1961
|
return Object.prototype.hasOwnProperty.call(record, key);
|
|
1817
1962
|
}
|
|
1818
|
-
function updatedValueAtPath(updated,
|
|
1963
|
+
function updatedValueAtPath(updated, path30) {
|
|
1819
1964
|
let current = updated;
|
|
1820
|
-
for (const part of
|
|
1965
|
+
for (const part of path30) {
|
|
1821
1966
|
const record = asRecord2(current);
|
|
1822
1967
|
if (!record || !hasOwn(record, part)) return { exists: false };
|
|
1823
1968
|
current = record[part];
|
|
@@ -1831,22 +1976,22 @@ function normalizedPaths(updates) {
|
|
|
1831
1976
|
throw new Error("TOML update path cannot be empty");
|
|
1832
1977
|
}
|
|
1833
1978
|
if (paths.some(
|
|
1834
|
-
(
|
|
1979
|
+
(path30) => pathsEqual(path30, update.path) || startsWithPath(update.path, path30)
|
|
1835
1980
|
)) {
|
|
1836
1981
|
continue;
|
|
1837
1982
|
}
|
|
1838
1983
|
for (let index = paths.length - 1; index >= 0; index -= 1) {
|
|
1839
|
-
const
|
|
1840
|
-
if (
|
|
1984
|
+
const path30 = paths[index];
|
|
1985
|
+
if (path30 && startsWithPath(path30, update.path)) paths.splice(index, 1);
|
|
1841
1986
|
}
|
|
1842
1987
|
paths.push([...update.path]);
|
|
1843
1988
|
}
|
|
1844
1989
|
return paths;
|
|
1845
1990
|
}
|
|
1846
|
-
function valueDocument(
|
|
1991
|
+
function valueDocument(path30, value) {
|
|
1847
1992
|
let nested = value;
|
|
1848
|
-
for (let index =
|
|
1849
|
-
const part =
|
|
1993
|
+
for (let index = path30.length - 1; index >= 0; index -= 1) {
|
|
1994
|
+
const part = path30[index];
|
|
1850
1995
|
if (part === void 0) throw new Error("TOML update path is invalid");
|
|
1851
1996
|
nested = { [part]: nested };
|
|
1852
1997
|
}
|
|
@@ -1865,12 +2010,12 @@ function insertAfterStatement(source, statement, addition) {
|
|
|
1865
2010
|
const separator = before.endsWith(eol) ? "" : eol;
|
|
1866
2011
|
return `${before}${separator}${normalized}${eol}${source.slice(statement.end)}`;
|
|
1867
2012
|
}
|
|
1868
|
-
function insertUpdatedValue(source,
|
|
1869
|
-
const key =
|
|
2013
|
+
function insertUpdatedValue(source, path30, value) {
|
|
2014
|
+
const key = path30.at(-1);
|
|
1870
2015
|
if (key === void 0) throw new Error("TOML update path cannot be empty");
|
|
1871
2016
|
const assignment = localAssignment(key, value);
|
|
1872
2017
|
if (assignment !== null) {
|
|
1873
|
-
const parent =
|
|
2018
|
+
const parent = path30.slice(0, -1);
|
|
1874
2019
|
const parentTables = scanStatements(source).filter(
|
|
1875
2020
|
(statement) => statement.isTable && pathsEqual(statement.path, parent)
|
|
1876
2021
|
);
|
|
@@ -1884,17 +2029,17 @@ function insertUpdatedValue(source, path29, value) {
|
|
|
1884
2029
|
return insertAfterStatement(source, parentTable, assignment);
|
|
1885
2030
|
}
|
|
1886
2031
|
}
|
|
1887
|
-
return appendToml(source, stringify(valueDocument(
|
|
2032
|
+
return appendToml(source, stringify(valueDocument(path30, value)));
|
|
1888
2033
|
}
|
|
1889
2034
|
function updateTomlPaths(source, updated, updates) {
|
|
1890
2035
|
const paths = normalizedPaths(updates);
|
|
1891
2036
|
if (paths.length === 0) return source;
|
|
1892
2037
|
const stripped = removeStatements(source, scanStatements(source), paths);
|
|
1893
2038
|
let result = stripped;
|
|
1894
|
-
for (const
|
|
1895
|
-
const next = updatedValueAtPath(updated,
|
|
2039
|
+
for (const path30 of paths) {
|
|
2040
|
+
const next = updatedValueAtPath(updated, path30);
|
|
1896
2041
|
if (!next.exists) continue;
|
|
1897
|
-
result = insertUpdatedValue(result,
|
|
2042
|
+
result = insertUpdatedValue(result, path30, next.value);
|
|
1898
2043
|
}
|
|
1899
2044
|
let reparsed;
|
|
1900
2045
|
try {
|
|
@@ -1913,7 +2058,7 @@ function updateTomlPaths(source, updated, updates) {
|
|
|
1913
2058
|
}
|
|
1914
2059
|
|
|
1915
2060
|
// ../../packages/agent-targets/src/install/hooks/shared.ts
|
|
1916
|
-
import
|
|
2061
|
+
import path7 from "path";
|
|
1917
2062
|
function asRecord3(value) {
|
|
1918
2063
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1919
2064
|
}
|
|
@@ -1973,7 +2118,7 @@ function changedMutation(snapshot, after) {
|
|
|
1973
2118
|
return before === after ? null : { path: snapshot.path, before, after };
|
|
1974
2119
|
}
|
|
1975
2120
|
function fmlHookCommand(pluginRoot, target2) {
|
|
1976
|
-
const handlerPath =
|
|
2121
|
+
const handlerPath = path7.join(pluginRoot, "bin", "hook-handler");
|
|
1977
2122
|
const encodedPath = Buffer.from(handlerPath, "utf8").toString("base64url");
|
|
1978
2123
|
return `node -e "${FML_HOOK_LOADER}" ${encodedPath} ${target2}`;
|
|
1979
2124
|
}
|
|
@@ -2086,11 +2231,11 @@ function uniquePaths(paths) {
|
|
|
2086
2231
|
function codexPaths(context) {
|
|
2087
2232
|
const configuredHome = context.env.CODEX_HOME;
|
|
2088
2233
|
const trimmedHome = typeof configuredHome === "string" ? configuredHome.trim() : "";
|
|
2089
|
-
const dir =
|
|
2090
|
-
trimmedHome.length > 0 ? trimmedHome :
|
|
2234
|
+
const dir = path8.resolve(
|
|
2235
|
+
trimmedHome.length > 0 ? trimmedHome : path8.join(context.homeDir, ".codex")
|
|
2091
2236
|
);
|
|
2092
|
-
const configPath4 =
|
|
2093
|
-
const hooksPath =
|
|
2237
|
+
const configPath4 = path8.join(dir, "config.toml");
|
|
2238
|
+
const hooksPath = path8.join(dir, "hooks.json");
|
|
2094
2239
|
return {
|
|
2095
2240
|
configPath: configPath4,
|
|
2096
2241
|
hooksPath,
|
|
@@ -2522,7 +2667,7 @@ function codexConfigUpdatePaths(original, updated) {
|
|
|
2522
2667
|
}
|
|
2523
2668
|
}
|
|
2524
2669
|
}
|
|
2525
|
-
return paths.map((
|
|
2670
|
+
return paths.map((path30) => ({ path: path30 }));
|
|
2526
2671
|
}
|
|
2527
2672
|
function updateCodexConfigToml(source, original, updated) {
|
|
2528
2673
|
return updateTomlPaths(
|
|
@@ -2972,7 +3117,7 @@ var CODEX_HOOK_INSTALLER = Object.freeze({
|
|
|
2972
3117
|
|
|
2973
3118
|
// ../../packages/agent-targets/src/install/hooks/gemini.ts
|
|
2974
3119
|
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
2975
|
-
import
|
|
3120
|
+
import path9 from "path";
|
|
2976
3121
|
|
|
2977
3122
|
// ../../packages/agent-targets/src/mcp/jsonc.ts
|
|
2978
3123
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
@@ -3028,7 +3173,7 @@ function longestCommonArraySubsequence(original, updated) {
|
|
|
3028
3173
|
}
|
|
3029
3174
|
return matches;
|
|
3030
3175
|
}
|
|
3031
|
-
function arrayDiff(original, updated,
|
|
3176
|
+
function arrayDiff(original, updated, path30) {
|
|
3032
3177
|
const updates = [];
|
|
3033
3178
|
const matches = longestCommonArraySubsequence(original, updated);
|
|
3034
3179
|
let originalStart = 0;
|
|
@@ -3046,19 +3191,19 @@ function arrayDiff(original, updated, path29) {
|
|
|
3046
3191
|
...jsoncUpdatesForObjectDiff(
|
|
3047
3192
|
original[originalStart + offset],
|
|
3048
3193
|
updated[updatedStart + offset],
|
|
3049
|
-
[...
|
|
3194
|
+
[...path30, currentIndex + offset]
|
|
3050
3195
|
)
|
|
3051
3196
|
);
|
|
3052
3197
|
}
|
|
3053
3198
|
for (let offset = pairedCount; offset < originalCount; offset += 1) {
|
|
3054
3199
|
updates.push({
|
|
3055
|
-
path: [...
|
|
3200
|
+
path: [...path30, currentIndex + pairedCount],
|
|
3056
3201
|
value: void 0
|
|
3057
3202
|
});
|
|
3058
3203
|
}
|
|
3059
3204
|
for (let offset = pairedCount; offset < updatedCount; offset += 1) {
|
|
3060
3205
|
updates.push({
|
|
3061
|
-
path: [...
|
|
3206
|
+
path: [...path30, currentIndex + offset],
|
|
3062
3207
|
value: updated[updatedStart + offset],
|
|
3063
3208
|
isArrayInsertion: true
|
|
3064
3209
|
});
|
|
@@ -3071,21 +3216,21 @@ function arrayDiff(original, updated, path29) {
|
|
|
3071
3216
|
}
|
|
3072
3217
|
return updates;
|
|
3073
3218
|
}
|
|
3074
|
-
function jsoncUpdatesForObjectDiff(original, updated,
|
|
3219
|
+
function jsoncUpdatesForObjectDiff(original, updated, path30 = []) {
|
|
3075
3220
|
if (isDeepStrictEqual3(original, updated)) return [];
|
|
3076
3221
|
if (Array.isArray(original) && Array.isArray(updated)) {
|
|
3077
|
-
return arrayDiff(original, updated,
|
|
3222
|
+
return arrayDiff(original, updated, path30);
|
|
3078
3223
|
}
|
|
3079
3224
|
const originalObject = asObject(original);
|
|
3080
3225
|
const updatedObject = asObject(updated);
|
|
3081
|
-
if (!originalObject || !updatedObject) return [{ path:
|
|
3226
|
+
if (!originalObject || !updatedObject) return [{ path: path30, value: updated }];
|
|
3082
3227
|
const keys = /* @__PURE__ */ new Set([
|
|
3083
3228
|
...Object.keys(originalObject),
|
|
3084
3229
|
...Object.keys(updatedObject)
|
|
3085
3230
|
]);
|
|
3086
3231
|
return [...keys].flatMap(
|
|
3087
3232
|
(key) => jsoncUpdatesForObjectDiff(originalObject[key], updatedObject[key], [
|
|
3088
|
-
...
|
|
3233
|
+
...path30,
|
|
3089
3234
|
key
|
|
3090
3235
|
])
|
|
3091
3236
|
);
|
|
@@ -3133,7 +3278,7 @@ var TARGET_ID3 = TARGET3.id;
|
|
|
3133
3278
|
var DISPLAY_NAME3 = TARGET3.displayName;
|
|
3134
3279
|
var MANAGED_HOOK_NAME = "fml-capture";
|
|
3135
3280
|
function settingsPath(context) {
|
|
3136
|
-
return
|
|
3281
|
+
return path9.join(geminiConfigDirectory(context), "settings.json");
|
|
3137
3282
|
}
|
|
3138
3283
|
function readGeminiSettings(snapshot) {
|
|
3139
3284
|
const failure = snapshotError(snapshot);
|
|
@@ -3366,15 +3511,15 @@ var GEMINI_HOOK_INSTALLER = Object.freeze({
|
|
|
3366
3511
|
});
|
|
3367
3512
|
|
|
3368
3513
|
// ../../packages/agent-targets/src/install/hooks/grok.ts
|
|
3369
|
-
import
|
|
3514
|
+
import path10 from "path";
|
|
3370
3515
|
var TARGET4 = agentTarget("grok");
|
|
3371
3516
|
var TARGET_ID4 = TARGET4.id;
|
|
3372
3517
|
var DISPLAY_NAME4 = TARGET4.displayName;
|
|
3373
3518
|
var HOOK_TIMEOUT_SECONDS2 = 10;
|
|
3374
3519
|
function grokHooksPath(context) {
|
|
3375
3520
|
const configuredHome = context.env.GROK_HOME?.trim();
|
|
3376
|
-
const grokHome = configuredHome ?
|
|
3377
|
-
return
|
|
3521
|
+
const grokHome = configuredHome ? path10.resolve(configuredHome) : path10.join(context.homeDir, ".grok");
|
|
3522
|
+
return path10.join(grokHome, "hooks", "fml.json");
|
|
3378
3523
|
}
|
|
3379
3524
|
function planInstall3(context) {
|
|
3380
3525
|
const configPath4 = grokHooksPath(context);
|
|
@@ -3493,14 +3638,14 @@ var HOOK_REGISTRATION_CAPABILITIES = Object.freeze([
|
|
|
3493
3638
|
]);
|
|
3494
3639
|
|
|
3495
3640
|
// src/commands/hook-config.ts
|
|
3496
|
-
var DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH =
|
|
3641
|
+
var DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH = path11.join(
|
|
3497
3642
|
FML_DATA_DIR,
|
|
3498
3643
|
"codex-hook-install.json"
|
|
3499
3644
|
);
|
|
3500
3645
|
function readHookFile(filePath) {
|
|
3501
3646
|
let stat;
|
|
3502
3647
|
try {
|
|
3503
|
-
stat =
|
|
3648
|
+
stat = fs6.lstatSync(filePath);
|
|
3504
3649
|
} catch (error) {
|
|
3505
3650
|
if (error.code === "ENOENT") {
|
|
3506
3651
|
return { path: filePath, kind: "missing" };
|
|
@@ -3529,7 +3674,7 @@ function readHookFile(filePath) {
|
|
|
3529
3674
|
return {
|
|
3530
3675
|
path: filePath,
|
|
3531
3676
|
kind: "file",
|
|
3532
|
-
contents:
|
|
3677
|
+
contents: fs6.readFileSync(filePath, "utf8")
|
|
3533
3678
|
};
|
|
3534
3679
|
} catch (error) {
|
|
3535
3680
|
return {
|
|
@@ -3541,17 +3686,17 @@ function readHookFile(filePath) {
|
|
|
3541
3686
|
}
|
|
3542
3687
|
function canonicalizePath(filePath) {
|
|
3543
3688
|
try {
|
|
3544
|
-
return
|
|
3689
|
+
return fs6.realpathSync(filePath);
|
|
3545
3690
|
} catch {
|
|
3546
3691
|
const missingSegments = [];
|
|
3547
3692
|
let ancestor = filePath;
|
|
3548
3693
|
while (true) {
|
|
3549
|
-
const parent =
|
|
3694
|
+
const parent = path11.dirname(ancestor);
|
|
3550
3695
|
if (parent === ancestor) return filePath;
|
|
3551
|
-
missingSegments.unshift(
|
|
3696
|
+
missingSegments.unshift(path11.basename(ancestor));
|
|
3552
3697
|
ancestor = parent;
|
|
3553
3698
|
try {
|
|
3554
|
-
return
|
|
3699
|
+
return path11.join(fs6.realpathSync(ancestor), ...missingSegments);
|
|
3555
3700
|
} catch {
|
|
3556
3701
|
}
|
|
3557
3702
|
}
|
|
@@ -3570,7 +3715,7 @@ function assertMutationPrecondition(mutation) {
|
|
|
3570
3715
|
}
|
|
3571
3716
|
function applyMutation(mutation) {
|
|
3572
3717
|
if (mutation.after === null) {
|
|
3573
|
-
|
|
3718
|
+
fs6.rmSync(mutation.path);
|
|
3574
3719
|
} else {
|
|
3575
3720
|
writeTextFileAtomic(mutation.path, mutation.after);
|
|
3576
3721
|
}
|
|
@@ -3583,7 +3728,7 @@ function rollbackMutation(mutation) {
|
|
|
3583
3728
|
};
|
|
3584
3729
|
assertMutationPrecondition(inverse);
|
|
3585
3730
|
if (inverse.after === null) {
|
|
3586
|
-
|
|
3731
|
+
fs6.rmSync(inverse.path);
|
|
3587
3732
|
} else {
|
|
3588
3733
|
writeTextFileAtomic(inverse.path, inverse.after);
|
|
3589
3734
|
}
|
|
@@ -3651,7 +3796,7 @@ function applyPlan(plan, warn, onFailure) {
|
|
|
3651
3796
|
};
|
|
3652
3797
|
}
|
|
3653
3798
|
function plannerContext(packageRoot, options) {
|
|
3654
|
-
const ownershipStatePath = options.ownershipStatePath ?? (options.homeDir ?
|
|
3799
|
+
const ownershipStatePath = options.ownershipStatePath ?? (options.homeDir ? path11.join(options.homeDir, ".fml", "codex-hook-install.json") : DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH);
|
|
3655
3800
|
return {
|
|
3656
3801
|
packageRoot,
|
|
3657
3802
|
homeDir: options.homeDir ?? os2.homedir(),
|
|
@@ -3682,10 +3827,10 @@ function removeFmlHooks(options = {}) {
|
|
|
3682
3827
|
}
|
|
3683
3828
|
|
|
3684
3829
|
// src/commands/marketplace-link.ts
|
|
3685
|
-
import
|
|
3830
|
+
import fs7 from "fs";
|
|
3686
3831
|
function existingPathKind(linkPath) {
|
|
3687
3832
|
try {
|
|
3688
|
-
return
|
|
3833
|
+
return fs7.lstatSync(linkPath).isSymbolicLink() ? "symlink" : "other";
|
|
3689
3834
|
} catch (error) {
|
|
3690
3835
|
if (error.code === "ENOENT") return "missing";
|
|
3691
3836
|
throw error;
|
|
@@ -3694,15 +3839,15 @@ function existingPathKind(linkPath) {
|
|
|
3694
3839
|
function replaceMarketplaceLink(linkPath, targetPath, type) {
|
|
3695
3840
|
const existing = existingPathKind(linkPath);
|
|
3696
3841
|
if (existing === "other") return "preserved";
|
|
3697
|
-
if (existing === "symlink")
|
|
3698
|
-
|
|
3842
|
+
if (existing === "symlink") fs7.unlinkSync(linkPath);
|
|
3843
|
+
fs7.symlinkSync(targetPath, linkPath, type);
|
|
3699
3844
|
return existing === "symlink" ? "replaced" : "created";
|
|
3700
3845
|
}
|
|
3701
3846
|
function removeMarketplaceLink(linkPath) {
|
|
3702
3847
|
const existing = existingPathKind(linkPath);
|
|
3703
3848
|
if (existing === "missing") return "missing";
|
|
3704
3849
|
if (existing === "other") return "preserved";
|
|
3705
|
-
|
|
3850
|
+
fs7.unlinkSync(linkPath);
|
|
3706
3851
|
return "removed";
|
|
3707
3852
|
}
|
|
3708
3853
|
|
|
@@ -3797,10 +3942,10 @@ function configRecord(value) {
|
|
|
3797
3942
|
}
|
|
3798
3943
|
|
|
3799
3944
|
// ../../packages/agent-targets/src/mcp/targets/claude-desktop.ts
|
|
3800
|
-
import
|
|
3945
|
+
import path13 from "path";
|
|
3801
3946
|
|
|
3802
3947
|
// ../../packages/agent-targets/src/mcp/capability.ts
|
|
3803
|
-
import
|
|
3948
|
+
import path12 from "path";
|
|
3804
3949
|
import { parse as parse4 } from "smol-toml";
|
|
3805
3950
|
|
|
3806
3951
|
// ../../packages/agent-targets/src/mcp/toml.ts
|
|
@@ -3906,7 +4051,7 @@ function changedConfigPlan(target2, current, before, data) {
|
|
|
3906
4051
|
function generatedServer(target2, context) {
|
|
3907
4052
|
return fmlMcpServerConfig(
|
|
3908
4053
|
target2.command,
|
|
3909
|
-
|
|
4054
|
+
path12.join(context.packageRoot, "bin", "mcp-server")
|
|
3910
4055
|
);
|
|
3911
4056
|
}
|
|
3912
4057
|
function planInstall4(target2, context) {
|
|
@@ -3986,7 +4131,7 @@ var CLAUDE_DESKTOP_DIRECT_MCP = createDirectMcpCapability({
|
|
|
3986
4131
|
configKey: "mcpServers",
|
|
3987
4132
|
configPath: ({ env, homeDir, platform }) => {
|
|
3988
4133
|
if (platform === "darwin") {
|
|
3989
|
-
return
|
|
4134
|
+
return path13.join(
|
|
3990
4135
|
homeDir,
|
|
3991
4136
|
"Library",
|
|
3992
4137
|
"Application Support",
|
|
@@ -3995,14 +4140,14 @@ var CLAUDE_DESKTOP_DIRECT_MCP = createDirectMcpCapability({
|
|
|
3995
4140
|
);
|
|
3996
4141
|
}
|
|
3997
4142
|
if (platform === "win32") {
|
|
3998
|
-
return
|
|
3999
|
-
env.APPDATA ??
|
|
4143
|
+
return path13.join(
|
|
4144
|
+
env.APPDATA ?? path13.join(homeDir, "AppData", "Roaming"),
|
|
4000
4145
|
"Claude",
|
|
4001
4146
|
"claude_desktop_config.json"
|
|
4002
4147
|
);
|
|
4003
4148
|
}
|
|
4004
|
-
return
|
|
4005
|
-
env.XDG_CONFIG_HOME ??
|
|
4149
|
+
return path13.join(
|
|
4150
|
+
env.XDG_CONFIG_HOME ?? path13.join(homeDir, ".config"),
|
|
4006
4151
|
"Claude",
|
|
4007
4152
|
"claude_desktop_config.json"
|
|
4008
4153
|
);
|
|
@@ -4011,7 +4156,7 @@ var CLAUDE_DESKTOP_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4011
4156
|
});
|
|
4012
4157
|
|
|
4013
4158
|
// ../../packages/agent-targets/src/mcp/targets/codex.ts
|
|
4014
|
-
import
|
|
4159
|
+
import path14 from "path";
|
|
4015
4160
|
var TARGET6 = agentTarget("codex");
|
|
4016
4161
|
var CODEX_DIRECT_MCP = createDirectMcpCapability({
|
|
4017
4162
|
targetId: TARGET6.id,
|
|
@@ -4020,26 +4165,26 @@ var CODEX_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4020
4165
|
configKey: "mcp_servers",
|
|
4021
4166
|
configPath: ({ env, homeDir }) => {
|
|
4022
4167
|
const configuredHome = env.CODEX_HOME;
|
|
4023
|
-
const codexHome = typeof configuredHome === "string" && configuredHome.length > 0 ?
|
|
4024
|
-
return
|
|
4168
|
+
const codexHome = typeof configuredHome === "string" && configuredHome.length > 0 ? path14.resolve(configuredHome) : path14.join(homeDir, ".codex");
|
|
4169
|
+
return path14.join(codexHome, "config.toml");
|
|
4025
4170
|
},
|
|
4026
4171
|
command: () => "node"
|
|
4027
4172
|
});
|
|
4028
4173
|
|
|
4029
4174
|
// ../../packages/agent-targets/src/mcp/targets/gemini.ts
|
|
4030
|
-
import
|
|
4175
|
+
import path15 from "path";
|
|
4031
4176
|
var TARGET7 = agentTarget("gemini");
|
|
4032
4177
|
var GEMINI_DIRECT_MCP = createDirectMcpCapability({
|
|
4033
4178
|
targetId: TARGET7.id,
|
|
4034
4179
|
displayName: TARGET7.displayName,
|
|
4035
4180
|
configFormat: "json",
|
|
4036
4181
|
configKey: "mcpServers",
|
|
4037
|
-
configPath: (context) =>
|
|
4182
|
+
configPath: (context) => path15.join(geminiConfigDirectory(context), "settings.json"),
|
|
4038
4183
|
command: () => "node"
|
|
4039
4184
|
});
|
|
4040
4185
|
|
|
4041
4186
|
// ../../packages/agent-targets/src/mcp/targets/grok.ts
|
|
4042
|
-
import
|
|
4187
|
+
import path16 from "path";
|
|
4043
4188
|
var TARGET8 = agentTarget("grok");
|
|
4044
4189
|
var GROK_DIRECT_MCP = createDirectMcpCapability({
|
|
4045
4190
|
targetId: TARGET8.id,
|
|
@@ -4048,8 +4193,8 @@ var GROK_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4048
4193
|
configKey: "mcp_servers",
|
|
4049
4194
|
configPath: ({ env, homeDir }) => {
|
|
4050
4195
|
const configuredHome = env.GROK_HOME;
|
|
4051
|
-
const grokHome = typeof configuredHome === "string" && configuredHome.length > 0 ?
|
|
4052
|
-
return
|
|
4196
|
+
const grokHome = typeof configuredHome === "string" && configuredHome.length > 0 ? path16.resolve(configuredHome) : path16.join(homeDir, ".grok");
|
|
4197
|
+
return path16.join(grokHome, "config.toml");
|
|
4053
4198
|
},
|
|
4054
4199
|
command: () => "node"
|
|
4055
4200
|
});
|
|
@@ -4063,7 +4208,7 @@ var DIRECT_MCP_CAPABILITIES = Object.freeze([
|
|
|
4063
4208
|
]);
|
|
4064
4209
|
|
|
4065
4210
|
// src/commands/mcp-config.ts
|
|
4066
|
-
import
|
|
4211
|
+
import fs8 from "fs";
|
|
4067
4212
|
import os3 from "os";
|
|
4068
4213
|
function resolutionContext(options) {
|
|
4069
4214
|
return {
|
|
@@ -4076,7 +4221,7 @@ function resolutionContext(options) {
|
|
|
4076
4221
|
function readMcpFile(filePath) {
|
|
4077
4222
|
let stat;
|
|
4078
4223
|
try {
|
|
4079
|
-
stat =
|
|
4224
|
+
stat = fs8.lstatSync(filePath);
|
|
4080
4225
|
} catch (error) {
|
|
4081
4226
|
if (error.code === "ENOENT") {
|
|
4082
4227
|
return { path: filePath, kind: "missing" };
|
|
@@ -4105,7 +4250,7 @@ function readMcpFile(filePath) {
|
|
|
4105
4250
|
return {
|
|
4106
4251
|
path: filePath,
|
|
4107
4252
|
kind: "file",
|
|
4108
|
-
contents:
|
|
4253
|
+
contents: fs8.readFileSync(filePath, "utf8")
|
|
4109
4254
|
};
|
|
4110
4255
|
} catch (error) {
|
|
4111
4256
|
return {
|
|
@@ -4141,14 +4286,14 @@ function preflightMutation(mutation) {
|
|
|
4141
4286
|
}
|
|
4142
4287
|
function writeMutation(mutation) {
|
|
4143
4288
|
if (mutation.after === null) {
|
|
4144
|
-
|
|
4289
|
+
fs8.rmSync(mutation.path, { force: true });
|
|
4145
4290
|
return;
|
|
4146
4291
|
}
|
|
4147
4292
|
writeTextFileAtomic(mutation.path, mutation.after);
|
|
4148
4293
|
}
|
|
4149
4294
|
function rollbackMutation2(mutation) {
|
|
4150
4295
|
if (mutation.before === null) {
|
|
4151
|
-
|
|
4296
|
+
fs8.rmSync(mutation.path, { force: true });
|
|
4152
4297
|
return;
|
|
4153
4298
|
}
|
|
4154
4299
|
writeTextFileAtomic(mutation.path, mutation.before);
|
|
@@ -4238,13 +4383,13 @@ function removeFmlDirectMcp(target2 = "all", options = {}) {
|
|
|
4238
4383
|
}
|
|
4239
4384
|
|
|
4240
4385
|
// src/commands/agent-skills.ts
|
|
4241
|
-
import { createHash as createHash2, randomUUID as
|
|
4242
|
-
import
|
|
4386
|
+
import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
|
|
4387
|
+
import fs9 from "fs";
|
|
4243
4388
|
import os4 from "os";
|
|
4244
|
-
import
|
|
4389
|
+
import path21 from "path";
|
|
4245
4390
|
|
|
4246
4391
|
// ../../packages/agent-targets/src/install/surfaces/capability.ts
|
|
4247
|
-
import
|
|
4392
|
+
import path17 from "path";
|
|
4248
4393
|
var SOURCE_PATH_SEGMENTS = ["agent-assets", "fml", "SKILL.md"];
|
|
4249
4394
|
var DESTINATION_PATH_SEGMENTS = ["skills", "fml", "SKILL.md"];
|
|
4250
4395
|
function createAgentSkillCapability(definition) {
|
|
@@ -4257,8 +4402,8 @@ function createAgentSkillCapability(definition) {
|
|
|
4257
4402
|
resolve: (context) => Object.freeze({
|
|
4258
4403
|
targetId: definition.targetId,
|
|
4259
4404
|
displayName: definition.displayName,
|
|
4260
|
-
sourcePath:
|
|
4261
|
-
destinationPath:
|
|
4405
|
+
sourcePath: path17.join(context.packageRoot, ...SOURCE_PATH_SEGMENTS),
|
|
4406
|
+
destinationPath: path17.join(
|
|
4262
4407
|
definition.destinationRoot(context),
|
|
4263
4408
|
...DESTINATION_PATH_SEGMENTS
|
|
4264
4409
|
),
|
|
@@ -4281,7 +4426,7 @@ var CLAUDE_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4281
4426
|
});
|
|
4282
4427
|
|
|
4283
4428
|
// ../../packages/agent-targets/src/install/surfaces/targets/codex.ts
|
|
4284
|
-
import
|
|
4429
|
+
import path18 from "path";
|
|
4285
4430
|
var TARGET10 = agentTarget("codex");
|
|
4286
4431
|
var CODEX_AGENT_SKILL = createAgentSkillCapability({
|
|
4287
4432
|
targetId: TARGET10.id,
|
|
@@ -4289,11 +4434,11 @@ var CODEX_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4289
4434
|
invocation: "$fml",
|
|
4290
4435
|
deliveryMode: "instruction-read",
|
|
4291
4436
|
argumentMode: "user-input",
|
|
4292
|
-
destinationRoot: ({ homeDir }) =>
|
|
4437
|
+
destinationRoot: ({ homeDir }) => path18.join(homeDir, ".agents")
|
|
4293
4438
|
});
|
|
4294
4439
|
|
|
4295
4440
|
// ../../packages/agent-targets/src/install/surfaces/targets/gemini.ts
|
|
4296
|
-
import
|
|
4441
|
+
import path19 from "path";
|
|
4297
4442
|
var TARGET11 = agentTarget("gemini");
|
|
4298
4443
|
var GEMINI_AGENT_SKILL = createAgentSkillCapability({
|
|
4299
4444
|
targetId: TARGET11.id,
|
|
@@ -4303,13 +4448,13 @@ var GEMINI_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4303
4448
|
argumentMode: "post-submit-prompt",
|
|
4304
4449
|
destinationRoot: ({ env, homeDir }) => {
|
|
4305
4450
|
const configuredHome = env.GEMINI_CLI_HOME?.trim();
|
|
4306
|
-
const homeRoot = configuredHome ?
|
|
4307
|
-
return
|
|
4451
|
+
const homeRoot = configuredHome ? path19.resolve(configuredHome) : homeDir;
|
|
4452
|
+
return path19.join(homeRoot, ".agents");
|
|
4308
4453
|
}
|
|
4309
4454
|
});
|
|
4310
4455
|
|
|
4311
4456
|
// ../../packages/agent-targets/src/install/surfaces/targets/grok.ts
|
|
4312
|
-
import
|
|
4457
|
+
import path20 from "path";
|
|
4313
4458
|
var TARGET12 = agentTarget("grok");
|
|
4314
4459
|
var GROK_AGENT_SKILL = createAgentSkillCapability({
|
|
4315
4460
|
targetId: TARGET12.id,
|
|
@@ -4317,7 +4462,7 @@ var GROK_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4317
4462
|
invocation: "/fml",
|
|
4318
4463
|
deliveryMode: "prompt-expansion",
|
|
4319
4464
|
argumentMode: "template-or-append",
|
|
4320
|
-
destinationRoot: ({ homeDir }) =>
|
|
4465
|
+
destinationRoot: ({ homeDir }) => path20.join(homeDir, ".agents")
|
|
4321
4466
|
});
|
|
4322
4467
|
|
|
4323
4468
|
// ../../packages/agent-targets/src/install/surfaces/registry.ts
|
|
@@ -4331,7 +4476,7 @@ var AGENT_SKILL_CAPABILITIES = Object.freeze([
|
|
|
4331
4476
|
// src/commands/agent-skills.ts
|
|
4332
4477
|
var FML_AGENT_SKILL_MARKER = "<!-- fml-managed-agent-surface:v1 -->";
|
|
4333
4478
|
var AGENT_SKILL_STATE_SCHEMA_VERSION = 1;
|
|
4334
|
-
var DEFAULT_STATE_PATH =
|
|
4479
|
+
var DEFAULT_STATE_PATH = path21.join(FML_DATA_DIR, "agent-skills.json");
|
|
4335
4480
|
function emptyState() {
|
|
4336
4481
|
return Object.freeze({
|
|
4337
4482
|
schemaVersion: AGENT_SKILL_STATE_SCHEMA_VERSION,
|
|
@@ -4344,7 +4489,7 @@ function sha256(contents) {
|
|
|
4344
4489
|
function readSkillFile(filePath) {
|
|
4345
4490
|
let stat;
|
|
4346
4491
|
try {
|
|
4347
|
-
stat =
|
|
4492
|
+
stat = fs9.lstatSync(filePath);
|
|
4348
4493
|
} catch (error) {
|
|
4349
4494
|
if (error.code === "ENOENT") {
|
|
4350
4495
|
return { kind: "missing" };
|
|
@@ -4367,7 +4512,7 @@ function readSkillFile(filePath) {
|
|
|
4367
4512
|
};
|
|
4368
4513
|
}
|
|
4369
4514
|
try {
|
|
4370
|
-
const contents =
|
|
4515
|
+
const contents = fs9.readFileSync(filePath, "utf8");
|
|
4371
4516
|
return { kind: "file", contents, sha256: sha256(contents) };
|
|
4372
4517
|
} catch (error) {
|
|
4373
4518
|
return {
|
|
@@ -4436,7 +4581,7 @@ function parseState(source, statePath) {
|
|
|
4436
4581
|
}
|
|
4437
4582
|
entries.push(
|
|
4438
4583
|
Object.freeze({
|
|
4439
|
-
path:
|
|
4584
|
+
path: path21.resolve(entry.path),
|
|
4440
4585
|
sha256: entry.sha256,
|
|
4441
4586
|
targetIds: Object.freeze([...entry.targetIds])
|
|
4442
4587
|
})
|
|
@@ -4462,7 +4607,7 @@ function loadState(statePath) {
|
|
|
4462
4607
|
}
|
|
4463
4608
|
function serializeState(entries) {
|
|
4464
4609
|
const sorted = [...entries].map((entry) => ({
|
|
4465
|
-
path:
|
|
4610
|
+
path: path21.resolve(entry.path),
|
|
4466
4611
|
sha256: entry.sha256,
|
|
4467
4612
|
targetIds: [...entry.targetIds].sort()
|
|
4468
4613
|
})).sort((left, right) => left.path.localeCompare(right.path));
|
|
@@ -4501,7 +4646,7 @@ function resolvedGroups(pluginRoot, options) {
|
|
|
4501
4646
|
const groups = /* @__PURE__ */ new Map();
|
|
4502
4647
|
for (const capability of AGENT_SKILL_CAPABILITIES) {
|
|
4503
4648
|
const resolved = capability.resolve(context);
|
|
4504
|
-
const destinationPath =
|
|
4649
|
+
const destinationPath = path21.resolve(resolved.destinationPath);
|
|
4505
4650
|
const key = process.platform === "win32" ? destinationPath.toLowerCase() : destinationPath;
|
|
4506
4651
|
const current = groups.get(key) ?? [];
|
|
4507
4652
|
current.push({ ...resolved, destinationPath });
|
|
@@ -4538,10 +4683,10 @@ function resultFor(group, status, reason) {
|
|
|
4538
4683
|
});
|
|
4539
4684
|
}
|
|
4540
4685
|
function destinationDirectoryIssue(destinationPath, requireEmpty) {
|
|
4541
|
-
const skillDir =
|
|
4686
|
+
const skillDir = path21.dirname(destinationPath);
|
|
4542
4687
|
let stat;
|
|
4543
4688
|
try {
|
|
4544
|
-
stat =
|
|
4689
|
+
stat = fs9.lstatSync(skillDir);
|
|
4545
4690
|
} catch (error) {
|
|
4546
4691
|
if (error.code === "ENOENT") return null;
|
|
4547
4692
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4549,7 +4694,7 @@ function destinationDirectoryIssue(destinationPath, requireEmpty) {
|
|
|
4549
4694
|
if (stat.isSymbolicLink()) return "skill directory is a symbolic link";
|
|
4550
4695
|
if (!stat.isDirectory()) return "skill directory is not a directory";
|
|
4551
4696
|
try {
|
|
4552
|
-
if (!requireEmpty ||
|
|
4697
|
+
if (!requireEmpty || fs9.readdirSync(skillDir).length === 0) return null;
|
|
4553
4698
|
return "skill directory contains unmanaged files";
|
|
4554
4699
|
} catch (error) {
|
|
4555
4700
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4566,9 +4711,9 @@ function rollbackSkillWrite(destinationPath, before) {
|
|
|
4566
4711
|
writeTextFileAtomic(destinationPath, before.contents);
|
|
4567
4712
|
return;
|
|
4568
4713
|
}
|
|
4569
|
-
|
|
4714
|
+
fs9.rmSync(destinationPath, { force: true });
|
|
4570
4715
|
try {
|
|
4571
|
-
|
|
4716
|
+
fs9.rmdirSync(path21.dirname(destinationPath));
|
|
4572
4717
|
} catch {
|
|
4573
4718
|
}
|
|
4574
4719
|
}
|
|
@@ -4611,12 +4756,12 @@ function installManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4611
4756
|
const loaded = loadState(statePath);
|
|
4612
4757
|
let stateSource = loaded.source;
|
|
4613
4758
|
const entries = new Map(
|
|
4614
|
-
loaded.state.entries.map((entry) => [
|
|
4759
|
+
loaded.state.entries.map((entry) => [path21.resolve(entry.path), entry])
|
|
4615
4760
|
);
|
|
4616
4761
|
const results = [];
|
|
4617
4762
|
for (const group of resolvedGroups(pluginRoot, options)) {
|
|
4618
4763
|
const source = sourceSkill(group.sourcePath);
|
|
4619
|
-
const destinationPath =
|
|
4764
|
+
const destinationPath = path21.resolve(group.destinationPath);
|
|
4620
4765
|
const current = readSkillFile(destinationPath);
|
|
4621
4766
|
const previous = entries.get(destinationPath);
|
|
4622
4767
|
const nextEntry = stateEntryFor(
|
|
@@ -4701,11 +4846,11 @@ function removeSkillFile(args) {
|
|
|
4701
4846
|
`Agent skill changed before ${args.destinationPath} could be removed.`
|
|
4702
4847
|
);
|
|
4703
4848
|
}
|
|
4704
|
-
const backupPath =
|
|
4705
|
-
|
|
4706
|
-
`.${
|
|
4849
|
+
const backupPath = path21.join(
|
|
4850
|
+
path21.dirname(args.destinationPath),
|
|
4851
|
+
`.${path21.basename(args.destinationPath)}.${process.pid}.${randomUUID3()}.bak`
|
|
4707
4852
|
);
|
|
4708
|
-
|
|
4853
|
+
fs9.renameSync(args.destinationPath, backupPath);
|
|
4709
4854
|
let stateSource;
|
|
4710
4855
|
try {
|
|
4711
4856
|
stateSource = writeState(
|
|
@@ -4715,7 +4860,7 @@ function removeSkillFile(args) {
|
|
|
4715
4860
|
);
|
|
4716
4861
|
} catch (error) {
|
|
4717
4862
|
try {
|
|
4718
|
-
|
|
4863
|
+
fs9.renameSync(backupPath, args.destinationPath);
|
|
4719
4864
|
} catch (rollbackError) {
|
|
4720
4865
|
const message = error instanceof Error ? error.message : String(error);
|
|
4721
4866
|
const rollbackMessage = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
|
|
@@ -4727,12 +4872,12 @@ function removeSkillFile(args) {
|
|
|
4727
4872
|
}
|
|
4728
4873
|
let warning;
|
|
4729
4874
|
try {
|
|
4730
|
-
|
|
4875
|
+
fs9.rmSync(backupPath, { force: true });
|
|
4731
4876
|
} catch (error) {
|
|
4732
4877
|
warning = `agent skill removal was committed, but backup cleanup failed at ${backupPath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
4733
4878
|
}
|
|
4734
4879
|
try {
|
|
4735
|
-
|
|
4880
|
+
fs9.rmdirSync(path21.dirname(args.destinationPath));
|
|
4736
4881
|
} catch {
|
|
4737
4882
|
}
|
|
4738
4883
|
return { stateSource, ...warning ? { warning } : {} };
|
|
@@ -4742,16 +4887,16 @@ function removeManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4742
4887
|
const loaded = loadState(statePath);
|
|
4743
4888
|
let stateSource = loaded.source;
|
|
4744
4889
|
const entries = new Map(
|
|
4745
|
-
loaded.state.entries.map((entry) => [
|
|
4890
|
+
loaded.state.entries.map((entry) => [path21.resolve(entry.path), entry])
|
|
4746
4891
|
);
|
|
4747
4892
|
const candidates = /* @__PURE__ */ new Map();
|
|
4748
4893
|
const currentGroups = resolvedGroups(pluginRoot, options);
|
|
4749
|
-
const packagedSourcePath = currentGroups[0]?.sourcePath ??
|
|
4894
|
+
const packagedSourcePath = currentGroups[0]?.sourcePath ?? path21.join(pluginRoot, "agent-assets", "fml", "SKILL.md");
|
|
4750
4895
|
for (const group of currentGroups) {
|
|
4751
|
-
candidates.set(
|
|
4896
|
+
candidates.set(path21.resolve(group.destinationPath), group);
|
|
4752
4897
|
}
|
|
4753
4898
|
for (const entry of entries.values()) {
|
|
4754
|
-
const destinationPath =
|
|
4899
|
+
const destinationPath = path21.resolve(entry.path);
|
|
4755
4900
|
if (candidates.has(destinationPath)) continue;
|
|
4756
4901
|
const targets = entry.targetIds.filter(isAgentSkillTargetId).map(targetForId);
|
|
4757
4902
|
if (targets.length === 0) continue;
|
|
@@ -4766,7 +4911,7 @@ function removeManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4766
4911
|
for (const group of [...candidates.values()].sort(
|
|
4767
4912
|
(left, right) => left.destinationPath.localeCompare(right.destinationPath)
|
|
4768
4913
|
)) {
|
|
4769
|
-
const destinationPath =
|
|
4914
|
+
const destinationPath = path21.resolve(group.destinationPath);
|
|
4770
4915
|
const current = readSkillFile(destinationPath);
|
|
4771
4916
|
const previous = entries.get(destinationPath);
|
|
4772
4917
|
if (current.kind === "missing") {
|
|
@@ -4824,13 +4969,13 @@ function removeManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4824
4969
|
}
|
|
4825
4970
|
|
|
4826
4971
|
// src/commands/install.ts
|
|
4827
|
-
function resolvePluginRoot(startDir =
|
|
4972
|
+
function resolvePluginRoot(startDir = path22.dirname(fileURLToPath(import.meta.url))) {
|
|
4828
4973
|
let directory = startDir;
|
|
4829
4974
|
while (true) {
|
|
4830
|
-
if (
|
|
4975
|
+
if (fs10.existsSync(path22.join(directory, "package.json")) && fs10.existsSync(path22.join(directory, "bin"))) {
|
|
4831
4976
|
return directory;
|
|
4832
4977
|
}
|
|
4833
|
-
const parent =
|
|
4978
|
+
const parent = path22.dirname(directory);
|
|
4834
4979
|
if (parent === directory) {
|
|
4835
4980
|
throw new Error(
|
|
4836
4981
|
`Could not locate the FML package root: no ancestor of ${startDir} contains both package.json and bin/. Reinstall @fml-inc/fml and retry.`
|
|
@@ -4845,7 +4990,7 @@ function getPluginRoot() {
|
|
|
4845
4990
|
function readJsonFileForUpdate(filePath) {
|
|
4846
4991
|
let source;
|
|
4847
4992
|
try {
|
|
4848
|
-
source =
|
|
4993
|
+
source = fs10.readFileSync(filePath, "utf8");
|
|
4849
4994
|
} catch (error) {
|
|
4850
4995
|
if (error.code === "ENOENT") {
|
|
4851
4996
|
return { ok: true, exists: false, data: {} };
|
|
@@ -4909,9 +5054,9 @@ async function handleInstall(opts = {}) {
|
|
|
4909
5054
|
FML_LOG_DIR,
|
|
4910
5055
|
FML_OBSERVER_DIR
|
|
4911
5056
|
])) {
|
|
4912
|
-
|
|
5057
|
+
fs10.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
4913
5058
|
}
|
|
4914
|
-
initializeSyncSettings(
|
|
5059
|
+
initializeSyncSettings(path22.join(FML_OBSERVER_DIR, "sync.json"));
|
|
4915
5060
|
let skillReady = false;
|
|
4916
5061
|
try {
|
|
4917
5062
|
const skillResults = installManagedAgentSkills(pluginRoot);
|
|
@@ -4930,7 +5075,35 @@ async function handleInstall(opts = {}) {
|
|
|
4930
5075
|
`Warning: agent-native skill setup could not be completed: ${message}`
|
|
4931
5076
|
);
|
|
4932
5077
|
}
|
|
4933
|
-
|
|
5078
|
+
let piExtensionReady = false;
|
|
5079
|
+
try {
|
|
5080
|
+
const piPaths = PI_EXTENSION_INSTALLER.resolvePaths({
|
|
5081
|
+
env: process.env,
|
|
5082
|
+
homeDir: os5.homedir(),
|
|
5083
|
+
packageRoot: pluginRoot,
|
|
5084
|
+
platform: process.platform
|
|
5085
|
+
});
|
|
5086
|
+
const piResult = PI_EXTENSION_INSTALLER.install(piPaths);
|
|
5087
|
+
piExtensionReady = piResult.status !== "preserved";
|
|
5088
|
+
if (piResult.status === "preserved") {
|
|
5089
|
+
console.log(
|
|
5090
|
+
` warn: preserved ${piResult.destinationPath} for Pi: ${piResult.reason}`
|
|
5091
|
+
);
|
|
5092
|
+
}
|
|
5093
|
+
if (piResult.legacyRemoved) {
|
|
5094
|
+
console.log(" Removed the legacy Panopticon Pi extension");
|
|
5095
|
+
} else if (piResult.legacyPreserved) {
|
|
5096
|
+
console.log(
|
|
5097
|
+
` warn: preserved unrecognized Pi extension ${piPaths.legacyDestinationPath}; inspect and remove it if it belongs to Panopticon`
|
|
5098
|
+
);
|
|
5099
|
+
}
|
|
5100
|
+
} catch (error) {
|
|
5101
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5102
|
+
console.log(
|
|
5103
|
+
` warn: Pi extension setup could not be completed: ${message}`
|
|
5104
|
+
);
|
|
5105
|
+
}
|
|
5106
|
+
const packageJson = readJsonFile(path22.join(pluginRoot, "package.json"));
|
|
4934
5107
|
const generatedManifest = readJsonFile(paths.pluginManifestPath);
|
|
4935
5108
|
const version = typeof generatedManifest?.version === "string" ? generatedManifest.version : typeof packageJson?.version === "string" ? packageJson.version : "0.0.0-dev";
|
|
4936
5109
|
writeJsonFile(
|
|
@@ -4947,7 +5120,7 @@ async function handleInstall(opts = {}) {
|
|
|
4947
5120
|
`Warning: preserved unreadable marketplace config ${paths.marketplaceManifestPath}: ${marketplaceResult.error}`
|
|
4948
5121
|
);
|
|
4949
5122
|
} else {
|
|
4950
|
-
|
|
5123
|
+
fs10.mkdirSync(paths.marketplaceDir, { recursive: true, mode: 448 });
|
|
4951
5124
|
const linkUpdate = replaceMarketplaceLink(
|
|
4952
5125
|
paths.marketplaceLinkPath,
|
|
4953
5126
|
pluginRoot,
|
|
@@ -5027,9 +5200,9 @@ async function handleInstall(opts = {}) {
|
|
|
5027
5200
|
}
|
|
5028
5201
|
});
|
|
5029
5202
|
}
|
|
5030
|
-
if (!skillReady || !marketplaceReady || !settingsReady || !hooksReady) {
|
|
5203
|
+
if (!skillReady || !piExtensionReady || !marketplaceReady || !settingsReady || !hooksReady) {
|
|
5031
5204
|
throw new Error(
|
|
5032
|
-
"FML install is incomplete: repair the preserved agent skill, hook configuration, Claude plugin path, or configuration reported above, then run `fml install` again."
|
|
5205
|
+
"FML install is incomplete: repair the preserved agent skill, Pi extension, hook configuration, Claude plugin path, or configuration reported above, then run `fml install` again."
|
|
5033
5206
|
);
|
|
5034
5207
|
}
|
|
5035
5208
|
try {
|
|
@@ -5056,12 +5229,12 @@ async function handleInstall(opts = {}) {
|
|
|
5056
5229
|
import { statSync } from "fs";
|
|
5057
5230
|
|
|
5058
5231
|
// src/commands/otel-config.ts
|
|
5059
|
-
import
|
|
5232
|
+
import fs12 from "fs";
|
|
5060
5233
|
import os6 from "os";
|
|
5061
|
-
import
|
|
5234
|
+
import path27 from "path";
|
|
5062
5235
|
|
|
5063
5236
|
// ../../packages/agent-targets/src/install/otel/claude.ts
|
|
5064
|
-
import
|
|
5237
|
+
import path23 from "path";
|
|
5065
5238
|
|
|
5066
5239
|
// ../../packages/agent-targets/src/install/otel/shared.ts
|
|
5067
5240
|
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
@@ -5198,9 +5371,9 @@ var MANAGED_MARKER = "FML_OTEL_MANAGED";
|
|
|
5198
5371
|
var CLAUDE_OTEL_SOURCE_LIMITATION = "Claude Code may truncate inline raw API bodies and tool content at 60 KiB and redact extended-thinking content before export";
|
|
5199
5372
|
function configPath(context) {
|
|
5200
5373
|
if (context.configPathOverride) {
|
|
5201
|
-
return
|
|
5374
|
+
return path23.resolve(context.configPathOverride);
|
|
5202
5375
|
}
|
|
5203
|
-
return
|
|
5376
|
+
return path23.join(
|
|
5204
5377
|
claudeConfigDirectory({ env: context.env, homeDir: context.homeDir }),
|
|
5205
5378
|
"settings.json"
|
|
5206
5379
|
);
|
|
@@ -5371,7 +5544,7 @@ var CLAUDE_OTEL_INSTALLER = Object.freeze({
|
|
|
5371
5544
|
|
|
5372
5545
|
// ../../packages/agent-targets/src/install/otel/codex.ts
|
|
5373
5546
|
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
5374
|
-
import
|
|
5547
|
+
import path24 from "path";
|
|
5375
5548
|
import { parse as parse5 } from "smol-toml";
|
|
5376
5549
|
var TARGET14 = agentTarget("codex");
|
|
5377
5550
|
var TARGET_ID6 = TARGET14.id;
|
|
@@ -5380,13 +5553,13 @@ var AUTHENTICATION2 = "bearer-header";
|
|
|
5380
5553
|
var CODEX_OTEL_SOURCE_LIMITATION = "Codex OTel has no documented raw API body or full tool-content export switch; tool-result content is an output snippet";
|
|
5381
5554
|
function configPath2(context) {
|
|
5382
5555
|
if (context.configPathOverride) {
|
|
5383
|
-
return
|
|
5556
|
+
return path24.resolve(context.configPathOverride);
|
|
5384
5557
|
}
|
|
5385
5558
|
const configuredHome = context.env.CODEX_HOME;
|
|
5386
|
-
const codexHome =
|
|
5387
|
-
typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome :
|
|
5559
|
+
const codexHome = path24.resolve(
|
|
5560
|
+
typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome : path24.join(context.homeDir, ".codex")
|
|
5388
5561
|
);
|
|
5389
|
-
return
|
|
5562
|
+
return path24.join(codexHome, "config.toml");
|
|
5390
5563
|
}
|
|
5391
5564
|
function readToml(snapshot) {
|
|
5392
5565
|
const failure = snapshotError2(snapshot);
|
|
@@ -5606,7 +5779,7 @@ var CODEX_OTEL_INSTALLER = Object.freeze({
|
|
|
5606
5779
|
});
|
|
5607
5780
|
|
|
5608
5781
|
// ../../packages/agent-targets/src/install/otel/gemini.ts
|
|
5609
|
-
import
|
|
5782
|
+
import path25 from "path";
|
|
5610
5783
|
var TARGET15 = agentTarget("gemini");
|
|
5611
5784
|
var TARGET_ID7 = TARGET15.id;
|
|
5612
5785
|
var DISPLAY_NAME7 = TARGET15.displayName;
|
|
@@ -5614,9 +5787,9 @@ var AUTHENTICATION3 = "path-token";
|
|
|
5614
5787
|
var GEMINI_OTEL_SOURCE_LIMITATION = "Gemini CLI has no documented OTLP header setting; FML uses an observer-local tokenized loopback path";
|
|
5615
5788
|
function configPath3(context) {
|
|
5616
5789
|
if (context.configPathOverride) {
|
|
5617
|
-
return
|
|
5790
|
+
return path25.resolve(context.configPathOverride);
|
|
5618
5791
|
}
|
|
5619
|
-
return
|
|
5792
|
+
return path25.join(geminiConfigDirectory(context), "settings.json");
|
|
5620
5793
|
}
|
|
5621
5794
|
function managedTelemetry(context) {
|
|
5622
5795
|
const destination = resolveDestination(context.observer);
|
|
@@ -5770,8 +5943,8 @@ var OTEL_INSTALLER_CAPABILITIES = Object.freeze([
|
|
|
5770
5943
|
]);
|
|
5771
5944
|
|
|
5772
5945
|
// src/commands/otel-config-state.ts
|
|
5773
|
-
import
|
|
5774
|
-
import
|
|
5946
|
+
import fs11 from "fs";
|
|
5947
|
+
import path26 from "path";
|
|
5775
5948
|
var OTEL_CONFIG_STATE_SCHEMA_VERSION = 1;
|
|
5776
5949
|
function emptyState2() {
|
|
5777
5950
|
return Object.freeze({
|
|
@@ -5785,12 +5958,12 @@ function invalidState2(statePath, reason) {
|
|
|
5785
5958
|
);
|
|
5786
5959
|
}
|
|
5787
5960
|
function enforceOwnerOnlyMode(statePath) {
|
|
5788
|
-
if (process.platform !== "win32")
|
|
5961
|
+
if (process.platform !== "win32") fs11.chmodSync(statePath, 384);
|
|
5789
5962
|
}
|
|
5790
5963
|
function readStateFile(statePath) {
|
|
5791
5964
|
let stat;
|
|
5792
5965
|
try {
|
|
5793
|
-
stat =
|
|
5966
|
+
stat = fs11.lstatSync(statePath);
|
|
5794
5967
|
} catch (error) {
|
|
5795
5968
|
if (error.code === "ENOENT") {
|
|
5796
5969
|
return { kind: "missing" };
|
|
@@ -5808,7 +5981,7 @@ function readStateFile(statePath) {
|
|
|
5808
5981
|
}
|
|
5809
5982
|
try {
|
|
5810
5983
|
enforceOwnerOnlyMode(statePath);
|
|
5811
|
-
return { kind: "file", contents:
|
|
5984
|
+
return { kind: "file", contents: fs11.readFileSync(statePath, "utf8") };
|
|
5812
5985
|
} catch (error) {
|
|
5813
5986
|
return {
|
|
5814
5987
|
kind: "invalid",
|
|
@@ -5817,7 +5990,7 @@ function readStateFile(statePath) {
|
|
|
5817
5990
|
}
|
|
5818
5991
|
}
|
|
5819
5992
|
function otelConfigStateEntryKey(targetId, configPath4) {
|
|
5820
|
-
const resolved =
|
|
5993
|
+
const resolved = path26.resolve(configPath4);
|
|
5821
5994
|
const pathKey = process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
5822
5995
|
return `${targetId}\0${pathKey}`;
|
|
5823
5996
|
}
|
|
@@ -5853,7 +6026,7 @@ function parseState2(source, statePath) {
|
|
|
5853
6026
|
if (typeof observerRecord.baseUrl !== "string" || observerRecord.baseUrl.length === 0 || typeof observerRecord.authToken !== "string" || observerRecord.authToken.length === 0) {
|
|
5854
6027
|
throw invalidState2(statePath, "contains an invalid observer destination");
|
|
5855
6028
|
}
|
|
5856
|
-
const resolvedPath =
|
|
6029
|
+
const resolvedPath = path26.resolve(entry.path);
|
|
5857
6030
|
const key = otelConfigStateEntryKey(entry.targetId, resolvedPath);
|
|
5858
6031
|
if (keys.has(key)) {
|
|
5859
6032
|
throw invalidState2(statePath, "contains duplicate entries");
|
|
@@ -5891,7 +6064,7 @@ function loadFmlOtelConfigState(statePath) {
|
|
|
5891
6064
|
function serializeState2(entries) {
|
|
5892
6065
|
const sorted = [...entries].map((entry) => ({
|
|
5893
6066
|
targetId: entry.targetId,
|
|
5894
|
-
path:
|
|
6067
|
+
path: path26.resolve(entry.path),
|
|
5895
6068
|
observer: {
|
|
5896
6069
|
baseUrl: entry.observer.baseUrl,
|
|
5897
6070
|
authToken: entry.observer.authToken
|
|
@@ -5928,7 +6101,7 @@ function isKnownOtelTargetId(targetId) {
|
|
|
5928
6101
|
}
|
|
5929
6102
|
|
|
5930
6103
|
// src/commands/otel-config.ts
|
|
5931
|
-
var DEFAULT_OTEL_CONFIG_STATE_PATH =
|
|
6104
|
+
var DEFAULT_OTEL_CONFIG_STATE_PATH = path27.join(
|
|
5932
6105
|
FML_DATA_DIR,
|
|
5933
6106
|
"otel-config.json"
|
|
5934
6107
|
);
|
|
@@ -5937,7 +6110,7 @@ function readLocalObserverOtelDestination(options) {
|
|
|
5937
6110
|
if (!authToken) return null;
|
|
5938
6111
|
try {
|
|
5939
6112
|
const parsed = JSON.parse(
|
|
5940
|
-
|
|
6113
|
+
fs12.readFileSync(options.endpointFile, "utf8")
|
|
5941
6114
|
);
|
|
5942
6115
|
const endpoint = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
5943
6116
|
const host = endpoint?.host;
|
|
@@ -5954,7 +6127,7 @@ function readLocalObserverOtelDestination(options) {
|
|
|
5954
6127
|
function readOtelFile(filePath) {
|
|
5955
6128
|
let stat;
|
|
5956
6129
|
try {
|
|
5957
|
-
stat =
|
|
6130
|
+
stat = fs12.lstatSync(filePath);
|
|
5958
6131
|
} catch (error) {
|
|
5959
6132
|
if (error.code === "ENOENT") {
|
|
5960
6133
|
return { path: filePath, kind: "missing" };
|
|
@@ -5983,7 +6156,7 @@ function readOtelFile(filePath) {
|
|
|
5983
6156
|
return {
|
|
5984
6157
|
path: filePath,
|
|
5985
6158
|
kind: "file",
|
|
5986
|
-
contents:
|
|
6159
|
+
contents: fs12.readFileSync(filePath, "utf8")
|
|
5987
6160
|
};
|
|
5988
6161
|
} catch (error) {
|
|
5989
6162
|
return {
|
|
@@ -6005,7 +6178,7 @@ function assertMutationPrecondition2(mutation) {
|
|
|
6005
6178
|
throw new Error(`configuration changed while planning ${mutation.path}`);
|
|
6006
6179
|
}
|
|
6007
6180
|
function applyMutation2(mutation) {
|
|
6008
|
-
if (mutation.after === null)
|
|
6181
|
+
if (mutation.after === null) fs12.rmSync(mutation.path);
|
|
6009
6182
|
else writeTextFileAtomic(mutation.path, mutation.after);
|
|
6010
6183
|
}
|
|
6011
6184
|
function enforceOwnerOnlyConfigPermissions(filePath) {
|
|
@@ -6018,7 +6191,7 @@ function enforceOwnerOnlyConfigPermissions(filePath) {
|
|
|
6018
6191
|
);
|
|
6019
6192
|
}
|
|
6020
6193
|
try {
|
|
6021
|
-
|
|
6194
|
+
fs12.chmodSync(filePath, 384);
|
|
6022
6195
|
} catch (error) {
|
|
6023
6196
|
const detail = error instanceof Error ? error.message : String(error);
|
|
6024
6197
|
throw new Error(
|
|
@@ -6113,7 +6286,7 @@ function plannerContext3(observer, options, configPathOverride, configOwnershipR
|
|
|
6113
6286
|
observer,
|
|
6114
6287
|
homeDir: options.homeDir ?? os6.homedir(),
|
|
6115
6288
|
env: options.env ?? process.env,
|
|
6116
|
-
...configPathOverride ? { configPathOverride:
|
|
6289
|
+
...configPathOverride ? { configPathOverride: path27.resolve(configPathOverride) } : {},
|
|
6117
6290
|
...configOwnershipRecorded ? { configOwnershipRecorded: true } : {},
|
|
6118
6291
|
readFile: readOtelFile
|
|
6119
6292
|
};
|
|
@@ -6156,7 +6329,7 @@ function commitStateEntry(state, key, next) {
|
|
|
6156
6329
|
function stateEntry(plan, observer) {
|
|
6157
6330
|
return Object.freeze({
|
|
6158
6331
|
targetId: plan.targetId,
|
|
6159
|
-
path:
|
|
6332
|
+
path: path27.resolve(plan.configPath),
|
|
6160
6333
|
observer: Object.freeze({
|
|
6161
6334
|
baseUrl: observer.baseUrl,
|
|
6162
6335
|
authToken: observer.authToken
|
|
@@ -6714,8 +6887,8 @@ async function canOpenBrowser() {
|
|
|
6714
6887
|
if (process.env.CODESPACES) return false;
|
|
6715
6888
|
if (process.env.REMOTE_CONTAINERS) return false;
|
|
6716
6889
|
try {
|
|
6717
|
-
const
|
|
6718
|
-
if (
|
|
6890
|
+
const fs14 = await import("fs");
|
|
6891
|
+
if (fs14.existsSync("/.dockerenv")) return false;
|
|
6719
6892
|
} catch {
|
|
6720
6893
|
}
|
|
6721
6894
|
return true;
|
|
@@ -7274,9 +7447,9 @@ async function handleSetup(dependencies = defaultDependencies) {
|
|
|
7274
7447
|
}
|
|
7275
7448
|
|
|
7276
7449
|
// src/commands/uninstall.ts
|
|
7277
|
-
import
|
|
7450
|
+
import fs13 from "fs";
|
|
7278
7451
|
import os7 from "os";
|
|
7279
|
-
import
|
|
7452
|
+
import path28 from "path";
|
|
7280
7453
|
import readline from "readline/promises";
|
|
7281
7454
|
var PURGE_WARNING = "This deletes FML credentials for ALL environments, logs, sync state, and every pending best-effort OTLP envelope.";
|
|
7282
7455
|
function tryDisableHookCapture() {
|
|
@@ -7292,19 +7465,19 @@ function tryDisableHookCapture() {
|
|
|
7292
7465
|
}
|
|
7293
7466
|
}
|
|
7294
7467
|
function resolvePreservedPaths(preservedFile) {
|
|
7295
|
-
const logicalPath =
|
|
7468
|
+
const logicalPath = path28.resolve(preservedFile);
|
|
7296
7469
|
try {
|
|
7297
|
-
const canonicalPath =
|
|
7470
|
+
const canonicalPath = fs13.realpathSync(preservedFile);
|
|
7298
7471
|
return pathsAreSame(canonicalPath, logicalPath) ? [logicalPath] : [logicalPath, canonicalPath];
|
|
7299
7472
|
} catch {
|
|
7300
7473
|
return [logicalPath];
|
|
7301
7474
|
}
|
|
7302
7475
|
}
|
|
7303
7476
|
function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot = false) {
|
|
7304
|
-
const resolvedDirectory =
|
|
7477
|
+
const resolvedDirectory = path28.resolve(directory);
|
|
7305
7478
|
let directoryStats;
|
|
7306
7479
|
try {
|
|
7307
|
-
directoryStats =
|
|
7480
|
+
directoryStats = fs13.lstatSync(directory);
|
|
7308
7481
|
} catch (error) {
|
|
7309
7482
|
if (error.code === "ENOENT") return true;
|
|
7310
7483
|
throw error;
|
|
@@ -7315,14 +7488,14 @@ function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot
|
|
|
7315
7488
|
(preservedPath) => pathContains(resolvedDirectory, preservedPath)
|
|
7316
7489
|
);
|
|
7317
7490
|
if (!containsLogicalMarker) {
|
|
7318
|
-
|
|
7491
|
+
fs13.rmSync(directory, { force: true });
|
|
7319
7492
|
return true;
|
|
7320
7493
|
}
|
|
7321
7494
|
return false;
|
|
7322
7495
|
}
|
|
7323
7496
|
const directoryPaths = [resolvedDirectory];
|
|
7324
7497
|
try {
|
|
7325
|
-
const canonicalDirectory =
|
|
7498
|
+
const canonicalDirectory = fs13.realpathSync(directory);
|
|
7326
7499
|
if (!pathsAreSame(canonicalDirectory, resolvedDirectory)) {
|
|
7327
7500
|
directoryPaths.push(canonicalDirectory);
|
|
7328
7501
|
}
|
|
@@ -7334,26 +7507,26 @@ function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot
|
|
|
7334
7507
|
)
|
|
7335
7508
|
);
|
|
7336
7509
|
if (!containsPreservedPath) {
|
|
7337
|
-
|
|
7510
|
+
fs13.rmSync(directory, { recursive: true, force: true });
|
|
7338
7511
|
return true;
|
|
7339
7512
|
}
|
|
7340
7513
|
const isPreservedPath = directoryPaths.some(
|
|
7341
7514
|
(directoryPath) => preservedPaths.some(
|
|
7342
|
-
(preservedPath) => pathsAreSame(directoryPath,
|
|
7515
|
+
(preservedPath) => pathsAreSame(directoryPath, path28.resolve(preservedPath))
|
|
7343
7516
|
)
|
|
7344
7517
|
);
|
|
7345
7518
|
if (isPreservedPath) return true;
|
|
7346
7519
|
if (!directoryStats.isDirectory()) return false;
|
|
7347
7520
|
let entries;
|
|
7348
7521
|
try {
|
|
7349
|
-
entries =
|
|
7522
|
+
entries = fs13.readdirSync(directory);
|
|
7350
7523
|
} catch (error) {
|
|
7351
7524
|
if (error.code === "ENOENT") return true;
|
|
7352
7525
|
throw error;
|
|
7353
7526
|
}
|
|
7354
7527
|
let complete = true;
|
|
7355
7528
|
for (const entry of entries) {
|
|
7356
|
-
const entryPath =
|
|
7529
|
+
const entryPath = path28.join(directory, entry);
|
|
7357
7530
|
if (!purgeDirectoryPreservingPaths(entryPath, preservedPaths, false)) {
|
|
7358
7531
|
complete = false;
|
|
7359
7532
|
}
|
|
@@ -7372,13 +7545,13 @@ function purgeDirectoryPreservingFiles(directory, preservedFiles) {
|
|
|
7372
7545
|
}
|
|
7373
7546
|
function finishCustomRootPurge(directory) {
|
|
7374
7547
|
const marker = managedDirectoryMarker(directory);
|
|
7375
|
-
|
|
7548
|
+
fs13.rmSync(marker, { force: true });
|
|
7376
7549
|
try {
|
|
7377
|
-
|
|
7550
|
+
fs13.rmdirSync(directory);
|
|
7378
7551
|
} catch (error) {
|
|
7379
7552
|
if (error.code === "ENOENT") return;
|
|
7380
7553
|
try {
|
|
7381
|
-
|
|
7554
|
+
fs13.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
|
|
7382
7555
|
encoding: "utf8",
|
|
7383
7556
|
flag: "wx",
|
|
7384
7557
|
mode: 384
|
|
@@ -7476,7 +7649,7 @@ async function handleUninstall(opts) {
|
|
|
7476
7649
|
return;
|
|
7477
7650
|
}
|
|
7478
7651
|
for (const root of purgeRoots) {
|
|
7479
|
-
if (!
|
|
7652
|
+
if (!fs13.existsSync(root.directory) && pathContains(root.directory, FML_OBSERVER_DIR)) {
|
|
7480
7653
|
prepareManagedDirectory(root);
|
|
7481
7654
|
}
|
|
7482
7655
|
}
|
|
@@ -7552,6 +7725,38 @@ async function handleUninstall(opts) {
|
|
|
7552
7725
|
);
|
|
7553
7726
|
}
|
|
7554
7727
|
let integrationsRemoved = true;
|
|
7728
|
+
try {
|
|
7729
|
+
const piPaths = PI_EXTENSION_INSTALLER.resolvePaths({
|
|
7730
|
+
env: process.env,
|
|
7731
|
+
homeDir: os7.homedir(),
|
|
7732
|
+
packageRoot: resolvePackageRoot(),
|
|
7733
|
+
platform: process.platform
|
|
7734
|
+
});
|
|
7735
|
+
const piResult = PI_EXTENSION_INSTALLER.uninstall(piPaths);
|
|
7736
|
+
if (piResult.status === "preserved") {
|
|
7737
|
+
integrationsRemoved = false;
|
|
7738
|
+
process.exitCode = 1;
|
|
7739
|
+
console.warn(
|
|
7740
|
+
`Warning: Preserved ${piResult.destinationPath} for Pi: ${piResult.reason}`
|
|
7741
|
+
);
|
|
7742
|
+
}
|
|
7743
|
+
if (piResult.legacyRemoved) {
|
|
7744
|
+
console.log("Removed the legacy Panopticon Pi extension");
|
|
7745
|
+
} else if (piResult.legacyPreserved) {
|
|
7746
|
+
integrationsRemoved = false;
|
|
7747
|
+
process.exitCode = 1;
|
|
7748
|
+
console.warn(
|
|
7749
|
+
`Warning: Preserved unrecognized Pi extension ${piPaths.legacyDestinationPath}; inspect and remove it if it belongs to Panopticon`
|
|
7750
|
+
);
|
|
7751
|
+
}
|
|
7752
|
+
} catch (error) {
|
|
7753
|
+
integrationsRemoved = false;
|
|
7754
|
+
process.exitCode = 1;
|
|
7755
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7756
|
+
console.warn(
|
|
7757
|
+
`Warning: Pi extension cleanup could not be completed: ${message}`
|
|
7758
|
+
);
|
|
7759
|
+
}
|
|
7555
7760
|
if (removeMarketplaceLink(paths.marketplaceLinkPath) === "preserved") {
|
|
7556
7761
|
integrationsRemoved = false;
|
|
7557
7762
|
console.warn(
|
|
@@ -7568,7 +7773,7 @@ async function handleUninstall(opts) {
|
|
|
7568
7773
|
)
|
|
7569
7774
|
);
|
|
7570
7775
|
}
|
|
7571
|
-
|
|
7776
|
+
fs13.rmSync(paths.pluginCacheDir, { recursive: true, force: true });
|
|
7572
7777
|
const reportIntegrationWarning = (message) => {
|
|
7573
7778
|
integrationsRemoved = false;
|
|
7574
7779
|
console.warn(message.replace(/^warn:/u, "Warning:"));
|
|
@@ -7690,7 +7895,7 @@ async function handleUninstall(opts) {
|
|
|
7690
7895
|
// src/commands/update.ts
|
|
7691
7896
|
var SEMVER_PATTERN = /^(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
7692
7897
|
function getCurrentVersion() {
|
|
7693
|
-
return true ? "0.8.0
|
|
7898
|
+
return true ? "0.8.0+246af775" : "unknown";
|
|
7694
7899
|
}
|
|
7695
7900
|
function resolveUpdateChannel(version) {
|
|
7696
7901
|
const match = SEMVER_PATTERN.exec(version);
|
|
@@ -8723,8 +8928,8 @@ async function handleConfigDetail(opts) {
|
|
|
8723
8928
|
|
|
8724
8929
|
// src/commands/tools.ts
|
|
8725
8930
|
import { readFileSync } from "fs";
|
|
8726
|
-
import
|
|
8727
|
-
var pluginVersion = true ? "0.8.0
|
|
8931
|
+
import path29 from "path";
|
|
8932
|
+
var pluginVersion = true ? "0.8.0+246af775" : void 0;
|
|
8728
8933
|
async function getApi() {
|
|
8729
8934
|
const api = await getAuthenticatedClient();
|
|
8730
8935
|
if (!api) {
|
|
@@ -8831,7 +9036,7 @@ async function handleToolsCall(name, opts) {
|
|
|
8831
9036
|
}
|
|
8832
9037
|
const raw = opts.file ? (() => {
|
|
8833
9038
|
try {
|
|
8834
|
-
return readFileSync(
|
|
9039
|
+
return readFileSync(path29.resolve(opts.file), "utf8");
|
|
8835
9040
|
} catch (err) {
|
|
8836
9041
|
const msg = err instanceof Error ? err.message : String(err);
|
|
8837
9042
|
console.error(`Could not read args file: ${msg}`);
|
|
@@ -8881,7 +9086,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
8881
9086
|
printBanner();
|
|
8882
9087
|
}
|
|
8883
9088
|
var program = new Command().name("fml").description("FML CLI and agent tools").version(
|
|
8884
|
-
true ? "0.8.0
|
|
9089
|
+
true ? "0.8.0+246af775" : "dev"
|
|
8885
9090
|
);
|
|
8886
9091
|
function formatCommandInventory(cmd, prefix = "") {
|
|
8887
9092
|
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
|