@fml-inc/fml 0.8.7 → 0.8.10-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/{chunk-6BTC3S7C.js → chunk-2DGHAVVR.js} +1 -1
- package/dist/{chunk-LPSZCTTJ.js → chunk-2ZCXGYI5.js} +1 -1
- package/dist/{chunk-4YLSKFDU.js → chunk-5PEFBQNX.js} +107 -64
- package/dist/{chunk-XFALHTDL.js → chunk-5SI6S4HW.js} +2 -2
- package/dist/{chunk-LOJPIJZW.js → chunk-GDOXY4W2.js} +2 -2
- package/dist/{chunk-B3H2YWPJ.js → chunk-HDAFEHUY.js} +62 -14
- package/dist/{chunk-5JJQWV4G.js → chunk-JPHN4VKM.js} +1 -1
- package/dist/{chunk-PJWMSHHZ.js → chunk-WE7MAWAW.js} +1 -1
- package/dist/cli.js +20 -10
- package/dist/hook-handler.js +4 -4
- package/dist/mcp/server.js +2 -2
- package/dist/observer-server.js +53 -13
- package/dist/pi/extension.js +1427 -1198
- package/dist/sync-cycle.js +3 -3
- package/dist/telemetry-config-HRSNDMTG.js +148 -0
- package/dist/{token-store-ORR5MIJL.js → token-store-GYU3AXBK.js} +1 -1
- package/package.json +2 -2
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
FML_OBSERVER_LOCK_FILE,
|
|
4
4
|
FML_OBSERVER_PORT,
|
|
5
5
|
FML_OBSERVER_STATE_FILE
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HDAFEHUY.js";
|
|
7
7
|
|
|
8
8
|
// ../../packages/panopticon/src/observer/auth.ts
|
|
9
9
|
import crypto from "crypto";
|
|
@@ -695,6 +695,7 @@ var MAX_HOOK_DESTINATION_IDENTITY_BYTES = 4 * 1024;
|
|
|
695
695
|
var DEFAULT_OTLP_OUTBOX_BATCH_SIZE = 100;
|
|
696
696
|
var MAX_OTLP_OUTBOX_BATCH_SIZE = 100;
|
|
697
697
|
var MAX_OTLP_ENVELOPE_BYTES = 16 * 1024 * 1024;
|
|
698
|
+
var DEFAULT_OTLP_SPOOL_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
698
699
|
var DEFAULT_OTLP_SPOOL_MAX_BYTES = 1024 * 1024 * 1024;
|
|
699
700
|
var MAX_OTLP_ENVELOPE_ID_BYTES = 1024;
|
|
700
701
|
var MAX_OTLP_OBSERVER_INSTANCE_ID_BYTES = 4 * 1024;
|
|
@@ -703,8 +704,6 @@ var MAX_OTLP_DROP_REASON_BYTES = 4 * 1024;
|
|
|
703
704
|
var MAX_OTLP_DESTINATION_ORGANIZATION_ID_BYTES = 128;
|
|
704
705
|
var MAX_OTLP_DESTINATION_ORGANIZATION_SLUG_BYTES = 4 * 1024;
|
|
705
706
|
var OWNERLESS_OTLP_DROP_REASON = "ownerless";
|
|
706
|
-
var OTLP_CAPACITY_DROP_REASON = "spool_capacity";
|
|
707
|
-
var OTLP_ENTRY_TOO_LARGE_DROP_REASON = "spool_entry_too_large";
|
|
708
707
|
var OTLP_ROW_FIXED_LOGICAL_BYTES = 256;
|
|
709
708
|
var MAX_TIMESTAMP_MS = 864e13;
|
|
710
709
|
var QUARANTINE_PRUNE_INTERVAL_MS = 5 * 60 * 1e3;
|
|
@@ -1002,15 +1001,23 @@ function enforceOwnerOnlyMode(filePath, mode) {
|
|
|
1002
1001
|
function openObserverDatabase(databaseFile, options = {}) {
|
|
1003
1002
|
const maxHookSpoolBytes = options.maxHookSpoolBytes;
|
|
1004
1003
|
const maxOtlpSpoolBytes = options.maxOtlpSpoolBytes ?? DEFAULT_OTLP_SPOOL_MAX_BYTES;
|
|
1005
|
-
|
|
1006
|
-
if (maxHookSpoolBytes !== void 0 && (!Number.isSafeInteger(maxHookSpoolBytes) || maxHookSpoolBytes < 1)) {
|
|
1004
|
+
if (!Number.isSafeInteger(maxOtlpSpoolBytes) || maxOtlpSpoolBytes < 1) {
|
|
1007
1005
|
throw new Error(
|
|
1008
|
-
"
|
|
1006
|
+
"OTLP spool maximum must be a positive safe integer number of bytes"
|
|
1009
1007
|
);
|
|
1010
1008
|
}
|
|
1011
|
-
|
|
1009
|
+
const otlpLowWaterBytes = Math.floor(maxOtlpSpoolBytes * 0.9);
|
|
1010
|
+
let otlpCapacityCleanupActive = false;
|
|
1011
|
+
const maxOtlpSpoolAgeMs = options.maxOtlpSpoolAgeMs ?? DEFAULT_OTLP_SPOOL_MAX_AGE_MS;
|
|
1012
|
+
if (!Number.isSafeInteger(maxOtlpSpoolAgeMs) || maxOtlpSpoolAgeMs < 1) {
|
|
1012
1013
|
throw new Error(
|
|
1013
|
-
"OTLP spool maximum must be a positive safe integer number of
|
|
1014
|
+
"OTLP spool maximum age must be a positive safe integer number of milliseconds"
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
const maxHookQuarantineAgeMs = options.maxHookQuarantineAgeMs;
|
|
1018
|
+
if (maxHookSpoolBytes !== void 0 && (!Number.isSafeInteger(maxHookSpoolBytes) || maxHookSpoolBytes < 1)) {
|
|
1019
|
+
throw new Error(
|
|
1020
|
+
"Hook spool maximum must be a positive safe integer number of bytes"
|
|
1014
1021
|
);
|
|
1015
1022
|
}
|
|
1016
1023
|
if (maxHookQuarantineAgeMs !== void 0 && (!Number.isSafeInteger(maxHookQuarantineAgeMs) || maxHookQuarantineAgeMs < 1)) {
|
|
@@ -2031,27 +2038,24 @@ function openObserverDatabase(databaseFile, options = {}) {
|
|
|
2031
2038
|
last_drop_reason = ?
|
|
2032
2039
|
WHERE singleton = 1
|
|
2033
2040
|
`);
|
|
2034
|
-
const
|
|
2035
|
-
|
|
2036
|
-
SELECT
|
|
2037
|
-
logical_bytes,
|
|
2038
|
-
length(body) AS body_bytes,
|
|
2039
|
-
SUM(logical_bytes) OVER (ORDER BY id ASC) - logical_bytes
|
|
2040
|
-
AS preceding_bytes
|
|
2041
|
-
FROM otlp_envelope_outbox
|
|
2042
|
-
)
|
|
2043
|
-
SELECT
|
|
2044
|
-
COUNT(*) AS record_count,
|
|
2045
|
-
COALESCE(SUM(logical_bytes), 0) AS logical_bytes,
|
|
2046
|
-
COALESCE(SUM(body_bytes), 0) AS body_bytes
|
|
2047
|
-
FROM ordered
|
|
2048
|
-
WHERE preceding_bytes < ?
|
|
2041
|
+
const hasExpiredOtlpEnvelopes = database.prepare(`
|
|
2042
|
+
SELECT 1 FROM otlp_envelope_outbox WHERE captured_at_ms < ? LIMIT 1
|
|
2049
2043
|
`);
|
|
2050
|
-
const
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2044
|
+
const expiredOtlpEnvelopes = database.prepare(`
|
|
2045
|
+
SELECT id, logical_bytes, length(body) AS body_bytes
|
|
2046
|
+
FROM otlp_envelope_outbox
|
|
2047
|
+
WHERE captured_at_ms < ?
|
|
2048
|
+
ORDER BY captured_at_ms, id
|
|
2049
|
+
LIMIT 100
|
|
2050
|
+
`);
|
|
2051
|
+
const oldestOtlpEnvelopes = database.prepare(`
|
|
2052
|
+
SELECT id, logical_bytes, length(body) AS body_bytes
|
|
2053
|
+
FROM otlp_envelope_outbox
|
|
2054
|
+
ORDER BY captured_at_ms, id
|
|
2055
|
+
LIMIT 100
|
|
2056
|
+
`);
|
|
2057
|
+
const deleteExpiredOtlpEnvelope = database.prepare(`
|
|
2058
|
+
DELETE FROM otlp_envelope_outbox WHERE id = ?
|
|
2055
2059
|
`);
|
|
2056
2060
|
const getDestinationPendingOtlpEnvelopeAccounting = database.prepare(`
|
|
2057
2061
|
SELECT logical_bytes, length(body) AS body_bytes
|
|
@@ -2652,42 +2656,6 @@ function openObserverDatabase(databaseFile, options = {}) {
|
|
|
2652
2656
|
);
|
|
2653
2657
|
return null;
|
|
2654
2658
|
}
|
|
2655
|
-
if (logicalBytes > maxOtlpSpoolBytes) {
|
|
2656
|
-
recordOtlpDrop(
|
|
2657
|
-
1,
|
|
2658
|
-
logicalBytes,
|
|
2659
|
-
envelope.body.byteLength,
|
|
2660
|
-
capturedAtMs,
|
|
2661
|
-
OTLP_ENTRY_TOO_LARGE_DROP_REASON
|
|
2662
|
-
);
|
|
2663
|
-
return null;
|
|
2664
|
-
}
|
|
2665
|
-
const retainedBytes = requireSpoolInteger(
|
|
2666
|
-
getOtlpSpoolState.get(),
|
|
2667
|
-
"logical_bytes"
|
|
2668
|
-
);
|
|
2669
|
-
const bytesToFree = retainedBytes + logicalBytes - maxOtlpSpoolBytes;
|
|
2670
|
-
if (bytesToFree > 0) {
|
|
2671
|
-
const plan = otlpCapacityEvictionPlan.get(bytesToFree);
|
|
2672
|
-
const evictedRecords = requireSpoolInteger(plan, "record_count");
|
|
2673
|
-
const evictedLogicalBytes = requireSpoolInteger(
|
|
2674
|
-
plan,
|
|
2675
|
-
"logical_bytes"
|
|
2676
|
-
);
|
|
2677
|
-
const evictedBodyBytes = requireSpoolInteger(plan, "body_bytes");
|
|
2678
|
-
if (evictedRecords === 0 || evictedLogicalBytes < bytesToFree || evictOldestPendingOtlpEnvelopes.run(evictedRecords).changes !== evictedRecords) {
|
|
2679
|
-
throw new Error(
|
|
2680
|
-
"FML observer OTLP spool accounting could not enforce its limit"
|
|
2681
|
-
);
|
|
2682
|
-
}
|
|
2683
|
-
recordOtlpDrop(
|
|
2684
|
-
evictedRecords,
|
|
2685
|
-
evictedLogicalBytes,
|
|
2686
|
-
evictedBodyBytes,
|
|
2687
|
-
capturedAtMs,
|
|
2688
|
-
OTLP_CAPACITY_DROP_REASON
|
|
2689
|
-
);
|
|
2690
|
-
}
|
|
2691
2659
|
captureOtlpEnvelope.run(
|
|
2692
2660
|
envelopeId,
|
|
2693
2661
|
envelope.observerInstanceId,
|
|
@@ -2885,6 +2853,80 @@ function openObserverDatabase(databaseFile, options = {}) {
|
|
|
2885
2853
|
return droppedRecords;
|
|
2886
2854
|
});
|
|
2887
2855
|
},
|
|
2856
|
+
pruneExpiredOtlpEnvelopes: (nowMs = Date.now()) => {
|
|
2857
|
+
requireTimestamp(nowMs, "OTLP retention timestamp");
|
|
2858
|
+
const cutoffMs = nowMs - maxOtlpSpoolAgeMs;
|
|
2859
|
+
if (!hasExpiredOtlpEnvelopes.get(cutoffMs)) return 0;
|
|
2860
|
+
return runImmediateTransaction(() => {
|
|
2861
|
+
const rows = expiredOtlpEnvelopes.all(cutoffMs);
|
|
2862
|
+
let logicalBytes = 0;
|
|
2863
|
+
let bodyBytes = 0;
|
|
2864
|
+
for (const row of rows) {
|
|
2865
|
+
logicalBytes += requireSpoolInteger(row, "logical_bytes");
|
|
2866
|
+
bodyBytes += requireSpoolInteger(row, "body_bytes");
|
|
2867
|
+
if (deleteExpiredOtlpEnvelope.run(row.id).changes !== 1) {
|
|
2868
|
+
throw new Error(
|
|
2869
|
+
"FML observer OTLP retention deletion was incomplete"
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
recordOtlpDrop(
|
|
2874
|
+
rows.length,
|
|
2875
|
+
logicalBytes,
|
|
2876
|
+
bodyBytes,
|
|
2877
|
+
nowMs,
|
|
2878
|
+
"spool_expired"
|
|
2879
|
+
);
|
|
2880
|
+
return rows.length;
|
|
2881
|
+
});
|
|
2882
|
+
},
|
|
2883
|
+
pruneOtlpCapacity: (nowMs = Date.now()) => {
|
|
2884
|
+
requireTimestamp(nowMs, "OTLP capacity cleanup timestamp");
|
|
2885
|
+
const retainedBytes = requireSpoolInteger(
|
|
2886
|
+
getOtlpSpoolState.get(),
|
|
2887
|
+
"logical_bytes"
|
|
2888
|
+
);
|
|
2889
|
+
if (retainedBytes <= otlpLowWaterBytes)
|
|
2890
|
+
otlpCapacityCleanupActive = false;
|
|
2891
|
+
if (retainedBytes > maxOtlpSpoolBytes) otlpCapacityCleanupActive = true;
|
|
2892
|
+
if (!otlpCapacityCleanupActive) return 0;
|
|
2893
|
+
return runImmediateTransaction(() => {
|
|
2894
|
+
const currentBytes = requireSpoolInteger(
|
|
2895
|
+
getOtlpSpoolState.get(),
|
|
2896
|
+
"logical_bytes"
|
|
2897
|
+
);
|
|
2898
|
+
if (currentBytes <= otlpLowWaterBytes) {
|
|
2899
|
+
otlpCapacityCleanupActive = false;
|
|
2900
|
+
return 0;
|
|
2901
|
+
}
|
|
2902
|
+
let records = 0;
|
|
2903
|
+
let logicalBytes = 0;
|
|
2904
|
+
let bodyBytes = 0;
|
|
2905
|
+
for (const row of oldestOtlpEnvelopes.all()) {
|
|
2906
|
+
logicalBytes += requireSpoolInteger(row, "logical_bytes");
|
|
2907
|
+
bodyBytes += requireSpoolInteger(row, "body_bytes");
|
|
2908
|
+
if (deleteExpiredOtlpEnvelope.run(row.id).changes !== 1) {
|
|
2909
|
+
throw new Error(
|
|
2910
|
+
"FML observer OTLP capacity deletion was incomplete"
|
|
2911
|
+
);
|
|
2912
|
+
}
|
|
2913
|
+
records += 1;
|
|
2914
|
+
if (currentBytes - logicalBytes <= otlpLowWaterBytes) break;
|
|
2915
|
+
}
|
|
2916
|
+
if (records === 0)
|
|
2917
|
+
throw new Error(
|
|
2918
|
+
"FML observer OTLP capacity accounting is inconsistent"
|
|
2919
|
+
);
|
|
2920
|
+
recordOtlpDrop(
|
|
2921
|
+
records,
|
|
2922
|
+
logicalBytes,
|
|
2923
|
+
bodyBytes,
|
|
2924
|
+
nowMs,
|
|
2925
|
+
"spool_capacity"
|
|
2926
|
+
);
|
|
2927
|
+
return records;
|
|
2928
|
+
});
|
|
2929
|
+
},
|
|
2888
2930
|
getOtlpSpoolStatus: () => {
|
|
2889
2931
|
const row = getOtlpSpoolState.get();
|
|
2890
2932
|
const lastDroppedAtMs = row?.last_dropped_at_ms;
|
|
@@ -2898,6 +2940,7 @@ function openObserverDatabase(databaseFile, options = {}) {
|
|
|
2898
2940
|
return {
|
|
2899
2941
|
unit: "logical_bytes",
|
|
2900
2942
|
maxBytes: maxOtlpSpoolBytes,
|
|
2943
|
+
maxAgeMs: maxOtlpSpoolAgeMs,
|
|
2901
2944
|
logicalBytes: requireSpoolInteger(row, "logical_bytes"),
|
|
2902
2945
|
bodyBytes: requireSpoolInteger(row, "body_bytes"),
|
|
2903
2946
|
droppedRecords: requireSpoolInteger(row, "dropped_records"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Sentry
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HDAFEHUY.js";
|
|
4
4
|
|
|
5
5
|
// src/bin-utils.ts
|
|
6
6
|
import fs from "fs";
|
|
@@ -53,7 +53,7 @@ var PACKAGE_NAME = "@fml-inc/fml";
|
|
|
53
53
|
var UPDATE_TIMEOUT_MS = 12e4;
|
|
54
54
|
var SETUP_TIMEOUT_MS = 3e5;
|
|
55
55
|
function getCurrentVersion() {
|
|
56
|
-
return true ? "0.8.
|
|
56
|
+
return true ? "0.8.10-dev.1+09fae5b6" : "unknown";
|
|
57
57
|
}
|
|
58
58
|
function parseVersion(version) {
|
|
59
59
|
const match = SEMVER_PATTERN.exec(version);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getSelectedOrg,
|
|
8
8
|
getSiteUrlForConvexUrl,
|
|
9
9
|
getValidToken
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HDAFEHUY.js";
|
|
11
11
|
|
|
12
12
|
// src/fml-client.ts
|
|
13
13
|
var LOGIN_EXPIRED_MESSAGE = "Authentication expired. Run `fml login` to sign in again, then restart Claude Code.";
|
|
@@ -79,7 +79,7 @@ function createFmlClient(token, options = {}) {
|
|
|
79
79
|
const repo = resolveRepoFromCwd(process.cwd());
|
|
80
80
|
if (repo) body.repo = repo.repo;
|
|
81
81
|
if (isServiceToken) {
|
|
82
|
-
const { readTokens, SERVICE_TOKEN_LOGIN_USER_ID } = await import("./token-store-
|
|
82
|
+
const { readTokens, SERVICE_TOKEN_LOGIN_USER_ID } = await import("./token-store-GYU3AXBK.js");
|
|
83
83
|
const stored = readTokens(options.envName);
|
|
84
84
|
const storedUserExternalId = stored?.tokenType === "service" && stored.user.id !== SERVICE_TOKEN_LOGIN_USER_ID ? stored.user.id : void 0;
|
|
85
85
|
const userExternalId = process.env.FML_USER_EXTERNAL_ID ?? storedUserExternalId;
|
|
@@ -193,6 +193,7 @@ function ensureDirs() {
|
|
|
193
193
|
|
|
194
194
|
// src/config.ts
|
|
195
195
|
var DEFAULT_PROD_URL = "https://api.fml.inc";
|
|
196
|
+
var DEFAULT_SYNC_URL = DEFAULT_PROD_URL;
|
|
196
197
|
var DEFAULT_TARGET_NAME = "fml";
|
|
197
198
|
var LEGACY_HOSTED_BACKEND_URLS = [
|
|
198
199
|
"https://trustworthy-chihuahua-382.convex.site"
|
|
@@ -338,9 +339,6 @@ function getSiteUrlForConvexUrl(convexUrl) {
|
|
|
338
339
|
var initialized = false;
|
|
339
340
|
var sentry = null;
|
|
340
341
|
var client = null;
|
|
341
|
-
function isSentryEnabled() {
|
|
342
|
-
return process.env.SENTRY_ENABLED === "true";
|
|
343
|
-
}
|
|
344
342
|
async function loadSentry() {
|
|
345
343
|
if (sentry) return sentry;
|
|
346
344
|
try {
|
|
@@ -350,15 +348,35 @@ async function loadSentry() {
|
|
|
350
348
|
return null;
|
|
351
349
|
}
|
|
352
350
|
}
|
|
353
|
-
async function initSentry() {
|
|
354
|
-
if (initialized) return;
|
|
351
|
+
async function initSentry(forceRefresh = false) {
|
|
352
|
+
if (initialized && !forceRefresh) return;
|
|
355
353
|
initialized = true;
|
|
356
|
-
|
|
354
|
+
let config;
|
|
355
|
+
try {
|
|
356
|
+
const { resolveCliSentryConfig } = await import("./telemetry-config-HRSNDMTG.js");
|
|
357
|
+
config = process.env.SENTRY_ENABLED === "false" ? null : await resolveCliSentryConfig(
|
|
358
|
+
process.env.SENTRY_ENABLED === "true" && true ? "https://4c243521c03917c886d0bf33bc0038c8@o4510167429873664.ingest.us.sentry.io/4511078213156864" : "",
|
|
359
|
+
forceRefresh
|
|
360
|
+
);
|
|
361
|
+
} catch {
|
|
362
|
+
config = null;
|
|
363
|
+
}
|
|
364
|
+
if (client) {
|
|
365
|
+
try {
|
|
366
|
+
await client.close(2e3);
|
|
367
|
+
} catch {
|
|
368
|
+
}
|
|
369
|
+
client = null;
|
|
370
|
+
}
|
|
371
|
+
if (!config?.dsn) {
|
|
372
|
+
sentry?.getCurrentScope().setClient(void 0);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
357
375
|
const mod = await loadSentry();
|
|
358
376
|
if (!mod) return;
|
|
359
377
|
client = new mod.ServerRuntimeClient({
|
|
360
|
-
dsn:
|
|
361
|
-
environment:
|
|
378
|
+
dsn: config.dsn,
|
|
379
|
+
environment: config.environment,
|
|
362
380
|
tracesSampleRate: 0,
|
|
363
381
|
integrations: [],
|
|
364
382
|
stackParser: mod.createStackParser(mod.nodeStackLineParser()),
|
|
@@ -1378,7 +1396,7 @@ async function getValidToken(opts) {
|
|
|
1378
1396
|
return stored.accessToken;
|
|
1379
1397
|
}
|
|
1380
1398
|
if (stored.tokenType === "service") {
|
|
1381
|
-
|
|
1399
|
+
const accessToken2 = await getOrStartTokenRefresh(
|
|
1382
1400
|
serviceRefreshPromises,
|
|
1383
1401
|
key,
|
|
1384
1402
|
forceRefresh,
|
|
@@ -1424,6 +1442,12 @@ async function getValidToken(opts) {
|
|
|
1424
1442
|
}),
|
|
1425
1443
|
opts?.signal
|
|
1426
1444
|
);
|
|
1445
|
+
await refreshTelemetryConfigAfterTokenRefresh(
|
|
1446
|
+
envName,
|
|
1447
|
+
accessToken2,
|
|
1448
|
+
opts?.signal
|
|
1449
|
+
);
|
|
1450
|
+
return accessToken2;
|
|
1427
1451
|
}
|
|
1428
1452
|
if (stored.refreshInvalidAt) {
|
|
1429
1453
|
console.error(
|
|
@@ -1431,13 +1455,34 @@ async function getValidToken(opts) {
|
|
|
1431
1455
|
);
|
|
1432
1456
|
return null;
|
|
1433
1457
|
}
|
|
1434
|
-
|
|
1458
|
+
const accessToken = await getOrStartTokenRefresh(
|
|
1435
1459
|
oauthRefreshPromises,
|
|
1436
1460
|
key,
|
|
1437
1461
|
forceRefresh,
|
|
1438
1462
|
() => refreshTokenWithLock(envName, forceRefresh, opts?.signal),
|
|
1439
1463
|
opts?.signal
|
|
1440
1464
|
);
|
|
1465
|
+
await refreshTelemetryConfigAfterTokenRefresh(
|
|
1466
|
+
envName,
|
|
1467
|
+
accessToken,
|
|
1468
|
+
opts?.signal
|
|
1469
|
+
);
|
|
1470
|
+
return accessToken;
|
|
1471
|
+
}
|
|
1472
|
+
async function refreshTelemetryConfigAfterTokenRefresh(envName, accessToken, signal) {
|
|
1473
|
+
if (!accessToken || signal?.aborted) return;
|
|
1474
|
+
try {
|
|
1475
|
+
const current = readTokens(envName);
|
|
1476
|
+
if (current?.accessToken !== accessToken) return;
|
|
1477
|
+
const { refreshCliTelemetryConfig } = await import("./telemetry-config-HRSNDMTG.js");
|
|
1478
|
+
await refreshCliTelemetryConfig({
|
|
1479
|
+
envName,
|
|
1480
|
+
accessToken,
|
|
1481
|
+
siteUrl: current.siteUrl,
|
|
1482
|
+
signal
|
|
1483
|
+
});
|
|
1484
|
+
} catch {
|
|
1485
|
+
}
|
|
1441
1486
|
}
|
|
1442
1487
|
async function refreshTokenWithLock(envName, forceRefresh = false, signal) {
|
|
1443
1488
|
const lock = await acquireRefreshLock(envName, signal);
|
|
@@ -1543,7 +1588,9 @@ async function refreshToken(stored, lock, envName, signal) {
|
|
|
1543
1588
|
},
|
|
1544
1589
|
orgId: stored.orgId,
|
|
1545
1590
|
orgSlug: stored.orgSlug,
|
|
1546
|
-
workosClientId: stored.workosClientId
|
|
1591
|
+
workosClientId: stored.workosClientId,
|
|
1592
|
+
// The backend this login belongs to does not change on rotation.
|
|
1593
|
+
...stored.siteUrl ? { siteUrl: stored.siteUrl } : {}
|
|
1547
1594
|
};
|
|
1548
1595
|
const pendingPath = stagePendingOAuthRefresh(
|
|
1549
1596
|
stored.refreshToken,
|
|
@@ -1580,8 +1627,6 @@ async function refreshToken(stored, lock, envName, signal) {
|
|
|
1580
1627
|
}
|
|
1581
1628
|
|
|
1582
1629
|
export {
|
|
1583
|
-
initSentry,
|
|
1584
|
-
Sentry,
|
|
1585
1630
|
resolveFmlDefaultDirectories,
|
|
1586
1631
|
FML_DATA_DIR,
|
|
1587
1632
|
FML_STATE_DIR,
|
|
@@ -1606,6 +1651,7 @@ export {
|
|
|
1606
1651
|
observerOnlyOverrideWarning,
|
|
1607
1652
|
ensureDirs,
|
|
1608
1653
|
DEFAULT_PROD_URL,
|
|
1654
|
+
DEFAULT_SYNC_URL,
|
|
1609
1655
|
DEFAULT_TARGET_NAME,
|
|
1610
1656
|
isHostedBackendUrl,
|
|
1611
1657
|
isValidEnvName,
|
|
@@ -1632,5 +1678,7 @@ export {
|
|
|
1632
1678
|
SERVICE_TOKEN_LOGIN_USER_ID,
|
|
1633
1679
|
clearStoredCredentials,
|
|
1634
1680
|
storeServiceRefreshToken,
|
|
1635
|
-
getValidToken
|
|
1681
|
+
getValidToken,
|
|
1682
|
+
initSentry,
|
|
1683
|
+
Sentry
|
|
1636
1684
|
};
|
package/dist/cli.js
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFmlClient,
|
|
4
4
|
getAuthenticatedClient
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GDOXY4W2.js";
|
|
6
6
|
import {
|
|
7
7
|
execBinSync,
|
|
8
8
|
handleUpdate,
|
|
9
9
|
resolveBin
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5SI6S4HW.js";
|
|
11
11
|
import {
|
|
12
12
|
openObserverLog,
|
|
13
13
|
readJsonFile,
|
|
14
14
|
setHookCaptureDisabled,
|
|
15
15
|
writeJsonFile,
|
|
16
16
|
writeTextFileAtomic
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-2ZCXGYI5.js";
|
|
18
18
|
import {
|
|
19
19
|
CODEX_HOOK_EVENTS,
|
|
20
20
|
GEMINI_HOOK_EVENTS,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
readObserverAuthToken,
|
|
30
30
|
readObserverStateStatus,
|
|
31
31
|
removeObserverStateIfOwned
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-5PEFBQNX.js";
|
|
33
33
|
import "./chunk-7V7G7NVF.js";
|
|
34
34
|
import {
|
|
35
35
|
claudeConfigDirectory,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
geminiConfigDirectory,
|
|
39
39
|
initializeSyncSettings,
|
|
40
40
|
runRawSyncOnce
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-JPHN4VKM.js";
|
|
42
42
|
import {
|
|
43
43
|
resolvePackageRoot
|
|
44
44
|
} from "./chunk-F57IFY3K.js";
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
storeServiceRefreshToken,
|
|
87
87
|
writeEnvConfig,
|
|
88
88
|
writeTokens
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-HDAFEHUY.js";
|
|
90
90
|
import "./chunk-MLKGABMK.js";
|
|
91
91
|
|
|
92
92
|
// src/cli.ts
|
|
@@ -132,7 +132,7 @@ var STOP_TIMEOUT_MS = 5e3;
|
|
|
132
132
|
var FORCE_STOP_TIMEOUT_MS = 2e3;
|
|
133
133
|
var POLL_INTERVAL_MS = 50;
|
|
134
134
|
function expectedObserverVersion() {
|
|
135
|
-
return true ? "0.8.
|
|
135
|
+
return true ? "0.8.10-dev.1+09fae5b6" : "dev";
|
|
136
136
|
}
|
|
137
137
|
function delay(ms) {
|
|
138
138
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -7438,6 +7438,7 @@ async function runServiceTokenLogin(refreshToken, backendUrl) {
|
|
|
7438
7438
|
throw new Error("Service token login failed.");
|
|
7439
7439
|
}
|
|
7440
7440
|
commitLoginEnvironment(environment);
|
|
7441
|
+
await initSentry(true);
|
|
7441
7442
|
await selectOrg(environment);
|
|
7442
7443
|
console.log("Logged in with FML service token.");
|
|
7443
7444
|
console.log(
|
|
@@ -7478,6 +7479,7 @@ async function runInteractiveLogin(opts = {}) {
|
|
|
7478
7479
|
);
|
|
7479
7480
|
}
|
|
7480
7481
|
await linkGitHubIdentity(environment);
|
|
7482
|
+
await initSentry(true);
|
|
7481
7483
|
await selectOrg(environment);
|
|
7482
7484
|
return;
|
|
7483
7485
|
}
|
|
@@ -7492,6 +7494,7 @@ async function runInteractiveLogin(opts = {}) {
|
|
|
7492
7494
|
commitLoginEnvironment(environment);
|
|
7493
7495
|
console.log(`Logged in as ${result.name} (${result.email})`);
|
|
7494
7496
|
await linkGitHubIdentity(environment);
|
|
7497
|
+
await initSentry(true);
|
|
7495
7498
|
await selectOrg(environment);
|
|
7496
7499
|
}
|
|
7497
7500
|
async function handleLogin(opts) {
|
|
@@ -8159,6 +8162,7 @@ function otlpSpoolStatus(value) {
|
|
|
8159
8162
|
const logicalBytes = nonNegativeInteger("logicalBytes");
|
|
8160
8163
|
const bodyBytes = nonNegativeInteger("bodyBytes");
|
|
8161
8164
|
const maxBytes = nonNegativeInteger("maxBytes");
|
|
8165
|
+
const maxAgeMs = nonNegativeInteger("maxAgeMs");
|
|
8162
8166
|
const droppedRecords = nonNegativeInteger("droppedRecords");
|
|
8163
8167
|
const droppedLogicalBytes = nonNegativeInteger("droppedLogicalBytes");
|
|
8164
8168
|
const droppedBodyBytes = nonNegativeInteger("droppedBodyBytes");
|
|
@@ -8169,6 +8173,7 @@ function otlpSpoolStatus(value) {
|
|
|
8169
8173
|
logicalBytes,
|
|
8170
8174
|
bodyBytes,
|
|
8171
8175
|
maxBytes,
|
|
8176
|
+
...maxAgeMs !== void 0 && maxAgeMs > 0 ? { maxAgeMs } : {},
|
|
8172
8177
|
droppedRecords,
|
|
8173
8178
|
droppedLogicalBytes,
|
|
8174
8179
|
droppedBodyBytes,
|
|
@@ -8360,9 +8365,14 @@ async function handleStatus() {
|
|
|
8360
8365
|
console.log(
|
|
8361
8366
|
` Spool: ${formatBytes2(otlp.spool.logicalBytes)} / ${formatBytes2(otlp.spool.maxBytes)} (${usedPercent.toFixed(1)}%; ${formatBytes2(otlp.spool.bodyBytes)} encoded bodies)`
|
|
8362
8367
|
);
|
|
8368
|
+
if (otlp.spool.maxAgeMs !== void 0) {
|
|
8369
|
+
console.log(
|
|
8370
|
+
` Retention: ${otlp.spool.maxAgeMs / 36e5} hour(s) (background cleanup)`
|
|
8371
|
+
);
|
|
8372
|
+
}
|
|
8363
8373
|
if (usedPercent >= 80) {
|
|
8364
8374
|
console.log(
|
|
8365
|
-
` Attention:
|
|
8375
|
+
` Attention: background cleanup removes oldest telemetry toward 90% of the ${formatBytes2(otlp.spool.maxBytes)} byte target after overflow; checks run every 5 minutes`
|
|
8366
8376
|
);
|
|
8367
8377
|
}
|
|
8368
8378
|
if (otlp.spool.droppedRecords > 0) {
|
|
@@ -8997,7 +9007,7 @@ async function handleConfigDetail(opts) {
|
|
|
8997
9007
|
// src/commands/tools.ts
|
|
8998
9008
|
import { readFileSync } from "fs";
|
|
8999
9009
|
import path29 from "path";
|
|
9000
|
-
var pluginVersion = true ? "0.8.
|
|
9010
|
+
var pluginVersion = true ? "0.8.10-dev.1+09fae5b6" : void 0;
|
|
9001
9011
|
async function getApi() {
|
|
9002
9012
|
const api = await getAuthenticatedClient();
|
|
9003
9013
|
if (!api) {
|
|
@@ -9154,7 +9164,7 @@ if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.
|
|
|
9154
9164
|
printBanner();
|
|
9155
9165
|
}
|
|
9156
9166
|
var program = new Command().name("fml").description("FML CLI and agent tools").version(
|
|
9157
|
-
true ? "0.8.
|
|
9167
|
+
true ? "0.8.10-dev.1+09fae5b6" : "dev"
|
|
9158
9168
|
);
|
|
9159
9169
|
function formatCommandInventory(cmd, prefix = "") {
|
|
9160
9170
|
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
|
package/dist/hook-handler.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
hookCaptureIsDisabled,
|
|
4
4
|
openObserverLog
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2ZCXGYI5.js";
|
|
6
6
|
import {
|
|
7
7
|
getActiveHookDestinationBinding
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WE7MAWAW.js";
|
|
9
9
|
import {
|
|
10
10
|
HookInboxCapacityError,
|
|
11
11
|
OBSERVER_HEARTBEAT_STALE_MS,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
readObserverAuthToken,
|
|
20
20
|
readObserverState,
|
|
21
21
|
recordHookInboxLoss
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-5PEFBQNX.js";
|
|
23
23
|
import {
|
|
24
24
|
resolveRepositoryRootFromCwd,
|
|
25
25
|
resolveRepositorySlugFromCwd
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
FML_OBSERVER_ENDPOINT_FILE,
|
|
36
36
|
FML_OBSERVER_STATE_FILE,
|
|
37
37
|
getValidToken
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-HDAFEHUY.js";
|
|
39
39
|
import "./chunk-MLKGABMK.js";
|
|
40
40
|
|
|
41
41
|
// src/hooks/handler.ts
|
package/dist/mcp/server.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFmlClient,
|
|
4
4
|
getAuthenticatedClient
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-GDOXY4W2.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveRepoFromCwd
|
|
8
8
|
} from "../chunk-7V7G7NVF.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
getValidToken,
|
|
18
18
|
initSentry,
|
|
19
19
|
readTokens
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-HDAFEHUY.js";
|
|
21
21
|
import "../chunk-MLKGABMK.js";
|
|
22
22
|
|
|
23
23
|
// src/mcp/server.ts
|