failproofai 1.0.4-beta.1 → 1.0.4-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 +5 -5
- package/.next/standalone/.next/prerender-manifest.json +5 -5
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.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/_not-found/__PAGE__.segment.rsc +14 -14
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route_client-reference-manifest.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/audit/status/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route_client-reference-manifest.js +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/api/download/[project]/[session]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +37 -4
- package/.next/standalone/.next/server/app/audit/page.js +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +1 -1
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__1zndo1i._.js → [externals]__1lh7m5d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0_gzk8q._.js → [externals]__1rqkg_y._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cuho4x._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adacul._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +5 -0
- package/.next/standalone/.next/server/chunks/_08w6xzm._.js +3 -0
- package/.next/standalone/.next/server/chunks/_09dz7xv._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +14 -21
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00-s7h8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0wvusu0._.js → [root-of-the-server]__0n_lxhg._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rgu2r3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190won8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
- 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]__1sc84bb._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zl_r0t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0-oij9d._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0l2hi_d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0oq1dh6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0wso5d3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +48 -168
- package/.next/standalone/.next/server/chunks/ssr/{_08f0jd2._.js → _1if9ixi._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -69
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_rerun-button_tsx_0blihgw._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_13n822a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +54 -21
- package/.next/standalone/.next/static/chunks/{1_bxotmf9qngs.js → 010bv1w6j171t.js} +1 -1
- package/.next/standalone/.next/static/chunks/04r6ch8uf_n8m.js +1 -0
- package/.next/standalone/.next/static/chunks/{29-iqnp9v_axt.css → 0o-hh5_turzlz.css} +1 -1
- package/.next/standalone/.next/static/chunks/0qmsunv04x4na.css +2 -0
- package/.next/standalone/.next/static/chunks/{00gv0v91mycm-.js → 0wz8yftk18ts2.js} +1 -1
- package/.next/standalone/.next/static/chunks/0zebh1n9jkfbt.js +1 -0
- package/.next/standalone/.next/static/chunks/{0qn9khv0oo9ex.js → 1pb1oztsbwcss.js} +1 -1
- package/.next/standalone/.next/static/chunks/2aquitk72k2op.js +1 -0
- package/.next/standalone/.next/static/chunks/2bi_1y0a_smt7.js +6 -0
- package/.next/standalone/.next/static/chunks/{1po3lirgk2riw.js → 2ej3b8gk5ittu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{01hvwwrhvbzyh.js → 2zafgs90r_leq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1_2jsatfuthrw.js → 32spub4wqjem-.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3_--3ibia6ba1.js → 3l36d73kj18zw.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2bvwsyu6x__ia.js → 3m4upvybtrexd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2k9f4tyv04809.css → 3uyhmm01g64k4.css} +1 -0
- package/.next/standalone/.next/static/chunks/{2bnf_4pgyk1rq.js → 40lpt2o2b283e.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-18qf4jodtft6b.js → turbopack-3s3c-u_u_l0u9.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +51 -27
- package/.next/standalone/app/actions/get-leaks.ts +100 -0
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +112 -33
- package/.next/standalone/app/audit/_components/audit-poster.tsx +29 -10
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +6 -1
- package/.next/standalone/app/audit/_components/empty-state.tsx +4 -1
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +19 -5
- package/.next/standalone/app/audit/_components/leak-section.tsx +179 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +110 -44
- package/.next/standalone/app/audit/audit-styles.css +114 -1
- package/.next/standalone/app/project/[name]/page.tsx +4 -24
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +26 -3
- package/.next/standalone/fp-cloud-cli/fp_cli/_click_compat.py +31 -8
- package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +1 -0
- package/.next/standalone/fp-cloud-cli/pyproject.toml +9 -2
- package/.next/standalone/fp-cloud-cli/tests/test_click_compat.py +54 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +9 -12
- package/.next/standalone/lib/auth/api-server-client.ts +28 -0
- package/.next/standalone/lib/claude-sessions.ts +101 -27
- package/.next/standalone/lib/cli-registry.ts +1 -33
- package/.next/standalone/lib/download-session.ts +0 -37
- package/.next/standalone/lib/projects.ts +3 -27
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/experimental/testmode/fetch.js +10 -2
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/lib/typescript/runTypeScriptCli.js +2 -2
- package/.next/standalone/node_modules/next/dist/lib/verify-typescript-setup.js +3 -1
- 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/image-optimizer.js +2 -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/start-server.js +1 -1
- 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 +11 -11
- package/.next/standalone/package.json +15 -14
- package/.next/standalone/sdk/python/CHANGELOG.md +155 -0
- package/.next/standalone/sdk/python/README.md +8 -0
- package/.next/standalone/sdk/python/examples/evaluator_worker.py +121 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__init__.py +101 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__main__.py +49 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/_sandbox_runner.py +63 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/authoring.py +404 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/client.py +299 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/protocol.py +754 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/runtime.py +936 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/source.py +684 -0
- package/.next/standalone/sdk/python/tests/fixtures/evaluator_v2/README.md +28 -0
- package/.next/standalone/sdk/python/tests/fixtures/evaluator_v2/contract.json +252 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_authoring.py +124 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_client.py +253 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_example.py +35 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_http_e2e.py +636 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_main.py +47 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_protocol.py +246 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_review_fixes.py +164 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_runtime.py +1103 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_source.py +430 -0
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +17 -0
- package/.next/standalone/sdk/python/uv.lock +18 -18
- package/.next/standalone/server.js +1 -1
- package/README.md +19 -95
- package/bin/failproofai.mjs +7 -24
- package/dist/cli.mjs +19910 -25855
- package/dist/worker.mjs +4818 -6344
- package/lib/auth/api-server-client.ts +28 -0
- package/lib/claude-sessions.ts +101 -27
- package/lib/cli-registry.ts +1 -33
- package/lib/download-session.ts +0 -37
- package/lib/projects.ts +3 -27
- package/package.json +15 -14
- package/pi-extension/index.ts +42 -4
- package/scripts/changelog-open.py +115 -0
- package/src/audit/cli-adapters/index.ts +0 -24
- package/src/audit/cli.ts +134 -0
- package/src/audit/desktop-notify.ts +420 -0
- package/src/audit/harm-report.ts +101 -0
- package/src/audit/index.ts +141 -13
- package/src/audit/leak-fingerprint.ts +200 -0
- package/src/audit/leak-notice.ts +161 -0
- package/src/audit/leak-record.ts +232 -0
- package/src/audit/leak-scan.ts +292 -0
- package/src/audit/leak-store.ts +217 -0
- package/src/audit/macos-notifier.ts +310 -0
- package/src/audit/redact-example.ts +266 -14
- package/src/audit/report-harm.ts +12 -1
- package/src/audit/report.ts +6 -3
- package/src/audit/schedule-cli.ts +37 -0
- package/src/audit/scoring.ts +49 -0
- package/src/audit/types.ts +41 -0
- package/src/hooks/builtin-policies.ts +71 -8
- package/src/hooks/configure-wizard.ts +20 -0
- package/src/hooks/enforcement-capability.ts +0 -97
- package/src/hooks/fp-config.ts +71 -11
- package/src/hooks/fp-home.ts +27 -0
- package/src/hooks/handler.ts +64 -62
- package/src/hooks/harness-cli.ts +1 -3
- package/src/hooks/integrations.ts +49 -769
- package/src/hooks/normalize-cli-payload.ts +0 -126
- package/src/hooks/notice.ts +155 -0
- package/src/hooks/policy-evaluator.ts +6 -297
- package/src/hooks/resolve-transcript-path.ts +0 -10
- package/src/hooks/tool-name-canonicalize.ts +0 -64
- package/src/hooks/types.ts +2 -533
- package/src/hooks/uninstall-cli.ts +15 -0
- package/.next/standalone/.grok/hooks/failproofai.json +0 -172
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07hor7h._.js +0 -5
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0elsuli._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gnj_qa._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljuzm_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w23bpg._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x5c7sh._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0yik9_w._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1jg6s9m._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1s6qci9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xfm05z._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0tdy_6l._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_grok-projects_ts_1i2epl_._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_qwen-projects_ts_0wu_a8e._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_4gcz8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0d--wmy._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qqrlf_._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s11fx1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gamwq._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1bbk-si._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1c3ybxr._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1izi7zn._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__21bj7uw._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_00z5uuq._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1byck5v._.js +0 -23
- package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_cline-projects_ts_13_hbdd._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_grok-projects_ts_0rc-d0o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_ori-projects_ts_04tofqo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_qwen-projects_ts_0w3i9o7._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +0 -3
- package/.next/standalone/.next/static/chunks/0hzmxwb2pvk5p.js +0 -6
- package/.next/standalone/.next/static/chunks/0j884dwnwtyrt.js +0 -1
- package/.next/standalone/.next/static/chunks/0mr9dg3bnloa1.js +0 -1
- package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +0 -1
- package/.next/standalone/.next/static/chunks/3gf1jg-5m-u1t.css +0 -2
- package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +0 -1
- package/.next/standalone/.next/static/chunks/3ws7eljkq25wg.js +0 -69
- package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +0 -1
- package/.next/standalone/.qwen/settings.json +0 -251
- package/.next/standalone/assets/logos/cline.png +0 -0
- package/.next/standalone/assets/logos/grok-dark.svg +0 -1
- package/.next/standalone/assets/logos/grok-light.svg +0 -1
- package/.next/standalone/assets/logos/ori-dark.svg +0 -1
- package/.next/standalone/assets/logos/ori-light.svg +0 -1
- package/.next/standalone/assets/logos/qwen.svg +0 -1
- package/.next/standalone/lib/cline-projects.ts +0 -155
- package/.next/standalone/lib/cline-sessions.ts +0 -268
- package/.next/standalone/lib/grok-projects.ts +0 -123
- package/.next/standalone/lib/grok-sessions.ts +0 -355
- package/.next/standalone/lib/ori-projects.ts +0 -141
- package/.next/standalone/lib/ori-sessions.ts +0 -221
- package/.next/standalone/lib/qwen-projects.ts +0 -106
- package/.next/standalone/lib/qwen-sessions.ts +0 -313
- package/lib/cline-projects.ts +0 -155
- package/lib/cline-sessions.ts +0 -268
- package/lib/grok-projects.ts +0 -123
- package/lib/grok-sessions.ts +0 -355
- package/lib/ori-projects.ts +0 -141
- package/lib/ori-sessions.ts +0 -221
- package/lib/qwen-projects.ts +0 -106
- package/lib/qwen-sessions.ts +0 -313
- package/src/audit/cli-adapters/cline.ts +0 -50
- package/src/audit/cli-adapters/grok.ts +0 -70
- package/src/audit/cli-adapters/ori.ts +0 -55
- package/src/audit/cli-adapters/qwen.ts +0 -71
- package/src/hooks/batch-expand.ts +0 -380
- package/src/hooks/batch-fanout.ts +0 -142
- package/src/hooks/risk-patterns.ts +0 -26
- /package/.next/standalone/.next/static/{qJx3mbOQV-5ElrcRb4Sp7 → aKNv4Kmv98Xpwns0Xa-C-}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{qJx3mbOQV-5ElrcRb4Sp7 → aKNv4Kmv98Xpwns0Xa-C-}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{qJx3mbOQV-5ElrcRb4Sp7 → aKNv4Kmv98Xpwns0Xa-C-}/_ssgManifest.js +0 -0
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* grok CLI transcript adapter — AUDIT (Pillar 2).
|
|
3
|
-
*
|
|
4
|
-
* grok writes one session DIRECTORY at
|
|
5
|
-
* `~/.grok/sessions/<percent-encoded-cwd>/<sessionId>/`, whose
|
|
6
|
-
* `chat_history.jsonl` holds the turns (verified live against grok 1.0.3).
|
|
7
|
-
* lib/grok-sessions.ts enumerates and parses them.
|
|
8
|
-
*
|
|
9
|
-
* `chat_history.jsonl` has no per-message timestamps, so the parser anchors a
|
|
10
|
-
* synthesized timeline on the session's `created_at` (from summary.json) —
|
|
11
|
-
* `listGrokTranscripts` already resolved that, so it is passed straight
|
|
12
|
-
* through here rather than re-read.
|
|
13
|
-
*/
|
|
14
|
-
import { readFile } from "node:fs/promises";
|
|
15
|
-
import { listGrokTranscripts, grokLinesToLogEntries } from "../../../lib/grok-sessions";
|
|
16
|
-
import { parseRawLines } from "../../../lib/log-entries";
|
|
17
|
-
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
18
|
-
import type { ListOpts } from "./claude";
|
|
19
|
-
import { logEntriesToEvents } from "./shared";
|
|
20
|
-
|
|
21
|
-
export async function listGrokTranscriptMetadata(
|
|
22
|
-
opts: ListOpts = {},
|
|
23
|
-
): Promise<TranscriptMetadata[]> {
|
|
24
|
-
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
25
|
-
const sinceMs = opts.sinceMs ?? 0;
|
|
26
|
-
const out: TranscriptMetadata[] = [];
|
|
27
|
-
|
|
28
|
-
for (const t of listGrokTranscripts()) {
|
|
29
|
-
if (t.mtimeMs < sinceMs) continue;
|
|
30
|
-
// `audit --project <cwd>` filters on the real cwd (summary.json's info.cwd
|
|
31
|
-
// when present, else the percent-decoded folder name).
|
|
32
|
-
if (projectFilter && !projectFilter.has(t.cwd)) continue;
|
|
33
|
-
out.push({
|
|
34
|
-
cli: "grok",
|
|
35
|
-
projectName: t.projectName,
|
|
36
|
-
sessionId: t.sessionId,
|
|
37
|
-
transcriptPath: t.transcriptPath,
|
|
38
|
-
mtimeMs: t.mtimeMs,
|
|
39
|
-
sizeBytes: t.sizeBytes,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return out;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function streamGrokEvents(meta: TranscriptMetadata): Promise<NormalizedToolEvent[]> {
|
|
46
|
-
let content: string;
|
|
47
|
-
try {
|
|
48
|
-
content = await readFile(meta.transcriptPath, "utf-8");
|
|
49
|
-
} catch {
|
|
50
|
-
return [];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Recover this session's cwd + created_at from the enumeration (both come
|
|
54
|
-
// from summary.json, which streamEvents is not otherwise given).
|
|
55
|
-
const known = listGrokTranscripts().find((t) => t.sessionId === meta.sessionId);
|
|
56
|
-
|
|
57
|
-
const rawLines = parseRawLines(content, "session");
|
|
58
|
-
const entries = grokLinesToLogEntries(
|
|
59
|
-
rawLines,
|
|
60
|
-
known?.createdAtMs ?? meta.mtimeMs,
|
|
61
|
-
"session",
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
return logEntriesToEvents(entries, {
|
|
65
|
-
cli: "grok",
|
|
66
|
-
sessionId: meta.sessionId,
|
|
67
|
-
transcriptPath: meta.transcriptPath,
|
|
68
|
-
cwd: known?.cwd ?? "",
|
|
69
|
-
});
|
|
70
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ori (OpenRouter's ori) transcript adapter — AUDIT-ONLY (Pillar 2).
|
|
3
|
-
*
|
|
4
|
-
* Covers ori's OWN agent (bare `ori` / `ori code`). Sessions launched through
|
|
5
|
-
* ori's LAUNCHER (`ori claude`, `ori codex`, …) are recorded by the launched
|
|
6
|
-
* CLI in its own store and are picked up by that CLI's adapter, not this one.
|
|
7
|
-
*
|
|
8
|
-
* ori keeps the whole conversation in one SQLite DB in its global workspace —
|
|
9
|
-
* lib/ori-projects.ts enumerates `ori_agent_loop_sessions`, lib/ori-sessions.ts
|
|
10
|
-
* parses each session's serialized message array — producing the same
|
|
11
|
-
* LogEntry[] shape the other adapters do, so `logEntriesToEvents` handles the
|
|
12
|
-
* rest. Each session carries a real `cwd`, so `audit --project <cwd>` filters
|
|
13
|
-
* work as they do for Devin and Goose.
|
|
14
|
-
*/
|
|
15
|
-
import { getOriSessions } from "../../../lib/ori-projects";
|
|
16
|
-
import { getOriSessionLog } from "../../../lib/ori-sessions";
|
|
17
|
-
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
18
|
-
import type { ListOpts } from "./claude";
|
|
19
|
-
import { logEntriesToEvents } from "./shared";
|
|
20
|
-
|
|
21
|
-
export async function listOriTranscriptMetadata(
|
|
22
|
-
opts: ListOpts = {},
|
|
23
|
-
): Promise<TranscriptMetadata[]> {
|
|
24
|
-
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
25
|
-
const sinceMs = opts.sinceMs ?? 0;
|
|
26
|
-
const sessions = await getOriSessions();
|
|
27
|
-
const out: TranscriptMetadata[] = [];
|
|
28
|
-
for (const s of sessions) {
|
|
29
|
-
if (s.mtimeMs < sinceMs) continue;
|
|
30
|
-
if (projectFilter && (!s.cwd || !projectFilter.has(s.cwd))) continue;
|
|
31
|
-
out.push({
|
|
32
|
-
cli: "ori",
|
|
33
|
-
projectName: s.projectName,
|
|
34
|
-
sessionId: s.sessionId,
|
|
35
|
-
transcriptPath: `ori-db://${s.sessionId}`,
|
|
36
|
-
mtimeMs: s.mtimeMs,
|
|
37
|
-
// updated_at advances on each turn, so (mtime) forms a real cache key.
|
|
38
|
-
sizeBytes: 0,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
return out;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function streamOriEvents(
|
|
45
|
-
meta: TranscriptMetadata,
|
|
46
|
-
): Promise<NormalizedToolEvent[]> {
|
|
47
|
-
const log = await getOriSessionLog(meta.sessionId);
|
|
48
|
-
if (!log) return [];
|
|
49
|
-
return logEntriesToEvents(log.entries, {
|
|
50
|
-
cli: "ori",
|
|
51
|
-
sessionId: meta.sessionId,
|
|
52
|
-
transcriptPath: meta.transcriptPath,
|
|
53
|
-
cwd: log.cwd ?? "",
|
|
54
|
-
});
|
|
55
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Qwen Code transcript adapter — AUDIT (Pillar 2).
|
|
3
|
-
*
|
|
4
|
-
* qwen writes real JSONL transcripts at
|
|
5
|
-
* `~/.qwen/projects/<encoded-cwd>/chats/<sessionId>.jsonl` (Claude-style
|
|
6
|
-
* encoded-cwd folders, one level deeper than Claude's; verified live against
|
|
7
|
-
* qwen-code 0.21.12). lib/qwen-sessions.ts enumerates and parses them — the
|
|
8
|
-
* message bodies are Gemini-shaped `parts[]`, not Claude content blocks — into
|
|
9
|
-
* the shared LogEntry[] shape, so `logEntriesToEvents` handles the rest.
|
|
10
|
-
*/
|
|
11
|
-
import { readFile } from "node:fs/promises";
|
|
12
|
-
import { listQwenTranscripts, qwenLinesToLogEntries } from "../../../lib/qwen-sessions";
|
|
13
|
-
import { parseRawLines } from "../../../lib/log-entries";
|
|
14
|
-
import type { NormalizedToolEvent, TranscriptMetadata } from "../types";
|
|
15
|
-
import type { ListOpts } from "./claude";
|
|
16
|
-
import { logEntriesToEvents } from "./shared";
|
|
17
|
-
|
|
18
|
-
export async function listQwenTranscriptMetadata(
|
|
19
|
-
opts: ListOpts = {},
|
|
20
|
-
): Promise<TranscriptMetadata[]> {
|
|
21
|
-
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
22
|
-
const sinceMs = opts.sinceMs ?? 0;
|
|
23
|
-
const out: TranscriptMetadata[] = [];
|
|
24
|
-
|
|
25
|
-
for (const t of listQwenTranscripts()) {
|
|
26
|
-
if (t.mtimeMs < sinceMs) continue;
|
|
27
|
-
// `audit --project <cwd>` filters on the decoded working directory.
|
|
28
|
-
if (projectFilter && !projectFilter.has(t.cwd)) continue;
|
|
29
|
-
out.push({
|
|
30
|
-
cli: "qwen",
|
|
31
|
-
projectName: t.projectName,
|
|
32
|
-
sessionId: t.sessionId,
|
|
33
|
-
transcriptPath: t.transcriptPath,
|
|
34
|
-
mtimeMs: t.mtimeMs,
|
|
35
|
-
sizeBytes: t.sizeBytes,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return out;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export async function streamQwenEvents(meta: TranscriptMetadata): Promise<NormalizedToolEvent[]> {
|
|
42
|
-
let content: string;
|
|
43
|
-
try {
|
|
44
|
-
content = await readFile(meta.transcriptPath, "utf-8");
|
|
45
|
-
} catch {
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const rawLines = parseRawLines(content, "session");
|
|
50
|
-
const entries = qwenLinesToLogEntries(rawLines, "session");
|
|
51
|
-
|
|
52
|
-
// Every qwen line carries the real cwd — take the first rather than
|
|
53
|
-
// re-decoding the (lossy) folder name.
|
|
54
|
-
let cwd = "";
|
|
55
|
-
for (const line of rawLines) {
|
|
56
|
-
if (line && typeof line === "object") {
|
|
57
|
-
const c = (line as Record<string, unknown>).cwd;
|
|
58
|
-
if (typeof c === "string" && c.length > 0) {
|
|
59
|
-
cwd = c;
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return logEntriesToEvents(entries, {
|
|
66
|
-
cli: "qwen",
|
|
67
|
-
sessionId: meta.sessionId,
|
|
68
|
-
transcriptPath: meta.transcriptPath,
|
|
69
|
-
cwd,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Expand a CLI's BATCH tool call into per-element canonical scalar inputs.
|
|
3
|
-
*
|
|
4
|
-
* failproofai's builtins read SCALARS — `tool_input.command`, `.file_path`,
|
|
5
|
-
* `.pattern`, `.old_string`. Cline delivers ARRAYS: `run_commands{commands[]}`,
|
|
6
|
-
* `read_files{files[]}`, `search_codebase{queries[]}`, plus one multi-file blob
|
|
7
|
-
* in `apply_patch{input}`. With only a key rename, `block-sudo`,
|
|
8
|
-
* `block-env-files`, `block-secrets-write`, `block-force-push` and
|
|
9
|
-
* `block-read-outside-cwd` all read `undefined` and ALLOW SILENTLY — the
|
|
10
|
-
* inert-hook failure this repo has already shipped twice (grok, and our own
|
|
11
|
-
* Claude hooks running inside grok).
|
|
12
|
-
*
|
|
13
|
-
* Joining the array into one string is NOT a fix, and the reason is specific:
|
|
14
|
-
* `SECRET_FILE_RE` is `/\.(?:pem|key)$/`. Under any join only the LAST element
|
|
15
|
-
* can ever match, so a `.pem` at `files[0]` rides straight through. That is why
|
|
16
|
-
* this expands and the evaluator runs the policy set once per element.
|
|
17
|
-
*
|
|
18
|
-
* PURE: no evaluator import, no fs, no policy registry — so the audit path can
|
|
19
|
-
* call it without dragging the policy engine along.
|
|
20
|
-
*
|
|
21
|
-
* CONTAINMENT: returns null for every CLI except cline and every tool except
|
|
22
|
-
* cline's four containers. `null` means "take the existing single-shot path,
|
|
23
|
-
* byte-for-byte unchanged", so this cannot regress the other 15 integrations.
|
|
24
|
-
*/
|
|
25
|
-
import type { IntegrationType } from "./types";
|
|
26
|
-
import {
|
|
27
|
-
ENV_FILE_PATH_RE,
|
|
28
|
-
SECRET_FILE_RE,
|
|
29
|
-
SECRET_FILE_ID_RSA_RE,
|
|
30
|
-
SECRET_FILE_CREDENTIALS_RE,
|
|
31
|
-
} from "./risk-patterns";
|
|
32
|
-
|
|
33
|
-
export interface FanoutElement {
|
|
34
|
-
/** Canonical SCALAR tool input: {command} | {file_path,…} | {pattern} |
|
|
35
|
-
* {file_path, old_string, new_string, patch}. */
|
|
36
|
-
input: Record<string, unknown>;
|
|
37
|
-
/** Short human locator; goes into the deny message and the activity row. */
|
|
38
|
-
label: string;
|
|
39
|
-
index: number;
|
|
40
|
-
/** True when this element is a COLLAPSE of several that the cap or the
|
|
41
|
-
* wall-clock budget refused to run apart. A weaker guarantee we state
|
|
42
|
-
* explicitly, never a silent skip. */
|
|
43
|
-
degraded?: boolean;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface BatchExpansion {
|
|
47
|
-
/** Canonical tool name (Bash | Read | Grep | Edit). */
|
|
48
|
-
tool: string;
|
|
49
|
-
elements: FanoutElement[];
|
|
50
|
-
/** The un-expanded original, so a batch-aware policy still sees the whole call. */
|
|
51
|
-
raw: Record<string, unknown>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* The separator used wherever a command list still has to collapse to one
|
|
56
|
-
* string. `" &&\n"` is DERIVED, not chosen:
|
|
57
|
-
* • `"\n"` alone silently disables `READ_LIKE_CMDS` — its boundary
|
|
58
|
-
* alternation `(?:^|;|&&|\|\||\|)` contains no newline, so a batched
|
|
59
|
-
* `cat /etc/passwd` stops looking read-like and `block-read-outside-cwd`
|
|
60
|
-
* never inspects it.
|
|
61
|
-
* • `" && "` alone manufactures a FALSE deny: a `.`-based lookahead can cross
|
|
62
|
-
* the boundary and fire on two commands neither of which triggers it alone.
|
|
63
|
-
* `" &&\n"` keeps every `&&`-aware segmenter alive while the newline stops
|
|
64
|
-
* `.`-based lookaheads crossing a boundary.
|
|
65
|
-
*/
|
|
66
|
-
export const BATCH_JOIN = " &&\n";
|
|
67
|
-
|
|
68
|
-
function omit(o: Record<string, unknown>, key: string): Record<string, unknown> {
|
|
69
|
-
const { [key]: _dropped, ...rest } = o;
|
|
70
|
-
return rest;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function expandBatchToolInput(
|
|
74
|
-
cli: IntegrationType,
|
|
75
|
-
toolName: string | undefined,
|
|
76
|
-
rawInput: unknown,
|
|
77
|
-
): BatchExpansion | null {
|
|
78
|
-
if (cli !== "cline" || !toolName) return null;
|
|
79
|
-
if (!rawInput || typeof rawInput !== "object" || Array.isArray(rawInput)) return null;
|
|
80
|
-
const raw = rawInput as Record<string, unknown>;
|
|
81
|
-
|
|
82
|
-
// An expansion to ZERO elements would evaluate nothing and report a clean
|
|
83
|
-
// allow — the exact inert-hook failure this exists to prevent. So an empty or
|
|
84
|
-
// mis-shaped container returns null and falls back to the collapse safety net
|
|
85
|
-
// in canonicalizeClineToolInput, which at least still reads SOMETHING.
|
|
86
|
-
const mk = (
|
|
87
|
-
parts: Array<{ input: Record<string, unknown>; label: string }>,
|
|
88
|
-
): BatchExpansion | null =>
|
|
89
|
-
parts.length === 0
|
|
90
|
-
? null
|
|
91
|
-
: { tool: toolName, raw, elements: parts.map((e, index) => ({ ...e, index })) };
|
|
92
|
-
|
|
93
|
-
switch (toolName) {
|
|
94
|
-
// run_commands {commands: ["cd '<dir>' && ls -la", …]}
|
|
95
|
-
case "Bash": {
|
|
96
|
-
const cmds = raw.commands;
|
|
97
|
-
if (!Array.isArray(cmds)) return null;
|
|
98
|
-
return mk(
|
|
99
|
-
cmds
|
|
100
|
-
.filter((c): c is string => typeof c === "string")
|
|
101
|
-
.map((c) => ({ input: { ...omit(raw, "commands"), command: c }, label: c })),
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
// read_files {files: [{path, start_line, …}, …]}
|
|
105
|
-
case "Read": {
|
|
106
|
-
const files = raw.files;
|
|
107
|
-
if (!Array.isArray(files)) return null;
|
|
108
|
-
return mk(
|
|
109
|
-
files.flatMap((f) => {
|
|
110
|
-
if (!f || typeof f !== "object" || Array.isArray(f)) return [];
|
|
111
|
-
const e = f as Record<string, unknown>;
|
|
112
|
-
if (typeof e.path !== "string") return [];
|
|
113
|
-
// Spread the entry so start_line/limit survive for policies that read
|
|
114
|
-
// them; `path` is KEPT too, because a cline-aware custom policy may
|
|
115
|
-
// already be reading it.
|
|
116
|
-
return [{ input: { ...e, file_path: e.path }, label: e.path }];
|
|
117
|
-
}),
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
// search_codebase {queries: ["alpha", …]}
|
|
121
|
-
case "Grep": {
|
|
122
|
-
const qs = raw.queries;
|
|
123
|
-
if (!Array.isArray(qs)) return null;
|
|
124
|
-
return mk(
|
|
125
|
-
qs
|
|
126
|
-
.filter((q): q is string => typeof q === "string")
|
|
127
|
-
.map((q) => ({ input: { ...omit(raw, "queries"), pattern: q }, label: q })),
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
// apply_patch {input: "*** Begin Patch …"} — byte-identical to the OpenAI
|
|
131
|
-
// apply_patch blob ori's `edit` tool carries, so this splitter is
|
|
132
|
-
// back-portable to ori and closes ori's documented multi-file KNOWN GAP.
|
|
133
|
-
case "Edit": {
|
|
134
|
-
const blob = raw.input;
|
|
135
|
-
if (typeof blob !== "string") return null;
|
|
136
|
-
return mk(
|
|
137
|
-
splitApplyPatch(blob).map((s) => ({
|
|
138
|
-
input: {
|
|
139
|
-
file_path: s.path,
|
|
140
|
-
old_string: s.oldText,
|
|
141
|
-
new_string: s.newText,
|
|
142
|
-
patch: s.subPatch,
|
|
143
|
-
cline_patch_op: s.op,
|
|
144
|
-
},
|
|
145
|
-
label: `${s.op} ${s.path}`,
|
|
146
|
-
})),
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
default:
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export interface PatchSection {
|
|
155
|
-
op: "add" | "update" | "delete" | "move";
|
|
156
|
-
path: string;
|
|
157
|
-
oldText: string;
|
|
158
|
-
newText: string;
|
|
159
|
-
/** A standalone, re-emittable patch for just this file. */
|
|
160
|
-
subPatch: string;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const FILE_OP_RE = /^\*\*\* (Add File|Update File|Delete File|Move to): (.+)$/;
|
|
164
|
-
const OPS: Record<string, PatchSection["op"]> = {
|
|
165
|
-
"Add File": "add",
|
|
166
|
-
"Update File": "update",
|
|
167
|
-
"Delete File": "delete",
|
|
168
|
-
"Move to": "move",
|
|
169
|
-
};
|
|
170
|
-
const HEADERS: Record<PatchSection["op"], string> = {
|
|
171
|
-
add: "Add File",
|
|
172
|
-
update: "Update File",
|
|
173
|
-
delete: "Delete File",
|
|
174
|
-
move: "Move to",
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
interface OpenSection {
|
|
178
|
-
op: PatchSection["op"];
|
|
179
|
-
path: string;
|
|
180
|
-
body: string[];
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function build(cur: OpenSection, op: PatchSection["op"], path: string): PatchSection {
|
|
184
|
-
const minus: string[] = [];
|
|
185
|
-
const plus: string[] = [];
|
|
186
|
-
for (const l of cur.body) {
|
|
187
|
-
if (l.startsWith("-")) minus.push(l.slice(1));
|
|
188
|
-
else if (l.startsWith("+")) plus.push(l.slice(1));
|
|
189
|
-
}
|
|
190
|
-
return {
|
|
191
|
-
op,
|
|
192
|
-
path,
|
|
193
|
-
oldText: minus.join("\n"),
|
|
194
|
-
newText: plus.join("\n"),
|
|
195
|
-
subPatch: ["*** Begin Patch", `*** ${HEADERS[op]}: ${path}`, ...cur.body, "*** End Patch"].join("\n"),
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Split an OpenAI apply_patch blob into one section per file it touches.
|
|
201
|
-
*
|
|
202
|
-
* Serves BOTH cline's `apply_patch` and ori's `edit` — the format is identical,
|
|
203
|
-
* and one implementation is what stops a third CLI adding a third regex.
|
|
204
|
-
*/
|
|
205
|
-
export function splitApplyPatch(patch: string): PatchSection[] {
|
|
206
|
-
const out: PatchSection[] = [];
|
|
207
|
-
let cur: OpenSection | null = null;
|
|
208
|
-
|
|
209
|
-
for (const line of patch.split("\n")) {
|
|
210
|
-
const m = FILE_OP_RE.exec(line);
|
|
211
|
-
if (m) {
|
|
212
|
-
const op = OPS[m[1]!]!;
|
|
213
|
-
const path = m[2]!.trim();
|
|
214
|
-
if (op === "move") {
|
|
215
|
-
// `Move to:` is a RENAME MODIFIER on the preceding Update File, not an
|
|
216
|
-
// independent op. We emit it as its OWN element anyway — deliberately —
|
|
217
|
-
// so a rename INTO `.env` is seen by the path builtins. It inherits the
|
|
218
|
-
// in-progress body so old/new_string stay right, and the Update element
|
|
219
|
-
// is still emitted at the next flush. Cost: one rename yields two
|
|
220
|
-
// elements. That is the trade: a duplicate row, never a missed path.
|
|
221
|
-
// Flush the section being renamed FIRST, then emit the move, so paths
|
|
222
|
-
// come out in literal file order — `Update File: a` + `Move to: b`
|
|
223
|
-
// yields [a, b], never [b, a]. Getting this backwards silently changes
|
|
224
|
-
// which path `pickRiskiestPath` and `file_path = paths[0]` land on.
|
|
225
|
-
if (cur) {
|
|
226
|
-
out.push(build(cur, cur.op, cur.path));
|
|
227
|
-
out.push(build(cur, "move", path));
|
|
228
|
-
cur = null;
|
|
229
|
-
} else
|
|
230
|
-
out.push({
|
|
231
|
-
op: "move",
|
|
232
|
-
path,
|
|
233
|
-
oldText: "",
|
|
234
|
-
newText: "",
|
|
235
|
-
subPatch: `*** Begin Patch\n*** Move to: ${path}\n*** End Patch`,
|
|
236
|
-
});
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
if (cur) out.push(build(cur, cur.op, cur.path));
|
|
240
|
-
cur = { op, path, body: [] };
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
if (line.startsWith("*** ")) continue; // Begin Patch / End Patch / End of File
|
|
244
|
-
if (cur) cur.body.push(line);
|
|
245
|
-
}
|
|
246
|
-
if (cur) out.push(build(cur, cur.op, cur.path));
|
|
247
|
-
return out;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/** Every path an apply_patch blob touches, in file order. */
|
|
251
|
-
export function applyPatchFilePaths(patch: string): string[] {
|
|
252
|
-
return splitApplyPatch(patch).map((s) => s.path);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* When a path list must still collapse to ONE (the overflow tail, and the
|
|
257
|
-
* non-fan-out safety net), pick the one a builtin is most likely to deny on
|
|
258
|
-
* rather than element [0]. The probes IMPORT the real builtin regexes — a
|
|
259
|
-
* second hand-maintained copy is how a bypass gets reintroduced by a builtin
|
|
260
|
-
* edit nobody thought to mirror. Falls back to paths[0] when nothing matches.
|
|
261
|
-
*
|
|
262
|
-
* NOT the primary mechanism, and it cannot be: it runs before params are bound,
|
|
263
|
-
* so `block-secrets-write`'s `additionalPatterns` and `block-read-outside-cwd`'s
|
|
264
|
-
* `allowPaths` have no influence on it, and neither does any custom policy.
|
|
265
|
-
* That is exactly why PreToolUse fans out instead of relying on this.
|
|
266
|
-
*/
|
|
267
|
-
export function pickRiskiestPath(paths: string[]): string | undefined {
|
|
268
|
-
if (paths.length === 0) return undefined;
|
|
269
|
-
for (const re of [
|
|
270
|
-
ENV_FILE_PATH_RE,
|
|
271
|
-
SECRET_FILE_RE,
|
|
272
|
-
SECRET_FILE_ID_RSA_RE,
|
|
273
|
-
SECRET_FILE_CREDENTIALS_RE,
|
|
274
|
-
]) {
|
|
275
|
-
const hit = paths.find((p) => re.test(p));
|
|
276
|
-
if (hit) return hit;
|
|
277
|
-
}
|
|
278
|
-
return paths[0];
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/** Everything past the cap / budget, joined into ONE degraded element. It is
|
|
282
|
-
* still EVALUATED — a weaker guarantee we can state honestly, never a silent
|
|
283
|
-
* skip. */
|
|
284
|
-
export function collapseElements(tool: string, els: FanoutElement[]): FanoutElement {
|
|
285
|
-
const first = els[0]!;
|
|
286
|
-
const base = { label: `${els.length} collapsed`, index: first.index, degraded: true as const };
|
|
287
|
-
switch (tool) {
|
|
288
|
-
case "Bash":
|
|
289
|
-
return {
|
|
290
|
-
...base,
|
|
291
|
-
input: {
|
|
292
|
-
...first.input,
|
|
293
|
-
command: els.map((e) => String(e.input.command ?? "")).join(BATCH_JOIN),
|
|
294
|
-
},
|
|
295
|
-
};
|
|
296
|
-
case "Read":
|
|
297
|
-
case "Edit": {
|
|
298
|
-
const paths = els.map((e) => String(e.input.file_path ?? "")).filter(Boolean);
|
|
299
|
-
return {
|
|
300
|
-
...base,
|
|
301
|
-
input: { ...first.input, file_path: pickRiskiestPath(paths), cline_collapsed_paths: paths },
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
case "Grep":
|
|
305
|
-
return {
|
|
306
|
-
...base,
|
|
307
|
-
input: { ...first.input, pattern: els.map((e) => String(e.input.pattern ?? "")).join("|") },
|
|
308
|
-
};
|
|
309
|
-
default:
|
|
310
|
-
return { ...first, ...base };
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Cline → canonical, for every path that does NOT fan out: PostToolUse, audit
|
|
316
|
-
* replay, fail-closed shaping, and a policy reading `ctx.payload`. Derives the
|
|
317
|
-
* best single scalar and PRESERVES the arrays under `cline_*` so a batch-aware
|
|
318
|
-
* policy can still see everything.
|
|
319
|
-
*
|
|
320
|
-
* This is a SAFETY NET, not the enforcement mechanism: a collapse cannot make
|
|
321
|
-
* an anchored regex match every element, which is precisely why PreToolUse fans
|
|
322
|
-
* out instead. `pickRiskiestPath` is what makes the net worth having — element
|
|
323
|
-
* [0] would silently miss a `.env` at `files[1]`.
|
|
324
|
-
*/
|
|
325
|
-
export function canonicalizeClineToolInput(
|
|
326
|
-
toolName: string,
|
|
327
|
-
input: Record<string, unknown>,
|
|
328
|
-
): Record<string, unknown> {
|
|
329
|
-
switch (toolName) {
|
|
330
|
-
case "Bash": {
|
|
331
|
-
const cs = input.commands;
|
|
332
|
-
if (!Array.isArray(cs)) return input;
|
|
333
|
-
const commands = cs.filter((c): c is string => typeof c === "string");
|
|
334
|
-
if (commands.length === 0) return input;
|
|
335
|
-
return { ...omit(input, "commands"), command: commands.join(BATCH_JOIN), cline_commands: commands };
|
|
336
|
-
}
|
|
337
|
-
case "Read": {
|
|
338
|
-
const files = input.files;
|
|
339
|
-
if (!Array.isArray(files)) return input;
|
|
340
|
-
const paths = files
|
|
341
|
-
.map((f) =>
|
|
342
|
-
f && typeof f === "object" && !Array.isArray(f)
|
|
343
|
-
? (f as Record<string, unknown>).path
|
|
344
|
-
: undefined,
|
|
345
|
-
)
|
|
346
|
-
.filter((p): p is string => typeof p === "string");
|
|
347
|
-
if (paths.length === 0) return input;
|
|
348
|
-
return {
|
|
349
|
-
...omit(input, "files"),
|
|
350
|
-
file_path: pickRiskiestPath(paths),
|
|
351
|
-
cline_files: files,
|
|
352
|
-
cline_file_paths: paths,
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
case "Grep": {
|
|
356
|
-
const qs = input.queries;
|
|
357
|
-
if (!Array.isArray(qs)) return input;
|
|
358
|
-
const queries = qs.filter((q): q is string => typeof q === "string");
|
|
359
|
-
if (queries.length === 0) return input;
|
|
360
|
-
return { ...omit(input, "queries"), pattern: queries.join("|"), cline_queries: queries };
|
|
361
|
-
}
|
|
362
|
-
case "Edit": {
|
|
363
|
-
const blob = input.input;
|
|
364
|
-
if (typeof blob !== "string") return input;
|
|
365
|
-
const sections = splitApplyPatch(blob);
|
|
366
|
-
if (sections.length === 0) return input;
|
|
367
|
-
const paths = sections.map((s) => s.path);
|
|
368
|
-
return {
|
|
369
|
-
...input,
|
|
370
|
-
patch: blob,
|
|
371
|
-
file_path: pickRiskiestPath(paths),
|
|
372
|
-
old_string: sections.map((s) => s.oldText).join("\n"),
|
|
373
|
-
new_string: sections.map((s) => s.newText).join("\n"),
|
|
374
|
-
cline_patch_files: paths,
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
default:
|
|
378
|
-
return input;
|
|
379
|
-
}
|
|
380
|
-
}
|