experimental-a2 0.16.1 → 0.18.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 (406) hide show
  1. package/CHANGELOG.md +373 -0
  2. package/README.md +1 -1
  3. package/dist/{actor-ohPC-81x.d.ts → actor-Bjce9_5U.d.ts} +21 -11
  4. package/dist/actor-Bjce9_5U.d.ts.map +1 -0
  5. package/dist/actor-client.d.ts +2 -5
  6. package/dist/actor-client.d.ts.map +1 -1
  7. package/dist/actor-client.js +13 -4
  8. package/dist/actor-client.js.map +1 -1
  9. package/dist/actor-react.d.ts +5 -3
  10. package/dist/actor-react.d.ts.map +1 -1
  11. package/dist/actor-react.js +20 -10
  12. package/dist/actor-react.js.map +1 -1
  13. package/dist/{actor-shared-B5tJfzt-.js → actor-shared-t7w8xIKP.js} +12 -7
  14. package/dist/actor-shared-t7w8xIKP.js.map +1 -0
  15. package/dist/actor.d.ts +1 -1
  16. package/dist/actor.js +42 -23
  17. package/dist/actor.js.map +1 -1
  18. package/dist/{ai-DgOBltJ_.js → ai-BpOGm-zB.js} +621 -216
  19. package/dist/ai-BpOGm-zB.js.map +1 -0
  20. package/dist/{ai-CrEf6p_W.d.ts → ai-DrUaMyRt.d.ts} +114 -100
  21. package/dist/ai-DrUaMyRt.d.ts.map +1 -0
  22. package/dist/ai-client.d.ts +27 -0
  23. package/dist/ai-client.d.ts.map +1 -0
  24. package/dist/ai-client.js +29 -0
  25. package/dist/ai-client.js.map +1 -0
  26. package/dist/ai-fx.browser.d.ts +1 -0
  27. package/dist/ai-fx.browser.js +6 -0
  28. package/dist/ai-fx.browser.js.map +1 -0
  29. package/dist/ai-fx.d.ts +10 -0
  30. package/dist/ai-fx.d.ts.map +1 -0
  31. package/dist/ai-fx.js +634 -0
  32. package/dist/ai-fx.js.map +1 -0
  33. package/dist/ai-harness-BuLh_EYi.js +273 -0
  34. package/dist/ai-harness-BuLh_EYi.js.map +1 -0
  35. package/dist/ai-harness-DvsPeJeB.d.ts +26 -0
  36. package/dist/ai-harness-DvsPeJeB.d.ts.map +1 -0
  37. package/dist/ai-pi.browser.d.ts +1 -0
  38. package/dist/ai-pi.browser.js +6 -0
  39. package/dist/ai-pi.browser.js.map +1 -0
  40. package/dist/ai-pi.d.ts +17 -0
  41. package/dist/ai-pi.d.ts.map +1 -0
  42. package/dist/ai-pi.js +904 -0
  43. package/dist/ai-pi.js.map +1 -0
  44. package/dist/ai-react.d.ts +96 -0
  45. package/dist/ai-react.d.ts.map +1 -0
  46. package/dist/ai-react.js +142 -0
  47. package/dist/ai-react.js.map +1 -0
  48. package/dist/ai-server.browser.js +2 -2
  49. package/dist/ai-server.browser.js.map +1 -1
  50. package/dist/ai-server.d.ts +109 -43
  51. package/dist/ai-server.d.ts.map +1 -1
  52. package/dist/ai-server.js +526 -283
  53. package/dist/ai-server.js.map +1 -1
  54. package/dist/ai.d.ts +2 -2
  55. package/dist/ai.js +2 -2
  56. package/dist/bounded-cache-CPHWF-8h.js +41 -0
  57. package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
  58. package/dist/{client-BYzHjkwU.js → client-BReKqwZC.js} +447 -80
  59. package/dist/client-BReKqwZC.js.map +1 -0
  60. package/dist/{client-CzyacQpJ.d.ts → client-h_DKFAjj.d.ts} +14 -13
  61. package/dist/client-h_DKFAjj.d.ts.map +1 -0
  62. package/dist/client.d.ts +4 -2
  63. package/dist/client.js +1 -1
  64. package/dist/{contract-CKRg_E4q.js → contract-BYKASlCV.js} +12 -21
  65. package/dist/contract-BYKASlCV.js.map +1 -0
  66. package/dist/{idempotent-replay-DVOlyYbx.js → idempotent-replay-JdgMQRRm.js} +2 -2
  67. package/dist/{idempotent-replay-DVOlyYbx.js.map → idempotent-replay-JdgMQRRm.js.map} +1 -1
  68. package/dist/index.d.ts +6 -5
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +4 -3
  71. package/dist/{errors-DvhSXnxk.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +7 -3
  72. package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +1 -0
  73. package/dist/{internal-Dq2qYxou.js → internal-B2T3U4Rq.js} +29 -2
  74. package/dist/internal-B2T3U4Rq.js.map +1 -0
  75. package/dist/otel.d.ts +1 -1
  76. package/dist/react-BBXgHWFc.d.ts +86 -0
  77. package/dist/react-BBXgHWFc.d.ts.map +1 -0
  78. package/dist/react.d.ts +2 -122
  79. package/dist/react.js +107 -100
  80. package/dist/react.js.map +1 -1
  81. package/dist/reducer-BAXc8JyF.js +87 -0
  82. package/dist/reducer-BAXc8JyF.js.map +1 -0
  83. package/dist/{reducer-otzHjuJj.d.ts → reducer-CqA59Q6U.d.ts} +46 -30
  84. package/dist/reducer-CqA59Q6U.d.ts.map +1 -0
  85. package/dist/reducer-runtime-DQwz_J59.js +28 -0
  86. package/dist/reducer-runtime-DQwz_J59.js.map +1 -0
  87. package/dist/scheduler-qstash.d.ts +3 -3
  88. package/dist/scheduler-qstash.d.ts.map +1 -1
  89. package/dist/scheduler-qstash.js +33 -10
  90. package/dist/scheduler-qstash.js.map +1 -1
  91. package/dist/{scheduler-task-BpzhPnRS.js → scheduler-task-X1SToDjP.js} +18 -3
  92. package/dist/scheduler-task-X1SToDjP.js.map +1 -0
  93. package/dist/scheduler-vercel.d.ts +4 -9
  94. package/dist/scheduler-vercel.d.ts.map +1 -1
  95. package/dist/scheduler-vercel.js +25 -44
  96. package/dist/scheduler-vercel.js.map +1 -1
  97. package/dist/{server-BD5ckxZb.js → server-Dw_k_7kO.js} +904 -219
  98. package/dist/server-Dw_k_7kO.js.map +1 -0
  99. package/dist/{server-DbD7IJVK.d.ts → server-En7cbi3v.d.ts} +116 -26
  100. package/dist/server-En7cbi3v.d.ts.map +1 -0
  101. package/dist/server.d.ts +4 -4
  102. package/dist/server.js +2 -2
  103. package/dist/session-clear-Bo-XTFEy.d.ts +12 -0
  104. package/dist/session-clear-Bo-XTFEy.d.ts.map +1 -0
  105. package/dist/{errors-DCk6ch5n.js → session-clear-DGI4jTQ5.js} +17 -2
  106. package/dist/session-clear-DGI4jTQ5.js.map +1 -0
  107. package/dist/{store-DyZM6fS5.d.ts → store-Djdv0bnZ.d.ts} +73 -3
  108. package/dist/store-Djdv0bnZ.d.ts.map +1 -0
  109. package/dist/store-N8PXxDAS.js.map +1 -1
  110. package/dist/store-memory.d.ts +1 -1
  111. package/dist/store-memory.d.ts.map +1 -1
  112. package/dist/store-memory.js +205 -66
  113. package/dist/store-memory.js.map +1 -1
  114. package/dist/{store-polling-CmxUbV93.js → store-polling-B5FcwJfo.js} +21 -4
  115. package/dist/store-polling-B5FcwJfo.js.map +1 -0
  116. package/dist/store-postgres.d.ts +1 -1
  117. package/dist/store-postgres.d.ts.map +1 -1
  118. package/dist/store-postgres.js +450 -108
  119. package/dist/store-postgres.js.map +1 -1
  120. package/dist/{store-presence-polling-C7-XZyW9.js → store-presence-polling-BAwS8RWn.js} +3 -3
  121. package/dist/{store-presence-polling-C7-XZyW9.js.map → store-presence-polling-BAwS8RWn.js.map} +1 -1
  122. package/dist/store-redis-http.d.ts +1 -1
  123. package/dist/store-redis-http.d.ts.map +1 -1
  124. package/dist/store-redis-http.js +293 -11
  125. package/dist/store-redis-http.js.map +1 -1
  126. package/dist/store-redis-notify-BRITti_o.js +2493 -0
  127. package/dist/store-redis-notify-BRITti_o.js.map +1 -0
  128. package/dist/store-redis.d.ts +1 -1
  129. package/dist/store-redis.d.ts.map +1 -1
  130. package/dist/store-redis.js +11 -11
  131. package/dist/store-redis.js.map +1 -1
  132. package/dist/store-sqlite.d.ts +1 -1
  133. package/dist/store-sqlite.d.ts.map +1 -1
  134. package/dist/store-sqlite.js +197 -33
  135. package/dist/store-sqlite.js.map +1 -1
  136. package/dist/stream-buffer-Cx7AAPGq.js +23 -0
  137. package/dist/stream-buffer-Cx7AAPGq.js.map +1 -0
  138. package/dist/{telemetry-B5jzpy6y.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
  139. package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
  140. package/dist/{wire-BO5wWCb1.js → wire-rSUglYo8.js} +132 -10
  141. package/dist/wire-rSUglYo8.js.map +1 -0
  142. package/docs/01-quickstart.mdx +50 -84
  143. package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
  144. package/docs/actors/01-introduction.mdx +48 -82
  145. package/docs/actors/02-concurrency.mdx +43 -70
  146. package/docs/actors/03-timers.mdx +28 -42
  147. package/docs/actors/04-routes.mdx +110 -137
  148. package/docs/actors/meta.ts +1 -1
  149. package/docs/agents/01-introduction.mdx +257 -0
  150. package/docs/agents/02-tools.mdx +247 -0
  151. package/docs/agents/03-conversations.mdx +538 -0
  152. package/docs/agents/04-harnesses.mdx +136 -0
  153. package/docs/agents/meta.ts +1 -0
  154. package/docs/client/01-react.mdx +294 -0
  155. package/docs/client/02-transports.mdx +86 -0
  156. package/docs/client/03-presence.mdx +224 -0
  157. package/docs/client/meta.ts +1 -0
  158. package/docs/contract/01-events.mdx +57 -0
  159. package/docs/contract/02-state.mdx +142 -0
  160. package/docs/contract/03-sessions.mdx +175 -0
  161. package/docs/index.mdx +112 -156
  162. package/docs/reference/01-core.mdx +139 -0
  163. package/docs/reference/02-server.mdx +855 -0
  164. package/docs/reference/03-client.mdx +301 -0
  165. package/docs/reference/04-ai.mdx +722 -0
  166. package/docs/reference/05-adapters.mdx +351 -0
  167. package/docs/reference/06-errors.mdx +138 -0
  168. package/docs/reference/meta.ts +1 -1
  169. package/docs/server/01-handlers.mdx +200 -0
  170. package/docs/server/02-timers.mdx +130 -0
  171. package/docs/server/03-cancellation.mdx +141 -0
  172. package/docs/server/04-routes.mdx +243 -0
  173. package/docs/server/05-production.mdx +322 -0
  174. package/docs/server/06-guarantees.mdx +123 -0
  175. package/examples/playground/DEPLOY.md +53 -7
  176. package/examples/playground/app/a0/[appId]/loading.tsx +16 -0
  177. package/examples/playground/app/a0/[appId]/page.tsx +53 -0
  178. package/examples/playground/app/a0/a0.css +818 -0
  179. package/examples/playground/app/a0/app-list.tsx +218 -0
  180. package/examples/playground/app/a0/app-view.tsx +63 -0
  181. package/examples/playground/app/a0/apps/[appId]/preview/route.ts +27 -0
  182. package/examples/playground/app/a0/apps/[appId]/route.ts +28 -0
  183. package/examples/playground/app/a0/apps.test.ts +128 -0
  184. package/examples/playground/app/a0/apps.ts +102 -0
  185. package/examples/playground/app/a0/chat.tsx +410 -0
  186. package/examples/playground/app/a0/columns.tsx +109 -0
  187. package/examples/playground/app/a0/context-menu.tsx +116 -0
  188. package/examples/playground/app/a0/cookies.ts +46 -0
  189. package/examples/playground/app/a0/crash-on-request.ts +72 -0
  190. package/examples/playground/app/a0/crashes/route.ts +3 -0
  191. package/examples/playground/app/a0/crashes.test.ts +33 -0
  192. package/examples/playground/app/a0/crashes.ts +28 -0
  193. package/examples/playground/app/a0/devtools.tsx +164 -0
  194. package/examples/playground/app/a0/events/route.ts +6 -0
  195. package/examples/playground/app/a0/flags.ts +30 -0
  196. package/examples/playground/app/a0/fx/events/route.ts +9 -0
  197. package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
  198. package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
  199. package/examples/playground/app/a0/layout.tsx +38 -0
  200. package/examples/playground/app/a0/list/route.ts +10 -0
  201. package/examples/playground/app/a0/model.test.ts +73 -0
  202. package/examples/playground/app/a0/model.ts +95 -0
  203. package/examples/playground/app/a0/no-photon.cjs +4 -0
  204. package/examples/playground/app/a0/no-quickjs.cjs +3 -0
  205. package/examples/playground/app/a0/page.tsx +14 -0
  206. package/examples/playground/app/a0/pi/events/route.ts +9 -0
  207. package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
  208. package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
  209. package/examples/playground/app/a0/preview-pane.tsx +145 -0
  210. package/examples/playground/app/a0/preview.test.ts +53 -0
  211. package/examples/playground/app/a0/preview.ts +26 -0
  212. package/examples/playground/app/a0/sandbox-log.ts +75 -0
  213. package/examples/playground/app/a0/sandbox-session.ts +152 -0
  214. package/examples/playground/app/a0/sandbox.ts +191 -0
  215. package/examples/playground/app/a0/sandboxes/scheduler/route.ts +6 -0
  216. package/examples/playground/app/a0/scheduler/route.ts +7 -0
  217. package/examples/playground/app/a0/server.ts +213 -0
  218. package/examples/playground/app/a0/session.ts +59 -0
  219. package/examples/playground/app/a0/shell.tsx +158 -0
  220. package/examples/playground/app/a0/short/events/route.ts +9 -0
  221. package/examples/playground/app/a0/splitter.tsx +120 -0
  222. package/examples/playground/app/agent/[agentId]/agent-client.tsx +144 -174
  223. package/examples/playground/app/agent/[agentId]/command-receipt.test.tsx +65 -0
  224. package/examples/playground/app/agent/[agentId]/command-receipt.tsx +27 -0
  225. package/examples/playground/app/agent/[agentId]/compaction-event.tsx +25 -24
  226. package/examples/playground/app/agent/[agentId]/compaction-panel.test.tsx +119 -0
  227. package/examples/playground/app/agent/[agentId]/compaction-panel.tsx +208 -165
  228. package/examples/playground/app/agent/[agentId]/page.tsx +2 -16
  229. package/examples/playground/app/agent/events/route.ts +5 -2
  230. package/examples/playground/app/agent/ingress.test.ts +101 -0
  231. package/examples/playground/app/agent/model-input.test.tsx +58 -0
  232. package/examples/playground/app/agent/model-input.tsx +115 -0
  233. package/examples/playground/app/agent/model.test.ts +73 -0
  234. package/examples/playground/app/agent/model.ts +58 -26
  235. package/examples/playground/app/agent/new-agent-session.tsx +37 -19
  236. package/examples/playground/app/agent/page.tsx +4 -4
  237. package/examples/playground/app/agent/server.ts +19 -15
  238. package/examples/playground/app/agent/session.ts +5 -6
  239. package/examples/playground/app/agent/telemetry.test.ts +189 -0
  240. package/examples/playground/app/agent/telemetry.ts +30 -0
  241. package/examples/playground/app/agent/trace.test.ts +23 -0
  242. package/examples/playground/app/agent/trace.ts +18 -0
  243. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +12 -12
  244. package/examples/playground/app/canvas/[canvasId]/page.tsx +1 -2
  245. package/examples/playground/app/canvas/[canvasId]/session.ts +2 -2
  246. package/examples/playground/app/canvas/model.ts +53 -53
  247. package/examples/playground/app/chat/[chatId]/agent-state.test.ts +176 -0
  248. package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +16 -1
  249. package/examples/playground/app/chat/[chatId]/chat-client.tsx +55 -77
  250. package/examples/playground/app/chat/[chatId]/chat-view.ts +37 -3
  251. package/examples/playground/app/chat/[chatId]/page.tsx +7 -15
  252. package/examples/playground/app/chat/[chatId]/session.ts +2 -19
  253. package/examples/playground/app/chat/agent/route.ts +9 -0
  254. package/examples/playground/app/chat/model.test.ts +46 -119
  255. package/examples/playground/app/chat/model.ts +82 -128
  256. package/examples/playground/app/chat/scheduler/route.ts +2 -2
  257. package/examples/playground/app/chat/server.test.ts +112 -0
  258. package/examples/playground/app/chat/server.ts +113 -117
  259. package/examples/playground/app/components/activity-feed.tsx +30 -1
  260. package/examples/playground/app/components/activity-history.test.tsx +35 -0
  261. package/examples/playground/app/components/demo-icons.tsx +89 -0
  262. package/examples/playground/app/components/demos.tsx +33 -0
  263. package/examples/playground/app/components/fast-link.test.tsx +58 -0
  264. package/examples/playground/app/components/fast-link.tsx +55 -0
  265. package/examples/playground/app/components/site-header.tsx +96 -0
  266. package/examples/playground/app/counter/counter-client.tsx +3 -3
  267. package/examples/playground/app/counter/model.test.ts +3 -3
  268. package/examples/playground/app/counter/model.ts +11 -21
  269. package/examples/playground/app/counter/page.tsx +2 -15
  270. package/examples/playground/app/counter/session.ts +2 -2
  271. package/examples/playground/app/documents/[documentId]/code-editor.tsx +12 -1
  272. package/examples/playground/app/documents/[documentId]/document-client.tsx +10 -11
  273. package/examples/playground/app/documents/[documentId]/page.tsx +1 -2
  274. package/examples/playground/app/documents/[documentId]/session.ts +2 -2
  275. package/examples/playground/app/documents/model.ts +27 -27
  276. package/examples/playground/app/globals.css +420 -207
  277. package/examples/playground/app/initial-state.test.tsx +54 -0
  278. package/examples/playground/app/layout.tsx +7 -23
  279. package/examples/playground/app/orders/[orderId]/page.tsx +1 -2
  280. package/examples/playground/app/orders/[orderId]/session.ts +2 -2
  281. package/examples/playground/app/orders/model.ts +49 -49
  282. package/examples/playground/app/page.tsx +13 -102
  283. package/examples/playground/app/recovery/[recoveryId]/page.tsx +1 -2
  284. package/examples/playground/app/recovery/[recoveryId]/session.ts +2 -2
  285. package/examples/playground/app/recovery/model.ts +30 -30
  286. package/examples/playground/instrumentation.ts +5 -0
  287. package/examples/playground/next.config.ts +17 -5
  288. package/examples/playground/package.json +13 -2
  289. package/examples/playground/scripts/a0-template.ts +77 -0
  290. package/examples/playground/vercel.json +36 -0
  291. package/package.json +29 -3
  292. package/src/actor-client.ts +16 -4
  293. package/src/actor-react.ts +25 -11
  294. package/src/actor-shared.ts +21 -6
  295. package/src/actor.ts +76 -31
  296. package/src/ai-agent-actions.ts +219 -0
  297. package/src/ai-agent.ts +2517 -0
  298. package/src/ai-app-state.ts +91 -0
  299. package/src/ai-client-state.ts +6 -3
  300. package/src/ai-client.ts +62 -0
  301. package/src/ai-context-schema.ts +25 -5
  302. package/src/ai-context.ts +90 -40
  303. package/src/ai-control-server.ts +92 -72
  304. package/src/ai-coordinator.ts +23 -22
  305. package/src/ai-fx.browser.ts +5 -0
  306. package/src/ai-fx.ts +833 -0
  307. package/src/ai-harness.ts +518 -0
  308. package/src/ai-message-base.ts +209 -0
  309. package/src/ai-message-projection.ts +262 -64
  310. package/src/ai-model-metadata.ts +11 -6
  311. package/src/ai-pi.browser.ts +5 -0
  312. package/src/ai-pi.ts +1263 -0
  313. package/src/ai-progress-batches.ts +26 -0
  314. package/src/ai-projector.ts +95 -14
  315. package/src/ai-react.ts +146 -0
  316. package/src/ai-sdk-step.ts +2 -2
  317. package/src/ai-server.browser.ts +2 -2
  318. package/src/ai-server.ts +23 -1965
  319. package/src/ai-stored-state.ts +48 -163
  320. package/src/ai.ts +339 -155
  321. package/src/bootstrap-stream.ts +72 -0
  322. package/src/bounded-cache.ts +55 -0
  323. package/src/client-render-session.ts +49 -0
  324. package/src/client.ts +688 -151
  325. package/src/contract.ts +92 -42
  326. package/src/deterministic-id.ts +37 -0
  327. package/src/equal-json.ts +32 -0
  328. package/src/errors.ts +13 -1
  329. package/src/index.ts +5 -1
  330. package/src/initial-snapshot.ts +39 -0
  331. package/src/internal.ts +52 -0
  332. package/src/libfx.d.ts +34 -0
  333. package/src/postgres-notification-scope.ts +14 -3
  334. package/src/react.ts +171 -206
  335. package/src/redis-http-reply.ts +256 -0
  336. package/src/redis-http-stream.ts +73 -0
  337. package/src/redis-http-subscriptions.ts +13 -5
  338. package/src/reducer-runtime.ts +52 -0
  339. package/src/reducer.ts +93 -11
  340. package/src/scheduler-qstash.ts +49 -20
  341. package/src/scheduler-task.ts +34 -2
  342. package/src/scheduler-vercel.ts +32 -84
  343. package/src/server-fetch.ts +139 -35
  344. package/src/server.ts +1133 -255
  345. package/src/session-clear.ts +23 -0
  346. package/src/session-socket.ts +154 -49
  347. package/src/sse.ts +71 -4
  348. package/src/store-memory.ts +252 -75
  349. package/src/store-polling.ts +18 -4
  350. package/src/store-postgres.ts +541 -114
  351. package/src/store-redis-core.ts +1450 -493
  352. package/src/store-redis-http.ts +18 -2
  353. package/src/store-redis-notify.ts +262 -85
  354. package/src/store-redis.ts +19 -9
  355. package/src/store-sqlite.ts +319 -45
  356. package/src/store.ts +79 -1
  357. package/src/stream-buffer.ts +43 -0
  358. package/src/telemetry.ts +14 -1
  359. package/src/wire.ts +241 -13
  360. package/dist/actor-ohPC-81x.d.ts.map +0 -1
  361. package/dist/actor-shared-B5tJfzt-.js.map +0 -1
  362. package/dist/ai-CrEf6p_W.d.ts.map +0 -1
  363. package/dist/ai-DgOBltJ_.js.map +0 -1
  364. package/dist/client-BYzHjkwU.js.map +0 -1
  365. package/dist/client-CzyacQpJ.d.ts.map +0 -1
  366. package/dist/contract-CKRg_E4q.js.map +0 -1
  367. package/dist/errors-DCk6ch5n.js.map +0 -1
  368. package/dist/errors-DvhSXnxk.d.ts.map +0 -1
  369. package/dist/internal-Dq2qYxou.js.map +0 -1
  370. package/dist/react.d.ts.map +0 -1
  371. package/dist/reducer-DEMjEY_O.js +0 -29
  372. package/dist/reducer-DEMjEY_O.js.map +0 -1
  373. package/dist/reducer-otzHjuJj.d.ts.map +0 -1
  374. package/dist/scheduler-task-BpzhPnRS.js.map +0 -1
  375. package/dist/server-BD5ckxZb.js.map +0 -1
  376. package/dist/server-DbD7IJVK.d.ts.map +0 -1
  377. package/dist/store-DyZM6fS5.d.ts.map +0 -1
  378. package/dist/store-polling-CmxUbV93.js.map +0 -1
  379. package/dist/store-redis-notify-BVLUfI3j.js +0 -1583
  380. package/dist/store-redis-notify-BVLUfI3j.js.map +0 -1
  381. package/dist/telemetry-B5jzpy6y.d.ts.map +0 -1
  382. package/dist/validate-XKT4FSNn.js +0 -30
  383. package/dist/validate-XKT4FSNn.js.map +0 -1
  384. package/dist/wire-BO5wWCb1.js.map +0 -1
  385. package/docs/concepts/01-contracts.mdx +0 -142
  386. package/docs/concepts/02-handlers.mdx +0 -284
  387. package/docs/concepts/03-durability.mdx +0 -314
  388. package/docs/concepts/04-state.mdx +0 -209
  389. package/docs/guides/01-timers.mdx +0 -185
  390. package/docs/guides/02-cancellation.mdx +0 -161
  391. package/docs/guides/03-react.mdx +0 -384
  392. package/docs/guides/04-local-first.mdx +0 -88
  393. package/docs/guides/05-production.mdx +0 -521
  394. package/docs/guides/06-ai-agents.mdx +0 -1318
  395. package/docs/guides/08-application-data.mdx +0 -113
  396. package/docs/guides/09-presence.mdx +0 -266
  397. package/docs/guides/10-transports.mdx +0 -221
  398. package/docs/reference/01-api.mdx +0 -1896
  399. package/docs/reference/02-errors.mdx +0 -149
  400. package/examples/playground/app/agent/[agentId]/compaction/route.ts +0 -14
  401. package/examples/playground/app/agent/compaction-settings.test.ts +0 -144
  402. package/examples/playground/app/agent/compaction-settings.ts +0 -49
  403. package/examples/playground/app/agent/compaction-timeline.test.ts +0 -377
  404. package/examples/playground/app/agent/compaction-timeline.ts +0 -208
  405. /package/docs/{concepts → contract}/meta.ts +0 -0
  406. /package/docs/{guides → server}/meta.ts +0 -0
@@ -0,0 +1,518 @@
1
+ import type {
2
+ Experimental_SandboxSession,
3
+ FinishReason,
4
+ LanguageModelUsage,
5
+ ToolSet,
6
+ UIMessage,
7
+ UIMessageChunk,
8
+ } from 'ai'
9
+ import type {
10
+ GenerationCompletedPayload,
11
+ ReasoningLevel,
12
+ ToolResultPayload,
13
+ } from './ai.ts'
14
+ import { boundedCache, type BoundedCache } from './bounded-cache.ts'
15
+ import type { ContractEvent, EventDefs } from './contract.ts'
16
+
17
+ declare const harnessBrand: unique symbol
18
+
19
+ /**
20
+ * A coding agent's own loop for `agent({ harness })`, from `fx()` or `pi()`.
21
+ * `Tools` names the tools the harness brings, which `toolRecovery` may name.
22
+ */
23
+ export type Harness<
24
+ Type extends 'fx' | 'pi' = 'fx' | 'pi',
25
+ Tools extends string = string,
26
+ > = {
27
+ readonly type: Type
28
+ readonly [harnessBrand]: { readonly tools: Tools }
29
+ }
30
+
31
+ /** What a harness's sandbox resolver receives for one step or tool execution. */
32
+ export type HarnessSandboxContext = {
33
+ session: { readonly id: string }
34
+ signal: AbortSignal
35
+ }
36
+
37
+ /** Resolves the AI SDK sandbox session for an agent session, the same one every time. */
38
+ export type HarnessSandbox = (
39
+ context: HarnessSandboxContext,
40
+ ) => Experimental_SandboxSession | Promise<Experimental_SandboxSession>
41
+
42
+ /** What a harness step streams, as the default generator does. */
43
+ export type HarnessGeneration = {
44
+ stream: ReadableStream<UIMessageChunk>
45
+ completion: () => { finishReason?: FinishReason; usage?: LanguageModelUsage }
46
+ }
47
+
48
+ /** One stored snapshot and the log after it, read in one store operation. */
49
+ export type HarnessLogRead = {
50
+ snapshot: { index: number; state: unknown } | null
51
+ events: ContractEvent<EventDefs>[]
52
+ }
53
+
54
+ /** The session log as a harness step reads it, plus the state saved in it. */
55
+ export type HarnessLog = {
56
+ /** The latest saved state under `name` and the log after it; `fresh` reads it all. */
57
+ read(options: {
58
+ name: string
59
+ throughIndex: number
60
+ fresh?: boolean
61
+ }): Promise<HarnessLogRead>
62
+ write(options: { name: string; index: number; state: unknown }): Promise<void>
63
+ }
64
+
65
+ /** Everything one durable generation hands its harness. */
66
+ export type HarnessStep = {
67
+ agentName: string
68
+ sessionId: string
69
+ requestIndex: number
70
+ /** This attempt at the generation. */
71
+ generationId: string
72
+ responseMessageId: string
73
+ /** The log index this step's context was read through. */
74
+ throughIndex: number
75
+ /** The transcript through that index. */
76
+ messages: readonly UIMessage[]
77
+ model: string
78
+ reasoning?: ReasoningLevel
79
+ speed?: 'fast' | 'standard'
80
+ instructions: string[]
81
+ tools: ToolSet
82
+ log: HarnessLog
83
+ signal: AbortSignal
84
+ }
85
+
86
+ /** The internal side of a harness value. */
87
+ export type HarnessDriver = {
88
+ /** The session's sandbox; every local tool execution receives it. */
89
+ readonly sandbox?: HarnessSandbox
90
+ /** Tools the harness brings; A2 executes them like the agent's own. */
91
+ readonly tools: ToolSet
92
+ step(step: HarnessStep): Promise<HarnessGeneration>
93
+ }
94
+
95
+ // A global symbol, so harness values work across separately bundled copies.
96
+ const DRIVER = Symbol.for('experimental-a2.ai.harness')
97
+
98
+ export function defineHarness<
99
+ Type extends 'fx' | 'pi',
100
+ Tools extends string = never,
101
+ >(type: Type, driver: HarnessDriver): Harness<Type, Tools> {
102
+ const harness = { type }
103
+ Object.defineProperty(harness, DRIVER, { value: driver })
104
+ return Object.freeze(harness) as unknown as Harness<Type, Tools>
105
+ }
106
+
107
+ export function harnessDriver(harness: unknown): HarnessDriver {
108
+ const driver =
109
+ typeof harness === 'object' && harness !== null
110
+ ? (harness as { [DRIVER]?: HarnessDriver })[DRIVER]
111
+ : undefined
112
+ if (driver === undefined)
113
+ throw new TypeError(
114
+ "harness must be { type: 'ai-sdk' }, or come from fx() or pi()",
115
+ )
116
+ return driver
117
+ }
118
+
119
+ // ------------------------------------------------------- saved state
120
+
121
+ /**
122
+ * What an agent's steps saved in this process at the end of a response, per
123
+ * session and harness. A cache: a cold process rebuilds from the whole log.
124
+ */
125
+ export type HarnessStates = BoundedCache<
126
+ string,
127
+ { index: number; state: unknown }
128
+ >
129
+
130
+ export const harnessStates = (): HarnessStates =>
131
+ boundedCache({ maxEntries: 1_000, maxBytes: 64 * 1024 * 1024 })
132
+
133
+ const savedKey = (sessionId: string, name: string): string =>
134
+ `${sessionId}\u0000${name}`
135
+
136
+ // Binary state counts its bytes; everything else its JSON text.
137
+ const sizeOf = (value: unknown): number => {
138
+ let binary = 0
139
+ const text = JSON.stringify(value, (_key, item: unknown) => {
140
+ if (!(item instanceof Uint8Array)) return item
141
+ binary += item.byteLength
142
+ return null
143
+ })
144
+ return binary + (text?.length ?? 0)
145
+ }
146
+
147
+ /**
148
+ * The session log as a harness step reads it: the state this process saved
149
+ * at the end of the last response, when it has one, and the log after it.
150
+ * Saved states are copied in and out, so a step cannot change one in place.
151
+ */
152
+ export function harnessLog(options: {
153
+ states: HarnessStates
154
+ session: {
155
+ readonly id: string
156
+ history(bounds: {
157
+ gte?: number
158
+ lte?: number
159
+ }): Promise<ContractEvent<EventDefs>[]>
160
+ }
161
+ }): HarnessLog {
162
+ const { states, session } = options
163
+ return {
164
+ read: async ({ name, throughIndex, fresh }) => {
165
+ const entry = fresh ? undefined : states.get(savedKey(session.id, name))
166
+ const snapshot =
167
+ entry === undefined || entry.index > throughIndex
168
+ ? null
169
+ : { index: entry.index, state: structuredClone(entry.state) }
170
+ const events = await session.history(
171
+ snapshot === null
172
+ ? { lte: throughIndex }
173
+ : { gte: snapshot.index + 1, lte: throughIndex },
174
+ )
175
+ return { snapshot, events }
176
+ },
177
+ write: async ({ name, index, state }) => {
178
+ const copy = structuredClone(state)
179
+ states.set(
180
+ savedKey(session.id, name),
181
+ { index, state: copy },
182
+ sizeOf(copy),
183
+ )
184
+ },
185
+ }
186
+ }
187
+
188
+ const agentStates = new WeakMap<object, HarnessStates>()
189
+
190
+ /** Registers an agent server's saved harness states, for `savedHarnessState`. */
191
+ export function registerHarnessStates(
192
+ server: object,
193
+ states: HarnessStates,
194
+ ): void {
195
+ agentStates.set(server, states)
196
+ }
197
+
198
+ /** What an agent's process saved for one session's harness; tests read it. */
199
+ export function savedHarnessState(
200
+ server: object,
201
+ options: { sessionId: string; name: string },
202
+ ): { index: number; state: unknown } | undefined {
203
+ return agentStates.get(server)?.get(savedKey(options.sessionId, options.name))
204
+ }
205
+
206
+ /** A harness's state at the end of a response, from the attempt that ran it. */
207
+ type SavedEnvelope = {
208
+ generationId: string
209
+ responseMessageId: string
210
+ state: unknown
211
+ }
212
+
213
+ export type HarnessRead<S> = {
214
+ /** The state saved at the end of the last response, when it is usable. */
215
+ saved: S | undefined
216
+ turns: HarnessTurn[]
217
+ results: Map<string, ToolResultPayload>
218
+ }
219
+
220
+ /**
221
+ * Reads a harness's saved state and the log since, as turns to replay. A
222
+ * snapshot counts only when the attempt that wrote it committed: a stopped,
223
+ * superseded, or still-running attempt can write one the log never kept.
224
+ * `replayAll` reads the whole log instead, for a state that fails to restore.
225
+ */
226
+ export async function readHarness<S>({
227
+ step,
228
+ name,
229
+ parse,
230
+ }: {
231
+ step: HarnessStep
232
+ name: string
233
+ parse: (state: unknown) => S | undefined
234
+ }): Promise<HarnessRead<S> & { replayAll: () => Promise<HarnessRead<S>> }> {
235
+ const replayAll = async (): Promise<HarnessRead<S>> => {
236
+ const read = await step.log.read({
237
+ name,
238
+ throughIndex: step.throughIndex,
239
+ fresh: true,
240
+ })
241
+ return { saved: undefined, ...harnessTurns(step, read.events, undefined) }
242
+ }
243
+ const read = await step.log.read({ name, throughIndex: step.throughIndex })
244
+ if (read.snapshot === null)
245
+ return {
246
+ saved: undefined,
247
+ ...harnessTurns(step, read.events, undefined),
248
+ replayAll,
249
+ }
250
+ const envelope = savedEnvelope(read.snapshot.state)
251
+ const saved = envelope === undefined ? undefined : parse(envelope.state)
252
+ const committed =
253
+ envelope !== undefined &&
254
+ read.events.some(
255
+ (event) =>
256
+ event.type === 'ai.generation.completed' &&
257
+ (event.payload as { generationId?: unknown }).generationId ===
258
+ envelope.generationId,
259
+ )
260
+ // A snapshot of this very response belongs to an earlier attempt at it.
261
+ if (
262
+ saved === undefined ||
263
+ !committed ||
264
+ envelope.responseMessageId === step.responseMessageId
265
+ )
266
+ return { ...(await replayAll()), replayAll }
267
+ return {
268
+ saved,
269
+ ...harnessTurns(step, read.events, envelope.responseMessageId),
270
+ replayAll,
271
+ }
272
+ }
273
+
274
+ /** Saves a harness's state at the end of a response; losing it costs a longer replay. */
275
+ export async function saveHarness({
276
+ step,
277
+ name,
278
+ state,
279
+ }: {
280
+ step: HarnessStep
281
+ name: string
282
+ state: unknown
283
+ }): Promise<void> {
284
+ const envelope: SavedEnvelope = {
285
+ generationId: step.generationId,
286
+ responseMessageId: step.responseMessageId,
287
+ state,
288
+ }
289
+ try {
290
+ await step.log.write({ name, index: step.requestIndex, state: envelope })
291
+ } catch {
292
+ // The snapshot is a cache.
293
+ }
294
+ }
295
+
296
+ function savedEnvelope(value: unknown): SavedEnvelope | undefined {
297
+ if (typeof value !== 'object' || value === null) return undefined
298
+ const { generationId, responseMessageId, state } = value as Record<
299
+ string,
300
+ unknown
301
+ >
302
+ return typeof generationId === 'string' &&
303
+ typeof responseMessageId === 'string'
304
+ ? { generationId, responseMessageId, state }
305
+ : undefined
306
+ }
307
+
308
+ // ------------------------------------------------- the log as harness turns
309
+
310
+ // A2's reason on `ai.message.interrupted` when a steer ends a response.
311
+ const STEERED = 'steered after step'
312
+
313
+ /** A completed generation as the log recorded it. */
314
+ export type RecordedGeneration = {
315
+ chunks: UIMessageChunk[]
316
+ completed: GenerationCompletedPayload
317
+ }
318
+
319
+ /** One harness turn to rebuild: its prompt, completed generations, and end. */
320
+ export type HarnessTurn = {
321
+ prompt: string
322
+ generations: RecordedGeneration[]
323
+ /** Steering that entered after the generation at that index. */
324
+ steers: Map<number, string[]>
325
+ end: 'stop' | 'interrupted' | 'live'
326
+ }
327
+
328
+ /**
329
+ * Groups the log since a harness snapshot into harness turns. A response
330
+ * steered after a step continues its turn, with the next response's prompt as
331
+ * steering. `covered` is the response the snapshot already holds.
332
+ */
333
+ export function harnessTurns(
334
+ step: HarnessStep,
335
+ events: readonly ContractEvent<EventDefs>[],
336
+ covered: string | undefined,
337
+ ): { turns: HarnessTurn[]; results: Map<string, ToolResultPayload> } {
338
+ type Generation = {
339
+ id: string
340
+ chunks: UIMessageChunk[]
341
+ completed?: GenerationCompletedPayload
342
+ }
343
+ type Response = {
344
+ id: string
345
+ prompt: string[]
346
+ generations: Generation[]
347
+ end?: 'stop' | 'steered' | 'interrupted'
348
+ }
349
+ // Queued messages are admitted together, possibly before the snapshot.
350
+ const userText = new Map<string, string>(
351
+ step.messages
352
+ .filter((message) => message.role === 'user')
353
+ .map((message) => [message.id, textOf(message)]),
354
+ )
355
+ let passive: string[] = []
356
+ const responses = new Map<string, Response>()
357
+ const byStart = new Map<number, Generation>()
358
+ const byId = new Map<string, Generation>()
359
+ const results = new Map<string, ToolResultPayload>()
360
+
361
+ for (const event of events) {
362
+ const payload = event.payload as Record<string, unknown>
363
+ switch (event.type) {
364
+ case 'ai.message.created': {
365
+ const message = payload['message'] as UIMessage
366
+ if (message.role !== 'user') break
367
+ userText.set(message.id, textOf(message))
368
+ if (payload['generate'] === false) passive.push(message.id)
369
+ break
370
+ }
371
+ case 'ai.generation.requested': {
372
+ const id = payload['responseMessageId'] as string
373
+ if (id === covered || responses.has(id)) break
374
+ const messageId = payload['messageId'] as string
375
+ const ids = [...passive.filter((p) => p !== messageId), messageId]
376
+ passive = []
377
+ responses.set(id, {
378
+ id,
379
+ prompt: ids.flatMap((p) => userText.get(p) ?? []),
380
+ generations: [],
381
+ })
382
+ break
383
+ }
384
+ case 'ai.generation.started': {
385
+ const response = responses.get(payload['responseMessageId'] as string)
386
+ if (response === undefined) break
387
+ const generation: Generation = {
388
+ id: payload['generationId'] as string,
389
+ chunks: [],
390
+ }
391
+ response.generations.push(generation)
392
+ byStart.set(event.index, generation)
393
+ byId.set(generation.id, generation)
394
+ break
395
+ }
396
+ case 'ai.generation.progress':
397
+ byStart
398
+ .get(payload['startIndex'] as number)
399
+ ?.chunks.push(...(payload['chunks'] as UIMessageChunk[]))
400
+ break
401
+ case 'ai.generation.completed': {
402
+ const generation = byId.get(payload['generationId'] as string)
403
+ if (generation)
404
+ generation.completed = event.payload as GenerationCompletedPayload
405
+ break
406
+ }
407
+ case 'ai.tool.result':
408
+ if (payload['preliminary'] !== true)
409
+ results.set(
410
+ payload['toolCallId'] as string,
411
+ event.payload as ToolResultPayload,
412
+ )
413
+ break
414
+ case 'ai.message.completed': {
415
+ const response = responses.get(payload['messageId'] as string)
416
+ if (response) response.end = 'stop'
417
+ break
418
+ }
419
+ case 'ai.message.interrupted': {
420
+ const response = responses.get(payload['messageId'] as string)
421
+ if (response)
422
+ response.end =
423
+ payload['reason'] === STEERED ? 'steered' : 'interrupted'
424
+ break
425
+ }
426
+ }
427
+ }
428
+
429
+ const turns: HarnessTurn[] = []
430
+ let steered = false
431
+ for (const response of responses.values()) {
432
+ const text = response.prompt.join('\n\n')
433
+ let turn = turns.at(-1)
434
+ if (steered && turn !== undefined) {
435
+ const at = Math.max(0, turn.generations.length - 1)
436
+ turn.steers.set(at, [...(turn.steers.get(at) ?? []), text])
437
+ } else {
438
+ turn = { prompt: text, generations: [], steers: new Map(), end: 'live' }
439
+ turns.push(turn)
440
+ }
441
+ for (const generation of response.generations)
442
+ if (generation.completed !== undefined)
443
+ turn.generations.push({
444
+ chunks: generation.chunks,
445
+ completed: generation.completed,
446
+ })
447
+ turn.end =
448
+ response.id === step.responseMessageId
449
+ ? 'live'
450
+ : response.end === 'stop'
451
+ ? 'stop'
452
+ : 'interrupted'
453
+ steered = response.end === 'steered'
454
+ }
455
+ return { turns, results }
456
+ }
457
+
458
+ function textOf(message: UIMessage): string {
459
+ return message.parts
460
+ .flatMap((part) => (part.type === 'text' ? [part.text] : []))
461
+ .join('\n')
462
+ }
463
+
464
+ // ------------------------------------------------------------- Gateway
465
+
466
+ export type GatewayCredential = { token: string; method: 'api-key' | 'oidc' }
467
+
468
+ /** Read per step: on Vercel the OIDC token rides on each function request. */
469
+ export function gatewayCredential(harness: string): GatewayCredential {
470
+ const key = process.env['AI_GATEWAY_API_KEY']
471
+ if (key) return { token: key, method: 'api-key' }
472
+ const oidc = requestOidcToken() ?? process.env['VERCEL_OIDC_TOKEN']
473
+ if (oidc) return { token: oidc, method: 'oidc' }
474
+ throw new Error(`${harness}() needs AI_GATEWAY_API_KEY or VERCEL_OIDC_TOKEN`)
475
+ }
476
+
477
+ // Where Vercel Functions keep the current request, as @vercel/oidc reads it.
478
+ const REQUEST_CONTEXT = Symbol.for('@vercel/request-context')
479
+
480
+ function requestOidcToken(): string | undefined {
481
+ const context = (
482
+ globalThis as {
483
+ [REQUEST_CONTEXT]?: { get?: () => { headers?: Record<string, unknown> } }
484
+ }
485
+ )[REQUEST_CONTEXT]
486
+ const token = context?.get?.()?.headers?.['x-vercel-oidc-token']
487
+ return typeof token === 'string' && token !== '' ? token : undefined
488
+ }
489
+
490
+ // ------------------------------------------------------------- helpers
491
+
492
+ export class Divergence extends Error {
493
+ constructor(harness: string, message: string) {
494
+ super(`${harness} replay diverged from the log: ${message}`)
495
+ }
496
+ }
497
+
498
+ export type Deferred = { promise: Promise<void>; resolve: () => void }
499
+
500
+ export function deferred(): Deferred {
501
+ let resolve!: () => void
502
+ const promise = new Promise<void>((done) => {
503
+ resolve = done
504
+ })
505
+ return { promise, resolve }
506
+ }
507
+
508
+ /** A result that never settles; the harness is stopped instead. */
509
+ export function pending(
510
+ signal: AbortSignal | null | undefined,
511
+ ): Promise<never> {
512
+ return new Promise((_, reject) => {
513
+ if (signal?.aborted) reject(signal.reason)
514
+ signal?.addEventListener('abort', () => reject(signal.reason), {
515
+ once: true,
516
+ })
517
+ })
518
+ }