failproofai 1.0.4-beta.7 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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 +4 -4
- 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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +4 -37
- package/.next/standalone/.next/server/app/audit/page.js +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -15
- 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/{[externals]__0v1hz15._.js → [externals]__0-9ti7z._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__1nb206a._.js → [externals]__0u3wrvq._.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]__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]__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/{_0otft92._.js → _1-akg6w._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +10 -10
- package/.next/standalone/.next/server/chunks/_1vslkoe._.js +1 -1
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1fvfw59._.js → [root-of-the-server]__00-s7h8._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__12hbpha._.js → [root-of-the-server]__09flfsx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0kokc8z._.js → [root-of-the-server]__0n_lxhg._.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]__0p-5p8u._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +6 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0dxf928._.js → [root-of-the-server]__190won8._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0n2txhk._.js → [root-of-the-server]__1ctpynv._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/_02yoeej._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0a0zlpr._.js → _04rbnaq._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0s-77v5._.js → _0h_douw._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1_ozgif._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1ddpc5g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +14 -51
- package/.next/standalone/.next/server/chunks/ssr/{_07t3jol._.js → _1u8-lu2._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +3 -0
- 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 +69 -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/node_modules_13n822a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +3 -0
- 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-config_ts_04t589g._.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 +5 -5
- 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 +21 -65
- package/.next/standalone/.next/static/chunks/{0f1pznnc7zlub.js → 0-tyrpwuc3lla.js} +1 -1
- package/.next/standalone/.next/static/chunks/0ca7octhod0g2.js +69 -0
- package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +1 -0
- package/.next/standalone/.next/static/chunks/{1csubx9gwhsf6.js → 1j6o9min_6qa9.js} +1 -1
- package/.next/standalone/.next/static/chunks/27cl8h-c2w7cd.js +1 -0
- package/.next/standalone/.next/static/chunks/{0jpd8dv2vk930.css → 29-iqnp9v_axt.css} +1 -1
- package/.next/standalone/.next/static/chunks/{3uyhmm01g64k4.css → 2k9f4tyv04809.css} +0 -1
- package/.next/standalone/.next/static/chunks/{0t6ea7d3bkmdv.js → 2lwipmv5etc8m.js} +1 -1
- package/.next/standalone/.next/static/chunks/2pd16tn5qmx13.js +1 -0
- package/.next/standalone/.next/static/chunks/{0ntdfr2552x-h.js → 2u8vh73tpw28_.js} +1 -1
- package/.next/standalone/.next/static/chunks/{15uon66hpwbgg.js → 31u94yukw9fz-.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2pwfrn6_mw-1u.js → 3p9_8x5ezce-9.js} +1 -1
- package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +1 -0
- package/.next/standalone/.next/static/chunks/{083fk73jtv9a0.js → 3tjji451hrgc0.js} +1 -1
- package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-3s3c-u_u_l0u9.js → turbopack-3p73obe0xmrxm.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +27 -51
- package/.next/standalone/app/actions/get-scheduled-audit.ts +0 -5
- package/.next/standalone/app/actions/update-scheduled-audit.ts +57 -18
- package/.next/standalone/app/api/auth/status/route.ts +2 -3
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +34 -140
- package/.next/standalone/app/audit/_components/audit-poster.tsx +10 -29
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -6
- package/.next/standalone/app/audit/_components/empty-state.tsx +1 -4
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +5 -19
- package/.next/standalone/app/audit/_components/share-templates.ts +44 -110
- package/.next/standalone/app/audit/audit-styles.css +1 -132
- package/.next/standalone/app/settings/page.tsx +1 -1
- package/.next/standalone/app/settings/settings-client.tsx +45 -50
- package/.next/standalone/lib/auth/api-server-client.ts +5 -33
- package/.next/standalone/lib/claude-sessions.ts +27 -101
- package/.next/standalone/lib/codex-sessions.ts +4 -20
- package/.next/standalone/lib/copilot-sessions.ts +1 -32
- package/.next/standalone/lib/cursor-sessions.ts +5 -62
- package/.next/standalone/lib/sqlite-reader.ts +1 -78
- package/.next/standalone/package.json +9 -9
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +1 -1
- package/dist/cli.mjs +500 -1762
- package/dist/worker.mjs +16 -138
- package/lib/auth/api-server-client.ts +5 -33
- package/lib/claude-sessions.ts +27 -101
- package/lib/codex-sessions.ts +4 -20
- package/lib/copilot-sessions.ts +1 -32
- package/lib/cursor-sessions.ts +5 -62
- package/lib/sqlite-reader.ts +1 -78
- package/package.json +9 -9
- package/pi-extension/index.ts +5 -50
- package/src/audit/cache.ts +0 -6
- package/src/audit/cli-adapters/claude.ts +0 -13
- package/src/audit/cli-login.ts +1 -4
- package/src/audit/cli.ts +7 -157
- package/src/audit/harm-report.ts +4 -111
- package/src/audit/index.ts +15 -286
- package/src/audit/machine-store.ts +9 -8
- package/src/audit/redact-example.ts +15 -324
- package/src/audit/report-harm.ts +37 -33
- package/src/audit/report.ts +3 -6
- package/src/audit/schedule-cli.ts +33 -54
- package/src/audit/scoring.ts +0 -49
- package/src/audit/types.ts +0 -52
- package/src/hooks/builtin-policies.ts +2 -67
- package/src/hooks/configure-wizard.ts +0 -55
- package/src/hooks/fp-config.ts +48 -83
- package/src/hooks/fp-home.ts +0 -27
- package/src/hooks/integrations.ts +14 -51
- package/src/hooks/uninstall-cli.ts +2 -17
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-4ja6q._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00cr3xu._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04px77e._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0egr5s1._.js +0 -6
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0i0l1di._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0r3c1_0._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17xnxlx._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ckpmkk._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/_04ng_6x._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0l2hi_d._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_rerun-button_tsx_0blihgw._.js +0 -3
- package/.next/standalone/.next/static/chunks/0divvxng208xo.js +0 -1
- package/.next/standalone/.next/static/chunks/27du9n7ssja7l.js +0 -1
- package/.next/standalone/.next/static/chunks/2h_pcb1y8_jde.js +0 -1
- package/.next/standalone/app/actions/get-leaks.ts +0 -104
- package/.next/standalone/app/audit/_components/leak-section.tsx +0 -192
- package/src/audit/desktop-notify.ts +0 -420
- package/src/audit/leak-fingerprint.ts +0 -198
- package/src/audit/leak-record.ts +0 -248
- package/src/audit/leak-scan.ts +0 -268
- package/src/audit/leak-store.ts +0 -220
- package/src/audit/macos-notifier.ts +0 -298
- package/src/hooks/notice.ts +0 -24
- /package/.next/standalone/.next/static/{YiPsVpjrc-pEQoN7XvhZ0 → dg8VQ7Ejlo0Qsh_x92oIt}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{YiPsVpjrc-pEQoN7XvhZ0 → dg8VQ7Ejlo0Qsh_x92oIt}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{YiPsVpjrc-pEQoN7XvhZ0 → dg8VQ7Ejlo0Qsh_x92oIt}/_ssgManifest.js +0 -0
package/dist/worker.mjs
CHANGED
|
@@ -2805,39 +2805,15 @@ var init_builtin_policies = __esm(() => {
|
|
|
2805
2805
|
SHELL_METACHAR_RE = /[;&<>`$()\\]/;
|
|
2806
2806
|
JWT_RE = /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/;
|
|
2807
2807
|
API_KEY_PATTERNS = [
|
|
2808
|
-
[/sk-ant-api03-[A-Za-z0-9\-_]{20,}/, "Anthropic API key"],
|
|
2809
|
-
[/sk-ant-oat01-[A-Za-z0-9\-_]{20,}/, "Anthropic OAuth token"],
|
|
2810
2808
|
[/sk-ant-[A-Za-z0-9\-_]{20,}/, "Anthropic API key"],
|
|
2811
2809
|
[/sk-proj-[A-Za-z0-9\-_]{20,}/, "OpenAI project API key"],
|
|
2812
|
-
[/
|
|
2813
|
-
[/(?<!\w)sk-admin-[A-Za-z0-9\-_]{20,}/, "OpenAI admin key"],
|
|
2814
|
-
[/sk-or-v1-[A-Za-z0-9\-_]{20,}/, "OpenRouter API key"],
|
|
2815
|
-
[/sk-[A-Za-z0-9]{20,}/, "OpenAI-compatible key (issuer unknown)"],
|
|
2816
|
-
[/github_pat_[A-Za-z0-9_]{82}/, "GitHub fine-grained token"],
|
|
2810
|
+
[/sk-[A-Za-z0-9]{20,}/, "OpenAI API key"],
|
|
2817
2811
|
[/ghp_[A-Za-z0-9]{36}/, "GitHub personal access token"],
|
|
2818
|
-
[/
|
|
2819
|
-
[/ghu_[A-Za-z0-9]{36}/, "GitHub user-to-server token"],
|
|
2820
|
-
[/ghs_[A-Za-z0-9]{36}/, "GitHub server-to-server token"],
|
|
2821
|
-
[/ghr_[A-Za-z0-9]{36}/, "GitHub refresh token"],
|
|
2822
|
-
[/glpat-[A-Za-z0-9\-_]{20,}/, "GitLab personal access token"],
|
|
2812
|
+
[/github_pat_[A-Za-z0-9_]{82}/, "GitHub fine-grained token"],
|
|
2823
2813
|
[/AKIA[A-Z0-9]{16}/, "AWS access key ID"],
|
|
2824
|
-
[/ASIA[A-Z0-9]{16}/, "AWS temporary access key ID"],
|
|
2825
2814
|
[/sk_live_[A-Za-z0-9]{24,}/, "Stripe live secret key"],
|
|
2826
2815
|
[/sk_test_[A-Za-z0-9]{24,}/, "Stripe test secret key"],
|
|
2827
|
-
[/
|
|
2828
|
-
[/AIza[0-9A-Za-z\-_]{35}/, "Google API key"],
|
|
2829
|
-
[/\d{8,10}:[A-Za-z0-9_-]{35}/, "Telegram bot token"],
|
|
2830
|
-
[/xox[baprs]-[A-Za-z0-9-]{10,}/, "Slack token"],
|
|
2831
|
-
[/xapp-[0-9]-[A-Za-z0-9-]{10,}/, "Slack app-level token"],
|
|
2832
|
-
[/hf_[A-Za-z0-9]{30,}/, "Hugging Face token"],
|
|
2833
|
-
[/gsk_[A-Za-z0-9]{40,}/, "Groq API key"],
|
|
2834
|
-
[/r8_[A-Za-z0-9]{30,}/, "Replicate token"],
|
|
2835
|
-
[/xai-[A-Za-z0-9]{40,}/, "xAI API key"],
|
|
2836
|
-
[/npm_[A-Za-z0-9]{36}/, "npm access token"],
|
|
2837
|
-
[/dop_v1_[a-f0-9]{64}/, "DigitalOcean token"],
|
|
2838
|
-
[/shpat_[a-fA-F0-9]{32}/, "Shopify access token"],
|
|
2839
|
-
[/sb_secret_[A-Za-z0-9\-_]{20,}/, "Supabase secret key"],
|
|
2840
|
-
[/sbp_[a-f0-9]{40}/, "Supabase personal token"]
|
|
2816
|
+
[/AIza[0-9A-Za-z\-_]{35}/, "Google API key"]
|
|
2841
2817
|
];
|
|
2842
2818
|
CONNECTION_STRING_RE = /(?:postgresql|postgres|mysql|mongodb(?:\+srv)?|redis|amqps?|smtps?):\/\/[^@\s]+@/;
|
|
2843
2819
|
PRIVATE_KEY_RE = /-----BEGIN (?:[A-Z]+ )?PRIVATE KEY-----/;
|
|
@@ -3507,7 +3483,7 @@ function parsePackPolicyName(canonicalName) {
|
|
|
3507
3483
|
}
|
|
3508
3484
|
|
|
3509
3485
|
// package.json
|
|
3510
|
-
var version = "1.0.4
|
|
3486
|
+
var version = "1.0.4";
|
|
3511
3487
|
var init_package = () => {};
|
|
3512
3488
|
|
|
3513
3489
|
// src/posthog-key.ts
|
|
@@ -3611,8 +3587,7 @@ function projectConfig(parsed) {
|
|
|
3611
3587
|
const daemon = parsed.daemon ?? {};
|
|
3612
3588
|
const collector = parsed.collector ?? {};
|
|
3613
3589
|
const telemetry = parsed.telemetry ?? {};
|
|
3614
|
-
const
|
|
3615
|
-
const audit = auditPresent ? parsed.audit : {};
|
|
3590
|
+
const audit = parsed.audit ?? {};
|
|
3616
3591
|
return {
|
|
3617
3592
|
mode: mode === "cloud" ? "cloud" : "oss",
|
|
3618
3593
|
daemon: { configured: daemon.configured === true },
|
|
@@ -3627,8 +3602,7 @@ function projectConfig(parsed) {
|
|
|
3627
3602
|
},
|
|
3628
3603
|
telemetry: { enabled: telemetry.enabled !== false },
|
|
3629
3604
|
audit: {
|
|
3630
|
-
auto:
|
|
3631
|
-
notify: audit.notify !== false,
|
|
3605
|
+
auto: audit.auto === true,
|
|
3632
3606
|
intervalDays: readIntervalDays(audit.interval_days),
|
|
3633
3607
|
reportsConsentedAt: typeof audit.reports_consented_at === "number" && Number.isFinite(audit.reports_consented_at) ? audit.reports_consented_at : undefined
|
|
3634
3608
|
}
|
|
@@ -3650,7 +3624,7 @@ var init_fp_config = __esm(() => {
|
|
|
3650
3624
|
environment: "local"
|
|
3651
3625
|
},
|
|
3652
3626
|
telemetry: { enabled: true },
|
|
3653
|
-
audit: { auto: false,
|
|
3627
|
+
audit: { auto: false, intervalDays: DEFAULT_AUDIT_INTERVAL_DAYS }
|
|
3654
3628
|
};
|
|
3655
3629
|
});
|
|
3656
3630
|
|
|
@@ -5902,21 +5876,8 @@ var init_cursor_projects = __esm(() => {
|
|
|
5902
5876
|
// lib/sqlite-reader.ts
|
|
5903
5877
|
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "node:fs";
|
|
5904
5878
|
import initSqlJs from "sql.js/dist/sql-asm.js";
|
|
5905
|
-
function silenceSqliteExperimentalWarning() {
|
|
5906
|
-
if (warningPatched)
|
|
5907
|
-
return;
|
|
5908
|
-
warningPatched = true;
|
|
5909
|
-
const original = process.emitWarning.bind(process);
|
|
5910
|
-
process.emitWarning = (warning, ...rest) => {
|
|
5911
|
-
const text = typeof warning === "string" ? warning : String(warning?.message ?? "");
|
|
5912
|
-
if (text.includes("SQLite is an experimental feature"))
|
|
5913
|
-
return;
|
|
5914
|
-
return original(warning, ...rest);
|
|
5915
|
-
};
|
|
5916
|
-
}
|
|
5917
5879
|
async function tryNodeSqlite(dbPath) {
|
|
5918
5880
|
try {
|
|
5919
|
-
silenceSqliteExperimentalWarning();
|
|
5920
5881
|
const mod = await import("node:sqlite");
|
|
5921
5882
|
const db = new mod.DatabaseSync(dbPath, { readOnly: true });
|
|
5922
5883
|
return {
|
|
@@ -5937,21 +5898,10 @@ function loadSqlJs() {
|
|
|
5937
5898
|
sqlPromise = initSqlJs();
|
|
5938
5899
|
return sqlPromise;
|
|
5939
5900
|
}
|
|
5940
|
-
function clearWalFlag(bytes) {
|
|
5941
|
-
if (bytes.length < 20)
|
|
5942
|
-
return bytes;
|
|
5943
|
-
if (bytes.toString("latin1", 0, 16) !== SQLITE_MAGIC)
|
|
5944
|
-
return bytes;
|
|
5945
|
-
if (bytes[18] === 1 && bytes[19] === 1)
|
|
5946
|
-
return bytes;
|
|
5947
|
-
bytes[18] = 1;
|
|
5948
|
-
bytes[19] = 1;
|
|
5949
|
-
return bytes;
|
|
5950
|
-
}
|
|
5951
5901
|
async function trySqlJs(dbPath) {
|
|
5952
5902
|
try {
|
|
5953
5903
|
const SQL = await loadSqlJs();
|
|
5954
|
-
const db = new SQL.Database(
|
|
5904
|
+
const db = new SQL.Database(readFileSync6(dbPath));
|
|
5955
5905
|
return {
|
|
5956
5906
|
query(sql, params) {
|
|
5957
5907
|
const stmt = db.prepare(sql);
|
|
@@ -5979,7 +5929,7 @@ async function openSqliteReadonly(dbPath) {
|
|
|
5979
5929
|
return null;
|
|
5980
5930
|
return await tryNodeSqlite(dbPath) ?? await trySqlJs(dbPath);
|
|
5981
5931
|
}
|
|
5982
|
-
var
|
|
5932
|
+
var sqlPromise = null;
|
|
5983
5933
|
var init_sqlite_reader = () => {};
|
|
5984
5934
|
|
|
5985
5935
|
// lib/opencode-db.ts
|
|
@@ -8777,15 +8727,6 @@ function joinTexts(blocks, wantedType) {
|
|
|
8777
8727
|
return blocks.filter((b) => b?.type === wantedType && typeof b.text === "string").map((b) => b.text).join(`
|
|
8778
8728
|
`);
|
|
8779
8729
|
}
|
|
8780
|
-
function toolOutputText(output) {
|
|
8781
|
-
if (typeof output === "string")
|
|
8782
|
-
return output;
|
|
8783
|
-
if (Array.isArray(output)) {
|
|
8784
|
-
return output.filter((block) => !!block && typeof block === "object").map((block) => typeof block.text === "string" ? block.text : "").filter(Boolean).join(`
|
|
8785
|
-
`);
|
|
8786
|
-
}
|
|
8787
|
-
return output === undefined ? "" : JSON.stringify(output);
|
|
8788
|
-
}
|
|
8789
8730
|
async function parseCodexLog(fileContent, source = "session") {
|
|
8790
8731
|
const lines = fileContent.split(`
|
|
8791
8732
|
`).filter((line) => line.trim() !== "");
|
|
@@ -8862,11 +8803,10 @@ async function parseCodexLog(fileContent, source = "session") {
|
|
|
8862
8803
|
});
|
|
8863
8804
|
continue;
|
|
8864
8805
|
}
|
|
8865
|
-
if (subType === "function_call"
|
|
8806
|
+
if (subType === "function_call") {
|
|
8866
8807
|
const callId = payload.call_id;
|
|
8867
8808
|
const name = payload.name ?? "function_call";
|
|
8868
|
-
const
|
|
8869
|
-
const input = safeJsonParse4(encodedInput);
|
|
8809
|
+
const input = safeJsonParse4(payload.arguments);
|
|
8870
8810
|
const toolUse = {
|
|
8871
8811
|
type: "tool_use",
|
|
8872
8812
|
id: callId ?? `${timestamp}-${name}`,
|
|
@@ -8885,7 +8825,7 @@ async function parseCodexLog(fileContent, source = "session") {
|
|
|
8885
8825
|
}
|
|
8886
8826
|
continue;
|
|
8887
8827
|
}
|
|
8888
|
-
if (subType === "function_call_output"
|
|
8828
|
+
if (subType === "function_call_output") {
|
|
8889
8829
|
const callId = payload.call_id;
|
|
8890
8830
|
const block = callId ? toolUseById.get(callId) : undefined;
|
|
8891
8831
|
if (block) {
|
|
@@ -8894,7 +8834,7 @@ async function parseCodexLog(fileContent, source = "session") {
|
|
|
8894
8834
|
block.result = {
|
|
8895
8835
|
timestamp,
|
|
8896
8836
|
timestampFormatted: formatTimestamp(date),
|
|
8897
|
-
content:
|
|
8837
|
+
content: typeof payload.output === "string" ? payload.output : JSON.stringify(payload.output),
|
|
8898
8838
|
durationMs: duration,
|
|
8899
8839
|
durationFormatted: formatDuration(duration)
|
|
8900
8840
|
};
|
|
@@ -9089,8 +9029,6 @@ async function parseCopilotLog(fileContent, source = "session") {
|
|
|
9089
9029
|
const rawLines = [];
|
|
9090
9030
|
const toolUseById = new Map;
|
|
9091
9031
|
const toolUseStartMs = new Map;
|
|
9092
|
-
let mostRecentToolUse;
|
|
9093
|
-
let mostRecentToolUseStartMs = 0;
|
|
9094
9032
|
let cwd;
|
|
9095
9033
|
let seenSessionStart = false;
|
|
9096
9034
|
for (let i = 0;i < lines.length; i++) {
|
|
@@ -9186,24 +9124,8 @@ async function parseCopilotLog(fileContent, source = "session") {
|
|
|
9186
9124
|
toolUseById.set(callId, toolUse);
|
|
9187
9125
|
toolUseStartMs.set(callId, date.getTime());
|
|
9188
9126
|
}
|
|
9189
|
-
mostRecentToolUse = toolUse;
|
|
9190
|
-
mostRecentToolUseStartMs = date.getTime();
|
|
9191
9127
|
continue;
|
|
9192
9128
|
}
|
|
9193
|
-
if (recType === "hook.start" && data.hookType === "postToolUse" && mostRecentToolUse) {
|
|
9194
|
-
const input = data.input ?? {};
|
|
9195
|
-
const hookResult = input.toolResult ?? {};
|
|
9196
|
-
const hookContent = hookResult.textResultForLlm ?? hookResult.sessionLog;
|
|
9197
|
-
if (typeof hookContent === "string" && hookContent.length > 0) {
|
|
9198
|
-
mostRecentToolUse.result = {
|
|
9199
|
-
timestamp,
|
|
9200
|
-
timestampFormatted: formatTimestamp(date),
|
|
9201
|
-
content: hookContent,
|
|
9202
|
-
durationMs: Math.max(0, date.getTime() - mostRecentToolUseStartMs),
|
|
9203
|
-
durationFormatted: formatDuration(Math.max(0, date.getTime() - mostRecentToolUseStartMs))
|
|
9204
|
-
};
|
|
9205
|
-
}
|
|
9206
|
-
}
|
|
9207
9129
|
if (recType === "tool.execution_complete") {
|
|
9208
9130
|
const callId = data.toolCallId;
|
|
9209
9131
|
const block = callId ? toolUseById.get(callId) : undefined;
|
|
@@ -9213,8 +9135,7 @@ async function parseCopilotLog(fileContent, source = "session") {
|
|
|
9213
9135
|
const telemetry = data.toolTelemetry ?? {};
|
|
9214
9136
|
const reportedMs = telemetry.metrics?.commandTimeMs ?? telemetry.metrics?.durationMs ?? null;
|
|
9215
9137
|
const durationMs = typeof reportedMs === "number" && reportedMs >= 0 ? reportedMs : Math.max(0, date.getTime() - startMs);
|
|
9216
|
-
const
|
|
9217
|
-
const content = block.result?.content || completionContent;
|
|
9138
|
+
const content = result.detailedContent ?? result.content ?? "";
|
|
9218
9139
|
block.result = {
|
|
9219
9140
|
timestamp,
|
|
9220
9141
|
timestampFormatted: formatTimestamp(date),
|
|
@@ -9338,27 +9259,8 @@ async function parseCursorLog(fileContent, source = "session") {
|
|
|
9338
9259
|
if (!raw.type && raw.role && raw.message?.content) {
|
|
9339
9260
|
const synthDate = new Date(SYNTH_T0 + i);
|
|
9340
9261
|
const synthTs = synthDate.toISOString();
|
|
9341
|
-
const
|
|
9342
|
-
const textParts = messageContent.filter((c) => c?.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
|
|
9262
|
+
const textParts = raw.message.content.filter((c) => c?.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
|
|
9343
9263
|
if (raw.role === "user") {
|
|
9344
|
-
let attachedResult = false;
|
|
9345
|
-
for (const block of messageContent) {
|
|
9346
|
-
if (block?.type !== "tool_result")
|
|
9347
|
-
continue;
|
|
9348
|
-
const callId = typeof block.tool_use_id === "string" ? block.tool_use_id : undefined;
|
|
9349
|
-
const toolUse = callId ? toolUseById.get(callId) : undefined;
|
|
9350
|
-
if (!toolUse)
|
|
9351
|
-
continue;
|
|
9352
|
-
const durationMs = Math.max(0, synthDate.getTime() - (toolUseStartMs.get(callId) ?? synthDate.getTime()));
|
|
9353
|
-
toolUse.result = {
|
|
9354
|
-
timestamp: synthTs,
|
|
9355
|
-
timestampFormatted: formatTimestamp(synthDate),
|
|
9356
|
-
content: typeof block.content === "string" ? block.content : block.content == null ? "" : JSON.stringify(block.content),
|
|
9357
|
-
durationMs,
|
|
9358
|
-
durationFormatted: formatDuration(durationMs)
|
|
9359
|
-
};
|
|
9360
|
-
attachedResult = true;
|
|
9361
|
-
}
|
|
9362
9264
|
const queryMatch = /<user_query>\s*([\s\S]*?)\s*<\/user_query>/.exec(textParts);
|
|
9363
9265
|
const text = queryMatch ? queryMatch[1] : textParts;
|
|
9364
9266
|
if (text) {
|
|
@@ -9367,35 +9269,11 @@ async function parseCursorLog(fileContent, source = "session") {
|
|
|
9367
9269
|
...baseEntry(rawCopy, synthTs, synthDate, source),
|
|
9368
9270
|
message: { role: "user", content: text }
|
|
9369
9271
|
});
|
|
9370
|
-
} else if (!attachedResult) {
|
|
9371
|
-
entries.push({
|
|
9372
|
-
type: "system",
|
|
9373
|
-
...baseEntry(rawCopy, synthTs, synthDate, source),
|
|
9374
|
-
raw: rawCopy
|
|
9375
|
-
});
|
|
9376
9272
|
}
|
|
9377
9273
|
continue;
|
|
9378
9274
|
}
|
|
9379
9275
|
if (raw.role === "assistant") {
|
|
9380
|
-
const blocks = [];
|
|
9381
|
-
if (textParts)
|
|
9382
|
-
blocks.push({ type: "text", text: textParts });
|
|
9383
|
-
for (let j = 0;j < messageContent.length; j++) {
|
|
9384
|
-
const contentBlock = messageContent[j];
|
|
9385
|
-
if (contentBlock?.type !== "tool_use")
|
|
9386
|
-
continue;
|
|
9387
|
-
const name = typeof contentBlock.name === "string" ? contentBlock.name : "tool";
|
|
9388
|
-
const id = typeof contentBlock.id === "string" && contentBlock.id ? contentBlock.id : `cursor-${i}-${name}-${j}`;
|
|
9389
|
-
const toolUse = {
|
|
9390
|
-
type: "tool_use",
|
|
9391
|
-
id,
|
|
9392
|
-
name,
|
|
9393
|
-
input: contentBlock.input && typeof contentBlock.input === "object" ? contentBlock.input : {}
|
|
9394
|
-
};
|
|
9395
|
-
blocks.push(toolUse);
|
|
9396
|
-
toolUseById.set(id, toolUse);
|
|
9397
|
-
toolUseStartMs.set(id, synthDate.getTime());
|
|
9398
|
-
}
|
|
9276
|
+
const blocks = textParts ? [{ type: "text", text: textParts }] : [];
|
|
9399
9277
|
if (blocks.length === 0) {
|
|
9400
9278
|
entries.push({
|
|
9401
9279
|
type: "system",
|
|
@@ -253,49 +253,21 @@ export interface AuditReportBody {
|
|
|
253
253
|
last_seen?: string;
|
|
254
254
|
examples: string[];
|
|
255
255
|
}[];
|
|
256
|
-
/**
|
|
257
|
-
* Credentials this machine found in its own transcripts.
|
|
258
|
-
*
|
|
259
|
-
* Optional on the wire, so a CLI newer than the api-server sends a field the
|
|
260
|
-
* server ignores rather than failing the whole report — the harmful counts
|
|
261
|
-
* are the older half of the contract and must keep arriving either way.
|
|
262
|
-
*
|
|
263
|
-
* Every field here is a mask, a label, a length or a location. There is no
|
|
264
|
-
* shape of this object that carries a secret, because the record it is built
|
|
265
|
-
* from never stores one: `recordLeaks` fingerprints at detection time and
|
|
266
|
-
* keeps only the masked rendering.
|
|
267
|
-
*/
|
|
268
|
-
leaks?: {
|
|
269
|
-
id: string;
|
|
270
|
-
display: string;
|
|
271
|
-
label: string;
|
|
272
|
-
length: number;
|
|
273
|
-
attributed: boolean;
|
|
274
|
-
name: string | null;
|
|
275
|
-
confidence: string;
|
|
276
|
-
first_seen: string;
|
|
277
|
-
last_seen: string;
|
|
278
|
-
occurrences: number;
|
|
279
|
-
cli: string;
|
|
280
|
-
project: string;
|
|
281
|
-
mechanism: string;
|
|
282
|
-
direction: "input" | "result";
|
|
283
|
-
}[];
|
|
284
256
|
}
|
|
285
257
|
|
|
286
258
|
export interface AuditReportResult {
|
|
287
259
|
report_id: string;
|
|
288
260
|
/** Whether this report produced an email. */
|
|
289
261
|
emailed: boolean;
|
|
290
|
-
/** `
|
|
262
|
+
/** `below_threshold`, `cooldown`, `send_failed`, or null when mail went out. */
|
|
291
263
|
reason: string | null;
|
|
292
264
|
/**
|
|
293
265
|
* Where the next window starts, per the SERVER.
|
|
294
266
|
*
|
|
295
267
|
* Persisted verbatim rather than computed locally. The server anchors it on
|
|
296
|
-
* the last DELIVERED
|
|
268
|
+
* the last DELIVERED digest, so a report held by the cooldown — or one whose
|
|
297
269
|
* send failed — correctly leaves the watermark where it was, and its findings
|
|
298
|
-
* turn up in the next
|
|
270
|
+
* turn up in the next digest instead of falling into a gap. A machine that
|
|
299
271
|
* lost `machine.json` also resyncs here rather than re-reporting from the
|
|
300
272
|
* beginning of time.
|
|
301
273
|
*/
|
|
@@ -303,11 +275,11 @@ export interface AuditReportResult {
|
|
|
303
275
|
}
|
|
304
276
|
|
|
305
277
|
/**
|
|
306
|
-
* Submit one scheduled scan's harmful findings
|
|
278
|
+
* Submit one scheduled scan's harmful findings.
|
|
307
279
|
*
|
|
308
280
|
* Called only by the audit child, and only on `--scheduled`. The destination
|
|
309
281
|
* address is never sent: the api-server takes it from the access-token claims,
|
|
310
|
-
* so a report cannot name where its
|
|
282
|
+
* so a report cannot name where its digest goes.
|
|
311
283
|
*/
|
|
312
284
|
export async function submitAuditReport(
|
|
313
285
|
accessToken: string,
|
package/lib/claude-sessions.ts
CHANGED
|
@@ -4,14 +4,8 @@
|
|
|
4
4
|
* Claude stores transcripts at:
|
|
5
5
|
* <CLAUDE_PROJECTS_PATH>/<encoded-cwd>/<sessionId>.jsonl
|
|
6
6
|
*
|
|
7
|
-
* Subagent transcripts (when a session spawned subagents) live alongside
|
|
8
|
-
* shapes — a direct child, and one nested per workflow run:
|
|
7
|
+
* Subagent transcripts (when a session spawned subagents) live alongside:
|
|
9
8
|
* <CLAUDE_PROJECTS_PATH>/<encoded-cwd>/<sessionId>/subagents/<agentId>.jsonl
|
|
10
|
-
* <CLAUDE_PROJECTS_PATH>/<encoded-cwd>/<sessionId>/subagents/workflows/<runId>/<agentId>.jsonl
|
|
11
|
-
*
|
|
12
|
-
* Everything below `subagents/` is walked to a bounded depth rather than one
|
|
13
|
-
* level, because the second shape arrived after this module was written and the
|
|
14
|
-
* miss was most of the corpus. See `collectSubagentTranscripts`.
|
|
15
9
|
*
|
|
16
10
|
* The parser for these files lives in `lib/log-entries.ts` (`parseLogContent`,
|
|
17
11
|
* `parseSessionLog`). This module exposes discovery only — the audit pipeline
|
|
@@ -76,99 +70,6 @@ export function listClaudeProjects(): ClaudeProjectFolder[] {
|
|
|
76
70
|
/** Lists every JSONL transcript under one Claude project folder, including
|
|
77
71
|
* subagent transcripts under `<sessionId>/subagents/`. Returns [] on missing
|
|
78
72
|
* or unreadable paths. */
|
|
79
|
-
/**
|
|
80
|
-
* Depth of nesting allowed below `subagents/`.
|
|
81
|
-
*
|
|
82
|
-
* The two shapes that exist today need 0 and 2 (`<agent>.jsonl` and
|
|
83
|
-
* `workflows/<runId>/<agent>.jsonl`). The cap is here so an unexpected layout —
|
|
84
|
-
* or a symlink cycle a future Claude build introduces — costs a bounded walk
|
|
85
|
-
* rather than an audit that never returns, and it is deliberately loose enough
|
|
86
|
-
* that a third shape lands inside it without another release.
|
|
87
|
-
*/
|
|
88
|
-
const MAX_SUBAGENT_DEPTH = 5;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Collect every `.jsonl` beneath a session's `subagents/` directory.
|
|
92
|
-
*
|
|
93
|
-
* This used to read only the DIRECT children of `subagents/`, which was correct
|
|
94
|
-
* for the layout Claude shipped when it was written and silently wrong the day
|
|
95
|
-
* workflow runs started nesting their agents one level further down. On a
|
|
96
|
-
* machine that uses them the miss is most of the corpus: 1,839 transcripts on
|
|
97
|
-
* disk, 1,741 under `subagents/`, and 1,679 of those inside
|
|
98
|
-
* `subagents/workflows/<runId>/` — so the audit was walking 160 files, 8.7% of
|
|
99
|
-
* the evidence, and reporting the result as though it had read everything.
|
|
100
|
-
*
|
|
101
|
-
* ## Session ids come from the relative path, not the basename
|
|
102
|
-
*
|
|
103
|
-
* Every workflow run writes a `journal.jsonl` beside its agents, so basenames
|
|
104
|
-
* are NOT unique below this directory — 1,741 files share 1,613 distinct names
|
|
105
|
-
* on the machine this was found on. A basename id would collide those 128 files
|
|
106
|
-
* onto ~one row each, and `sessionId` is what the cache, the per-session
|
|
107
|
-
* detector state and the example attribution are keyed by, so the collision
|
|
108
|
-
* would silently merge unrelated sessions rather than fail.
|
|
109
|
-
*
|
|
110
|
-
* Nor is the path below `subagents/` unique on its own. A workflow run id is
|
|
111
|
-
* reused when its session is resumed, so `wf_3d609e92-a38/journal.jsonl` exists
|
|
112
|
-
* under two different parent sessions in the same project — found by asserting
|
|
113
|
-
* uniqueness over the real corpus, not by reasoning about it.
|
|
114
|
-
*
|
|
115
|
-
* The id is therefore the PARENT SESSION id followed by the path relative to
|
|
116
|
-
* `subagents/`, minus the extension, joined with `__`:
|
|
117
|
-
* `<parentUuid>__workflows__wf_123__agent-abc`. That is a filesystem path
|
|
118
|
-
* within the project, so it is unique by construction rather than by argument,
|
|
119
|
-
* and it names the session the subagent belongs to. `__` is safe as the joiner
|
|
120
|
-
* because no id Claude generates contains one — verified against 1,741 real
|
|
121
|
-
* files, zero hits. Top-level session ids are untouched.
|
|
122
|
-
*
|
|
123
|
-
* Symlinks are not followed. Nothing in the layout uses them, and following one
|
|
124
|
-
* is how a directory walk turns into an infinite loop.
|
|
125
|
-
*/
|
|
126
|
-
function collectSubagentTranscripts(
|
|
127
|
-
dir: string,
|
|
128
|
-
relPrefix: string,
|
|
129
|
-
project: ClaudeProjectFolder,
|
|
130
|
-
out: ClaudeTranscriptFile[],
|
|
131
|
-
depth: number,
|
|
132
|
-
): void {
|
|
133
|
-
if (depth > MAX_SUBAGENT_DEPTH) return;
|
|
134
|
-
let entries: import("node:fs").Dirent[];
|
|
135
|
-
try {
|
|
136
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
137
|
-
} catch {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
for (const entry of entries) {
|
|
141
|
-
if (entry.isSymbolicLink()) continue;
|
|
142
|
-
if (entry.isDirectory()) {
|
|
143
|
-
collectSubagentTranscripts(
|
|
144
|
-
join(dir, entry.name),
|
|
145
|
-
relPrefix ? `${relPrefix}__${entry.name}` : entry.name,
|
|
146
|
-
project,
|
|
147
|
-
out,
|
|
148
|
-
depth + 1,
|
|
149
|
-
);
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
153
|
-
const stem = entry.name.slice(0, -".jsonl".length);
|
|
154
|
-
const transcriptPath = join(dir, entry.name);
|
|
155
|
-
try {
|
|
156
|
-
const s = statSync(transcriptPath);
|
|
157
|
-
out.push({
|
|
158
|
-
projectName: project.name,
|
|
159
|
-
cwd: project.cwd,
|
|
160
|
-
sessionId: relPrefix ? `${relPrefix}__${stem}` : stem,
|
|
161
|
-
transcriptPath,
|
|
162
|
-
mtimeMs: s.mtimeMs,
|
|
163
|
-
sizeBytes: s.size,
|
|
164
|
-
isSubagent: true,
|
|
165
|
-
});
|
|
166
|
-
} catch {
|
|
167
|
-
// unreadable — skip
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
73
|
export function listClaudeTranscripts(project: ClaudeProjectFolder): ClaudeTranscriptFile[] {
|
|
173
74
|
const out: ClaudeTranscriptFile[] = [];
|
|
174
75
|
let entries: import("node:fs").Dirent[];
|
|
@@ -198,9 +99,34 @@ export function listClaudeTranscripts(project: ClaudeProjectFolder): ClaudeTrans
|
|
|
198
99
|
// unreadable — skip
|
|
199
100
|
}
|
|
200
101
|
} else if (entry.isDirectory() && UUID_RE.test(entry.name)) {
|
|
102
|
+
// Subagent transcripts at <sessionId>/subagents/<agentId>.jsonl
|
|
201
103
|
const subDir = join(project.path, entry.name, "subagents");
|
|
202
104
|
if (!existsSync(subDir)) continue;
|
|
203
|
-
|
|
105
|
+
let subEntries: import("node:fs").Dirent[];
|
|
106
|
+
try {
|
|
107
|
+
subEntries = readdirSync(subDir, { withFileTypes: true });
|
|
108
|
+
} catch {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
for (const sub of subEntries) {
|
|
112
|
+
if (!sub.isFile() || !sub.name.endsWith(".jsonl")) continue;
|
|
113
|
+
const agentId = sub.name.slice(0, -".jsonl".length);
|
|
114
|
+
const transcriptPath = join(subDir, sub.name);
|
|
115
|
+
try {
|
|
116
|
+
const s = statSync(transcriptPath);
|
|
117
|
+
out.push({
|
|
118
|
+
projectName: project.name,
|
|
119
|
+
cwd: project.cwd,
|
|
120
|
+
sessionId: agentId,
|
|
121
|
+
transcriptPath,
|
|
122
|
+
mtimeMs: s.mtimeMs,
|
|
123
|
+
sizeBytes: s.size,
|
|
124
|
+
isSubagent: true,
|
|
125
|
+
});
|
|
126
|
+
} catch {
|
|
127
|
+
// unreadable — skip
|
|
128
|
+
}
|
|
129
|
+
}
|
|
204
130
|
}
|
|
205
131
|
}
|
|
206
132
|
|
package/lib/codex-sessions.ts
CHANGED
|
@@ -158,21 +158,6 @@ function joinTexts(blocks: CodexContentBlock[] | undefined, wantedType: "input_t
|
|
|
158
158
|
.join("\n");
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
/** Text carried by tool outputs. Newer Codex chronicles use an array of
|
|
162
|
-
* `input_text` blocks for `custom_tool_call_output`, while older releases use
|
|
163
|
-
* one string for `function_call_output`. */
|
|
164
|
-
function toolOutputText(output: unknown): string {
|
|
165
|
-
if (typeof output === "string") return output;
|
|
166
|
-
if (Array.isArray(output)) {
|
|
167
|
-
return output
|
|
168
|
-
.filter((block): block is CodexContentBlock => !!block && typeof block === "object")
|
|
169
|
-
.map((block) => typeof block.text === "string" ? block.text : "")
|
|
170
|
-
.filter(Boolean)
|
|
171
|
-
.join("\n");
|
|
172
|
-
}
|
|
173
|
-
return output === undefined ? "" : JSON.stringify(output);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
161
|
/**
|
|
177
162
|
* Parse a Codex JSONL transcript into `LogEntry[]` plus the raw lines.
|
|
178
163
|
* Yields to the event loop every 200 lines so big transcripts don't block.
|
|
@@ -265,11 +250,10 @@ export async function parseCodexLog(
|
|
|
265
250
|
continue;
|
|
266
251
|
}
|
|
267
252
|
|
|
268
|
-
if (subType === "function_call"
|
|
253
|
+
if (subType === "function_call") {
|
|
269
254
|
const callId = payload.call_id as string | undefined;
|
|
270
255
|
const name = (payload.name as string | undefined) ?? "function_call";
|
|
271
|
-
const
|
|
272
|
-
const input = safeJsonParse(encodedInput);
|
|
256
|
+
const input = safeJsonParse(payload.arguments as string | undefined);
|
|
273
257
|
const toolUse: ToolUseBlock = {
|
|
274
258
|
type: "tool_use",
|
|
275
259
|
id: callId ?? `${timestamp}-${name}`,
|
|
@@ -289,7 +273,7 @@ export async function parseCodexLog(
|
|
|
289
273
|
continue;
|
|
290
274
|
}
|
|
291
275
|
|
|
292
|
-
if (subType === "function_call_output"
|
|
276
|
+
if (subType === "function_call_output") {
|
|
293
277
|
const callId = payload.call_id as string | undefined;
|
|
294
278
|
const block = callId ? toolUseById.get(callId) : undefined;
|
|
295
279
|
if (block) {
|
|
@@ -298,7 +282,7 @@ export async function parseCodexLog(
|
|
|
298
282
|
block.result = {
|
|
299
283
|
timestamp,
|
|
300
284
|
timestampFormatted: formatTimestamp(date),
|
|
301
|
-
content:
|
|
285
|
+
content: typeof payload.output === "string" ? (payload.output as string) : JSON.stringify(payload.output),
|
|
302
286
|
durationMs: duration,
|
|
303
287
|
durationFormatted: formatDuration(duration),
|
|
304
288
|
};
|
package/lib/copilot-sessions.ts
CHANGED
|
@@ -151,11 +151,6 @@ interface CopilotToolResult {
|
|
|
151
151
|
detailedContent?: string;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
interface CopilotHookToolResult {
|
|
155
|
-
textResultForLlm?: string;
|
|
156
|
-
sessionLog?: string;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
154
|
interface CopilotToolTelemetry {
|
|
160
155
|
metrics?: { commandTimeMs?: number; durationMs?: number };
|
|
161
156
|
properties?: Record<string, unknown>;
|
|
@@ -176,8 +171,6 @@ export async function parseCopilotLog(
|
|
|
176
171
|
// toolCallId → tool_use block, so we can attach tool.execution_complete back.
|
|
177
172
|
const toolUseById = new Map<string, ToolUseBlock>();
|
|
178
173
|
const toolUseStartMs = new Map<string, number>();
|
|
179
|
-
let mostRecentToolUse: ToolUseBlock | undefined;
|
|
180
|
-
let mostRecentToolUseStartMs = 0;
|
|
181
174
|
let cwd: string | undefined;
|
|
182
175
|
let seenSessionStart = false;
|
|
183
176
|
|
|
@@ -280,32 +273,9 @@ export async function parseCopilotLog(
|
|
|
280
273
|
toolUseById.set(callId, toolUse);
|
|
281
274
|
toolUseStartMs.set(callId, date.getTime());
|
|
282
275
|
}
|
|
283
|
-
mostRecentToolUse = toolUse;
|
|
284
|
-
mostRecentToolUseStartMs = date.getTime();
|
|
285
276
|
continue;
|
|
286
277
|
}
|
|
287
278
|
|
|
288
|
-
// Copilot CLI 1.0.39 can omit the command's real stdout from
|
|
289
|
-
// `tool.execution_complete` and expose it only to the PostToolUse hook as
|
|
290
|
-
// `input.toolResult.textResultForLlm`. That is the value the model saw and
|
|
291
|
-
// the value failproofai must audit. Keep it on the active tool block; the
|
|
292
|
-
// later completion record may still contribute timing, but must not replace
|
|
293
|
-
// this output with its shorter status-only summary.
|
|
294
|
-
if (recType === "hook.start" && data.hookType === "postToolUse" && mostRecentToolUse) {
|
|
295
|
-
const input = (data.input as Record<string, unknown> | undefined) ?? {};
|
|
296
|
-
const hookResult = (input.toolResult as CopilotHookToolResult | undefined) ?? {};
|
|
297
|
-
const hookContent = hookResult.textResultForLlm ?? hookResult.sessionLog;
|
|
298
|
-
if (typeof hookContent === "string" && hookContent.length > 0) {
|
|
299
|
-
mostRecentToolUse.result = {
|
|
300
|
-
timestamp,
|
|
301
|
-
timestampFormatted: formatTimestamp(date),
|
|
302
|
-
content: hookContent,
|
|
303
|
-
durationMs: Math.max(0, date.getTime() - mostRecentToolUseStartMs),
|
|
304
|
-
durationFormatted: formatDuration(Math.max(0, date.getTime() - mostRecentToolUseStartMs)),
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
279
|
if (recType === "tool.execution_complete") {
|
|
310
280
|
const callId = data.toolCallId as string | undefined;
|
|
311
281
|
const block = callId ? toolUseById.get(callId) : undefined;
|
|
@@ -319,8 +289,7 @@ export async function parseCopilotLog(
|
|
|
319
289
|
typeof reportedMs === "number" && reportedMs >= 0
|
|
320
290
|
? reportedMs
|
|
321
291
|
: Math.max(0, date.getTime() - startMs);
|
|
322
|
-
const
|
|
323
|
-
const content = block.result?.content || completionContent;
|
|
292
|
+
const content = result.detailedContent ?? result.content ?? "";
|
|
324
293
|
block.result = {
|
|
325
294
|
timestamp,
|
|
326
295
|
timestampFormatted: formatTimestamp(date),
|