@fml-inc/fml 0.8.6 → 0.8.7
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 +16 -5
- package/dist/{chunk-5TOOBX7I.js → chunk-4YLSKFDU.js} +1140 -111
- package/dist/{chunk-V2XC7JTB.js → chunk-5JJQWV4G.js} +381 -95
- package/dist/{chunk-YFHZJPTC.js → chunk-6BTC3S7C.js} +4 -2
- package/dist/chunk-F57IFY3K.js +21 -0
- package/dist/{chunk-2DQQXBWM.js → chunk-LPSZCTTJ.js} +37 -1
- package/dist/chunk-XFALHTDL.js +277 -0
- package/dist/cli.js +168 -126
- package/dist/hook-handler.js +214 -22
- package/dist/observer-server.js +108 -22
- package/dist/sync-cycle.js +3 -2
- package/package.json +1 -1
- package/dist/chunk-E2MATWOU.js +0 -1225
package/dist/cli.js
CHANGED
|
@@ -4,30 +4,32 @@ import {
|
|
|
4
4
|
getAuthenticatedClient
|
|
5
5
|
} from "./chunk-LOJPIJZW.js";
|
|
6
6
|
import {
|
|
7
|
-
OBSERVER_HEARTBEAT_STALE_MS,
|
|
8
7
|
execBinSync,
|
|
9
|
-
getProcessIdentity,
|
|
10
8
|
handleUpdate,
|
|
11
|
-
inspectObserverLease,
|
|
12
|
-
isPidAlive,
|
|
13
|
-
readObserverStateStatus,
|
|
14
|
-
removeObserverStateIfOwned,
|
|
15
9
|
resolveBin
|
|
16
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XFALHTDL.js";
|
|
17
11
|
import {
|
|
12
|
+
openObserverLog,
|
|
18
13
|
readJsonFile,
|
|
19
14
|
setHookCaptureDisabled,
|
|
20
15
|
writeJsonFile,
|
|
21
16
|
writeTextFileAtomic
|
|
22
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-LPSZCTTJ.js";
|
|
23
18
|
import {
|
|
24
19
|
CODEX_HOOK_EVENTS,
|
|
25
20
|
GEMINI_HOOK_EVENTS,
|
|
26
21
|
GROK_HOOK_EVENTS,
|
|
22
|
+
OBSERVER_HEARTBEAT_STALE_MS,
|
|
23
|
+
getProcessIdentity,
|
|
24
|
+
inspectObserverLease,
|
|
27
25
|
isObserverHealth,
|
|
26
|
+
isPidAlive,
|
|
27
|
+
readHookInboxCapacityCounters,
|
|
28
28
|
readHookInboxStatus,
|
|
29
|
-
readObserverAuthToken
|
|
30
|
-
|
|
29
|
+
readObserverAuthToken,
|
|
30
|
+
readObserverStateStatus,
|
|
31
|
+
removeObserverStateIfOwned
|
|
32
|
+
} from "./chunk-4YLSKFDU.js";
|
|
31
33
|
import "./chunk-7V7G7NVF.js";
|
|
32
34
|
import {
|
|
33
35
|
claudeConfigDirectory,
|
|
@@ -35,14 +37,17 @@ import {
|
|
|
35
37
|
createRawArtifactSync,
|
|
36
38
|
geminiConfigDirectory,
|
|
37
39
|
initializeSyncSettings,
|
|
38
|
-
resolvePackageRoot,
|
|
39
40
|
runRawSyncOnce
|
|
40
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-5JJQWV4G.js";
|
|
42
|
+
import {
|
|
43
|
+
resolvePackageRoot
|
|
44
|
+
} from "./chunk-F57IFY3K.js";
|
|
41
45
|
import {
|
|
42
46
|
DEFAULT_PROD_URL,
|
|
43
47
|
DEFAULT_TARGET_NAME,
|
|
44
48
|
FML_DATA_DIR,
|
|
45
49
|
FML_HOOK_CAPTURE_DISABLED_FILE,
|
|
50
|
+
FML_HOOK_INBOX_DIR,
|
|
46
51
|
FML_LEGACY_OBSERVER_DB_FILE,
|
|
47
52
|
FML_LOG_DIR,
|
|
48
53
|
FML_OBSERVER_AUTH_TOKEN_FILE,
|
|
@@ -126,10 +131,8 @@ var START_TIMEOUT_MS = process.platform === "win32" ? 15e3 : 8e3;
|
|
|
126
131
|
var STOP_TIMEOUT_MS = 5e3;
|
|
127
132
|
var FORCE_STOP_TIMEOUT_MS = 2e3;
|
|
128
133
|
var POLL_INTERVAL_MS = 50;
|
|
129
|
-
var LOG_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
130
|
-
var LOG_ROTATE_FILES = 3;
|
|
131
134
|
function expectedObserverVersion() {
|
|
132
|
-
return true ? "0.8.
|
|
135
|
+
return true ? "0.8.7+af45d2af" : "dev";
|
|
133
136
|
}
|
|
134
137
|
function delay(ms) {
|
|
135
138
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -255,34 +258,6 @@ async function wakeObserverSync() {
|
|
|
255
258
|
return false;
|
|
256
259
|
}
|
|
257
260
|
}
|
|
258
|
-
function rotateObserverLog() {
|
|
259
|
-
let size = 0;
|
|
260
|
-
try {
|
|
261
|
-
size = fs.statSync(FML_OBSERVER_LOG_FILE).size;
|
|
262
|
-
} catch {
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
if (size < LOG_ROTATE_BYTES) return;
|
|
266
|
-
try {
|
|
267
|
-
fs.rmSync(`${FML_OBSERVER_LOG_FILE}.${LOG_ROTATE_FILES}`, { force: true });
|
|
268
|
-
for (let index = LOG_ROTATE_FILES - 1; index >= 1; index -= 1) {
|
|
269
|
-
const source = `${FML_OBSERVER_LOG_FILE}.${index}`;
|
|
270
|
-
if (fs.existsSync(source)) {
|
|
271
|
-
fs.renameSync(source, `${FML_OBSERVER_LOG_FILE}.${index + 1}`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
fs.renameSync(FML_OBSERVER_LOG_FILE, `${FML_OBSERVER_LOG_FILE}.1`);
|
|
275
|
-
} catch {
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
function openObserverLog() {
|
|
279
|
-
fs.mkdirSync(path.dirname(FML_OBSERVER_LOG_FILE), {
|
|
280
|
-
recursive: true,
|
|
281
|
-
mode: 448
|
|
282
|
-
});
|
|
283
|
-
rotateObserverLog();
|
|
284
|
-
return fs.openSync(FML_OBSERVER_LOG_FILE, "a", 384);
|
|
285
|
-
}
|
|
286
261
|
async function waitForReady(timeoutMs = START_TIMEOUT_MS, abortError) {
|
|
287
262
|
const startedAtMs = Date.now();
|
|
288
263
|
while (Date.now() - startedAtMs < timeoutMs) {
|
|
@@ -1797,7 +1772,7 @@ function asRecord2(value) {
|
|
|
1797
1772
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1798
1773
|
}
|
|
1799
1774
|
function singlePath(value) {
|
|
1800
|
-
const
|
|
1775
|
+
const path30 = [];
|
|
1801
1776
|
let current = value;
|
|
1802
1777
|
while (true) {
|
|
1803
1778
|
if (Array.isArray(current) && current.length === 1) {
|
|
@@ -1805,13 +1780,13 @@ function singlePath(value) {
|
|
|
1805
1780
|
continue;
|
|
1806
1781
|
}
|
|
1807
1782
|
const record = asRecord2(current);
|
|
1808
|
-
if (!record) return
|
|
1783
|
+
if (!record) return path30;
|
|
1809
1784
|
const keys = Object.keys(record);
|
|
1810
|
-
if (keys.length === 0) return
|
|
1785
|
+
if (keys.length === 0) return path30;
|
|
1811
1786
|
if (keys.length !== 1) throw new Error("ambiguous TOML statement path");
|
|
1812
1787
|
const key = keys[0];
|
|
1813
1788
|
if (key === void 0) throw new Error("missing TOML statement key");
|
|
1814
|
-
|
|
1789
|
+
path30.push(key);
|
|
1815
1790
|
current = record[key];
|
|
1816
1791
|
}
|
|
1817
1792
|
}
|
|
@@ -1893,8 +1868,8 @@ function scanStatements(source) {
|
|
|
1893
1868
|
}
|
|
1894
1869
|
return statements;
|
|
1895
1870
|
}
|
|
1896
|
-
function startsWithPath(
|
|
1897
|
-
return prefix.every((part, index) =>
|
|
1871
|
+
function startsWithPath(path30, prefix) {
|
|
1872
|
+
return prefix.every((part, index) => path30[index] === part);
|
|
1898
1873
|
}
|
|
1899
1874
|
function pathsEqual(left, right) {
|
|
1900
1875
|
return left.length === right.length && left.every((part, index) => part === right[index]);
|
|
@@ -1920,9 +1895,9 @@ function appendToml(source, addition) {
|
|
|
1920
1895
|
function hasOwn(record, key) {
|
|
1921
1896
|
return Object.prototype.hasOwnProperty.call(record, key);
|
|
1922
1897
|
}
|
|
1923
|
-
function updatedValueAtPath(updated,
|
|
1898
|
+
function updatedValueAtPath(updated, path30) {
|
|
1924
1899
|
let current = updated;
|
|
1925
|
-
for (const part of
|
|
1900
|
+
for (const part of path30) {
|
|
1926
1901
|
const record = asRecord2(current);
|
|
1927
1902
|
if (!record || !hasOwn(record, part)) return { exists: false };
|
|
1928
1903
|
current = record[part];
|
|
@@ -1936,22 +1911,22 @@ function normalizedPaths(updates) {
|
|
|
1936
1911
|
throw new Error("TOML update path cannot be empty");
|
|
1937
1912
|
}
|
|
1938
1913
|
if (paths.some(
|
|
1939
|
-
(
|
|
1914
|
+
(path30) => pathsEqual(path30, update.path) || startsWithPath(update.path, path30)
|
|
1940
1915
|
)) {
|
|
1941
1916
|
continue;
|
|
1942
1917
|
}
|
|
1943
1918
|
for (let index = paths.length - 1; index >= 0; index -= 1) {
|
|
1944
|
-
const
|
|
1945
|
-
if (
|
|
1919
|
+
const path30 = paths[index];
|
|
1920
|
+
if (path30 && startsWithPath(path30, update.path)) paths.splice(index, 1);
|
|
1946
1921
|
}
|
|
1947
1922
|
paths.push([...update.path]);
|
|
1948
1923
|
}
|
|
1949
1924
|
return paths;
|
|
1950
1925
|
}
|
|
1951
|
-
function valueDocument(
|
|
1926
|
+
function valueDocument(path30, value) {
|
|
1952
1927
|
let nested = value;
|
|
1953
|
-
for (let index =
|
|
1954
|
-
const part =
|
|
1928
|
+
for (let index = path30.length - 1; index >= 0; index -= 1) {
|
|
1929
|
+
const part = path30[index];
|
|
1955
1930
|
if (part === void 0) throw new Error("TOML update path is invalid");
|
|
1956
1931
|
nested = { [part]: nested };
|
|
1957
1932
|
}
|
|
@@ -1970,12 +1945,12 @@ function insertAfterStatement(source, statement, addition) {
|
|
|
1970
1945
|
const separator = before.endsWith(eol) ? "" : eol;
|
|
1971
1946
|
return `${before}${separator}${normalized}${eol}${source.slice(statement.end)}`;
|
|
1972
1947
|
}
|
|
1973
|
-
function insertUpdatedValue(source,
|
|
1974
|
-
const key =
|
|
1948
|
+
function insertUpdatedValue(source, path30, value) {
|
|
1949
|
+
const key = path30.at(-1);
|
|
1975
1950
|
if (key === void 0) throw new Error("TOML update path cannot be empty");
|
|
1976
1951
|
const assignment = localAssignment(key, value);
|
|
1977
1952
|
if (assignment !== null) {
|
|
1978
|
-
const parent =
|
|
1953
|
+
const parent = path30.slice(0, -1);
|
|
1979
1954
|
const parentTables = scanStatements(source).filter(
|
|
1980
1955
|
(statement) => statement.isTable && pathsEqual(statement.path, parent)
|
|
1981
1956
|
);
|
|
@@ -1989,17 +1964,17 @@ function insertUpdatedValue(source, path29, value) {
|
|
|
1989
1964
|
return insertAfterStatement(source, parentTable, assignment);
|
|
1990
1965
|
}
|
|
1991
1966
|
}
|
|
1992
|
-
return appendToml(source, stringify(valueDocument(
|
|
1967
|
+
return appendToml(source, stringify(valueDocument(path30, value)));
|
|
1993
1968
|
}
|
|
1994
1969
|
function updateTomlPaths(source, updated, updates) {
|
|
1995
1970
|
const paths = normalizedPaths(updates);
|
|
1996
1971
|
if (paths.length === 0) return source;
|
|
1997
1972
|
const stripped = removeStatements(source, scanStatements(source), paths);
|
|
1998
1973
|
let result = stripped;
|
|
1999
|
-
for (const
|
|
2000
|
-
const next = updatedValueAtPath(updated,
|
|
1974
|
+
for (const path30 of paths) {
|
|
1975
|
+
const next = updatedValueAtPath(updated, path30);
|
|
2001
1976
|
if (!next.exists) continue;
|
|
2002
|
-
result = insertUpdatedValue(result,
|
|
1977
|
+
result = insertUpdatedValue(result, path30, next.value);
|
|
2003
1978
|
}
|
|
2004
1979
|
let reparsed;
|
|
2005
1980
|
try {
|
|
@@ -2627,7 +2602,7 @@ function codexConfigUpdatePaths(original, updated) {
|
|
|
2627
2602
|
}
|
|
2628
2603
|
}
|
|
2629
2604
|
}
|
|
2630
|
-
return paths.map((
|
|
2605
|
+
return paths.map((path30) => ({ path: path30 }));
|
|
2631
2606
|
}
|
|
2632
2607
|
function updateCodexConfigToml(source, original, updated) {
|
|
2633
2608
|
return updateTomlPaths(
|
|
@@ -3133,7 +3108,7 @@ function longestCommonArraySubsequence(original, updated) {
|
|
|
3133
3108
|
}
|
|
3134
3109
|
return matches;
|
|
3135
3110
|
}
|
|
3136
|
-
function arrayDiff(original, updated,
|
|
3111
|
+
function arrayDiff(original, updated, path30) {
|
|
3137
3112
|
const updates = [];
|
|
3138
3113
|
const matches = longestCommonArraySubsequence(original, updated);
|
|
3139
3114
|
let originalStart = 0;
|
|
@@ -3151,19 +3126,19 @@ function arrayDiff(original, updated, path29) {
|
|
|
3151
3126
|
...jsoncUpdatesForObjectDiff(
|
|
3152
3127
|
original[originalStart + offset],
|
|
3153
3128
|
updated[updatedStart + offset],
|
|
3154
|
-
[...
|
|
3129
|
+
[...path30, currentIndex + offset]
|
|
3155
3130
|
)
|
|
3156
3131
|
);
|
|
3157
3132
|
}
|
|
3158
3133
|
for (let offset = pairedCount; offset < originalCount; offset += 1) {
|
|
3159
3134
|
updates.push({
|
|
3160
|
-
path: [...
|
|
3135
|
+
path: [...path30, currentIndex + pairedCount],
|
|
3161
3136
|
value: void 0
|
|
3162
3137
|
});
|
|
3163
3138
|
}
|
|
3164
3139
|
for (let offset = pairedCount; offset < updatedCount; offset += 1) {
|
|
3165
3140
|
updates.push({
|
|
3166
|
-
path: [...
|
|
3141
|
+
path: [...path30, currentIndex + offset],
|
|
3167
3142
|
value: updated[updatedStart + offset],
|
|
3168
3143
|
isArrayInsertion: true
|
|
3169
3144
|
});
|
|
@@ -3176,21 +3151,21 @@ function arrayDiff(original, updated, path29) {
|
|
|
3176
3151
|
}
|
|
3177
3152
|
return updates;
|
|
3178
3153
|
}
|
|
3179
|
-
function jsoncUpdatesForObjectDiff(original, updated,
|
|
3154
|
+
function jsoncUpdatesForObjectDiff(original, updated, path30 = []) {
|
|
3180
3155
|
if (isDeepStrictEqual3(original, updated)) return [];
|
|
3181
3156
|
if (Array.isArray(original) && Array.isArray(updated)) {
|
|
3182
|
-
return arrayDiff(original, updated,
|
|
3157
|
+
return arrayDiff(original, updated, path30);
|
|
3183
3158
|
}
|
|
3184
3159
|
const originalObject = asObject(original);
|
|
3185
3160
|
const updatedObject = asObject(updated);
|
|
3186
|
-
if (!originalObject || !updatedObject) return [{ path:
|
|
3161
|
+
if (!originalObject || !updatedObject) return [{ path: path30, value: updated }];
|
|
3187
3162
|
const keys = /* @__PURE__ */ new Set([
|
|
3188
3163
|
...Object.keys(originalObject),
|
|
3189
3164
|
...Object.keys(updatedObject)
|
|
3190
3165
|
]);
|
|
3191
3166
|
return [...keys].flatMap(
|
|
3192
3167
|
(key) => jsoncUpdatesForObjectDiff(originalObject[key], updatedObject[key], [
|
|
3193
|
-
...
|
|
3168
|
+
...path30,
|
|
3194
3169
|
key
|
|
3195
3170
|
])
|
|
3196
3171
|
);
|
|
@@ -5188,13 +5163,67 @@ async function handleInstall(opts = {}) {
|
|
|
5188
5163
|
// src/commands/sync.ts
|
|
5189
5164
|
import { statSync } from "fs";
|
|
5190
5165
|
|
|
5166
|
+
// src/hooks/inbox-refusals.ts
|
|
5167
|
+
import fs10 from "fs";
|
|
5168
|
+
import path22 from "path";
|
|
5169
|
+
var FML_HOOK_INBOX_LOSS_LEDGER_FILE = path22.join(
|
|
5170
|
+
FML_OBSERVER_DIR,
|
|
5171
|
+
"hook-inbox-loss.reported.json"
|
|
5172
|
+
);
|
|
5173
|
+
function readLedger(ledgerFile) {
|
|
5174
|
+
try {
|
|
5175
|
+
const parsed = JSON.parse(fs10.readFileSync(ledgerFile, "utf8"));
|
|
5176
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5177
|
+
const record = parsed;
|
|
5178
|
+
const entries = record.reportedEntries;
|
|
5179
|
+
const bytes = record.reportedBytes;
|
|
5180
|
+
if (typeof entries === "number" && Number.isSafeInteger(entries) && entries >= 0 && typeof bytes === "number" && Number.isSafeInteger(bytes) && bytes >= 0) {
|
|
5181
|
+
return { reportedEntries: entries, reportedBytes: bytes };
|
|
5182
|
+
}
|
|
5183
|
+
}
|
|
5184
|
+
} catch {
|
|
5185
|
+
}
|
|
5186
|
+
return { reportedEntries: 0, reportedBytes: 0 };
|
|
5187
|
+
}
|
|
5188
|
+
function takeUnreportedInboxLoss(options = {}) {
|
|
5189
|
+
const inboxDir = options.inboxDir ?? FML_HOOK_INBOX_DIR;
|
|
5190
|
+
const ledgerFile = options.ledgerFile ?? FML_HOOK_INBOX_LOSS_LEDGER_FILE;
|
|
5191
|
+
try {
|
|
5192
|
+
const counters = readHookInboxCapacityCounters(inboxDir);
|
|
5193
|
+
if (!counters) return null;
|
|
5194
|
+
const ledger = readLedger(ledgerFile);
|
|
5195
|
+
if (counters.lostEntries === ledger.reportedEntries && counters.lostBytes === ledger.reportedBytes) {
|
|
5196
|
+
return null;
|
|
5197
|
+
}
|
|
5198
|
+
const entries = Math.max(0, counters.lostEntries - ledger.reportedEntries);
|
|
5199
|
+
const bytes = Math.max(0, counters.lostBytes - ledger.reportedBytes);
|
|
5200
|
+
fs10.mkdirSync(path22.dirname(ledgerFile), { recursive: true, mode: 448 });
|
|
5201
|
+
writeTextFileAtomic(
|
|
5202
|
+
ledgerFile,
|
|
5203
|
+
`${JSON.stringify({
|
|
5204
|
+
reportedEntries: counters.lostEntries,
|
|
5205
|
+
reportedBytes: counters.lostBytes
|
|
5206
|
+
})}
|
|
5207
|
+
`
|
|
5208
|
+
);
|
|
5209
|
+
if (entries === 0) return null;
|
|
5210
|
+
return {
|
|
5211
|
+
entries,
|
|
5212
|
+
bytes,
|
|
5213
|
+
...counters.lastLostAtMs === void 0 ? {} : { lastAtMs: counters.lastLostAtMs }
|
|
5214
|
+
};
|
|
5215
|
+
} catch {
|
|
5216
|
+
return null;
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5219
|
+
|
|
5191
5220
|
// src/commands/otel-config.ts
|
|
5192
|
-
import
|
|
5221
|
+
import fs12 from "fs";
|
|
5193
5222
|
import os6 from "os";
|
|
5194
|
-
import
|
|
5223
|
+
import path27 from "path";
|
|
5195
5224
|
|
|
5196
5225
|
// ../../packages/agent-targets/src/install/otel/claude.ts
|
|
5197
|
-
import
|
|
5226
|
+
import path23 from "path";
|
|
5198
5227
|
|
|
5199
5228
|
// ../../packages/agent-targets/src/install/otel/shared.ts
|
|
5200
5229
|
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
@@ -5331,9 +5360,9 @@ var MANAGED_MARKER = "FML_OTEL_MANAGED";
|
|
|
5331
5360
|
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";
|
|
5332
5361
|
function configPath(context) {
|
|
5333
5362
|
if (context.configPathOverride) {
|
|
5334
|
-
return
|
|
5363
|
+
return path23.resolve(context.configPathOverride);
|
|
5335
5364
|
}
|
|
5336
|
-
return
|
|
5365
|
+
return path23.join(
|
|
5337
5366
|
claudeConfigDirectory({ env: context.env, homeDir: context.homeDir }),
|
|
5338
5367
|
"settings.json"
|
|
5339
5368
|
);
|
|
@@ -5504,7 +5533,7 @@ var CLAUDE_OTEL_INSTALLER = Object.freeze({
|
|
|
5504
5533
|
|
|
5505
5534
|
// ../../packages/agent-targets/src/install/otel/codex.ts
|
|
5506
5535
|
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
5507
|
-
import
|
|
5536
|
+
import path24 from "path";
|
|
5508
5537
|
import { parse as parse5 } from "smol-toml";
|
|
5509
5538
|
var TARGET14 = agentTarget("codex");
|
|
5510
5539
|
var TARGET_ID6 = TARGET14.id;
|
|
@@ -5513,13 +5542,13 @@ var AUTHENTICATION2 = "bearer-header";
|
|
|
5513
5542
|
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";
|
|
5514
5543
|
function configPath2(context) {
|
|
5515
5544
|
if (context.configPathOverride) {
|
|
5516
|
-
return
|
|
5545
|
+
return path24.resolve(context.configPathOverride);
|
|
5517
5546
|
}
|
|
5518
5547
|
const configuredHome = context.env.CODEX_HOME;
|
|
5519
|
-
const codexHome =
|
|
5520
|
-
typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome :
|
|
5548
|
+
const codexHome = path24.resolve(
|
|
5549
|
+
typeof configuredHome === "string" && configuredHome.trim().length > 0 ? configuredHome : path24.join(context.homeDir, ".codex")
|
|
5521
5550
|
);
|
|
5522
|
-
return
|
|
5551
|
+
return path24.join(codexHome, "config.toml");
|
|
5523
5552
|
}
|
|
5524
5553
|
function readToml(snapshot) {
|
|
5525
5554
|
const failure = snapshotError2(snapshot);
|
|
@@ -5739,7 +5768,7 @@ var CODEX_OTEL_INSTALLER = Object.freeze({
|
|
|
5739
5768
|
});
|
|
5740
5769
|
|
|
5741
5770
|
// ../../packages/agent-targets/src/install/otel/gemini.ts
|
|
5742
|
-
import
|
|
5771
|
+
import path25 from "path";
|
|
5743
5772
|
var TARGET15 = agentTarget("gemini");
|
|
5744
5773
|
var TARGET_ID7 = TARGET15.id;
|
|
5745
5774
|
var DISPLAY_NAME7 = TARGET15.displayName;
|
|
@@ -5747,9 +5776,9 @@ var AUTHENTICATION3 = "path-token";
|
|
|
5747
5776
|
var GEMINI_OTEL_SOURCE_LIMITATION = "Gemini CLI has no documented OTLP header setting; FML uses an observer-local tokenized loopback path";
|
|
5748
5777
|
function configPath3(context) {
|
|
5749
5778
|
if (context.configPathOverride) {
|
|
5750
|
-
return
|
|
5779
|
+
return path25.resolve(context.configPathOverride);
|
|
5751
5780
|
}
|
|
5752
|
-
return
|
|
5781
|
+
return path25.join(geminiConfigDirectory(context), "settings.json");
|
|
5753
5782
|
}
|
|
5754
5783
|
function managedTelemetry(context) {
|
|
5755
5784
|
const destination = resolveDestination(context.observer);
|
|
@@ -5903,8 +5932,8 @@ var OTEL_INSTALLER_CAPABILITIES = Object.freeze([
|
|
|
5903
5932
|
]);
|
|
5904
5933
|
|
|
5905
5934
|
// src/commands/otel-config-state.ts
|
|
5906
|
-
import
|
|
5907
|
-
import
|
|
5935
|
+
import fs11 from "fs";
|
|
5936
|
+
import path26 from "path";
|
|
5908
5937
|
var OTEL_CONFIG_STATE_SCHEMA_VERSION = 1;
|
|
5909
5938
|
function emptyState2() {
|
|
5910
5939
|
return Object.freeze({
|
|
@@ -5918,12 +5947,12 @@ function invalidState2(statePath, reason) {
|
|
|
5918
5947
|
);
|
|
5919
5948
|
}
|
|
5920
5949
|
function enforceOwnerOnlyMode(statePath) {
|
|
5921
|
-
if (process.platform !== "win32")
|
|
5950
|
+
if (process.platform !== "win32") fs11.chmodSync(statePath, 384);
|
|
5922
5951
|
}
|
|
5923
5952
|
function readStateFile(statePath) {
|
|
5924
5953
|
let stat;
|
|
5925
5954
|
try {
|
|
5926
|
-
stat =
|
|
5955
|
+
stat = fs11.lstatSync(statePath);
|
|
5927
5956
|
} catch (error) {
|
|
5928
5957
|
if (error.code === "ENOENT") {
|
|
5929
5958
|
return { kind: "missing" };
|
|
@@ -5941,7 +5970,7 @@ function readStateFile(statePath) {
|
|
|
5941
5970
|
}
|
|
5942
5971
|
try {
|
|
5943
5972
|
enforceOwnerOnlyMode(statePath);
|
|
5944
|
-
return { kind: "file", contents:
|
|
5973
|
+
return { kind: "file", contents: fs11.readFileSync(statePath, "utf8") };
|
|
5945
5974
|
} catch (error) {
|
|
5946
5975
|
return {
|
|
5947
5976
|
kind: "invalid",
|
|
@@ -5950,7 +5979,7 @@ function readStateFile(statePath) {
|
|
|
5950
5979
|
}
|
|
5951
5980
|
}
|
|
5952
5981
|
function otelConfigStateEntryKey(targetId, configPath4) {
|
|
5953
|
-
const resolved =
|
|
5982
|
+
const resolved = path26.resolve(configPath4);
|
|
5954
5983
|
const pathKey = process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
5955
5984
|
return `${targetId}\0${pathKey}`;
|
|
5956
5985
|
}
|
|
@@ -5986,7 +6015,7 @@ function parseState2(source, statePath) {
|
|
|
5986
6015
|
if (typeof observerRecord.baseUrl !== "string" || observerRecord.baseUrl.length === 0 || typeof observerRecord.authToken !== "string" || observerRecord.authToken.length === 0) {
|
|
5987
6016
|
throw invalidState2(statePath, "contains an invalid observer destination");
|
|
5988
6017
|
}
|
|
5989
|
-
const resolvedPath =
|
|
6018
|
+
const resolvedPath = path26.resolve(entry.path);
|
|
5990
6019
|
const key = otelConfigStateEntryKey(entry.targetId, resolvedPath);
|
|
5991
6020
|
if (keys.has(key)) {
|
|
5992
6021
|
throw invalidState2(statePath, "contains duplicate entries");
|
|
@@ -6024,7 +6053,7 @@ function loadFmlOtelConfigState(statePath) {
|
|
|
6024
6053
|
function serializeState2(entries) {
|
|
6025
6054
|
const sorted = [...entries].map((entry) => ({
|
|
6026
6055
|
targetId: entry.targetId,
|
|
6027
|
-
path:
|
|
6056
|
+
path: path26.resolve(entry.path),
|
|
6028
6057
|
observer: {
|
|
6029
6058
|
baseUrl: entry.observer.baseUrl,
|
|
6030
6059
|
authToken: entry.observer.authToken
|
|
@@ -6061,7 +6090,7 @@ function isKnownOtelTargetId(targetId) {
|
|
|
6061
6090
|
}
|
|
6062
6091
|
|
|
6063
6092
|
// src/commands/otel-config.ts
|
|
6064
|
-
var DEFAULT_OTEL_CONFIG_STATE_PATH =
|
|
6093
|
+
var DEFAULT_OTEL_CONFIG_STATE_PATH = path27.join(
|
|
6065
6094
|
FML_DATA_DIR,
|
|
6066
6095
|
"otel-config.json"
|
|
6067
6096
|
);
|
|
@@ -6070,7 +6099,7 @@ function readLocalObserverOtelDestination(options) {
|
|
|
6070
6099
|
if (!authToken) return null;
|
|
6071
6100
|
try {
|
|
6072
6101
|
const parsed = JSON.parse(
|
|
6073
|
-
|
|
6102
|
+
fs12.readFileSync(options.endpointFile, "utf8")
|
|
6074
6103
|
);
|
|
6075
6104
|
const endpoint = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
6076
6105
|
const host = endpoint?.host;
|
|
@@ -6087,7 +6116,7 @@ function readLocalObserverOtelDestination(options) {
|
|
|
6087
6116
|
function readOtelFile(filePath) {
|
|
6088
6117
|
let stat;
|
|
6089
6118
|
try {
|
|
6090
|
-
stat =
|
|
6119
|
+
stat = fs12.lstatSync(filePath);
|
|
6091
6120
|
} catch (error) {
|
|
6092
6121
|
if (error.code === "ENOENT") {
|
|
6093
6122
|
return { path: filePath, kind: "missing" };
|
|
@@ -6116,7 +6145,7 @@ function readOtelFile(filePath) {
|
|
|
6116
6145
|
return {
|
|
6117
6146
|
path: filePath,
|
|
6118
6147
|
kind: "file",
|
|
6119
|
-
contents:
|
|
6148
|
+
contents: fs12.readFileSync(filePath, "utf8")
|
|
6120
6149
|
};
|
|
6121
6150
|
} catch (error) {
|
|
6122
6151
|
return {
|
|
@@ -6138,7 +6167,7 @@ function assertMutationPrecondition2(mutation) {
|
|
|
6138
6167
|
throw new Error(`configuration changed while planning ${mutation.path}`);
|
|
6139
6168
|
}
|
|
6140
6169
|
function applyMutation2(mutation) {
|
|
6141
|
-
if (mutation.after === null)
|
|
6170
|
+
if (mutation.after === null) fs12.rmSync(mutation.path);
|
|
6142
6171
|
else writeTextFileAtomic(mutation.path, mutation.after);
|
|
6143
6172
|
}
|
|
6144
6173
|
function enforceOwnerOnlyConfigPermissions(filePath) {
|
|
@@ -6151,7 +6180,7 @@ function enforceOwnerOnlyConfigPermissions(filePath) {
|
|
|
6151
6180
|
);
|
|
6152
6181
|
}
|
|
6153
6182
|
try {
|
|
6154
|
-
|
|
6183
|
+
fs12.chmodSync(filePath, 384);
|
|
6155
6184
|
} catch (error) {
|
|
6156
6185
|
const detail = error instanceof Error ? error.message : String(error);
|
|
6157
6186
|
throw new Error(
|
|
@@ -6246,7 +6275,7 @@ function plannerContext3(observer, options, configPathOverride, configOwnershipR
|
|
|
6246
6275
|
observer,
|
|
6247
6276
|
homeDir: options.homeDir ?? os6.homedir(),
|
|
6248
6277
|
env: options.env ?? process.env,
|
|
6249
|
-
...configPathOverride ? { configPathOverride:
|
|
6278
|
+
...configPathOverride ? { configPathOverride: path27.resolve(configPathOverride) } : {},
|
|
6250
6279
|
...configOwnershipRecorded ? { configOwnershipRecorded: true } : {},
|
|
6251
6280
|
readFile: readOtelFile
|
|
6252
6281
|
};
|
|
@@ -6289,7 +6318,7 @@ function commitStateEntry(state, key, next) {
|
|
|
6289
6318
|
function stateEntry(plan, observer) {
|
|
6290
6319
|
return Object.freeze({
|
|
6291
6320
|
targetId: plan.targetId,
|
|
6292
|
-
path:
|
|
6321
|
+
path: path27.resolve(plan.configPath),
|
|
6293
6322
|
observer: Object.freeze({
|
|
6294
6323
|
baseUrl: observer.baseUrl,
|
|
6295
6324
|
authToken: observer.authToken
|
|
@@ -6633,6 +6662,13 @@ async function handleSyncEnable(opts = {}) {
|
|
|
6633
6662
|
if (observer.status === "already_running") {
|
|
6634
6663
|
await wakeObserverSync();
|
|
6635
6664
|
}
|
|
6665
|
+
const loss = takeUnreportedInboxLoss();
|
|
6666
|
+
if (loss && !opts.json) {
|
|
6667
|
+
const lastAt = loss.lastAtMs ? ` (last at ${new Date(loss.lastAtMs).toISOString()})` : "";
|
|
6668
|
+
console.warn(
|
|
6669
|
+
`Warning: ${loss.entries} hook event(s) (${formatBytes(loss.bytes)}) were lost: the hook inbox was full and no FML observer was running to take them${lastAt}. Keep the observer running, or raise FML_HOOK_INBOX_MAX_BYTES, to avoid further loss.`
|
|
6670
|
+
);
|
|
6671
|
+
}
|
|
6636
6672
|
const port = observer.runtime.health?.port;
|
|
6637
6673
|
const authToken = port ? readObserverAuthToken(FML_OBSERVER_AUTH_TOKEN_FILE) : null;
|
|
6638
6674
|
if (port && authToken) {
|
|
@@ -6650,7 +6686,8 @@ async function handleSyncEnable(opts = {}) {
|
|
|
6650
6686
|
ok: true,
|
|
6651
6687
|
sync: settings,
|
|
6652
6688
|
observer,
|
|
6653
|
-
...observer.retainedLegacyDatabase ? { retainedLegacyDatabase: observer.retainedLegacyDatabase } : {}
|
|
6689
|
+
...observer.retainedLegacyDatabase ? { retainedLegacyDatabase: observer.retainedLegacyDatabase } : {},
|
|
6690
|
+
...loss ? { hookInboxLoss: loss } : {}
|
|
6654
6691
|
});
|
|
6655
6692
|
} else {
|
|
6656
6693
|
const pid = observer.runtime.health?.pid;
|
|
@@ -6859,8 +6896,8 @@ async function canOpenBrowser() {
|
|
|
6859
6896
|
if (process.env.CODESPACES) return false;
|
|
6860
6897
|
if (process.env.REMOTE_CONTAINERS) return false;
|
|
6861
6898
|
try {
|
|
6862
|
-
const
|
|
6863
|
-
if (
|
|
6899
|
+
const fs14 = await import("fs");
|
|
6900
|
+
if (fs14.existsSync("/.dockerenv")) return false;
|
|
6864
6901
|
} catch {
|
|
6865
6902
|
}
|
|
6866
6903
|
return true;
|
|
@@ -7523,9 +7560,9 @@ async function handleSetup(dependencies = defaultDependencies, options = {}) {
|
|
|
7523
7560
|
}
|
|
7524
7561
|
|
|
7525
7562
|
// src/commands/uninstall.ts
|
|
7526
|
-
import
|
|
7563
|
+
import fs13 from "fs";
|
|
7527
7564
|
import os7 from "os";
|
|
7528
|
-
import
|
|
7565
|
+
import path28 from "path";
|
|
7529
7566
|
import readline from "readline/promises";
|
|
7530
7567
|
var PURGE_WARNING = "This deletes FML credentials for ALL environments, logs, sync state, and every pending best-effort OTLP envelope.";
|
|
7531
7568
|
function tryDisableHookCapture() {
|
|
@@ -7541,19 +7578,19 @@ function tryDisableHookCapture() {
|
|
|
7541
7578
|
}
|
|
7542
7579
|
}
|
|
7543
7580
|
function resolvePreservedPaths(preservedFile) {
|
|
7544
|
-
const logicalPath =
|
|
7581
|
+
const logicalPath = path28.resolve(preservedFile);
|
|
7545
7582
|
try {
|
|
7546
|
-
const canonicalPath =
|
|
7583
|
+
const canonicalPath = fs13.realpathSync(preservedFile);
|
|
7547
7584
|
return pathsAreSame(canonicalPath, logicalPath) ? [logicalPath] : [logicalPath, canonicalPath];
|
|
7548
7585
|
} catch {
|
|
7549
7586
|
return [logicalPath];
|
|
7550
7587
|
}
|
|
7551
7588
|
}
|
|
7552
7589
|
function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot = false) {
|
|
7553
|
-
const resolvedDirectory =
|
|
7590
|
+
const resolvedDirectory = path28.resolve(directory);
|
|
7554
7591
|
let directoryStats;
|
|
7555
7592
|
try {
|
|
7556
|
-
directoryStats =
|
|
7593
|
+
directoryStats = fs13.lstatSync(directory);
|
|
7557
7594
|
} catch (error) {
|
|
7558
7595
|
if (error.code === "ENOENT") return true;
|
|
7559
7596
|
throw error;
|
|
@@ -7564,14 +7601,14 @@ function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot
|
|
|
7564
7601
|
(preservedPath) => pathContains(resolvedDirectory, preservedPath)
|
|
7565
7602
|
);
|
|
7566
7603
|
if (!containsLogicalMarker) {
|
|
7567
|
-
|
|
7604
|
+
fs13.rmSync(directory, { force: true });
|
|
7568
7605
|
return true;
|
|
7569
7606
|
}
|
|
7570
7607
|
return false;
|
|
7571
7608
|
}
|
|
7572
7609
|
const directoryPaths = [resolvedDirectory];
|
|
7573
7610
|
try {
|
|
7574
|
-
const canonicalDirectory =
|
|
7611
|
+
const canonicalDirectory = fs13.realpathSync(directory);
|
|
7575
7612
|
if (!pathsAreSame(canonicalDirectory, resolvedDirectory)) {
|
|
7576
7613
|
directoryPaths.push(canonicalDirectory);
|
|
7577
7614
|
}
|
|
@@ -7583,26 +7620,26 @@ function purgeDirectoryPreservingPaths(directory, preservedPaths, configuredRoot
|
|
|
7583
7620
|
)
|
|
7584
7621
|
);
|
|
7585
7622
|
if (!containsPreservedPath) {
|
|
7586
|
-
|
|
7623
|
+
fs13.rmSync(directory, { recursive: true, force: true });
|
|
7587
7624
|
return true;
|
|
7588
7625
|
}
|
|
7589
7626
|
const isPreservedPath = directoryPaths.some(
|
|
7590
7627
|
(directoryPath) => preservedPaths.some(
|
|
7591
|
-
(preservedPath) => pathsAreSame(directoryPath,
|
|
7628
|
+
(preservedPath) => pathsAreSame(directoryPath, path28.resolve(preservedPath))
|
|
7592
7629
|
)
|
|
7593
7630
|
);
|
|
7594
7631
|
if (isPreservedPath) return true;
|
|
7595
7632
|
if (!directoryStats.isDirectory()) return false;
|
|
7596
7633
|
let entries;
|
|
7597
7634
|
try {
|
|
7598
|
-
entries =
|
|
7635
|
+
entries = fs13.readdirSync(directory);
|
|
7599
7636
|
} catch (error) {
|
|
7600
7637
|
if (error.code === "ENOENT") return true;
|
|
7601
7638
|
throw error;
|
|
7602
7639
|
}
|
|
7603
7640
|
let complete = true;
|
|
7604
7641
|
for (const entry of entries) {
|
|
7605
|
-
const entryPath =
|
|
7642
|
+
const entryPath = path28.join(directory, entry);
|
|
7606
7643
|
if (!purgeDirectoryPreservingPaths(entryPath, preservedPaths, false)) {
|
|
7607
7644
|
complete = false;
|
|
7608
7645
|
}
|
|
@@ -7621,13 +7658,13 @@ function purgeDirectoryPreservingFiles(directory, preservedFiles) {
|
|
|
7621
7658
|
}
|
|
7622
7659
|
function finishCustomRootPurge(directory) {
|
|
7623
7660
|
const marker = managedDirectoryMarker(directory);
|
|
7624
|
-
|
|
7661
|
+
fs13.rmSync(marker, { force: true });
|
|
7625
7662
|
try {
|
|
7626
|
-
|
|
7663
|
+
fs13.rmdirSync(directory);
|
|
7627
7664
|
} catch (error) {
|
|
7628
7665
|
if (error.code === "ENOENT") return;
|
|
7629
7666
|
try {
|
|
7630
|
-
|
|
7667
|
+
fs13.writeFileSync(marker, FML_MANAGED_DIRECTORY_MARKER_CONTENT, {
|
|
7631
7668
|
encoding: "utf8",
|
|
7632
7669
|
flag: "wx",
|
|
7633
7670
|
mode: 384
|
|
@@ -7725,7 +7762,7 @@ async function handleUninstall(opts) {
|
|
|
7725
7762
|
return;
|
|
7726
7763
|
}
|
|
7727
7764
|
for (const root of purgeRoots) {
|
|
7728
|
-
if (!
|
|
7765
|
+
if (!fs13.existsSync(root.directory) && pathContains(root.directory, FML_OBSERVER_DIR)) {
|
|
7729
7766
|
prepareManagedDirectory(root);
|
|
7730
7767
|
}
|
|
7731
7768
|
}
|
|
@@ -7849,7 +7886,7 @@ async function handleUninstall(opts) {
|
|
|
7849
7886
|
)
|
|
7850
7887
|
);
|
|
7851
7888
|
}
|
|
7852
|
-
|
|
7889
|
+
fs13.rmSync(paths.pluginCacheDir, { recursive: true, force: true });
|
|
7853
7890
|
const reportIntegrationWarning = (message) => {
|
|
7854
7891
|
integrationsRemoved = false;
|
|
7855
7892
|
console.warn(message.replace(/^warn:/u, "Warning:"));
|
|
@@ -8300,6 +8337,11 @@ async function handleStatus() {
|
|
|
8300
8337
|
);
|
|
8301
8338
|
}
|
|
8302
8339
|
}
|
|
8340
|
+
if (hookInbox.lostEntries > 0) {
|
|
8341
|
+
console.log(
|
|
8342
|
+
` Inbox loss: ${hookInbox.lostEntries} record(s), ${formatBytes2(hookInbox.lostBytes)} refused with no observer to take them${hookInbox.lastLostAtMs !== void 0 ? ` (last at ${new Date(hookInbox.lastLostAtMs).toISOString()})` : ""}`
|
|
8343
|
+
);
|
|
8344
|
+
}
|
|
8303
8345
|
if (hookInbox.retiredEntries > 0) {
|
|
8304
8346
|
console.log(
|
|
8305
8347
|
` Inbox retired: ${hookInbox.retiredEntries} record(s), ${formatBytes2(hookInbox.retiredBytes)}`
|
|
@@ -8954,8 +8996,8 @@ async function handleConfigDetail(opts) {
|
|
|
8954
8996
|
|
|
8955
8997
|
// src/commands/tools.ts
|
|
8956
8998
|
import { readFileSync } from "fs";
|
|
8957
|
-
import
|
|
8958
|
-
var pluginVersion = true ? "0.8.
|
|
8999
|
+
import path29 from "path";
|
|
9000
|
+
var pluginVersion = true ? "0.8.7+af45d2af" : void 0;
|
|
8959
9001
|
async function getApi() {
|
|
8960
9002
|
const api = await getAuthenticatedClient();
|
|
8961
9003
|
if (!api) {
|
|
@@ -9062,7 +9104,7 @@ async function handleToolsCall(name, opts) {
|
|
|
9062
9104
|
}
|
|
9063
9105
|
const raw = opts.file ? (() => {
|
|
9064
9106
|
try {
|
|
9065
|
-
return readFileSync(
|
|
9107
|
+
return readFileSync(path29.resolve(opts.file), "utf8");
|
|
9066
9108
|
} catch (err) {
|
|
9067
9109
|
const msg = err instanceof Error ? err.message : String(err);
|
|
9068
9110
|
console.error(`Could not read args file: ${msg}`);
|
|
@@ -9112,7 +9154,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
9112
9154
|
printBanner();
|
|
9113
9155
|
}
|
|
9114
9156
|
var program = new Command().name("fml").description("FML CLI and agent tools").version(
|
|
9115
|
-
true ? "0.8.
|
|
9157
|
+
true ? "0.8.7+af45d2af" : "dev"
|
|
9116
9158
|
);
|
|
9117
9159
|
function formatCommandInventory(cmd, prefix = "") {
|
|
9118
9160
|
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
|