failproofai 1.0.1 → 1.0.2-beta.0

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 (389) 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 +6 -6
  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 +2 -2
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
  24. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/run/route.js +5 -4
  26. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +2 -2
  29. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +4 -3
  31. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/auth/logout/route.js +4 -4
  33. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/auth/status/route.js +4 -4
  35. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  38. package/.next/standalone/.next/server/app/audit/page.js +2 -2
  39. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/index.html +1 -1
  42. package/.next/standalone/.next/server/app/index.rsc +15 -15
  43. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  44. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  45. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  46. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  47. package/.next/standalone/.next/server/app/page.js +2 -2
  48. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +66 -22
  51. package/.next/standalone/.next/server/app/policies/page.js +5 -4
  52. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  55. package/.next/standalone/.next/server/app/project/[name]/page.js +2 -2
  56. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  59. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  60. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
  61. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  64. package/.next/standalone/.next/server/app/projects/page.js +2 -2
  65. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  68. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  69. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/chunks/{[externals]__1qzqcio._.js → [externals]__0e32-7c._.js} +1 -1
  72. package/.next/standalone/.next/server/chunks/[externals]__1s462yl._.js +3 -0
  73. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01eqny5._.js +3 -0
  74. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p8poxd._.js → [root-of-the-server]__0igxt32._.js} +2 -2
  76. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0neqlu-._.js +3 -0
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +3 -0
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t9oqnn._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/_0bs-v8p._.js +3 -0
  80. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +3 -0
  81. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/_185gyk9._.js +3 -0
  83. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +5 -6
  84. package/.next/standalone/.next/server/chunks/lib_telemetry-id_ts_1k8gj9o._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_09d5c79._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_04op_ou._.js} +1 -1
  86. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_1d2g73o._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dr20uz._.js} +1 -1
  87. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/src_hooks_0xbw3bu._.js +12 -0
  89. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
  90. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +4 -0
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +4 -0
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +4 -0
  93. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0spkm68._.js → [root-of-the-server]__07gm3zl._.js} +21 -20
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +4 -0
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +4 -0
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +4 -0
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +6 -0
  99. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07tbbf3._.js → [root-of-the-server]__0zig5sv._.js} +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__192nhvh._.js +5 -0
  101. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +4 -0
  102. package/.next/standalone/.next/server/chunks/ssr/{_0lvyuv4._.js → _00e9tnf._.js} +2 -2
  103. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/ssr/{_0u5zauv._.js → _12l4a_k._.js} +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +13 -13
  108. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  110. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/ssr/src_hooks_08o7bqo._.js +10 -0
  112. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
  114. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  115. package/.next/standalone/.next/server/middleware.js +1 -1
  116. package/.next/standalone/.next/server/pages/404.html +1 -1
  117. package/.next/standalone/.next/server/pages/500.html +1 -1
  118. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  119. package/.next/standalone/.next/server/server-reference-manifest.json +71 -27
  120. package/.next/standalone/.next/static/chunks/{37fcpc36x9gpe.js → 0eqky-7n7dgdm.js} +1 -1
  121. package/.next/standalone/.next/static/chunks/{1ide1wl2f7zi1.js → 0sa9v5mhc8861.js} +13 -13
  122. package/.next/standalone/.next/static/chunks/1mfzsja6ftim5.css +2 -0
  123. package/.next/standalone/.next/static/chunks/{3k7mxbp9hiom0.js → 1nuqytbta44af.js} +1 -1
  124. package/.next/standalone/.next/static/chunks/1sl2xmn9inx3y.js +6 -0
  125. package/.next/standalone/.next/static/chunks/{2_2lhuojq2xop.js → 2aawsjld9ied_.js} +1 -1
  126. package/.next/standalone/.next/static/chunks/2gn7ut4svofm2.js +1 -0
  127. package/.next/standalone/.next/static/chunks/{31s1smp-g7gks.js → 2hs7ycvsav7v2.js} +1 -1
  128. package/.next/standalone/.next/static/chunks/{0k5050ezjvv49.js → 2i2yt3hzjredm.js} +1 -1
  129. package/.next/standalone/.next/static/chunks/{3c808qrfcq0im.js → 35xg6retpe6rp.js} +1 -1
  130. package/.next/standalone/.next/static/chunks/{2zpp1we2jv6tb.js → 3y54nw0i7dsjl.js} +1 -1
  131. package/.next/standalone/SECURITY.md +5 -4
  132. package/.next/standalone/app/actions/get-hooks-config.ts +108 -17
  133. package/.next/standalone/app/actions/pack-actions.ts +153 -0
  134. package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
  135. package/.next/standalone/app/audit/_components/share-templates.ts +13 -13
  136. package/.next/standalone/app/policies/hooks-client.tsx +320 -14
  137. package/.next/standalone/components/navbar.tsx +2 -28
  138. package/.next/standalone/components/reach-developers.tsx +8 -1
  139. package/.next/standalone/docs-old/agenteye/python-sdk-skill.mdx +1 -1
  140. package/.next/standalone/docs-old/agenteye/python-sdk.mdx +59 -35
  141. package/.next/standalone/docs-old/i18n/README.ar.md +1 -0
  142. package/.next/standalone/docs-old/i18n/README.de.md +1 -0
  143. package/.next/standalone/docs-old/i18n/README.es.md +1 -0
  144. package/.next/standalone/docs-old/i18n/README.fr.md +1 -0
  145. package/.next/standalone/docs-old/i18n/README.he.md +1 -0
  146. package/.next/standalone/docs-old/i18n/README.hi.md +1 -0
  147. package/.next/standalone/docs-old/i18n/README.it.md +1 -0
  148. package/.next/standalone/docs-old/i18n/README.ja.md +1 -0
  149. package/.next/standalone/docs-old/i18n/README.ko.md +1 -0
  150. package/.next/standalone/docs-old/i18n/README.pt-br.md +1 -0
  151. package/.next/standalone/docs-old/i18n/README.ru.md +1 -0
  152. package/.next/standalone/docs-old/i18n/README.tr.md +1 -0
  153. package/.next/standalone/docs-old/i18n/README.vi.md +1 -0
  154. package/.next/standalone/docs-old/i18n/README.zh.md +1 -0
  155. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +431 -0
  156. package/.next/standalone/fp-cloud-cli/LICENSE +42 -0
  157. package/.next/standalone/fp-cloud-cli/MANIFEST.in +10 -0
  158. package/.next/standalone/fp-cloud-cli/README.md +259 -0
  159. package/.next/standalone/fp-cloud-cli/fp_cli/__init__.py +10 -0
  160. package/.next/standalone/fp-cloud-cli/fp_cli/__main__.py +4 -0
  161. package/.next/standalone/fp-cloud-cli/fp_cli/_click_compat.py +64 -0
  162. package/.next/standalone/fp-cloud-cli/fp_cli/_context.py +332 -0
  163. package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -0
  164. package/.next/standalone/fp-cloud-cli/fp_cli/analytics.py +432 -0
  165. package/.next/standalone/fp-cloud-cli/fp_cli/analytics_config.py +77 -0
  166. package/.next/standalone/fp-cloud-cli/fp_cli/analytics_registry.py +83 -0
  167. package/.next/standalone/fp-cloud-cli/fp_cli/app.py +492 -0
  168. package/.next/standalone/fp-cloud-cli/fp_cli/auth.py +160 -0
  169. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +1694 -0
  170. package/.next/standalone/fp-cloud-cli/fp_cli/commands/__init__.py +0 -0
  171. package/.next/standalone/fp-cloud-cli/fp_cli/commands/_write.py +214 -0
  172. package/.next/standalone/fp-cloud-cli/fp_cli/commands/agent_cmds.py +407 -0
  173. package/.next/standalone/fp-cloud-cli/fp_cli/commands/alerts_cmds.py +445 -0
  174. package/.next/standalone/fp-cloud-cli/fp_cli/commands/audits_cmds.py +1054 -0
  175. package/.next/standalone/fp-cloud-cli/fp_cli/commands/auth_cmds.py +512 -0
  176. package/.next/standalone/fp-cloud-cli/fp_cli/commands/errors_cmds.py +190 -0
  177. package/.next/standalone/fp-cloud-cli/fp_cli/commands/evals_cmds.py +161 -0
  178. package/.next/standalone/fp-cloud-cli/fp_cli/commands/events_cmds.py +159 -0
  179. package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +416 -0
  180. package/.next/standalone/fp-cloud-cli/fp_cli/commands/guardrails_cmds.py +148 -0
  181. package/.next/standalone/fp-cloud-cli/fp_cli/commands/incidents_cmds.py +472 -0
  182. package/.next/standalone/fp-cloud-cli/fp_cli/commands/keys_cmds.py +407 -0
  183. package/.next/standalone/fp-cloud-cli/fp_cli/commands/list_cmds.py +63 -0
  184. package/.next/standalone/fp-cloud-cli/fp_cli/commands/orgs_cmds.py +319 -0
  185. package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +499 -0
  186. package/.next/standalone/fp-cloud-cli/fp_cli/commands/queries_cmds.py +378 -0
  187. package/.next/standalone/fp-cloud-cli/fp_cli/commands/sessions_cmds.py +151 -0
  188. package/.next/standalone/fp-cloud-cli/fp_cli/commands/settings_cmds.py +150 -0
  189. package/.next/standalone/fp-cloud-cli/fp_cli/commands/usage_cmds.py +35 -0
  190. package/.next/standalone/fp-cloud-cli/fp_cli/commands/users_cmds.py +404 -0
  191. package/.next/standalone/fp-cloud-cli/fp_cli/config.py +330 -0
  192. package/.next/standalone/fp-cloud-cli/fp_cli/dates.py +78 -0
  193. package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +345 -0
  194. package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +98 -0
  195. package/.next/standalone/fp-cloud-cli/fp_cli/models.py +891 -0
  196. package/.next/standalone/fp-cloud-cli/fp_cli/orgs.py +30 -0
  197. package/.next/standalone/fp-cloud-cli/fp_cli/output.py +6593 -0
  198. package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +208 -0
  199. package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +290 -0
  200. package/.next/standalone/fp-cloud-cli/fp_cli/py.typed +0 -0
  201. package/.next/standalone/fp-cloud-cli/fp_cli/select.py +322 -0
  202. package/.next/standalone/fp-cloud-cli/fp_cli/theme.py +53 -0
  203. package/.next/standalone/fp-cloud-cli/pyproject.toml +106 -0
  204. package/.next/standalone/fp-cloud-cli/skill/SKILL.md +302 -0
  205. package/.next/standalone/fp-cloud-cli/skill/agents/openai.yaml +8 -0
  206. package/.next/standalone/fp-cloud-cli/skill/references/commands.md +254 -0
  207. package/.next/standalone/fp-cloud-cli/tests/__init__.py +0 -0
  208. package/.next/standalone/fp-cloud-cli/tests/conftest.py +92 -0
  209. package/.next/standalone/fp-cloud-cli/tests/test_alerting.py +644 -0
  210. package/.next/standalone/fp-cloud-cli/tests/test_analytics.py +385 -0
  211. package/.next/standalone/fp-cloud-cli/tests/test_audits.py +950 -0
  212. package/.next/standalone/fp-cloud-cli/tests/test_auth.py +98 -0
  213. package/.next/standalone/fp-cloud-cli/tests/test_auth_mode.py +272 -0
  214. package/.next/standalone/fp-cloud-cli/tests/test_click_compat.py +118 -0
  215. package/.next/standalone/fp-cloud-cli/tests/test_client.py +299 -0
  216. package/.next/standalone/fp-cloud-cli/tests/test_commands.py +814 -0
  217. package/.next/standalone/fp-cloud-cli/tests/test_config.py +99 -0
  218. package/.next/standalone/fp-cloud-cli/tests/test_dashboards_agent.py +340 -0
  219. package/.next/standalone/fp-cloud-cli/tests/test_dates.py +76 -0
  220. package/.next/standalone/fp-cloud-cli/tests/test_enforcement_logic.py +481 -0
  221. package/.next/standalone/fp-cloud-cli/tests/test_facets.py +170 -0
  222. package/.next/standalone/fp-cloud-cli/tests/test_failproofai_home.py +722 -0
  223. package/.next/standalone/fp-cloud-cli/tests/test_fp_home_contract.py +198 -0
  224. package/.next/standalone/fp-cloud-cli/tests/test_hardening.py +186 -0
  225. package/.next/standalone/fp-cloud-cli/tests/test_help_table_coverage.py +127 -0
  226. package/.next/standalone/fp-cloud-cli/tests/test_keys_queries.py +496 -0
  227. package/.next/standalone/fp-cloud-cli/tests/test_list.py +59 -0
  228. package/.next/standalone/fp-cloud-cli/tests/test_multivalue.py +183 -0
  229. package/.next/standalone/fp-cloud-cli/tests/test_no_customer_identifiers.py +168 -0
  230. package/.next/standalone/fp-cloud-cli/tests/test_operator.py +492 -0
  231. package/.next/standalone/fp-cloud-cli/tests/test_orgs.py +692 -0
  232. package/.next/standalone/fp-cloud-cli/tests/test_output.py +1732 -0
  233. package/.next/standalone/fp-cloud-cli/tests/test_policy_check.py +191 -0
  234. package/.next/standalone/fp-cloud-cli/tests/test_readme_matches_reality.py +125 -0
  235. package/.next/standalone/fp-cloud-cli/tests/test_review_fixes.py +161 -0
  236. package/.next/standalone/fp-cloud-cli/tests/test_telemetry_completeness.py +90 -0
  237. package/.next/standalone/fp-cloud-cli/tests/test_usage.py +115 -0
  238. package/.next/standalone/fp-cloud-cli/tests/test_v1_origin_diagnostic.py +70 -0
  239. package/.next/standalone/fp-cloud-cli/tests/test_v1_routing.py +214 -0
  240. package/.next/standalone/fp-cloud-cli/tests/test_whoami.py +104 -0
  241. package/.next/standalone/fp-cloud-cli/uv.lock +552 -0
  242. package/.next/standalone/package.json +29 -22
  243. package/.next/standalone/sdk/python/CHANGELOG.md +70 -0
  244. package/.next/standalone/sdk/python/LICENSE +42 -0
  245. package/.next/standalone/sdk/python/MANIFEST.in +21 -0
  246. package/.next/standalone/sdk/python/README.md +466 -0
  247. package/.next/standalone/sdk/python/docs/README.md +249 -0
  248. package/.next/standalone/sdk/python/docs/_shared/README.md +43 -0
  249. package/.next/standalone/sdk/python/docs/_shared/__init__.py +195 -0
  250. package/.next/standalone/sdk/python/docs/crewai/README.md +328 -0
  251. package/.next/standalone/sdk/python/docs/crewai/examples/quickstart.py +61 -0
  252. package/.next/standalone/sdk/python/docs/crewai/examples/research_crew.py +92 -0
  253. package/.next/standalone/sdk/python/docs/langgraph/README.md +481 -0
  254. package/.next/standalone/sdk/python/docs/langgraph/examples/quickstart.py +51 -0
  255. package/.next/standalone/sdk/python/docs/langgraph/examples/research_agent.py +86 -0
  256. package/.next/standalone/sdk/python/docs/langgraph/examples/supervisor_handoff.py +83 -0
  257. package/.next/standalone/sdk/python/docs/llama_index/README.md +332 -0
  258. package/.next/standalone/sdk/python/docs/llama_index/examples/quickstart.py +62 -0
  259. package/.next/standalone/sdk/python/docs/llama_index/examples/research_agent.py +93 -0
  260. package/.next/standalone/sdk/python/docs/manual/README.md +491 -0
  261. package/.next/standalone/sdk/python/docs/manual/examples/quickstart.py +57 -0
  262. package/.next/standalone/sdk/python/docs/manual/examples/research_agent.py +133 -0
  263. package/.next/standalone/sdk/python/docs/pydantic_ai/README.md +323 -0
  264. package/.next/standalone/sdk/python/docs/pydantic_ai/examples/quickstart.py +48 -0
  265. package/.next/standalone/sdk/python/docs/pydantic_ai/examples/research_agent.py +94 -0
  266. package/.next/standalone/sdk/python/failproofai_sdk/__init__.py +131 -0
  267. package/.next/standalone/sdk/python/failproofai_sdk/_context.py +218 -0
  268. package/.next/standalone/sdk/python/failproofai_sdk/_environment.py +78 -0
  269. package/.next/standalone/sdk/python/failproofai_sdk/_events.py +752 -0
  270. package/.next/standalone/sdk/python/failproofai_sdk/_resolver.py +118 -0
  271. package/.next/standalone/sdk/python/failproofai_sdk/_runtime.py +21 -0
  272. package/.next/standalone/sdk/python/failproofai_sdk/_schema.py +317 -0
  273. package/.next/standalone/sdk/python/failproofai_sdk/_scopes.py +422 -0
  274. package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -0
  275. package/.next/standalone/sdk/python/failproofai_sdk/_writer.py +750 -0
  276. package/.next/standalone/sdk/python/failproofai_sdk/integrations/__init__.py +274 -0
  277. package/.next/standalone/sdk/python/failproofai_sdk/integrations/_compat.py +247 -0
  278. package/.next/standalone/sdk/python/failproofai_sdk/integrations/_core.py +1076 -0
  279. package/.next/standalone/sdk/python/failproofai_sdk/integrations/crewai.py +1669 -0
  280. package/.next/standalone/sdk/python/failproofai_sdk/integrations/langchain.py +2151 -0
  281. package/.next/standalone/sdk/python/failproofai_sdk/integrations/llama_index.py +1588 -0
  282. package/.next/standalone/sdk/python/failproofai_sdk/integrations/pydantic_ai.py +977 -0
  283. package/.next/standalone/sdk/python/failproofai_sdk/py.typed +0 -0
  284. package/.next/standalone/sdk/python/pyproject.toml +92 -0
  285. package/.next/standalone/sdk/python/skill/SKILL.md +399 -0
  286. package/.next/standalone/sdk/python/skill/agents/openai.yaml +8 -0
  287. package/.next/standalone/sdk/python/skill/references/events.md +234 -0
  288. package/.next/standalone/sdk/python/skill/references/frameworks.md +314 -0
  289. package/.next/standalone/sdk/python/skill/references/install.md +100 -0
  290. package/.next/standalone/sdk/python/skill/references/integration.md +352 -0
  291. package/.next/standalone/sdk/python/tests/__init__.py +0 -0
  292. package/.next/standalone/sdk/python/tests/conftest.py +169 -0
  293. package/.next/standalone/sdk/python/tests/integrations/__init__.py +6 -0
  294. package/.next/standalone/sdk/python/tests/integrations/test_crewai.py +1299 -0
  295. package/.next/standalone/sdk/python/tests/integrations/test_langchain.py +2338 -0
  296. package/.next/standalone/sdk/python/tests/integrations/test_llama_index.py +1576 -0
  297. package/.next/standalone/sdk/python/tests/integrations/test_pydantic_ai.py +1102 -0
  298. package/.next/standalone/sdk/python/tests/test_context.py +410 -0
  299. package/.next/standalone/sdk/python/tests/test_docs.py +411 -0
  300. package/.next/standalone/sdk/python/tests/test_durability.py +1352 -0
  301. package/.next/standalone/sdk/python/tests/test_encoding.py +571 -0
  302. package/.next/standalone/sdk/python/tests/test_integrations.py +1127 -0
  303. package/.next/standalone/sdk/python/tests/test_no_customer_identifiers.py +214 -0
  304. package/.next/standalone/sdk/python/tests/test_packaging.py +185 -0
  305. package/.next/standalone/sdk/python/tests/test_resolver_umbrella.py +178 -0
  306. package/.next/standalone/sdk/python/tests/test_scopes.py +487 -0
  307. package/.next/standalone/sdk/python/tests/test_sdk.py +923 -0
  308. package/.next/standalone/sdk/python/tests/test_server_contract.py +650 -0
  309. package/.next/standalone/sdk/python/tests/test_site_docs.py +371 -0
  310. package/.next/standalone/sdk/python/tests/test_skill_snippets.py +165 -0
  311. package/.next/standalone/sdk/python/tests/test_spool_contract.py +287 -0
  312. package/.next/standalone/sdk/python/tests/test_spool_creation.py +360 -0
  313. package/.next/standalone/sdk/python/tests/test_wire_format.py +279 -0
  314. package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +378 -0
  315. package/.next/standalone/sdk/python/uv.lock +6005 -0
  316. package/.next/standalone/server.js +1 -1
  317. package/README.md +77 -21
  318. package/bin/failproofai.mjs +145 -11
  319. package/dist/cli.mjs +4482 -2205
  320. package/dist/index.js +5 -5
  321. package/dist/worker.mjs +2399 -1978
  322. package/package.json +29 -22
  323. package/policy-pack/SHA256SUMS +2 -0
  324. package/policy-pack/failproofai-pack.json +732 -0
  325. package/policy-pack/failproofai-pack.mjs +2017 -0
  326. package/scripts/build-policy-pack.mjs +121 -0
  327. package/scripts/changelog-section.py +77 -0
  328. package/scripts/prune-standalone.mjs +3 -0
  329. package/scripts/python-version.py +232 -0
  330. package/scripts/translate-docs/cli.ts +21 -0
  331. package/scripts/translate-docs/mintlify-nav.ts +85 -13
  332. package/scripts/translate-docs/translator.ts +66 -11
  333. package/src/audit/cache.ts +40 -3
  334. package/src/audit/cli.ts +1 -1
  335. package/src/audit/index.ts +1 -1
  336. package/src/audit/replay.ts +89 -3
  337. package/src/audit/report.ts +5 -5
  338. package/src/audit/schedule-cli.ts +49 -53
  339. package/src/hooks/builtin-policies.ts +217 -579
  340. package/src/hooks/cloud-enrollment-cli.ts +66 -27
  341. package/src/hooks/cloud-managed-policies.ts +6 -1
  342. package/src/hooks/configure-wizard.ts +1 -1
  343. package/src/hooks/custom-hooks-loader.ts +89 -6
  344. package/src/hooks/fp-home.ts +92 -4
  345. package/src/hooks/fp-reset.ts +26 -2
  346. package/src/hooks/handler.ts +181 -11
  347. package/src/hooks/harness-cli.ts +79 -25
  348. package/src/hooks/hook-activity-store.ts +13 -3
  349. package/src/hooks/install-prompt.ts +25 -3
  350. package/src/hooks/manager.ts +418 -172
  351. package/src/hooks/migrations.ts +2 -2
  352. package/src/hooks/pack-cli.ts +505 -0
  353. package/src/hooks/pack-failclosed.ts +189 -0
  354. package/src/hooks/pack-manifest.ts +344 -0
  355. package/src/hooks/pack-store.ts +930 -0
  356. package/src/hooks/policy-catalog.ts +535 -0
  357. package/src/hooks/policy-evaluator.ts +24 -16
  358. package/src/hooks/policy-presets.ts +4 -2
  359. package/src/hooks/policy-registry.ts +8 -2
  360. package/src/hooks/policy-types.ts +26 -0
  361. package/src/hooks/session-pause-cli.ts +33 -9
  362. package/src/hooks/tui.ts +570 -0
  363. package/src/hooks/types.ts +15 -1
  364. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_usx0j._.js +0 -3
  365. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_zk340._.js +0 -3
  366. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0agdw2a._.js +0 -3
  367. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d1u_na._.js +0 -3
  368. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oy4kxb._.js +0 -3
  369. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zf034w._.js +0 -3
  370. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +0 -3
  371. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +0 -3
  372. package/.next/standalone/.next/server/chunks/_1ger0a2._.js +0 -3
  373. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +0 -3
  374. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1iiwm5e._.js +0 -3
  375. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kc8_v5._.js +0 -4
  376. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kgy9da._.js +0 -4
  377. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0mhqk5a._.js +0 -4
  378. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pltpn8._.js +0 -4
  379. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qkcyf-._.js +0 -4
  380. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w0x_ok._.js +0 -4
  381. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_dfocn._.js +0 -4
  382. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1bfex62._.js +0 -5
  383. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1kzapg5._.js +0 -6
  384. package/.next/standalone/.next/static/chunks/36fw6yk1s6x_f.js +0 -1
  385. package/.next/standalone/.next/static/chunks/3tzq0260n17ae.js +0 -6
  386. package/.next/standalone/.next/static/chunks/3wq9x0c-7ld5d.css +0 -2
  387. /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → nwbyWT06Ud0XdXOrVJyvS}/_buildManifest.js +0 -0
  388. /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → nwbyWT06Ud0XdXOrVJyvS}/_clientMiddlewareManifest.js +0 -0
  389. /package/.next/standalone/.next/static/{ZklXxyA5ygsWSQz2u_zii → nwbyWT06Ud0XdXOrVJyvS}/_ssgManifest.js +0 -0
