@fml-inc/fml 0.8.3 → 0.8.4-rc.2
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 +19 -0
- package/dist/{chunk-F4A2POJX.js → chunk-732O7ISN.js} +1 -1
- package/dist/{chunk-UZG65JUB.js → chunk-IIGTUGO5.js} +1 -1
- package/dist/{chunk-IZH4MDS4.js → chunk-LWOINL4K.js} +1 -1
- package/dist/{chunk-3WDAKM5B.js → chunk-NP7HI4UC.js} +276 -4
- package/dist/{chunk-26RJC76L.js → chunk-P4HOUZXC.js} +2 -2
- package/dist/{chunk-UGUYQVUW.js → chunk-T3ZFT3QP.js} +5 -3
- package/dist/{chunk-TNJVAET3.js → chunk-ZBSC57CW.js} +2 -0
- package/dist/{chunk-E6YIJCIE.js → chunk-ZGA57JPY.js} +11 -1
- package/dist/cli.js +231 -432
- package/dist/hook-handler.js +4 -4
- package/dist/mcp/server.js +6 -3
- package/dist/observer-server.js +239 -14
- package/dist/pi/extension.js +1 -0
- package/dist/sync-cycle.js +3 -3
- package/dist/{token-store-7OI3CMM4.js → token-store-QYXUL4NG.js} +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,21 +2,24 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFmlClient,
|
|
4
4
|
getAuthenticatedClient
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-P4HOUZXC.js";
|
|
6
6
|
import {
|
|
7
7
|
OBSERVER_HEARTBEAT_STALE_MS,
|
|
8
|
+
execBinSync,
|
|
8
9
|
getProcessIdentity,
|
|
10
|
+
handleUpdate,
|
|
9
11
|
inspectObserverLease,
|
|
10
12
|
isPidAlive,
|
|
11
13
|
readObserverStateStatus,
|
|
12
|
-
removeObserverStateIfOwned
|
|
13
|
-
|
|
14
|
+
removeObserverStateIfOwned,
|
|
15
|
+
resolveBin
|
|
16
|
+
} from "./chunk-NP7HI4UC.js";
|
|
14
17
|
import {
|
|
15
18
|
readJsonFile,
|
|
16
19
|
setHookCaptureDisabled,
|
|
17
20
|
writeJsonFile,
|
|
18
21
|
writeTextFileAtomic
|
|
19
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-IIGTUGO5.js";
|
|
20
23
|
import {
|
|
21
24
|
CODEX_HOOK_EVENTS,
|
|
22
25
|
GEMINI_HOOK_EVENTS,
|
|
@@ -24,7 +27,7 @@ import {
|
|
|
24
27
|
isObserverHealth,
|
|
25
28
|
readHookInboxStatus,
|
|
26
29
|
readObserverAuthToken
|
|
27
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-732O7ISN.js";
|
|
28
31
|
import "./chunk-7V7G7NVF.js";
|
|
29
32
|
import {
|
|
30
33
|
claudeConfigDirectory,
|
|
@@ -34,7 +37,7 @@ import {
|
|
|
34
37
|
initializeSyncSettings,
|
|
35
38
|
resolvePackageRoot,
|
|
36
39
|
runRawSyncOnce
|
|
37
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-T3ZFT3QP.js";
|
|
38
41
|
import {
|
|
39
42
|
DEFAULT_PROD_URL,
|
|
40
43
|
DEFAULT_TARGET_NAME,
|
|
@@ -76,11 +79,11 @@ import {
|
|
|
76
79
|
storeServiceRefreshToken,
|
|
77
80
|
writeEnvConfig,
|
|
78
81
|
writeTokens
|
|
79
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-ZBSC57CW.js";
|
|
80
83
|
import "./chunk-MLKGABMK.js";
|
|
81
84
|
|
|
82
85
|
// src/cli.ts
|
|
83
|
-
import { Command } from "commander";
|
|
86
|
+
import { Command, Option } from "commander";
|
|
84
87
|
|
|
85
88
|
// src/commands/doctor.ts
|
|
86
89
|
import { randomUUID } from "crypto";
|
|
@@ -124,7 +127,7 @@ var POLL_INTERVAL_MS = 50;
|
|
|
124
127
|
var LOG_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
125
128
|
var LOG_ROTATE_FILES = 3;
|
|
126
129
|
function expectedObserverVersion() {
|
|
127
|
-
return true ? "0.8.
|
|
130
|
+
return true ? "0.8.4-rc.2+f282df41" : "dev";
|
|
128
131
|
}
|
|
129
132
|
function delay(ms) {
|
|
130
133
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -1062,9 +1065,9 @@ async function handleDoctor(opts) {
|
|
|
1062
1065
|
}
|
|
1063
1066
|
|
|
1064
1067
|
// src/commands/install.ts
|
|
1065
|
-
import
|
|
1068
|
+
import fs9 from "fs";
|
|
1066
1069
|
import os5 from "os";
|
|
1067
|
-
import
|
|
1070
|
+
import path21 from "path";
|
|
1068
1071
|
import { fileURLToPath } from "url";
|
|
1069
1072
|
|
|
1070
1073
|
// ../../packages/agent-targets/src/install/claude/index.ts
|
|
@@ -1450,64 +1453,19 @@ var PI_EXTENSION_INSTALLER = Object.freeze({
|
|
|
1450
1453
|
}
|
|
1451
1454
|
});
|
|
1452
1455
|
|
|
1453
|
-
// src/bin-utils.ts
|
|
1454
|
-
import fs4 from "fs";
|
|
1455
|
-
import path5 from "path";
|
|
1456
|
-
import { execFileSync, execSync } from "child_process";
|
|
1457
|
-
var IS_WIN = process.platform === "win32";
|
|
1458
|
-
var DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
|
|
1459
|
-
function resolveBin(name) {
|
|
1460
|
-
const pathDirs = (process.env.PATH ?? "").split(path5.delimiter).filter(Boolean);
|
|
1461
|
-
const hasExt = path5.extname(name) !== "";
|
|
1462
|
-
const exts = !IS_WIN || hasExt ? [""] : (process.env.PATHEXT ?? DEFAULT_PATHEXT).split(";").filter(Boolean);
|
|
1463
|
-
for (const dir of pathDirs) {
|
|
1464
|
-
for (const ext of exts) {
|
|
1465
|
-
const candidate = path5.join(dir, name + ext);
|
|
1466
|
-
try {
|
|
1467
|
-
if (fs4.statSync(candidate).isFile()) return candidate;
|
|
1468
|
-
} catch {
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
return null;
|
|
1473
|
-
}
|
|
1474
|
-
function isWinShim(bin) {
|
|
1475
|
-
return IS_WIN && /\.(cmd|bat)$/i.test(bin);
|
|
1476
|
-
}
|
|
1477
|
-
function quoteWinArg(arg) {
|
|
1478
|
-
if (arg.length === 0) return '""';
|
|
1479
|
-
if (/^[A-Za-z0-9@\-_+=:/.,]+$/.test(arg)) return arg;
|
|
1480
|
-
const crt = arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/, "$1$1");
|
|
1481
|
-
const quoted = `"${crt}"`;
|
|
1482
|
-
return quoted.replace(/([()%!^<>&|"])/g, "^$1");
|
|
1483
|
-
}
|
|
1484
|
-
function execBinSync(bin, args, opts = {}) {
|
|
1485
|
-
const {
|
|
1486
|
-
timeout = 1e4,
|
|
1487
|
-
encoding = "utf-8",
|
|
1488
|
-
stdio = "pipe",
|
|
1489
|
-
env = process.env
|
|
1490
|
-
} = opts;
|
|
1491
|
-
if (isWinShim(bin)) {
|
|
1492
|
-
const command = [bin, ...args].map(quoteWinArg).join(" ");
|
|
1493
|
-
return execSync(command, { timeout, encoding, stdio, env });
|
|
1494
|
-
}
|
|
1495
|
-
return execFileSync(bin, args, { timeout, encoding, stdio, env });
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
1456
|
// src/managed-directories.ts
|
|
1499
|
-
import
|
|
1457
|
+
import fs4 from "fs";
|
|
1500
1458
|
import os from "os";
|
|
1501
|
-
import
|
|
1459
|
+
import path5 from "path";
|
|
1502
1460
|
var FML_MANAGED_DIRECTORY_MARKER = ".fml-managed-root";
|
|
1503
1461
|
var FML_MANAGED_DIRECTORY_MARKER_CONTENT = "fml-managed-directory-v1\n";
|
|
1504
1462
|
function comparisonPathApi(platform, targetPaths) {
|
|
1505
1463
|
if (platform === "win32" && targetPaths.some(
|
|
1506
1464
|
(targetPath) => /^[A-Za-z]:[\\/]/u.test(targetPath) || targetPath.startsWith("\\\\") || targetPath.startsWith("//")
|
|
1507
1465
|
)) {
|
|
1508
|
-
return
|
|
1466
|
+
return path5.win32;
|
|
1509
1467
|
}
|
|
1510
|
-
return
|
|
1468
|
+
return path5;
|
|
1511
1469
|
}
|
|
1512
1470
|
function resolveComparisonPath(targetPath, platform) {
|
|
1513
1471
|
return comparisonPathApi(platform, [targetPath]).resolve(targetPath);
|
|
@@ -1580,7 +1538,7 @@ function configuredManagedRoots(platform = process.platform) {
|
|
|
1580
1538
|
);
|
|
1581
1539
|
}
|
|
1582
1540
|
function managedDirectoryMarker(directory) {
|
|
1583
|
-
return
|
|
1541
|
+
return path5.join(directory, FML_MANAGED_DIRECTORY_MARKER);
|
|
1584
1542
|
}
|
|
1585
1543
|
function ownershipStatus(stats, platform) {
|
|
1586
1544
|
if (platform === "win32") return "unverifiable";
|
|
@@ -1591,8 +1549,8 @@ function ownershipStatus(stats, platform) {
|
|
|
1591
1549
|
function hasManagedDirectoryMarkerContents(directory) {
|
|
1592
1550
|
const marker = managedDirectoryMarker(directory);
|
|
1593
1551
|
try {
|
|
1594
|
-
const stats =
|
|
1595
|
-
return stats.isFile() &&
|
|
1552
|
+
const stats = fs4.lstatSync(marker);
|
|
1553
|
+
return stats.isFile() && fs4.readFileSync(marker, "utf8") === FML_MANAGED_DIRECTORY_MARKER_CONTENT;
|
|
1596
1554
|
} catch {
|
|
1597
1555
|
return false;
|
|
1598
1556
|
}
|
|
@@ -1600,11 +1558,11 @@ function hasManagedDirectoryMarkerContents(directory) {
|
|
|
1600
1558
|
function hasManagedDirectoryMarker(directory, platform = process.platform) {
|
|
1601
1559
|
const marker = managedDirectoryMarker(directory);
|
|
1602
1560
|
try {
|
|
1603
|
-
const stats =
|
|
1561
|
+
const stats = fs4.lstatSync(marker);
|
|
1604
1562
|
if (!stats.isFile() || ownershipStatus(stats, platform) !== "owned") {
|
|
1605
1563
|
return false;
|
|
1606
1564
|
}
|
|
1607
|
-
return
|
|
1565
|
+
return fs4.readFileSync(marker, "utf8") === FML_MANAGED_DIRECTORY_MARKER_CONTENT;
|
|
1608
1566
|
} catch {
|
|
1609
1567
|
return false;
|
|
1610
1568
|
}
|
|
@@ -1612,7 +1570,7 @@ function hasManagedDirectoryMarker(directory, platform = process.platform) {
|
|
|
1612
1570
|
function writeManagedDirectoryMarker(directory, platform) {
|
|
1613
1571
|
const marker = managedDirectoryMarker(directory);
|
|
1614
1572
|
try {
|
|
1615
|
-
|
|
1573
|
+
fs4.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
|
|
1616
1574
|
encoding: "utf8",
|
|
1617
1575
|
flag: "wx",
|
|
1618
1576
|
mode: 384
|
|
@@ -1637,23 +1595,23 @@ function prepareManagedDirectory(root, platform = process.platform) {
|
|
|
1637
1595
|
let created = false;
|
|
1638
1596
|
let existingStats = null;
|
|
1639
1597
|
try {
|
|
1640
|
-
existingStats =
|
|
1598
|
+
existingStats = fs4.lstatSync(root.directory);
|
|
1641
1599
|
} catch (error) {
|
|
1642
1600
|
if (error.code !== "ENOENT") throw error;
|
|
1643
1601
|
existed = false;
|
|
1644
1602
|
}
|
|
1645
1603
|
if (!existed) {
|
|
1646
|
-
|
|
1604
|
+
fs4.mkdirSync(path5.dirname(root.directory), {
|
|
1647
1605
|
recursive: true,
|
|
1648
1606
|
mode: 448
|
|
1649
1607
|
});
|
|
1650
1608
|
try {
|
|
1651
|
-
|
|
1609
|
+
fs4.mkdirSync(root.directory, { mode: 448 });
|
|
1652
1610
|
created = true;
|
|
1653
1611
|
} catch (error) {
|
|
1654
1612
|
if (error.code !== "EEXIST") throw error;
|
|
1655
1613
|
existed = true;
|
|
1656
|
-
existingStats =
|
|
1614
|
+
existingStats = fs4.lstatSync(root.directory);
|
|
1657
1615
|
}
|
|
1658
1616
|
}
|
|
1659
1617
|
if (hasSymlinkedParentBelowTrustedAnchor(root.directory, platform)) {
|
|
@@ -1663,7 +1621,7 @@ function prepareManagedDirectory(root, platform = process.platform) {
|
|
|
1663
1621
|
markerCreated: false
|
|
1664
1622
|
};
|
|
1665
1623
|
}
|
|
1666
|
-
const directoryStats = existingStats ??
|
|
1624
|
+
const directoryStats = existingStats ?? fs4.lstatSync(root.directory);
|
|
1667
1625
|
const ownership = ownershipStatus(directoryStats, platform);
|
|
1668
1626
|
const recognizedWindowsMarker = platform === "win32" && hasManagedDirectoryMarkerContents(root.directory);
|
|
1669
1627
|
if (directoryStats.isSymbolicLink() || !directoryStats.isDirectory() || ownership === "foreign" || !root.nativeDefault && ownership !== "owned" && !(created && ownership === "unverifiable") && !recognizedWindowsMarker) {
|
|
@@ -1687,7 +1645,7 @@ function prepareManagedDirectory(root, platform = process.platform) {
|
|
|
1687
1645
|
markerCreated: false
|
|
1688
1646
|
};
|
|
1689
1647
|
}
|
|
1690
|
-
const mayClaim =
|
|
1648
|
+
const mayClaim = fs4.readdirSync(root.directory).length === 0;
|
|
1691
1649
|
if (!mayClaim) {
|
|
1692
1650
|
return {
|
|
1693
1651
|
directory: root.directory,
|
|
@@ -1746,7 +1704,7 @@ function hasSymlinkedParentBelowTrustedAnchor(targetPath, platform = process.pla
|
|
|
1746
1704
|
for (const component of relativeParent.split(pathApi.sep)) {
|
|
1747
1705
|
current = pathApi.join(current, component);
|
|
1748
1706
|
try {
|
|
1749
|
-
if (
|
|
1707
|
+
if (fs4.lstatSync(current).isSymbolicLink()) return true;
|
|
1750
1708
|
} catch (error) {
|
|
1751
1709
|
if (error.code === "ENOENT") return false;
|
|
1752
1710
|
return true;
|
|
@@ -1771,7 +1729,7 @@ function unsafePurgeRoots(roots, platform = process.platform) {
|
|
|
1771
1729
|
}
|
|
1772
1730
|
let stats;
|
|
1773
1731
|
try {
|
|
1774
|
-
stats =
|
|
1732
|
+
stats = fs4.lstatSync(root.directory);
|
|
1775
1733
|
} catch (error) {
|
|
1776
1734
|
if (error.code === "ENOENT") continue;
|
|
1777
1735
|
unsafe.push({
|
|
@@ -1820,14 +1778,14 @@ function unsafePurgeRoots(roots, platform = process.platform) {
|
|
|
1820
1778
|
}
|
|
1821
1779
|
|
|
1822
1780
|
// src/commands/hook-config.ts
|
|
1823
|
-
import
|
|
1781
|
+
import fs5 from "fs";
|
|
1824
1782
|
import os2 from "os";
|
|
1825
|
-
import
|
|
1783
|
+
import path10 from "path";
|
|
1826
1784
|
|
|
1827
1785
|
// ../../packages/agent-targets/src/install/hooks/codex.ts
|
|
1828
1786
|
import { createHash } from "crypto";
|
|
1829
1787
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
1830
|
-
import
|
|
1788
|
+
import path7 from "path";
|
|
1831
1789
|
import { parse as parse2 } from "smol-toml";
|
|
1832
1790
|
|
|
1833
1791
|
// ../../packages/agent-targets/src/toml.ts
|
|
@@ -1837,7 +1795,7 @@ function asRecord2(value) {
|
|
|
1837
1795
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1838
1796
|
}
|
|
1839
1797
|
function singlePath(value) {
|
|
1840
|
-
const
|
|
1798
|
+
const path29 = [];
|
|
1841
1799
|
let current = value;
|
|
1842
1800
|
while (true) {
|
|
1843
1801
|
if (Array.isArray(current) && current.length === 1) {
|
|
@@ -1845,13 +1803,13 @@ function singlePath(value) {
|
|
|
1845
1803
|
continue;
|
|
1846
1804
|
}
|
|
1847
1805
|
const record = asRecord2(current);
|
|
1848
|
-
if (!record) return
|
|
1806
|
+
if (!record) return path29;
|
|
1849
1807
|
const keys = Object.keys(record);
|
|
1850
|
-
if (keys.length === 0) return
|
|
1808
|
+
if (keys.length === 0) return path29;
|
|
1851
1809
|
if (keys.length !== 1) throw new Error("ambiguous TOML statement path");
|
|
1852
1810
|
const key = keys[0];
|
|
1853
1811
|
if (key === void 0) throw new Error("missing TOML statement key");
|
|
1854
|
-
|
|
1812
|
+
path29.push(key);
|
|
1855
1813
|
current = record[key];
|
|
1856
1814
|
}
|
|
1857
1815
|
}
|
|
@@ -1933,8 +1891,8 @@ function scanStatements(source) {
|
|
|
1933
1891
|
}
|
|
1934
1892
|
return statements;
|
|
1935
1893
|
}
|
|
1936
|
-
function startsWithPath(
|
|
1937
|
-
return prefix.every((part, index) =>
|
|
1894
|
+
function startsWithPath(path29, prefix) {
|
|
1895
|
+
return prefix.every((part, index) => path29[index] === part);
|
|
1938
1896
|
}
|
|
1939
1897
|
function pathsEqual(left, right) {
|
|
1940
1898
|
return left.length === right.length && left.every((part, index) => part === right[index]);
|
|
@@ -1960,9 +1918,9 @@ function appendToml(source, addition) {
|
|
|
1960
1918
|
function hasOwn(record, key) {
|
|
1961
1919
|
return Object.prototype.hasOwnProperty.call(record, key);
|
|
1962
1920
|
}
|
|
1963
|
-
function updatedValueAtPath(updated,
|
|
1921
|
+
function updatedValueAtPath(updated, path29) {
|
|
1964
1922
|
let current = updated;
|
|
1965
|
-
for (const part of
|
|
1923
|
+
for (const part of path29) {
|
|
1966
1924
|
const record = asRecord2(current);
|
|
1967
1925
|
if (!record || !hasOwn(record, part)) return { exists: false };
|
|
1968
1926
|
current = record[part];
|
|
@@ -1976,22 +1934,22 @@ function normalizedPaths(updates) {
|
|
|
1976
1934
|
throw new Error("TOML update path cannot be empty");
|
|
1977
1935
|
}
|
|
1978
1936
|
if (paths.some(
|
|
1979
|
-
(
|
|
1937
|
+
(path29) => pathsEqual(path29, update.path) || startsWithPath(update.path, path29)
|
|
1980
1938
|
)) {
|
|
1981
1939
|
continue;
|
|
1982
1940
|
}
|
|
1983
1941
|
for (let index = paths.length - 1; index >= 0; index -= 1) {
|
|
1984
|
-
const
|
|
1985
|
-
if (
|
|
1942
|
+
const path29 = paths[index];
|
|
1943
|
+
if (path29 && startsWithPath(path29, update.path)) paths.splice(index, 1);
|
|
1986
1944
|
}
|
|
1987
1945
|
paths.push([...update.path]);
|
|
1988
1946
|
}
|
|
1989
1947
|
return paths;
|
|
1990
1948
|
}
|
|
1991
|
-
function valueDocument(
|
|
1949
|
+
function valueDocument(path29, value) {
|
|
1992
1950
|
let nested = value;
|
|
1993
|
-
for (let index =
|
|
1994
|
-
const part =
|
|
1951
|
+
for (let index = path29.length - 1; index >= 0; index -= 1) {
|
|
1952
|
+
const part = path29[index];
|
|
1995
1953
|
if (part === void 0) throw new Error("TOML update path is invalid");
|
|
1996
1954
|
nested = { [part]: nested };
|
|
1997
1955
|
}
|
|
@@ -2010,12 +1968,12 @@ function insertAfterStatement(source, statement, addition) {
|
|
|
2010
1968
|
const separator = before.endsWith(eol) ? "" : eol;
|
|
2011
1969
|
return `${before}${separator}${normalized}${eol}${source.slice(statement.end)}`;
|
|
2012
1970
|
}
|
|
2013
|
-
function insertUpdatedValue(source,
|
|
2014
|
-
const key =
|
|
1971
|
+
function insertUpdatedValue(source, path29, value) {
|
|
1972
|
+
const key = path29.at(-1);
|
|
2015
1973
|
if (key === void 0) throw new Error("TOML update path cannot be empty");
|
|
2016
1974
|
const assignment = localAssignment(key, value);
|
|
2017
1975
|
if (assignment !== null) {
|
|
2018
|
-
const parent =
|
|
1976
|
+
const parent = path29.slice(0, -1);
|
|
2019
1977
|
const parentTables = scanStatements(source).filter(
|
|
2020
1978
|
(statement) => statement.isTable && pathsEqual(statement.path, parent)
|
|
2021
1979
|
);
|
|
@@ -2029,17 +1987,17 @@ function insertUpdatedValue(source, path30, value) {
|
|
|
2029
1987
|
return insertAfterStatement(source, parentTable, assignment);
|
|
2030
1988
|
}
|
|
2031
1989
|
}
|
|
2032
|
-
return appendToml(source, stringify(valueDocument(
|
|
1990
|
+
return appendToml(source, stringify(valueDocument(path29, value)));
|
|
2033
1991
|
}
|
|
2034
1992
|
function updateTomlPaths(source, updated, updates) {
|
|
2035
1993
|
const paths = normalizedPaths(updates);
|
|
2036
1994
|
if (paths.length === 0) return source;
|
|
2037
1995
|
const stripped = removeStatements(source, scanStatements(source), paths);
|
|
2038
1996
|
let result = stripped;
|
|
2039
|
-
for (const
|
|
2040
|
-
const next = updatedValueAtPath(updated,
|
|
1997
|
+
for (const path29 of paths) {
|
|
1998
|
+
const next = updatedValueAtPath(updated, path29);
|
|
2041
1999
|
if (!next.exists) continue;
|
|
2042
|
-
result = insertUpdatedValue(result,
|
|
2000
|
+
result = insertUpdatedValue(result, path29, next.value);
|
|
2043
2001
|
}
|
|
2044
2002
|
let reparsed;
|
|
2045
2003
|
try {
|
|
@@ -2058,7 +2016,7 @@ function updateTomlPaths(source, updated, updates) {
|
|
|
2058
2016
|
}
|
|
2059
2017
|
|
|
2060
2018
|
// ../../packages/agent-targets/src/install/hooks/shared.ts
|
|
2061
|
-
import
|
|
2019
|
+
import path6 from "path";
|
|
2062
2020
|
function asRecord3(value) {
|
|
2063
2021
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2064
2022
|
}
|
|
@@ -2118,7 +2076,7 @@ function changedMutation(snapshot, after) {
|
|
|
2118
2076
|
return before === after ? null : { path: snapshot.path, before, after };
|
|
2119
2077
|
}
|
|
2120
2078
|
function fmlHookCommand(pluginRoot, target2) {
|
|
2121
|
-
const handlerPath =
|
|
2079
|
+
const handlerPath = path6.join(pluginRoot, "bin", "hook-handler");
|
|
2122
2080
|
const encodedPath = Buffer.from(handlerPath, "utf8").toString("base64url");
|
|
2123
2081
|
return `node -e "${FML_HOOK_LOADER}" ${encodedPath} ${target2}`;
|
|
2124
2082
|
}
|
|
@@ -2231,11 +2189,11 @@ function uniquePaths(paths) {
|
|
|
2231
2189
|
function codexPaths(context) {
|
|
2232
2190
|
const configuredHome = context.env.CODEX_HOME;
|
|
2233
2191
|
const trimmedHome = typeof configuredHome === "string" ? configuredHome.trim() : "";
|
|
2234
|
-
const dir =
|
|
2235
|
-
trimmedHome.length > 0 ? trimmedHome :
|
|
2192
|
+
const dir = path7.resolve(
|
|
2193
|
+
trimmedHome.length > 0 ? trimmedHome : path7.join(context.homeDir, ".codex")
|
|
2236
2194
|
);
|
|
2237
|
-
const configPath4 =
|
|
2238
|
-
const hooksPath =
|
|
2195
|
+
const configPath4 = path7.join(dir, "config.toml");
|
|
2196
|
+
const hooksPath = path7.join(dir, "hooks.json");
|
|
2239
2197
|
return {
|
|
2240
2198
|
configPath: configPath4,
|
|
2241
2199
|
hooksPath,
|
|
@@ -2667,7 +2625,7 @@ function codexConfigUpdatePaths(original, updated) {
|
|
|
2667
2625
|
}
|
|
2668
2626
|
}
|
|
2669
2627
|
}
|
|
2670
|
-
return paths.map((
|
|
2628
|
+
return paths.map((path29) => ({ path: path29 }));
|
|
2671
2629
|
}
|
|
2672
2630
|
function updateCodexConfigToml(source, original, updated) {
|
|
2673
2631
|
return updateTomlPaths(
|
|
@@ -3117,7 +3075,7 @@ var CODEX_HOOK_INSTALLER = Object.freeze({
|
|
|
3117
3075
|
|
|
3118
3076
|
// ../../packages/agent-targets/src/install/hooks/gemini.ts
|
|
3119
3077
|
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
3120
|
-
import
|
|
3078
|
+
import path8 from "path";
|
|
3121
3079
|
|
|
3122
3080
|
// ../../packages/agent-targets/src/mcp/jsonc.ts
|
|
3123
3081
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
@@ -3173,7 +3131,7 @@ function longestCommonArraySubsequence(original, updated) {
|
|
|
3173
3131
|
}
|
|
3174
3132
|
return matches;
|
|
3175
3133
|
}
|
|
3176
|
-
function arrayDiff(original, updated,
|
|
3134
|
+
function arrayDiff(original, updated, path29) {
|
|
3177
3135
|
const updates = [];
|
|
3178
3136
|
const matches = longestCommonArraySubsequence(original, updated);
|
|
3179
3137
|
let originalStart = 0;
|
|
@@ -3191,19 +3149,19 @@ function arrayDiff(original, updated, path30) {
|
|
|
3191
3149
|
...jsoncUpdatesForObjectDiff(
|
|
3192
3150
|
original[originalStart + offset],
|
|
3193
3151
|
updated[updatedStart + offset],
|
|
3194
|
-
[...
|
|
3152
|
+
[...path29, currentIndex + offset]
|
|
3195
3153
|
)
|
|
3196
3154
|
);
|
|
3197
3155
|
}
|
|
3198
3156
|
for (let offset = pairedCount; offset < originalCount; offset += 1) {
|
|
3199
3157
|
updates.push({
|
|
3200
|
-
path: [...
|
|
3158
|
+
path: [...path29, currentIndex + pairedCount],
|
|
3201
3159
|
value: void 0
|
|
3202
3160
|
});
|
|
3203
3161
|
}
|
|
3204
3162
|
for (let offset = pairedCount; offset < updatedCount; offset += 1) {
|
|
3205
3163
|
updates.push({
|
|
3206
|
-
path: [...
|
|
3164
|
+
path: [...path29, currentIndex + offset],
|
|
3207
3165
|
value: updated[updatedStart + offset],
|
|
3208
3166
|
isArrayInsertion: true
|
|
3209
3167
|
});
|
|
@@ -3216,21 +3174,21 @@ function arrayDiff(original, updated, path30) {
|
|
|
3216
3174
|
}
|
|
3217
3175
|
return updates;
|
|
3218
3176
|
}
|
|
3219
|
-
function jsoncUpdatesForObjectDiff(original, updated,
|
|
3177
|
+
function jsoncUpdatesForObjectDiff(original, updated, path29 = []) {
|
|
3220
3178
|
if (isDeepStrictEqual3(original, updated)) return [];
|
|
3221
3179
|
if (Array.isArray(original) && Array.isArray(updated)) {
|
|
3222
|
-
return arrayDiff(original, updated,
|
|
3180
|
+
return arrayDiff(original, updated, path29);
|
|
3223
3181
|
}
|
|
3224
3182
|
const originalObject = asObject(original);
|
|
3225
3183
|
const updatedObject = asObject(updated);
|
|
3226
|
-
if (!originalObject || !updatedObject) return [{ path:
|
|
3184
|
+
if (!originalObject || !updatedObject) return [{ path: path29, value: updated }];
|
|
3227
3185
|
const keys = /* @__PURE__ */ new Set([
|
|
3228
3186
|
...Object.keys(originalObject),
|
|
3229
3187
|
...Object.keys(updatedObject)
|
|
3230
3188
|
]);
|
|
3231
3189
|
return [...keys].flatMap(
|
|
3232
3190
|
(key) => jsoncUpdatesForObjectDiff(originalObject[key], updatedObject[key], [
|
|
3233
|
-
...
|
|
3191
|
+
...path29,
|
|
3234
3192
|
key
|
|
3235
3193
|
])
|
|
3236
3194
|
);
|
|
@@ -3278,7 +3236,7 @@ var TARGET_ID3 = TARGET3.id;
|
|
|
3278
3236
|
var DISPLAY_NAME3 = TARGET3.displayName;
|
|
3279
3237
|
var MANAGED_HOOK_NAME = "fml-capture";
|
|
3280
3238
|
function settingsPath(context) {
|
|
3281
|
-
return
|
|
3239
|
+
return path8.join(geminiConfigDirectory(context), "settings.json");
|
|
3282
3240
|
}
|
|
3283
3241
|
function readGeminiSettings(snapshot) {
|
|
3284
3242
|
const failure = snapshotError(snapshot);
|
|
@@ -3511,15 +3469,15 @@ var GEMINI_HOOK_INSTALLER = Object.freeze({
|
|
|
3511
3469
|
});
|
|
3512
3470
|
|
|
3513
3471
|
// ../../packages/agent-targets/src/install/hooks/grok.ts
|
|
3514
|
-
import
|
|
3472
|
+
import path9 from "path";
|
|
3515
3473
|
var TARGET4 = agentTarget("grok");
|
|
3516
3474
|
var TARGET_ID4 = TARGET4.id;
|
|
3517
3475
|
var DISPLAY_NAME4 = TARGET4.displayName;
|
|
3518
3476
|
var HOOK_TIMEOUT_SECONDS2 = 10;
|
|
3519
3477
|
function grokHooksPath(context) {
|
|
3520
3478
|
const configuredHome = context.env.GROK_HOME?.trim();
|
|
3521
|
-
const grokHome = configuredHome ?
|
|
3522
|
-
return
|
|
3479
|
+
const grokHome = configuredHome ? path9.resolve(configuredHome) : path9.join(context.homeDir, ".grok");
|
|
3480
|
+
return path9.join(grokHome, "hooks", "fml.json");
|
|
3523
3481
|
}
|
|
3524
3482
|
function planInstall3(context) {
|
|
3525
3483
|
const configPath4 = grokHooksPath(context);
|
|
@@ -3638,14 +3596,14 @@ var HOOK_REGISTRATION_CAPABILITIES = Object.freeze([
|
|
|
3638
3596
|
]);
|
|
3639
3597
|
|
|
3640
3598
|
// src/commands/hook-config.ts
|
|
3641
|
-
var DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH =
|
|
3599
|
+
var DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH = path10.join(
|
|
3642
3600
|
FML_DATA_DIR,
|
|
3643
3601
|
"codex-hook-install.json"
|
|
3644
3602
|
);
|
|
3645
3603
|
function readHookFile(filePath) {
|
|
3646
3604
|
let stat;
|
|
3647
3605
|
try {
|
|
3648
|
-
stat =
|
|
3606
|
+
stat = fs5.lstatSync(filePath);
|
|
3649
3607
|
} catch (error) {
|
|
3650
3608
|
if (error.code === "ENOENT") {
|
|
3651
3609
|
return { path: filePath, kind: "missing" };
|
|
@@ -3674,7 +3632,7 @@ function readHookFile(filePath) {
|
|
|
3674
3632
|
return {
|
|
3675
3633
|
path: filePath,
|
|
3676
3634
|
kind: "file",
|
|
3677
|
-
contents:
|
|
3635
|
+
contents: fs5.readFileSync(filePath, "utf8")
|
|
3678
3636
|
};
|
|
3679
3637
|
} catch (error) {
|
|
3680
3638
|
return {
|
|
@@ -3686,17 +3644,17 @@ function readHookFile(filePath) {
|
|
|
3686
3644
|
}
|
|
3687
3645
|
function canonicalizePath(filePath) {
|
|
3688
3646
|
try {
|
|
3689
|
-
return
|
|
3647
|
+
return fs5.realpathSync(filePath);
|
|
3690
3648
|
} catch {
|
|
3691
3649
|
const missingSegments = [];
|
|
3692
3650
|
let ancestor = filePath;
|
|
3693
3651
|
while (true) {
|
|
3694
|
-
const parent =
|
|
3652
|
+
const parent = path10.dirname(ancestor);
|
|
3695
3653
|
if (parent === ancestor) return filePath;
|
|
3696
|
-
missingSegments.unshift(
|
|
3654
|
+
missingSegments.unshift(path10.basename(ancestor));
|
|
3697
3655
|
ancestor = parent;
|
|
3698
3656
|
try {
|
|
3699
|
-
return
|
|
3657
|
+
return path10.join(fs5.realpathSync(ancestor), ...missingSegments);
|
|
3700
3658
|
} catch {
|
|
3701
3659
|
}
|
|
3702
3660
|
}
|
|
@@ -3715,7 +3673,7 @@ function assertMutationPrecondition(mutation) {
|
|
|
3715
3673
|
}
|
|
3716
3674
|
function applyMutation(mutation) {
|
|
3717
3675
|
if (mutation.after === null) {
|
|
3718
|
-
|
|
3676
|
+
fs5.rmSync(mutation.path);
|
|
3719
3677
|
} else {
|
|
3720
3678
|
writeTextFileAtomic(mutation.path, mutation.after);
|
|
3721
3679
|
}
|
|
@@ -3728,7 +3686,7 @@ function rollbackMutation(mutation) {
|
|
|
3728
3686
|
};
|
|
3729
3687
|
assertMutationPrecondition(inverse);
|
|
3730
3688
|
if (inverse.after === null) {
|
|
3731
|
-
|
|
3689
|
+
fs5.rmSync(inverse.path);
|
|
3732
3690
|
} else {
|
|
3733
3691
|
writeTextFileAtomic(inverse.path, inverse.after);
|
|
3734
3692
|
}
|
|
@@ -3796,7 +3754,7 @@ function applyPlan(plan, warn, onFailure) {
|
|
|
3796
3754
|
};
|
|
3797
3755
|
}
|
|
3798
3756
|
function plannerContext(packageRoot, options) {
|
|
3799
|
-
const ownershipStatePath = options.ownershipStatePath ?? (options.homeDir ?
|
|
3757
|
+
const ownershipStatePath = options.ownershipStatePath ?? (options.homeDir ? path10.join(options.homeDir, ".fml", "codex-hook-install.json") : DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH);
|
|
3800
3758
|
return {
|
|
3801
3759
|
packageRoot,
|
|
3802
3760
|
homeDir: options.homeDir ?? os2.homedir(),
|
|
@@ -3827,10 +3785,10 @@ function removeFmlHooks(options = {}) {
|
|
|
3827
3785
|
}
|
|
3828
3786
|
|
|
3829
3787
|
// src/commands/marketplace-link.ts
|
|
3830
|
-
import
|
|
3788
|
+
import fs6 from "fs";
|
|
3831
3789
|
function existingPathKind(linkPath) {
|
|
3832
3790
|
try {
|
|
3833
|
-
return
|
|
3791
|
+
return fs6.lstatSync(linkPath).isSymbolicLink() ? "symlink" : "other";
|
|
3834
3792
|
} catch (error) {
|
|
3835
3793
|
if (error.code === "ENOENT") return "missing";
|
|
3836
3794
|
throw error;
|
|
@@ -3839,15 +3797,15 @@ function existingPathKind(linkPath) {
|
|
|
3839
3797
|
function replaceMarketplaceLink(linkPath, targetPath, type) {
|
|
3840
3798
|
const existing = existingPathKind(linkPath);
|
|
3841
3799
|
if (existing === "other") return "preserved";
|
|
3842
|
-
if (existing === "symlink")
|
|
3843
|
-
|
|
3800
|
+
if (existing === "symlink") fs6.unlinkSync(linkPath);
|
|
3801
|
+
fs6.symlinkSync(targetPath, linkPath, type);
|
|
3844
3802
|
return existing === "symlink" ? "replaced" : "created";
|
|
3845
3803
|
}
|
|
3846
3804
|
function removeMarketplaceLink(linkPath) {
|
|
3847
3805
|
const existing = existingPathKind(linkPath);
|
|
3848
3806
|
if (existing === "missing") return "missing";
|
|
3849
3807
|
if (existing === "other") return "preserved";
|
|
3850
|
-
|
|
3808
|
+
fs6.unlinkSync(linkPath);
|
|
3851
3809
|
return "removed";
|
|
3852
3810
|
}
|
|
3853
3811
|
|
|
@@ -3942,10 +3900,10 @@ function configRecord(value) {
|
|
|
3942
3900
|
}
|
|
3943
3901
|
|
|
3944
3902
|
// ../../packages/agent-targets/src/mcp/targets/claude-desktop.ts
|
|
3945
|
-
import
|
|
3903
|
+
import path12 from "path";
|
|
3946
3904
|
|
|
3947
3905
|
// ../../packages/agent-targets/src/mcp/capability.ts
|
|
3948
|
-
import
|
|
3906
|
+
import path11 from "path";
|
|
3949
3907
|
import { parse as parse4 } from "smol-toml";
|
|
3950
3908
|
|
|
3951
3909
|
// ../../packages/agent-targets/src/mcp/toml.ts
|
|
@@ -4051,7 +4009,7 @@ function changedConfigPlan(target2, current, before, data) {
|
|
|
4051
4009
|
function generatedServer(target2, context) {
|
|
4052
4010
|
return fmlMcpServerConfig(
|
|
4053
4011
|
target2.command,
|
|
4054
|
-
|
|
4012
|
+
path11.join(context.packageRoot, "bin", "mcp-server")
|
|
4055
4013
|
);
|
|
4056
4014
|
}
|
|
4057
4015
|
function planInstall4(target2, context) {
|
|
@@ -4131,7 +4089,7 @@ var CLAUDE_DESKTOP_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4131
4089
|
configKey: "mcpServers",
|
|
4132
4090
|
configPath: ({ env, homeDir, platform }) => {
|
|
4133
4091
|
if (platform === "darwin") {
|
|
4134
|
-
return
|
|
4092
|
+
return path12.join(
|
|
4135
4093
|
homeDir,
|
|
4136
4094
|
"Library",
|
|
4137
4095
|
"Application Support",
|
|
@@ -4140,14 +4098,14 @@ var CLAUDE_DESKTOP_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4140
4098
|
);
|
|
4141
4099
|
}
|
|
4142
4100
|
if (platform === "win32") {
|
|
4143
|
-
return
|
|
4144
|
-
env.APPDATA ??
|
|
4101
|
+
return path12.join(
|
|
4102
|
+
env.APPDATA ?? path12.join(homeDir, "AppData", "Roaming"),
|
|
4145
4103
|
"Claude",
|
|
4146
4104
|
"claude_desktop_config.json"
|
|
4147
4105
|
);
|
|
4148
4106
|
}
|
|
4149
|
-
return
|
|
4150
|
-
env.XDG_CONFIG_HOME ??
|
|
4107
|
+
return path12.join(
|
|
4108
|
+
env.XDG_CONFIG_HOME ?? path12.join(homeDir, ".config"),
|
|
4151
4109
|
"Claude",
|
|
4152
4110
|
"claude_desktop_config.json"
|
|
4153
4111
|
);
|
|
@@ -4156,7 +4114,7 @@ var CLAUDE_DESKTOP_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4156
4114
|
});
|
|
4157
4115
|
|
|
4158
4116
|
// ../../packages/agent-targets/src/mcp/targets/codex.ts
|
|
4159
|
-
import
|
|
4117
|
+
import path13 from "path";
|
|
4160
4118
|
var TARGET6 = agentTarget("codex");
|
|
4161
4119
|
var CODEX_DIRECT_MCP = createDirectMcpCapability({
|
|
4162
4120
|
targetId: TARGET6.id,
|
|
@@ -4165,26 +4123,26 @@ var CODEX_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4165
4123
|
configKey: "mcp_servers",
|
|
4166
4124
|
configPath: ({ env, homeDir }) => {
|
|
4167
4125
|
const configuredHome = env.CODEX_HOME;
|
|
4168
|
-
const codexHome = typeof configuredHome === "string" && configuredHome.length > 0 ?
|
|
4169
|
-
return
|
|
4126
|
+
const codexHome = typeof configuredHome === "string" && configuredHome.length > 0 ? path13.resolve(configuredHome) : path13.join(homeDir, ".codex");
|
|
4127
|
+
return path13.join(codexHome, "config.toml");
|
|
4170
4128
|
},
|
|
4171
4129
|
command: () => "node"
|
|
4172
4130
|
});
|
|
4173
4131
|
|
|
4174
4132
|
// ../../packages/agent-targets/src/mcp/targets/gemini.ts
|
|
4175
|
-
import
|
|
4133
|
+
import path14 from "path";
|
|
4176
4134
|
var TARGET7 = agentTarget("gemini");
|
|
4177
4135
|
var GEMINI_DIRECT_MCP = createDirectMcpCapability({
|
|
4178
4136
|
targetId: TARGET7.id,
|
|
4179
4137
|
displayName: TARGET7.displayName,
|
|
4180
4138
|
configFormat: "json",
|
|
4181
4139
|
configKey: "mcpServers",
|
|
4182
|
-
configPath: (context) =>
|
|
4140
|
+
configPath: (context) => path14.join(geminiConfigDirectory(context), "settings.json"),
|
|
4183
4141
|
command: () => "node"
|
|
4184
4142
|
});
|
|
4185
4143
|
|
|
4186
4144
|
// ../../packages/agent-targets/src/mcp/targets/grok.ts
|
|
4187
|
-
import
|
|
4145
|
+
import path15 from "path";
|
|
4188
4146
|
var TARGET8 = agentTarget("grok");
|
|
4189
4147
|
var GROK_DIRECT_MCP = createDirectMcpCapability({
|
|
4190
4148
|
targetId: TARGET8.id,
|
|
@@ -4193,8 +4151,8 @@ var GROK_DIRECT_MCP = createDirectMcpCapability({
|
|
|
4193
4151
|
configKey: "mcp_servers",
|
|
4194
4152
|
configPath: ({ env, homeDir }) => {
|
|
4195
4153
|
const configuredHome = env.GROK_HOME;
|
|
4196
|
-
const grokHome = typeof configuredHome === "string" && configuredHome.length > 0 ?
|
|
4197
|
-
return
|
|
4154
|
+
const grokHome = typeof configuredHome === "string" && configuredHome.length > 0 ? path15.resolve(configuredHome) : path15.join(homeDir, ".grok");
|
|
4155
|
+
return path15.join(grokHome, "config.toml");
|
|
4198
4156
|
},
|
|
4199
4157
|
command: () => "node"
|
|
4200
4158
|
});
|
|
@@ -4208,7 +4166,7 @@ var DIRECT_MCP_CAPABILITIES = Object.freeze([
|
|
|
4208
4166
|
]);
|
|
4209
4167
|
|
|
4210
4168
|
// src/commands/mcp-config.ts
|
|
4211
|
-
import
|
|
4169
|
+
import fs7 from "fs";
|
|
4212
4170
|
import os3 from "os";
|
|
4213
4171
|
function resolutionContext(options) {
|
|
4214
4172
|
return {
|
|
@@ -4221,7 +4179,7 @@ function resolutionContext(options) {
|
|
|
4221
4179
|
function readMcpFile(filePath) {
|
|
4222
4180
|
let stat;
|
|
4223
4181
|
try {
|
|
4224
|
-
stat =
|
|
4182
|
+
stat = fs7.lstatSync(filePath);
|
|
4225
4183
|
} catch (error) {
|
|
4226
4184
|
if (error.code === "ENOENT") {
|
|
4227
4185
|
return { path: filePath, kind: "missing" };
|
|
@@ -4250,7 +4208,7 @@ function readMcpFile(filePath) {
|
|
|
4250
4208
|
return {
|
|
4251
4209
|
path: filePath,
|
|
4252
4210
|
kind: "file",
|
|
4253
|
-
contents:
|
|
4211
|
+
contents: fs7.readFileSync(filePath, "utf8")
|
|
4254
4212
|
};
|
|
4255
4213
|
} catch (error) {
|
|
4256
4214
|
return {
|
|
@@ -4286,14 +4244,14 @@ function preflightMutation(mutation) {
|
|
|
4286
4244
|
}
|
|
4287
4245
|
function writeMutation(mutation) {
|
|
4288
4246
|
if (mutation.after === null) {
|
|
4289
|
-
|
|
4247
|
+
fs7.rmSync(mutation.path, { force: true });
|
|
4290
4248
|
return;
|
|
4291
4249
|
}
|
|
4292
4250
|
writeTextFileAtomic(mutation.path, mutation.after);
|
|
4293
4251
|
}
|
|
4294
4252
|
function rollbackMutation2(mutation) {
|
|
4295
4253
|
if (mutation.before === null) {
|
|
4296
|
-
|
|
4254
|
+
fs7.rmSync(mutation.path, { force: true });
|
|
4297
4255
|
return;
|
|
4298
4256
|
}
|
|
4299
4257
|
writeTextFileAtomic(mutation.path, mutation.before);
|
|
@@ -4384,12 +4342,12 @@ function removeFmlDirectMcp(target2 = "all", options = {}) {
|
|
|
4384
4342
|
|
|
4385
4343
|
// src/commands/agent-skills.ts
|
|
4386
4344
|
import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
|
|
4387
|
-
import
|
|
4345
|
+
import fs8 from "fs";
|
|
4388
4346
|
import os4 from "os";
|
|
4389
|
-
import
|
|
4347
|
+
import path20 from "path";
|
|
4390
4348
|
|
|
4391
4349
|
// ../../packages/agent-targets/src/install/surfaces/capability.ts
|
|
4392
|
-
import
|
|
4350
|
+
import path16 from "path";
|
|
4393
4351
|
var SOURCE_PATH_SEGMENTS = ["agent-assets", "fml", "SKILL.md"];
|
|
4394
4352
|
var DESTINATION_PATH_SEGMENTS = ["skills", "fml", "SKILL.md"];
|
|
4395
4353
|
function createAgentSkillCapability(definition) {
|
|
@@ -4402,8 +4360,8 @@ function createAgentSkillCapability(definition) {
|
|
|
4402
4360
|
resolve: (context) => Object.freeze({
|
|
4403
4361
|
targetId: definition.targetId,
|
|
4404
4362
|
displayName: definition.displayName,
|
|
4405
|
-
sourcePath:
|
|
4406
|
-
destinationPath:
|
|
4363
|
+
sourcePath: path16.join(context.packageRoot, ...SOURCE_PATH_SEGMENTS),
|
|
4364
|
+
destinationPath: path16.join(
|
|
4407
4365
|
definition.destinationRoot(context),
|
|
4408
4366
|
...DESTINATION_PATH_SEGMENTS
|
|
4409
4367
|
),
|
|
@@ -4426,7 +4384,7 @@ var CLAUDE_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4426
4384
|
});
|
|
4427
4385
|
|
|
4428
4386
|
// ../../packages/agent-targets/src/install/surfaces/targets/codex.ts
|
|
4429
|
-
import
|
|
4387
|
+
import path17 from "path";
|
|
4430
4388
|
var TARGET10 = agentTarget("codex");
|
|
4431
4389
|
var CODEX_AGENT_SKILL = createAgentSkillCapability({
|
|
4432
4390
|
targetId: TARGET10.id,
|
|
@@ -4434,11 +4392,11 @@ var CODEX_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4434
4392
|
invocation: "$fml",
|
|
4435
4393
|
deliveryMode: "instruction-read",
|
|
4436
4394
|
argumentMode: "user-input",
|
|
4437
|
-
destinationRoot: ({ homeDir }) =>
|
|
4395
|
+
destinationRoot: ({ homeDir }) => path17.join(homeDir, ".agents")
|
|
4438
4396
|
});
|
|
4439
4397
|
|
|
4440
4398
|
// ../../packages/agent-targets/src/install/surfaces/targets/gemini.ts
|
|
4441
|
-
import
|
|
4399
|
+
import path18 from "path";
|
|
4442
4400
|
var TARGET11 = agentTarget("gemini");
|
|
4443
4401
|
var GEMINI_AGENT_SKILL = createAgentSkillCapability({
|
|
4444
4402
|
targetId: TARGET11.id,
|
|
@@ -4448,13 +4406,13 @@ var GEMINI_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4448
4406
|
argumentMode: "post-submit-prompt",
|
|
4449
4407
|
destinationRoot: ({ env, homeDir }) => {
|
|
4450
4408
|
const configuredHome = env.GEMINI_CLI_HOME?.trim();
|
|
4451
|
-
const homeRoot = configuredHome ?
|
|
4452
|
-
return
|
|
4409
|
+
const homeRoot = configuredHome ? path18.resolve(configuredHome) : homeDir;
|
|
4410
|
+
return path18.join(homeRoot, ".agents");
|
|
4453
4411
|
}
|
|
4454
4412
|
});
|
|
4455
4413
|
|
|
4456
4414
|
// ../../packages/agent-targets/src/install/surfaces/targets/grok.ts
|
|
4457
|
-
import
|
|
4415
|
+
import path19 from "path";
|
|
4458
4416
|
var TARGET12 = agentTarget("grok");
|
|
4459
4417
|
var GROK_AGENT_SKILL = createAgentSkillCapability({
|
|
4460
4418
|
targetId: TARGET12.id,
|
|
@@ -4462,7 +4420,7 @@ var GROK_AGENT_SKILL = createAgentSkillCapability({
|
|
|
4462
4420
|
invocation: "/fml",
|
|
4463
4421
|
deliveryMode: "prompt-expansion",
|
|
4464
4422
|
argumentMode: "template-or-append",
|
|
4465
|
-
destinationRoot: ({ homeDir }) =>
|
|
4423
|
+
destinationRoot: ({ homeDir }) => path19.join(homeDir, ".agents")
|
|
4466
4424
|
});
|
|
4467
4425
|
|
|
4468
4426
|
// ../../packages/agent-targets/src/install/surfaces/registry.ts
|
|
@@ -4476,7 +4434,7 @@ var AGENT_SKILL_CAPABILITIES = Object.freeze([
|
|
|
4476
4434
|
// src/commands/agent-skills.ts
|
|
4477
4435
|
var FML_AGENT_SKILL_MARKER = "<!-- fml-managed-agent-surface:v1 -->";
|
|
4478
4436
|
var AGENT_SKILL_STATE_SCHEMA_VERSION = 1;
|
|
4479
|
-
var DEFAULT_STATE_PATH =
|
|
4437
|
+
var DEFAULT_STATE_PATH = path20.join(FML_DATA_DIR, "agent-skills.json");
|
|
4480
4438
|
function emptyState() {
|
|
4481
4439
|
return Object.freeze({
|
|
4482
4440
|
schemaVersion: AGENT_SKILL_STATE_SCHEMA_VERSION,
|
|
@@ -4489,7 +4447,7 @@ function sha256(contents) {
|
|
|
4489
4447
|
function readSkillFile(filePath) {
|
|
4490
4448
|
let stat;
|
|
4491
4449
|
try {
|
|
4492
|
-
stat =
|
|
4450
|
+
stat = fs8.lstatSync(filePath);
|
|
4493
4451
|
} catch (error) {
|
|
4494
4452
|
if (error.code === "ENOENT") {
|
|
4495
4453
|
return { kind: "missing" };
|
|
@@ -4512,7 +4470,7 @@ function readSkillFile(filePath) {
|
|
|
4512
4470
|
};
|
|
4513
4471
|
}
|
|
4514
4472
|
try {
|
|
4515
|
-
const contents =
|
|
4473
|
+
const contents = fs8.readFileSync(filePath, "utf8");
|
|
4516
4474
|
return { kind: "file", contents, sha256: sha256(contents) };
|
|
4517
4475
|
} catch (error) {
|
|
4518
4476
|
return {
|
|
@@ -4581,7 +4539,7 @@ function parseState(source, statePath) {
|
|
|
4581
4539
|
}
|
|
4582
4540
|
entries.push(
|
|
4583
4541
|
Object.freeze({
|
|
4584
|
-
path:
|
|
4542
|
+
path: path20.resolve(entry.path),
|
|
4585
4543
|
sha256: entry.sha256,
|
|
4586
4544
|
targetIds: Object.freeze([...entry.targetIds])
|
|
4587
4545
|
})
|
|
@@ -4607,7 +4565,7 @@ function loadState(statePath) {
|
|
|
4607
4565
|
}
|
|
4608
4566
|
function serializeState(entries) {
|
|
4609
4567
|
const sorted = [...entries].map((entry) => ({
|
|
4610
|
-
path:
|
|
4568
|
+
path: path20.resolve(entry.path),
|
|
4611
4569
|
sha256: entry.sha256,
|
|
4612
4570
|
targetIds: [...entry.targetIds].sort()
|
|
4613
4571
|
})).sort((left, right) => left.path.localeCompare(right.path));
|
|
@@ -4646,7 +4604,7 @@ function resolvedGroups(pluginRoot, options) {
|
|
|
4646
4604
|
const groups = /* @__PURE__ */ new Map();
|
|
4647
4605
|
for (const capability of AGENT_SKILL_CAPABILITIES) {
|
|
4648
4606
|
const resolved = capability.resolve(context);
|
|
4649
|
-
const destinationPath =
|
|
4607
|
+
const destinationPath = path20.resolve(resolved.destinationPath);
|
|
4650
4608
|
const key = process.platform === "win32" ? destinationPath.toLowerCase() : destinationPath;
|
|
4651
4609
|
const current = groups.get(key) ?? [];
|
|
4652
4610
|
current.push({ ...resolved, destinationPath });
|
|
@@ -4683,10 +4641,10 @@ function resultFor(group, status, reason) {
|
|
|
4683
4641
|
});
|
|
4684
4642
|
}
|
|
4685
4643
|
function destinationDirectoryIssue(destinationPath, requireEmpty) {
|
|
4686
|
-
const skillDir =
|
|
4644
|
+
const skillDir = path20.dirname(destinationPath);
|
|
4687
4645
|
let stat;
|
|
4688
4646
|
try {
|
|
4689
|
-
stat =
|
|
4647
|
+
stat = fs8.lstatSync(skillDir);
|
|
4690
4648
|
} catch (error) {
|
|
4691
4649
|
if (error.code === "ENOENT") return null;
|
|
4692
4650
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4694,7 +4652,7 @@ function destinationDirectoryIssue(destinationPath, requireEmpty) {
|
|
|
4694
4652
|
if (stat.isSymbolicLink()) return "skill directory is a symbolic link";
|
|
4695
4653
|
if (!stat.isDirectory()) return "skill directory is not a directory";
|
|
4696
4654
|
try {
|
|
4697
|
-
if (!requireEmpty ||
|
|
4655
|
+
if (!requireEmpty || fs8.readdirSync(skillDir).length === 0) return null;
|
|
4698
4656
|
return "skill directory contains unmanaged files";
|
|
4699
4657
|
} catch (error) {
|
|
4700
4658
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4711,9 +4669,9 @@ function rollbackSkillWrite(destinationPath, before) {
|
|
|
4711
4669
|
writeTextFileAtomic(destinationPath, before.contents);
|
|
4712
4670
|
return;
|
|
4713
4671
|
}
|
|
4714
|
-
|
|
4672
|
+
fs8.rmSync(destinationPath, { force: true });
|
|
4715
4673
|
try {
|
|
4716
|
-
|
|
4674
|
+
fs8.rmdirSync(path20.dirname(destinationPath));
|
|
4717
4675
|
} catch {
|
|
4718
4676
|
}
|
|
4719
4677
|
}
|
|
@@ -4756,12 +4714,12 @@ function installManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4756
4714
|
const loaded = loadState(statePath);
|
|
4757
4715
|
let stateSource = loaded.source;
|
|
4758
4716
|
const entries = new Map(
|
|
4759
|
-
loaded.state.entries.map((entry) => [
|
|
4717
|
+
loaded.state.entries.map((entry) => [path20.resolve(entry.path), entry])
|
|
4760
4718
|
);
|
|
4761
4719
|
const results = [];
|
|
4762
4720
|
for (const group of resolvedGroups(pluginRoot, options)) {
|
|
4763
4721
|
const source = sourceSkill(group.sourcePath);
|
|
4764
|
-
const destinationPath =
|
|
4722
|
+
const destinationPath = path20.resolve(group.destinationPath);
|
|
4765
4723
|
const current = readSkillFile(destinationPath);
|
|
4766
4724
|
const previous = entries.get(destinationPath);
|
|
4767
4725
|
const nextEntry = stateEntryFor(
|
|
@@ -4846,11 +4804,11 @@ function removeSkillFile(args) {
|
|
|
4846
4804
|
`Agent skill changed before ${args.destinationPath} could be removed.`
|
|
4847
4805
|
);
|
|
4848
4806
|
}
|
|
4849
|
-
const backupPath =
|
|
4850
|
-
|
|
4851
|
-
`.${
|
|
4807
|
+
const backupPath = path20.join(
|
|
4808
|
+
path20.dirname(args.destinationPath),
|
|
4809
|
+
`.${path20.basename(args.destinationPath)}.${process.pid}.${randomUUID3()}.bak`
|
|
4852
4810
|
);
|
|
4853
|
-
|
|
4811
|
+
fs8.renameSync(args.destinationPath, backupPath);
|
|
4854
4812
|
let stateSource;
|
|
4855
4813
|
try {
|
|
4856
4814
|
stateSource = writeState(
|
|
@@ -4860,7 +4818,7 @@ function removeSkillFile(args) {
|
|
|
4860
4818
|
);
|
|
4861
4819
|
} catch (error) {
|
|
4862
4820
|
try {
|
|
4863
|
-
|
|
4821
|
+
fs8.renameSync(backupPath, args.destinationPath);
|
|
4864
4822
|
} catch (rollbackError) {
|
|
4865
4823
|
const message = error instanceof Error ? error.message : String(error);
|
|
4866
4824
|
const rollbackMessage = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
|
|
@@ -4872,12 +4830,12 @@ function removeSkillFile(args) {
|
|
|
4872
4830
|
}
|
|
4873
4831
|
let warning;
|
|
4874
4832
|
try {
|
|
4875
|
-
|
|
4833
|
+
fs8.rmSync(backupPath, { force: true });
|
|
4876
4834
|
} catch (error) {
|
|
4877
4835
|
warning = `agent skill removal was committed, but backup cleanup failed at ${backupPath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
4878
4836
|
}
|
|
4879
4837
|
try {
|
|
4880
|
-
|
|
4838
|
+
fs8.rmdirSync(path20.dirname(args.destinationPath));
|
|
4881
4839
|
} catch {
|
|
4882
4840
|
}
|
|
4883
4841
|
return { stateSource, ...warning ? { warning } : {} };
|
|
@@ -4887,16 +4845,16 @@ function removeManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4887
4845
|
const loaded = loadState(statePath);
|
|
4888
4846
|
let stateSource = loaded.source;
|
|
4889
4847
|
const entries = new Map(
|
|
4890
|
-
loaded.state.entries.map((entry) => [
|
|
4848
|
+
loaded.state.entries.map((entry) => [path20.resolve(entry.path), entry])
|
|
4891
4849
|
);
|
|
4892
4850
|
const candidates = /* @__PURE__ */ new Map();
|
|
4893
4851
|
const currentGroups = resolvedGroups(pluginRoot, options);
|
|
4894
|
-
const packagedSourcePath = currentGroups[0]?.sourcePath ??
|
|
4852
|
+
const packagedSourcePath = currentGroups[0]?.sourcePath ?? path20.join(pluginRoot, "agent-assets", "fml", "SKILL.md");
|
|
4895
4853
|
for (const group of currentGroups) {
|
|
4896
|
-
candidates.set(
|
|
4854
|
+
candidates.set(path20.resolve(group.destinationPath), group);
|
|
4897
4855
|
}
|
|
4898
4856
|
for (const entry of entries.values()) {
|
|
4899
|
-
const destinationPath =
|
|
4857
|
+
const destinationPath = path20.resolve(entry.path);
|
|
4900
4858
|
if (candidates.has(destinationPath)) continue;
|
|
4901
4859
|
const targets = entry.targetIds.filter(isAgentSkillTargetId).map(targetForId);
|
|
4902
4860
|
if (targets.length === 0) continue;
|
|
@@ -4911,7 +4869,7 @@ function removeManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4911
4869
|
for (const group of [...candidates.values()].sort(
|
|
4912
4870
|
(left, right) => left.destinationPath.localeCompare(right.destinationPath)
|
|
4913
4871
|
)) {
|
|
4914
|
-
const destinationPath =
|
|
4872
|
+
const destinationPath = path20.resolve(group.destinationPath);
|
|
4915
4873
|
const current = readSkillFile(destinationPath);
|
|
4916
4874
|
const previous = entries.get(destinationPath);
|
|
4917
4875
|
if (current.kind === "missing") {
|
|
@@ -4969,13 +4927,13 @@ function removeManagedAgentSkills(pluginRoot, options = {}) {
|
|
|
4969
4927
|
}
|
|
4970
4928
|
|
|
4971
4929
|
// src/commands/install.ts
|
|
4972
|
-
function resolvePluginRoot(startDir =
|
|
4930
|
+
function resolvePluginRoot(startDir = path21.dirname(fileURLToPath(import.meta.url))) {
|
|
4973
4931
|
let directory = startDir;
|
|
4974
4932
|
while (true) {
|
|
4975
|
-
if (
|
|
4933
|
+
if (fs9.existsSync(path21.join(directory, "package.json")) && fs9.existsSync(path21.join(directory, "bin"))) {
|
|
4976
4934
|
return directory;
|
|
4977
4935
|
}
|
|
4978
|
-
const parent =
|
|
4936
|
+
const parent = path21.dirname(directory);
|
|
4979
4937
|
if (parent === directory) {
|
|
4980
4938
|
throw new Error(
|
|
4981
4939
|
`Could not locate the FML package root: no ancestor of ${startDir} contains both package.json and bin/. Reinstall @fml-inc/fml and retry.`
|
|
@@ -4990,7 +4948,7 @@ function getPluginRoot() {
|
|
|
4990
4948
|
function readJsonFileForUpdate(filePath) {
|
|
4991
4949
|
let source;
|
|
4992
4950
|
try {
|
|
4993
|
-
source =
|
|
4951
|
+
source = fs9.readFileSync(filePath, "utf8");
|
|
4994
4952
|
} catch (error) {
|
|
4995
4953
|
if (error.code === "ENOENT") {
|
|
4996
4954
|
return { ok: true, exists: false, data: {} };
|
|
@@ -5054,9 +5012,9 @@ async function handleInstall(opts = {}) {
|
|
|
5054
5012
|
FML_LOG_DIR,
|
|
5055
5013
|
FML_OBSERVER_DIR
|
|
5056
5014
|
])) {
|
|
5057
|
-
|
|
5015
|
+
fs9.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
5058
5016
|
}
|
|
5059
|
-
initializeSyncSettings(
|
|
5017
|
+
initializeSyncSettings(path21.join(FML_OBSERVER_DIR, "sync.json"));
|
|
5060
5018
|
let skillReady = false;
|
|
5061
5019
|
try {
|
|
5062
5020
|
const skillResults = installManagedAgentSkills(pluginRoot);
|
|
@@ -5103,7 +5061,7 @@ async function handleInstall(opts = {}) {
|
|
|
5103
5061
|
` warn: Pi extension setup could not be completed: ${message}`
|
|
5104
5062
|
);
|
|
5105
5063
|
}
|
|
5106
|
-
const packageJson = readJsonFile(
|
|
5064
|
+
const packageJson = readJsonFile(path21.join(pluginRoot, "package.json"));
|
|
5107
5065
|
const generatedManifest = readJsonFile(paths.pluginManifestPath);
|
|
5108
5066
|
const version = typeof generatedManifest?.version === "string" ? generatedManifest.version : typeof packageJson?.version === "string" ? packageJson.version : "0.0.0-dev";
|
|
5109
5067
|
writeJsonFile(
|
|
@@ -5120,7 +5078,7 @@ async function handleInstall(opts = {}) {
|
|
|
5120
5078
|
`Warning: preserved unreadable marketplace config ${paths.marketplaceManifestPath}: ${marketplaceResult.error}`
|
|
5121
5079
|
);
|
|
5122
5080
|
} else {
|
|
5123
|
-
|
|
5081
|
+
fs9.mkdirSync(paths.marketplaceDir, { recursive: true, mode: 448 });
|
|
5124
5082
|
const linkUpdate = replaceMarketplaceLink(
|
|
5125
5083
|
paths.marketplaceLinkPath,
|
|
5126
5084
|
pluginRoot,
|
|
@@ -5229,12 +5187,12 @@ async function handleInstall(opts = {}) {
|
|
|
5229
5187
|
import { statSync } from "fs";
|
|
5230
5188
|
|
|
5231
5189
|
// src/commands/otel-config.ts
|
|
5232
|
-
import
|
|
5190
|
+
import fs11 from "fs";
|
|
5233
5191
|
import os6 from "os";
|
|
5234
|
-
import
|
|
5192
|
+
import path26 from "path";
|
|
5235
5193
|
|
|
5236
5194
|
// ../../packages/agent-targets/src/install/otel/claude.ts
|
|
5237
|
-
import
|
|
5195
|
+
import path22 from "path";
|
|
5238
5196
|
|
|
5239
5197
|
// ../../packages/agent-targets/src/install/otel/shared.ts
|
|
5240
5198
|
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
@@ -5371,9 +5329,9 @@ var MANAGED_MARKER = "FML_OTEL_MANAGED";
|
|
|
5371
5329
|
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";
|
|
5372
5330
|
function configPath(context) {
|
|
5373
5331
|
if (context.configPathOverride) {
|
|
5374
|
-
return
|
|
5332
|
+
return path22.resolve(context.configPathOverride);
|
|
5375
5333
|
}
|
|
5376
|
-
return
|
|
5334
|
+
return path22.join(
|
|
5377
5335
|
claudeConfigDirectory({ env: context.env, homeDir: context.homeDir }),
|
|
5378
5336
|
"settings.json"
|
|
5379
5337
|
);
|
|
@@ -5544,7 +5502,7 @@ var CLAUDE_OTEL_INSTALLER = Object.freeze({
|
|
|
5544
5502
|
|
|
5545
5503
|
// ../../packages/agent-targets/src/install/otel/codex.ts
|
|
5546
5504
|
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
5547
|
-
import
|
|
5505
|
+
import path23 from "path";
|
|
5548
5506
|
import { parse as parse5 } from "smol-toml";
|
|
5549
5507
|
var TARGET14 = agentTarget("codex");
|
|
5550
5508
|
var TARGET_ID6 = TARGET14.id;
|
|
@@ -5553,13 +5511,13 @@ var AUTHENTICATION2 = "bearer-header";
|
|
|
5553
5511
|
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";
|
|
5554
5512
|
function configPath2(context) {
|
|
5555
5513
|
if (context.configPathOverride) {
|
|
5556
|
-
return
|
|
5514
|
+
return path23.resolve(context.configPathOverride);
|
|
5557
5515
|
}
|
|
5558
5516
|
const configuredHome = context.env.CODEX_HOME;
|
|
5559
|
-
const codexHome =
|
|
5560
|
-
typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome :
|
|
5517
|
+
const codexHome = path23.resolve(
|
|
5518
|
+
typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome : path23.join(context.homeDir, ".codex")
|
|
5561
5519
|
);
|
|
5562
|
-
return
|
|
5520
|
+
return path23.join(codexHome, "config.toml");
|
|
5563
5521
|
}
|
|
5564
5522
|
function readToml(snapshot) {
|
|
5565
5523
|
const failure = snapshotError2(snapshot);
|
|
@@ -5779,7 +5737,7 @@ var CODEX_OTEL_INSTALLER = Object.freeze({
|
|
|
5779
5737
|
});
|
|
5780
5738
|
|
|
5781
5739
|
// ../../packages/agent-targets/src/install/otel/gemini.ts
|
|
5782
|
-
import
|
|
5740
|
+
import path24 from "path";
|
|
5783
5741
|
var TARGET15 = agentTarget("gemini");
|
|
5784
5742
|
var TARGET_ID7 = TARGET15.id;
|
|
5785
5743
|
var DISPLAY_NAME7 = TARGET15.displayName;
|
|
@@ -5787,9 +5745,9 @@ var AUTHENTICATION3 = "path-token";
|
|
|
5787
5745
|
var GEMINI_OTEL_SOURCE_LIMITATION = "Gemini CLI has no documented OTLP header setting; FML uses an observer-local tokenized loopback path";
|
|
5788
5746
|
function configPath3(context) {
|
|
5789
5747
|
if (context.configPathOverride) {
|
|
5790
|
-
return
|
|
5748
|
+
return path24.resolve(context.configPathOverride);
|
|
5791
5749
|
}
|
|
5792
|
-
return
|
|
5750
|
+
return path24.join(geminiConfigDirectory(context), "settings.json");
|
|
5793
5751
|
}
|
|
5794
5752
|
function managedTelemetry(context) {
|
|
5795
5753
|
const destination = resolveDestination(context.observer);
|
|
@@ -5943,8 +5901,8 @@ var OTEL_INSTALLER_CAPABILITIES = Object.freeze([
|
|
|
5943
5901
|
]);
|
|
5944
5902
|
|
|
5945
5903
|
// src/commands/otel-config-state.ts
|
|
5946
|
-
import
|
|
5947
|
-
import
|
|
5904
|
+
import fs10 from "fs";
|
|
5905
|
+
import path25 from "path";
|
|
5948
5906
|
var OTEL_CONFIG_STATE_SCHEMA_VERSION = 1;
|
|
5949
5907
|
function emptyState2() {
|
|
5950
5908
|
return Object.freeze({
|
|
@@ -5958,12 +5916,12 @@ function invalidState2(statePath, reason) {
|
|
|
5958
5916
|
);
|
|
5959
5917
|
}
|
|
5960
5918
|
function enforceOwnerOnlyMode(statePath) {
|
|
5961
|
-
if (process.platform !== "win32")
|
|
5919
|
+
if (process.platform !== "win32") fs10.chmodSync(statePath, 384);
|
|
5962
5920
|
}
|
|
5963
5921
|
function readStateFile(statePath) {
|
|
5964
5922
|
let stat;
|
|
5965
5923
|
try {
|
|
5966
|
-
stat =
|
|
5924
|
+
stat = fs10.lstatSync(statePath);
|
|
5967
5925
|
} catch (error) {
|
|
5968
5926
|
if (error.code === "ENOENT") {
|
|
5969
5927
|
return { kind: "missing" };
|
|
@@ -5981,7 +5939,7 @@ function readStateFile(statePath) {
|
|
|
5981
5939
|
}
|
|
5982
5940
|
try {
|
|
5983
5941
|
enforceOwnerOnlyMode(statePath);
|
|
5984
|
-
return { kind: "file", contents:
|
|
5942
|
+
return { kind: "file", contents: fs10.readFileSync(statePath, "utf8") };
|
|
5985
5943
|
} catch (error) {
|
|
5986
5944
|
return {
|
|
5987
5945
|
kind: "invalid",
|
|
@@ -5990,7 +5948,7 @@ function readStateFile(statePath) {
|
|
|
5990
5948
|
}
|
|
5991
5949
|
}
|
|
5992
5950
|
function otelConfigStateEntryKey(targetId, configPath4) {
|
|
5993
|
-
const resolved =
|
|
5951
|
+
const resolved = path25.resolve(configPath4);
|
|
5994
5952
|
const pathKey = process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
5995
5953
|
return `${targetId}\0${pathKey}`;
|
|
5996
5954
|
}
|
|
@@ -6026,7 +5984,7 @@ function parseState2(source, statePath) {
|
|
|
6026
5984
|
if (typeof observerRecord.baseUrl !== "string" || observerRecord.baseUrl.length === 0 || typeof observerRecord.authToken !== "string" || observerRecord.authToken.length === 0) {
|
|
6027
5985
|
throw invalidState2(statePath, "contains an invalid observer destination");
|
|
6028
5986
|
}
|
|
6029
|
-
const resolvedPath =
|
|
5987
|
+
const resolvedPath = path25.resolve(entry.path);
|
|
6030
5988
|
const key = otelConfigStateEntryKey(entry.targetId, resolvedPath);
|
|
6031
5989
|
if (keys.has(key)) {
|
|
6032
5990
|
throw invalidState2(statePath, "contains duplicate entries");
|
|
@@ -6064,7 +6022,7 @@ function loadFmlOtelConfigState(statePath) {
|
|
|
6064
6022
|
function serializeState2(entries) {
|
|
6065
6023
|
const sorted = [...entries].map((entry) => ({
|
|
6066
6024
|
targetId: entry.targetId,
|
|
6067
|
-
path:
|
|
6025
|
+
path: path25.resolve(entry.path),
|
|
6068
6026
|
observer: {
|
|
6069
6027
|
baseUrl: entry.observer.baseUrl,
|
|
6070
6028
|
authToken: entry.observer.authToken
|
|
@@ -6101,7 +6059,7 @@ function isKnownOtelTargetId(targetId) {
|
|
|
6101
6059
|
}
|
|
6102
6060
|
|
|
6103
6061
|
// src/commands/otel-config.ts
|
|
6104
|
-
var DEFAULT_OTEL_CONFIG_STATE_PATH =
|
|
6062
|
+
var DEFAULT_OTEL_CONFIG_STATE_PATH = path26.join(
|
|
6105
6063
|
FML_DATA_DIR,
|
|
6106
6064
|
"otel-config.json"
|
|
6107
6065
|
);
|
|
@@ -6110,7 +6068,7 @@ function readLocalObserverOtelDestination(options) {
|
|
|
6110
6068
|
if (!authToken) return null;
|
|
6111
6069
|
try {
|
|
6112
6070
|
const parsed = JSON.parse(
|
|
6113
|
-
|
|
6071
|
+
fs11.readFileSync(options.endpointFile, "utf8")
|
|
6114
6072
|
);
|
|
6115
6073
|
const endpoint = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
6116
6074
|
const host = endpoint?.host;
|
|
@@ -6127,7 +6085,7 @@ function readLocalObserverOtelDestination(options) {
|
|
|
6127
6085
|
function readOtelFile(filePath) {
|
|
6128
6086
|
let stat;
|
|
6129
6087
|
try {
|
|
6130
|
-
stat =
|
|
6088
|
+
stat = fs11.lstatSync(filePath);
|
|
6131
6089
|
} catch (error) {
|
|
6132
6090
|
if (error.code === "ENOENT") {
|
|
6133
6091
|
return { path: filePath, kind: "missing" };
|
|
@@ -6156,7 +6114,7 @@ function readOtelFile(filePath) {
|
|
|
6156
6114
|
return {
|
|
6157
6115
|
path: filePath,
|
|
6158
6116
|
kind: "file",
|
|
6159
|
-
contents:
|
|
6117
|
+
contents: fs11.readFileSync(filePath, "utf8")
|
|
6160
6118
|
};
|
|
6161
6119
|
} catch (error) {
|
|
6162
6120
|
return {
|
|
@@ -6178,7 +6136,7 @@ function assertMutationPrecondition2(mutation) {
|
|
|
6178
6136
|
throw new Error(`configuration changed while planning ${mutation.path}`);
|
|
6179
6137
|
}
|
|
6180
6138
|
function applyMutation2(mutation) {
|
|
6181
|
-
if (mutation.after === null)
|
|
6139
|
+
if (mutation.after === null) fs11.rmSync(mutation.path);
|
|
6182
6140
|
else writeTextFileAtomic(mutation.path, mutation.after);
|
|
6183
6141
|
}
|
|
6184
6142
|
function enforceOwnerOnlyConfigPermissions(filePath) {
|
|
@@ -6191,7 +6149,7 @@ function enforceOwnerOnlyConfigPermissions(filePath) {
|
|
|
6191
6149
|
);
|
|
6192
6150
|
}
|
|
6193
6151
|
try {
|
|
6194
|
-
|
|
6152
|
+
fs11.chmodSync(filePath, 384);
|
|
6195
6153
|
} catch (error) {
|
|
6196
6154
|
const detail = error instanceof Error ? error.message : String(error);
|
|
6197
6155
|
throw new Error(
|
|
@@ -6286,7 +6244,7 @@ function plannerContext3(observer, options, configPathOverride, configOwnershipR
|
|
|
6286
6244
|
observer,
|
|
6287
6245
|
homeDir: options.homeDir ?? os6.homedir(),
|
|
6288
6246
|
env: options.env ?? process.env,
|
|
6289
|
-
...configPathOverride ? { configPathOverride:
|
|
6247
|
+
...configPathOverride ? { configPathOverride: path26.resolve(configPathOverride) } : {},
|
|
6290
6248
|
...configOwnershipRecorded ? { configOwnershipRecorded: true } : {},
|
|
6291
6249
|
readFile: readOtelFile
|
|
6292
6250
|
};
|
|
@@ -6329,7 +6287,7 @@ function commitStateEntry(state, key, next) {
|
|
|
6329
6287
|
function stateEntry(plan, observer) {
|
|
6330
6288
|
return Object.freeze({
|
|
6331
6289
|
targetId: plan.targetId,
|
|
6332
|
-
path:
|
|
6290
|
+
path: path26.resolve(plan.configPath),
|
|
6333
6291
|
observer: Object.freeze({
|
|
6334
6292
|
baseUrl: observer.baseUrl,
|
|
6335
6293
|
authToken: observer.authToken
|
|
@@ -6887,8 +6845,8 @@ async function canOpenBrowser() {
|
|
|
6887
6845
|
if (process.env.CODESPACES) return false;
|
|
6888
6846
|
if (process.env.REMOTE_CONTAINERS) return false;
|
|
6889
6847
|
try {
|
|
6890
|
-
const
|
|
6891
|
-
if (
|
|
6848
|
+
const fs13 = await import("fs");
|
|
6849
|
+
if (fs13.existsSync("/.dockerenv")) return false;
|
|
6892
6850
|
} catch {
|
|
6893
6851
|
}
|
|
6894
6852
|
return true;
|
|
@@ -7155,7 +7113,7 @@ async function deviceLogin(options) {
|
|
|
7155
7113
|
}
|
|
7156
7114
|
|
|
7157
7115
|
// src/sync/client.ts
|
|
7158
|
-
import { execSync
|
|
7116
|
+
import { execSync } from "child_process";
|
|
7159
7117
|
var TOKEN_TTL_MS = 5 * 60 * 1e3;
|
|
7160
7118
|
var cachedGitHubToken = null;
|
|
7161
7119
|
function resolveGitHubToken() {
|
|
@@ -7171,7 +7129,7 @@ function resolveGitHubToken() {
|
|
|
7171
7129
|
return envToken;
|
|
7172
7130
|
}
|
|
7173
7131
|
try {
|
|
7174
|
-
const token =
|
|
7132
|
+
const token = execSync("gh auth token", {
|
|
7175
7133
|
encoding: "utf-8",
|
|
7176
7134
|
timeout: 5e3
|
|
7177
7135
|
}).trim();
|
|
@@ -7370,7 +7328,7 @@ async function runInteractiveLogin(opts = {}) {
|
|
|
7370
7328
|
const envName = environment.envName;
|
|
7371
7329
|
const existingToken = await getValidToken({ env: envName });
|
|
7372
7330
|
if (existingToken) {
|
|
7373
|
-
const { readTokens: readTokens2 } = await import("./token-store-
|
|
7331
|
+
const { readTokens: readTokens2 } = await import("./token-store-QYXUL4NG.js");
|
|
7374
7332
|
const stored = readTokens2(envName);
|
|
7375
7333
|
if (stored?.tokenType === "service") {
|
|
7376
7334
|
const label = stored.user.id === SERVICE_TOKEN_LOGIN_USER_ID ? "a service token" : `${stored.user.name} (${stored.user.email})`;
|
|
@@ -7427,7 +7385,7 @@ async function runStep(name, operation) {
|
|
|
7427
7385
|
throw new Error(`FML setup could not complete ${name}.`);
|
|
7428
7386
|
}
|
|
7429
7387
|
}
|
|
7430
|
-
async function handleSetup(dependencies = defaultDependencies) {
|
|
7388
|
+
async function handleSetup(dependencies = defaultDependencies, options = {}) {
|
|
7431
7389
|
if (process.exitCode) {
|
|
7432
7390
|
throw new Error("FML setup cannot run after an earlier command failure.");
|
|
7433
7391
|
}
|
|
@@ -7436,6 +7394,8 @@ async function handleSetup(dependencies = defaultDependencies) {
|
|
|
7436
7394
|
const token = await dependencies.getActiveToken();
|
|
7437
7395
|
if (token) {
|
|
7438
7396
|
console.log("Already signed in.");
|
|
7397
|
+
} else if (options.nonInteractive) {
|
|
7398
|
+
console.log("Not signed in; skipping login (non-interactive).");
|
|
7439
7399
|
} else {
|
|
7440
7400
|
await runStep("login", dependencies.login);
|
|
7441
7401
|
}
|
|
@@ -7447,9 +7407,9 @@ async function handleSetup(dependencies = defaultDependencies) {
|
|
|
7447
7407
|
}
|
|
7448
7408
|
|
|
7449
7409
|
// src/commands/uninstall.ts
|
|
7450
|
-
import
|
|
7410
|
+
import fs12 from "fs";
|
|
7451
7411
|
import os7 from "os";
|
|
7452
|
-
import
|
|
7412
|
+
import path27 from "path";
|
|
7453
7413
|
import readline from "readline/promises";
|
|
7454
7414
|
var PURGE_WARNING = "This deletes FML credentials for ALL environments, logs, sync state, and every pending best-effort OTLP envelope.";
|
|
7455
7415
|
function tryDisableHookCapture() {
|
|
@@ -7465,19 +7425,19 @@ function tryDisableHookCapture() {
|
|
|
7465
7425
|
}
|
|
7466
7426
|
}
|
|
7467
7427
|
function resolvePreservedPaths(preservedFile) {
|
|
7468
|
-
const logicalPath =
|
|
7428
|
+
const logicalPath = path27.resolve(preservedFile);
|
|
7469
7429
|
try {
|
|
7470
|
-
const canonicalPath =
|
|
7430
|
+
const canonicalPath = fs12.realpathSync(preservedFile);
|
|
7471
7431
|
return pathsAreSame(canonicalPath, logicalPath) ? [logicalPath] : [logicalPath, canonicalPath];
|
|
7472
7432
|
} catch {
|
|
7473
7433
|
return [logicalPath];
|
|
7474
7434
|
}
|
|
7475
7435
|
}
|
|
7476
7436
|
function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot = false) {
|
|
7477
|
-
const resolvedDirectory =
|
|
7437
|
+
const resolvedDirectory = path27.resolve(directory);
|
|
7478
7438
|
let directoryStats;
|
|
7479
7439
|
try {
|
|
7480
|
-
directoryStats =
|
|
7440
|
+
directoryStats = fs12.lstatSync(directory);
|
|
7481
7441
|
} catch (error) {
|
|
7482
7442
|
if (error.code === "ENOENT") return true;
|
|
7483
7443
|
throw error;
|
|
@@ -7488,14 +7448,14 @@ function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot
|
|
|
7488
7448
|
(preservedPath) => pathContains(resolvedDirectory, preservedPath)
|
|
7489
7449
|
);
|
|
7490
7450
|
if (!containsLogicalMarker) {
|
|
7491
|
-
|
|
7451
|
+
fs12.rmSync(directory, { force: true });
|
|
7492
7452
|
return true;
|
|
7493
7453
|
}
|
|
7494
7454
|
return false;
|
|
7495
7455
|
}
|
|
7496
7456
|
const directoryPaths = [resolvedDirectory];
|
|
7497
7457
|
try {
|
|
7498
|
-
const canonicalDirectory =
|
|
7458
|
+
const canonicalDirectory = fs12.realpathSync(directory);
|
|
7499
7459
|
if (!pathsAreSame(canonicalDirectory, resolvedDirectory)) {
|
|
7500
7460
|
directoryPaths.push(canonicalDirectory);
|
|
7501
7461
|
}
|
|
@@ -7507,26 +7467,26 @@ function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot
|
|
|
7507
7467
|
)
|
|
7508
7468
|
);
|
|
7509
7469
|
if (!containsPreservedPath) {
|
|
7510
|
-
|
|
7470
|
+
fs12.rmSync(directory, { recursive: true, force: true });
|
|
7511
7471
|
return true;
|
|
7512
7472
|
}
|
|
7513
7473
|
const isPreservedPath = directoryPaths.some(
|
|
7514
7474
|
(directoryPath) => preservedPaths.some(
|
|
7515
|
-
(preservedPath) => pathsAreSame(directoryPath,
|
|
7475
|
+
(preservedPath) => pathsAreSame(directoryPath, path27.resolve(preservedPath))
|
|
7516
7476
|
)
|
|
7517
7477
|
);
|
|
7518
7478
|
if (isPreservedPath) return true;
|
|
7519
7479
|
if (!directoryStats.isDirectory()) return false;
|
|
7520
7480
|
let entries;
|
|
7521
7481
|
try {
|
|
7522
|
-
entries =
|
|
7482
|
+
entries = fs12.readdirSync(directory);
|
|
7523
7483
|
} catch (error) {
|
|
7524
7484
|
if (error.code === "ENOENT") return true;
|
|
7525
7485
|
throw error;
|
|
7526
7486
|
}
|
|
7527
7487
|
let complete = true;
|
|
7528
7488
|
for (const entry of entries) {
|
|
7529
|
-
const entryPath =
|
|
7489
|
+
const entryPath = path27.join(directory, entry);
|
|
7530
7490
|
if (!purgeDirectoryPreservingPaths(entryPath, preservedPaths, false)) {
|
|
7531
7491
|
complete = false;
|
|
7532
7492
|
}
|
|
@@ -7545,13 +7505,13 @@ function purgeDirectoryPreservingFiles(directory, preservedFiles) {
|
|
|
7545
7505
|
}
|
|
7546
7506
|
function finishCustomRootPurge(directory) {
|
|
7547
7507
|
const marker = managedDirectoryMarker(directory);
|
|
7548
|
-
|
|
7508
|
+
fs12.rmSync(marker, { force: true });
|
|
7549
7509
|
try {
|
|
7550
|
-
|
|
7510
|
+
fs12.rmdirSync(directory);
|
|
7551
7511
|
} catch (error) {
|
|
7552
7512
|
if (error.code === "ENOENT") return;
|
|
7553
7513
|
try {
|
|
7554
|
-
|
|
7514
|
+
fs12.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
|
|
7555
7515
|
encoding: "utf8",
|
|
7556
7516
|
flag: "wx",
|
|
7557
7517
|
mode: 384
|
|
@@ -7649,7 +7609,7 @@ async function handleUninstall(opts) {
|
|
|
7649
7609
|
return;
|
|
7650
7610
|
}
|
|
7651
7611
|
for (const root of purgeRoots) {
|
|
7652
|
-
if (!
|
|
7612
|
+
if (!fs12.existsSync(root.directory) && pathContains(root.directory, FML_OBSERVER_DIR)) {
|
|
7653
7613
|
prepareManagedDirectory(root);
|
|
7654
7614
|
}
|
|
7655
7615
|
}
|
|
@@ -7773,7 +7733,7 @@ async function handleUninstall(opts) {
|
|
|
7773
7733
|
)
|
|
7774
7734
|
);
|
|
7775
7735
|
}
|
|
7776
|
-
|
|
7736
|
+
fs12.rmSync(paths.pluginCacheDir, { recursive: true, force: true });
|
|
7777
7737
|
const reportIntegrationWarning = (message) => {
|
|
7778
7738
|
integrationsRemoved = false;
|
|
7779
7739
|
console.warn(message.replace(/^warn:/u, "Warning:"));
|
|
@@ -7892,181 +7852,6 @@ async function handleUninstall(opts) {
|
|
|
7892
7852
|
}
|
|
7893
7853
|
}
|
|
7894
7854
|
|
|
7895
|
-
// src/commands/update.ts
|
|
7896
|
-
var SEMVER_PATTERN = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
7897
|
-
var PACKAGE_NAME = "@fml-inc/fml";
|
|
7898
|
-
var UPDATE_TIMEOUT_MS = 12e4;
|
|
7899
|
-
var SETUP_TIMEOUT_MS = 3e5;
|
|
7900
|
-
function getCurrentVersion() {
|
|
7901
|
-
return true ? "0.8.3+499a546c" : "unknown";
|
|
7902
|
-
}
|
|
7903
|
-
function parseVersion(version) {
|
|
7904
|
-
const match = SEMVER_PATTERN.exec(version);
|
|
7905
|
-
if (!match) return null;
|
|
7906
|
-
return {
|
|
7907
|
-
major: match[1],
|
|
7908
|
-
minor: match[2],
|
|
7909
|
-
patch: match[3],
|
|
7910
|
-
prerelease: match[4]?.split(".") ?? []
|
|
7911
|
-
};
|
|
7912
|
-
}
|
|
7913
|
-
function compareNumericIdentifiers(left, right) {
|
|
7914
|
-
if (left.length !== right.length) return left.length - right.length;
|
|
7915
|
-
if (left === right) return 0;
|
|
7916
|
-
return left < right ? -1 : 1;
|
|
7917
|
-
}
|
|
7918
|
-
function compareIdentifiers(left, right) {
|
|
7919
|
-
const leftIsNumeric = /^[0-9]+$/u.test(left);
|
|
7920
|
-
const rightIsNumeric = /^[0-9]+$/u.test(right);
|
|
7921
|
-
if (leftIsNumeric && rightIsNumeric) {
|
|
7922
|
-
return compareNumericIdentifiers(left, right);
|
|
7923
|
-
}
|
|
7924
|
-
if (leftIsNumeric) return -1;
|
|
7925
|
-
if (rightIsNumeric) return 1;
|
|
7926
|
-
if (left === right) return 0;
|
|
7927
|
-
return left < right ? -1 : 1;
|
|
7928
|
-
}
|
|
7929
|
-
function compareVersions(left, right) {
|
|
7930
|
-
const leftVersion = parseVersion(left);
|
|
7931
|
-
const rightVersion = parseVersion(right);
|
|
7932
|
-
if (!leftVersion || !rightVersion) {
|
|
7933
|
-
throw new Error("FML update requires valid semantic versions.");
|
|
7934
|
-
}
|
|
7935
|
-
for (const part of ["major", "minor", "patch"]) {
|
|
7936
|
-
const difference = compareNumericIdentifiers(
|
|
7937
|
-
leftVersion[part],
|
|
7938
|
-
rightVersion[part]
|
|
7939
|
-
);
|
|
7940
|
-
if (difference) return difference;
|
|
7941
|
-
}
|
|
7942
|
-
if (!leftVersion.prerelease.length && !rightVersion.prerelease.length) {
|
|
7943
|
-
return 0;
|
|
7944
|
-
}
|
|
7945
|
-
if (!leftVersion.prerelease.length) return 1;
|
|
7946
|
-
if (!rightVersion.prerelease.length) return -1;
|
|
7947
|
-
const length = Math.max(
|
|
7948
|
-
leftVersion.prerelease.length,
|
|
7949
|
-
rightVersion.prerelease.length
|
|
7950
|
-
);
|
|
7951
|
-
for (let index = 0; index < length; index += 1) {
|
|
7952
|
-
const leftIdentifier = leftVersion.prerelease[index];
|
|
7953
|
-
const rightIdentifier = rightVersion.prerelease[index];
|
|
7954
|
-
if (leftIdentifier === void 0) return -1;
|
|
7955
|
-
if (rightIdentifier === void 0) return 1;
|
|
7956
|
-
const difference = compareIdentifiers(leftIdentifier, rightIdentifier);
|
|
7957
|
-
if (difference) return difference;
|
|
7958
|
-
}
|
|
7959
|
-
return 0;
|
|
7960
|
-
}
|
|
7961
|
-
function resolveUpdateChannel(version) {
|
|
7962
|
-
const match = SEMVER_PATTERN.exec(version);
|
|
7963
|
-
if (!match) return "latest";
|
|
7964
|
-
const prerelease = match[4];
|
|
7965
|
-
if (!prerelease) return "latest";
|
|
7966
|
-
return prerelease.split(".").every((identifier) => {
|
|
7967
|
-
return !(identifier.length > 1 && identifier.startsWith("0") && /^[0-9]+$/u.test(identifier));
|
|
7968
|
-
}) ? "next" : "latest";
|
|
7969
|
-
}
|
|
7970
|
-
function resolveUpdateTarget(version) {
|
|
7971
|
-
return `${PACKAGE_NAME}@${resolveUpdateChannel(version)}`;
|
|
7972
|
-
}
|
|
7973
|
-
function createUpdateEnvironment(env) {
|
|
7974
|
-
const updateEnv = { ...env };
|
|
7975
|
-
for (const key of Object.keys(updateEnv)) {
|
|
7976
|
-
if (key.toLowerCase() === "npm_config_registry") {
|
|
7977
|
-
delete updateEnv[key];
|
|
7978
|
-
}
|
|
7979
|
-
}
|
|
7980
|
-
return updateEnv;
|
|
7981
|
-
}
|
|
7982
|
-
function parseAvailableVersion(output) {
|
|
7983
|
-
let response;
|
|
7984
|
-
try {
|
|
7985
|
-
response = JSON.parse(output);
|
|
7986
|
-
} catch {
|
|
7987
|
-
throw new Error("Could not read the available FML version from npm.");
|
|
7988
|
-
}
|
|
7989
|
-
const version = Array.isArray(response) && response.length === 1 ? response[0] : response;
|
|
7990
|
-
if (typeof version !== "string" || !parseVersion(version)) {
|
|
7991
|
-
throw new Error("Could not read the available FML version from npm.");
|
|
7992
|
-
}
|
|
7993
|
-
return version;
|
|
7994
|
-
}
|
|
7995
|
-
function formatUpdateError(err) {
|
|
7996
|
-
if (!(err instanceof Error)) return String(err);
|
|
7997
|
-
const stderr = err.stderr;
|
|
7998
|
-
if (typeof stderr === "string") return stderr;
|
|
7999
|
-
if (Buffer.isBuffer(stderr)) return stderr.toString();
|
|
8000
|
-
return err.message;
|
|
8001
|
-
}
|
|
8002
|
-
async function handleUpdate(overrides = {}) {
|
|
8003
|
-
const dependencies = {
|
|
8004
|
-
currentVersion: getCurrentVersion(),
|
|
8005
|
-
env: process.env,
|
|
8006
|
-
resolveBin,
|
|
8007
|
-
execBinSync,
|
|
8008
|
-
captureException: Sentry.captureException,
|
|
8009
|
-
log: console.log,
|
|
8010
|
-
error: console.error,
|
|
8011
|
-
exit: process.exit,
|
|
8012
|
-
...overrides
|
|
8013
|
-
};
|
|
8014
|
-
const channel = resolveUpdateChannel(dependencies.currentVersion);
|
|
8015
|
-
const target2 = resolveUpdateTarget(dependencies.currentVersion);
|
|
8016
|
-
dependencies.log(`Current version: ${dependencies.currentVersion}`);
|
|
8017
|
-
try {
|
|
8018
|
-
const npm = dependencies.resolveBin("npm");
|
|
8019
|
-
if (!npm) throw new Error("npm was not found on PATH");
|
|
8020
|
-
const updateEnv = createUpdateEnvironment(dependencies.env);
|
|
8021
|
-
const availableVersion = parseAvailableVersion(
|
|
8022
|
-
dependencies.execBinSync(npm, ["view", target2, "version", "--json"], {
|
|
8023
|
-
timeout: UPDATE_TIMEOUT_MS,
|
|
8024
|
-
env: updateEnv
|
|
8025
|
-
})
|
|
8026
|
-
);
|
|
8027
|
-
if (compareVersions(availableVersion, dependencies.currentVersion) <= 0) {
|
|
8028
|
-
dependencies.log(
|
|
8029
|
-
`FML is already up to date (${dependencies.currentVersion}).`
|
|
8030
|
-
);
|
|
8031
|
-
return;
|
|
8032
|
-
}
|
|
8033
|
-
dependencies.log(
|
|
8034
|
-
`Updating FML from ${dependencies.currentVersion} to ${availableVersion} on the ${channel} channel...
|
|
8035
|
-
`
|
|
8036
|
-
);
|
|
8037
|
-
dependencies.execBinSync(
|
|
8038
|
-
npm,
|
|
8039
|
-
["install", "--global", `${PACKAGE_NAME}@${availableVersion}`],
|
|
8040
|
-
{ timeout: UPDATE_TIMEOUT_MS, env: updateEnv }
|
|
8041
|
-
);
|
|
8042
|
-
dependencies.log(
|
|
8043
|
-
`
|
|
8044
|
-
FML updated from ${dependencies.currentVersion} to ${availableVersion}. Refreshing setup...`
|
|
8045
|
-
);
|
|
8046
|
-
try {
|
|
8047
|
-
const fml = dependencies.resolveBin("fml");
|
|
8048
|
-
if (!fml) throw new Error("Updated FML was not found on PATH");
|
|
8049
|
-
dependencies.execBinSync(fml, ["setup"], {
|
|
8050
|
-
timeout: SETUP_TIMEOUT_MS,
|
|
8051
|
-
stdio: "inherit"
|
|
8052
|
-
});
|
|
8053
|
-
dependencies.log("FML setup complete.");
|
|
8054
|
-
} catch (err) {
|
|
8055
|
-
dependencies.captureException(err);
|
|
8056
|
-
dependencies.error(
|
|
8057
|
-
"FML updated, but setup failed:",
|
|
8058
|
-
formatUpdateError(err)
|
|
8059
|
-
);
|
|
8060
|
-
dependencies.error("Run `fml setup` to finish refreshing FML.");
|
|
8061
|
-
dependencies.exit(1);
|
|
8062
|
-
}
|
|
8063
|
-
} catch (err) {
|
|
8064
|
-
dependencies.captureException(err);
|
|
8065
|
-
dependencies.error("Update failed:", formatUpdateError(err));
|
|
8066
|
-
dependencies.exit(1);
|
|
8067
|
-
}
|
|
8068
|
-
}
|
|
8069
|
-
|
|
8070
7855
|
// src/commands/logout.ts
|
|
8071
7856
|
async function handleLogout() {
|
|
8072
7857
|
const { name } = getActiveEnv();
|
|
@@ -9036,8 +8821,8 @@ async function handleConfigDetail(opts) {
|
|
|
9036
8821
|
|
|
9037
8822
|
// src/commands/tools.ts
|
|
9038
8823
|
import { readFileSync } from "fs";
|
|
9039
|
-
import
|
|
9040
|
-
var pluginVersion = true ? "0.8.
|
|
8824
|
+
import path28 from "path";
|
|
8825
|
+
var pluginVersion = true ? "0.8.4-rc.2+f282df41" : void 0;
|
|
9041
8826
|
async function getApi() {
|
|
9042
8827
|
const api = await getAuthenticatedClient();
|
|
9043
8828
|
if (!api) {
|
|
@@ -9144,7 +8929,7 @@ async function handleToolsCall(name, opts) {
|
|
|
9144
8929
|
}
|
|
9145
8930
|
const raw = opts.file ? (() => {
|
|
9146
8931
|
try {
|
|
9147
|
-
return readFileSync(
|
|
8932
|
+
return readFileSync(path28.resolve(opts.file), "utf8");
|
|
9148
8933
|
} catch (err) {
|
|
9149
8934
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9150
8935
|
console.error(`Could not read args file: ${msg}`);
|
|
@@ -9194,7 +8979,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
9194
8979
|
printBanner();
|
|
9195
8980
|
}
|
|
9196
8981
|
var program = new Command().name("fml").description("FML CLI and agent tools").version(
|
|
9197
|
-
true ? "0.8.
|
|
8982
|
+
true ? "0.8.4-rc.2+f282df41" : "dev"
|
|
9198
8983
|
);
|
|
9199
8984
|
function formatCommandInventory(cmd, prefix = "") {
|
|
9200
8985
|
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
|
|
@@ -9223,12 +9008,26 @@ tools.command("call").description("Invoke a backend tool by name with JSON args"
|
|
|
9223
9008
|
program.command("mcp-server", { hidden: true }).description("Run the FML MCP server on stdio").action(async () => {
|
|
9224
9009
|
await import("./mcp/server.js");
|
|
9225
9010
|
});
|
|
9226
|
-
program.command("setup").description("Install integrations, sign in if needed, and start FML").
|
|
9011
|
+
program.command("setup").description("Install integrations, sign in if needed, and start FML").addOption(
|
|
9012
|
+
new Option(
|
|
9013
|
+
"--non-interactive",
|
|
9014
|
+
"Skip interactive login (internal)"
|
|
9015
|
+
).hideHelp()
|
|
9016
|
+
).action(
|
|
9017
|
+
(opts) => handleSetup(void 0, { nonInteractive: Boolean(opts.nonInteractive) })
|
|
9018
|
+
);
|
|
9227
9019
|
program.command("install").description("Register FML agent integrations and the MCP server").action(() => handleInstall());
|
|
9228
9020
|
program.command("uninstall").description("Remove FML agent integrations and optionally local data").option("--purge", "Also remove all data, logs, and auth tokens").option("-y, --yes", "Skip the purge confirmation prompt").action(
|
|
9229
9021
|
(opts) => handleUninstall({ purge: opts.purge, assumeYes: opts.yes })
|
|
9230
9022
|
);
|
|
9231
|
-
program.command("update").description("Update fml when a newer release is available and refresh setup").
|
|
9023
|
+
program.command("update").description("Update fml when a newer release is available and refresh setup").addOption(
|
|
9024
|
+
new Option(
|
|
9025
|
+
"--non-interactive",
|
|
9026
|
+
"Skip interactive prompts (internal)"
|
|
9027
|
+
).hideHelp()
|
|
9028
|
+
).action(
|
|
9029
|
+
(opts) => handleUpdate({ nonInteractive: Boolean(opts.nonInteractive) })
|
|
9030
|
+
);
|
|
9232
9031
|
program.command("login").description("Sign in to your FML account").option("--device", "Use device authorization flow (no browser needed)").option(
|
|
9233
9032
|
"--service-token",
|
|
9234
9033
|
"Sign in with an org service refresh token (prompts for fml_srt_*)"
|