failproofai 1.0.4-beta.4 → 1.0.4-beta.6
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +5 -5
- package/.next/standalone/.next/server/app/audit/page.js +3 -3
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +4 -4
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +4 -4
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +3 -3
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js +2 -2
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0--lkk6._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q0qzx1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +4 -4
- package/.next/standalone/.next/server/chunks/lib_factory-projects_ts_1eo_bk-._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0p-5p8u._.js → [root-of-the-server]__0-4ja6q._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1p2otjt._.js → [root-of-the-server]__00cr3xu._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__013jr2b._.js → [root-of-the-server]__04px77e._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__190won8._.js → [root-of-the-server]__0dxf928._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0s740oi._.js → [root-of-the-server]__0egr5s1._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01wy8d-._.js → [root-of-the-server]__0i0l1di._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0n_lxhg._.js → [root-of-the-server]__0kokc8z._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1ctpynv._.js → [root-of-the-server]__0n2txhk._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__02npjtd._.js → [root-of-the-server]__0r3c1_0._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ftmoxc._.js → [root-of-the-server]__17xnxlx._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0da85px._.js → [root-of-the-server]__1ckpmkk._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__00-s7h8._.js → [root-of-the-server]__1fvfw59._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0yl9wb5._.js → [root-of-the-server]__1ui5ur8._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0guxnh-._.js → _02b3i98._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_04ng_6x._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_1u8-lu2._.js → _07t3jol._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0h_douw._.js → _0s-77v5._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1ddpc5g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +4 -14
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +22 -22
- package/.next/standalone/.next/static/chunks/{364cqbpeg1y5i.js → 07c6l1lq5_69b.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2bxr2_2h4kaqq.js → 12bsgz8czvcnn.js} +1 -1
- package/.next/standalone/.next/static/chunks/{38dqur43qthrl.js → 1gn08w2pgqh09.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1i-i0pxg9q_8y.js → 1xgq22tri86an.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17tfki9x5rd_7.js → 20xkiqzvfkuvm.js} +1 -1
- package/.next/standalone/.next/static/chunks/{42gwu2bsz4ske.js → 2a84ug32tzik2.js} +2 -2
- package/.next/standalone/.next/static/chunks/{0po8n4tyotjf2.js → 32m2ryfankf_2.js} +1 -1
- package/.next/standalone/.next/static/chunks/3ioub_lpen-sq.js +1 -0
- package/.next/standalone/.next/static/chunks/{323cyb3a2s06y.js → 3jxd133cw2vm3.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0qx7gav1c2_vu.js → 44ncu88eq6z71.js} +1 -1
- package/.next/standalone/app/actions/get-leaks.ts +0 -5
- package/.next/standalone/app/actions/update-scheduled-audit.ts +4 -56
- package/.next/standalone/app/api/auth/status/route.ts +3 -2
- package/.next/standalone/app/settings/page.tsx +1 -1
- package/.next/standalone/app/settings/settings-client.tsx +13 -39
- package/.next/standalone/lib/auth/api-server-client.ts +6 -6
- package/.next/standalone/lib/codex-sessions.ts +20 -4
- package/.next/standalone/lib/copilot-sessions.ts +32 -1
- package/.next/standalone/lib/cursor-sessions.ts +62 -5
- package/.next/standalone/package.json +9 -9
- package/.next/standalone/server.js +1 -1
- package/dist/cli.mjs +952 -1063
- package/dist/worker.mjs +173 -380
- package/lib/auth/api-server-client.ts +6 -6
- package/lib/codex-sessions.ts +20 -4
- package/lib/copilot-sessions.ts +32 -1
- package/lib/cursor-sessions.ts +62 -5
- package/package.json +9 -9
- package/pi-extension/index.ts +10 -18
- package/src/audit/cli.ts +72 -81
- package/src/audit/harm-report.ts +12 -6
- package/src/audit/index.ts +2 -0
- package/src/audit/leak-fingerprint.ts +2 -4
- package/src/audit/leak-record.ts +13 -9
- package/src/audit/leak-scan.ts +1 -1
- package/src/audit/leak-store.ts +1 -46
- package/src/audit/machine-store.ts +8 -9
- package/src/audit/macos-notifier.ts +2 -2
- package/src/audit/redact-example.ts +2 -0
- package/src/audit/report-harm.ts +31 -46
- package/src/audit/schedule-cli.ts +17 -33
- package/src/audit/types.ts +5 -0
- package/src/hooks/configure-wizard.ts +28 -0
- package/src/hooks/fp-config.ts +29 -54
- package/src/hooks/handler.ts +1 -79
- package/src/hooks/integrations.ts +4 -15
- package/src/hooks/notice.ts +12 -179
- package/.next/standalone/.next/server/chunks/ssr/_0oq1dh6._.js +0 -3
- package/.next/standalone/.next/static/chunks/04o5zfl7p5lhx.js +0 -1
- package/src/audit/leak-notice.ts +0 -259
- /package/.next/standalone/.next/static/{P6icI2V2PvVuePJrqjHCr → aeM365dNTtUZOZvNkX8ba}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{P6icI2V2PvVuePJrqjHCr → aeM365dNTtUZOZvNkX8ba}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{P6icI2V2PvVuePJrqjHCr → aeM365dNTtUZOZvNkX8ba}/_ssgManifest.js +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -29,7 +29,7 @@ var __esm = (fn, res, err) => () => {
|
|
|
29
29
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
30
30
|
|
|
31
31
|
// package.json
|
|
32
|
-
var version2 = "1.0.4-beta.
|
|
32
|
+
var version2 = "1.0.4-beta.6", package_default;
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "failproofai",
|
|
@@ -154,16 +154,16 @@ var init_package = __esm(() => {
|
|
|
154
154
|
browserslist: "4.28.8"
|
|
155
155
|
},
|
|
156
156
|
optionalDependencies: {
|
|
157
|
-
"@failproofai/failproofaid-linux-x64": "1.0.4-beta.
|
|
158
|
-
"@failproofai/failproofaid-linux-arm64": "1.0.4-beta.
|
|
159
|
-
"@failproofai/failproofaid-darwin-x64": "1.0.4-beta.
|
|
160
|
-
"@failproofai/failproofaid-darwin-arm64": "1.0.4-beta.
|
|
157
|
+
"@failproofai/failproofaid-linux-x64": "1.0.4-beta.6",
|
|
158
|
+
"@failproofai/failproofaid-linux-arm64": "1.0.4-beta.6",
|
|
159
|
+
"@failproofai/failproofaid-darwin-x64": "1.0.4-beta.6",
|
|
160
|
+
"@failproofai/failproofaid-darwin-arm64": "1.0.4-beta.6"
|
|
161
161
|
},
|
|
162
162
|
failproofaidBinaries: {
|
|
163
|
-
"linux-x64": "
|
|
164
|
-
"linux-arm64": "
|
|
165
|
-
"darwin-x64": "
|
|
166
|
-
"darwin-arm64": "
|
|
163
|
+
"linux-x64": "24118b8bd058cc5d8711053c4c77cdca9361c12dbf0f421a757d33f07596d428",
|
|
164
|
+
"linux-arm64": "b4278c34a288de2c747bcebcc623d8fd5bda3a1f1e55800926eb1a4b89f0a5e9",
|
|
165
|
+
"darwin-x64": "ecb66699f45f605b0d54ac9e4bac360ac11e4e136442dcccdd083514d77c7d42",
|
|
166
|
+
"darwin-arm64": "b3dbad58bda960ef9481f90bc5085ba8624b2472519cc0bf212a0e8451dd2db4"
|
|
167
167
|
}
|
|
168
168
|
};
|
|
169
169
|
});
|
|
@@ -11810,19 +11810,6 @@ async function applyDecision(result, ctx, eventName) {
|
|
|
11810
11810
|
if (out && out.decision && out.decision.behavior === "deny") {
|
|
11811
11811
|
throw new Error((out.decision.message) || "Blocked by failproofai");
|
|
11812
11812
|
}
|
|
11813
|
-
const notice = parsed.failproofaiNotice;
|
|
11814
|
-
if (typeof notice === "string" && notice && ctx && ctx.client && ctx.client.tui) {
|
|
11815
|
-
try {
|
|
11816
|
-
await ctx.client.tui.showToast({
|
|
11817
|
-
body: {
|
|
11818
|
-
title: "failproofai audit",
|
|
11819
|
-
message: notice,
|
|
11820
|
-
variant: "warning",
|
|
11821
|
-
duration: 12_000,
|
|
11822
|
-
},
|
|
11823
|
-
});
|
|
11824
|
-
} catch { /* a courtesy notice must never break the host hook */ }
|
|
11825
|
-
}
|
|
11826
11813
|
// Forward additional context as a prompt to the session. For Stop /
|
|
11827
11814
|
// SubagentStop the prompt is the only force-retry channel (session.idle
|
|
11828
11815
|
// already fired), so AWAIT to ensure the SDK round-trip completes before
|
|
@@ -11878,7 +11865,10 @@ export default async function failproofaiPlugin({ client, directory }) {
|
|
|
11878
11865
|
const claudeEvent = BUS_EVENT_MAP[event.type];
|
|
11879
11866
|
if (!claudeEvent) return;
|
|
11880
11867
|
const props = event.properties || {};
|
|
11881
|
-
const
|
|
11868
|
+
const info = props.info || props.session || {};
|
|
11869
|
+
|
|
11870
|
+
const sessionID = info.id || info.sessionID || info.sessionId || info.session_id ||
|
|
11871
|
+
props.sessionID || props.sessionId || props.session_id || props.id;
|
|
11882
11872
|
const r = await runFailproofai(claudeEvent, {
|
|
11883
11873
|
session_id: sessionID, cwd: directory, hook_event_name: claudeEvent,
|
|
11884
11874
|
}, directory);
|
|
@@ -16493,432 +16483,6 @@ var init_delivery_health = __esm(() => {
|
|
|
16493
16483
|
};
|
|
16494
16484
|
});
|
|
16495
16485
|
|
|
16496
|
-
// src/hooks/notice.ts
|
|
16497
|
-
function shapeNotice(cli, notice, existingStdout = "") {
|
|
16498
|
-
const empty = { stdout: existingStdout, stderr: "" };
|
|
16499
|
-
if (!notice.trim() || !cli)
|
|
16500
|
-
return empty;
|
|
16501
|
-
const channel = NOTICE_CHANNEL[cli] ?? "none";
|
|
16502
|
-
const text = notice.length > MAX_NOTICE_CHARS ? notice.slice(0, MAX_NOTICE_CHARS - 1) + "…" : notice;
|
|
16503
|
-
switch (channel) {
|
|
16504
|
-
case "systemMessage": {
|
|
16505
|
-
if (existingStdout.trim().startsWith("{")) {
|
|
16506
|
-
try {
|
|
16507
|
-
const parsed = JSON.parse(existingStdout);
|
|
16508
|
-
parsed.systemMessage = text;
|
|
16509
|
-
return { stdout: JSON.stringify(parsed), stderr: "" };
|
|
16510
|
-
} catch {
|
|
16511
|
-
return empty;
|
|
16512
|
-
}
|
|
16513
|
-
}
|
|
16514
|
-
if (existingStdout.trim())
|
|
16515
|
-
return empty;
|
|
16516
|
-
return { stdout: JSON.stringify({ systemMessage: text }), stderr: "" };
|
|
16517
|
-
}
|
|
16518
|
-
case "stderr":
|
|
16519
|
-
return { stdout: existingStdout, stderr: text + `
|
|
16520
|
-
` };
|
|
16521
|
-
case "stdout":
|
|
16522
|
-
if (existingStdout.trim())
|
|
16523
|
-
return empty;
|
|
16524
|
-
return { stdout: text + `
|
|
16525
|
-
`, stderr: "" };
|
|
16526
|
-
case "shim": {
|
|
16527
|
-
if (existingStdout.trim().startsWith("{")) {
|
|
16528
|
-
try {
|
|
16529
|
-
const parsed = JSON.parse(existingStdout);
|
|
16530
|
-
parsed.failproofaiNotice = text;
|
|
16531
|
-
return { stdout: JSON.stringify(parsed), stderr: "" };
|
|
16532
|
-
} catch {
|
|
16533
|
-
return empty;
|
|
16534
|
-
}
|
|
16535
|
-
}
|
|
16536
|
-
if (existingStdout.trim())
|
|
16537
|
-
return empty;
|
|
16538
|
-
return { stdout: JSON.stringify({ failproofaiNotice: text }), stderr: "" };
|
|
16539
|
-
}
|
|
16540
|
-
default:
|
|
16541
|
-
return empty;
|
|
16542
|
-
}
|
|
16543
|
-
}
|
|
16544
|
-
function canDeliverNotice(cli) {
|
|
16545
|
-
return !!cli && (NOTICE_CHANNEL[cli] ?? "none") !== "none";
|
|
16546
|
-
}
|
|
16547
|
-
function leakNoticeText(newFindings) {
|
|
16548
|
-
const n = newFindings === 1 ? "a possible credential exposure" : `${newFindings} possible credential exposures`;
|
|
16549
|
-
return `failproofai found ${n} in this project's agent transcripts.
|
|
16550
|
-
` + "Run `failproofai audit` to review the matches and rotate anything real.";
|
|
16551
|
-
}
|
|
16552
|
-
function desktopLeakNotice() {
|
|
16553
|
-
return {
|
|
16554
|
-
title: "failproofai audit needs review",
|
|
16555
|
-
body: "Possible credential exposure was found in your agent transcripts. " + "Run failproofai audit to verify the matches and rotate anything real."
|
|
16556
|
-
};
|
|
16557
|
-
}
|
|
16558
|
-
var NOTICE_CHANNEL, MAX_NOTICE_CHARS = 900;
|
|
16559
|
-
var init_notice = __esm(() => {
|
|
16560
|
-
NOTICE_CHANNEL = {
|
|
16561
|
-
claude: "systemMessage",
|
|
16562
|
-
codex: "systemMessage",
|
|
16563
|
-
copilot: "stderr",
|
|
16564
|
-
factory: "stdout",
|
|
16565
|
-
opencode: "shim",
|
|
16566
|
-
pi: "shim"
|
|
16567
|
-
};
|
|
16568
|
-
});
|
|
16569
|
-
|
|
16570
|
-
// lib/atomic-write.ts
|
|
16571
|
-
import {
|
|
16572
|
-
chmodSync as chmodSync2,
|
|
16573
|
-
existsSync as existsSync11,
|
|
16574
|
-
mkdirSync as mkdirSync7,
|
|
16575
|
-
renameSync as renameSync4,
|
|
16576
|
-
rmSync as rmSync3,
|
|
16577
|
-
statSync as statSync7,
|
|
16578
|
-
writeFileSync as writeFileSync6
|
|
16579
|
-
} from "node:fs";
|
|
16580
|
-
import { dirname as dirname7 } from "node:path";
|
|
16581
|
-
import { randomBytes } from "node:crypto";
|
|
16582
|
-
function writeJsonAtomically(filePath, value, opts = {}) {
|
|
16583
|
-
const mode = opts.mode ?? 384;
|
|
16584
|
-
const dirMode = opts.dirMode ?? 448;
|
|
16585
|
-
const dir = dirname7(filePath);
|
|
16586
|
-
if (!existsSync11(dir))
|
|
16587
|
-
mkdirSync7(dir, { recursive: true, mode: dirMode });
|
|
16588
|
-
const tmp = `${filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
16589
|
-
try {
|
|
16590
|
-
writeFileSync6(tmp, JSON.stringify(value, null, 2), { mode });
|
|
16591
|
-
try {
|
|
16592
|
-
if ((statSync7(tmp).mode & 63) !== 0)
|
|
16593
|
-
chmodSync2(tmp, mode);
|
|
16594
|
-
} catch {}
|
|
16595
|
-
renameSync4(tmp, filePath);
|
|
16596
|
-
try {
|
|
16597
|
-
if ((statSync7(filePath).mode & 63) !== 0)
|
|
16598
|
-
chmodSync2(filePath, mode);
|
|
16599
|
-
} catch {}
|
|
16600
|
-
} catch (err) {
|
|
16601
|
-
try {
|
|
16602
|
-
rmSync3(tmp, { force: true });
|
|
16603
|
-
} catch {}
|
|
16604
|
-
throw err;
|
|
16605
|
-
}
|
|
16606
|
-
}
|
|
16607
|
-
var init_atomic_write = () => {};
|
|
16608
|
-
|
|
16609
|
-
// src/audit/leak-record.ts
|
|
16610
|
-
function upsertFinding(record, incoming) {
|
|
16611
|
-
const { sighting, ...rest } = incoming;
|
|
16612
|
-
const existing = record.findings.find((f) => f.id === rest.id);
|
|
16613
|
-
if (!existing) {
|
|
16614
|
-
record.findings.push({
|
|
16615
|
-
...rest,
|
|
16616
|
-
firstSeen: sighting.at,
|
|
16617
|
-
lastSeen: sighting.at,
|
|
16618
|
-
occurrences: 1,
|
|
16619
|
-
sightings: [sighting]
|
|
16620
|
-
});
|
|
16621
|
-
return { record, isNew: true };
|
|
16622
|
-
}
|
|
16623
|
-
existing.occurrences += 1;
|
|
16624
|
-
if (sighting.at > existing.lastSeen)
|
|
16625
|
-
existing.lastSeen = sighting.at;
|
|
16626
|
-
if (sighting.at < existing.firstSeen)
|
|
16627
|
-
existing.firstSeen = sighting.at;
|
|
16628
|
-
if (existing.sightings.length < MAX_SIGHTINGS) {
|
|
16629
|
-
const seen = existing.sightings.some((s) => s.sessionId === sighting.sessionId && s.at === sighting.at);
|
|
16630
|
-
if (!seen)
|
|
16631
|
-
existing.sightings.push(sighting);
|
|
16632
|
-
}
|
|
16633
|
-
return { record, isNew: false };
|
|
16634
|
-
}
|
|
16635
|
-
function pruneRecord(record, nowMs) {
|
|
16636
|
-
const cutoff = new Date(nowMs - FINDING_TTL_DAYS * 86400000).toISOString();
|
|
16637
|
-
const live = record.findings.filter((f) => f.lastSeen >= cutoff);
|
|
16638
|
-
live.sort((a, b) => a.lastSeen < b.lastSeen ? 1 : a.lastSeen > b.lastSeen ? -1 : 0);
|
|
16639
|
-
record.findings = live.slice(0, MAX_FINDINGS);
|
|
16640
|
-
return record;
|
|
16641
|
-
}
|
|
16642
|
-
function emptyRecord(salt, nowIso) {
|
|
16643
|
-
return {
|
|
16644
|
-
schemaVersion: LEAK_RECORD_SCHEMA_VERSION,
|
|
16645
|
-
salt,
|
|
16646
|
-
updatedAt: nowIso,
|
|
16647
|
-
findings: []
|
|
16648
|
-
};
|
|
16649
|
-
}
|
|
16650
|
-
function describeMechanism(toolName, direction, shortPath) {
|
|
16651
|
-
const where = shortPath ? ` ${shortPath}` : "";
|
|
16652
|
-
let summary;
|
|
16653
|
-
if (direction === "result") {
|
|
16654
|
-
summary = shortPath ? `appeared in the output of reading${where}` : "appeared in tool output";
|
|
16655
|
-
} else {
|
|
16656
|
-
switch (toolName) {
|
|
16657
|
-
case "Read":
|
|
16658
|
-
summary = `read from${where || " a file"}`;
|
|
16659
|
-
break;
|
|
16660
|
-
case "Write":
|
|
16661
|
-
summary = `written to${where || " a file"}`;
|
|
16662
|
-
break;
|
|
16663
|
-
case "Edit":
|
|
16664
|
-
case "NotebookEdit":
|
|
16665
|
-
summary = `edited into${where || " a file"}`;
|
|
16666
|
-
break;
|
|
16667
|
-
case "Bash":
|
|
16668
|
-
summary = "passed in a shell command";
|
|
16669
|
-
break;
|
|
16670
|
-
default:
|
|
16671
|
-
summary = `sent to the ${toolName} tool`;
|
|
16672
|
-
}
|
|
16673
|
-
}
|
|
16674
|
-
return { summary, toolName, direction };
|
|
16675
|
-
}
|
|
16676
|
-
var MAX_SIGHTINGS = 5, FINDING_TTL_DAYS = 90, MAX_FINDINGS = 500, LEAK_RECORD_SCHEMA_VERSION = 1;
|
|
16677
|
-
|
|
16678
|
-
// src/audit/leak-fingerprint.ts
|
|
16679
|
-
function matchPublicPrefix(value) {
|
|
16680
|
-
for (const entry of PUBLIC_PREFIXES) {
|
|
16681
|
-
if (value.startsWith(entry[0]))
|
|
16682
|
-
return entry;
|
|
16683
|
-
}
|
|
16684
|
-
return null;
|
|
16685
|
-
}
|
|
16686
|
-
function fingerprintSecret(value, fallbackLabel = "secret") {
|
|
16687
|
-
const length = value.length;
|
|
16688
|
-
const matched = matchPublicPrefix(value);
|
|
16689
|
-
if (!matched) {
|
|
16690
|
-
return {
|
|
16691
|
-
display: `[${length}-char ${fallbackLabel}]`,
|
|
16692
|
-
label: fallbackLabel,
|
|
16693
|
-
length,
|
|
16694
|
-
attributed: false
|
|
16695
|
-
};
|
|
16696
|
-
}
|
|
16697
|
-
const [prefix, label] = matched;
|
|
16698
|
-
const bodyLength = length - prefix.length;
|
|
16699
|
-
const run = MASK_CHAR.repeat(Math.max(1, Math.min(MAX_MASK_RUN, bodyLength)));
|
|
16700
|
-
if (length >= MIN_LEN_FOR_TAIL && bodyLength > TAIL_CHARS * 2) {
|
|
16701
|
-
return {
|
|
16702
|
-
display: `${prefix}${run}${value.slice(-TAIL_CHARS)}`,
|
|
16703
|
-
label,
|
|
16704
|
-
length,
|
|
16705
|
-
attributed: true
|
|
16706
|
-
};
|
|
16707
|
-
}
|
|
16708
|
-
return { display: `${prefix}${run}`, label, length, attributed: true };
|
|
16709
|
-
}
|
|
16710
|
-
function isFindingId(id) {
|
|
16711
|
-
return /^[0-9a-f]{16}$/.test(id);
|
|
16712
|
-
}
|
|
16713
|
-
function fingerprintId(value, machineSalt) {
|
|
16714
|
-
const { createHmac } = __require("node:crypto");
|
|
16715
|
-
return createHmac("sha256", machineSalt).update(value).digest("hex").slice(0, 16);
|
|
16716
|
-
}
|
|
16717
|
-
var MASK_CHAR = "•", MAX_MASK_RUN = 8, MIN_LEN_FOR_TAIL = 24, TAIL_CHARS = 4, PUBLIC_PREFIXES;
|
|
16718
|
-
var init_leak_fingerprint = __esm(() => {
|
|
16719
|
-
PUBLIC_PREFIXES = [
|
|
16720
|
-
["sk-ant-api03-", "Anthropic API key"],
|
|
16721
|
-
["sk-ant-oat01-", "Anthropic OAuth token"],
|
|
16722
|
-
["sk-ant-", "Anthropic key"],
|
|
16723
|
-
["sk-proj-", "OpenAI project key"],
|
|
16724
|
-
["sk-svcacct-", "OpenAI service-account key"],
|
|
16725
|
-
["sk-admin-", "OpenAI admin key"],
|
|
16726
|
-
["sk-or-v1-", "OpenRouter key"],
|
|
16727
|
-
["github_pat_", "GitHub fine-grained token"],
|
|
16728
|
-
["ghp_", "GitHub personal access token"],
|
|
16729
|
-
["gho_", "GitHub OAuth token"],
|
|
16730
|
-
["ghu_", "GitHub user-to-server token"],
|
|
16731
|
-
["ghs_", "GitHub server-to-server token"],
|
|
16732
|
-
["ghr_", "GitHub refresh token"],
|
|
16733
|
-
["glpat-", "GitLab personal access token"],
|
|
16734
|
-
["xoxb-", "Slack bot token"],
|
|
16735
|
-
["xoxp-", "Slack user token"],
|
|
16736
|
-
["xapp-", "Slack app-level token"],
|
|
16737
|
-
["sk_live_", "Stripe live secret key"],
|
|
16738
|
-
["sk_test_", "Stripe test secret key"],
|
|
16739
|
-
["rk_live_", "Stripe restricted key"],
|
|
16740
|
-
["AKIA", "AWS access key ID"],
|
|
16741
|
-
["ASIA", "AWS temporary access key ID"],
|
|
16742
|
-
["AIza", "Google API key"],
|
|
16743
|
-
["hf_", "Hugging Face token"],
|
|
16744
|
-
["gsk_", "Groq API key"],
|
|
16745
|
-
["r8_", "Replicate token"],
|
|
16746
|
-
["xai-", "xAI key"],
|
|
16747
|
-
["npm_", "npm access token"],
|
|
16748
|
-
["dop_v1_", "DigitalOcean token"],
|
|
16749
|
-
["shpat_", "Shopify access token"],
|
|
16750
|
-
["sbp_", "Supabase token"]
|
|
16751
|
-
];
|
|
16752
|
-
});
|
|
16753
|
-
|
|
16754
|
-
// src/audit/leak-store.ts
|
|
16755
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
16756
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync8 } from "node:fs";
|
|
16757
|
-
import { dirname as dirname8 } from "node:path";
|
|
16758
|
-
function readJson(path) {
|
|
16759
|
-
try {
|
|
16760
|
-
if (!existsSync12(path))
|
|
16761
|
-
return null;
|
|
16762
|
-
return JSON.parse(readFileSync8(path, "utf8"));
|
|
16763
|
-
} catch {
|
|
16764
|
-
return null;
|
|
16765
|
-
}
|
|
16766
|
-
}
|
|
16767
|
-
function readLeakIdentity(home) {
|
|
16768
|
-
const existing = readJson(auditLeakIdentityFile(home));
|
|
16769
|
-
if (existing && typeof existing.salt === "string" && existing.salt.length >= 32) {
|
|
16770
|
-
return {
|
|
16771
|
-
salt: existing.salt,
|
|
16772
|
-
dismissed: existing.dismissed ?? [],
|
|
16773
|
-
reportViewedAt: typeof existing.reportViewedAt === "number" && Number.isFinite(existing.reportViewedAt) ? existing.reportViewedAt : undefined
|
|
16774
|
-
};
|
|
16775
|
-
}
|
|
16776
|
-
const minted = { salt: randomBytes2(32).toString("hex"), dismissed: [] };
|
|
16777
|
-
writeLeakIdentity(minted, home);
|
|
16778
|
-
return minted;
|
|
16779
|
-
}
|
|
16780
|
-
function writeLeakIdentity(identity, home) {
|
|
16781
|
-
const path = auditLeakIdentityFile(home);
|
|
16782
|
-
try {
|
|
16783
|
-
mkdirSync8(dirname8(path), { recursive: true });
|
|
16784
|
-
writeJsonAtomically(path, identity, { mode: FILE_MODE });
|
|
16785
|
-
return true;
|
|
16786
|
-
} catch {
|
|
16787
|
-
return false;
|
|
16788
|
-
}
|
|
16789
|
-
}
|
|
16790
|
-
function sanitizeFinding(raw) {
|
|
16791
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
16792
|
-
return null;
|
|
16793
|
-
const f = raw;
|
|
16794
|
-
if (typeof f.id !== "string" || !isFindingId(f.id))
|
|
16795
|
-
return null;
|
|
16796
|
-
const fp = f.fingerprint;
|
|
16797
|
-
if (!fp || typeof fp !== "object" || typeof fp.display !== "string" || typeof fp.label !== "string") {
|
|
16798
|
-
return null;
|
|
16799
|
-
}
|
|
16800
|
-
const sightings = Array.isArray(f.sightings) ? f.sightings.filter((s) => {
|
|
16801
|
-
if (!s || typeof s !== "object")
|
|
16802
|
-
return false;
|
|
16803
|
-
const m = s.mechanism;
|
|
16804
|
-
return !!m && typeof m === "object" && typeof m.summary === "string";
|
|
16805
|
-
}) : [];
|
|
16806
|
-
return {
|
|
16807
|
-
...f,
|
|
16808
|
-
fingerprint: {
|
|
16809
|
-
display: fp.display,
|
|
16810
|
-
label: fp.label,
|
|
16811
|
-
length: typeof fp.length === "number" && Number.isFinite(fp.length) ? fp.length : 0,
|
|
16812
|
-
attributed: fp.attributed === true
|
|
16813
|
-
},
|
|
16814
|
-
name: typeof f.name === "string" ? f.name : null,
|
|
16815
|
-
firstSeen: typeof f.firstSeen === "string" ? f.firstSeen : "",
|
|
16816
|
-
lastSeen: typeof f.lastSeen === "string" ? f.lastSeen : "",
|
|
16817
|
-
occurrences: typeof f.occurrences === "number" && Number.isFinite(f.occurrences) ? f.occurrences : sightings.length,
|
|
16818
|
-
sightings
|
|
16819
|
-
};
|
|
16820
|
-
}
|
|
16821
|
-
function readLeakRecord(home) {
|
|
16822
|
-
const identity = readLeakIdentity(home);
|
|
16823
|
-
const raw = readJson(auditLeaksFile(home));
|
|
16824
|
-
if (!raw || raw.schemaVersion !== LEAK_RECORD_SCHEMA_VERSION || !Array.isArray(raw.findings)) {
|
|
16825
|
-
return emptyRecord(identity.salt, new Date().toISOString());
|
|
16826
|
-
}
|
|
16827
|
-
const findings = raw.findings.map(sanitizeFinding).filter((f) => f !== null);
|
|
16828
|
-
return { ...raw, findings, salt: identity.salt };
|
|
16829
|
-
}
|
|
16830
|
-
function writeLeakRecord(record, home, nowMs = Date.now()) {
|
|
16831
|
-
const path = auditLeaksFile(home);
|
|
16832
|
-
try {
|
|
16833
|
-
mkdirSync8(dirname8(path), { recursive: true });
|
|
16834
|
-
const pruned = pruneRecord(record, nowMs);
|
|
16835
|
-
pruned.updatedAt = new Date(nowMs).toISOString();
|
|
16836
|
-
writeJsonAtomically(path, pruned, { mode: FILE_MODE });
|
|
16837
|
-
return true;
|
|
16838
|
-
} catch {
|
|
16839
|
-
return false;
|
|
16840
|
-
}
|
|
16841
|
-
}
|
|
16842
|
-
function activeFindings(record, home) {
|
|
16843
|
-
const dismissed = new Set(readLeakIdentity(home).dismissed);
|
|
16844
|
-
return record.findings.filter((f) => !dismissed.has(f.id)).sort((a, b) => a.lastSeen < b.lastSeen ? 1 : a.lastSeen > b.lastSeen ? -1 : 0);
|
|
16845
|
-
}
|
|
16846
|
-
var FILE_MODE = 384;
|
|
16847
|
-
var init_leak_store = __esm(() => {
|
|
16848
|
-
init_fp_home();
|
|
16849
|
-
init_atomic_write();
|
|
16850
|
-
init_leak_fingerprint();
|
|
16851
|
-
});
|
|
16852
|
-
|
|
16853
|
-
// src/audit/leak-notice.ts
|
|
16854
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync9, readdirSync as readdirSync5, statSync as statSync8, writeFileSync as writeFileSync7, rmSync as rmSync4 } from "node:fs";
|
|
16855
|
-
import { resolve as resolve11 } from "node:path";
|
|
16856
|
-
function markLeakNoticeDelivered(ids, home, channel = "cli") {
|
|
16857
|
-
const won = [];
|
|
16858
|
-
try {
|
|
16859
|
-
const dir = NOTICE_DIR(home, channel);
|
|
16860
|
-
mkdirSync9(dir, { recursive: true });
|
|
16861
|
-
for (const id of ids) {
|
|
16862
|
-
if (!isFindingId(id))
|
|
16863
|
-
continue;
|
|
16864
|
-
try {
|
|
16865
|
-
writeFileSync7(resolve11(dir, id), "", { flag: "wx", mode: 384 });
|
|
16866
|
-
won.push(id);
|
|
16867
|
-
} catch {}
|
|
16868
|
-
}
|
|
16869
|
-
} catch {}
|
|
16870
|
-
return won;
|
|
16871
|
-
}
|
|
16872
|
-
function releaseLeakNoticeClaims(ids, home, channel = "cli") {
|
|
16873
|
-
try {
|
|
16874
|
-
const dir = NOTICE_DIR(home, channel);
|
|
16875
|
-
for (const id of ids) {
|
|
16876
|
-
if (!isFindingId(id))
|
|
16877
|
-
continue;
|
|
16878
|
-
rmSync4(resolve11(dir, id), { force: true });
|
|
16879
|
-
}
|
|
16880
|
-
} catch {}
|
|
16881
|
-
}
|
|
16882
|
-
function sessionNoticePending(sessionId, home) {
|
|
16883
|
-
try {
|
|
16884
|
-
if (!sessionId || !/^[\w.:-]{1,200}$/.test(sessionId))
|
|
16885
|
-
return { ids: [], count: 0 };
|
|
16886
|
-
const dir = resolve11(auditDir(home), "notified-sessions");
|
|
16887
|
-
if (existsSync13(resolve11(dir, sessionId)))
|
|
16888
|
-
return { ids: [], count: 0 };
|
|
16889
|
-
const findings = activeFindings(readLeakRecord(home), home);
|
|
16890
|
-
if (findings.length === 0)
|
|
16891
|
-
return { ids: [], count: 0 };
|
|
16892
|
-
const viewedAt = readLeakIdentity(home).reportViewedAt ?? 0;
|
|
16893
|
-
const unviewed = findings.filter((f) => {
|
|
16894
|
-
const seen = Date.parse(f.firstSeen);
|
|
16895
|
-
return !Number.isFinite(seen) || seen > viewedAt;
|
|
16896
|
-
});
|
|
16897
|
-
return { ids: unviewed.map((f) => f.id), count: unviewed.length };
|
|
16898
|
-
} catch {
|
|
16899
|
-
return { ids: [], count: 0 };
|
|
16900
|
-
}
|
|
16901
|
-
}
|
|
16902
|
-
function markSessionNoticed(sessionId, home) {
|
|
16903
|
-
try {
|
|
16904
|
-
if (!sessionId || !/^[\w.:-]{1,200}$/.test(sessionId))
|
|
16905
|
-
return false;
|
|
16906
|
-
const dir = resolve11(auditDir(home), "notified-sessions");
|
|
16907
|
-
mkdirSync9(dir, { recursive: true });
|
|
16908
|
-
writeFileSync7(resolve11(dir, sessionId), "", { flag: "wx", mode: 384 });
|
|
16909
|
-
return true;
|
|
16910
|
-
} catch {
|
|
16911
|
-
return false;
|
|
16912
|
-
}
|
|
16913
|
-
}
|
|
16914
|
-
var NOTICE_DIR = (home, channel = "cli") => resolve11(auditDir(home), channel === "cli" ? "notified" : `notified-${channel}`), MARKER_TTL_MS;
|
|
16915
|
-
var init_leak_notice = __esm(() => {
|
|
16916
|
-
init_fp_home();
|
|
16917
|
-
init_leak_store();
|
|
16918
|
-
init_leak_fingerprint();
|
|
16919
|
-
MARKER_TTL_MS = 120 * 86400000;
|
|
16920
|
-
});
|
|
16921
|
-
|
|
16922
16486
|
// src/hooks/resolve-cwd.ts
|
|
16923
16487
|
function resolveCwd(integration, parsed) {
|
|
16924
16488
|
const direct = typeof parsed.cwd === "string" && parsed.cwd.length > 0 ? parsed.cwd : undefined;
|
|
@@ -17611,7 +17175,7 @@ var init_cursor_projects = __esm(() => {
|
|
|
17611
17175
|
});
|
|
17612
17176
|
|
|
17613
17177
|
// lib/sqlite-reader.ts
|
|
17614
|
-
import { existsSync as
|
|
17178
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
17615
17179
|
import initSqlJs from "sql.js/dist/sql-asm.js";
|
|
17616
17180
|
function silenceSqliteExperimentalWarning() {
|
|
17617
17181
|
if (warningPatched)
|
|
@@ -17662,7 +17226,7 @@ function clearWalFlag(bytes) {
|
|
|
17662
17226
|
async function trySqlJs(dbPath) {
|
|
17663
17227
|
try {
|
|
17664
17228
|
const SQL = await loadSqlJs();
|
|
17665
|
-
const db = new SQL.Database(clearWalFlag(
|
|
17229
|
+
const db = new SQL.Database(clearWalFlag(readFileSync8(dbPath)));
|
|
17666
17230
|
return {
|
|
17667
17231
|
query(sql, params) {
|
|
17668
17232
|
const stmt = db.prepare(sql);
|
|
@@ -17686,7 +17250,7 @@ async function trySqlJs(dbPath) {
|
|
|
17686
17250
|
}
|
|
17687
17251
|
}
|
|
17688
17252
|
async function openSqliteReadonly(dbPath) {
|
|
17689
|
-
if (!
|
|
17253
|
+
if (!existsSync11(dbPath))
|
|
17690
17254
|
return null;
|
|
17691
17255
|
return await tryNodeSqlite(dbPath) ?? await trySqlJs(dbPath);
|
|
17692
17256
|
}
|
|
@@ -18343,7 +17907,7 @@ var init_hermes_projects = __esm(() => {
|
|
|
18343
17907
|
|
|
18344
17908
|
// lib/openclaw-sessions.ts
|
|
18345
17909
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
18346
|
-
import { readdirSync as
|
|
17910
|
+
import { readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
|
|
18347
17911
|
import { homedir as homedir12 } from "node:os";
|
|
18348
17912
|
import { join as join14 } from "node:path";
|
|
18349
17913
|
function openclawHome() {
|
|
@@ -18462,7 +18026,7 @@ function openclawLinesToLogEntries(lines, source = "session") {
|
|
|
18462
18026
|
}
|
|
18463
18027
|
function listOpenClawAgents() {
|
|
18464
18028
|
try {
|
|
18465
|
-
return
|
|
18029
|
+
return readdirSync5(join14(openclawHome(), "agents"), { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name).sort();
|
|
18466
18030
|
} catch {
|
|
18467
18031
|
return [];
|
|
18468
18032
|
}
|
|
@@ -18472,7 +18036,7 @@ function listOpenClawTranscripts() {
|
|
|
18472
18036
|
const out = [];
|
|
18473
18037
|
let agentIds;
|
|
18474
18038
|
try {
|
|
18475
|
-
agentIds =
|
|
18039
|
+
agentIds = readdirSync5(agentsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
18476
18040
|
} catch {
|
|
18477
18041
|
return out;
|
|
18478
18042
|
}
|
|
@@ -18480,7 +18044,7 @@ function listOpenClawTranscripts() {
|
|
|
18480
18044
|
const sessionsDir = join14(agentsDir, agentId, "sessions");
|
|
18481
18045
|
let files;
|
|
18482
18046
|
try {
|
|
18483
|
-
files =
|
|
18047
|
+
files = readdirSync5(sessionsDir);
|
|
18484
18048
|
} catch {
|
|
18485
18049
|
continue;
|
|
18486
18050
|
}
|
|
@@ -18492,7 +18056,7 @@ function listOpenClawTranscripts() {
|
|
|
18492
18056
|
continue;
|
|
18493
18057
|
const transcriptPath = join14(sessionsDir, file);
|
|
18494
18058
|
try {
|
|
18495
|
-
const st =
|
|
18059
|
+
const st = statSync7(transcriptPath);
|
|
18496
18060
|
out.push({ agentId, sessionId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
|
|
18497
18061
|
} catch {}
|
|
18498
18062
|
}
|
|
@@ -18543,7 +18107,7 @@ __export(exports_openclaw_projects, {
|
|
|
18543
18107
|
getOpenClawSessions: () => getOpenClawSessions,
|
|
18544
18108
|
openClawProjectPath: () => openClawProjectPath
|
|
18545
18109
|
});
|
|
18546
|
-
import { readFileSync as
|
|
18110
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
18547
18111
|
import { join as join15 } from "node:path";
|
|
18548
18112
|
function str(v) {
|
|
18549
18113
|
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
@@ -18553,7 +18117,7 @@ function readSessionsIndex(agentId) {
|
|
|
18553
18117
|
const indexPath = join15(openclawHome(), "agents", agentId, "sessions", "sessions.json");
|
|
18554
18118
|
let raw;
|
|
18555
18119
|
try {
|
|
18556
|
-
raw = JSON.parse(
|
|
18120
|
+
raw = JSON.parse(readFileSync9(indexPath, "utf-8"));
|
|
18557
18121
|
} catch {
|
|
18558
18122
|
return out;
|
|
18559
18123
|
}
|
|
@@ -18702,7 +18266,7 @@ var init_openclaw_projects = __esm(() => {
|
|
|
18702
18266
|
|
|
18703
18267
|
// lib/factory-sessions.ts
|
|
18704
18268
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
18705
|
-
import { readdirSync as
|
|
18269
|
+
import { readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
18706
18270
|
import { homedir as homedir13 } from "node:os";
|
|
18707
18271
|
import { join as join16 } from "node:path";
|
|
18708
18272
|
function factoryHome() {
|
|
@@ -18848,7 +18412,7 @@ function listFactoryTranscripts() {
|
|
|
18848
18412
|
const out = [];
|
|
18849
18413
|
let projectDirs;
|
|
18850
18414
|
try {
|
|
18851
|
-
projectDirs =
|
|
18415
|
+
projectDirs = readdirSync6(root, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
18852
18416
|
} catch {
|
|
18853
18417
|
return out;
|
|
18854
18418
|
}
|
|
@@ -18858,7 +18422,7 @@ function listFactoryTranscripts() {
|
|
|
18858
18422
|
const projectPath = join16(root, projectName);
|
|
18859
18423
|
let files;
|
|
18860
18424
|
try {
|
|
18861
|
-
files =
|
|
18425
|
+
files = readdirSync6(projectPath);
|
|
18862
18426
|
} catch {
|
|
18863
18427
|
continue;
|
|
18864
18428
|
}
|
|
@@ -18870,7 +18434,7 @@ function listFactoryTranscripts() {
|
|
|
18870
18434
|
continue;
|
|
18871
18435
|
const transcriptPath = join16(projectPath, file);
|
|
18872
18436
|
try {
|
|
18873
|
-
const st =
|
|
18437
|
+
const st = statSync8(transcriptPath);
|
|
18874
18438
|
out.push({ projectName, cwd, sessionId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
|
|
18875
18439
|
} catch {}
|
|
18876
18440
|
}
|
|
@@ -19290,7 +18854,7 @@ var init_devin_projects = __esm(() => {
|
|
|
19290
18854
|
|
|
19291
18855
|
// lib/antigravity-sessions.ts
|
|
19292
18856
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
19293
|
-
import { readdirSync as
|
|
18857
|
+
import { readdirSync as readdirSync7, statSync as statSync9 } from "node:fs";
|
|
19294
18858
|
import { homedir as homedir15 } from "node:os";
|
|
19295
18859
|
import { join as join18 } from "node:path";
|
|
19296
18860
|
function antigravityHome() {
|
|
@@ -19415,7 +18979,7 @@ function listAntigravityTranscripts() {
|
|
|
19415
18979
|
const out = [];
|
|
19416
18980
|
let convoDirs;
|
|
19417
18981
|
try {
|
|
19418
|
-
convoDirs =
|
|
18982
|
+
convoDirs = readdirSync7(root, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
19419
18983
|
} catch {
|
|
19420
18984
|
return out;
|
|
19421
18985
|
}
|
|
@@ -19425,7 +18989,7 @@ function listAntigravityTranscripts() {
|
|
|
19425
18989
|
continue;
|
|
19426
18990
|
const transcriptPath = join18(root, conversationId, rel);
|
|
19427
18991
|
try {
|
|
19428
|
-
const st =
|
|
18992
|
+
const st = statSync9(transcriptPath);
|
|
19429
18993
|
if (!st.isFile())
|
|
19430
18994
|
continue;
|
|
19431
18995
|
out.push({ conversationId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
|
|
@@ -19438,7 +19002,7 @@ function findAntigravityTranscript(conversationId) {
|
|
|
19438
19002
|
return null;
|
|
19439
19003
|
const transcriptPath = join18(antigravityBrainRoot(), conversationId, antigravityTranscriptRelPath());
|
|
19440
19004
|
try {
|
|
19441
|
-
if (
|
|
19005
|
+
if (statSync9(transcriptPath).isFile())
|
|
19442
19006
|
return transcriptPath;
|
|
19443
19007
|
} catch {}
|
|
19444
19008
|
return null;
|
|
@@ -19890,7 +19454,7 @@ var init_goose_projects = __esm(() => {
|
|
|
19890
19454
|
|
|
19891
19455
|
// lib/projects.ts
|
|
19892
19456
|
import { readdir as readdir5, stat as stat4 } from "node:fs/promises";
|
|
19893
|
-
import { join as join21, resolve as
|
|
19457
|
+
import { join as join21, resolve as resolve11, sep } from "node:path";
|
|
19894
19458
|
async function getMtime(path, label) {
|
|
19895
19459
|
try {
|
|
19896
19460
|
return (await stat4(path)).mtime;
|
|
@@ -20042,8 +19606,8 @@ function resolveProjectPath(projectName) {
|
|
|
20042
19606
|
throw new RangeError("Empty project name");
|
|
20043
19607
|
if (/^[/\\]/.test(projectName))
|
|
20044
19608
|
throw new RangeError("Absolute project name");
|
|
20045
|
-
const projectsPath =
|
|
20046
|
-
const candidate =
|
|
19609
|
+
const projectsPath = resolve11(getClaudeProjectsPath());
|
|
19610
|
+
const candidate = resolve11(join21(projectsPath, projectName));
|
|
20047
19611
|
if (!candidate.startsWith(projectsPath + sep)) {
|
|
20048
19612
|
throw new RangeError("Project path escapes root");
|
|
20049
19613
|
}
|
|
@@ -20353,30 +19917,30 @@ var init_log_entries = __esm(() => {
|
|
|
20353
19917
|
});
|
|
20354
19918
|
|
|
20355
19919
|
// lib/codex-sessions.ts
|
|
20356
|
-
import { readFileSync as
|
|
19920
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync8, existsSync as existsSync12, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, statSync as statSync10 } from "node:fs";
|
|
20357
19921
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
20358
|
-
import { dirname as
|
|
19922
|
+
import { dirname as dirname7, join as join24 } from "node:path";
|
|
20359
19923
|
import { homedir as homedir17 } from "node:os";
|
|
20360
19924
|
function readCache() {
|
|
20361
19925
|
try {
|
|
20362
|
-
if (!
|
|
19926
|
+
if (!existsSync12(CACHE_PATH))
|
|
20363
19927
|
return {};
|
|
20364
|
-
return JSON.parse(
|
|
19928
|
+
return JSON.parse(readFileSync10(CACHE_PATH, "utf-8"));
|
|
20365
19929
|
} catch {
|
|
20366
19930
|
return {};
|
|
20367
19931
|
}
|
|
20368
19932
|
}
|
|
20369
19933
|
function writeCacheEntry(sessionId, path) {
|
|
20370
19934
|
try {
|
|
20371
|
-
|
|
19935
|
+
mkdirSync7(dirname7(CACHE_PATH), { recursive: true });
|
|
20372
19936
|
const cache = readCache();
|
|
20373
19937
|
cache[sessionId] = path;
|
|
20374
|
-
|
|
19938
|
+
writeFileSync6(CACHE_PATH, JSON.stringify(cache), "utf-8");
|
|
20375
19939
|
} catch {}
|
|
20376
19940
|
}
|
|
20377
19941
|
function dirSearch(dir, sessionId) {
|
|
20378
19942
|
try {
|
|
20379
|
-
for (const f of
|
|
19943
|
+
for (const f of readdirSync8(dir, { withFileTypes: true })) {
|
|
20380
19944
|
if (f.isFile() && f.name.includes(sessionId) && f.name.endsWith(".jsonl")) {
|
|
20381
19945
|
return join24(dir, f.name);
|
|
20382
19946
|
}
|
|
@@ -20387,7 +19951,7 @@ function dirSearch(dir, sessionId) {
|
|
|
20387
19951
|
function findCodexTranscript(sessionId) {
|
|
20388
19952
|
const cache = readCache();
|
|
20389
19953
|
const cached = cache[sessionId];
|
|
20390
|
-
if (cached &&
|
|
19954
|
+
if (cached && existsSync12(cached))
|
|
20391
19955
|
return cached;
|
|
20392
19956
|
const root = join24(homedir17(), ".codex", "sessions");
|
|
20393
19957
|
const today = new Date;
|
|
@@ -20406,13 +19970,13 @@ function findCodexTranscript(sessionId) {
|
|
|
20406
19970
|
}
|
|
20407
19971
|
}
|
|
20408
19972
|
try {
|
|
20409
|
-
for (const y of
|
|
19973
|
+
for (const y of readdirSync8(root, { withFileTypes: true })) {
|
|
20410
19974
|
if (!y.isDirectory())
|
|
20411
19975
|
continue;
|
|
20412
|
-
for (const m of
|
|
19976
|
+
for (const m of readdirSync8(join24(root, y.name), { withFileTypes: true })) {
|
|
20413
19977
|
if (!m.isDirectory())
|
|
20414
19978
|
continue;
|
|
20415
|
-
for (const d of
|
|
19979
|
+
for (const d of readdirSync8(join24(root, y.name, m.name), { withFileTypes: true })) {
|
|
20416
19980
|
if (!d.isDirectory())
|
|
20417
19981
|
continue;
|
|
20418
19982
|
const hit = dirSearch(join24(root, y.name, m.name, d.name), sessionId);
|
|
@@ -20441,6 +20005,15 @@ function joinTexts(blocks, wantedType) {
|
|
|
20441
20005
|
return blocks.filter((b) => b?.type === wantedType && typeof b.text === "string").map((b) => b.text).join(`
|
|
20442
20006
|
`);
|
|
20443
20007
|
}
|
|
20008
|
+
function toolOutputText(output) {
|
|
20009
|
+
if (typeof output === "string")
|
|
20010
|
+
return output;
|
|
20011
|
+
if (Array.isArray(output)) {
|
|
20012
|
+
return output.filter((block) => !!block && typeof block === "object").map((block) => typeof block.text === "string" ? block.text : "").filter(Boolean).join(`
|
|
20013
|
+
`);
|
|
20014
|
+
}
|
|
20015
|
+
return output === undefined ? "" : JSON.stringify(output);
|
|
20016
|
+
}
|
|
20444
20017
|
async function parseCodexLog(fileContent, source = "session") {
|
|
20445
20018
|
const lines = fileContent.split(`
|
|
20446
20019
|
`).filter((line) => line.trim() !== "");
|
|
@@ -20517,10 +20090,11 @@ async function parseCodexLog(fileContent, source = "session") {
|
|
|
20517
20090
|
});
|
|
20518
20091
|
continue;
|
|
20519
20092
|
}
|
|
20520
|
-
if (subType === "function_call") {
|
|
20093
|
+
if (subType === "function_call" || subType === "custom_tool_call") {
|
|
20521
20094
|
const callId = payload.call_id;
|
|
20522
20095
|
const name = payload.name ?? "function_call";
|
|
20523
|
-
const
|
|
20096
|
+
const encodedInput = payload.arguments ?? payload.input;
|
|
20097
|
+
const input = safeJsonParse4(encodedInput);
|
|
20524
20098
|
const toolUse = {
|
|
20525
20099
|
type: "tool_use",
|
|
20526
20100
|
id: callId ?? `${timestamp}-${name}`,
|
|
@@ -20539,7 +20113,7 @@ async function parseCodexLog(fileContent, source = "session") {
|
|
|
20539
20113
|
}
|
|
20540
20114
|
continue;
|
|
20541
20115
|
}
|
|
20542
|
-
if (subType === "function_call_output") {
|
|
20116
|
+
if (subType === "function_call_output" || subType === "custom_tool_call_output") {
|
|
20543
20117
|
const callId = payload.call_id;
|
|
20544
20118
|
const block = callId ? toolUseById.get(callId) : undefined;
|
|
20545
20119
|
if (block) {
|
|
@@ -20548,7 +20122,7 @@ async function parseCodexLog(fileContent, source = "session") {
|
|
|
20548
20122
|
block.result = {
|
|
20549
20123
|
timestamp,
|
|
20550
20124
|
timestampFormatted: formatTimestamp(date),
|
|
20551
|
-
content:
|
|
20125
|
+
content: toolOutputText(payload.output),
|
|
20552
20126
|
durationMs: duration,
|
|
20553
20127
|
durationFormatted: formatDuration(duration)
|
|
20554
20128
|
};
|
|
@@ -20641,7 +20215,7 @@ var init_codex_sessions = __esm(() => {
|
|
|
20641
20215
|
});
|
|
20642
20216
|
|
|
20643
20217
|
// src/hooks/resolve-permission-mode.ts
|
|
20644
|
-
import { readFileSync as
|
|
20218
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
20645
20219
|
function resolvePermissionMode(integration, parsed, sessionId) {
|
|
20646
20220
|
if (integration === "claude") {
|
|
20647
20221
|
return parsed.permission_mode ?? "default";
|
|
@@ -20656,7 +20230,7 @@ function resolveCodexMode(sessionId) {
|
|
|
20656
20230
|
const path = findCodexTranscript(sessionId);
|
|
20657
20231
|
if (!path)
|
|
20658
20232
|
return;
|
|
20659
|
-
for (const line of
|
|
20233
|
+
for (const line of readFileSync11(path, "utf-8").split(`
|
|
20660
20234
|
`)) {
|
|
20661
20235
|
if (!line.includes("turn_context"))
|
|
20662
20236
|
continue;
|
|
@@ -20681,9 +20255,9 @@ var init_resolve_permission_mode = __esm(() => {
|
|
|
20681
20255
|
});
|
|
20682
20256
|
|
|
20683
20257
|
// lib/copilot-sessions.ts
|
|
20684
|
-
import { readFileSync as
|
|
20258
|
+
import { readFileSync as readFileSync12, readdirSync as readdirSync9, existsSync as existsSync13, statSync as statSync11 } from "node:fs";
|
|
20685
20259
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
20686
|
-
import { join as join25, resolve as
|
|
20260
|
+
import { join as join25, resolve as resolve12, sep as sep2 } from "node:path";
|
|
20687
20261
|
import { homedir as homedir18 } from "node:os";
|
|
20688
20262
|
function getCopilotHome() {
|
|
20689
20263
|
return process.env.COPILOT_HOME || join25(homedir18(), ".copilot");
|
|
@@ -20694,8 +20268,8 @@ function getCopilotSessionStateRoot2() {
|
|
|
20694
20268
|
function getCopilotSessionDir(sessionId) {
|
|
20695
20269
|
if (!sessionId)
|
|
20696
20270
|
return null;
|
|
20697
|
-
const root =
|
|
20698
|
-
const candidate =
|
|
20271
|
+
const root = resolve12(getCopilotSessionStateRoot2());
|
|
20272
|
+
const candidate = resolve12(root, sessionId);
|
|
20699
20273
|
if (candidate === root || !candidate.startsWith(`${root}${sep2}`))
|
|
20700
20274
|
return null;
|
|
20701
20275
|
return candidate;
|
|
@@ -20710,17 +20284,17 @@ function findCopilotTranscript(sessionId) {
|
|
|
20710
20284
|
const candidate = resolveSessionFile(sessionId, "events.jsonl");
|
|
20711
20285
|
if (!candidate)
|
|
20712
20286
|
return null;
|
|
20713
|
-
return
|
|
20287
|
+
return existsSync13(candidate) ? candidate : null;
|
|
20714
20288
|
}
|
|
20715
20289
|
function findCopilotWorkspace(sessionId) {
|
|
20716
20290
|
const candidate = resolveSessionFile(sessionId, "workspace.yaml");
|
|
20717
20291
|
if (!candidate)
|
|
20718
20292
|
return null;
|
|
20719
|
-
return
|
|
20293
|
+
return existsSync13(candidate) ? candidate : null;
|
|
20720
20294
|
}
|
|
20721
20295
|
function readYamlScalar(path, key) {
|
|
20722
20296
|
try {
|
|
20723
|
-
const text =
|
|
20297
|
+
const text = readFileSync12(path, "utf-8");
|
|
20724
20298
|
const re = new RegExp(`^${key}\\s*:\\s*(.+?)\\s*$`, "m");
|
|
20725
20299
|
const m = text.match(re);
|
|
20726
20300
|
if (!m)
|
|
@@ -20743,6 +20317,8 @@ async function parseCopilotLog(fileContent, source = "session") {
|
|
|
20743
20317
|
const rawLines = [];
|
|
20744
20318
|
const toolUseById = new Map;
|
|
20745
20319
|
const toolUseStartMs = new Map;
|
|
20320
|
+
let mostRecentToolUse;
|
|
20321
|
+
let mostRecentToolUseStartMs = 0;
|
|
20746
20322
|
let cwd;
|
|
20747
20323
|
let seenSessionStart = false;
|
|
20748
20324
|
for (let i = 0;i < lines.length; i++) {
|
|
@@ -20838,8 +20414,24 @@ async function parseCopilotLog(fileContent, source = "session") {
|
|
|
20838
20414
|
toolUseById.set(callId, toolUse);
|
|
20839
20415
|
toolUseStartMs.set(callId, date.getTime());
|
|
20840
20416
|
}
|
|
20417
|
+
mostRecentToolUse = toolUse;
|
|
20418
|
+
mostRecentToolUseStartMs = date.getTime();
|
|
20841
20419
|
continue;
|
|
20842
20420
|
}
|
|
20421
|
+
if (recType === "hook.start" && data.hookType === "postToolUse" && mostRecentToolUse) {
|
|
20422
|
+
const input = data.input ?? {};
|
|
20423
|
+
const hookResult = input.toolResult ?? {};
|
|
20424
|
+
const hookContent = hookResult.textResultForLlm ?? hookResult.sessionLog;
|
|
20425
|
+
if (typeof hookContent === "string" && hookContent.length > 0) {
|
|
20426
|
+
mostRecentToolUse.result = {
|
|
20427
|
+
timestamp,
|
|
20428
|
+
timestampFormatted: formatTimestamp(date),
|
|
20429
|
+
content: hookContent,
|
|
20430
|
+
durationMs: Math.max(0, date.getTime() - mostRecentToolUseStartMs),
|
|
20431
|
+
durationFormatted: formatDuration(Math.max(0, date.getTime() - mostRecentToolUseStartMs))
|
|
20432
|
+
};
|
|
20433
|
+
}
|
|
20434
|
+
}
|
|
20843
20435
|
if (recType === "tool.execution_complete") {
|
|
20844
20436
|
const callId = data.toolCallId;
|
|
20845
20437
|
const block = callId ? toolUseById.get(callId) : undefined;
|
|
@@ -20849,7 +20441,8 @@ async function parseCopilotLog(fileContent, source = "session") {
|
|
|
20849
20441
|
const telemetry = data.toolTelemetry ?? {};
|
|
20850
20442
|
const reportedMs = telemetry.metrics?.commandTimeMs ?? telemetry.metrics?.durationMs ?? null;
|
|
20851
20443
|
const durationMs = typeof reportedMs === "number" && reportedMs >= 0 ? reportedMs : Math.max(0, date.getTime() - startMs);
|
|
20852
|
-
const
|
|
20444
|
+
const completionContent = result.detailedContent ?? result.content ?? "";
|
|
20445
|
+
const content = block.result?.content || completionContent;
|
|
20853
20446
|
block.result = {
|
|
20854
20447
|
timestamp,
|
|
20855
20448
|
timestampFormatted: formatTimestamp(date),
|
|
@@ -20898,9 +20491,9 @@ var init_copilot_sessions = __esm(() => {
|
|
|
20898
20491
|
});
|
|
20899
20492
|
|
|
20900
20493
|
// lib/cursor-sessions.ts
|
|
20901
|
-
import { readFileSync as
|
|
20494
|
+
import { readFileSync as readFileSync13, readdirSync as readdirSync10, existsSync as existsSync14, statSync as statSync12 } from "node:fs";
|
|
20902
20495
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
20903
|
-
import { basename as basename3, join as join26, resolve as
|
|
20496
|
+
import { basename as basename3, join as join26, resolve as resolve13, sep as sep3 } from "node:path";
|
|
20904
20497
|
import { homedir as homedir19 } from "node:os";
|
|
20905
20498
|
function getCursorHome2() {
|
|
20906
20499
|
return process.env.CURSOR_HOME || join26(homedir19(), ".cursor");
|
|
@@ -20908,28 +20501,28 @@ function getCursorHome2() {
|
|
|
20908
20501
|
function getCursorSessionDir(sessionId) {
|
|
20909
20502
|
if (!sessionId)
|
|
20910
20503
|
return null;
|
|
20911
|
-
const home =
|
|
20912
|
-
const projectsRoot =
|
|
20504
|
+
const home = resolve13(getCursorHome2());
|
|
20505
|
+
const projectsRoot = resolve13(home, NEW_PROJECTS_DIR2);
|
|
20913
20506
|
let projectEntries = [];
|
|
20914
20507
|
try {
|
|
20915
|
-
projectEntries =
|
|
20508
|
+
projectEntries = readdirSync10(projectsRoot, { withFileTypes: true });
|
|
20916
20509
|
} catch {}
|
|
20917
20510
|
for (const entry of projectEntries) {
|
|
20918
20511
|
if (!entry.isDirectory())
|
|
20919
20512
|
continue;
|
|
20920
|
-
const candidate =
|
|
20921
|
-
const transcriptRoot =
|
|
20513
|
+
const candidate = resolve13(projectsRoot, entry.name, NEW_AGENT_TRANSCRIPTS_DIR2, sessionId);
|
|
20514
|
+
const transcriptRoot = resolve13(projectsRoot, entry.name, NEW_AGENT_TRANSCRIPTS_DIR2);
|
|
20922
20515
|
if (candidate === transcriptRoot || !candidate.startsWith(`${transcriptRoot}${sep3}`))
|
|
20923
20516
|
continue;
|
|
20924
|
-
if (
|
|
20517
|
+
if (existsSync14(candidate))
|
|
20925
20518
|
return candidate;
|
|
20926
20519
|
}
|
|
20927
20520
|
for (const sub of LEGACY_SESSION_ROOT_CANDIDATES2) {
|
|
20928
|
-
const root =
|
|
20929
|
-
const candidate =
|
|
20521
|
+
const root = resolve13(home, sub);
|
|
20522
|
+
const candidate = resolve13(root, sessionId);
|
|
20930
20523
|
if (candidate === root || !candidate.startsWith(`${root}${sep3}`))
|
|
20931
20524
|
continue;
|
|
20932
|
-
if (
|
|
20525
|
+
if (existsSync14(candidate))
|
|
20933
20526
|
return candidate;
|
|
20934
20527
|
}
|
|
20935
20528
|
return null;
|
|
@@ -20939,11 +20532,11 @@ function findCursorTranscript(sessionId) {
|
|
|
20939
20532
|
if (!dir)
|
|
20940
20533
|
return null;
|
|
20941
20534
|
const newCandidate = join26(dir, `${basename3(dir)}.jsonl`);
|
|
20942
|
-
if (
|
|
20535
|
+
if (existsSync14(newCandidate))
|
|
20943
20536
|
return newCandidate;
|
|
20944
20537
|
for (const name of LEGACY_TRANSCRIPT_FILE_CANDIDATES2) {
|
|
20945
20538
|
const candidate = join26(dir, name);
|
|
20946
|
-
if (
|
|
20539
|
+
if (existsSync14(candidate))
|
|
20947
20540
|
return candidate;
|
|
20948
20541
|
}
|
|
20949
20542
|
return null;
|
|
@@ -20973,8 +20566,27 @@ async function parseCursorLog(fileContent, source = "session") {
|
|
|
20973
20566
|
if (!raw.type && raw.role && raw.message?.content) {
|
|
20974
20567
|
const synthDate = new Date(SYNTH_T0 + i);
|
|
20975
20568
|
const synthTs = synthDate.toISOString();
|
|
20976
|
-
const
|
|
20569
|
+
const messageContent = raw.message.content;
|
|
20570
|
+
const textParts = messageContent.filter((c) => c?.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
|
|
20977
20571
|
if (raw.role === "user") {
|
|
20572
|
+
let attachedResult = false;
|
|
20573
|
+
for (const block of messageContent) {
|
|
20574
|
+
if (block?.type !== "tool_result")
|
|
20575
|
+
continue;
|
|
20576
|
+
const callId = typeof block.tool_use_id === "string" ? block.tool_use_id : undefined;
|
|
20577
|
+
const toolUse = callId ? toolUseById.get(callId) : undefined;
|
|
20578
|
+
if (!toolUse)
|
|
20579
|
+
continue;
|
|
20580
|
+
const durationMs = Math.max(0, synthDate.getTime() - (toolUseStartMs.get(callId) ?? synthDate.getTime()));
|
|
20581
|
+
toolUse.result = {
|
|
20582
|
+
timestamp: synthTs,
|
|
20583
|
+
timestampFormatted: formatTimestamp(synthDate),
|
|
20584
|
+
content: typeof block.content === "string" ? block.content : block.content == null ? "" : JSON.stringify(block.content),
|
|
20585
|
+
durationMs,
|
|
20586
|
+
durationFormatted: formatDuration(durationMs)
|
|
20587
|
+
};
|
|
20588
|
+
attachedResult = true;
|
|
20589
|
+
}
|
|
20978
20590
|
const queryMatch = /<user_query>\s*([\s\S]*?)\s*<\/user_query>/.exec(textParts);
|
|
20979
20591
|
const text = queryMatch ? queryMatch[1] : textParts;
|
|
20980
20592
|
if (text) {
|
|
@@ -20983,11 +20595,35 @@ async function parseCursorLog(fileContent, source = "session") {
|
|
|
20983
20595
|
...baseEntry(rawCopy, synthTs, synthDate, source),
|
|
20984
20596
|
message: { role: "user", content: text }
|
|
20985
20597
|
});
|
|
20598
|
+
} else if (!attachedResult) {
|
|
20599
|
+
entries.push({
|
|
20600
|
+
type: "system",
|
|
20601
|
+
...baseEntry(rawCopy, synthTs, synthDate, source),
|
|
20602
|
+
raw: rawCopy
|
|
20603
|
+
});
|
|
20986
20604
|
}
|
|
20987
20605
|
continue;
|
|
20988
20606
|
}
|
|
20989
20607
|
if (raw.role === "assistant") {
|
|
20990
|
-
const blocks =
|
|
20608
|
+
const blocks = [];
|
|
20609
|
+
if (textParts)
|
|
20610
|
+
blocks.push({ type: "text", text: textParts });
|
|
20611
|
+
for (let j = 0;j < messageContent.length; j++) {
|
|
20612
|
+
const contentBlock = messageContent[j];
|
|
20613
|
+
if (contentBlock?.type !== "tool_use")
|
|
20614
|
+
continue;
|
|
20615
|
+
const name = typeof contentBlock.name === "string" ? contentBlock.name : "tool";
|
|
20616
|
+
const id = typeof contentBlock.id === "string" && contentBlock.id ? contentBlock.id : `cursor-${i}-${name}-${j}`;
|
|
20617
|
+
const toolUse = {
|
|
20618
|
+
type: "tool_use",
|
|
20619
|
+
id,
|
|
20620
|
+
name,
|
|
20621
|
+
input: contentBlock.input && typeof contentBlock.input === "object" ? contentBlock.input : {}
|
|
20622
|
+
};
|
|
20623
|
+
blocks.push(toolUse);
|
|
20624
|
+
toolUseById.set(id, toolUse);
|
|
20625
|
+
toolUseStartMs.set(id, synthDate.getTime());
|
|
20626
|
+
}
|
|
20991
20627
|
if (blocks.length === 0) {
|
|
20992
20628
|
entries.push({
|
|
20993
20629
|
type: "system",
|
|
@@ -21154,9 +20790,9 @@ var init_cursor_sessions = __esm(() => {
|
|
|
21154
20790
|
});
|
|
21155
20791
|
|
|
21156
20792
|
// lib/pi-sessions.ts
|
|
21157
|
-
import { readFileSync as
|
|
20793
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync11, existsSync as existsSync15, statSync as statSync13 } from "node:fs";
|
|
21158
20794
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
21159
|
-
import { join as join27, resolve as
|
|
20795
|
+
import { join as join27, resolve as resolve14, sep as sep4 } from "node:path";
|
|
21160
20796
|
import { homedir as homedir20 } from "node:os";
|
|
21161
20797
|
function getPiSessionStateRoot() {
|
|
21162
20798
|
return process.env.PI_SESSIONS_DIR || join27(homedir20(), ".pi", "agent", "sessions");
|
|
@@ -21167,20 +20803,20 @@ function isSafeSessionId(sessionId) {
|
|
|
21167
20803
|
function findPiTranscript(sessionId) {
|
|
21168
20804
|
if (!isSafeSessionId(sessionId))
|
|
21169
20805
|
return null;
|
|
21170
|
-
const root =
|
|
20806
|
+
const root = resolve14(getPiSessionStateRoot());
|
|
21171
20807
|
let cwdDirs;
|
|
21172
20808
|
try {
|
|
21173
|
-
cwdDirs =
|
|
20809
|
+
cwdDirs = readdirSync11(root);
|
|
21174
20810
|
} catch {
|
|
21175
20811
|
return null;
|
|
21176
20812
|
}
|
|
21177
20813
|
for (const cwdDir of cwdDirs) {
|
|
21178
|
-
const cwdPath =
|
|
20814
|
+
const cwdPath = resolve14(root, cwdDir);
|
|
21179
20815
|
if (!cwdPath.startsWith(`${root}${sep4}`))
|
|
21180
20816
|
continue;
|
|
21181
20817
|
let files;
|
|
21182
20818
|
try {
|
|
21183
|
-
files =
|
|
20819
|
+
files = readdirSync11(cwdPath);
|
|
21184
20820
|
} catch {
|
|
21185
20821
|
continue;
|
|
21186
20822
|
}
|
|
@@ -21188,10 +20824,10 @@ function findPiTranscript(sessionId) {
|
|
|
21188
20824
|
const m = SESSION_FILE_RE2.exec(f);
|
|
21189
20825
|
if (!m || m[1].toLowerCase() !== sessionId.toLowerCase())
|
|
21190
20826
|
continue;
|
|
21191
|
-
const candidate =
|
|
20827
|
+
const candidate = resolve14(cwdPath, f);
|
|
21192
20828
|
if (!candidate.startsWith(`${cwdPath}${sep4}`))
|
|
21193
20829
|
continue;
|
|
21194
|
-
if (
|
|
20830
|
+
if (existsSync15(candidate))
|
|
21195
20831
|
return candidate;
|
|
21196
20832
|
}
|
|
21197
20833
|
}
|
|
@@ -21594,14 +21230,53 @@ var init_pack_failclosed = __esm(() => {
|
|
|
21594
21230
|
]);
|
|
21595
21231
|
});
|
|
21596
21232
|
|
|
21233
|
+
// lib/atomic-write.ts
|
|
21234
|
+
import {
|
|
21235
|
+
chmodSync as chmodSync2,
|
|
21236
|
+
existsSync as existsSync16,
|
|
21237
|
+
mkdirSync as mkdirSync8,
|
|
21238
|
+
renameSync as renameSync4,
|
|
21239
|
+
rmSync as rmSync3,
|
|
21240
|
+
statSync as statSync14,
|
|
21241
|
+
writeFileSync as writeFileSync7
|
|
21242
|
+
} from "node:fs";
|
|
21243
|
+
import { dirname as dirname8 } from "node:path";
|
|
21244
|
+
import { randomBytes } from "node:crypto";
|
|
21245
|
+
function writeJsonAtomically(filePath, value, opts = {}) {
|
|
21246
|
+
const mode = opts.mode ?? 384;
|
|
21247
|
+
const dirMode = opts.dirMode ?? 448;
|
|
21248
|
+
const dir = dirname8(filePath);
|
|
21249
|
+
if (!existsSync16(dir))
|
|
21250
|
+
mkdirSync8(dir, { recursive: true, mode: dirMode });
|
|
21251
|
+
const tmp = `${filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
21252
|
+
try {
|
|
21253
|
+
writeFileSync7(tmp, JSON.stringify(value, null, 2), { mode });
|
|
21254
|
+
try {
|
|
21255
|
+
if ((statSync14(tmp).mode & 63) !== 0)
|
|
21256
|
+
chmodSync2(tmp, mode);
|
|
21257
|
+
} catch {}
|
|
21258
|
+
renameSync4(tmp, filePath);
|
|
21259
|
+
try {
|
|
21260
|
+
if ((statSync14(filePath).mode & 63) !== 0)
|
|
21261
|
+
chmodSync2(filePath, mode);
|
|
21262
|
+
} catch {}
|
|
21263
|
+
} catch (err) {
|
|
21264
|
+
try {
|
|
21265
|
+
rmSync3(tmp, { force: true });
|
|
21266
|
+
} catch {}
|
|
21267
|
+
throw err;
|
|
21268
|
+
}
|
|
21269
|
+
}
|
|
21270
|
+
var init_atomic_write = () => {};
|
|
21271
|
+
|
|
21597
21272
|
// src/hooks/session-pause.ts
|
|
21598
|
-
import { existsSync as
|
|
21273
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync9, readdirSync as readdirSync12, readFileSync as readFileSync15, rmSync as rmSync4 } from "node:fs";
|
|
21599
21274
|
import { createHash as createHash6 } from "node:crypto";
|
|
21600
|
-
import { join as join28, resolve as
|
|
21275
|
+
import { join as join28, resolve as resolve15 } from "node:path";
|
|
21601
21276
|
function pauseStateDir() {
|
|
21602
21277
|
const override = process.env.FAILPROOFAI_STATE_DIR;
|
|
21603
21278
|
if (override)
|
|
21604
|
-
return
|
|
21279
|
+
return resolve15(override, "sessions");
|
|
21605
21280
|
return sessionPauseDir();
|
|
21606
21281
|
}
|
|
21607
21282
|
function pauseFilePath(sessionId) {
|
|
@@ -21662,9 +21337,9 @@ function readActivePause(sessionId, now = Date.now()) {
|
|
|
21662
21337
|
return null;
|
|
21663
21338
|
try {
|
|
21664
21339
|
const path = pauseFilePath(sessionId);
|
|
21665
|
-
if (!
|
|
21340
|
+
if (!existsSync17(path))
|
|
21666
21341
|
return null;
|
|
21667
|
-
const stored = parseStored(JSON.parse(
|
|
21342
|
+
const stored = parseStored(JSON.parse(readFileSync15(path, "utf8")));
|
|
21668
21343
|
if (!stored)
|
|
21669
21344
|
return null;
|
|
21670
21345
|
if (stored.expiresAt <= now)
|
|
@@ -21687,16 +21362,16 @@ function writePause(opts) {
|
|
|
21687
21362
|
setBy: opts.setBy ?? "cli",
|
|
21688
21363
|
...opts.cwd ? { cwd: opts.cwd } : {}
|
|
21689
21364
|
};
|
|
21690
|
-
|
|
21365
|
+
mkdirSync9(pauseStateDir(), { recursive: true, mode: 448 });
|
|
21691
21366
|
writeJsonAtomically(pauseFilePath(opts.sessionId), { schemaVersion: SCHEMA_VERSION, ...pause });
|
|
21692
21367
|
return pause;
|
|
21693
21368
|
}
|
|
21694
21369
|
function clearPause(sessionId) {
|
|
21695
21370
|
const path = pauseFilePath(sessionId);
|
|
21696
|
-
if (!
|
|
21371
|
+
if (!existsSync17(path))
|
|
21697
21372
|
return false;
|
|
21698
21373
|
try {
|
|
21699
|
-
|
|
21374
|
+
rmSync4(path);
|
|
21700
21375
|
return true;
|
|
21701
21376
|
} catch {
|
|
21702
21377
|
return false;
|
|
@@ -21704,12 +21379,12 @@ function clearPause(sessionId) {
|
|
|
21704
21379
|
}
|
|
21705
21380
|
function listActivePauses(now = Date.now()) {
|
|
21706
21381
|
const dir = pauseStateDir();
|
|
21707
|
-
if (!
|
|
21382
|
+
if (!existsSync17(dir))
|
|
21708
21383
|
return [];
|
|
21709
21384
|
const out = [];
|
|
21710
21385
|
let names;
|
|
21711
21386
|
try {
|
|
21712
|
-
names =
|
|
21387
|
+
names = readdirSync12(dir);
|
|
21713
21388
|
} catch {
|
|
21714
21389
|
return [];
|
|
21715
21390
|
}
|
|
@@ -21717,7 +21392,7 @@ function listActivePauses(now = Date.now()) {
|
|
|
21717
21392
|
if (!name.endsWith(".json"))
|
|
21718
21393
|
continue;
|
|
21719
21394
|
try {
|
|
21720
|
-
const stored = parseStored(JSON.parse(
|
|
21395
|
+
const stored = parseStored(JSON.parse(readFileSync15(join28(dir, name), "utf8")));
|
|
21721
21396
|
if (!stored || stored.expiresAt <= now)
|
|
21722
21397
|
continue;
|
|
21723
21398
|
const { schemaVersion: _ignored, ...pause } = stored;
|
|
@@ -21758,17 +21433,17 @@ var init_session_pause = __esm(() => {
|
|
|
21758
21433
|
import { createHash as createHash7 } from "node:crypto";
|
|
21759
21434
|
import {
|
|
21760
21435
|
chmodSync as chmodSync3,
|
|
21761
|
-
existsSync as
|
|
21762
|
-
mkdirSync as
|
|
21763
|
-
readdirSync as
|
|
21764
|
-
readFileSync as
|
|
21436
|
+
existsSync as existsSync18,
|
|
21437
|
+
mkdirSync as mkdirSync10,
|
|
21438
|
+
readdirSync as readdirSync13,
|
|
21439
|
+
readFileSync as readFileSync16,
|
|
21765
21440
|
renameSync as renameSync5,
|
|
21766
|
-
rmSync as
|
|
21767
|
-
statSync as
|
|
21768
|
-
writeFileSync as
|
|
21441
|
+
rmSync as rmSync5,
|
|
21442
|
+
statSync as statSync15,
|
|
21443
|
+
writeFileSync as writeFileSync8
|
|
21769
21444
|
} from "node:fs";
|
|
21770
21445
|
import { createRequire as createRequire2 } from "node:module";
|
|
21771
|
-
import { dirname as
|
|
21446
|
+
import { dirname as dirname9, resolve as resolve16 } from "node:path";
|
|
21772
21447
|
import { gunzipSync } from "node:zlib";
|
|
21773
21448
|
function baseUrl2() {
|
|
21774
21449
|
return (process.env.FAILPROOFAI_DAEMON_BASE_URL || DEFAULT_BASE_URL2).replace(/\/+$/, "");
|
|
@@ -21777,7 +21452,7 @@ function daemonBinaryDir() {
|
|
|
21777
21452
|
return binDir();
|
|
21778
21453
|
}
|
|
21779
21454
|
function installedBinaryPath(ver = version2) {
|
|
21780
|
-
return
|
|
21455
|
+
return resolve16(daemonBinaryDir(), `failproofaid-${ver}`);
|
|
21781
21456
|
}
|
|
21782
21457
|
function daemonAssetUrl(key, ver = version2) {
|
|
21783
21458
|
return `${baseUrl2()}/v${ver}/failproofaid-${key}.gz`;
|
|
@@ -21794,35 +21469,35 @@ function npmPlatformBinaryPath(key) {
|
|
|
21794
21469
|
return null;
|
|
21795
21470
|
const name = platformPackageName(key);
|
|
21796
21471
|
try {
|
|
21797
|
-
const requireFromRoot = createRequire2(
|
|
21798
|
-
const found = platformPackageBinary(
|
|
21472
|
+
const requireFromRoot = createRequire2(resolve16(packageRoot, "package.json"));
|
|
21473
|
+
const found = platformPackageBinary(dirname9(requireFromRoot.resolve(`${name}/package.json`)));
|
|
21799
21474
|
if (found)
|
|
21800
21475
|
return found;
|
|
21801
21476
|
} catch {}
|
|
21802
|
-
return platformPackageBinary(
|
|
21477
|
+
return platformPackageBinary(resolve16(packageRoot, "node_modules", name));
|
|
21803
21478
|
}
|
|
21804
21479
|
function platformPackageBinary(dir) {
|
|
21805
21480
|
try {
|
|
21806
|
-
const manifest = JSON.parse(
|
|
21481
|
+
const manifest = JSON.parse(readFileSync16(resolve16(dir, "package.json"), "utf8"));
|
|
21807
21482
|
if (manifest.version !== version2)
|
|
21808
21483
|
return null;
|
|
21809
21484
|
} catch {
|
|
21810
21485
|
return null;
|
|
21811
21486
|
}
|
|
21812
|
-
const candidate =
|
|
21813
|
-
return
|
|
21487
|
+
const candidate = resolve16(dir, "bin", "failproofaid");
|
|
21488
|
+
return existsSync18(candidate) ? candidate : null;
|
|
21814
21489
|
}
|
|
21815
21490
|
function pruneOldDaemonBinaries(keep = 2) {
|
|
21816
21491
|
const removed = [];
|
|
21817
21492
|
try {
|
|
21818
21493
|
const dir = daemonBinaryDir();
|
|
21819
|
-
const entries =
|
|
21820
|
-
const full =
|
|
21821
|
-
return { full, mtime:
|
|
21494
|
+
const entries = readdirSync13(dir).filter((f) => f.startsWith("failproofaid-") && !f.endsWith(".tmp")).map((f) => {
|
|
21495
|
+
const full = resolve16(dir, f);
|
|
21496
|
+
return { full, mtime: statSync15(full).mtimeMs };
|
|
21822
21497
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
21823
21498
|
for (const stale of entries.slice(keep)) {
|
|
21824
21499
|
try {
|
|
21825
|
-
|
|
21500
|
+
rmSync5(stale.full, { force: true });
|
|
21826
21501
|
removed.push(stale.full);
|
|
21827
21502
|
} catch {}
|
|
21828
21503
|
}
|
|
@@ -21833,13 +21508,13 @@ function installBinaryBytes(binary) {
|
|
|
21833
21508
|
const target = installedBinaryPath();
|
|
21834
21509
|
const tempPath = `${target}.${process.pid}.tmp`;
|
|
21835
21510
|
try {
|
|
21836
|
-
|
|
21837
|
-
|
|
21511
|
+
mkdirSync10(daemonBinaryDir(), { recursive: true });
|
|
21512
|
+
writeFileSync8(tempPath, binary);
|
|
21838
21513
|
chmodSync3(tempPath, 493);
|
|
21839
21514
|
renameSync5(tempPath, target);
|
|
21840
21515
|
return target;
|
|
21841
21516
|
} catch (err) {
|
|
21842
|
-
|
|
21517
|
+
rmSync5(tempPath, { force: true });
|
|
21843
21518
|
throw err;
|
|
21844
21519
|
}
|
|
21845
21520
|
}
|
|
@@ -21853,7 +21528,7 @@ function installFromNpmPackage(key) {
|
|
|
21853
21528
|
if (!source)
|
|
21854
21529
|
return { error: `${platformPackageName(key)} is not installed` };
|
|
21855
21530
|
try {
|
|
21856
|
-
const bytes =
|
|
21531
|
+
const bytes = readFileSync16(source);
|
|
21857
21532
|
const mismatch = binaryDigestMismatch(expectedNpmBinaryDigest(key), bytes, source);
|
|
21858
21533
|
if (mismatch)
|
|
21859
21534
|
return { error: mismatch };
|
|
@@ -21888,7 +21563,7 @@ function digestFor2(manifest, assetName) {
|
|
|
21888
21563
|
}
|
|
21889
21564
|
async function downloadFailproofaidBinary(key) {
|
|
21890
21565
|
const target = installedBinaryPath();
|
|
21891
|
-
if (
|
|
21566
|
+
if (existsSync18(target))
|
|
21892
21567
|
return { path: target };
|
|
21893
21568
|
if (process.env.FAILPROOFAI_NO_DOWNLOAD) {
|
|
21894
21569
|
return { error: "daemon downloads are disabled (FAILPROOFAI_NO_DOWNLOAD)" };
|
|
@@ -21922,10 +21597,10 @@ var init_daemon_download = __esm(() => {
|
|
|
21922
21597
|
|
|
21923
21598
|
// src/hooks/daemon-client.ts
|
|
21924
21599
|
import { createConnection as createConnection2 } from "node:net";
|
|
21925
|
-
import { existsSync as
|
|
21600
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
21926
21601
|
function daemonSocketPresent() {
|
|
21927
21602
|
try {
|
|
21928
|
-
return
|
|
21603
|
+
return existsSync19(socketPath2());
|
|
21929
21604
|
} catch {
|
|
21930
21605
|
return false;
|
|
21931
21606
|
}
|
|
@@ -22051,16 +21726,16 @@ var init_daemon_client2 = __esm(() => {
|
|
|
22051
21726
|
|
|
22052
21727
|
// src/hooks/daemon-service.ts
|
|
22053
21728
|
import {
|
|
22054
|
-
existsSync as
|
|
22055
|
-
mkdirSync as
|
|
21729
|
+
existsSync as existsSync20,
|
|
21730
|
+
mkdirSync as mkdirSync11,
|
|
22056
21731
|
mkdtempSync,
|
|
22057
|
-
readFileSync as
|
|
22058
|
-
writeFileSync as
|
|
21732
|
+
readFileSync as readFileSync17,
|
|
21733
|
+
writeFileSync as writeFileSync9,
|
|
22059
21734
|
unlinkSync as unlinkSync3,
|
|
22060
|
-
rmSync as
|
|
21735
|
+
rmSync as rmSync6
|
|
22061
21736
|
} from "node:fs";
|
|
22062
21737
|
import { homedir as homedir21, tmpdir as tmpdir2, userInfo } from "node:os";
|
|
22063
|
-
import { resolve as
|
|
21738
|
+
import { resolve as resolve17 } from "node:path";
|
|
22064
21739
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
22065
21740
|
function setDaemonConfigured(value, installedVersion) {
|
|
22066
21741
|
try {
|
|
@@ -22082,13 +21757,13 @@ function resolveFailproofaidBinaryPath() {
|
|
|
22082
21757
|
if (process.env.FAILPROOFAI_DAEMON_BINARY)
|
|
22083
21758
|
return process.env.FAILPROOFAI_DAEMON_BINARY;
|
|
22084
21759
|
const downloaded = installedBinaryPath();
|
|
22085
|
-
if (
|
|
21760
|
+
if (existsSync20(downloaded))
|
|
22086
21761
|
return downloaded;
|
|
22087
21762
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
22088
21763
|
if (packageRoot) {
|
|
22089
21764
|
for (const profile of ["release", "debug"]) {
|
|
22090
|
-
const candidate =
|
|
22091
|
-
if (
|
|
21765
|
+
const candidate = resolve17(packageRoot, "target", profile, "failproofaid");
|
|
21766
|
+
if (existsSync20(candidate))
|
|
22092
21767
|
return candidate;
|
|
22093
21768
|
}
|
|
22094
21769
|
}
|
|
@@ -22118,8 +21793,8 @@ function resolveWorkerCommand() {
|
|
|
22118
21793
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
22119
21794
|
if (!packageRoot)
|
|
22120
21795
|
return null;
|
|
22121
|
-
const workerScript =
|
|
22122
|
-
if (!
|
|
21796
|
+
const workerScript = resolve17(packageRoot, "dist", "worker.mjs");
|
|
21797
|
+
if (!existsSync20(workerScript))
|
|
22123
21798
|
return null;
|
|
22124
21799
|
return `${shellQuote(process.execPath)} ${shellQuote(workerScript)}`;
|
|
22125
21800
|
}
|
|
@@ -22129,8 +21804,8 @@ function resolveCliCommand() {
|
|
|
22129
21804
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
22130
21805
|
if (!packageRoot)
|
|
22131
21806
|
return null;
|
|
22132
|
-
const cliScript =
|
|
22133
|
-
if (!
|
|
21807
|
+
const cliScript = resolve17(packageRoot, "dist", "cli.mjs");
|
|
21808
|
+
if (!existsSync20(cliScript))
|
|
22134
21809
|
return null;
|
|
22135
21810
|
return `${shellQuote(process.execPath)} ${shellQuote(cliScript)}`;
|
|
22136
21811
|
}
|
|
@@ -22143,8 +21818,8 @@ function workerScriptPath() {
|
|
|
22143
21818
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
22144
21819
|
if (!packageRoot)
|
|
22145
21820
|
return null;
|
|
22146
|
-
const workerScript =
|
|
22147
|
-
return
|
|
21821
|
+
const workerScript = resolve17(packageRoot, "dist", "worker.mjs");
|
|
21822
|
+
return existsSync20(workerScript) ? workerScript : null;
|
|
22148
21823
|
}
|
|
22149
21824
|
function assertUnitSafe(value, field) {
|
|
22150
21825
|
if (UNIT_UNSAFE_RE.test(value)) {
|
|
@@ -22170,10 +21845,10 @@ function systemdUnitDir() {
|
|
|
22170
21845
|
return process.env.FAILPROOFAI_SYSTEMD_DIR || "/etc/systemd/system";
|
|
22171
21846
|
}
|
|
22172
21847
|
function systemdUnitPath(user = serviceUser()) {
|
|
22173
|
-
return
|
|
21848
|
+
return resolve17(systemdUnitDir(), systemdUnitName(user));
|
|
22174
21849
|
}
|
|
22175
21850
|
function legacySystemdUserUnitPath() {
|
|
22176
|
-
return
|
|
21851
|
+
return resolve17(homedir21(), ".config", "systemd", "user", "failproofaid.service");
|
|
22177
21852
|
}
|
|
22178
21853
|
function launchdLabel(user = serviceUser()) {
|
|
22179
21854
|
return `ai.failproof.failproofaid.${user}`;
|
|
@@ -22182,7 +21857,7 @@ function launchdPlistPath(user = serviceUser()) {
|
|
|
22182
21857
|
return `/Library/LaunchDaemons/${launchdLabel(user)}.plist`;
|
|
22183
21858
|
}
|
|
22184
21859
|
function legacyLaunchAgentPlistPath() {
|
|
22185
|
-
return
|
|
21860
|
+
return resolve17(homedir21(), "Library", "LaunchAgents", "ai.failproof.failproofaid.plist");
|
|
22186
21861
|
}
|
|
22187
21862
|
function legacySharedLaunchDaemonPath() {
|
|
22188
21863
|
return "/Library/LaunchDaemons/ai.failproof.failproofaid.plist";
|
|
@@ -22230,20 +21905,20 @@ function runPrivileged(command, args) {
|
|
|
22230
21905
|
execFileSync2(cmd, argv, { stdio: "ignore", timeout: SERVICE_CMD_TIMEOUT_MS });
|
|
22231
21906
|
}
|
|
22232
21907
|
function writePrivilegedFile(destination, contents, mode = "0644") {
|
|
22233
|
-
const stagingDir = mkdtempSync(
|
|
22234
|
-
const staging =
|
|
21908
|
+
const stagingDir = mkdtempSync(resolve17(tmpdir2(), "failproofaid-stage-"));
|
|
21909
|
+
const staging = resolve17(stagingDir, "service-definition");
|
|
22235
21910
|
try {
|
|
22236
|
-
|
|
21911
|
+
writeFileSync9(staging, contents, "utf8");
|
|
22237
21912
|
runPrivileged("install", ["-m", mode, staging, destination]);
|
|
22238
21913
|
} finally {
|
|
22239
|
-
|
|
21914
|
+
rmSync6(stagingDir, { recursive: true, force: true });
|
|
22240
21915
|
}
|
|
22241
21916
|
}
|
|
22242
21917
|
function removeLegacyUserService() {
|
|
22243
21918
|
try {
|
|
22244
21919
|
if (process.platform === "linux") {
|
|
22245
21920
|
const legacy = legacySystemdUserUnitPath();
|
|
22246
|
-
if (!
|
|
21921
|
+
if (!existsSync20(legacy))
|
|
22247
21922
|
return;
|
|
22248
21923
|
try {
|
|
22249
21924
|
execFileSync2("systemctl", ["--user", "disable", "--now", "failproofaid.service"], {
|
|
@@ -22260,7 +21935,7 @@ function removeLegacyUserService() {
|
|
|
22260
21935
|
} catch {}
|
|
22261
21936
|
} else {
|
|
22262
21937
|
const legacyAgent = legacyLaunchAgentPlistPath();
|
|
22263
|
-
if (
|
|
21938
|
+
if (existsSync20(legacyAgent)) {
|
|
22264
21939
|
try {
|
|
22265
21940
|
execFileSync2("launchctl", ["unload", "-w", legacyAgent], {
|
|
22266
21941
|
stdio: "ignore",
|
|
@@ -22270,7 +21945,7 @@ function removeLegacyUserService() {
|
|
|
22270
21945
|
unlinkSync3(legacyAgent);
|
|
22271
21946
|
}
|
|
22272
21947
|
const legacyDaemon = legacySharedLaunchDaemonPath();
|
|
22273
|
-
if (
|
|
21948
|
+
if (existsSync20(legacyDaemon)) {
|
|
22274
21949
|
try {
|
|
22275
21950
|
runPrivileged("launchctl", ["unload", "-w", legacyDaemon]);
|
|
22276
21951
|
} catch {}
|
|
@@ -22287,7 +21962,7 @@ function systemdUnitContents(binaryPath, workerCmd, cliCmd = null) {
|
|
|
22287
21962
|
const user = assertUnitSafe(serviceUser(), "User");
|
|
22288
21963
|
assertUnitSafe(binaryPath, "ExecStart");
|
|
22289
21964
|
assertUnitSafe(homedir21(), "HOME");
|
|
22290
|
-
const conditionPaths = [binaryPath, workerScriptPath()].filter((p) => typeof p === "string" &&
|
|
21965
|
+
const conditionPaths = [binaryPath, workerScriptPath()].filter((p) => typeof p === "string" && existsSync20(p));
|
|
22291
21966
|
const conditionLines = conditionPaths.map((p) => `ConditionPathExists=${assertUnitSafe(p, "ConditionPathExists")}
|
|
22292
21967
|
`).join("");
|
|
22293
21968
|
return `[Unit]
|
|
@@ -22348,9 +22023,9 @@ ${env.map(([key, value]) => ` <key>${key}</key>
|
|
|
22348
22023
|
<key>UserName</key>
|
|
22349
22024
|
<string>${escapeXml(serviceUser())}</string>
|
|
22350
22025
|
${envBlock} <key>StandardOutPath</key>
|
|
22351
|
-
<string>${escapeXml(
|
|
22026
|
+
<string>${escapeXml(resolve17(logDir, "failproofaid.log"))}</string>
|
|
22352
22027
|
<key>StandardErrorPath</key>
|
|
22353
|
-
<string>${escapeXml(
|
|
22028
|
+
<string>${escapeXml(resolve17(logDir, "failproofaid.err.log"))}</string>
|
|
22354
22029
|
</dict>
|
|
22355
22030
|
</plist>
|
|
22356
22031
|
`;
|
|
@@ -22396,7 +22071,7 @@ async function installDaemonService() {
|
|
|
22396
22071
|
} else {
|
|
22397
22072
|
const plistPath = launchdPlistPath();
|
|
22398
22073
|
const logDir = logsDir();
|
|
22399
|
-
|
|
22074
|
+
mkdirSync11(logDir, { recursive: true });
|
|
22400
22075
|
try {
|
|
22401
22076
|
runPrivileged("launchctl", ["unload", plistPath]);
|
|
22402
22077
|
} catch {}
|
|
@@ -22482,10 +22157,10 @@ function readInstalledServiceDefinition() {
|
|
|
22482
22157
|
if (!isDaemonSupportedPlatform())
|
|
22483
22158
|
return null;
|
|
22484
22159
|
const path = daemonServiceFilePath();
|
|
22485
|
-
if (!path || !
|
|
22160
|
+
if (!path || !existsSync20(path))
|
|
22486
22161
|
return null;
|
|
22487
22162
|
try {
|
|
22488
|
-
return
|
|
22163
|
+
return readFileSync17(path, "utf8");
|
|
22489
22164
|
} catch {
|
|
22490
22165
|
return null;
|
|
22491
22166
|
}
|
|
@@ -22594,7 +22269,7 @@ async function ensureDaemonServiceCurrent() {
|
|
|
22594
22269
|
restartSystemdUnit();
|
|
22595
22270
|
} else {
|
|
22596
22271
|
const plistPath = launchdPlistPath();
|
|
22597
|
-
|
|
22272
|
+
mkdirSync11(logDir, { recursive: true });
|
|
22598
22273
|
previous = definition;
|
|
22599
22274
|
try {
|
|
22600
22275
|
runPrivileged("launchctl", ["unload", plistPath]);
|
|
@@ -22618,7 +22293,7 @@ async function uninstallDaemonService() {
|
|
|
22618
22293
|
try {
|
|
22619
22294
|
if (process.platform === "linux") {
|
|
22620
22295
|
const unitPath = systemdUnitPath();
|
|
22621
|
-
if (!
|
|
22296
|
+
if (!existsSync20(unitPath))
|
|
22622
22297
|
return;
|
|
22623
22298
|
try {
|
|
22624
22299
|
runPrivileged("systemctl", ["disable", "--now", systemdUnitName()]);
|
|
@@ -22629,7 +22304,7 @@ async function uninstallDaemonService() {
|
|
|
22629
22304
|
} catch {}
|
|
22630
22305
|
} else {
|
|
22631
22306
|
const plistPath = launchdPlistPath();
|
|
22632
|
-
if (!
|
|
22307
|
+
if (!existsSync20(plistPath))
|
|
22633
22308
|
return;
|
|
22634
22309
|
try {
|
|
22635
22310
|
runPrivileged("launchctl", ["unload", "-w", plistPath]);
|
|
@@ -22646,7 +22321,7 @@ function daemonVersionSkew() {
|
|
|
22646
22321
|
const recorded = readVersionFile()?.daemon;
|
|
22647
22322
|
if (!recorded)
|
|
22648
22323
|
return null;
|
|
22649
|
-
if (!
|
|
22324
|
+
if (!existsSync20(installedBinaryPath(recorded)))
|
|
22650
22325
|
return null;
|
|
22651
22326
|
return recorded === version2 ? null : { installed: recorded, expected: version2 };
|
|
22652
22327
|
}
|
|
@@ -22664,7 +22339,7 @@ function daemonServiceStatus() {
|
|
|
22664
22339
|
if (!isDaemonSupportedPlatform())
|
|
22665
22340
|
return "unsupported-platform";
|
|
22666
22341
|
if (process.platform === "linux") {
|
|
22667
|
-
if (!
|
|
22342
|
+
if (!existsSync20(systemdUnitPath()))
|
|
22668
22343
|
return "not-installed";
|
|
22669
22344
|
try {
|
|
22670
22345
|
const out = execFileSync2("systemctl", ["is-active", systemdUnitName()], {
|
|
@@ -22677,7 +22352,7 @@ function daemonServiceStatus() {
|
|
|
22677
22352
|
}
|
|
22678
22353
|
}
|
|
22679
22354
|
const plistPath = launchdPlistPath();
|
|
22680
|
-
if (!
|
|
22355
|
+
if (!existsSync20(plistPath))
|
|
22681
22356
|
return "not-installed";
|
|
22682
22357
|
try {
|
|
22683
22358
|
const root = typeof process.getuid === "function" && process.getuid() === 0;
|
|
@@ -22709,48 +22384,48 @@ var init_daemon_service = __esm(() => {
|
|
|
22709
22384
|
// src/hooks/fp-reset.ts
|
|
22710
22385
|
import {
|
|
22711
22386
|
copyFileSync,
|
|
22712
|
-
existsSync as
|
|
22713
|
-
mkdirSync as
|
|
22714
|
-
readFileSync as
|
|
22715
|
-
readdirSync as
|
|
22387
|
+
existsSync as existsSync21,
|
|
22388
|
+
mkdirSync as mkdirSync12,
|
|
22389
|
+
readFileSync as readFileSync18,
|
|
22390
|
+
readdirSync as readdirSync14,
|
|
22716
22391
|
renameSync as renameSync6,
|
|
22717
|
-
rmSync as
|
|
22392
|
+
rmSync as rmSync7,
|
|
22718
22393
|
rmdirSync,
|
|
22719
|
-
statSync as
|
|
22720
|
-
writeFileSync as
|
|
22394
|
+
statSync as statSync16,
|
|
22395
|
+
writeFileSync as writeFileSync10
|
|
22721
22396
|
} from "node:fs";
|
|
22722
|
-
import { dirname as
|
|
22397
|
+
import { dirname as dirname10, isAbsolute as isAbsolute3, relative as relative4, resolve as resolve18 } from "node:path";
|
|
22723
22398
|
function migrateConventionPolicies() {
|
|
22724
22399
|
const from = legacy.customPoliciesDir();
|
|
22725
|
-
if (!
|
|
22400
|
+
if (!existsSync21(from))
|
|
22726
22401
|
return [];
|
|
22727
22402
|
const moved = [];
|
|
22728
22403
|
const mergeInto = (dir, dest, prefix) => {
|
|
22729
22404
|
let entries;
|
|
22730
22405
|
try {
|
|
22731
|
-
entries =
|
|
22406
|
+
entries = readdirSync14(dir, { withFileTypes: true });
|
|
22732
22407
|
} catch {
|
|
22733
22408
|
return;
|
|
22734
22409
|
}
|
|
22735
22410
|
if (entries.length === 0)
|
|
22736
22411
|
return;
|
|
22737
22412
|
try {
|
|
22738
|
-
|
|
22413
|
+
mkdirSync12(dest, { recursive: true });
|
|
22739
22414
|
} catch {
|
|
22740
22415
|
return;
|
|
22741
22416
|
}
|
|
22742
22417
|
for (const entry of entries) {
|
|
22743
|
-
const source =
|
|
22744
|
-
const target =
|
|
22418
|
+
const source = resolve18(dir, entry.name);
|
|
22419
|
+
const target = resolve18(dest, entry.name);
|
|
22745
22420
|
const name = `${prefix}${entry.name}`;
|
|
22746
|
-
if (!
|
|
22421
|
+
if (!existsSync21(target)) {
|
|
22747
22422
|
try {
|
|
22748
22423
|
renameSync6(source, target);
|
|
22749
22424
|
moved.push(name);
|
|
22750
22425
|
} catch {}
|
|
22751
22426
|
continue;
|
|
22752
22427
|
}
|
|
22753
|
-
if (entry.isDirectory() &&
|
|
22428
|
+
if (entry.isDirectory() && statSync16(target).isDirectory()) {
|
|
22754
22429
|
mergeInto(source, target, `${name}/`);
|
|
22755
22430
|
try {
|
|
22756
22431
|
rmdirSync(source);
|
|
@@ -22770,23 +22445,23 @@ function migrateLegacySpool() {
|
|
|
22770
22445
|
[legacy.spoolDir(), spoolDir()],
|
|
22771
22446
|
[legacy.failedDir(), failedDir()]
|
|
22772
22447
|
]) {
|
|
22773
|
-
if (!
|
|
22448
|
+
if (!existsSync21(from))
|
|
22774
22449
|
continue;
|
|
22775
22450
|
try {
|
|
22776
|
-
|
|
22777
|
-
for (const entry of
|
|
22451
|
+
mkdirSync12(to, { recursive: true });
|
|
22452
|
+
for (const entry of readdirSync14(from, { withFileTypes: true })) {
|
|
22778
22453
|
if (!entry.isFile())
|
|
22779
22454
|
continue;
|
|
22780
22455
|
let name = entry.name;
|
|
22781
22456
|
let n = 0;
|
|
22782
|
-
while (
|
|
22457
|
+
while (existsSync21(resolve18(to, name)))
|
|
22783
22458
|
name = `legacy-${n++}-${entry.name}`;
|
|
22784
22459
|
try {
|
|
22785
|
-
renameSync6(
|
|
22460
|
+
renameSync6(resolve18(from, entry.name), resolve18(to, name));
|
|
22786
22461
|
moved.push(name);
|
|
22787
22462
|
} catch {
|
|
22788
22463
|
try {
|
|
22789
|
-
copyFileSync(
|
|
22464
|
+
copyFileSync(resolve18(from, entry.name), resolve18(to, name));
|
|
22790
22465
|
moved.push(name);
|
|
22791
22466
|
} catch {}
|
|
22792
22467
|
}
|
|
@@ -22797,24 +22472,24 @@ function migrateLegacySpool() {
|
|
|
22797
22472
|
}
|
|
22798
22473
|
function migrateHookActivity() {
|
|
22799
22474
|
const from = legacy.hookActivityDir();
|
|
22800
|
-
if (!
|
|
22475
|
+
if (!existsSync21(from))
|
|
22801
22476
|
return [];
|
|
22802
22477
|
const moved = [];
|
|
22803
22478
|
try {
|
|
22804
|
-
const entries =
|
|
22479
|
+
const entries = readdirSync14(from, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl"));
|
|
22805
22480
|
if (entries.length === 0)
|
|
22806
22481
|
return [];
|
|
22807
22482
|
const to = hookActivityDir();
|
|
22808
|
-
|
|
22483
|
+
mkdirSync12(to, { recursive: true });
|
|
22809
22484
|
const stamp = Date.now();
|
|
22810
22485
|
let seq = 0;
|
|
22811
22486
|
for (const entry of entries) {
|
|
22812
|
-
const source =
|
|
22487
|
+
const source = resolve18(from, entry.name);
|
|
22813
22488
|
let name = entry.name === "current.jsonl" ? `page-${stamp}-${seq++}.jsonl` : entry.name;
|
|
22814
|
-
let target =
|
|
22815
|
-
while (
|
|
22489
|
+
let target = resolve18(to, name);
|
|
22490
|
+
while (existsSync21(target)) {
|
|
22816
22491
|
name = `page-${stamp}-${seq++}.jsonl`;
|
|
22817
|
-
target =
|
|
22492
|
+
target = resolve18(to, name);
|
|
22818
22493
|
}
|
|
22819
22494
|
try {
|
|
22820
22495
|
renameSync6(source, target);
|
|
@@ -22838,7 +22513,7 @@ function retirePolicyConfigKeys() {
|
|
|
22838
22513
|
const at = globalPolicyConfigFile();
|
|
22839
22514
|
let parsed;
|
|
22840
22515
|
try {
|
|
22841
|
-
const raw = JSON.parse(
|
|
22516
|
+
const raw = JSON.parse(readFileSync18(at, "utf8"));
|
|
22842
22517
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
22843
22518
|
return [];
|
|
22844
22519
|
parsed = raw;
|
|
@@ -22852,9 +22527,9 @@ function retirePolicyConfigKeys() {
|
|
|
22852
22527
|
delete parsed[key];
|
|
22853
22528
|
try {
|
|
22854
22529
|
if (Object.keys(parsed).length === 0)
|
|
22855
|
-
|
|
22530
|
+
rmSync7(at, { force: true });
|
|
22856
22531
|
else
|
|
22857
|
-
|
|
22532
|
+
writeFileSync10(at, JSON.stringify(parsed, null, 2) + `
|
|
22858
22533
|
`, "utf8");
|
|
22859
22534
|
} catch {
|
|
22860
22535
|
return [];
|
|
@@ -22862,12 +22537,12 @@ function retirePolicyConfigKeys() {
|
|
|
22862
22537
|
return [...removed];
|
|
22863
22538
|
}
|
|
22864
22539
|
function readCarriedPolicyConfig() {
|
|
22865
|
-
const from =
|
|
22866
|
-
if (!
|
|
22540
|
+
const from = resolve18(legacy.localPoliciesDir(), "policies-config.json");
|
|
22541
|
+
if (!existsSync21(from))
|
|
22867
22542
|
return null;
|
|
22868
22543
|
let parsed;
|
|
22869
22544
|
try {
|
|
22870
|
-
parsed = JSON.parse(
|
|
22545
|
+
parsed = JSON.parse(readFileSync18(from, "utf8"));
|
|
22871
22546
|
} catch {
|
|
22872
22547
|
return null;
|
|
22873
22548
|
}
|
|
@@ -22892,11 +22567,11 @@ function rewriteCarriedCustomPaths(carried) {
|
|
|
22892
22567
|
const repoint = (value) => {
|
|
22893
22568
|
if (typeof value !== "string" || value === "")
|
|
22894
22569
|
return value;
|
|
22895
|
-
const abs =
|
|
22570
|
+
const abs = resolve18(value);
|
|
22896
22571
|
const rel = relative4(fromDir, abs);
|
|
22897
22572
|
if (rel === "" || rel.startsWith("..") || isAbsolute3(rel))
|
|
22898
22573
|
return value;
|
|
22899
|
-
return
|
|
22574
|
+
return resolve18(toDir, rel);
|
|
22900
22575
|
};
|
|
22901
22576
|
if (Array.isArray(carried.customPoliciesPaths)) {
|
|
22902
22577
|
carried.customPoliciesPaths = carried.customPoliciesPaths.map(repoint);
|
|
@@ -22911,14 +22586,14 @@ function writeCarriedPolicyConfig(carried) {
|
|
|
22911
22586
|
const to = globalPolicyConfigFile();
|
|
22912
22587
|
let existing = {};
|
|
22913
22588
|
try {
|
|
22914
|
-
const parsed = JSON.parse(
|
|
22589
|
+
const parsed = JSON.parse(readFileSync18(to, "utf8"));
|
|
22915
22590
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
22916
22591
|
existing = parsed;
|
|
22917
22592
|
}
|
|
22918
22593
|
} catch {}
|
|
22919
22594
|
try {
|
|
22920
|
-
|
|
22921
|
-
|
|
22595
|
+
mkdirSync12(dirname10(to), { recursive: true });
|
|
22596
|
+
writeFileSync10(to, JSON.stringify({ ...existing, ...carried }, null, 2) + `
|
|
22922
22597
|
`, "utf8");
|
|
22923
22598
|
} catch {
|
|
22924
22599
|
return [];
|
|
@@ -22927,10 +22602,10 @@ function writeCarriedPolicyConfig(carried) {
|
|
|
22927
22602
|
}
|
|
22928
22603
|
function readCarriedTelemetryOptOut() {
|
|
22929
22604
|
const from = legacy.configToml();
|
|
22930
|
-
if (!
|
|
22605
|
+
if (!existsSync21(from))
|
|
22931
22606
|
return false;
|
|
22932
22607
|
try {
|
|
22933
|
-
const text =
|
|
22608
|
+
const text = readFileSync18(from, "utf8");
|
|
22934
22609
|
const start = text.search(/^\s*\[telemetry\]\s*$/m);
|
|
22935
22610
|
if (start === -1)
|
|
22936
22611
|
return false;
|
|
@@ -22982,26 +22657,26 @@ function parseLegacyToml(text) {
|
|
|
22982
22657
|
}
|
|
22983
22658
|
function readCarriedLegacyConfig() {
|
|
22984
22659
|
const from = legacy.configToml();
|
|
22985
|
-
if (!
|
|
22660
|
+
if (!existsSync21(from))
|
|
22986
22661
|
return null;
|
|
22987
22662
|
try {
|
|
22988
|
-
return projectConfig(parseLegacyToml(
|
|
22663
|
+
return projectConfig(parseLegacyToml(readFileSync18(from, "utf8")));
|
|
22989
22664
|
} catch {
|
|
22990
22665
|
return null;
|
|
22991
22666
|
}
|
|
22992
22667
|
}
|
|
22993
22668
|
function readCarriedLegacyCredentials() {
|
|
22994
22669
|
const toml = legacy.credentialsToml();
|
|
22995
|
-
if (
|
|
22670
|
+
if (existsSync21(toml)) {
|
|
22996
22671
|
try {
|
|
22997
|
-
const creds = projectCredentials(parseLegacyToml(
|
|
22672
|
+
const creds = projectCredentials(parseLegacyToml(readFileSync18(toml, "utf8")));
|
|
22998
22673
|
if (Object.keys(creds).length > 0)
|
|
22999
22674
|
return creds;
|
|
23000
22675
|
} catch {}
|
|
23001
22676
|
}
|
|
23002
22677
|
const readJson = (path) => {
|
|
23003
22678
|
try {
|
|
23004
|
-
const parsed = JSON.parse(
|
|
22679
|
+
const parsed = JSON.parse(readFileSync18(path, "utf8"));
|
|
23005
22680
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
23006
22681
|
} catch {
|
|
23007
22682
|
return null;
|
|
@@ -23035,10 +22710,10 @@ function resetHome(from, to = LAYOUT_VERSION) {
|
|
|
23035
22710
|
const spooled = migrateLegacySpool();
|
|
23036
22711
|
const removed = [];
|
|
23037
22712
|
for (const path of resettablePaths()) {
|
|
23038
|
-
if (!
|
|
22713
|
+
if (!existsSync21(path))
|
|
23039
22714
|
continue;
|
|
23040
22715
|
try {
|
|
23041
|
-
|
|
22716
|
+
rmSync7(path, { recursive: true, force: true });
|
|
23042
22717
|
removed.push(path);
|
|
23043
22718
|
} catch {}
|
|
23044
22719
|
}
|
|
@@ -23060,7 +22735,7 @@ function layoutWarningForHook() {
|
|
|
23060
22735
|
if (state.kind === "future") {
|
|
23061
22736
|
return `[failproofai] this directory was written by a newer version (layout ${state.found} vs ${LAYOUT_VERSION}) — policies are NOT being enforced. ` + `Upgrade failproofai.`;
|
|
23062
22737
|
}
|
|
23063
|
-
if (
|
|
22738
|
+
if (existsSync21(globalPolicyConfigFile()))
|
|
23064
22739
|
return null;
|
|
23065
22740
|
return `[failproofai] setup predates this version — global policies are NOT being enforced. ` + `Run \`failproofai config\` to re-create it.`;
|
|
23066
22741
|
}
|
|
@@ -23107,31 +22782,6 @@ function canonicalizeEventType(raw, cli) {
|
|
|
23107
22782
|
}
|
|
23108
22783
|
return raw;
|
|
23109
22784
|
}
|
|
23110
|
-
function attachLeakNotice(eventType, cli, outcome, sessionId) {
|
|
23111
|
-
try {
|
|
23112
|
-
if (!canDeliverNotice(cli))
|
|
23113
|
-
return outcome;
|
|
23114
|
-
if (!cli)
|
|
23115
|
-
return outcome;
|
|
23116
|
-
const canonical = canonicalizeEventType(eventType, cli);
|
|
23117
|
-
if (canonical !== "Stop")
|
|
23118
|
-
return outcome;
|
|
23119
|
-
const pending = sessionNoticePending(sessionId ?? "");
|
|
23120
|
-
if (pending.count === 0)
|
|
23121
|
-
return outcome;
|
|
23122
|
-
const shaped = shapeNotice(cli, leakNoticeText(pending.count), outcome.stdout);
|
|
23123
|
-
if (shaped.stdout === outcome.stdout && !shaped.stderr)
|
|
23124
|
-
return outcome;
|
|
23125
|
-
markSessionNoticed(sessionId ?? "");
|
|
23126
|
-
return {
|
|
23127
|
-
exitCode: outcome.exitCode,
|
|
23128
|
-
stdout: shaped.stdout,
|
|
23129
|
-
stderr: outcome.stderr + shaped.stderr
|
|
23130
|
-
};
|
|
23131
|
-
} catch {
|
|
23132
|
-
return outcome;
|
|
23133
|
-
}
|
|
23134
|
-
}
|
|
23135
22785
|
async function runObserved(hook, ctx, hookName, eventType, cli) {
|
|
23136
22786
|
try {
|
|
23137
22787
|
return await Promise.race([
|
|
@@ -23434,8 +23084,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
23434
23084
|
}
|
|
23435
23085
|
} catch {}
|
|
23436
23086
|
}
|
|
23437
|
-
|
|
23438
|
-
return withNotice;
|
|
23087
|
+
return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr };
|
|
23439
23088
|
} finally {
|
|
23440
23089
|
if (opts?.awaitTelemetryFlush ?? true) {
|
|
23441
23090
|
await flushHookTelemetry2();
|
|
@@ -23494,8 +23143,6 @@ var init_handler = __esm(() => {
|
|
|
23494
23143
|
init_custom_hooks_loader();
|
|
23495
23144
|
init_hook_activity_store();
|
|
23496
23145
|
init_delivery_health();
|
|
23497
|
-
init_notice();
|
|
23498
|
-
init_leak_notice();
|
|
23499
23146
|
init_hook_telemetry2();
|
|
23500
23147
|
init_resolve_permission_mode();
|
|
23501
23148
|
init_resolve_transcript_path();
|
|
@@ -24136,17 +23783,17 @@ var init_collector_config = __esm(() => {
|
|
|
24136
23783
|
});
|
|
24137
23784
|
|
|
24138
23785
|
// src/hooks/flush-cli.ts
|
|
24139
|
-
import { existsSync as
|
|
24140
|
-
import { dirname as
|
|
23786
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11, readdirSync as readdirSync15 } from "node:fs";
|
|
23787
|
+
import { dirname as dirname11, join as join29 } from "node:path";
|
|
24141
23788
|
function flushRequestPath(home) {
|
|
24142
23789
|
return join29(failproofaiHome(home), "state", "flush-request.json");
|
|
24143
23790
|
}
|
|
24144
23791
|
function spoolDirs(home) {
|
|
24145
23792
|
const root = spoolDir(home);
|
|
24146
|
-
if (!
|
|
23793
|
+
if (!existsSync22(root))
|
|
24147
23794
|
return [];
|
|
24148
23795
|
try {
|
|
24149
|
-
return
|
|
23796
|
+
return readdirSync15(root, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name !== "failed").map((e) => join29(root, e.name));
|
|
24150
23797
|
} catch {
|
|
24151
23798
|
return [];
|
|
24152
23799
|
}
|
|
@@ -24155,7 +23802,7 @@ function pendingBatches(home) {
|
|
|
24155
23802
|
let n = 0;
|
|
24156
23803
|
for (const dir of spoolDirs(home)) {
|
|
24157
23804
|
try {
|
|
24158
|
-
n +=
|
|
23805
|
+
n += readdirSync15(dir).filter((f) => f.endsWith(".jsonl")).length;
|
|
24159
23806
|
} catch {}
|
|
24160
23807
|
}
|
|
24161
23808
|
return n;
|
|
@@ -24212,8 +23859,8 @@ async function runFlushCommand(opts = {}) {
|
|
|
24212
23859
|
return { exitCode: 0, pending: 0, lines: ["Nothing spooled — everything already delivered."] };
|
|
24213
23860
|
}
|
|
24214
23861
|
const path = flushRequestPath(home);
|
|
24215
|
-
|
|
24216
|
-
|
|
23862
|
+
mkdirSync13(dirname11(path), { recursive: true });
|
|
23863
|
+
writeFileSync11(path, `${JSON.stringify({ requestedAtMs: Date.now() }, null, 2)}
|
|
24217
23864
|
`, {
|
|
24218
23865
|
mode: 384
|
|
24219
23866
|
});
|
|
@@ -24247,14 +23894,14 @@ var init_flush_cli = __esm(() => {
|
|
|
24247
23894
|
import {
|
|
24248
23895
|
chmodSync as chmodSync4,
|
|
24249
23896
|
copyFileSync as copyFileSync2,
|
|
24250
|
-
existsSync as
|
|
24251
|
-
mkdirSync as
|
|
24252
|
-
readFileSync as
|
|
23897
|
+
existsSync as existsSync23,
|
|
23898
|
+
mkdirSync as mkdirSync14,
|
|
23899
|
+
readFileSync as readFileSync19,
|
|
24253
23900
|
renameSync as renameSync7,
|
|
24254
|
-
rmSync as
|
|
24255
|
-
writeFileSync as
|
|
23901
|
+
rmSync as rmSync8,
|
|
23902
|
+
writeFileSync as writeFileSync12
|
|
24256
23903
|
} from "node:fs";
|
|
24257
|
-
import { basename as basename4, dirname as
|
|
23904
|
+
import { basename as basename4, dirname as dirname12, join as join30, resolve as resolve19 } from "node:path";
|
|
24258
23905
|
function migrateToLayout4() {
|
|
24259
23906
|
const moves = [
|
|
24260
23907
|
{ from: legacy.authJson(), to: auditSessionFile() },
|
|
@@ -24270,13 +23917,13 @@ function migrateToLayout4() {
|
|
|
24270
23917
|
}
|
|
24271
23918
|
const migrated = [];
|
|
24272
23919
|
for (const { from, to } of moves) {
|
|
24273
|
-
if (!
|
|
23920
|
+
if (!existsSync23(from))
|
|
24274
23921
|
continue;
|
|
24275
|
-
if (
|
|
24276
|
-
|
|
23922
|
+
if (existsSync23(to)) {
|
|
23923
|
+
rmSync8(from, { force: true });
|
|
24277
23924
|
continue;
|
|
24278
23925
|
}
|
|
24279
|
-
|
|
23926
|
+
mkdirSync14(dirname12(to), { recursive: true });
|
|
24280
23927
|
try {
|
|
24281
23928
|
renameSync7(from, to);
|
|
24282
23929
|
} catch {
|
|
@@ -24284,16 +23931,16 @@ function migrateToLayout4() {
|
|
|
24284
23931
|
copyFileSync2(from, to);
|
|
24285
23932
|
} catch (err) {
|
|
24286
23933
|
try {
|
|
24287
|
-
|
|
23934
|
+
rmSync8(to, { force: true });
|
|
24288
23935
|
} catch {}
|
|
24289
23936
|
throw err;
|
|
24290
23937
|
}
|
|
24291
|
-
|
|
23938
|
+
rmSync8(from, { force: true });
|
|
24292
23939
|
}
|
|
24293
23940
|
migrated.push(`${basename4(from)} → audit/${basename4(to)}`);
|
|
24294
23941
|
}
|
|
24295
23942
|
for (const secret of [auditSessionFile()]) {
|
|
24296
|
-
if (!
|
|
23943
|
+
if (!existsSync23(secret))
|
|
24297
23944
|
continue;
|
|
24298
23945
|
try {
|
|
24299
23946
|
chmodSync4(secret, 384);
|
|
@@ -24319,7 +23966,7 @@ function planMigration(from, registry = MIGRATIONS) {
|
|
|
24319
23966
|
}
|
|
24320
23967
|
function readLedger() {
|
|
24321
23968
|
try {
|
|
24322
|
-
const parsed = JSON.parse(
|
|
23969
|
+
const parsed = JSON.parse(readFileSync19(migrationLedgerFile(), "utf8"));
|
|
24323
23970
|
return Array.isArray(parsed) ? parsed : [];
|
|
24324
23971
|
} catch {
|
|
24325
23972
|
return [];
|
|
@@ -24327,9 +23974,9 @@ function readLedger() {
|
|
|
24327
23974
|
}
|
|
24328
23975
|
function appendLedger(entry) {
|
|
24329
23976
|
try {
|
|
24330
|
-
|
|
23977
|
+
mkdirSync14(migrationsDir(), { recursive: true });
|
|
24331
23978
|
const all = [...readLedger(), entry];
|
|
24332
|
-
|
|
23979
|
+
writeFileSync12(migrationLedgerFile(), `${JSON.stringify(all, null, 2)}
|
|
24333
23980
|
`, "utf8");
|
|
24334
23981
|
} catch {}
|
|
24335
23982
|
}
|
|
@@ -24341,12 +23988,12 @@ function pruneMigratedCredentials(from) {
|
|
|
24341
23988
|
for (let layout = from;layout < LAYOUT_VERSION; layout++) {
|
|
24342
23989
|
for (const { as, landsAt } of PRUNED_AFTER_SUCCESS) {
|
|
24343
23990
|
try {
|
|
24344
|
-
if (!
|
|
23991
|
+
if (!existsSync23(landsAt()))
|
|
24345
23992
|
continue;
|
|
24346
|
-
const copy =
|
|
24347
|
-
if (!
|
|
23993
|
+
const copy = resolve19(migrationBackupDir(layout), as);
|
|
23994
|
+
if (!existsSync23(copy))
|
|
24348
23995
|
continue;
|
|
24349
|
-
|
|
23996
|
+
rmSync8(copy, { force: true });
|
|
24350
23997
|
pruned.push(as);
|
|
24351
23998
|
} catch {}
|
|
24352
23999
|
}
|
|
@@ -24357,7 +24004,7 @@ function filesToBackUp() {
|
|
|
24357
24004
|
const seen = new Map;
|
|
24358
24005
|
for (const f of [...BACKED_UP, ...BACKED_UP_LEGACY]) {
|
|
24359
24006
|
const path = f.at();
|
|
24360
|
-
if (
|
|
24007
|
+
if (existsSync23(path))
|
|
24361
24008
|
seen.set(path, backupNameOf(f));
|
|
24362
24009
|
}
|
|
24363
24010
|
return [...seen].map(([path, as]) => ({ path, as }));
|
|
@@ -24366,14 +24013,14 @@ function backupBeforeMigrating(from) {
|
|
|
24366
24013
|
const dir = migrationBackupDir(from);
|
|
24367
24014
|
const saved = [];
|
|
24368
24015
|
try {
|
|
24369
|
-
|
|
24370
|
-
|
|
24016
|
+
rmSync8(dir, { recursive: true, force: true });
|
|
24017
|
+
mkdirSync14(dir, { recursive: true });
|
|
24371
24018
|
} catch {
|
|
24372
24019
|
return [];
|
|
24373
24020
|
}
|
|
24374
24021
|
for (const { path: source, as } of filesToBackUp()) {
|
|
24375
24022
|
try {
|
|
24376
|
-
copyFileSync2(source,
|
|
24023
|
+
copyFileSync2(source, resolve19(dir, as));
|
|
24377
24024
|
saved.push(as);
|
|
24378
24025
|
} catch {}
|
|
24379
24026
|
}
|
|
@@ -24663,7 +24310,7 @@ var init_fp_reset2 = __esm(() => {
|
|
|
24663
24310
|
// scripts/install-telemetry.mjs
|
|
24664
24311
|
import { createHmac, randomUUID as randomUUID2 } from "node:crypto";
|
|
24665
24312
|
import { execSync as execSync5 } from "node:child_process";
|
|
24666
|
-
import { readFileSync as
|
|
24313
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, mkdirSync as mkdirSync15 } from "node:fs";
|
|
24667
24314
|
import { homedir as homedir22, platform, arch, hostname, cpus } from "node:os";
|
|
24668
24315
|
import { join as join31 } from "node:path";
|
|
24669
24316
|
function hashToId3(raw) {
|
|
@@ -24673,7 +24320,7 @@ function getInstanceId3() {
|
|
|
24673
24320
|
const idDir = join31(homedir22(), ".failproofai");
|
|
24674
24321
|
const idFile = join31(idDir, "instance-id");
|
|
24675
24322
|
try {
|
|
24676
|
-
const existing =
|
|
24323
|
+
const existing = readFileSync20(idFile, "utf-8").trim();
|
|
24677
24324
|
if (existing)
|
|
24678
24325
|
return existing;
|
|
24679
24326
|
} catch {}
|
|
@@ -24682,7 +24329,7 @@ function getInstanceId3() {
|
|
|
24682
24329
|
if (p === "linux") {
|
|
24683
24330
|
for (const machineIdPath of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
24684
24331
|
try {
|
|
24685
|
-
const id =
|
|
24332
|
+
const id = readFileSync20(machineIdPath, "utf-8").trim();
|
|
24686
24333
|
if (id)
|
|
24687
24334
|
return hashToId3(id);
|
|
24688
24335
|
} catch {}
|
|
@@ -24714,8 +24361,8 @@ function getInstanceId3() {
|
|
|
24714
24361
|
} catch {}
|
|
24715
24362
|
const id = randomUUID2();
|
|
24716
24363
|
try {
|
|
24717
|
-
|
|
24718
|
-
|
|
24364
|
+
mkdirSync15(idDir, { recursive: true });
|
|
24365
|
+
writeFileSync13(idFile, id, "utf-8");
|
|
24719
24366
|
} catch {}
|
|
24720
24367
|
return id;
|
|
24721
24368
|
}
|
|
@@ -24747,8 +24394,8 @@ var NAMESPACE3 = "failproofai-telemetry-v1", API_KEY3 = "phc_Ac1Ww1GqKc0z1SyrRWb
|
|
|
24747
24394
|
var init_install_telemetry = () => {};
|
|
24748
24395
|
|
|
24749
24396
|
// lib/install-check.ts
|
|
24750
|
-
import { existsSync as
|
|
24751
|
-
import { dirname as
|
|
24397
|
+
import { existsSync as existsSync24, readFileSync as readFileSync21, writeFileSync as writeFileSync14, mkdirSync as mkdirSync16 } from "node:fs";
|
|
24398
|
+
import { dirname as dirname13, resolve as resolve20 } from "node:path";
|
|
24752
24399
|
import { platform as platform2, arch as arch2, release, homedir as homedir23, hostname as hostname2 } from "node:os";
|
|
24753
24400
|
import { createHmac as createHmac2 } from "node:crypto";
|
|
24754
24401
|
function hashToId4(raw) {
|
|
@@ -24803,12 +24450,12 @@ function compareSemver(a, b) {
|
|
|
24803
24450
|
}
|
|
24804
24451
|
function checkHooks() {
|
|
24805
24452
|
const hooksConfigPath = globalPolicyConfigFile();
|
|
24806
|
-
if (!
|
|
24453
|
+
if (!existsSync24(hooksConfigPath)) {
|
|
24807
24454
|
return { configured: false, registered: false, policyCount: 0 };
|
|
24808
24455
|
}
|
|
24809
24456
|
let config;
|
|
24810
24457
|
try {
|
|
24811
|
-
config = JSON.parse(
|
|
24458
|
+
config = JSON.parse(readFileSync21(hooksConfigPath, "utf8"));
|
|
24812
24459
|
} catch {
|
|
24813
24460
|
return { configured: false, registered: false, policyCount: 0 };
|
|
24814
24461
|
}
|
|
@@ -24816,12 +24463,12 @@ function checkHooks() {
|
|
|
24816
24463
|
return { configured: false, registered: false, policyCount: 0 };
|
|
24817
24464
|
}
|
|
24818
24465
|
const policyCount = config.enabledPolicies.length;
|
|
24819
|
-
const settingsPath =
|
|
24820
|
-
if (!
|
|
24466
|
+
const settingsPath = resolve20(homedir23(), ".claude", "settings.json");
|
|
24467
|
+
if (!existsSync24(settingsPath))
|
|
24821
24468
|
return { configured: true, registered: false, policyCount };
|
|
24822
24469
|
let settings;
|
|
24823
24470
|
try {
|
|
24824
|
-
settings = JSON.parse(
|
|
24471
|
+
settings = JSON.parse(readFileSync21(settingsPath, "utf8"));
|
|
24825
24472
|
} catch {
|
|
24826
24473
|
return { configured: true, registered: false, policyCount };
|
|
24827
24474
|
}
|
|
@@ -24845,8 +24492,8 @@ async function maybeReportInstall(version) {
|
|
|
24845
24492
|
const versionFile = lastVersionPath();
|
|
24846
24493
|
let previousVersion = null;
|
|
24847
24494
|
try {
|
|
24848
|
-
if (
|
|
24849
|
-
previousVersion =
|
|
24495
|
+
if (existsSync24(versionFile)) {
|
|
24496
|
+
previousVersion = readFileSync21(versionFile, "utf8").trim() || null;
|
|
24850
24497
|
}
|
|
24851
24498
|
} catch {}
|
|
24852
24499
|
if (previousVersion === version)
|
|
@@ -24882,8 +24529,8 @@ async function maybeReportInstall(version) {
|
|
|
24882
24529
|
enabled_policy_count: hooks.policyCount
|
|
24883
24530
|
}, { version, timeoutMs: REPORT_TIMEOUT_MS, enabled: telemetryEnabled }));
|
|
24884
24531
|
try {
|
|
24885
|
-
|
|
24886
|
-
|
|
24532
|
+
mkdirSync16(dirname13(versionFile), { recursive: true });
|
|
24533
|
+
writeFileSync14(versionFile, version, "utf8");
|
|
24887
24534
|
} catch {}
|
|
24888
24535
|
await Promise.all(events.map((p) => p.catch(() => {})));
|
|
24889
24536
|
} catch {}
|
|
@@ -24933,8 +24580,8 @@ var init_cli_error = __esm(() => {
|
|
|
24933
24580
|
|
|
24934
24581
|
// src/hooks/manager.ts
|
|
24935
24582
|
import { execSync as execSync6 } from "node:child_process";
|
|
24936
|
-
import { existsSync as
|
|
24937
|
-
import { resolve as
|
|
24583
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
24584
|
+
import { resolve as resolve21, basename as basename5 } from "node:path";
|
|
24938
24585
|
import { platform as platform3, arch as arch3, release as release2, hostname as hostname3 } from "node:os";
|
|
24939
24586
|
function getSettingsPath(scope, cwd) {
|
|
24940
24587
|
return claudeCode.getSettingsPath(scope, cwd);
|
|
@@ -25153,9 +24800,9 @@ async function installHooksImpl(policyNames, scope = "user", cwd, includeBeta =
|
|
|
25153
24800
|
delete configToWrite.customPoliciesPath;
|
|
25154
24801
|
delete configToWrite.customPoliciesPaths;
|
|
25155
24802
|
} else if (customPoliciesPath && (typeof customPoliciesPath === "string" || customPoliciesPath.length > 0)) {
|
|
25156
|
-
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path) =>
|
|
25157
|
-
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path) =>
|
|
25158
|
-
if (
|
|
24803
|
+
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path) => resolve21(path));
|
|
24804
|
+
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path) => resolve21(path)).filter((path) => {
|
|
24805
|
+
if (existsSync25(path))
|
|
25159
24806
|
return true;
|
|
25160
24807
|
console.log(`Dropping custom policies path (file no longer exists): ${path}`);
|
|
25161
24808
|
return false;
|
|
@@ -25378,7 +25025,7 @@ async function removeHooks(policyNames, scope = "user", cwd, opts) {
|
|
|
25378
25025
|
const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
|
|
25379
25026
|
for (const s of scopesToRemove) {
|
|
25380
25027
|
const settingsPaths = settingsPathsFor(integration, s, cwd);
|
|
25381
|
-
const existing = settingsPaths.filter((p) =>
|
|
25028
|
+
const existing = settingsPaths.filter((p) => existsSync25(p));
|
|
25382
25029
|
if (existing.length === 0) {
|
|
25383
25030
|
if (scope !== "all" && selectedClis.length === 1) {
|
|
25384
25031
|
console.log("No settings file found. Nothing to remove.");
|
|
@@ -25465,16 +25112,92 @@ var init_manager = __esm(() => {
|
|
|
25465
25112
|
VALID_POLICY_NAMES = new Set(BUILTIN_POLICIES.map((p) => p.name));
|
|
25466
25113
|
});
|
|
25467
25114
|
|
|
25115
|
+
// src/audit/leak-fingerprint.ts
|
|
25116
|
+
function matchPublicPrefix(value) {
|
|
25117
|
+
for (const entry of PUBLIC_PREFIXES) {
|
|
25118
|
+
if (value.startsWith(entry[0]))
|
|
25119
|
+
return entry;
|
|
25120
|
+
}
|
|
25121
|
+
return null;
|
|
25122
|
+
}
|
|
25123
|
+
function fingerprintSecret(value, fallbackLabel = "secret") {
|
|
25124
|
+
const length = value.length;
|
|
25125
|
+
const matched = matchPublicPrefix(value);
|
|
25126
|
+
if (!matched) {
|
|
25127
|
+
return {
|
|
25128
|
+
display: `[${length}-char ${fallbackLabel}]`,
|
|
25129
|
+
label: fallbackLabel,
|
|
25130
|
+
length,
|
|
25131
|
+
attributed: false
|
|
25132
|
+
};
|
|
25133
|
+
}
|
|
25134
|
+
const [prefix, label] = matched;
|
|
25135
|
+
const bodyLength = length - prefix.length;
|
|
25136
|
+
const run = MASK_CHAR.repeat(Math.max(1, Math.min(MAX_MASK_RUN, bodyLength)));
|
|
25137
|
+
if (length >= MIN_LEN_FOR_TAIL && bodyLength > TAIL_CHARS * 2) {
|
|
25138
|
+
return {
|
|
25139
|
+
display: `${prefix}${run}${value.slice(-TAIL_CHARS)}`,
|
|
25140
|
+
label,
|
|
25141
|
+
length,
|
|
25142
|
+
attributed: true
|
|
25143
|
+
};
|
|
25144
|
+
}
|
|
25145
|
+
return { display: `${prefix}${run}`, label, length, attributed: true };
|
|
25146
|
+
}
|
|
25147
|
+
function isFindingId(id) {
|
|
25148
|
+
return /^[0-9a-f]{16}$/.test(id);
|
|
25149
|
+
}
|
|
25150
|
+
function fingerprintId(value, machineSalt) {
|
|
25151
|
+
const { createHmac } = __require("node:crypto");
|
|
25152
|
+
return createHmac("sha256", machineSalt).update(value).digest("hex").slice(0, 16);
|
|
25153
|
+
}
|
|
25154
|
+
var MASK_CHAR = "•", MAX_MASK_RUN = 8, MIN_LEN_FOR_TAIL = 24, TAIL_CHARS = 4, PUBLIC_PREFIXES;
|
|
25155
|
+
var init_leak_fingerprint = __esm(() => {
|
|
25156
|
+
PUBLIC_PREFIXES = [
|
|
25157
|
+
["sk-ant-api03-", "Anthropic API key"],
|
|
25158
|
+
["sk-ant-oat01-", "Anthropic OAuth token"],
|
|
25159
|
+
["sk-ant-", "Anthropic key"],
|
|
25160
|
+
["sk-proj-", "OpenAI project key"],
|
|
25161
|
+
["sk-svcacct-", "OpenAI service-account key"],
|
|
25162
|
+
["sk-admin-", "OpenAI admin key"],
|
|
25163
|
+
["sk-or-v1-", "OpenRouter key"],
|
|
25164
|
+
["github_pat_", "GitHub fine-grained token"],
|
|
25165
|
+
["ghp_", "GitHub personal access token"],
|
|
25166
|
+
["gho_", "GitHub OAuth token"],
|
|
25167
|
+
["ghu_", "GitHub user-to-server token"],
|
|
25168
|
+
["ghs_", "GitHub server-to-server token"],
|
|
25169
|
+
["ghr_", "GitHub refresh token"],
|
|
25170
|
+
["glpat-", "GitLab personal access token"],
|
|
25171
|
+
["xoxb-", "Slack bot token"],
|
|
25172
|
+
["xoxp-", "Slack user token"],
|
|
25173
|
+
["xapp-", "Slack app-level token"],
|
|
25174
|
+
["sk_live_", "Stripe live secret key"],
|
|
25175
|
+
["sk_test_", "Stripe test secret key"],
|
|
25176
|
+
["rk_live_", "Stripe restricted key"],
|
|
25177
|
+
["AKIA", "AWS access key ID"],
|
|
25178
|
+
["ASIA", "AWS temporary access key ID"],
|
|
25179
|
+
["AIza", "Google API key"],
|
|
25180
|
+
["hf_", "Hugging Face token"],
|
|
25181
|
+
["gsk_", "Groq API key"],
|
|
25182
|
+
["r8_", "Replicate token"],
|
|
25183
|
+
["xai-", "xAI key"],
|
|
25184
|
+
["npm_", "npm access token"],
|
|
25185
|
+
["dop_v1_", "DigitalOcean token"],
|
|
25186
|
+
["shpat_", "Shopify access token"],
|
|
25187
|
+
["sbp_", "Supabase token"]
|
|
25188
|
+
];
|
|
25189
|
+
});
|
|
25190
|
+
|
|
25468
25191
|
// src/audit/macos-notifier.ts
|
|
25469
25192
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
25470
|
-
import { existsSync as
|
|
25193
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync17, readdirSync as readdirSync16, renameSync as renameSync8, rmSync as rmSync9, writeFileSync as writeFileSync15 } from "node:fs";
|
|
25471
25194
|
import { homedir as homedir24 } from "node:os";
|
|
25472
|
-
import { resolve as
|
|
25195
|
+
import { resolve as resolve22 } from "node:path";
|
|
25473
25196
|
function macNotifierAppPath(home) {
|
|
25474
|
-
return
|
|
25197
|
+
return resolve22(runDir(home), "..", "bin", "FailproofAI Notifier.app");
|
|
25475
25198
|
}
|
|
25476
25199
|
function macNotifierPlistPath() {
|
|
25477
|
-
return
|
|
25200
|
+
return resolve22(homedir24(), "Library", "LaunchAgents", `${MAC_NOTIFIER_LABEL}.plist`);
|
|
25478
25201
|
}
|
|
25479
25202
|
function escapeXml2(s) {
|
|
25480
25203
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -25518,7 +25241,7 @@ function notifierPlistContents(appPath, watchDir) {
|
|
|
25518
25241
|
<string>${escapeXml2(MAC_NOTIFIER_LABEL)}</string>
|
|
25519
25242
|
<key>ProgramArguments</key>
|
|
25520
25243
|
<array>
|
|
25521
|
-
<string>${escapeXml2(
|
|
25244
|
+
<string>${escapeXml2(resolve22(appPath, "Contents", "MacOS", "applet"))}</string>
|
|
25522
25245
|
</array>
|
|
25523
25246
|
<!-- Started only when something is queued, and it exits when the queue is
|
|
25524
25247
|
empty. RunAtLoad would fire it once at login with nothing to say. -->
|
|
@@ -25547,18 +25270,18 @@ function installMacNotifier(home) {
|
|
|
25547
25270
|
try {
|
|
25548
25271
|
const app = macNotifierAppPath(home);
|
|
25549
25272
|
const watch = macNotifyDir(home);
|
|
25550
|
-
|
|
25551
|
-
|
|
25552
|
-
const scriptPath =
|
|
25553
|
-
|
|
25554
|
-
|
|
25273
|
+
mkdirSync17(watch, { recursive: true, mode: 448 });
|
|
25274
|
+
mkdirSync17(resolve22(app, ".."), { recursive: true });
|
|
25275
|
+
const scriptPath = resolve22(watch, "..", "notifier.applescript");
|
|
25276
|
+
writeFileSync15(scriptPath, notifierScript(home), { mode: 384 });
|
|
25277
|
+
rmSync9(app, { recursive: true, force: true });
|
|
25555
25278
|
run("osacompile", ["-o", app, scriptPath]);
|
|
25556
|
-
|
|
25557
|
-
const plist =
|
|
25279
|
+
rmSync9(scriptPath, { force: true });
|
|
25280
|
+
const plist = resolve22(app, "Contents", "Info.plist");
|
|
25558
25281
|
run("defaults", ["write", plist, "CFBundleIdentifier", MAC_NOTIFIER_LABEL]);
|
|
25559
25282
|
run("defaults", ["write", plist, "CFBundleName", "failproofai"]);
|
|
25560
|
-
|
|
25561
|
-
|
|
25283
|
+
mkdirSync17(resolve22(macNotifierPlistPath(), ".."), { recursive: true });
|
|
25284
|
+
writeFileSync15(macNotifierPlistPath(), notifierPlistContents(app, watch), { mode: 420 });
|
|
25562
25285
|
const target = `gui/${process.getuid?.() ?? 0}`;
|
|
25563
25286
|
try {
|
|
25564
25287
|
run("launchctl", ["bootout", `${target}/${MAC_NOTIFIER_LABEL}`]);
|
|
@@ -25575,49 +25298,49 @@ function uninstallMacNotifier(home) {
|
|
|
25575
25298
|
try {
|
|
25576
25299
|
run("launchctl", ["bootout", `gui/${process.getuid?.() ?? 0}/${MAC_NOTIFIER_LABEL}`]);
|
|
25577
25300
|
} catch {}
|
|
25578
|
-
|
|
25579
|
-
|
|
25580
|
-
|
|
25301
|
+
rmSync9(macNotifierPlistPath(), { force: true });
|
|
25302
|
+
rmSync9(macNotifierAppPath(home), { recursive: true, force: true });
|
|
25303
|
+
rmSync9(macNotifyDir(home), { recursive: true, force: true });
|
|
25581
25304
|
}
|
|
25582
25305
|
function queueMacNotification(id, title, body, home) {
|
|
25583
25306
|
if (!isFindingId(id))
|
|
25584
25307
|
return false;
|
|
25585
25308
|
const dir = macNotifyDir(home);
|
|
25586
|
-
const tmp =
|
|
25309
|
+
const tmp = resolve22(dir, "..", `notify-${id}.tmp`);
|
|
25587
25310
|
try {
|
|
25588
|
-
|
|
25311
|
+
mkdirSync17(dir, { recursive: true, mode: 448 });
|
|
25589
25312
|
const payload = `${title.replace(/\s+/g, " ")}
|
|
25590
25313
|
${body.replace(/\s+/g, " ")}
|
|
25591
25314
|
`;
|
|
25592
|
-
|
|
25593
|
-
renameSync8(tmp,
|
|
25315
|
+
writeFileSync15(tmp, payload, { mode: 384 });
|
|
25316
|
+
renameSync8(tmp, resolve22(dir, id));
|
|
25594
25317
|
return true;
|
|
25595
25318
|
} catch {
|
|
25596
25319
|
try {
|
|
25597
|
-
|
|
25320
|
+
rmSync9(tmp, { force: true });
|
|
25598
25321
|
} catch {}
|
|
25599
25322
|
return false;
|
|
25600
25323
|
}
|
|
25601
25324
|
}
|
|
25602
25325
|
function macNotifierInstalled(home) {
|
|
25603
|
-
return
|
|
25326
|
+
return existsSync26(macNotifierPlistPath()) && existsSync26(macNotifierAppPath(home));
|
|
25604
25327
|
}
|
|
25605
25328
|
function pruneMacNotifyQueue(home, maxAgeMs = 7 * 86400000) {
|
|
25606
25329
|
try {
|
|
25607
25330
|
const dir = macNotifyDir(home);
|
|
25608
|
-
if (!
|
|
25331
|
+
if (!existsSync26(dir))
|
|
25609
25332
|
return;
|
|
25610
25333
|
const { statSync } = __require("node:fs");
|
|
25611
|
-
for (const name of
|
|
25612
|
-
const path =
|
|
25334
|
+
for (const name of readdirSync16(dir)) {
|
|
25335
|
+
const path = resolve22(dir, name);
|
|
25613
25336
|
try {
|
|
25614
25337
|
if (Date.now() - statSync(path).mtimeMs > maxAgeMs)
|
|
25615
|
-
|
|
25338
|
+
rmSync9(path, { force: true });
|
|
25616
25339
|
} catch {}
|
|
25617
25340
|
}
|
|
25618
25341
|
} catch {}
|
|
25619
25342
|
}
|
|
25620
|
-
var MAC_NOTIFIER_LABEL = "ai.failproof.notifier", macNotifyDir = (home) =>
|
|
25343
|
+
var MAC_NOTIFIER_LABEL = "ai.failproof.notifier", macNotifyDir = (home) => resolve22(runDir(home), "notify");
|
|
25621
25344
|
var init_macos_notifier = __esm(() => {
|
|
25622
25345
|
init_fp_home();
|
|
25623
25346
|
init_leak_fingerprint();
|
|
@@ -25639,7 +25362,7 @@ var DEFAULT_FETCH_TIMEOUT_MS = 15000;
|
|
|
25639
25362
|
|
|
25640
25363
|
// src/hooks/cloud-enrollment.ts
|
|
25641
25364
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
25642
|
-
import { existsSync as
|
|
25365
|
+
import { existsSync as existsSync27, readFileSync as readFileSync22, rmSync as rmSync10 } from "node:fs";
|
|
25643
25366
|
import { hostname as hostname4 } from "node:os";
|
|
25644
25367
|
function cloudCredentialPath() {
|
|
25645
25368
|
return process.env.FAILPROOFAI_CLOUD_CREDENTIALS ?? credentialsFile();
|
|
@@ -25678,10 +25401,10 @@ function readCloudCredentials() {
|
|
|
25678
25401
|
if (!usingJsonOverride())
|
|
25679
25402
|
return readCredentials().cloud ?? null;
|
|
25680
25403
|
const path = cloudCredentialPath();
|
|
25681
|
-
if (!
|
|
25404
|
+
if (!existsSync27(path))
|
|
25682
25405
|
return null;
|
|
25683
25406
|
try {
|
|
25684
|
-
const raw = JSON.parse(
|
|
25407
|
+
const raw = JSON.parse(readFileSync22(path, "utf8"));
|
|
25685
25408
|
if (raw.schemaVersion !== SCHEMA_VERSION2)
|
|
25686
25409
|
return null;
|
|
25687
25410
|
if (typeof raw.url !== "string" || typeof raw.machineId !== "string" || typeof raw.token !== "string") {
|
|
@@ -25720,10 +25443,10 @@ function resolveMachineLabel(explicit) {
|
|
|
25720
25443
|
function clearCloudCredentials() {
|
|
25721
25444
|
if (usingJsonOverride()) {
|
|
25722
25445
|
const path = cloudCredentialPath();
|
|
25723
|
-
if (!
|
|
25446
|
+
if (!existsSync27(path))
|
|
25724
25447
|
return false;
|
|
25725
25448
|
try {
|
|
25726
|
-
|
|
25449
|
+
rmSync10(path);
|
|
25727
25450
|
return true;
|
|
25728
25451
|
} catch {
|
|
25729
25452
|
return false;
|
|
@@ -25971,21 +25694,21 @@ var init_cloud_connection = __esm(() => {
|
|
|
25971
25694
|
});
|
|
25972
25695
|
|
|
25973
25696
|
// src/hooks/setup-state.ts
|
|
25974
|
-
import { existsSync as
|
|
25975
|
-
import { dirname as
|
|
25697
|
+
import { existsSync as existsSync28, realpathSync as realpathSync2, statSync as statSync17 } from "node:fs";
|
|
25698
|
+
import { dirname as dirname14, resolve as resolve23 } from "node:path";
|
|
25976
25699
|
import { homedir as homedir25 } from "node:os";
|
|
25977
25700
|
function globalConfigPath(home = homedir25()) {
|
|
25978
25701
|
return globalPolicyConfigFile(home);
|
|
25979
25702
|
}
|
|
25980
25703
|
function projectConfigPath(projectRoot) {
|
|
25981
|
-
return
|
|
25704
|
+
return resolve23(projectRoot, ".failproofai", "policies-config.json");
|
|
25982
25705
|
}
|
|
25983
25706
|
function legacyMarkerPath(home) {
|
|
25984
25707
|
return launcherMarker(home);
|
|
25985
25708
|
}
|
|
25986
25709
|
function isDir(path) {
|
|
25987
25710
|
try {
|
|
25988
|
-
return
|
|
25711
|
+
return statSync17(path).isDirectory();
|
|
25989
25712
|
} catch {
|
|
25990
25713
|
return false;
|
|
25991
25714
|
}
|
|
@@ -25994,14 +25717,14 @@ function findProjectRoot(start, home = homedir25()) {
|
|
|
25994
25717
|
const resolvedHome = realResolve(home);
|
|
25995
25718
|
let dir = realResolve(start);
|
|
25996
25719
|
while (dir !== resolvedHome) {
|
|
25997
|
-
if (isDir(
|
|
25720
|
+
if (isDir(resolve23(dir, ".failproofai")))
|
|
25998
25721
|
return dir;
|
|
25999
|
-
const parent =
|
|
25722
|
+
const parent = dirname14(dir);
|
|
26000
25723
|
if (parent === dir)
|
|
26001
25724
|
break;
|
|
26002
25725
|
dir = parent;
|
|
26003
25726
|
}
|
|
26004
|
-
return
|
|
25727
|
+
return resolve23(start);
|
|
26005
25728
|
}
|
|
26006
25729
|
function hasGlobalHooksInstalled() {
|
|
26007
25730
|
for (const id of INTEGRATION_TYPES) {
|
|
@@ -26013,7 +25736,7 @@ function hasGlobalHooksInstalled() {
|
|
|
26013
25736
|
return false;
|
|
26014
25737
|
}
|
|
26015
25738
|
function realResolve(path) {
|
|
26016
|
-
const lexical =
|
|
25739
|
+
const lexical = resolve23(path);
|
|
26017
25740
|
try {
|
|
26018
25741
|
return realpathSync2(lexical);
|
|
26019
25742
|
} catch {
|
|
@@ -26028,10 +25751,10 @@ function detectSetupState(cwd = process.cwd(), home = homedir25()) {
|
|
|
26028
25751
|
cwd: resolvedCwd,
|
|
26029
25752
|
home: resolvedHome,
|
|
26030
25753
|
projectRoot,
|
|
26031
|
-
hasGlobalConfig:
|
|
26032
|
-
hasProjectConfig: projectRoot !== resolvedHome &&
|
|
25754
|
+
hasGlobalConfig: existsSync28(globalConfigPath(resolvedHome)),
|
|
25755
|
+
hasProjectConfig: projectRoot !== resolvedHome && existsSync28(projectConfigPath(projectRoot)),
|
|
26033
25756
|
hasGlobalHooks: hasGlobalHooksInstalled(),
|
|
26034
|
-
hasLegacyMarker:
|
|
25757
|
+
hasLegacyMarker: existsSync28(legacyMarkerPath(resolvedHome)),
|
|
26035
25758
|
inHomeDir: resolvedCwd === resolvedHome
|
|
26036
25759
|
};
|
|
26037
25760
|
}
|
|
@@ -26048,14 +25771,14 @@ var init_setup_state = __esm(() => {
|
|
|
26048
25771
|
});
|
|
26049
25772
|
|
|
26050
25773
|
// src/hooks/onboarding-attempt.ts
|
|
26051
|
-
import { existsSync as
|
|
26052
|
-
import { dirname as
|
|
25774
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync18, readFileSync as readFileSync23, rmSync as rmSync11, writeFileSync as writeFileSync16 } from "node:fs";
|
|
25775
|
+
import { dirname as dirname15 } from "node:path";
|
|
26053
25776
|
function readOnboardingAttempt() {
|
|
26054
25777
|
const path = onboardingAttemptFile();
|
|
26055
|
-
if (!
|
|
25778
|
+
if (!existsSync29(path))
|
|
26056
25779
|
return null;
|
|
26057
25780
|
try {
|
|
26058
|
-
const raw = JSON.parse(
|
|
25781
|
+
const raw = JSON.parse(readFileSync23(path, "utf8"));
|
|
26059
25782
|
if (raw.schemaVersion !== SCHEMA_VERSION3)
|
|
26060
25783
|
return null;
|
|
26061
25784
|
if (typeof raw.reason !== "string" || typeof raw.cliVersion !== "string")
|
|
@@ -26074,7 +25797,7 @@ function readOnboardingAttempt() {
|
|
|
26074
25797
|
function recordOnboardingAttempt(reason, cliVersion, daemonStatus, now = Date.now()) {
|
|
26075
25798
|
try {
|
|
26076
25799
|
const path = onboardingAttemptFile();
|
|
26077
|
-
|
|
25800
|
+
mkdirSync18(dirname15(path), { recursive: true });
|
|
26078
25801
|
const record = {
|
|
26079
25802
|
schemaVersion: SCHEMA_VERSION3,
|
|
26080
25803
|
reason,
|
|
@@ -26082,12 +25805,12 @@ function recordOnboardingAttempt(reason, cliVersion, daemonStatus, now = Date.no
|
|
|
26082
25805
|
daemonStatus,
|
|
26083
25806
|
at: now
|
|
26084
25807
|
};
|
|
26085
|
-
|
|
25808
|
+
writeFileSync16(path, JSON.stringify(record, null, 2), "utf8");
|
|
26086
25809
|
} catch {}
|
|
26087
25810
|
}
|
|
26088
25811
|
function clearOnboardingAttempt() {
|
|
26089
25812
|
try {
|
|
26090
|
-
|
|
25813
|
+
rmSync11(onboardingAttemptFile(), { force: true });
|
|
26091
25814
|
} catch {}
|
|
26092
25815
|
}
|
|
26093
25816
|
function blockerCleared(attempt, probe) {
|
|
@@ -26129,7 +25852,7 @@ var init_onboarding_attempt = __esm(() => {
|
|
|
26129
25852
|
});
|
|
26130
25853
|
|
|
26131
25854
|
// src/hooks/onboarding-lock.ts
|
|
26132
|
-
import { mkdirSync as
|
|
25855
|
+
import { mkdirSync as mkdirSync19, readFileSync as readFileSync24, rmSync as rmSync12, writeFileSync as writeFileSync17 } from "node:fs";
|
|
26133
25856
|
import { homedir as homedir26 } from "node:os";
|
|
26134
25857
|
function onboardingLockPath(home = homedir26()) {
|
|
26135
25858
|
return onboardingLockFile(home);
|
|
@@ -26146,7 +25869,7 @@ function processAlive(pid) {
|
|
|
26146
25869
|
}
|
|
26147
25870
|
function readLock(path) {
|
|
26148
25871
|
try {
|
|
26149
|
-
const parsed = JSON.parse(
|
|
25872
|
+
const parsed = JSON.parse(readFileSync24(path, "utf8"));
|
|
26150
25873
|
if (typeof parsed.pid !== "number")
|
|
26151
25874
|
return null;
|
|
26152
25875
|
return { pid: parsed.pid, startedAt: Number(parsed.startedAt) || 0 };
|
|
@@ -26160,9 +25883,9 @@ function acquireOnboardingLock(home = homedir26()) {
|
|
|
26160
25883
|
const held = readLock(path);
|
|
26161
25884
|
if (held && held.pid !== process.pid && processAlive(held.pid))
|
|
26162
25885
|
return null;
|
|
26163
|
-
|
|
25886
|
+
mkdirSync19(stateDir(home), { recursive: true });
|
|
26164
25887
|
const body = { pid: process.pid, startedAt: Date.now() };
|
|
26165
|
-
|
|
25888
|
+
writeFileSync17(path, JSON.stringify(body), "utf8");
|
|
26166
25889
|
let released = false;
|
|
26167
25890
|
return {
|
|
26168
25891
|
release() {
|
|
@@ -26172,7 +25895,7 @@ function acquireOnboardingLock(home = homedir26()) {
|
|
|
26172
25895
|
try {
|
|
26173
25896
|
const current = readLock(path);
|
|
26174
25897
|
if (!current || current.pid === process.pid)
|
|
26175
|
-
|
|
25898
|
+
rmSync12(path, { force: true });
|
|
26176
25899
|
} catch {}
|
|
26177
25900
|
}
|
|
26178
25901
|
};
|
|
@@ -26185,7 +25908,7 @@ var init_onboarding_lock = __esm(() => {
|
|
|
26185
25908
|
});
|
|
26186
25909
|
|
|
26187
25910
|
// lib/claude-sessions.ts
|
|
26188
|
-
import { readdirSync as
|
|
25911
|
+
import { readdirSync as readdirSync17, statSync as statSync18, existsSync as existsSync30 } from "node:fs";
|
|
26189
25912
|
import { join as join32, basename as basename6 } from "node:path";
|
|
26190
25913
|
function getClaudeProjectsRoot() {
|
|
26191
25914
|
return getClaudeProjectsPath();
|
|
@@ -26194,7 +25917,7 @@ function listClaudeProjects() {
|
|
|
26194
25917
|
const root = getClaudeProjectsRoot();
|
|
26195
25918
|
let entries;
|
|
26196
25919
|
try {
|
|
26197
|
-
entries =
|
|
25920
|
+
entries = readdirSync17(root, { withFileTypes: true });
|
|
26198
25921
|
} catch {
|
|
26199
25922
|
return [];
|
|
26200
25923
|
}
|
|
@@ -26209,7 +25932,7 @@ function collectSubagentTranscripts(dir, relPrefix, project, out, depth) {
|
|
|
26209
25932
|
return;
|
|
26210
25933
|
let entries;
|
|
26211
25934
|
try {
|
|
26212
|
-
entries =
|
|
25935
|
+
entries = readdirSync17(dir, { withFileTypes: true });
|
|
26213
25936
|
} catch {
|
|
26214
25937
|
return;
|
|
26215
25938
|
}
|
|
@@ -26225,7 +25948,7 @@ function collectSubagentTranscripts(dir, relPrefix, project, out, depth) {
|
|
|
26225
25948
|
const stem = entry.name.slice(0, -".jsonl".length);
|
|
26226
25949
|
const transcriptPath = join32(dir, entry.name);
|
|
26227
25950
|
try {
|
|
26228
|
-
const s =
|
|
25951
|
+
const s = statSync18(transcriptPath);
|
|
26229
25952
|
out.push({
|
|
26230
25953
|
projectName: project.name,
|
|
26231
25954
|
cwd: project.cwd,
|
|
@@ -26242,7 +25965,7 @@ function listClaudeTranscripts(project) {
|
|
|
26242
25965
|
const out = [];
|
|
26243
25966
|
let entries;
|
|
26244
25967
|
try {
|
|
26245
|
-
entries =
|
|
25968
|
+
entries = readdirSync17(project.path, { withFileTypes: true });
|
|
26246
25969
|
} catch {
|
|
26247
25970
|
return out;
|
|
26248
25971
|
}
|
|
@@ -26253,7 +25976,7 @@ function listClaudeTranscripts(project) {
|
|
|
26253
25976
|
continue;
|
|
26254
25977
|
const transcriptPath = join32(project.path, entry.name);
|
|
26255
25978
|
try {
|
|
26256
|
-
const s =
|
|
25979
|
+
const s = statSync18(transcriptPath);
|
|
26257
25980
|
out.push({
|
|
26258
25981
|
projectName: project.name,
|
|
26259
25982
|
cwd: project.cwd,
|
|
@@ -26266,7 +25989,7 @@ function listClaudeTranscripts(project) {
|
|
|
26266
25989
|
} catch {}
|
|
26267
25990
|
} else if (entry.isDirectory() && UUID_RE2.test(entry.name)) {
|
|
26268
25991
|
const subDir = join32(project.path, entry.name, "subagents");
|
|
26269
|
-
if (!
|
|
25992
|
+
if (!existsSync30(subDir))
|
|
26270
25993
|
continue;
|
|
26271
25994
|
collectSubagentTranscripts(subDir, entry.name, project, out, 0);
|
|
26272
25995
|
}
|
|
@@ -26332,7 +26055,7 @@ var init_shared = __esm(() => {
|
|
|
26332
26055
|
|
|
26333
26056
|
// src/audit/cli-adapters/claude.ts
|
|
26334
26057
|
import { readFile as readFile15, open as open2 } from "node:fs/promises";
|
|
26335
|
-
import { readFileSync as
|
|
26058
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
26336
26059
|
async function listClaudeTranscriptMetadata(opts = {}) {
|
|
26337
26060
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26338
26061
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26352,7 +26075,7 @@ async function listClaudeTranscriptMetadata(opts = {}) {
|
|
|
26352
26075
|
let sessionDescription;
|
|
26353
26076
|
if (t.isSubagent) {
|
|
26354
26077
|
try {
|
|
26355
|
-
const meta = JSON.parse(
|
|
26078
|
+
const meta = JSON.parse(readFileSync25(t.transcriptPath.replace(/\.jsonl$/, ".meta.json"), "utf8"));
|
|
26356
26079
|
if (typeof meta.description === "string")
|
|
26357
26080
|
sessionDescription = meta.description;
|
|
26358
26081
|
} catch {}
|
|
@@ -26483,7 +26206,7 @@ var init_claude = __esm(() => {
|
|
|
26483
26206
|
});
|
|
26484
26207
|
|
|
26485
26208
|
// src/audit/cli-adapters/codex.ts
|
|
26486
|
-
import { statSync as
|
|
26209
|
+
import { statSync as statSync19 } from "node:fs";
|
|
26487
26210
|
async function listCodexTranscriptMetadata(opts = {}) {
|
|
26488
26211
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26489
26212
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26500,7 +26223,7 @@ async function listCodexTranscriptMetadata(opts = {}) {
|
|
|
26500
26223
|
continue;
|
|
26501
26224
|
let sizeBytes = 0;
|
|
26502
26225
|
try {
|
|
26503
|
-
sizeBytes =
|
|
26226
|
+
sizeBytes = statSync19(s.path).size;
|
|
26504
26227
|
} catch {}
|
|
26505
26228
|
if (!s.sessionId)
|
|
26506
26229
|
continue;
|
|
@@ -26534,7 +26257,7 @@ var init_codex = __esm(() => {
|
|
|
26534
26257
|
});
|
|
26535
26258
|
|
|
26536
26259
|
// src/audit/cli-adapters/copilot.ts
|
|
26537
|
-
import { statSync as
|
|
26260
|
+
import { statSync as statSync20 } from "node:fs";
|
|
26538
26261
|
async function listCopilotTranscriptMetadata(opts = {}) {
|
|
26539
26262
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26540
26263
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26551,7 +26274,7 @@ async function listCopilotTranscriptMetadata(opts = {}) {
|
|
|
26551
26274
|
continue;
|
|
26552
26275
|
let sizeBytes = 0;
|
|
26553
26276
|
try {
|
|
26554
|
-
sizeBytes =
|
|
26277
|
+
sizeBytes = statSync20(s.path).size;
|
|
26555
26278
|
} catch {}
|
|
26556
26279
|
if (!s.sessionId)
|
|
26557
26280
|
continue;
|
|
@@ -26585,7 +26308,7 @@ var init_copilot = __esm(() => {
|
|
|
26585
26308
|
});
|
|
26586
26309
|
|
|
26587
26310
|
// src/audit/cli-adapters/cursor.ts
|
|
26588
|
-
import { statSync as
|
|
26311
|
+
import { statSync as statSync21 } from "node:fs";
|
|
26589
26312
|
async function listCursorTranscriptMetadata(opts = {}) {
|
|
26590
26313
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26591
26314
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26602,7 +26325,7 @@ async function listCursorTranscriptMetadata(opts = {}) {
|
|
|
26602
26325
|
continue;
|
|
26603
26326
|
let sizeBytes = 0;
|
|
26604
26327
|
try {
|
|
26605
|
-
sizeBytes =
|
|
26328
|
+
sizeBytes = statSync21(s.path).size;
|
|
26606
26329
|
} catch {}
|
|
26607
26330
|
if (!s.sessionId)
|
|
26608
26331
|
continue;
|
|
@@ -26843,7 +26566,7 @@ var init_opencode = __esm(() => {
|
|
|
26843
26566
|
});
|
|
26844
26567
|
|
|
26845
26568
|
// src/audit/cli-adapters/pi.ts
|
|
26846
|
-
import { statSync as
|
|
26569
|
+
import { statSync as statSync22 } from "node:fs";
|
|
26847
26570
|
async function listPiTranscriptMetadata(opts = {}) {
|
|
26848
26571
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26849
26572
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26860,7 +26583,7 @@ async function listPiTranscriptMetadata(opts = {}) {
|
|
|
26860
26583
|
continue;
|
|
26861
26584
|
let sizeBytes = 0;
|
|
26862
26585
|
try {
|
|
26863
|
-
sizeBytes =
|
|
26586
|
+
sizeBytes = statSync22(s.path).size;
|
|
26864
26587
|
} catch {}
|
|
26865
26588
|
if (!s.sessionId)
|
|
26866
26589
|
continue;
|
|
@@ -27669,7 +27392,7 @@ function flattenToolInput(input, depth = 0) {
|
|
|
27669
27392
|
}
|
|
27670
27393
|
return "";
|
|
27671
27394
|
}
|
|
27672
|
-
var LEAK_SCAN_VERSION =
|
|
27395
|
+
var LEAK_SCAN_VERSION = 6, ASSIGNMENT_RE, DOCS_LITERALS, SELF_OUTPUT_MARKERS, GATED_PATTERNS;
|
|
27673
27396
|
var init_leak_scan = __esm(() => {
|
|
27674
27397
|
init_builtin_policies();
|
|
27675
27398
|
ASSIGNMENT_RE = /(["']?)\b([A-Za-z_][A-Za-z0-9_]{0,127})\1([ \t]*(?::(?!\/\/)|=)[ \t]*)("[^"]*"|'[^']*'|[^\s;|&"']+)/g;
|
|
@@ -27694,6 +27417,176 @@ var init_leak_scan = __esm(() => {
|
|
|
27694
27417
|
GATED_PATTERNS = SECRET_PATTERNS.map(([re, label]) => [re, label, literalPrefixOf(re.source)]);
|
|
27695
27418
|
});
|
|
27696
27419
|
|
|
27420
|
+
// src/audit/leak-record.ts
|
|
27421
|
+
function upsertFinding(record, incoming) {
|
|
27422
|
+
const { sighting, ...rest } = incoming;
|
|
27423
|
+
const existing = record.findings.find((f) => f.id === rest.id);
|
|
27424
|
+
if (!existing) {
|
|
27425
|
+
record.findings.push({
|
|
27426
|
+
...rest,
|
|
27427
|
+
firstSeen: sighting.at,
|
|
27428
|
+
lastSeen: sighting.at,
|
|
27429
|
+
occurrences: 1,
|
|
27430
|
+
sightings: [sighting]
|
|
27431
|
+
});
|
|
27432
|
+
return { record, isNew: true };
|
|
27433
|
+
}
|
|
27434
|
+
existing.occurrences += 1;
|
|
27435
|
+
if (sighting.at > existing.lastSeen)
|
|
27436
|
+
existing.lastSeen = sighting.at;
|
|
27437
|
+
if (sighting.at < existing.firstSeen)
|
|
27438
|
+
existing.firstSeen = sighting.at;
|
|
27439
|
+
const seen = existing.sightings.some((s) => s.sessionId === sighting.sessionId && s.at === sighting.at);
|
|
27440
|
+
if (!seen) {
|
|
27441
|
+
existing.sightings.push(sighting);
|
|
27442
|
+
existing.sightings.sort((a, b) => a.at.localeCompare(b.at));
|
|
27443
|
+
if (existing.sightings.length > MAX_SIGHTINGS) {
|
|
27444
|
+
existing.sightings.splice(1, existing.sightings.length - MAX_SIGHTINGS);
|
|
27445
|
+
}
|
|
27446
|
+
}
|
|
27447
|
+
return { record, isNew: false };
|
|
27448
|
+
}
|
|
27449
|
+
function pruneRecord(record, nowMs) {
|
|
27450
|
+
const cutoff = new Date(nowMs - FINDING_TTL_DAYS * 86400000).toISOString();
|
|
27451
|
+
const live = record.findings.filter((f) => f.lastSeen >= cutoff);
|
|
27452
|
+
live.sort((a, b) => a.lastSeen < b.lastSeen ? 1 : a.lastSeen > b.lastSeen ? -1 : 0);
|
|
27453
|
+
record.findings = live.slice(0, MAX_FINDINGS);
|
|
27454
|
+
return record;
|
|
27455
|
+
}
|
|
27456
|
+
function emptyRecord(salt, nowIso) {
|
|
27457
|
+
return {
|
|
27458
|
+
schemaVersion: LEAK_RECORD_SCHEMA_VERSION,
|
|
27459
|
+
salt,
|
|
27460
|
+
updatedAt: nowIso,
|
|
27461
|
+
findings: []
|
|
27462
|
+
};
|
|
27463
|
+
}
|
|
27464
|
+
function describeMechanism(toolName, direction, shortPath) {
|
|
27465
|
+
const where = shortPath ? ` ${shortPath}` : "";
|
|
27466
|
+
let summary;
|
|
27467
|
+
if (direction === "result") {
|
|
27468
|
+
summary = shortPath ? `appeared in the output of reading${where}` : "appeared in tool output";
|
|
27469
|
+
} else {
|
|
27470
|
+
switch (toolName) {
|
|
27471
|
+
case "Read":
|
|
27472
|
+
summary = `read from${where || " a file"}`;
|
|
27473
|
+
break;
|
|
27474
|
+
case "Write":
|
|
27475
|
+
summary = `written to${where || " a file"}`;
|
|
27476
|
+
break;
|
|
27477
|
+
case "Edit":
|
|
27478
|
+
case "NotebookEdit":
|
|
27479
|
+
summary = `edited into${where || " a file"}`;
|
|
27480
|
+
break;
|
|
27481
|
+
case "Bash":
|
|
27482
|
+
summary = "passed in a shell command";
|
|
27483
|
+
break;
|
|
27484
|
+
default:
|
|
27485
|
+
summary = `sent to the ${toolName} tool`;
|
|
27486
|
+
}
|
|
27487
|
+
}
|
|
27488
|
+
return { summary, toolName, direction };
|
|
27489
|
+
}
|
|
27490
|
+
var MAX_SIGHTINGS = 5, FINDING_TTL_DAYS = 90, MAX_FINDINGS = 500, LEAK_RECORD_SCHEMA_VERSION = 1;
|
|
27491
|
+
|
|
27492
|
+
// src/audit/leak-store.ts
|
|
27493
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
27494
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync20, readFileSync as readFileSync26 } from "node:fs";
|
|
27495
|
+
import { dirname as dirname16 } from "node:path";
|
|
27496
|
+
function readJson(path) {
|
|
27497
|
+
try {
|
|
27498
|
+
if (!existsSync31(path))
|
|
27499
|
+
return null;
|
|
27500
|
+
return JSON.parse(readFileSync26(path, "utf8"));
|
|
27501
|
+
} catch {
|
|
27502
|
+
return null;
|
|
27503
|
+
}
|
|
27504
|
+
}
|
|
27505
|
+
function readLeakIdentity(home) {
|
|
27506
|
+
const existing = readJson(auditLeakIdentityFile(home));
|
|
27507
|
+
if (existing && typeof existing.salt === "string" && existing.salt.length >= 32) {
|
|
27508
|
+
return {
|
|
27509
|
+
salt: existing.salt,
|
|
27510
|
+
dismissed: existing.dismissed ?? []
|
|
27511
|
+
};
|
|
27512
|
+
}
|
|
27513
|
+
const minted = { salt: randomBytes2(32).toString("hex"), dismissed: [] };
|
|
27514
|
+
writeLeakIdentity(minted, home);
|
|
27515
|
+
return minted;
|
|
27516
|
+
}
|
|
27517
|
+
function writeLeakIdentity(identity, home) {
|
|
27518
|
+
const path = auditLeakIdentityFile(home);
|
|
27519
|
+
try {
|
|
27520
|
+
mkdirSync20(dirname16(path), { recursive: true });
|
|
27521
|
+
writeJsonAtomically(path, identity, { mode: FILE_MODE });
|
|
27522
|
+
return true;
|
|
27523
|
+
} catch {
|
|
27524
|
+
return false;
|
|
27525
|
+
}
|
|
27526
|
+
}
|
|
27527
|
+
function sanitizeFinding(raw) {
|
|
27528
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
27529
|
+
return null;
|
|
27530
|
+
const f = raw;
|
|
27531
|
+
if (typeof f.id !== "string" || !isFindingId(f.id))
|
|
27532
|
+
return null;
|
|
27533
|
+
const fp = f.fingerprint;
|
|
27534
|
+
if (!fp || typeof fp !== "object" || typeof fp.display !== "string" || typeof fp.label !== "string") {
|
|
27535
|
+
return null;
|
|
27536
|
+
}
|
|
27537
|
+
const sightings = Array.isArray(f.sightings) ? f.sightings.filter((s) => {
|
|
27538
|
+
if (!s || typeof s !== "object")
|
|
27539
|
+
return false;
|
|
27540
|
+
const m = s.mechanism;
|
|
27541
|
+
return !!m && typeof m === "object" && typeof m.summary === "string";
|
|
27542
|
+
}) : [];
|
|
27543
|
+
return {
|
|
27544
|
+
...f,
|
|
27545
|
+
fingerprint: {
|
|
27546
|
+
display: fp.display,
|
|
27547
|
+
label: fp.label,
|
|
27548
|
+
length: typeof fp.length === "number" && Number.isFinite(fp.length) ? fp.length : 0,
|
|
27549
|
+
attributed: fp.attributed === true
|
|
27550
|
+
},
|
|
27551
|
+
name: typeof f.name === "string" ? f.name : null,
|
|
27552
|
+
firstSeen: typeof f.firstSeen === "string" ? f.firstSeen : "",
|
|
27553
|
+
lastSeen: typeof f.lastSeen === "string" ? f.lastSeen : "",
|
|
27554
|
+
occurrences: typeof f.occurrences === "number" && Number.isFinite(f.occurrences) ? f.occurrences : sightings.length,
|
|
27555
|
+
sightings
|
|
27556
|
+
};
|
|
27557
|
+
}
|
|
27558
|
+
function readLeakRecord(home) {
|
|
27559
|
+
const identity = readLeakIdentity(home);
|
|
27560
|
+
const raw = readJson(auditLeaksFile(home));
|
|
27561
|
+
if (!raw || raw.schemaVersion !== LEAK_RECORD_SCHEMA_VERSION || !Array.isArray(raw.findings)) {
|
|
27562
|
+
return emptyRecord(identity.salt, new Date().toISOString());
|
|
27563
|
+
}
|
|
27564
|
+
const findings = raw.findings.map(sanitizeFinding).filter((f) => f !== null);
|
|
27565
|
+
return { ...raw, findings, salt: identity.salt };
|
|
27566
|
+
}
|
|
27567
|
+
function writeLeakRecord(record, home, nowMs = Date.now()) {
|
|
27568
|
+
const path = auditLeaksFile(home);
|
|
27569
|
+
try {
|
|
27570
|
+
mkdirSync20(dirname16(path), { recursive: true });
|
|
27571
|
+
const pruned = pruneRecord(record, nowMs);
|
|
27572
|
+
pruned.updatedAt = new Date(nowMs).toISOString();
|
|
27573
|
+
writeJsonAtomically(path, pruned, { mode: FILE_MODE });
|
|
27574
|
+
return true;
|
|
27575
|
+
} catch {
|
|
27576
|
+
return false;
|
|
27577
|
+
}
|
|
27578
|
+
}
|
|
27579
|
+
function activeFindings(record, home) {
|
|
27580
|
+
const dismissed = new Set(readLeakIdentity(home).dismissed);
|
|
27581
|
+
return record.findings.filter((f) => !dismissed.has(f.id)).sort((a, b) => a.lastSeen < b.lastSeen ? 1 : a.lastSeen > b.lastSeen ? -1 : 0);
|
|
27582
|
+
}
|
|
27583
|
+
var FILE_MODE = 384;
|
|
27584
|
+
var init_leak_store = __esm(() => {
|
|
27585
|
+
init_fp_home();
|
|
27586
|
+
init_atomic_write();
|
|
27587
|
+
init_leak_fingerprint();
|
|
27588
|
+
});
|
|
27589
|
+
|
|
27697
27590
|
// src/audit/redact-example.ts
|
|
27698
27591
|
import { homedir as homedir27 } from "node:os";
|
|
27699
27592
|
function maskTruncatedSecret(input) {
|
|
@@ -27837,7 +27730,7 @@ var init_redact_example = __esm(() => {
|
|
|
27837
27730
|
|
|
27838
27731
|
// src/audit/cache.ts
|
|
27839
27732
|
import { createHash as createHash8 } from "node:crypto";
|
|
27840
|
-
import { existsSync as
|
|
27733
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync21, readFileSync as readFileSync27, writeFileSync as writeFileSync18, chmodSync as chmodSync5, openSync, readSync, closeSync } from "node:fs";
|
|
27841
27734
|
import { join as join33 } from "node:path";
|
|
27842
27735
|
function getEngineVersion() {
|
|
27843
27736
|
if (cachedEngineVersion)
|
|
@@ -27898,7 +27791,7 @@ function readCachedTranscript(transcriptPath, mtimeMs, sizeBytes) {
|
|
|
27898
27791
|
if (sizeBytes === 0)
|
|
27899
27792
|
return null;
|
|
27900
27793
|
const cachePath = getCachePathFor(transcriptPath);
|
|
27901
|
-
if (!
|
|
27794
|
+
if (!existsSync32(cachePath))
|
|
27902
27795
|
return null;
|
|
27903
27796
|
try {
|
|
27904
27797
|
const raw = readFileSync27(cachePath, "utf-8");
|
|
@@ -27942,7 +27835,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result,
|
|
|
27942
27835
|
return;
|
|
27943
27836
|
const cachePath = getCachePathFor(transcriptPath);
|
|
27944
27837
|
try {
|
|
27945
|
-
|
|
27838
|
+
mkdirSync21(auditCacheDir(), { recursive: true });
|
|
27946
27839
|
const entry = {
|
|
27947
27840
|
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
27948
27841
|
cachedAt: Date.now(),
|
|
@@ -27961,7 +27854,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result,
|
|
|
27961
27854
|
entry.detectorState = encodeDetectorState(resume.detectorState);
|
|
27962
27855
|
}
|
|
27963
27856
|
}
|
|
27964
|
-
|
|
27857
|
+
writeFileSync18(cachePath, JSON.stringify(entry), { encoding: "utf-8", mode: 384 });
|
|
27965
27858
|
try {
|
|
27966
27859
|
chmodSync5(cachePath, 384);
|
|
27967
27860
|
} catch {}
|
|
@@ -28480,8 +28373,10 @@ async function runAuditInner(opts, startedAt) {
|
|
|
28480
28373
|
}
|
|
28481
28374
|
const coversAllHistory = opts.clis === undefined && opts.projects === undefined && opts.since === undefined && discoveryErrors === 0 && errors === 0 && skipped === 0;
|
|
28482
28375
|
const newFindingIds = persistLeaks(perTranscript, coversAllHistory);
|
|
28376
|
+
const leakIds = [...new Set(perTranscript.flatMap((t) => (t.leaks ?? []).map((leak) => leak.id)))];
|
|
28483
28377
|
const auditResult = {
|
|
28484
28378
|
version: 2,
|
|
28379
|
+
leakIds,
|
|
28485
28380
|
newLeakIds: newFindingIds,
|
|
28486
28381
|
scannedAt: new Date(startedAt).toISOString(),
|
|
28487
28382
|
scope: {
|
|
@@ -28537,11 +28432,11 @@ var init_audit = __esm(() => {
|
|
|
28537
28432
|
import {
|
|
28538
28433
|
closeSync as closeSync2,
|
|
28539
28434
|
linkSync,
|
|
28540
|
-
mkdirSync as
|
|
28435
|
+
mkdirSync as mkdirSync22,
|
|
28541
28436
|
openSync as openSync2,
|
|
28542
28437
|
readFileSync as readFileSync28,
|
|
28543
28438
|
unlinkSync as unlinkSync4,
|
|
28544
|
-
writeFileSync as
|
|
28439
|
+
writeFileSync as writeFileSync19,
|
|
28545
28440
|
writeSync
|
|
28546
28441
|
} from "node:fs";
|
|
28547
28442
|
function acquireAuditLock(source, now = Date.now()) {
|
|
@@ -28616,7 +28511,7 @@ function writeLockExclusive(path, info) {
|
|
|
28616
28511
|
const body = JSON.stringify(info);
|
|
28617
28512
|
const staging = `${path}.${process.pid}.tmp`;
|
|
28618
28513
|
try {
|
|
28619
|
-
|
|
28514
|
+
writeFileSync19(staging, body, { mode: 384 });
|
|
28620
28515
|
} catch {
|
|
28621
28516
|
return false;
|
|
28622
28517
|
}
|
|
@@ -28650,8 +28545,8 @@ function createThenWrite(path, body) {
|
|
|
28650
28545
|
}
|
|
28651
28546
|
}
|
|
28652
28547
|
function ensureRunDir() {
|
|
28653
|
-
|
|
28654
|
-
|
|
28548
|
+
mkdirSync22(failproofaiHome(), { recursive: true });
|
|
28549
|
+
mkdirSync22(runDir(), { recursive: true, mode: 448 });
|
|
28655
28550
|
}
|
|
28656
28551
|
var AUDIT_LOCK_MAX_AGE_MS;
|
|
28657
28552
|
var init_audit_lock = __esm(() => {
|
|
@@ -28660,7 +28555,7 @@ var init_audit_lock = __esm(() => {
|
|
|
28660
28555
|
});
|
|
28661
28556
|
|
|
28662
28557
|
// src/audit/dashboard-cache.ts
|
|
28663
|
-
import { existsSync as
|
|
28558
|
+
import { existsSync as existsSync33, readFileSync as readFileSync29 } from "node:fs";
|
|
28664
28559
|
function getCachePath() {
|
|
28665
28560
|
return auditDashboardFile();
|
|
28666
28561
|
}
|
|
@@ -28680,7 +28575,7 @@ function writeDashboardCache(params, result) {
|
|
|
28680
28575
|
}
|
|
28681
28576
|
function readDashboardCacheMeta() {
|
|
28682
28577
|
const cachePath = getCachePath();
|
|
28683
|
-
if (!
|
|
28578
|
+
if (!existsSync33(cachePath))
|
|
28684
28579
|
return null;
|
|
28685
28580
|
try {
|
|
28686
28581
|
const raw = readFileSync29(cachePath, "utf-8");
|
|
@@ -28907,15 +28802,15 @@ var init_api_server_client = __esm(() => {
|
|
|
28907
28802
|
});
|
|
28908
28803
|
|
|
28909
28804
|
// lib/auth/auth-store.ts
|
|
28910
|
-
import { existsSync as
|
|
28911
|
-
import { join as join34, resolve as
|
|
28805
|
+
import { existsSync as existsSync34, readFileSync as readFileSync30, readdirSync as readdirSync18, rmSync as rmSync13 } from "node:fs";
|
|
28806
|
+
import { join as join34, resolve as resolve24 } from "node:path";
|
|
28912
28807
|
function getAuthFilePath() {
|
|
28913
28808
|
const override = process.env.FAILPROOFAI_AUTH_DIR;
|
|
28914
28809
|
return override ? join34(override, "session.json") : auditSessionFile();
|
|
28915
28810
|
}
|
|
28916
28811
|
function readAuth() {
|
|
28917
28812
|
const p = getAuthFilePath();
|
|
28918
|
-
if (!
|
|
28813
|
+
if (!existsSync34(p))
|
|
28919
28814
|
return null;
|
|
28920
28815
|
try {
|
|
28921
28816
|
const raw = readFileSync30(p, "utf-8");
|
|
@@ -28942,18 +28837,18 @@ function writeAuth(auth) {
|
|
|
28942
28837
|
}
|
|
28943
28838
|
function deleteAuth() {
|
|
28944
28839
|
const p = getAuthFilePath();
|
|
28945
|
-
if (
|
|
28946
|
-
|
|
28840
|
+
if (existsSync34(p))
|
|
28841
|
+
rmSync13(p, { force: true });
|
|
28947
28842
|
try {
|
|
28948
28843
|
const root = migrationsDir();
|
|
28949
|
-
if (!
|
|
28844
|
+
if (!existsSync34(root))
|
|
28950
28845
|
return;
|
|
28951
|
-
for (const entry of
|
|
28846
|
+
for (const entry of readdirSync18(root)) {
|
|
28952
28847
|
if (!entry.startsWith("backup-layout"))
|
|
28953
28848
|
continue;
|
|
28954
|
-
const copy =
|
|
28955
|
-
if (
|
|
28956
|
-
|
|
28849
|
+
const copy = resolve24(root, entry, "auth.json");
|
|
28850
|
+
if (existsSync34(copy))
|
|
28851
|
+
rmSync13(copy, { force: true });
|
|
28957
28852
|
}
|
|
28958
28853
|
} catch {}
|
|
28959
28854
|
}
|
|
@@ -29085,7 +28980,11 @@ function selectLeaks(findings, from, to) {
|
|
|
29085
28980
|
const last = ts(f.lastSeen);
|
|
29086
28981
|
if (last !== null && (last < lo || last > hi))
|
|
29087
28982
|
continue;
|
|
29088
|
-
const seen = f.sightings?.
|
|
28983
|
+
const seen = f.sightings?.reduce((latest, candidate) => {
|
|
28984
|
+
if (!latest)
|
|
28985
|
+
return candidate;
|
|
28986
|
+
return (ts(candidate.at) ?? 0) >= (ts(latest.at) ?? 0) ? candidate : latest;
|
|
28987
|
+
}, undefined);
|
|
29089
28988
|
out.push({
|
|
29090
28989
|
id: f.id,
|
|
29091
28990
|
display: f.fingerprint?.display ?? "[credential]",
|
|
@@ -29117,7 +29016,7 @@ function buildHarmReport(result, lastReportedAt, intervalDays, leakFindings = []
|
|
|
29117
29016
|
window_from: from.toISOString(),
|
|
29118
29017
|
window_to: windowTo.toISOString(),
|
|
29119
29018
|
harmful: selectHarmful(result, from, windowTo, { includeUnplaceable: isFirstReport }),
|
|
29120
|
-
leaks: selectLeaks(leakFindings, from, windowTo)
|
|
29019
|
+
leaks: selectLeaks(leakFindings, from, windowTo).slice(0, 1)
|
|
29121
29020
|
};
|
|
29122
29021
|
}
|
|
29123
29022
|
var HARMFUL_SEVERITIES, ALSO_HARMFUL;
|
|
@@ -29128,12 +29027,12 @@ var init_harm_report = __esm(() => {
|
|
|
29128
29027
|
});
|
|
29129
29028
|
|
|
29130
29029
|
// src/audit/machine-store.ts
|
|
29131
|
-
import { existsSync as
|
|
29030
|
+
import { existsSync as existsSync35, readFileSync as readFileSync31, rmSync as rmSync14 } from "node:fs";
|
|
29132
29031
|
import { hostname as hostname5 } from "node:os";
|
|
29133
29032
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
29134
29033
|
function readMachineIdentity(home) {
|
|
29135
29034
|
const path = auditMachineFile(home);
|
|
29136
|
-
if (!
|
|
29035
|
+
if (!existsSync35(path))
|
|
29137
29036
|
return null;
|
|
29138
29037
|
try {
|
|
29139
29038
|
const parsed = JSON.parse(readFileSync31(path, "utf8"));
|
|
@@ -29182,20 +29081,20 @@ var init_machine_store = __esm(() => {
|
|
|
29182
29081
|
// src/audit/report-harm.ts
|
|
29183
29082
|
async function reportHarm(result) {
|
|
29184
29083
|
let auto = false;
|
|
29185
|
-
let consentedAt;
|
|
29186
29084
|
let intervalDays = 7;
|
|
29187
29085
|
try {
|
|
29188
29086
|
const config = readConfig();
|
|
29189
29087
|
auto = config.audit.auto;
|
|
29190
|
-
consentedAt = config.audit.reportsConsentedAt;
|
|
29191
29088
|
intervalDays = config.audit.intervalDays;
|
|
29192
29089
|
} catch {
|
|
29193
29090
|
return { kind: "disabled" };
|
|
29194
29091
|
}
|
|
29195
29092
|
if (!auto)
|
|
29196
29093
|
return { kind: "disabled" };
|
|
29197
|
-
|
|
29198
|
-
|
|
29094
|
+
const prior = readMachineIdentity();
|
|
29095
|
+
const report = buildHarmReport(result, prior?.last_reported_at, intervalDays, activeFindings(readLeakRecord()));
|
|
29096
|
+
if (report.leaks.length === 0)
|
|
29097
|
+
return { kind: "no-leak" };
|
|
29199
29098
|
const auth = await getValidAccessToken();
|
|
29200
29099
|
if (!auth) {
|
|
29201
29100
|
return { kind: "signed-out" };
|
|
@@ -29206,8 +29105,6 @@ async function reportHarm(result) {
|
|
|
29206
29105
|
} catch (err) {
|
|
29207
29106
|
return { kind: "failed", error: err instanceof Error ? err.message : String(err) };
|
|
29208
29107
|
}
|
|
29209
|
-
const report = buildHarmReport(result, identity.last_reported_at, intervalDays, activeFindings(readLeakRecord()));
|
|
29210
|
-
const hits = report.harmful.reduce((n, p) => n + p.hits, 0);
|
|
29211
29108
|
try {
|
|
29212
29109
|
const res = await submitAuditReport(auth.access_token, {
|
|
29213
29110
|
machine_id: identity.machine_id,
|
|
@@ -29221,7 +29118,7 @@ async function reportHarm(result) {
|
|
|
29221
29118
|
try {
|
|
29222
29119
|
recordReportWatermark(res.next_window_from);
|
|
29223
29120
|
} catch {}
|
|
29224
|
-
return res.emailed ? { kind: "sent",
|
|
29121
|
+
return res.emailed ? { kind: "sent", leaks: report.leaks.length } : { kind: "held", leaks: report.leaks.length, reason: res.reason ?? "not_sent" };
|
|
29225
29122
|
} catch (err) {
|
|
29226
29123
|
const error = err instanceof AuthApiError ? `${err.code}: ${err.message}` : err instanceof Error ? err.message : String(err);
|
|
29227
29124
|
return { kind: "failed", error };
|
|
@@ -29230,17 +29127,16 @@ async function reportHarm(result) {
|
|
|
29230
29127
|
function describeOutcome2(outcome) {
|
|
29231
29128
|
switch (outcome.kind) {
|
|
29232
29129
|
case "disabled":
|
|
29130
|
+
case "no-leak":
|
|
29233
29131
|
return null;
|
|
29234
|
-
case "consent-required":
|
|
29235
|
-
return "failproofai: scheduled scans are on, but emailing what they find needs a fresh opt-in — run `failproofai audit --schedule` (or visit /settings) to turn digests on";
|
|
29236
29132
|
case "signed-out":
|
|
29237
|
-
return "failproofai:
|
|
29133
|
+
return "failproofai: a credential exposure was found, but no email is configured — run `failproofai audit --schedule --email you@example.com`";
|
|
29238
29134
|
case "sent":
|
|
29239
|
-
return
|
|
29135
|
+
return "failproofai: emailed the most recent credential exposure";
|
|
29240
29136
|
case "held":
|
|
29241
|
-
return `failproofai:
|
|
29137
|
+
return `failproofai: credential exposure reported, no email (${outcome.reason})`;
|
|
29242
29138
|
case "failed":
|
|
29243
|
-
return `failproofai: could not send the
|
|
29139
|
+
return `failproofai: could not send the credential alert: ${outcome.error}`;
|
|
29244
29140
|
}
|
|
29245
29141
|
}
|
|
29246
29142
|
var init_report_harm = __esm(() => {
|
|
@@ -29514,6 +29410,15 @@ var init_desktop_notify = __esm(() => {
|
|
|
29514
29410
|
];
|
|
29515
29411
|
});
|
|
29516
29412
|
|
|
29413
|
+
// src/hooks/notice.ts
|
|
29414
|
+
function desktopLeakNotice(email = "held") {
|
|
29415
|
+
const followUp = email === "sent" ? "A masked alert was also sent to your email." : email === "missing" ? "Add email alerts with: failproofai audit --schedule --email you@example.com" : email === "failed" ? "Email delivery failed this time; the local result is still available." : "Email was not sent for this run.";
|
|
29416
|
+
return {
|
|
29417
|
+
title: "failproofai audit needs review",
|
|
29418
|
+
body: "Possible credential exposure was found in your agent transcripts. " + `Run failproofai audit to verify the matches and rotate anything real. ${followUp}`
|
|
29419
|
+
};
|
|
29420
|
+
}
|
|
29421
|
+
|
|
29517
29422
|
// src/audit/cli.ts
|
|
29518
29423
|
function colorOn() {
|
|
29519
29424
|
if (process.env.NO_COLOR && process.env.NO_COLOR !== "")
|
|
@@ -29706,10 +29611,8 @@ var init_cli = __esm(() => {
|
|
|
29706
29611
|
init_report_harm();
|
|
29707
29612
|
init_desktop_notify();
|
|
29708
29613
|
init_macos_notifier();
|
|
29709
|
-
init_leak_notice();
|
|
29710
|
-
init_notice();
|
|
29711
|
-
init_leak_store();
|
|
29712
29614
|
init_fp_config();
|
|
29615
|
+
init_auth_store();
|
|
29713
29616
|
init_tui();
|
|
29714
29617
|
init_package();
|
|
29715
29618
|
AUDIT_STAGES = [
|
|
@@ -29728,9 +29631,9 @@ var init_cli = __esm(() => {
|
|
|
29728
29631
|
});
|
|
29729
29632
|
|
|
29730
29633
|
// src/hooks/configure-wizard.ts
|
|
29731
|
-
import { existsSync as
|
|
29634
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync23, writeFileSync as writeFileSync20, readFileSync as readFileSync32 } from "node:fs";
|
|
29732
29635
|
import { homedir as homedir28 } from "node:os";
|
|
29733
|
-
import { dirname as dirname17, resolve as
|
|
29636
|
+
import { dirname as dirname17, resolve as resolve25, sep as sep5 } from "node:path";
|
|
29734
29637
|
async function emit(event, props) {
|
|
29735
29638
|
try {
|
|
29736
29639
|
await trackHookEvent2(getInstanceId2(), event, props);
|
|
@@ -29753,7 +29656,7 @@ function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
|
29753
29656
|
const path = getConfigPathForScope(scope, cwd);
|
|
29754
29657
|
let config = {};
|
|
29755
29658
|
try {
|
|
29756
|
-
if (
|
|
29659
|
+
if (existsSync36(path))
|
|
29757
29660
|
config = JSON.parse(readFileSync32(path, "utf8"));
|
|
29758
29661
|
} catch {
|
|
29759
29662
|
return;
|
|
@@ -29763,7 +29666,7 @@ function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
|
29763
29666
|
else
|
|
29764
29667
|
config.customPoliciesEnabled = false;
|
|
29765
29668
|
try {
|
|
29766
|
-
|
|
29669
|
+
writeFileSync20(path, JSON.stringify(config, null, 2) + `
|
|
29767
29670
|
`, "utf8");
|
|
29768
29671
|
} catch {}
|
|
29769
29672
|
}
|
|
@@ -29794,7 +29697,7 @@ function describeCustomPolicies(cwd) {
|
|
|
29794
29697
|
const scopes = [];
|
|
29795
29698
|
let fileCount = 0;
|
|
29796
29699
|
const dirs = [
|
|
29797
|
-
{ dir:
|
|
29700
|
+
{ dir: resolve25(cwd, ".failproofai", "policies"), label: "project" },
|
|
29798
29701
|
{ dir: customPoliciesDir(), label: "global" }
|
|
29799
29702
|
];
|
|
29800
29703
|
for (const { dir, label } of dirs) {
|
|
@@ -29805,7 +29708,7 @@ function describeCustomPolicies(cwd) {
|
|
|
29805
29708
|
fileCount += found.length;
|
|
29806
29709
|
}
|
|
29807
29710
|
for (const name of findSkippedPolicyFiles(dir)) {
|
|
29808
|
-
warnings.push(`! ${homeify(
|
|
29711
|
+
warnings.push(`! ${homeify(resolve25(dir, name))} is NOT loaded — rename to ` + `${name.replace(/\.(js|mjs|ts)$/, "-policies.$1")}`);
|
|
29809
29712
|
}
|
|
29810
29713
|
}
|
|
29811
29714
|
return { active, warnings, fileCount, scopes };
|
|
@@ -29898,8 +29801,8 @@ function firstRunMarkerPath() {
|
|
|
29898
29801
|
}
|
|
29899
29802
|
function markLauncherSeen() {
|
|
29900
29803
|
try {
|
|
29901
|
-
|
|
29902
|
-
|
|
29804
|
+
mkdirSync23(dirname17(firstRunMarkerPath()), { recursive: true });
|
|
29805
|
+
writeFileSync20(firstRunMarkerPath(), "1", "utf8");
|
|
29903
29806
|
} catch {}
|
|
29904
29807
|
}
|
|
29905
29808
|
function retryProbe() {
|
|
@@ -29977,6 +29880,8 @@ async function runConfigureWizard(io = {}, answers = {}) {
|
|
|
29977
29880
|
const cwd = process.cwd();
|
|
29978
29881
|
const unattended = !stdin.isTTY || !stdout.isTTY;
|
|
29979
29882
|
const preAnswered = Boolean(answers.token);
|
|
29883
|
+
const initialAudit = readConfigRaw().raw.audit;
|
|
29884
|
+
const hadExplicitAuditAuto = !!initialAudit && typeof initialAudit === "object" && !Array.isArray(initialAudit) && typeof initialAudit.auto === "boolean";
|
|
29980
29885
|
if (typeof process.getuid === "function" && process.getuid() === 0 && process.env.SUDO_USER) {
|
|
29981
29886
|
stdout.write(`Run failproofai config as ${process.env.SUDO_USER}, not under sudo.
|
|
29982
29887
|
` + `Everything it configures is per-user — hooks, policies and the daemon's own
|
|
@@ -30299,6 +30204,11 @@ Hooks keep enforcing; scheduled audits stay off until it is.
|
|
|
30299
30204
|
}
|
|
30300
30205
|
if (daemonInstalled) {
|
|
30301
30206
|
setDaemonConfigured(true, version2);
|
|
30207
|
+
if (!hadExplicitAuditAuto) {
|
|
30208
|
+
try {
|
|
30209
|
+
updateConfig({ audit: { auto: true } });
|
|
30210
|
+
} catch {}
|
|
30211
|
+
}
|
|
30302
30212
|
pruneOldDaemonBinaries();
|
|
30303
30213
|
installMacNotifier();
|
|
30304
30214
|
}
|
|
@@ -30388,21 +30298,22 @@ var init_configure_wizard = __esm(() => {
|
|
|
30388
30298
|
init_package();
|
|
30389
30299
|
init_onboarding_attempt();
|
|
30390
30300
|
init_onboarding_lock();
|
|
30301
|
+
init_fp_config();
|
|
30391
30302
|
POLICY_LIST_INDENT = " ".repeat(15);
|
|
30392
30303
|
});
|
|
30393
30304
|
|
|
30394
30305
|
// src/hooks/flush-cli.ts
|
|
30395
|
-
import { existsSync as
|
|
30306
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync24, writeFileSync as writeFileSync21, readdirSync as readdirSync19 } from "node:fs";
|
|
30396
30307
|
import { dirname as dirname18, join as join35 } from "node:path";
|
|
30397
30308
|
function flushRequestPath2(home) {
|
|
30398
30309
|
return join35(failproofaiHome(home), "state", "flush-request.json");
|
|
30399
30310
|
}
|
|
30400
30311
|
function spoolDirs2(home) {
|
|
30401
30312
|
const root = spoolDir(home);
|
|
30402
|
-
if (!
|
|
30313
|
+
if (!existsSync37(root))
|
|
30403
30314
|
return [];
|
|
30404
30315
|
try {
|
|
30405
|
-
return
|
|
30316
|
+
return readdirSync19(root, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name !== "failed").map((e) => join35(root, e.name));
|
|
30406
30317
|
} catch {
|
|
30407
30318
|
return [];
|
|
30408
30319
|
}
|
|
@@ -30411,7 +30322,7 @@ function pendingBatches2(home) {
|
|
|
30411
30322
|
let n = 0;
|
|
30412
30323
|
for (const dir of spoolDirs2(home)) {
|
|
30413
30324
|
try {
|
|
30414
|
-
n +=
|
|
30325
|
+
n += readdirSync19(dir).filter((f) => f.endsWith(".jsonl")).length;
|
|
30415
30326
|
} catch {}
|
|
30416
30327
|
}
|
|
30417
30328
|
return n;
|
|
@@ -30468,8 +30379,8 @@ async function runFlushCommand2(opts = {}) {
|
|
|
30468
30379
|
return { exitCode: 0, pending: 0, lines: ["Nothing spooled — everything already delivered."] };
|
|
30469
30380
|
}
|
|
30470
30381
|
const path = flushRequestPath2(home);
|
|
30471
|
-
|
|
30472
|
-
|
|
30382
|
+
mkdirSync24(dirname18(path), { recursive: true });
|
|
30383
|
+
writeFileSync21(path, `${JSON.stringify({ requestedAtMs: Date.now() }, null, 2)}
|
|
30473
30384
|
`, {
|
|
30474
30385
|
mode: 384
|
|
30475
30386
|
});
|
|
@@ -30500,7 +30411,7 @@ var init_flush_cli2 = __esm(() => {
|
|
|
30500
30411
|
});
|
|
30501
30412
|
|
|
30502
30413
|
// src/hooks/backfill-cli.ts
|
|
30503
|
-
import { existsSync as
|
|
30414
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync25, writeFileSync as writeFileSync22, readdirSync as readdirSync20, statSync as statSync23 } from "node:fs";
|
|
30504
30415
|
import { dirname as dirname19, join as join36 } from "node:path";
|
|
30505
30416
|
function backfillRequestPath(home) {
|
|
30506
30417
|
return join36(failproofaiHome(home), "state", "backfill-request.json");
|
|
@@ -30509,7 +30420,7 @@ function surveySessions(sinceMs, homeDir) {
|
|
|
30509
30420
|
const out = [];
|
|
30510
30421
|
for (const { cli, dir } of SESSION_DIRS) {
|
|
30511
30422
|
const root = join36(homeDir, dir);
|
|
30512
|
-
if (!
|
|
30423
|
+
if (!existsSync38(root))
|
|
30513
30424
|
continue;
|
|
30514
30425
|
let files = 0;
|
|
30515
30426
|
let newest = 0;
|
|
@@ -30518,7 +30429,7 @@ function surveySessions(sinceMs, homeDir) {
|
|
|
30518
30429
|
return;
|
|
30519
30430
|
let entries;
|
|
30520
30431
|
try {
|
|
30521
|
-
entries =
|
|
30432
|
+
entries = readdirSync20(d, { withFileTypes: true });
|
|
30522
30433
|
} catch {
|
|
30523
30434
|
return;
|
|
30524
30435
|
}
|
|
@@ -30529,7 +30440,7 @@ function surveySessions(sinceMs, homeDir) {
|
|
|
30529
30440
|
continue;
|
|
30530
30441
|
}
|
|
30531
30442
|
try {
|
|
30532
|
-
const st =
|
|
30443
|
+
const st = statSync23(p);
|
|
30533
30444
|
if (st.mtimeMs >= sinceMs) {
|
|
30534
30445
|
files += 1;
|
|
30535
30446
|
newest = Math.max(newest, st.mtimeMs);
|
|
@@ -30547,7 +30458,7 @@ function runBackfillCommand(opts = {}) {
|
|
|
30547
30458
|
const now = opts.now ?? Date.now();
|
|
30548
30459
|
const sinceMs = opts.sinceMs ?? now - DEFAULT_BACKFILL_DAYS * 24 * 60 * 60 * 1000;
|
|
30549
30460
|
const home = failproofaiHome();
|
|
30550
|
-
if (!
|
|
30461
|
+
if (!existsSync38(home)) {
|
|
30551
30462
|
return {
|
|
30552
30463
|
exitCode: 1,
|
|
30553
30464
|
lines: [`No failproofai home at ${home}. Run \`failproofai config\` first.`]
|
|
@@ -30602,8 +30513,8 @@ function runBackfillCommand(opts = {}) {
|
|
|
30602
30513
|
}
|
|
30603
30514
|
try {
|
|
30604
30515
|
const path = backfillRequestPath();
|
|
30605
|
-
|
|
30606
|
-
|
|
30516
|
+
mkdirSync25(dirname19(path), { recursive: true });
|
|
30517
|
+
writeFileSync22(path, `${JSON.stringify({ sinceMs, requestedAtMs: now }, null, 2)}
|
|
30607
30518
|
`, {
|
|
30608
30519
|
mode: 384
|
|
30609
30520
|
});
|
|
@@ -30646,7 +30557,7 @@ var init_backfill_cli = __esm(() => {
|
|
|
30646
30557
|
|
|
30647
30558
|
// src/hooks/harness-cli.ts
|
|
30648
30559
|
import { homedir as homedir29 } from "node:os";
|
|
30649
|
-
import { resolve as
|
|
30560
|
+
import { resolve as resolve26 } from "node:path";
|
|
30650
30561
|
function unknownHarness(name) {
|
|
30651
30562
|
return fail([
|
|
30652
30563
|
`Unknown harness: ${name}`,
|
|
@@ -30690,7 +30601,7 @@ function comparableLabel(raw) {
|
|
|
30690
30601
|
}
|
|
30691
30602
|
function comparablePath(raw) {
|
|
30692
30603
|
const home = homedir29();
|
|
30693
|
-
const expanded = raw === "~" ? home : raw.startsWith("~/") ?
|
|
30604
|
+
const expanded = raw === "~" ? home : raw.startsWith("~/") ? resolve26(home, raw.slice(2)) : raw;
|
|
30694
30605
|
return expanded.replace(/\/+$/, "");
|
|
30695
30606
|
}
|
|
30696
30607
|
function effectiveLabel(entry) {
|
|
@@ -30878,7 +30789,7 @@ var init_harness_cli = __esm(() => {
|
|
|
30878
30789
|
});
|
|
30879
30790
|
|
|
30880
30791
|
// src/hooks/fp-config.ts
|
|
30881
|
-
import { chmodSync as chmodSync6, existsSync as
|
|
30792
|
+
import { chmodSync as chmodSync6, existsSync as existsSync39, mkdirSync as mkdirSync26, readFileSync as readFileSync33, statSync as statSync24, writeFileSync as writeFileSync23 } from "node:fs";
|
|
30882
30793
|
function detectLayout2() {
|
|
30883
30794
|
const raw = readVersionFile2();
|
|
30884
30795
|
if (raw) {
|
|
@@ -30886,17 +30797,17 @@ function detectLayout2() {
|
|
|
30886
30797
|
return { kind: "current", version: raw };
|
|
30887
30798
|
return raw.layout > LAYOUT_VERSION ? { kind: "future", found: raw.layout } : { kind: "stale", found: raw.layout };
|
|
30888
30799
|
}
|
|
30889
|
-
if (
|
|
30800
|
+
if (existsSync39(configFile())) {
|
|
30890
30801
|
const layoutThreePositions = [
|
|
30891
30802
|
legacy.authJson(),
|
|
30892
30803
|
legacy.nextAudit(),
|
|
30893
30804
|
legacy.auditSchedule()
|
|
30894
30805
|
];
|
|
30895
|
-
if (layoutThreePositions.some((p) =>
|
|
30806
|
+
if (layoutThreePositions.some((p) => existsSync39(p)))
|
|
30896
30807
|
return { kind: "stale", found: 3 };
|
|
30897
30808
|
return { kind: "current", version: { layout: LAYOUT_VERSION, cli: "" }, inferred: true };
|
|
30898
30809
|
}
|
|
30899
|
-
if (
|
|
30810
|
+
if (existsSync39(legacy.configToml()))
|
|
30900
30811
|
return { kind: "stale", found: 2 };
|
|
30901
30812
|
const layoutOneMarkers = [
|
|
30902
30813
|
legacy.policyConfig(),
|
|
@@ -30907,7 +30818,7 @@ function detectLayout2() {
|
|
|
30907
30818
|
legacy.ingestCredentials(),
|
|
30908
30819
|
legacy.auditDashboard()
|
|
30909
30820
|
];
|
|
30910
|
-
return layoutOneMarkers.some((p) =>
|
|
30821
|
+
return layoutOneMarkers.some((p) => existsSync39(p)) ? { kind: "stale", found: 1 } : { kind: "absent" };
|
|
30911
30822
|
}
|
|
30912
30823
|
function readLegacyTomlVersion2(text) {
|
|
30913
30824
|
const layout = Number(/^\s*layout\s*=\s*(\d+)\s*$/m.exec(text)?.[1]);
|
|
@@ -30950,14 +30861,14 @@ var init_fp_home2 = () => {};
|
|
|
30950
30861
|
import {
|
|
30951
30862
|
chmodSync as chmodSync7,
|
|
30952
30863
|
copyFileSync as copyFileSync3,
|
|
30953
|
-
existsSync as
|
|
30954
|
-
mkdirSync as
|
|
30864
|
+
existsSync as existsSync40,
|
|
30865
|
+
mkdirSync as mkdirSync27,
|
|
30955
30866
|
readFileSync as readFileSync34,
|
|
30956
30867
|
renameSync as renameSync9,
|
|
30957
|
-
rmSync as
|
|
30958
|
-
writeFileSync as
|
|
30868
|
+
rmSync as rmSync15,
|
|
30869
|
+
writeFileSync as writeFileSync24
|
|
30959
30870
|
} from "node:fs";
|
|
30960
|
-
import { basename as basename7, dirname as dirname20, join as join37, resolve as
|
|
30871
|
+
import { basename as basename7, dirname as dirname20, join as join37, resolve as resolve27 } from "node:path";
|
|
30961
30872
|
function migrateToLayout42() {
|
|
30962
30873
|
const moves = [
|
|
30963
30874
|
{ from: legacy.authJson(), to: auditSessionFile() },
|
|
@@ -30973,13 +30884,13 @@ function migrateToLayout42() {
|
|
|
30973
30884
|
}
|
|
30974
30885
|
const migrated = [];
|
|
30975
30886
|
for (const { from, to } of moves) {
|
|
30976
|
-
if (!
|
|
30887
|
+
if (!existsSync40(from))
|
|
30977
30888
|
continue;
|
|
30978
|
-
if (
|
|
30979
|
-
|
|
30889
|
+
if (existsSync40(to)) {
|
|
30890
|
+
rmSync15(from, { force: true });
|
|
30980
30891
|
continue;
|
|
30981
30892
|
}
|
|
30982
|
-
|
|
30893
|
+
mkdirSync27(dirname20(to), { recursive: true });
|
|
30983
30894
|
try {
|
|
30984
30895
|
renameSync9(from, to);
|
|
30985
30896
|
} catch {
|
|
@@ -30987,16 +30898,16 @@ function migrateToLayout42() {
|
|
|
30987
30898
|
copyFileSync3(from, to);
|
|
30988
30899
|
} catch (err) {
|
|
30989
30900
|
try {
|
|
30990
|
-
|
|
30901
|
+
rmSync15(to, { force: true });
|
|
30991
30902
|
} catch {}
|
|
30992
30903
|
throw err;
|
|
30993
30904
|
}
|
|
30994
|
-
|
|
30905
|
+
rmSync15(from, { force: true });
|
|
30995
30906
|
}
|
|
30996
30907
|
migrated.push(`${basename7(from)} → audit/${basename7(to)}`);
|
|
30997
30908
|
}
|
|
30998
30909
|
for (const secret of [auditSessionFile()]) {
|
|
30999
|
-
if (!
|
|
30910
|
+
if (!existsSync40(secret))
|
|
31000
30911
|
continue;
|
|
31001
30912
|
try {
|
|
31002
30913
|
chmodSync7(secret, 384);
|
|
@@ -31030,9 +30941,9 @@ function readLedger2() {
|
|
|
31030
30941
|
}
|
|
31031
30942
|
function appendLedger2(entry) {
|
|
31032
30943
|
try {
|
|
31033
|
-
|
|
30944
|
+
mkdirSync27(migrationsDir(), { recursive: true });
|
|
31034
30945
|
const all = [...readLedger2(), entry];
|
|
31035
|
-
|
|
30946
|
+
writeFileSync24(migrationLedgerFile(), `${JSON.stringify(all, null, 2)}
|
|
31036
30947
|
`, "utf8");
|
|
31037
30948
|
} catch {}
|
|
31038
30949
|
}
|
|
@@ -31044,12 +30955,12 @@ function pruneMigratedCredentials2(from) {
|
|
|
31044
30955
|
for (let layout = from;layout < LAYOUT_VERSION; layout++) {
|
|
31045
30956
|
for (const { as, landsAt } of PRUNED_AFTER_SUCCESS2) {
|
|
31046
30957
|
try {
|
|
31047
|
-
if (!
|
|
30958
|
+
if (!existsSync40(landsAt()))
|
|
31048
30959
|
continue;
|
|
31049
|
-
const copy =
|
|
31050
|
-
if (!
|
|
30960
|
+
const copy = resolve27(migrationBackupDir(layout), as);
|
|
30961
|
+
if (!existsSync40(copy))
|
|
31051
30962
|
continue;
|
|
31052
|
-
|
|
30963
|
+
rmSync15(copy, { force: true });
|
|
31053
30964
|
pruned.push(as);
|
|
31054
30965
|
} catch {}
|
|
31055
30966
|
}
|
|
@@ -31060,7 +30971,7 @@ function filesToBackUp2() {
|
|
|
31060
30971
|
const seen = new Map;
|
|
31061
30972
|
for (const f of [...BACKED_UP2, ...BACKED_UP_LEGACY2]) {
|
|
31062
30973
|
const path = f.at();
|
|
31063
|
-
if (
|
|
30974
|
+
if (existsSync40(path))
|
|
31064
30975
|
seen.set(path, backupNameOf2(f));
|
|
31065
30976
|
}
|
|
31066
30977
|
return [...seen].map(([path, as]) => ({ path, as }));
|
|
@@ -31069,14 +30980,14 @@ function backupBeforeMigrating2(from) {
|
|
|
31069
30980
|
const dir = migrationBackupDir(from);
|
|
31070
30981
|
const saved = [];
|
|
31071
30982
|
try {
|
|
31072
|
-
|
|
31073
|
-
|
|
30983
|
+
rmSync15(dir, { recursive: true, force: true });
|
|
30984
|
+
mkdirSync27(dir, { recursive: true });
|
|
31074
30985
|
} catch {
|
|
31075
30986
|
return [];
|
|
31076
30987
|
}
|
|
31077
30988
|
for (const { path: source, as } of filesToBackUp2()) {
|
|
31078
30989
|
try {
|
|
31079
|
-
copyFileSync3(source,
|
|
30990
|
+
copyFileSync3(source, resolve27(dir, as));
|
|
31080
30991
|
saved.push(as);
|
|
31081
30992
|
} catch {}
|
|
31082
30993
|
}
|
|
@@ -31214,16 +31125,16 @@ var init_migrations2 = __esm(() => {
|
|
|
31214
31125
|
|
|
31215
31126
|
// src/hooks/daemon-service.ts
|
|
31216
31127
|
import {
|
|
31217
|
-
existsSync as
|
|
31218
|
-
mkdirSync as
|
|
31128
|
+
existsSync as existsSync41,
|
|
31129
|
+
mkdirSync as mkdirSync28,
|
|
31219
31130
|
mkdtempSync as mkdtempSync2,
|
|
31220
31131
|
readFileSync as readFileSync35,
|
|
31221
|
-
writeFileSync as
|
|
31132
|
+
writeFileSync as writeFileSync25,
|
|
31222
31133
|
unlinkSync as unlinkSync5,
|
|
31223
|
-
rmSync as
|
|
31134
|
+
rmSync as rmSync16
|
|
31224
31135
|
} from "node:fs";
|
|
31225
31136
|
import { homedir as homedir30, tmpdir as tmpdir3, userInfo as userInfo2 } from "node:os";
|
|
31226
|
-
import { resolve as
|
|
31137
|
+
import { resolve as resolve28 } from "node:path";
|
|
31227
31138
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
31228
31139
|
function isDaemonSupportedPlatform2() {
|
|
31229
31140
|
return process.platform === "linux" || process.platform === "darwin";
|
|
@@ -31239,13 +31150,13 @@ function resolveFailproofaidBinaryPath2() {
|
|
|
31239
31150
|
if (process.env.FAILPROOFAI_DAEMON_BINARY)
|
|
31240
31151
|
return process.env.FAILPROOFAI_DAEMON_BINARY;
|
|
31241
31152
|
const downloaded = installedBinaryPath();
|
|
31242
|
-
if (
|
|
31153
|
+
if (existsSync41(downloaded))
|
|
31243
31154
|
return downloaded;
|
|
31244
31155
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
31245
31156
|
if (packageRoot) {
|
|
31246
31157
|
for (const profile of ["release", "debug"]) {
|
|
31247
|
-
const candidate =
|
|
31248
|
-
if (
|
|
31158
|
+
const candidate = resolve28(packageRoot, "target", profile, "failproofaid");
|
|
31159
|
+
if (existsSync41(candidate))
|
|
31249
31160
|
return candidate;
|
|
31250
31161
|
}
|
|
31251
31162
|
}
|
|
@@ -31275,8 +31186,8 @@ function resolveWorkerCommand2() {
|
|
|
31275
31186
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
31276
31187
|
if (!packageRoot)
|
|
31277
31188
|
return null;
|
|
31278
|
-
const workerScript =
|
|
31279
|
-
if (!
|
|
31189
|
+
const workerScript = resolve28(packageRoot, "dist", "worker.mjs");
|
|
31190
|
+
if (!existsSync41(workerScript))
|
|
31280
31191
|
return null;
|
|
31281
31192
|
return `${shellQuote2(process.execPath)} ${shellQuote2(workerScript)}`;
|
|
31282
31193
|
}
|
|
@@ -31286,8 +31197,8 @@ function resolveCliCommand2() {
|
|
|
31286
31197
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
31287
31198
|
if (!packageRoot)
|
|
31288
31199
|
return null;
|
|
31289
|
-
const cliScript =
|
|
31290
|
-
if (!
|
|
31200
|
+
const cliScript = resolve28(packageRoot, "dist", "cli.mjs");
|
|
31201
|
+
if (!existsSync41(cliScript))
|
|
31291
31202
|
return null;
|
|
31292
31203
|
return `${shellQuote2(process.execPath)} ${shellQuote2(cliScript)}`;
|
|
31293
31204
|
}
|
|
@@ -31300,8 +31211,8 @@ function workerScriptPath2() {
|
|
|
31300
31211
|
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
31301
31212
|
if (!packageRoot)
|
|
31302
31213
|
return null;
|
|
31303
|
-
const workerScript =
|
|
31304
|
-
return
|
|
31214
|
+
const workerScript = resolve28(packageRoot, "dist", "worker.mjs");
|
|
31215
|
+
return existsSync41(workerScript) ? workerScript : null;
|
|
31305
31216
|
}
|
|
31306
31217
|
function assertUnitSafe2(value, field) {
|
|
31307
31218
|
if (UNIT_UNSAFE_RE2.test(value)) {
|
|
@@ -31327,10 +31238,10 @@ function systemdUnitDir2() {
|
|
|
31327
31238
|
return process.env.FAILPROOFAI_SYSTEMD_DIR || "/etc/systemd/system";
|
|
31328
31239
|
}
|
|
31329
31240
|
function systemdUnitPath2(user = serviceUser2()) {
|
|
31330
|
-
return
|
|
31241
|
+
return resolve28(systemdUnitDir2(), systemdUnitName2(user));
|
|
31331
31242
|
}
|
|
31332
31243
|
function legacySystemdUserUnitPath2() {
|
|
31333
|
-
return
|
|
31244
|
+
return resolve28(homedir30(), ".config", "systemd", "user", "failproofaid.service");
|
|
31334
31245
|
}
|
|
31335
31246
|
function launchdLabel2(user = serviceUser2()) {
|
|
31336
31247
|
return `ai.failproof.failproofaid.${user}`;
|
|
@@ -31339,7 +31250,7 @@ function launchdPlistPath2(user = serviceUser2()) {
|
|
|
31339
31250
|
return `/Library/LaunchDaemons/${launchdLabel2(user)}.plist`;
|
|
31340
31251
|
}
|
|
31341
31252
|
function legacyLaunchAgentPlistPath2() {
|
|
31342
|
-
return
|
|
31253
|
+
return resolve28(homedir30(), "Library", "LaunchAgents", "ai.failproof.failproofaid.plist");
|
|
31343
31254
|
}
|
|
31344
31255
|
function legacySharedLaunchDaemonPath2() {
|
|
31345
31256
|
return "/Library/LaunchDaemons/ai.failproof.failproofaid.plist";
|
|
@@ -31377,20 +31288,20 @@ function runPrivileged2(command, args) {
|
|
|
31377
31288
|
execFileSync4(cmd, argv, { stdio: "ignore", timeout: SERVICE_CMD_TIMEOUT_MS2 });
|
|
31378
31289
|
}
|
|
31379
31290
|
function writePrivilegedFile2(destination, contents, mode = "0644") {
|
|
31380
|
-
const stagingDir = mkdtempSync2(
|
|
31381
|
-
const staging =
|
|
31291
|
+
const stagingDir = mkdtempSync2(resolve28(tmpdir3(), "failproofaid-stage-"));
|
|
31292
|
+
const staging = resolve28(stagingDir, "service-definition");
|
|
31382
31293
|
try {
|
|
31383
|
-
|
|
31294
|
+
writeFileSync25(staging, contents, "utf8");
|
|
31384
31295
|
runPrivileged2("install", ["-m", mode, staging, destination]);
|
|
31385
31296
|
} finally {
|
|
31386
|
-
|
|
31297
|
+
rmSync16(stagingDir, { recursive: true, force: true });
|
|
31387
31298
|
}
|
|
31388
31299
|
}
|
|
31389
31300
|
function removeLegacyUserService2() {
|
|
31390
31301
|
try {
|
|
31391
31302
|
if (process.platform === "linux") {
|
|
31392
31303
|
const legacy = legacySystemdUserUnitPath2();
|
|
31393
|
-
if (!
|
|
31304
|
+
if (!existsSync41(legacy))
|
|
31394
31305
|
return;
|
|
31395
31306
|
try {
|
|
31396
31307
|
execFileSync4("systemctl", ["--user", "disable", "--now", "failproofaid.service"], {
|
|
@@ -31407,7 +31318,7 @@ function removeLegacyUserService2() {
|
|
|
31407
31318
|
} catch {}
|
|
31408
31319
|
} else {
|
|
31409
31320
|
const legacyAgent = legacyLaunchAgentPlistPath2();
|
|
31410
|
-
if (
|
|
31321
|
+
if (existsSync41(legacyAgent)) {
|
|
31411
31322
|
try {
|
|
31412
31323
|
execFileSync4("launchctl", ["unload", "-w", legacyAgent], {
|
|
31413
31324
|
stdio: "ignore",
|
|
@@ -31417,7 +31328,7 @@ function removeLegacyUserService2() {
|
|
|
31417
31328
|
unlinkSync5(legacyAgent);
|
|
31418
31329
|
}
|
|
31419
31330
|
const legacyDaemon = legacySharedLaunchDaemonPath2();
|
|
31420
|
-
if (
|
|
31331
|
+
if (existsSync41(legacyDaemon)) {
|
|
31421
31332
|
try {
|
|
31422
31333
|
runPrivileged2("launchctl", ["unload", "-w", legacyDaemon]);
|
|
31423
31334
|
} catch {}
|
|
@@ -31434,7 +31345,7 @@ function systemdUnitContents2(binaryPath, workerCmd, cliCmd = null) {
|
|
|
31434
31345
|
const user = assertUnitSafe2(serviceUser2(), "User");
|
|
31435
31346
|
assertUnitSafe2(binaryPath, "ExecStart");
|
|
31436
31347
|
assertUnitSafe2(homedir30(), "HOME");
|
|
31437
|
-
const conditionPaths = [binaryPath, workerScriptPath2()].filter((p) => typeof p === "string" &&
|
|
31348
|
+
const conditionPaths = [binaryPath, workerScriptPath2()].filter((p) => typeof p === "string" && existsSync41(p));
|
|
31438
31349
|
const conditionLines = conditionPaths.map((p) => `ConditionPathExists=${assertUnitSafe2(p, "ConditionPathExists")}
|
|
31439
31350
|
`).join("");
|
|
31440
31351
|
return `[Unit]
|
|
@@ -31492,9 +31403,9 @@ ${env.map(([key, value]) => ` <key>${key}</key>
|
|
|
31492
31403
|
<key>UserName</key>
|
|
31493
31404
|
<string>${escapeXml3(serviceUser2())}</string>
|
|
31494
31405
|
${envBlock} <key>StandardOutPath</key>
|
|
31495
|
-
<string>${escapeXml3(
|
|
31406
|
+
<string>${escapeXml3(resolve28(logDir, "failproofaid.log"))}</string>
|
|
31496
31407
|
<key>StandardErrorPath</key>
|
|
31497
|
-
<string>${escapeXml3(
|
|
31408
|
+
<string>${escapeXml3(resolve28(logDir, "failproofaid.err.log"))}</string>
|
|
31498
31409
|
</dict>
|
|
31499
31410
|
</plist>
|
|
31500
31411
|
`;
|
|
@@ -31540,7 +31451,7 @@ async function installDaemonService2() {
|
|
|
31540
31451
|
} else {
|
|
31541
31452
|
const plistPath = launchdPlistPath2();
|
|
31542
31453
|
const logDir = logsDir();
|
|
31543
|
-
|
|
31454
|
+
mkdirSync28(logDir, { recursive: true });
|
|
31544
31455
|
try {
|
|
31545
31456
|
runPrivileged2("launchctl", ["unload", plistPath]);
|
|
31546
31457
|
} catch {}
|
|
@@ -31639,7 +31550,7 @@ function daemonServiceStatus2() {
|
|
|
31639
31550
|
if (!isDaemonSupportedPlatform2())
|
|
31640
31551
|
return "unsupported-platform";
|
|
31641
31552
|
if (process.platform === "linux") {
|
|
31642
|
-
if (!
|
|
31553
|
+
if (!existsSync41(systemdUnitPath2()))
|
|
31643
31554
|
return "not-installed";
|
|
31644
31555
|
try {
|
|
31645
31556
|
const out = execFileSync4("systemctl", ["is-active", systemdUnitName2()], {
|
|
@@ -31652,7 +31563,7 @@ function daemonServiceStatus2() {
|
|
|
31652
31563
|
}
|
|
31653
31564
|
}
|
|
31654
31565
|
const plistPath = launchdPlistPath2();
|
|
31655
|
-
if (!
|
|
31566
|
+
if (!existsSync41(plistPath))
|
|
31656
31567
|
return "not-installed";
|
|
31657
31568
|
try {
|
|
31658
31569
|
const root = typeof process.getuid === "function" && process.getuid() === 0;
|
|
@@ -31682,7 +31593,7 @@ var init_daemon_service2 = __esm(() => {
|
|
|
31682
31593
|
});
|
|
31683
31594
|
|
|
31684
31595
|
// src/hooks/uninstall-cli.ts
|
|
31685
|
-
import { existsSync as
|
|
31596
|
+
import { existsSync as existsSync42, rmSync as rmSync17 } from "node:fs";
|
|
31686
31597
|
function survey(cwd) {
|
|
31687
31598
|
const clis = [];
|
|
31688
31599
|
for (const id of listInstallableIds()) {
|
|
@@ -31703,9 +31614,9 @@ function survey(cwd) {
|
|
|
31703
31614
|
return {
|
|
31704
31615
|
clis,
|
|
31705
31616
|
servicePath,
|
|
31706
|
-
serviceInstalled: !!servicePath &&
|
|
31617
|
+
serviceInstalled: !!servicePath && existsSync42(servicePath),
|
|
31707
31618
|
daemonConfigured,
|
|
31708
|
-
homeExists:
|
|
31619
|
+
homeExists: existsSync42(failproofaiHome())
|
|
31709
31620
|
};
|
|
31710
31621
|
}
|
|
31711
31622
|
async function runUninstallCommand(opts = {}) {
|
|
@@ -31803,7 +31714,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31803
31714
|
} catch {}
|
|
31804
31715
|
try {
|
|
31805
31716
|
await uninstallDaemonService();
|
|
31806
|
-
if (found.servicePath &&
|
|
31717
|
+
if (found.servicePath && existsSync42(found.servicePath)) {
|
|
31807
31718
|
failures.push(`the service at ${found.servicePath} is still there (most often: no sudo). ` + `Remove it with the commands below.`);
|
|
31808
31719
|
} else {
|
|
31809
31720
|
lines.push(`✓ stopped and removed the daemon service`);
|
|
@@ -31818,7 +31729,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31818
31729
|
}
|
|
31819
31730
|
if (opts.purge && found.homeExists) {
|
|
31820
31731
|
try {
|
|
31821
|
-
|
|
31732
|
+
rmSync17(failproofaiHome(), { recursive: true, force: true });
|
|
31822
31733
|
purged = true;
|
|
31823
31734
|
lines.push(`✓ deleted ${failproofaiHome()}`);
|
|
31824
31735
|
} catch (err) {
|
|
@@ -31829,7 +31740,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31829
31740
|
lines.push(``, `Not everything could be removed:`);
|
|
31830
31741
|
for (const f of failures)
|
|
31831
31742
|
lines.push(` ✗ ${f}`);
|
|
31832
|
-
if (found.servicePath &&
|
|
31743
|
+
if (found.servicePath && existsSync42(found.servicePath)) {
|
|
31833
31744
|
lines.push(``, `To remove the service by hand:`, ...manualServiceRemoval(found.servicePath), ``, `(\`${daemonStatusCommand()}\` shows its current state.)`);
|
|
31834
31745
|
}
|
|
31835
31746
|
return { exitCode: 1, lines, planLines, purged };
|
|
@@ -31864,8 +31775,8 @@ var init_uninstall_cli = __esm(() => {
|
|
|
31864
31775
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
31865
31776
|
import { homedir as homedir31, tmpdir as tmpdir4 } from "node:os";
|
|
31866
31777
|
import { createHash as createHash9 } from "node:crypto";
|
|
31867
|
-
import { copyFileSync as copyFileSync4, existsSync as
|
|
31868
|
-
import { basename as basename8, dirname as dirname21, isAbsolute as isAbsolute4, join as join38, relative as relative5, resolve as
|
|
31778
|
+
import { copyFileSync as copyFileSync4, existsSync as existsSync43, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync3, readFileSync as readFileSync36, readdirSync as readdirSync21, realpathSync as realpathSync3, rmSync as rmSync18, statSync as statSync25, writeFileSync as writeFileSync26 } from "node:fs";
|
|
31779
|
+
import { basename as basename8, dirname as dirname21, isAbsolute as isAbsolute4, join as join38, relative as relative5, resolve as resolve29, sep as sep6 } from "node:path";
|
|
31869
31780
|
function parseList(rest, flag) {
|
|
31870
31781
|
const idx = rest.findIndex((a) => a === flag || a.startsWith(`${flag}=`));
|
|
31871
31782
|
if (idx === -1)
|
|
@@ -31965,7 +31876,7 @@ async function build(rest) {
|
|
|
31965
31876
|
const version = flag("version");
|
|
31966
31877
|
const commit = flag("commit");
|
|
31967
31878
|
const effect = flag("effect") ?? "enforce";
|
|
31968
|
-
const outDir =
|
|
31879
|
+
const outDir = resolve29(flag("out") ?? "dist-pack");
|
|
31969
31880
|
if (!entry || !id || !version) {
|
|
31970
31881
|
return fail2([
|
|
31971
31882
|
"Usage: failproofai publish <entry.mjs> --repo <owner>/<repo> --version <version>",
|
|
@@ -31978,8 +31889,8 @@ async function build(rest) {
|
|
|
31978
31889
|
} catch (err) {
|
|
31979
31890
|
return fail2([err instanceof Error ? err.message : String(err)]);
|
|
31980
31891
|
}
|
|
31981
|
-
const entryPath =
|
|
31982
|
-
if (!
|
|
31892
|
+
const entryPath = resolve29(entry);
|
|
31893
|
+
if (!existsSync43(entryPath))
|
|
31983
31894
|
return fail2([`No such file: ${entryPath}`]);
|
|
31984
31895
|
const source = readFileSync36(entryPath, "utf8");
|
|
31985
31896
|
const localImport = /(?:^|\n)\s*(?:import|export)[^;\n]*from\s+["'](\.[^"']*)["']/.exec(source);
|
|
@@ -32037,13 +31948,13 @@ async function build(rest) {
|
|
|
32037
31948
|
policies
|
|
32038
31949
|
}, null, 2) + `
|
|
32039
31950
|
`;
|
|
32040
|
-
|
|
32041
|
-
const manifestPath =
|
|
32042
|
-
const entryOut =
|
|
32043
|
-
|
|
31951
|
+
mkdirSync29(outDir, { recursive: true });
|
|
31952
|
+
const manifestPath = resolve29(outDir, PACK_MANIFEST_ASSET);
|
|
31953
|
+
const entryOut = resolve29(outDir, PACK_ENTRY_ASSET);
|
|
31954
|
+
writeFileSync26(manifestPath, manifest, "utf8");
|
|
32044
31955
|
copyFileSync4(entryPath, entryOut);
|
|
32045
31956
|
const sha = (bytes) => createHash9("sha256").update(bytes).digest("hex");
|
|
32046
|
-
|
|
31957
|
+
writeFileSync26(resolve29(outDir, PACK_CHECKSUMS_ASSET), `${sha(manifest)} ${PACK_MANIFEST_ASSET}
|
|
32047
31958
|
${sha(readFileSync36(entryOut))} ${PACK_ENTRY_ASSET}
|
|
32048
31959
|
`, "utf8");
|
|
32049
31960
|
const on = policies.filter((p) => p.defaultEnabled).length;
|
|
@@ -32173,12 +32084,12 @@ async function scaffold(target) {
|
|
|
32173
32084
|
return ok2(["Nothing written."]);
|
|
32174
32085
|
chosen = answer.trim();
|
|
32175
32086
|
}
|
|
32176
|
-
const path =
|
|
32177
|
-
if (
|
|
32087
|
+
const path = resolve29(withPolicyExtension(chosen ?? "my-policies"));
|
|
32088
|
+
if (existsSync43(path)) {
|
|
32178
32089
|
return fail2([`${path} already exists — name a different file, or edit that one.`]);
|
|
32179
32090
|
}
|
|
32180
|
-
|
|
32181
|
-
|
|
32091
|
+
mkdirSync29(resolve29(path, ".."), { recursive: true });
|
|
32092
|
+
writeFileSync26(path, `import { customPolicies, allow, deny } from "failproofai";
|
|
32182
32093
|
|
|
32183
32094
|
// One file, no relative imports: only this entry is digest-pinned, so a pack
|
|
32184
32095
|
// that imported siblings could not honestly claim to be verified.
|
|
@@ -32215,7 +32126,7 @@ customPolicies.add({
|
|
|
32215
32126
|
function inferRepo(entryPath) {
|
|
32216
32127
|
try {
|
|
32217
32128
|
const url = execFileSync5("git", ["remote", "get-url", "origin"], {
|
|
32218
|
-
cwd:
|
|
32129
|
+
cwd: resolve29(entryPath, ".."),
|
|
32219
32130
|
encoding: "utf8",
|
|
32220
32131
|
stdio: ["ignore", "pipe", "ignore"],
|
|
32221
32132
|
timeout: 5000
|
|
@@ -32227,7 +32138,7 @@ function inferRepo(entryPath) {
|
|
|
32227
32138
|
}
|
|
32228
32139
|
}
|
|
32229
32140
|
function inferCommit(entryPath, outDir, sources) {
|
|
32230
|
-
const cwd =
|
|
32141
|
+
const cwd = resolve29(entryPath, "..");
|
|
32231
32142
|
const raw = (args) => {
|
|
32232
32143
|
try {
|
|
32233
32144
|
return execFileSync5("git", args, {
|
|
@@ -32282,9 +32193,9 @@ function realOrSelf(path) {
|
|
|
32282
32193
|
}
|
|
32283
32194
|
}
|
|
32284
32195
|
function sourcesInHead(git, raw, sources) {
|
|
32285
|
-
const paths = sources.map((f) => realOrSelf(
|
|
32196
|
+
const paths = sources.map((f) => realOrSelf(resolve29(f)));
|
|
32286
32197
|
const shown = git(["rev-parse", "--show-toplevel"]);
|
|
32287
|
-
const top = shown === null ? null : realOrSelf(
|
|
32198
|
+
const top = shown === null ? null : realOrSelf(resolve29(shown));
|
|
32288
32199
|
const missing = [];
|
|
32289
32200
|
for (const path of paths) {
|
|
32290
32201
|
const rel = top ? relative5(top, path) : null;
|
|
@@ -32308,7 +32219,7 @@ function sourcesInHead(git, raw, sources) {
|
|
|
32308
32219
|
]);
|
|
32309
32220
|
if (status === null)
|
|
32310
32221
|
return { ok: false, offending: paths, why: "modified" };
|
|
32311
|
-
const dirty = porcelainEntries(status).flatMap((entry) => [entry.path, entry.from].filter(Boolean).map((path) =>
|
|
32222
|
+
const dirty = porcelainEntries(status).flatMap((entry) => [entry.path, entry.from].filter(Boolean).map((path) => resolve29(top ?? ".", path)));
|
|
32312
32223
|
if (dirty.length > 0)
|
|
32313
32224
|
return { ok: false, offending: dirty, why: "modified" };
|
|
32314
32225
|
return { ok: true };
|
|
@@ -32316,19 +32227,19 @@ function sourcesInHead(git, raw, sources) {
|
|
|
32316
32227
|
function skipOutDir(git, entryPath, outDir) {
|
|
32317
32228
|
if (!outDir)
|
|
32318
32229
|
return [];
|
|
32319
|
-
const out =
|
|
32320
|
-
if (
|
|
32230
|
+
const out = resolve29(outDir);
|
|
32231
|
+
if (resolve29(entryPath).startsWith(out + sep6))
|
|
32321
32232
|
return [];
|
|
32322
32233
|
const top = git(["rev-parse", "--show-toplevel"]);
|
|
32323
32234
|
if (!top)
|
|
32324
32235
|
return [];
|
|
32325
|
-
const rel = relative5(
|
|
32236
|
+
const rel = relative5(resolve29(top), out);
|
|
32326
32237
|
if (!rel || rel.startsWith("..") || isAbsolute4(rel))
|
|
32327
32238
|
return [];
|
|
32328
32239
|
return ["--", ":(top)", `:(exclude,literal,top)${rel.split(sep6).join("/")}`];
|
|
32329
32240
|
}
|
|
32330
32241
|
function inferTaggedVersion(entryPath, sources) {
|
|
32331
|
-
const cwd =
|
|
32242
|
+
const cwd = resolve29(entryPath, "..");
|
|
32332
32243
|
const raw = (args) => {
|
|
32333
32244
|
try {
|
|
32334
32245
|
return execFileSync5("git", args, {
|
|
@@ -32358,7 +32269,7 @@ function inferTaggedVersion(entryPath, sources) {
|
|
|
32358
32269
|
function findEntry(dir) {
|
|
32359
32270
|
let names;
|
|
32360
32271
|
try {
|
|
32361
|
-
names =
|
|
32272
|
+
names = readdirSync21(dir);
|
|
32362
32273
|
} catch {
|
|
32363
32274
|
return [];
|
|
32364
32275
|
}
|
|
@@ -32366,9 +32277,9 @@ function findEntry(dir) {
|
|
|
32366
32277
|
for (const name of names) {
|
|
32367
32278
|
if (!/\.(mjs|js|ts)$/.test(name))
|
|
32368
32279
|
continue;
|
|
32369
|
-
const full =
|
|
32280
|
+
const full = resolve29(dir, name);
|
|
32370
32281
|
try {
|
|
32371
|
-
if (
|
|
32282
|
+
if (statSync25(full).size > 512 * 1024)
|
|
32372
32283
|
continue;
|
|
32373
32284
|
const text = readFileSync36(full, "utf8");
|
|
32374
32285
|
if (/from\s+["']failproofai["']/.test(text) && /customPolicies\s*\.\s*add\s*\(/.test(text)) {
|
|
@@ -32381,13 +32292,13 @@ function findEntry(dir) {
|
|
|
32381
32292
|
return found.sort();
|
|
32382
32293
|
}
|
|
32383
32294
|
function withLocalImports(sources) {
|
|
32384
|
-
const seen = new Set(sources.map((f) =>
|
|
32295
|
+
const seen = new Set(sources.map((f) => resolve29(f)));
|
|
32385
32296
|
const queue = [...seen];
|
|
32386
32297
|
while (queue.length > 0 && seen.size < 500) {
|
|
32387
32298
|
const file = queue.shift();
|
|
32388
32299
|
let text;
|
|
32389
32300
|
try {
|
|
32390
|
-
if (
|
|
32301
|
+
if (statSync25(file).size > 512 * 1024)
|
|
32391
32302
|
continue;
|
|
32392
32303
|
text = readFileSync36(file, "utf8");
|
|
32393
32304
|
} catch {
|
|
@@ -32395,13 +32306,13 @@ function withLocalImports(sources) {
|
|
|
32395
32306
|
}
|
|
32396
32307
|
for (const re of LOCAL_IMPORT_RES) {
|
|
32397
32308
|
for (const match of text.matchAll(re)) {
|
|
32398
|
-
const base =
|
|
32309
|
+
const base = resolve29(dirname21(file), match[1]);
|
|
32399
32310
|
for (const ext of LOCAL_IMPORT_EXTENSIONS) {
|
|
32400
32311
|
const candidate = base + ext;
|
|
32401
32312
|
if (seen.has(candidate))
|
|
32402
32313
|
break;
|
|
32403
32314
|
try {
|
|
32404
|
-
if (!
|
|
32315
|
+
if (!statSync25(candidate).isFile())
|
|
32405
32316
|
continue;
|
|
32406
32317
|
} catch {
|
|
32407
32318
|
continue;
|
|
@@ -32416,7 +32327,7 @@ function withLocalImports(sources) {
|
|
|
32416
32327
|
return [...seen];
|
|
32417
32328
|
}
|
|
32418
32329
|
function settleGitState(entryPath, provenance, packFiles, id, outDir) {
|
|
32419
|
-
const cwd =
|
|
32330
|
+
const cwd = resolve29(entryPath, "..");
|
|
32420
32331
|
const raw = (args) => {
|
|
32421
32332
|
try {
|
|
32422
32333
|
return execFileSync5("git", args, {
|
|
@@ -32491,11 +32402,11 @@ function settleGitState(entryPath, provenance, packFiles, id, outDir) {
|
|
|
32491
32402
|
if (root === null || status === null)
|
|
32492
32403
|
return null;
|
|
32493
32404
|
const entries = porcelainEntries(status);
|
|
32494
|
-
const dirty = entries.map((entry) =>
|
|
32495
|
-
const renamedFrom = entries.filter((entry) => entry.from).map((entry) =>
|
|
32405
|
+
const dirty = entries.map((entry) => resolve29(root, entry.path));
|
|
32406
|
+
const renamedFrom = entries.filter((entry) => entry.from).map((entry) => resolve29(root, entry.from));
|
|
32496
32407
|
if (dirty.length === 0)
|
|
32497
32408
|
return null;
|
|
32498
|
-
const mine = new Set(packFiles.map((f) =>
|
|
32409
|
+
const mine = new Set(packFiles.map((f) => resolve29(f)));
|
|
32499
32410
|
const foreign = dirty.filter((path) => !mine.has(path));
|
|
32500
32411
|
const toStage = [...dirty, ...renamedFrom];
|
|
32501
32412
|
if (foreign.length > 0) {
|
|
@@ -32628,7 +32539,7 @@ function pushExistingHistory(dir, owner, name, token) {
|
|
|
32628
32539
|
return false;
|
|
32629
32540
|
const askpass = join38(mkdtempSync3(join38(tmpdir4(), "fpai-askpass-")), "askpass.sh");
|
|
32630
32541
|
try {
|
|
32631
|
-
|
|
32542
|
+
writeFileSync26(askpass, `#!/bin/sh
|
|
32632
32543
|
case "$1" in
|
|
32633
32544
|
*Username*) echo x-access-token ;;
|
|
32634
32545
|
*) echo "$FPAI_GH_TOKEN" ;;
|
|
@@ -32648,7 +32559,7 @@ esac
|
|
|
32648
32559
|
return true;
|
|
32649
32560
|
} finally {
|
|
32650
32561
|
try {
|
|
32651
|
-
|
|
32562
|
+
rmSync18(dirname21(askpass), { recursive: true, force: true });
|
|
32652
32563
|
} catch {}
|
|
32653
32564
|
}
|
|
32654
32565
|
}
|
|
@@ -32672,8 +32583,8 @@ failproofai policies add ${owner}/${name}
|
|
|
32672
32583
|
function findBun() {
|
|
32673
32584
|
const candidates = [
|
|
32674
32585
|
"bun",
|
|
32675
|
-
process.env.BUN_INSTALL ?
|
|
32676
|
-
|
|
32586
|
+
process.env.BUN_INSTALL ? resolve29(process.env.BUN_INSTALL, "bin", "bun") : null,
|
|
32587
|
+
resolve29(homedir31(), ".bun", "bin", "bun"),
|
|
32677
32588
|
"/opt/homebrew/bin/bun",
|
|
32678
32589
|
"/usr/local/bin/bun"
|
|
32679
32590
|
].filter((c) => c !== null);
|
|
@@ -32699,12 +32610,12 @@ function bundleEntry(sources, outDir) {
|
|
|
32699
32610
|
]
|
|
32700
32611
|
};
|
|
32701
32612
|
}
|
|
32702
|
-
|
|
32703
|
-
const entry =
|
|
32704
|
-
|
|
32613
|
+
mkdirSync29(outDir, { recursive: true });
|
|
32614
|
+
const entry = resolve29(outDir, ".entry.generated.mjs");
|
|
32615
|
+
writeFileSync26(entry, sources.map((f) => `import ${JSON.stringify(f.startsWith("/") ? f : resolve29(f))};`).join(`
|
|
32705
32616
|
`) + `
|
|
32706
32617
|
`, "utf8");
|
|
32707
|
-
const bundled =
|
|
32618
|
+
const bundled = resolve29(outDir, ".bundled.mjs");
|
|
32708
32619
|
try {
|
|
32709
32620
|
execFileSync5(bun, [
|
|
32710
32621
|
"build",
|
|
@@ -32822,7 +32733,7 @@ async function publish(rest) {
|
|
|
32822
32733
|
`);
|
|
32823
32734
|
const token = githubToken();
|
|
32824
32735
|
const login = token ? await credentialLogin(token) : null;
|
|
32825
|
-
const folder = basename8(
|
|
32736
|
+
const folder = basename8(resolve29(entry, ".."));
|
|
32826
32737
|
const answered = await askWhereToPublish(`${login ?? "your-account"}/${folder}`, { stdin: process.stdin, stdout: process.stdout });
|
|
32827
32738
|
if (answered === null)
|
|
32828
32739
|
return ok2(["Nothing was published."]);
|
|
@@ -32833,7 +32744,7 @@ async function publish(rest) {
|
|
|
32833
32744
|
let versionFromSha = false;
|
|
32834
32745
|
const dryRun = rest.includes("--dry-run") || !repo;
|
|
32835
32746
|
const allowPrivate = rest.includes("--allow-private");
|
|
32836
|
-
const id = flag("id") ?? repo ?? (dryRun && entry ? `local/${basename8(
|
|
32747
|
+
const id = flag("id") ?? repo ?? (dryRun && entry ? `local/${basename8(resolve29(entry, ".."))}` : undefined);
|
|
32837
32748
|
const [owner, name] = (repo ?? "/").split("/");
|
|
32838
32749
|
if (repo && (!owner || !name || repo.split("/").length !== 2)) {
|
|
32839
32750
|
return fail2([`--repo must be <owner>/<repo>, got ${JSON.stringify(repo)}`]);
|
|
@@ -32852,7 +32763,7 @@ async function publish(rest) {
|
|
|
32852
32763
|
"With no --repo it writes the three release assets and stops."
|
|
32853
32764
|
]);
|
|
32854
32765
|
}
|
|
32855
|
-
const outDirEarly =
|
|
32766
|
+
const outDirEarly = resolve29(flag("out") ?? "dist-pack");
|
|
32856
32767
|
let provenance = entry ? inferCommit(entry, outDirEarly, bundledSources) : null;
|
|
32857
32768
|
const gitLines = [];
|
|
32858
32769
|
if (!version && entry && interactive) {
|
|
@@ -32892,7 +32803,7 @@ async function publish(rest) {
|
|
|
32892
32803
|
"It needs write access to releases on that repository, and nothing else."
|
|
32893
32804
|
]);
|
|
32894
32805
|
}
|
|
32895
|
-
const ensured = await ensureRepo(owner, name, id, token,
|
|
32806
|
+
const ensured = await ensureRepo(owner, name, id, token, resolve29(entry, ".."));
|
|
32896
32807
|
if ("error" in ensured)
|
|
32897
32808
|
return fail2(ensured.error);
|
|
32898
32809
|
created = ensured.created;
|
|
@@ -32991,7 +32902,7 @@ async function publish(rest) {
|
|
|
32991
32902
|
if (prior) {
|
|
32992
32903
|
await gh(`${GITHUB_API2}/repos/${owner}/${name}/releases/assets/${prior.id}`, auth, { method: "DELETE" });
|
|
32993
32904
|
}
|
|
32994
|
-
const bytes = readFileSync36(
|
|
32905
|
+
const bytes = readFileSync36(resolve29(outDir, asset));
|
|
32995
32906
|
const upload = await gh(`${GITHUB_UPLOADS2}/repos/${owner}/${name}/releases/${releaseId}/assets?name=${encodeURIComponent(asset)}`, auth, {
|
|
32996
32907
|
method: "POST",
|
|
32997
32908
|
contentType: asset.endsWith(".json") ? "application/json" : "application/octet-stream",
|
|
@@ -33672,8 +33583,8 @@ var init_install_prompt = __esm(() => {
|
|
|
33672
33583
|
|
|
33673
33584
|
// src/hooks/manager.ts
|
|
33674
33585
|
import { execSync as execSync7 } from "node:child_process";
|
|
33675
|
-
import { existsSync as
|
|
33676
|
-
import { resolve as
|
|
33586
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
33587
|
+
import { resolve as resolve30, basename as basename9 } from "node:path";
|
|
33677
33588
|
import { platform as platform4, arch as arch4, release as release3, hostname as hostname6 } from "node:os";
|
|
33678
33589
|
function getSettingsPath2(scope, cwd) {
|
|
33679
33590
|
return claudeCode.getSettingsPath(scope, cwd);
|
|
@@ -33892,9 +33803,9 @@ async function installHooksImpl2(policyNames, scope = "user", cwd, includeBeta =
|
|
|
33892
33803
|
delete configToWrite.customPoliciesPath;
|
|
33893
33804
|
delete configToWrite.customPoliciesPaths;
|
|
33894
33805
|
} else if (customPoliciesPath && (typeof customPoliciesPath === "string" || customPoliciesPath.length > 0)) {
|
|
33895
|
-
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path) =>
|
|
33896
|
-
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path) =>
|
|
33897
|
-
if (
|
|
33806
|
+
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path) => resolve30(path));
|
|
33807
|
+
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path) => resolve30(path)).filter((path) => {
|
|
33808
|
+
if (existsSync44(path))
|
|
33898
33809
|
return true;
|
|
33899
33810
|
console.log(`Dropping custom policies path (file no longer exists): ${path}`);
|
|
33900
33811
|
return false;
|
|
@@ -34117,7 +34028,7 @@ async function removeHooks2(policyNames, scope = "user", cwd, opts) {
|
|
|
34117
34028
|
const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
|
|
34118
34029
|
for (const s of scopesToRemove) {
|
|
34119
34030
|
const settingsPaths = settingsPathsFor(integration, s, cwd);
|
|
34120
|
-
const existing = settingsPaths.filter((p) =>
|
|
34031
|
+
const existing = settingsPaths.filter((p) => existsSync44(p));
|
|
34121
34032
|
if (existing.length === 0) {
|
|
34122
34033
|
if (scope !== "all" && selectedClis.length === 1) {
|
|
34123
34034
|
console.log("No settings file found. Nothing to remove.");
|
|
@@ -34261,9 +34172,9 @@ async function listHooks(cwd) {
|
|
|
34261
34172
|
if (explicitPaths.length > 0) {
|
|
34262
34173
|
groups.push(rule("Custom Policies", opts));
|
|
34263
34174
|
for (const path of explicitPaths) {
|
|
34264
|
-
const absPath =
|
|
34175
|
+
const absPath = resolve30(findProjectConfigDir(cwd ?? process.cwd()), path);
|
|
34265
34176
|
groups.push(note(absPath, opts));
|
|
34266
|
-
if (!
|
|
34177
|
+
if (!existsSync44(absPath)) {
|
|
34267
34178
|
groups.push(warning([`file not found: ${absPath}`], opts));
|
|
34268
34179
|
continue;
|
|
34269
34180
|
}
|
|
@@ -34283,7 +34194,7 @@ async function listHooks(cwd) {
|
|
|
34283
34194
|
}
|
|
34284
34195
|
}
|
|
34285
34196
|
const base = findProjectConfigDir(cwd ?? process.cwd());
|
|
34286
|
-
const projectDir =
|
|
34197
|
+
const projectDir = resolve30(base, ".failproofai", "policies");
|
|
34287
34198
|
const userDir = customPoliciesDir();
|
|
34288
34199
|
const sameDir = userDir === projectDir;
|
|
34289
34200
|
const conventionDirs = [
|
|
@@ -34589,21 +34500,20 @@ async function runScheduleOn(daysArg, emailArg) {
|
|
|
34589
34500
|
if (bad)
|
|
34590
34501
|
throw new ScheduleCliError(bad);
|
|
34591
34502
|
}
|
|
34592
|
-
const { user, prompted }
|
|
34503
|
+
const signedIn = emailArg === undefined ? { user: readAuth()?.user ?? null, prompted: false } : await ensureSignedIn(emailArg);
|
|
34593
34504
|
const next = updateConfig({
|
|
34594
34505
|
audit: {
|
|
34595
34506
|
auto: true,
|
|
34596
|
-
reportsConsentedAt: Date.now(),
|
|
34597
34507
|
...days !== undefined ? { intervalDays: days } : {}
|
|
34598
34508
|
}
|
|
34599
34509
|
});
|
|
34600
34510
|
const interval = next.audit.intervalDays;
|
|
34601
34511
|
const summary = [
|
|
34602
|
-
`every ${interval} day${interval === 1 ? "" : "s"} ·
|
|
34603
|
-
|
|
34604
|
-
"
|
|
34512
|
+
`every ${interval} day${interval === 1 ? "" : "s"} · desktop notification on leaks`,
|
|
34513
|
+
signedIn.user ? `masked leak alerts also go to ${signedIn.user.email}` : "email is optional · add it with --email you@example.com",
|
|
34514
|
+
"email contains only the most recent masked credential exposure"
|
|
34605
34515
|
];
|
|
34606
|
-
if (prompted) {
|
|
34516
|
+
if (signedIn.prompted) {
|
|
34607
34517
|
step("scheduled audits are on", summary);
|
|
34608
34518
|
} else {
|
|
34609
34519
|
process.stdout.write(`
|
|
@@ -34612,7 +34522,7 @@ ${green("✓")} ${bold("scheduled audits are on")}
|
|
|
34612
34522
|
`).join(""));
|
|
34613
34523
|
}
|
|
34614
34524
|
warnIfDaemonWontRun();
|
|
34615
|
-
if (prompted) {
|
|
34525
|
+
if (signedIn.prompted) {
|
|
34616
34526
|
outro("failproofai audit --status · when the next scan is due");
|
|
34617
34527
|
} else {
|
|
34618
34528
|
process.stdout.write(dim(`
|
|
@@ -34664,12 +34574,7 @@ function runScheduleStatus() {
|
|
|
34664
34574
|
]);
|
|
34665
34575
|
detail.push(["reports to", live ? live.user.email : dim("— signed out")]);
|
|
34666
34576
|
if (on && !live) {
|
|
34667
|
-
detail.push(["", pink("scans continue;
|
|
34668
|
-
} else if (on && config.audit.reportsConsentedAt === undefined) {
|
|
34669
|
-
detail.push([
|
|
34670
|
-
"",
|
|
34671
|
-
pink("scans continue; digests need a fresh opt-in — run `--schedule` to turn them on")
|
|
34672
|
-
]);
|
|
34577
|
+
detail.push(["", pink("scans and desktop alerts continue; email alerts are paused")]);
|
|
34673
34578
|
}
|
|
34674
34579
|
detail.push(["daemon", describeDaemon(daemon)]);
|
|
34675
34580
|
if (sched?.nextDueAtMs != null && on) {
|
|
@@ -34784,14 +34689,14 @@ var init_schedule_cli = __esm(() => {
|
|
|
34784
34689
|
});
|
|
34785
34690
|
|
|
34786
34691
|
// scripts/parse-script-args.ts
|
|
34787
|
-
import { resolve as
|
|
34692
|
+
import { resolve as resolve31 } from "path";
|
|
34788
34693
|
function parseStringFlag(flagName, errorLabel, inlineValue, args, index, options) {
|
|
34789
34694
|
const raw = inlineValue ?? args[index + 1];
|
|
34790
34695
|
if (raw === undefined || inlineValue === null && raw.startsWith("-")) {
|
|
34791
34696
|
console.error(`Error: ${flagName} requires ${errorLabel}`);
|
|
34792
34697
|
process.exit(1);
|
|
34793
34698
|
}
|
|
34794
|
-
const value = options?.resolve ?
|
|
34699
|
+
const value = options?.resolve ? resolve31(raw) : raw;
|
|
34795
34700
|
return { value, spliceCount: inlineValue !== null ? 1 : 2 };
|
|
34796
34701
|
}
|
|
34797
34702
|
function parseScriptArgs(argv) {
|
|
@@ -34847,19 +34752,19 @@ function parseScriptArgs(argv) {
|
|
|
34847
34752
|
var init_parse_script_args = () => {};
|
|
34848
34753
|
|
|
34849
34754
|
// scripts/install-diagnosis.mjs
|
|
34850
|
-
import { existsSync as
|
|
34851
|
-
import { dirname as dirname22, resolve as
|
|
34755
|
+
import { existsSync as existsSync45, readFileSync as readFileSync38, realpathSync as realpathSync4 } from "node:fs";
|
|
34756
|
+
import { dirname as dirname22, resolve as resolve32 } from "node:path";
|
|
34852
34757
|
import { homedir as homedir32, platform as platform5 } from "node:os";
|
|
34853
34758
|
import { spawnSync } from "node:child_process";
|
|
34854
34759
|
function findPackageRoot(start) {
|
|
34855
34760
|
try {
|
|
34856
34761
|
let dir = realpathSync4(start);
|
|
34857
|
-
if (
|
|
34762
|
+
if (existsSync45(dir) && !existsSync45(resolve32(dir, "package.json"))) {
|
|
34858
34763
|
dir = dirname22(dir);
|
|
34859
34764
|
}
|
|
34860
34765
|
while (true) {
|
|
34861
|
-
const pkgPath =
|
|
34862
|
-
if (
|
|
34766
|
+
const pkgPath = resolve32(dir, "package.json");
|
|
34767
|
+
if (existsSync45(pkgPath)) {
|
|
34863
34768
|
try {
|
|
34864
34769
|
const pkg = JSON.parse(readFileSync38(pkgPath, "utf8"));
|
|
34865
34770
|
if (pkg.name === PKG_NAME)
|
|
@@ -34879,7 +34784,7 @@ function readPackageVersion(packageRoot) {
|
|
|
34879
34784
|
if (!packageRoot)
|
|
34880
34785
|
return null;
|
|
34881
34786
|
try {
|
|
34882
|
-
const pkg = JSON.parse(readFileSync38(
|
|
34787
|
+
const pkg = JSON.parse(readFileSync38(resolve32(packageRoot, "package.json"), "utf8"));
|
|
34883
34788
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
34884
34789
|
} catch {
|
|
34885
34790
|
return null;
|
|
@@ -34905,16 +34810,16 @@ function locateNpmGlobal() {
|
|
|
34905
34810
|
const root = (res.stdout || "").trim();
|
|
34906
34811
|
if (!root)
|
|
34907
34812
|
return null;
|
|
34908
|
-
const candidate =
|
|
34909
|
-
return
|
|
34813
|
+
const candidate = resolve32(root, PKG_NAME);
|
|
34814
|
+
return existsSync45(resolve32(candidate, "package.json")) ? candidate : null;
|
|
34910
34815
|
} catch {
|
|
34911
34816
|
return null;
|
|
34912
34817
|
}
|
|
34913
34818
|
}
|
|
34914
34819
|
function locateBunGlobal() {
|
|
34915
34820
|
try {
|
|
34916
|
-
const candidate =
|
|
34917
|
-
return
|
|
34821
|
+
const candidate = resolve32(homedir32(), ".bun", "install", "global", "node_modules", PKG_NAME);
|
|
34822
|
+
return existsSync45(resolve32(candidate, "package.json")) ? candidate : null;
|
|
34918
34823
|
} catch {
|
|
34919
34824
|
return null;
|
|
34920
34825
|
}
|
|
@@ -34922,8 +34827,8 @@ function locateBunGlobal() {
|
|
|
34922
34827
|
function buildRecommendation(pathFirstBin) {
|
|
34923
34828
|
if (!pathFirstBin)
|
|
34924
34829
|
return null;
|
|
34925
|
-
const bunBinPrefix =
|
|
34926
|
-
const bunGlobalPrefix =
|
|
34830
|
+
const bunBinPrefix = resolve32(homedir32(), ".bun", "bin") + "/";
|
|
34831
|
+
const bunGlobalPrefix = resolve32(homedir32(), ".bun", "install", "global") + "/";
|
|
34927
34832
|
const isBun = pathFirstBin.startsWith(bunBinPrefix) || pathFirstBin.startsWith(bunGlobalPrefix);
|
|
34928
34833
|
if (isBun) {
|
|
34929
34834
|
return `rm -f ~/.bun/bin/${PKG_NAME} && rm -rf ~/.bun/install/global/node_modules/${PKG_NAME}`;
|
|
@@ -35017,8 +34922,8 @@ var init_dashboard_host = __esm(() => {
|
|
|
35017
34922
|
|
|
35018
34923
|
// scripts/launch.ts
|
|
35019
34924
|
import { spawn as spawn2 } from "child_process";
|
|
35020
|
-
import { realpathSync as realpathSync5, existsSync as
|
|
35021
|
-
import { resolve as
|
|
34925
|
+
import { realpathSync as realpathSync5, existsSync as existsSync46 } from "node:fs";
|
|
34926
|
+
import { resolve as resolve33, dirname as dirname23 } from "node:path";
|
|
35022
34927
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
35023
34928
|
import { createInterface } from "node:readline";
|
|
35024
34929
|
function launch(mode) {
|
|
@@ -35042,9 +34947,9 @@ function launch(mode) {
|
|
|
35042
34947
|
process.env.PORT = port;
|
|
35043
34948
|
process.env.HOSTNAME = bindHost;
|
|
35044
34949
|
cmd = "node";
|
|
35045
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ??
|
|
35046
|
-
const serverJsPath =
|
|
35047
|
-
if (!
|
|
34950
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve33(dirname23(realpathSync5(fileURLToPath2(import.meta.url))), "..");
|
|
34951
|
+
const serverJsPath = resolve33(packageRoot, ".next/standalone/server.js");
|
|
34952
|
+
if (!existsSync46(serverJsPath)) {
|
|
35048
34953
|
let shadowMessage = null;
|
|
35049
34954
|
try {
|
|
35050
34955
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -35133,20 +35038,20 @@ function helpText() {
|
|
|
35133
35038
|
label: "usage",
|
|
35134
35039
|
entries: [
|
|
35135
35040
|
["(bare)", `Scan your session history for leaked keys, then open http://localhost:${DASHBOARD_PORT}/audit`],
|
|
35136
|
-
["--schedule [days]", "Scan on a timer
|
|
35137
|
-
["--email <address>", "With --schedule,
|
|
35041
|
+
["--schedule [days]", "Scan on a timer and notify you on this machine. Default 7 days, range 1-90. No account required."],
|
|
35042
|
+
["--email <address>", "With --schedule, add email alerts for the most recent masked credential leak. A sign-in code is emailed to you."],
|
|
35138
35043
|
["--no-schedule", "Stop the timer. Leaves you signed in."],
|
|
35139
35044
|
["--notify", "Show a desktop notification when a scan finds a credential. On by default."],
|
|
35140
|
-
["--no-notify", "Stop
|
|
35045
|
+
["--no-notify", "Stop desktop notifications. Scheduled scans and optional email alerts are unaffected."],
|
|
35141
35046
|
["--status", "Whether scheduling is on, where reports go, the daemon's state, and when the next scan is due."],
|
|
35142
35047
|
["-h, --help", "Show this help."]
|
|
35143
35048
|
]
|
|
35144
35049
|
}
|
|
35145
35050
|
],
|
|
35146
35051
|
footer: [
|
|
35147
|
-
"
|
|
35148
|
-
"
|
|
35149
|
-
"and
|
|
35052
|
+
"Every scan runs on this machine. Leak alerts appear as desktop system",
|
|
35053
|
+
"notifications, never inside agent sessions. If you add email, only the",
|
|
35054
|
+
"newest masked credential exposure and its metadata leave the machine."
|
|
35150
35055
|
]
|
|
35151
35056
|
}, helpOptsFor(process.stdout));
|
|
35152
35057
|
return ["", ...lines, ""].join(`
|
|
@@ -35296,52 +35201,38 @@ function heldByLine(held) {
|
|
|
35296
35201
|
const ageS = Math.max(0, Math.round((Date.now() - held.startedAt) / 1000));
|
|
35297
35202
|
return `another audit is already running (pid ${held.pid}, started by ${held.source} ${ageS}s ago)`;
|
|
35298
35203
|
}
|
|
35299
|
-
async function announceLeaksOnDesktop(result) {
|
|
35204
|
+
async function announceLeaksOnDesktop(result, report) {
|
|
35300
35205
|
try {
|
|
35301
|
-
await announceLeaksOrThrow(result);
|
|
35206
|
+
await announceLeaksOrThrow(result, report);
|
|
35302
35207
|
} catch (err) {
|
|
35303
35208
|
process.stderr.write(`failproofai: could not announce a leak on the desktop: ` + `${err instanceof Error ? err.message : String(err)}
|
|
35304
35209
|
`);
|
|
35305
35210
|
}
|
|
35306
35211
|
}
|
|
35307
|
-
async function announceLeaksOrThrow(result) {
|
|
35308
|
-
const ids = result.newLeakIds ?? [];
|
|
35212
|
+
async function announceLeaksOrThrow(result, report) {
|
|
35213
|
+
const ids = result.leakIds ?? result.newLeakIds ?? [];
|
|
35309
35214
|
if (ids.length === 0)
|
|
35310
35215
|
return;
|
|
35311
35216
|
if (!readConfig().audit.notify)
|
|
35312
35217
|
return;
|
|
35313
|
-
const
|
|
35314
|
-
|
|
35315
|
-
|
|
35316
|
-
|
|
35317
|
-
|
|
35318
|
-
|
|
35319
|
-
|
|
35320
|
-
let delivered = false;
|
|
35321
|
-
try {
|
|
35322
|
-
if (process.platform === "darwin") {
|
|
35323
|
-
pruneMacNotifyQueue();
|
|
35324
|
-
if (!queueMacNotification(claimed[0], title, body)) {
|
|
35325
|
-
process.stderr.write(`failproofai: found ${n} but could not queue a notification
|
|
35218
|
+
const n = ids.length === 1 ? "a possible credential exposure" : `${ids.length} possible credential exposures`;
|
|
35219
|
+
const emailState = report.kind === "sent" ? "sent" : report.kind === "signed-out" || !readAuth() ? "missing" : report.kind === "failed" ? "failed" : "held";
|
|
35220
|
+
const { title, body } = desktopLeakNotice(emailState);
|
|
35221
|
+
if (process.platform === "darwin") {
|
|
35222
|
+
pruneMacNotifyQueue();
|
|
35223
|
+
if (!queueMacNotification(ids[0], title, body)) {
|
|
35224
|
+
process.stderr.write(`failproofai: found ${n} but could not queue a notification
|
|
35326
35225
|
`);
|
|
35327
|
-
|
|
35328
|
-
|
|
35329
|
-
}
|
|
35330
|
-
if (delivered && !macNotifierInstalled()) {
|
|
35331
|
-
process.stderr.write(`failproofai: found ${n}; the notifier is not installed, so nothing will show it ` + `(run \`failproofai config\`)
|
|
35226
|
+
} else if (!macNotifierInstalled()) {
|
|
35227
|
+
process.stderr.write(`failproofai: found ${n}; the notifier is not installed, so nothing will show it ` + `(run \`failproofai config\`)
|
|
35332
35228
|
`);
|
|
35333
|
-
}
|
|
35334
|
-
return;
|
|
35335
35229
|
}
|
|
35336
|
-
|
|
35337
|
-
|
|
35338
|
-
|
|
35339
|
-
|
|
35230
|
+
return;
|
|
35231
|
+
}
|
|
35232
|
+
const outcome = await notifyDesktop(title, body, 0);
|
|
35233
|
+
if (!outcome.ok) {
|
|
35234
|
+
process.stderr.write(`failproofai: found ${n} but could not raise a desktop notification (${outcome.reason})
|
|
35340
35235
|
`);
|
|
35341
|
-
}
|
|
35342
|
-
} finally {
|
|
35343
|
-
if (!delivered)
|
|
35344
|
-
releaseLeakNoticeClaims(claimed, undefined, "desktop");
|
|
35345
35236
|
}
|
|
35346
35237
|
}
|
|
35347
35238
|
async function runScheduledAudit() {
|
|
@@ -35375,8 +35266,8 @@ async function runScheduledAudit() {
|
|
|
35375
35266
|
}
|
|
35376
35267
|
process.stdout.write(`failproofai: audit complete — ${num2(result.eventsScanned)} tool calls across ` + `${num2(result.transcripts.scanned)} sessions, ${num2(result.totals.hits)} hits
|
|
35377
35268
|
`);
|
|
35378
|
-
await announceLeaksOnDesktop(result);
|
|
35379
35269
|
const outcome = await reportHarm(result);
|
|
35270
|
+
await announceLeaksOnDesktop(result, outcome);
|
|
35380
35271
|
const line = describeOutcome2(outcome);
|
|
35381
35272
|
if (line) {
|
|
35382
35273
|
const stream = outcome.kind === "sent" ? process.stdout : process.stderr;
|
|
@@ -35534,10 +35425,8 @@ var init_cli2 = __esm(() => {
|
|
|
35534
35425
|
init_report_harm();
|
|
35535
35426
|
init_desktop_notify();
|
|
35536
35427
|
init_macos_notifier();
|
|
35537
|
-
init_leak_notice();
|
|
35538
|
-
init_notice();
|
|
35539
|
-
init_leak_store();
|
|
35540
35428
|
init_fp_config();
|
|
35429
|
+
init_auth_store();
|
|
35541
35430
|
init_tui();
|
|
35542
35431
|
init_package();
|
|
35543
35432
|
AUDIT_STAGES2 = [
|
|
@@ -35870,8 +35759,8 @@ var init_session_pause_cli = __esm(() => {
|
|
|
35870
35759
|
|
|
35871
35760
|
// scripts/launch.ts
|
|
35872
35761
|
import { spawn as spawn3 } from "child_process";
|
|
35873
|
-
import { realpathSync as realpathSync6, existsSync as
|
|
35874
|
-
import { resolve as
|
|
35762
|
+
import { realpathSync as realpathSync6, existsSync as existsSync47 } from "node:fs";
|
|
35763
|
+
import { resolve as resolve34, dirname as dirname24 } from "node:path";
|
|
35875
35764
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
35876
35765
|
import { createInterface as createInterface2 } from "node:readline";
|
|
35877
35766
|
function launch2(mode) {
|
|
@@ -35895,9 +35784,9 @@ function launch2(mode) {
|
|
|
35895
35784
|
process.env.PORT = port;
|
|
35896
35785
|
process.env.HOSTNAME = bindHost;
|
|
35897
35786
|
cmd = "node";
|
|
35898
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ??
|
|
35899
|
-
const serverJsPath =
|
|
35900
|
-
if (!
|
|
35787
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve34(dirname24(realpathSync6(fileURLToPath3(import.meta.url))), "..");
|
|
35788
|
+
const serverJsPath = resolve34(packageRoot, ".next/standalone/server.js");
|
|
35789
|
+
if (!existsSync47(serverJsPath)) {
|
|
35901
35790
|
let shadowMessage = null;
|
|
35902
35791
|
try {
|
|
35903
35792
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -35994,17 +35883,17 @@ var init_cli_error2 = __esm(() => {
|
|
|
35994
35883
|
|
|
35995
35884
|
// bin/failproofai.mjs
|
|
35996
35885
|
import { realpathSync as realpathSync7 } from "fs";
|
|
35997
|
-
import { dirname as dirname25, resolve as
|
|
35886
|
+
import { dirname as dirname25, resolve as resolve35 } from "path";
|
|
35998
35887
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
35999
35888
|
// package.json
|
|
36000
|
-
var version = "1.0.4-beta.
|
|
35889
|
+
var version = "1.0.4-beta.6";
|
|
36001
35890
|
|
|
36002
35891
|
// bin/failproofai.mjs
|
|
36003
35892
|
if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
|
|
36004
|
-
process.env.FAILPROOFAI_PACKAGE_ROOT =
|
|
35893
|
+
process.env.FAILPROOFAI_PACKAGE_ROOT = resolve35(dirname25(realpathSync7(fileURLToPath4(import.meta.url))), "..");
|
|
36005
35894
|
}
|
|
36006
35895
|
if (!process.env.FAILPROOFAI_DIST_PATH) {
|
|
36007
|
-
process.env.FAILPROOFAI_DIST_PATH =
|
|
35896
|
+
process.env.FAILPROOFAI_DIST_PATH = resolve35(dirname25(realpathSync7(fileURLToPath4(import.meta.url))), "..", "dist");
|
|
36008
35897
|
}
|
|
36009
35898
|
var args = process.argv.slice(2);
|
|
36010
35899
|
if (args[0] === "p" || args[0] === "policy")
|