@@ -0,0 +1,410 @@
1
+ """Tests for the identity layer: contextvars, the agent stack, and propagate().
2
+
3
+ The tests that matter here are the ones a reviewer cannot derive from reading
4
+ the diff:
5
+
6
+ * the **adversarially interleaved** task test, which is the only shape that
7
+ fails against a module-global implementation;
8
+ * the **tuple test**, which is the only shape that fails against
9
+ `ContextVar[list]`;
10
+ * `propagate` under `pool.map`, which is the only shape that fails against
11
+ `partial(copy_context().run, fn)`.
12
+ """
13
+
14
+ import asyncio
15
+ import threading
16
+ from concurrent.futures import ThreadPoolExecutor
17
+
18
+ import pytest
19
+
20
+ import failproofai_sdk
21
+ import failproofai_sdk._context as _context
22
+ import failproofai_sdk._runtime as _runtime
23
+
24
+
25
+ # ---------------------------------------------------------------------------
26
+ # Basic binding
27
+ # ---------------------------------------------------------------------------
28
+
29
+ def test_nothing_bound_by_default():
30
+ ident = failproofai_sdk.current()
31
+ assert ident.session_id is None
32
+ assert ident.agent_id is None
33
+ assert ident.parent_id is None
34
+ assert ident.depth == 0
35
+
36
+
37
+ def test_session_binds_and_unbinds():
38
+ with failproofai_sdk.session("s-1") as sid:
39
+ assert sid == "s-1"
40
+ assert failproofai_sdk.current().session_id == "s-1"
41
+ assert failproofai_sdk.current().session_id is None
42
+
43
+
44
+ def test_session_generates_an_id_when_none_bound():
45
+ with failproofai_sdk.session() as sid:
46
+ assert isinstance(sid, str) and len(sid) == 32
47
+ assert failproofai_sdk.current().session_id == sid
48
+
49
+
50
+ def test_nested_session_inherits_rather_than_generating(events):
51
+ with failproofai_sdk.session() as outer:
52
+ with failproofai_sdk.session() as inner:
53
+ assert inner == outer
54
+ with failproofai_sdk.agent("child") as ident:
55
+ assert ident.session_id == outer
56
+
57
+
58
+ def test_agent_id_falls_back_to_main():
59
+ assert _context.agent_id() == _context.DEFAULT_AGENT_ID == "main"
60
+ with failproofai_sdk.session("s-1", agent_id="worker"):
61
+ assert _context.agent_id() == "worker"
62
+
63
+
64
+ # ---------------------------------------------------------------------------
65
+ # Task isolation — must FAIL against a module-global implementation
66
+ # ---------------------------------------------------------------------------
67
+
68
+ def test_tasks_are_isolated_when_adversarially_interleaved(events):
69
+ """Two tasks bind different sessions, then are forced to interleave.
70
+
71
+ The `await asyncio.sleep(0)` between binding and emitting is the whole
72
+ point: it yields to the event loop *while the scope is open*, so task B
73
+ binds its session before task A emits. Against a module global, A's
74
+ tool_use would carry B's session_id and this assertion fails. Without the
75
+ forced interleave the same test passes on a global and proves nothing.
76
+ """
77
+ order: list[str] = []
78
+
79
+ async def run(name: str) -> None:
80
+ async with failproofai_sdk.agent(name, session_id=f"sess-{name}"):
81
+ order.append(f"bound-{name}")
82
+ await asyncio.sleep(0)
83
+ await asyncio.sleep(0)
84
+ order.append(f"emit-{name}")
85
+ _runtime.event.tool_use(tool_name="t", tool_call_id=f"tc-{name}")
86
+ await asyncio.sleep(0)
87
+
88
+ async def main() -> None:
89
+ await asyncio.gather(run("a"), run("b"))
90
+
91
+ asyncio.run(main())
92
+
93
+ # Prove the interleave actually happened; otherwise the test is vacuous.
94
+ assert order.index("bound-b") < order.index("emit-a")
95
+
96
+ by_call = {e["tool_call_id"]: e for e in events.entries if e["type"] == "tool_use"}
97
+ assert by_call["tc-a"]["session_id"] == "sess-a"
98
+ assert by_call["tc-a"]["agent_id"] == "a"
99
+ assert by_call["tc-b"]["session_id"] == "sess-b"
100
+ assert by_call["tc-b"]["agent_id"] == "b"
101
+
102
+
103
+ def test_agent_stack_is_a_tuple_not_a_shared_list(events):
104
+ """Task A's stack must be unmodified by task B pushing a nested agent.
105
+
106
+ A `ContextVar[list]` holds the *same list object* in both tasks, so B's
107
+ push would show up in A's view. This is the test that catches it.
108
+ """
109
+ seen: dict[str, tuple[str, ...]] = {}
110
+ pushed = asyncio.Event()
111
+
112
+ async def first() -> None:
113
+ async with failproofai_sdk.agent("root-a", session_id="s"):
114
+ async with failproofai_sdk.agent("child-a"):
115
+ # Hand control to the other task, which pushes child-b.
116
+ await pushed.wait()
117
+ seen["a"] = _context._AGENT_STACK.get()
118
+
119
+ async def second() -> None:
120
+ async with failproofai_sdk.agent("root-b", session_id="s"):
121
+ async with failproofai_sdk.agent("child-b"):
122
+ seen["b"] = _context._AGENT_STACK.get()
123
+ pushed.set()
124
+ await asyncio.sleep(0)
125
+
126
+ async def main() -> None:
127
+ await asyncio.gather(first(), second())
128
+
129
+ asyncio.run(main())
130
+
131
+ assert seen["a"] == ("root-a", "child-a")
132
+ assert seen["b"] == ("root-b", "child-b")
133
+ assert isinstance(seen["a"], tuple)
134
+
135
+
136
+ def test_create_task_inherits_without_propagate(events):
137
+ """Pinned deliberately: contextvars DO flow into asyncio tasks.
138
+
139
+ Nobody should later sprinkle `propagate()` over async code — a Task copies
140
+ the current context at creation, so the identity is already there.
141
+ """
142
+ captured: list = []
143
+
144
+ async def child() -> None:
145
+ captured.append(failproofai_sdk.current())
146
+
147
+ async def main() -> None:
148
+ with failproofai_sdk.agent("parent", session_id="s-async"):
149
+ await asyncio.create_task(child())
150
+
151
+ asyncio.run(main())
152
+ assert captured[0].session_id == "s-async"
153
+ assert captured[0].agent_id == "parent"
154
+
155
+
156
+ # ---------------------------------------------------------------------------
157
+ # Thread isolation and propagate()
158
+ # ---------------------------------------------------------------------------
159
+
160
+ def test_threads_do_not_inherit_identity():
161
+ seen: list = []
162
+
163
+ def worker() -> None:
164
+ seen.append(failproofai_sdk.current())
165
+
166
+ with failproofai_sdk.session("s-thread"):
167
+ t = threading.Thread(target=worker)
168
+ t.start()
169
+ t.join()
170
+
171
+ assert seen[0].session_id is None
172
+
173
+
174
+ def test_bare_submit_inside_agent_raises_naming_propagate(events):
175
+ def worker():
176
+ _runtime.event.tool_use(tool_name="t", tool_call_id="tc")
177
+
178
+ with failproofai_sdk.agent("a", session_id="s"):
179
+ with ThreadPoolExecutor(max_workers=1) as pool:
180
+ future = pool.submit(worker)
181
+ with pytest.raises(TypeError) as excinfo:
182
+ future.result()
183
+
184
+ assert "propagate" in str(excinfo.value)
185
+
186
+
187
+ def test_propagate_with_pool_submit(events):
188
+ def worker(n):
189
+ _runtime.event.tool_use(tool_name="t", tool_call_id=f"tc-{n}")
190
+ return failproofai_sdk.current().session_id
191
+
192
+ with failproofai_sdk.agent("a", session_id="s-submit"):
193
+ with ThreadPoolExecutor(max_workers=2) as pool:
194
+ results = [pool.submit(failproofai_sdk.propagate(worker), n).result() for n in range(3)]
195
+
196
+ assert results == ["s-submit"] * 3
197
+ tool_uses = [e for e in events.entries if e["type"] == "tool_use"]
198
+ assert {e["session_id"] for e in tool_uses} == {"s-submit"}
199
+ assert {e["agent_id"] for e in tool_uses} == {"a"}
200
+
201
+
202
+ def test_propagate_survives_reuse_via_pool_map(events):
203
+ """`pool.map` calls ONE wrapper object many times, concurrently.
204
+
205
+ This is what `partial(contextvars.copy_context().run, fn)` cannot do: a
206
+ `Context` raises `RuntimeError: cannot enter context ... already entered`
207
+ on the second concurrent entry, and mutations inside it persist into the
208
+ next call. Snapshot/restore has neither problem.
209
+ """
210
+ # Forces four workers to be *inside* the wrapper simultaneously. Without
211
+ # it the calls serialise and a copy_context() implementation passes by
212
+ # accident, which makes the test worthless.
213
+ barrier = threading.Barrier(4)
214
+
215
+ def worker(n):
216
+ ident = failproofai_sdk.current()
217
+ barrier.wait(timeout=5)
218
+ # Mutate the stack, to prove the mutation does not leak into the next
219
+ # invocation of the same wrapper.
220
+ with failproofai_sdk.agent(f"child-{n}", session_id=ident.session_id):
221
+ pass
222
+ return (ident.session_id, ident.agent_id, ident.depth)
223
+
224
+ with failproofai_sdk.agent("a", session_id="s-map"):
225
+ wrapped = failproofai_sdk.propagate(worker)
226
+ with ThreadPoolExecutor(max_workers=4) as pool:
227
+ results = list(pool.map(wrapped, range(8)))
228
+
229
+ assert results == [("s-map", "a", 1)] * 8
230
+
231
+
232
+ def test_propagate_with_threading_thread(events):
233
+ seen: list = []
234
+
235
+ def worker():
236
+ seen.append(failproofai_sdk.current())
237
+
238
+ with failproofai_sdk.agent("a", session_id="s-thread2"):
239
+ t = threading.Thread(target=failproofai_sdk.propagate(worker))
240
+ t.start()
241
+ t.join()
242
+
243
+ assert seen[0].session_id == "s-thread2"
244
+ assert seen[0].agent_id == "a"
245
+
246
+
247
+ def test_propagate_with_run_in_executor(events):
248
+ def worker():
249
+ return failproofai_sdk.current().session_id
250
+
251
+ async def main():
252
+ with failproofai_sdk.agent("a", session_id="s-executor"):
253
+ loop = asyncio.get_running_loop()
254
+ with ThreadPoolExecutor(max_workers=1) as pool:
255
+ return await loop.run_in_executor(pool, failproofai_sdk.propagate(worker))
256
+
257
+ assert asyncio.run(main()) == "s-executor"
258
+
259
+
260
+ def test_propagate_does_not_leak_into_the_worker_thread_afterwards():
261
+ seen: list = []
262
+
263
+ def worker():
264
+ pass
265
+
266
+ def after():
267
+ seen.append(failproofai_sdk.current().session_id)
268
+
269
+ with failproofai_sdk.session("s-leak"):
270
+ wrapped = failproofai_sdk.propagate(worker)
271
+ with ThreadPoolExecutor(max_workers=1) as pool:
272
+ pool.submit(wrapped).result()
273
+ pool.submit(after).result()
274
+
275
+ assert seen[0] is None
276
+
277
+
278
+ def test_propagate_preserves_metadata():
279
+ def worker(a, b=2):
280
+ """docstring."""
281
+ return a + b
282
+
283
+ wrapped = failproofai_sdk.propagate(worker)
284
+ assert wrapped.__name__ == "worker"
285
+ assert wrapped.__doc__ == "docstring."
286
+ assert wrapped(1, b=3) == 4
287
+
288
+
289
+ # ---------------------------------------------------------------------------
290
+ # Explicit identity always wins
291
+ # ---------------------------------------------------------------------------
292
+
293
+ def test_explicit_ids_override_the_context(events):
294
+ with failproofai_sdk.agent("ctx-agent", session_id="ctx-session"):
295
+ _runtime.event.tool_use(
296
+ session_id="explicit-session",
297
+ agent_id="explicit-agent",
298
+ tool_name="t",
299
+ tool_call_id="tc",
300
+ )
301
+ entry = [e for e in events.entries if e["type"] == "tool_use"][0]
302
+ assert entry["session_id"] == "explicit-session"
303
+ assert entry["agent_id"] == "explicit-agent"
304
+
305
+
306
+ def test_explicit_agent_id_only_keeps_context_session(events):
307
+ with failproofai_sdk.agent("ctx-agent", session_id="ctx-session"):
308
+ _runtime.event.tool_use(agent_id="other", tool_name="t", tool_call_id="tc")
309
+ entry = [e for e in events.entries if e["type"] == "tool_use"][0]
310
+ assert entry["session_id"] == "ctx-session"
311
+ assert entry["agent_id"] == "other"
312
+
313
+
314
+ def test_missing_session_outside_any_scope_raises(events):
315
+ with pytest.raises(TypeError, match="propagate"):
316
+ _runtime.event.agent_start()
317
+
318
+
319
+ def test_agent_id_defaults_to_main_with_only_a_session(events):
320
+ with failproofai_sdk.session("s-only"):
321
+ _runtime.event.agent_start()
322
+ assert events.last()["agent_id"] == "main"
323
+
324
+
325
+ # ---------------------------------------------------------------------------
326
+ # Exception precedence is unchanged by the identity fallback
327
+ # ---------------------------------------------------------------------------
328
+
329
+ def test_duration_ms_guard_still_beats_the_identity_error(events):
330
+ """No session bound, and duration_ms passed. The ValueError must win.
331
+
332
+ `_identity()` runs after the guard precisely so today's precedence holds.
333
+ """
334
+ with pytest.raises(ValueError, match="duration_ms"):
335
+ _runtime.event.tool_result(tool_name="t", tool_call_id="tc", duration_ms=99)
336
+
337
+
338
+ def test_reserved_field_error_still_beats_the_identity_error(events):
339
+ with pytest.raises(ValueError, match="Reserved field"):
340
+ _runtime.event.agent_start(timestamp="nope")
341
+
342
+
343
+ def test_duplicate_session_id_still_raises_type_error(events):
344
+ with pytest.raises(TypeError):
345
+ _runtime.event.agent_start(session_id="s", **{"session_id": "s2"})
346
+
347
+
348
+ # ---------------------------------------------------------------------------
349
+ # `_pending` correlation keys
350
+ # ---------------------------------------------------------------------------
351
+
352
+ def test_hook_id_no_longer_collides_with_tool_call_id(events):
353
+ ns = _runtime.event
354
+ ns.tool_use(session_id="s", agent_id="a", tool_name="t", tool_call_id="x1")
355
+ ns.hook_completed(session_id="s", agent_id="a", hook_name="h", hook_id="x1")
356
+ assert "duration_ms" not in events.last()
357
+ # And the tool's own pending entry is untouched, so it still pairs.
358
+ ns.tool_result(session_id="s", agent_id="a", tool_name="t", tool_call_id="x1")
359
+ assert "duration_ms" in events.last()
360
+
361
+
362
+ def test_hook_pair_still_produces_a_duration(events):
363
+ ns = _runtime.event
364
+ ns.hook_triggered(session_id="s", agent_id="a", hook_name="h", hook_id="h1")
365
+ ns.hook_completed(session_id="s", agent_id="a", hook_name="h", hook_id="h1")
366
+ assert "duration_ms" in events.last()
367
+
368
+
369
+ def test_tool_keys_stay_bare_so_cross_agent_pairs_still_match(events):
370
+ """A tool started under one agent and finished under another must pair.
371
+
372
+ Namespacing tool keys by agent_id would silently turn this correct
373
+ duration_ms into a missing one, and this is routine once frameworks run
374
+ tools inside sub-agents.
375
+ """
376
+ ns = _runtime.event
377
+ ns.tool_use(session_id="s", agent_id="planner", tool_name="t", tool_call_id="tc")
378
+ ns.tool_result(session_id="s", agent_id="worker", tool_name="t", tool_call_id="tc")
379
+ assert "duration_ms" in events.last()
380
+
381
+
382
+ def test_track_pending_is_thread_safe_at_the_cap(events):
383
+ """Hammer `_track_pending` at the cap from several threads.
384
+
385
+ Unlocked, the read-modify-write lets two threads pick the same `oldest` and
386
+ the second `del` raises KeyError *inside* the caller's event.tool_use().
387
+ """
388
+ from failproofai_sdk._events import _PENDING_CAP
389
+
390
+ ns = _runtime.event
391
+ for i in range(_PENDING_CAP):
392
+ ns._track_pending(f"seed-{i}", ns._now())
393
+
394
+ errors: list[Exception] = []
395
+
396
+ def hammer(worker: int) -> None:
397
+ try:
398
+ for i in range(200):
399
+ ns._track_pending(f"w{worker}-{i}", ns._now())
400
+ except Exception as exc:
401
+ errors.append(exc)
402
+
403
+ threads = [threading.Thread(target=hammer, args=(w,)) for w in range(8)]
404
+ for t in threads:
405
+ t.start()
406
+ for t in threads:
407
+ t.join()
408
+
409
+ assert errors == []
410
+ assert len(ns._pending) == _PENDING_CAP