failproofai 1.0.7-beta.1 → 1.0.7-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  30. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/index.html +1 -1
  33. package/.next/standalone/.next/server/app/index.rsc +15 -15
  34. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  35. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  36. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  37. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  38. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  41. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  44. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  47. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  48. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  51. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +7 -7
  54. package/.next/standalone/.next/server/app/settings/page.js +2 -2
  55. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l3yhx4._.js +2 -2
  58. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  59. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  60. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  61. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
  62. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  63. package/.next/standalone/.next/server/chunks/src_hooks_18qtd42._.js +1 -1
  64. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +2 -2
  65. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +2 -2
  66. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0yxwl6j._.js → [root-of-the-server]__0l44ual._.js} +2 -2
  67. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +2 -2
  68. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +2 -2
  69. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s_yomn._.js +2 -2
  70. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +2 -2
  71. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
  72. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +2 -2
  73. package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
  76. package/.next/standalone/.next/server/chunks/ssr/{_214wgrp._.js → _1mel6y1._.js} +2 -2
  77. package/.next/standalone/.next/server/chunks/ssr/{_0bn2oo8._.js → _1v-jvrv._.js} +1 -1
  78. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  80. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +1 -1
  85. package/.next/standalone/.next/server/chunks/ssr/src_hooks_15t8kqj._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1fm2w5z._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1j0zy3v._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  89. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  90. package/.next/standalone/.next/server/pages/404.html +1 -1
  91. package/.next/standalone/.next/server/pages/500.html +1 -1
  92. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  93. package/.next/standalone/.next/server/server-reference-manifest.json +22 -22
  94. package/.next/standalone/.next/static/chunks/043j99m8ykg__.css +2 -0
  95. package/.next/standalone/.next/static/chunks/0fqd7m_u81mi5.js +1 -0
  96. package/.next/standalone/.next/static/chunks/129ag2bw93bdh.js +1 -0
  97. package/.next/standalone/.next/static/chunks/{29fql3nbnfc9q.js → 1qd741hzlmjbo.js} +1 -1
  98. package/.next/standalone/.next/static/chunks/{0vmd180qfntfb.js → 2_pltstd8-xgs.js} +1 -1
  99. package/.next/standalone/.next/static/chunks/{1u5zsejmgrir_.js → 2c8j9l6j_b1ci.js} +1 -1
  100. package/.next/standalone/.next/static/chunks/3-k569wzcli8q.js +1 -0
  101. package/.next/standalone/.next/static/chunks/{258668t68du6b.js → 3brze37td_wnc.js} +1 -1
  102. package/.next/standalone/.next/static/chunks/3otmypm6j_xfo.js +6 -0
  103. package/.next/standalone/.next/static/chunks/{12tvm75t5ffui.js → 3ugmd_7dyn0id.js} +1 -1
  104. package/.next/standalone/.next/static/chunks/3yxro_r2_o9ad.js +69 -0
  105. package/.next/standalone/PROBE-FOLLOWUP.md +186 -0
  106. package/.next/standalone/app/actions/get-jev-config.ts +38 -23
  107. package/.next/standalone/app/actions/update-jev-config.ts +1 -1
  108. package/.next/standalone/app/settings/jev-panel.tsx +33 -29
  109. package/.next/standalone/package.json +10 -10
  110. package/.next/standalone/sdk/python/skill/SKILL.md +60 -14
  111. package/.next/standalone/sdk/python/skill/agents/openai.yaml +2 -1
  112. package/.next/standalone/sdk/python/skill/references/evaluator.md +255 -0
  113. package/.next/standalone/sdk/python/skill/references/events.md +17 -8
  114. package/.next/standalone/sdk/python/skill/references/frameworks.md +3 -0
  115. package/.next/standalone/sdk/python/skill/references/install.md +3 -0
  116. package/.next/standalone/sdk/python/skill/references/integration.md +6 -2
  117. package/.next/standalone/sdk/python/skill/references/typescript.md +568 -0
  118. package/.next/standalone/sdk/typescript/CHANGELOG.md +119 -0
  119. package/.next/standalone/sdk/typescript/LICENSE +42 -0
  120. package/.next/standalone/sdk/typescript/README.md +552 -0
  121. package/.next/standalone/sdk/typescript/eslint.config.mjs +59 -0
  122. package/.next/standalone/sdk/typescript/examples/research-agent.ts +197 -0
  123. package/.next/standalone/sdk/typescript/integration/ai.test.ts +920 -0
  124. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/agent.ts +337 -0
  125. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package-lock.json +281 -0
  126. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package.json +13 -0
  127. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/surfaces.ts +605 -0
  128. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/tsconfig.json +12 -0
  129. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/tsconfig.surfaces.json +4 -0
  130. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/agent.ts +342 -0
  131. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +168 -0
  132. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +13 -0
  133. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/surfaces.ts +628 -0
  134. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/tsconfig.json +12 -0
  135. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/tsconfig.surfaces.json +4 -0
  136. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/agent.ts +346 -0
  137. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package-lock.json +156 -0
  138. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package.json +13 -0
  139. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/surfaces.ts +651 -0
  140. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/tsconfig.json +12 -0
  141. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/tsconfig.surfaces.json +4 -0
  142. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/agent.ts +350 -0
  143. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package-lock.json +153 -0
  144. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package.json +13 -0
  145. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/surfaces.ts +651 -0
  146. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/tsconfig.json +12 -0
  147. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/tsconfig.surfaces.json +4 -0
  148. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/agent.ts +623 -0
  149. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package-lock.json +463 -0
  150. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package.json +15 -0
  151. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/tsconfig.json +12 -0
  152. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/agent-v1.ts +99 -0
  153. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/agent.ts +623 -0
  154. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package-lock.json +336 -0
  155. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package.json +15 -0
  156. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/tsconfig.json +12 -0
  157. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/agent.ts +96 -0
  158. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +579 -0
  159. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +15 -0
  160. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/tsconfig.json +12 -0
  161. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/index.cjs +53 -0
  162. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/index.mjs +55 -0
  163. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/vendor/lc-weather-provider/package.json +18 -0
  164. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/agent.ts +659 -0
  165. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +635 -0
  166. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +15 -0
  167. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/tsconfig.json +12 -0
  168. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/agent.ts +659 -0
  169. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package-lock.json +553 -0
  170. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package.json +15 -0
  171. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/tsconfig.json +12 -0
  172. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/agent.ts +877 -0
  173. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/mcp-server.mjs +66 -0
  174. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +6417 -0
  175. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +15 -0
  176. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/tsconfig.json +12 -0
  177. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/agent.ts +872 -0
  178. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/mcp-server.mjs +66 -0
  179. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +2540 -0
  180. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +15 -0
  181. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/tsconfig.json +12 -0
  182. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/actions.ts +18 -0
  183. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/ai/route.ts +42 -0
  184. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/edge/route.ts +29 -0
  185. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/langgraph/route.ts +21 -0
  186. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/llamaindex/route.ts +11 -0
  187. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/mastra/route.ts +19 -0
  188. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/api/status/route.ts +7 -0
  189. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/layout.tsx +9 -0
  190. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/app/page.tsx +15 -0
  191. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/instrumentation.ts +15 -0
  192. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/ai.ts +61 -0
  193. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/langgraph.ts +68 -0
  194. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/llamaindex.ts +98 -0
  195. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/lib/mastra.ts +90 -0
  196. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/next.config.ts +52 -0
  197. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4343 -0
  198. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +28 -0
  199. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/agent.ts +51 -0
  200. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/deno-npm.ts +76 -0
  201. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package-lock.json +484 -0
  202. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package.json +15 -0
  203. package/.next/standalone/sdk/typescript/integration/fixtures/types/agent.ts +79 -0
  204. package/.next/standalone/sdk/typescript/integration/fixtures/types/package-lock.json +740 -0
  205. package/.next/standalone/sdk/typescript/integration/fixtures/types/package.json +11 -0
  206. package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/agent.ts +197 -0
  207. package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/package-lock.json +70 -0
  208. package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/package.json +12 -0
  209. package/.next/standalone/sdk/typescript/integration/fixtures/vanilla/tsconfig.json +12 -0
  210. package/.next/standalone/sdk/typescript/integration/global-setup.ts +29 -0
  211. package/.next/standalone/sdk/typescript/integration/harness.ts +451 -0
  212. package/.next/standalone/sdk/typescript/integration/langchain.test.ts +682 -0
  213. package/.next/standalone/sdk/typescript/integration/llamaindex.test.ts +709 -0
  214. package/.next/standalone/sdk/typescript/integration/mastra-coverage.test.ts +386 -0
  215. package/.next/standalone/sdk/typescript/integration/mastra.test.ts +311 -0
  216. package/.next/standalone/sdk/typescript/integration/nextjs.test.ts +341 -0
  217. package/.next/standalone/sdk/typescript/integration/runtime-parity.ts +180 -0
  218. package/.next/standalone/sdk/typescript/integration/runtimes.bun.test.ts +15 -0
  219. package/.next/standalone/sdk/typescript/integration/runtimes.core.test.ts +113 -0
  220. package/.next/standalone/sdk/typescript/integration/runtimes.deno.test.ts +19 -0
  221. package/.next/standalone/sdk/typescript/integration/types.test.ts +141 -0
  222. package/.next/standalone/sdk/typescript/integration/vanilla.test.ts +255 -0
  223. package/.next/standalone/sdk/typescript/package-lock.json +2640 -0
  224. package/.next/standalone/sdk/typescript/package.json +401 -0
  225. package/.next/standalone/sdk/typescript/scripts/finalize-build.mjs +123 -0
  226. package/.next/standalone/sdk/typescript/scripts/release.mjs +177 -0
  227. package/.next/standalone/sdk/typescript/src/clock.ts +58 -0
  228. package/.next/standalone/sdk/typescript/src/context.ts +214 -0
  229. package/.next/standalone/sdk/typescript/src/edge/adapter.ts +18 -0
  230. package/.next/standalone/sdk/typescript/src/edge/ai.ts +116 -0
  231. package/.next/standalone/sdk/typescript/src/edge/index.ts +238 -0
  232. package/.next/standalone/sdk/typescript/src/edge/langchain.ts +18 -0
  233. package/.next/standalone/sdk/typescript/src/edge/llamaindex.ts +12 -0
  234. package/.next/standalone/sdk/typescript/src/edge/mastra.ts +17 -0
  235. package/.next/standalone/sdk/typescript/src/edge/notice.ts +33 -0
  236. package/.next/standalone/sdk/typescript/src/environment.ts +75 -0
  237. package/.next/standalone/sdk/typescript/src/evaluator/authoring.ts +480 -0
  238. package/.next/standalone/sdk/typescript/src/evaluator/cli.ts +96 -0
  239. package/.next/standalone/sdk/typescript/src/evaluator/client.ts +421 -0
  240. package/.next/standalone/sdk/typescript/src/evaluator/expression.ts +1292 -0
  241. package/.next/standalone/sdk/typescript/src/evaluator/index.ts +144 -0
  242. package/.next/standalone/sdk/typescript/src/evaluator/protocol.ts +747 -0
  243. package/.next/standalone/sdk/typescript/src/evaluator/runtime.ts +930 -0
  244. package/.next/standalone/sdk/typescript/src/evaluator/sandbox-worker.ts +171 -0
  245. package/.next/standalone/sdk/typescript/src/evaluator/source-limits.ts +27 -0
  246. package/.next/standalone/sdk/typescript/src/evaluator/source.ts +509 -0
  247. package/.next/standalone/sdk/typescript/src/events.ts +879 -0
  248. package/.next/standalone/sdk/typescript/src/exit.ts +117 -0
  249. package/.next/standalone/sdk/typescript/src/index.ts +186 -0
  250. package/.next/standalone/sdk/typescript/src/integrations/ai.ts +1566 -0
  251. package/.next/standalone/sdk/typescript/src/integrations/compat.ts +322 -0
  252. package/.next/standalone/sdk/typescript/src/integrations/core.ts +1321 -0
  253. package/.next/standalone/sdk/typescript/src/integrations/index.ts +355 -0
  254. package/.next/standalone/sdk/typescript/src/integrations/langchain.ts +2340 -0
  255. package/.next/standalone/sdk/typescript/src/integrations/llamaindex.ts +2111 -0
  256. package/.next/standalone/sdk/typescript/src/integrations/mastra.ts +1802 -0
  257. package/.next/standalone/sdk/typescript/src/logger.ts +98 -0
  258. package/.next/standalone/sdk/typescript/src/next.ts +115 -0
  259. package/.next/standalone/sdk/typescript/src/node-require.ts +446 -0
  260. package/.next/standalone/sdk/typescript/src/redact.ts +305 -0
  261. package/.next/standalone/sdk/typescript/src/resolver.ts +120 -0
  262. package/.next/standalone/sdk/typescript/src/runtime.ts +29 -0
  263. package/.next/standalone/sdk/typescript/src/schema.ts +410 -0
  264. package/.next/standalone/sdk/typescript/src/scopes.ts +701 -0
  265. package/.next/standalone/sdk/typescript/src/shared.ts +33 -0
  266. package/.next/standalone/sdk/typescript/src/version.ts +5 -0
  267. package/.next/standalone/sdk/typescript/src/writer.ts +934 -0
  268. package/.next/standalone/sdk/typescript/test/adapters.test.ts +397 -0
  269. package/.next/standalone/sdk/typescript/test/ai.test.ts +1076 -0
  270. package/.next/standalone/sdk/typescript/test/copies.test.ts +204 -0
  271. package/.next/standalone/sdk/typescript/test/edge.test.ts +183 -0
  272. package/.next/standalone/sdk/typescript/test/evaluator-client.test.ts +234 -0
  273. package/.next/standalone/sdk/typescript/test/evaluator-protocol.test.ts +225 -0
  274. package/.next/standalone/sdk/typescript/test/events.test.ts +193 -0
  275. package/.next/standalone/sdk/typescript/test/expression.test.ts +181 -0
  276. package/.next/standalone/sdk/typescript/test/global-setup.ts +26 -0
  277. package/.next/standalone/sdk/typescript/test/helpers.ts +130 -0
  278. package/.next/standalone/sdk/typescript/test/integrations.test.ts +369 -0
  279. package/.next/standalone/sdk/typescript/test/langchain-copies.test.ts +204 -0
  280. package/.next/standalone/sdk/typescript/test/langchain.test.ts +999 -0
  281. package/.next/standalone/sdk/typescript/test/llamaindex.test.ts +1760 -0
  282. package/.next/standalone/sdk/typescript/test/mastra-coverage.test.ts +501 -0
  283. package/.next/standalone/sdk/typescript/test/mastra-lifecycle.test.ts +479 -0
  284. package/.next/standalone/sdk/typescript/test/mastra.test.ts +285 -0
  285. package/.next/standalone/sdk/typescript/test/next.test.ts +109 -0
  286. package/.next/standalone/sdk/typescript/test/packaging.test.ts +312 -0
  287. package/.next/standalone/sdk/typescript/test/redaction.test.ts +171 -0
  288. package/.next/standalone/sdk/typescript/test/runtimes.test.ts +101 -0
  289. package/.next/standalone/sdk/typescript/test/sandbox.test.ts +189 -0
  290. package/.next/standalone/sdk/typescript/test/scopes.test.ts +271 -0
  291. package/.next/standalone/sdk/typescript/test/setup.ts +19 -0
  292. package/.next/standalone/sdk/typescript/test/skill-snippets.test.ts +73 -0
  293. package/.next/standalone/sdk/typescript/test/spool-contract.test.ts +124 -0
  294. package/.next/standalone/sdk/typescript/test/tracker-bounds.test.ts +191 -0
  295. package/.next/standalone/sdk/typescript/test/wire-format.test.ts +214 -0
  296. package/.next/standalone/sdk/typescript/test/writer.test.ts +407 -0
  297. package/.next/standalone/sdk/typescript/tsconfig.build.json +15 -0
  298. package/.next/standalone/sdk/typescript/tsconfig.cjs.json +19 -0
  299. package/.next/standalone/sdk/typescript/tsconfig.json +28 -0
  300. package/.next/standalone/sdk/typescript/vitest.config.ts +33 -0
  301. package/.next/standalone/sdk/typescript/vitest.integration.config.ts +23 -0
  302. package/.next/standalone/server.js +1 -1
  303. package/README.md +2 -2
  304. package/dist/cli.mjs +208 -27
  305. package/dist/worker.mjs +120 -14
  306. package/package.json +10 -10
  307. package/scripts/build-policy-pack.mjs +14 -0
  308. package/src/audit/features.ts +3 -2
  309. package/src/hooks/builtin-policies.ts +156 -5
  310. package/src/hooks/jev-cli.ts +57 -1
  311. package/src/hooks/manager.ts +1 -1
  312. package/src/hooks/pack-cli.ts +150 -18
  313. package/src/hooks/pack-store.ts +1 -1
  314. package/src/hooks/policy-catalog.ts +148 -9
  315. package/src/hooks/types.ts +1 -1
  316. package/.next/standalone/.next/static/chunks/0cd-_8-c-m1ea.js +0 -6
  317. package/.next/standalone/.next/static/chunks/0qrbdkv9qmvli.js +0 -69
  318. package/.next/standalone/.next/static/chunks/0uldbut9y2-e8.js +0 -1
  319. package/.next/standalone/.next/static/chunks/285spx855h_3r.css +0 -2
  320. package/.next/standalone/.next/static/chunks/2vkvu9-opa_1z.js +0 -1
  321. package/.next/standalone/.next/static/chunks/37lhv7wa3ywt6.js +0 -1
  322. /package/.next/standalone/.next/static/{T8YAYM9h_64fKv705vug7 → gbEOjBgZAxF2UIUwZVHNu}/_buildManifest.js +0 -0
  323. /package/.next/standalone/.next/static/{T8YAYM9h_64fKv705vug7 → gbEOjBgZAxF2UIUwZVHNu}/_clientMiddlewareManifest.js +0 -0
  324. /package/.next/standalone/.next/static/{T8YAYM9h_64fKv705vug7 → gbEOjBgZAxF2UIUwZVHNu}/_ssgManifest.js +0 -0
