failproofai 1.0.0-beta.0 → 1.0.0-beta.10
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/app-path-routes-manifest.json +2 -1
- package/.next/standalone/.next/build-manifest.json +6 -6
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/routes-manifest.json +6 -0
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- 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 +3 -1
- 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 +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- 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 +3 -3
- 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 +3 -1
- 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 +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
- 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 -3
- 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 +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 +2 -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 +3 -2
- 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 +3 -2
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
- 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 +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 +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +5 -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 +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +3 -1
- 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 +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +30 -18
- package/.next/standalone/.next/server/app/policies/page.js +5 -3
- 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 +3 -3
- 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 +4 -2
- 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 +3 -3
- 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 +6 -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 +3 -3
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +4 -2
- 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/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
- package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
- package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
- package/.next/standalone/.next/server/app/settings/page.js +18 -0
- package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
- package/.next/standalone/.next/server/chunks/[externals]__0h9_83k._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[externals]__1ifpkx-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ky_n0r._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0lk_935._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__16le-kd._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0v2fpxe._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +3 -3
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__1_ps0jw._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__1a7i2q4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1iny24d._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tyedjt._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +5 -0
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +5 -0
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +5 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[externals]__1aq139v._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04pwh4t._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__170799-._.js → [root-of-the-server]__0spkm68._.js} +11 -11
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__10butu6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1a2hcb_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1apb7k_._.js → [root-of-the-server]__1rdruw4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tyf0tc._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01od0m6._.js → [root-of-the-server]__1yw368c._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_04mekdy._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0r-dsre._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0se484m._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0uz7o9y._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1e19atl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1fahg9e._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1gmzkwj._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/_1w8sola._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1w_6p9g._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1y4qr7u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
- 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 +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +5 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
- package/.next/standalone/.next/server/middleware.js +2 -2
- 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 +74 -20
- package/.next/standalone/.next/static/chunks/00adubtgov21s.js +1 -0
- package/.next/standalone/.next/static/chunks/{03fmihek9n986.js → 06zgzyh3wv1ig.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1hdhteui932bq.js → 0qmo2t50kpb30.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1grd7y94-igz9.js → 0yudogeqddpzr.js} +1 -1
- package/.next/standalone/.next/static/chunks/16p68cybetr31.js +1 -0
- package/.next/standalone/.next/static/chunks/1bm0q12hgs22l.css +2 -0
- package/.next/standalone/.next/static/chunks/{1d6ncspjagm53.js → 1fu90ch80qngv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2vr7aazw6k2-n.js → 1m416lie3qwsj.js} +1 -1
- package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
- package/.next/standalone/.next/static/chunks/1ypqzvoal8j56.js +6 -0
- package/.next/standalone/.next/static/chunks/23kev26by1e4f.js +1 -0
- package/.next/standalone/.next/static/chunks/{29k6ef49zppxj.js → 2h4sbmp0ad78w.js} +1 -1
- package/.next/standalone/.next/static/chunks/2obwg4tterjpa.js +1 -0
- package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
- package/.next/standalone/.next/static/chunks/{29ydr-8q0zis6.js → 30ufy4_e2n78e.js} +22 -22
- package/.next/standalone/.next/static/chunks/31coz11ia5vc4.js +1 -0
- package/.next/standalone/.next/static/chunks/{1s-_swlc80y43.js → 3p4j0l1o_p-nm.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ip1n8xmgxarv.js → 3uxnxwxcctyj0.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-1lsv92x7klwrn.js → turbopack-3diub4ctvn1n0.js} +1 -1
- package/.next/standalone/app/actions/get-active-pauses.ts +16 -0
- package/.next/standalone/app/actions/get-hooks-config.ts +2 -1
- package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
- package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
- package/.next/standalone/app/api/audit/run/route.ts +28 -0
- package/.next/standalone/app/api/audit/status/route.ts +13 -1
- package/.next/standalone/app/api/auth/status/route.ts +1 -1
- package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
- package/.next/standalone/app/audit/audit-styles.css +6 -149
- package/.next/standalone/app/components/pause-notices.tsx +111 -0
- package/.next/standalone/app/policies/hooks-client.tsx +81 -6
- package/.next/standalone/app/settings/page.tsx +31 -0
- package/.next/standalone/app/settings/settings-client.tsx +488 -0
- package/.next/standalone/components/navbar.tsx +2 -0
- package/.next/standalone/lib/auth/api-server-client.ts +2 -3
- package/.next/standalone/lib/auth/auth-store.ts +4 -4
- package/.next/standalone/lib/codex-sessions.ts +2 -1
- package/.next/standalone/lib/dashboard-host.ts +101 -0
- package/.next/standalone/lib/install-check.ts +22 -7
- package/.next/standalone/lib/pi-sessions.ts +99 -14
- package/.next/standalone/lib/telemetry-enabled.ts +54 -0
- package/.next/standalone/lib/telemetry-id.ts +52 -1
- package/.next/standalone/lib/telemetry.ts +8 -4
- package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
- package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
- package/.next/standalone/node_modules/react/package.json +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/package.json +4 -4
- package/.next/standalone/package.json +17 -10
- package/.next/standalone/proxy.ts +89 -1
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +518 -79
- package/dist/cli.mjs +11484 -6046
- package/dist/worker.mjs +2019 -272
- package/lib/auth/api-server-client.ts +2 -3
- package/lib/auth/auth-store.ts +4 -4
- package/lib/codex-sessions.ts +2 -1
- package/lib/dashboard-host.ts +101 -0
- package/lib/install-check.ts +22 -7
- package/lib/pi-sessions.ts +99 -14
- package/lib/telemetry-enabled.ts +54 -0
- package/lib/telemetry-id.ts +52 -1
- package/lib/telemetry.ts +8 -4
- package/package.json +17 -10
- package/scripts/build-daemon-packages.mjs +210 -0
- package/scripts/daemon-platforms.mjs +42 -0
- package/scripts/install-telemetry.mjs +8 -1
- package/scripts/launch.ts +25 -3
- package/scripts/parse-script-args.ts +17 -1
- package/scripts/prune-standalone.mjs +26 -0
- package/scripts/publish-aliases.mjs +62 -41
- package/scripts/repro-npm-install.sh +155 -0
- package/scripts/translate-docs/readme-translator.ts +163 -4
- package/scripts/validate-mdx.ts +153 -13
- package/src/audit/audit-lock.ts +285 -0
- package/src/audit/audit-schedule.ts +111 -0
- package/src/audit/cache.ts +18 -4
- package/src/audit/cli-adapters/goose.ts +2 -1
- package/src/audit/cli-adapters/hermes.ts +28 -10
- package/src/audit/cli.ts +191 -35
- package/src/audit/dashboard-cache.ts +2 -1
- package/src/hooks/backfill-cli.ts +247 -0
- package/src/hooks/builtin-policies.ts +390 -2
- package/src/hooks/cloud-connection.ts +354 -0
- package/src/hooks/cloud-enrollment-cli.ts +325 -0
- package/src/hooks/cloud-enrollment.ts +243 -0
- package/src/hooks/cloud-introspect.ts +147 -0
- package/src/hooks/cloud-managed-policies.ts +169 -0
- package/src/hooks/collector-config.ts +234 -0
- package/src/hooks/configure-wizard.ts +915 -158
- package/src/hooks/custom-hooks-loader.ts +191 -33
- package/src/hooks/daemon-client.ts +136 -17
- package/src/hooks/daemon-download.ts +192 -30
- package/src/hooks/daemon-service.ts +1190 -92
- package/src/hooks/first-run-gate.ts +50 -0
- package/src/hooks/fp-config.ts +497 -0
- package/src/hooks/fp-home.ts +375 -0
- package/src/hooks/fp-reset.ts +464 -0
- package/src/hooks/handler.ts +185 -6
- package/src/hooks/hook-activity-store.ts +85 -20
- package/src/hooks/hook-logger.ts +2 -1
- package/src/hooks/hook-telemetry.ts +5 -1
- package/src/hooks/hooks-config.ts +4 -3
- package/src/hooks/loader-utils.ts +171 -8
- package/src/hooks/manager.ts +5 -4
- package/src/hooks/onboarding-attempt.ts +179 -0
- package/src/hooks/onboarding-lock.ts +119 -0
- package/src/hooks/policy-types.ts +28 -0
- package/src/hooks/session-pause-cli.ts +159 -0
- package/src/hooks/session-pause.ts +268 -0
- package/src/hooks/setup-state.ts +256 -0
- package/src/hooks/tui.ts +119 -4
- package/src/hooks/uninstall-cli.ts +345 -0
- package/src/hooks/worker-server.ts +65 -3
- package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +0 -3
- package/.next/standalone/.next/server/chunks/[externals]__1s61mel._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0id_xf7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0longh-._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__1_g_b3t._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0259h38._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uno39i._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zj-87g._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1-upb14.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
- package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
- package/.next/standalone/.next/static/chunks/0u9hc6oxx-gpj.js +0 -6
- package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +0 -1
- package/.next/standalone/.next/static/chunks/2mazwb1qmur1p.js +0 -1
- package/.next/standalone/.next/static/chunks/2pujpnfx4pws6.css +0 -2
- package/.next/standalone/.next/static/chunks/33u59vf_8xpd-.js +0 -1
- package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
- package/.next/standalone/.next/static/chunks/3wrgbih-516uj.js +0 -1
- package/.next/standalone/Cargo.lock +0 -428
- package/.next/standalone/Cargo.toml +0 -9
- package/.next/standalone/crates/PROTOCOL.md +0 -122
- package/.next/standalone/crates/failproofaid/Cargo.toml +0 -18
- package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
- package/.next/standalone/crates/failproofaid/src/main.rs +0 -83
- package/.next/standalone/crates/failproofaid/src/paths.rs +0 -172
- package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
- package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
- package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
- package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
- package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
- package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
- package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
- package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
- package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
- package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
- package/.next/standalone/integration-suite/Dockerfile +0 -47
- package/.next/standalone/integration-suite/README.md +0 -129
- package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
- package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
- package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
- package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
- package/.next/standalone/integration-suite/install-clis.sh +0 -136
- package/.next/standalone/integration-suite/probe-cli.sh +0 -248
- package/.next/standalone/integration-suite/report.js +0 -120
- package/.next/standalone/integration-suite/run.sh +0 -159
- package/.next/standalone/openclaw-plugin/index.js +0 -223
- package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
- package/.next/standalone/openclaw-plugin/package.json +0 -12
- package/.next/standalone/osv-scanner.toml +0 -17
- package/.next/standalone/pi-extension/index.ts +0 -524
- package/.next/standalone/pi-extension/package.json +0 -12
- package/.next/standalone/postcss.config.mjs +0 -8
- package/.next/standalone/readme-arch-hq.gif +0 -0
- package/.next/standalone/rust-toolchain.toml +0 -4
- package/src/auth/cli.ts +0 -371
- /package/.next/standalone/.next/static/{7Lxtd352rSaHB-pmm6G8M → pBBcTvE6_VueYGbacy1kg}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{7Lxtd352rSaHB-pmm6G8M → pBBcTvE6_VueYGbacy1kg}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{7Lxtd352rSaHB-pmm6G8M → pBBcTvE6_VueYGbacy1kg}/_ssgManifest.js +0 -0
package/dist/worker.mjs
CHANGED
|
@@ -362,6 +362,37 @@ function normalizeCliPayload(cli, parsed) {
|
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
+
// src/hooks/fp-home.ts
|
|
366
|
+
import { homedir } from "node:os";
|
|
367
|
+
import { resolve } from "node:path";
|
|
368
|
+
function failproofaiHome(home) {
|
|
369
|
+
if (home)
|
|
370
|
+
return resolve(home, ".failproofai");
|
|
371
|
+
return process.env.FAILPROOFAI_HOME || resolve(homedir(), ".failproofai");
|
|
372
|
+
}
|
|
373
|
+
var LAYOUT_VERSION = 2, at = (...parts) => resolve(failproofaiHome(), ...parts), atHome = (home, ...parts) => home ? resolve(failproofaiHome(home), ...parts) : at(...parts), versionFile = (home) => atHome(home, "VERSION"), configFile = (home) => atHome(home, "config.toml"), policiesDir = (home) => atHome(home, "policies"), localPoliciesDir = (home) => atHome(home, "policies", "local-policies"), globalPolicyConfigFile = (home) => resolve(localPoliciesDir(home), "policies-config.json"), cloudPoliciesDir = (home) => resolve(policiesDir(home), "cloud-policies"), customPoliciesDir = (home) => resolve(policiesDir(home), "custom-policies"), hookActivityDir = (home) => atHome(home, "hook-activity"), stateDir = (home) => atHome(home, "state"), shimsDir = (home) => resolve(stateDir(home), "shims"), sessionPauseDir = () => resolve(stateDir(), "sessions"), telemetryIdFile = (home) => resolve(stateDir(home), "telemetry-id"), codexSessionPathsFile = (home) => resolve(stateDir(home), "codex-session-paths.json"), logsDir = (home) => atHome(home, "logs"), legacy;
|
|
374
|
+
var init_fp_home = __esm(() => {
|
|
375
|
+
legacy = {
|
|
376
|
+
policyConfig: () => at("policies-config.json"),
|
|
377
|
+
policyConfigLocal: () => at("policies-config.local.json"),
|
|
378
|
+
cloudCredentials: () => at("cloud.json"),
|
|
379
|
+
ingestCredentials: () => at("ingest.json"),
|
|
380
|
+
launcherMarker: () => at(".launcher-configured"),
|
|
381
|
+
lastVersion: () => at("last-version"),
|
|
382
|
+
auditDashboard: () => at("audit-dashboard.json"),
|
|
383
|
+
cacheDir: () => at("cache"),
|
|
384
|
+
hookActivityDir: () => at("cache", "hook-activity"),
|
|
385
|
+
auditCacheDir: () => at("cache", "audit"),
|
|
386
|
+
codexSessionPaths: () => at("cache", "codex-session-paths.json"),
|
|
387
|
+
spoolDir: () => at("spool"),
|
|
388
|
+
failedDir: () => at("failed"),
|
|
389
|
+
collectorHealth: () => at("collector-health.json"),
|
|
390
|
+
sessionPauseDir: () => at("state", "sessions"),
|
|
391
|
+
cloudManagedPolicies: () => at("policies", "cloud-managed"),
|
|
392
|
+
onboardingLock: () => at(".onboarding.lock")
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
|
|
365
396
|
// src/hooks/hook-logger.ts
|
|
366
397
|
import {
|
|
367
398
|
appendFileSync,
|
|
@@ -371,7 +402,6 @@ import {
|
|
|
371
402
|
statSync
|
|
372
403
|
} from "node:fs";
|
|
373
404
|
import { join } from "node:path";
|
|
374
|
-
import { homedir } from "node:os";
|
|
375
405
|
function ensureResolved() {
|
|
376
406
|
if (resolved)
|
|
377
407
|
return;
|
|
@@ -443,15 +473,16 @@ function hookLogError(msg) {
|
|
|
443
473
|
}
|
|
444
474
|
var LEVEL_ORDER, MAX_FILE_SIZE, LOG_FILENAME = "hooks.log", DEFAULT_LOG_DIR, resolved = false, currentLevel = "warn", fileLoggingEnabled = false, logDir;
|
|
445
475
|
var init_hook_logger = __esm(() => {
|
|
476
|
+
init_fp_home();
|
|
446
477
|
LEVEL_ORDER = { info: 0, warn: 1, error: 2 };
|
|
447
478
|
MAX_FILE_SIZE = 512 * 1024;
|
|
448
|
-
DEFAULT_LOG_DIR =
|
|
479
|
+
DEFAULT_LOG_DIR = logsDir();
|
|
449
480
|
logDir = DEFAULT_LOG_DIR;
|
|
450
481
|
});
|
|
451
482
|
|
|
452
483
|
// src/hooks/hooks-config.ts
|
|
453
484
|
import { readFileSync, writeFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, statSync as statSync2 } from "node:fs";
|
|
454
|
-
import { resolve, dirname } from "node:path";
|
|
485
|
+
import { resolve as resolve2, dirname } from "node:path";
|
|
455
486
|
import { homedir as homedir2 } from "node:os";
|
|
456
487
|
function readConfigAt(path) {
|
|
457
488
|
if (!existsSync2(path))
|
|
@@ -466,9 +497,9 @@ function readConfigAt(path) {
|
|
|
466
497
|
}
|
|
467
498
|
function findProjectConfigDir(start) {
|
|
468
499
|
const home = homedir2();
|
|
469
|
-
let dir =
|
|
500
|
+
let dir = resolve2(start);
|
|
470
501
|
while (dir !== home) {
|
|
471
|
-
const marker =
|
|
502
|
+
const marker = resolve2(dir, ".failproofai");
|
|
472
503
|
try {
|
|
473
504
|
if (statSync2(marker).isDirectory())
|
|
474
505
|
return dir;
|
|
@@ -478,13 +509,13 @@ function findProjectConfigDir(start) {
|
|
|
478
509
|
break;
|
|
479
510
|
dir = parent;
|
|
480
511
|
}
|
|
481
|
-
return
|
|
512
|
+
return resolve2(start);
|
|
482
513
|
}
|
|
483
514
|
function readMergedHooksConfig(cwd) {
|
|
484
515
|
const base = findProjectConfigDir(cwd ?? process.cwd());
|
|
485
|
-
const projectPath =
|
|
486
|
-
const localPath =
|
|
487
|
-
const globalPath =
|
|
516
|
+
const projectPath = resolve2(base, ".failproofai", "policies-config.json");
|
|
517
|
+
const localPath = resolve2(base, ".failproofai", "policies-config.local.json");
|
|
518
|
+
const globalPath = globalPolicyConfigFile();
|
|
488
519
|
const project = readConfigAt(projectPath);
|
|
489
520
|
const local = readConfigAt(localPath);
|
|
490
521
|
const global_ = readConfigAt(globalPath);
|
|
@@ -522,6 +553,7 @@ function readMergedHooksConfig(cwd) {
|
|
|
522
553
|
}
|
|
523
554
|
var init_hooks_config = __esm(() => {
|
|
524
555
|
init_hook_logger();
|
|
556
|
+
init_fp_home();
|
|
525
557
|
});
|
|
526
558
|
|
|
527
559
|
// src/hooks/policy-helpers.ts
|
|
@@ -596,7 +628,7 @@ function clearPolicies() {
|
|
|
596
628
|
var REGISTRY_KEY = "__FAILPROOFAI_POLICY_REGISTRY__", INDEX_CACHE_KEY = "__FAILPROOFAI_POLICY_INDEX_CACHE__", DEFAULT_POLICY_NAMESPACE = "failproofai";
|
|
597
629
|
|
|
598
630
|
// src/hooks/builtin-policies.ts
|
|
599
|
-
import { resolve as
|
|
631
|
+
import { resolve as resolve3, join as join2 } from "node:path";
|
|
600
632
|
import { statSync as statSync3 } from "node:fs";
|
|
601
633
|
import { readFile, writeFile } from "node:fs/promises";
|
|
602
634
|
import { execSync, execFileSync } from "node:child_process";
|
|
@@ -655,6 +687,65 @@ function getFilePath(ctx) {
|
|
|
655
687
|
function parseArgvTokens(cmd) {
|
|
656
688
|
return cmd.trim().split(/\s+/).map((t) => t.replace(/^['"]|['"]$/g, ""));
|
|
657
689
|
}
|
|
690
|
+
function namesSelfPause(command) {
|
|
691
|
+
for (const segment of command.split(SEGMENT_SEPARATORS)) {
|
|
692
|
+
const tokens = segment.split(/\s+/).filter(Boolean);
|
|
693
|
+
let i = 0;
|
|
694
|
+
while (i < tokens.length) {
|
|
695
|
+
const token = tokens[i];
|
|
696
|
+
const isSkippable = ENV_ASSIGNMENT_RE.test(token) || token.startsWith("-") || token.startsWith(">") || token.startsWith("<") || RUNNER_OPERAND_RE.test(token) || COMMAND_PREFIX_TOKENS.has(token.slice(token.lastIndexOf("/") + 1));
|
|
697
|
+
if (!isSkippable)
|
|
698
|
+
break;
|
|
699
|
+
i++;
|
|
700
|
+
}
|
|
701
|
+
if (i >= tokens.length)
|
|
702
|
+
continue;
|
|
703
|
+
if (!SELF_BINARY_TOKEN_RE.test(tokens[i]))
|
|
704
|
+
continue;
|
|
705
|
+
const args = tokens.slice(i + 1);
|
|
706
|
+
const configAt = args.findIndex((a) => CONFIG_SUBCOMMAND_RE.test(a));
|
|
707
|
+
if (configAt === -1)
|
|
708
|
+
continue;
|
|
709
|
+
if (args.slice(configAt + 1).some((a) => PAUSE_FLAG_RE.test(a)))
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
function decodeAnsiC(body) {
|
|
715
|
+
return body.replace(/\\(x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{1,4}|U[0-9A-Fa-f]{1,8}|[0-7]{1,3}|.)/g, (_, seq) => {
|
|
716
|
+
try {
|
|
717
|
+
if (seq[0] === "x")
|
|
718
|
+
return String.fromCharCode(parseInt(seq.slice(1), 16));
|
|
719
|
+
if (seq[0] === "u" || seq[0] === "U")
|
|
720
|
+
return String.fromCodePoint(parseInt(seq.slice(1), 16));
|
|
721
|
+
if (/^[0-7]+$/.test(seq))
|
|
722
|
+
return String.fromCharCode(parseInt(seq, 8));
|
|
723
|
+
} catch {
|
|
724
|
+
return seq;
|
|
725
|
+
}
|
|
726
|
+
const named = {
|
|
727
|
+
a: "\x07",
|
|
728
|
+
b: "\b",
|
|
729
|
+
e: "\x1B",
|
|
730
|
+
f: "\f",
|
|
731
|
+
n: `
|
|
732
|
+
`,
|
|
733
|
+
r: "\r",
|
|
734
|
+
t: "\t",
|
|
735
|
+
v: "\v",
|
|
736
|
+
"\\": "\\",
|
|
737
|
+
"'": "'",
|
|
738
|
+
'"': '"',
|
|
739
|
+
"?": "?"
|
|
740
|
+
};
|
|
741
|
+
return named[seq] ?? seq;
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
function stripShellQuoting(command) {
|
|
745
|
+
const joined = command.replace(/\\\r?\n/g, "");
|
|
746
|
+
const ansiDecoded = joined.replace(/\$'((?:[^'\\]|\\.)*)'/g, (_, body) => decodeAnsiC(body));
|
|
747
|
+
return ansiDecoded.replace(/\\(.)/g, "$1").replace(/['"]/g, "");
|
|
748
|
+
}
|
|
658
749
|
function statGitHeadMtimeMs(cwd) {
|
|
659
750
|
try {
|
|
660
751
|
return statSync3(join2(cwd, ".git", "HEAD")).mtimeMs;
|
|
@@ -899,11 +990,82 @@ function blockEnvFiles(ctx) {
|
|
|
899
990
|
}
|
|
900
991
|
return allow();
|
|
901
992
|
}
|
|
993
|
+
function quoteAwareSegments(command) {
|
|
994
|
+
const segments = [];
|
|
995
|
+
let tokens = [];
|
|
996
|
+
let token = "";
|
|
997
|
+
let quote = null;
|
|
998
|
+
const endToken = () => {
|
|
999
|
+
if (token)
|
|
1000
|
+
tokens.push(token);
|
|
1001
|
+
token = "";
|
|
1002
|
+
};
|
|
1003
|
+
const endSegment = () => {
|
|
1004
|
+
endToken();
|
|
1005
|
+
if (tokens.length)
|
|
1006
|
+
segments.push(tokens);
|
|
1007
|
+
tokens = [];
|
|
1008
|
+
};
|
|
1009
|
+
for (let i = 0;i < command.length; i++) {
|
|
1010
|
+
const c = command[i];
|
|
1011
|
+
if (quote) {
|
|
1012
|
+
if (c === "\\" && quote === '"' && i + 1 < command.length) {
|
|
1013
|
+
token += command[++i];
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
if (c === quote) {
|
|
1017
|
+
quote = null;
|
|
1018
|
+
continue;
|
|
1019
|
+
}
|
|
1020
|
+
token += c;
|
|
1021
|
+
continue;
|
|
1022
|
+
}
|
|
1023
|
+
if (c === "\\" && i + 1 < command.length) {
|
|
1024
|
+
token += command[++i];
|
|
1025
|
+
continue;
|
|
1026
|
+
}
|
|
1027
|
+
if (c === '"' || c === "'") {
|
|
1028
|
+
quote = c;
|
|
1029
|
+
continue;
|
|
1030
|
+
}
|
|
1031
|
+
if (/\s/.test(c)) {
|
|
1032
|
+
endToken();
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
if (/[;&|\n\r(){}`]/.test(c)) {
|
|
1036
|
+
endSegment();
|
|
1037
|
+
continue;
|
|
1038
|
+
}
|
|
1039
|
+
token += c;
|
|
1040
|
+
}
|
|
1041
|
+
endSegment();
|
|
1042
|
+
return segments;
|
|
1043
|
+
}
|
|
1044
|
+
function namesElevation(command, depth = 0) {
|
|
1045
|
+
for (const tokens of quoteAwareSegments(command)) {
|
|
1046
|
+
let i = 0;
|
|
1047
|
+
while (i < tokens.length) {
|
|
1048
|
+
const token = tokens[i];
|
|
1049
|
+
const base = token.slice(token.lastIndexOf("/") + 1);
|
|
1050
|
+
if (base === "sudo" || base === "doas")
|
|
1051
|
+
return true;
|
|
1052
|
+
const isSkippable = ENV_ASSIGNMENT_RE.test(token) || token.startsWith("-") || token.startsWith(">") || token.startsWith("<") || RUNNER_OPERAND_RE.test(token) || COMMAND_PREFIX_TOKENS.has(base);
|
|
1053
|
+
if (!isSkippable)
|
|
1054
|
+
break;
|
|
1055
|
+
if (EVAL_FLAG_RE.test(token) && depth < 3 && i + 1 < tokens.length) {
|
|
1056
|
+
if (namesElevation(tokens[i + 1], depth + 1))
|
|
1057
|
+
return true;
|
|
1058
|
+
}
|
|
1059
|
+
i++;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
902
1064
|
function blockSudo(ctx) {
|
|
903
1065
|
if (ctx.toolName !== "Bash")
|
|
904
1066
|
return allow();
|
|
905
1067
|
const cmd = getCommand(ctx).trimStart();
|
|
906
|
-
if (
|
|
1068
|
+
if (namesElevation(cmd)) {
|
|
907
1069
|
const allowPatterns = ctx.params?.allowPatterns ?? [];
|
|
908
1070
|
if (allowPatterns.some((p) => matchesAllowedPattern(cmd, p)))
|
|
909
1071
|
return allow();
|
|
@@ -917,6 +1079,15 @@ function blockSudo(ctx) {
|
|
|
917
1079
|
}
|
|
918
1080
|
return allow();
|
|
919
1081
|
}
|
|
1082
|
+
function blockSelfPause(ctx) {
|
|
1083
|
+
if (ctx.toolName !== "Bash")
|
|
1084
|
+
return allow();
|
|
1085
|
+
const cmd = getCommand(ctx);
|
|
1086
|
+
if (namesSelfPause(cmd) || namesSelfPause(stripShellQuoting(cmd))) {
|
|
1087
|
+
return deny("Pausing failproofai enforcement is a human action, not an agent one. " + "If a policy is blocking legitimate work, say so and let the operator decide.");
|
|
1088
|
+
}
|
|
1089
|
+
return allow();
|
|
1090
|
+
}
|
|
920
1091
|
function blockCurlPipeSh(ctx) {
|
|
921
1092
|
if (ctx.toolName !== "Bash")
|
|
922
1093
|
return allow();
|
|
@@ -1142,7 +1313,7 @@ function blockReadOutsideCwd(ctx) {
|
|
|
1142
1313
|
const paths = extractAbsolutePaths(cmd);
|
|
1143
1314
|
const cwdWithSep2 = cwd.endsWith("/") ? cwd : cwd + "/";
|
|
1144
1315
|
for (const p of paths) {
|
|
1145
|
-
const resolved3 =
|
|
1316
|
+
const resolved3 = resolve3(cwd, p);
|
|
1146
1317
|
if (isClaudeSettingsFile(resolved3)) {
|
|
1147
1318
|
return deny(`Reading agent settings file blocked: ${resolved3}`);
|
|
1148
1319
|
}
|
|
@@ -1163,7 +1334,7 @@ function blockReadOutsideCwd(ctx) {
|
|
|
1163
1334
|
const target = filePath || searchPath;
|
|
1164
1335
|
if (!target)
|
|
1165
1336
|
return allow();
|
|
1166
|
-
const resolved2 =
|
|
1337
|
+
const resolved2 = resolve3(cwd, target);
|
|
1167
1338
|
if (isClaudeSettingsFile(resolved2)) {
|
|
1168
1339
|
return deny(`Reading agent settings file blocked: ${resolved2}`);
|
|
1169
1340
|
}
|
|
@@ -1654,7 +1825,7 @@ function registerBuiltinPolicies(enabledNames) {
|
|
|
1654
1825
|
}
|
|
1655
1826
|
}
|
|
1656
1827
|
}
|
|
1657
|
-
var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE,
|
|
1828
|
+
var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, SEGMENT_SEPARATORS, COMMAND_PREFIX_TOKENS, SELF_BINARY_TOKEN_RE, CONFIG_SUBCOMMAND_RE, PAUSE_FLAG_RE, ENV_ASSIGNMENT_RE, RUNNER_OPERAND_RE, PS_WEB_PIPE_RE, SHORT_FLAG_BUNDLE_RE, SAFE_FORCE_PREFIXES, SECRET_FILE_RE, SECRET_FILE_ID_RSA_RE, SECRET_FILE_CREDENTIALS_RE, GIT_COMMIT_MERGE_RE, FAILPROOFAI_CLI_RE, FAILPROOFAI_UNINSTALL_RE, GIT_AMEND_RE, GIT_STASH_DROP_RE, GIT_ADD_ALL_RE, NPM_GLOBAL_RE, YARN_GLOBAL_RE, PNPM_GLOBAL_RE, BUN_GLOBAL_RE, CARGO_INSTALL_RE, PIP_SYSTEM_RE, PKG_MANAGER_DETECTORS, NOHUP_RE, SCREEN_DETACH_RE, TMUX_DETACH_RE, DISOWN_RE, BACKGROUND_AMPERSAND_RE, KUBECTL_RE, TERRAFORM_RE, AWS_CLI_RE, GCLOUD_RE, AZ_CLI_RE, HELM_RE, GH_PIPELINE_RE, gitBranchCache, GIT_BRANCH_CACHE_MAX_ENTRIES = 500, EVAL_FLAG_RE, HOME_PREFIX_RE, RM_CMD_RE, FIND_CMD_RE, FIND_EXEC_RE, FIND_GLOBAL_OPT_RE, FIND_EXPR_START_RE, SCRATCH_ROOTS, CATASTROPHIC_DEPTH = 2, READ_LIKE_CMDS, TOOL_CALL_TRACKER_MAX_BYTES = 65536, SEGMENT_SPLIT_RE, BUILTIN_POLICIES;
|
|
1658
1829
|
var init_builtin_policies = __esm(() => {
|
|
1659
1830
|
init_hook_logger();
|
|
1660
1831
|
isClaudeInternalPath = isAgentInternalPath;
|
|
@@ -1691,10 +1862,48 @@ var init_builtin_policies = __esm(() => {
|
|
|
1691
1862
|
CMD_ECHO_ENV_RE = /echo\s+%[A-Za-z_]/i;
|
|
1692
1863
|
ENV_FILE_PATH_RE = /(?:^|[\\/])\.env(?:\.|$)/;
|
|
1693
1864
|
ENV_CMD_RE = /\.env(?:\b|\s|$|\.)/;
|
|
1694
|
-
SUDO_RE = /(?:^|;|&&|\|\|)\s*sudo\s/;
|
|
1695
1865
|
PS_ELEVATION_RE = /Start-Process\s+.*-Verb\s+RunAs/i;
|
|
1696
1866
|
RUNAS_RE = /(?:^|;|&&|\|\|)\s*runas\s/i;
|
|
1697
1867
|
CURL_PIPE_SH_RE = /(?:curl|wget)\s.*\|\s*(?:sh|bash|zsh|dash|ksh|csh|tcsh|fish|ash)\b/;
|
|
1868
|
+
SEGMENT_SEPARATORS = /[;&|\n\r(){}`]+/;
|
|
1869
|
+
COMMAND_PREFIX_TOKENS = new Set([
|
|
1870
|
+
"npx",
|
|
1871
|
+
"bunx",
|
|
1872
|
+
"pnpx",
|
|
1873
|
+
"npm",
|
|
1874
|
+
"pnpm",
|
|
1875
|
+
"yarn",
|
|
1876
|
+
"dlx",
|
|
1877
|
+
"exec",
|
|
1878
|
+
"run",
|
|
1879
|
+
"node",
|
|
1880
|
+
"bun",
|
|
1881
|
+
"deno",
|
|
1882
|
+
"env",
|
|
1883
|
+
"command",
|
|
1884
|
+
"builtin",
|
|
1885
|
+
"nohup",
|
|
1886
|
+
"setsid",
|
|
1887
|
+
"time",
|
|
1888
|
+
"timeout",
|
|
1889
|
+
"nice",
|
|
1890
|
+
"stdbuf",
|
|
1891
|
+
"xargs",
|
|
1892
|
+
"sudo",
|
|
1893
|
+
"doas",
|
|
1894
|
+
"sh",
|
|
1895
|
+
"bash",
|
|
1896
|
+
"zsh",
|
|
1897
|
+
"dash",
|
|
1898
|
+
"ksh",
|
|
1899
|
+
"fish",
|
|
1900
|
+
"ash"
|
|
1901
|
+
]);
|
|
1902
|
+
SELF_BINARY_TOKEN_RE = /(?:^|\/)failproofai[^/]*$/;
|
|
1903
|
+
CONFIG_SUBCOMMAND_RE = /^(?:config|configure|setup)$/;
|
|
1904
|
+
PAUSE_FLAG_RE = /^--pause(?:=|$)/;
|
|
1905
|
+
ENV_ASSIGNMENT_RE = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
1906
|
+
RUNNER_OPERAND_RE = /^\d+[a-z]*$/i;
|
|
1698
1907
|
PS_WEB_PIPE_RE = /(?:Invoke-WebRequest|iwr|Invoke-RestMethod|irm)\s+.*\|\s*(?:Invoke-Expression|iex)/i;
|
|
1699
1908
|
SHORT_FLAG_BUNDLE_RE = /^-[a-zA-Z]*f[a-zA-Z]*$/;
|
|
1700
1909
|
SAFE_FORCE_PREFIXES = ["--force-with-lease", "--force-if-includes"];
|
|
@@ -1738,6 +1947,7 @@ var init_builtin_policies = __esm(() => {
|
|
|
1738
1947
|
HELM_RE = /(?:^|[;\n]|&&|\|\|?|&)\s*helm(?:\s|$)/;
|
|
1739
1948
|
GH_PIPELINE_RE = /(?:^|[;\n]|&&|\|\|?|&)\s*gh\s+(?:workflow\s+(?:run|enable|disable)|run\s+(?:rerun|cancel)|pr\s+merge|release\s+(?:create|delete)|cache\s+delete|secret\s+(?:set|delete))\b/;
|
|
1740
1949
|
gitBranchCache = new Map;
|
|
1950
|
+
EVAL_FLAG_RE = /^-{1,2}c$/;
|
|
1741
1951
|
HOME_PREFIX_RE = /^(?:~[A-Za-z0-9_.-]*|\$HOME|\$\{HOME\})(?=$|\/)/;
|
|
1742
1952
|
RM_CMD_RE = /^(?:\/\S*\/)?rm$/;
|
|
1743
1953
|
FIND_CMD_RE = /^(?:\/\S*\/)?find$/;
|
|
@@ -1842,6 +2052,16 @@ var init_builtin_policies = __esm(() => {
|
|
|
1842
2052
|
}
|
|
1843
2053
|
}
|
|
1844
2054
|
},
|
|
2055
|
+
{
|
|
2056
|
+
name: "block-self-pause",
|
|
2057
|
+
displayTitle: "Tried to pause failproofai enforcement",
|
|
2058
|
+
impact: "An agent that can pause enforcement can switch off every other policy.",
|
|
2059
|
+
description: "Block agents from pausing failproofai enforcement",
|
|
2060
|
+
fn: blockSelfPause,
|
|
2061
|
+
match: { events: ["PreToolUse", "PermissionRequest"], toolNames: ["Bash"] },
|
|
2062
|
+
defaultEnabled: true,
|
|
2063
|
+
category: "Dangerous Commands"
|
|
2064
|
+
},
|
|
1845
2065
|
{
|
|
1846
2066
|
name: "block-sudo",
|
|
1847
2067
|
displayTitle: "Tried to run a command with sudo",
|
|
@@ -2285,12 +2505,1080 @@ var init_builtin_policies = __esm(() => {
|
|
|
2285
2505
|
});
|
|
2286
2506
|
|
|
2287
2507
|
// package.json
|
|
2288
|
-
var version = "1.0.0-beta.
|
|
2508
|
+
var version = "1.0.0-beta.10";
|
|
2289
2509
|
var init_package = () => {};
|
|
2290
2510
|
|
|
2291
2511
|
// src/posthog-key.ts
|
|
2292
2512
|
var POSTHOG_API_KEY = "phc_Ac1Ww1GqKc0z1SyrRWbmatEeQdlOQIsDEEdP8l8JRgX", POSTHOG_PRODUCT = "failproofai-oss";
|
|
2293
2513
|
|
|
2514
|
+
// node_modules/smol-toml/dist/date.js
|
|
2515
|
+
var DATE_TIME_RE, TomlDate;
|
|
2516
|
+
var init_date = __esm(() => {
|
|
2517
|
+
/*!
|
|
2518
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2519
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2520
|
+
*
|
|
2521
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2522
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2523
|
+
*
|
|
2524
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2525
|
+
* list of conditions and the following disclaimer.
|
|
2526
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2527
|
+
* this list of conditions and the following disclaimer in the
|
|
2528
|
+
* documentation and/or other materials provided with the distribution.
|
|
2529
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2530
|
+
* may be used to endorse or promote products derived from this software without
|
|
2531
|
+
* specific prior written permission.
|
|
2532
|
+
*
|
|
2533
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2534
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2535
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2536
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2537
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2538
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2539
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2540
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2541
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2542
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2543
|
+
*/
|
|
2544
|
+
DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
2545
|
+
TomlDate = class TomlDate extends Date {
|
|
2546
|
+
#hasDate = false;
|
|
2547
|
+
#hasTime = false;
|
|
2548
|
+
#offset = null;
|
|
2549
|
+
constructor(date) {
|
|
2550
|
+
let hasDate = true;
|
|
2551
|
+
let hasTime = true;
|
|
2552
|
+
let offset = "Z";
|
|
2553
|
+
if (typeof date === "string") {
|
|
2554
|
+
let match = date.match(DATE_TIME_RE);
|
|
2555
|
+
if (match) {
|
|
2556
|
+
if (!match[1]) {
|
|
2557
|
+
hasDate = false;
|
|
2558
|
+
date = `0000-01-01T${date}`;
|
|
2559
|
+
}
|
|
2560
|
+
hasTime = !!match[2];
|
|
2561
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
2562
|
+
if (match[2] && +match[2] > 23) {
|
|
2563
|
+
date = "";
|
|
2564
|
+
} else {
|
|
2565
|
+
offset = match[3] || null;
|
|
2566
|
+
date = date.toUpperCase();
|
|
2567
|
+
if (!offset && hasTime)
|
|
2568
|
+
date += "Z";
|
|
2569
|
+
}
|
|
2570
|
+
} else {
|
|
2571
|
+
date = "";
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
super(date);
|
|
2575
|
+
if (!isNaN(this.getTime())) {
|
|
2576
|
+
this.#hasDate = hasDate;
|
|
2577
|
+
this.#hasTime = hasTime;
|
|
2578
|
+
this.#offset = offset;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
isDateTime() {
|
|
2582
|
+
return this.#hasDate && this.#hasTime;
|
|
2583
|
+
}
|
|
2584
|
+
isLocal() {
|
|
2585
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
2586
|
+
}
|
|
2587
|
+
isDate() {
|
|
2588
|
+
return this.#hasDate && !this.#hasTime;
|
|
2589
|
+
}
|
|
2590
|
+
isTime() {
|
|
2591
|
+
return this.#hasTime && !this.#hasDate;
|
|
2592
|
+
}
|
|
2593
|
+
isValid() {
|
|
2594
|
+
return this.#hasDate || this.#hasTime;
|
|
2595
|
+
}
|
|
2596
|
+
toISOString() {
|
|
2597
|
+
let iso = super.toISOString();
|
|
2598
|
+
if (this.isDate())
|
|
2599
|
+
return iso.slice(0, 10);
|
|
2600
|
+
if (this.isTime())
|
|
2601
|
+
return iso.slice(11, 23);
|
|
2602
|
+
if (this.#offset === null)
|
|
2603
|
+
return iso.slice(0, -1);
|
|
2604
|
+
if (this.#offset === "Z")
|
|
2605
|
+
return iso;
|
|
2606
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
2607
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
2608
|
+
let offsetDate = new Date(this.getTime() - offset * 60000);
|
|
2609
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
2610
|
+
}
|
|
2611
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
2612
|
+
let date = new TomlDate(jsDate);
|
|
2613
|
+
date.#offset = offset;
|
|
2614
|
+
return date;
|
|
2615
|
+
}
|
|
2616
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
2617
|
+
let date = new TomlDate(jsDate);
|
|
2618
|
+
date.#offset = null;
|
|
2619
|
+
return date;
|
|
2620
|
+
}
|
|
2621
|
+
static wrapAsLocalDate(jsDate) {
|
|
2622
|
+
let date = new TomlDate(jsDate);
|
|
2623
|
+
date.#hasTime = false;
|
|
2624
|
+
date.#offset = null;
|
|
2625
|
+
return date;
|
|
2626
|
+
}
|
|
2627
|
+
static wrapAsLocalTime(jsDate) {
|
|
2628
|
+
let date = new TomlDate(jsDate);
|
|
2629
|
+
date.#hasDate = false;
|
|
2630
|
+
date.#offset = null;
|
|
2631
|
+
return date;
|
|
2632
|
+
}
|
|
2633
|
+
};
|
|
2634
|
+
});
|
|
2635
|
+
|
|
2636
|
+
// node_modules/smol-toml/dist/error.js
|
|
2637
|
+
function getLineColFromPtr(string, ptr) {
|
|
2638
|
+
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
|
2639
|
+
return [lines.length, lines.pop().length + 1];
|
|
2640
|
+
}
|
|
2641
|
+
function makeCodeBlock(string, line, column) {
|
|
2642
|
+
let lines = string.split(/\r\n|\n|\r/g);
|
|
2643
|
+
let codeblock = "";
|
|
2644
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
2645
|
+
for (let i = line - 1;i <= line + 1; i++) {
|
|
2646
|
+
let l = lines[i - 1];
|
|
2647
|
+
if (!l)
|
|
2648
|
+
continue;
|
|
2649
|
+
codeblock += i.toString().padEnd(numberLen, " ");
|
|
2650
|
+
codeblock += ": ";
|
|
2651
|
+
codeblock += l;
|
|
2652
|
+
codeblock += `
|
|
2653
|
+
`;
|
|
2654
|
+
if (i === line) {
|
|
2655
|
+
codeblock += " ".repeat(numberLen + column + 2);
|
|
2656
|
+
codeblock += `^
|
|
2657
|
+
`;
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
return codeblock;
|
|
2661
|
+
}
|
|
2662
|
+
var TomlError;
|
|
2663
|
+
var init_error = __esm(() => {
|
|
2664
|
+
/*!
|
|
2665
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2666
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2667
|
+
*
|
|
2668
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2669
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2670
|
+
*
|
|
2671
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2672
|
+
* list of conditions and the following disclaimer.
|
|
2673
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2674
|
+
* this list of conditions and the following disclaimer in the
|
|
2675
|
+
* documentation and/or other materials provided with the distribution.
|
|
2676
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2677
|
+
* may be used to endorse or promote products derived from this software without
|
|
2678
|
+
* specific prior written permission.
|
|
2679
|
+
*
|
|
2680
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2681
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2682
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2683
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2684
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2685
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2686
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2687
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2688
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2689
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2690
|
+
*/
|
|
2691
|
+
TomlError = class TomlError extends Error {
|
|
2692
|
+
line;
|
|
2693
|
+
column;
|
|
2694
|
+
codeblock;
|
|
2695
|
+
constructor(message, options) {
|
|
2696
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
2697
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
2698
|
+
super(`Invalid TOML document: ${message}
|
|
2699
|
+
|
|
2700
|
+
${codeblock}`, options);
|
|
2701
|
+
this.line = line;
|
|
2702
|
+
this.column = column;
|
|
2703
|
+
this.codeblock = codeblock;
|
|
2704
|
+
}
|
|
2705
|
+
};
|
|
2706
|
+
});
|
|
2707
|
+
|
|
2708
|
+
// node_modules/smol-toml/dist/primitive.js
|
|
2709
|
+
function parseString(str, ptr) {
|
|
2710
|
+
let c = str[ptr++];
|
|
2711
|
+
let first = c;
|
|
2712
|
+
let isLiteral = c === "'";
|
|
2713
|
+
let isMultiline = c === str[ptr] && c === str[ptr + 1];
|
|
2714
|
+
if (isMultiline) {
|
|
2715
|
+
if (str[ptr += 2] === `
|
|
2716
|
+
`)
|
|
2717
|
+
ptr++;
|
|
2718
|
+
else if (str[ptr] === "\r" && str[ptr + 1] === `
|
|
2719
|
+
`)
|
|
2720
|
+
ptr += 2;
|
|
2721
|
+
}
|
|
2722
|
+
let parsed = "";
|
|
2723
|
+
let sliceStart = ptr;
|
|
2724
|
+
let state = 0;
|
|
2725
|
+
for (let i = ptr;i < str.length; i++) {
|
|
2726
|
+
c = str[i];
|
|
2727
|
+
if (isMultiline && (c === `
|
|
2728
|
+
` || c === "\r" && str[i + 1] === `
|
|
2729
|
+
`)) {
|
|
2730
|
+
state = state && 3;
|
|
2731
|
+
} else if (c < " " && c !== "\t" || c === "") {
|
|
2732
|
+
throw new TomlError("control characters are not allowed in strings", {
|
|
2733
|
+
toml: str,
|
|
2734
|
+
ptr: i
|
|
2735
|
+
});
|
|
2736
|
+
} else if ((!state || state === 3) && c === first && (!isMultiline || str[i + 1] === first && str[i + 2] === first)) {
|
|
2737
|
+
if (isMultiline) {
|
|
2738
|
+
if (str[i + 3] === first)
|
|
2739
|
+
i++;
|
|
2740
|
+
if (str[i + 3] === first)
|
|
2741
|
+
i++;
|
|
2742
|
+
}
|
|
2743
|
+
return [
|
|
2744
|
+
state ? parsed : parsed + str.slice(sliceStart, i),
|
|
2745
|
+
i + (isMultiline ? 3 : 1)
|
|
2746
|
+
];
|
|
2747
|
+
} else if (!state) {
|
|
2748
|
+
if (!isLiteral && c === "\\") {
|
|
2749
|
+
parsed += str.slice(sliceStart, sliceStart = i);
|
|
2750
|
+
state = 1;
|
|
2751
|
+
}
|
|
2752
|
+
} else if (state === 1) {
|
|
2753
|
+
if (c === "x" || c === "u" || c === "U") {
|
|
2754
|
+
let value = 0;
|
|
2755
|
+
let len = c === "x" ? 2 : c === "u" ? 4 : 8;
|
|
2756
|
+
for (let j = 0;j < len; j++, i++) {
|
|
2757
|
+
let hex = str.charCodeAt(i + 1);
|
|
2758
|
+
let digit = hex >= 48 && hex <= 57 ? hex - 48 : hex >= 65 && hex <= 70 ? hex - 65 + 10 : hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1;
|
|
2759
|
+
if (digit < 0)
|
|
2760
|
+
throw new TomlError("invalid non-hex character in unicode escape", { toml: str, ptr: i + 1 });
|
|
2761
|
+
value = value << 4 | digit;
|
|
2762
|
+
}
|
|
2763
|
+
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
|
2764
|
+
throw new TomlError("invalid unicode escape", { toml: str, ptr: i });
|
|
2765
|
+
}
|
|
2766
|
+
parsed += String.fromCodePoint(value);
|
|
2767
|
+
sliceStart = i + 1;
|
|
2768
|
+
state = 0;
|
|
2769
|
+
} else if (c === " " || c === "\t") {
|
|
2770
|
+
state = 2;
|
|
2771
|
+
} else {
|
|
2772
|
+
if (c === "b")
|
|
2773
|
+
parsed += "\b";
|
|
2774
|
+
else if (c === "t")
|
|
2775
|
+
parsed += "\t";
|
|
2776
|
+
else if (c === "n")
|
|
2777
|
+
parsed += `
|
|
2778
|
+
`;
|
|
2779
|
+
else if (c === "f")
|
|
2780
|
+
parsed += "\f";
|
|
2781
|
+
else if (c === "r")
|
|
2782
|
+
parsed += "\r";
|
|
2783
|
+
else if (c === "e")
|
|
2784
|
+
parsed += "\x1B";
|
|
2785
|
+
else if (c === '"')
|
|
2786
|
+
parsed += '"';
|
|
2787
|
+
else if (c === "\\")
|
|
2788
|
+
parsed += "\\";
|
|
2789
|
+
else
|
|
2790
|
+
throw new TomlError("unrecognized escape sequence", { toml: str, ptr: i });
|
|
2791
|
+
sliceStart = i + 1;
|
|
2792
|
+
state = 0;
|
|
2793
|
+
}
|
|
2794
|
+
} else if (c !== " " && c !== "\t") {
|
|
2795
|
+
if (state === 2) {
|
|
2796
|
+
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
|
2797
|
+
toml: str,
|
|
2798
|
+
ptr: sliceStart
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2801
|
+
state = !isLiteral && c === "\\" ? 1 : 0;
|
|
2802
|
+
sliceStart = i;
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
throw new TomlError("unfinished string", { toml: str, ptr });
|
|
2806
|
+
}
|
|
2807
|
+
function parseValue(value, toml, ptr, integersAsBigInt) {
|
|
2808
|
+
if (value === "true")
|
|
2809
|
+
return true;
|
|
2810
|
+
if (value === "false")
|
|
2811
|
+
return false;
|
|
2812
|
+
if (value === "-inf")
|
|
2813
|
+
return -Infinity;
|
|
2814
|
+
if (value === "inf" || value === "+inf")
|
|
2815
|
+
return Infinity;
|
|
2816
|
+
if (value === "nan" || value === "+nan" || value === "-nan")
|
|
2817
|
+
return NaN;
|
|
2818
|
+
if (value === "-0")
|
|
2819
|
+
return integersAsBigInt ? 0n : 0;
|
|
2820
|
+
let isInt = INT_REGEX.test(value);
|
|
2821
|
+
if (isInt || FLOAT_REGEX.test(value)) {
|
|
2822
|
+
if (LEADING_ZERO.test(value)) {
|
|
2823
|
+
throw new TomlError("leading zeroes are not allowed", {
|
|
2824
|
+
toml,
|
|
2825
|
+
ptr
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
value = value.replace(/_/g, "");
|
|
2829
|
+
let numeric = +value;
|
|
2830
|
+
if (isNaN(numeric)) {
|
|
2831
|
+
throw new TomlError("invalid number", {
|
|
2832
|
+
toml,
|
|
2833
|
+
ptr
|
|
2834
|
+
});
|
|
2835
|
+
}
|
|
2836
|
+
if (isInt) {
|
|
2837
|
+
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
2838
|
+
throw new TomlError("integer value cannot be represented losslessly", {
|
|
2839
|
+
toml,
|
|
2840
|
+
ptr
|
|
2841
|
+
});
|
|
2842
|
+
}
|
|
2843
|
+
if (isInt || integersAsBigInt === true)
|
|
2844
|
+
numeric = BigInt(value);
|
|
2845
|
+
}
|
|
2846
|
+
return numeric;
|
|
2847
|
+
}
|
|
2848
|
+
const date = new TomlDate(value);
|
|
2849
|
+
if (!date.isValid()) {
|
|
2850
|
+
throw new TomlError("invalid value", {
|
|
2851
|
+
toml,
|
|
2852
|
+
ptr
|
|
2853
|
+
});
|
|
2854
|
+
}
|
|
2855
|
+
return date;
|
|
2856
|
+
}
|
|
2857
|
+
var INT_REGEX, FLOAT_REGEX, LEADING_ZERO;
|
|
2858
|
+
var init_primitive = __esm(() => {
|
|
2859
|
+
init_date();
|
|
2860
|
+
init_error();
|
|
2861
|
+
/*!
|
|
2862
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2863
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2864
|
+
*
|
|
2865
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2866
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2867
|
+
*
|
|
2868
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2869
|
+
* list of conditions and the following disclaimer.
|
|
2870
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2871
|
+
* this list of conditions and the following disclaimer in the
|
|
2872
|
+
* documentation and/or other materials provided with the distribution.
|
|
2873
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2874
|
+
* may be used to endorse or promote products derived from this software without
|
|
2875
|
+
* specific prior written permission.
|
|
2876
|
+
*
|
|
2877
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2878
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2879
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2880
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2881
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2882
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2883
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2884
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2885
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2886
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2887
|
+
*/
|
|
2888
|
+
INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
|
2889
|
+
FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
|
2890
|
+
LEADING_ZERO = /^[+-]?0[0-9_]/;
|
|
2891
|
+
});
|
|
2892
|
+
|
|
2893
|
+
// node_modules/smol-toml/dist/util.js
|
|
2894
|
+
function indexOfNewline(str, start = 0, end = str.length) {
|
|
2895
|
+
let idx = str.indexOf(`
|
|
2896
|
+
`, start);
|
|
2897
|
+
if (str[idx - 1] === "\r")
|
|
2898
|
+
idx--;
|
|
2899
|
+
return idx <= end ? idx : -1;
|
|
2900
|
+
}
|
|
2901
|
+
function skipComment(str, ptr) {
|
|
2902
|
+
for (let i = ptr;i < str.length; i++) {
|
|
2903
|
+
let c = str[i];
|
|
2904
|
+
if (c === `
|
|
2905
|
+
`)
|
|
2906
|
+
return i;
|
|
2907
|
+
if (c === "\r" && str[i + 1] === `
|
|
2908
|
+
`)
|
|
2909
|
+
return i + 1;
|
|
2910
|
+
if (c < " " && c !== "\t" || c === "") {
|
|
2911
|
+
throw new TomlError("control characters are not allowed in comments", {
|
|
2912
|
+
toml: str,
|
|
2913
|
+
ptr
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
return str.length;
|
|
2918
|
+
}
|
|
2919
|
+
function skipVoid(str, ptr, banNewLines, banComments) {
|
|
2920
|
+
let c;
|
|
2921
|
+
while (true) {
|
|
2922
|
+
while ((c = str[ptr]) === " " || c === "\t" || !banNewLines && (c === `
|
|
2923
|
+
` || c === "\r" && str[ptr + 1] === `
|
|
2924
|
+
`))
|
|
2925
|
+
ptr++;
|
|
2926
|
+
if (banComments || c !== "#")
|
|
2927
|
+
break;
|
|
2928
|
+
ptr = skipComment(str, ptr);
|
|
2929
|
+
}
|
|
2930
|
+
return ptr;
|
|
2931
|
+
}
|
|
2932
|
+
function skipUntil(str, ptr, sep, end, banNewLines = false) {
|
|
2933
|
+
if (!end) {
|
|
2934
|
+
ptr = indexOfNewline(str, ptr);
|
|
2935
|
+
return ptr < 0 ? str.length : ptr;
|
|
2936
|
+
}
|
|
2937
|
+
for (let i = ptr;i < str.length; i++) {
|
|
2938
|
+
let c = str[i];
|
|
2939
|
+
if (c === "#") {
|
|
2940
|
+
i = indexOfNewline(str, i);
|
|
2941
|
+
if (i < 0)
|
|
2942
|
+
break;
|
|
2943
|
+
} else if (c === sep) {
|
|
2944
|
+
return i + 1;
|
|
2945
|
+
} else if (c === end || banNewLines && (c === `
|
|
2946
|
+
` || c === "\r" && str[i + 1] === `
|
|
2947
|
+
`)) {
|
|
2948
|
+
return i;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
throw new TomlError("cannot find end of structure", {
|
|
2952
|
+
toml: str,
|
|
2953
|
+
ptr
|
|
2954
|
+
});
|
|
2955
|
+
}
|
|
2956
|
+
var init_util = __esm(() => {
|
|
2957
|
+
init_error();
|
|
2958
|
+
/*!
|
|
2959
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2960
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2961
|
+
*
|
|
2962
|
+
* Redistribution and use in source and binary forms, with or without
|
|
2963
|
+
* modification, are permitted provided that the following conditions are met:
|
|
2964
|
+
*
|
|
2965
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
2966
|
+
* list of conditions and the following disclaimer.
|
|
2967
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
2968
|
+
* this list of conditions and the following disclaimer in the
|
|
2969
|
+
* documentation and/or other materials provided with the distribution.
|
|
2970
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
2971
|
+
* may be used to endorse or promote products derived from this software without
|
|
2972
|
+
* specific prior written permission.
|
|
2973
|
+
*
|
|
2974
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
2975
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
2976
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
2977
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
2978
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
2979
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
2980
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
2981
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
2982
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
2983
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
2984
|
+
*/
|
|
2985
|
+
});
|
|
2986
|
+
|
|
2987
|
+
// node_modules/smol-toml/dist/extract.js
|
|
2988
|
+
function sliceAndTrimEndOf(str, startPtr, endPtr) {
|
|
2989
|
+
let value = str.slice(startPtr, endPtr);
|
|
2990
|
+
let commentIdx = value.indexOf("#");
|
|
2991
|
+
if (commentIdx > -1) {
|
|
2992
|
+
skipComment(str, commentIdx);
|
|
2993
|
+
value = value.slice(0, commentIdx);
|
|
2994
|
+
}
|
|
2995
|
+
return [value.trimEnd(), commentIdx];
|
|
2996
|
+
}
|
|
2997
|
+
function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
|
2998
|
+
if (depth === 0) {
|
|
2999
|
+
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
3000
|
+
toml: str,
|
|
3001
|
+
ptr
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
3004
|
+
let c = str[ptr];
|
|
3005
|
+
if (c === "[" || c === "{") {
|
|
3006
|
+
let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
|
|
3007
|
+
if (end) {
|
|
3008
|
+
endPtr2 = skipVoid(str, endPtr2);
|
|
3009
|
+
if (str[endPtr2] === ",")
|
|
3010
|
+
endPtr2++;
|
|
3011
|
+
else if (str[endPtr2] !== end) {
|
|
3012
|
+
throw new TomlError("expected comma or end of structure", {
|
|
3013
|
+
toml: str,
|
|
3014
|
+
ptr: endPtr2
|
|
3015
|
+
});
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
return [value, endPtr2];
|
|
3019
|
+
}
|
|
3020
|
+
if (c === '"' || c === "'") {
|
|
3021
|
+
let [parsed, endPtr2] = parseString(str, ptr);
|
|
3022
|
+
if (end) {
|
|
3023
|
+
endPtr2 = skipVoid(str, endPtr2);
|
|
3024
|
+
if (str[endPtr2] && str[endPtr2] !== "," && str[endPtr2] !== end && str[endPtr2] !== `
|
|
3025
|
+
` && str[endPtr2] !== "\r") {
|
|
3026
|
+
throw new TomlError("unexpected character encountered", {
|
|
3027
|
+
toml: str,
|
|
3028
|
+
ptr: endPtr2
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
if (str[endPtr2] === ",")
|
|
3032
|
+
endPtr2++;
|
|
3033
|
+
}
|
|
3034
|
+
return [parsed, endPtr2];
|
|
3035
|
+
}
|
|
3036
|
+
let endPtr = skipUntil(str, ptr, ",", end);
|
|
3037
|
+
let slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === "," ? 1 : 0));
|
|
3038
|
+
if (!slice[0]) {
|
|
3039
|
+
throw new TomlError("incomplete key-value declaration: no value specified", {
|
|
3040
|
+
toml: str,
|
|
3041
|
+
ptr
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3044
|
+
if (end && slice[1] > -1) {
|
|
3045
|
+
endPtr = skipVoid(str, ptr + slice[1]);
|
|
3046
|
+
if (str[endPtr] === ",")
|
|
3047
|
+
endPtr++;
|
|
3048
|
+
}
|
|
3049
|
+
return [
|
|
3050
|
+
parseValue(slice[0], str, ptr, integersAsBigInt),
|
|
3051
|
+
endPtr
|
|
3052
|
+
];
|
|
3053
|
+
}
|
|
3054
|
+
var init_extract = __esm(() => {
|
|
3055
|
+
init_primitive();
|
|
3056
|
+
init_struct();
|
|
3057
|
+
init_util();
|
|
3058
|
+
init_error();
|
|
3059
|
+
/*!
|
|
3060
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3061
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
3062
|
+
*
|
|
3063
|
+
* Redistribution and use in source and binary forms, with or without
|
|
3064
|
+
* modification, are permitted provided that the following conditions are met:
|
|
3065
|
+
*
|
|
3066
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
3067
|
+
* list of conditions and the following disclaimer.
|
|
3068
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
3069
|
+
* this list of conditions and the following disclaimer in the
|
|
3070
|
+
* documentation and/or other materials provided with the distribution.
|
|
3071
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
3072
|
+
* may be used to endorse or promote products derived from this software without
|
|
3073
|
+
* specific prior written permission.
|
|
3074
|
+
*
|
|
3075
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
3076
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
3077
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
3078
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
3079
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
3080
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
3081
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
3082
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
3083
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
3084
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3085
|
+
*/
|
|
3086
|
+
});
|
|
3087
|
+
|
|
3088
|
+
// node_modules/smol-toml/dist/struct.js
|
|
3089
|
+
function parseKey(str, ptr, end = "=") {
|
|
3090
|
+
let dot = ptr - 1;
|
|
3091
|
+
let parsed = [];
|
|
3092
|
+
let endPtr = str.indexOf(end, ptr);
|
|
3093
|
+
if (endPtr < 0) {
|
|
3094
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
3095
|
+
toml: str,
|
|
3096
|
+
ptr
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3099
|
+
do {
|
|
3100
|
+
let c = str[ptr = ++dot];
|
|
3101
|
+
if (c !== " " && c !== "\t") {
|
|
3102
|
+
if (c === '"' || c === "'") {
|
|
3103
|
+
if (c === str[ptr + 1] && c === str[ptr + 2]) {
|
|
3104
|
+
throw new TomlError("multiline strings are not allowed in keys", {
|
|
3105
|
+
toml: str,
|
|
3106
|
+
ptr
|
|
3107
|
+
});
|
|
3108
|
+
}
|
|
3109
|
+
let [part, eos] = parseString(str, ptr);
|
|
3110
|
+
dot = str.indexOf(".", eos);
|
|
3111
|
+
let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
3112
|
+
let newLine = indexOfNewline(strEnd);
|
|
3113
|
+
if (newLine > -1) {
|
|
3114
|
+
throw new TomlError("newlines are not allowed in keys", {
|
|
3115
|
+
toml: str,
|
|
3116
|
+
ptr: ptr + dot + newLine
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3119
|
+
if (strEnd.trimStart()) {
|
|
3120
|
+
throw new TomlError("found extra tokens after the string part", {
|
|
3121
|
+
toml: str,
|
|
3122
|
+
ptr: eos
|
|
3123
|
+
});
|
|
3124
|
+
}
|
|
3125
|
+
if (endPtr < eos) {
|
|
3126
|
+
endPtr = str.indexOf(end, eos);
|
|
3127
|
+
if (endPtr < 0) {
|
|
3128
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
3129
|
+
toml: str,
|
|
3130
|
+
ptr
|
|
3131
|
+
});
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
parsed.push(part);
|
|
3135
|
+
} else {
|
|
3136
|
+
dot = str.indexOf(".", ptr);
|
|
3137
|
+
let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
3138
|
+
if (!KEY_PART_RE.test(part)) {
|
|
3139
|
+
throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
|
|
3140
|
+
toml: str,
|
|
3141
|
+
ptr
|
|
3142
|
+
});
|
|
3143
|
+
}
|
|
3144
|
+
parsed.push(part.trimEnd());
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
} while (dot + 1 && dot < endPtr);
|
|
3148
|
+
return [parsed, skipVoid(str, endPtr + 1, true, true)];
|
|
3149
|
+
}
|
|
3150
|
+
function parseInlineTable(str, ptr, depth, integersAsBigInt) {
|
|
3151
|
+
let res = {};
|
|
3152
|
+
let seen = new Set;
|
|
3153
|
+
let c;
|
|
3154
|
+
ptr++;
|
|
3155
|
+
while ((c = str[ptr++]) !== "}" && c) {
|
|
3156
|
+
if (c === ",") {
|
|
3157
|
+
throw new TomlError("expected value, found comma", {
|
|
3158
|
+
toml: str,
|
|
3159
|
+
ptr: ptr - 1
|
|
3160
|
+
});
|
|
3161
|
+
} else if (c === "#")
|
|
3162
|
+
ptr = skipComment(str, ptr);
|
|
3163
|
+
else if (c !== " " && c !== "\t" && c !== `
|
|
3164
|
+
` && c !== "\r") {
|
|
3165
|
+
let k;
|
|
3166
|
+
let t = res;
|
|
3167
|
+
let hasOwn = false;
|
|
3168
|
+
let [key, keyEndPtr] = parseKey(str, ptr - 1);
|
|
3169
|
+
for (let i = 0;i < key.length; i++) {
|
|
3170
|
+
if (i)
|
|
3171
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
3172
|
+
k = key[i];
|
|
3173
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
3174
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
3175
|
+
toml: str,
|
|
3176
|
+
ptr
|
|
3177
|
+
});
|
|
3178
|
+
}
|
|
3179
|
+
if (!hasOwn && k === "__proto__") {
|
|
3180
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
if (hasOwn) {
|
|
3184
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
3185
|
+
toml: str,
|
|
3186
|
+
ptr
|
|
3187
|
+
});
|
|
3188
|
+
}
|
|
3189
|
+
let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt);
|
|
3190
|
+
seen.add(value);
|
|
3191
|
+
t[k] = value;
|
|
3192
|
+
ptr = valueEndPtr;
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
if (!c) {
|
|
3196
|
+
throw new TomlError("unfinished table encountered", {
|
|
3197
|
+
toml: str,
|
|
3198
|
+
ptr
|
|
3199
|
+
});
|
|
3200
|
+
}
|
|
3201
|
+
return [res, ptr];
|
|
3202
|
+
}
|
|
3203
|
+
function parseArray(str, ptr, depth, integersAsBigInt) {
|
|
3204
|
+
let res = [];
|
|
3205
|
+
let c;
|
|
3206
|
+
ptr++;
|
|
3207
|
+
while ((c = str[ptr++]) !== "]" && c) {
|
|
3208
|
+
if (c === ",") {
|
|
3209
|
+
throw new TomlError("expected value, found comma", {
|
|
3210
|
+
toml: str,
|
|
3211
|
+
ptr: ptr - 1
|
|
3212
|
+
});
|
|
3213
|
+
} else if (c === "#")
|
|
3214
|
+
ptr = skipComment(str, ptr);
|
|
3215
|
+
else if (c !== " " && c !== "\t" && c !== `
|
|
3216
|
+
` && c !== "\r") {
|
|
3217
|
+
let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt);
|
|
3218
|
+
res.push(e[0]);
|
|
3219
|
+
ptr = e[1];
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
if (!c) {
|
|
3223
|
+
throw new TomlError("unfinished array encountered", {
|
|
3224
|
+
toml: str,
|
|
3225
|
+
ptr
|
|
3226
|
+
});
|
|
3227
|
+
}
|
|
3228
|
+
return [res, ptr];
|
|
3229
|
+
}
|
|
3230
|
+
var KEY_PART_RE;
|
|
3231
|
+
var init_struct = __esm(() => {
|
|
3232
|
+
init_primitive();
|
|
3233
|
+
init_extract();
|
|
3234
|
+
init_util();
|
|
3235
|
+
init_error();
|
|
3236
|
+
/*!
|
|
3237
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3238
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
3239
|
+
*
|
|
3240
|
+
* Redistribution and use in source and binary forms, with or without
|
|
3241
|
+
* modification, are permitted provided that the following conditions are met:
|
|
3242
|
+
*
|
|
3243
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
3244
|
+
* list of conditions and the following disclaimer.
|
|
3245
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
3246
|
+
* this list of conditions and the following disclaimer in the
|
|
3247
|
+
* documentation and/or other materials provided with the distribution.
|
|
3248
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
3249
|
+
* may be used to endorse or promote products derived from this software without
|
|
3250
|
+
* specific prior written permission.
|
|
3251
|
+
*
|
|
3252
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
3253
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
3254
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
3255
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
3256
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
3257
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
3258
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
3259
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
3260
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
3261
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3262
|
+
*/
|
|
3263
|
+
KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
3264
|
+
});
|
|
3265
|
+
|
|
3266
|
+
// node_modules/smol-toml/dist/parse.js
|
|
3267
|
+
function peekTable(key, table, meta, type) {
|
|
3268
|
+
let t = table;
|
|
3269
|
+
let m = meta;
|
|
3270
|
+
let k;
|
|
3271
|
+
let hasOwn = false;
|
|
3272
|
+
let state;
|
|
3273
|
+
for (let i = 0;i < key.length; i++) {
|
|
3274
|
+
if (i) {
|
|
3275
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
3276
|
+
m = (state = m[k]).c;
|
|
3277
|
+
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
3278
|
+
return null;
|
|
3279
|
+
}
|
|
3280
|
+
if (state.t === 2) {
|
|
3281
|
+
let l = t.length - 1;
|
|
3282
|
+
t = t[l];
|
|
3283
|
+
m = m[l].c;
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
k = key[i];
|
|
3287
|
+
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
|
|
3288
|
+
return null;
|
|
3289
|
+
}
|
|
3290
|
+
if (!hasOwn) {
|
|
3291
|
+
if (k === "__proto__") {
|
|
3292
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
3293
|
+
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
3294
|
+
}
|
|
3295
|
+
m[k] = {
|
|
3296
|
+
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
3297
|
+
d: false,
|
|
3298
|
+
i: 0,
|
|
3299
|
+
c: {}
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
state = m[k];
|
|
3304
|
+
if (state.t !== type && !(type === 1 && state.t === 3)) {
|
|
3305
|
+
return null;
|
|
3306
|
+
}
|
|
3307
|
+
if (type === 2) {
|
|
3308
|
+
if (!state.d) {
|
|
3309
|
+
state.d = true;
|
|
3310
|
+
t[k] = [];
|
|
3311
|
+
}
|
|
3312
|
+
t[k].push(t = {});
|
|
3313
|
+
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
|
|
3314
|
+
}
|
|
3315
|
+
if (state.d) {
|
|
3316
|
+
return null;
|
|
3317
|
+
}
|
|
3318
|
+
state.d = true;
|
|
3319
|
+
if (type === 1) {
|
|
3320
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
3321
|
+
} else if (type === 0 && hasOwn) {
|
|
3322
|
+
return null;
|
|
3323
|
+
}
|
|
3324
|
+
return [k, t, state.c];
|
|
3325
|
+
}
|
|
3326
|
+
function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
3327
|
+
let res = {};
|
|
3328
|
+
let meta = {};
|
|
3329
|
+
let tbl = res;
|
|
3330
|
+
let m = meta;
|
|
3331
|
+
for (let ptr = skipVoid(toml, 0);ptr < toml.length; ) {
|
|
3332
|
+
if (toml[ptr] === "[") {
|
|
3333
|
+
let isTableArray = toml[++ptr] === "[";
|
|
3334
|
+
let k = parseKey(toml, ptr += +isTableArray, "]");
|
|
3335
|
+
if (isTableArray) {
|
|
3336
|
+
if (toml[k[1] - 1] !== "]") {
|
|
3337
|
+
throw new TomlError("expected end of table declaration", {
|
|
3338
|
+
toml,
|
|
3339
|
+
ptr: k[1] - 1
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
k[1]++;
|
|
3343
|
+
}
|
|
3344
|
+
let p = peekTable(k[0], res, meta, isTableArray ? 2 : 1);
|
|
3345
|
+
if (!p) {
|
|
3346
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
3347
|
+
toml,
|
|
3348
|
+
ptr
|
|
3349
|
+
});
|
|
3350
|
+
}
|
|
3351
|
+
m = p[2];
|
|
3352
|
+
tbl = p[1];
|
|
3353
|
+
ptr = k[1];
|
|
3354
|
+
} else {
|
|
3355
|
+
let k = parseKey(toml, ptr);
|
|
3356
|
+
let p = peekTable(k[0], tbl, m, 0);
|
|
3357
|
+
if (!p) {
|
|
3358
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
3359
|
+
toml,
|
|
3360
|
+
ptr
|
|
3361
|
+
});
|
|
3362
|
+
}
|
|
3363
|
+
let v = extractValue(toml, k[1], undefined, maxDepth, integersAsBigInt);
|
|
3364
|
+
p[1][p[0]] = v[0];
|
|
3365
|
+
ptr = v[1];
|
|
3366
|
+
}
|
|
3367
|
+
ptr = skipVoid(toml, ptr, true);
|
|
3368
|
+
if (toml[ptr] && toml[ptr] !== `
|
|
3369
|
+
` && toml[ptr] !== "\r") {
|
|
3370
|
+
throw new TomlError("each key-value declaration must be followed by an end-of-line", {
|
|
3371
|
+
toml,
|
|
3372
|
+
ptr
|
|
3373
|
+
});
|
|
3374
|
+
}
|
|
3375
|
+
ptr = skipVoid(toml, ptr);
|
|
3376
|
+
}
|
|
3377
|
+
return res;
|
|
3378
|
+
}
|
|
3379
|
+
var init_parse = __esm(() => {
|
|
3380
|
+
init_struct();
|
|
3381
|
+
init_extract();
|
|
3382
|
+
init_util();
|
|
3383
|
+
init_error();
|
|
3384
|
+
/*!
|
|
3385
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3386
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
3387
|
+
*
|
|
3388
|
+
* Redistribution and use in source and binary forms, with or without
|
|
3389
|
+
* modification, are permitted provided that the following conditions are met:
|
|
3390
|
+
*
|
|
3391
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
3392
|
+
* list of conditions and the following disclaimer.
|
|
3393
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
3394
|
+
* this list of conditions and the following disclaimer in the
|
|
3395
|
+
* documentation and/or other materials provided with the distribution.
|
|
3396
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
3397
|
+
* may be used to endorse or promote products derived from this software without
|
|
3398
|
+
* specific prior written permission.
|
|
3399
|
+
*
|
|
3400
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
3401
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
3402
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
3403
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
3404
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
3405
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
3406
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
3407
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
3408
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
3409
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3410
|
+
*/
|
|
3411
|
+
});
|
|
3412
|
+
|
|
3413
|
+
// node_modules/smol-toml/dist/stringify.js
|
|
3414
|
+
var init_stringify = __esm(() => {
|
|
3415
|
+
/*!
|
|
3416
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3417
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
3418
|
+
*
|
|
3419
|
+
* Redistribution and use in source and binary forms, with or without
|
|
3420
|
+
* modification, are permitted provided that the following conditions are met:
|
|
3421
|
+
*
|
|
3422
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
3423
|
+
* list of conditions and the following disclaimer.
|
|
3424
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
3425
|
+
* this list of conditions and the following disclaimer in the
|
|
3426
|
+
* documentation and/or other materials provided with the distribution.
|
|
3427
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
3428
|
+
* may be used to endorse or promote products derived from this software without
|
|
3429
|
+
* specific prior written permission.
|
|
3430
|
+
*
|
|
3431
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
3432
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
3433
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
3434
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
3435
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
3436
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
3437
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
3438
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
3439
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
3440
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3441
|
+
*/
|
|
3442
|
+
});
|
|
3443
|
+
|
|
3444
|
+
// node_modules/smol-toml/dist/index.js
|
|
3445
|
+
var init_dist = __esm(() => {
|
|
3446
|
+
init_parse();
|
|
3447
|
+
init_stringify();
|
|
3448
|
+
init_date();
|
|
3449
|
+
init_error();
|
|
3450
|
+
/*!
|
|
3451
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3452
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
3453
|
+
*
|
|
3454
|
+
* Redistribution and use in source and binary forms, with or without
|
|
3455
|
+
* modification, are permitted provided that the following conditions are met:
|
|
3456
|
+
*
|
|
3457
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
3458
|
+
* list of conditions and the following disclaimer.
|
|
3459
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
3460
|
+
* this list of conditions and the following disclaimer in the
|
|
3461
|
+
* documentation and/or other materials provided with the distribution.
|
|
3462
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
3463
|
+
* may be used to endorse or promote products derived from this software without
|
|
3464
|
+
* specific prior written permission.
|
|
3465
|
+
*
|
|
3466
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
3467
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
3468
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
3469
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
3470
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
3471
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
3472
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
3473
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
3474
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
3475
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
3476
|
+
*/
|
|
3477
|
+
});
|
|
3478
|
+
|
|
3479
|
+
// src/hooks/fp-config.ts
|
|
3480
|
+
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3481
|
+
function detectLayout() {
|
|
3482
|
+
const raw = readVersionFile();
|
|
3483
|
+
if (raw) {
|
|
3484
|
+
if (raw.layout === LAYOUT_VERSION)
|
|
3485
|
+
return { kind: "current", version: raw };
|
|
3486
|
+
return raw.layout > LAYOUT_VERSION ? { kind: "future", found: raw.layout } : { kind: "stale", found: raw.layout };
|
|
3487
|
+
}
|
|
3488
|
+
const layoutOneMarkers = [
|
|
3489
|
+
legacy.policyConfig(),
|
|
3490
|
+
legacy.cacheDir(),
|
|
3491
|
+
legacy.launcherMarker(),
|
|
3492
|
+
legacy.lastVersion(),
|
|
3493
|
+
legacy.cloudCredentials(),
|
|
3494
|
+
legacy.ingestCredentials(),
|
|
3495
|
+
legacy.auditDashboard()
|
|
3496
|
+
];
|
|
3497
|
+
return layoutOneMarkers.some((p) => existsSync3(p)) ? { kind: "stale", found: 1 } : { kind: "absent" };
|
|
3498
|
+
}
|
|
3499
|
+
function readVersionFile() {
|
|
3500
|
+
try {
|
|
3501
|
+
const parsed = parse(readFileSync2(versionFile(), "utf8"));
|
|
3502
|
+
const layout = Number(parsed.layout);
|
|
3503
|
+
if (!Number.isFinite(layout))
|
|
3504
|
+
return null;
|
|
3505
|
+
return {
|
|
3506
|
+
layout,
|
|
3507
|
+
cli: typeof parsed.cli === "string" ? parsed.cli : "",
|
|
3508
|
+
daemon: typeof parsed.daemon === "string" ? parsed.daemon : undefined
|
|
3509
|
+
};
|
|
3510
|
+
} catch {
|
|
3511
|
+
return null;
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
function readIntervalDays(raw) {
|
|
3515
|
+
if (typeof raw !== "number" || !Number.isFinite(raw))
|
|
3516
|
+
return DEFAULT_AUDIT_INTERVAL_DAYS;
|
|
3517
|
+
const days = Math.floor(raw);
|
|
3518
|
+
if (days < MIN_AUDIT_INTERVAL_DAYS)
|
|
3519
|
+
return DEFAULT_AUDIT_INTERVAL_DAYS;
|
|
3520
|
+
return Math.min(days, MAX_AUDIT_INTERVAL_DAYS);
|
|
3521
|
+
}
|
|
3522
|
+
function readConfig() {
|
|
3523
|
+
try {
|
|
3524
|
+
const parsed = parse(readFileSync2(configFile(), "utf8"));
|
|
3525
|
+
const mode = parsed.mode?.kind;
|
|
3526
|
+
const daemon = parsed.daemon ?? {};
|
|
3527
|
+
const collector = parsed.collector ?? {};
|
|
3528
|
+
const telemetry = parsed.telemetry ?? {};
|
|
3529
|
+
const audit = parsed.audit ?? {};
|
|
3530
|
+
return {
|
|
3531
|
+
mode: mode === "cloud" ? "cloud" : "oss",
|
|
3532
|
+
daemon: { configured: daemon.configured === true },
|
|
3533
|
+
collector: {
|
|
3534
|
+
sessions: collector.sessions === true,
|
|
3535
|
+
hooks: collector.hooks !== false,
|
|
3536
|
+
hooksVerbosity: collector.hooks_verbosity === "all" || collector.hooks_verbosity === "off" ? collector.hooks_verbosity : "decisions",
|
|
3537
|
+
redact: collector.redact === "off" ? "off" : "minimal",
|
|
3538
|
+
environment: typeof collector.environment === "string" ? collector.environment : "local",
|
|
3539
|
+
machineId: typeof collector.machine_id === "string" ? collector.machine_id : undefined
|
|
3540
|
+
},
|
|
3541
|
+
telemetry: { enabled: telemetry.enabled !== false },
|
|
3542
|
+
audit: { auto: audit.auto === true, intervalDays: readIntervalDays(audit.interval_days) }
|
|
3543
|
+
};
|
|
3544
|
+
} catch {
|
|
3545
|
+
return structuredClone(DEFAULT_CONFIG);
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
var DEFAULT_AUDIT_INTERVAL_DAYS = 7, MIN_AUDIT_INTERVAL_DAYS = 1, MAX_AUDIT_INTERVAL_DAYS = 90, DEFAULT_CONFIG;
|
|
3549
|
+
var init_fp_config = __esm(() => {
|
|
3550
|
+
init_dist();
|
|
3551
|
+
init_package();
|
|
3552
|
+
init_fp_home();
|
|
3553
|
+
DEFAULT_CONFIG = {
|
|
3554
|
+
mode: "oss",
|
|
3555
|
+
daemon: { configured: false },
|
|
3556
|
+
collector: {
|
|
3557
|
+
sessions: false,
|
|
3558
|
+
hooks: true,
|
|
3559
|
+
hooksVerbosity: "decisions",
|
|
3560
|
+
redact: "minimal",
|
|
3561
|
+
environment: "local"
|
|
3562
|
+
},
|
|
3563
|
+
telemetry: { enabled: true },
|
|
3564
|
+
audit: { auto: false, intervalDays: DEFAULT_AUDIT_INTERVAL_DAYS }
|
|
3565
|
+
};
|
|
3566
|
+
});
|
|
3567
|
+
|
|
3568
|
+
// lib/telemetry-enabled.ts
|
|
3569
|
+
function isTelemetryEnabled() {
|
|
3570
|
+
if (process.env.FAILPROOFAI_TELEMETRY_DISABLED === "1")
|
|
3571
|
+
return false;
|
|
3572
|
+
try {
|
|
3573
|
+
return readConfig().telemetry.enabled;
|
|
3574
|
+
} catch {
|
|
3575
|
+
return true;
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
var init_telemetry_enabled = __esm(() => {
|
|
3579
|
+
init_fp_config();
|
|
3580
|
+
});
|
|
3581
|
+
|
|
2294
3582
|
// src/hooks/hook-telemetry.ts
|
|
2295
3583
|
async function sendEvent(distinctId, event, properties) {
|
|
2296
3584
|
const body = JSON.stringify({
|
|
@@ -2309,7 +3597,7 @@ async function sendEvent(distinctId, event, properties) {
|
|
|
2309
3597
|
} catch {}
|
|
2310
3598
|
}
|
|
2311
3599
|
async function trackHookEvent(distinctId, event, properties) {
|
|
2312
|
-
if (
|
|
3600
|
+
if (!isTelemetryEnabled())
|
|
2313
3601
|
return;
|
|
2314
3602
|
const p = sendEvent(distinctId, event, properties);
|
|
2315
3603
|
pending.add(p);
|
|
@@ -2324,6 +3612,7 @@ async function flushHookTelemetry() {
|
|
|
2324
3612
|
var API_KEY, CAPTURE_URL = "https://us.i.posthog.com/capture/", pending;
|
|
2325
3613
|
var init_hook_telemetry = __esm(() => {
|
|
2326
3614
|
init_package();
|
|
3615
|
+
init_telemetry_enabled();
|
|
2327
3616
|
API_KEY = POSTHOG_API_KEY;
|
|
2328
3617
|
pending = new Set;
|
|
2329
3618
|
});
|
|
@@ -2387,24 +3676,48 @@ function getFileBasedId() {
|
|
|
2387
3676
|
} catch {}
|
|
2388
3677
|
return id;
|
|
2389
3678
|
}
|
|
3679
|
+
function publishInstanceId(id) {
|
|
3680
|
+
let target;
|
|
3681
|
+
try {
|
|
3682
|
+
target = telemetryIdFile();
|
|
3683
|
+
if (fs.readFileSync(target, "utf-8").trim() === id)
|
|
3684
|
+
return;
|
|
3685
|
+
} catch {
|
|
3686
|
+
try {
|
|
3687
|
+
target = telemetryIdFile();
|
|
3688
|
+
} catch {
|
|
3689
|
+
return;
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
try {
|
|
3693
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
3694
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
3695
|
+
fs.writeFileSync(tmp, id, { encoding: "utf-8", mode: 384 });
|
|
3696
|
+
fs.renameSync(tmp, target);
|
|
3697
|
+
} catch {}
|
|
3698
|
+
}
|
|
2390
3699
|
function getInstanceId() {
|
|
2391
3700
|
if (cachedId)
|
|
2392
3701
|
return cachedId;
|
|
2393
3702
|
const machineId = getPlatformMachineId();
|
|
2394
3703
|
if (machineId) {
|
|
2395
3704
|
cachedId = hashToId(machineId);
|
|
3705
|
+
publishInstanceId(cachedId);
|
|
2396
3706
|
return cachedId;
|
|
2397
3707
|
}
|
|
2398
3708
|
const sysProps = getSystemPropertiesId();
|
|
2399
3709
|
if (sysProps) {
|
|
2400
3710
|
cachedId = hashToId(sysProps);
|
|
3711
|
+
publishInstanceId(cachedId);
|
|
2401
3712
|
return cachedId;
|
|
2402
3713
|
}
|
|
2403
3714
|
cachedId = getFileBasedId();
|
|
3715
|
+
publishInstanceId(cachedId);
|
|
2404
3716
|
return cachedId;
|
|
2405
3717
|
}
|
|
2406
3718
|
var NAMESPACE = "failproofai-telemetry-v1", ID_DIR, ID_FILE, cachedId;
|
|
2407
3719
|
var init_telemetry_id = __esm(() => {
|
|
3720
|
+
init_fp_home();
|
|
2408
3721
|
ID_DIR = path.join(os.homedir(), ".failproofai");
|
|
2409
3722
|
ID_FILE = path.join(ID_DIR, "instance-id");
|
|
2410
3723
|
});
|
|
@@ -3158,13 +4471,43 @@ function clearCustomHooks() {
|
|
|
3158
4471
|
const g = globalThis;
|
|
3159
4472
|
g[REGISTRY_KEY2] = [];
|
|
3160
4473
|
}
|
|
3161
|
-
var REGISTRY_KEY2 = "__failproofai_custom_hooks__";
|
|
3162
|
-
var init_custom_hooks_registry = () => {
|
|
4474
|
+
var REGISTRY_KEY2 = "__failproofai_custom_hooks__", customPolicies;
|
|
4475
|
+
var init_custom_hooks_registry = __esm(() => {
|
|
4476
|
+
customPolicies = {
|
|
4477
|
+
add(hook) {
|
|
4478
|
+
getRegistry2().push(hook);
|
|
4479
|
+
}
|
|
4480
|
+
};
|
|
4481
|
+
});
|
|
3163
4482
|
|
|
3164
4483
|
// src/hooks/loader-utils.ts
|
|
3165
|
-
import { readFile as readFile2, writeFile as writeFile2, unlink, access } from "fs/promises";
|
|
3166
|
-
import {
|
|
4484
|
+
import { readFile as readFile2, writeFile as writeFile2, unlink, access, mkdir, lstat } from "fs/promises";
|
|
4485
|
+
import { tmpdir } from "os";
|
|
4486
|
+
import { resolve as resolve4, dirname as dirname2, relative, join as join3 } from "path";
|
|
3167
4487
|
import { pathToFileURL } from "url";
|
|
4488
|
+
import { createHash } from "crypto";
|
|
4489
|
+
function isTmpArtifact(name) {
|
|
4490
|
+
return TMP_ARTIFACT_RE.test(name);
|
|
4491
|
+
}
|
|
4492
|
+
async function sweepStaleTmpArtifacts(dir, now = Date.now()) {
|
|
4493
|
+
let removed = 0;
|
|
4494
|
+
try {
|
|
4495
|
+
const { readdir, stat: stat2 } = await import("fs/promises");
|
|
4496
|
+
for (const name of await readdir(dir)) {
|
|
4497
|
+
if (!isTmpArtifact(name))
|
|
4498
|
+
continue;
|
|
4499
|
+
const path2 = resolve4(dir, name);
|
|
4500
|
+
try {
|
|
4501
|
+
const info = await stat2(path2);
|
|
4502
|
+
if (now - info.mtimeMs < TMP_SWEEP_MIN_AGE_MS)
|
|
4503
|
+
continue;
|
|
4504
|
+
await unlink(path2);
|
|
4505
|
+
removed++;
|
|
4506
|
+
} catch {}
|
|
4507
|
+
}
|
|
4508
|
+
} catch {}
|
|
4509
|
+
return removed;
|
|
4510
|
+
}
|
|
3168
4511
|
async function fileExists(path2) {
|
|
3169
4512
|
try {
|
|
3170
4513
|
await access(path2);
|
|
@@ -3176,14 +4519,14 @@ async function fileExists(path2) {
|
|
|
3176
4519
|
async function findDistIndex() {
|
|
3177
4520
|
const distPath = process.env.FAILPROOFAI_DIST_PATH;
|
|
3178
4521
|
if (distPath) {
|
|
3179
|
-
const candidate =
|
|
4522
|
+
const candidate = resolve4(distPath, "index.js");
|
|
3180
4523
|
if (await fileExists(candidate))
|
|
3181
4524
|
return candidate;
|
|
3182
4525
|
}
|
|
3183
4526
|
const candidates = [
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
4527
|
+
resolve4(dirname2(process.execPath), "..", "assets", "dist", "index.js"),
|
|
4528
|
+
resolve4(process.cwd(), "dist", "index.js"),
|
|
4529
|
+
resolve4(process.cwd(), "node_modules", "failproofai", "dist", "index.js")
|
|
3187
4530
|
];
|
|
3188
4531
|
for (const c of candidates) {
|
|
3189
4532
|
if (await fileExists(c))
|
|
@@ -3192,16 +4535,24 @@ async function findDistIndex() {
|
|
|
3192
4535
|
return null;
|
|
3193
4536
|
}
|
|
3194
4537
|
async function resolveLocalImport(fromDir, specifier) {
|
|
3195
|
-
const base =
|
|
3196
|
-
const candidates = [base, `${base}.js`, `${base}.mjs`, `${base}.ts`,
|
|
4538
|
+
const base = resolve4(fromDir, specifier);
|
|
4539
|
+
const candidates = [base, `${base}.js`, `${base}.mjs`, `${base}.ts`, resolve4(base, "index.js")];
|
|
3197
4540
|
for (const c of candidates) {
|
|
3198
4541
|
if (await fileExists(c))
|
|
3199
4542
|
return c;
|
|
3200
4543
|
}
|
|
3201
4544
|
return null;
|
|
3202
4545
|
}
|
|
3203
|
-
async function
|
|
3204
|
-
const shimPath =
|
|
4546
|
+
async function writeShim(dir, name, code, exclusive) {
|
|
4547
|
+
const shimPath = join3(dir, name);
|
|
4548
|
+
await writeFile2(shimPath, code, {
|
|
4549
|
+
encoding: "utf-8",
|
|
4550
|
+
mode: 384,
|
|
4551
|
+
...exclusive ? { flag: "wx" } : {}
|
|
4552
|
+
});
|
|
4553
|
+
return shimPath;
|
|
4554
|
+
}
|
|
4555
|
+
async function createEsmShim(distIndex, distUrl, tmpSuffix = TMP_SUFFIX) {
|
|
3205
4556
|
const shimCode = [
|
|
3206
4557
|
`import _cjs from '${distUrl}';`,
|
|
3207
4558
|
`export const customPolicies = _cjs.customPolicies;`,
|
|
@@ -3213,16 +4564,30 @@ async function createEsmShim(distIndex, distUrl) {
|
|
|
3213
4564
|
`export default _cjs;`
|
|
3214
4565
|
].join(`
|
|
3215
4566
|
`);
|
|
3216
|
-
|
|
4567
|
+
const name = `failproofai-dist${tmpSuffix}.shim.mjs`;
|
|
4568
|
+
try {
|
|
4569
|
+
const dir = shimsDir();
|
|
4570
|
+
await mkdir(dir, { recursive: true, mode: 448 });
|
|
4571
|
+
const st = await lstat(dir);
|
|
4572
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : null;
|
|
4573
|
+
if (!st.isDirectory() || st.isSymbolicLink() || uid !== null && st.uid !== uid || st.mode & 63) {
|
|
4574
|
+
throw new Error(`${dir} is not a private directory owned by this user`);
|
|
4575
|
+
}
|
|
4576
|
+
const shimPath2 = await writeShim(dir, name, shimCode, false);
|
|
4577
|
+
return { shimPath: shimPath2, shimUrl: pathToFileURL(shimPath2).href };
|
|
4578
|
+
} catch (err) {
|
|
4579
|
+
hookLogWarn(`policy shim directory unusable (${err instanceof Error ? err.message : String(err)}); falling back to ${tmpdir()}`);
|
|
4580
|
+
}
|
|
4581
|
+
const shimPath = await writeShim(tmpdir(), name, shimCode, true);
|
|
3217
4582
|
return { shimPath, shimUrl: pathToFileURL(shimPath).href };
|
|
3218
4583
|
}
|
|
3219
|
-
async function rewriteFileTree(entryPath, distUrl, distIndex) {
|
|
4584
|
+
async function rewriteFileTree(entryPath, distUrl, distIndex, tmpSuffix = TMP_SUFFIX, entrySha256) {
|
|
3220
4585
|
const queue = [entryPath];
|
|
3221
4586
|
const visited = new Set;
|
|
3222
4587
|
const tmpFiles = [];
|
|
3223
4588
|
let esmShimUrl = null;
|
|
3224
4589
|
if (distIndex && distUrl) {
|
|
3225
|
-
const shim = await createEsmShim(distIndex, distUrl);
|
|
4590
|
+
const shim = await createEsmShim(distIndex, distUrl, tmpSuffix);
|
|
3226
4591
|
tmpFiles.push(shim.shimPath);
|
|
3227
4592
|
esmShimUrl = shim.shimUrl;
|
|
3228
4593
|
}
|
|
@@ -3231,7 +4596,17 @@ async function rewriteFileTree(entryPath, distUrl, distIndex) {
|
|
|
3231
4596
|
if (visited.has(filePath))
|
|
3232
4597
|
continue;
|
|
3233
4598
|
visited.add(filePath);
|
|
3234
|
-
let code
|
|
4599
|
+
let code;
|
|
4600
|
+
if (entrySha256 && filePath === entryPath) {
|
|
4601
|
+
const buf = await readFile2(filePath);
|
|
4602
|
+
const actual = createHash("sha256").update(buf).digest("hex");
|
|
4603
|
+
if (actual !== entrySha256) {
|
|
4604
|
+
throw new Error(`cloud-managed policy failed integrity re-verification at load: expected ${entrySha256}, got ${actual}`);
|
|
4605
|
+
}
|
|
4606
|
+
code = buf.toString("utf-8");
|
|
4607
|
+
} else {
|
|
4608
|
+
code = await readFile2(filePath, "utf-8");
|
|
4609
|
+
}
|
|
3235
4610
|
if (esmShimUrl) {
|
|
3236
4611
|
code = code.replace(/from\s+(['"])(?:claudeye|failproofai)\1/g, `from '${esmShimUrl}'`);
|
|
3237
4612
|
}
|
|
@@ -3253,7 +4628,7 @@ async function rewriteFileTree(entryPath, distUrl, distIndex) {
|
|
|
3253
4628
|
if (!visited.has(resolved2) && !queue.includes(resolved2)) {
|
|
3254
4629
|
queue.push(resolved2);
|
|
3255
4630
|
}
|
|
3256
|
-
let relPath = relative(dir, resolved2 +
|
|
4631
|
+
let relPath = relative(dir, resolved2 + tmpSuffix).split("\\").join("/");
|
|
3257
4632
|
if (!relPath.startsWith("."))
|
|
3258
4633
|
relPath = "./" + relPath;
|
|
3259
4634
|
rewrites.set(specifier, relPath);
|
|
@@ -3266,7 +4641,7 @@ async function rewriteFileTree(entryPath, distUrl, distIndex) {
|
|
|
3266
4641
|
code = code.replace(new RegExp(`'${escaped}'`, "g"), `'${replacement}'`);
|
|
3267
4642
|
code = code.replace(new RegExp(`"${escaped}"`, "g"), `"${replacement}"`);
|
|
3268
4643
|
}
|
|
3269
|
-
const tmpPath = filePath +
|
|
4644
|
+
const tmpPath = filePath + tmpSuffix;
|
|
3270
4645
|
await writeFile2(tmpPath, code, "utf-8");
|
|
3271
4646
|
tmpFiles.push(tmpPath);
|
|
3272
4647
|
}
|
|
@@ -3279,36 +4654,61 @@ async function cleanupTmpFiles(tmpFiles) {
|
|
|
3279
4654
|
} catch {}
|
|
3280
4655
|
}
|
|
3281
4656
|
}
|
|
3282
|
-
var TMP_SUFFIX = ".__failproofai_tmp__.mjs", LOCAL_IMPORT_RE, LOCAL_REQUIRE_RE;
|
|
4657
|
+
var TMP_SUFFIX = ".__failproofai_tmp__.mjs", TMP_ARTIFACT_RE, TMP_SWEEP_MIN_AGE_MS = 60000, LOCAL_IMPORT_RE, LOCAL_REQUIRE_RE;
|
|
3283
4658
|
var init_loader_utils = __esm(() => {
|
|
4659
|
+
init_fp_home();
|
|
4660
|
+
init_hook_logger();
|
|
4661
|
+
TMP_ARTIFACT_RE = /\.__failproofai_tmp__\./;
|
|
3284
4662
|
LOCAL_IMPORT_RE = /(?:import\s+(?:[\s\S]*?\s+from\s+)?|export\s+(?:[\s\S]*?\s+from\s+))(['"])(\.\.?\/[^'"]+)\1/g;
|
|
3285
4663
|
LOCAL_REQUIRE_RE = /require\s*\(\s*(['"])(\.\.?\/[^'"]+)\1\s*\)/g;
|
|
3286
4664
|
});
|
|
3287
4665
|
|
|
3288
4666
|
// src/hooks/custom-hooks-loader.ts
|
|
3289
|
-
import { resolve as
|
|
3290
|
-
import {
|
|
4667
|
+
import { resolve as resolve5, isAbsolute, basename } from "node:path";
|
|
4668
|
+
import { randomUUID } from "crypto";
|
|
4669
|
+
import { existsSync as existsSync4, readdirSync } from "node:fs";
|
|
4670
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
3291
4671
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
3292
|
-
import {
|
|
4672
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
3293
4673
|
function discoverPolicyFiles(dir) {
|
|
3294
|
-
if (!
|
|
4674
|
+
if (!existsSync4(dir))
|
|
3295
4675
|
return [];
|
|
3296
4676
|
try {
|
|
3297
4677
|
const entries = readdirSync(dir, { withFileTypes: true });
|
|
3298
|
-
return entries.filter((e) => e.isFile() && CONVENTION_FILE_RE.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) =>
|
|
4678
|
+
return entries.filter((e) => e.isFile() && CONVENTION_FILE_RE.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => resolve5(dir, e.name));
|
|
3299
4679
|
} catch {
|
|
3300
4680
|
return [];
|
|
3301
4681
|
}
|
|
3302
4682
|
}
|
|
3303
4683
|
function findSkippedPolicyFiles(dir) {
|
|
3304
|
-
if (!
|
|
4684
|
+
if (!existsSync4(dir))
|
|
3305
4685
|
return [];
|
|
3306
4686
|
try {
|
|
3307
|
-
return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && LOADABLE_EXT_RE.test(e.name) && !CONVENTION_FILE_RE.test(e.name) && !e.name.endsWith(".d.ts")).map((e) => e.name).sort((a, b) => a.localeCompare(b));
|
|
4687
|
+
return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && LOADABLE_EXT_RE.test(e.name) && !CONVENTION_FILE_RE.test(e.name) && !e.name.endsWith(".d.ts") && !isTmpArtifact(e.name)).map((e) => e.name).sort((a, b) => a.localeCompare(b));
|
|
3308
4688
|
} catch {
|
|
3309
4689
|
return [];
|
|
3310
4690
|
}
|
|
3311
4691
|
}
|
|
4692
|
+
function moduleLoadTimeoutMs() {
|
|
4693
|
+
const override = Number(process.env.FAILPROOFAI_POLICY_LOAD_TIMEOUT_MS);
|
|
4694
|
+
return Number.isFinite(override) && override > 0 ? override : 1e4;
|
|
4695
|
+
}
|
|
4696
|
+
async function importWithDeadline(fileUrl) {
|
|
4697
|
+
const budget = moduleLoadTimeoutMs();
|
|
4698
|
+
let timer;
|
|
4699
|
+
try {
|
|
4700
|
+
await Promise.race([
|
|
4701
|
+
import(fileUrl),
|
|
4702
|
+
new Promise((_, reject) => {
|
|
4703
|
+
timer = setTimeout(() => reject(new Error(`timed out loading module after ${budget}ms`)), budget);
|
|
4704
|
+
timer.unref?.();
|
|
4705
|
+
})
|
|
4706
|
+
]);
|
|
4707
|
+
} finally {
|
|
4708
|
+
if (timer)
|
|
4709
|
+
clearTimeout(timer);
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
3312
4712
|
async function loadSingleFile(absPath, opts) {
|
|
3313
4713
|
const g = globalThis;
|
|
3314
4714
|
g[LOADING_KEY] = true;
|
|
@@ -3316,13 +4716,29 @@ async function loadSingleFile(absPath, opts) {
|
|
|
3316
4716
|
try {
|
|
3317
4717
|
const distIndex = await findDistIndex();
|
|
3318
4718
|
const distUrl = distIndex ? pathToFileURL2(distIndex).href : null;
|
|
3319
|
-
|
|
3320
|
-
const
|
|
3321
|
-
|
|
3322
|
-
await
|
|
4719
|
+
const sequence = ++loadSequence;
|
|
4720
|
+
const tmpSuffix = `${TMP_SUFFIX}.${process.pid}.${sequence}.${randomUUID()}.mjs`;
|
|
4721
|
+
tmpFiles = await rewriteFileTree(absPath, distUrl, distIndex, tmpSuffix, opts?.verifyEntrySha);
|
|
4722
|
+
const fingerprint = await fingerprintTemporaryTree(tmpFiles, tmpSuffix);
|
|
4723
|
+
const cached = policyModuleCache.get(absPath);
|
|
4724
|
+
if (cached?.fingerprint === fingerprint) {
|
|
4725
|
+
for (const hook of cached.hooks)
|
|
4726
|
+
customPolicies.add({ ...hook });
|
|
4727
|
+
return;
|
|
4728
|
+
}
|
|
4729
|
+
const entryTmp = absPath + tmpSuffix;
|
|
4730
|
+
const fileUrl = pathToFileURL2(entryTmp).href;
|
|
4731
|
+
const hooksBefore = getCustomHooks().length;
|
|
4732
|
+
await importWithDeadline(fileUrl);
|
|
4733
|
+
if (policyModuleCache.size >= POLICY_MODULE_CACHE_MAX_ENTRIES)
|
|
4734
|
+
policyModuleCache.clear();
|
|
4735
|
+
policyModuleCache.set(absPath, {
|
|
4736
|
+
fingerprint,
|
|
4737
|
+
hooks: getCustomHooks().slice(hooksBefore).map((hook) => ({ ...hook }))
|
|
4738
|
+
});
|
|
3323
4739
|
} catch (err) {
|
|
3324
4740
|
const msg = err instanceof Error ? err.message : String(err);
|
|
3325
|
-
const errorType = /Cannot find module|MODULE_NOT_FOUND|ENOENT/i.test(msg) ? "module_not_found" : /SyntaxError|Unexpected token/i.test(msg) ? "syntax_error" : "runtime_error";
|
|
4741
|
+
const errorType = /Cannot find module|MODULE_NOT_FOUND|ENOENT/i.test(msg) ? "module_not_found" : /SyntaxError|Unexpected token/i.test(msg) ? "syntax_error" : /timed out loading module/i.test(msg) ? "load_timeout" : "runtime_error";
|
|
3326
4742
|
trackHookEvent(getInstanceId(), "custom_hooks_load_error", {
|
|
3327
4743
|
error_type: errorType,
|
|
3328
4744
|
is_convention: !!opts?.conventionScope,
|
|
@@ -3337,6 +4753,15 @@ async function loadSingleFile(absPath, opts) {
|
|
|
3337
4753
|
await cleanupTmpFiles(tmpFiles);
|
|
3338
4754
|
}
|
|
3339
4755
|
}
|
|
4756
|
+
async function fingerprintTemporaryTree(tmpFiles, tmpSuffix) {
|
|
4757
|
+
const hash = createHash2("sha256");
|
|
4758
|
+
for (const tmpFile of [...tmpFiles].sort()) {
|
|
4759
|
+
hash.update(tmpFile.replaceAll(tmpSuffix, TMP_SUFFIX));
|
|
4760
|
+
const contents = await readFile3(tmpFile, "utf8");
|
|
4761
|
+
hash.update(contents.replaceAll(tmpSuffix, TMP_SUFFIX));
|
|
4762
|
+
}
|
|
4763
|
+
return hash.digest("hex");
|
|
4764
|
+
}
|
|
3340
4765
|
function customPolicyId(file, name) {
|
|
3341
4766
|
return `custom:${file}:${name}`;
|
|
3342
4767
|
}
|
|
@@ -3356,15 +4781,25 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
3356
4781
|
const projectRoot = findProjectConfigDir(opts?.sessionCwd ?? process.cwd());
|
|
3357
4782
|
const conventionEnabled = opts?.customPoliciesEnabled !== false;
|
|
3358
4783
|
const loadedPaths = new Set;
|
|
4784
|
+
const cloudManagedByPath = new Map((opts?.cloudManagedPolicies ?? []).map((policy) => [resolve5(policy.path), policy]));
|
|
3359
4785
|
for (const customPoliciesPath of typeof customPoliciesPaths === "string" ? [customPoliciesPaths] : customPoliciesPaths ?? []) {
|
|
3360
|
-
const absPath =
|
|
3361
|
-
if (
|
|
4786
|
+
const absPath = resolve5(projectRoot, customPoliciesPath);
|
|
4787
|
+
if (existsSync4(absPath)) {
|
|
3362
4788
|
if (!loadedPaths.has(absPath)) {
|
|
3363
4789
|
loadedPaths.add(absPath);
|
|
3364
4790
|
const hooksBefore = getCustomHooks().length;
|
|
3365
|
-
await loadSingleFile(absPath
|
|
4791
|
+
await loadSingleFile(absPath, {
|
|
4792
|
+
verifyEntrySha: cloudManagedByPath.get(absPath)?.sha256
|
|
4793
|
+
});
|
|
3366
4794
|
for (const hook of getCustomHooks().slice(hooksBefore)) {
|
|
3367
|
-
|
|
4795
|
+
const cloudManaged = cloudManagedByPath.get(absPath);
|
|
4796
|
+
const tagged = hook;
|
|
4797
|
+
if (cloudManaged) {
|
|
4798
|
+
tagged.__cloudManaged = cloudManaged;
|
|
4799
|
+
tagged.__policyId = `cloud:${cloudManaged.id}@${cloudManaged.revision}:${hook.name}`;
|
|
4800
|
+
} else {
|
|
4801
|
+
tagged.__policyId = customPolicyId(absPath, hook.name);
|
|
4802
|
+
}
|
|
3368
4803
|
}
|
|
3369
4804
|
}
|
|
3370
4805
|
} else {
|
|
@@ -3372,9 +4807,12 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
3372
4807
|
}
|
|
3373
4808
|
}
|
|
3374
4809
|
const hooksBeforeConvention = getCustomHooks().length;
|
|
3375
|
-
const projectDir =
|
|
3376
|
-
if (conventionEnabled)
|
|
4810
|
+
const projectDir = resolve5(projectRoot, ".failproofai", "policies");
|
|
4811
|
+
if (conventionEnabled) {
|
|
4812
|
+
sweepStaleTmpArtifacts(projectDir);
|
|
3377
4813
|
warnSkippedPolicyFiles(projectDir, "project");
|
|
4814
|
+
}
|
|
4815
|
+
sweepStaleTmpArtifacts(shimsDir());
|
|
3378
4816
|
const projectFiles = conventionEnabled ? discoverPolicyFiles(projectDir).filter((f) => !loadedPaths.has(f)) : [];
|
|
3379
4817
|
for (const file of projectFiles) {
|
|
3380
4818
|
loadedPaths.add(file);
|
|
@@ -3392,9 +4830,11 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
3392
4830
|
});
|
|
3393
4831
|
}
|
|
3394
4832
|
}
|
|
3395
|
-
const userDir =
|
|
3396
|
-
if (conventionEnabled && userDir !== projectDir)
|
|
4833
|
+
const userDir = customPoliciesDir();
|
|
4834
|
+
if (conventionEnabled && userDir !== projectDir) {
|
|
4835
|
+
sweepStaleTmpArtifacts(userDir);
|
|
3397
4836
|
warnSkippedPolicyFiles(userDir, "user");
|
|
4837
|
+
}
|
|
3398
4838
|
const userFiles = conventionEnabled && userDir !== projectDir ? discoverPolicyFiles(userDir).filter((f) => !loadedPaths.has(f)) : [];
|
|
3399
4839
|
for (const file of userFiles) {
|
|
3400
4840
|
loadedPaths.add(file);
|
|
@@ -3436,7 +4876,7 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
3436
4876
|
}
|
|
3437
4877
|
return { hooks: allHooks, conventionSources };
|
|
3438
4878
|
}
|
|
3439
|
-
var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE, loadSequence = 0, LOADABLE_EXT_RE;
|
|
4879
|
+
var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE, loadSequence = 0, policyModuleCache, POLICY_MODULE_CACHE_MAX_ENTRIES = 500, LOADABLE_EXT_RE;
|
|
3440
4880
|
var init_custom_hooks_loader = __esm(() => {
|
|
3441
4881
|
init_hook_logger();
|
|
3442
4882
|
init_custom_hooks_registry();
|
|
@@ -3444,44 +4884,45 @@ var init_custom_hooks_loader = __esm(() => {
|
|
|
3444
4884
|
init_hooks_config();
|
|
3445
4885
|
init_hook_telemetry();
|
|
3446
4886
|
init_telemetry_id();
|
|
4887
|
+
init_fp_home();
|
|
3447
4888
|
CONVENTION_FILE_RE = /policies\.(js|mjs|ts)$/;
|
|
4889
|
+
policyModuleCache = new Map;
|
|
3448
4890
|
LOADABLE_EXT_RE = /\.(js|mjs|ts)$/;
|
|
3449
4891
|
});
|
|
3450
4892
|
|
|
3451
4893
|
// src/hooks/hook-activity-store.ts
|
|
3452
4894
|
import {
|
|
3453
|
-
readFileSync as
|
|
3454
|
-
writeFileSync as
|
|
4895
|
+
readFileSync as readFileSync3,
|
|
4896
|
+
writeFileSync as writeFileSync3,
|
|
3455
4897
|
appendFileSync as appendFileSync2,
|
|
3456
4898
|
renameSync as renameSync2,
|
|
3457
4899
|
readdirSync as readdirSync2,
|
|
3458
|
-
mkdirSync as
|
|
3459
|
-
existsSync as
|
|
3460
|
-
statSync as
|
|
4900
|
+
mkdirSync as mkdirSync4,
|
|
4901
|
+
existsSync as existsSync5,
|
|
4902
|
+
statSync as statSync5,
|
|
3461
4903
|
unlinkSync
|
|
3462
4904
|
} from "node:fs";
|
|
3463
|
-
import { join as
|
|
3464
|
-
import { homedir as homedir5 } from "node:os";
|
|
4905
|
+
import { join as join4 } from "node:path";
|
|
3465
4906
|
function ensureDir() {
|
|
3466
|
-
if (!
|
|
3467
|
-
|
|
4907
|
+
if (!existsSync5(storeDirValue())) {
|
|
4908
|
+
mkdirSync4(storeDirValue(), { recursive: true });
|
|
3468
4909
|
}
|
|
3469
4910
|
}
|
|
3470
4911
|
function acquireLock() {
|
|
3471
4912
|
ensureDir();
|
|
3472
|
-
const lockPath =
|
|
4913
|
+
const lockPath = join4(storeDirValue(), LOCK_FILE);
|
|
3473
4914
|
const deadline = Date.now() + LOCK_STALE_MS;
|
|
3474
4915
|
while (Date.now() < deadline) {
|
|
3475
4916
|
try {
|
|
3476
|
-
|
|
4917
|
+
writeFileSync3(lockPath, String(process.pid), { flag: "wx" });
|
|
3477
4918
|
return;
|
|
3478
4919
|
} catch (e) {
|
|
3479
4920
|
if (e.code !== "EEXIST")
|
|
3480
4921
|
return;
|
|
3481
4922
|
try {
|
|
3482
|
-
const s =
|
|
4923
|
+
const s = statSync5(lockPath);
|
|
3483
4924
|
if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
|
|
3484
|
-
|
|
4925
|
+
writeFileSync3(lockPath, String(process.pid), "utf-8");
|
|
3485
4926
|
return;
|
|
3486
4927
|
}
|
|
3487
4928
|
} catch {}
|
|
@@ -3490,15 +4931,15 @@ function acquireLock() {
|
|
|
3490
4931
|
}
|
|
3491
4932
|
function releaseLock() {
|
|
3492
4933
|
try {
|
|
3493
|
-
unlinkSync(
|
|
4934
|
+
unlinkSync(join4(storeDirValue(), LOCK_FILE));
|
|
3494
4935
|
} catch {}
|
|
3495
4936
|
}
|
|
3496
4937
|
function persistHookActivity(entry) {
|
|
3497
4938
|
ensureDir();
|
|
3498
4939
|
acquireLock();
|
|
3499
4940
|
try {
|
|
3500
|
-
const currentPath =
|
|
3501
|
-
const countPath =
|
|
4941
|
+
const currentPath = join4(storeDirValue(), CURRENT_FILE);
|
|
4942
|
+
const countPath = join4(storeDirValue(), COUNT_FILE);
|
|
3502
4943
|
const lineCount = readCount(countPath);
|
|
3503
4944
|
if (lineCount >= PAGE_SIZE) {
|
|
3504
4945
|
try {
|
|
@@ -3518,13 +4959,13 @@ function persistHookActivity(entry) {
|
|
|
3518
4959
|
}
|
|
3519
4960
|
function rotate(currentPath, countPath) {
|
|
3520
4961
|
const archiveName = `page-${Date.now()}-${rotateSeq++}.jsonl`;
|
|
3521
|
-
const archivePath =
|
|
4962
|
+
const archivePath = join4(storeDirValue(), archiveName);
|
|
3522
4963
|
renameSync2(currentPath, archivePath);
|
|
3523
4964
|
writeCount(countPath, 0);
|
|
3524
4965
|
}
|
|
3525
4966
|
function readCount(countPath) {
|
|
3526
4967
|
try {
|
|
3527
|
-
const n = parseInt(
|
|
4968
|
+
const n = parseInt(readFileSync3(countPath, "utf-8"), 10);
|
|
3528
4969
|
return isNaN(n) ? 0 : n;
|
|
3529
4970
|
} catch {
|
|
3530
4971
|
return 0;
|
|
@@ -3532,12 +4973,12 @@ function readCount(countPath) {
|
|
|
3532
4973
|
}
|
|
3533
4974
|
function writeCount(countPath, n) {
|
|
3534
4975
|
try {
|
|
3535
|
-
|
|
4976
|
+
writeFileSync3(countPath, String(n), "utf-8");
|
|
3536
4977
|
} catch {}
|
|
3537
4978
|
}
|
|
3538
4979
|
function readStoredStats() {
|
|
3539
4980
|
try {
|
|
3540
|
-
return JSON.parse(
|
|
4981
|
+
return JSON.parse(readFileSync3(join4(storeDirValue(), STATS_FILE), "utf-8"));
|
|
3541
4982
|
} catch {
|
|
3542
4983
|
return { totalEvents: 0, denyCount: 0, policyMap: {} };
|
|
3543
4984
|
}
|
|
@@ -3554,20 +4995,19 @@ function updateStats(entry) {
|
|
|
3554
4995
|
} else if (entry.policyName) {
|
|
3555
4996
|
s.policyMap[entry.policyName] = (s.policyMap[entry.policyName] ?? 0) + 1;
|
|
3556
4997
|
}
|
|
3557
|
-
const tmpPath =
|
|
4998
|
+
const tmpPath = join4(storeDirValue(), `stats.json.${process.pid}.tmp`);
|
|
3558
4999
|
try {
|
|
3559
|
-
|
|
3560
|
-
renameSync2(tmpPath,
|
|
5000
|
+
writeFileSync3(tmpPath, JSON.stringify(s), "utf-8");
|
|
5001
|
+
renameSync2(tmpPath, join4(storeDirValue(), STATS_FILE));
|
|
3561
5002
|
} catch {
|
|
3562
5003
|
try {
|
|
3563
5004
|
unlinkSync(tmpPath);
|
|
3564
5005
|
} catch {}
|
|
3565
5006
|
}
|
|
3566
5007
|
}
|
|
3567
|
-
var PAGE_SIZE = 25,
|
|
5008
|
+
var PAGE_SIZE = 25, defaultStoreDir = () => hookActivityDir(), CURRENT_FILE = "current.jsonl", COUNT_FILE = "current.count", STATS_FILE = "stats.json", LOCK_FILE = "current.lock", LOCK_STALE_MS = 2000, storeDirOverride = null, storeDirValue = () => storeDirOverride ?? defaultStoreDir(), rotateSeq = 0;
|
|
3568
5009
|
var init_hook_activity_store = __esm(() => {
|
|
3569
|
-
|
|
3570
|
-
storeDir = DEFAULT_STORE_DIR;
|
|
5010
|
+
init_fp_home();
|
|
3571
5011
|
});
|
|
3572
5012
|
|
|
3573
5013
|
// src/hooks/resolve-cwd.ts
|
|
@@ -3616,10 +5056,10 @@ function runtimeCache(fn, revalidateSeconds, options) {
|
|
|
3616
5056
|
}
|
|
3617
5057
|
|
|
3618
5058
|
// lib/paths.ts
|
|
3619
|
-
import { homedir as
|
|
3620
|
-
import { join as
|
|
5059
|
+
import { homedir as homedir4 } from "os";
|
|
5060
|
+
import { join as join5 } from "path";
|
|
3621
5061
|
function getDefaultClaudeProjectsPath() {
|
|
3622
|
-
return
|
|
5062
|
+
return join5(homedir4(), ".claude", "projects");
|
|
3623
5063
|
}
|
|
3624
5064
|
function decodeFolderName(name) {
|
|
3625
5065
|
if (/^[A-Za-z]--/.test(name)) {
|
|
@@ -3713,8 +5153,8 @@ __export(exports_codex_projects, {
|
|
|
3713
5153
|
getCachedCodexProjects: () => getCachedCodexProjects
|
|
3714
5154
|
});
|
|
3715
5155
|
import { open as open2, readdir } from "node:fs/promises";
|
|
3716
|
-
import { homedir as
|
|
3717
|
-
import { join as
|
|
5156
|
+
import { homedir as homedir5 } from "node:os";
|
|
5157
|
+
import { join as join6 } from "node:path";
|
|
3718
5158
|
async function safeReaddir(dir) {
|
|
3719
5159
|
try {
|
|
3720
5160
|
return await readdir(dir, { withFileTypes: true });
|
|
@@ -3762,7 +5202,7 @@ async function listJsonlFiles(dir) {
|
|
|
3762
5202
|
const entries = await safeReaddir(dir);
|
|
3763
5203
|
if (!entries)
|
|
3764
5204
|
return [];
|
|
3765
|
-
return entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) =>
|
|
5205
|
+
return entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => join6(dir, e.name));
|
|
3766
5206
|
}
|
|
3767
5207
|
async function scanCodexSessions() {
|
|
3768
5208
|
const yearDirs = await safeReaddir(CODEX_SESSIONS_ROOT);
|
|
@@ -3772,19 +5212,19 @@ async function scanCodexSessions() {
|
|
|
3772
5212
|
for (const y of yearDirs) {
|
|
3773
5213
|
if (!y.isDirectory())
|
|
3774
5214
|
continue;
|
|
3775
|
-
const monthDirs = await safeReaddir(
|
|
5215
|
+
const monthDirs = await safeReaddir(join6(CODEX_SESSIONS_ROOT, y.name));
|
|
3776
5216
|
if (!monthDirs)
|
|
3777
5217
|
continue;
|
|
3778
5218
|
for (const m of monthDirs) {
|
|
3779
5219
|
if (!m.isDirectory())
|
|
3780
5220
|
continue;
|
|
3781
|
-
const dayDirs = await safeReaddir(
|
|
5221
|
+
const dayDirs = await safeReaddir(join6(CODEX_SESSIONS_ROOT, y.name, m.name));
|
|
3782
5222
|
if (!dayDirs)
|
|
3783
5223
|
continue;
|
|
3784
5224
|
for (const d of dayDirs) {
|
|
3785
5225
|
if (!d.isDirectory())
|
|
3786
5226
|
continue;
|
|
3787
|
-
const dayPath =
|
|
5227
|
+
const dayPath = join6(CODEX_SESSIONS_ROOT, y.name, m.name, d.name);
|
|
3788
5228
|
filePaths.push(...await listJsonlFiles(dayPath));
|
|
3789
5229
|
}
|
|
3790
5230
|
}
|
|
@@ -3892,7 +5332,7 @@ var CODEX_SESSIONS_ROOT, SESSION_ID_RE, FIRST_LINE_CHUNK_BYTES, cachedScan, getC
|
|
|
3892
5332
|
var init_codex_projects = __esm(() => {
|
|
3893
5333
|
init_paths();
|
|
3894
5334
|
init_logger();
|
|
3895
|
-
CODEX_SESSIONS_ROOT =
|
|
5335
|
+
CODEX_SESSIONS_ROOT = join6(homedir5(), ".codex", "sessions");
|
|
3896
5336
|
SESSION_ID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
|
3897
5337
|
FIRST_LINE_CHUNK_BYTES = 256 * 1024;
|
|
3898
5338
|
cachedScan = runtimeCache(scanCodexSessions, 30);
|
|
@@ -3911,11 +5351,11 @@ __export(exports_copilot_projects, {
|
|
|
3911
5351
|
getCachedCopilotSessionsByEncodedName: () => getCachedCopilotSessionsByEncodedName,
|
|
3912
5352
|
getCachedCopilotProjects: () => getCachedCopilotProjects
|
|
3913
5353
|
});
|
|
3914
|
-
import { readdir as readdir2, readFile as
|
|
3915
|
-
import { homedir as
|
|
3916
|
-
import { join as
|
|
5354
|
+
import { readdir as readdir2, readFile as readFile4, stat as stat2 } from "node:fs/promises";
|
|
5355
|
+
import { homedir as homedir6 } from "node:os";
|
|
5356
|
+
import { join as join7 } from "node:path";
|
|
3917
5357
|
function getCopilotSessionStateRoot() {
|
|
3918
|
-
return
|
|
5358
|
+
return join7(process.env.COPILOT_HOME || join7(homedir6(), ".copilot"), "session-state");
|
|
3919
5359
|
}
|
|
3920
5360
|
async function safeReaddir2(dir) {
|
|
3921
5361
|
try {
|
|
@@ -3944,13 +5384,13 @@ async function scanCopilotSessions() {
|
|
|
3944
5384
|
return [];
|
|
3945
5385
|
const candidates = entries.filter((e) => e.isDirectory()).map((e) => ({
|
|
3946
5386
|
sessionId: e.name,
|
|
3947
|
-
workspacePath:
|
|
3948
|
-
eventsPath:
|
|
5387
|
+
workspacePath: join7(root, e.name, "workspace.yaml"),
|
|
5388
|
+
eventsPath: join7(root, e.name, "events.jsonl")
|
|
3949
5389
|
}));
|
|
3950
5390
|
const settled = await batchAll(candidates.map((c) => async () => {
|
|
3951
5391
|
let workspaceText;
|
|
3952
5392
|
try {
|
|
3953
|
-
workspaceText = await
|
|
5393
|
+
workspaceText = await readFile4(c.workspacePath, "utf-8");
|
|
3954
5394
|
} catch {
|
|
3955
5395
|
return null;
|
|
3956
5396
|
}
|
|
@@ -4059,11 +5499,11 @@ __export(exports_cursor_projects, {
|
|
|
4059
5499
|
getCachedCursorSessionsByEncodedName: () => getCachedCursorSessionsByEncodedName,
|
|
4060
5500
|
getCachedCursorProjects: () => getCachedCursorProjects
|
|
4061
5501
|
});
|
|
4062
|
-
import { readdir as readdir3, readFile as
|
|
4063
|
-
import { homedir as
|
|
4064
|
-
import { join as
|
|
5502
|
+
import { readdir as readdir3, readFile as readFile5, stat as stat3 } from "node:fs/promises";
|
|
5503
|
+
import { homedir as homedir7 } from "node:os";
|
|
5504
|
+
import { join as join8 } from "node:path";
|
|
4065
5505
|
function getCursorHome() {
|
|
4066
|
-
return process.env.CURSOR_HOME ||
|
|
5506
|
+
return process.env.CURSOR_HOME || join8(homedir7(), ".cursor");
|
|
4067
5507
|
}
|
|
4068
5508
|
async function safeReaddir3(dir) {
|
|
4069
5509
|
try {
|
|
@@ -4095,12 +5535,12 @@ function parseCwdFromMetaText(text) {
|
|
|
4095
5535
|
}
|
|
4096
5536
|
async function findFirstUsableMeta(dir, candidates) {
|
|
4097
5537
|
for (const name of candidates) {
|
|
4098
|
-
const path2 =
|
|
5538
|
+
const path2 = join8(dir, name);
|
|
4099
5539
|
if (await statMtime2(path2) === null)
|
|
4100
5540
|
continue;
|
|
4101
5541
|
let text;
|
|
4102
5542
|
try {
|
|
4103
|
-
text = await
|
|
5543
|
+
text = await readFile5(path2, "utf-8");
|
|
4104
5544
|
} catch {
|
|
4105
5545
|
continue;
|
|
4106
5546
|
}
|
|
@@ -4112,7 +5552,7 @@ async function findFirstUsableMeta(dir, candidates) {
|
|
|
4112
5552
|
}
|
|
4113
5553
|
async function findFirstExistingPath(dir, candidates) {
|
|
4114
5554
|
for (const name of candidates) {
|
|
4115
|
-
const path2 =
|
|
5555
|
+
const path2 = join8(dir, name);
|
|
4116
5556
|
if (await statMtime2(path2) !== null)
|
|
4117
5557
|
return path2;
|
|
4118
5558
|
}
|
|
@@ -4122,7 +5562,7 @@ async function scanCursorSessions() {
|
|
|
4122
5562
|
const home = getCursorHome();
|
|
4123
5563
|
const newCandidates = [];
|
|
4124
5564
|
const legacyCandidates = [];
|
|
4125
|
-
const projectsRoot =
|
|
5565
|
+
const projectsRoot = join8(home, NEW_PROJECTS_DIR);
|
|
4126
5566
|
const projectEntries = await safeReaddir3(projectsRoot);
|
|
4127
5567
|
if (projectEntries) {
|
|
4128
5568
|
for (const proj of projectEntries) {
|
|
@@ -4130,7 +5570,7 @@ async function scanCursorSessions() {
|
|
|
4130
5570
|
continue;
|
|
4131
5571
|
const decoded = decodeFolderName(proj.name);
|
|
4132
5572
|
const cwd = decoded.startsWith("/") || /^[A-Za-z]:\//.test(decoded) ? decoded : `/${decoded}`;
|
|
4133
|
-
const transcriptsRoot =
|
|
5573
|
+
const transcriptsRoot = join8(projectsRoot, proj.name, NEW_AGENT_TRANSCRIPTS_DIR);
|
|
4134
5574
|
const sessionDirs = await safeReaddir3(transcriptsRoot);
|
|
4135
5575
|
if (!sessionDirs)
|
|
4136
5576
|
continue;
|
|
@@ -4139,28 +5579,28 @@ async function scanCursorSessions() {
|
|
|
4139
5579
|
continue;
|
|
4140
5580
|
newCandidates.push({
|
|
4141
5581
|
sessionId: sd.name,
|
|
4142
|
-
dir:
|
|
5582
|
+
dir: join8(transcriptsRoot, sd.name),
|
|
4143
5583
|
cwd
|
|
4144
5584
|
});
|
|
4145
5585
|
}
|
|
4146
5586
|
}
|
|
4147
5587
|
}
|
|
4148
5588
|
for (const sub of LEGACY_SESSION_ROOT_CANDIDATES) {
|
|
4149
|
-
const root =
|
|
5589
|
+
const root = join8(home, sub);
|
|
4150
5590
|
const entries = await safeReaddir3(root);
|
|
4151
5591
|
if (!entries)
|
|
4152
5592
|
continue;
|
|
4153
5593
|
for (const e of entries) {
|
|
4154
5594
|
if (!e.isDirectory())
|
|
4155
5595
|
continue;
|
|
4156
|
-
legacyCandidates.push({ sessionId: e.name, dir:
|
|
5596
|
+
legacyCandidates.push({ sessionId: e.name, dir: join8(root, e.name) });
|
|
4157
5597
|
}
|
|
4158
5598
|
}
|
|
4159
5599
|
if (newCandidates.length === 0 && legacyCandidates.length === 0)
|
|
4160
5600
|
return [];
|
|
4161
5601
|
const settled = await batchAll([
|
|
4162
5602
|
...newCandidates.map((c) => async () => {
|
|
4163
|
-
const transcriptPath =
|
|
5603
|
+
const transcriptPath = join8(c.dir, `${c.sessionId}.jsonl`);
|
|
4164
5604
|
const transcriptMtime = await statMtime2(transcriptPath);
|
|
4165
5605
|
if (!transcriptMtime)
|
|
4166
5606
|
return null;
|
|
@@ -4432,11 +5872,11 @@ __export(exports_pi_projects, {
|
|
|
4432
5872
|
getCachedPiSessionsByEncodedName: () => getCachedPiSessionsByEncodedName,
|
|
4433
5873
|
getCachedPiProjects: () => getCachedPiProjects
|
|
4434
5874
|
});
|
|
4435
|
-
import { readdir as readdir4, readFile as
|
|
4436
|
-
import { homedir as
|
|
4437
|
-
import { join as
|
|
5875
|
+
import { readdir as readdir4, readFile as readFile6, stat as stat4 } from "node:fs/promises";
|
|
5876
|
+
import { homedir as homedir8 } from "node:os";
|
|
5877
|
+
import { join as join9 } from "node:path";
|
|
4438
5878
|
function getPiSessionsRoot() {
|
|
4439
|
-
return process.env.PI_SESSIONS_DIR ||
|
|
5879
|
+
return process.env.PI_SESSIONS_DIR || join9(homedir8(), ".pi", "agent", "sessions");
|
|
4440
5880
|
}
|
|
4441
5881
|
async function safeReaddir4(dir) {
|
|
4442
5882
|
try {
|
|
@@ -4455,7 +5895,7 @@ async function statMtime3(path2) {
|
|
|
4455
5895
|
async function readSessionCwd(filePath) {
|
|
4456
5896
|
let text;
|
|
4457
5897
|
try {
|
|
4458
|
-
text = await
|
|
5898
|
+
text = await readFile6(filePath, "utf-8");
|
|
4459
5899
|
} catch {
|
|
4460
5900
|
return null;
|
|
4461
5901
|
}
|
|
@@ -4484,7 +5924,7 @@ async function scanPiSessions() {
|
|
|
4484
5924
|
for (const cwdDir of cwdDirs) {
|
|
4485
5925
|
if (!cwdDir.isDirectory())
|
|
4486
5926
|
continue;
|
|
4487
|
-
const cwdPath =
|
|
5927
|
+
const cwdPath = join9(root, cwdDir.name);
|
|
4488
5928
|
const sessionFiles = await safeReaddir4(cwdPath);
|
|
4489
5929
|
if (!sessionFiles)
|
|
4490
5930
|
continue;
|
|
@@ -4494,7 +5934,7 @@ async function scanPiSessions() {
|
|
|
4494
5934
|
const m = SESSION_FILE_RE.exec(f.name);
|
|
4495
5935
|
if (!m)
|
|
4496
5936
|
continue;
|
|
4497
|
-
candidates.push({ sessionId: m[1], filePath:
|
|
5937
|
+
candidates.push({ sessionId: m[1], filePath: join9(cwdPath, f.name) });
|
|
4498
5938
|
}
|
|
4499
5939
|
}
|
|
4500
5940
|
if (candidates.length === 0)
|
|
@@ -4596,7 +6036,7 @@ var init_pi_projects = __esm(() => {
|
|
|
4596
6036
|
});
|
|
4597
6037
|
|
|
4598
6038
|
// lib/sqlite-reader.ts
|
|
4599
|
-
import { existsSync as
|
|
6039
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
|
|
4600
6040
|
import initSqlJs from "sql.js/dist/sql-asm.js";
|
|
4601
6041
|
async function tryNodeSqlite(dbPath) {
|
|
4602
6042
|
try {
|
|
@@ -4623,7 +6063,7 @@ function loadSqlJs() {
|
|
|
4623
6063
|
async function trySqlJs(dbPath) {
|
|
4624
6064
|
try {
|
|
4625
6065
|
const SQL = await loadSqlJs();
|
|
4626
|
-
const db = new SQL.Database(
|
|
6066
|
+
const db = new SQL.Database(readFileSync4(dbPath));
|
|
4627
6067
|
return {
|
|
4628
6068
|
query(sql, params) {
|
|
4629
6069
|
const stmt = db.prepare(sql);
|
|
@@ -4647,7 +6087,7 @@ async function trySqlJs(dbPath) {
|
|
|
4647
6087
|
}
|
|
4648
6088
|
}
|
|
4649
6089
|
async function openSqliteReadonly(dbPath) {
|
|
4650
|
-
if (!
|
|
6090
|
+
if (!existsSync6(dbPath))
|
|
4651
6091
|
return null;
|
|
4652
6092
|
return await tryNodeSqlite(dbPath) ?? await trySqlJs(dbPath);
|
|
4653
6093
|
}
|
|
@@ -4656,18 +6096,18 @@ var init_sqlite_reader = () => {};
|
|
|
4656
6096
|
|
|
4657
6097
|
// lib/hermes-profiles.ts
|
|
4658
6098
|
import { readdirSync as readdirSync3 } from "node:fs";
|
|
4659
|
-
import { homedir as
|
|
4660
|
-
import { basename as basename2, dirname as dirname3, join as
|
|
6099
|
+
import { homedir as homedir9 } from "node:os";
|
|
6100
|
+
import { basename as basename2, dirname as dirname3, join as join10, resolve as resolve6 } from "node:path";
|
|
4661
6101
|
function hermesRoot() {
|
|
4662
6102
|
const env = (process.env.HERMES_HOME || "").trim();
|
|
4663
6103
|
if (env) {
|
|
4664
|
-
const home =
|
|
6104
|
+
const home = resolve6(env);
|
|
4665
6105
|
const parent = dirname3(home);
|
|
4666
6106
|
if (basename2(parent) === PROFILES_DIR)
|
|
4667
6107
|
return dirname3(parent);
|
|
4668
6108
|
return home;
|
|
4669
6109
|
}
|
|
4670
|
-
return
|
|
6110
|
+
return join10(homedir9(), ".hermes");
|
|
4671
6111
|
}
|
|
4672
6112
|
function listHermesProfiles() {
|
|
4673
6113
|
const root = hermesRoot();
|
|
@@ -4675,7 +6115,7 @@ function listHermesProfiles() {
|
|
|
4675
6115
|
const seen = new Set([HERMES_DEFAULT_PROFILE]);
|
|
4676
6116
|
let names;
|
|
4677
6117
|
try {
|
|
4678
|
-
names = readdirSync3(
|
|
6118
|
+
names = readdirSync3(join10(root, PROFILES_DIR), { withFileTypes: true }).filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
4679
6119
|
} catch {
|
|
4680
6120
|
return out;
|
|
4681
6121
|
}
|
|
@@ -4683,7 +6123,7 @@ function listHermesProfiles() {
|
|
|
4683
6123
|
if (seen.has(name))
|
|
4684
6124
|
continue;
|
|
4685
6125
|
seen.add(name);
|
|
4686
|
-
out.push({ name, home:
|
|
6126
|
+
out.push({ name, home: join10(root, PROFILES_DIR, name) });
|
|
4687
6127
|
}
|
|
4688
6128
|
return out;
|
|
4689
6129
|
}
|
|
@@ -4734,14 +6174,14 @@ function formatDuration(ms) {
|
|
|
4734
6174
|
}
|
|
4735
6175
|
|
|
4736
6176
|
// lib/hermes-sessions.ts
|
|
4737
|
-
import { join as
|
|
6177
|
+
import { join as join11 } from "node:path";
|
|
4738
6178
|
function hermesDbPaths() {
|
|
4739
6179
|
const override = process.env.HERMES_DB_PATH;
|
|
4740
6180
|
if (override)
|
|
4741
6181
|
return [{ profile: HERMES_DEFAULT_PROFILE, dbPath: override }];
|
|
4742
6182
|
return listHermesProfiles().map((p) => ({
|
|
4743
6183
|
profile: p.name,
|
|
4744
|
-
dbPath:
|
|
6184
|
+
dbPath: join11(p.home, "state.db")
|
|
4745
6185
|
}));
|
|
4746
6186
|
}
|
|
4747
6187
|
function epochToMs(value) {
|
|
@@ -5037,12 +6477,12 @@ var init_hermes_projects = __esm(() => {
|
|
|
5037
6477
|
});
|
|
5038
6478
|
|
|
5039
6479
|
// lib/openclaw-sessions.ts
|
|
5040
|
-
import { readFile as
|
|
5041
|
-
import { readdirSync as readdirSync4, statSync as
|
|
5042
|
-
import { homedir as
|
|
5043
|
-
import { join as
|
|
6480
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
6481
|
+
import { readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
|
|
6482
|
+
import { homedir as homedir10 } from "node:os";
|
|
6483
|
+
import { join as join12 } from "node:path";
|
|
5044
6484
|
function openclawHome() {
|
|
5045
|
-
return process.env.OPENCLAW_HOME ||
|
|
6485
|
+
return process.env.OPENCLAW_HOME || join12(homedir10(), ".openclaw");
|
|
5046
6486
|
}
|
|
5047
6487
|
function isPlainObject2(v) {
|
|
5048
6488
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
@@ -5157,13 +6597,13 @@ function openclawLinesToLogEntries(lines, source = "session") {
|
|
|
5157
6597
|
}
|
|
5158
6598
|
function listOpenClawAgents() {
|
|
5159
6599
|
try {
|
|
5160
|
-
return readdirSync4(
|
|
6600
|
+
return readdirSync4(join12(openclawHome(), "agents"), { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name).sort();
|
|
5161
6601
|
} catch {
|
|
5162
6602
|
return [];
|
|
5163
6603
|
}
|
|
5164
6604
|
}
|
|
5165
6605
|
function listOpenClawTranscripts() {
|
|
5166
|
-
const agentsDir =
|
|
6606
|
+
const agentsDir = join12(openclawHome(), "agents");
|
|
5167
6607
|
const out = [];
|
|
5168
6608
|
let agentIds;
|
|
5169
6609
|
try {
|
|
@@ -5172,7 +6612,7 @@ function listOpenClawTranscripts() {
|
|
|
5172
6612
|
return out;
|
|
5173
6613
|
}
|
|
5174
6614
|
for (const agentId of agentIds) {
|
|
5175
|
-
const sessionsDir =
|
|
6615
|
+
const sessionsDir = join12(agentsDir, agentId, "sessions");
|
|
5176
6616
|
let files;
|
|
5177
6617
|
try {
|
|
5178
6618
|
files = readdirSync4(sessionsDir);
|
|
@@ -5185,9 +6625,9 @@ function listOpenClawTranscripts() {
|
|
|
5185
6625
|
const sessionId = file.slice(0, -".jsonl".length);
|
|
5186
6626
|
if (!OPENCLAW_SESSION_ID_RE.test(sessionId))
|
|
5187
6627
|
continue;
|
|
5188
|
-
const transcriptPath =
|
|
6628
|
+
const transcriptPath = join12(sessionsDir, file);
|
|
5189
6629
|
try {
|
|
5190
|
-
const st =
|
|
6630
|
+
const st = statSync6(transcriptPath);
|
|
5191
6631
|
out.push({ agentId, sessionId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
|
|
5192
6632
|
} catch {}
|
|
5193
6633
|
}
|
|
@@ -5209,7 +6649,7 @@ async function getOpenClawSessionLog(sessionId) {
|
|
|
5209
6649
|
return null;
|
|
5210
6650
|
let content;
|
|
5211
6651
|
try {
|
|
5212
|
-
content = await
|
|
6652
|
+
content = await readFile7(filePath, "utf-8");
|
|
5213
6653
|
} catch {
|
|
5214
6654
|
return null;
|
|
5215
6655
|
}
|
|
@@ -5245,17 +6685,17 @@ __export(exports_openclaw_projects, {
|
|
|
5245
6685
|
getCachedOpenClawSessions: () => getCachedOpenClawSessions,
|
|
5246
6686
|
getCachedOpenClawProjects: () => getCachedOpenClawProjects
|
|
5247
6687
|
});
|
|
5248
|
-
import { readFileSync as
|
|
5249
|
-
import { join as
|
|
6688
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
6689
|
+
import { join as join13 } from "node:path";
|
|
5250
6690
|
function str(v) {
|
|
5251
6691
|
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
5252
6692
|
}
|
|
5253
6693
|
function readSessionsIndex(agentId) {
|
|
5254
6694
|
const out = new Map;
|
|
5255
|
-
const indexPath =
|
|
6695
|
+
const indexPath = join13(openclawHome(), "agents", agentId, "sessions", "sessions.json");
|
|
5256
6696
|
let raw;
|
|
5257
6697
|
try {
|
|
5258
|
-
raw = JSON.parse(
|
|
6698
|
+
raw = JSON.parse(readFileSync5(indexPath, "utf-8"));
|
|
5259
6699
|
} catch {
|
|
5260
6700
|
return out;
|
|
5261
6701
|
}
|
|
@@ -5406,15 +6846,15 @@ var init_openclaw_projects = __esm(() => {
|
|
|
5406
6846
|
});
|
|
5407
6847
|
|
|
5408
6848
|
// lib/factory-sessions.ts
|
|
5409
|
-
import { readFile as
|
|
5410
|
-
import { readdirSync as readdirSync5, statSync as
|
|
5411
|
-
import { homedir as
|
|
5412
|
-
import { join as
|
|
6849
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
6850
|
+
import { readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
|
|
6851
|
+
import { homedir as homedir11 } from "node:os";
|
|
6852
|
+
import { join as join14 } from "node:path";
|
|
5413
6853
|
function factoryHome() {
|
|
5414
|
-
return process.env.FACTORY_HOME ||
|
|
6854
|
+
return process.env.FACTORY_HOME || join14(homedir11(), ".factory");
|
|
5415
6855
|
}
|
|
5416
6856
|
function factorySessionsRoot() {
|
|
5417
|
-
return
|
|
6857
|
+
return join14(factoryHome(), "sessions");
|
|
5418
6858
|
}
|
|
5419
6859
|
function isPlainObject3(v) {
|
|
5420
6860
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
@@ -5560,7 +7000,7 @@ function listFactoryTranscripts() {
|
|
|
5560
7000
|
for (const dir of projectDirs) {
|
|
5561
7001
|
const projectName = dir.name;
|
|
5562
7002
|
const cwd = decodeFolderName(projectName);
|
|
5563
|
-
const projectPath =
|
|
7003
|
+
const projectPath = join14(root, projectName);
|
|
5564
7004
|
let files;
|
|
5565
7005
|
try {
|
|
5566
7006
|
files = readdirSync5(projectPath);
|
|
@@ -5573,9 +7013,9 @@ function listFactoryTranscripts() {
|
|
|
5573
7013
|
const sessionId = file.slice(0, -".jsonl".length);
|
|
5574
7014
|
if (!FACTORY_SESSION_ID_RE.test(sessionId))
|
|
5575
7015
|
continue;
|
|
5576
|
-
const transcriptPath =
|
|
7016
|
+
const transcriptPath = join14(projectPath, file);
|
|
5577
7017
|
try {
|
|
5578
|
-
const st =
|
|
7018
|
+
const st = statSync7(transcriptPath);
|
|
5579
7019
|
out.push({ projectName, cwd, sessionId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
|
|
5580
7020
|
} catch {}
|
|
5581
7021
|
}
|
|
@@ -5597,7 +7037,7 @@ async function getFactorySessionLog(sessionId) {
|
|
|
5597
7037
|
return null;
|
|
5598
7038
|
let content;
|
|
5599
7039
|
try {
|
|
5600
|
-
content = await
|
|
7040
|
+
content = await readFile8(filePath, "utf-8");
|
|
5601
7041
|
} catch {
|
|
5602
7042
|
return null;
|
|
5603
7043
|
}
|
|
@@ -5699,13 +7139,13 @@ var init_factory_projects = __esm(() => {
|
|
|
5699
7139
|
});
|
|
5700
7140
|
|
|
5701
7141
|
// lib/devin-sessions.ts
|
|
5702
|
-
import { homedir as
|
|
5703
|
-
import { join as
|
|
7142
|
+
import { homedir as homedir12 } from "node:os";
|
|
7143
|
+
import { join as join15 } from "node:path";
|
|
5704
7144
|
function devinHome() {
|
|
5705
|
-
return process.env.DEVIN_HOME ||
|
|
7145
|
+
return process.env.DEVIN_HOME || join15(homedir12(), ".local", "share", "devin");
|
|
5706
7146
|
}
|
|
5707
7147
|
function devinDbPath() {
|
|
5708
|
-
return process.env.DEVIN_DB_PATH ||
|
|
7148
|
+
return process.env.DEVIN_DB_PATH || join15(devinHome(), "cli", "sessions.db");
|
|
5709
7149
|
}
|
|
5710
7150
|
function devinEpochToMs(value) {
|
|
5711
7151
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -6001,18 +7441,18 @@ var init_devin_projects = __esm(() => {
|
|
|
6001
7441
|
});
|
|
6002
7442
|
|
|
6003
7443
|
// lib/antigravity-sessions.ts
|
|
6004
|
-
import { readFile as
|
|
6005
|
-
import { readdirSync as readdirSync6, statSync as
|
|
6006
|
-
import { homedir as
|
|
6007
|
-
import { join as
|
|
7444
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
7445
|
+
import { readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
7446
|
+
import { homedir as homedir13 } from "node:os";
|
|
7447
|
+
import { join as join16 } from "node:path";
|
|
6008
7448
|
function antigravityHome() {
|
|
6009
|
-
return process.env.ANTIGRAVITY_HOME ||
|
|
7449
|
+
return process.env.ANTIGRAVITY_HOME || join16(homedir13(), ".gemini", "antigravity-cli");
|
|
6010
7450
|
}
|
|
6011
7451
|
function antigravityBrainRoot() {
|
|
6012
|
-
return
|
|
7452
|
+
return join16(antigravityHome(), "brain");
|
|
6013
7453
|
}
|
|
6014
7454
|
function antigravityTranscriptRelPath() {
|
|
6015
|
-
return
|
|
7455
|
+
return join16(".system_generated", "logs", "transcript_full.jsonl");
|
|
6016
7456
|
}
|
|
6017
7457
|
function isPlainObject5(v) {
|
|
6018
7458
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
@@ -6135,9 +7575,9 @@ function listAntigravityTranscripts() {
|
|
|
6135
7575
|
const conversationId = dir.name;
|
|
6136
7576
|
if (!ANTIGRAVITY_CONVERSATION_ID_RE.test(conversationId))
|
|
6137
7577
|
continue;
|
|
6138
|
-
const transcriptPath =
|
|
7578
|
+
const transcriptPath = join16(root, conversationId, rel);
|
|
6139
7579
|
try {
|
|
6140
|
-
const st =
|
|
7580
|
+
const st = statSync8(transcriptPath);
|
|
6141
7581
|
if (!st.isFile())
|
|
6142
7582
|
continue;
|
|
6143
7583
|
out.push({ conversationId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
|
|
@@ -6148,9 +7588,9 @@ function listAntigravityTranscripts() {
|
|
|
6148
7588
|
function findAntigravityTranscript(conversationId) {
|
|
6149
7589
|
if (!ANTIGRAVITY_CONVERSATION_ID_RE.test(conversationId))
|
|
6150
7590
|
return null;
|
|
6151
|
-
const transcriptPath =
|
|
7591
|
+
const transcriptPath = join16(antigravityBrainRoot(), conversationId, antigravityTranscriptRelPath());
|
|
6152
7592
|
try {
|
|
6153
|
-
if (
|
|
7593
|
+
if (statSync8(transcriptPath).isFile())
|
|
6154
7594
|
return transcriptPath;
|
|
6155
7595
|
} catch {}
|
|
6156
7596
|
return null;
|
|
@@ -6161,7 +7601,7 @@ async function getAntigravitySessionLog(conversationId) {
|
|
|
6161
7601
|
return null;
|
|
6162
7602
|
let content;
|
|
6163
7603
|
try {
|
|
6164
|
-
content = await
|
|
7604
|
+
content = await readFile9(filePath, "utf-8");
|
|
6165
7605
|
} catch {
|
|
6166
7606
|
return null;
|
|
6167
7607
|
}
|
|
@@ -6188,9 +7628,9 @@ __export(exports_antigravity_projects, {
|
|
|
6188
7628
|
getAntigravityIndex: () => getAntigravityIndex,
|
|
6189
7629
|
antigravitySummariesDbPath: () => antigravitySummariesDbPath
|
|
6190
7630
|
});
|
|
6191
|
-
import { join as
|
|
7631
|
+
import { join as join17 } from "node:path";
|
|
6192
7632
|
function antigravitySummariesDbPath() {
|
|
6193
|
-
return
|
|
7633
|
+
return join17(antigravityHome(), "conversation_summaries.db");
|
|
6194
7634
|
}
|
|
6195
7635
|
function parseWorkspaceCwd(raw) {
|
|
6196
7636
|
if (!raw)
|
|
@@ -6333,16 +7773,16 @@ var init_antigravity_projects = __esm(() => {
|
|
|
6333
7773
|
});
|
|
6334
7774
|
|
|
6335
7775
|
// lib/goose-sessions.ts
|
|
6336
|
-
import { homedir as
|
|
6337
|
-
import { join as
|
|
7776
|
+
import { homedir as homedir14 } from "node:os";
|
|
7777
|
+
import { join as join18 } from "node:path";
|
|
6338
7778
|
function gooseHome() {
|
|
6339
7779
|
if (process.env.GOOSE_HOME)
|
|
6340
7780
|
return process.env.GOOSE_HOME;
|
|
6341
7781
|
const xdg = process.env.XDG_DATA_HOME;
|
|
6342
|
-
return
|
|
7782
|
+
return join18(xdg && xdg.length > 0 ? xdg : join18(homedir14(), ".local", "share"), "goose");
|
|
6343
7783
|
}
|
|
6344
7784
|
function gooseDbPath() {
|
|
6345
|
-
return process.env.GOOSE_DB_PATH ||
|
|
7785
|
+
return process.env.GOOSE_DB_PATH || join18(gooseHome(), "sessions", "sessions.db");
|
|
6346
7786
|
}
|
|
6347
7787
|
function gooseTimestampToMs(value) {
|
|
6348
7788
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -6610,7 +8050,7 @@ var init_goose_projects = __esm(() => {
|
|
|
6610
8050
|
|
|
6611
8051
|
// lib/projects.ts
|
|
6612
8052
|
import { readdir as readdir5, stat as stat5 } from "node:fs/promises";
|
|
6613
|
-
import { join as
|
|
8053
|
+
import { join as join19, resolve as resolve7, sep } from "node:path";
|
|
6614
8054
|
async function getMtime(path2, label) {
|
|
6615
8055
|
try {
|
|
6616
8056
|
return (await stat5(path2)).mtime;
|
|
@@ -6636,7 +8076,7 @@ async function getClaudeProjectFolders() {
|
|
|
6636
8076
|
if (!entries)
|
|
6637
8077
|
return [];
|
|
6638
8078
|
const settled = await batchAll(entries.filter((entry) => entry.isDirectory()).map((entry) => async () => {
|
|
6639
|
-
const folderPath =
|
|
8079
|
+
const folderPath = join19(projectsPath, entry.name);
|
|
6640
8080
|
const mtime = await getMtime(folderPath, entry.name);
|
|
6641
8081
|
return {
|
|
6642
8082
|
name: entry.name,
|
|
@@ -6762,8 +8202,8 @@ function resolveProjectPath(projectName) {
|
|
|
6762
8202
|
throw new RangeError("Empty project name");
|
|
6763
8203
|
if (/^[/\\]/.test(projectName))
|
|
6764
8204
|
throw new RangeError("Absolute project name");
|
|
6765
|
-
const projectsPath =
|
|
6766
|
-
const candidate =
|
|
8205
|
+
const projectsPath = resolve7(getClaudeProjectsPath());
|
|
8206
|
+
const candidate = resolve7(join19(projectsPath, projectName));
|
|
6767
8207
|
if (!candidate.startsWith(projectsPath + sep)) {
|
|
6768
8208
|
throw new RangeError("Project path escapes root");
|
|
6769
8209
|
}
|
|
@@ -6781,7 +8221,7 @@ async function getSessionFiles(projectPath) {
|
|
|
6781
8221
|
return [];
|
|
6782
8222
|
const jsonlEntries = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl") && extractSessionId2(entry.name));
|
|
6783
8223
|
const settled = await batchAll(jsonlEntries.map((entry) => async () => {
|
|
6784
|
-
const filePath =
|
|
8224
|
+
const filePath = join19(projectPath, entry.name);
|
|
6785
8225
|
const mtime = await getMtime(filePath, entry.name);
|
|
6786
8226
|
return {
|
|
6787
8227
|
name: entry.name,
|
|
@@ -6810,13 +8250,13 @@ var init_projects = __esm(() => {
|
|
|
6810
8250
|
|
|
6811
8251
|
// lib/resolve-subagent-path.ts
|
|
6812
8252
|
import { access as access2 } from "fs/promises";
|
|
6813
|
-
import { join as
|
|
8253
|
+
import { join as join20, relative as relative2 } from "path";
|
|
6814
8254
|
async function resolveSubagentPath(projectsPath, projectName, sessionId, agentId) {
|
|
6815
8255
|
const fileName = `agent-${agentId}.jsonl`;
|
|
6816
8256
|
const candidatePaths = [
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
8257
|
+
join20(projectsPath, projectName, fileName),
|
|
8258
|
+
join20(projectsPath, projectName, sessionId, fileName),
|
|
8259
|
+
join20(projectsPath, projectName, sessionId, "subagents", fileName)
|
|
6820
8260
|
];
|
|
6821
8261
|
for (const candidatePath of candidatePaths) {
|
|
6822
8262
|
if (relative2(projectsPath, candidatePath).startsWith("..")) {
|
|
@@ -6837,8 +8277,8 @@ async function resolveSubagentPath(projectsPath, projectName, sessionId, agentId
|
|
|
6837
8277
|
var init_resolve_subagent_path = () => {};
|
|
6838
8278
|
|
|
6839
8279
|
// lib/log-entries.ts
|
|
6840
|
-
import { readFile as
|
|
6841
|
-
import { join as
|
|
8280
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
8281
|
+
import { join as join21 } from "path";
|
|
6842
8282
|
function formatTimestamp(date) {
|
|
6843
8283
|
const base = formatDate(date);
|
|
6844
8284
|
const ms = date.getMilliseconds().toString().padStart(3, "0");
|
|
@@ -7032,8 +8472,8 @@ async function parseFileContent(fileContent, source) {
|
|
|
7032
8472
|
async function parseSessionLog(projectName, sessionId) {
|
|
7033
8473
|
const projectDir = resolveProjectPath(projectName);
|
|
7034
8474
|
const projectsPath = getClaudeProjectsPath();
|
|
7035
|
-
const filePath =
|
|
7036
|
-
const fileContent = await
|
|
8475
|
+
const filePath = join21(projectDir, `${sessionId}.jsonl`);
|
|
8476
|
+
const fileContent = await readFile10(filePath, "utf-8");
|
|
7037
8477
|
const { entries: sessionEntries, rawLines: sessionRawLines, subagentIds } = await parseFileContent(fileContent, "session");
|
|
7038
8478
|
if (subagentIds.length === 0) {
|
|
7039
8479
|
return { entries: sessionEntries, rawLines: sessionRawLines, subagentIds: [] };
|
|
@@ -7043,7 +8483,7 @@ async function parseSessionLog(projectName, sessionId) {
|
|
|
7043
8483
|
const agentPath = await resolveSubagentPath(projectsPath, projectName, sessionId, agentId);
|
|
7044
8484
|
if (!agentPath)
|
|
7045
8485
|
return null;
|
|
7046
|
-
const agentContent = await
|
|
8486
|
+
const agentContent = await readFile10(agentPath, "utf-8");
|
|
7047
8487
|
const { entries, rawLines } = await parseFileContent(agentContent, agentSource);
|
|
7048
8488
|
return { entries, rawLines };
|
|
7049
8489
|
}), SUBAGENT_CONCURRENCY);
|
|
@@ -7069,32 +8509,32 @@ var init_log_entries = __esm(() => {
|
|
|
7069
8509
|
});
|
|
7070
8510
|
|
|
7071
8511
|
// lib/codex-sessions.ts
|
|
7072
|
-
import { readFileSync as
|
|
7073
|
-
import { readFile as
|
|
7074
|
-
import { dirname as dirname4, join as
|
|
7075
|
-
import { homedir as
|
|
8512
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync7, existsSync as existsSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, statSync as statSync9 } from "node:fs";
|
|
8513
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
8514
|
+
import { dirname as dirname4, join as join22 } from "node:path";
|
|
8515
|
+
import { homedir as homedir15 } from "node:os";
|
|
7076
8516
|
function readCache() {
|
|
7077
8517
|
try {
|
|
7078
|
-
if (!
|
|
8518
|
+
if (!existsSync7(CACHE_PATH))
|
|
7079
8519
|
return {};
|
|
7080
|
-
return JSON.parse(
|
|
8520
|
+
return JSON.parse(readFileSync6(CACHE_PATH, "utf-8"));
|
|
7081
8521
|
} catch {
|
|
7082
8522
|
return {};
|
|
7083
8523
|
}
|
|
7084
8524
|
}
|
|
7085
8525
|
function writeCacheEntry(sessionId, path2) {
|
|
7086
8526
|
try {
|
|
7087
|
-
|
|
8527
|
+
mkdirSync5(dirname4(CACHE_PATH), { recursive: true });
|
|
7088
8528
|
const cache = readCache();
|
|
7089
8529
|
cache[sessionId] = path2;
|
|
7090
|
-
|
|
8530
|
+
writeFileSync4(CACHE_PATH, JSON.stringify(cache), "utf-8");
|
|
7091
8531
|
} catch {}
|
|
7092
8532
|
}
|
|
7093
8533
|
function dirSearch(dir, sessionId) {
|
|
7094
8534
|
try {
|
|
7095
8535
|
for (const f of readdirSync7(dir, { withFileTypes: true })) {
|
|
7096
8536
|
if (f.isFile() && f.name.includes(sessionId) && f.name.endsWith(".jsonl")) {
|
|
7097
|
-
return
|
|
8537
|
+
return join22(dir, f.name);
|
|
7098
8538
|
}
|
|
7099
8539
|
}
|
|
7100
8540
|
} catch {}
|
|
@@ -7103,16 +8543,16 @@ function dirSearch(dir, sessionId) {
|
|
|
7103
8543
|
function findCodexTranscript(sessionId) {
|
|
7104
8544
|
const cache = readCache();
|
|
7105
8545
|
const cached = cache[sessionId];
|
|
7106
|
-
if (cached &&
|
|
8546
|
+
if (cached && existsSync7(cached))
|
|
7107
8547
|
return cached;
|
|
7108
|
-
const root =
|
|
8548
|
+
const root = join22(homedir15(), ".codex", "sessions");
|
|
7109
8549
|
const today = new Date;
|
|
7110
8550
|
const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
|
|
7111
8551
|
const datedDirs = [today, yesterday].map((d) => {
|
|
7112
8552
|
const y = String(d.getUTCFullYear());
|
|
7113
8553
|
const m = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
7114
8554
|
const day = String(d.getUTCDate()).padStart(2, "0");
|
|
7115
|
-
return
|
|
8555
|
+
return join22(root, y, m, day);
|
|
7116
8556
|
});
|
|
7117
8557
|
for (const dir of datedDirs) {
|
|
7118
8558
|
const hit = dirSearch(dir, sessionId);
|
|
@@ -7125,13 +8565,13 @@ function findCodexTranscript(sessionId) {
|
|
|
7125
8565
|
for (const y of readdirSync7(root, { withFileTypes: true })) {
|
|
7126
8566
|
if (!y.isDirectory())
|
|
7127
8567
|
continue;
|
|
7128
|
-
for (const m of readdirSync7(
|
|
8568
|
+
for (const m of readdirSync7(join22(root, y.name), { withFileTypes: true })) {
|
|
7129
8569
|
if (!m.isDirectory())
|
|
7130
8570
|
continue;
|
|
7131
|
-
for (const d of readdirSync7(
|
|
8571
|
+
for (const d of readdirSync7(join22(root, y.name, m.name), { withFileTypes: true })) {
|
|
7132
8572
|
if (!d.isDirectory())
|
|
7133
8573
|
continue;
|
|
7134
|
-
const hit = dirSearch(
|
|
8574
|
+
const hit = dirSearch(join22(root, y.name, m.name, d.name), sessionId);
|
|
7135
8575
|
if (hit) {
|
|
7136
8576
|
writeCacheEntry(sessionId, hit);
|
|
7137
8577
|
return hit;
|
|
@@ -7344,19 +8784,20 @@ async function getCodexSessionLog(sessionId) {
|
|
|
7344
8784
|
const filePath = findCodexTranscript(sessionId);
|
|
7345
8785
|
if (!filePath)
|
|
7346
8786
|
return null;
|
|
7347
|
-
const fileContent = await
|
|
8787
|
+
const fileContent = await readFile11(filePath, "utf-8");
|
|
7348
8788
|
const { entries, rawLines, cwd } = await parseCodexLog(fileContent, "session");
|
|
7349
8789
|
return { entries, rawLines, cwd, filePath };
|
|
7350
8790
|
}
|
|
7351
8791
|
var CACHE_PATH, getCachedCodexSessionLog;
|
|
7352
8792
|
var init_codex_sessions = __esm(() => {
|
|
7353
8793
|
init_log_entries();
|
|
7354
|
-
|
|
8794
|
+
init_fp_home();
|
|
8795
|
+
CACHE_PATH = codexSessionPathsFile();
|
|
7355
8796
|
getCachedCodexSessionLog = runtimeCache((sessionId) => getCodexSessionLog(sessionId), 60, { maxSize: 50 });
|
|
7356
8797
|
});
|
|
7357
8798
|
|
|
7358
8799
|
// src/hooks/resolve-permission-mode.ts
|
|
7359
|
-
import { readFileSync as
|
|
8800
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
7360
8801
|
function resolvePermissionMode(integration, parsed, sessionId) {
|
|
7361
8802
|
if (integration === "claude") {
|
|
7362
8803
|
return parsed.permission_mode ?? "default";
|
|
@@ -7371,7 +8812,7 @@ function resolveCodexMode(sessionId) {
|
|
|
7371
8812
|
const path2 = findCodexTranscript(sessionId);
|
|
7372
8813
|
if (!path2)
|
|
7373
8814
|
return;
|
|
7374
|
-
for (const line of
|
|
8815
|
+
for (const line of readFileSync7(path2, "utf-8").split(`
|
|
7375
8816
|
`)) {
|
|
7376
8817
|
if (!line.includes("turn_context"))
|
|
7377
8818
|
continue;
|
|
@@ -7396,21 +8837,21 @@ var init_resolve_permission_mode = __esm(() => {
|
|
|
7396
8837
|
});
|
|
7397
8838
|
|
|
7398
8839
|
// lib/copilot-sessions.ts
|
|
7399
|
-
import { readFileSync as
|
|
7400
|
-
import { readFile as
|
|
7401
|
-
import { join as
|
|
7402
|
-
import { homedir as
|
|
8840
|
+
import { readFileSync as readFileSync8, readdirSync as readdirSync8, existsSync as existsSync8, statSync as statSync10 } from "node:fs";
|
|
8841
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
8842
|
+
import { join as join23, resolve as resolve8, sep as sep2 } from "node:path";
|
|
8843
|
+
import { homedir as homedir16 } from "node:os";
|
|
7403
8844
|
function getCopilotHome() {
|
|
7404
|
-
return process.env.COPILOT_HOME ||
|
|
8845
|
+
return process.env.COPILOT_HOME || join23(homedir16(), ".copilot");
|
|
7405
8846
|
}
|
|
7406
8847
|
function getCopilotSessionStateRoot2() {
|
|
7407
|
-
return
|
|
8848
|
+
return join23(getCopilotHome(), "session-state");
|
|
7408
8849
|
}
|
|
7409
8850
|
function getCopilotSessionDir(sessionId) {
|
|
7410
8851
|
if (!sessionId)
|
|
7411
8852
|
return null;
|
|
7412
|
-
const root =
|
|
7413
|
-
const candidate =
|
|
8853
|
+
const root = resolve8(getCopilotSessionStateRoot2());
|
|
8854
|
+
const candidate = resolve8(root, sessionId);
|
|
7414
8855
|
if (candidate === root || !candidate.startsWith(`${root}${sep2}`))
|
|
7415
8856
|
return null;
|
|
7416
8857
|
return candidate;
|
|
@@ -7419,23 +8860,23 @@ function resolveSessionFile(sessionId, filename) {
|
|
|
7419
8860
|
const dir = getCopilotSessionDir(sessionId);
|
|
7420
8861
|
if (!dir)
|
|
7421
8862
|
return null;
|
|
7422
|
-
return
|
|
8863
|
+
return join23(dir, filename);
|
|
7423
8864
|
}
|
|
7424
8865
|
function findCopilotTranscript(sessionId) {
|
|
7425
8866
|
const candidate = resolveSessionFile(sessionId, "events.jsonl");
|
|
7426
8867
|
if (!candidate)
|
|
7427
8868
|
return null;
|
|
7428
|
-
return
|
|
8869
|
+
return existsSync8(candidate) ? candidate : null;
|
|
7429
8870
|
}
|
|
7430
8871
|
function findCopilotWorkspace(sessionId) {
|
|
7431
8872
|
const candidate = resolveSessionFile(sessionId, "workspace.yaml");
|
|
7432
8873
|
if (!candidate)
|
|
7433
8874
|
return null;
|
|
7434
|
-
return
|
|
8875
|
+
return existsSync8(candidate) ? candidate : null;
|
|
7435
8876
|
}
|
|
7436
8877
|
function readYamlScalar(path2, key) {
|
|
7437
8878
|
try {
|
|
7438
|
-
const text =
|
|
8879
|
+
const text = readFileSync8(path2, "utf-8");
|
|
7439
8880
|
const re = new RegExp(`^${key}\\s*:\\s*(.+?)\\s*$`, "m");
|
|
7440
8881
|
const m = text.match(re);
|
|
7441
8882
|
if (!m)
|
|
@@ -7598,7 +9039,7 @@ async function getCopilotSessionLog(sessionId) {
|
|
|
7598
9039
|
return null;
|
|
7599
9040
|
let fileContent;
|
|
7600
9041
|
try {
|
|
7601
|
-
fileContent = await
|
|
9042
|
+
fileContent = await readFile12(filePath, "utf-8");
|
|
7602
9043
|
} catch {
|
|
7603
9044
|
return null;
|
|
7604
9045
|
}
|
|
@@ -7613,18 +9054,18 @@ var init_copilot_sessions = __esm(() => {
|
|
|
7613
9054
|
});
|
|
7614
9055
|
|
|
7615
9056
|
// lib/cursor-sessions.ts
|
|
7616
|
-
import { readFileSync as
|
|
7617
|
-
import { readFile as
|
|
7618
|
-
import { basename as basename3, join as
|
|
7619
|
-
import { homedir as
|
|
9057
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync9, existsSync as existsSync9, statSync as statSync11 } from "node:fs";
|
|
9058
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
9059
|
+
import { basename as basename3, join as join24, resolve as resolve9, sep as sep3 } from "node:path";
|
|
9060
|
+
import { homedir as homedir17 } from "node:os";
|
|
7620
9061
|
function getCursorHome2() {
|
|
7621
|
-
return process.env.CURSOR_HOME ||
|
|
9062
|
+
return process.env.CURSOR_HOME || join24(homedir17(), ".cursor");
|
|
7622
9063
|
}
|
|
7623
9064
|
function getCursorSessionDir(sessionId) {
|
|
7624
9065
|
if (!sessionId)
|
|
7625
9066
|
return null;
|
|
7626
|
-
const home =
|
|
7627
|
-
const projectsRoot =
|
|
9067
|
+
const home = resolve9(getCursorHome2());
|
|
9068
|
+
const projectsRoot = resolve9(home, NEW_PROJECTS_DIR2);
|
|
7628
9069
|
let projectEntries = [];
|
|
7629
9070
|
try {
|
|
7630
9071
|
projectEntries = readdirSync9(projectsRoot, { withFileTypes: true });
|
|
@@ -7632,19 +9073,19 @@ function getCursorSessionDir(sessionId) {
|
|
|
7632
9073
|
for (const entry of projectEntries) {
|
|
7633
9074
|
if (!entry.isDirectory())
|
|
7634
9075
|
continue;
|
|
7635
|
-
const candidate =
|
|
7636
|
-
const transcriptRoot =
|
|
9076
|
+
const candidate = resolve9(projectsRoot, entry.name, NEW_AGENT_TRANSCRIPTS_DIR2, sessionId);
|
|
9077
|
+
const transcriptRoot = resolve9(projectsRoot, entry.name, NEW_AGENT_TRANSCRIPTS_DIR2);
|
|
7637
9078
|
if (candidate === transcriptRoot || !candidate.startsWith(`${transcriptRoot}${sep3}`))
|
|
7638
9079
|
continue;
|
|
7639
|
-
if (
|
|
9080
|
+
if (existsSync9(candidate))
|
|
7640
9081
|
return candidate;
|
|
7641
9082
|
}
|
|
7642
9083
|
for (const sub of LEGACY_SESSION_ROOT_CANDIDATES2) {
|
|
7643
|
-
const root =
|
|
7644
|
-
const candidate =
|
|
9084
|
+
const root = resolve9(home, sub);
|
|
9085
|
+
const candidate = resolve9(root, sessionId);
|
|
7645
9086
|
if (candidate === root || !candidate.startsWith(`${root}${sep3}`))
|
|
7646
9087
|
continue;
|
|
7647
|
-
if (
|
|
9088
|
+
if (existsSync9(candidate))
|
|
7648
9089
|
return candidate;
|
|
7649
9090
|
}
|
|
7650
9091
|
return null;
|
|
@@ -7653,12 +9094,12 @@ function findCursorTranscript(sessionId) {
|
|
|
7653
9094
|
const dir = getCursorSessionDir(sessionId);
|
|
7654
9095
|
if (!dir)
|
|
7655
9096
|
return null;
|
|
7656
|
-
const newCandidate =
|
|
7657
|
-
if (
|
|
9097
|
+
const newCandidate = join24(dir, `${basename3(dir)}.jsonl`);
|
|
9098
|
+
if (existsSync9(newCandidate))
|
|
7658
9099
|
return newCandidate;
|
|
7659
9100
|
for (const name of LEGACY_TRANSCRIPT_FILE_CANDIDATES2) {
|
|
7660
|
-
const candidate =
|
|
7661
|
-
if (
|
|
9101
|
+
const candidate = join24(dir, name);
|
|
9102
|
+
if (existsSync9(candidate))
|
|
7662
9103
|
return candidate;
|
|
7663
9104
|
}
|
|
7664
9105
|
return null;
|
|
@@ -7853,7 +9294,7 @@ async function getCursorSessionLog(sessionId) {
|
|
|
7853
9294
|
return null;
|
|
7854
9295
|
let fileContent;
|
|
7855
9296
|
try {
|
|
7856
|
-
fileContent = await
|
|
9297
|
+
fileContent = await readFile13(filePath, "utf-8");
|
|
7857
9298
|
} catch {
|
|
7858
9299
|
return null;
|
|
7859
9300
|
}
|
|
@@ -7869,12 +9310,12 @@ var init_cursor_sessions = __esm(() => {
|
|
|
7869
9310
|
});
|
|
7870
9311
|
|
|
7871
9312
|
// lib/pi-sessions.ts
|
|
7872
|
-
import { readFileSync as
|
|
7873
|
-
import { readFile as
|
|
7874
|
-
import { join as
|
|
7875
|
-
import { homedir as
|
|
9313
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync10, existsSync as existsSync10, statSync as statSync12 } from "node:fs";
|
|
9314
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
9315
|
+
import { join as join25, resolve as resolve10, sep as sep4 } from "node:path";
|
|
9316
|
+
import { homedir as homedir18 } from "node:os";
|
|
7876
9317
|
function getPiSessionStateRoot() {
|
|
7877
|
-
return process.env.PI_SESSIONS_DIR ||
|
|
9318
|
+
return process.env.PI_SESSIONS_DIR || join25(homedir18(), ".pi", "agent", "sessions");
|
|
7878
9319
|
}
|
|
7879
9320
|
function isSafeSessionId(sessionId) {
|
|
7880
9321
|
return UUID_RE.test(sessionId);
|
|
@@ -7882,7 +9323,7 @@ function isSafeSessionId(sessionId) {
|
|
|
7882
9323
|
function findPiTranscript(sessionId) {
|
|
7883
9324
|
if (!isSafeSessionId(sessionId))
|
|
7884
9325
|
return null;
|
|
7885
|
-
const root =
|
|
9326
|
+
const root = resolve10(getPiSessionStateRoot());
|
|
7886
9327
|
let cwdDirs;
|
|
7887
9328
|
try {
|
|
7888
9329
|
cwdDirs = readdirSync10(root);
|
|
@@ -7890,7 +9331,7 @@ function findPiTranscript(sessionId) {
|
|
|
7890
9331
|
return null;
|
|
7891
9332
|
}
|
|
7892
9333
|
for (const cwdDir of cwdDirs) {
|
|
7893
|
-
const cwdPath =
|
|
9334
|
+
const cwdPath = resolve10(root, cwdDir);
|
|
7894
9335
|
if (!cwdPath.startsWith(`${root}${sep4}`))
|
|
7895
9336
|
continue;
|
|
7896
9337
|
let files;
|
|
@@ -7903,10 +9344,10 @@ function findPiTranscript(sessionId) {
|
|
|
7903
9344
|
const m = SESSION_FILE_RE2.exec(f);
|
|
7904
9345
|
if (!m || m[1].toLowerCase() !== sessionId.toLowerCase())
|
|
7905
9346
|
continue;
|
|
7906
|
-
const candidate =
|
|
9347
|
+
const candidate = resolve10(cwdPath, f);
|
|
7907
9348
|
if (!candidate.startsWith(`${cwdPath}${sep4}`))
|
|
7908
9349
|
continue;
|
|
7909
|
-
if (
|
|
9350
|
+
if (existsSync10(candidate))
|
|
7910
9351
|
return candidate;
|
|
7911
9352
|
}
|
|
7912
9353
|
}
|
|
@@ -7924,7 +9365,7 @@ function extractMessageText(content) {
|
|
|
7924
9365
|
|
|
7925
9366
|
`);
|
|
7926
9367
|
}
|
|
7927
|
-
function buildAssistantContent(content) {
|
|
9368
|
+
function buildAssistantContent(content, onToolUse) {
|
|
7928
9369
|
if (!Array.isArray(content))
|
|
7929
9370
|
return [];
|
|
7930
9371
|
const blocks = [];
|
|
@@ -7935,6 +9376,14 @@ function buildAssistantContent(content) {
|
|
|
7935
9376
|
if (block?.type === "thinking" && typeof block.thinking === "string" && block.thinking.length > 0) {
|
|
7936
9377
|
blocks.push({ type: "text", text: `[thinking] ${block.thinking}` });
|
|
7937
9378
|
}
|
|
9379
|
+
if (block?.type === "toolCall") {
|
|
9380
|
+
const id = typeof block.id === "string" && block.id.length > 0 ? block.id : `${typeof block.name === "string" ? block.name : "tool"}-${blocks.length}`;
|
|
9381
|
+
const name = typeof block.name === "string" ? block.name : "tool";
|
|
9382
|
+
const input = block.arguments && typeof block.arguments === "object" && !Array.isArray(block.arguments) ? block.arguments : {};
|
|
9383
|
+
const toolUse = { type: "tool_use", id, name, input };
|
|
9384
|
+
blocks.push(toolUse);
|
|
9385
|
+
onToolUse?.(toolUse);
|
|
9386
|
+
}
|
|
7938
9387
|
}
|
|
7939
9388
|
return blocks;
|
|
7940
9389
|
}
|
|
@@ -7945,6 +9394,8 @@ async function parsePiLog(fileContent, source = "session") {
|
|
|
7945
9394
|
const rawLines = [];
|
|
7946
9395
|
let cwd;
|
|
7947
9396
|
let seenSessionStart = false;
|
|
9397
|
+
const toolUseById = new Map;
|
|
9398
|
+
const toolUseStartMs = new Map;
|
|
7948
9399
|
for (let i = 0;i < lines.length; i++) {
|
|
7949
9400
|
if (i > 0 && i % 200 === 0)
|
|
7950
9401
|
await new Promise((r) => setImmediate(r));
|
|
@@ -7992,7 +9443,10 @@ async function parsePiLog(fileContent, source = "session") {
|
|
|
7992
9443
|
continue;
|
|
7993
9444
|
}
|
|
7994
9445
|
if (role === "assistant") {
|
|
7995
|
-
const blocks = buildAssistantContent(content)
|
|
9446
|
+
const blocks = buildAssistantContent(content, (block) => {
|
|
9447
|
+
toolUseById.set(block.id, block);
|
|
9448
|
+
toolUseStartMs.set(block.id, date.getTime());
|
|
9449
|
+
});
|
|
7996
9450
|
if (blocks.length === 0) {
|
|
7997
9451
|
entries.push({
|
|
7998
9452
|
type: "system",
|
|
@@ -8008,6 +9462,22 @@ async function parsePiLog(fileContent, source = "session") {
|
|
|
8008
9462
|
});
|
|
8009
9463
|
continue;
|
|
8010
9464
|
}
|
|
9465
|
+
if (role === "toolResult") {
|
|
9466
|
+
const callId = raw.message.toolCallId;
|
|
9467
|
+
const block = typeof callId === "string" ? toolUseById.get(callId) : undefined;
|
|
9468
|
+
if (block) {
|
|
9469
|
+
const startMs = typeof callId === "string" && toolUseStartMs.get(callId) || date.getTime();
|
|
9470
|
+
const durationMs = Math.max(0, date.getTime() - startMs);
|
|
9471
|
+
block.result = {
|
|
9472
|
+
timestamp,
|
|
9473
|
+
timestampFormatted: formatTimestamp(date),
|
|
9474
|
+
content: extractMessageText(content),
|
|
9475
|
+
durationMs,
|
|
9476
|
+
durationFormatted: formatDuration(durationMs)
|
|
9477
|
+
};
|
|
9478
|
+
continue;
|
|
9479
|
+
}
|
|
9480
|
+
}
|
|
8011
9481
|
entries.push({
|
|
8012
9482
|
type: "system",
|
|
8013
9483
|
...baseEntry(rawCopy, timestamp, date, source),
|
|
@@ -8032,7 +9502,7 @@ async function getPiSessionLog(sessionId) {
|
|
|
8032
9502
|
return null;
|
|
8033
9503
|
let fileContent;
|
|
8034
9504
|
try {
|
|
8035
|
-
fileContent = await
|
|
9505
|
+
fileContent = await readFile14(filePath, "utf-8");
|
|
8036
9506
|
} catch {
|
|
8037
9507
|
return null;
|
|
8038
9508
|
}
|
|
@@ -8101,6 +9571,192 @@ var init_resolve_transcript_path = __esm(() => {
|
|
|
8101
9571
|
init_factory_sessions();
|
|
8102
9572
|
init_antigravity_sessions();
|
|
8103
9573
|
});
|
|
9574
|
+
// src/hooks/cloud-managed-policies.ts
|
|
9575
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
9576
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, realpathSync, rmSync } from "node:fs";
|
|
9577
|
+
import { isAbsolute as isAbsolute2, relative as relative3, resolve as resolve11 } from "node:path";
|
|
9578
|
+
function cloudManagedPolicyRoot() {
|
|
9579
|
+
return process.env.FAILPROOFAI_CLOUD_POLICY_DIR ?? cloudPoliciesDir();
|
|
9580
|
+
}
|
|
9581
|
+
function parseManifest(value) {
|
|
9582
|
+
if (!value || typeof value !== "object")
|
|
9583
|
+
throw new Error("active manifest is not an object");
|
|
9584
|
+
const manifest = value;
|
|
9585
|
+
if (manifest.schemaVersion !== ACTIVE_SCHEMA_VERSION) {
|
|
9586
|
+
throw new Error(`unsupported active manifest schema ${String(manifest.schemaVersion)}`);
|
|
9587
|
+
}
|
|
9588
|
+
if (!Number.isSafeInteger(manifest.generation) || (manifest.generation ?? -1) < 0) {
|
|
9589
|
+
throw new Error("active manifest generation is invalid");
|
|
9590
|
+
}
|
|
9591
|
+
if (!Array.isArray(manifest.policies))
|
|
9592
|
+
throw new Error("active manifest policies is not an array");
|
|
9593
|
+
return manifest;
|
|
9594
|
+
}
|
|
9595
|
+
function resolveManagedPath(root, candidate) {
|
|
9596
|
+
if (!candidate || isAbsolute2(candidate))
|
|
9597
|
+
throw new Error(`unsafe managed policy path ${JSON.stringify(candidate)}`);
|
|
9598
|
+
const absolute = resolve11(root, candidate);
|
|
9599
|
+
const lexicalRelative = relative3(root, absolute);
|
|
9600
|
+
if (lexicalRelative.startsWith("..") || isAbsolute2(lexicalRelative)) {
|
|
9601
|
+
throw new Error(`managed policy path escapes its root: ${JSON.stringify(candidate)}`);
|
|
9602
|
+
}
|
|
9603
|
+
const realRoot = realpathSync(root);
|
|
9604
|
+
const realFile = realpathSync(absolute);
|
|
9605
|
+
const physicalRelative = relative3(realRoot, realFile);
|
|
9606
|
+
if (physicalRelative.startsWith("..") || isAbsolute2(physicalRelative)) {
|
|
9607
|
+
throw new Error(`managed policy symlink escapes its root: ${JSON.stringify(candidate)}`);
|
|
9608
|
+
}
|
|
9609
|
+
return realFile;
|
|
9610
|
+
}
|
|
9611
|
+
function readActiveCloudManagedPolicies() {
|
|
9612
|
+
const root = cloudManagedPolicyRoot();
|
|
9613
|
+
const activePath = resolve11(root, "active.json");
|
|
9614
|
+
if (!existsSync11(activePath))
|
|
9615
|
+
return [];
|
|
9616
|
+
let raw;
|
|
9617
|
+
try {
|
|
9618
|
+
raw = JSON.parse(readFileSync11(activePath, "utf8"));
|
|
9619
|
+
} catch (err) {
|
|
9620
|
+
throw new Error(`failed to read cloud-managed active manifest: ${err instanceof Error ? err.message : String(err)}`);
|
|
9621
|
+
}
|
|
9622
|
+
const manifest = parseManifest(raw);
|
|
9623
|
+
const seen = new Set;
|
|
9624
|
+
return manifest.policies.map((policy) => {
|
|
9625
|
+
if (!POLICY_ID_RE.test(policy.id) || policy.id === "." || policy.id === "..") {
|
|
9626
|
+
throw new Error(`unsafe cloud-managed policy id ${JSON.stringify(policy.id)}`);
|
|
9627
|
+
}
|
|
9628
|
+
if (!Number.isSafeInteger(policy.revision) || policy.revision < 0) {
|
|
9629
|
+
throw new Error(`invalid revision for cloud-managed policy ${policy.id}`);
|
|
9630
|
+
}
|
|
9631
|
+
if (!SHA256_RE.test(policy.sha256)) {
|
|
9632
|
+
throw new Error(`invalid SHA-256 for cloud-managed policy ${policy.id}`);
|
|
9633
|
+
}
|
|
9634
|
+
if (seen.has(policy.id))
|
|
9635
|
+
throw new Error(`duplicate cloud-managed policy id ${policy.id}`);
|
|
9636
|
+
seen.add(policy.id);
|
|
9637
|
+
const path2 = resolveManagedPath(root, policy.path);
|
|
9638
|
+
const bytes = readFileSync11(path2);
|
|
9639
|
+
const actual = createHash3("sha256").update(bytes).digest("hex");
|
|
9640
|
+
if (actual !== policy.sha256) {
|
|
9641
|
+
throw new Error(`cloud-managed policy ${policy.id} failed integrity verification: expected ${policy.sha256}, got ${actual}`);
|
|
9642
|
+
}
|
|
9643
|
+
if (policy.effect !== undefined && policy.effect !== "enforce" && policy.effect !== "observe") {
|
|
9644
|
+
throw new Error(`unknown effect ${JSON.stringify(policy.effect)} for cloud-managed policy ${policy.id}`);
|
|
9645
|
+
}
|
|
9646
|
+
return {
|
|
9647
|
+
id: policy.id,
|
|
9648
|
+
revision: policy.revision,
|
|
9649
|
+
effect: policy.effect ?? "enforce",
|
|
9650
|
+
sha256: policy.sha256,
|
|
9651
|
+
path: path2,
|
|
9652
|
+
generation: manifest.generation
|
|
9653
|
+
};
|
|
9654
|
+
});
|
|
9655
|
+
}
|
|
9656
|
+
var ACTIVE_SCHEMA_VERSION = 1, SHA256_RE, POLICY_ID_RE;
|
|
9657
|
+
var init_cloud_managed_policies = __esm(() => {
|
|
9658
|
+
init_fp_home();
|
|
9659
|
+
SHA256_RE = /^[a-f0-9]{64}$/;
|
|
9660
|
+
POLICY_ID_RE = /^[A-Za-z0-9._-]{1,128}$/;
|
|
9661
|
+
});
|
|
9662
|
+
|
|
9663
|
+
// lib/atomic-write.ts
|
|
9664
|
+
var init_atomic_write = () => {};
|
|
9665
|
+
|
|
9666
|
+
// src/hooks/session-pause.ts
|
|
9667
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readdirSync as readdirSync11, readFileSync as readFileSync12, rmSync as rmSync2 } from "node:fs";
|
|
9668
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
9669
|
+
import { join as join26, resolve as resolve12 } from "node:path";
|
|
9670
|
+
function pauseStateDir() {
|
|
9671
|
+
const override = process.env.FAILPROOFAI_STATE_DIR;
|
|
9672
|
+
if (override)
|
|
9673
|
+
return resolve12(override, "sessions");
|
|
9674
|
+
return sessionPauseDir();
|
|
9675
|
+
}
|
|
9676
|
+
function pauseFilePath(sessionId) {
|
|
9677
|
+
const digest = createHash4("sha256").update(sessionId).digest("hex").slice(0, 32);
|
|
9678
|
+
return join26(pauseStateDir(), `${digest}.json`);
|
|
9679
|
+
}
|
|
9680
|
+
function parseStored(raw) {
|
|
9681
|
+
if (!raw || typeof raw !== "object")
|
|
9682
|
+
return null;
|
|
9683
|
+
const p = raw;
|
|
9684
|
+
if (p.schemaVersion !== SCHEMA_VERSION)
|
|
9685
|
+
return null;
|
|
9686
|
+
if (typeof p.sessionId !== "string" || p.sessionId.length === 0)
|
|
9687
|
+
return null;
|
|
9688
|
+
if (!Number.isFinite(p.pausedAt) || !Number.isFinite(p.expiresAt))
|
|
9689
|
+
return null;
|
|
9690
|
+
const pausedAt = p.pausedAt;
|
|
9691
|
+
const firstPausedAt = Number.isFinite(p.firstPausedAt) ? p.firstPausedAt : pausedAt;
|
|
9692
|
+
return {
|
|
9693
|
+
schemaVersion: SCHEMA_VERSION,
|
|
9694
|
+
sessionId: p.sessionId,
|
|
9695
|
+
pausedAt,
|
|
9696
|
+
firstPausedAt,
|
|
9697
|
+
expiresAt: Math.min(p.expiresAt, firstPausedAt + PAUSE_CEILING_MS),
|
|
9698
|
+
setBy: typeof p.setBy === "string" ? p.setBy : "unknown",
|
|
9699
|
+
...typeof p.cwd === "string" ? { cwd: p.cwd } : {}
|
|
9700
|
+
};
|
|
9701
|
+
}
|
|
9702
|
+
function readActivePause(sessionId, now = Date.now()) {
|
|
9703
|
+
if (!sessionId)
|
|
9704
|
+
return null;
|
|
9705
|
+
try {
|
|
9706
|
+
const path2 = pauseFilePath(sessionId);
|
|
9707
|
+
if (!existsSync12(path2))
|
|
9708
|
+
return null;
|
|
9709
|
+
const stored = parseStored(JSON.parse(readFileSync12(path2, "utf8")));
|
|
9710
|
+
if (!stored)
|
|
9711
|
+
return null;
|
|
9712
|
+
if (stored.expiresAt <= now)
|
|
9713
|
+
return null;
|
|
9714
|
+
const { schemaVersion: _ignored, ...pause } = stored;
|
|
9715
|
+
return pause;
|
|
9716
|
+
} catch {
|
|
9717
|
+
return null;
|
|
9718
|
+
}
|
|
9719
|
+
}
|
|
9720
|
+
var SCHEMA_VERSION = 1, PAUSE_DEFAULT_MS, PAUSE_CEILING_MS;
|
|
9721
|
+
var init_session_pause = __esm(() => {
|
|
9722
|
+
init_atomic_write();
|
|
9723
|
+
init_hook_activity_store();
|
|
9724
|
+
init_fp_home();
|
|
9725
|
+
PAUSE_DEFAULT_MS = 30 * 60000;
|
|
9726
|
+
PAUSE_CEILING_MS = 8 * 60 * 60000;
|
|
9727
|
+
});
|
|
9728
|
+
|
|
9729
|
+
// src/hooks/daemon-download.ts
|
|
9730
|
+
var init_daemon_download = __esm(() => {
|
|
9731
|
+
init_package();
|
|
9732
|
+
init_fp_home();
|
|
9733
|
+
});
|
|
9734
|
+
|
|
9735
|
+
// src/hooks/daemon-service.ts
|
|
9736
|
+
var init_daemon_service = __esm(() => {
|
|
9737
|
+
init_hook_logger();
|
|
9738
|
+
init_daemon_download();
|
|
9739
|
+
init_fp_home();
|
|
9740
|
+
init_package();
|
|
9741
|
+
init_fp_config();
|
|
9742
|
+
});
|
|
9743
|
+
|
|
9744
|
+
// src/hooks/fp-reset.ts
|
|
9745
|
+
function layoutWarningForHook() {
|
|
9746
|
+
const state = detectLayout();
|
|
9747
|
+
if (state.kind === "current" || state.kind === "absent")
|
|
9748
|
+
return null;
|
|
9749
|
+
if (state.kind === "future") {
|
|
9750
|
+
return `[failproofai] this directory was written by a newer version ` + `(layout ${state.found} vs ${LAYOUT_VERSION}) — policies are NOT being enforced. ` + `Upgrade failproofai.`;
|
|
9751
|
+
}
|
|
9752
|
+
return `[failproofai] setup predates this version — global policies are NOT being enforced. ` + `Run \`failproofai config\` to re-create it.`;
|
|
9753
|
+
}
|
|
9754
|
+
var init_fp_reset = __esm(() => {
|
|
9755
|
+
init_fp_home();
|
|
9756
|
+
init_fp_config();
|
|
9757
|
+
init_daemon_service();
|
|
9758
|
+
});
|
|
9759
|
+
|
|
8104
9760
|
// src/hooks/handler.ts
|
|
8105
9761
|
function canonicalizeEventType(raw, cli) {
|
|
8106
9762
|
if (cli === "codex") {
|
|
@@ -8135,8 +9791,29 @@ function canonicalizeEventType(raw, cli) {
|
|
|
8135
9791
|
}
|
|
8136
9792
|
return raw;
|
|
8137
9793
|
}
|
|
9794
|
+
async function runObserved(hook, ctx, hookName, eventType, cli) {
|
|
9795
|
+
try {
|
|
9796
|
+
return await Promise.race([
|
|
9797
|
+
hook.fn(ctx),
|
|
9798
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 1e4))
|
|
9799
|
+
]);
|
|
9800
|
+
} catch (err) {
|
|
9801
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
9802
|
+
trackHookEvent(getInstanceId(), "custom_hook_error", {
|
|
9803
|
+
hook_name: hookName,
|
|
9804
|
+
error_type: msg === "timeout" ? "timeout" : "exception",
|
|
9805
|
+
event_type: eventType,
|
|
9806
|
+
cli,
|
|
9807
|
+
is_observe_mode: true
|
|
9808
|
+
});
|
|
9809
|
+
return { decision: "allow" };
|
|
9810
|
+
}
|
|
9811
|
+
}
|
|
8138
9812
|
async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts) {
|
|
8139
9813
|
const startTime = performance.now();
|
|
9814
|
+
const layoutWarning = layoutWarningForHook();
|
|
9815
|
+
if (layoutWarning)
|
|
9816
|
+
hookLogWarn(layoutWarning);
|
|
8140
9817
|
try {
|
|
8141
9818
|
let parsed = {};
|
|
8142
9819
|
if (stdinPayload) {
|
|
@@ -8176,6 +9853,10 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
8176
9853
|
let config;
|
|
8177
9854
|
let customHooksList = [];
|
|
8178
9855
|
let conventionHookNames = new Set;
|
|
9856
|
+
let activePause = null;
|
|
9857
|
+
const policyAttribution = new Map;
|
|
9858
|
+
let cloudGeneration;
|
|
9859
|
+
const observedResults = [];
|
|
8179
9860
|
if (opts?.forceDecision) {
|
|
8180
9861
|
config = { enabledPolicies: [] };
|
|
8181
9862
|
clearPolicies();
|
|
@@ -8184,23 +9865,59 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
8184
9865
|
} else {
|
|
8185
9866
|
config = readMergedHooksConfig(session.cwd);
|
|
8186
9867
|
clearPolicies();
|
|
8187
|
-
|
|
8188
|
-
|
|
9868
|
+
activePause = readActivePause(session.sessionId);
|
|
9869
|
+
registerBuiltinPolicies(activePause ? [] : config.enabledPolicies);
|
|
9870
|
+
let cloudManagedPolicies = [];
|
|
9871
|
+
try {
|
|
9872
|
+
cloudManagedPolicies = readActiveCloudManagedPolicies();
|
|
9873
|
+
} catch (err) {
|
|
9874
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
9875
|
+
hookLogWarn(`[failproofai] cloud-managed policies could NOT be loaded and are not being enforced: ${msg}. ` + `Local policies are unaffected. Run \`failproofai config --status\` to check this machine's enrolment.`);
|
|
9876
|
+
trackHookEvent(getInstanceId(), "cloud_managed_load_error", {
|
|
9877
|
+
event_type: eventType,
|
|
9878
|
+
cli
|
|
9879
|
+
});
|
|
9880
|
+
}
|
|
9881
|
+
cloudGeneration = cloudManagedPolicies[0]?.generation;
|
|
9882
|
+
const configuredCustomPaths = config.customPoliciesPaths ?? config.customPoliciesPath;
|
|
9883
|
+
const allExplicitPaths = cloudManagedPolicies.length === 0 ? configuredCustomPaths : [
|
|
9884
|
+
...typeof configuredCustomPaths === "string" ? [configuredCustomPaths] : configuredCustomPaths ?? [],
|
|
9885
|
+
...cloudManagedPolicies.map((policy) => policy.path)
|
|
9886
|
+
];
|
|
9887
|
+
const loadResult = await loadAllCustomHooks(allExplicitPaths, {
|
|
8189
9888
|
sessionCwd: session.cwd,
|
|
8190
|
-
customPoliciesEnabled: config.customPoliciesEnabled
|
|
9889
|
+
customPoliciesEnabled: config.customPoliciesEnabled,
|
|
9890
|
+
...cloudManagedPolicies.length > 0 ? { cloudManagedPolicies } : {}
|
|
8191
9891
|
});
|
|
8192
9892
|
customHooksList = loadResult.hooks;
|
|
8193
9893
|
const disabledCustomPolicies = new Set(config.disabledCustomPolicies ?? []);
|
|
8194
9894
|
conventionHookNames = new Set(loadResult.conventionSources.flatMap((s) => s.hookNames));
|
|
8195
9895
|
for (const hook of customHooksList) {
|
|
8196
|
-
const
|
|
8197
|
-
|
|
9896
|
+
const taggedHook = hook;
|
|
9897
|
+
const policyId = taggedHook.__policyId;
|
|
9898
|
+
const cloudManaged = taggedHook.__cloudManaged;
|
|
9899
|
+
if (!cloudManaged && policyId && disabledCustomPolicies.has(policyId))
|
|
9900
|
+
continue;
|
|
9901
|
+
if (!cloudManaged && activePause)
|
|
8198
9902
|
continue;
|
|
8199
9903
|
const hookName = hook.name;
|
|
8200
9904
|
const conventionScope = hook.__conventionScope;
|
|
8201
9905
|
const isConvention = !!conventionScope;
|
|
8202
|
-
const prefix = isConvention ? `.failproofai-${conventionScope}` : "custom";
|
|
9906
|
+
const prefix = cloudManaged ? `cloud/${cloudManaged.id}@${cloudManaged.revision}` : isConvention ? `.failproofai-${conventionScope}` : "custom";
|
|
9907
|
+
const observeOnly = cloudManaged?.effect === "observe";
|
|
8203
9908
|
const fn = async (ctx) => {
|
|
9909
|
+
if (observeOnly) {
|
|
9910
|
+
const shadow = await runObserved(hook, ctx, hookName, eventType, cli);
|
|
9911
|
+
if (shadow.decision !== "allow") {
|
|
9912
|
+
observedResults.push({
|
|
9913
|
+
policyId: cloudManaged.id,
|
|
9914
|
+
revision: cloudManaged.revision,
|
|
9915
|
+
decision: shadow.decision,
|
|
9916
|
+
reason: shadow.reason ?? null
|
|
9917
|
+
});
|
|
9918
|
+
}
|
|
9919
|
+
return { decision: "allow" };
|
|
9920
|
+
}
|
|
8204
9921
|
try {
|
|
8205
9922
|
const result2 = await Promise.race([
|
|
8206
9923
|
hook.fn(ctx),
|
|
@@ -8222,7 +9939,12 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
8222
9939
|
return { decision: "allow" };
|
|
8223
9940
|
}
|
|
8224
9941
|
};
|
|
8225
|
-
|
|
9942
|
+
const registeredName = `${prefix}/${hookName}`;
|
|
9943
|
+
policyAttribution.set(registeredName, {
|
|
9944
|
+
source: cloudManaged ? "cloud" : isConvention ? "convention" : "custom",
|
|
9945
|
+
...cloudManaged ? { cloudPolicyId: cloudManaged.id, cloudRevision: cloudManaged.revision } : {}
|
|
9946
|
+
});
|
|
9947
|
+
registerPolicy(registeredName, hook.description ?? "", fn, hook.match ?? {}, -1);
|
|
8226
9948
|
}
|
|
8227
9949
|
if (customHooksList.length > 0) {
|
|
8228
9950
|
trackHookEvent(getInstanceId(), "custom_hooks_loaded", {
|
|
@@ -8263,7 +9985,18 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
8263
9985
|
transcriptPath: session.transcriptPath,
|
|
8264
9986
|
cwd: session.cwd,
|
|
8265
9987
|
permissionMode: session.permissionMode,
|
|
8266
|
-
hookEventName: session.hookEventName
|
|
9988
|
+
hookEventName: session.hookEventName,
|
|
9989
|
+
...result.policyName ? (() => {
|
|
9990
|
+
const attribution = policyAttribution.get(result.policyName);
|
|
9991
|
+
return {
|
|
9992
|
+
policySource: attribution?.source ?? "builtin",
|
|
9993
|
+
...attribution?.cloudPolicyId ? { cloudPolicyId: attribution.cloudPolicyId } : {},
|
|
9994
|
+
...attribution?.cloudRevision !== undefined ? { cloudRevision: attribution.cloudRevision } : {}
|
|
9995
|
+
};
|
|
9996
|
+
})() : {},
|
|
9997
|
+
...cloudGeneration !== undefined ? { cloudGeneration } : {},
|
|
9998
|
+
...observedResults.length > 0 ? { observed: observedResults } : {},
|
|
9999
|
+
...activePause ? { pausedBy: activePause.setBy, pauseExpiresAt: activePause.expiresAt } : {}
|
|
8267
10000
|
};
|
|
8268
10001
|
try {
|
|
8269
10002
|
persistHookActivity(activityEntry);
|
|
@@ -8315,6 +10048,9 @@ var init_handler = __esm(() => {
|
|
|
8315
10048
|
init_resolve_transcript_path();
|
|
8316
10049
|
init_telemetry_id();
|
|
8317
10050
|
init_hook_logger();
|
|
10051
|
+
init_cloud_managed_policies();
|
|
10052
|
+
init_session_pause();
|
|
10053
|
+
init_fp_reset();
|
|
8318
10054
|
});
|
|
8319
10055
|
|
|
8320
10056
|
// src/hooks/worker-server.ts
|
|
@@ -8323,12 +10059,12 @@ __export(exports_worker_server, {
|
|
|
8323
10059
|
startWorkerServer: () => startWorkerServer
|
|
8324
10060
|
});
|
|
8325
10061
|
import { createServer } from "node:net";
|
|
8326
|
-
import { existsSync as
|
|
10062
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync2 } from "node:fs";
|
|
8327
10063
|
function isWorkerHookRequest(msg) {
|
|
8328
10064
|
if (!msg || typeof msg !== "object")
|
|
8329
10065
|
return false;
|
|
8330
10066
|
const m = msg;
|
|
8331
|
-
return m.type === "hook" && typeof m.hookEvent === "string" && typeof m.cli === "string" && typeof m.stdin === "string" && (m.cwd === undefined || typeof m.cwd === "string");
|
|
10067
|
+
return m.type === "hook" && typeof m.hookEvent === "string" && typeof m.cli === "string" && typeof m.stdin === "string" && (m.cwd === undefined || m.cwd === null || typeof m.cwd === "string");
|
|
8332
10068
|
}
|
|
8333
10069
|
function encodeFrame(value) {
|
|
8334
10070
|
const body = Buffer.from(JSON.stringify(value), "utf8");
|
|
@@ -8337,7 +10073,18 @@ function encodeFrame(value) {
|
|
|
8337
10073
|
return Buffer.concat([header, body]);
|
|
8338
10074
|
}
|
|
8339
10075
|
function enqueue(task) {
|
|
8340
|
-
processingChain = processingChain.then(
|
|
10076
|
+
processingChain = processingChain.then(() => new Promise((settle) => {
|
|
10077
|
+
const timer = setTimeout(() => {
|
|
10078
|
+
hookLogWarn(`worker: a request did not settle within ${TASK_DEADLINE_MS}ms; ` + `exiting so the supervisor can respawn a clean worker`);
|
|
10079
|
+
process.exit(WEDGED_EXIT_CODE);
|
|
10080
|
+
}, TASK_DEADLINE_MS);
|
|
10081
|
+
timer.unref?.();
|
|
10082
|
+
const done = () => {
|
|
10083
|
+
clearTimeout(timer);
|
|
10084
|
+
settle();
|
|
10085
|
+
};
|
|
10086
|
+
task().then(done, done);
|
|
10087
|
+
})).catch(() => {});
|
|
8341
10088
|
}
|
|
8342
10089
|
function handleConnection(socket) {
|
|
8343
10090
|
let recvBuf = Buffer.alloc(0);
|
|
@@ -8376,7 +10123,7 @@ function handleConnection(socket) {
|
|
|
8376
10123
|
try {
|
|
8377
10124
|
const result = await evaluateHookEvent(request.hookEvent, request.cli, request.stdin, {
|
|
8378
10125
|
awaitTelemetryFlush: false,
|
|
8379
|
-
fallbackCwd: request.cwd
|
|
10126
|
+
fallbackCwd: request.cwd ?? undefined
|
|
8380
10127
|
});
|
|
8381
10128
|
socket.write(encodeFrame({
|
|
8382
10129
|
type: "hookResult",
|
|
@@ -8395,7 +10142,7 @@ function handleConnection(socket) {
|
|
|
8395
10142
|
socket.on("error", () => {});
|
|
8396
10143
|
}
|
|
8397
10144
|
function startWorkerServer(socketPath) {
|
|
8398
|
-
if (
|
|
10145
|
+
if (existsSync13(socketPath)) {
|
|
8399
10146
|
try {
|
|
8400
10147
|
unlinkSync2(socketPath);
|
|
8401
10148
|
} catch {}
|
|
@@ -8404,7 +10151,7 @@ function startWorkerServer(socketPath) {
|
|
|
8404
10151
|
server.listen(socketPath);
|
|
8405
10152
|
return server;
|
|
8406
10153
|
}
|
|
8407
|
-
var MAX_FRAME_LEN, processingChain;
|
|
10154
|
+
var MAX_FRAME_LEN, TASK_DEADLINE_MS = 60000, WEDGED_EXIT_CODE = 75, processingChain;
|
|
8408
10155
|
var init_worker_server = __esm(() => {
|
|
8409
10156
|
init_handler();
|
|
8410
10157
|
init_hook_logger();
|
|
@@ -8413,14 +10160,14 @@ var init_worker_server = __esm(() => {
|
|
|
8413
10160
|
});
|
|
8414
10161
|
|
|
8415
10162
|
// bin/failproofai-worker.mjs
|
|
8416
|
-
import { realpathSync } from "node:fs";
|
|
8417
|
-
import { dirname as dirname5, resolve as
|
|
10163
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
10164
|
+
import { dirname as dirname5, resolve as resolve13 } from "node:path";
|
|
8418
10165
|
import { fileURLToPath } from "node:url";
|
|
8419
10166
|
if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
|
|
8420
|
-
process.env.FAILPROOFAI_PACKAGE_ROOT =
|
|
10167
|
+
process.env.FAILPROOFAI_PACKAGE_ROOT = resolve13(dirname5(realpathSync2(fileURLToPath(import.meta.url))), "..");
|
|
8421
10168
|
}
|
|
8422
10169
|
if (!process.env.FAILPROOFAI_DIST_PATH) {
|
|
8423
|
-
process.env.FAILPROOFAI_DIST_PATH =
|
|
10170
|
+
process.env.FAILPROOFAI_DIST_PATH = resolve13(dirname5(realpathSync2(fileURLToPath(import.meta.url))), "..", "dist");
|
|
8424
10171
|
}
|
|
8425
10172
|
var socketPath = process.env.FAILPROOFAI_WORKER_SOCKET;
|
|
8426
10173
|
if (!socketPath) {
|