@fml-inc/fml 0.8.4-rc.1 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -2,21 +2,24 @@
2
2
  import {
3
3
  createFmlClient,
4
4
  getAuthenticatedClient
5
- } from "./chunk-26RJC76L.js";
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
- } from "./chunk-3WDAKM5B.js";
14
+ removeObserverStateIfOwned,
15
+ resolveBin
16
+ } from "./chunk-GSFUCFSC.js";
14
17
  import {
15
18
  readJsonFile,
16
19
  setHookCaptureDisabled,
17
20
  writeJsonFile,
18
21
  writeTextFileAtomic
19
- } from "./chunk-UZG65JUB.js";
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-F4A2POJX.js";
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-4LJVPXII.js";
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-TNJVAET3.js";
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.4-rc.1+bb22ea9f" : "dev";
130
+ return true ? "0.8.4+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 fs10 from "fs";
1068
+ import fs9 from "fs";
1066
1069
  import os5 from "os";
1067
- import path22 from "path";
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 fs5 from "fs";
1457
+ import fs4 from "fs";
1500
1458
  import os from "os";
1501
- import path6 from "path";
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 path6.win32;
1466
+ return path5.win32;
1509
1467
  }
1510
- return path6;
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 path6.join(directory, FML_MANAGED_DIRECTORY_MARKER);
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 = fs5.lstatSync(marker);
1595
- return stats.isFile() && fs5.readFileSync(marker, "utf8") === FML_MANAGED_DIRECTORY_MARKER_CONTENT;
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 = fs5.lstatSync(marker);
1561
+ const stats = fs4.lstatSync(marker);
1604
1562
  if (!stats.isFile() || ownershipStatus(stats, platform) !== "owned") {
1605
1563
  return false;
1606
1564
  }
