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,311 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ FORMATS,
5
+ count,
6
+ describeTrace,
7
+ ofType,
8
+ runAgent,
9
+ traceViolations,
10
+ typecheck,
11
+ type Event,
12
+ } from "./harness.js";
13
+
14
+ /**
15
+ * Mastra (`@mastra/core`), against real releases.
16
+ *
17
+ * Mastra has no Python counterpart, so the expected traces are derived from the
18
+ * rule every adapter follows (`sdk/python/skill/references/frameworks.md`, "The
19
+ * rule the mappings follow"), using CrewAI and LlamaIndex as the analogues:
20
+ *
21
+ * * an `Agent.generate()` / `.stream()` call owns an LLM decision loop, so it
22
+ * is an AGENT, named after the Mastra agent — never its id if that is a
23
+ * UUID, never a constant;
24
+ * * a Mastra agent another agent calls (Mastra's `agents: {…}` delegation) is
25
+ * a nested agent under the caller, reached through the caller's tool call;
26
+ * * every LLM step is its own `model_request`/`model_response` pair — a
27
+ * two-step tool loop is two pairs, not one — carrying the model id, integer
28
+ * tokens and a string stop reason;
29
+ * * a tool is a `tool_use`/`tool_result` pair carrying the MODEL's tool call
30
+ * id, attributed to the agent that called it;
31
+ * * a workflow run is an agent named after the workflow, and its steps are
32
+ * HOOKS (`trigger_event="workflow_step"`), exactly as LlamaIndex workflow
33
+ * steps are;
34
+ * * Mastra's own machinery — the agentic loop is itself built from internal
35
+ * workflows — emits nothing;
36
+ * * a failure is carried by the events it happened in: no `error` events.
37
+ */
38
+
39
+ const FIXTURES = ["mastra-1", "mastra-0"] as const;
40
+
41
+ /** One line per event: `agent_id type [hook|tool]`. */
42
+ const shape = (events: Event[]): string[] =>
43
+ events.map((e) =>
44
+ [e.agent_id, e.type, (e.hook_name ?? e.tool_name ?? "") as string].join(" ").trim(),
45
+ );
46
+
47
+ const loop = (agent: string): string[] => [
48
+ `${agent} agent_start`,
49
+ `${agent} model_request`,
50
+ `${agent} model_response`,
51
+ `${agent} tool_use weather`,
52
+ `${agent} tool_result weather`,
53
+ `${agent} model_request`,
54
+ `${agent} model_response`,
55
+ `${agent} agent_end`,
56
+ ];
57
+
58
+ const LOOP = loop("weather-agent");
59
+
60
+ describe.each(FIXTURES)("%s", (fixture) => {
61
+ it("typechecks as a customer's nodenext ES-module project", () => {
62
+ expect(typecheck(fixture)).toBe("");
63
+ });
64
+
65
+ describe.each(FORMATS)("as %s", (format) => {
66
+ const run = (scenario: string) => {
67
+ const result = runAgent(fixture, format, scenario);
68
+ expect(result.status, describeTrace(result)).toBe(0);
69
+ return result;
70
+ };
71
+
72
+ it("records generate() as one agent with one model pair per LLM step", () => {
73
+ const result = run("generate");
74
+ expect(shape(result.events), describeTrace(result)).toEqual(LOOP);
75
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
76
+ expect(new Set(result.events.map((e) => e.session_id)).size).toBe(1);
77
+
78
+ const responses = ofType(result.events, "model_response");
79
+ expect(responses.map((e) => [e.input_tokens, e.output_tokens])).toEqual([
80
+ [11, 7],
81
+ [23, 9],
82
+ ]);
83
+ expect(responses.map((e) => e.stop_reason)).toEqual(["tool-calls", "stop"]);
84
+ for (const event of [...ofType(result.events, "model_request"), ...responses]) {
85
+ expect(event.model).toBe("scripted-model");
86
+ }
87
+ expect(responses[1]!.content).toBe("It is sunny in Paris.");
88
+ const request = ofType(result.events, "model_request")[0]!;
89
+ expect(JSON.stringify(request.messages)).toContain("What is the weather in Paris?");
90
+
91
+ // The model's own tool call id, so a tool_use joins to the tool call in
92
+ // the model_response that asked for it.
93
+ const use = ofType(result.events, "tool_use")[0]!;
94
+ expect(use.tool_call_id).toBe("call_1");
95
+ expect(use.input).toEqual({ city: "Paris" });
96
+ const toolResult = ofType(result.events, "tool_result")[0]!;
97
+ expect(toolResult.tool_call_id).toBe("call_1");
98
+ expect(toolResult.output).toEqual({ city: "Paris", forecast: "sunny" });
99
+ expect(typeof toolResult.duration_ms).toBe("number");
100
+
101
+ const end = ofType(result.events, "agent_end")[0]!;
102
+ expect(end.outcome).toBe("success");
103
+ expect(typeof end.duration_ms).toBe("number");
104
+ for (const event of result.events) {
105
+ expect(event.framework).toBe("mastra");
106
+ expect(typeof event.framework_version).toBe("string");
107
+ }
108
+ expect(result.stdout).toContain("It is sunny in Paris.");
109
+ });
110
+
111
+ it("records a fully consumed stream() exactly like generate()", () => {
112
+ const result = run("stream");
113
+ expect(shape(result.events), describeTrace(result)).toEqual(LOOP);
114
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
115
+ const responses = ofType(result.events, "model_response");
116
+ expect(responses.map((e) => [e.input_tokens, e.output_tokens])).toEqual([
117
+ [11, 7],
118
+ [23, 9],
119
+ ]);
120
+ expect(responses.map((e) => e.stop_reason)).toEqual(["tool-calls", "stop"]);
121
+ expect(responses[1]!.content).toBe("It is sunny in Paris.");
122
+ expect(ofType(result.events, "tool_use")[0]!.tool_call_id).toBe("call_1");
123
+ expect(ofType(result.events, "agent_end")[0]!.outcome).toBe("success");
124
+ expect(result.stdout).toContain("It is sunny in Paris.");
125
+ });
126
+
127
+ it("nests a sub-agent under the agent whose tool call delegated to it", () => {
128
+ const result = run("subagent");
129
+ expect(shape(result.events), describeTrace(result)).toEqual([
130
+ "boss agent_start",
131
+ "boss model_request",
132
+ "boss model_response",
133
+ "boss tool_use agent-helper",
134
+ ...loop("helper"),
135
+ "boss tool_result agent-helper",
136
+ "boss model_request",
137
+ "boss model_response",
138
+ "boss agent_end",
139
+ ]);
140
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
141
+ expect(new Set(result.events.map((e) => e.session_id)).size).toBe(1);
142
+ const starts = ofType(result.events, "agent_start");
143
+ expect(starts[0]!.parent_id).toBeUndefined();
144
+ expect(starts[1]!.parent_id).toBe("boss");
145
+ expect(
146
+ ofType(result.events, "model_response")
147
+ .filter((e) => e.agent_id === "boss")
148
+ .map((e) => [e.input_tokens, e.output_tokens]),
149
+ ).toEqual([
150
+ [40, 12],
151
+ [60, 8],
152
+ ]);
153
+ });
154
+
155
+ it("records a workflow run as one agent with its steps as hooks", () => {
156
+ const result = run("workflow");
157
+ expect(shape(result.events), describeTrace(result)).toEqual([
158
+ "weather-flow agent_start",
159
+ "weather-flow hook_triggered fetch-city",
160
+ "weather-flow hook_completed fetch-city",
161
+ "weather-flow hook_triggered ask-agent",
162
+ ...LOOP,
163
+ "weather-flow hook_completed ask-agent",
164
+ "weather-flow agent_end",
165
+ ]);
166
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
167
+ expect(new Set(result.events.map((e) => e.session_id)).size).toBe(1);
168
+ for (const hook of ofType(result.events, "hook_triggered")) {
169
+ expect(hook.trigger_event).toBe("workflow_step");
170
+ }
171
+ for (const hook of ofType(result.events, "hook_completed")) {
172
+ expect(hook.outcome).toBe("success");
173
+ }
174
+ // The agent a step calls is nested under the workflow, and the tool that
175
+ // agent calls is ITS tool, not the workflow's.
176
+ expect(ofType(result.events, "agent_start")[1]!.parent_id).toBe("weather-flow");
177
+ expect(ofType(result.events, "tool_use")[0]!.agent_id).toBe("weather-agent");
178
+ expect(ofType(result.events, "agent_end").at(-1)!.outcome).toBe("success");
179
+ expect(result.stdout).toContain('"status":"success"');
180
+ });
181
+
182
+ it("records a failed workflow step once, on the step", () => {
183
+ const result = run("workflow-error");
184
+ expect(shape(result.events), describeTrace(result)).toEqual([
185
+ "weather-flow agent_start",
186
+ "weather-flow hook_triggered fetch-city",
187
+ "weather-flow hook_completed fetch-city",
188
+ "weather-flow hook_triggered ask-agent",
189
+ "weather-flow hook_completed ask-agent",
190
+ "weather-flow agent_end",
191
+ ]);
192
+ const failed = ofType(result.events, "hook_completed")[1]!;
193
+ expect(failed.outcome).toBe("failed");
194
+ expect(String(failed.error)).toMatch(/step exploded/);
195
+ expect(ofType(result.events, "agent_end")[0]!.outcome).toBe("failed");
196
+ expect(count(result.events, "error")).toBe(0);
197
+ });
198
+
199
+ it("records a bare wrapTool() call as its own run", () => {
200
+ const result = run("wraptool");
201
+ expect(shape(result.events), describeTrace(result)).toEqual([
202
+ "weather agent_start",
203
+ "weather tool_use weather",
204
+ "weather tool_result weather",
205
+ "weather agent_end",
206
+ ]);
207
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
208
+ expect(ofType(result.events, "tool_use")[0]!.input).toEqual({ city: "Rome" });
209
+ expect(ofType(result.events, "tool_result")[0]!.output).toEqual({ city: "Rome", forecast: "sunny" });
210
+ });
211
+
212
+ it("records a tool failure on the tool, and the agent carries on", () => {
213
+ const result = run("tool-error");
214
+ expect(shape(result.events), describeTrace(result)).toEqual(LOOP);
215
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
216
+ expect(String(ofType(result.events, "tool_result")[0]!.error)).toMatch(/tool exploded/);
217
+ expect(ofType(result.events, "agent_end")[0]!.outcome).toBe("success");
218
+ expect(count(result.events, "error")).toBe(0);
219
+ });
220
+
221
+ for (const scenario of ["model-error", "stream-model-error"]) {
222
+ it(`records a model failure once, where it happened (${scenario})`, () => {
223
+ const result = run(scenario);
224
+ expect(result.stdout).toContain("model exploded");
225
+ // Once per provider call. Mastra 0.x retries a failed model call
226
+ // itself (`maxRetries: 2` by default); each retry is a real request —
227
+ // it costs latency and, against a real provider, tokens — so each is
228
+ // its own pair, each carrying the error. 1.x does not retry.
229
+ const attempts = fixture === "mastra-0" ? 3 : 1;
230
+ expect(shape(result.events), describeTrace(result)).toEqual([
231
+ "weather-agent agent_start",
232
+ ...Array.from({ length: attempts }, () => [
233
+ "weather-agent model_request",
234
+ "weather-agent model_response",
235
+ ]).flat(),
236
+ "weather-agent agent_end",
237
+ ]);
238
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
239
+ for (const response of ofType(result.events, "model_response")) {
240
+ expect(String(response.error)).toMatch(/model exploded/);
241
+ }
242
+ expect(ofType(result.events, "agent_end")[0]!.outcome).toBe("failed");
243
+ expect(count(result.events, "error")).toBe(0);
244
+ });
245
+ }
246
+
247
+ it("nests the agent under an enclosing agent() scope", () => {
248
+ const result = run("scope");
249
+ expect(shape(result.events), describeTrace(result)).toEqual([
250
+ "planner agent_start",
251
+ ...LOOP,
252
+ "planner agent_end",
253
+ ]);
254
+ expect(new Set(result.events.map((e) => e.session_id))).toEqual(new Set(["req-1"]));
255
+ expect(ofType(result.events, "agent_start")[1]!.parent_id).toBe("planner");
256
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
257
+ });
258
+
259
+ it("records nothing after uninstrument()", () => {
260
+ const result = run("uninstrument");
261
+ expect(result.events, describeTrace(result)).toEqual([]);
262
+ expect(result.stdout).toContain('"removed":["mastra"]');
263
+ });
264
+
265
+ // uninstrument() does not reach what an instrumented run already built —
266
+ // a model behind a proxy, tools behind wrappers, a stream the caller is
267
+ // still reading — so each of these runs inside a session scope, where a
268
+ // stray event would have somewhere to land instead of being dropped.
269
+
270
+ it("stops a stream in flight at uninstrument(), closing its agent cancelled", () => {
271
+ const result = run("uninstrument-midstream");
272
+ expect(result.stdout).toContain('"removed":["mastra"]');
273
+ // The stream is the caller's: it runs to the end, tool call and all.
274
+ expect(result.stdout).toContain("It is sunny in Paris.");
275
+ expect(shape(result.events), describeTrace(result)).toEqual([
276
+ "weather-agent agent_start",
277
+ "weather-agent model_request",
278
+ "weather-agent model_response",
279
+ "weather-agent agent_end",
280
+ ]);
281
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
282
+ const response = ofType(result.events, "model_response")[0]!;
283
+ expect(response.stop_reason).toBe("incomplete");
284
+ expect(response.fw_incomplete).toBe(true);
285
+ expect(ofType(result.events, "agent_end")[0]!.outcome).toBe("cancelled");
286
+ });
287
+
288
+ it("records nothing from an Agent reused after uninstrument()", () => {
289
+ const result = run("uninstrument-reuse");
290
+ expect(result.stdout).toContain('"answers":["It is sunny in Paris.","It is sunny in Paris."]');
291
+ expect(shape(result.events), describeTrace(result)).toEqual(LOOP);
292
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
293
+ });
294
+
295
+ it("records a run once after instrument() → uninstrument() → instrument()", () => {
296
+ const result = run("reinstrument");
297
+ expect(result.stdout).toContain('"removed":["mastra"]');
298
+ expect(shape(result.events), describeTrace(result)).toEqual(LOOP);
299
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
300
+ });
301
+
302
+ it("records an Agent reused across uninstrument() → instrument() once per run", () => {
303
+ const result = run("reinstrument-reuse");
304
+ expect(shape(result.events), describeTrace(result)).toEqual([...LOOP, ...LOOP]);
305
+ expect(traceViolations(result.events), describeTrace(result)).toEqual([]);
306
+ const sessions = result.events.map((e) => e.session_id);
307
+ expect(new Set(sessions.slice(0, LOOP.length)).size).toBe(1);
308
+ expect(new Set(sessions.slice(LOOP.length)).size).toBe(1);
309
+ });
310
+ });
311
+ });
@@ -0,0 +1,341 @@
1
+ import { spawn, spawnSync, type ChildProcess } from "node:child_process";
2
+ import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync } from "node:fs";
3
+ import { createServer } from "node:net";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+
7
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
8
+
9
+ import { FIXTURES, describeTrace, runAgentAsync, traceViolations, type Event, type RunResult } from "./harness.js";
10
+ import { digest } from "./runtime-parity.js";
11
+
12
+ /**
13
+ * Next.js (App Router), the way it is deployed next to failproofaid: `next
14
+ * build`, then `next start` as a long-running server, `instrument()` called
15
+ * from `instrumentation.ts` — Next's documented startup hook.
16
+ *
17
+ * Each route runs the same program as a framework fixture's scenario (its
18
+ * "twin"), with the same scripted model; the trace the route leaves in the
19
+ * spool must equal the twin's trace under plain Node.
20
+ *
21
+ * ## Bundled or external — the question this file answers per framework
22
+ *
23
+ * Next 16's built-in `serverExternalPackages` list includes none of the four
24
+ * frameworks, so by DEFAULT every one of them is bundled into the server
25
+ * chunks: a copy that no `require`/`import` of `node_modules` can reach.
26
+ *
27
+ * * `ai` records through `instrument()` either way — ai 7 reads its
28
+ * telemetry integrations from a global, which the bundled copy reads too.
29
+ * * LangChain, Mastra and LlamaIndex record through `instrument()` ONLY when
30
+ * listed in `serverExternalPackages`. Bundled, `instrument()` returns their
31
+ * names and records NOTHING: it patched the `node_modules` copy, the routes
32
+ * run the bundled one. Asserted below as empty, so a change shows up.
33
+ * * The call-site helpers (`langchainHandler()`, `telemetry()`, Mastra
34
+ * `wrapTool()`) work in every configuration: they travel with the call.
35
+ *
36
+ * External packages are loaded by Next with `import()` (Turbopack and webpack
37
+ * alike) from a CommonJS launcher; before `appImportsReachCommonJs` the SDK
38
+ * patched the CommonJS copies there and even the external configuration
39
+ * recorded nothing for those three.
40
+ *
41
+ * Twin fixtures (langchain-1, ai-7, mastra-1, llamaindex-0.12) must be
42
+ * installed alongside `nextjs`: `FAILPROOFAI_IT_FIXTURES=nextjs,langchain-1,ai-7,mastra-1,llamaindex-0.12`.
43
+ */
44
+
45
+ const APP = join(FIXTURES, "nextjs");
46
+ const NEXT = join(APP, "node_modules", "next", "dist", "bin", "next");
47
+
48
+ interface Variant {
49
+ name: string;
50
+ dist: string;
51
+ bundler: "turbopack" | "webpack";
52
+ external: boolean;
53
+ /** Built with `withFailproofai(config)` instead of a hand-written list. */
54
+ wrapped?: boolean;
55
+ }
56
+
57
+ const VARIANTS: Variant[] = [
58
+ { name: "turbopack, default config (frameworks bundled)", dist: ".next-it-turbopack", bundler: "turbopack", external: false },
59
+ { name: "turbopack, frameworks in serverExternalPackages", dist: ".next-it-turbopack-external", bundler: "turbopack", external: true },
60
+ { name: "webpack, default config (frameworks bundled)", dist: ".next-it-webpack", bundler: "webpack", external: false },
61
+ { name: "webpack, frameworks in serverExternalPackages", dist: ".next-it-webpack-external", bundler: "webpack", external: true },
62
+ { name: "turbopack, withFailproofai(nextConfig)", dist: ".next-it-turbopack-wrapped", bundler: "turbopack", external: true, wrapped: true },
63
+ ];
64
+
65
+ const nextEnv = (variant: Variant): Record<string, string> => ({
66
+ NEXT_TELEMETRY_DISABLED: "1",
67
+ FAILPROOFAI_IT_NEXT_DIST: variant.dist,
68
+ FAILPROOFAI_IT_NEXT_EXTERNAL: variant.external && !variant.wrapped ? "1" : "",
69
+ FAILPROOFAI_IT_NEXT_WRAP: variant.wrapped ? "1" : "",
70
+ // A hand-written list carries no marker, so the documented override tells
71
+ // `instrument()` the app is configured. The wrapper needs none: it records
72
+ // what it externalized when Next evaluates the config.
73
+ FAILPROOFAI_NEXT_EXTERNALS: variant.external && !variant.wrapped ? "1" : "",
74
+ });
75
+
76
+ async function freePort(): Promise<number> {
77
+ return await new Promise((resolvePort, reject) => {
78
+ const server = createServer();
79
+ server.once("error", reject);
80
+ server.listen(0, "127.0.0.1", () => {
81
+ const address = server.address();
82
+ server.close(() => resolvePort(typeof address === "object" && address !== null ? address.port : 0));
83
+ });
84
+ });
85
+ }
86
+
87
+ const sleep = (ms: number) => new Promise<void>((resolveSleep) => setTimeout(resolveSleep, ms));
88
+
89
+ /** Reads only the spool files that appeared since the last call. */
90
+ class Spool {
91
+ private seen = new Set<string>();
92
+ constructor(readonly dir: string) {}
93
+
94
+ private fresh(): string[] {
95
+ if (!existsSync(this.dir)) return [];
96
+ return readdirSync(this.dir)
97
+ .filter((name) => name.endsWith(".jsonl") && !this.seen.has(name))
98
+ .sort();
99
+ }
100
+
101
+ /** Wait for the request's events to land and stop arriving, then take them. */
102
+ async take(options: { expectNone?: boolean } = {}): Promise<Event[]> {
103
+ const deadline = Date.now() + 20_000;
104
+ let lastCount = -1;
105
+ let stableSince = Date.now();
106
+ // Four flush intervals with nothing new is "done"; for a case expected to
107
+ // record nothing, that same quiet period is the whole wait.
108
+ const quiet = 2_000;
109
+ for (;;) {
110
+ const count = this.fresh().length;
111
+ if (count !== lastCount) {
112
+ lastCount = count;
113
+ stableSince = Date.now();
114
+ }
115
+ if ((count > 0 || options.expectNone) && Date.now() - stableSince >= quiet) break;
116
+ if (Date.now() > deadline) break;
117
+ await sleep(200);
118
+ }
119
+ const events: Event[] = [];
120
+ for (const name of this.fresh()) {
121
+ this.seen.add(name);
122
+ for (const line of readFileSync(join(this.dir, name), "utf8").split("\n")) {
123
+ if (line.trim()) events.push(JSON.parse(line) as Event);
124
+ }
125
+ }
126
+ return events.sort((a, b) => String(a.timestamp).localeCompare(String(b.timestamp)));
127
+ }
128
+ }
129
+
130
+ /** Twins run once per file: the same scenario always yields the same trace. */
131
+ const twins = new Map<string, Promise<RunResult>>();
132
+ function twin(fixture: string, scenario: string): Promise<RunResult> {
133
+ const key = `${fixture}:${scenario}`;
134
+ if (!twins.has(key)) {
135
+ if (!existsSync(join(FIXTURES, fixture, ".run", "agent.mjs"))) {
136
+ throw new Error(`twin fixture ${fixture} is not installed; add it to FAILPROOFAI_IT_FIXTURES`);
137
+ }
138
+ twins.set(key, runAgentAsync(fixture, "esm", scenario));
139
+ }
140
+ return twins.get(key)!;
141
+ }
142
+
143
+ const asTrace = (events: Event[], stderr = ""): RunResult => ({ events, stdout: "", stderr, status: 0 });
144
+
145
+ describe.each(VARIANTS)("Next.js 16, $name", (variant) => {
146
+ let server: ChildProcess | null = null;
147
+ let base = "";
148
+ let home = "";
149
+ let spool: Spool;
150
+ let stderr = "";
151
+
152
+ beforeAll(async () => {
153
+ // Build from scratch. The harness extracts the freshly PACKED SDK into
154
+ // node_modules, and `npm pack` stamps every file with the same fixed mtime —
155
+ // so webpack's persistent cache (in the distDir) saw an unchanged SDK and
156
+ // kept compiling the previous run's copy into the bundle. Turbopack hashes
157
+ // content and was not fooled; webpack silently tested stale SDK code.
158
+ rmSync(join(APP, variant.dist), { recursive: true, force: true });
159
+ const args = [NEXT, "build", ...(variant.bundler === "webpack" ? ["--webpack"] : [])];
160
+ const build = spawnSync(process.execPath, args, {
161
+ cwd: APP,
162
+ encoding: "utf8",
163
+ env: { ...process.env, ...nextEnv(variant), NODE_OPTIONS: "" },
164
+ timeout: 600_000,
165
+ });
166
+ if (build.status !== 0) {
167
+ throw new Error(`next build failed (${variant.name}):\n${build.stdout}\n${build.stderr}`);
168
+ }
169
+
170
+ home = mkdtempSync(join(tmpdir(), "failproofai-it-nextjs-"));
171
+ spool = new Spool(join(home, "custom-agents", "events"));
172
+ const port = await freePort();
173
+ base = `http://127.0.0.1:${port}`;
174
+ server = spawn(process.execPath, [NEXT, "start", "-p", String(port), "-H", "127.0.0.1"], {
175
+ cwd: APP,
176
+ stdio: ["ignore", "pipe", "pipe"],
177
+ env: {
178
+ ...process.env,
179
+ ...nextEnv(variant),
180
+ NODE_OPTIONS: "",
181
+ FAILPROOFAI_HOME: home,
182
+ FAILPROOFAI_SDK_STRICT: "1",
183
+ },
184
+ });
185
+ server.stdout!.on("data", (chunk: Buffer) => (stderr += chunk.toString()));
186
+ server.stderr!.on("data", (chunk: Buffer) => (stderr += chunk.toString()));
187
+ for (let i = 0; i < 150; i += 1) {
188
+ try {
189
+ if ((await fetch(`${base}/api/status`)).ok) return;
190
+ } catch {
191
+ /* not up yet */
192
+ }
193
+ await sleep(200);
194
+ }
195
+ throw new Error(`next start never answered:\n${stderr}`);
196
+ });
197
+
198
+ afterAll(async () => {
199
+ if (server !== null) {
200
+ server.kill("SIGTERM");
201
+ await new Promise((resolveExit) => server!.once("exit", resolveExit));
202
+ }
203
+ if (home) rmSync(home, { recursive: true, force: true });
204
+ });
205
+
206
+ /** GET a route (reading the whole body, as a client does) and take its trace. */
207
+ const call = async (path: string, options: { expectNone?: boolean } = {}) => {
208
+ const response = await fetch(`${base}${path}`);
209
+ const body = await response.text();
210
+ expect(response.status, body).toBe(200);
211
+ return { body, events: await spool.take(options) };
212
+ };
213
+
214
+ const expectTwin = async (events: Event[], fixture: string, scenario: string) => {
215
+ const expected = await twin(fixture, scenario);
216
+ expect(expected.status, describeTrace(expected)).toBe(0);
217
+ const context = `NEXT (${variant.name})\n${describeTrace(asTrace(events, stderr))}\n\nTWIN ${fixture} ${scenario}\n${describeTrace(expected)}`;
218
+ let got = events;
219
+ let want = expected.events;
220
+ if (fixture.startsWith("langchain")) {
221
+ // KNOWN ADAPTER ISSUE, pinned so its fix shows up: for a chat model with
222
+ // no model-name parameter the LangChain adapter falls back to the model's
223
+ // CLASS name, and Next minifies the app's classes — `ScriptedModel`
224
+ // arrives as `d` or `v5`. The rest of the trace must still match.
225
+ const models = (list: Event[]) =>
226
+ [...new Set(list.filter((e) => e.type.startsWith("model_")).map((e) => e.model))];
227
+ expect(models(want)).toEqual(["ScriptedModel"]);
228
+ expect(models(got), context).not.toEqual(["ScriptedModel"]);
229
+ const mask = (list: Event[]) => list.map((e) => (e.type.startsWith("model_") ? { ...e, model: "<class>" } : e));
230
+ got = mask(got);
231
+ want = mask(want);
232
+ }
233
+ expect(digest(got), context).toEqual(digest(want));
234
+ expect(traceViolations(events), context).toEqual([]);
235
+ };
236
+
237
+ it("runs instrument() from instrumentation.ts before the first request", async () => {
238
+ const status = (await (await fetch(`${base}/api/status`)).json()) as { instrumented: string[] | null };
239
+ expect(status.instrumented).toEqual(["ai", "langchain", "llamaindex", "mastra"]);
240
+ });
241
+
242
+ describe("call-site helpers work whether the framework is bundled or not", () => {
243
+ it("LangGraph with langchainHandler()", async () => {
244
+ const { body, events } = await call("/api/langgraph?mode=handler");
245
+ expect(body).toContain("It is sunny in Paris.");
246
+ await expectTwin(events, "langchain-1", variant.external ? "handler-and-instrument" : "handler");
247
+ });
248
+
249
+ it("ai generateText with telemetry()", async () => {
250
+ const { body, events } = await call("/api/ai?mode=telemetry");
251
+ expect(body).toContain("It is 20C in Paris.");
252
+ await expectTwin(events, "ai-7", "generate");
253
+ });
254
+
255
+ it("ai streamText with telemetry(), returned as toUIMessageStreamResponse()", async () => {
256
+ const { body, events } = await call("/api/ai?mode=stream");
257
+ expect(body).toContain('"type":"finish"');
258
+ await expectTwin(events, "ai-7", "stream");
259
+ });
260
+
261
+ it("Mastra wrapTool()", async () => {
262
+ const { body, events } = await call("/api/mastra?mode=wraptool");
263
+ expect(body).toContain("sunny");
264
+ await expectTwin(events, "mastra-1", "wraptool");
265
+ });
266
+
267
+ it("a server action running an agent", async () => {
268
+ const manifest = JSON.parse(
269
+ readFileSync(join(APP, variant.dist, "server", "server-reference-manifest.json"), "utf8"),
270
+ ) as { node: Record<string, { exportedName?: string }> };
271
+ const id = Object.entries(manifest.node).find(([, entry]) => entry.exportedName === "askWeather")?.[0];
272
+ expect(id, "askWeather is in the server-reference manifest").toBeDefined();
273
+ const response = await fetch(`${base}/`, {
274
+ method: "POST",
275
+ headers: { "Next-Action": id!, "Content-Type": "text/plain;charset=UTF-8", Accept: "text/x-component" },
276
+ body: "[]",
277
+ });
278
+ expect(await response.text()).toContain("It is 20C in Paris.");
279
+ await expectTwin(await spool.take(), "ai-7", "generate");
280
+ });
281
+ });
282
+
283
+ describe("instrument()", () => {
284
+ it("records the Vercel AI SDK, bundled or not", async () => {
285
+ await expectTwin((await call("/api/ai?mode=instrument")).events, "ai-7", "instrument");
286
+ await expectTwin((await call("/api/ai?mode=instrument-stream")).events, "ai-7", "instrument-stream");
287
+ });
288
+
289
+ const patched: Array<[string, string, string, string]> = [
290
+ ["LangGraph", "/api/langgraph?mode=instrument", "langchain-1", "graph"],
291
+ ["a Mastra agent", "/api/mastra?mode=instrument", "mastra-1", "generate"],
292
+ ["a LlamaIndex agent workflow", "/api/llamaindex", "llamaindex-0.12", "workflow"],
293
+ ];
294
+ if (variant.external) {
295
+ it.each(patched)("records %s when it is in serverExternalPackages", async (_label, path, fixture, scenario) => {
296
+ await expectTwin((await call(path)).events, fixture, scenario);
297
+ });
298
+ } else {
299
+ it.each(patched)(
300
+ "records NOTHING for %s when Next bundles it — the known limitation",
301
+ async (_label, path) => {
302
+ const { body, events } = await call(path, { expectNone: true });
303
+ expect(body).toContain("sunny");
304
+ expect(events, describeTrace(asTrace(events, stderr))).toEqual([]);
305
+ },
306
+ );
307
+ }
308
+ });
309
+
310
+ it("serves an Edge-runtime route that imports the SDK: its no-op build, announced once, nothing recorded", async () => {
311
+ const { body, events } = await call("/api/edge", { expectNone: true });
312
+ expect(JSON.parse(body)).toEqual({ imported: true, emitted: true, flushed: true });
313
+ expect(events).toEqual([]);
314
+ expect(stderr.match(/loaded its no-op build/g) ?? []).toHaveLength(1);
315
+ });
316
+
317
+ it("warns for each adapter Next bundles, and otherwise prints nothing from the SDK", () => {
318
+ const lines = stderr
319
+ .split("\n")
320
+ .filter((line) => line.includes("[failproofai-sdk]") && !line.includes("loaded its no-op build"));
321
+ const warned = lines
322
+ .map((line) => /instrument\("([a-z]+)"\) is running under Next\.js/.exec(line)?.[1])
323
+ .filter((name): name is string => name !== undefined)
324
+ .sort();
325
+ // Bundled: exactly the three adapters that cannot reach a bundled copy,
326
+ // each once, naming the wrapper. Never the Vercel AI SDK, which records
327
+ // bundled or not. Configured (wrapper or hand-written list + override):
328
+ // silence.
329
+ expect(warned, stderr).toEqual(variant.external ? [] : ["langchain", "llamaindex", "mastra"]);
330
+ if (!variant.external) {
331
+ for (const line of lines) expect(line).toContain("withFailproofai");
332
+ }
333
+ expect(lines.length, stderr).toBe(warned.length);
334
+ // Loading a second copy of LlamaIndex beside the one the app runs makes
335
+ // LlamaIndex itself warn. External: the SDK patches the app's own copy, so
336
+ // there is no second one. Bundled: `instrument()` loads the node_modules
337
+ // copy the bundle never uses — LlamaIndex notices, and says so.
338
+ const doubled = stderr.includes("llamaindex was already imported");
339
+ expect(doubled, stderr).toBe(!variant.external);
340
+ });
341
+ });