failproofai 1.0.7-beta.1 → 1.0.7
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 +3 -3
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +4 -4
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +4 -4
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_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/run/route.js +7 -8
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +5 -7
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +6 -6
- 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/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +11 -13
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +7 -8
- 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/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 +7 -7
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +6 -7
- 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/server-reference-manifest.json +8 -41
- package/.next/standalone/.next/server/app/settings/page.js +9 -12
- 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]__1j-zsg5._.js → [externals]__1_bftcl._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__19_pzeq._.js → [externals]__1msfs-h._.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]__1bf34x4._.js → [root-of-the-server]__1_r2rbg._.js} +7 -5
- package/.next/standalone/.next/server/chunks/_09dz7xv._.js +21 -21
- 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/{_1q5i8mb._.js → _1c3k-8x._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +16 -16
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +3 -0
- package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3._.js +2 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-_ki57._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0yxwl6j._.js → [root-of-the-server]__0bd3mje._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cg-bgc._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cpu_mj._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1mf3zp6._.js → [root-of-the-server]__0cxe_2_._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u3w0ll._.js +22 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17d_ffl._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19d9tgz._.js +5 -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]__1jiwfsj._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1phc187._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_06imw3p._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1w_5l7t._.js → _0h_douw._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_214wgrp._.js → _1-i_gzc._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0bn2oo8._.js → _166t73i._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1q46vxx._.js → _1_qswah._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1gb0ifp._.js → _1es2j7i._.js} +5 -5
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.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 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_18_d8l1._.js → node_modules_next_dist_0drixxt._.js} +4 -4
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4._.js +10 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me65._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- 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 +23 -56
- package/.next/standalone/.next/static/chunks/094xgi4owxaqf.js +1 -0
- package/.next/standalone/.next/static/chunks/0__8a7m868fvf.js +1 -0
- package/.next/standalone/.next/static/chunks/{12tvm75t5ffui.js → 0o6qlkgubtoex.js} +1 -1
- package/.next/standalone/.next/static/chunks/13i7-9is-vhys.js +1 -0
- package/.next/standalone/.next/static/chunks/1rz20_pz828f3.js +6 -0
- package/.next/standalone/.next/static/chunks/2k9f4tyv04809.css +1 -0
- package/.next/standalone/.next/static/chunks/{0vmd180qfntfb.js → 2klitrtzpaoe0.js} +1 -1
- package/.next/standalone/.next/static/chunks/{258668t68du6b.js → 2mdh397ghgnvv.js} +1 -1
- package/.next/standalone/.next/static/chunks/2rshywgeqsyzk.css +2 -0
- package/.next/standalone/.next/static/chunks/3pzx4chkhko9k.js +1 -0
- package/.next/standalone/.next/static/chunks/{0qrbdkv9qmvli.js → 3rh5o7e16irrm.js} +1 -1
- package/.next/standalone/.next/static/chunks/{29fql3nbnfc9q.js → 43ufqrz8qo3h-.js} +1 -1
- package/.next/standalone/SECURITY.md +53 -0
- package/.next/standalone/app/actions/pack-actions.ts +0 -12
- package/.next/standalone/app/policies/hooks-client.tsx +0 -9
- package/.next/standalone/app/settings/page.tsx +1 -20
- package/.next/standalone/app/settings/settings-client.tsx +1 -27
- package/.next/standalone/app/settings/settings.css +0 -79
- package/.next/standalone/package.json +9 -9
- package/.next/standalone/sdk/python/skill/SKILL.md +60 -14
- package/.next/standalone/sdk/python/skill/agents/openai.yaml +2 -1
- package/.next/standalone/sdk/python/skill/references/evaluator.md +255 -0
- package/.next/standalone/sdk/python/skill/references/events.md +17 -8
- package/.next/standalone/sdk/python/skill/references/frameworks.md +3 -0
- package/.next/standalone/sdk/python/skill/references/install.md +3 -0
- package/.next/standalone/sdk/python/skill/references/integration.md +6 -2
- package/.next/standalone/sdk/python/skill/references/typescript.md +568 -0
- package/.next/standalone/sdk/typescript/CHANGELOG.md +133 -0
- package/.next/standalone/sdk/typescript/LICENSE +42 -0
- package/.next/standalone/sdk/typescript/README.md +552 -0
- package/.next/standalone/sdk/typescript/eslint.config.mjs +59 -0
- package/.next/standalone/sdk/typescript/examples/research-agent.ts +197 -0
- package/.next/standalone/sdk/typescript/integration/ai.test.ts +920 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/agent.ts +337 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package-lock.json +261 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package.json +16 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/surfaces.ts +605 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/agent.ts +342 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +156 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +16 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/surfaces.ts +628 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/agent.ts +346 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package-lock.json +156 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package.json +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/surfaces.ts +651 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/agent.ts +350 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package-lock.json +153 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package.json +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/surfaces.ts +651 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/tsconfig.surfaces.json +4 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/agent.ts +623 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package-lock.json +344 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package.json +19 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/agent-v1.ts +99 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/agent.ts +623 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package-lock.json +336 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/agent.ts +96 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +441 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +19 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/index.cjs +53 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/index.mjs +55 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/package.json +18 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/agent.ts +659 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +635 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/agent.ts +659 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package-lock.json +553 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/agent.ts +877 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/mcp-server.mjs +66 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +6797 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +24 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/agent.ts +872 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/mcp-server.mjs +66 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +2540 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/actions.ts +18 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/ai/route.ts +42 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/edge/route.ts +29 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/langgraph/route.ts +21 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/llamaindex/route.ts +11 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/mastra/route.ts +19 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/status/route.ts +7 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/layout.tsx +9 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/page.tsx +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/instrumentation.ts +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/ai.ts +61 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/langgraph.ts +68 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/llamaindex.ts +98 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/mastra.ts +90 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/next.config.ts +52 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4343 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +28 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/agent.ts +51 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/deno-npm.ts +76 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package-lock.json +484 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package.json +15 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/types/agent.ts +79 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/types/package-lock.json +740 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/types/package.json +11 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/agent.ts +197 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/package-lock.json +70 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/package.json +12 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/tsconfig.json +12 -0
- package/.next/standalone/sdk/typescript/integration/global-setup.ts +29 -0
- package/.next/standalone/sdk/typescript/integration/harness.ts +451 -0
- package/.next/standalone/sdk/typescript/integration/langchain.test.ts +682 -0
- package/.next/standalone/sdk/typescript/integration/llamaindex.test.ts +709 -0
- package/.next/standalone/sdk/typescript/integration/mastra-coverage.test.ts +386 -0
- package/.next/standalone/sdk/typescript/integration/mastra.test.ts +311 -0
- package/.next/standalone/sdk/typescript/integration/nextjs.test.ts +341 -0
- package/.next/standalone/sdk/typescript/integration/runtime-parity.ts +180 -0
- package/.next/standalone/sdk/typescript/integration/runtimes.bun.test.ts +15 -0
- package/.next/standalone/sdk/typescript/integration/runtimes.core.test.ts +113 -0
- package/.next/standalone/sdk/typescript/integration/runtimes.deno.test.ts +19 -0
- package/.next/standalone/sdk/typescript/integration/types.test.ts +141 -0
- package/.next/standalone/sdk/typescript/integration/vanilla.test.ts +255 -0
- package/.next/standalone/sdk/typescript/package-lock.json +2640 -0
- package/.next/standalone/sdk/typescript/package.json +401 -0
- package/.next/standalone/sdk/typescript/scripts/finalize-build.mjs +123 -0
- package/.next/standalone/sdk/typescript/scripts/release.mjs +177 -0
- package/.next/standalone/sdk/typescript/src/clock.ts +58 -0
- package/.next/standalone/sdk/typescript/src/context.ts +214 -0
- package/.next/standalone/sdk/typescript/src/edge/adapter.ts +18 -0
- package/.next/standalone/sdk/typescript/src/edge/ai.ts +116 -0
- package/.next/standalone/sdk/typescript/src/edge/index.ts +238 -0
- package/.next/standalone/sdk/typescript/src/edge/langchain.ts +18 -0
- package/.next/standalone/sdk/typescript/src/edge/llamaindex.ts +12 -0
- package/.next/standalone/sdk/typescript/src/edge/mastra.ts +17 -0
- package/.next/standalone/sdk/typescript/src/edge/notice.ts +33 -0
- package/.next/standalone/sdk/typescript/src/environment.ts +75 -0
- package/.next/standalone/sdk/typescript/src/evaluator/authoring.ts +480 -0
- package/.next/standalone/sdk/typescript/src/evaluator/cli.ts +96 -0
- package/.next/standalone/sdk/typescript/src/evaluator/client.ts +421 -0
- package/.next/standalone/sdk/typescript/src/evaluator/expression.ts +1292 -0
- package/.next/standalone/sdk/typescript/src/evaluator/index.ts +144 -0
- package/.next/standalone/sdk/typescript/src/evaluator/protocol.ts +747 -0
- package/.next/standalone/sdk/typescript/src/evaluator/runtime.ts +930 -0
- package/.next/standalone/sdk/typescript/src/evaluator/sandbox-worker.ts +171 -0
- package/.next/standalone/sdk/typescript/src/evaluator/source-limits.ts +27 -0
- package/.next/standalone/sdk/typescript/src/evaluator/source.ts +509 -0
- package/.next/standalone/sdk/typescript/src/events.ts +879 -0
- package/.next/standalone/sdk/typescript/src/exit.ts +117 -0
- package/.next/standalone/sdk/typescript/src/index.ts +186 -0
- package/.next/standalone/sdk/typescript/src/integrations/ai.ts +1566 -0
- package/.next/standalone/sdk/typescript/src/integrations/compat.ts +322 -0
- package/.next/standalone/sdk/typescript/src/integrations/core.ts +1321 -0
- package/.next/standalone/sdk/typescript/src/integrations/index.ts +355 -0
- package/.next/standalone/sdk/typescript/src/integrations/langchain.ts +2340 -0
- package/.next/standalone/sdk/typescript/src/integrations/llamaindex.ts +2111 -0
- package/.next/standalone/sdk/typescript/src/integrations/mastra.ts +1802 -0
- package/.next/standalone/sdk/typescript/src/logger.ts +98 -0
- package/.next/standalone/sdk/typescript/src/next.ts +115 -0
- package/.next/standalone/sdk/typescript/src/node-require.ts +446 -0
- package/.next/standalone/sdk/typescript/src/redact.ts +305 -0
- package/.next/standalone/sdk/typescript/src/resolver.ts +120 -0
- package/.next/standalone/sdk/typescript/src/runtime.ts +29 -0
- package/.next/standalone/sdk/typescript/src/schema.ts +410 -0
- package/.next/standalone/sdk/typescript/src/scopes.ts +701 -0
- package/.next/standalone/sdk/typescript/src/shared.ts +33 -0
- package/.next/standalone/sdk/typescript/src/version.ts +5 -0
- package/.next/standalone/sdk/typescript/src/writer.ts +934 -0
- package/.next/standalone/sdk/typescript/test/adapters.test.ts +397 -0
- package/.next/standalone/sdk/typescript/test/ai.test.ts +1076 -0
- package/.next/standalone/sdk/typescript/test/copies.test.ts +204 -0
- package/.next/standalone/sdk/typescript/test/edge.test.ts +183 -0
- package/.next/standalone/sdk/typescript/test/evaluator-client.test.ts +234 -0
- package/.next/standalone/sdk/typescript/test/evaluator-protocol.test.ts +225 -0
- package/.next/standalone/sdk/typescript/test/events.test.ts +193 -0
- package/.next/standalone/sdk/typescript/test/expression.test.ts +181 -0
- package/.next/standalone/sdk/typescript/test/global-setup.ts +26 -0
- package/.next/standalone/sdk/typescript/test/helpers.ts +130 -0
- package/.next/standalone/sdk/typescript/test/integrations.test.ts +369 -0
- package/.next/standalone/sdk/typescript/test/langchain-copies.test.ts +204 -0
- package/.next/standalone/sdk/typescript/test/langchain.test.ts +999 -0
- package/.next/standalone/sdk/typescript/test/llamaindex.test.ts +1760 -0
- package/.next/standalone/sdk/typescript/test/mastra-coverage.test.ts +501 -0
- package/.next/standalone/sdk/typescript/test/mastra-lifecycle.test.ts +479 -0
- package/.next/standalone/sdk/typescript/test/mastra.test.ts +285 -0
- package/.next/standalone/sdk/typescript/test/next.test.ts +109 -0
- package/.next/standalone/sdk/typescript/test/packaging.test.ts +312 -0
- package/.next/standalone/sdk/typescript/test/redaction.test.ts +171 -0
- package/.next/standalone/sdk/typescript/test/runtimes.test.ts +101 -0
- package/.next/standalone/sdk/typescript/test/sandbox.test.ts +189 -0
- package/.next/standalone/sdk/typescript/test/scopes.test.ts +271 -0
- package/.next/standalone/sdk/typescript/test/setup.ts +19 -0
- package/.next/standalone/sdk/typescript/test/skill-snippets.test.ts +73 -0
- package/.next/standalone/sdk/typescript/test/spool-contract.test.ts +124 -0
- package/.next/standalone/sdk/typescript/test/tracker-bounds.test.ts +191 -0
- package/.next/standalone/sdk/typescript/test/wire-format.test.ts +214 -0
- package/.next/standalone/sdk/typescript/test/writer.test.ts +407 -0
- package/.next/standalone/sdk/typescript/tsconfig.build.json +15 -0
- package/.next/standalone/sdk/typescript/tsconfig.cjs.json +19 -0
- package/.next/standalone/sdk/typescript/tsconfig.json +28 -0
- package/.next/standalone/sdk/typescript/vitest.config.ts +33 -0
- package/.next/standalone/sdk/typescript/vitest.integration.config.ts +23 -0
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +2 -115
- package/dist/cli.mjs +6538 -13686
- package/dist/index.js +1 -19
- package/dist/worker.mjs +2085 -8012
- package/package.json +9 -9
- package/pi-extension/index.ts +0 -11
- package/scripts/build-policy-pack.mjs +2 -39
- package/src/hooks/builtin-policies.ts +3 -21
- package/src/hooks/cloud-enrollment-cli.ts +1 -1
- package/src/hooks/cloud-managed-policies.ts +0 -22
- package/src/hooks/custom-hooks-loader.ts +7 -45
- package/src/hooks/custom-hooks-registry.ts +1 -45
- package/src/hooks/first-run-gate.ts +0 -5
- package/src/hooks/fp-home.ts +0 -23
- package/src/hooks/handler.ts +6 -265
- package/src/hooks/hook-activity-store.ts +1 -105
- package/src/hooks/hook-telemetry.ts +0 -41
- package/src/hooks/loader-utils.ts +0 -6
- package/src/hooks/pack-cli.ts +17 -278
- package/src/hooks/pack-manifest.ts +7 -479
- package/src/hooks/pack-store.ts +10 -156
- package/src/hooks/policy-catalog.ts +0 -65
- package/src/hooks/policy-evaluator.ts +796 -940
- package/src/hooks/policy-registry.ts +0 -25
- package/src/hooks/policy-types.ts +0 -126
- package/src/hooks/worker-server.ts +26 -119
- package/src/index.ts +0 -6
- package/.next/standalone/.next/server/chunks/src_hooks_01frwmb._.js +0 -5
- package/.next/standalone/.next/server/chunks/src_hooks_18qtd42._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01bmjsj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__059yza8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0eip4_k._.js +0 -22
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qcb0mg._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qxnccm._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s_yomn._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0soxz2z._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yrsbd_._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__13d-wb6._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dinjii._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qiz0e4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0uyu3jf._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1feuvhb._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0w6mzq5._.js +0 -151
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_095a_79._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_15t8kqj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_18k8rl0._.js +0 -12
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1fm2w5z._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1j0zy3v._.js +0 -3
- package/.next/standalone/.next/static/chunks/0cd-_8-c-m1ea.js +0 -6
- package/.next/standalone/.next/static/chunks/0uldbut9y2-e8.js +0 -1
- package/.next/standalone/.next/static/chunks/1u5zsejmgrir_.js +0 -1
- package/.next/standalone/.next/static/chunks/285spx855h_3r.css +0 -2
- package/.next/standalone/.next/static/chunks/2qv4hshejedtx.css +0 -1
- package/.next/standalone/.next/static/chunks/2vkvu9-opa_1z.js +0 -1
- package/.next/standalone/.next/static/chunks/37lhv7wa3ywt6.js +0 -1
- package/.next/standalone/app/actions/get-jev-config.ts +0 -409
- package/.next/standalone/app/actions/update-jev-config.ts +0 -420
- package/.next/standalone/app/components/jev-notices.tsx +0 -96
- package/.next/standalone/app/settings/jev-panel.tsx +0 -469
- package/src/hooks/effective-reviewers.ts +0 -79
- package/src/hooks/jev-activity.ts +0 -385
- package/src/hooks/jev-cli.ts +0 -1193
- package/src/hooks/policy-authority.ts +0 -333
- package/src/hooks/policy-reviewability.ts +0 -229
- package/src/hooks/semantic/combine.ts +0 -541
- package/src/hooks/semantic/compile.ts +0 -176
- package/src/hooks/semantic/decide.ts +0 -392
- package/src/hooks/semantic/envelope.ts +0 -1296
- package/src/hooks/semantic/evaluator.ts +0 -547
- package/src/hooks/semantic/facts.ts +0 -292
- package/src/hooks/semantic/intent.ts +0 -1190
- package/src/hooks/semantic/jev-client.ts +0 -643
- package/src/hooks/semantic/jev-config.ts +0 -594
- package/src/hooks/semantic/jev-review.ts +0 -374
- package/src/hooks/semantic/jev-stats.ts +0 -289
- package/src/hooks/semantic/jev-throttle.ts +0 -421
- package/src/hooks/semantic/pack-policies.ts +0 -251
- package/src/hooks/semantic/policies.ts +0 -596
- package/src/hooks/semantic/precondition-names.ts +0 -60
- package/src/hooks/semantic/preconditions.ts +0 -58
- package/src/hooks/semantic/redact.ts +0 -2910
- package/src/hooks/semantic/types.ts +0 -145
- package/src/hooks/semver-precedence.ts +0 -128
- /package/.next/standalone/.next/static/{T8YAYM9h_64fKv705vug7 → PgeWCHmyVbjRznv2VO7KF}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{T8YAYM9h_64fKv705vug7 → PgeWCHmyVbjRznv2VO7KF}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{T8YAYM9h_64fKv705vug7 → PgeWCHmyVbjRznv2VO7KF}/_ssgManifest.js +0 -0
|
@@ -1,547 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The semantic evaluator: one tool call in, one allow / deny / instruct out,
|
|
3
|
-
* decided by a single Jev request carrying every applicable policy.
|
|
4
|
-
*
|
|
5
|
-
* It never throws and it never guesses. Anything that stops it from getting a
|
|
6
|
-
* complete, valid answer — no transport, timeout, HTTP error, malformed body, a
|
|
7
|
-
* different model than the one pinned, an abort — comes back as `degraded`,
|
|
8
|
-
* and the two-tier combine then keeps the regex result for that call exactly
|
|
9
|
-
* as it is today. A semantic outage is a return to the old engine, not an
|
|
10
|
-
* open door.
|
|
11
|
-
*
|
|
12
|
-
* The caller always supplies the transport: in the product that is the
|
|
13
|
-
* customer's own BYOK config (`transportForConfig` behind `throttleTransport`,
|
|
14
|
-
* see `jev-review.ts`). There is deliberately no fallback that goes looking
|
|
15
|
-
* for credentials on disk — a machine without a `jev.json` must never reach
|
|
16
|
-
* Jev at all.
|
|
17
|
-
*
|
|
18
|
-
* Every evaluation, degraded ones included, is written to
|
|
19
|
-
* `~/.failproofai/state/semantic/verdicts.jsonl` with the per-question
|
|
20
|
-
* probabilities, so any verdict can be re-derived later with `decide()`.
|
|
21
|
-
*/
|
|
22
|
-
import { createHash } from "node:crypto";
|
|
23
|
-
import { appendFileSync, mkdirSync, renameSync, statSync } from "node:fs";
|
|
24
|
-
import { resolve } from "node:path";
|
|
25
|
-
import { semanticDir } from "../fp-home";
|
|
26
|
-
import { DEFAULT_JEV_MODEL, MAX_REQUEST_CHARS, compileRequest, selectPolicies, type CompiledRequest } from "./compile";
|
|
27
|
-
import { DEFAULT_THRESHOLDS, decide, decideV1, type DecideV1Options, type Thresholds } from "./decide";
|
|
28
|
-
import { MAX_USER_MESSAGE_CHARS, buildEnvelope, redactSecrets, type Envelope } from "./envelope";
|
|
29
|
-
import { computeFacts, scanCommand } from "./facts";
|
|
30
|
-
import { cleanUserSaid } from "./intent";
|
|
31
|
-
import { JevError, readAnswers, type JevTransport } from "./jev-client";
|
|
32
|
-
import type { JevProviderKind } from "./jev-config";
|
|
33
|
-
import { resolveSemanticPolicies } from "./pack-policies";
|
|
34
|
-
import type { Facts, IntentMode, SemanticInput, SemanticPolicy, SemanticVerdict } from "./types";
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* How long a Jev call may take before the regex engine decides alone.
|
|
38
|
-
*
|
|
39
|
-
* 3000 ms, from 1,449 answered Cloudflare calls over five separate sessions:
|
|
40
|
-
* 1,187 labelled-corpus and 202 intent-set replays through the real handler,
|
|
41
|
-
* plus 60 live calls measured for this decision. Pooled p50 508 ms, p90
|
|
42
|
-
* 1425 ms, p95 1692 ms, p99 2370 ms, max 3624 ms. Latency does not track
|
|
43
|
-
* request size or question count (p50 is flat from 2 to 24 questions), so the
|
|
44
|
-
* tail is provider-side jitter, not something a caller can shrink.
|
|
45
|
-
*
|
|
46
|
-
* The old 1500 ms came from a sandbox reading of p95 210 ms that no longer
|
|
47
|
-
* reproduces — today's p50 alone is ~500 ms. At 1500 ms, 8.4% of answered
|
|
48
|
-
* calls pooled, and 43% of the cold-process calls in the worst session, were
|
|
49
|
-
* aborted and quietly downgraded to the regex verdict: the timeout was a
|
|
50
|
-
* routine event rather than a failure, and on a fresh install Jev was
|
|
51
|
-
* effectively off. At 3000 ms it is 0.28% — about 1 call in 360 — and no
|
|
52
|
-
* measured session is above 1.0%.
|
|
53
|
-
*
|
|
54
|
-
* THE TRADEOFF. This runs inside a PreToolUse hook, so the budget is a direct
|
|
55
|
-
* tax on every tool call — but only on the calls the provider does not answer
|
|
56
|
-
* in time. The typical cost is the p50 (~500 ms) and does not move with the
|
|
57
|
-
* budget; what doubles is the worst case, 1.5 s to 3.0 s per tool call. There
|
|
58
|
-
* is no circuit breaker, so a provider that accepts a connection and then
|
|
59
|
-
* stalls charges the full budget on every call until the user lowers
|
|
60
|
-
* `timeoutMs` or removes the config. We take that ceiling because the failure
|
|
61
|
-
* it replaces is worse and invisible: a budget under the provider's real
|
|
62
|
-
* latency does not just slow the hook down, it silently returns the weaker
|
|
63
|
-
* regex verdict for roughly 1 call in 12 and lets the same event be enforced
|
|
64
|
-
* two different ways on two runs.
|
|
65
|
-
*
|
|
66
|
-
* 3000 ms is where the tail flattens: 2500 → 3000 recovers 9 calls per 1,449,
|
|
67
|
-
* 3000 → 4000 only 4 more. Past it the budget buys almost nothing and the
|
|
68
|
-
* worst case keeps growing.
|
|
69
|
-
*
|
|
70
|
-
* NO SEPARATE COLD-START BUDGET, deliberately. Measured in pairs — call 1
|
|
71
|
-
* against call 2 in the same fresh process, same second, n=30 — the cold
|
|
72
|
-
* connection setup costs a median of +180 ms (mean +266 ms). That is an order
|
|
73
|
-
* of magnitude below the provider jitter both share (warm p50 617 ms to p95
|
|
74
|
-
* 1964 ms), so a cold-only budget would be tuning the small term. It would
|
|
75
|
-
* also not reach the path that needs it: without the daemon each hook is its
|
|
76
|
-
* own process, so every call is a cold call and a first-call exemption is
|
|
77
|
-
* just this default under another name, while with the daemon the worker
|
|
78
|
-
* lives for hours and the exemption would buy one verdict per worker. And a
|
|
79
|
-
* second budget is a second way for one event to be enforced two ways
|
|
80
|
-
* depending on how old the process happens to be.
|
|
81
|
-
*
|
|
82
|
-
* Per-machine override: `timeoutMs` in the Jev config file, or
|
|
83
|
-
* `FAILPROOFAI_JEV_TIMEOUT_MS`. Bounds: `MIN_JEV_TIMEOUT_MS` /
|
|
84
|
-
* `MAX_JEV_TIMEOUT_MS` (100 ms – 10 s).
|
|
85
|
-
*/
|
|
86
|
-
export const DEFAULT_JEV_TIMEOUT_MS = 3_000;
|
|
87
|
-
|
|
88
|
-
export interface SemanticOptions {
|
|
89
|
-
/** How to reach Jev. Required for a request to be made; absent → `degraded("no-transport")`. */
|
|
90
|
-
transport?: JevTransport;
|
|
91
|
-
/** Which provider `transport` reaches, for the outcome and the verdict log. */
|
|
92
|
-
via?: JevProviderKind;
|
|
93
|
-
timeoutMs?: number;
|
|
94
|
-
/**
|
|
95
|
-
* Aborts the request from outside — the two-tier handler does this the
|
|
96
|
-
* moment a hard regex deny makes Jev's answer irrelevant. An abort comes
|
|
97
|
-
* back as `degraded("aborted")`, never as a timeout.
|
|
98
|
-
*/
|
|
99
|
-
signal?: AbortSignal;
|
|
100
|
-
model?: string;
|
|
101
|
-
/** Overrides the resolved set (an installed pack's, else the compiled-in one). */
|
|
102
|
-
policies?: ReadonlyArray<SemanticPolicy>;
|
|
103
|
-
thresholds?: Thresholds;
|
|
104
|
-
/** How "did the human ask for this?" is asked; see {@link IntentMode}. Defaults to v0. */
|
|
105
|
-
intent?: IntentMode;
|
|
106
|
-
/** v1 only: decision options (thresholds, ablations). */
|
|
107
|
-
v1?: DecideV1Options;
|
|
108
|
-
/** v1 only: send `agent_last_message`. Defaults to true; false is an ablation. */
|
|
109
|
-
includeAgentLastMessage?: boolean;
|
|
110
|
-
/** v1 only: strip harness-written text from `user_said`. Defaults to true; false is an ablation. */
|
|
111
|
-
cleanHarnessText?: boolean;
|
|
112
|
-
/**
|
|
113
|
-
* The human turns or the agent message handed in were already cut before
|
|
114
|
-
* they got here — the intent store caps what it keeps, and caps it to fit
|
|
115
|
-
* inside the envelope's own limit, so the envelope cannot see that cut
|
|
116
|
-
* (see {@link intentStoreCut}).
|
|
117
|
-
*
|
|
118
|
-
* This is metadata from the store, deliberately out of band: the messages
|
|
119
|
-
* themselves are agent-authored (and repeat file and tool-output text a
|
|
120
|
-
* third party controls), so a cut read out of their text would be an off
|
|
121
|
-
* switch for the semantic tier that a repo file could pull. A store that
|
|
122
|
-
* reports it here is believed exactly; `undefined` (a store that does not)
|
|
123
|
-
* leaves `intentStoreCut`'s narrower guess.
|
|
124
|
-
*/
|
|
125
|
-
contextTruncated?: boolean;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export interface PreparedCall {
|
|
129
|
-
facts: Facts;
|
|
130
|
-
selected: SemanticPolicy[];
|
|
131
|
-
envelope: Envelope;
|
|
132
|
-
compiled: CompiledRequest;
|
|
133
|
-
intent: IntentMode;
|
|
134
|
-
/**
|
|
135
|
-
* The human turns the envelope CARRIES — `envelope.evidence`, which is the
|
|
136
|
-
* window Jev was shown with its text uncut. See {@link Envelope.evidence}
|
|
137
|
-
* for why it is neither the full list handed in nor the capped strings.
|
|
138
|
-
*/
|
|
139
|
-
userSaid: string[];
|
|
140
|
-
/** The agent message the envelope carries (v1), or null. Same rule. */
|
|
141
|
-
agentLastMessage: string | null;
|
|
142
|
-
/**
|
|
143
|
-
* Something did not fit: the envelope cut it (`envelope.truncated`), or a
|
|
144
|
-
* human or agent message it carries had already been cut before it got here
|
|
145
|
-
* (`opts.contextTruncated`, or failing that `intentStoreCut`).
|
|
146
|
-
*
|
|
147
|
-
* Informational. It is recorded, and it changes no verdict — a prompt or a
|
|
148
|
-
* pasted stack trace over the per-message cap is ordinary work. The flag
|
|
149
|
-
* that does change something is {@link requestCut}.
|
|
150
|
-
*/
|
|
151
|
-
truncated: boolean;
|
|
152
|
-
/**
|
|
153
|
-
* Part of what the CALL DOES was not shown to Jev (`envelope.requestCut`):
|
|
154
|
-
* the tool input did not fit `MAX_AGENT_REQUEST_CHARS`, a redaction
|
|
155
|
-
* swallowed a span of it that could have been executable, or a computed fact
|
|
156
|
-
* about it was dropped.
|
|
157
|
-
*
|
|
158
|
-
* Jev is still asked with whatever fitted and its deny or instruct still
|
|
159
|
-
* counts; what it may not do is CLEAR a reviewable policy. See
|
|
160
|
-
* `envelope.ts`'s header and `combine.ts`.
|
|
161
|
-
*
|
|
162
|
-
* A cut the intent store made is NOT one of these: what it cuts is what the
|
|
163
|
-
* human typed, not the call.
|
|
164
|
-
*/
|
|
165
|
-
requestCut: boolean;
|
|
166
|
-
/**
|
|
167
|
-
* The compiled request does not fit `MAX_REQUEST_CHARS`.
|
|
168
|
-
*
|
|
169
|
-
* The state is bounded by `MAX_STATE_CHARS` however the call was shaped, so
|
|
170
|
-
* this is reachable only if OUR OWN question set overruns the budget — a
|
|
171
|
-
* policy-set problem, not something a caller can provoke. It is NOT a
|
|
172
|
-
* refusal and not a degrade: the request is still sent (the provider's own
|
|
173
|
-
* error is the honest answer if it really is too big), and it counts as a
|
|
174
|
-
* cut, so nothing can be cleared on it. Pinned by
|
|
175
|
-
* `__tests__/hooks/semantic/envelope-budget.test.ts`.
|
|
176
|
-
*/
|
|
177
|
-
oversized: boolean;
|
|
178
|
-
/**
|
|
179
|
-
* A human turn in the window arrived already cut (T4's store caps what it
|
|
180
|
-
* keeps). Read ONLY by the deciders' local target check, which it makes
|
|
181
|
-
* inconclusive rather than negative. See {@link humanTurnCut}.
|
|
182
|
-
*/
|
|
183
|
-
userSaidCut: boolean;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* The mark a head-and-tail cap leaves where it cut: `capHeadTail`
|
|
188
|
-
* (`envelope.ts`) writes it, and so does the intent store when it caps a
|
|
189
|
-
* stored prompt or agent message (T4's `intent.ts` uses the same marker).
|
|
190
|
-
*/
|
|
191
|
-
const OMISSION_MARK = /\n…\[\d+ characters omitted\]…\n/;
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* How far below the envelope's own per-message cap a message the intent store
|
|
195
|
-
* cut can land. The store fits what it keeps INSIDE that cap, the mark
|
|
196
|
-
* included (T4's `capWithin`), so what it stores ends within about one mark's
|
|
197
|
-
* length of the cap; this is comfortably longer than the longest mark.
|
|
198
|
-
*/
|
|
199
|
-
const STORE_CUT_SLACK = 64;
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* A guess — used only when the caller does not say
|
|
203
|
-
* ({@link SemanticOptions.contextTruncated}) — at whether a human message or
|
|
204
|
-
* the agent message in the envelope was cut BEFORE the envelope saw it. The
|
|
205
|
-
* intent store caps what it keeps to fit inside the envelope's own limit,
|
|
206
|
-
* marker included, precisely so the envelope does not cut it a second time —
|
|
207
|
-
* which also means the envelope cannot tell it was cut, and
|
|
208
|
-
* `envelope.truncated` stays false.
|
|
209
|
-
*
|
|
210
|
-
* What it feeds is `truncated`, which is RECORDED and changes no verdict. It
|
|
211
|
-
* used to withdraw every clear, and that made the length of the human's own
|
|
212
|
-
* prompt the difference between an allow and a deny on identical work: a
|
|
213
|
-
* pasted spec or stack trace over 1,200 characters is routine, and the store
|
|
214
|
-
* keeps a capped prompt for hours, so the clearing half of the tier stayed off
|
|
215
|
-
* for the rest of the session.
|
|
216
|
-
*
|
|
217
|
-
* The mark alone is NOT the test, and that is what the length is for.
|
|
218
|
-
* `agent_last_message` is written by the agent, which repeats text from files,
|
|
219
|
-
* web pages and command output that a third party controls, so a message that
|
|
220
|
-
* merely quotes the mark — an excerpt of one of our own capped prompts, say —
|
|
221
|
-
* should not read as a cut. A message the store actually cut also FILLS the
|
|
222
|
-
* cap; a quoted mark in ordinary prose does not. Only what is actually sent is
|
|
223
|
-
* looked at: `user_said` (cleaned, the last few) and `agent_last_message`.
|
|
224
|
-
*/
|
|
225
|
-
function storeCut(message: unknown): boolean {
|
|
226
|
-
return typeof message === "string" && message.length >= MAX_USER_MESSAGE_CHARS - STORE_CUT_SLACK && OMISSION_MARK.test(message);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function intentStoreCut(state: Record<string, unknown>): boolean {
|
|
230
|
-
const said = Array.isArray(state.user_said) ? state.user_said : [];
|
|
231
|
-
return [...said, state.agent_last_message].some(storeCut);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* The same guess, over the HUMAN channel only — and it feeds something that
|
|
236
|
-
* does change a verdict, so the narrowing is the point.
|
|
237
|
-
*
|
|
238
|
-
* `decide` / `decideV1` run one check of their own that the model does not:
|
|
239
|
-
* when a call names an identifiable target, one of those targets has to appear
|
|
240
|
-
* in what the human typed before an `op-requested` answer may clear the
|
|
241
|
-
* policy. Run over a prompt the store CUT, that check reads a head and a tail
|
|
242
|
-
* and calls a target named in the middle absent — so a 12,000-character prompt
|
|
243
|
-
* asking for exactly this file came out `instruct` + every clear withdrawn,
|
|
244
|
-
* where the same sentence on its own came out `allow`. The length of the
|
|
245
|
-
* human's own paste decided the verdict, which is what the design forbids.
|
|
246
|
-
*
|
|
247
|
-
* So a cut prompt makes that local check INCONCLUSIVE rather than negative:
|
|
248
|
-
* the same answer the deciders already give when a call names no identifiable
|
|
249
|
-
* target at all, where the model's own `op_requested` / `scope` answers carry
|
|
250
|
-
* the override. It can only ever restore a clear a short prompt would have
|
|
251
|
-
* had; it never adds one where the human's words are whole.
|
|
252
|
-
*
|
|
253
|
-
* The AGENT's message is deliberately NOT in here, and `opts.contextTruncated`
|
|
254
|
-
* deliberately not consulted: the agent writes its own channel and chooses its
|
|
255
|
-
* own length, so letting a cut there relax a local check would hand it the
|
|
256
|
-
* switch. The human's turns are read from a channel the agent cannot write.
|
|
257
|
-
*/
|
|
258
|
-
function humanTurnCut(turns: ReadonlyArray<string>): boolean {
|
|
259
|
-
return turns.some(storeCut);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export type SemanticOutcome =
|
|
263
|
-
| {
|
|
264
|
-
status: "ok";
|
|
265
|
-
verdict: SemanticVerdict;
|
|
266
|
-
answers: Record<string, number>;
|
|
267
|
-
latencyMs: number;
|
|
268
|
-
inputTokens: number | null;
|
|
269
|
-
questionCount: number;
|
|
270
|
-
/** Something did not fit. Recorded; changes no verdict. See {@link PreparedCall.truncated}. */
|
|
271
|
-
truncated: boolean;
|
|
272
|
-
/** Part of what the call DOES was not shown to Jev, so it may clear nothing. */
|
|
273
|
-
requestCut: boolean;
|
|
274
|
-
redactions: number;
|
|
275
|
-
model: string;
|
|
276
|
-
/** False when the provider did not say which Jev version answered. */
|
|
277
|
-
modelVerified: boolean;
|
|
278
|
-
/** Which route answered; `none` when no policy applied and nothing was sent. */
|
|
279
|
-
via: JevProviderKind | "none";
|
|
280
|
-
}
|
|
281
|
-
| {
|
|
282
|
-
status: "degraded";
|
|
283
|
-
reason: string;
|
|
284
|
-
latencyMs: number;
|
|
285
|
-
questionCount: number;
|
|
286
|
-
truncated: boolean;
|
|
287
|
-
requestCut: boolean;
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
function envNumber(name: string, fallback: number): number {
|
|
291
|
-
const n = Number(process.env[name]);
|
|
292
|
-
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/** Everything that happens locally before the network: facts, policy selection, envelope, request. */
|
|
296
|
-
export function prepareSemantic(input: SemanticInput, opts: SemanticOptions = {}): PreparedCall {
|
|
297
|
-
const command = input.toolInput.command;
|
|
298
|
-
const scanned = typeof command === "string" ? scanCommand(command) : null;
|
|
299
|
-
const facts = computeFacts(input.toolName, input.toolInput, input.cwd ?? null, input.permissionMode ?? null, scanned);
|
|
300
|
-
// The set an installed pack declared, or the compiled-in one when no pack
|
|
301
|
-
// declares any — see `pack-policies.ts` for the replacement rule. Resolved
|
|
302
|
-
// here rather than by the caller because this is the one place the policy set
|
|
303
|
-
// is read, and a second resolution site is a second answer to "what does this
|
|
304
|
-
// machine ask Jev". A caller that supplies `policies` (a replay, an ablation,
|
|
305
|
-
// `jev test`) still decides for itself.
|
|
306
|
-
const selected = selectPolicies(opts.policies ?? resolveSemanticPolicies(), facts);
|
|
307
|
-
const intent = opts.intent ?? "v0";
|
|
308
|
-
const cleaned = intent === "v1" && opts.cleanHarnessText !== false ? cleanUserSaid(input.userSaid) : input.userSaid;
|
|
309
|
-
const agentLastMessage =
|
|
310
|
-
intent === "v1" && opts.includeAgentLastMessage !== false && typeof input.agentLastMessage === "string"
|
|
311
|
-
? input.agentLastMessage
|
|
312
|
-
: null;
|
|
313
|
-
const model = opts.model ?? (process.env.FAILPROOFAI_JEV_MODEL || DEFAULT_JEV_MODEL);
|
|
314
|
-
|
|
315
|
-
// One build, no "try again smaller": `buildEnvelope` spends a fixed budget
|
|
316
|
-
// (`MAX_STATE_CHARS`) as it goes, so the state's size is a function of the
|
|
317
|
-
// caps and never of what the agent sent. A call cannot come out too big.
|
|
318
|
-
const envelope = buildEnvelope(input.toolInput, cleaned, facts, scanned, { agentLastMessage });
|
|
319
|
-
const compiled = compileRequest(selected, envelope.state, envelope.evidence.userSaid, model, intent);
|
|
320
|
-
|
|
321
|
-
// Nothing is sent when no question applies, so an inert call is not measured.
|
|
322
|
-
// This is also the one place the budget is CHECKED rather than asserted: the
|
|
323
|
-
// accounting in `envelope.ts` is supposed to make it impossible to exceed,
|
|
324
|
-
// and a claim like that belongs in the code that can still notice it is
|
|
325
|
-
// wrong. Being wrong costs the call its clears; it never costs it a verdict.
|
|
326
|
-
const chars = Object.keys(compiled.request.questions).length > 0 ? JSON.stringify(compiled.request).length : 0;
|
|
327
|
-
const oversized = chars > MAX_REQUEST_CHARS;
|
|
328
|
-
|
|
329
|
-
const truncated = envelope.truncated || (opts.contextTruncated ?? intentStoreCut(envelope.state));
|
|
330
|
-
return {
|
|
331
|
-
facts,
|
|
332
|
-
selected,
|
|
333
|
-
envelope,
|
|
334
|
-
compiled,
|
|
335
|
-
intent,
|
|
336
|
-
userSaid: envelope.evidence.userSaid,
|
|
337
|
-
agentLastMessage: envelope.evidence.agentLastMessage,
|
|
338
|
-
truncated: truncated || oversized,
|
|
339
|
-
requestCut: envelope.requestCut || oversized,
|
|
340
|
-
oversized,
|
|
341
|
-
userSaidCut: humanTurnCut(envelope.evidence.userSaid),
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
export async function evaluateSemantic(input: SemanticInput, opts: SemanticOptions = {}): Promise<SemanticOutcome> {
|
|
346
|
-
const started = performance.now();
|
|
347
|
-
const elapsed = () => Math.round(performance.now() - started);
|
|
348
|
-
let prepared: PreparedCall;
|
|
349
|
-
try {
|
|
350
|
-
prepared = prepareSemantic(input, opts);
|
|
351
|
-
} catch (err) {
|
|
352
|
-
// `buildEnvelope` never throws, whatever the caller's input looks like —
|
|
353
|
-
// that is rule 4 there, because a `prepare:` degrade is a verdict thrown
|
|
354
|
-
// away on the shape of the tool input. This stays as a floor under the
|
|
355
|
-
// code around it (`scanCommand`, `computeFacts`, the policy set), never as
|
|
356
|
-
// the plan for an exotic payload.
|
|
357
|
-
return {
|
|
358
|
-
status: "degraded",
|
|
359
|
-
reason: `prepare: ${err instanceof Error ? err.message : String(err)}`,
|
|
360
|
-
latencyMs: elapsed(),
|
|
361
|
-
questionCount: 0,
|
|
362
|
-
truncated: false,
|
|
363
|
-
requestCut: false,
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
const { selected, envelope, compiled, truncated, requestCut } = prepared;
|
|
367
|
-
const questionCount = Object.keys(compiled.request.questions).length;
|
|
368
|
-
const thresholds = opts.thresholds ?? DEFAULT_THRESHOLDS;
|
|
369
|
-
const judge = (answers: Record<string, number>): SemanticVerdict =>
|
|
370
|
-
prepared.intent === "v1"
|
|
371
|
-
? decideV1(selected, answers, input.toolInput, prepared.userSaid, prepared.agentLastMessage, {
|
|
372
|
-
...opts.v1,
|
|
373
|
-
userSaidCut: prepared.userSaidCut,
|
|
374
|
-
})
|
|
375
|
-
: decide(selected, answers, input.toolInput, prepared.userSaid, thresholds, prepared.userSaidCut);
|
|
376
|
-
|
|
377
|
-
// Nothing applies (an inert tool, or every precondition false): the answer
|
|
378
|
-
// is allow and no request is made.
|
|
379
|
-
if (questionCount === 0) {
|
|
380
|
-
return {
|
|
381
|
-
status: "ok",
|
|
382
|
-
verdict: judge({}),
|
|
383
|
-
answers: {},
|
|
384
|
-
latencyMs: elapsed(),
|
|
385
|
-
inputTokens: null,
|
|
386
|
-
questionCount: 0,
|
|
387
|
-
truncated,
|
|
388
|
-
requestCut,
|
|
389
|
-
redactions: envelope.redactions,
|
|
390
|
-
model: compiled.request.model,
|
|
391
|
-
modelVerified: true,
|
|
392
|
-
via: "none",
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const degraded = (reason: string): SemanticOutcome => ({
|
|
397
|
-
status: "degraded",
|
|
398
|
-
reason,
|
|
399
|
-
latencyMs: elapsed(),
|
|
400
|
-
questionCount,
|
|
401
|
-
truncated,
|
|
402
|
-
requestCut,
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
// Size is NOT a reason to refuse to ask. An oversized or truncated call used
|
|
406
|
-
// to come back `degraded("request-too-large")`, which `toReview` maps to a
|
|
407
|
-
// `fallback` — Jev's verdict discarded, the regex tier's floor (allow, in
|
|
408
|
-
// the case this tier exists for) applied. That made "make the request big"
|
|
409
|
-
// an off switch, and the size that triggered it was reachable from ordinary
|
|
410
|
-
// work. So the request goes out with whatever fitted: what did not fit is
|
|
411
|
-
// already recorded as `requestCut`, which stops any clear, and a request the
|
|
412
|
-
// provider genuinely cannot accept degrades on its own error, honestly.
|
|
413
|
-
const transport = opts.transport;
|
|
414
|
-
if (!transport) return degraded("no-transport");
|
|
415
|
-
const via: JevProviderKind = opts.via ?? "custom";
|
|
416
|
-
if (opts.signal?.aborted) return degraded("aborted");
|
|
417
|
-
|
|
418
|
-
try {
|
|
419
|
-
const timeout = AbortSignal.timeout(opts.timeoutMs ?? envNumber("FAILPROOFAI_JEV_TIMEOUT_MS", DEFAULT_JEV_TIMEOUT_MS));
|
|
420
|
-
const signal = opts.signal ? AbortSignal.any([timeout, opts.signal]) : timeout;
|
|
421
|
-
const response = await transport(compiled.request, signal);
|
|
422
|
-
const answers = readAnswers(compiled.request, response);
|
|
423
|
-
return {
|
|
424
|
-
status: "ok",
|
|
425
|
-
verdict: judge(answers),
|
|
426
|
-
answers,
|
|
427
|
-
latencyMs: elapsed(),
|
|
428
|
-
inputTokens: typeof response.usage?.input_tokens === "number" ? response.usage.input_tokens : null,
|
|
429
|
-
questionCount,
|
|
430
|
-
truncated,
|
|
431
|
-
requestCut,
|
|
432
|
-
redactions: envelope.redactions,
|
|
433
|
-
model: response.model,
|
|
434
|
-
modelVerified: response.modelUnverified !== true,
|
|
435
|
-
via,
|
|
436
|
-
};
|
|
437
|
-
} catch (err) {
|
|
438
|
-
// Checked first: a transport that surfaces the abort as its own timeout
|
|
439
|
-
// error must still read as the caller's abort, not as Jev being slow.
|
|
440
|
-
if (opts.signal?.aborted) return degraded("aborted");
|
|
441
|
-
if (err instanceof JevError) return degraded(err.code);
|
|
442
|
-
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) return degraded("timeout");
|
|
443
|
-
return degraded(`error: ${err instanceof Error ? err.message : String(err)}`);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// ── Verdict log ──────────────────────────────────────────────────────────────
|
|
448
|
-
|
|
449
|
-
const VERDICT_LOG_MAX_BYTES = 5 * 1024 * 1024;
|
|
450
|
-
export const verdictLogFile = (): string => resolve(semanticDir(), "verdicts.jsonl");
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* `JSON.stringify` on a caller-shaped value, which can throw: a bigint, a
|
|
454
|
-
* cycle, a getter that raises, or nesting deep enough for a RangeError. The
|
|
455
|
-
* verdict log runs INSIDE the promise chain that produces the review, so a
|
|
456
|
-
* throw here would turn an answered call into `kind: "fallback"` — Jev's
|
|
457
|
-
* verdict discarded because of the shape of the tool input, which is the
|
|
458
|
-
* padding attack in one more spelling. Logging is best-effort; a verdict is not.
|
|
459
|
-
*/
|
|
460
|
-
function safeStringify(value: unknown): string {
|
|
461
|
-
try {
|
|
462
|
-
return JSON.stringify(value) ?? String(value);
|
|
463
|
-
} catch {
|
|
464
|
-
return "<unserialisable>";
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
function inputPreview(toolInput: Record<string, unknown>): string {
|
|
469
|
-
const primary =
|
|
470
|
-
["command", "file_path", "path", "url", "query", "pattern"].map((k) => toolInput[k]).find((v) => typeof v === "string") ??
|
|
471
|
-
safeStringify(toolInput);
|
|
472
|
-
// The narrow rules only (`blunt` is opt-in, and this is not the envelope).
|
|
473
|
-
// This preview goes to `~/.failproofai/semantic/verdicts.jsonl` on this
|
|
474
|
-
// machine and nowhere else — it is what an operator reads to see what the
|
|
475
|
-
// agent tried. With the blunt rules on, every command that merely NAMED a
|
|
476
|
-
// credential came back cut off at the name: `bun test -t "sends
|
|
477
|
-
// authorization: Bearer when configured"` logged as `… authorization:
|
|
478
|
-
// <redacted:authorization header>`. A secret that is actually in the command
|
|
479
|
-
// is still removed by the shared floor, the vendor prefixes and the
|
|
480
|
-
// secret-named assignment and flag rules.
|
|
481
|
-
return redactSecrets(String(primary).slice(0, 240), { blunt: false }).text;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
export interface VerdictLogMeta {
|
|
485
|
-
sessionId?: string;
|
|
486
|
-
cli?: string;
|
|
487
|
-
eventType: string;
|
|
488
|
-
/**
|
|
489
|
-
* What the handler did with the outcome: combined it with the regex results
|
|
490
|
-
* (`two-tier`), logged it while enforcing the regex result (`shadow`), or
|
|
491
|
-
* kept the regex result because Jev never answered (`legacy-fallback`).
|
|
492
|
-
*
|
|
493
|
-
* A TRUNCATED call is `two-tier`, not `legacy-fallback`: its clears were
|
|
494
|
-
* withdrawn, but Jev's own verdict still joined the most-severe rule (see
|
|
495
|
-
* `combine.ts`). `truncated` on the same row is what says the clearing half
|
|
496
|
-
* was off for it; the activity row records `jev-fallback` / `truncated`.
|
|
497
|
-
*/
|
|
498
|
-
applied: "two-tier" | "shadow" | "legacy-fallback";
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
export function verdictLogRow(input: SemanticInput, outcome: SemanticOutcome, meta: VerdictLogMeta): Record<string, unknown> {
|
|
502
|
-
const base = {
|
|
503
|
-
ts: Date.now(),
|
|
504
|
-
sessionId: meta.sessionId ?? null,
|
|
505
|
-
cli: meta.cli ?? null,
|
|
506
|
-
eventType: meta.eventType,
|
|
507
|
-
tool: input.toolName,
|
|
508
|
-
inputDigest: createHash("sha256").update(safeStringify(input.toolInput)).digest("hex").slice(0, 16),
|
|
509
|
-
inputPreview: inputPreview(input.toolInput),
|
|
510
|
-
userSaidCount: input.userSaid.length,
|
|
511
|
-
applied: meta.applied,
|
|
512
|
-
latencyMs: outcome.latencyMs,
|
|
513
|
-
questionCount: outcome.questionCount,
|
|
514
|
-
truncated: outcome.truncated,
|
|
515
|
-
requestCut: outcome.requestCut,
|
|
516
|
-
};
|
|
517
|
-
if (outcome.status === "degraded") return { ...base, status: "degraded", reason: outcome.reason };
|
|
518
|
-
return {
|
|
519
|
-
...base,
|
|
520
|
-
status: "ok",
|
|
521
|
-
model: outcome.model,
|
|
522
|
-
decision: outcome.verdict.decision,
|
|
523
|
-
reason: outcome.verdict.reason,
|
|
524
|
-
outcomes: outcome.verdict.outcomes.filter((o) => o.verdict !== "none"),
|
|
525
|
-
answers: outcome.answers,
|
|
526
|
-
inputTokens: outcome.inputTokens,
|
|
527
|
-
redactions: outcome.redactions,
|
|
528
|
-
via: outcome.via,
|
|
529
|
-
modelVerified: outcome.modelVerified,
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/** Append one row. Never throws: a full disk must not change a verdict. */
|
|
534
|
-
export function appendVerdictLog(row: Record<string, unknown>): void {
|
|
535
|
-
try {
|
|
536
|
-
const file = verdictLogFile();
|
|
537
|
-
mkdirSync(semanticDir(), { recursive: true, mode: 0o700 });
|
|
538
|
-
try {
|
|
539
|
-
if (statSync(file).size > VERDICT_LOG_MAX_BYTES) renameSync(file, `${file}.1`);
|
|
540
|
-
} catch {
|
|
541
|
-
// No file yet.
|
|
542
|
-
}
|
|
543
|
-
appendFileSync(file, JSON.stringify(row) + "\n", { mode: 0o600 });
|
|
544
|
-
} catch {
|
|
545
|
-
// Logging is best-effort by design.
|
|
546
|
-
}
|
|
547
|
-
}
|