failproofai 1.0.12 → 1.0.13-beta.1
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 +13 -13
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +2 -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 +2 -2
- 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 +2 -2
- 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 +4 -3
- 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 +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +6 -5
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +27 -26
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js +4 -3
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +6 -5
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +6 -5
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +6 -5
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +6 -5
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +4 -3
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +7 -6
- 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 +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +6 -5
- 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 +5 -4
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +21 -20
- 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 +10 -9
- 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 +7 -6
- 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 +8 -8
- package/.next/standalone/.next/server/app/settings/page.js +6 -5
- 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]__0vt9i6fqinjne._.js → [externals]__1h83uo-b1b6-2._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__214wn4wh2x79y._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__1rlxpymm37wel._.js → [root-of-the-server]__031qp1lkow_kc._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__038kwryp970nh._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0_hsnj_a2mvl_._.js → [root-of-the-server]__03s1za0hn71yp._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0wg9dk8x8bnau._.js → [root-of-the-server]__07a0sa6fuw5_b._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08atcie7jzswm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfudh2_4f._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0spt0kv8azrpl._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__12kq3x-h7t7i1._.js → [root-of-the-server]__0yvyp5b7jmlc4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__02vous7mpi2xm._.js → [root-of-the-server]__145vo_drnuvas._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[externals]__0h0p9dmv_e7r7._.js → [root-of-the-server]__1a2d0ewycsp6k._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[externals]__1_407huhlmj1m._.js → [root-of-the-server]__1am_1tz0o0aqz._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__03i5o4a840guz._.js → [root-of-the-server]__1gxfzuvpyw30j._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1j6kfp0vzu5rw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l0ayum_hqqsw._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1lh8c0mmhdrbj._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1o9rznwc0w7og._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0f_4g-vazrvxv._.js → [root-of-the-server]__1o_622x0fglpr._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1oclamblhzhrf._.js +68 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1v1-l-83czzsr._.js +63 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1a5zkndjwlc13._.js → [root-of-the-server]__1wwi53kkqhnfi._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{_1y590mjzpkbos._.js → _02sa8fcu9_9xo._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1-2owkp-1_987._.js +1 -1
- package/.next/standalone/.next/server/chunks/_13ltj8a9z92o8._.js +1 -1
- package/.next/standalone/.next/server/chunks/_15k37au70vjvg._.js +1 -1
- package/.next/standalone/.next/server/chunks/_18rfu4__wjhwb._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +2 -2
- package/.next/standalone/.next/server/chunks/_1fz8m31sndkcu._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ogwigfb0163w._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_@opentelemetry_api_build_esm_index_0oo58a7rymoxh.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_@opentelemetry_api_build_esm_index_1jp9ij0_ddtgk.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oigsgz07._.js +2 -2
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p77cu37y._.js +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ffu2-38y03ic._.js → [root-of-the-server]__021vebe-4il8s._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__075uro8t92s0_._.js +14 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[externals]__12qr51qgrrt6o._.js → [root-of-the-server]__097i34ct1o88x._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0alpzjn3450sr._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0aup10z2o8zc1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bioghlkjf7s7._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01j58mdcdw0vn._.js → [root-of-the-server]__0ed1zh4scn7-k._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0naevg4bcoh54._.js → [root-of-the-server]__0evgy902m9h5e._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__167mipqmjprq5._.js → [root-of-the-server]__0mhtkwwx1pxcq._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nhm28v58ty9z._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vse4qi496ol-._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__17r4zrwanhp6r._.js → [root-of-the-server]__0yb3u36xjy3b9._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0g8b0kyorya-t._.js → [root-of-the-server]__0ywj2u6ovfm_5._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0zn1d4blhd3bu._.js → [root-of-the-server]__10v5cyxvj64j4._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190xwrr5zrfi3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1vx7o8ukefudh._.js → [root-of-the-server]__1guwlpkyurdn9._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1k96jctukf65_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1sj-wn2jp6va5._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vofkb2oq7p7e._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1s2-ck3k3rsoo._.js → [root-of-the-server]__20dt376-socef._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1lnfv02ucky7m._.js → [root-of-the-server]__2158020r_amn9._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1d98fyfrcaqhy._.js → _0bc4f4quq6w47._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0ouu886szh6yj._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_09s4n108bqreq._.js → node_modules_0ptcnmeaxvd_a._.js} +22 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_@opentelemetry_api_build_esm_index_0ntwr8lzj6p2i.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_0tqc05n832v7a.js → node_modules_html-to-image_es_index_1jwgv0pf-gy96.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0bz67659f5z-3._.js +32 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0janj0i6dqko7._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0ocrceo0c9psx._.js +32 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1alv566ojmz5j._.js +32 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1khq67j4vo9y4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_shared_lib_0ftnv26hg1lry._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dagmbznysrc2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuznb72p7z._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +13 -13
- package/.next/standalone/.next/server/middleware.js +2 -2
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
- package/.next/standalone/.next/static/chunks/0cbom4-ijx_a_.js +1 -0
- package/.next/standalone/.next/static/chunks/0u5weo5jdn2s8.js +1 -0
- package/.next/standalone/.next/static/chunks/{0el9n3h9_zp5m.js → 18-icoqze51kl.js} +1 -1
- package/.next/standalone/.next/static/chunks/2d-u90dt4-8rd.js +6 -0
- package/.next/standalone/.next/static/chunks/2n-bzb7pxe7hu.js +1 -0
- package/.next/standalone/.next/static/chunks/{0umzct31duk5g.js → 2zc7lg-jq353g.js} +1 -1
- package/.next/standalone/.next/static/chunks/{27cavoc8paelg.js → 33djjf12bhcsv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0wobqgosirs8p.js → 38u_i3j5funpi.js} +1 -1
- package/.next/standalone/.next/static/chunks/3symuj7t4js-c.js +1 -0
- package/.next/standalone/.next/static/chunks/{1kduj74-715jh.js → 3vzut6zpdrvtx.js} +1 -1
- package/.next/standalone/.next/static/chunks/{063al_q720fkj.js → 3xgxl1s_in776.js} +2 -2
- package/.next/standalone/SECURITY.md +20 -4
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +15 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -1
- package/.next/standalone/fp-cloud-cli/uv.lock +4 -4
- package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
- 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/app-page-turbo-experimental.runtime.prod.js +24 -24
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +26 -26
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +3 -3
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +13 -13
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/app-render/app-render.js +41 -40
- package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering-validation.js +814 -0
- package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering.js +1 -799
- package/.next/standalone/node_modules/next/dist/server/base-server.js +39 -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/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/dedupe-fetch.js +4 -43
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch-symbol.js +13 -0
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +3 -7
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/instrumentation-globals.external.js +77 -12
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/trace/constants.js +12 -0
- package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +30 -14
- package/.next/standalone/node_modules/next/dist/server/next-server.js +10 -11
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/pages-handler.js +29 -23
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +85 -8
- 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 +124 -65
- package/.next/standalone/node_modules/next/dist/server/web/forward-trace-context.js +102 -0
- 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 +10 -10
- 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 +31 -27
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +33 -27
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +38 -30
- 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 +10 -10
- package/.next/standalone/sdk/python/CHANGELOG.md +8 -4
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/source.py +2 -2
- package/.next/standalone/sdk/python/pyproject.toml +2 -7
- package/.next/standalone/sdk/python/skill/references/frameworks.md +0 -15
- package/.next/standalone/sdk/python/tests/test_docs.py +1 -4
- package/.next/standalone/sdk/python/tests/test_evaluator_source.py +1 -1
- package/.next/standalone/sdk/python/tests/test_packaging.py +4 -7
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +2 -13
- package/.next/standalone/sdk/python/uv.lock +43 -905
- package/.next/standalone/sdk/typescript/CHANGELOG.md +52 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package-lock.json +176 -68
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package.json +2 -2
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +3 -3
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package-lock.json +115 -98
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package.json +3 -3
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +4 -4
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +171 -149
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +5 -2
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +27 -15
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +2 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/deno-npm.ts +1 -1
- package/.next/standalone/server.js +1 -1
- package/README.md +0 -6
- package/dist/cli.mjs +12 -11
- package/dist/worker.mjs +1 -1
- package/hermes-plugin/plugin.yaml +1 -1
- package/openclaw-plugin/daemon-client.js +254 -0
- package/openclaw-plugin/hooks.js +187 -0
- package/openclaw-plugin/index.js +17 -211
- package/package.json +10 -10
- package/scripts/sync-agent-cli-harnesses-prompt.md +26 -31
- package/src/hooks/enforcement-capability.ts +1 -1
- package/src/hooks/integrations.ts +5 -2
- package/.next/standalone/.codex/hooks.json +0 -76
- package/.next/standalone/.cursor/hooks.json +0 -47
- package/.next/standalone/.factory/hooks.json +0 -112
- package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t9ufnv5hi2hq._.js +0 -327
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1aaw59g-5uty7._.js +0 -322
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__0ilfh9mfnzsth._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__0ohnuzsaozaca._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pwj2h2efe5f-._.js +0 -14
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0zuikgt2xho-v._.js +0 -271
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_158jo-9mwvgad._.js +0 -291
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_19r82zsxo2jj1._.js +0 -291
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1dupwucoqt5qm._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_shared_lib_03w27x2kh17_8._.js +0 -23
- package/.next/standalone/.next/static/chunks/0k7g_8x3o6gd-.js +0 -1
- package/.next/standalone/.next/static/chunks/12rug3jilwqzs.js +0 -1
- package/.next/standalone/.next/static/chunks/2701amhrbsbot.js +0 -1
- package/.next/standalone/.next/static/chunks/2ve23a7keupjw.js +0 -1
- package/.next/standalone/.next/static/chunks/3bv6xaoitjpnh.js +0 -6
- package/.next/standalone/.opencode/opencode.json +0 -4
- package/.next/standalone/.opencode/plugins/failproofai.mjs +0 -210
- package/.next/standalone/.pi/settings.json +0 -5
- package/.next/standalone/node_modules/react/cjs/react.development.js +0 -1330
- package/scripts/dev-hook.mjs +0 -333
- /package/.next/standalone/.next/static/{D7LY1YSrw96ZxKSpxxrFw → 1n2dyfTQb0MDajeqlipJy}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{D7LY1YSrw96ZxKSpxxrFw → 1n2dyfTQb0MDajeqlipJy}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{D7LY1YSrw96ZxKSpxxrFw → 1n2dyfTQb0MDajeqlipJy}/_ssgManifest.js +0 -0
package/dist/worker.mjs
CHANGED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asks failproofaid for a verdict over its owner-only Unix socket — the same
|
|
3
|
+
* `hook` request `failproofai --hook <event> --cli openclaw` sends to the
|
|
4
|
+
* daemon (crates/PROTOCOL.md), made from inside the gateway instead of from a
|
|
5
|
+
* process spawned per hook. The Hermes plugin (hermes-plugin/client.py) reaches
|
|
6
|
+
* the daemon the same way.
|
|
7
|
+
*
|
|
8
|
+
* Why not spawn the CLI: OpenClaw ≥ 2026.9.6 imports this plugin from a copy
|
|
9
|
+
* under ~/.openclaw/tmp/plugin-captures/…, and the copy holds only this
|
|
10
|
+
* directory's files. A CLI path derived from import.meta.url (`../dist/cli.mjs`)
|
|
11
|
+
* then points at nothing; the old shim read the spawn failure as "allow", so
|
|
12
|
+
* every tool call ran unchecked and no hook activity was recorded. The socket
|
|
13
|
+
* path depends only on the environment, never on where this file sits.
|
|
14
|
+
*
|
|
15
|
+
* Self-contained on purpose — node built-ins only, nothing imported from
|
|
16
|
+
* outside this directory — because the capture copies nothing else.
|
|
17
|
+
*/
|
|
18
|
+
import { createConnection } from "node:net";
|
|
19
|
+
import { homedir } from "node:os";
|
|
20
|
+
import { resolve } from "node:path";
|
|
21
|
+
|
|
22
|
+
export const PROTOCOL_VERSION = 2;
|
|
23
|
+
// The daemon's frame limit (crates/fpai-ipc/src/framing.rs), both ways.
|
|
24
|
+
const MAX_FRAME_BYTES = 16 * 1024 * 1024;
|
|
25
|
+
// The payload limit the CLI applies to its stdin (handler.ts, read-stdin.ts).
|
|
26
|
+
// It bounds the RAW payload: the envelope carries it as an escaped JSON
|
|
27
|
+
// string plus routing fields, so it is larger, and only the frame limit
|
|
28
|
+
// applies to the envelope.
|
|
29
|
+
export const MAX_PAYLOAD_BYTES = 1_048_576;
|
|
30
|
+
|
|
31
|
+
// The CLI's daemon client budgets these separately for the reason it gives:
|
|
32
|
+
// connecting is the "is anything listening" probe, the response covers the
|
|
33
|
+
// whole evaluation. 250 ms matches the Hermes plugin; 30 s matches the
|
|
34
|
+
// daemon's own read timeout on its worker (worker.rs).
|
|
35
|
+
export const CONNECT_TIMEOUT_MS = 250;
|
|
36
|
+
export const RESPONSE_TIMEOUT_MS = 30_000;
|
|
37
|
+
|
|
38
|
+
const PROTOCOL_MISMATCH_MESSAGE =
|
|
39
|
+
"failproofaid is running a different protocol version than this plugin, so it cannot " +
|
|
40
|
+
"evaluate this call. Run `failproofai update` to update the daemon.";
|
|
41
|
+
const UNREACHABLE_MESSAGE =
|
|
42
|
+
"failproofaid could not be reached. This machine is configured to run hooks through it " +
|
|
43
|
+
"— check the daemon (see `failproofai config`) rather than retrying blindly.";
|
|
44
|
+
|
|
45
|
+
/** Mirrors `daemonSocket()` in src/hooks/fp-home.ts. */
|
|
46
|
+
export function daemonSocketPath(env = process.env, home = homedir()) {
|
|
47
|
+
return (
|
|
48
|
+
env.FAILPROOFAI_DAEMON_SOCKET ||
|
|
49
|
+
resolve(env.FAILPROOFAI_HOME || resolve(home, ".failproofai"), "run", "failproofaid.sock")
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The gateway profile's openclaw.json — what the spawned CLI computed from the
|
|
55
|
+
* gateway's environment (`runtimeAgentSettingsPath("openclaw", …)` in
|
|
56
|
+
* src/hooks/agent-roster.ts). Sent explicitly: left out, the daemon's worker
|
|
57
|
+
* would resolve it from the DAEMON's environment and attribute a
|
|
58
|
+
* `--profile <name>` gateway to the default profile.
|
|
59
|
+
*/
|
|
60
|
+
export function openclawAgentSettingsPath(env = process.env, home = homedir()) {
|
|
61
|
+
const config = env.OPENCLAW_CONFIG_PATH;
|
|
62
|
+
if (config?.trim()) return resolve(config);
|
|
63
|
+
const state = env.OPENCLAW_STATE_DIR || env.OPENCLAW_HOME;
|
|
64
|
+
if (state?.trim()) return resolve(state, "openclaw.json");
|
|
65
|
+
const profile = env.OPENCLAW_PROFILE?.trim();
|
|
66
|
+
if (profile && profile !== "default" && /^[A-Za-z0-9._-]{1,80}$/.test(profile) && !profile.startsWith(".")) {
|
|
67
|
+
return resolve(home, `.openclaw-${profile}`, "openclaw.json");
|
|
68
|
+
}
|
|
69
|
+
return resolve(home, ".openclaw", "openclaw.json");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function failed(failure, message) {
|
|
73
|
+
return { ok: false, failure, message };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Turn the daemon's reply into a flat `{permission, reason}` verdict. For
|
|
78
|
+
* OpenClaw the evaluator always exits 0 and prints either nothing (allow) or
|
|
79
|
+
* one JSON object, so anything else is an evaluation failure — never an allow.
|
|
80
|
+
*/
|
|
81
|
+
function readHookResult(message) {
|
|
82
|
+
if (message === null || typeof message !== "object" || Array.isArray(message)) {
|
|
83
|
+
return failed("invalid", "failproofaid returned a non-object response");
|
|
84
|
+
}
|
|
85
|
+
if (message.protocolVersion !== PROTOCOL_VERSION) {
|
|
86
|
+
return failed("protocol-mismatch", PROTOCOL_MISMATCH_MESSAGE);
|
|
87
|
+
}
|
|
88
|
+
if (message.type === "error") {
|
|
89
|
+
const detail = typeof message.message === "string" && message.message ? message.message : "no detail";
|
|
90
|
+
return failed("evaluation", `failproofaid could not evaluate this call: ${detail}`);
|
|
91
|
+
}
|
|
92
|
+
if (message.type !== "hookResult") {
|
|
93
|
+
return failed("invalid", `failproofaid returned an unexpected ${JSON.stringify(message.type)} response`);
|
|
94
|
+
}
|
|
95
|
+
// The daemon always serializes all three (crates/fpai-ipc/src/envelope.rs);
|
|
96
|
+
// a frame missing one is not a hookResult, and must not read as an empty
|
|
97
|
+
// stdout — that is the allow.
|
|
98
|
+
if (
|
|
99
|
+
!Number.isInteger(message.exitCode) ||
|
|
100
|
+
typeof message.stdout !== "string" ||
|
|
101
|
+
typeof message.stderr !== "string"
|
|
102
|
+
) {
|
|
103
|
+
return failed("invalid", "failproofaid returned an incomplete hookResult");
|
|
104
|
+
}
|
|
105
|
+
if (message.exitCode !== 0) {
|
|
106
|
+
return failed("evaluation", `failproofai exited ${String(message.exitCode)} without a verdict`);
|
|
107
|
+
}
|
|
108
|
+
const stdout = message.stdout.trim();
|
|
109
|
+
if (!stdout) return { ok: true, verdict: { permission: "allow" } };
|
|
110
|
+
let verdict;
|
|
111
|
+
try {
|
|
112
|
+
verdict = JSON.parse(stdout);
|
|
113
|
+
} catch {
|
|
114
|
+
return failed("invalid", "failproofai returned a verdict that is not JSON");
|
|
115
|
+
}
|
|
116
|
+
return isVerdict(verdict)
|
|
117
|
+
? { ok: true, verdict }
|
|
118
|
+
: failed("invalid", "failproofai returned a malformed verdict");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const PERMISSIONS = new Set(["allow", "deny", "instruct"]);
|
|
122
|
+
|
|
123
|
+
/** The flat shape policy-evaluator.ts prints for `--cli openclaw`; unknown keys are ignored. */
|
|
124
|
+
function isVerdict(verdict) {
|
|
125
|
+
if (verdict === null || typeof verdict !== "object" || Array.isArray(verdict)) return false;
|
|
126
|
+
if (!PERMISSIONS.has(verdict.permission)) return false;
|
|
127
|
+
if (verdict.reason !== undefined && typeof verdict.reason !== "string") return false;
|
|
128
|
+
if (verdict.policyName !== undefined && typeof verdict.policyName !== "string") return false;
|
|
129
|
+
if (
|
|
130
|
+
verdict.policyNames !== undefined &&
|
|
131
|
+
!(Array.isArray(verdict.policyNames) && verdict.policyNames.every((name) => typeof name === "string"))
|
|
132
|
+
) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* One request, one connection, one frame each way. Never rejects: resolves to
|
|
140
|
+
* `{ok: true, verdict}` (plus `oversized: true`, see below) or
|
|
141
|
+
* `{ok: false, failure, message}`.
|
|
142
|
+
*
|
|
143
|
+
* A payload over MAX_PAYLOAD_BYTES is sent as an empty stdin, exactly as the
|
|
144
|
+
* CLI discards an oversized stdin and evaluates an empty payload;
|
|
145
|
+
* `oversized: true` lets the caller say so instead of discarding it silently.
|
|
146
|
+
*/
|
|
147
|
+
export function requestHookVerdict({
|
|
148
|
+
event,
|
|
149
|
+
payload,
|
|
150
|
+
cwd = "",
|
|
151
|
+
agentSettingsPath = "",
|
|
152
|
+
socketPath = daemonSocketPath(),
|
|
153
|
+
connectTimeoutMs = CONNECT_TIMEOUT_MS,
|
|
154
|
+
responseTimeoutMs = RESPONSE_TIMEOUT_MS,
|
|
155
|
+
}) {
|
|
156
|
+
return new Promise((done) => {
|
|
157
|
+
let body;
|
|
158
|
+
let oversized = false;
|
|
159
|
+
try {
|
|
160
|
+
let stdin = JSON.stringify(payload ?? {});
|
|
161
|
+
if (Buffer.byteLength(stdin, "utf8") > MAX_PAYLOAD_BYTES) {
|
|
162
|
+
stdin = "";
|
|
163
|
+
oversized = true;
|
|
164
|
+
}
|
|
165
|
+
body = Buffer.from(
|
|
166
|
+
JSON.stringify({
|
|
167
|
+
type: "hook",
|
|
168
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
169
|
+
hookEvent: event,
|
|
170
|
+
cli: "openclaw",
|
|
171
|
+
stdin,
|
|
172
|
+
...(typeof cwd === "string" && cwd ? { cwd } : {}),
|
|
173
|
+
agentSettingsPath: agentSettingsPath || "",
|
|
174
|
+
}),
|
|
175
|
+
"utf8",
|
|
176
|
+
);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
done(failed("invalid", `could not encode the hook request: ${err?.message ?? String(err)}`));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Unreachable for a payload within MAX_PAYLOAD_BYTES (escaping at most
|
|
182
|
+
// sextuples it); kept so nothing over the daemon's limit is ever sent.
|
|
183
|
+
if (body.length > MAX_FRAME_BYTES) {
|
|
184
|
+
done(failed("invalid", "hook request exceeds the daemon's 16 MiB frame limit"));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let settled = false;
|
|
189
|
+
let connected = false;
|
|
190
|
+
let received = Buffer.alloc(0);
|
|
191
|
+
let timer;
|
|
192
|
+
let socket;
|
|
193
|
+
const finish = (result) => {
|
|
194
|
+
if (settled) return;
|
|
195
|
+
settled = true;
|
|
196
|
+
clearTimeout(timer);
|
|
197
|
+
try { socket?.destroy(); } catch { /* already closed */ }
|
|
198
|
+
done(result);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
socket = createConnection(socketPath);
|
|
203
|
+
} catch {
|
|
204
|
+
finish(failed("unreachable", UNREACHABLE_MESSAGE));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
timer = setTimeout(() => finish(failed("unreachable", UNREACHABLE_MESSAGE)), connectTimeoutMs);
|
|
208
|
+
|
|
209
|
+
socket.on("connect", () => {
|
|
210
|
+
connected = true;
|
|
211
|
+
clearTimeout(timer);
|
|
212
|
+
timer = setTimeout(
|
|
213
|
+
() => finish(failed("timeout", `failproofaid did not answer within ${responseTimeoutMs} ms`)),
|
|
214
|
+
responseTimeoutMs,
|
|
215
|
+
);
|
|
216
|
+
const header = Buffer.alloc(4);
|
|
217
|
+
header.writeUInt32BE(body.length, 0);
|
|
218
|
+
socket.write(Buffer.concat([header, body]));
|
|
219
|
+
});
|
|
220
|
+
socket.on("data", (chunk) => {
|
|
221
|
+
received = Buffer.concat([received, chunk]);
|
|
222
|
+
if (received.length < 4) return;
|
|
223
|
+
const length = received.readUInt32BE(0);
|
|
224
|
+
if (length > MAX_FRAME_BYTES) {
|
|
225
|
+
finish(failed("invalid", "failproofaid response exceeds the 16 MiB limit"));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (received.length < 4 + length) return;
|
|
229
|
+
let message;
|
|
230
|
+
try {
|
|
231
|
+
message = JSON.parse(received.subarray(4, 4 + length).toString("utf8"));
|
|
232
|
+
} catch {
|
|
233
|
+
finish(failed("invalid", "failproofaid returned a response that is not JSON"));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const result = readHookResult(message);
|
|
237
|
+
finish(result.ok && oversized ? { ...result, oversized: true } : result);
|
|
238
|
+
});
|
|
239
|
+
socket.on("error", (err) => {
|
|
240
|
+
finish(
|
|
241
|
+
connected
|
|
242
|
+
? failed("evaluation", `failproofaid connection failed: ${err?.message ?? String(err)}`)
|
|
243
|
+
: failed("unreachable", UNREACHABLE_MESSAGE),
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
socket.on("close", () => {
|
|
247
|
+
finish(
|
|
248
|
+
connected
|
|
249
|
+
? failed("evaluation", "failproofaid closed the connection before returning a verdict")
|
|
250
|
+
: failed("unreachable", UNREACHABLE_MESSAGE),
|
|
251
|
+
);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw typed plugin hooks → failproofai verdicts.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from index.js (whose only job is `definePluginEntry`) so the
|
|
5
|
+
* hook wiring is importable without the `openclaw/plugin-sdk` package, which
|
|
6
|
+
* only resolves inside the gateway.
|
|
7
|
+
*
|
|
8
|
+
* Each hook sends a Claude-shaped payload (params→tool_input, toolName→
|
|
9
|
+
* tool_name, transcriptPath→transcript_path, stopHookActive→stop_hook_active,
|
|
10
|
+
* sessionKey→session_id) with the RAW event and tool names; the daemon's
|
|
11
|
+
* worker canonicalizes them via the OPENCLAW_* maps in src/hooks/types.ts
|
|
12
|
+
* (single source of truth — no inline maps here, unlike the OpenCode/Pi shims).
|
|
13
|
+
*
|
|
14
|
+
* When failproofaid cannot return a verdict the gates fail closed, as every
|
|
15
|
+
* other CLI does on a daemon-configured machine (bin/failproofai.mjs): a tool
|
|
16
|
+
* call or prompt is blocked with the reason, and the reason is logged. The
|
|
17
|
+
* turn-end gate is the exception — a revise cannot bring the daemon back, so
|
|
18
|
+
* forcing one would loop the turn instead of protecting anything.
|
|
19
|
+
*/
|
|
20
|
+
import { createInstructRetryGate, mapBeforeToolVerdict } from "./instruct-retry-gate.js";
|
|
21
|
+
import { createWorkspaceContext } from "./workspace-context.js";
|
|
22
|
+
import { openclawAgentSettingsPath, requestHookVerdict } from "./daemon-client.js";
|
|
23
|
+
|
|
24
|
+
const sharedRetryGate = createInstructRetryGate();
|
|
25
|
+
const sharedWorkspace = createWorkspaceContext();
|
|
26
|
+
|
|
27
|
+
const OBSERVATION_EVENTS = [
|
|
28
|
+
"after_tool_call",
|
|
29
|
+
"session_start",
|
|
30
|
+
"session_end",
|
|
31
|
+
"subagent_ended",
|
|
32
|
+
"before_compaction",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const HOOK_OPTIONS = { priority: 100, timeoutMs: 60_000 };
|
|
36
|
+
|
|
37
|
+
/** Claude-shaped stdin base. Extra keys are ignored by the evaluator's payload
|
|
38
|
+
* parser; they're forwarded for activity attribution. */
|
|
39
|
+
function baseMeta(payload, ctx, config, workspace) {
|
|
40
|
+
const p = payload || {};
|
|
41
|
+
const c = ctx || {};
|
|
42
|
+
return {
|
|
43
|
+
session_id: c.sessionId ?? p.sessionId ?? c.sessionKey ?? p.sessionKey,
|
|
44
|
+
cwd: workspace.resolveWorkspace(p, c, config) ?? process.cwd(),
|
|
45
|
+
transcript_path: p.transcriptPath,
|
|
46
|
+
stop_hook_active: p.stopHookActive === true,
|
|
47
|
+
openclaw: {
|
|
48
|
+
agentId: c.agentId,
|
|
49
|
+
sessionKey: c.sessionKey ?? p.sessionKey,
|
|
50
|
+
runId: c.runId ?? p.runId,
|
|
51
|
+
provider: p.provider,
|
|
52
|
+
model: p.model,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function defaultEvaluate(event, payload) {
|
|
58
|
+
return requestHookVerdict({
|
|
59
|
+
event,
|
|
60
|
+
payload,
|
|
61
|
+
cwd: payload.cwd,
|
|
62
|
+
agentSettingsPath: openclawAgentSettingsPath(),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function logFailure(api, event, message) {
|
|
67
|
+
const line = `[failproofai] ${event}: ${message}`;
|
|
68
|
+
try {
|
|
69
|
+
if (typeof api?.logger?.error === "function") {
|
|
70
|
+
api.logger.error(line);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
} catch { /* fall through to stderr */ }
|
|
74
|
+
process.stderr.write(`${line}\n`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const blockedReason = (message) => `FailproofAI could not check this call, so it was blocked: ${message}`;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Register every hook on `api`. `evaluate(event, payload)` resolves to
|
|
81
|
+
* `{ok: true, verdict}` or `{ok: false, message}`; tests inject their own.
|
|
82
|
+
*/
|
|
83
|
+
export function registerFailproofaiHooks(api, {
|
|
84
|
+
evaluate = defaultEvaluate,
|
|
85
|
+
retryGate = sharedRetryGate,
|
|
86
|
+
workspace = sharedWorkspace,
|
|
87
|
+
} = {}) {
|
|
88
|
+
const ask = async (event, payload) => {
|
|
89
|
+
let result;
|
|
90
|
+
try {
|
|
91
|
+
result = await evaluate(event, payload);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
result = { ok: false, message: `the failproofai plugin failed: ${err?.message ?? String(err)}` };
|
|
94
|
+
}
|
|
95
|
+
if (!result?.ok) logFailure(api, event, result?.message ?? "no verdict");
|
|
96
|
+
// Same outcome as the CLI's oversized stdin (warn, evaluate an empty
|
|
97
|
+
// payload), and said out loud for the same reason it is there.
|
|
98
|
+
else if (result.oversized) {
|
|
99
|
+
logFailure(api, event, "payload exceeds 1 MiB, so it was evaluated as an empty payload");
|
|
100
|
+
}
|
|
101
|
+
return result ?? { ok: false, message: "no verdict" };
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// before_tool_call → PreToolUse. Deny always blocks. Instruct blocks the
|
|
105
|
+
// first matching attempt only, using blockReason to give the model the
|
|
106
|
+
// instruction, then permits retries from that session/policy for 5 minutes.
|
|
107
|
+
api.on(
|
|
108
|
+
"before_tool_call",
|
|
109
|
+
async (payload, ctx) => {
|
|
110
|
+
const p = payload || {};
|
|
111
|
+
const result = await ask("before_tool_call", {
|
|
112
|
+
...baseMeta(payload, ctx, api.config, workspace),
|
|
113
|
+
tool_name: p.toolName,
|
|
114
|
+
tool_input: p.params,
|
|
115
|
+
hook_event_name: "before_tool_call",
|
|
116
|
+
});
|
|
117
|
+
if (!result.ok) return { block: true, blockReason: blockedReason(result.message) };
|
|
118
|
+
return mapBeforeToolVerdict(result.verdict, payload, ctx, retryGate);
|
|
119
|
+
},
|
|
120
|
+
HOOK_OPTIONS,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// before_agent_run → UserPromptSubmit. Deny: return {outcome:"block", reason}.
|
|
124
|
+
api.on(
|
|
125
|
+
"before_agent_run",
|
|
126
|
+
async (payload, ctx) => {
|
|
127
|
+
const p = payload || {};
|
|
128
|
+
workspace.remember(payload, ctx);
|
|
129
|
+
const result = await ask("before_agent_run", {
|
|
130
|
+
...baseMeta(payload, ctx, api.config, workspace),
|
|
131
|
+
prompt: p.prompt,
|
|
132
|
+
hook_event_name: "before_agent_run",
|
|
133
|
+
});
|
|
134
|
+
if (!result.ok) return { outcome: "block", reason: blockedReason(result.message) };
|
|
135
|
+
if (result.verdict.permission === "deny") {
|
|
136
|
+
return { outcome: "block", reason: result.verdict.reason || "Blocked by failproofai" };
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
},
|
|
140
|
+
HOOK_OPTIONS,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// before_agent_finalize → Stop. The real turn-end gate: a deny becomes a
|
|
144
|
+
// revise so the agent runs another pass. The evaluator supplies the
|
|
145
|
+
// MANDATORY ACTION wording; the payload's stop_hook_active guards the
|
|
146
|
+
// require-*-before-stop builtins against infinite loops.
|
|
147
|
+
api.on(
|
|
148
|
+
"before_agent_finalize",
|
|
149
|
+
async (payload, ctx) => {
|
|
150
|
+
const result = await ask("before_agent_finalize", {
|
|
151
|
+
...baseMeta(payload, ctx, api.config, workspace),
|
|
152
|
+
hook_event_name: "before_agent_finalize",
|
|
153
|
+
});
|
|
154
|
+
if (result.ok && result.verdict.permission === "deny") {
|
|
155
|
+
return { action: "revise", reason: result.verdict.reason || "Action required by failproofai" };
|
|
156
|
+
}
|
|
157
|
+
return undefined;
|
|
158
|
+
},
|
|
159
|
+
HOOK_OPTIONS,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Observation hooks — await so activity ordering is stable, ignore verdict.
|
|
163
|
+
// after_tool_call → PostToolUse; session_start/end → SessionStart/End;
|
|
164
|
+
// subagent_ended → SubagentStop (obs only); before_compaction → PreCompact.
|
|
165
|
+
for (const event of OBSERVATION_EVENTS) {
|
|
166
|
+
api.on(
|
|
167
|
+
event,
|
|
168
|
+
async (payload, ctx) => {
|
|
169
|
+
const p = payload || {};
|
|
170
|
+
await ask(event, {
|
|
171
|
+
...baseMeta(payload, ctx, api.config, workspace),
|
|
172
|
+
tool_name: p.toolName,
|
|
173
|
+
tool_input: p.params,
|
|
174
|
+
tool_response: p.result,
|
|
175
|
+
reason: p.reason,
|
|
176
|
+
hook_event_name: event,
|
|
177
|
+
});
|
|
178
|
+
if (event === "session_end") {
|
|
179
|
+
retryGate.clear(payload, ctx);
|
|
180
|
+
workspace.clear(payload, ctx);
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
},
|
|
184
|
+
HOOK_OPTIONS,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|