1607
- return fs5.readFileSync(marker, "utf8") === FML_MANAGED_DIRECTORY_MARKER_CONTENT;
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
- fs5.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
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 = fs5.lstatSync(root.directory);
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
- fs5.mkdirSync(path6.dirname(root.directory), {
1604
+ fs4.mkdirSync(path5.dirname(root.directory), {
1647
1605
  recursive: true,
1648
1606
  mode: 448
1649
1607
  });
1650
1608
  try {
1651
- fs5.mkdirSync(root.directory, { mode: 448 });
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 = fs5.lstatSync(root.directory);
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 ?? fs5.lstatSync(root.directory);
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 = fs5.readdirSync(root.directory).length === 0;
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 (fs5.lstatSync(current).isSymbolicLink()) return true;
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 = fs5.lstatSync(root.directory);
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 fs6 from "fs";
1781
+ import fs5 from "fs";
1824
1782
  import os2 from "os";
1825
- import path11 from "path";
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 path8 from "path";
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 path30 = [];
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 path30;
1806
+ if (!record) return path29;
1849
1807
  const keys = Object.keys(record);
1850
- if (keys.length === 0) return path30;
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
- path30.push(key);
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(path30, prefix) {
1937
- return prefix.every((part, index) => path30[index] === part);
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, path30) {
1921
+ function updatedValueAtPath(updated, path29) {
1964
1922
  let current = updated;
1965
- for (const part of path30) {
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
- (path30) => pathsEqual(path30, update.path) || startsWithPath(update.path, path30)
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 path30 = paths[index];
1985
- if (path30 && startsWithPath(path30, update.path)) paths.splice(index, 1);
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(path30, value) {
1949
+ function valueDocument(path29, value) {
1992
1950
  let nested = value;
1993
- for (let index = path30.length - 1; index >= 0; index -= 1) {
1994
- const part = path30[index];
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, path30, value) {
2014
- const key = path30.at(-1);
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 = path30.slice(0, -1);
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(path30, value)));
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 path30 of paths) {
2040
- const next = updatedValueAtPath(updated, path30);
1997
+ for (const path29 of paths) {
1998
+ const next = updatedValueAtPath(updated, path29);
2041
1999
  if (!next.exists) continue;
2042
- result = insertUpdatedValue(result, path30, next.value);
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 path7 from "path";
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 = path7.join(pluginRoot, "bin", "hook-handler");
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 = path8.resolve(
2235
- trimmedHome.length > 0 ? trimmedHome : path8.join(context.homeDir, ".codex")
2192
+ const dir = path7.resolve(
2193
+ trimmedHome.length > 0 ? trimmedHome : path7.join(context.homeDir, ".codex")
2236
2194
  );
2237
- const configPath4 = path8.join(dir, "config.toml");
2238
- const hooksPath = path8.join(dir, "hooks.json");
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((path30) => ({ path: path30 }));
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 path9 from "path";
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, path30) {
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
- [...path30, currentIndex + offset]
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: [...path30, currentIndex + pairedCount],
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: [...path30, currentIndex + offset],
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, path30 = []) {
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, path30);
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: path30, value: updated }];
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
- ...path30,
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 path9.join(geminiConfigDirectory(context), "settings.json");
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 path10 from "path";
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 ? path10.resolve(configuredHome) : path10.join(context.homeDir, ".grok");
3522
- return path10.join(grokHome, "hooks", "fml.json");
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 = path11.join(
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 = fs6.lstatSync(filePath);
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: fs6.readFileSync(filePath, "utf8")
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 fs6.realpathSync(filePath);
3647
+ return fs5.realpathSync(filePath);
3690
3648
  } catch {
3691
3649
  const missingSegments = [];
3692
3650
  let ancestor = filePath;
3693
3651
  while (true) {
3694
- const parent = path11.dirname(ancestor);
3652
+ const parent = path10.dirname(ancestor);
3695
3653
  if (parent === ancestor) return filePath;
3696
- missingSegments.unshift(path11.basename(ancestor));
3654
+ missingSegments.unshift(path10.basename(ancestor));
3697
3655
  ancestor = parent;
3698
3656
  try {
3699
- return path11.join(fs6.realpathSync(ancestor), ...missingSegments);
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
- fs6.rmSync(mutation.path);
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
- fs6.rmSync(inverse.path);
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 ? path11.join(options.homeDir, ".fml", "codex-hook-install.json") : DEFAULT_CODEX_HOOK_OWNERSHIP_STATE_PATH);
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 fs7 from "fs";
3788
+ import fs6 from "fs";
3831
3789
  function existingPathKind(linkPath) {
3832
3790
  try {
3833
- return fs7.lstatSync(linkPath).isSymbolicLink() ? "symlink" : "other";
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") fs7.unlinkSync(linkPath);
3843
- fs7.symlinkSync(targetPath, linkPath, type);
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
- fs7.unlinkSync(linkPath);
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 path13 from "path";
3903
+ import path12 from "path";
3946
3904
 
3947
3905
  // ../../packages/agent-targets/src/mcp/capability.ts
3948
- import path12 from "path";
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
- path12.join(context.packageRoot, "bin", "mcp-server")
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 path13.join(
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 path13.join(
4144
- env.APPDATA ?? path13.join(homeDir, "AppData", "Roaming"),
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 path13.join(
4150
- env.XDG_CONFIG_HOME ?? path13.join(homeDir, ".config"),
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 path14 from "path";
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 ? path14.resolve(configuredHome) : path14.join(homeDir, ".codex");
4169
- return path14.join(codexHome, "config.toml");
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 path15 from "path";
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) => path15.join(geminiConfigDirectory(context), "settings.json"),
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 path16 from "path";
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 ? path16.resolve(configuredHome) : path16.join(homeDir, ".grok");
4197
- return path16.join(grokHome, "config.toml");
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 fs8 from "fs";
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 = fs8.lstatSync(filePath);
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: fs8.readFileSync(filePath, "utf8")
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
- fs8.rmSync(mutation.path, { force: true });
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
- fs8.rmSync(mutation.path, { force: true });
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 fs9 from "fs";
4345
+ import fs8 from "fs";
4388
4346
  import os4 from "os";
4389
- import path21 from "path";
4347
+ import path20 from "path";
4390
4348
 
4391
4349
  // ../../packages/agent-targets/src/install/surfaces/capability.ts
4392
- import path17 from "path";
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: path17.join(context.packageRoot, ...SOURCE_PATH_SEGMENTS),
4406
- destinationPath: path17.join(
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 path18 from "path";
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 }) => path18.join(homeDir, ".agents")
4395
+ destinationRoot: ({ homeDir }) => path17.join(homeDir, ".agents")
4438
4396
  });
4439
4397
 
4440
4398
  // ../../packages/agent-targets/src/install/surfaces/targets/gemini.ts
4441
- import path19 from "path";
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 ? path19.resolve(configuredHome) : homeDir;
4452
- return path19.join(homeRoot, ".agents");
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 path20 from "path";
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 }) => path20.join(homeDir, ".agents")
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 = path21.join(FML_DATA_DIR, "agent-skills.json");
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 = fs9.lstatSync(filePath);
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 = fs9.readFileSync(filePath, "utf8");
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: path21.resolve(entry.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: path21.resolve(entry.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 = path21.resolve(resolved.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 = path21.dirname(destinationPath);
4644
+ const skillDir = path20.dirname(destinationPath);
4687
4645
  let stat;
4688
4646
  try {
4689
- stat = fs9.lstatSync(skillDir);
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 || fs9.readdirSync(skillDir).length === 0) return null;
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
- fs9.rmSync(destinationPath, { force: true });
4672
+ fs8.rmSync(destinationPath, { force: true });
4715
4673
  try {
4716
- fs9.rmdirSync(path21.dirname(destinationPath));
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) => [path21.resolve(entry.path), 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 = path21.resolve(group.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 = path21.join(
4850
- path21.dirname(args.destinationPath),
4851
- `.${path21.basename(args.destinationPath)}.${process.pid}.${randomUUID3()}.bak`
4807
+ const backupPath = path20.join(
4808
+ path20.dirname(args.destinationPath),
4809
+ `.${path20.basename(args.destinationPath)}.${process.pid}.${randomUUID3()}.bak`
4852
4810
  );
4853
- fs9.renameSync(args.destinationPath, backupPath);
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
- fs9.renameSync(backupPath, args.destinationPath);
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
- fs9.rmSync(backupPath, { force: true });
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
- fs9.rmdirSync(path21.dirname(args.destinationPath));
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) => [path21.resolve(entry.path), 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 ?? path21.join(pluginRoot, "agent-assets", "fml", "SKILL.md");
4852
+ const packagedSourcePath = currentGroups[0]?.sourcePath ?? path20.join(pluginRoot, "agent-assets", "fml", "SKILL.md");
4895
4853
  for (const group of currentGroups) {
4896
- candidates.set(path21.resolve(group.destinationPath), group);
4854
+ candidates.set(path20.resolve(group.destinationPath), group);
4897
4855
  }
4898
4856
  for (const entry of entries.values()) {
4899
- const destinationPath = path21.resolve(entry.path);
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 = path21.resolve(group.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 = path22.dirname(fileURLToPath(import.meta.url))) {
4930
+ function resolvePluginRoot(startDir = path21.dirname(fileURLToPath(import.meta.url))) {
4973
4931
  let directory = startDir;
4974
4932
  while (true) {
4975
- if (fs10.existsSync(path22.join(directory, "package.json")) && fs10.existsSync(path22.join(directory, "bin"))) {
4933
+ if (fs9.existsSync(path21.join(directory, "package.json")) && fs9.existsSync(path21.join(directory, "bin"))) {
4976
4934
  return directory;
4977
4935
  }
4978
- const parent = path22.dirname(directory);
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 = fs10.readFileSync(filePath, "utf8");
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
- fs10.mkdirSync(directory, { recursive: true, mode: 448 });
5015
+ fs9.mkdirSync(directory, { recursive: true, mode: 448 });
5058
5016
  }
5059
- initializeSyncSettings(path22.join(FML_OBSERVER_DIR, "sync.json"));
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(path22.join(pluginRoot, "package.json"));
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
- fs10.mkdirSync(paths.marketplaceDir, { recursive: true, mode: 448 });
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 fs12 from "fs";
5190
+ import fs11 from "fs";
5233
5191
  import os6 from "os";
5234
- import path27 from "path";
5192
+ import path26 from "path";
5235
5193
 
5236
5194
  // ../../packages/agent-targets/src/install/otel/claude.ts
5237
- import path23 from "path";
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 path23.resolve(context.configPathOverride);
5332
+ return path22.resolve(context.configPathOverride);
5375
5333
  }
5376
- return path23.join(
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 path24 from "path";
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 path24.resolve(context.configPathOverride);
5514
+ return path23.resolve(context.configPathOverride);
5557
5515
  }
5558
5516
  const configuredHome = context.env.CODEX_HOME;
5559
- const codexHome = path24.resolve(
5560
- typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome : path24.join(context.homeDir, ".codex")
5517
+ const codexHome = path23.resolve(
5518
+ typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome : path23.join(context.homeDir, ".codex")
5561
5519
  );
5562
- return path24.join(codexHome, "config.toml");
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 path25 from "path";
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 path25.resolve(context.configPathOverride);
5748
+ return path24.resolve(context.configPathOverride);
5791
5749
  }
5792
- return path25.join(geminiConfigDirectory(context), "settings.json");
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 fs11 from "fs";
5947
- import path26 from "path";
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") fs11.chmodSync(statePath, 384);
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 = fs11.lstatSync(statePath);
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: fs11.readFileSync(statePath, "utf8") };
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 = path26.resolve(configPath4);
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 = path26.resolve(entry.path);
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: path26.resolve(entry.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 = path27.join(
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
- fs12.readFileSync(options.endpointFile, "utf8")
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 = fs12.lstatSync(filePath);
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: fs12.readFileSync(filePath, "utf8")
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) fs12.rmSync(mutation.path);
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
- fs12.chmodSync(filePath, 384);
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: path27.resolve(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: path27.resolve(plan.configPath),
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 fs14 = await import("fs");
6891
- if (fs14.existsSync("/.dockerenv")) return false;
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 as execSync2 } from "child_process";
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 = execSync2("gh auth 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-7OI3CMM4.js");
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 fs13 from "fs";
7410
+ import fs12 from "fs";
7451
7411
  import os7 from "os";
7452
- import path28 from "path";
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 = path28.resolve(preservedFile);
7428
+ const logicalPath = path27.resolve(preservedFile);
7469
7429
  try {
7470
- const canonicalPath = fs13.realpathSync(preservedFile);
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 = path28.resolve(directory);
7437
+ const resolvedDirectory = path27.resolve(directory);
7478
7438
  let directoryStats;
7479
7439
  try {
7480
- directoryStats = fs13.lstatSync(directory);
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
- fs13.rmSync(directory, { force: true });
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 = fs13.realpathSync(directory);
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
- fs13.rmSync(directory, { recursive: true, force: true });
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, path28.resolve(preservedPath))
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 = fs13.readdirSync(directory);
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 = path28.join(directory, entry);
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
- fs13.rmSync(marker, { force: true });
7508
+ fs12.rmSync(marker, { force: true });
7549
7509
  try {
7550
- fs13.rmdirSync(directory);
7510
+ fs12.rmdirSync(directory);
7551
7511
  } catch (error) {
7552
7512
  if (error.code === "ENOENT") return;
7553
7513
  try {
7554
- fs13.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
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 (!fs13.existsSync(root.directory) && pathContains(root.directory, FML_OBSERVER_DIR)) {
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
- fs13.rmSync(paths.pluginCacheDir, { recursive: true, force: true });
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.4-rc.1+bb22ea9f" : "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 path29 from "path";
9040
- var pluginVersion = true ? "0.8.4-rc.1+bb22ea9f" : void 0;
8824
+ import path28 from "path";
8825
+ var pluginVersion = true ? "0.8.4+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(path29.resolve(opts.file), "utf8");
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.4-rc.1+bb22ea9f" : "dev"
8982
+ true ? "0.8.4+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").action(() => handleSetup());
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").action(() => handleUpdate());
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_*)"