failproofai 1.0.4-beta.4 → 1.0.4-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.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 +15 -4
- package/.next/standalone/.next/server/app/settings/page.js +4 -4
- 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 +11 -11
- 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]__0yl9wb5._.js → [root-of-the-server]__12hbpha._.js} +2 -2
- 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/_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/{_0guxnh-._.js → _0a0zlpr._.js} +2 -2
- 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_builtin-policies_ts_09j2ndl._.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 +33 -22
- package/.next/standalone/.next/static/chunks/{17tfki9x5rd_7.js → 083fk73jtv9a0.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1i-i0pxg9q_8y.js → 0divvxng208xo.js} +1 -1
- package/.next/standalone/.next/static/chunks/{38dqur43qthrl.js → 0f1pznnc7zlub.js} +1 -1
- package/.next/standalone/.next/static/chunks/{323cyb3a2s06y.js → 0ntdfr2552x-h.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0po8n4tyotjf2.js → 0t6ea7d3bkmdv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{364cqbpeg1y5i.js → 15uon66hpwbgg.js} +1 -1
- package/.next/standalone/.next/static/chunks/{42gwu2bsz4ske.js → 1csubx9gwhsf6.js} +2 -2
- package/.next/standalone/.next/static/chunks/27du9n7ssja7l.js +1 -0
- package/.next/standalone/.next/static/chunks/2h_pcb1y8_jde.js +1 -0
- package/.next/standalone/.next/static/chunks/{2bxr2_2h4kaqq.js → 2pwfrn6_mw-1u.js} +1 -1
- package/.next/standalone/app/actions/get-leaks.ts +0 -5
- package/.next/standalone/app/actions/get-scheduled-audit.ts +5 -0
- package/.next/standalone/app/actions/update-scheduled-audit.ts +18 -57
- package/.next/standalone/app/api/auth/status/route.ts +3 -2
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +1 -1
- package/.next/standalone/app/audit/_components/empty-state.tsx +1 -1
- package/.next/standalone/app/audit/_components/leak-section.tsx +1 -1
- package/.next/standalone/app/settings/page.tsx +1 -1
- package/.next/standalone/app/settings/settings-client.tsx +50 -45
- 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 +991 -1101
- package/dist/worker.mjs +175 -382
- 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 +3 -1
- package/src/audit/leak-fingerprint.ts +2 -4
- package/src/audit/leak-record.ts +26 -10
- 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 +56 -68
- 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/builtin-policies.ts +2 -2
- package/src/hooks/configure-wizard.ts +36 -1
- 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/src/hooks/uninstall-cli.ts +3 -3
- package/.next/standalone/.next/server/chunks/ssr/_0oq1dh6._.js +0 -3
- package/.next/standalone/.next/static/chunks/04o5zfl7p5lhx.js +0 -1
- package/.next/standalone/.next/static/chunks/0qx7gav1c2_vu.js +0 -1
- package/src/audit/leak-notice.ts +0 -259
- /package/.next/standalone/.next/static/{P6icI2V2PvVuePJrqjHCr → YiPsVpjrc-pEQoN7XvhZ0}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{P6icI2V2PvVuePJrqjHCr → YiPsVpjrc-pEQoN7XvhZ0}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{P6icI2V2PvVuePJrqjHCr → YiPsVpjrc-pEQoN7XvhZ0}/_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.7", 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.7",
|
|
158
|
+
"@failproofai/failproofaid-linux-arm64": "1.0.4-beta.7",
|
|
159
|
+
"@failproofai/failproofaid-darwin-x64": "1.0.4-beta.7",
|
|
160
|
+
"@failproofai/failproofaid-darwin-arm64": "1.0.4-beta.7"
|
|
161
161
|
},
|
|
162
162
|
failproofaidBinaries: {
|
|
163
|
-
"linux-x64": "
|
|
164
|
-
"linux-arm64": "
|
|
165
|
-
"darwin-x64": "
|
|
166
|
-
"darwin-arm64": "
|
|
163
|
+
"linux-x64": "e59735a8f94cd8ac697b2bd67aafdd8d76a8394d53db229876980cc13a18f07e",
|
|
164
|
+
"linux-arm64": "b9ce50dd2f79b55f4f7112add265a776a4a6d002c2a56f971e666fbb796f3906",
|
|
165
|
+
"darwin-x64": "b46efc8ec33945a5cc26b7bb288fb87cea65b5983bd83094b5e607d53b8eda4c",
|
|
166
|
+
"darwin-arm64": "a8cc6112cee5ca8a7d517900e9ce32118855135980f22979fa0ff7aa6f68d954"
|
|
167
167
|
}
|
|
168
168
|
};
|
|
169
169
|
});
|
|
@@ -3874,8 +3874,8 @@ var init_builtin_policies = __esm(() => {
|
|
|
3874
3874
|
[/sk-ant-oat01-[A-Za-z0-9\-_]{20,}/, "Anthropic OAuth token"],
|
|
3875
3875
|
[/sk-ant-[A-Za-z0-9\-_]{20,}/, "Anthropic API key"],
|
|
3876
3876
|
[/sk-proj-[A-Za-z0-9\-_]{20,}/, "OpenAI project API key"],
|
|
3877
|
-
[/sk-svcacct-[A-Za-z0-9\-_]{20,}/, "OpenAI service-account key"],
|
|
3878
|
-
[/sk-admin-[A-Za-z0-9\-_]{20,}/, "OpenAI admin key"],
|
|
3877
|
+
[/(?<!\w)sk-svcacct-[A-Za-z0-9\-_]{20,}/, "OpenAI service-account key"],
|
|
3878
|
+
[/(?<!\w)sk-admin-[A-Za-z0-9\-_]{20,}/, "OpenAI admin key"],
|
|
3879
3879
|
[/sk-or-v1-[A-Za-z0-9\-_]{20,}/, "OpenRouter API key"],
|
|
3880
3880
|
[/sk-[A-Za-z0-9]{20,}/, "OpenAI-compatible key (issuer unknown)"],
|
|
3881
3881
|
[/github_pat_[A-Za-z0-9_]{82}/, "GitHub fine-grained token"],
|
|
@@ -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,51 +25112,123 @@ 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 { chmodSync as chmodSync5, 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");
|
|
25198
|
+
}
|
|
25199
|
+
function macNotifierRunnerPath(home) {
|
|
25200
|
+
return resolve22(runDir(home), "..", "bin", "failproofai-notifier.zsh");
|
|
25475
25201
|
}
|
|
25476
25202
|
function macNotifierPlistPath() {
|
|
25477
|
-
return
|
|
25203
|
+
return resolve22(homedir24(), "Library", "LaunchAgents", `${MAC_NOTIFIER_LABEL}.plist`);
|
|
25478
25204
|
}
|
|
25479
25205
|
function escapeXml2(s) {
|
|
25480
25206
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
25481
25207
|
}
|
|
25482
25208
|
function notifierScript(home) {
|
|
25483
25209
|
const dir = macNotifyDir(home);
|
|
25484
|
-
|
|
25485
|
-
|
|
25486
|
-
|
|
25487
|
-
|
|
25488
|
-
|
|
25489
|
-
|
|
25490
|
-
|
|
25491
|
-
|
|
25492
|
-
|
|
25493
|
-
|
|
25494
|
-
|
|
25495
|
-
|
|
25496
|
-
|
|
25497
|
-
|
|
25498
|
-
|
|
25499
|
-
|
|
25500
|
-
repeat with i from 2 to (count of lines_)
|
|
25501
|
-
if noteBody is not "" then set noteBody to noteBody & " "
|
|
25502
|
-
set noteBody to noteBody & (item i of lines_)
|
|
25503
|
-
end repeat
|
|
25504
|
-
display notification noteBody with title noteTitle
|
|
25505
|
-
end if
|
|
25506
|
-
end try
|
|
25507
|
-
end if
|
|
25508
|
-
end repeat
|
|
25210
|
+
const quotedDir = `'${dir.replace(/'/g, `'\\''`)}'`;
|
|
25211
|
+
return `#!/bin/zsh
|
|
25212
|
+
set -u
|
|
25213
|
+
setopt NULL_GLOB
|
|
25214
|
+
|
|
25215
|
+
drop_dir=${quotedDir}
|
|
25216
|
+
|
|
25217
|
+
for entry_path in "$drop_dir"/*; do
|
|
25218
|
+
[ -f "$entry_path" ] || continue
|
|
25219
|
+
note_title=$(/usr/bin/sed -n '1p' "$entry_path")
|
|
25220
|
+
note_body=$(/usr/bin/sed -n '2,$p' "$entry_path" | /usr/bin/tr '\\n' ' ')
|
|
25221
|
+
/bin/rm -f "$entry_path"
|
|
25222
|
+
[ -n "$note_title" ] || continue
|
|
25223
|
+
/usr/bin/osascript - "$note_title" "$note_body" <<'APPLESCRIPT'
|
|
25224
|
+
on run argv
|
|
25225
|
+
display notification (item 2 of argv) with title (item 1 of argv)
|
|
25509
25226
|
end run
|
|
25227
|
+
APPLESCRIPT
|
|
25228
|
+
done
|
|
25510
25229
|
`;
|
|
25511
25230
|
}
|
|
25512
|
-
function notifierPlistContents(
|
|
25231
|
+
function notifierPlistContents(runnerPath, watchDir) {
|
|
25513
25232
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
25514
25233
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
25515
25234
|
<plist version="1.0">
|
|
@@ -25518,7 +25237,7 @@ function notifierPlistContents(appPath, watchDir) {
|
|
|
25518
25237
|
<string>${escapeXml2(MAC_NOTIFIER_LABEL)}</string>
|
|
25519
25238
|
<key>ProgramArguments</key>
|
|
25520
25239
|
<array>
|
|
25521
|
-
<string>${escapeXml2(
|
|
25240
|
+
<string>${escapeXml2(runnerPath)}</string>
|
|
25522
25241
|
</array>
|
|
25523
25242
|
<!-- Started only when something is queued, and it exits when the queue is
|
|
25524
25243
|
empty. RunAtLoad would fire it once at login with nothing to say. -->
|
|
@@ -25545,20 +25264,15 @@ function installMacNotifier(home) {
|
|
|
25545
25264
|
if (process.platform !== "darwin")
|
|
25546
25265
|
return { installed: false, reason: "not macOS" };
|
|
25547
25266
|
try {
|
|
25548
|
-
const
|
|
25267
|
+
const runner = macNotifierRunnerPath(home);
|
|
25549
25268
|
const watch = macNotifyDir(home);
|
|
25550
|
-
|
|
25551
|
-
|
|
25552
|
-
|
|
25553
|
-
|
|
25554
|
-
|
|
25555
|
-
|
|
25556
|
-
|
|
25557
|
-
const plist = resolve23(app, "Contents", "Info.plist");
|
|
25558
|
-
run("defaults", ["write", plist, "CFBundleIdentifier", MAC_NOTIFIER_LABEL]);
|
|
25559
|
-
run("defaults", ["write", plist, "CFBundleName", "failproofai"]);
|
|
25560
|
-
mkdirSync19(resolve23(macNotifierPlistPath(), ".."), { recursive: true });
|
|
25561
|
-
writeFileSync16(macNotifierPlistPath(), notifierPlistContents(app, watch), { mode: 420 });
|
|
25269
|
+
mkdirSync17(watch, { recursive: true, mode: 448 });
|
|
25270
|
+
mkdirSync17(resolve22(runner, ".."), { recursive: true });
|
|
25271
|
+
writeFileSync15(runner, notifierScript(home), { mode: 448 });
|
|
25272
|
+
chmodSync5(runner, 448);
|
|
25273
|
+
rmSync9(macNotifierAppPath(home), { recursive: true, force: true });
|
|
25274
|
+
mkdirSync17(resolve22(macNotifierPlistPath(), ".."), { recursive: true });
|
|
25275
|
+
writeFileSync15(macNotifierPlistPath(), notifierPlistContents(runner, watch), { mode: 420 });
|
|
25562
25276
|
const target = `gui/${process.getuid?.() ?? 0}`;
|
|
25563
25277
|
try {
|
|
25564
25278
|
run("launchctl", ["bootout", `${target}/${MAC_NOTIFIER_LABEL}`]);
|
|
@@ -25575,49 +25289,50 @@ function uninstallMacNotifier(home) {
|
|
|
25575
25289
|
try {
|
|
25576
25290
|
run("launchctl", ["bootout", `gui/${process.getuid?.() ?? 0}/${MAC_NOTIFIER_LABEL}`]);
|
|
25577
25291
|
} catch {}
|
|
25578
|
-
|
|
25579
|
-
|
|
25580
|
-
|
|
25292
|
+
rmSync9(macNotifierPlistPath(), { force: true });
|
|
25293
|
+
rmSync9(macNotifierAppPath(home), { recursive: true, force: true });
|
|
25294
|
+
rmSync9(macNotifierRunnerPath(home), { force: true });
|
|
25295
|
+
rmSync9(macNotifyDir(home), { recursive: true, force: true });
|
|
25581
25296
|
}
|
|
25582
25297
|
function queueMacNotification(id, title, body, home) {
|
|
25583
25298
|
if (!isFindingId(id))
|
|
25584
25299
|
return false;
|
|
25585
25300
|
const dir = macNotifyDir(home);
|
|
25586
|
-
const tmp =
|
|
25301
|
+
const tmp = resolve22(dir, "..", `notify-${id}.tmp`);
|
|
25587
25302
|
try {
|
|
25588
|
-
|
|
25303
|
+
mkdirSync17(dir, { recursive: true, mode: 448 });
|
|
25589
25304
|
const payload = `${title.replace(/\s+/g, " ")}
|
|
25590
25305
|
${body.replace(/\s+/g, " ")}
|
|
25591
25306
|
`;
|
|
25592
|
-
|
|
25593
|
-
renameSync8(tmp,
|
|
25307
|
+
writeFileSync15(tmp, payload, { mode: 384 });
|
|
25308
|
+
renameSync8(tmp, resolve22(dir, id));
|
|
25594
25309
|
return true;
|
|
25595
25310
|
} catch {
|
|
25596
25311
|
try {
|
|
25597
|
-
|
|
25312
|
+
rmSync9(tmp, { force: true });
|
|
25598
25313
|
} catch {}
|
|
25599
25314
|
return false;
|
|
25600
25315
|
}
|
|
25601
25316
|
}
|
|
25602
25317
|
function macNotifierInstalled(home) {
|
|
25603
|
-
return
|
|
25318
|
+
return existsSync26(macNotifierPlistPath()) && existsSync26(macNotifierRunnerPath(home));
|
|
25604
25319
|
}
|
|
25605
25320
|
function pruneMacNotifyQueue(home, maxAgeMs = 7 * 86400000) {
|
|
25606
25321
|
try {
|
|
25607
25322
|
const dir = macNotifyDir(home);
|
|
25608
|
-
if (!
|
|
25323
|
+
if (!existsSync26(dir))
|
|
25609
25324
|
return;
|
|
25610
25325
|
const { statSync } = __require("node:fs");
|
|
25611
|
-
for (const name of
|
|
25612
|
-
const path =
|
|
25326
|
+
for (const name of readdirSync16(dir)) {
|
|
25327
|
+
const path = resolve22(dir, name);
|
|
25613
25328
|
try {
|
|
25614
25329
|
if (Date.now() - statSync(path).mtimeMs > maxAgeMs)
|
|
25615
|
-
|
|
25330
|
+
rmSync9(path, { force: true });
|
|
25616
25331
|
} catch {}
|
|
25617
25332
|
}
|
|
25618
25333
|
} catch {}
|
|
25619
25334
|
}
|
|
25620
|
-
var MAC_NOTIFIER_LABEL = "ai.failproof.notifier", macNotifyDir = (home) =>
|
|
25335
|
+
var MAC_NOTIFIER_LABEL = "ai.failproof.notifier", macNotifyDir = (home) => resolve22(runDir(home), "notify");
|
|
25621
25336
|
var init_macos_notifier = __esm(() => {
|
|
25622
25337
|
init_fp_home();
|
|
25623
25338
|
init_leak_fingerprint();
|
|
@@ -25639,7 +25354,7 @@ var DEFAULT_FETCH_TIMEOUT_MS = 15000;
|
|
|
25639
25354
|
|
|
25640
25355
|
// src/hooks/cloud-enrollment.ts
|
|
25641
25356
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
25642
|
-
import { existsSync as
|
|
25357
|
+
import { existsSync as existsSync27, readFileSync as readFileSync22, rmSync as rmSync10 } from "node:fs";
|
|
25643
25358
|
import { hostname as hostname4 } from "node:os";
|
|
25644
25359
|
function cloudCredentialPath() {
|
|
25645
25360
|
return process.env.FAILPROOFAI_CLOUD_CREDENTIALS ?? credentialsFile();
|
|
@@ -25678,10 +25393,10 @@ function readCloudCredentials() {
|
|
|
25678
25393
|
if (!usingJsonOverride())
|
|
25679
25394
|
return readCredentials().cloud ?? null;
|
|
25680
25395
|
const path = cloudCredentialPath();
|
|
25681
|
-
if (!
|
|
25396
|
+
if (!existsSync27(path))
|
|
25682
25397
|
return null;
|
|
25683
25398
|
try {
|
|
25684
|
-
const raw = JSON.parse(
|
|
25399
|
+
const raw = JSON.parse(readFileSync22(path, "utf8"));
|
|
25685
25400
|
if (raw.schemaVersion !== SCHEMA_VERSION2)
|
|
25686
25401
|
return null;
|
|
25687
25402
|
if (typeof raw.url !== "string" || typeof raw.machineId !== "string" || typeof raw.token !== "string") {
|
|
@@ -25720,10 +25435,10 @@ function resolveMachineLabel(explicit) {
|
|
|
25720
25435
|
function clearCloudCredentials() {
|
|
25721
25436
|
if (usingJsonOverride()) {
|
|
25722
25437
|
const path = cloudCredentialPath();
|
|
25723
|
-
if (!
|
|
25438
|
+
if (!existsSync27(path))
|
|
25724
25439
|
return false;
|
|
25725
25440
|
try {
|
|
25726
|
-
|
|
25441
|
+
rmSync10(path);
|
|
25727
25442
|
return true;
|
|
25728
25443
|
} catch {
|
|
25729
25444
|
return false;
|
|
@@ -25971,21 +25686,21 @@ var init_cloud_connection = __esm(() => {
|
|
|
25971
25686
|
});
|
|
25972
25687
|
|
|
25973
25688
|
// src/hooks/setup-state.ts
|
|
25974
|
-
import { existsSync as
|
|
25975
|
-
import { dirname as
|
|
25689
|
+
import { existsSync as existsSync28, realpathSync as realpathSync2, statSync as statSync17 } from "node:fs";
|
|
25690
|
+
import { dirname as dirname14, resolve as resolve23 } from "node:path";
|
|
25976
25691
|
import { homedir as homedir25 } from "node:os";
|
|
25977
25692
|
function globalConfigPath(home = homedir25()) {
|
|
25978
25693
|
return globalPolicyConfigFile(home);
|
|
25979
25694
|
}
|
|
25980
25695
|
function projectConfigPath(projectRoot) {
|
|
25981
|
-
return
|
|
25696
|
+
return resolve23(projectRoot, ".failproofai", "policies-config.json");
|
|
25982
25697
|
}
|
|
25983
25698
|
function legacyMarkerPath(home) {
|
|
25984
25699
|
return launcherMarker(home);
|
|
25985
25700
|
}
|
|
25986
25701
|
function isDir(path) {
|
|
25987
25702
|
try {
|
|
25988
|
-
return
|
|
25703
|
+
return statSync17(path).isDirectory();
|
|
25989
25704
|
} catch {
|
|
25990
25705
|
return false;
|
|
25991
25706
|
}
|
|
@@ -25994,14 +25709,14 @@ function findProjectRoot(start, home = homedir25()) {
|
|
|
25994
25709
|
const resolvedHome = realResolve(home);
|
|
25995
25710
|
let dir = realResolve(start);
|
|
25996
25711
|
while (dir !== resolvedHome) {
|
|
25997
|
-
if (isDir(
|
|
25712
|
+
if (isDir(resolve23(dir, ".failproofai")))
|
|
25998
25713
|
return dir;
|
|
25999
|
-
const parent =
|
|
25714
|
+
const parent = dirname14(dir);
|
|
26000
25715
|
if (parent === dir)
|
|
26001
25716
|
break;
|
|
26002
25717
|
dir = parent;
|
|
26003
25718
|
}
|
|
26004
|
-
return
|
|
25719
|
+
return resolve23(start);
|
|
26005
25720
|
}
|
|
26006
25721
|
function hasGlobalHooksInstalled() {
|
|
26007
25722
|
for (const id of INTEGRATION_TYPES) {
|
|
@@ -26013,7 +25728,7 @@ function hasGlobalHooksInstalled() {
|
|
|
26013
25728
|
return false;
|
|
26014
25729
|
}
|
|
26015
25730
|
function realResolve(path) {
|
|
26016
|
-
const lexical =
|
|
25731
|
+
const lexical = resolve23(path);
|
|
26017
25732
|
try {
|
|
26018
25733
|
return realpathSync2(lexical);
|
|
26019
25734
|
} catch {
|
|
@@ -26028,10 +25743,10 @@ function detectSetupState(cwd = process.cwd(), home = homedir25()) {
|
|
|
26028
25743
|
cwd: resolvedCwd,
|
|
26029
25744
|
home: resolvedHome,
|
|
26030
25745
|
projectRoot,
|
|
26031
|
-
hasGlobalConfig:
|
|
26032
|
-
hasProjectConfig: projectRoot !== resolvedHome &&
|
|
25746
|
+
hasGlobalConfig: existsSync28(globalConfigPath(resolvedHome)),
|
|
25747
|
+
hasProjectConfig: projectRoot !== resolvedHome && existsSync28(projectConfigPath(projectRoot)),
|
|
26033
25748
|
hasGlobalHooks: hasGlobalHooksInstalled(),
|
|
26034
|
-
hasLegacyMarker:
|
|
25749
|
+
hasLegacyMarker: existsSync28(legacyMarkerPath(resolvedHome)),
|
|
26035
25750
|
inHomeDir: resolvedCwd === resolvedHome
|
|
26036
25751
|
};
|
|
26037
25752
|
}
|
|
@@ -26048,14 +25763,14 @@ var init_setup_state = __esm(() => {
|
|
|
26048
25763
|
});
|
|
26049
25764
|
|
|
26050
25765
|
// src/hooks/onboarding-attempt.ts
|
|
26051
|
-
import { existsSync as
|
|
26052
|
-
import { dirname as
|
|
25766
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync18, readFileSync as readFileSync23, rmSync as rmSync11, writeFileSync as writeFileSync16 } from "node:fs";
|
|
25767
|
+
import { dirname as dirname15 } from "node:path";
|
|
26053
25768
|
function readOnboardingAttempt() {
|
|
26054
25769
|
const path = onboardingAttemptFile();
|
|
26055
|
-
if (!
|
|
25770
|
+
if (!existsSync29(path))
|
|
26056
25771
|
return null;
|
|
26057
25772
|
try {
|
|
26058
|
-
const raw = JSON.parse(
|
|
25773
|
+
const raw = JSON.parse(readFileSync23(path, "utf8"));
|
|
26059
25774
|
if (raw.schemaVersion !== SCHEMA_VERSION3)
|
|
26060
25775
|
return null;
|
|
26061
25776
|
if (typeof raw.reason !== "string" || typeof raw.cliVersion !== "string")
|
|
@@ -26074,7 +25789,7 @@ function readOnboardingAttempt() {
|
|
|
26074
25789
|
function recordOnboardingAttempt(reason, cliVersion, daemonStatus, now = Date.now()) {
|
|
26075
25790
|
try {
|
|
26076
25791
|
const path = onboardingAttemptFile();
|
|
26077
|
-
|
|
25792
|
+
mkdirSync18(dirname15(path), { recursive: true });
|
|
26078
25793
|
const record = {
|
|
26079
25794
|
schemaVersion: SCHEMA_VERSION3,
|
|
26080
25795
|
reason,
|
|
@@ -26082,12 +25797,12 @@ function recordOnboardingAttempt(reason, cliVersion, daemonStatus, now = Date.no
|
|
|
26082
25797
|
daemonStatus,
|
|
26083
25798
|
at: now
|
|
26084
25799
|
};
|
|
26085
|
-
|
|
25800
|
+
writeFileSync16(path, JSON.stringify(record, null, 2), "utf8");
|
|
26086
25801
|
} catch {}
|
|
26087
25802
|
}
|
|
26088
25803
|
function clearOnboardingAttempt() {
|
|
26089
25804
|
try {
|
|
26090
|
-
|
|
25805
|
+
rmSync11(onboardingAttemptFile(), { force: true });
|
|
26091
25806
|
} catch {}
|
|
26092
25807
|
}
|
|
26093
25808
|
function blockerCleared(attempt, probe) {
|
|
@@ -26129,7 +25844,7 @@ var init_onboarding_attempt = __esm(() => {
|
|
|
26129
25844
|
});
|
|
26130
25845
|
|
|
26131
25846
|
// src/hooks/onboarding-lock.ts
|
|
26132
|
-
import { mkdirSync as
|
|
25847
|
+
import { mkdirSync as mkdirSync19, readFileSync as readFileSync24, rmSync as rmSync12, writeFileSync as writeFileSync17 } from "node:fs";
|
|
26133
25848
|
import { homedir as homedir26 } from "node:os";
|
|
26134
25849
|
function onboardingLockPath(home = homedir26()) {
|
|
26135
25850
|
return onboardingLockFile(home);
|
|
@@ -26146,7 +25861,7 @@ function processAlive(pid) {
|
|
|
26146
25861
|
}
|
|
26147
25862
|
function readLock(path) {
|
|
26148
25863
|
try {
|
|
26149
|
-
const parsed = JSON.parse(
|
|
25864
|
+
const parsed = JSON.parse(readFileSync24(path, "utf8"));
|
|
26150
25865
|
if (typeof parsed.pid !== "number")
|
|
26151
25866
|
return null;
|
|
26152
25867
|
return { pid: parsed.pid, startedAt: Number(parsed.startedAt) || 0 };
|
|
@@ -26160,9 +25875,9 @@ function acquireOnboardingLock(home = homedir26()) {
|
|
|
26160
25875
|
const held = readLock(path);
|
|
26161
25876
|
if (held && held.pid !== process.pid && processAlive(held.pid))
|
|
26162
25877
|
return null;
|
|
26163
|
-
|
|
25878
|
+
mkdirSync19(stateDir(home), { recursive: true });
|
|
26164
25879
|
const body = { pid: process.pid, startedAt: Date.now() };
|
|
26165
|
-
|
|
25880
|
+
writeFileSync17(path, JSON.stringify(body), "utf8");
|
|
26166
25881
|
let released = false;
|
|
26167
25882
|
return {
|
|
26168
25883
|
release() {
|
|
@@ -26172,7 +25887,7 @@ function acquireOnboardingLock(home = homedir26()) {
|
|
|
26172
25887
|
try {
|
|
26173
25888
|
const current = readLock(path);
|
|
26174
25889
|
if (!current || current.pid === process.pid)
|
|
26175
|
-
|
|
25890
|
+
rmSync12(path, { force: true });
|
|
26176
25891
|
} catch {}
|
|
26177
25892
|
}
|
|
26178
25893
|
};
|
|
@@ -26185,7 +25900,7 @@ var init_onboarding_lock = __esm(() => {
|
|
|
26185
25900
|
});
|
|
26186
25901
|
|
|
26187
25902
|
// lib/claude-sessions.ts
|
|
26188
|
-
import { readdirSync as
|
|
25903
|
+
import { readdirSync as readdirSync17, statSync as statSync18, existsSync as existsSync30 } from "node:fs";
|
|
26189
25904
|
import { join as join32, basename as basename6 } from "node:path";
|
|
26190
25905
|
function getClaudeProjectsRoot() {
|
|
26191
25906
|
return getClaudeProjectsPath();
|
|
@@ -26194,7 +25909,7 @@ function listClaudeProjects() {
|
|
|
26194
25909
|
const root = getClaudeProjectsRoot();
|
|
26195
25910
|
let entries;
|
|
26196
25911
|
try {
|
|
26197
|
-
entries =
|
|
25912
|
+
entries = readdirSync17(root, { withFileTypes: true });
|
|
26198
25913
|
} catch {
|
|
26199
25914
|
return [];
|
|
26200
25915
|
}
|
|
@@ -26209,7 +25924,7 @@ function collectSubagentTranscripts(dir, relPrefix, project, out, depth) {
|
|
|
26209
25924
|
return;
|
|
26210
25925
|
let entries;
|
|
26211
25926
|
try {
|
|
26212
|
-
entries =
|
|
25927
|
+
entries = readdirSync17(dir, { withFileTypes: true });
|
|
26213
25928
|
} catch {
|
|
26214
25929
|
return;
|
|
26215
25930
|
}
|
|
@@ -26225,7 +25940,7 @@ function collectSubagentTranscripts(dir, relPrefix, project, out, depth) {
|
|
|
26225
25940
|
const stem = entry.name.slice(0, -".jsonl".length);
|
|
26226
25941
|
const transcriptPath = join32(dir, entry.name);
|
|
26227
25942
|
try {
|
|
26228
|
-
const s =
|
|
25943
|
+
const s = statSync18(transcriptPath);
|
|
26229
25944
|
out.push({
|
|
26230
25945
|
projectName: project.name,
|
|
26231
25946
|
cwd: project.cwd,
|
|
@@ -26242,7 +25957,7 @@ function listClaudeTranscripts(project) {
|
|
|
26242
25957
|
const out = [];
|
|
26243
25958
|
let entries;
|
|
26244
25959
|
try {
|
|
26245
|
-
entries =
|
|
25960
|
+
entries = readdirSync17(project.path, { withFileTypes: true });
|
|
26246
25961
|
} catch {
|
|
26247
25962
|
return out;
|
|
26248
25963
|
}
|
|
@@ -26253,7 +25968,7 @@ function listClaudeTranscripts(project) {
|
|
|
26253
25968
|
continue;
|
|
26254
25969
|
const transcriptPath = join32(project.path, entry.name);
|
|
26255
25970
|
try {
|
|
26256
|
-
const s =
|
|
25971
|
+
const s = statSync18(transcriptPath);
|
|
26257
25972
|
out.push({
|
|
26258
25973
|
projectName: project.name,
|
|
26259
25974
|
cwd: project.cwd,
|
|
@@ -26266,7 +25981,7 @@ function listClaudeTranscripts(project) {
|
|
|
26266
25981
|
} catch {}
|
|
26267
25982
|
} else if (entry.isDirectory() && UUID_RE2.test(entry.name)) {
|
|
26268
25983
|
const subDir = join32(project.path, entry.name, "subagents");
|
|
26269
|
-
if (!
|
|
25984
|
+
if (!existsSync30(subDir))
|
|
26270
25985
|
continue;
|
|
26271
25986
|
collectSubagentTranscripts(subDir, entry.name, project, out, 0);
|
|
26272
25987
|
}
|
|
@@ -26332,7 +26047,7 @@ var init_shared = __esm(() => {
|
|
|
26332
26047
|
|
|
26333
26048
|
// src/audit/cli-adapters/claude.ts
|
|
26334
26049
|
import { readFile as readFile15, open as open2 } from "node:fs/promises";
|
|
26335
|
-
import { readFileSync as
|
|
26050
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
26336
26051
|
async function listClaudeTranscriptMetadata(opts = {}) {
|
|
26337
26052
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26338
26053
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26352,7 +26067,7 @@ async function listClaudeTranscriptMetadata(opts = {}) {
|
|
|
26352
26067
|
let sessionDescription;
|
|
26353
26068
|
if (t.isSubagent) {
|
|
26354
26069
|
try {
|
|
26355
|
-
const meta = JSON.parse(
|
|
26070
|
+
const meta = JSON.parse(readFileSync25(t.transcriptPath.replace(/\.jsonl$/, ".meta.json"), "utf8"));
|
|
26356
26071
|
if (typeof meta.description === "string")
|
|
26357
26072
|
sessionDescription = meta.description;
|
|
26358
26073
|
} catch {}
|
|
@@ -26483,7 +26198,7 @@ var init_claude = __esm(() => {
|
|
|
26483
26198
|
});
|
|
26484
26199
|
|
|
26485
26200
|
// src/audit/cli-adapters/codex.ts
|
|
26486
|
-
import { statSync as
|
|
26201
|
+
import { statSync as statSync19 } from "node:fs";
|
|
26487
26202
|
async function listCodexTranscriptMetadata(opts = {}) {
|
|
26488
26203
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26489
26204
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26500,7 +26215,7 @@ async function listCodexTranscriptMetadata(opts = {}) {
|
|
|
26500
26215
|
continue;
|
|
26501
26216
|
let sizeBytes = 0;
|
|
26502
26217
|
try {
|
|
26503
|
-
sizeBytes =
|
|
26218
|
+
sizeBytes = statSync19(s.path).size;
|
|
26504
26219
|
} catch {}
|
|
26505
26220
|
if (!s.sessionId)
|
|
26506
26221
|
continue;
|
|
@@ -26534,7 +26249,7 @@ var init_codex = __esm(() => {
|
|
|
26534
26249
|
});
|
|
26535
26250
|
|
|
26536
26251
|
// src/audit/cli-adapters/copilot.ts
|
|
26537
|
-
import { statSync as
|
|
26252
|
+
import { statSync as statSync20 } from "node:fs";
|
|
26538
26253
|
async function listCopilotTranscriptMetadata(opts = {}) {
|
|
26539
26254
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26540
26255
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26551,7 +26266,7 @@ async function listCopilotTranscriptMetadata(opts = {}) {
|
|
|
26551
26266
|
continue;
|
|
26552
26267
|
let sizeBytes = 0;
|
|
26553
26268
|
try {
|
|
26554
|
-
sizeBytes =
|
|
26269
|
+
sizeBytes = statSync20(s.path).size;
|
|
26555
26270
|
} catch {}
|
|
26556
26271
|
if (!s.sessionId)
|
|
26557
26272
|
continue;
|
|
@@ -26585,7 +26300,7 @@ var init_copilot = __esm(() => {
|
|
|
26585
26300
|
});
|
|
26586
26301
|
|
|
26587
26302
|
// src/audit/cli-adapters/cursor.ts
|
|
26588
|
-
import { statSync as
|
|
26303
|
+
import { statSync as statSync21 } from "node:fs";
|
|
26589
26304
|
async function listCursorTranscriptMetadata(opts = {}) {
|
|
26590
26305
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26591
26306
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26602,7 +26317,7 @@ async function listCursorTranscriptMetadata(opts = {}) {
|
|
|
26602
26317
|
continue;
|
|
26603
26318
|
let sizeBytes = 0;
|
|
26604
26319
|
try {
|
|
26605
|
-
sizeBytes =
|
|
26320
|
+
sizeBytes = statSync21(s.path).size;
|
|
26606
26321
|
} catch {}
|
|
26607
26322
|
if (!s.sessionId)
|
|
26608
26323
|
continue;
|
|
@@ -26843,7 +26558,7 @@ var init_opencode = __esm(() => {
|
|
|
26843
26558
|
});
|
|
26844
26559
|
|
|
26845
26560
|
// src/audit/cli-adapters/pi.ts
|
|
26846
|
-
import { statSync as
|
|
26561
|
+
import { statSync as statSync22 } from "node:fs";
|
|
26847
26562
|
async function listPiTranscriptMetadata(opts = {}) {
|
|
26848
26563
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
26849
26564
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -26860,7 +26575,7 @@ async function listPiTranscriptMetadata(opts = {}) {
|
|
|
26860
26575
|
continue;
|
|
26861
26576
|
let sizeBytes = 0;
|
|
26862
26577
|
try {
|
|
26863
|
-
sizeBytes =
|
|
26578
|
+
sizeBytes = statSync22(s.path).size;
|
|
26864
26579
|
} catch {}
|
|
26865
26580
|
if (!s.sessionId)
|
|
26866
26581
|
continue;
|
|
@@ -27669,7 +27384,7 @@ function flattenToolInput(input, depth = 0) {
|
|
|
27669
27384
|
}
|
|
27670
27385
|
return "";
|
|
27671
27386
|
}
|
|
27672
|
-
var LEAK_SCAN_VERSION =
|
|
27387
|
+
var LEAK_SCAN_VERSION = 6, ASSIGNMENT_RE, DOCS_LITERALS, SELF_OUTPUT_MARKERS, GATED_PATTERNS;
|
|
27673
27388
|
var init_leak_scan = __esm(() => {
|
|
27674
27389
|
init_builtin_policies();
|
|
27675
27390
|
ASSIGNMENT_RE = /(["']?)\b([A-Za-z_][A-Za-z0-9_]{0,127})\1([ \t]*(?::(?!\/\/)|=)[ \t]*)("[^"]*"|'[^']*'|[^\s;|&"']+)/g;
|
|
@@ -27694,6 +27409,176 @@ var init_leak_scan = __esm(() => {
|
|
|
27694
27409
|
GATED_PATTERNS = SECRET_PATTERNS.map(([re, label]) => [re, label, literalPrefixOf(re.source)]);
|
|
27695
27410
|
});
|
|
27696
27411
|
|
|
27412
|
+
// src/audit/leak-record.ts
|
|
27413
|
+
function upsertFinding(record, incoming) {
|
|
27414
|
+
const { sighting, ...rest } = incoming;
|
|
27415
|
+
const existing = record.findings.find((f) => f.id === rest.id);
|
|
27416
|
+
if (!existing) {
|
|
27417
|
+
record.findings.push({
|
|
27418
|
+
...rest,
|
|
27419
|
+
firstSeen: sighting.at,
|
|
27420
|
+
lastSeen: sighting.at,
|
|
27421
|
+
occurrences: 1,
|
|
27422
|
+
sightings: [sighting]
|
|
27423
|
+
});
|
|
27424
|
+
return { record, isNew: true };
|
|
27425
|
+
}
|
|
27426
|
+
const seen = existing.sightings.some((s) => s.sessionId === sighting.sessionId && s.at === sighting.at && s.mechanism.direction === sighting.mechanism.direction && s.mechanism.summary === sighting.mechanism.summary);
|
|
27427
|
+
if (seen)
|
|
27428
|
+
return { record, isNew: false };
|
|
27429
|
+
existing.occurrences += 1;
|
|
27430
|
+
if (sighting.at > existing.lastSeen)
|
|
27431
|
+
existing.lastSeen = sighting.at;
|
|
27432
|
+
if (sighting.at < existing.firstSeen)
|
|
27433
|
+
existing.firstSeen = sighting.at;
|
|
27434
|
+
existing.sightings.push(sighting);
|
|
27435
|
+
existing.sightings.sort((a, b) => a.at.localeCompare(b.at));
|
|
27436
|
+
if (existing.sightings.length > MAX_SIGHTINGS) {
|
|
27437
|
+
existing.sightings.splice(1, existing.sightings.length - MAX_SIGHTINGS);
|
|
27438
|
+
}
|
|
27439
|
+
return { record, isNew: false };
|
|
27440
|
+
}
|
|
27441
|
+
function pruneRecord(record, nowMs) {
|
|
27442
|
+
const cutoff = new Date(nowMs - FINDING_TTL_DAYS * 86400000).toISOString();
|
|
27443
|
+
const live = record.findings.filter((f) => !f.lastSeen || !Number.isFinite(Date.parse(f.lastSeen)) || f.lastSeen >= cutoff);
|
|
27444
|
+
live.sort((a, b) => a.lastSeen < b.lastSeen ? 1 : a.lastSeen > b.lastSeen ? -1 : 0);
|
|
27445
|
+
record.findings = live.slice(0, MAX_FINDINGS);
|
|
27446
|
+
return record;
|
|
27447
|
+
}
|
|
27448
|
+
function emptyRecord(salt, nowIso) {
|
|
27449
|
+
return {
|
|
27450
|
+
schemaVersion: LEAK_RECORD_SCHEMA_VERSION,
|
|
27451
|
+
salt,
|
|
27452
|
+
updatedAt: nowIso,
|
|
27453
|
+
findings: []
|
|
27454
|
+
};
|
|
27455
|
+
}
|
|
27456
|
+
function describeMechanism(toolName, direction, shortPath) {
|
|
27457
|
+
const where = shortPath ? ` ${shortPath}` : "";
|
|
27458
|
+
let summary;
|
|
27459
|
+
if (direction === "result") {
|
|
27460
|
+
summary = shortPath ? `appeared in the output of reading${where}` : "appeared in tool output";
|
|
27461
|
+
} else {
|
|
27462
|
+
switch (toolName) {
|
|
27463
|
+
case "Read":
|
|
27464
|
+
summary = `read from${where || " a file"}`;
|
|
27465
|
+
break;
|
|
27466
|
+
case "Write":
|
|
27467
|
+
summary = `written to${where || " a file"}`;
|
|
27468
|
+
break;
|
|
27469
|
+
case "Edit":
|
|
27470
|
+
case "NotebookEdit":
|
|
27471
|
+
summary = `edited into${where || " a file"}`;
|
|
27472
|
+
break;
|
|
27473
|
+
case "Bash":
|
|
27474
|
+
summary = "passed in a shell command";
|
|
27475
|
+
break;
|
|
27476
|
+
default:
|
|
27477
|
+
summary = `sent to the ${toolName} tool`;
|
|
27478
|
+
}
|
|
27479
|
+
}
|
|
27480
|
+
return { summary, toolName, direction };
|
|
27481
|
+
}
|
|
27482
|
+
var MAX_SIGHTINGS = 5, FINDING_TTL_DAYS = 90, MAX_FINDINGS = 500, LEAK_RECORD_SCHEMA_VERSION = 1;
|
|
27483
|
+
|
|
27484
|
+
// src/audit/leak-store.ts
|
|
27485
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
27486
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync20, readFileSync as readFileSync26 } from "node:fs";
|
|
27487
|
+
import { dirname as dirname16 } from "node:path";
|
|
27488
|
+
function readJson(path) {
|
|
27489
|
+
try {
|
|
27490
|
+
if (!existsSync31(path))
|
|
27491
|
+
return null;
|
|
27492
|
+
return JSON.parse(readFileSync26(path, "utf8"));
|
|
27493
|
+
} catch {
|
|
27494
|
+
return null;
|
|
27495
|
+
}
|
|
27496
|
+
}
|
|
27497
|
+
function readLeakIdentity(home) {
|
|
27498
|
+
const existing = readJson(auditLeakIdentityFile(home));
|
|
27499
|
+
if (existing && typeof existing.salt === "string" && existing.salt.length >= 32) {
|
|
27500
|
+
return {
|
|
27501
|
+
salt: existing.salt,
|
|
27502
|
+
dismissed: existing.dismissed ?? []
|
|
27503
|
+
};
|
|
27504
|
+
}
|
|
27505
|
+
const minted = { salt: randomBytes2(32).toString("hex"), dismissed: [] };
|
|
27506
|
+
writeLeakIdentity(minted, home);
|
|
27507
|
+
return minted;
|
|
27508
|
+
}
|
|
27509
|
+
function writeLeakIdentity(identity, home) {
|
|
27510
|
+
const path = auditLeakIdentityFile(home);
|
|
27511
|
+
try {
|
|
27512
|
+
mkdirSync20(dirname16(path), { recursive: true });
|
|
27513
|
+
writeJsonAtomically(path, identity, { mode: FILE_MODE });
|
|
27514
|
+
return true;
|
|
27515
|
+
} catch {
|
|
27516
|
+
return false;
|
|
27517
|
+
}
|
|
27518
|
+
}
|
|
27519
|
+
function sanitizeFinding(raw) {
|
|
27520
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
27521
|
+
return null;
|
|
27522
|
+
const f = raw;
|
|
27523
|
+
if (typeof f.id !== "string" || !isFindingId(f.id))
|
|
27524
|
+
return null;
|
|
27525
|
+
const fp = f.fingerprint;
|
|
27526
|
+
if (!fp || typeof fp !== "object" || typeof fp.display !== "string" || typeof fp.label !== "string") {
|
|
27527
|
+
return null;
|
|
27528
|
+
}
|
|
27529
|
+
const sightings = Array.isArray(f.sightings) ? f.sightings.filter((s) => {
|
|
27530
|
+
if (!s || typeof s !== "object")
|
|
27531
|
+
return false;
|
|
27532
|
+
const m = s.mechanism;
|
|
27533
|
+
return !!m && typeof m === "object" && typeof m.summary === "string";
|
|
27534
|
+
}) : [];
|
|
27535
|
+
return {
|
|
27536
|
+
...f,
|
|
27537
|
+
fingerprint: {
|
|
27538
|
+
display: fp.display,
|
|
27539
|
+
label: fp.label,
|
|
27540
|
+
length: typeof fp.length === "number" && Number.isFinite(fp.length) ? fp.length : 0,
|
|
27541
|
+
attributed: fp.attributed === true
|
|
27542
|
+
},
|
|
27543
|
+
name: typeof f.name === "string" ? f.name : null,
|
|
27544
|
+
firstSeen: typeof f.firstSeen === "string" ? f.firstSeen : "",
|
|
27545
|
+
lastSeen: typeof f.lastSeen === "string" ? f.lastSeen : "",
|
|
27546
|
+
occurrences: typeof f.occurrences === "number" && Number.isFinite(f.occurrences) ? f.occurrences : sightings.length,
|
|
27547
|
+
sightings
|
|
27548
|
+
};
|
|
27549
|
+
}
|
|
27550
|
+
function readLeakRecord(home) {
|
|
27551
|
+
const identity = readLeakIdentity(home);
|
|
27552
|
+
const raw = readJson(auditLeaksFile(home));
|
|
27553
|
+
if (!raw || raw.schemaVersion !== LEAK_RECORD_SCHEMA_VERSION || !Array.isArray(raw.findings)) {
|
|
27554
|
+
return emptyRecord(identity.salt, new Date().toISOString());
|
|
27555
|
+
}
|
|
27556
|
+
const findings = raw.findings.map(sanitizeFinding).filter((f) => f !== null);
|
|
27557
|
+
return { ...raw, findings, salt: identity.salt };
|
|
27558
|
+
}
|
|
27559
|
+
function writeLeakRecord(record, home, nowMs = Date.now()) {
|
|
27560
|
+
const path = auditLeaksFile(home);
|
|
27561
|
+
try {
|
|
27562
|
+
mkdirSync20(dirname16(path), { recursive: true });
|
|
27563
|
+
const pruned = pruneRecord(record, nowMs);
|
|
27564
|
+
pruned.updatedAt = new Date(nowMs).toISOString();
|
|
27565
|
+
writeJsonAtomically(path, pruned, { mode: FILE_MODE });
|
|
27566
|
+
return true;
|
|
27567
|
+
} catch {
|
|
27568
|
+
return false;
|
|
27569
|
+
}
|
|
27570
|
+
}
|
|
27571
|
+
function activeFindings(record, home) {
|
|
27572
|
+
const dismissed = new Set(readLeakIdentity(home).dismissed);
|
|
27573
|
+
return record.findings.filter((f) => !dismissed.has(f.id)).sort((a, b) => a.lastSeen < b.lastSeen ? 1 : a.lastSeen > b.lastSeen ? -1 : 0);
|
|
27574
|
+
}
|
|
27575
|
+
var FILE_MODE = 384;
|
|
27576
|
+
var init_leak_store = __esm(() => {
|
|
27577
|
+
init_fp_home();
|
|
27578
|
+
init_atomic_write();
|
|
27579
|
+
init_leak_fingerprint();
|
|
27580
|
+
});
|
|
27581
|
+
|
|
27697
27582
|
// src/audit/redact-example.ts
|
|
27698
27583
|
import { homedir as homedir27 } from "node:os";
|
|
27699
27584
|
function maskTruncatedSecret(input) {
|
|
@@ -27837,7 +27722,7 @@ var init_redact_example = __esm(() => {
|
|
|
27837
27722
|
|
|
27838
27723
|
// src/audit/cache.ts
|
|
27839
27724
|
import { createHash as createHash8 } from "node:crypto";
|
|
27840
|
-
import { existsSync as
|
|
27725
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync21, readFileSync as readFileSync27, writeFileSync as writeFileSync18, chmodSync as chmodSync6, openSync, readSync, closeSync } from "node:fs";
|
|
27841
27726
|
import { join as join33 } from "node:path";
|
|
27842
27727
|
function getEngineVersion() {
|
|
27843
27728
|
if (cachedEngineVersion)
|
|
@@ -27898,7 +27783,7 @@ function readCachedTranscript(transcriptPath, mtimeMs, sizeBytes) {
|
|
|
27898
27783
|
if (sizeBytes === 0)
|
|
27899
27784
|
return null;
|
|
27900
27785
|
const cachePath = getCachePathFor(transcriptPath);
|
|
27901
|
-
if (!
|
|
27786
|
+
if (!existsSync32(cachePath))
|
|
27902
27787
|
return null;
|
|
27903
27788
|
try {
|
|
27904
27789
|
const raw = readFileSync27(cachePath, "utf-8");
|
|
@@ -27942,7 +27827,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result,
|
|
|
27942
27827
|
return;
|
|
27943
27828
|
const cachePath = getCachePathFor(transcriptPath);
|
|
27944
27829
|
try {
|
|
27945
|
-
|
|
27830
|
+
mkdirSync21(auditCacheDir(), { recursive: true });
|
|
27946
27831
|
const entry = {
|
|
27947
27832
|
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
27948
27833
|
cachedAt: Date.now(),
|
|
@@ -27961,9 +27846,9 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result,
|
|
|
27961
27846
|
entry.detectorState = encodeDetectorState(resume.detectorState);
|
|
27962
27847
|
}
|
|
27963
27848
|
}
|
|
27964
|
-
|
|
27849
|
+
writeFileSync18(cachePath, JSON.stringify(entry), { encoding: "utf-8", mode: 384 });
|
|
27965
27850
|
try {
|
|
27966
|
-
|
|
27851
|
+
chmodSync6(cachePath, 384);
|
|
27967
27852
|
} catch {}
|
|
27968
27853
|
} catch {}
|
|
27969
27854
|
}
|
|
@@ -28480,8 +28365,10 @@ async function runAuditInner(opts, startedAt) {
|
|
|
28480
28365
|
}
|
|
28481
28366
|
const coversAllHistory = opts.clis === undefined && opts.projects === undefined && opts.since === undefined && discoveryErrors === 0 && errors === 0 && skipped === 0;
|
|
28482
28367
|
const newFindingIds = persistLeaks(perTranscript, coversAllHistory);
|
|
28368
|
+
const leakIds = [...new Set(perTranscript.flatMap((t) => (t.leaks ?? []).map((leak) => leak.id)))];
|
|
28483
28369
|
const auditResult = {
|
|
28484
28370
|
version: 2,
|
|
28371
|
+
leakIds,
|
|
28485
28372
|
newLeakIds: newFindingIds,
|
|
28486
28373
|
scannedAt: new Date(startedAt).toISOString(),
|
|
28487
28374
|
scope: {
|
|
@@ -28537,11 +28424,11 @@ var init_audit = __esm(() => {
|
|
|
28537
28424
|
import {
|
|
28538
28425
|
closeSync as closeSync2,
|
|
28539
28426
|
linkSync,
|
|
28540
|
-
mkdirSync as
|
|
28427
|
+
mkdirSync as mkdirSync22,
|
|
28541
28428
|
openSync as openSync2,
|
|
28542
28429
|
readFileSync as readFileSync28,
|
|
28543
28430
|
unlinkSync as unlinkSync4,
|
|
28544
|
-
writeFileSync as
|
|
28431
|
+
writeFileSync as writeFileSync19,
|
|
28545
28432
|
writeSync
|
|
28546
28433
|
} from "node:fs";
|
|
28547
28434
|
function acquireAuditLock(source, now = Date.now()) {
|
|
@@ -28616,7 +28503,7 @@ function writeLockExclusive(path, info) {
|
|
|
28616
28503
|
const body = JSON.stringify(info);
|
|
28617
28504
|
const staging = `${path}.${process.pid}.tmp`;
|
|
28618
28505
|
try {
|
|
28619
|
-
|
|
28506
|
+
writeFileSync19(staging, body, { mode: 384 });
|
|
28620
28507
|
} catch {
|
|
28621
28508
|
return false;
|
|
28622
28509
|
}
|
|
@@ -28650,8 +28537,8 @@ function createThenWrite(path, body) {
|
|
|
28650
28537
|
}
|
|
28651
28538
|
}
|
|
28652
28539
|
function ensureRunDir() {
|
|
28653
|
-
|
|
28654
|
-
|
|
28540
|
+
mkdirSync22(failproofaiHome(), { recursive: true });
|
|
28541
|
+
mkdirSync22(runDir(), { recursive: true, mode: 448 });
|
|
28655
28542
|
}
|
|
28656
28543
|
var AUDIT_LOCK_MAX_AGE_MS;
|
|
28657
28544
|
var init_audit_lock = __esm(() => {
|
|
@@ -28660,7 +28547,7 @@ var init_audit_lock = __esm(() => {
|
|
|
28660
28547
|
});
|
|
28661
28548
|
|
|
28662
28549
|
// src/audit/dashboard-cache.ts
|
|
28663
|
-
import { existsSync as
|
|
28550
|
+
import { existsSync as existsSync33, readFileSync as readFileSync29 } from "node:fs";
|
|
28664
28551
|
function getCachePath() {
|
|
28665
28552
|
return auditDashboardFile();
|
|
28666
28553
|
}
|
|
@@ -28680,7 +28567,7 @@ function writeDashboardCache(params, result) {
|
|
|
28680
28567
|
}
|
|
28681
28568
|
function readDashboardCacheMeta() {
|
|
28682
28569
|
const cachePath = getCachePath();
|
|
28683
|
-
if (!
|
|
28570
|
+
if (!existsSync33(cachePath))
|
|
28684
28571
|
return null;
|
|
28685
28572
|
try {
|
|
28686
28573
|
const raw = readFileSync29(cachePath, "utf-8");
|
|
@@ -28907,15 +28794,15 @@ var init_api_server_client = __esm(() => {
|
|
|
28907
28794
|
});
|
|
28908
28795
|
|
|
28909
28796
|
// lib/auth/auth-store.ts
|
|
28910
|
-
import { existsSync as
|
|
28911
|
-
import { join as join34, resolve as
|
|
28797
|
+
import { existsSync as existsSync34, readFileSync as readFileSync30, readdirSync as readdirSync18, rmSync as rmSync13 } from "node:fs";
|
|
28798
|
+
import { join as join34, resolve as resolve24 } from "node:path";
|
|
28912
28799
|
function getAuthFilePath() {
|
|
28913
28800
|
const override = process.env.FAILPROOFAI_AUTH_DIR;
|
|
28914
28801
|
return override ? join34(override, "session.json") : auditSessionFile();
|
|
28915
28802
|
}
|
|
28916
28803
|
function readAuth() {
|
|
28917
28804
|
const p = getAuthFilePath();
|
|
28918
|
-
if (!
|
|
28805
|
+
if (!existsSync34(p))
|
|
28919
28806
|
return null;
|
|
28920
28807
|
try {
|
|
28921
28808
|
const raw = readFileSync30(p, "utf-8");
|
|
@@ -28942,18 +28829,18 @@ function writeAuth(auth) {
|
|
|
28942
28829
|
}
|
|
28943
28830
|
function deleteAuth() {
|
|
28944
28831
|
const p = getAuthFilePath();
|
|
28945
|
-
if (
|
|
28946
|
-
|
|
28832
|
+
if (existsSync34(p))
|
|
28833
|
+
rmSync13(p, { force: true });
|
|
28947
28834
|
try {
|
|
28948
28835
|
const root = migrationsDir();
|
|
28949
|
-
if (!
|
|
28836
|
+
if (!existsSync34(root))
|
|
28950
28837
|
return;
|
|
28951
|
-
for (const entry of
|
|
28838
|
+
for (const entry of readdirSync18(root)) {
|
|
28952
28839
|
if (!entry.startsWith("backup-layout"))
|
|
28953
28840
|
continue;
|
|
28954
|
-
const copy =
|
|
28955
|
-
if (
|
|
28956
|
-
|
|
28841
|
+
const copy = resolve24(root, entry, "auth.json");
|
|
28842
|
+
if (existsSync34(copy))
|
|
28843
|
+
rmSync13(copy, { force: true });
|
|
28957
28844
|
}
|
|
28958
28845
|
} catch {}
|
|
28959
28846
|
}
|
|
@@ -29085,7 +28972,11 @@ function selectLeaks(findings, from, to) {
|
|
|
29085
28972
|
const last = ts(f.lastSeen);
|
|
29086
28973
|
if (last !== null && (last < lo || last > hi))
|
|
29087
28974
|
continue;
|
|
29088
|
-
const seen = f.sightings?.
|
|
28975
|
+
const seen = f.sightings?.reduce((latest, candidate) => {
|
|
28976
|
+
if (!latest)
|
|
28977
|
+
return candidate;
|
|
28978
|
+
return (ts(candidate.at) ?? 0) >= (ts(latest.at) ?? 0) ? candidate : latest;
|
|
28979
|
+
}, undefined);
|
|
29089
28980
|
out.push({
|
|
29090
28981
|
id: f.id,
|
|
29091
28982
|
display: f.fingerprint?.display ?? "[credential]",
|
|
@@ -29117,7 +29008,7 @@ function buildHarmReport(result, lastReportedAt, intervalDays, leakFindings = []
|
|
|
29117
29008
|
window_from: from.toISOString(),
|
|
29118
29009
|
window_to: windowTo.toISOString(),
|
|
29119
29010
|
harmful: selectHarmful(result, from, windowTo, { includeUnplaceable: isFirstReport }),
|
|
29120
|
-
leaks: selectLeaks(leakFindings, from, windowTo)
|
|
29011
|
+
leaks: selectLeaks(leakFindings, from, windowTo).slice(0, 1)
|
|
29121
29012
|
};
|
|
29122
29013
|
}
|
|
29123
29014
|
var HARMFUL_SEVERITIES, ALSO_HARMFUL;
|
|
@@ -29128,12 +29019,12 @@ var init_harm_report = __esm(() => {
|
|
|
29128
29019
|
});
|
|
29129
29020
|
|
|
29130
29021
|
// src/audit/machine-store.ts
|
|
29131
|
-
import { existsSync as
|
|
29022
|
+
import { existsSync as existsSync35, readFileSync as readFileSync31, rmSync as rmSync14 } from "node:fs";
|
|
29132
29023
|
import { hostname as hostname5 } from "node:os";
|
|
29133
29024
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
29134
29025
|
function readMachineIdentity(home) {
|
|
29135
29026
|
const path = auditMachineFile(home);
|
|
29136
|
-
if (!
|
|
29027
|
+
if (!existsSync35(path))
|
|
29137
29028
|
return null;
|
|
29138
29029
|
try {
|
|
29139
29030
|
const parsed = JSON.parse(readFileSync31(path, "utf8"));
|
|
@@ -29182,20 +29073,20 @@ var init_machine_store = __esm(() => {
|
|
|
29182
29073
|
// src/audit/report-harm.ts
|
|
29183
29074
|
async function reportHarm(result) {
|
|
29184
29075
|
let auto = false;
|
|
29185
|
-
let consentedAt;
|
|
29186
29076
|
let intervalDays = 7;
|
|
29187
29077
|
try {
|
|
29188
29078
|
const config = readConfig();
|
|
29189
29079
|
auto = config.audit.auto;
|
|
29190
|
-
consentedAt = config.audit.reportsConsentedAt;
|
|
29191
29080
|
intervalDays = config.audit.intervalDays;
|
|
29192
29081
|
} catch {
|
|
29193
29082
|
return { kind: "disabled" };
|
|
29194
29083
|
}
|
|
29195
29084
|
if (!auto)
|
|
29196
29085
|
return { kind: "disabled" };
|
|
29197
|
-
|
|
29198
|
-
|
|
29086
|
+
const prior = readMachineIdentity();
|
|
29087
|
+
const report = buildHarmReport(result, prior?.last_reported_at, intervalDays, activeFindings(readLeakRecord()));
|
|
29088
|
+
if (report.leaks.length === 0)
|
|
29089
|
+
return { kind: "no-leak" };
|
|
29199
29090
|
const auth = await getValidAccessToken();
|
|
29200
29091
|
if (!auth) {
|
|
29201
29092
|
return { kind: "signed-out" };
|
|
@@ -29206,8 +29097,6 @@ async function reportHarm(result) {
|
|
|
29206
29097
|
} catch (err) {
|
|
29207
29098
|
return { kind: "failed", error: err instanceof Error ? err.message : String(err) };
|
|
29208
29099
|
}
|
|
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
29100
|
try {
|
|
29212
29101
|
const res = await submitAuditReport(auth.access_token, {
|
|
29213
29102
|
machine_id: identity.machine_id,
|
|
@@ -29221,7 +29110,7 @@ async function reportHarm(result) {
|
|
|
29221
29110
|
try {
|
|
29222
29111
|
recordReportWatermark(res.next_window_from);
|
|
29223
29112
|
} catch {}
|
|
29224
|
-
return res.emailed ? { kind: "sent",
|
|
29113
|
+
return res.emailed ? { kind: "sent", leaks: report.leaks.length } : { kind: "held", leaks: report.leaks.length, reason: res.reason ?? "not_sent" };
|
|
29225
29114
|
} catch (err) {
|
|
29226
29115
|
const error = err instanceof AuthApiError ? `${err.code}: ${err.message}` : err instanceof Error ? err.message : String(err);
|
|
29227
29116
|
return { kind: "failed", error };
|
|
@@ -29230,17 +29119,16 @@ async function reportHarm(result) {
|
|
|
29230
29119
|
function describeOutcome2(outcome) {
|
|
29231
29120
|
switch (outcome.kind) {
|
|
29232
29121
|
case "disabled":
|
|
29122
|
+
case "no-leak":
|
|
29233
29123
|
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
29124
|
case "signed-out":
|
|
29237
|
-
return "failproofai:
|
|
29125
|
+
return "failproofai: a credential exposure was found, but no email is configured — run `failproofai audit --schedule --email you@example.com`";
|
|
29238
29126
|
case "sent":
|
|
29239
|
-
return
|
|
29127
|
+
return "failproofai: emailed the most recent credential exposure";
|
|
29240
29128
|
case "held":
|
|
29241
|
-
return `failproofai:
|
|
29129
|
+
return `failproofai: credential exposure reported, no email (${outcome.reason})`;
|
|
29242
29130
|
case "failed":
|
|
29243
|
-
return `failproofai: could not send the
|
|
29131
|
+
return `failproofai: could not send the credential alert: ${outcome.error}`;
|
|
29244
29132
|
}
|
|
29245
29133
|
}
|
|
29246
29134
|
var init_report_harm = __esm(() => {
|
|
@@ -29514,6 +29402,15 @@ var init_desktop_notify = __esm(() => {
|
|
|
29514
29402
|
];
|
|
29515
29403
|
});
|
|
29516
29404
|
|
|
29405
|
+
// src/hooks/notice.ts
|
|
29406
|
+
function desktopLeakNotice(email = "held") {
|
|
29407
|
+
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.";
|
|
29408
|
+
return {
|
|
29409
|
+
title: "failproofai audit needs review",
|
|
29410
|
+
body: "Possible credential exposure was found in your agent transcripts. " + `Run failproofai audit to verify the matches and rotate anything real. ${followUp}`
|
|
29411
|
+
};
|
|
29412
|
+
}
|
|
29413
|
+
|
|
29517
29414
|
// src/audit/cli.ts
|
|
29518
29415
|
function colorOn() {
|
|
29519
29416
|
if (process.env.NO_COLOR && process.env.NO_COLOR !== "")
|
|
@@ -29706,10 +29603,8 @@ var init_cli = __esm(() => {
|
|
|
29706
29603
|
init_report_harm();
|
|
29707
29604
|
init_desktop_notify();
|
|
29708
29605
|
init_macos_notifier();
|
|
29709
|
-
init_leak_notice();
|
|
29710
|
-
init_notice();
|
|
29711
|
-
init_leak_store();
|
|
29712
29606
|
init_fp_config();
|
|
29607
|
+
init_auth_store();
|
|
29713
29608
|
init_tui();
|
|
29714
29609
|
init_package();
|
|
29715
29610
|
AUDIT_STAGES = [
|
|
@@ -29728,9 +29623,9 @@ var init_cli = __esm(() => {
|
|
|
29728
29623
|
});
|
|
29729
29624
|
|
|
29730
29625
|
// src/hooks/configure-wizard.ts
|
|
29731
|
-
import { existsSync as
|
|
29626
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync23, writeFileSync as writeFileSync20, readFileSync as readFileSync32 } from "node:fs";
|
|
29732
29627
|
import { homedir as homedir28 } from "node:os";
|
|
29733
|
-
import { dirname as dirname17, resolve as
|
|
29628
|
+
import { dirname as dirname17, resolve as resolve25, sep as sep5 } from "node:path";
|
|
29734
29629
|
async function emit(event, props) {
|
|
29735
29630
|
try {
|
|
29736
29631
|
await trackHookEvent2(getInstanceId2(), event, props);
|
|
@@ -29753,7 +29648,7 @@ function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
|
29753
29648
|
const path = getConfigPathForScope(scope, cwd);
|
|
29754
29649
|
let config = {};
|
|
29755
29650
|
try {
|
|
29756
|
-
if (
|
|
29651
|
+
if (existsSync36(path))
|
|
29757
29652
|
config = JSON.parse(readFileSync32(path, "utf8"));
|
|
29758
29653
|
} catch {
|
|
29759
29654
|
return;
|
|
@@ -29763,7 +29658,7 @@ function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
|
29763
29658
|
else
|
|
29764
29659
|
config.customPoliciesEnabled = false;
|
|
29765
29660
|
try {
|
|
29766
|
-
|
|
29661
|
+
writeFileSync20(path, JSON.stringify(config, null, 2) + `
|
|
29767
29662
|
`, "utf8");
|
|
29768
29663
|
} catch {}
|
|
29769
29664
|
}
|
|
@@ -29794,7 +29689,7 @@ function describeCustomPolicies(cwd) {
|
|
|
29794
29689
|
const scopes = [];
|
|
29795
29690
|
let fileCount = 0;
|
|
29796
29691
|
const dirs = [
|
|
29797
|
-
{ dir:
|
|
29692
|
+
{ dir: resolve25(cwd, ".failproofai", "policies"), label: "project" },
|
|
29798
29693
|
{ dir: customPoliciesDir(), label: "global" }
|
|
29799
29694
|
];
|
|
29800
29695
|
for (const { dir, label } of dirs) {
|
|
@@ -29805,7 +29700,7 @@ function describeCustomPolicies(cwd) {
|
|
|
29805
29700
|
fileCount += found.length;
|
|
29806
29701
|
}
|
|
29807
29702
|
for (const name of findSkippedPolicyFiles(dir)) {
|
|
29808
|
-
warnings.push(`! ${homeify(
|
|
29703
|
+
warnings.push(`! ${homeify(resolve25(dir, name))} is NOT loaded — rename to ` + `${name.replace(/\.(js|mjs|ts)$/, "-policies.$1")}`);
|
|
29809
29704
|
}
|
|
29810
29705
|
}
|
|
29811
29706
|
return { active, warnings, fileCount, scopes };
|
|
@@ -29898,8 +29793,8 @@ function firstRunMarkerPath() {
|
|
|
29898
29793
|
}
|
|
29899
29794
|
function markLauncherSeen() {
|
|
29900
29795
|
try {
|
|
29901
|
-
|
|
29902
|
-
|
|
29796
|
+
mkdirSync23(dirname17(firstRunMarkerPath()), { recursive: true });
|
|
29797
|
+
writeFileSync20(firstRunMarkerPath(), "1", "utf8");
|
|
29903
29798
|
} catch {}
|
|
29904
29799
|
}
|
|
29905
29800
|
function retryProbe() {
|
|
@@ -29977,6 +29872,8 @@ async function runConfigureWizard(io = {}, answers = {}) {
|
|
|
29977
29872
|
const cwd = process.cwd();
|
|
29978
29873
|
const unattended = !stdin.isTTY || !stdout.isTTY;
|
|
29979
29874
|
const preAnswered = Boolean(answers.token);
|
|
29875
|
+
const initialAudit = readConfigRaw().raw.audit;
|
|
29876
|
+
const hadExplicitAuditAuto = !!initialAudit && typeof initialAudit === "object" && !Array.isArray(initialAudit) && typeof initialAudit.auto === "boolean";
|
|
29980
29877
|
if (typeof process.getuid === "function" && process.getuid() === 0 && process.env.SUDO_USER) {
|
|
29981
29878
|
stdout.write(`Run failproofai config as ${process.env.SUDO_USER}, not under sudo.
|
|
29982
29879
|
` + `Everything it configures is per-user — hooks, policies and the daemon's own
|
|
@@ -30299,8 +30196,21 @@ Hooks keep enforcing; scheduled audits stay off until it is.
|
|
|
30299
30196
|
}
|
|
30300
30197
|
if (daemonInstalled) {
|
|
30301
30198
|
setDaemonConfigured(true, version2);
|
|
30199
|
+
if (!hadExplicitAuditAuto) {
|
|
30200
|
+
try {
|
|
30201
|
+
updateConfig({ audit: { auto: true } });
|
|
30202
|
+
} catch {}
|
|
30203
|
+
}
|
|
30302
30204
|
pruneOldDaemonBinaries();
|
|
30303
|
-
installMacNotifier();
|
|
30205
|
+
const notifier = installMacNotifier();
|
|
30206
|
+
if (process.platform === "darwin" && !notifier.installed) {
|
|
30207
|
+
hookLogWarn(`macOS notification helper was not installed: ${notifier.reason ?? "unknown error"}`);
|
|
30208
|
+
stdout.write(`
|
|
30209
|
+
System notifications could not be installed. Scheduled scans and email alerts
|
|
30210
|
+
still work; re-run \`failproofai config\` after checking the local LaunchAgent.
|
|
30211
|
+
|
|
30212
|
+
`);
|
|
30213
|
+
}
|
|
30304
30214
|
}
|
|
30305
30215
|
const applied = emit("configure_applied", {
|
|
30306
30216
|
target,
|
|
@@ -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
|
|
30792
|
+
import { chmodSync as chmodSync7, 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]);
|
|
@@ -30948,16 +30859,16 @@ var init_fp_home2 = () => {};
|
|
|
30948
30859
|
|
|
30949
30860
|
// src/hooks/migrations.ts
|
|
30950
30861
|
import {
|
|
30951
|
-
chmodSync as
|
|
30862
|
+
chmodSync as chmodSync8,
|
|
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,19 +30898,19 @@ 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
|
+
chmodSync8(secret, 384);
|
|
31003
30914
|
} catch {}
|
|
31004
30915
|
}
|
|
31005
30916
|
writeVersionFile({ layout: 4 });
|
|
@@ -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 = {}) {
|
|
@@ -31734,6 +31645,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31734
31645
|
if (found.daemonConfigured) {
|
|
31735
31646
|
plan.push(` • stop requiring the daemon (policies go back to evaluating in-process)`);
|
|
31736
31647
|
}
|
|
31648
|
+
let removeDaemon = opts.purge === true;
|
|
31737
31649
|
if (found.serviceInstalled) {
|
|
31738
31650
|
plan.push(opts.purge || opts.yes ? ` • stop, disable and delete the service at ${found.servicePath} — needs sudo` : ` • ask whether to remove the service at ${found.servicePath} (kept unless you say so)`);
|
|
31739
31651
|
}
|
|
@@ -31793,7 +31705,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31793
31705
|
}
|
|
31794
31706
|
}
|
|
31795
31707
|
if (found.serviceInstalled) {
|
|
31796
|
-
|
|
31708
|
+
removeDaemon = opts.purge || opts.yes ? true : await opts.confirmDaemon?.() ?? false;
|
|
31797
31709
|
if (!removeDaemon) {
|
|
31798
31710
|
lines.push(`• kept the daemon service at ${found.servicePath}`, ` Remove it later with: failproofai uninstall --purge`);
|
|
31799
31711
|
} else {
|
|
@@ -31803,7 +31715,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31803
31715
|
} catch {}
|
|
31804
31716
|
try {
|
|
31805
31717
|
await uninstallDaemonService();
|
|
31806
|
-
if (found.servicePath &&
|
|
31718
|
+
if (found.servicePath && existsSync42(found.servicePath)) {
|
|
31807
31719
|
failures.push(`the service at ${found.servicePath} is still there (most often: no sudo). ` + `Remove it with the commands below.`);
|
|
31808
31720
|
} else {
|
|
31809
31721
|
lines.push(`✓ stopped and removed the daemon service`);
|
|
@@ -31813,12 +31725,12 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31813
31725
|
}
|
|
31814
31726
|
}
|
|
31815
31727
|
}
|
|
31816
|
-
if (opts.purge ||
|
|
31728
|
+
if (opts.purge || removeDaemon) {
|
|
31817
31729
|
uninstallMacNotifier();
|
|
31818
31730
|
}
|
|
31819
31731
|
if (opts.purge && found.homeExists) {
|
|
31820
31732
|
try {
|
|
31821
|
-
|
|
31733
|
+
rmSync17(failproofaiHome(), { recursive: true, force: true });
|
|
31822
31734
|
purged = true;
|
|
31823
31735
|
lines.push(`✓ deleted ${failproofaiHome()}`);
|
|
31824
31736
|
} catch (err) {
|
|
@@ -31829,7 +31741,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
31829
31741
|
lines.push(``, `Not everything could be removed:`);
|
|
31830
31742
|
for (const f of failures)
|
|
31831
31743
|
lines.push(` ✗ ${f}`);
|
|
31832
|
-
if (found.servicePath &&
|
|
31744
|
+
if (found.servicePath && existsSync42(found.servicePath)) {
|
|
31833
31745
|
lines.push(``, `To remove the service by hand:`, ...manualServiceRemoval(found.servicePath), ``, `(\`${daemonStatusCommand()}\` shows its current state.)`);
|
|
31834
31746
|
}
|
|
31835
31747
|
return { exitCode: 1, lines, planLines, purged };
|
|
@@ -31864,8 +31776,8 @@ var init_uninstall_cli = __esm(() => {
|
|
|
31864
31776
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
31865
31777
|
import { homedir as homedir31, tmpdir as tmpdir4 } from "node:os";
|
|
31866
31778
|
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
|
|
31779
|
+
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";
|
|
31780
|
+
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
31781
|
function parseList(rest, flag) {
|
|
31870
31782
|
const idx = rest.findIndex((a) => a === flag || a.startsWith(`${flag}=`));
|
|
31871
31783
|
if (idx === -1)
|
|
@@ -31965,7 +31877,7 @@ async function build(rest) {
|
|
|
31965
31877
|
const version = flag("version");
|
|
31966
31878
|
const commit = flag("commit");
|
|
31967
31879
|
const effect = flag("effect") ?? "enforce";
|
|
31968
|
-
const outDir =
|
|
31880
|
+
const outDir = resolve29(flag("out") ?? "dist-pack");
|
|
31969
31881
|
if (!entry || !id || !version) {
|
|
31970
31882
|
return fail2([
|
|
31971
31883
|
"Usage: failproofai publish <entry.mjs> --repo <owner>/<repo> --version <version>",
|
|
@@ -31978,8 +31890,8 @@ async function build(rest) {
|
|
|
31978
31890
|
} catch (err) {
|
|
31979
31891
|
return fail2([err instanceof Error ? err.message : String(err)]);
|
|
31980
31892
|
}
|
|
31981
|
-
const entryPath =
|
|
31982
|
-
if (!
|
|
31893
|
+
const entryPath = resolve29(entry);
|
|
31894
|
+
if (!existsSync43(entryPath))
|
|
31983
31895
|
return fail2([`No such file: ${entryPath}`]);
|
|
31984
31896
|
const source = readFileSync36(entryPath, "utf8");
|
|
31985
31897
|
const localImport = /(?:^|\n)\s*(?:import|export)[^;\n]*from\s+["'](\.[^"']*)["']/.exec(source);
|
|
@@ -32037,13 +31949,13 @@ async function build(rest) {
|
|
|
32037
31949
|
policies
|
|
32038
31950
|
}, null, 2) + `
|
|
32039
31951
|
`;
|
|
32040
|
-
|
|
32041
|
-
const manifestPath =
|
|
32042
|
-
const entryOut =
|
|
32043
|
-
|
|
31952
|
+
mkdirSync29(outDir, { recursive: true });
|
|
31953
|
+
const manifestPath = resolve29(outDir, PACK_MANIFEST_ASSET);
|
|
31954
|
+
const entryOut = resolve29(outDir, PACK_ENTRY_ASSET);
|
|
31955
|
+
writeFileSync26(manifestPath, manifest, "utf8");
|
|
32044
31956
|
copyFileSync4(entryPath, entryOut);
|
|
32045
31957
|
const sha = (bytes) => createHash9("sha256").update(bytes).digest("hex");
|
|
32046
|
-
|
|
31958
|
+
writeFileSync26(resolve29(outDir, PACK_CHECKSUMS_ASSET), `${sha(manifest)} ${PACK_MANIFEST_ASSET}
|
|
32047
31959
|
${sha(readFileSync36(entryOut))} ${PACK_ENTRY_ASSET}
|
|
32048
31960
|
`, "utf8");
|
|
32049
31961
|
const on = policies.filter((p) => p.defaultEnabled).length;
|
|
@@ -32173,12 +32085,12 @@ async function scaffold(target) {
|
|
|
32173
32085
|
return ok2(["Nothing written."]);
|
|
32174
32086
|
chosen = answer.trim();
|
|
32175
32087
|
}
|
|
32176
|
-
const path =
|
|
32177
|
-
if (
|
|
32088
|
+
const path = resolve29(withPolicyExtension(chosen ?? "my-policies"));
|
|
32089
|
+
if (existsSync43(path)) {
|
|
32178
32090
|
return fail2([`${path} already exists — name a different file, or edit that one.`]);
|
|
32179
32091
|
}
|
|
32180
|
-
|
|
32181
|
-
|
|
32092
|
+
mkdirSync29(resolve29(path, ".."), { recursive: true });
|
|
32093
|
+
writeFileSync26(path, `import { customPolicies, allow, deny } from "failproofai";
|
|
32182
32094
|
|
|
32183
32095
|
// One file, no relative imports: only this entry is digest-pinned, so a pack
|
|
32184
32096
|
// that imported siblings could not honestly claim to be verified.
|
|
@@ -32215,7 +32127,7 @@ customPolicies.add({
|
|
|
32215
32127
|
function inferRepo(entryPath) {
|
|
32216
32128
|
try {
|
|
32217
32129
|
const url = execFileSync5("git", ["remote", "get-url", "origin"], {
|
|
32218
|
-
cwd:
|
|
32130
|
+
cwd: resolve29(entryPath, ".."),
|
|
32219
32131
|
encoding: "utf8",
|
|
32220
32132
|
stdio: ["ignore", "pipe", "ignore"],
|
|
32221
32133
|
timeout: 5000
|
|
@@ -32227,7 +32139,7 @@ function inferRepo(entryPath) {
|
|
|
32227
32139
|
}
|
|
32228
32140
|
}
|
|
32229
32141
|
function inferCommit(entryPath, outDir, sources) {
|
|
32230
|
-
const cwd =
|
|
32142
|
+
const cwd = resolve29(entryPath, "..");
|
|
32231
32143
|
const raw = (args) => {
|
|
32232
32144
|
try {
|
|
32233
32145
|
return execFileSync5("git", args, {
|
|
@@ -32282,9 +32194,9 @@ function realOrSelf(path) {
|
|
|
32282
32194
|
}
|
|
32283
32195
|
}
|
|
32284
32196
|
function sourcesInHead(git, raw, sources) {
|
|
32285
|
-
const paths = sources.map((f) => realOrSelf(
|
|
32197
|
+
const paths = sources.map((f) => realOrSelf(resolve29(f)));
|
|
32286
32198
|
const shown = git(["rev-parse", "--show-toplevel"]);
|
|
32287
|
-
const top = shown === null ? null : realOrSelf(
|
|
32199
|
+
const top = shown === null ? null : realOrSelf(resolve29(shown));
|
|
32288
32200
|
const missing = [];
|
|
32289
32201
|
for (const path of paths) {
|
|
32290
32202
|
const rel = top ? relative5(top, path) : null;
|
|
@@ -32308,7 +32220,7 @@ function sourcesInHead(git, raw, sources) {
|
|
|
32308
32220
|
]);
|
|
32309
32221
|
if (status === null)
|
|
32310
32222
|
return { ok: false, offending: paths, why: "modified" };
|
|
32311
|
-
const dirty = porcelainEntries(status).flatMap((entry) => [entry.path, entry.from].filter(Boolean).map((path) =>
|
|
32223
|
+
const dirty = porcelainEntries(status).flatMap((entry) => [entry.path, entry.from].filter(Boolean).map((path) => resolve29(top ?? ".", path)));
|
|
32312
32224
|
if (dirty.length > 0)
|
|
32313
32225
|
return { ok: false, offending: dirty, why: "modified" };
|
|
32314
32226
|
return { ok: true };
|
|
@@ -32316,19 +32228,19 @@ function sourcesInHead(git, raw, sources) {
|
|
|
32316
32228
|
function skipOutDir(git, entryPath, outDir) {
|
|
32317
32229
|
if (!outDir)
|
|
32318
32230
|
return [];
|
|
32319
|
-
const out =
|
|
32320
|
-
if (
|
|
32231
|
+
const out = resolve29(outDir);
|
|
32232
|
+
if (resolve29(entryPath).startsWith(out + sep6))
|
|
32321
32233
|
return [];
|
|
32322
32234
|
const top = git(["rev-parse", "--show-toplevel"]);
|
|
32323
32235
|
if (!top)
|
|
32324
32236
|
return [];
|
|
32325
|
-
const rel = relative5(
|
|
32237
|
+
const rel = relative5(resolve29(top), out);
|
|
32326
32238
|
if (!rel || rel.startsWith("..") || isAbsolute4(rel))
|
|
32327
32239
|
return [];
|
|
32328
32240
|
return ["--", ":(top)", `:(exclude,literal,top)${rel.split(sep6).join("/")}`];
|
|
32329
32241
|
}
|
|
32330
32242
|
function inferTaggedVersion(entryPath, sources) {
|
|
32331
|
-
const cwd =
|
|
32243
|
+
const cwd = resolve29(entryPath, "..");
|
|
32332
32244
|
const raw = (args) => {
|
|
32333
32245
|
try {
|
|
32334
32246
|
return execFileSync5("git", args, {
|
|
@@ -32358,7 +32270,7 @@ function inferTaggedVersion(entryPath, sources) {
|
|
|
32358
32270
|
function findEntry(dir) {
|
|
32359
32271
|
let names;
|
|
32360
32272
|
try {
|
|
32361
|
-
names =
|
|
32273
|
+
names = readdirSync21(dir);
|
|
32362
32274
|
} catch {
|
|
32363
32275
|
return [];
|
|
32364
32276
|
}
|
|
@@ -32366,9 +32278,9 @@ function findEntry(dir) {
|
|
|
32366
32278
|
for (const name of names) {
|
|
32367
32279
|
if (!/\.(mjs|js|ts)$/.test(name))
|
|
32368
32280
|
continue;
|
|
32369
|
-
const full =
|
|
32281
|
+
const full = resolve29(dir, name);
|
|
32370
32282
|
try {
|
|
32371
|
-
if (
|
|
32283
|
+
if (statSync25(full).size > 512 * 1024)
|
|
32372
32284
|
continue;
|
|
32373
32285
|
const text = readFileSync36(full, "utf8");
|
|
32374
32286
|
if (/from\s+["']failproofai["']/.test(text) && /customPolicies\s*\.\s*add\s*\(/.test(text)) {
|
|
@@ -32381,13 +32293,13 @@ function findEntry(dir) {
|
|
|
32381
32293
|
return found.sort();
|
|
32382
32294
|
}
|
|
32383
32295
|
function withLocalImports(sources) {
|
|
32384
|
-
const seen = new Set(sources.map((f) =>
|
|
32296
|
+
const seen = new Set(sources.map((f) => resolve29(f)));
|
|
32385
32297
|
const queue = [...seen];
|
|
32386
32298
|
while (queue.length > 0 && seen.size < 500) {
|
|
32387
32299
|
const file = queue.shift();
|
|
32388
32300
|
let text;
|
|
32389
32301
|
try {
|
|
32390
|
-
if (
|
|
32302
|
+
if (statSync25(file).size > 512 * 1024)
|
|
32391
32303
|
continue;
|
|
32392
32304
|
text = readFileSync36(file, "utf8");
|
|
32393
32305
|
} catch {
|
|
@@ -32395,13 +32307,13 @@ function withLocalImports(sources) {
|
|
|
32395
32307
|
}
|
|
32396
32308
|
for (const re of LOCAL_IMPORT_RES) {
|
|
32397
32309
|
for (const match of text.matchAll(re)) {
|
|
32398
|
-
const base =
|
|
32310
|
+
const base = resolve29(dirname21(file), match[1]);
|
|
32399
32311
|
for (const ext of LOCAL_IMPORT_EXTENSIONS) {
|
|
32400
32312
|
const candidate = base + ext;
|
|
32401
32313
|
if (seen.has(candidate))
|
|
32402
32314
|
break;
|
|
32403
32315
|
try {
|
|
32404
|
-
if (!
|
|
32316
|
+
if (!statSync25(candidate).isFile())
|
|
32405
32317
|
continue;
|
|
32406
32318
|
} catch {
|
|
32407
32319
|
continue;
|
|
@@ -32416,7 +32328,7 @@ function withLocalImports(sources) {
|
|
|
32416
32328
|
return [...seen];
|
|
32417
32329
|
}
|
|
32418
32330
|
function settleGitState(entryPath, provenance, packFiles, id, outDir) {
|
|
32419
|
-
const cwd =
|
|
32331
|
+
const cwd = resolve29(entryPath, "..");
|
|
32420
32332
|
const raw = (args) => {
|
|
32421
32333
|
try {
|
|
32422
32334
|
return execFileSync5("git", args, {
|
|
@@ -32491,11 +32403,11 @@ function settleGitState(entryPath, provenance, packFiles, id, outDir) {
|
|
|
32491
32403
|
if (root === null || status === null)
|
|
32492
32404
|
return null;
|
|
32493
32405
|
const entries = porcelainEntries(status);
|
|
32494
|
-
const dirty = entries.map((entry) =>
|
|
32495
|
-
const renamedFrom = entries.filter((entry) => entry.from).map((entry) =>
|
|
32406
|
+
const dirty = entries.map((entry) => resolve29(root, entry.path));
|
|
32407
|
+
const renamedFrom = entries.filter((entry) => entry.from).map((entry) => resolve29(root, entry.from));
|
|
32496
32408
|
if (dirty.length === 0)
|
|
32497
32409
|
return null;
|
|
32498
|
-
const mine = new Set(packFiles.map((f) =>
|
|
32410
|
+
const mine = new Set(packFiles.map((f) => resolve29(f)));
|
|
32499
32411
|
const foreign = dirty.filter((path) => !mine.has(path));
|
|
32500
32412
|
const toStage = [...dirty, ...renamedFrom];
|
|
32501
32413
|
if (foreign.length > 0) {
|
|
@@ -32628,7 +32540,7 @@ function pushExistingHistory(dir, owner, name, token) {
|
|
|
32628
32540
|
return false;
|
|
32629
32541
|
const askpass = join38(mkdtempSync3(join38(tmpdir4(), "fpai-askpass-")), "askpass.sh");
|
|
32630
32542
|
try {
|
|
32631
|
-
|
|
32543
|
+
writeFileSync26(askpass, `#!/bin/sh
|
|
32632
32544
|
case "$1" in
|
|
32633
32545
|
*Username*) echo x-access-token ;;
|
|
32634
32546
|
*) echo "$FPAI_GH_TOKEN" ;;
|
|
@@ -32648,7 +32560,7 @@ esac
|
|
|
32648
32560
|
return true;
|
|
32649
32561
|
} finally {
|
|
32650
32562
|
try {
|
|
32651
|
-
|
|
32563
|
+
rmSync18(dirname21(askpass), { recursive: true, force: true });
|
|
32652
32564
|
} catch {}
|
|
32653
32565
|
}
|
|
32654
32566
|
}
|
|
@@ -32672,8 +32584,8 @@ failproofai policies add ${owner}/${name}
|
|
|
32672
32584
|
function findBun() {
|
|
32673
32585
|
const candidates = [
|
|
32674
32586
|
"bun",
|
|
32675
|
-
process.env.BUN_INSTALL ?
|
|
32676
|
-
|
|
32587
|
+
process.env.BUN_INSTALL ? resolve29(process.env.BUN_INSTALL, "bin", "bun") : null,
|
|
32588
|
+
resolve29(homedir31(), ".bun", "bin", "bun"),
|
|
32677
32589
|
"/opt/homebrew/bin/bun",
|
|
32678
32590
|
"/usr/local/bin/bun"
|
|
32679
32591
|
].filter((c) => c !== null);
|
|
@@ -32699,12 +32611,12 @@ function bundleEntry(sources, outDir) {
|
|
|
32699
32611
|
]
|
|
32700
32612
|
};
|
|
32701
32613
|
}
|
|
32702
|
-
|
|
32703
|
-
const entry =
|
|
32704
|
-
|
|
32614
|
+
mkdirSync29(outDir, { recursive: true });
|
|
32615
|
+
const entry = resolve29(outDir, ".entry.generated.mjs");
|
|
32616
|
+
writeFileSync26(entry, sources.map((f) => `import ${JSON.stringify(f.startsWith("/") ? f : resolve29(f))};`).join(`
|
|
32705
32617
|
`) + `
|
|
32706
32618
|
`, "utf8");
|
|
32707
|
-
const bundled =
|
|
32619
|
+
const bundled = resolve29(outDir, ".bundled.mjs");
|
|
32708
32620
|
try {
|
|
32709
32621
|
execFileSync5(bun, [
|
|
32710
32622
|
"build",
|
|
@@ -32822,7 +32734,7 @@ async function publish(rest) {
|
|
|
32822
32734
|
`);
|
|
32823
32735
|
const token = githubToken();
|
|
32824
32736
|
const login = token ? await credentialLogin(token) : null;
|
|
32825
|
-
const folder = basename8(
|
|
32737
|
+
const folder = basename8(resolve29(entry, ".."));
|
|
32826
32738
|
const answered = await askWhereToPublish(`${login ?? "your-account"}/${folder}`, { stdin: process.stdin, stdout: process.stdout });
|
|
32827
32739
|
if (answered === null)
|
|
32828
32740
|
return ok2(["Nothing was published."]);
|
|
@@ -32833,7 +32745,7 @@ async function publish(rest) {
|
|
|
32833
32745
|
let versionFromSha = false;
|
|
32834
32746
|
const dryRun = rest.includes("--dry-run") || !repo;
|
|
32835
32747
|
const allowPrivate = rest.includes("--allow-private");
|
|
32836
|
-
const id = flag("id") ?? repo ?? (dryRun && entry ? `local/${basename8(
|
|
32748
|
+
const id = flag("id") ?? repo ?? (dryRun && entry ? `local/${basename8(resolve29(entry, ".."))}` : undefined);
|
|
32837
32749
|
const [owner, name] = (repo ?? "/").split("/");
|
|
32838
32750
|
if (repo && (!owner || !name || repo.split("/").length !== 2)) {
|
|
32839
32751
|
return fail2([`--repo must be <owner>/<repo>, got ${JSON.stringify(repo)}`]);
|
|
@@ -32852,7 +32764,7 @@ async function publish(rest) {
|
|
|
32852
32764
|
"With no --repo it writes the three release assets and stops."
|
|
32853
32765
|
]);
|
|
32854
32766
|
}
|
|
32855
|
-
const outDirEarly =
|
|
32767
|
+
const outDirEarly = resolve29(flag("out") ?? "dist-pack");
|
|
32856
32768
|
let provenance = entry ? inferCommit(entry, outDirEarly, bundledSources) : null;
|
|
32857
32769
|
const gitLines = [];
|
|
32858
32770
|
if (!version && entry && interactive) {
|
|
@@ -32892,7 +32804,7 @@ async function publish(rest) {
|
|
|
32892
32804
|
"It needs write access to releases on that repository, and nothing else."
|
|
32893
32805
|
]);
|
|
32894
32806
|
}
|
|
32895
|
-
const ensured = await ensureRepo(owner, name, id, token,
|
|
32807
|
+
const ensured = await ensureRepo(owner, name, id, token, resolve29(entry, ".."));
|
|
32896
32808
|
if ("error" in ensured)
|
|
32897
32809
|
return fail2(ensured.error);
|
|
32898
32810
|
created = ensured.created;
|
|
@@ -32991,7 +32903,7 @@ async function publish(rest) {
|
|
|
32991
32903
|
if (prior) {
|
|
32992
32904
|
await gh(`${GITHUB_API2}/repos/${owner}/${name}/releases/assets/${prior.id}`, auth, { method: "DELETE" });
|
|
32993
32905
|
}
|
|
32994
|
-
const bytes = readFileSync36(
|
|
32906
|
+
const bytes = readFileSync36(resolve29(outDir, asset));
|
|
32995
32907
|
const upload = await gh(`${GITHUB_UPLOADS2}/repos/${owner}/${name}/releases/${releaseId}/assets?name=${encodeURIComponent(asset)}`, auth, {
|
|
32996
32908
|
method: "POST",
|
|
32997
32909
|
contentType: asset.endsWith(".json") ? "application/json" : "application/octet-stream",
|
|
@@ -33672,8 +33584,8 @@ var init_install_prompt = __esm(() => {
|
|
|
33672
33584
|
|
|
33673
33585
|
// src/hooks/manager.ts
|
|
33674
33586
|
import { execSync as execSync7 } from "node:child_process";
|
|
33675
|
-
import { existsSync as
|
|
33676
|
-
import { resolve as
|
|
33587
|
+
import { existsSync as existsSync44 } from "node:fs";
|
|
33588
|
+
import { resolve as resolve30, basename as basename9 } from "node:path";
|
|
33677
33589
|
import { platform as platform4, arch as arch4, release as release3, hostname as hostname6 } from "node:os";
|
|
33678
33590
|
function getSettingsPath2(scope, cwd) {
|
|
33679
33591
|
return claudeCode.getSettingsPath(scope, cwd);
|
|
@@ -33892,9 +33804,9 @@ async function installHooksImpl2(policyNames, scope = "user", cwd, includeBeta =
|
|
|
33892
33804
|
delete configToWrite.customPoliciesPath;
|
|
33893
33805
|
delete configToWrite.customPoliciesPaths;
|
|
33894
33806
|
} 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 (
|
|
33807
|
+
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path) => resolve30(path));
|
|
33808
|
+
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path) => resolve30(path)).filter((path) => {
|
|
33809
|
+
if (existsSync44(path))
|
|
33898
33810
|
return true;
|
|
33899
33811
|
console.log(`Dropping custom policies path (file no longer exists): ${path}`);
|
|
33900
33812
|
return false;
|
|
@@ -34117,7 +34029,7 @@ async function removeHooks2(policyNames, scope = "user", cwd, opts) {
|
|
|
34117
34029
|
const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
|
|
34118
34030
|
for (const s of scopesToRemove) {
|
|
34119
34031
|
const settingsPaths = settingsPathsFor(integration, s, cwd);
|
|
34120
|
-
const existing = settingsPaths.filter((p) =>
|
|
34032
|
+
const existing = settingsPaths.filter((p) => existsSync44(p));
|
|
34121
34033
|
if (existing.length === 0) {
|
|
34122
34034
|
if (scope !== "all" && selectedClis.length === 1) {
|
|
34123
34035
|
console.log("No settings file found. Nothing to remove.");
|
|
@@ -34261,9 +34173,9 @@ async function listHooks(cwd) {
|
|
|
34261
34173
|
if (explicitPaths.length > 0) {
|
|
34262
34174
|
groups.push(rule("Custom Policies", opts));
|
|
34263
34175
|
for (const path of explicitPaths) {
|
|
34264
|
-
const absPath =
|
|
34176
|
+
const absPath = resolve30(findProjectConfigDir(cwd ?? process.cwd()), path);
|
|
34265
34177
|
groups.push(note(absPath, opts));
|
|
34266
|
-
if (!
|
|
34178
|
+
if (!existsSync44(absPath)) {
|
|
34267
34179
|
groups.push(warning([`file not found: ${absPath}`], opts));
|
|
34268
34180
|
continue;
|
|
34269
34181
|
}
|
|
@@ -34283,7 +34195,7 @@ async function listHooks(cwd) {
|
|
|
34283
34195
|
}
|
|
34284
34196
|
}
|
|
34285
34197
|
const base = findProjectConfigDir(cwd ?? process.cwd());
|
|
34286
|
-
const projectDir =
|
|
34198
|
+
const projectDir = resolve30(base, ".failproofai", "policies");
|
|
34287
34199
|
const userDir = customPoliciesDir();
|
|
34288
34200
|
const sameDir = userDir === projectDir;
|
|
34289
34201
|
const conventionDirs = [
|
|
@@ -34589,21 +34501,20 @@ async function runScheduleOn(daysArg, emailArg) {
|
|
|
34589
34501
|
if (bad)
|
|
34590
34502
|
throw new ScheduleCliError(bad);
|
|
34591
34503
|
}
|
|
34592
|
-
const { user, prompted }
|
|
34504
|
+
const signedIn = emailArg === undefined ? { user: readAuth()?.user ?? null, prompted: false } : await ensureSignedIn(emailArg);
|
|
34593
34505
|
const next = updateConfig({
|
|
34594
34506
|
audit: {
|
|
34595
34507
|
auto: true,
|
|
34596
|
-
reportsConsentedAt: Date.now(),
|
|
34597
34508
|
...days !== undefined ? { intervalDays: days } : {}
|
|
34598
34509
|
}
|
|
34599
34510
|
});
|
|
34600
34511
|
const interval = next.audit.intervalDays;
|
|
34601
34512
|
const summary = [
|
|
34602
|
-
`every ${interval} day${interval === 1 ? "" : "s"} ·
|
|
34603
|
-
|
|
34604
|
-
"
|
|
34513
|
+
`every ${interval} day${interval === 1 ? "" : "s"} · desktop notification on leaks`,
|
|
34514
|
+
signedIn.user ? `masked leak alerts also go to ${signedIn.user.email}` : "email is optional · add it with --email you@example.com",
|
|
34515
|
+
"email contains only the most recent masked credential exposure"
|
|
34605
34516
|
];
|
|
34606
|
-
if (prompted) {
|
|
34517
|
+
if (signedIn.prompted) {
|
|
34607
34518
|
step("scheduled audits are on", summary);
|
|
34608
34519
|
} else {
|
|
34609
34520
|
process.stdout.write(`
|
|
@@ -34612,7 +34523,7 @@ ${green("✓")} ${bold("scheduled audits are on")}
|
|
|
34612
34523
|
`).join(""));
|
|
34613
34524
|
}
|
|
34614
34525
|
warnIfDaemonWontRun();
|
|
34615
|
-
if (prompted) {
|
|
34526
|
+
if (signedIn.prompted) {
|
|
34616
34527
|
outro("failproofai audit --status · when the next scan is due");
|
|
34617
34528
|
} else {
|
|
34618
34529
|
process.stdout.write(dim(`
|
|
@@ -34664,12 +34575,7 @@ function runScheduleStatus() {
|
|
|
34664
34575
|
]);
|
|
34665
34576
|
detail.push(["reports to", live ? live.user.email : dim("— signed out")]);
|
|
34666
34577
|
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
|
-
]);
|
|
34578
|
+
detail.push(["", pink("scans and desktop alerts continue; email alerts are paused")]);
|
|
34673
34579
|
}
|
|
34674
34580
|
detail.push(["daemon", describeDaemon(daemon)]);
|
|
34675
34581
|
if (sched?.nextDueAtMs != null && on) {
|
|
@@ -34784,14 +34690,14 @@ var init_schedule_cli = __esm(() => {
|
|
|
34784
34690
|
});
|
|
34785
34691
|
|
|
34786
34692
|
// scripts/parse-script-args.ts
|
|
34787
|
-
import { resolve as
|
|
34693
|
+
import { resolve as resolve31 } from "path";
|
|
34788
34694
|
function parseStringFlag(flagName, errorLabel, inlineValue, args, index, options) {
|
|
34789
34695
|
const raw = inlineValue ?? args[index + 1];
|
|
34790
34696
|
if (raw === undefined || inlineValue === null && raw.startsWith("-")) {
|
|
34791
34697
|
console.error(`Error: ${flagName} requires ${errorLabel}`);
|
|
34792
34698
|
process.exit(1);
|
|
34793
34699
|
}
|
|
34794
|
-
const value = options?.resolve ?
|
|
34700
|
+
const value = options?.resolve ? resolve31(raw) : raw;
|
|
34795
34701
|
return { value, spliceCount: inlineValue !== null ? 1 : 2 };
|
|
34796
34702
|
}
|
|
34797
34703
|
function parseScriptArgs(argv) {
|
|
@@ -34847,19 +34753,19 @@ function parseScriptArgs(argv) {
|
|
|
34847
34753
|
var init_parse_script_args = () => {};
|
|
34848
34754
|
|
|
34849
34755
|
// scripts/install-diagnosis.mjs
|
|
34850
|
-
import { existsSync as
|
|
34851
|
-
import { dirname as dirname22, resolve as
|
|
34756
|
+
import { existsSync as existsSync45, readFileSync as readFileSync38, realpathSync as realpathSync4 } from "node:fs";
|
|
34757
|
+
import { dirname as dirname22, resolve as resolve32 } from "node:path";
|
|
34852
34758
|
import { homedir as homedir32, platform as platform5 } from "node:os";
|
|
34853
34759
|
import { spawnSync } from "node:child_process";
|
|
34854
34760
|
function findPackageRoot(start) {
|
|
34855
34761
|
try {
|
|
34856
34762
|
let dir = realpathSync4(start);
|
|
34857
|
-
if (
|
|
34763
|
+
if (existsSync45(dir) && !existsSync45(resolve32(dir, "package.json"))) {
|
|
34858
34764
|
dir = dirname22(dir);
|
|
34859
34765
|
}
|
|
34860
34766
|
while (true) {
|
|
34861
|
-
const pkgPath =
|
|
34862
|
-
if (
|
|
34767
|
+
const pkgPath = resolve32(dir, "package.json");
|
|
34768
|
+
if (existsSync45(pkgPath)) {
|
|
34863
34769
|
try {
|
|
34864
34770
|
const pkg = JSON.parse(readFileSync38(pkgPath, "utf8"));
|
|
34865
34771
|
if (pkg.name === PKG_NAME)
|
|
@@ -34879,7 +34785,7 @@ function readPackageVersion(packageRoot) {
|
|
|
34879
34785
|
if (!packageRoot)
|
|
34880
34786
|
return null;
|
|
34881
34787
|
try {
|
|
34882
|
-
const pkg = JSON.parse(readFileSync38(
|
|
34788
|
+
const pkg = JSON.parse(readFileSync38(resolve32(packageRoot, "package.json"), "utf8"));
|
|
34883
34789
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
34884
34790
|
} catch {
|
|
34885
34791
|
return null;
|
|
@@ -34905,16 +34811,16 @@ function locateNpmGlobal() {
|
|
|
34905
34811
|
const root = (res.stdout || "").trim();
|
|
34906
34812
|
if (!root)
|
|
34907
34813
|
return null;
|
|
34908
|
-
const candidate =
|
|
34909
|
-
return
|
|
34814
|
+
const candidate = resolve32(root, PKG_NAME);
|
|
34815
|
+
return existsSync45(resolve32(candidate, "package.json")) ? candidate : null;
|
|
34910
34816
|
} catch {
|
|
34911
34817
|
return null;
|
|
34912
34818
|
}
|
|
34913
34819
|
}
|
|
34914
34820
|
function locateBunGlobal() {
|
|
34915
34821
|
try {
|
|
34916
|
-
const candidate =
|
|
34917
|
-
return
|
|
34822
|
+
const candidate = resolve32(homedir32(), ".bun", "install", "global", "node_modules", PKG_NAME);
|
|
34823
|
+
return existsSync45(resolve32(candidate, "package.json")) ? candidate : null;
|
|
34918
34824
|
} catch {
|
|
34919
34825
|
return null;
|
|
34920
34826
|
}
|
|
@@ -34922,8 +34828,8 @@ function locateBunGlobal() {
|
|
|
34922
34828
|
function buildRecommendation(pathFirstBin) {
|
|
34923
34829
|
if (!pathFirstBin)
|
|
34924
34830
|
return null;
|
|
34925
|
-
const bunBinPrefix =
|
|
34926
|
-
const bunGlobalPrefix =
|
|
34831
|
+
const bunBinPrefix = resolve32(homedir32(), ".bun", "bin") + "/";
|
|
34832
|
+
const bunGlobalPrefix = resolve32(homedir32(), ".bun", "install", "global") + "/";
|
|
34927
34833
|
const isBun = pathFirstBin.startsWith(bunBinPrefix) || pathFirstBin.startsWith(bunGlobalPrefix);
|
|
34928
34834
|
if (isBun) {
|
|
34929
34835
|
return `rm -f ~/.bun/bin/${PKG_NAME} && rm -rf ~/.bun/install/global/node_modules/${PKG_NAME}`;
|
|
@@ -35017,8 +34923,8 @@ var init_dashboard_host = __esm(() => {
|
|
|
35017
34923
|
|
|
35018
34924
|
// scripts/launch.ts
|
|
35019
34925
|
import { spawn as spawn2 } from "child_process";
|
|
35020
|
-
import { realpathSync as realpathSync5, existsSync as
|
|
35021
|
-
import { resolve as
|
|
34926
|
+
import { realpathSync as realpathSync5, existsSync as existsSync46 } from "node:fs";
|
|
34927
|
+
import { resolve as resolve33, dirname as dirname23 } from "node:path";
|
|
35022
34928
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
35023
34929
|
import { createInterface } from "node:readline";
|
|
35024
34930
|
function launch(mode) {
|
|
@@ -35042,9 +34948,9 @@ function launch(mode) {
|
|
|
35042
34948
|
process.env.PORT = port;
|
|
35043
34949
|
process.env.HOSTNAME = bindHost;
|
|
35044
34950
|
cmd = "node";
|
|
35045
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ??
|
|
35046
|
-
const serverJsPath =
|
|
35047
|
-
if (!
|
|
34951
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve33(dirname23(realpathSync5(fileURLToPath2(import.meta.url))), "..");
|
|
34952
|
+
const serverJsPath = resolve33(packageRoot, ".next/standalone/server.js");
|
|
34953
|
+
if (!existsSync46(serverJsPath)) {
|
|
35048
34954
|
let shadowMessage = null;
|
|
35049
34955
|
try {
|
|
35050
34956
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -35133,20 +35039,20 @@ function helpText() {
|
|
|
35133
35039
|
label: "usage",
|
|
35134
35040
|
entries: [
|
|
35135
35041
|
["(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,
|
|
35042
|
+
["--schedule [days]", "Scan on a timer and notify you on this machine. Default 7 days, range 1-90. No account required."],
|
|
35043
|
+
["--email <address>", "With --schedule, add email alerts for the most recent masked credential leak. A sign-in code is emailed to you."],
|
|
35138
35044
|
["--no-schedule", "Stop the timer. Leaves you signed in."],
|
|
35139
35045
|
["--notify", "Show a desktop notification when a scan finds a credential. On by default."],
|
|
35140
|
-
["--no-notify", "Stop
|
|
35046
|
+
["--no-notify", "Stop desktop notifications. Scheduled scans and optional email alerts are unaffected."],
|
|
35141
35047
|
["--status", "Whether scheduling is on, where reports go, the daemon's state, and when the next scan is due."],
|
|
35142
35048
|
["-h, --help", "Show this help."]
|
|
35143
35049
|
]
|
|
35144
35050
|
}
|
|
35145
35051
|
],
|
|
35146
35052
|
footer: [
|
|
35147
|
-
"
|
|
35148
|
-
"
|
|
35149
|
-
"and
|
|
35053
|
+
"Every scan runs on this machine. Leak alerts appear as desktop system",
|
|
35054
|
+
"notifications, never inside agent sessions. If you add email, only the",
|
|
35055
|
+
"newest masked credential exposure and its metadata leave the machine."
|
|
35150
35056
|
]
|
|
35151
35057
|
}, helpOptsFor(process.stdout));
|
|
35152
35058
|
return ["", ...lines, ""].join(`
|
|
@@ -35296,52 +35202,38 @@ function heldByLine(held) {
|
|
|
35296
35202
|
const ageS = Math.max(0, Math.round((Date.now() - held.startedAt) / 1000));
|
|
35297
35203
|
return `another audit is already running (pid ${held.pid}, started by ${held.source} ${ageS}s ago)`;
|
|
35298
35204
|
}
|
|
35299
|
-
async function announceLeaksOnDesktop(result) {
|
|
35205
|
+
async function announceLeaksOnDesktop(result, report) {
|
|
35300
35206
|
try {
|
|
35301
|
-
await announceLeaksOrThrow(result);
|
|
35207
|
+
await announceLeaksOrThrow(result, report);
|
|
35302
35208
|
} catch (err) {
|
|
35303
35209
|
process.stderr.write(`failproofai: could not announce a leak on the desktop: ` + `${err instanceof Error ? err.message : String(err)}
|
|
35304
35210
|
`);
|
|
35305
35211
|
}
|
|
35306
35212
|
}
|
|
35307
|
-
async function announceLeaksOrThrow(result) {
|
|
35308
|
-
const ids = result.newLeakIds ?? [];
|
|
35213
|
+
async function announceLeaksOrThrow(result, report) {
|
|
35214
|
+
const ids = result.leakIds ?? result.newLeakIds ?? [];
|
|
35309
35215
|
if (ids.length === 0)
|
|
35310
35216
|
return;
|
|
35311
35217
|
if (!readConfig().audit.notify)
|
|
35312
35218
|
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
|
|
35219
|
+
const n = ids.length === 1 ? "a possible credential exposure" : `${ids.length} possible credential exposures`;
|
|
35220
|
+
const emailState = report.kind === "sent" ? "sent" : report.kind === "signed-out" || !readAuth() ? "missing" : report.kind === "failed" ? "failed" : "held";
|
|
35221
|
+
const { title, body } = desktopLeakNotice(emailState);
|
|
35222
|
+
if (process.platform === "darwin") {
|
|
35223
|
+
pruneMacNotifyQueue();
|
|
35224
|
+
if (!queueMacNotification(ids[0], title, body)) {
|
|
35225
|
+
process.stderr.write(`failproofai: found ${n} but could not queue a notification
|
|
35326
35226
|
`);
|
|
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\`)
|
|
35227
|
+
} else if (!macNotifierInstalled()) {
|
|
35228
|
+
process.stderr.write(`failproofai: found ${n}; the notifier is not installed, so nothing will show it ` + `(run \`failproofai config\`)
|
|
35332
35229
|
`);
|
|
35333
|
-
}
|
|
35334
|
-
return;
|
|
35335
35230
|
}
|
|
35336
|
-
|
|
35337
|
-
|
|
35338
|
-
|
|
35339
|
-
|
|
35231
|
+
return;
|
|
35232
|
+
}
|
|
35233
|
+
const outcome = await notifyDesktop(title, body, 0);
|
|
35234
|
+
if (!outcome.ok) {
|
|
35235
|
+
process.stderr.write(`failproofai: found ${n} but could not raise a desktop notification (${outcome.reason})
|
|
35340
35236
|
`);
|
|
35341
|
-
}
|
|
35342
|
-
} finally {
|
|
35343
|
-
if (!delivered)
|
|
35344
|
-
releaseLeakNoticeClaims(claimed, undefined, "desktop");
|
|
35345
35237
|
}
|
|
35346
35238
|
}
|
|
35347
35239
|
async function runScheduledAudit() {
|
|
@@ -35375,8 +35267,8 @@ async function runScheduledAudit() {
|
|
|
35375
35267
|
}
|
|
35376
35268
|
process.stdout.write(`failproofai: audit complete — ${num2(result.eventsScanned)} tool calls across ` + `${num2(result.transcripts.scanned)} sessions, ${num2(result.totals.hits)} hits
|
|
35377
35269
|
`);
|
|
35378
|
-
await announceLeaksOnDesktop(result);
|
|
35379
35270
|
const outcome = await reportHarm(result);
|
|
35271
|
+
await announceLeaksOnDesktop(result, outcome);
|
|
35380
35272
|
const line = describeOutcome2(outcome);
|
|
35381
35273
|
if (line) {
|
|
35382
35274
|
const stream = outcome.kind === "sent" ? process.stdout : process.stderr;
|
|
@@ -35534,10 +35426,8 @@ var init_cli2 = __esm(() => {
|
|
|
35534
35426
|
init_report_harm();
|
|
35535
35427
|
init_desktop_notify();
|
|
35536
35428
|
init_macos_notifier();
|
|
35537
|
-
init_leak_notice();
|
|
35538
|
-
init_notice();
|
|
35539
|
-
init_leak_store();
|
|
35540
35429
|
init_fp_config();
|
|
35430
|
+
init_auth_store();
|
|
35541
35431
|
init_tui();
|
|
35542
35432
|
init_package();
|
|
35543
35433
|
AUDIT_STAGES2 = [
|
|
@@ -35870,8 +35760,8 @@ var init_session_pause_cli = __esm(() => {
|
|
|
35870
35760
|
|
|
35871
35761
|
// scripts/launch.ts
|
|
35872
35762
|
import { spawn as spawn3 } from "child_process";
|
|
35873
|
-
import { realpathSync as realpathSync6, existsSync as
|
|
35874
|
-
import { resolve as
|
|
35763
|
+
import { realpathSync as realpathSync6, existsSync as existsSync47 } from "node:fs";
|
|
35764
|
+
import { resolve as resolve34, dirname as dirname24 } from "node:path";
|
|
35875
35765
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
35876
35766
|
import { createInterface as createInterface2 } from "node:readline";
|
|
35877
35767
|
function launch2(mode) {
|
|
@@ -35895,9 +35785,9 @@ function launch2(mode) {
|
|
|
35895
35785
|
process.env.PORT = port;
|
|
35896
35786
|
process.env.HOSTNAME = bindHost;
|
|
35897
35787
|
cmd = "node";
|
|
35898
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ??
|
|
35899
|
-
const serverJsPath =
|
|
35900
|
-
if (!
|
|
35788
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve34(dirname24(realpathSync6(fileURLToPath3(import.meta.url))), "..");
|
|
35789
|
+
const serverJsPath = resolve34(packageRoot, ".next/standalone/server.js");
|
|
35790
|
+
if (!existsSync47(serverJsPath)) {
|
|
35901
35791
|
let shadowMessage = null;
|
|
35902
35792
|
try {
|
|
35903
35793
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -35994,17 +35884,17 @@ var init_cli_error2 = __esm(() => {
|
|
|
35994
35884
|
|
|
35995
35885
|
// bin/failproofai.mjs
|
|
35996
35886
|
import { realpathSync as realpathSync7 } from "fs";
|
|
35997
|
-
import { dirname as dirname25, resolve as
|
|
35887
|
+
import { dirname as dirname25, resolve as resolve35 } from "path";
|
|
35998
35888
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
35999
35889
|
// package.json
|
|
36000
|
-
var version = "1.0.4-beta.
|
|
35890
|
+
var version = "1.0.4-beta.7";
|
|
36001
35891
|
|
|
36002
35892
|
// bin/failproofai.mjs
|
|
36003
35893
|
if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
|
|
36004
|
-
process.env.FAILPROOFAI_PACKAGE_ROOT =
|
|
35894
|
+
process.env.FAILPROOFAI_PACKAGE_ROOT = resolve35(dirname25(realpathSync7(fileURLToPath4(import.meta.url))), "..");
|
|
36005
35895
|
}
|
|
36006
35896
|
if (!process.env.FAILPROOFAI_DIST_PATH) {
|
|
36007
|
-
process.env.FAILPROOFAI_DIST_PATH =
|
|
35897
|
+
process.env.FAILPROOFAI_DIST_PATH = resolve35(dirname25(realpathSync7(fileURLToPath4(import.meta.url))), "..", "dist");
|
|
36008
35898
|
}
|
|
36009
35899
|
var args = process.argv.slice(2);
|
|
36010
35900
|
if (args[0] === "p" || args[0] === "policy")
|