@@ -0,0 +1,171 @@
1
+ /**
2
+ * The sandbox worker entry: evaluates ONE piece of server-authored source and
3
+ * posts the result back.
4
+ *
5
+ * Started by `source.ts` as a fresh `worker_threads` Worker per evaluation,
6
+ * with V8 heap limits, an empty environment and a wall-clock `terminate()`
7
+ * above it. Nothing here is trusted to enforce those — a worker cannot bound
8
+ * itself, which is exactly why the bound lives in the parent.
9
+ *
10
+ * What this file IS responsible for:
11
+ *
12
+ * * **Re-validating the source.** The parent already parsed it. Parsing it
13
+ * again here means a worker can never evaluate source the parent has not
14
+ * vetted, whatever reaches `workerData`.
15
+ * * **Bounding the result before it crosses back.** A permitted expression can
16
+ * build a result far larger than any real evaluation; measuring it here means
17
+ * the parent never has to hold it to find that out.
18
+ * * **Reporting failures as data, not as a crash.** An evaluation that throws
19
+ * is an ordinary outcome — a failed run — and has to arrive as one, with the
20
+ * original error's name preserved so the parent can rebuild its semantics.
21
+ */
22
+
23
+ import { parentPort, workerData } from "node:worker_threads";
24
+
25
+ import { Assertion, ConditionResult, EvalResult, Metric, Score } from "./authoring.js";
26
+ import {
27
+ MAX_CONDITION_SOURCE_BYTES,
28
+ MAX_EVALUATOR_SOURCE_BYTES,
29
+ SANDBOX_GLOBAL_NAMES,
30
+ } from "./source-limits.js";
31
+ import { compileExpression } from "./expression.js";
32
+ import { sessionTranscriptFromWire } from "./protocol.js";
33
+ import type { WireObject } from "./protocol.js";
34
+
35
+ interface SandboxRequest {
36
+ kind: "condition" | "evaluator";
37
+ source: string;
38
+ session: WireObject;
39
+ evalKey: string | null;
40
+ maxResultBytes: number;
41
+ }
42
+
43
+ type SandboxOutcome =
44
+ | { ok: true; value: unknown }
45
+ | { ok: false; name: string; message: string };
46
+
47
+ /**
48
+ * The constructors the language exposes, as plain functions.
49
+ *
50
+ * Callable WITHOUT `new`, so an expression reads the way the Python SDK's does
51
+ * (`EvalResult(score=Score(0.9))` there, `EvalResult({score: Score(0.9)})`
52
+ * here). The interpreter has no `new` in its grammar at all, so a class would
53
+ * simply be uncallable.
54
+ */
55
+ function sandboxGlobals(session: unknown): Record<string, unknown> {
56
+ return {
57
+ session,
58
+ EvalResult: (options?: ConstructorParameters<typeof EvalResult>[0]) => new EvalResult(options),
59
+ Score: (value: number, options?: ConstructorParameters<typeof Score>[1]) =>
60
+ new Score(value, options),
61
+ Metric: (value: number, options?: ConstructorParameters<typeof Metric>[1]) =>
62
+ new Metric(value, options),
63
+ Assertion: (passed: boolean, options?: ConstructorParameters<typeof Assertion>[1]) =>
64
+ new Assertion(passed, options),
65
+ ConditionResult: (applicable: boolean, reasonCode?: string) =>
66
+ new ConditionResult(applicable, reasonCode),
67
+ };
68
+ }
69
+
70
+ function serializeEvalResult(result: EvalResult): Record<string, unknown> {
71
+ const metrics: Record<string, unknown> = {};
72
+ for (const [key, metric] of Object.entries(result.metrics)) {
73
+ metrics[key] =
74
+ metric instanceof Metric
75
+ ? {
76
+ value: metric.value,
77
+ unit: metric.unit,
78
+ displayValue: metric.displayValue,
79
+ description: metric.description,
80
+ }
81
+ : metric;
82
+ }
83
+ const assertions: Record<string, unknown> = {};
84
+ for (const [key, assertion] of Object.entries(result.assertions)) {
85
+ assertions[key] =
86
+ assertion instanceof Assertion
87
+ ? { passed: assertion.passed, description: assertion.description }
88
+ : assertion;
89
+ }
90
+ return {
91
+ score:
92
+ result.score === undefined
93
+ ? undefined
94
+ : {
95
+ value: result.score.value,
96
+ passed: result.score.passed,
97
+ unit: result.score.unit,
98
+ displayValue: result.score.displayValue,
99
+ description: result.score.description,
100
+ },
101
+ metrics,
102
+ assertions,
103
+ reasoning: result.reasoning,
104
+ summary: result.summary,
105
+ labels: [...result.labels],
106
+ };
107
+ }
108
+
109
+ function run(request: SandboxRequest): unknown {
110
+ const isCondition = request.kind === "condition";
111
+ const compiled = compileExpression(request.source, {
112
+ fieldName: isCondition ? "condition_source" : "evaluator_source",
113
+ maximumBytes: isCondition ? MAX_CONDITION_SOURCE_BYTES : MAX_EVALUATOR_SOURCE_BYTES,
114
+ globalNames: SANDBOX_GLOBAL_NAMES,
115
+ });
116
+
117
+ const session = sessionTranscriptFromWire(request.session);
118
+ const value = compiled(sandboxGlobals(session));
119
+
120
+ if (isCondition) {
121
+ if (typeof value === "boolean") return value;
122
+ if (value instanceof ConditionResult) {
123
+ return { applicable: value.applicable, reasonCode: value.reasonCode };
124
+ }
125
+ throw new TypeError("condition_source must return a boolean or a ConditionResult");
126
+ }
127
+
128
+ if (!(value instanceof EvalResult)) {
129
+ throw new TypeError("evaluator_source must return an EvalResult");
130
+ }
131
+ // Validate the item count HERE, where the result is still cheap to discard.
132
+ // The parent would reject it too, but only after paying to receive it.
133
+ if (request.evalKey !== null) value.resultItems(request.evalKey);
134
+ return serializeEvalResult(value);
135
+ }
136
+
137
+ function main(): void {
138
+ const port = parentPort;
139
+ if (port === null) {
140
+ // Started as a main module rather than as a worker. There is nothing to
141
+ // report to and nothing to evaluate; exiting quietly is the only sensible
142
+ // behaviour, and a non-zero code says it was not a normal run.
143
+ process.exitCode = 2;
144
+ return;
145
+ }
146
+ const request = workerData as SandboxRequest;
147
+
148
+ let outcome: SandboxOutcome;
149
+ try {
150
+ const value = run(request);
151
+ const encoded = Buffer.byteLength(JSON.stringify(value ?? null), "utf8");
152
+ if (encoded > request.maxResultBytes) {
153
+ outcome = {
154
+ ok: false,
155
+ name: "EvaluationBudgetExceeded",
156
+ message: `evaluation result is ${encoded} bytes; the limit is ${request.maxResultBytes}`,
157
+ };
158
+ } else {
159
+ outcome = { ok: true, value };
160
+ }
161
+ } catch (error) {
162
+ outcome =
163
+ error instanceof Error
164
+ ? { ok: false, name: error.name || "Error", message: error.message }
165
+ : { ok: false, name: "Error", message: String(error) };
166
+ }
167
+
168
+ port.postMessage(outcome);
169
+ }
170
+
171
+ main();
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The handful of constants the sandbox worker and its parent must agree on.
3
+ *
4
+ * They live apart from `source.ts` so that `sandbox-worker.ts` can read them
5
+ * without importing it — and importing it would drag `node:worker_threads`'s
6
+ * `Worker`, the semaphore and the spawn logic into every sandbox child, giving
7
+ * each evaluation the machinery for starting more of them. A worker that cannot
8
+ * spawn a worker is a smaller thing to reason about.
9
+ */
10
+
11
+ export const MAX_CONDITION_SOURCE_BYTES = 16 * 1024;
12
+ export const MAX_EVALUATOR_SOURCE_BYTES = 128 * 1024;
13
+
14
+ /** The names an evaluation expression may reference. */
15
+ export const SANDBOX_GLOBAL_NAMES = [
16
+ "session",
17
+ "EvalResult",
18
+ "Score",
19
+ "Metric",
20
+ "Assertion",
21
+ "ConditionResult",
22
+ "Math",
23
+ "Object",
24
+ "Array",
25
+ "Number",
26
+ "JSON",
27
+ ] as const;
@@ -0,0 +1,509 @@
1
+ /**
2
+ * Compiling and sandboxing server-authored ("managed") evaluations.
3
+ *
4
+ * Two independent boundaries, and they guard different things:
5
+ *
6
+ * 1. **The language** (`expression.ts`). Parsed and interpreted, never `eval`'d
7
+ * and never handed to `node:vm`, so tenant source has no reachable path to a
8
+ * function constructor, a module, `process`, or anything else in the worker.
9
+ * This is the CORRECTNESS boundary and it holds on its own.
10
+ *
11
+ * 2. **A `worker_threads` sandbox** (this file). A fresh Worker per evaluation
12
+ * with V8 `resourceLimits` on the heap, a wall-clock `terminate()`, a cap on
13
+ * the bytes the result may occupy, and a semaphore bounding how many run at
14
+ * once. This is the RESOURCE boundary: it stops a permitted expression from
15
+ * eating the worker even though every operation in it is individually legal.
16
+ *
17
+ * This is the same division the Python SDK draws between its AST allowlist and
18
+ * its fork+RLIMIT subprocess, with one difference that matters: there, the
19
+ * subprocess is the real bound because `eval` with empty builtins is porous.
20
+ * Here the language is genuinely closed, so the sandbox is defence in depth
21
+ * rather than the only thing holding.
22
+ *
23
+ * **It still fails closed.** If the sandbox cannot be established — no
24
+ * `worker_threads`, no resolvable worker entry — managed source is REFUSED
25
+ * rather than run unbounded in the worker's own thread. An evaluation that
26
+ * cannot be terminated is not an evaluation we are willing to start.
27
+ */
28
+
29
+ import { createHash } from "node:crypto";
30
+ import { Worker } from "node:worker_threads";
31
+
32
+ import { resolveFrom } from "../node-require.js";
33
+ import { Assertion, ConditionResult, EvalResult, Metric, Score } from "./authoring.js";
34
+ import { UnsafeEvaluatorSource, compileExpression } from "./expression.js";
35
+ import type { SessionTranscript } from "./protocol.js";
36
+ import {
37
+ MAX_CONDITION_SOURCE_BYTES,
38
+ MAX_EVALUATOR_SOURCE_BYTES,
39
+ SANDBOX_GLOBAL_NAMES,
40
+ } from "./source-limits.js";
41
+
42
+ export { UnsafeEvaluatorSource };
43
+ export { MAX_CONDITION_SOURCE_BYTES, MAX_EVALUATOR_SOURCE_BYTES, SANDBOX_GLOBAL_NAMES };
44
+
45
+ /** Wall-clock and heap budget for ONE sandboxed evaluation. */
46
+ export const DEFAULT_SANDBOX_TIMEOUT_SECONDS = 30;
47
+ /**
48
+ * The effective budget is CLAMPED to this ceiling regardless of the
49
+ * (server-set) per-definition timeout, so a large `timeout_seconds` can never
50
+ * remove the execution bound.
51
+ */
52
+ export const MAX_SANDBOX_TIMEOUT_SECONDS = 60;
53
+ /**
54
+ * Per-sandbox heap cap. A managed eval works over a transcript (<= 25 MiB) and
55
+ * returns a small result, so this is generous; it also stops an allocation bomb
56
+ * before it can return a valid result.
57
+ */
58
+ export const SANDBOX_MEMORY_MB = 512;
59
+ /**
60
+ * A per-worker cap alone does not bound the HOST: a worker with
61
+ * `maxConcurrency: 32` could run 32 sandboxes at once. Capping how many run
62
+ * concurrently makes the AGGREGATE bounded independently of the claim
63
+ * concurrency; extra evaluations queue on the semaphore rather than pile up
64
+ * memory.
65
+ */
66
+ export const MAX_CONCURRENT_SANDBOXES = 4;
67
+ /**
68
+ * The result crossing back is bounded so that a permitted expression which
69
+ * builds a huge result cannot exhaust the parent even though the child's heap
70
+ * limit let it construct one. A valid result (<= 25 items, bounded fields) is
71
+ * far under this.
72
+ */
73
+ export const SANDBOX_MAX_RESULT_BYTES = 1024 * 1024;
74
+
75
+ /**
76
+ * A sandboxed evaluation exceeded its CPU/memory/wall-clock budget.
77
+ *
78
+ * Distinct from an eval that *returned* an error: the computation was forcibly
79
+ * terminated because it could not be allowed to keep running.
80
+ */
81
+ export class EvaluationTimeout extends Error {
82
+ constructor(message: string) {
83
+ super(message);
84
+ this.name = "EvaluationTimeout";
85
+ }
86
+ }
87
+
88
+ /**
89
+ * The killable sandbox could not be established.
90
+ *
91
+ * Thrown instead of running server-authored source unsandboxed — if the worker
92
+ * cannot be started there is no way to bound or terminate the evaluation, so we
93
+ * fail closed.
94
+ */
95
+ export class EvaluationSandboxUnavailable extends Error {
96
+ constructor(message: string) {
97
+ super(message);
98
+ this.name = "EvaluationSandboxUnavailable";
99
+ }
100
+ }
101
+
102
+ export function sourceChecksum(
103
+ conditionSource: string | null | undefined,
104
+ evaluatorSource: string,
105
+ ): string {
106
+ const payload = Buffer.concat([
107
+ Buffer.from(conditionSource ?? "", "utf8"),
108
+ Buffer.from([0]),
109
+ Buffer.from(evaluatorSource, "utf8"),
110
+ ]);
111
+ return `sha256:${createHash("sha256").update(payload).digest("hex")}`;
112
+ }
113
+
114
+ /**
115
+ * The wall-clock/heap budget for one evaluation: a positive value no larger
116
+ * than `MAX_SANDBOX_TIMEOUT_SECONDS`. Server-provided timeouts cannot exceed it.
117
+ */
118
+ function clampBudget(timeoutSeconds: number | null | undefined): number {
119
+ const requested = Number(timeoutSeconds ?? DEFAULT_SANDBOX_TIMEOUT_SECONDS);
120
+ const positive =
121
+ Number.isFinite(requested) && requested > 0 ? requested : DEFAULT_SANDBOX_TIMEOUT_SECONDS;
122
+ return Math.min(positive, MAX_SANDBOX_TIMEOUT_SECONDS);
123
+ }
124
+
125
+ // ---------------------------------------------------------------------------
126
+ // Locating the worker entry
127
+ // ---------------------------------------------------------------------------
128
+
129
+ /**
130
+ * Where the sandbox worker's compiled entry lives.
131
+ *
132
+ * `import.meta.url` would answer this in one line and is deliberately not used:
133
+ * it is a syntax error in the CommonJS half of this package's dual build, and a
134
+ * telemetry SDK that only works from one module system is a telemetry SDK half
135
+ * its users cannot install. The resolution order instead is:
136
+ *
137
+ * 1. `FAILPROOFAI_SDK_SANDBOX_WORKER` — an explicit path. Used by this
138
+ * repository's own tests, and the supported answer for anyone bundling
139
+ * this package into a single file, where the published layout is gone.
140
+ * 2. The package's own `./sandbox-worker` export, resolved through the
141
+ * consuming application. This is the installed case and needs no setup.
142
+ *
143
+ * Failure names the variable rather than falling back to an unsandboxed run.
144
+ */
145
+ function sandboxWorkerPath(): string {
146
+ const override = process.env.FAILPROOFAI_SDK_SANDBOX_WORKER;
147
+ if (override) return override;
148
+ const resolved = resolveFrom("@failproofai/sdk/sandbox-worker");
149
+ if (resolved !== null) return resolved;
150
+ throw new EvaluationSandboxUnavailable(
151
+ "could not locate the evaluator sandbox worker. This happens when @failproofai/sdk has " +
152
+ "been bundled and its published file layout is gone. Set " +
153
+ "FAILPROOFAI_SDK_SANDBOX_WORKER to the path of the package's sandbox-worker entry, " +
154
+ "or run managed evaluations from an unbundled install. Refusing to evaluate " +
155
+ "server-authored source without a sandbox.",
156
+ );
157
+ }
158
+
159
+ // ---------------------------------------------------------------------------
160
+ // The concurrency gate
161
+ // ---------------------------------------------------------------------------
162
+
163
+ class Semaphore {
164
+ private available: number;
165
+ private readonly waiters: Array<(granted: boolean) => void> = [];
166
+
167
+ constructor(permits: number) {
168
+ this.available = permits;
169
+ }
170
+
171
+ /**
172
+ * Acquire within `timeoutMs`, or resolve false.
173
+ *
174
+ * The timeout is not decoration: the runtime awaits an evaluation with its
175
+ * own deadline, and a queue wait that ignored it would let a thread launch a
176
+ * sandbox after its run had already been reported timed out — twenty-eight
177
+ * of them queued behind four long sandboxes, all still to come.
178
+ */
179
+ acquire(timeoutMs: number): Promise<boolean> {
180
+ if (this.available > 0) {
181
+ this.available -= 1;
182
+ return Promise.resolve(true);
183
+ }
184
+ if (timeoutMs <= 0) return Promise.resolve(false);
185
+ return new Promise<boolean>((resolve) => {
186
+ let settled = false;
187
+ const timer = setTimeout(() => {
188
+ if (settled) return;
189
+ settled = true;
190
+ const index = this.waiters.indexOf(waiter);
191
+ if (index !== -1) this.waiters.splice(index, 1);
192
+ resolve(false);
193
+ }, timeoutMs);
194
+ timer.unref?.();
195
+ const waiter = (granted: boolean): void => {
196
+ if (settled) return;
197
+ settled = true;
198
+ clearTimeout(timer);
199
+ resolve(granted);
200
+ };
201
+ this.waiters.push(waiter);
202
+ });
203
+ }
204
+
205
+ release(): void {
206
+ const waiter = this.waiters.shift();
207
+ if (waiter === undefined) {
208
+ this.available += 1;
209
+ return;
210
+ }
211
+ waiter(true);
212
+ }
213
+ }
214
+
215
+ const slots = new Semaphore(MAX_CONCURRENT_SANDBOXES);
216
+
217
+ // ---------------------------------------------------------------------------
218
+ // Running one evaluation in a sandbox
219
+ // ---------------------------------------------------------------------------
220
+
221
+ interface SandboxRequest {
222
+ kind: "condition" | "evaluator";
223
+ source: string;
224
+ session: Record<string, unknown>;
225
+ evalKey: string | null;
226
+ maxResultBytes: number;
227
+ }
228
+
229
+ type SandboxOutcome =
230
+ | { ok: true; value: unknown }
231
+ | { ok: false; name: string; message: string };
232
+
233
+ async function runSandboxed(
234
+ request: Omit<SandboxRequest, "maxResultBytes">,
235
+ budgetSeconds: number,
236
+ ): Promise<unknown> {
237
+ const workerPath = sandboxWorkerPath();
238
+ const deadline = Date.now() + budgetSeconds * 1000;
239
+
240
+ // One deadline covers BOTH the queue wait and the execution, so a run cannot
241
+ // spend its whole budget waiting and then start anyway.
242
+ const granted = await slots.acquire(deadline - Date.now());
243
+ if (!granted) throw new EvaluationTimeout("evaluation timed out waiting for a sandbox slot");
244
+
245
+ try {
246
+ const remaining = deadline - Date.now();
247
+ if (remaining <= 0) {
248
+ // Slot acquired exactly at the deadline: a worker started now could only
249
+ // be killed immediately, so do not start one at all.
250
+ throw new EvaluationTimeout("evaluation timed out waiting for a sandbox slot");
251
+ }
252
+ return await runWorker(workerPath, { ...request, maxResultBytes: SANDBOX_MAX_RESULT_BYTES }, remaining);
253
+ } finally {
254
+ slots.release();
255
+ }
256
+ }
257
+
258
+ function runWorker(
259
+ workerPath: string,
260
+ request: SandboxRequest,
261
+ timeoutMs: number,
262
+ ): Promise<unknown> {
263
+ return new Promise<unknown>((resolve, reject) => {
264
+ let worker: Worker;
265
+ try {
266
+ worker = new Worker(workerPath, {
267
+ workerData: request,
268
+ // Nothing from the parent's environment crosses. On a hosted worker
269
+ // `FAILPROOFAI_EVALUATOR_TOKEN` is the credential the fleet
270
+ // authenticates with; the language cannot reach `process` at all, so
271
+ // this is defence in depth rather than a fix for a live escape — it
272
+ // means a future gap could not be escalated into credential theft.
273
+ env: {},
274
+ argv: [],
275
+ execArgv: [],
276
+ resourceLimits: {
277
+ maxOldGenerationSizeMb: SANDBOX_MEMORY_MB,
278
+ maxYoungGenerationSizeMb: 64,
279
+ codeRangeSizeMb: 32,
280
+ stackSizeMb: 8,
281
+ },
282
+ stdin: false,
283
+ stdout: true,
284
+ stderr: true,
285
+ });
286
+ } catch (error) {
287
+ reject(
288
+ new EvaluationSandboxUnavailable(
289
+ `could not start the evaluation sandbox: ${error instanceof Error ? error.message : String(error)}`,
290
+ ),
291
+ );
292
+ return;
293
+ }
294
+
295
+ let settled = false;
296
+ const finish = (run: () => void): void => {
297
+ if (settled) return;
298
+ settled = true;
299
+ clearTimeout(timer);
300
+ void worker.terminate();
301
+ run();
302
+ };
303
+
304
+ const timer = setTimeout(() => {
305
+ finish(() => {
306
+ reject(new EvaluationTimeout("evaluation exceeded its wall-clock budget"));
307
+ });
308
+ }, timeoutMs);
309
+ timer.unref?.();
310
+
311
+ worker.on("message", (outcome: SandboxOutcome) => {
312
+ finish(() => {
313
+ if (outcome.ok) {
314
+ resolve(outcome.value);
315
+ return;
316
+ }
317
+ // Preserve the child's original error SEMANTICS, so an eval's
318
+ // TypeError and the sandbox's own UnsafeEvaluatorSource read the same
319
+ // as they would in-process.
320
+ if (outcome.name === "UnsafeEvaluatorSource") {
321
+ reject(new UnsafeEvaluatorSource(outcome.message));
322
+ return;
323
+ }
324
+ if (outcome.name === "EvaluationBudgetExceeded") {
325
+ reject(new EvaluationTimeout(outcome.message));
326
+ return;
327
+ }
328
+ reject(rebuildError(outcome.name, outcome.message));
329
+ });
330
+ });
331
+
332
+ worker.on("error", (error: Error & { code?: string }) => {
333
+ finish(() => {
334
+ // A heap-limit kill arrives here, not as a message. It is a resource
335
+ // failure, not an evaluation that returned something.
336
+ if (error.code === "ERR_WORKER_OUT_OF_MEMORY") {
337
+ reject(new EvaluationTimeout("evaluation exceeded its memory budget"));
338
+ return;
339
+ }
340
+ reject(error);
341
+ });
342
+ });
343
+
344
+ worker.on("exit", (code) => {
345
+ finish(() => {
346
+ reject(
347
+ new EvaluationTimeout(
348
+ `evaluation was terminated before producing a result (exit code ${code})`,
349
+ ),
350
+ );
351
+ });
352
+ });
353
+ });
354
+ }
355
+
356
+ /**
357
+ * The built-in error types an evaluation can realistically produce.
358
+ *
359
+ * Reconstructing the REAL constructor, rather than an `Error` with its `name`
360
+ * reassigned, is what keeps `instanceof TypeError` true on this side of the
361
+ * worker boundary. An author debugging their own evaluation — or a `catch` in a
362
+ * custom managed compiler — cannot tell a sandboxed run from an in-process one
363
+ * otherwise, which turns every sandbox-only bug into a mystery.
364
+ */
365
+ const BUILTIN_ERRORS: Record<string, ErrorConstructor> = {
366
+ Error,
367
+ TypeError: TypeError,
368
+ RangeError: RangeError,
369
+ ReferenceError: ReferenceError,
370
+ SyntaxError: SyntaxError,
371
+ EvalError: EvalError,
372
+ URIError: URIError,
373
+ };
374
+
375
+ function rebuildError(name: string, message: string): Error {
376
+ const Builtin = BUILTIN_ERRORS[name];
377
+ if (Builtin !== undefined) return new Builtin(message);
378
+ const error = new Error(message);
379
+ error.name = name;
380
+ return error;
381
+ }
382
+
383
+ // ---------------------------------------------------------------------------
384
+ // Rebuilding results on this side of the boundary
385
+ // ---------------------------------------------------------------------------
386
+
387
+ interface WireScore {
388
+ value: number;
389
+ passed?: boolean;
390
+ unit?: string;
391
+ displayValue?: string;
392
+ description?: string;
393
+ }
394
+
395
+ interface WireEvalResult {
396
+ score?: WireScore;
397
+ metrics?: Record<string, number | { value: number; unit?: string; displayValue?: string; description?: string }>;
398
+ assertions?: Record<string, boolean | { passed: boolean; description?: string }>;
399
+ reasoning?: string;
400
+ summary?: string;
401
+ labels?: string[];
402
+ }
403
+
404
+ function rebuildEvalResult(value: unknown): EvalResult {
405
+ const wire = value as WireEvalResult;
406
+ if (typeof wire !== "object" || wire === null) {
407
+ throw new TypeError("evaluator source must return an EvalResult");
408
+ }
409
+ const metrics: Record<string, Metric | number> = {};
410
+ for (const [key, metric] of Object.entries(wire.metrics ?? {})) {
411
+ metrics[key] =
412
+ typeof metric === "number"
413
+ ? metric
414
+ : new Metric(metric.value, {
415
+ unit: metric.unit,
416
+ displayValue: metric.displayValue,
417
+ description: metric.description,
418
+ });
419
+ }
420
+ const assertions: Record<string, Assertion | boolean> = {};
421
+ for (const [key, assertion] of Object.entries(wire.assertions ?? {})) {
422
+ assertions[key] =
423
+ typeof assertion === "boolean"
424
+ ? assertion
425
+ : new Assertion(assertion.passed, { description: assertion.description });
426
+ }
427
+ return new EvalResult({
428
+ score:
429
+ wire.score === undefined
430
+ ? undefined
431
+ : new Score(wire.score.value, {
432
+ passed: wire.score.passed,
433
+ unit: wire.score.unit,
434
+ displayValue: wire.score.displayValue,
435
+ description: wire.score.description,
436
+ }),
437
+ metrics,
438
+ assertions,
439
+ reasoning: wire.reasoning,
440
+ summary: wire.summary,
441
+ labels: wire.labels ?? [],
442
+ });
443
+ }
444
+
445
+ function rebuildCondition(value: unknown): boolean | ConditionResult {
446
+ if (typeof value === "boolean") return value;
447
+ const wire = value as { applicable?: unknown; reasonCode?: unknown };
448
+ if (typeof wire?.applicable !== "boolean") {
449
+ throw new TypeError("condition source must return a boolean or a ConditionResult");
450
+ }
451
+ return new ConditionResult(
452
+ wire.applicable,
453
+ typeof wire.reasonCode === "string" ? wire.reasonCode : undefined,
454
+ );
455
+ }
456
+
457
+ // ---------------------------------------------------------------------------
458
+ // Public compile API
459
+ // ---------------------------------------------------------------------------
460
+
461
+ /**
462
+ * Validate `source` here, in the PARENT, so unsafe or malformed source is
463
+ * rejected before any worker is started — and return a function that runs it in
464
+ * the sandbox. The worker parses it again as defence in depth, so a worker can
465
+ * never evaluate source the parent has not vetted.
466
+ */
467
+ function validateLocally(source: string, kind: "condition" | "evaluator"): void {
468
+ compileExpression(source, {
469
+ fieldName: kind === "condition" ? "condition_source" : "evaluator_source",
470
+ maximumBytes: kind === "condition" ? MAX_CONDITION_SOURCE_BYTES : MAX_EVALUATOR_SOURCE_BYTES,
471
+ globalNames: SANDBOX_GLOBAL_NAMES,
472
+ });
473
+ }
474
+
475
+ export function compileCondition(
476
+ source: string,
477
+ options: { timeoutSeconds?: number | null } = {},
478
+ ): (session: SessionTranscript) => Promise<boolean | ConditionResult> {
479
+ validateLocally(source, "condition");
480
+ const budget = clampBudget(options.timeoutSeconds);
481
+
482
+ return async (session: SessionTranscript): Promise<boolean | ConditionResult> => {
483
+ // Conditions are sandboxed exactly like evaluators. A condition has no
484
+ // runtime-level timeout above it, so an unbounded one would block the
485
+ // worker with no deadline at all.
486
+ const value = await runSandboxed(
487
+ { kind: "condition", source, session: session.toWire(), evalKey: null },
488
+ budget,
489
+ );
490
+ return rebuildCondition(value);
491
+ };
492
+ }
493
+
494
+ export function compileEvaluator(
495
+ source: string,
496
+ options: { timeoutSeconds?: number | null; evalKey?: string | null } = {},
497
+ ): (session: SessionTranscript) => Promise<EvalResult> {
498
+ validateLocally(source, "evaluator");
499
+ const budget = clampBudget(options.timeoutSeconds);
500
+ const evalKey = options.evalKey ?? null;
501
+
502
+ return async (session: SessionTranscript): Promise<EvalResult> => {
503
+ const value = await runSandboxed(
504
+ { kind: "evaluator", source, session: session.toWire(), evalKey },
505
+ budget,
506
+ );
507
+ return rebuildEvalResult(value);
508
+ };
509
+ }