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,225 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ Assertion,
5
+ ConditionResult,
6
+ EvalResult,
7
+ Evaluator,
8
+ Metric,
9
+ Score,
10
+ } from "../src/evaluator/authoring.js";
11
+ import {
12
+ ExecutionMode,
13
+ PROTOCOL_VERSION,
14
+ ProtocolError,
15
+ ResultKind,
16
+ UnsupportedProtocolVersion,
17
+ assignmentDefinitionFromWire,
18
+ assignmentFromWire,
19
+ claimResponseFromWire,
20
+ planResponseFromWire,
21
+ registerResponseFromWire,
22
+ sessionTranscriptFromWire,
23
+ } from "../src/evaluator/protocol.js";
24
+ import { transcriptWire } from "./helpers.js";
25
+
26
+ /**
27
+ * Every `fromWire` is a VALIDATOR, not a cast. The server is across a network
28
+ * boundary: a field that arrives as a number where a string was promised has to
29
+ * fail here, naming the field — not three frames later as an undefined property
30
+ * nobody can explain.
31
+ */
32
+
33
+ describe("protocol version", () => {
34
+ it("refuses a version it does not implement", () => {
35
+ expect(() =>
36
+ registerResponseFromWire({ protocol_version: "3", evaluator_instance_id: "x" }),
37
+ ).toThrow(UnsupportedProtocolVersion);
38
+ });
39
+
40
+ it("accepts its own", () => {
41
+ expect(PROTOCOL_VERSION).toBe("2");
42
+ });
43
+ });
44
+
45
+ describe("wire validation", () => {
46
+ const assignment = {
47
+ assignment_id: "a1",
48
+ lease_generation: 1,
49
+ lease_expires_at: "2026-01-01T00:02:00Z",
50
+ session_id: "s1",
51
+ session_revision_id: "r1",
52
+ agent_id: "main",
53
+ environment: "dev",
54
+ trigger_reason: "session_end",
55
+ event_count: 3,
56
+ transcript_url: "/v1/evaluator/assignments/a1/transcript",
57
+ };
58
+
59
+ it("reads a well-formed assignment", () => {
60
+ expect(assignmentFromWire(assignment)).toMatchObject({ assignmentId: "a1", eventCount: 3 });
61
+ });
62
+
63
+ it("names the offending field", () => {
64
+ expect(() => assignmentFromWire({ ...assignment, session_id: 7 })).toThrow(
65
+ /session_id must be a string/,
66
+ );
67
+ expect(() => assignmentFromWire({ ...assignment, lease_generation: 0 })).toThrow(
68
+ /lease_generation must be greater than zero/,
69
+ );
70
+ expect(() => assignmentFromWire({ ...assignment, event_count: -1 })).toThrow(
71
+ /event_count must not be negative/,
72
+ );
73
+ });
74
+
75
+ it("requires execution_mode explicitly rather than defaulting to local", () => {
76
+ // Coercing a missing value to `local` silently runs a server-authored
77
+ // definition down the customer-local path, or the reverse.
78
+ const definition = {
79
+ eval_key: "k",
80
+ display_name: "K",
81
+ eval_version: "1",
82
+ result_kind: "score",
83
+ labels: [],
84
+ };
85
+ expect(() => assignmentDefinitionFromWire(definition)).toThrow(ProtocolError);
86
+ expect(
87
+ assignmentDefinitionFromWire({ ...definition, execution_mode: "local" }).executionMode,
88
+ ).toBe(ExecutionMode.LOCAL);
89
+ // `python` is the wire spelling of "the server authored this, sandbox it".
90
+ expect(
91
+ assignmentDefinitionFromWire({ ...definition, execution_mode: "python" }).executionMode,
92
+ ).toBe(ExecutionMode.SANDBOX);
93
+ });
94
+
95
+ it("refuses a transcript whose event_count disagrees with its events", () => {
96
+ const wire = transcriptWire([{ type: "tool_use" }]);
97
+ wire.event_count = 5;
98
+ expect(() => sessionTranscriptFromWire(wire)).toThrow(/event_count is 5/);
99
+ });
100
+
101
+ it("refuses a transcript schema version it does not implement", () => {
102
+ const wire = transcriptWire();
103
+ wire.schema_version = "9";
104
+ expect(() => sessionTranscriptFromWire(wire)).toThrow(/unsupported transcript schema version/);
105
+ });
106
+
107
+ it("round-trips a transcript through toWire", () => {
108
+ const wire = transcriptWire([{ type: "tool_use", payload: { a: 1 } }]);
109
+ expect(sessionTranscriptFromWire(sessionTranscriptFromWire(wire).toWire()).events).toHaveLength(1);
110
+ });
111
+
112
+ it("refuses a non-boolean idempotent_replay", () => {
113
+ expect(() =>
114
+ planResponseFromWire({
115
+ protocol_version: "2",
116
+ assignment_id: "a1",
117
+ assignment_status: "planned",
118
+ runs: [],
119
+ idempotent_replay: "yes",
120
+ }),
121
+ ).toThrow(/idempotent_replay must be a boolean/);
122
+ });
123
+
124
+ it("refuses a non-array assignments list", () => {
125
+ expect(() => claimResponseFromWire({ protocol_version: "2", assignments: {} })).toThrow(
126
+ /assignments must be an array/,
127
+ );
128
+ });
129
+ });
130
+
131
+ describe("transcript helpers", () => {
132
+ const session = sessionTranscriptFromWire(
133
+ transcriptWire([{ type: "tool_use" }, { type: "tool_result" }, { type: "tool_result" }]),
134
+ );
135
+
136
+ it("filters and counts by event type", () => {
137
+ expect(session.count("tool_result")).toBe(2);
138
+ expect(session.eventsOfType("tool_use")).toHaveLength(1);
139
+ expect(session.count("absent")).toBe(0);
140
+ });
141
+ });
142
+
143
+ describe("authoring bounds", () => {
144
+ it("keeps a score inside 0..1", () => {
145
+ expect(() => new Score(1.5)).toThrow(/between 0 and 1/);
146
+ expect(() => new Score(Number.NaN)).toThrow(/must be finite/);
147
+ expect(new Score(0.5).unit).toBe("ratio");
148
+ });
149
+
150
+ it("refuses control characters the server would 422 on", () => {
151
+ // A non-retryable 422 loses a SUCCESSFUL evaluation and dead-letters its
152
+ // assignment, so this has to fail at the line that wrote it.
153
+ expect(() => new EvalResult({ reasoning: "line\u0000break" })).toThrow(
154
+ /must not contain control characters/,
155
+ );
156
+ // Real multi-line reasoning is fine.
157
+ expect(() => new EvalResult({ reasoning: "line\nbreak\ttab" })).not.toThrow();
158
+ });
159
+
160
+ it("normalizes and de-duplicates labels", () => {
161
+ expect(new EvalResult({ score: new Score(1), labels: ["b", "a"] }).labels).toEqual(["a", "b"]);
162
+ expect(() => new EvalResult({ labels: ["a", "a"] })).toThrow(/must be unique/);
163
+ });
164
+
165
+ it("requires at least one result", () => {
166
+ expect(() => new EvalResult({}).resultItems("k")).toThrow(/must contain a score, metric/);
167
+ });
168
+
169
+ it("attaches the eval's reasoning to the PRIMARY result of a non-score eval", () => {
170
+ const items = new EvalResult({
171
+ metrics: { latency: 12, other: 3 },
172
+ reasoning: "because",
173
+ }).resultItems("latency");
174
+ expect(items.find((item) => item.resultKey === "latency")!.reasoning).toBe("because");
175
+ expect(items.find((item) => item.resultKey === "other")!.reasoning).toBeNull();
176
+ });
177
+
178
+ it("coerces a bare number or boolean into a Metric or an Assertion", () => {
179
+ const items = new EvalResult({ metrics: { a: 1 }, assertions: { b: true } }).resultItems("a");
180
+ expect(items.map((item) => item.resultKind)).toEqual([ResultKind.METRIC, ResultKind.ASSERTION]);
181
+ expect(new Metric(1).unit).toBe("");
182
+ expect(new Assertion(true).passed).toBe(true);
183
+ });
184
+
185
+ it("validates a condition's reason code as a key", () => {
186
+ expect(() => new ConditionResult(false, "Not A Key")).toThrow(/must match/);
187
+ expect(new ConditionResult(false).reasonCode).toBe("condition_false");
188
+ });
189
+ });
190
+
191
+ describe("Evaluator registry", () => {
192
+ it("validates the eval key shape", () => {
193
+ const app = new Evaluator({ name: "n", version: "1" });
194
+ expect(() => app.eval("Bad-Key", { version: "1" }, () => new EvalResult())).toThrow(/must match/);
195
+ });
196
+
197
+ it("refuses a duplicate key", () => {
198
+ const app = new Evaluator({ name: "n", version: "1" });
199
+ app.eval("a", { version: "1" }, () => new EvalResult());
200
+ expect(() => app.eval("a", { version: "2" }, () => new EvalResult())).toThrow(/duplicate/);
201
+ });
202
+
203
+ it("derives a display name from the key", () => {
204
+ const app = new Evaluator({ name: "n", version: "1" });
205
+ app.eval("tool_success_rate", { version: "1" }, () => new EvalResult());
206
+ expect(app.definition("tool_success_rate").displayName).toBe("Tool success rate");
207
+ });
208
+
209
+ it("produces a stable catalog revision that changes with the catalog", () => {
210
+ const build = (version: string): string => {
211
+ const app = new Evaluator({ name: "n", version: "1" });
212
+ app.eval("b", { version }, () => new EvalResult());
213
+ app.eval("a", { version: "1" }, () => new EvalResult());
214
+ return app.catalogRevision;
215
+ };
216
+ expect(build("1")).toBe(build("1"));
217
+ expect(build("1")).not.toBe(build("2"));
218
+ expect(build("1")).toMatch(/^sha256:[0-9a-f]{64}$/);
219
+ // Sorted, so registration order cannot change the hash.
220
+ const app = new Evaluator({ name: "n", version: "1" });
221
+ app.eval("z", { version: "1" }, () => new EvalResult());
222
+ app.eval("a", { version: "1" }, () => new EvalResult());
223
+ expect(app.catalog().map((item) => item.evalKey)).toEqual(["a", "z"]);
224
+ });
225
+ });
@@ -0,0 +1,193 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ import { EventNamespace } from "../src/events.js";
4
+ import { agent, session } from "../src/scopes.js";
5
+ import { runtime } from "../src/runtime.js";
6
+ import { setLogger } from "../src/logger.js";
7
+ import { flushed, useSpool } from "./helpers.js";
8
+ import type { Spool } from "./helpers.js";
9
+
10
+ let spool: Spool;
11
+
12
+ beforeEach(() => {
13
+ spool = useSpool();
14
+ });
15
+
16
+ afterEach(async () => {
17
+ await spool.cleanup();
18
+ setLogger(null);
19
+ });
20
+
21
+ const event = (): EventNamespace => runtime.event;
22
+
23
+ describe("identity resolution", () => {
24
+ it("resolves sessionId and agentId from the enclosing scope", async () => {
25
+ await session({ sessionId: "s1" }, async () => {
26
+ await agent("planner", async () => {
27
+ event().toolUse({ toolName: "t", toolCallId: "c1" });
28
+ });
29
+ });
30
+ const events = await flushed(spool);
31
+ const toolUse = events.find((e) => e.type === "tool_use")!;
32
+ expect(toolUse.session_id).toBe("s1");
33
+ expect(toolUse.agent_id).toBe("planner");
34
+ });
35
+
36
+ it("falls back to 'main' for agentId but never invents a sessionId", async () => {
37
+ await session({ sessionId: "s1" }, () => {
38
+ event().toolUse({ toolName: "t", toolCallId: "c1" });
39
+ });
40
+ expect((await flushed(spool))[0]!.agent_id).toBe("main");
41
+ });
42
+
43
+ it("throws, naming the fix, when nothing is bound", () => {
44
+ expect(() => event().toolUse({ toolName: "t", toolCallId: "c1" })).toThrow(
45
+ /sessionId is required and nothing is bound/,
46
+ );
47
+ });
48
+
49
+ it("refuses an empty sessionId, which the server would accept and silently merge", () => {
50
+ expect(() => event().toolUse({ sessionId: " ", toolName: "t", toolCallId: "c" })).toThrow(
51
+ /must not be empty/,
52
+ );
53
+ });
54
+
55
+ it("refuses a non-string sessionId, which the server skips at 200 OK", () => {
56
+ expect(() =>
57
+ event().toolUse({ sessionId: 42 as unknown as string, toolName: "t", toolCallId: "c" }),
58
+ ).toThrow(TypeError);
59
+ });
60
+ });
61
+
62
+ describe("reserved and promoted fields", () => {
63
+ it("refuses a reserved name as a custom field", () => {
64
+ expect(() =>
65
+ event().toolUse({ sessionId: "s", toolName: "t", toolCallId: "c", type: "nope" }),
66
+ ).toThrow(/Reserved field names/);
67
+ });
68
+
69
+ it("reports the reserved-field fault before the identity fault", () => {
70
+ // Both are true here. The reserved name reads identically from anywhere, so
71
+ // it is the more useful of the two to hear.
72
+ expect(() => event().toolUse({ toolName: "t", toolCallId: "c", timestamp: "x" })).toThrow(
73
+ /Reserved field names/,
74
+ );
75
+ });
76
+
77
+ it("drops a nullish promoted extra with a warning rather than NULLing the column", async () => {
78
+ const warn = vi.fn();
79
+ setLogger({ debug: vi.fn(), info: vi.fn(), warn, error: vi.fn() });
80
+ event().agentStart({ sessionId: "s", model: null });
81
+ expect(warn).toHaveBeenCalledWith(expect.stringContaining("model was passed as null"));
82
+ const [emitted] = await flushed(spool);
83
+ expect("model" in emitted!).toBe(false);
84
+ });
85
+
86
+ it("refuses a non-integer token count, which the server stores as NULL", () => {
87
+ expect(() => event().modelResponse({ sessionId: "s", inputTokens: 1.5 })).toThrow(TypeError);
88
+ expect(() => event().modelResponse({ sessionId: "s", outputTokens: -1 })).toThrow(RangeError);
89
+ expect(() => event().modelResponse({ sessionId: "s", inputTokens: 2 ** 32 })).toThrow(RangeError);
90
+ });
91
+
92
+ it("refuses a non-string promoted extra", () => {
93
+ expect(() =>
94
+ event().agentStart({ sessionId: "s", tool_name: 7 as unknown as string }),
95
+ ).toThrow(TypeError);
96
+ });
97
+ });
98
+
99
+ describe("duration pairing", () => {
100
+ it("computes duration_ms from the matching start event", async () => {
101
+ event().toolUse({ sessionId: "s", toolName: "t", toolCallId: "c1" });
102
+ await new Promise((resolve) => setTimeout(resolve, 12));
103
+ event().toolResult({ sessionId: "s", toolName: "t", toolCallId: "c1" });
104
+ const result = (await flushed(spool)).find((e) => e.type === "tool_result")!;
105
+ expect(typeof result.duration_ms).toBe("number");
106
+ expect(result.duration_ms as number).toBeGreaterThanOrEqual(10);
107
+ });
108
+
109
+ it("refuses a caller-supplied duration_ms on every paired event", () => {
110
+ const cases: Array<() => void> = [
111
+ () => event().toolResult({ sessionId: "s", toolName: "t", toolCallId: "c", duration_ms: 1 }),
112
+ () => event().agentResume({ sessionId: "s", pauseId: "p", duration_ms: 1 }),
113
+ () => event().hookCompleted({ sessionId: "s", hookName: "h", hookId: "h", duration_ms: 1 }),
114
+ () => event().humanInput({ sessionId: "s", inputId: "i", duration_ms: 1 }),
115
+ ];
116
+ for (const run of cases) expect(run).toThrow(/auto-computed/);
117
+ });
118
+
119
+ it("keys the pair by kind AND session, so a shared step id cannot cross-pair", async () => {
120
+ // A tool call and a hook sharing an id is not exotic — both are frequently
121
+ // the harness's own step id.
122
+ event().toolUse({ sessionId: "s", toolName: "t", toolCallId: "step-1" });
123
+ event().hookCompleted({ sessionId: "s", hookName: "h", hookId: "step-1" });
124
+ event().toolResult({ sessionId: "s", toolName: "t", toolCallId: "step-1" });
125
+
126
+ const events = await flushed(spool);
127
+ const hook = events.find((e) => e.type === "hook_completed")!;
128
+ const tool = events.find((e) => e.type === "tool_result")!;
129
+ // The hook never opened, so it has no duration; the tool's survived.
130
+ expect("duration_ms" in hook).toBe(false);
131
+ expect(typeof tool.duration_ms).toBe("number");
132
+ });
133
+
134
+ it("does not key the pair by agent, so a tool opened and closed under different agents still pairs", async () => {
135
+ event().toolUse({ sessionId: "s", agentId: "planner", toolName: "t", toolCallId: "c1" });
136
+ event().toolResult({ sessionId: "s", agentId: "worker", toolName: "t", toolCallId: "c1" });
137
+ const result = (await flushed(spool)).find((e) => e.type === "tool_result")!;
138
+ expect(typeof result.duration_ms).toBe("number");
139
+ });
140
+
141
+ it("separates identical step ids in different sessions", async () => {
142
+ event().toolUse({ sessionId: "a", toolName: "t", toolCallId: "step" });
143
+ event().toolUse({ sessionId: "b", toolName: "t", toolCallId: "step" });
144
+ event().toolResult({ sessionId: "a", toolName: "t", toolCallId: "step" });
145
+ const result = (await flushed(spool)).find((e) => e.type === "tool_result")!;
146
+ expect(result.session_id).toBe("a");
147
+ expect(typeof result.duration_ms).toBe("number");
148
+ });
149
+ });
150
+
151
+ describe("timestamps", () => {
152
+ it("formats with six fractional digits, matching the Python SDK and the ingest parser", async () => {
153
+ event().agentStart({ sessionId: "s" });
154
+ const [emitted] = await flushed(spool);
155
+ expect(emitted!.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z$/);
156
+ });
157
+
158
+ it("orders a burst inside one millisecond: every timestamp strictly after the last", async () => {
159
+ // A fast agent emits model_response, tool_use, tool_result and the next
160
+ // model_request inside one millisecond. With the last three digits always
161
+ // 000 they all carried the same timestamp, and the dashboard — which sorts
162
+ // on it — showed tool_result before its tool_use.
163
+ vi.useFakeTimers({ toFake: ["Date"] });
164
+ try {
165
+ vi.setSystemTime(new Date("2026-09-23T15:55:44.134Z"));
166
+ event().toolUse({ sessionId: "s", toolName: "t", toolCallId: "c1" });
167
+ event().toolResult({ sessionId: "s", toolName: "t", toolCallId: "c1" });
168
+ event().modelRequest({ sessionId: "s" });
169
+ event().agentEnd({ sessionId: "s" });
170
+ } finally {
171
+ vi.useRealTimers();
172
+ }
173
+ const stamps = (await flushed(spool)).map((e) => e.timestamp as string);
174
+ expect(stamps).toHaveLength(4);
175
+ for (const stamp of stamps) expect(stamp.startsWith("2026-09-23T15:55:44.134")).toBe(true);
176
+ expect([...stamps].sort()).toEqual(stamps);
177
+ expect(new Set(stamps).size).toBe(4);
178
+ });
179
+
180
+ it("re-anchors to the wall clock when it steps back, rather than freezing", async () => {
181
+ vi.useFakeTimers({ toFake: ["Date"] });
182
+ try {
183
+ vi.setSystemTime(new Date("2026-09-23T16:00:00.000Z"));
184
+ event().agentStart({ sessionId: "s" });
185
+ vi.setSystemTime(new Date("2026-09-23T15:00:00.000Z")); // NTP stepped back an hour
186
+ event().agentEnd({ sessionId: "s" });
187
+ } finally {
188
+ vi.useRealTimers();
189
+ }
190
+ const [, end] = await flushed(spool);
191
+ expect((end!.timestamp as string).startsWith("2026-09-23T15:00:00.000")).toBe(true);
192
+ });
193
+ });
@@ -0,0 +1,181 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ EvaluationBudgetExceeded,
5
+ MAX_POW_EXPONENT,
6
+ UnsafeEvaluatorSource,
7
+ compileExpression,
8
+ } from "../src/evaluator/expression.js";
9
+ import { sessionTranscriptFromWire } from "../src/evaluator/protocol.js";
10
+ import { transcriptWire } from "./helpers.js";
11
+
12
+ /**
13
+ * The language is the correctness boundary for server-authored source — the
14
+ * `worker_threads` sandbox around it bounds RESOURCES, not reach. So the cases
15
+ * that matter most here are the ones that must be refused, and every one of
16
+ * them is a real escape in a naive `eval`- or `vm`-based design.
17
+ */
18
+
19
+ const session = sessionTranscriptFromWire(
20
+ transcriptWire([
21
+ { type: "tool_use", payload: { tool_name: "search" } },
22
+ { type: "tool_result", payload: { error: "timeout" } },
23
+ { type: "tool_result", payload: { output: "ok" } },
24
+ ]),
25
+ );
26
+
27
+ const GLOBALS = ["session", "Math", "Object", "Array", "Number", "JSON"] as const;
28
+
29
+ function run(source: string): unknown {
30
+ const compiled = compileExpression(source, {
31
+ fieldName: "evaluator_source",
32
+ maximumBytes: 128 * 1024,
33
+ globalNames: GLOBALS,
34
+ });
35
+ return compiled({ session });
36
+ }
37
+
38
+ function compileOnly(source: string): void {
39
+ compileExpression(source, {
40
+ fieldName: "evaluator_source",
41
+ maximumBytes: 128 * 1024,
42
+ globalNames: GLOBALS,
43
+ });
44
+ }
45
+
46
+ describe("what the language can express", () => {
47
+ it("reads the transcript surface", () => {
48
+ expect(run("session.eventCount")).toBe(3);
49
+ expect(run("session.count('tool_result')")).toBe(2);
50
+ expect(run("session.eventsOfType('tool_use').length")).toBe(1);
51
+ expect(run("session.agentId")).toBe("main");
52
+ });
53
+
54
+ it("reads arbitrary payload keys, which no static allowlist could enumerate", () => {
55
+ expect(run("session.eventsOfType('tool_result')[0].payload.error")).toBe("timeout");
56
+ expect(run("session.eventsOfType('tool_result')[1].payload['output']")).toBe("ok");
57
+ });
58
+
59
+ it("supports `!= null`, the idiom for an optional payload field", () => {
60
+ // Mapping `!=` to `!==` would silently stop this matching a missing key,
61
+ // so an evaluation over a payload that omits the field would report the
62
+ // opposite of the truth.
63
+ expect(
64
+ run("session.eventsOfType('tool_result').filter(e => e.payload.error != null).length"),
65
+ ).toBe(1);
66
+ expect(run("session.eventsOfType('tool_result')[1].payload.error == null")).toBe(true);
67
+ });
68
+
69
+ it("supports arrow functions, arithmetic, comparison and the conditional operator", () => {
70
+ expect(run("[1, 2, 3].map(x => x * 2).filter(x => x > 2)")).toEqual([4, 6]);
71
+ expect(run("session.eventCount > 0 ? 'busy' : 'idle'")).toBe("busy");
72
+ expect(run("Math.round(1 / 3 * 100) / 100")).toBe(0.33);
73
+ expect(run("[1, 2, 3].reduce((a, b) => a + b, 0)")).toBe(6);
74
+ });
75
+
76
+ it("supports template strings and object literals", () => {
77
+ expect(run("`saw ${session.eventCount} events`")).toBe("saw 3 events");
78
+ expect(run("({ total: session.eventCount, ok: true })")).toEqual({ total: 3, ok: true });
79
+ });
80
+
81
+ it("supports the namespace globals it advertises", () => {
82
+ expect(run("Object.keys({ a: 1, b: 2 })")).toEqual(["a", "b"]);
83
+ expect(run("Array.isArray(session.events)")).toBe(true);
84
+ expect(run("Number.isInteger(session.eventCount)")).toBe(true);
85
+ expect(run("JSON.stringify({ a: 1 })")).toBe('{"a":1}');
86
+ });
87
+ });
88
+
89
+ describe("escapes that must be refused", () => {
90
+ const rejected: Array<[string, string]> = [
91
+ ["a function constructor", "(x => x).constructor"],
92
+ ["a literal computed constructor", "session['constructor']"],
93
+ ["prototype", "session.prototype"],
94
+ ["__proto__", "session.__proto__"],
95
+ ["call", "session.count.call"],
96
+ ["bind", "session.count.bind"],
97
+ ["toString, which runs arbitrary code", "session.toString"],
98
+ ["a reference to process", "process.env"],
99
+ ["a reference to globalThis", "globalThis"],
100
+ ["require", "require('fs')"],
101
+ ["import", "import('fs')"],
102
+ ["new", "new Object()"],
103
+ ["a function expression", "function () { return 1 }"],
104
+ ["assignment", "session.eventCount = 5"],
105
+ ["a statement", "if (true) 1"],
106
+ ["a block-bodied arrow", "(x) => { return x }"],
107
+ ["an unbound identifier", "somethingElse"],
108
+ ["a private name", "_secret"],
109
+ ["a regular expression literal", "/abc/.test('abc')"],
110
+ ["a comment, which the grammar does not accept", "1 // trailing"],
111
+ ["a compile-time exponent bomb", "10 ** 99"],
112
+ ["a generator", "function* () { yield 1 }"],
113
+ ["a BigInt literal", "1n"],
114
+ ["optional chaining onto a forbidden key", "session?.constructor"],
115
+ ];
116
+
117
+ for (const [label, source] of rejected) {
118
+ it(`refuses ${label}`, () => {
119
+ expect(() => compileOnly(source)).toThrow(UnsafeEvaluatorSource);
120
+ });
121
+ }
122
+
123
+ it("refuses a bare method reference, which is only useful for smuggling one out", () => {
124
+ expect(() => compileOnly("session.count")).toThrow(/only to call it/);
125
+ expect(() => compileOnly("[].map")).toThrow(/only to call it/);
126
+ });
127
+
128
+ it("names the exponent ceiling in the message", () => {
129
+ expect(() => compileOnly("2 ** 100")).toThrow(
130
+ new RegExp(`integer constant in 0\\.\\.${MAX_POW_EXPONENT}`),
131
+ );
132
+ });
133
+
134
+ it("refuses a RUNTIME-computed forbidden key, which no source check can see", () => {
135
+ // This is why the boundary is `readProperty` and not the parser.
136
+ expect(() => run("session[['con','structor'].join('')]")).toThrow(UnsafeEvaluatorSource);
137
+ expect(() => run("session['con' + 'structor']")).toThrow(UnsafeEvaluatorSource);
138
+ });
139
+
140
+ it("refuses a non-allowlisted method on a built-in prototype", () => {
141
+ expect(() => run("[1, 2].sort()")).toThrow(UnsafeEvaluatorSource);
142
+ expect(() => run("'abc'.matchAll('a')")).toThrow(UnsafeEvaluatorSource);
143
+ });
144
+
145
+ it("refuses a namespace member outside its set", () => {
146
+ expect(() => run("Object.getPrototypeOf({})")).toThrow(UnsafeEvaluatorSource);
147
+ expect(() => run("Math.random()")).toThrow(UnsafeEvaluatorSource);
148
+ });
149
+
150
+ it("does not walk a prototype for a plain object's missing key", () => {
151
+ expect(run("({}).somethingAbsent")).toBeUndefined();
152
+ });
153
+ });
154
+
155
+ describe("budgets", () => {
156
+ it("bounds unbounded self-application", () => {
157
+ // `(f => f(f))(f => f(f))` is reachable with nothing but arrow functions,
158
+ // and runs forever.
159
+ expect(() => run("(f => f(f))(f => f(f))")).toThrow(EvaluationBudgetExceeded);
160
+ });
161
+
162
+ it("bounds a string bomb", () => {
163
+ expect(() => run("'x'.repeat(64) .repeat(64) .repeat(64) .repeat(64)")).toThrow(
164
+ EvaluationBudgetExceeded,
165
+ );
166
+ });
167
+
168
+ it("refuses source above the byte ceiling", () => {
169
+ expect(() =>
170
+ compileExpression(`'${"x".repeat(200)}'`, {
171
+ fieldName: "evaluator_source",
172
+ maximumBytes: 100,
173
+ globalNames: GLOBALS,
174
+ }),
175
+ ).toThrow(/exceeds 100 bytes/);
176
+ });
177
+
178
+ it("refuses empty source", () => {
179
+ expect(() => compileOnly(" ")).toThrow(/must not be empty/);
180
+ });
181
+ });
@@ -0,0 +1,26 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ /**
6
+ * Point the evaluator sandbox at this checkout's built worker.
7
+ *
8
+ * The tests run against `src/` through Vitest's TypeScript loader, but a
9
+ * `worker_threads` Worker is a real Node process entry and cannot load a `.ts`
10
+ * file. In an installed package `source.ts` resolves `@failproofai/sdk/sandbox-worker`
11
+ * through the exports map; here there is no installed package, so the env
12
+ * override — the same one the code documents for bundled consumers — points at
13
+ * `dist/`. `npm test` builds first, which is why this can assert rather than
14
+ * skip: a sandbox test that silently did not run is worse than no sandbox test.
15
+ */
16
+ export default function setup(): void {
17
+ const root = dirname(dirname(fileURLToPath(import.meta.url)));
18
+ const worker = resolve(root, "dist/cjs/evaluator/sandbox-worker.js");
19
+ if (!existsSync(worker)) {
20
+ throw new Error(
21
+ `the evaluator sandbox worker is not built at ${worker}. Run \`npm run build\` first ` +
22
+ "(`npm test` does it for you).",
23
+ );
24
+ }
25
+ process.env.FAILPROOFAI_SDK_SANDBOX_WORKER = worker;
26
+ }