failproofai 0.0.10 → 0.0.11-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +7 -7
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +4 -4
- 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 +4 -4
- 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 +4 -4
- package/.next/standalone/.next/server/app/_not-found/page/next-font-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +4 -4
- 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/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/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +16 -16
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -16
- 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 +3 -3
- package/.next/standalone/.next/server/app/page/build-manifest.json +4 -4
- package/.next/standalone/.next/server/app/page/next-font-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +4 -4
- 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 +4 -4
- package/.next/standalone/.next/server/app/policies/page/next-font-manifest.json +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +4 -4
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +4 -4
- package/.next/standalone/.next/server/app/project/[name]/page/next-font-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +4 -4
- 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 +4 -4
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/next-font-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +4 -4
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +4 -4
- package/.next/standalone/.next/server/app/projects/page/next-font-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +4 -4
- 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/chunks/[root-of-the-server]__0d_ob4n._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__044xt9.._.js → [root-of-the-server]__0fwb7ao._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g48iv.._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0j8-xkl._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0bdfoky.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_05pz9._._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wn51s._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01as125._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__098zro9._.js +19 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__02r.cjq._.js → [root-of-the-server]__09v.ljl._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0agrcb8._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0b7hkr~._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehh6vp._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8l0tu._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0j4l6hl._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ye1w50._.js → [root-of-the-server]__0k5n2kz._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lp08ll._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0yaqw._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0o21f.o._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t8juvy._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__10xgshr._.js → [root-of-the-server]__0tcyn68._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ts150~._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0podumr._.js → [root-of-the-server]__0uylufv._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ymlddl._.js +5 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0~03grs._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_0cdqd9w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/lib_utils_ts_068jk73._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_0ttbz1~._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_06u0kr8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0h9llsw._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a_7sdg.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0ef3uwk.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0j79~gv.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0pbja1x.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0r6o0i2.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11y81~_.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12or2kf.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mebn66._.js +1 -1
- package/.next/standalone/.next/server/functions-config-manifest.json +2 -2
- package/.next/standalone/.next/server/middleware-build-manifest.js +7 -7
- package/.next/standalone/.next/server/next-font-manifest.js +1 -1
- package/.next/standalone/.next/server/next-font-manifest.json +6 -6
- 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 +9 -9
- package/.next/standalone/.next/static/chunks/07kpqoo7kuckx.js +6 -0
- package/.next/standalone/.next/static/chunks/0a40sy4tk8ioe.js +1 -0
- package/.next/standalone/.next/static/chunks/{12l2t63hkyo2q.js → 0azb~vy9ds_uy.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0j171xiqge4rv.js → 0bke.~atnsbeb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0lt8ko3lw.5yt.js → 0bv1oyxspkpkb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{179yytvmam0ug.js → 0dvhi-prcsh3~.js} +1 -1
- package/.next/standalone/.next/static/chunks/0f5p9plm.aqlp.css +2 -0
- package/.next/standalone/.next/static/chunks/0ffvlbgzgnlw7.js +2 -0
- package/.next/standalone/.next/static/chunks/{150i0n26fnvso.js → 0n1n67imq.udf.js} +1 -1
- package/.next/standalone/.next/static/chunks/0spktq7xqab9h.js +1 -0
- package/.next/standalone/.next/static/chunks/{14lii11wmo450.js → 118q3uljozd5z.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0pkl..xgo-qox.js → 11w14gnqzprir.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0rnqmir4cd5p9.js → 17mubwtqwijpu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-05z7a19q43zfq.js → turbopack-0nh.aopesgj~5.js} +1 -1
- package/.next/standalone/.next/static/media/4fa387ec64143e14-s.0.qu-9752pffj.woff2 +0 -0
- package/.next/standalone/.next/static/media/5ce348bf30bf5439-s.0ee55_hj9qcer.woff2 +0 -0
- package/.next/standalone/.next/static/media/6306c77e7c8268e4-s.0mao5jbfbduzp.woff2 +0 -0
- package/.next/standalone/.next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2 +0 -0
- package/.next/standalone/.next/static/media/7d817b4c03b0c5f1-s.0uzt.a6d44yda.woff2 +0 -0
- package/.next/standalone/.next/static/media/bbc41e54d2fcbd21-s.0mvwgmnhv29no.woff2 +0 -0
- package/.next/standalone/.next/static/{dAuQps6jUwCz9X1Q5FFOO → tGVQM5SE3NvbVu0gbAJm7}/_clientMiddlewareManifest.js +2 -2
- package/.next/standalone/app/policies/hooks-client.tsx +111 -14
- package/.next/standalone/components/navbar.tsx +1 -1
- package/.next/standalone/components/reach-developers.tsx +2 -2
- package/.next/standalone/lib/claude-sessions.ts +181 -0
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/static-paths/app.js +2 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/build/utils.js +2 -1
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/fetch-server-response.js +2 -2
- package/.next/standalone/node_modules/next/dist/client/components/router-reducer/set-cache-busting-search-param.js +8 -2
- package/.next/standalone/node_modules/next/dist/client/route-params.js +23 -6
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +13 -13
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +11 -11
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +2 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +10 -10
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/app-render/action-handler.js +3 -6
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render.js +62 -9
- package/.next/standalone/node_modules/next/dist/server/app-render/collect-segment-data.js +16 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/create-component-tree.js +49 -19
- package/.next/standalone/node_modules/next/dist/server/app-render/get-script-nonce-from-header.js +8 -20
- package/.next/standalone/node_modules/next/dist/server/app-render/metadata-insertion/create-server-inserted-metadata.js +8 -7
- package/.next/standalone/node_modules/next/dist/server/app-render/use-flight-response.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/async-storage/work-store.js +2 -1
- package/.next/standalone/node_modules/next/dist/server/base-server.js +13 -5
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/static-paths-worker.js +2 -1
- package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +22 -2
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/is-rsc-request.js +18 -0
- package/.next/standalone/node_modules/next/dist/server/lib/mock-request.js +30 -5
- package/.next/standalone/node_modules/next/dist/server/lib/patch-set-header.js +7 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +6 -3
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/resolve-routes.js +18 -4
- package/.next/standalone/node_modules/next/dist/server/lib/server-ipc/utils.js +3 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/next-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/request/fallback-params.js +27 -1
- package/.next/standalone/node_modules/next/dist/server/route-modules/app-route/module.js +1 -0
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +11 -1
- package/.next/standalone/node_modules/next/dist/server/server-utils.js +19 -2
- package/.next/standalone/node_modules/next/dist/server/stream-utils/node-web-streams-helper.js +5 -5
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/web/adapter.js +4 -1
- package/.next/standalone/node_modules/next/dist/server/web/edge-route-module-wrapper.js +2 -1
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
- package/.next/standalone/node_modules/next/dist/{server → shared/lib}/htmlescape.js +15 -0
- package/.next/standalone/node_modules/next/dist/shared/lib/router/routes/app.js +13 -1
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/cache-busting-search-param.js +56 -10
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +15 -15
- 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 +1 -1
- 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 +2 -2
- package/.next/standalone/package.json +5 -5
- package/.next/standalone/proxy.ts +1 -1
- package/.next/standalone/server.js +1 -1
- package/README.md +4 -4
- package/bin/failproofai.mjs +230 -73
- package/dist/cli.mjs +3028 -1453
- package/lib/claude-sessions.ts +181 -0
- package/package.json +5 -5
- package/scripts/launch.ts +1 -1
- package/scripts/postinstall.mjs +89 -1
- package/src/audit/cache.ts +113 -0
- package/src/audit/cli-adapters/claude.ts +97 -0
- package/src/audit/cli-adapters/codex.ts +56 -0
- package/src/audit/cli-adapters/copilot.ts +51 -0
- package/src/audit/cli-adapters/cursor.ts +51 -0
- package/src/audit/cli-adapters/gemini.ts +51 -0
- package/src/audit/cli-adapters/index.ts +70 -0
- package/src/audit/cli-adapters/opencode.ts +52 -0
- package/src/audit/cli-adapters/pi.ts +51 -0
- package/src/audit/cli-adapters/shared.ts +85 -0
- package/src/audit/detectors/find-from-root.ts +27 -0
- package/src/audit/detectors/git-commit-no-verify.ts +22 -0
- package/src/audit/detectors/index.ts +33 -0
- package/src/audit/detectors/prefer-edit-over-read-cat.ts +31 -0
- package/src/audit/detectors/prefer-edit-over-sed-awk.ts +27 -0
- package/src/audit/detectors/prefer-write-over-heredoc.ts +36 -0
- package/src/audit/detectors/redundant-cd-cwd.ts +28 -0
- package/src/audit/detectors/reread-after-edit.ts +58 -0
- package/src/audit/detectors/sleep-polling-loop.ts +34 -0
- package/src/audit/index.ts +369 -0
- package/src/audit/replay.ts +121 -0
- package/src/audit/report.ts +349 -0
- package/src/audit/telemetry.ts +113 -0
- package/src/audit/types.ts +193 -0
- package/src/hooks/builtin-policies.ts +79 -1
- package/src/hooks/custom-hooks-loader.ts +19 -3
- package/src/hooks/first-run-nudge.ts +146 -0
- package/src/hooks/handler.ts +21 -102
- package/src/hooks/install-prompt.ts +34 -4
- package/src/hooks/manager.ts +72 -5
- package/src/hooks/policy-evaluator.ts +19 -4
- package/src/hooks/policy-registry.ts +1 -1
- package/src/hooks/policy-types.ts +9 -0
- package/src/hooks/tool-name-canonicalize.ts +65 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0609ezh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__07_-mkc._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09z7o2x._.js +0 -19
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_sh2n0._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e9o9ri._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0l6swv1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0logebz._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0mi5ejy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0odijkc._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rkxer-._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rl2kwi._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vg0uey._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0x5limi._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__10._f0s._.js +0 -4
- package/.next/standalone/.next/static/chunks/01q52wg_amm60.js +0 -2
- package/.next/standalone/.next/static/chunks/0kqar56yl~41o.js +0 -6
- package/.next/standalone/.next/static/chunks/0ml1.ck_5t36i.js +0 -1
- package/.next/standalone/.next/static/chunks/0zig0fh30t6ou.js +0 -1
- package/.next/standalone/.next/static/chunks/17rm86uz2nd5a.css +0 -2
- package/.next/standalone/.next/static/media/4fa387ec64143e14-s.0q3udbd2bu5yp.woff2 +0 -0
- package/.next/standalone/.next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2 +0 -0
- package/.next/standalone/.next/static/media/bbc41e54d2fcbd21-s.0gw~uztddq1df.woff2 +0 -0
- package/src/auth/login.ts +0 -104
- package/src/auth/logout.ts +0 -50
- package/src/auth/token-store.ts +0 -64
- package/src/relay/daemon.ts +0 -362
- package/src/relay/pid.ts +0 -76
- package/src/relay/queue.ts +0 -225
- /package/.next/standalone/.next/static/{dAuQps6jUwCz9X1Q5FFOO → tGVQM5SE3NvbVu0gbAJm7}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{dAuQps6jUwCz9X1Q5FFOO → tGVQM5SE3NvbVu0gbAJm7}/_ssgManifest.js +0 -0
package/src/hooks/handler.ts
CHANGED
|
@@ -19,15 +19,8 @@ import {
|
|
|
19
19
|
CURSOR_EVENT_MAP,
|
|
20
20
|
PI_EVENT_MAP,
|
|
21
21
|
GEMINI_EVENT_MAP,
|
|
22
|
-
GEMINI_TOOL_MAP,
|
|
23
|
-
COPILOT_TOOL_MAP,
|
|
24
|
-
CURSOR_TOOL_MAP,
|
|
25
|
-
CODEX_TOOL_MAP,
|
|
26
|
-
OPENCODE_TOOL_MAP,
|
|
27
|
-
OPENCODE_TOOL_INPUT_MAP,
|
|
28
|
-
PI_TOOL_MAP,
|
|
29
|
-
PI_TOOL_INPUT_MAP,
|
|
30
22
|
} from "./types";
|
|
23
|
+
import { canonicalizeToolName, canonicalizeToolInput } from "./tool-name-canonicalize";
|
|
31
24
|
import type { PolicyFunction, PolicyResult } from "./policy-types";
|
|
32
25
|
import { readMergedHooksConfig } from "./hooks-config";
|
|
33
26
|
import { registerBuiltinPolicies } from "./builtin-policies";
|
|
@@ -77,80 +70,6 @@ function canonicalizeEventType(raw: string, cli: IntegrationType): HookEventType
|
|
|
77
70
|
return raw as HookEventType;
|
|
78
71
|
}
|
|
79
72
|
|
|
80
|
-
/**
|
|
81
|
-
* Canonicalize a per-CLI tool name to the Claude PascalCase form that builtin
|
|
82
|
-
* policies match on (e.g. `Bash`, `Read`, `Write`, `Edit`). The registry filter
|
|
83
|
-
* at policy-registry.ts:93-95 is case-sensitive `Array.includes`, so any
|
|
84
|
-
* mismatch silently no-ops every Bash/Read/Write/Edit builtin.
|
|
85
|
-
*
|
|
86
|
-
* Per-CLI tool-name shapes (verified from in-repo evidence and vendor docs):
|
|
87
|
-
* • Claude: PascalCase native — passthrough
|
|
88
|
-
* • Codex: `Bash` PascalCase passthrough; `apply_patch` → `Edit`,
|
|
89
|
-
* `write_stdin` → `Bash` via CODEX_TOOL_MAP
|
|
90
|
-
* • Copilot: lowercase IDs (`bash`, `read`, `view`, …) — COPILOT_TOOL_MAP
|
|
91
|
-
* • Cursor: PascalCase per Cursor docs but uses `Shell` for the bash-
|
|
92
|
-
* equivalent — CURSOR_TOOL_MAP rewrites `Shell → Bash`; other
|
|
93
|
-
* tool names already canonical and pass through
|
|
94
|
-
* • OpenCode: lowercase IDs (`bash`, `read`, …) — OPENCODE_TOOL_MAP. The
|
|
95
|
-
* OpenCode plugin shim ALSO canonicalizes inline as defense-in-
|
|
96
|
-
* depth; both passes are idempotent. Handler-side coverage
|
|
97
|
-
* here means a stale user-scope shim that pre-dates #337 still
|
|
98
|
-
* gets the canonicalization, without forcing a re-install.
|
|
99
|
-
* • Pi: lowercase IDs (`bash`, `read`, …) — PI_TOOL_MAP. Same dual-
|
|
100
|
-
* canonicalization story as OpenCode (shim + handler).
|
|
101
|
-
* • Gemini: snake_case — GEMINI_TOOL_MAP
|
|
102
|
-
*
|
|
103
|
-
* Unknown tool names (MCP `mcp_*`, third-party extensions, Skills) pass
|
|
104
|
-
* through unchanged so non-builtin tooling isn't lost.
|
|
105
|
-
*/
|
|
106
|
-
function canonicalizeToolName(raw: string | undefined, cli: IntegrationType): string | undefined {
|
|
107
|
-
if (!raw) return raw;
|
|
108
|
-
if (cli === "copilot") return COPILOT_TOOL_MAP[raw] ?? raw;
|
|
109
|
-
if (cli === "cursor") return CURSOR_TOOL_MAP[raw] ?? raw;
|
|
110
|
-
if (cli === "codex") return CODEX_TOOL_MAP[raw] ?? raw;
|
|
111
|
-
if (cli === "gemini") return GEMINI_TOOL_MAP[raw] ?? raw;
|
|
112
|
-
if (cli === "opencode") return OPENCODE_TOOL_MAP[raw] ?? raw;
|
|
113
|
-
if (cli === "pi") return PI_TOOL_MAP[raw] ?? raw;
|
|
114
|
-
return raw;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Canonicalize per-CLI tool-input keys to the snake_case shape that builtin
|
|
119
|
-
* policies read (e.g. `file_path`, `old_string`). OpenCode delivers args as
|
|
120
|
-
* camelCase (`filePath`, `oldString`, `newString`, `replaceAll`); Pi delivers
|
|
121
|
-
* `path` for Read/Write/Edit. Without translation, `getFilePath()` reads "" and
|
|
122
|
-
* the path-checking builtins (`block-read-outside-cwd`, `block-env-files`,
|
|
123
|
-
* `block-secrets-write`) silently no-op.
|
|
124
|
-
*
|
|
125
|
-
* Both CLIs' shims canonicalize inline before the JSON crosses to this binary.
|
|
126
|
-
* Handler-side coverage here is defense-in-depth: a user-scope shim that pre-
|
|
127
|
-
* dates #337 still passes the raw camelCase keys, and we want those installs
|
|
128
|
-
* to start enforcing the moment failproofai upgrades — without requiring a
|
|
129
|
-
* `failproofai policies --install --cli opencode` re-run.
|
|
130
|
-
*
|
|
131
|
-
* Idempotent: when the shim already canonicalized, the keys are snake_case
|
|
132
|
-
* and the per-tool map's camelCase keys don't match, so the loop is a no-op.
|
|
133
|
-
*
|
|
134
|
-
* Tools outside the per-CLI map (MCP `mcp_*`, third-party extensions) pass
|
|
135
|
-
* through unchanged so their schemas aren't corrupted.
|
|
136
|
-
*/
|
|
137
|
-
function canonicalizeToolInput(
|
|
138
|
-
toolName: string | undefined,
|
|
139
|
-
rawInput: unknown,
|
|
140
|
-
cli: IntegrationType,
|
|
141
|
-
): unknown {
|
|
142
|
-
if (!toolName || !rawInput || typeof rawInput !== "object") return rawInput;
|
|
143
|
-
let perToolMap: Record<string, string> | undefined;
|
|
144
|
-
if (cli === "opencode") perToolMap = OPENCODE_TOOL_INPUT_MAP[toolName];
|
|
145
|
-
else if (cli === "pi") perToolMap = PI_TOOL_INPUT_MAP[toolName];
|
|
146
|
-
if (!perToolMap) return rawInput;
|
|
147
|
-
const out: Record<string, unknown> = {};
|
|
148
|
-
for (const [k, v] of Object.entries(rawInput as Record<string, unknown>)) {
|
|
149
|
-
out[perToolMap[k] ?? k] = v;
|
|
150
|
-
}
|
|
151
|
-
return out;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
73
|
export async function handleHookEvent(
|
|
155
74
|
eventType: string,
|
|
156
75
|
cli: IntegrationType = "claude",
|
|
@@ -160,6 +79,7 @@ export async function handleHookEvent(
|
|
|
160
79
|
// Read stdin payload (Claude passes JSON)
|
|
161
80
|
const MAX_STDIN_BYTES = 1_048_576; // 1 MB
|
|
162
81
|
let payload = "";
|
|
82
|
+
let stdinOversized = false;
|
|
163
83
|
try {
|
|
164
84
|
payload = await new Promise<string>((resolve, reject) => {
|
|
165
85
|
const chunks: string[] = [];
|
|
@@ -169,6 +89,7 @@ export async function handleHookEvent(
|
|
|
169
89
|
totalBytes += Buffer.byteLength(chunk);
|
|
170
90
|
if (totalBytes > MAX_STDIN_BYTES) {
|
|
171
91
|
hookLogWarn(`stdin payload exceeds 1 MB for ${eventType}, discarding`);
|
|
92
|
+
stdinOversized = true;
|
|
172
93
|
process.stdin.destroy();
|
|
173
94
|
resolve("");
|
|
174
95
|
return;
|
|
@@ -180,8 +101,20 @@ export async function handleHookEvent(
|
|
|
180
101
|
// If stdin is already closed or not piped, resolve immediately
|
|
181
102
|
if (process.stdin.readableEnded) resolve("");
|
|
182
103
|
});
|
|
183
|
-
} catch {
|
|
104
|
+
} catch (err) {
|
|
184
105
|
hookLogWarn(`stdin read failed for ${eventType}`);
|
|
106
|
+
void trackHookEvent(getInstanceId(), "hook_stdin_error", {
|
|
107
|
+
event_type: eventType,
|
|
108
|
+
cli,
|
|
109
|
+
error_type: err instanceof Error ? err.name : "unknown",
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (stdinOversized) {
|
|
113
|
+
void trackHookEvent(getInstanceId(), "hook_stdin_error", {
|
|
114
|
+
event_type: eventType,
|
|
115
|
+
cli,
|
|
116
|
+
error_type: "oversized",
|
|
117
|
+
});
|
|
185
118
|
}
|
|
186
119
|
|
|
187
120
|
let parsed: Record<string, unknown> = {};
|
|
@@ -190,6 +123,11 @@ export async function handleHookEvent(
|
|
|
190
123
|
parsed = JSON.parse(payload) as Record<string, unknown>;
|
|
191
124
|
} catch {
|
|
192
125
|
hookLogWarn(`payload parse failed for ${eventType} (${payload.length} bytes)`);
|
|
126
|
+
void trackHookEvent(getInstanceId(), "hook_payload_parse_error", {
|
|
127
|
+
event_type: eventType,
|
|
128
|
+
cli,
|
|
129
|
+
payload_size: payload.length,
|
|
130
|
+
});
|
|
193
131
|
}
|
|
194
132
|
}
|
|
195
133
|
|
|
@@ -340,25 +278,6 @@ export async function handleHookEvent(
|
|
|
340
278
|
hookLogWarn("activity persistence failed");
|
|
341
279
|
}
|
|
342
280
|
|
|
343
|
-
// Enqueue for server relay — fire-and-forget, never blocks hook.
|
|
344
|
-
// queue.ts is a no-op if the user is not logged in (no auth.json), and
|
|
345
|
-
// sanitizes the entry before persisting (drops toolInput/transcriptPath,
|
|
346
|
-
// hashes cwd, redacts known secret patterns in `reason`).
|
|
347
|
-
try {
|
|
348
|
-
const { appendToServerQueue } = await import("../relay/queue");
|
|
349
|
-
appendToServerQueue(activityEntry);
|
|
350
|
-
} catch {
|
|
351
|
-
// Server queue is best-effort; fail-open
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Lazy-start relay daemon if user is logged in — ~1ms when already running
|
|
355
|
-
try {
|
|
356
|
-
const { ensureRelayRunning } = await import("../relay/daemon");
|
|
357
|
-
ensureRelayRunning();
|
|
358
|
-
} catch {
|
|
359
|
-
// Relay is best-effort; hook must succeed regardless
|
|
360
|
-
}
|
|
361
|
-
|
|
362
281
|
// Fire PostHog telemetry for decisions that affect Claude's behavior
|
|
363
282
|
if (result.decision === "deny" || result.decision === "instruct") {
|
|
364
283
|
try {
|
|
@@ -13,6 +13,8 @@ import * as readline from "node:readline";
|
|
|
13
13
|
import { BUILTIN_POLICIES } from "./builtin-policies";
|
|
14
14
|
import { detectInstalledClis, getIntegration } from "./integrations";
|
|
15
15
|
import { INTEGRATION_TYPES, type IntegrationType } from "./types";
|
|
16
|
+
import { trackHookEvent } from "./hook-telemetry";
|
|
17
|
+
import { getInstanceId } from "../../lib/telemetry-id";
|
|
16
18
|
|
|
17
19
|
interface SelectItem {
|
|
18
20
|
name: string;
|
|
@@ -51,9 +53,29 @@ export async function resolveTargetClis(
|
|
|
51
53
|
explicit?: IntegrationType[],
|
|
52
54
|
action: CliPromptAction = "install",
|
|
53
55
|
): Promise<IntegrationType[]> {
|
|
54
|
-
|
|
56
|
+
const detected = explicit && explicit.length > 0 ? [] : detectInstalledClis();
|
|
57
|
+
const stdinIsTty = !!process.stdin.isTTY;
|
|
58
|
+
const explicitList = explicit && explicit.length > 0 ? [...new Set(explicit)] : [];
|
|
59
|
+
|
|
60
|
+
const fireDetectionEvent = (
|
|
61
|
+
selected: IntegrationType[],
|
|
62
|
+
resolutionMode: "explicit" | "single_detected" | "all_detected" | "interactive_prompt" | "defaulted_to_claude",
|
|
63
|
+
): void => {
|
|
64
|
+
void trackHookEvent(getInstanceId(), "cli_detection_summary", {
|
|
65
|
+
action,
|
|
66
|
+
detected_clis: detected,
|
|
67
|
+
explicit_clis: explicitList,
|
|
68
|
+
selected_clis: selected,
|
|
69
|
+
defaulted_to_claude: resolutionMode === "defaulted_to_claude",
|
|
70
|
+
stdin_is_tty: stdinIsTty,
|
|
71
|
+
resolution_mode: resolutionMode,
|
|
72
|
+
});
|
|
73
|
+
};
|
|
55
74
|
|
|
56
|
-
|
|
75
|
+
if (explicit && explicit.length > 0) {
|
|
76
|
+
fireDetectionEvent(explicitList, "explicit");
|
|
77
|
+
return explicitList;
|
|
78
|
+
}
|
|
57
79
|
|
|
58
80
|
if (detected.length === 0) {
|
|
59
81
|
if (action === "uninstall") {
|
|
@@ -63,12 +85,14 @@ export async function resolveTargetClis(
|
|
|
63
85
|
"\x1B[33mWarning: no agent CLI binary found in PATH (claude, codex, copilot, cursor-agent, opencode, pi, gemini). " +
|
|
64
86
|
"Defaulting to Claude Code; nothing will be removed if no settings file exists.\x1B[0m",
|
|
65
87
|
);
|
|
88
|
+
fireDetectionEvent(["claude"], "defaulted_to_claude");
|
|
66
89
|
return ["claude"];
|
|
67
90
|
}
|
|
68
91
|
console.log(
|
|
69
92
|
"\x1B[33mWarning: no agent CLI binary found in PATH (claude, codex, copilot, cursor-agent, opencode, pi, gemini). " +
|
|
70
93
|
"Defaulting to Claude Code; hooks will activate when an agent is installed.\x1B[0m",
|
|
71
94
|
);
|
|
95
|
+
fireDetectionEvent(["claude"], "defaulted_to_claude");
|
|
72
96
|
return ["claude"];
|
|
73
97
|
}
|
|
74
98
|
|
|
@@ -76,13 +100,19 @@ export async function resolveTargetClis(
|
|
|
76
100
|
const integration = getIntegration(detected[0]);
|
|
77
101
|
const verb = action === "uninstall" ? "removing hooks from" : "installing hooks for";
|
|
78
102
|
console.log(`Detected ${integration.displayName}; ${verb} it.`);
|
|
103
|
+
fireDetectionEvent(detected, "single_detected");
|
|
79
104
|
return detected;
|
|
80
105
|
}
|
|
81
106
|
|
|
82
107
|
// Multiple detected. Prompt or default.
|
|
83
|
-
if (!process.stdin.isTTY)
|
|
108
|
+
if (!process.stdin.isTTY) {
|
|
109
|
+
fireDetectionEvent(detected, "all_detected");
|
|
110
|
+
return detected;
|
|
111
|
+
}
|
|
84
112
|
|
|
85
|
-
|
|
113
|
+
const selected = await promptCliTargetSelection(detected, action);
|
|
114
|
+
fireDetectionEvent(selected, "interactive_prompt");
|
|
115
|
+
return selected;
|
|
86
116
|
}
|
|
87
117
|
|
|
88
118
|
/** Selectable row in the CLI target menu. Exported for unit tests. */
|
package/src/hooks/manager.ts
CHANGED
|
@@ -127,6 +127,13 @@ export async function installHooks(
|
|
|
127
127
|
for (const cliId of selectedClis) {
|
|
128
128
|
const integration = getIntegration(cliId);
|
|
129
129
|
if (!integration.scopes.includes(scope)) {
|
|
130
|
+
try {
|
|
131
|
+
await trackHookEvent(getInstanceId(), "scope_validation_failed", {
|
|
132
|
+
cli: cliId,
|
|
133
|
+
scope,
|
|
134
|
+
supported_scopes: integration.scopes,
|
|
135
|
+
});
|
|
136
|
+
} catch {}
|
|
130
137
|
throw new CliError(
|
|
131
138
|
`Scope "${scope}" is not supported by ${integration.displayName}. ` +
|
|
132
139
|
`Valid scopes: ${integration.scopes.join(", ")}`
|
|
@@ -171,10 +178,23 @@ export async function installHooks(
|
|
|
171
178
|
try {
|
|
172
179
|
validatedHooks = await loadCustomHooks(configToWrite.customPoliciesPath, { strict: true });
|
|
173
180
|
} catch (err) {
|
|
174
|
-
|
|
181
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
182
|
+
try {
|
|
183
|
+
await trackHookEvent(getInstanceId(), "custom_policy_validation_failed", {
|
|
184
|
+
scope,
|
|
185
|
+
error_type: /not found/i.test(msg) ? "file_not_found" : "load_error",
|
|
186
|
+
});
|
|
187
|
+
} catch {}
|
|
188
|
+
console.error(`Error: ${msg}`);
|
|
175
189
|
process.exit(1);
|
|
176
190
|
}
|
|
177
191
|
if (validatedHooks.length === 0) {
|
|
192
|
+
try {
|
|
193
|
+
await trackHookEvent(getInstanceId(), "custom_policy_validation_failed", {
|
|
194
|
+
scope,
|
|
195
|
+
error_type: "no_hooks_registered",
|
|
196
|
+
});
|
|
197
|
+
} catch {}
|
|
178
198
|
console.error(
|
|
179
199
|
`Error: no hooks registered in ${customPoliciesPath}. ` +
|
|
180
200
|
`Make sure your file calls customPolicies.add(...) at least once.`,
|
|
@@ -198,10 +218,26 @@ export async function installHooks(
|
|
|
198
218
|
for (const cliId of selectedClis) {
|
|
199
219
|
const integration = getIntegration(cliId);
|
|
200
220
|
const settingsPath = integration.getSettingsPath(scope, cwd);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
221
|
+
try {
|
|
222
|
+
const settings = integration.readSettings(settingsPath);
|
|
223
|
+
integration.writeHookEntries(settings, binaryPath, scope);
|
|
224
|
+
integration.writeSettings(settingsPath, settings);
|
|
225
|
+
writtenSettingsPaths.push({ cli: cliId, path: settingsPath });
|
|
226
|
+
} catch (err) {
|
|
227
|
+
const errorType = err instanceof Error && /EACCES|EPERM/.test(err.message)
|
|
228
|
+
? "permission_denied"
|
|
229
|
+
: err instanceof Error && /ENOENT|ENOTDIR/.test(err.message)
|
|
230
|
+
? "path_not_found"
|
|
231
|
+
: "write_error";
|
|
232
|
+
try {
|
|
233
|
+
await trackHookEvent(getInstanceId(), "hook_write_failed", {
|
|
234
|
+
cli: cliId,
|
|
235
|
+
scope,
|
|
236
|
+
error_type: errorType,
|
|
237
|
+
});
|
|
238
|
+
} catch {}
|
|
239
|
+
throw err;
|
|
240
|
+
}
|
|
205
241
|
}
|
|
206
242
|
|
|
207
243
|
// Telemetry: track successful hook installation (with diff vs previous config)
|
|
@@ -228,6 +264,20 @@ export async function installHooks(
|
|
|
228
264
|
param_policy_names: configToWrite.policyParams ? Object.keys(configToWrite.policyParams) : [],
|
|
229
265
|
command_format: scope === "project" ? "npx" : "absolute",
|
|
230
266
|
});
|
|
267
|
+
|
|
268
|
+
if (includeBeta) {
|
|
269
|
+
const betaNames = new Set(BUILTIN_POLICIES.filter((p) => p.beta).map((p) => p.name));
|
|
270
|
+
const installedBeta = selectedPolicies.filter((p) => betaNames.has(p));
|
|
271
|
+
if (installedBeta.length > 0) {
|
|
272
|
+
await trackHookEvent(distinctId, "beta_policies_installed", {
|
|
273
|
+
scope,
|
|
274
|
+
cli: selectedClis,
|
|
275
|
+
beta_count: installedBeta.length,
|
|
276
|
+
beta_policy_names: installedBeta,
|
|
277
|
+
...(source ? { source } : {}),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
231
281
|
} catch {
|
|
232
282
|
// Telemetry is best-effort — never block the operation
|
|
233
283
|
}
|
|
@@ -257,6 +307,13 @@ export async function installHooks(
|
|
|
257
307
|
console.log(`Having hooks in multiple scopes may cause duplicate policy evaluation.`);
|
|
258
308
|
console.log(`Use \`failproofai policies --uninstall --scope ${duplicates[0]}\` to remove the other installation,`);
|
|
259
309
|
console.log(`or \`failproofai policies\` to see all scopes.`);
|
|
310
|
+
try {
|
|
311
|
+
await trackHookEvent(getInstanceId(), "multi_scope_warning_shown", {
|
|
312
|
+
new_scope: scope,
|
|
313
|
+
existing_scopes: duplicates,
|
|
314
|
+
cli: selectedClis,
|
|
315
|
+
});
|
|
316
|
+
} catch {}
|
|
260
317
|
}
|
|
261
318
|
}
|
|
262
319
|
|
|
@@ -558,11 +615,21 @@ export async function listHooks(cwd?: string): Promise<void> {
|
|
|
558
615
|
|
|
559
616
|
// Warn about unknown policyParams keys
|
|
560
617
|
if (config.policyParams) {
|
|
618
|
+
const unknownKeys: string[] = [];
|
|
561
619
|
for (const key of Object.keys(config.policyParams)) {
|
|
562
620
|
if (!builtinPolicyNames.has(key)) {
|
|
563
621
|
console.log(` \x1B[33mWarning: unknown policyParams key "${key}" — possible typo\x1B[0m`);
|
|
622
|
+
unknownKeys.push(key);
|
|
564
623
|
}
|
|
565
624
|
}
|
|
625
|
+
if (unknownKeys.length > 0) {
|
|
626
|
+
try {
|
|
627
|
+
await trackHookEvent(getInstanceId(), "policy_params_validation_warning", {
|
|
628
|
+
unknown_keys_count: unknownKeys.length,
|
|
629
|
+
unknown_keys: unknownKeys,
|
|
630
|
+
});
|
|
631
|
+
} catch {}
|
|
632
|
+
}
|
|
566
633
|
}
|
|
567
634
|
|
|
568
635
|
// Custom Policies section
|
|
@@ -7,6 +7,8 @@ import type { PolicyContext, HooksConfig } from "./policy-types";
|
|
|
7
7
|
import { BUILTIN_POLICIES } from "./builtin-policies";
|
|
8
8
|
import { DEFAULT_POLICY_NAMESPACE, getPoliciesForEvent, normalizePolicyName } from "./policy-registry";
|
|
9
9
|
import { hookLogInfo, hookLogWarn } from "./hook-logger";
|
|
10
|
+
import { trackHookEvent } from "./hook-telemetry";
|
|
11
|
+
import { getInstanceId } from "../../lib/telemetry-id";
|
|
10
12
|
|
|
11
13
|
function appendHint(baseReason: string, hint: unknown): string {
|
|
12
14
|
const base = baseReason.trim();
|
|
@@ -35,11 +37,11 @@ const POLICY_PARAMS_MAP = new Map(
|
|
|
35
37
|
/**
|
|
36
38
|
* Look up policy params for a canonical policy name in the user config,
|
|
37
39
|
* tolerating either flat ("block-force-push") or qualified
|
|
38
|
-
* ("
|
|
40
|
+
* ("failproofai/block-force-push") config keys for built-in policies.
|
|
39
41
|
*
|
|
40
42
|
* The flat-key fallback is intentionally limited to the default namespace
|
|
41
43
|
* so namespace isolation is preserved: `policyParams.foo` only matches
|
|
42
|
-
* `
|
|
44
|
+
* `failproofai/foo`, never `myorg/foo` or `custom/foo`.
|
|
43
45
|
*/
|
|
44
46
|
function getConfigParamsFor(
|
|
45
47
|
config: HooksConfig | undefined,
|
|
@@ -87,7 +89,7 @@ export async function evaluatePolicies(
|
|
|
87
89
|
|
|
88
90
|
for (const policy of policies) {
|
|
89
91
|
// Inject params: merge policyParams[policy.name] over schema defaults.
|
|
90
|
-
// policy.name is canonical (e.g. "
|
|
92
|
+
// policy.name is canonical (e.g. "failproofai/block-force-push"); user
|
|
91
93
|
// config keys may be flat or canonical — getConfigParamsFor accepts both.
|
|
92
94
|
const schema = POLICY_PARAMS_MAP.get(policy.name);
|
|
93
95
|
let ctx: PolicyContext;
|
|
@@ -107,7 +109,20 @@ export async function evaluatePolicies(
|
|
|
107
109
|
try {
|
|
108
110
|
result = await policy.fn(ctx);
|
|
109
111
|
} catch (err) {
|
|
110
|
-
|
|
112
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
113
|
+
hookLogWarn(`policy "${policy.name}" threw: ${msg}`);
|
|
114
|
+
// Custom hooks are wrapped in handler.ts with their own try/catch that
|
|
115
|
+
// emits custom_hook_error. Anything reaching here is a builtin policy
|
|
116
|
+
// crash — track separately so we can surface regressions in builtins.
|
|
117
|
+
const isCustom = policy.name.startsWith("custom/") || policy.name.startsWith(".failproofai-");
|
|
118
|
+
if (!isCustom) {
|
|
119
|
+
void trackHookEvent(getInstanceId(), "policy_evaluation_error", {
|
|
120
|
+
policy_name: policy.name,
|
|
121
|
+
event_type: eventType,
|
|
122
|
+
cli: session?.cli ?? null,
|
|
123
|
+
error_type: err instanceof Error ? err.name : "unknown",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
111
126
|
continue;
|
|
112
127
|
}
|
|
113
128
|
|
|
@@ -16,7 +16,7 @@ const INDEX_CACHE_KEY = "__FAILPROOFAI_POLICY_INDEX_CACHE__";
|
|
|
16
16
|
* `<namespace>/` prefix. Builtins live under this namespace; custom hooks
|
|
17
17
|
* loaded by the handler get their own prefixes (e.g. `custom/foo`).
|
|
18
18
|
*/
|
|
19
|
-
export const DEFAULT_POLICY_NAMESPACE = "
|
|
19
|
+
export const DEFAULT_POLICY_NAMESPACE = "failproofai";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Canonicalize a policy name. If the name already contains a `/`, it is
|
|
@@ -54,6 +54,15 @@ export interface BuiltinPolicyDefinition {
|
|
|
54
54
|
category: string;
|
|
55
55
|
beta?: boolean;
|
|
56
56
|
params?: PolicyParamsSchema;
|
|
57
|
+
/** User-facing past-tense phrase used in `failproofai audit` output.
|
|
58
|
+
* Frames the agent's action as something the user observes after-the-fact,
|
|
59
|
+
* e.g. "Tried to push to main branch" or "Redacted JWT from tool output".
|
|
60
|
+
* Falls back to `description` when omitted. */
|
|
61
|
+
displayTitle?: string;
|
|
62
|
+
/** One short clause describing the consequence of the action, used as a
|
|
63
|
+
* secondary line in the audit report. e.g. "Could leak code from neighboring
|
|
64
|
+
* repos to the model." */
|
|
65
|
+
impact?: string;
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
export interface CustomHook {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-CLI canonicalization of tool names and tool-input keys.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from handler.ts so the audit replay engine and the live hook
|
|
5
|
+
* handler share one implementation. Re-importing this module from
|
|
6
|
+
* `src/audit/cli-adapters/*.ts` keeps the per-CLI maps in one place.
|
|
7
|
+
*/
|
|
8
|
+
import type { IntegrationType } from "./types";
|
|
9
|
+
import {
|
|
10
|
+
CODEX_TOOL_MAP,
|
|
11
|
+
COPILOT_TOOL_MAP,
|
|
12
|
+
CURSOR_TOOL_MAP,
|
|
13
|
+
OPENCODE_TOOL_MAP,
|
|
14
|
+
OPENCODE_TOOL_INPUT_MAP,
|
|
15
|
+
PI_TOOL_MAP,
|
|
16
|
+
PI_TOOL_INPUT_MAP,
|
|
17
|
+
GEMINI_TOOL_MAP,
|
|
18
|
+
} from "./types";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Canonicalize a per-CLI tool name to the Claude PascalCase form that builtin
|
|
22
|
+
* policies match on (e.g. `Bash`, `Read`, `Write`, `Edit`). Unknown tool names
|
|
23
|
+
* (MCP `mcp_*`, third-party extensions, Skills) pass through unchanged.
|
|
24
|
+
*/
|
|
25
|
+
export function canonicalizeToolName(
|
|
26
|
+
raw: string | undefined,
|
|
27
|
+
cli: IntegrationType,
|
|
28
|
+
): string | undefined {
|
|
29
|
+
if (!raw) return raw;
|
|
30
|
+
if (cli === "copilot") return COPILOT_TOOL_MAP[raw] ?? raw;
|
|
31
|
+
if (cli === "cursor") return CURSOR_TOOL_MAP[raw] ?? raw;
|
|
32
|
+
if (cli === "codex") return CODEX_TOOL_MAP[raw] ?? raw;
|
|
33
|
+
if (cli === "gemini") return GEMINI_TOOL_MAP[raw] ?? raw;
|
|
34
|
+
if (cli === "opencode") return OPENCODE_TOOL_MAP[raw] ?? raw;
|
|
35
|
+
if (cli === "pi") return PI_TOOL_MAP[raw] ?? raw;
|
|
36
|
+
return raw;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Canonicalize per-CLI tool-input keys to the snake_case shape that builtin
|
|
41
|
+
* policies read (e.g. `file_path`, `old_string`). OpenCode delivers args as
|
|
42
|
+
* camelCase; Pi delivers `path` for Read/Write/Edit. Idempotent — when already
|
|
43
|
+
* canonical the loop is a no-op.
|
|
44
|
+
*/
|
|
45
|
+
export function canonicalizeToolInput(
|
|
46
|
+
toolName: string | undefined,
|
|
47
|
+
rawInput: unknown,
|
|
48
|
+
cli: IntegrationType,
|
|
49
|
+
): unknown {
|
|
50
|
+
// Arrays are objects too — pass them through verbatim instead of letting
|
|
51
|
+
// Object.entries flatten them into a numeric-keyed plain object (which would
|
|
52
|
+
// silently corrupt array-shaped tool inputs).
|
|
53
|
+
if (!toolName || !rawInput || typeof rawInput !== "object" || Array.isArray(rawInput)) {
|
|
54
|
+
return rawInput;
|
|
55
|
+
}
|
|
56
|
+
let perToolMap: Record<string, string> | undefined;
|
|
57
|
+
if (cli === "opencode") perToolMap = OPENCODE_TOOL_INPUT_MAP[toolName];
|
|
58
|
+
else if (cli === "pi") perToolMap = PI_TOOL_INPUT_MAP[toolName];
|
|
59
|
+
if (!perToolMap) return rawInput;
|
|
60
|
+
const out: Record<string, unknown> = {};
|
|
61
|
+
for (const [k, v] of Object.entries(rawInput as Record<string, unknown>)) {
|
|
62
|
+
out[perToolMap[k] ?? k] = v;
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[46786,(a,b,c)=>{b.exports=a.x("os",()=>require("os"))},12714,(a,b,c)=>{b.exports=a.x("node:fs/promises",()=>require("node:fs/promises"))},90798,a=>{"use strict";var b=a.i(46786),c=a.i(14747);a.s(["decodeFolderName",0,function(a){return/^[A-Za-z]--/.test(a)?a[0]+":/"+a.slice(3).replace(/-/g,"/"):a.replace(/-/g,"/")},"encodeFolderName",0,function(a){let b=/^([A-Za-z]):[\\/](.*)$/.exec(a);return b?b[1]+"--"+b[2].replace(/[\\/]/g,"-"):a.replace(/[\\/]/g,"-")},"getClaudeProjectsPath",0,function(){let a=process.env.CLAUDE_PROJECTS_PATH;return a||(0,c.join)((0,b.homedir)(),".claude","projects")}])},34900,a=>{"use strict";a.s(["runtimeCache",0,function(a,b,c){let d=new Map,e=new Map,f=c?.maxSize;return async(...c)=>{let g=JSON.stringify(c),h=d.get(g);if(h&&Date.now()<h.expiry)return h.data;let i=e.get(g);if(i)return i;let j=a(...c).then(a=>{if(e.delete(g),f&&d.size>=f){let a=d.keys().next().value;d.delete(a)}return d.set(g,{data:a,expiry:Date.now()+1e3*b}),a},a=>{throw e.delete(g),a});return e.set(g,j),j}}])},76668,a=>{"use strict";let b=1;function c(a){return`[failproofai${new Date().toISOString()}] ${a}`}a.s(["logError",0,function(a,b){void 0!==b?console.error(c("ERROR"),a,b):console.error(c("ERROR"),a)},"logWarn",0,function(a,d){b>=b&&(void 0!==d?console.warn(c("WARN"),a,d):console.warn(c("WARN"),a))}])},33432,a=>{"use strict";a.s(["formatDate",0,function(a){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).format(a)}])},26192,a=>{"use strict";async function b(a,b){let c=Array(a.length),d=0;async function e(){for(;d<a.length;){let b=d++;try{c[b]={status:"fulfilled",value:await a[b]()}}catch(a){c[b]={status:"rejected",reason:a}}}}let f=Array.from({length:Math.min(b,a.length)},()=>e());return await Promise.all(f),c}a.s(["batchAll",0,b])},50640,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"InvariantError",{enumerable:!0,get:function(){return d}});class d extends Error{constructor(a,b){super(`Invariant: ${a.endsWith(".")?a:a+"."} This is a bug in Next.js.`,b),this.name="InvariantError"}}},64240,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},93695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},71306,(a,b,c)=>{b.exports=a.r(18622)},79847,a=>{a.n(a.i(3343))},9185,a=>{a.n(a.i(29432))},72842,a=>{a.n(a.i(75164))},54897,a=>{a.n(a.i(30106))},56157,a=>{a.n(a.i(18970))},94331,a=>{a.n(a.i(60644))},15988,a=>{a.n(a.i(56952))},25766,a=>{a.n(a.i(77341))},29725,a=>{a.n(a.i(94290))},5785,a=>{a.n(a.i(90588))},74793,a=>{a.n(a.i(33169))},85826,a=>{a.n(a.i(37111))},21565,a=>{a.n(a.i(41763))},65911,a=>{a.n(a.i(8950))},25128,a=>{a.n(a.i(91562))},40781,a=>{a.n(a.i(49670))},69411,a=>{a.n(a.i(75700))},63081,a=>{a.n(a.i(276))},62837,a=>{a.n(a.i(40795))},34607,a=>{a.n(a.i(11614))},96338,a=>{a.n(a.i(21751))},50642,a=>{a.n(a.i(12213))},32242,a=>{a.n(a.i(22693))},88530,a=>{a.n(a.i(10531))},8583,a=>{a.n(a.i(1082))},38534,a=>{a.n(a.i(98175))},70408,a=>{a.n(a.i(9095))},22922,a=>{a.n(a.i(96772))},78294,a=>{a.n(a.i(71717))},16625,a=>{a.n(a.i(85034))},88648,a=>{a.n(a.i(68113))},51914,a=>{a.n(a.i(66482))},25466,a=>{a.n(a.i(91505))},69191,a=>{"use strict";var b=a.i(12714),c=a.i(50227),d=a.i(90798),e=a.i(34900),f=a.i(26192),g=a.i(76668),h=a.i(33432);async function i(a,c){try{return(await (0,b.stat)(a)).mtime}catch(a){return(0,g.logWarn)(`Failed to stat ${c}:`,a),new Date(0)}}async function j(a){try{if(!(await (0,b.stat)(a)).isDirectory())return null;return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function k(){try{let a=(0,d.getClaudeProjectsPath)(),b=await j(a);if(!b)return[];let e=(await (0,f.batchAll)(b.filter(a=>a.isDirectory()).map(b=>async()=>{let d=(0,c.join)(a,b.name),e=await i(d,b.name);return{name:b.name,path:d,isDirectory:!0,lastModified:e,lastModifiedFormatted:(0,h.formatDate)(e),cli:["claude"]}}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value);return e.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),e}catch(a){return(0,g.logError)("Error reading Claude project folders:",a),[]}}async function l(){let[{getCodexProjects:b},{getCopilotProjects:c},{getCursorProjects:d},{getOpenCodeProjects:e},{getPiProjects:f},{getGeminiProjects:h}]=await Promise.all([a.A(93658),a.A(60956),a.A(26244),a.A(2164),a.A(92351),a.A(26396)]),[i,j,l,m,n,o,p]=await Promise.all([k(),b().catch(a=>((0,g.logError)("Error reading Codex projects:",a),[])),c().catch(a=>((0,g.logError)("Error reading Copilot projects:",a),[])),d().catch(a=>((0,g.logError)("Error reading Cursor projects:",a),[])),e().catch(a=>((0,g.logError)("Error reading OpenCode projects:",a),[])),f().catch(a=>((0,g.logError)("Error reading Pi projects:",a),[])),h().catch(a=>((0,g.logError)("Error reading Gemini projects:",a),[]))]);return function(...a){let b=new Map;for(let c of a)for(let a of c){let c=b.get(a.name);if(!c){b.set(a.name,{...a,cli:[...a.cli]});continue}let d=[...c.cli];for(let b of a.cli)d.includes(b)||d.push(b);let e=a.lastModified.getTime()>c.lastModified.getTime()?a:c;b.set(a.name,{...c,cli:d,lastModified:e.lastModified,lastModifiedFormatted:e.lastModifiedFormatted})}let c=Array.from(b.values());return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}(i,j,l,m,n,o,p)}function m(a){let b=a.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);return b?b[0]:void 0}async function n(a){try{let b=await j(a);if(!b)return[];let d=b.filter(a=>a.isFile()&&a.name.endsWith(".jsonl")&&m(a.name)),e=(await (0,f.batchAll)(d.map(b=>async()=>{let d=(0,c.join)(a,b.name),e=await i(d,b.name);return{name:b.name,path:d,lastModified:e,lastModifiedFormatted:(0,h.formatDate)(e),sessionId:m(b.name),cli:"claude"}}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value);return e.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),e}catch(a){return(0,g.logError)("Error reading session files:",a),[]}}let o=(0,e.runtimeCache)(l,30),p=(0,e.runtimeCache)(a=>n(a),30);a.s(["UUID_RE",0,/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/,"getCachedProjectFolders",0,o,"getCachedSessionFiles",0,p,"resolveProjectPath",0,function(a){if(!a)throw RangeError("Empty project name");if(/^[/\\]/.test(a))throw RangeError("Absolute project name");let b=(0,c.resolve)((0,d.getClaudeProjectsPath)()),e=(0,c.resolve)((0,c.join)(b,a));if(!e.startsWith(b+c.sep))throw RangeError("Project path escapes root");return e}])},71224,a=>{a.v("/_next/static/media/icon.0a.gigb3_x5pd.png"+(globalThis.NEXT_CLIENT_ASSET_SUFFIX||""))},1022,a=>{"use strict";let b={src:a.i(71224).default,width:1920,height:1920};a.s(["default",0,b])},82165,a=>{"use strict";a.s(["default",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call the default export of [project]/app/components/project-list.tsx <module evaluation> from the server, but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/app/components/project-list.tsx <module evaluation>","default")},92887,a=>{"use strict";a.s(["default",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call the default export of [project]/app/components/project-list.tsx from the server, but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/app/components/project-list.tsx","default")},17048,a=>{"use strict";a.i(82165);var b=a.i(92887);a.n(b)},61594,a=>{"use strict";var b=a.i(7997),c=a.i(717);a.i(70396);var d=a.i(73727),e=a.i(69191),f=a.i(17048);async function g(){(process.env.FAILPROOFAI_DISABLE_PAGES??"").split(",").map(a=>a.trim()).filter(Boolean).includes("projects")&&(0,d.notFound)();let a=await (0,e.getCachedProjectFolders)();return(0,b.jsx)("main",{className:"min-h-screen bg-background",children:(0,b.jsx)("div",{className:"container mx-auto p-8",children:(0,b.jsxs)("div",{className:"bg-card text-card-foreground rounded-lg border border-border p-6 shadow-sm",children:[(0,b.jsx)("h2",{className:"text-2xl font-semibold mb-4",children:"Projects"}),0===a.length?(0,b.jsxs)("div",{className:"text-center py-8",children:[(0,b.jsx)("p",{className:"text-muted-foreground mb-2",children:"No projects found in the .claude/projects directory."}),(0,b.jsx)("p",{className:"text-sm text-muted-foreground",children:"Make sure the directory exists and contains project folders."})]}):(0,b.jsx)(c.Suspense,{children:(0,b.jsx)(f.default,{folders:a})})]})})})}a.s(["default",0,g,"dynamic",0,"force-dynamic"])},19057,a=>{a.n(a.i(61594))},93658,a=>{a.v(b=>Promise.all(["server/chunks/ssr/lib_codex-projects_ts_0eosib~._.js"].map(b=>a.l(b))).then(()=>b(1024)))},60956,a=>{a.v(b=>Promise.all(["server/chunks/ssr/lib_copilot-projects_ts_0r8xkn8._.js"].map(b=>a.l(b))).then(()=>b(88890)))},26244,a=>{a.v(b=>Promise.all(["server/chunks/ssr/lib_cursor-projects_ts_0qt1scg._.js"].map(b=>a.l(b))).then(()=>b(93087)))},2164,a=>{a.v(b=>Promise.all(["server/chunks/ssr/lib_opencode-projects_ts_0op9gyp._.js"].map(b=>a.l(b))).then(()=>b(64458)))},92351,a=>{a.v(b=>Promise.all(["server/chunks/ssr/lib_pi-projects_ts_103tsh1._.js"].map(b=>a.l(b))).then(()=>b(2727)))},26396,a=>{a.v(b=>Promise.all(["server/chunks/ssr/lib_gemini-projects_ts_0sl~yqr._.js"].map(b=>a.l(b))).then(()=>b(62074)))}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__0609ezh._.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[46786,(a,b,c)=>{b.exports=a.x("os",()=>require("os"))},12714,(a,b,c)=>{b.exports=a.x("node:fs/promises",()=>require("node:fs/promises"))},24868,(a,b,c)=>{b.exports=a.x("fs/promises",()=>require("fs/promises"))},90798,a=>{"use strict";var b=a.i(46786),c=a.i(14747);a.s(["decodeFolderName",0,function(a){return/^[A-Za-z]--/.test(a)?a[0]+":/"+a.slice(3).replace(/-/g,"/"):a.replace(/-/g,"/")},"encodeFolderName",0,function(a){let b=/^([A-Za-z]):[\\/](.*)$/.exec(a);return b?b[1]+"--"+b[2].replace(/[\\/]/g,"-"):a.replace(/[\\/]/g,"-")},"getClaudeProjectsPath",0,function(){let a=process.env.CLAUDE_PROJECTS_PATH;return a||(0,c.join)((0,b.homedir)(),".claude","projects")}])},34900,a=>{"use strict";a.s(["runtimeCache",0,function(a,b,c){let d=new Map,e=new Map,f=c?.maxSize;return async(...c)=>{let g=JSON.stringify(c),h=d.get(g);if(h&&Date.now()<h.expiry)return h.data;let i=e.get(g);if(i)return i;let j=a(...c).then(a=>{if(e.delete(g),f&&d.size>=f){let a=d.keys().next().value;d.delete(a)}return d.set(g,{data:a,expiry:Date.now()+1e3*b}),a},a=>{throw e.delete(g),a});return e.set(g,j),j}}])},76668,a=>{"use strict";let b=1;function c(a){return`[failproofai${new Date().toISOString()}] ${a}`}a.s(["logError",0,function(a,b){void 0!==b?console.error(c("ERROR"),a,b):console.error(c("ERROR"),a)},"logWarn",0,function(a,d){b>=b&&(void 0!==d?console.warn(c("WARN"),a,d):console.warn(c("WARN"),a))}])},33432,a=>{"use strict";a.s(["formatDate",0,function(a){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).format(a)}])},26192,a=>{"use strict";async function b(a,b){let c=Array(a.length),d=0;async function e(){for(;d<a.length;){let b=d++;try{c[b]={status:"fulfilled",value:await a[b]()}}catch(a){c[b]={status:"rejected",reason:a}}}}let f=Array.from({length:Math.min(b,a.length)},()=>e());return await Promise.all(f),c}a.s(["batchAll",0,b])},50640,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"InvariantError",{enumerable:!0,get:function(){return d}});class d extends Error{constructor(a,b){super(`Invariant: ${a.endsWith(".")?a:a+"."} This is a bug in Next.js.`,b),this.name="InvariantError"}}},64240,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},93695,(a,b,c)=>{b.exports=a.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},71306,(a,b,c)=>{b.exports=a.r(18622)},79847,a=>{a.n(a.i(3343))},9185,a=>{a.n(a.i(29432))},72842,a=>{a.n(a.i(75164))},54897,a=>{a.n(a.i(30106))},56157,a=>{a.n(a.i(18970))},94331,a=>{a.n(a.i(60644))},15988,a=>{a.n(a.i(56952))},25766,a=>{a.n(a.i(77341))},29725,a=>{a.n(a.i(94290))},5785,a=>{a.n(a.i(90588))},74793,a=>{a.n(a.i(33169))},85826,a=>{a.n(a.i(37111))},21565,a=>{a.n(a.i(41763))},65911,a=>{a.n(a.i(8950))},25128,a=>{a.n(a.i(91562))},40781,a=>{a.n(a.i(49670))},69411,a=>{a.n(a.i(75700))},63081,a=>{a.n(a.i(276))},62837,a=>{a.n(a.i(40795))},34607,a=>{a.n(a.i(11614))},96338,a=>{a.n(a.i(21751))},50642,a=>{a.n(a.i(12213))},32242,a=>{a.n(a.i(22693))},88530,a=>{a.n(a.i(10531))},8583,a=>{a.n(a.i(1082))},38534,a=>{a.n(a.i(98175))},70408,a=>{a.n(a.i(9095))},22922,a=>{a.n(a.i(96772))},78294,a=>{a.n(a.i(71717))},16625,a=>{a.n(a.i(85034))},88648,a=>{a.n(a.i(68113))},51914,a=>{a.n(a.i(66482))},25466,a=>{a.n(a.i(91505))},22734,(a,b,c)=>{b.exports=a.x("fs",()=>require("fs"))},88890,a=>{"use strict";var b=a.i(12714),c=a.i(60526),d=a.i(50227),e=a.i(90798),f=a.i(34900),g=a.i(26192),h=a.i(33432),i=a.i(76668);async function j(a){try{return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function k(a){try{return(await (0,b.stat)(a)).mtime}catch{return null}}async function l(){let a=(0,d.join)(process.env.COPILOT_HOME||(0,d.join)((0,c.homedir)(),".copilot"),"session-state"),e=await j(a);if(!e)return[];let f=e.filter(a=>a.isDirectory()).map(b=>({sessionId:b.name,workspacePath:(0,d.join)(a,b.name,"workspace.yaml"),eventsPath:(0,d.join)(a,b.name,"events.jsonl")}));return(await (0,g.batchAll)(f.map(a=>async()=>{let c;try{c=await (0,b.readFile)(a.workspacePath,"utf-8")}catch{return null}let d=function(a){let b=a.match(/^cwd\s*:\s*(.+?)\s*$/m);if(b)return b[1].replace(/^['"]|['"]$/g,"")}(c);if(!d)return null;let e=await k(a.eventsPath),f=await k(a.workspacePath),g=null!==e,h=e&&f?new Date(Math.max(e.getTime(),f.getTime())):e??f??new Date(0);return{workspacePath:a.workspacePath,eventsPath:a.eventsPath,sessionId:a.sessionId,cwd:d,fileMtime:h,hasTranscript:g}}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value).filter(a=>null!==a)}let m=(0,f.runtimeCache)(l,30);async function n(){let a;try{a=await m()}catch(a){return(0,i.logWarn)("Failed to scan Copilot sessions:",a),[]}let b=new Map;for(let c of a){if(!c.hasTranscript)continue;let a=b.get(c.cwd);(!a||c.fileMtime.getTime()>a.latest.getTime())&&b.set(c.cwd,{latest:c.fileMtime,cwd:c.cwd})}let c=[];for(let{cwd:a,latest:d}of b.values())c.push({name:(0,e.encodeFolderName)(a),path:a,isDirectory:!0,lastModified:d,lastModifiedFormatted:(0,h.formatDate)(d),cli:["copilot"]});return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}function o(a){let b=a.filter(a=>a.hasTranscript).map(a=>({name:a.sessionId,path:a.eventsPath,lastModified:a.fileMtime,lastModifiedFormatted:(0,h.formatDate)(a.fileMtime),sessionId:a.sessionId,cli:"copilot"}));return b.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),b}async function p(a){let b;try{b=await m()}catch(a){return(0,i.logWarn)("Failed to scan Copilot sessions:",a),[]}return o(b.filter(b=>b.cwd===a))}async function q(a){let b;try{b=await m()}catch(a){return(0,i.logWarn)("Failed to scan Copilot sessions:",a),{cwd:null,sessions:[]}}let c=b.filter(b=>b.hasTranscript&&(0,e.encodeFolderName)(b.cwd)===a);return{cwd:c[0]?.cwd??null,sessions:o(c)}}let r=(0,f.runtimeCache)(n,30),s=(0,f.runtimeCache)(a=>p(a),30,{maxSize:50}),t=(0,f.runtimeCache)(a=>q(a),30,{maxSize:50});a.s(["getCachedCopilotProjects",0,r,"getCachedCopilotSessionsByEncodedName",0,t,"getCachedCopilotSessionsForCwd",0,s,"getCopilotProjects",0,n,"getCopilotSessionsByEncodedName",0,q,"getCopilotSessionsForCwd",0,p])},1024,a=>{"use strict";var b=a.i(12714),c=a.i(60526),d=a.i(50227),e=a.i(90798),f=a.i(34900),g=a.i(26192),h=a.i(33432),i=a.i(76668);let j=(0,d.join)((0,c.homedir)(),".codex","sessions"),k=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;async function l(a){try{return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function m(a){let c=null;try{c=await (0,b.open)(a,"r");let d=Buffer.alloc(262144),{bytesRead:e}=await c.read(d,0,262144,0);if(0===e)return null;let f=d.subarray(0,e),g=f.indexOf(10),h=-1===g?e:g;return f.subarray(0,h).toString("utf-8")}catch{return null}finally{c&&await c.close().catch(()=>{})}}async function n(a){let b=await l(a);return b?b.filter(a=>a.isFile()&&a.name.endsWith(".jsonl")).map(b=>(0,d.join)(a,b.name)):[]}async function o(){let a=await l(j);if(!a)return[];let c=[];for(let b of a){if(!b.isDirectory())continue;let a=await l((0,d.join)(j,b.name));if(a)for(let e of a){if(!e.isDirectory())continue;let a=await l((0,d.join)(j,b.name,e.name));if(a)for(let f of a){if(!f.isDirectory())continue;let a=(0,d.join)(j,b.name,e.name,f.name);c.push(...await n(a))}}}return 0===c.length?[]:(await (0,g.batchAll)(c.map(a=>async()=>{let c,d,e=(d=(a.split("/").pop()??"").match(k))?d[0]:null;if(!e)return null;let f=await m(a);if(!f)return null;let{cwd:g}=function(a){try{let b=JSON.parse(a);if("session_meta"!==b.type)return{};let c=b.payload?.cwd;if("string"!=typeof c||0===c.length)return{};return{cwd:c}}catch{return{}}}(f);if(!g)return null;try{let d=await (0,b.open)(a,"r");try{c=(await d.stat()).mtime}finally{await d.close().catch(()=>{})}}catch{c=new Date(0)}return{filePath:a,fileName:a.split("/").pop()??"",cwd:g,sessionId:e,fileMtime:c}}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value).filter(a=>null!==a)}let p=(0,f.runtimeCache)(o,30);async function q(){let a;try{a=await p()}catch(a){return(0,i.logWarn)("Failed to scan Codex sessions:",a),[]}let b=new Map;for(let c of a){let a=b.get(c.cwd);(!a||c.fileMtime.getTime()>a.latest.getTime())&&b.set(c.cwd,{latest:c.fileMtime,cwd:c.cwd})}let c=[];for(let{cwd:a,latest:d}of b.values())c.push({name:(0,e.encodeFolderName)(a),path:a,isDirectory:!0,lastModified:d,lastModifiedFormatted:(0,h.formatDate)(d),cli:["codex"]});return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}function r(a){let b=a.map(a=>({name:a.fileName.replace(/\.jsonl$/,""),path:a.filePath,lastModified:a.fileMtime,lastModifiedFormatted:(0,h.formatDate)(a.fileMtime),sessionId:a.sessionId,cli:"codex"}));return b.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),b}async function s(a){let b;try{b=await p()}catch(a){return(0,i.logWarn)("Failed to scan Codex sessions:",a),[]}return r(b.filter(b=>b.cwd===a))}async function t(a){let b;try{b=await p()}catch(a){return(0,i.logWarn)("Failed to scan Codex sessions:",a),{cwd:null,sessions:[]}}let c=b.filter(b=>(0,e.encodeFolderName)(b.cwd)===a);return{cwd:c[0]?.cwd??null,sessions:r(c)}}let u=(0,f.runtimeCache)(q,30),v=(0,f.runtimeCache)(a=>s(a),30,{maxSize:50}),w=(0,f.runtimeCache)(a=>t(a),30,{maxSize:50});a.s(["getCachedCodexProjects",0,u,"getCachedCodexSessionsByEncodedName",0,w,"getCachedCodexSessionsForCwd",0,v,"getCodexProjects",0,q,"getCodexSessionsByEncodedName",0,t,"getCodexSessionsForCwd",0,s])},2727,a=>{"use strict";var b=a.i(12714),c=a.i(60526),d=a.i(50227),e=a.i(90798),f=a.i(34900),g=a.i(26192),h=a.i(33432),i=a.i(76668);let j=/^[\d-]+T[\d-]+Z_([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i;async function k(a){try{return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function l(a){try{return(await (0,b.stat)(a)).mtime}catch{return null}}async function m(a){let c;try{c=await (0,b.readFile)(a,"utf-8")}catch{return null}let d=c.indexOf("\n")>=0?c.slice(0,c.indexOf("\n")):c;if(!d)return null;try{let a=JSON.parse(d);if("session"!==a.type||"string"!=typeof a.cwd||0===a.cwd.length)return null;return a.cwd}catch{return null}}async function n(){let a=process.env.PI_SESSIONS_DIR||(0,d.join)((0,c.homedir)(),".pi","agent","sessions"),b=await k(a);if(!b)return[];let e=[];for(let c of b){if(!c.isDirectory())continue;let b=(0,d.join)(a,c.name),f=await k(b);if(f)for(let a of f){if(!a.isFile())continue;let c=j.exec(a.name);c&&e.push({sessionId:c[1],filePath:(0,d.join)(b,a.name)})}}return 0===e.length?[]:(await (0,g.batchAll)(e.map(a=>async()=>{let b=await m(a.filePath);if(!b)return null;let c=await l(a.filePath);return c?{filePath:a.filePath,sessionId:a.sessionId,cwd:b,fileMtime:c}:null}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value).filter(a=>null!==a)}let o=(0,f.runtimeCache)(n,30);async function p(){let a;try{a=await o()}catch(a){return(0,i.logWarn)("Failed to scan Pi sessions:",a),[]}let b=new Map;for(let c of a){let a=b.get(c.cwd);(!a||c.fileMtime.getTime()>a.latest.getTime())&&b.set(c.cwd,{latest:c.fileMtime,cwd:c.cwd})}let c=[];for(let{cwd:a,latest:d}of b.values())c.push({name:(0,e.encodeFolderName)(a),path:a,isDirectory:!0,lastModified:d,lastModifiedFormatted:(0,h.formatDate)(d),cli:["pi"]});return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}function q(a){let b=a.map(a=>({name:a.sessionId,path:a.filePath,lastModified:a.fileMtime,lastModifiedFormatted:(0,h.formatDate)(a.fileMtime),sessionId:a.sessionId,cli:"pi"}));return b.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),b}async function r(a){let b;try{b=await o()}catch(a){return(0,i.logWarn)("Failed to scan Pi sessions:",a),[]}return q(b.filter(b=>b.cwd===a))}async function s(a){let b;try{b=await o()}catch(a){return(0,i.logWarn)("Failed to scan Pi sessions:",a),{cwd:null,sessions:[]}}let c=b.filter(b=>(0,e.encodeFolderName)(b.cwd)===a),d=Array.from(new Set(c.map(a=>a.cwd)));return 1!==d.length?{cwd:null,sessions:[]}:{cwd:d[0],sessions:q(c)}}let t=(0,f.runtimeCache)(p,30),u=(0,f.runtimeCache)(a=>r(a),30,{maxSize:50}),v=(0,f.runtimeCache)(a=>s(a),30,{maxSize:50});a.s(["getCachedPiProjects",0,t,"getCachedPiSessionsByEncodedName",0,v,"getCachedPiSessionsForCwd",0,u,"getPiProjects",0,p,"getPiSessionsByEncodedName",0,s,"getPiSessionsForCwd",0,r])},64458,a=>{"use strict";var b=a.i(74533),c=a.i(90798),d=a.i(34900),e=a.i(33432),f=a.i(76668);function g(a){try{let c=(0,b.execFileSync)("opencode",["db","--format","json",a],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","pipe"]});if(!c.trim())return[];let d=JSON.parse(c);if(!Array.isArray(d))return null;return d}catch{return null}}function h(){return g("SELECT id, project_id, slug, directory, title, time_created, time_updated FROM session ORDER BY time_updated DESC LIMIT 1000")}function i(){return g("SELECT id, worktree, vcs, name, time_created, time_updated FROM project")}async function j(){let a=h(),b=i();if(null===a&&null===b)return[];let d=new Map;for(let a of b??[])d.set(a.id,a);let f=new Map;for(let b of a??[]){if(!b.project_id)continue;let a=f.get(b.project_id);a||(a={rows:[],latest:0},f.set(b.project_id,a)),a.rows.push(b),b.time_updated>a.latest&&(a.latest=b.time_updated)}let g=new Set,j=[];for(let[a,b]of f){g.add(a);let f=d.get(a),h=f?.worktree??b.rows[0]?.directory??null,i=h?(0,c.encodeFolderName)(h):a,k=h??"",l=new Date(Math.max(b.latest,f?.time_updated??0));j.push({name:i,path:k,isDirectory:!0,lastModified:l,lastModifiedFormatted:(0,e.formatDate)(l),cli:["opencode"]})}for(let a of b??[]){if(g.has(a.id))continue;let b=a.worktree??"",d=b?(0,c.encodeFolderName)(b):a.id,f=new Date(a.time_updated);j.push({name:d,path:b,isDirectory:!0,lastModified:f,lastModifiedFormatted:(0,e.formatDate)(f),cli:["opencode"]})}return j.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),j}async function k(a){let b=h();return b?b.filter(b=>b.directory===a).map(a=>{let b=new Date(a.time_updated);return{name:a.title??a.slug??a.id,path:`opencode://${a.id}`,lastModified:b,lastModifiedFormatted:(0,e.formatDate)(b),sessionId:a.id,cli:"opencode"}}):[]}async function l(a){let b,d;try{b=i(),d=h()}catch(a){return(0,f.logWarn)("Failed to read OpenCode DB:",a),{cwd:null,sessions:[]}}if(!b||!d)return{cwd:null,sessions:[]};let g=b.find(b=>b.worktree&&(0,c.encodeFolderName)(b.worktree)===a);if(!g||!g.worktree)return{cwd:null,sessions:[]};let j=d.filter(a=>a.project_id===g.id);return{cwd:g.worktree,sessions:j.map(a=>{let b=new Date(a.time_updated);return{name:a.title??a.slug??a.id,path:`opencode://${a.id}`,lastModified:b,lastModifiedFormatted:(0,e.formatDate)(b),sessionId:a.id,cli:"opencode"}})}}let m=(0,d.runtimeCache)(j,30),n=(0,d.runtimeCache)(a=>k(a),30,{maxSize:50}),o=(0,d.runtimeCache)(a=>l(a),30,{maxSize:50});a.s(["getCachedOpenCodeProjects",0,m,"getCachedOpenCodeSessionsByEncodedName",0,o,"getCachedOpenCodeSessionsForCwd",0,n,"getOpenCodeProjects",0,j,"getOpenCodeSessionsByEncodedName",0,l,"getOpenCodeSessionsForCwd",0,k])},62074,a=>{"use strict";var b=a.i(12714),c=a.i(60526),d=a.i(50227),e=a.i(34900),f=a.i(26192),g=a.i(33432),h=a.i(90798),i=a.i(76668);let j=/^session-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2})-([0-9a-f]{8})\.jsonl$/i,k=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;async function l(a){try{return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function m(a){try{return(await (0,b.stat)(a)).mtime}catch{return null}}async function n(a){let c=null;try{c=await (0,b.open)(a,"r");let d=Buffer.alloc(4096),{bytesRead:e}=await c.read(d,0,4096,0);if(0===e)return null;let f=d.subarray(0,e),g=f.indexOf(10),h=-1===g?e:g;return f.subarray(0,h).toString("utf-8")}catch{return null}finally{c&&await c.close().catch(()=>{})}}async function o(a){try{let c=(await (0,b.readFile)((0,d.join)(a,".project_root"),"utf-8")).trim();return c.length>0?c:null}catch{return null}}async function p(){let a=process.env.GEMINI_SESSIONS_DIR||(0,d.join)((0,c.homedir)(),".gemini","tmp"),b=await l(a);if(!b)return[];let e=[];return await (0,f.batchAll)(b.filter(a=>a.isDirectory()).map(b=>async()=>{let c=(0,d.join)(a,b.name),f=await o(c);if(!f)return;let g=(0,d.join)(c,"chats"),h=await l(g);if(h)for(let a of h){if(!a.isFile()||!j.test(a.name))continue;let b=(0,d.join)(g,a.name),c=await m(b);if(!c)continue;let h=function(a){if(a)try{let b=JSON.parse(a);if("string"!=typeof b.sessionId)return;return k.test(b.sessionId)?b.sessionId:void 0}catch{return}}(await n(b));e.push({filePath:b,sessionFilename:a.name,cwd:f,fileMtime:c,sessionId:h})}}),16),e}async function q(){let a=await p(),b=new Map;for(let c of a){let a=b.get(c.cwd);(!a||c.fileMtime.getTime()>a.mtime.getTime())&&b.set(c.cwd,{mtime:c.fileMtime})}let c=[...b.entries()].map(([a,{mtime:b}])=>({name:(0,h.encodeFolderName)(a),path:a,isDirectory:!0,lastModified:b,lastModifiedFormatted:(0,g.formatDate)(b),cli:["gemini"]}));return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}async function r(a){let b=(await p()).filter(b=>b.cwd===a).map(a=>({name:a.sessionFilename,path:a.filePath,lastModified:a.fileMtime,lastModifiedFormatted:(0,g.formatDate)(a.fileMtime),sessionId:a.sessionId,cli:"gemini"}));return b.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),b}async function s(a){let b;try{b=await p()}catch(a){return(0,i.logWarn)("Failed to scan Gemini sessions:",a),{cwd:null,sessions:[]}}let c=b.filter(b=>(0,h.encodeFolderName)(b.cwd)===a),d=Array.from(new Set(c.map(a=>a.cwd)));if(1!==d.length)return{cwd:null,sessions:[]};let e=c.map(a=>({name:a.sessionFilename,path:a.filePath,lastModified:a.fileMtime,lastModifiedFormatted:(0,g.formatDate)(a.fileMtime),sessionId:a.sessionId,cli:"gemini"}));return e.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),{cwd:d[0],sessions:e}}let t=(0,e.runtimeCache)(q,30),u=(0,e.runtimeCache)(a=>s(a),30,{maxSize:50});a.s(["getCachedGeminiProjects",0,t,"getCachedGeminiSessionsByEncodedName",0,u,"getGeminiProjects",0,q,"getGeminiSessionsByEncodedName",0,s,"getGeminiSessionsForCwd",0,r])},93087,a=>{"use strict";var b=a.i(12714),c=a.i(60526),d=a.i(50227),e=a.i(90798),f=a.i(34900),g=a.i(26192),h=a.i(33432),i=a.i(76668);let j=["agent-sessions","conversations","sessions"],k=["meta.json","session.json","workspace.json","workspace.yaml"],l=["events.jsonl","transcript.jsonl","messages.jsonl"];async function m(a){try{return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function n(a){try{return(await (0,b.stat)(a)).mtime}catch{return null}}async function o(a,c){for(let e of c){let c,f=(0,d.join)(a,e);if(await n(f)===null)continue;try{c=await (0,b.readFile)(f,"utf-8")}catch{continue}let g=function(a){try{let b=JSON.parse(a);if("string"==typeof b.cwd&&b.cwd.length>0)return b.cwd}catch{}let b=a.match(/^\s*cwd\s*:\s*(.+?)\s*$/m);if(b){let a=b[1].replace(/^['"]|['"]$/g,"");if(a.length>0)return a}}(c);if(g)return{path:f,cwd:g}}return null}async function p(a,b){for(let c of b){let b=(0,d.join)(a,c);if(await n(b)!==null)return b}return null}async function q(){let a=process.env.CURSOR_HOME||(0,d.join)((0,c.homedir)(),".cursor"),b=[],f=[],h=(0,d.join)(a,"projects"),i=await m(h);if(i)for(let a of i){if(!a.isDirectory())continue;let c=(0,e.decodeFolderName)(a.name),f=c.startsWith("/")||/^[A-Za-z]:\//.test(c)?c:`/${c}`,g=(0,d.join)(h,a.name,"agent-transcripts"),i=await m(g);if(i)for(let a of i)a.isDirectory()&&b.push({sessionId:a.name,dir:(0,d.join)(g,a.name),cwd:f})}for(let b of j){let c=(0,d.join)(a,b),e=await m(c);if(e)for(let a of e)a.isDirectory()&&f.push({sessionId:a.name,dir:(0,d.join)(c,a.name)})}return 0===b.length&&0===f.length?[]:(await (0,g.batchAll)([...b.map(a=>async()=>{let b=(0,d.join)(a.dir,`${a.sessionId}.jsonl`),c=await n(b);return c?{metaPath:a.dir,transcriptPath:b,sessionId:a.sessionId,cwd:a.cwd,fileMtime:c,hasTranscript:!0}:null}),...f.map(a=>async()=>{let b=await o(a.dir,k);if(!b)return null;let c=await p(a.dir,l),d=c?await n(c):null,e=await n(b.path),f=d&&e?new Date(Math.max(d.getTime(),e.getTime())):d??e??new Date(0);return{metaPath:b.path,transcriptPath:c,sessionId:a.sessionId,cwd:b.cwd,fileMtime:f,hasTranscript:null!==c}})],16)).filter(a=>"fulfilled"===a.status).map(a=>a.value).filter(a=>null!==a)}let r=(0,f.runtimeCache)(q,30);async function s(){let a;try{a=await r()}catch(a){return(0,i.logWarn)("Failed to scan Cursor sessions:",a),[]}let b=new Map;for(let c of a){if(!c.hasTranscript)continue;let a=b.get(c.cwd);(!a||c.fileMtime.getTime()>a.latest.getTime())&&b.set(c.cwd,{latest:c.fileMtime,cwd:c.cwd})}let c=[];for(let{cwd:a,latest:d}of b.values())c.push({name:(0,e.encodeFolderName)(a),path:a,isDirectory:!0,lastModified:d,lastModifiedFormatted:(0,h.formatDate)(d),cli:["cursor"]});return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}function t(a){let b=a.filter(a=>a.hasTranscript&&a.transcriptPath).map(a=>({name:a.sessionId,path:a.transcriptPath,lastModified:a.fileMtime,lastModifiedFormatted:(0,h.formatDate)(a.fileMtime),sessionId:a.sessionId,cli:"cursor"}));return b.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),b}async function u(a){let b;try{b=await r()}catch(a){return(0,i.logWarn)("Failed to scan Cursor sessions:",a),[]}return t(b.filter(b=>b.cwd===a))}async function v(a){let b;try{b=await r()}catch(a){return(0,i.logWarn)("Failed to scan Cursor sessions:",a),{cwd:null,sessions:[]}}let c=b.filter(b=>b.hasTranscript&&(0,e.encodeFolderName)(b.cwd)===a);return{cwd:c[0]?.cwd??null,sessions:t(c)}}let w=(0,f.runtimeCache)(s,30),x=(0,f.runtimeCache)(a=>u(a),30,{maxSize:50}),y=(0,f.runtimeCache)(a=>v(a),30,{maxSize:50});a.s(["getCachedCursorProjects",0,w,"getCachedCursorSessionsByEncodedName",0,y,"getCachedCursorSessionsForCwd",0,x,"getCursorProjects",0,s,"getCursorSessionsByEncodedName",0,v,"getCursorSessionsForCwd",0,u])},69191,a=>{"use strict";var b=a.i(12714),c=a.i(50227),d=a.i(90798),e=a.i(34900),f=a.i(26192),g=a.i(76668),h=a.i(33432);async function i(a,c){try{return(await (0,b.stat)(a)).mtime}catch(a){return(0,g.logWarn)(`Failed to stat ${c}:`,a),new Date(0)}}async function j(a){try{if(!(await (0,b.stat)(a)).isDirectory())return null;return await (0,b.readdir)(a,{withFileTypes:!0})}catch{return null}}async function k(){try{let a=(0,d.getClaudeProjectsPath)(),b=await j(a);if(!b)return[];let e=(await (0,f.batchAll)(b.filter(a=>a.isDirectory()).map(b=>async()=>{let d=(0,c.join)(a,b.name),e=await i(d,b.name);return{name:b.name,path:d,isDirectory:!0,lastModified:e,lastModifiedFormatted:(0,h.formatDate)(e),cli:["claude"]}}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value);return e.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),e}catch(a){return(0,g.logError)("Error reading Claude project folders:",a),[]}}async function l(){let[{getCodexProjects:b},{getCopilotProjects:c},{getCursorProjects:d},{getOpenCodeProjects:e},{getPiProjects:f},{getGeminiProjects:h}]=await Promise.all([a.A(93658),a.A(60956),a.A(26244),a.A(2164),a.A(92351),a.A(26396)]),[i,j,l,m,n,o,p]=await Promise.all([k(),b().catch(a=>((0,g.logError)("Error reading Codex projects:",a),[])),c().catch(a=>((0,g.logError)("Error reading Copilot projects:",a),[])),d().catch(a=>((0,g.logError)("Error reading Cursor projects:",a),[])),e().catch(a=>((0,g.logError)("Error reading OpenCode projects:",a),[])),f().catch(a=>((0,g.logError)("Error reading Pi projects:",a),[])),h().catch(a=>((0,g.logError)("Error reading Gemini projects:",a),[]))]);return function(...a){let b=new Map;for(let c of a)for(let a of c){let c=b.get(a.name);if(!c){b.set(a.name,{...a,cli:[...a.cli]});continue}let d=[...c.cli];for(let b of a.cli)d.includes(b)||d.push(b);let e=a.lastModified.getTime()>c.lastModified.getTime()?a:c;b.set(a.name,{...c,cli:d,lastModified:e.lastModified,lastModifiedFormatted:e.lastModifiedFormatted})}let c=Array.from(b.values());return c.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),c}(i,j,l,m,n,o,p)}function m(a){let b=a.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);return b?b[0]:void 0}async function n(a){try{let b=await j(a);if(!b)return[];let d=b.filter(a=>a.isFile()&&a.name.endsWith(".jsonl")&&m(a.name)),e=(await (0,f.batchAll)(d.map(b=>async()=>{let d=(0,c.join)(a,b.name),e=await i(d,b.name);return{name:b.name,path:d,lastModified:e,lastModifiedFormatted:(0,h.formatDate)(e),sessionId:m(b.name),cli:"claude"}}),16)).filter(a=>"fulfilled"===a.status).map(a=>a.value);return e.sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),e}catch(a){return(0,g.logError)("Error reading session files:",a),[]}}let o=(0,e.runtimeCache)(l,30),p=(0,e.runtimeCache)(a=>n(a),30);a.s(["UUID_RE",0,/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/,"getCachedProjectFolders",0,o,"getCachedSessionFiles",0,p,"resolveProjectPath",0,function(a){if(!a)throw RangeError("Empty project name");if(/^[/\\]/.test(a))throw RangeError("Absolute project name");let b=(0,c.resolve)((0,d.getClaudeProjectsPath)()),e=(0,c.resolve)((0,c.join)(b,a));if(!e.startsWith(b+c.sep))throw RangeError("Project path escapes root");return e}])},790,(a,b,c)=>{let{createClientModuleProxy:d}=a.r(11857);a.n(d("[project]/node_modules/next/dist/client/app-dir/link.js <module evaluation>"))},84707,(a,b,c)=>{let{createClientModuleProxy:d}=a.r(11857);a.n(d("[project]/node_modules/next/dist/client/app-dir/link.js"))},97647,a=>{"use strict";a.i(790);var b=a.i(84707);a.n(b)},95936,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={default:function(){return i},useLinkStatus:function(){return h.useLinkStatus}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(64240),g=a.r(7997),h=f._(a.r(97647));function i(a){let b=a.legacyBehavior,c="string"==typeof a.children||"number"==typeof a.children||"string"==typeof a.children?.type,d=a.children?.type?.$$typeof===Symbol.for("react.client.reference");return!b||c||d||(a.children?.type?.$$typeof===Symbol.for("react.lazy")?console.error("Using a Lazy Component as a direct child of `<Link legacyBehavior>` from a Server Component is not supported. If you need legacyBehavior, wrap your Lazy Component in a Client Component that renders the Link's `<a>` tag."):console.error("Using a Server Component as a direct child of `<Link legacyBehavior>` is not supported. If you need legacyBehavior, wrap your Server Component in a Client Component that renders the Link's `<a>` tag.")),(0,g.jsx)(h.default,{...a})}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},8174,a=>{"use strict";a.s(["default",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call the default export of [project]/node_modules/lucide-react/dist/esm/Icon.mjs <module evaluation> from the server, but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/node_modules/lucide-react/dist/esm/Icon.mjs <module evaluation>","default")},90697,a=>{"use strict";a.s(["default",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call the default export of [project]/node_modules/lucide-react/dist/esm/Icon.mjs from the server, but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/node_modules/lucide-react/dist/esm/Icon.mjs","default")},53808,a=>{"use strict";a.i(8174);var b=a.i(90697);a.n(b)},84930,92277,a=>{"use strict";var b=a.i(717);let c=a=>{let b=a.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,b,c)=>c?c.toUpperCase():b.toLowerCase());return b.charAt(0).toUpperCase()+b.slice(1)};var d=a.i(53808);let e=(a,e)=>{let f=(0,b.forwardRef)(({className:f,...g},h)=>(0,b.createElement)(d.default,{ref:h,iconNode:e,className:((...a)=>a.filter((a,b,c)=>!!a&&""!==a.trim()&&c.indexOf(a)===b).join(" ").trim())(`lucide-${c(a).replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,`lucide-${a}`,f),...g}));return f.displayName=c(a),f};a.s(["default",0,e],92277);let f=e("arrow-left",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]);a.s(["ArrowLeft",0,f],84930)},71224,a=>{a.v("/_next/static/media/icon.0a.gigb3_x5pd.png"+(globalThis.NEXT_CLIENT_ASSET_SUFFIX||""))},1022,a=>{"use strict";let b={src:a.i(71224).default,width:1920,height:1920};a.s(["default",0,b])},34417,a=>{"use strict";a.s(["default",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call the default export of [project]/app/components/sessions-list.tsx <module evaluation> from the server, but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/app/components/sessions-list.tsx <module evaluation>","default")},46201,a=>{"use strict";a.s(["default",()=>b]);let b=(0,a.i(11857).registerClientReference)(function(){throw Error("Attempted to call the default export of [project]/app/components/sessions-list.tsx from the server, but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.")},"[project]/app/components/sessions-list.tsx","default")},13853,a=>{"use strict";a.i(34417);var b=a.i(46201);a.n(b)},80776,a=>{"use strict";var b=a.i(7997),c=a.i(717),d=a.i(69191),e=a.i(1024),f=a.i(88890),g=a.i(93087),h=a.i(64458),i=a.i(2727),j=a.i(62074),k=a.i(76668),l=a.i(90798);a.i(70396);var m=a.i(73727),n=a.i(22734),o=a.i(24868),p=a.i(95936),q=a.i(84930),r=a.i(33432),s=a.i(13853);async function t({params:a}){let{name:u}=await a,v=null;try{v=(0,d.resolveProjectPath)(u)}catch{v=null}let w=(0,l.decodeFolderName)(u),x=!!v&&(0,n.existsSync)(v),y=[];x&&v&&(y=await (0,d.getCachedSessionFiles)(v));let[z,A,B,C,D,E]=await Promise.all([(0,e.getCachedCodexSessionsByEncodedName)(u),(0,f.getCachedCopilotSessionsByEncodedName)(u),(0,g.getCachedCursorSessionsByEncodedName)(u),(0,h.getCachedOpenCodeSessionsByEncodedName)(u),(0,i.getCachedPiSessionsByEncodedName)(u),(0,j.getCachedGeminiSessionsByEncodedName)(u)]),F=z.sessions,G=A.sessions,H=B.sessions,I=C.sessions,J=D.sessions,K=E.sessions;x||0!==F.length||0!==G.length||0!==H.length||0!==I.length||0!==J.length||0!==K.length||(0,m.notFound)();let L=z.cwd??A.cwd??B.cwd??C.cwd??D.cwd??E.cwd??w,M=null,N=null;if(x&&v)try{let a=await (0,o.stat)(v);M=a.mtime,N=(0,r.formatDate)(a.mtime)}catch(a){(0,k.logWarn)(`Failed to get stats for project ${w}:`,a)}let O=[F[0],G[0],H[0],I[0],J[0],K[0]].filter(a=>!!a).map(a=>a.lastModified).reduce((a,b)=>!a||b.getTime()>a.getTime()?b:a,null);O&&(!M||O.getTime()>M.getTime())&&(M=O,N=(0,r.formatDate)(O));let P=[...y,...F,...G,...H,...I,...J,...K].sort((a,b)=>b.lastModified.getTime()-a.lastModified.getTime()),Q=x&&v?v:L;return(0,b.jsx)("main",{className:"min-h-screen bg-background",children:(0,b.jsxs)("div",{className:"container mx-auto p-8",children:[(0,b.jsxs)(p.default,{href:"/projects",className:"inline-flex items-center gap-2 text-muted-foreground hover:text-foreground mb-6 transition-colors",children:[(0,b.jsx)(q.ArrowLeft,{className:"w-4 h-4"}),(0,b.jsx)("span",{children:"Back to Projects"})]}),(0,b.jsxs)("div",{className:"mb-8",children:[(0,b.jsx)("h1",{className:"text-4xl font-bold text-foreground mb-2 break-words break-all",children:L}),(0,b.jsxs)("div",{className:"space-y-1",children:[(0,b.jsxs)("p",{className:"text-muted-foreground",children:[(0,b.jsx)("span",{className:"font-medium",children:"Path:"})," ",Q]}),N&&(0,b.jsxs)("p",{className:"text-muted-foreground",children:[(0,b.jsx)("span",{className:"font-medium",children:"Modified:"})," ",N]})]})]}),(0,b.jsxs)("div",{className:"bg-card text-card-foreground rounded-lg border border-border p-6 shadow-sm",children:[(0,b.jsx)("h2",{className:"text-2xl font-semibold mb-4",children:"Sessions"}),0===P.length?(0,b.jsxs)("div",{className:"text-center py-8",children:[(0,b.jsx)("p",{className:"text-muted-foreground mb-2",children:"No .jsonl files found in this project."}),(0,b.jsx)("p",{className:"text-sm text-muted-foreground",children:"Session files will appear here once they are created."})]}):(0,b.jsx)(c.Suspense,{children:(0,b.jsx)(s.default,{files:P,projectName:u})})]})]})})}a.s(["default",0,t,"dynamic",0,"force-dynamic"])},11363,a=>{a.n(a.i(80776))},93658,a=>{a.v(a=>Promise.resolve().then(()=>a(1024)))},60956,a=>{a.v(a=>Promise.resolve().then(()=>a(88890)))},26244,a=>{a.v(a=>Promise.resolve().then(()=>a(93087)))},2164,a=>{a.v(a=>Promise.resolve().then(()=>a(64458)))},92351,a=>{a.v(a=>Promise.resolve().then(()=>a(2727)))},26396,a=>{a.v(a=>Promise.resolve().then(()=>a(62074)))}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__07_-mkc._.js.map
|