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,568 @@
1
+ # TypeScript and JavaScript agents — `@failproofai/sdk`
2
+
3
+ Everything in `SKILL.md` §2 (plan) and §6 (production) applies unchanged. The
4
+ TypeScript SDK writes the **same 15 events, the same wire format, into the same
5
+ spool directory** as the Python one, and `failproofaid` ships both. A fleet running
6
+ both languages writes into one pipe, and the dashboard cannot tell which language
7
+ wrote what. This page is what differs: install, names, adapters, bundlers, runtimes,
8
+ shutdown and verification.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @failproofai/sdk # or: pnpm add / yarn add / bun add
14
+ ```
15
+
16
+ Node ≥ 20.9, Bun, or Deno (`npm:@failproofai/sdk`). ES modules and CommonJS both
17
+ work. It has zero runtime dependencies. The framework packages are optional peer
18
+ dependencies, loaded only when you ask for them.
19
+
20
+ ```ts
21
+ import * as failproofai from "@failproofai/sdk"; // ESM
22
+ // const failproofai = require("@failproofai/sdk"); // CommonJS
23
+ ```
24
+
25
+ Confirm what you have:
26
+
27
+ ```bash
28
+ node -e 'console.log(require("@failproofai/sdk").version)'
29
+ ```
30
+
31
+ | Import | What it holds |
32
+ |---|---|
33
+ | `@failproofai/sdk` | scopes, `event.*`, `configure`, `flush`/`flushSync`, `instrument`/`uninstrument` |
34
+ | `@failproofai/sdk/langchain` | `langchainHandler()` — a callback handler, no patching |
35
+ | `@failproofai/sdk/ai` | `telemetry()`, `wrapModel()` for the Vercel AI SDK |
36
+ | `@failproofai/sdk/mastra` | `wrapTool()`, `workflow()` |
37
+ | `@failproofai/sdk/llamaindex` | the adapter's internals — nothing to import; use `instrument("llamaindex", { … })` |
38
+ | `@failproofai/sdk/next` | `withFailproofai()` for `next.config` |
39
+ | `@failproofai/sdk/evaluator` | the evaluator worker — see `evaluator.md` |
40
+
41
+ The root import deliberately does not re-export the subpaths.
42
+
43
+ ## Names: camelCase in, snake_case on the wire
44
+
45
+ Every Python name has a camelCase twin, and the file on disk is identical:
46
+
47
+ | Python | TypeScript |
48
+ |---|---|
49
+ | `failproofai_sdk.agent("x", goal=g)` | `failproofai.agent("x", { goal: g }, fn)` |
50
+ | `failproofai_sdk.tool_call(...)` | `failproofai.toolCall(name, { toolCallId, input }, fn)` |
51
+ | `failproofai_sdk.session(session_id=...)` | `failproofai.session({ sessionId }, fn)` |
52
+ | `event.tool_use(tool_name=, tool_call_id=)` | `event.toolUse({ toolName, toolCallId })` |
53
+ | `event.model_response(input_tokens=, stop_reason=, request_id=)` | `event.modelResponse({ inputTokens, stopReason, requestId })` |
54
+ | `event.error(error_type=, message=)` | `event.error({ errorType, message })` |
55
+ | `event.human_wait(input_id=)` / `agent_pause(pause_id=)` / `hook_triggered(hook_id=, trigger_event=)` | `inputId` / `pauseId` / `hookId`, `triggerEvent` |
56
+ | `configure(base_dir=, flush_interval=, environment=)` | `configure({ baseDir, flushInterval, environment })` |
57
+ | `failproofai_sdk._writer.flush_now()` | `await failproofai.flush()` / `failproofai.flushSync()` |
58
+ | `propagate(fn)` | `propagate(fn)` |
59
+
60
+ **Only declared option names are camelCase.** Any other key is a custom payload
61
+ field and is written **verbatim**, so `duration_ms` stays `duration_ms`. A camelCase
62
+ typo of a declared name (`toolCallID`) is not an error: it becomes a new field, and
63
+ nothing tells you.
64
+
65
+ ## The contract, in TypeScript
66
+
67
+ `SKILL.md` §3 holds, with these spellings:
68
+
69
+ - **Identity is ambient.** It rides on `AsyncLocalStorage`, so it follows `await`,
70
+ `.then()`, timers and callbacks created inside the scope. Two concurrent runs in
71
+ one process never mix. A callback **stored** in one run and invoked from another
72
+ does not inherit it: wrap it with `failproofai.propagate(fn)`.
73
+ - **No session bound and none passed throws `TypeError`** from `event.*` and
74
+ `toolCall()`. `agent()` and `session()` mint a fresh session instead. A non-string id also
75
+ throws `TypeError`. An empty or whitespace id throws `Error`. `agentId` falls back
76
+ to `"main"`.
77
+ - **A reserved extra throws.** `timestamp`, `session_id`, `agent_id`, `type` and
78
+ `environment` cannot be custom fields.
79
+ - **Token counts must be integers.** `inputTokens: 12.5` throws `TypeError`.
80
+ `null` is fine: the key is omitted.
81
+ - **`duration_ms` is refused on the four paired closers**: `toolResult`,
82
+ `hookCompleted`, `humanInput` and `agentResume`. They compute it. On every other
83
+ method, including `modelResponse`, it is accepted as a custom field, and that is
84
+ how you time a model call yourself.
85
+ - **`configure()`**: call it once, at startup, before the first event.
86
+ - Omitted options reset to their defaults.
87
+ - Nothing is applied unless every option validates.
88
+ - A comma in `environment` throws.
89
+ - A comma in `AGENTEYE_ENVIRONMENT` does not throw. It warns and falls back to
90
+ `"dev"`.
91
+ - `environment` and `baseDir` apply to the whole process — every copy of the
92
+ SDK loaded into it (the ESM and CommonJS builds, or a copy a bundler put in a
93
+ Next.js route) — so configure once, anywhere at startup.
94
+ - **`environment` defaults to `"dev"`.** Set it in `configure` or with
95
+ `AGENTEYE_ENVIRONMENT`.
96
+ - **Scope outcomes**:
97
+ - The body returned: `agent_end` with `outcome: "success"`.
98
+ - The body threw: `error`, then `agent_end` with `outcome: "failed"`.
99
+ - An `AbortError`: `agent_end` with `outcome: "cancelled"`.
100
+
101
+ The error is always rethrown. A tool failure is recorded on its `tool_result` and
102
+ emits no run-level `error`.
103
+ - **`error_type` is the error's class.** When an error's `name` is just `"Error"`
104
+ (openai's `BadRequestError`, many SDK errors) the class name is recorded instead.
105
+ - **Timestamps order events within a millisecond.** The last three of the six
106
+ fractional digits are a per-process sequence, not a measurement, so events
107
+ emitted in the same millisecond still sort in the order they happened.
108
+ - **Unencodable values never take the process down.** Circular references,
109
+ `BigInt`, throwing getters and lone surrogates are handled. One bad event is
110
+ dropped alone, not the batch around it.
111
+ - **Credentials are redacted before the bytes reach disk.** That covers API keys,
112
+ tokens, JWTs and bearer headers.
113
+ - **The SDK's own warnings go to stderr, prefixed `[failproofai-sdk]`.**
114
+ - Route them with `failproofai.setLogger({ debug, info, warn, error })`.
115
+ - Set verbosity with `FAILPROOFAI_SDK_LOG_LEVEL`: `debug`, `info`, `warn`
116
+ (the default), `error` or `silent`.
117
+ - `FAILPROOFAI_SDK_STRICT=1` makes a swallowed adapter failure throw.
118
+
119
+ ## Shutdown — the part that loses data
120
+
121
+ - **A normal exit is covered.** Buffered events flush on `process.on("exit")`, and
122
+ the flush timer is `unref`'d, so importing the SDK never keeps a script alive.
123
+ - **Short-lived work that returns rather than exits** — a serverless handler, a
124
+ queue job in a long-lived worker — should `await failproofai.flush()` before
125
+ returning: the process lives on, so no exit flush comes.
126
+ - **Signals.** `SIGTERM` (every deploy, `docker stop`, a Kubernetes eviction) kills
127
+ Node **without** running exit handlers. The SDK will not install a signal handler
128
+ in your process (that would change what Ctrl-C does), so add one at startup:
129
+
130
+ ```ts
131
+ for (const [signal, code] of [["SIGINT", 130], ["SIGTERM", 143]] as const) {
132
+ process.once(signal, () => {
133
+ failproofai.flushSync();
134
+ process.exit(code); // 128 + signal number: the orchestrator sees a termination, not a success
135
+ });
136
+ }
137
+ ```
138
+
139
+ On the way out the SDK **closes whatever is still open**, most recently opened
140
+ first — including what an adapter opened: an interrupted tool gets its
141
+ `tool_result`, a hook its `hook_completed`, a model call its `model_response`
142
+ (`stop_reason: "error"`), each with a `ProcessExit: …` error, and each open agent
143
+ gets an `error` event and `agent_end` with `outcome: "failed"`. So a deploy never
144
+ leaves a run showing as running forever. (Python gets the same through
145
+ `SystemExit` unwinding.) A `flushSync()` while the process carries on closes
146
+ nothing, and a run paused on a human is left open for whoever resumes it.
147
+ - **Every exit path, not just signals.** The same closing happens on an uncaught
148
+ exception or unhandled rejection (the message names it — `… on an uncaught
149
+ QuotaError: …`), on `process.exit()` from anywhere, and when the event loop
150
+ drains with a run still pending. A run still open when the process ends is a
151
+ failed run, whatever the exit code.
152
+ - **Your own records.** `process.exit()` in that handler skips your code's
153
+ `catch`/`finally`, so a job that records its own result (a database row, a
154
+ status file) should record "interrupted" in the handler too, before
155
+ `flushSync()` — or the dashboard shows a failed run your own store never heard of.
156
+ - **Run `node` directly in services and containers.** `npx tsx` does not pass
157
+ SIGTERM on to the program, which then runs on, finishes, and records `success`
158
+ for a job that was killed. Use `node --import tsx app.ts`, or compile.
159
+ - **Next.js:** put that handler in its own module and import it from
160
+ `instrumentation.ts` behind the runtime check (see *Next.js* below) — `process.once`
161
+ in `instrumentation.ts` itself makes Turbopack warn about the Edge runtime.
162
+
163
+ ## A framework agent — turn it on
164
+
165
+ ```ts
166
+ import * as failproofai from "@failproofai/sdk";
167
+
168
+ failproofai.configure({ environment: "production" });
169
+ await failproofai.instrument("langchain"); // name the framework you use
170
+ ```
171
+
172
+ | Framework | Tested range | How it attaches |
173
+ |---|---|---|
174
+ | LangChain.js / LangGraph.js | `@langchain/core` 0.3 – 1.x, LangGraph 0.4 – 1.x | global callback configuration — no `callbacks:` needed. Or pass `langchainHandler()` yourself and patch nothing |
175
+ | Vercel AI SDK | `ai` 4 – 7 | `telemetry()` at the call site (every major); `instrument("ai")` process-wide on `ai` 7 only |
176
+ | Mastra | `@mastra/core` 0.20 – 1.x | `Agent.generate`/`.stream`, tool resolution, the workflow engine |
177
+ | LlamaIndex.TS | `llamaindex` 0.11.4 – 0.x | `Settings.callbackManager` plus `AgentWorkflow.runStream` |
178
+
179
+ **`instrument()` — the rules:**
180
+
181
+ - **Await it, before the first run.** An unawaited `instrument()` may happen to
182
+ work when the first run starts late — which is why it passes a local test and
183
+ fails under load. When it loses the race it does not record nothing; it records a
184
+ *wrong* trace: the root run starts before the adapter
185
+ exists, so a graph node, a tool or a bare model call becomes the session's agent,
186
+ or each becomes its own one-call session. The LangChain adapter warns when it sees
187
+ this (`… started under a parent run the langchain adapter never saw …`); the
188
+ others cannot tell it apart from a bare call.
189
+ - **Name the framework.** A bare `instrument()` patches *every* supported framework
190
+ that resolves from the project — including ones installed but unused, and ones
191
+ resolving from a parent directory's `node_modules`. It resolves to the names it
192
+ instrumented, and `[]` plus a warning when it found nothing. An unknown name throws.
193
+ - **Options** go in the second argument, `instrument("<name>", { … })`:
194
+
195
+ | Adapter | Options |
196
+ |---|---|
197
+ | `langchain` | `sessionId`, `captureContent` (default `true`), `includeChains`, `graphCallbacks`, `captureLimit` — also accepted by `langchainHandler({ … })` |
198
+ | `llamaindex` | `captureMessages` (default `true`), `steps` (default `true`; `false` drops the workflow-step hooks), `embeddings`, `staleAfter`, `reaperInterval`, `captureLimit` |
199
+ | `ai` | `registerGlobalTracer` (ai 4–6 only, see below), `captureLimit` |
200
+ | `mastra` | `captureLimit` |
201
+
202
+ Content capture is **on** by default: a LangGraph node's `hook_triggered` carries
203
+ the message history as `input`, and a hand-written `model_request` carries what
204
+ you pass. `captureContent: false` / `captureMessages: false` keep structure,
205
+ durations and tokens and drop the text.
206
+
207
+ **The mapping is the Python SDK's.** An **agent** is anything that owns an LLM
208
+ decision loop: a graph or chain run, `generateText`/`streamText`, a Mastra agent or
209
+ workflow, a LlamaIndex agent run. A LangGraph node or a workflow step is a **hook**
210
+ (`hook_triggered`/`hook_completed` with a `trigger_event`), never a nested agent.
211
+ Model pairs carry token counts; tool pairs carry the model's own tool-call id. A
212
+ failure is recorded once, where it happened — a tool that throws is an `error` on its
213
+ `tool_result`, and if the model then recovers the run still ends `success`.
214
+
215
+ ### Naming the agent, and owning the session id
216
+
217
+ `agent_id` is the facet every dashboard view groups by, and each framework takes it
218
+ from a different place. Set it, or you get the framework's default:
219
+
220
+ | Framework | `agent_id` comes from | Default when unset |
221
+ |---|---|---|
222
+ | LangGraph / LangChain | the root run's name: `createReactAgent({ name })`, or `.withConfig({ runName })` on a compiled graph | `"LangGraph"` |
223
+ | Vercel AI SDK | `functionId` in the call's telemetry settings — `telemetry({ functionId })`. An agent class's own `id` (`ToolLoopAgent({ id })`) is **not** passed through | `"ai.generateText"` / `"ai.streamText"` |
224
+ | Mastra | the agent's `name` (not its `id`, not its registration key). A workflow run is rooted under the **workflow's** id, with the agent nested under it | — |
225
+ | LlamaIndex.TS | `agent({ name })` | the class or operation name |
226
+
227
+ Mastra's `tool_name` is the key in the agent's `tools` map, not the `createTool` id.
228
+
229
+ An adapter mints a random session id when nothing is bound, and nothing reads it
230
+ back to you. To use your own — a request or job id, so a dashboard session and your
231
+ own logs or database share it — bind it around the framework call:
232
+
233
+ ```ts
234
+ await failproofai.session({ sessionId: requestId }, () => graph.invoke(input));
235
+ ```
236
+
237
+ `session()` emits nothing; each framework run inside it is its own agent — so
238
+ three AI SDK calls under one `session()` are three agents in one session. Wrapping in
239
+ `agent()` also works: under the **same** name as the framework agent it becomes that
240
+ agent (one `agent_start`, and every call inside joins it — how several AI SDK
241
+ calls become one agent); under a **different** name the framework agent nests
242
+ under yours (`parent_id` = your name), which is right when your wrapper is a real
243
+ outer agent. A joined agent's `agent_start` is yours, so put the `goal` on it. Inside either, `failproofai.current().sessionId` is the id.
244
+
245
+ Two consequences of owning it: a **retried** job that reuses its job id lands in the
246
+ **same** session, as a second run in it — append the attempt (`${jobId}-2`) if you
247
+ want retries separate. And LangChain also accepts it per call, as
248
+ `metadata: { failproofai_sdk_session_id }`.
249
+
250
+ ### Per framework
251
+
252
+ - **Vercel AI SDK.** `telemetry()` at each call site works on every major and is the
253
+ one way to name the agent. On `ai` 7, `instrument("ai")` covers every call in the
254
+ process too; using both does not double-record.
255
+
256
+ ```ts
257
+ import { telemetry } from "@failproofai/sdk/ai";
258
+
259
+ await generateText({
260
+ model,
261
+ prompt,
262
+ telemetry: telemetry({ functionId: "answer-question" }), // ai 4–6: `experimental_telemetry:`
263
+ });
264
+ ```
265
+
266
+ On `ai` 4–6, `instrument("ai")` records nothing by itself and warns: the only
267
+ process-wide hook there is the global OpenTelemetry tracer, and taking it would
268
+ break the app's own tracing. `instrument("ai", { registerGlobalTracer: true })`
269
+ opts in when the process runs no OpenTelemetry of its own. An agent class takes
270
+ it the same way — `new ToolLoopAgent({ model, tools, telemetry: telemetry({
271
+ functionId: "ai-research" }) })` — since its own `id` is not passed through.
272
+ `await wrapModel(model)`
273
+ (async — pass the resolved model) records model calls only; tools run above the
274
+ model layer. In a route handler on `ai` 7, pass `abortSignal: request.signal` so a
275
+ client that disconnects mid-stream closes the run instead of leaving it open.
276
+ - **Mastra.** `instrument("mastra")` is enough for agents on a `Mastra` instance,
277
+ their tools, and workflows. `wrapTool(tool)` is only for a tool called directly —
278
+ from your own code or a workflow step, not by an agent; `workflow(name, body)` only
279
+ groups work that is not a Mastra workflow under one named span.
280
+ - **LlamaIndex.TS.** A tool or LLM call made *outside* an agent workflow is recorded
281
+ as its own one-call run — that is how bare calls are shown, not a bug. Its
282
+ `openai()` client sends `temperature: 0.1` by default, which some models reject
283
+ with a 400 that crashes the workflow; set `temperature` on `openai({ … })` then.
284
+
285
+ **Token counts — set usage on the model client, or they are silently missing.**
286
+ OpenAI-compatible APIs report usage on a stream only when asked, and some framework
287
+ clients stream even for a non-streaming call:
288
+
289
+ | Framework | Where | Needed for |
290
+ |---|---|---|
291
+ | Vercel AI SDK + `@ai-sdk/openai-compatible` | `createOpenAICompatible({ …, includeUsage: true })` | `streamText` |
292
+ | Mastra (same provider package) | `createOpenAICompatible({ …, includeUsage: true })` | `.stream()` |
293
+ | LlamaIndex.TS | `openai({ …, additionalChatOptions: { stream_options: { include_usage: true } } })` | **every** agent run — its agent streams internally even for `run()` |
294
+
295
+ LangChain's `ChatOpenAI` already asks. For any other client, check for
296
+ `input_tokens`/`output_tokens` on each `model_response` when you verify.
297
+
298
+ ### Bundlers — the silent one
299
+
300
+ Most of these frameworks ship an ESM build and a CJS build. Node loads them as two
301
+ unrelated copies. The adapters patch the copy your app loads, plus a CJS copy that
302
+ something has already `require`d.
303
+
304
+ No adapter can reach a framework **bundled into your own output** (esbuild,
305
+ webpack, `ncc`). The copy in `node_modules` is not the one running, and nothing is
306
+ recorded. Either keep the framework external in the bundler config, or use the
307
+ call-site helpers, which work bundled: `langchainHandler()`, `telemetry()`,
308
+ `wrapTool()`.
309
+
310
+ ### Next.js
311
+
312
+ `next build` bundles server dependencies by default. Wrap the config, and configure
313
+ and instrument from Next's startup hook:
314
+
315
+ ```ts
316
+ // next.config.ts
317
+ import { withFailproofai } from "@failproofai/sdk/next";
318
+ export default withFailproofai({ /* your config */ });
319
+ ```
320
+
321
+ ```ts
322
+ // instrumentation.ts
323
+ export async function register() {
324
+ if (process.env.NEXT_RUNTIME !== "nodejs") return;
325
+ const failproofai = await import("@failproofai/sdk");
326
+ failproofai.configure({ environment: "production" });
327
+ await failproofai.instrument("langchain");
328
+ await import("./instrumentation-node"); // the signal handler from *Shutdown*
329
+ }
330
+ ```
331
+
332
+ - `withFailproofai` adds LangChain, Mastra, LlamaIndex and the SDK to
333
+ `serverExternalPackages` and keeps your own list. Without it, `instrument()` warns
334
+ when `next start` boots — not at `next build` — for each framework it cannot
335
+ reach, and those frameworks record nothing. If you list the packages by hand,
336
+ `FAILPROOFAI_NEXT_EXTERNALS=1` silences the warning.
337
+ - The Vercel AI SDK is not externalized and does not need to be: `telemetry()` and
338
+ `instrument("ai")` on `ai` 7 both work in a bundled route.
339
+ - `configure()` in `register()` applies to the whole server process, including a copy
340
+ of the SDK bundled into a route.
341
+ - Route handlers have no request id of their own: use the `x-request-id` header your
342
+ platform or proxy sets, with a fallback —
343
+ `session({ sessionId: request.headers.get("x-request-id") ?? randomUUID() }, …)`.
344
+ - Pass the request's signal down, so a client that disconnects ends the run
345
+ (`cancelled`) instead of it running on: `graph.invoke(input, { signal:
346
+ request.signal })` for LangGraph, `abortSignal: request.signal` for the AI SDK.
347
+ - **Edge runtimes** (Next.js Edge routes, workers) get a no-op build. Importing is
348
+ safe, and nothing is recorded there. Instrument the Node side.
349
+
350
+ ## An agent with no framework — three edit sites
351
+
352
+ This is the path for a hand-built loop: an OpenAI or Anthropic client, a `for` loop
353
+ and a tool table. It also covers any framework without an adapter, whatever else the
354
+ agent does, such as writing its own records to a database. You emit the events
355
+ yourself with the same API the adapters use, so the trace is the same shape — and,
356
+ if you record what the snippet below records, the same quality.
357
+
358
+ Every hand-built agent already has these three places, whatever its functions are
359
+ called. Find them in the codebase first:
360
+
361
+ | Where | Add | Emits |
362
+ |---|---|---|
363
+ | where **one run** starts and ends | `failproofai.agent("name", { goal }, async () => …)` | `agent_start` / `agent_end` |
364
+ | the **one function that calls the model** | `event.modelRequest` before, `event.modelResponse` after — **both halves, even on failure** | one pair per model turn |
365
+ | the **one function that runs tools** | `failproofai.toolCall(name, { toolCallId, input }, () => run())` | `tool_use` / `tool_result` |
366
+
367
+ ```ts
368
+ import { randomUUID } from "node:crypto";
369
+ import * as failproofai from "@failproofai/sdk";
370
+ import OpenAI from "openai";
371
+ import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";
372
+
373
+ // 1. the run — everything inside lands on this session, with no ids passed
374
+ const answer = await failproofai.agent("inventory", { goal: question }, async () => {
375
+ for (let turn = 0; turn < 6; turn++) {
376
+ const message = await callModel(messages);
377
+ const calls = (message.tool_calls ?? []).filter((c) => c.type === "function");
378
+ if (calls.length === 0) return message.content ?? "";
379
+ messages.push(message);
380
+ for (const call of calls) {
381
+ messages.push({ role: "tool", tool_call_id: call.id, content: await dispatch(call) });
382
+ }
383
+ }
384
+ return "(gave up)";
385
+ });
386
+
387
+ // 2. the model call — pair on requestId, time it yourself, close it on failure
388
+ async function callModel(messages: ChatCompletionMessageParam[]) {
389
+ const requestId = randomUUID();
390
+ const started = Date.now();
391
+ failproofai.event.modelRequest({
392
+ model: MODEL,
393
+ requestId,
394
+ // Role and content, plus the ids linking a tool result to its call. (openai's
395
+ // own message types do not satisfy the SDK's JSON types under `tsc --strict`.)
396
+ messages: messages.map((m) => ({
397
+ role: m.role,
398
+ content: typeof m.content === "string" ? m.content : m.content == null ? "" : JSON.stringify(m.content),
399
+ ...(m.role === "tool" ? { tool_call_id: m.tool_call_id } : {}),
400
+ ...(m.role === "assistant" && m.tool_calls
401
+ ? { tool_calls: m.tool_calls.map((c) => ({ id: c.id, name: c.type === "function" ? c.function.name : c.type })) }
402
+ : {}),
403
+ })),
404
+ // Tool and tool-call types are unions in openai ≥ 6 (custom tools): narrow them.
405
+ tools: TOOLS.flatMap((t) => (t.type === "function" ? [{ name: t.function.name, description: t.function.description ?? "" }] : [])),
406
+ });
407
+ let reply: OpenAI.Chat.Completions.ChatCompletion;
408
+ try {
409
+ // Only the provider call in the `try`: nothing else can reach the error path.
410
+ reply = await client.chat.completions.create({ model: MODEL, messages, tools: TOOLS });
411
+ } catch (error) {
412
+ failproofai.event.modelResponse({
413
+ model: MODEL,
414
+ requestId,
415
+ stopReason: "error",
416
+ error: error instanceof Error ? `${error.constructor.name}: ${error.message}` : String(error),
417
+ duration_ms: Date.now() - started,
418
+ });
419
+ throw error; // the enclosing agent() then ends "failed"
420
+ }
421
+ const choice = reply.choices[0]!;
422
+ const calls = (choice.message.tool_calls ?? []).filter((c) => c.type === "function");
423
+ failproofai.event.modelResponse({
424
+ model: reply.model,
425
+ requestId,
426
+ role: choice.message.role,
427
+ content: choice.message.content ?? "",
428
+ stopReason: choice.finish_reason,
429
+ inputTokens: reply.usage?.prompt_tokens ?? null,
430
+ outputTokens: reply.usage?.completion_tokens ?? null,
431
+ duration_ms: Date.now() - started,
432
+ // the field and shape the adapters write
433
+ fw_tool_calls: calls.map((c) => ({ toolCallId: c.id, toolName: c.function.name, input: c.function.arguments })),
434
+ });
435
+ return choice.message;
436
+ }
437
+
438
+ // 3. the tool dispatcher — reuse the model's own tool-call id
439
+ async function dispatch(call: { id: string; function: { name: string; arguments: string } }): Promise<string> {
440
+ // Malformed arguments are still a tool call: recorded, and failed inside
441
+ // toolCall(), so the trace shows it and the model gets an error to recover from.
442
+ let input: Record<string, unknown> = {};
443
+ let malformed: unknown;
444
+ try {
445
+ const parsed: unknown = JSON.parse(call.function.arguments || "{}");
446
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
447
+ throw new TypeError("tool arguments must be a JSON object");
448
+ }
449
+ input = parsed as Record<string, unknown>;
450
+ } catch (error) {
451
+ malformed = error;
452
+ input = { arguments: call.function.arguments };
453
+ }
454
+ try {
455
+ return await failproofai.toolCall(call.function.name, { toolCallId: call.id, input }, async () => {
456
+ if (malformed !== undefined) throw malformed;
457
+ return runTool(call.function.name, input);
458
+ });
459
+ } catch (error) {
460
+ return `error: ${error instanceof Error ? error.message : String(error)}`; // let the model recover
461
+ }
462
+ }
463
+ ```
464
+
465
+ The rules that make this correct:
466
+
467
+ - **Emit both halves of the model pair.** A `modelRequest` with no `modelResponse`
468
+ is a span the dashboard shows as running forever — hence the `catch`.
469
+ - **Record what the adapters record.** `role`, `content`, the tool calls the model
470
+ asked for, tokens, stop reason and duration on the response. Leave them out and the
471
+ trace has the shape but not the substance.
472
+ - **Pair model calls on `requestId`**, generated per call, so overlapping calls
473
+ cannot cross-pair.
474
+ - **Model calls are not timed for you.** Pass `duration_ms` yourself — an integer
475
+ (`Date.now()` differences are); a float throws `TypeError`.
476
+ - **Reuse the model's tool-call id** as `toolCallId`, so a `tool_use` lines up with
477
+ the `tool_calls[]` entry that asked for it. `toolCall()` times the call and records
478
+ a throw as `tool_result.error`, then rethrows.
479
+ - **Services and workers.** Pass your own request or job id as `sessionId`
480
+ (`agent("assistant", { sessionId: jobId }, fn)`). A dashboard session and the
481
+ record in your own logs or database are then the same string. (Retries: see
482
+ *Naming the agent, and owning the session id*.)
483
+ - **Sub-agents.** Nest `agent()` calls — directly, or from inside a tool the outer
484
+ agent runs. The inner one joins the session, and its `parent_id` is the outer
485
+ agent's name.
486
+ - **Don't reach for a module-level session variable.** Two overlapping runs mix
487
+ their events. `AsyncLocalStorage` already does this correctly.
488
+ - **A failed tool does not fail the run.** It is an `error` on its `tool_result`,
489
+ and if the model recovers the run ends `success` with no `error` event — so an
490
+ evaluation that counts `error` events will not see it. Count `tool_result`s
491
+ with an `error` instead.
492
+ - **Types are the only guard on names in plain JavaScript.** A misspelt required
493
+ option (`toolCallID`) is not a runtime error: the event is written without it and
494
+ never pairs. Use TypeScript, or check the ids when you verify.
495
+ - **`input` is typed as an object.** The SDK does not reject a primitive at
496
+ runtime, so wrap it yourself: `{ query: q }`.
497
+ - **Watch the size of `messages`.** Each `model_request` carries whatever you pass,
498
+ and the history grows every turn — including provider blobs such as encrypted
499
+ reasoning. Send role/content, and trim what a reader does not need.
500
+ - **Don't emit your own `agent_end` inside `agent()`.** The scope emits one; a second
501
+ is accepted and duplicates it.
502
+
503
+ The complete, runnable version is `sdk/typescript/examples/research-agent.ts` in the
504
+ FailproofAI/failproofai repo. CI runs it, as an ES module and as CommonJS, against
505
+ the real `openai` client.
506
+
507
+ **`using`, when a callback will not fit.** Use it for a scope opened in a
508
+ constructor and closed in a teardown:
509
+
510
+ ```ts
511
+ {
512
+ using span = failproofai.agent.open("planner", { goal });
513
+ using call = failproofai.toolCall.open("search", { input: { q } });
514
+ call.call.output = await search(q);
515
+ } // tool_result, then agent_end
516
+ ```
517
+
518
+ Prefer the callback form. It has nothing to unwind.
519
+
520
+ ## Verify
521
+
522
+ The spool is the same directory the Python SDK uses:
523
+ `${FAILPROOFAI_HOME:-~/.failproofai}/custom-agents/events/`, unless the app passed
524
+ `configure({ baseDir })`.
525
+
526
+ **On a machine running `failproofaid`, that directory is empty seconds after a
527
+ healthy run** — the daemon ships each file and deletes it. An empty real spool
528
+ means nothing; check with a throwaway spool the daemon does not watch. Use a
529
+ directory of your own, so parallel checks on one machine cannot delete each other's:
530
+
531
+ ```bash
532
+ export FAILPROOFAI_HOME="$(mktemp -d)"
533
+ npx tsx your-agent.ts # Next.js: set it on `next start`
534
+ node -e '
535
+ const fs = require("fs"), d = process.env.FAILPROOFAI_HOME + "/custom-agents/events";
536
+ for (const f of fs.readdirSync(d).filter(f => f.endsWith(".jsonl")).sort())
537
+ for (const l of fs.readFileSync(d + "/" + f, "utf8").split("\n").filter(Boolean)) {
538
+ const e = JSON.parse(l);
539
+ console.log(e.timestamp, e.session_id, e.agent_id, e.type, e.tool_name ?? "",
540
+ e.tool_call_id ?? e.request_id ?? "", e.input_tokens ?? "", e.output_tokens ?? "",
541
+ e.outcome ?? "", e.error ?? "", e.environment);
542
+ }'
543
+ ```
544
+
545
+ Then walk the same checklist as `SKILL.md` §5 (its first item — a dead flush
546
+ thread — is Python's; the TypeScript SDK logs `[failproofai-sdk]` warnings to
547
+ stderr instead):
548
+
549
+ 1. **One `agent_start`/`agent_end` pair per agent per run** — two when a sub-agent
550
+ runs, each with the right `parent_id`. No files at all usually means one of these:
551
+ - The process was killed by a signal with no handler, or returned from a
552
+ serverless handler without `await failproofai.flush()`.
553
+ - `instrument()` found nothing, or was not awaited: look for the
554
+ `[failproofai-sdk]` warning on stderr.
555
+ - The framework is bundled.
556
+ 2. **Every pair closed, with the ids you expect** — each
557
+ `model_request`/`model_response` on `request_id`, each `tool_use`/`tool_result` on
558
+ `tool_call_id` — and **token counts** on every `model_response` (missing on
559
+ streams: see *Token counts*).
560
+ 3. **Two overlapping runs give two session ids, with no events crossing.**
561
+ 4. **`environment` is the label you expect** on every event.
562
+ 5. **The `agent_id`s are your names**, not `LangGraph` or `ai.generateText`.
563
+
564
+ Then confirm the real thing arrived, from a separate environment, with the
565
+ `fp-cloud-cli` skill: `fp sessions --session-id <id> --since 1h` (the id you bound
566
+ with `session()`, or read with `failproofai.current()`). A session's `status` says
567
+ whether it finished, not whether it succeeded — a killed run is `done` too; its
568
+ `agent_end` `outcome` (`fp events --session-id <id> --full`) is what says `failed`.