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
package/docs/index.mdx CHANGED
@@ -1,27 +1,20 @@
1
1
  ---
2
2
  title: Introduction
3
- description: A2 is durable sync and reactions for things with a lifecycle. Append or schedule events, run handlers, and keep one live view from server to browser.
3
+ description: A2 syncs your immutable event log, from server to browser.
4
4
  ---
5
5
 
6
6
  ```bash
7
7
  pnpm add experimental-a2
8
8
  ```
9
9
 
10
- A2 is durable sync and reactions for things with a lifecycle.
11
-
12
- An order, agent run, approval, or import gets a session. You append events.
13
- Handlers react to them, and usually return the next one. The browser follows
14
- the same log and folds the same state as the server. That's the whole model;
15
- the rest of this page is it happening.
16
-
17
- Events record facts, reducers compute the current view, and handlers perform
18
- the reactions.
10
+ ```bash
11
+ npx skills add vercel-labs/a2
12
+ ```
19
13
 
20
- ## Define a contract
14
+ ## Define a shared contract
21
15
 
22
- Events are the vocabulary. A contract names them once, as a plain
23
- importable value. The server implements it, and the browser types itself
24
- off it later.
16
+ Name the events once. The server implements the contract, and the browser
17
+ types itself off it.
25
18
 
26
19
  ```ts contracts.ts
27
20
  import { z } from 'zod'
@@ -30,152 +23,143 @@ import * as a2 from 'experimental-a2'
30
23
  export const orders = a2.contract({
31
24
  name: 'orders',
32
25
  events: {
33
- created: z.object({ items: z.array(z.string()) }),
34
- 'shop.notified': z.object({}),
35
- cancelled: z.object({}),
26
+ 'order.created': z.object({
27
+ shopId: z.string(),
28
+ items: z.array(z.string()),
29
+ }),
30
+ 'shop.notified': z.object({ shopId: z.string() }),
31
+ 'courier.assigned': z.object({ courierId: z.string() }),
32
+ 'order.delivered': z.object({ signedBy: z.string() }),
33
+ 'order.cancelled': z.object({ reason: z.string() }),
34
+ },
35
+ reducer: {
36
+ name: 'order-status',
37
+ initialState: { status: 'new' },
38
+ fold: (state, event) => ({ status: event.type }),
36
39
  },
37
40
  })
38
41
  ```
39
42
 
40
- ## React to events
43
+ ## Implement the server
41
44
 
42
- Handlers are plain async functions. Each one reacts to a fact and usually
43
- returns the next one.
45
+ Bind the contract to a store, a scheduler, and the handlers that react to its
46
+ events.
44
47
 
45
48
  ```ts server/orders.ts
46
49
  import { createServer } from 'experimental-a2/server'
50
+ import { vercelQueues } from 'experimental-a2/scheduler-vercel'
51
+ import { redis } from 'experimental-a2/store-redis'
47
52
  import { orders } from '@/contracts'
48
53
 
49
54
  export const ordersServer = createServer({
50
55
  contract: orders,
56
+ store: redis({ url: process.env.REDIS_URL }),
57
+ scheduler: vercelQueues(),
51
58
  handlers: {
52
- created: async ({ event }) => {
59
+ 'order.created': async ({ event }) => {
53
60
  // your side effect; event.id makes a stable idempotency key:
54
61
  // await notifyShop(event.payload, { idempotencyKey: event.id })
55
- return { type: 'shop.notified', payload: {} }
62
+ const { shopId } = event.payload
63
+ return { type: 'shop.notified', payload: { shopId } }
56
64
  },
57
65
  },
58
66
  })
59
67
  ```
60
68
 
61
- ## Open a session
62
-
63
- A session is one instance of the contract, with its own ordered log. It is the
64
- thing A2 keeps durable and live. The id is yours:
65
-
66
- - `session('order-8194')`: an order moving through fulfillment
67
- - `session('chat-a8c1')`: an agent chat streaming its reply
68
- - `session('cart-julian')`: a shopping cart
69
- - `session('doc-roadmap')`: a document with three people typing in it
70
-
71
- Anything whose story spans more than one request. Put events in the same
72
- session when they form one history or view. Handlers are concurrent unless
73
- they share a lane. Any server code can open
74
- one and append: a route handler, a webhook, a cron job.
69
+ One route serves every session to the browser:
75
70
 
76
71
  ```ts app/api/orders/route.ts
77
72
  import { ordersServer } from '@/server/orders'
78
73
 
79
- export async function POST(req: Request) {
80
- const body = await req.json()
81
- await ordersServer.session(body.orderId).append({
82
- type: 'created',
83
- payload: { items: body.items },
84
- })
85
- return Response.json({ ok: true })
86
- }
74
+ export const GET = ordersServer.fetch
75
+ export const POST = ordersServer.fetch
87
76
  ```
88
77
 
89
- A2 commits the event before its handler can start. The handler may begin before
90
- `append` returns; the return confirms durability, not handler completion.
91
- A queue-backed scheduler wakes pending work after a crash or timeout. The same
92
- scheduler lets a session append a typed event later with
93
- `session.schedule(name, { delay: '30s' }, event)`.
94
-
95
- ## State is a fold
78
+ ## Implement the client
96
79
 
97
- There is no separate state record for the session to keep in sync. Fold its log
98
- through a reducer, a pure function derived from the contract. It imports
99
- nothing server-only, which is about to matter.
80
+ The browser follows a session over SSE or a
81
+ [WebSocket](/client/transports) and folds the same state. `push` applies
82
+ instantly and rolls back if the server says no.
100
83
 
101
- ```ts reducer.ts
84
+ ```tsx app/orders/[orderId]/order.tsx
85
+ 'use client'
86
+ import { createClient } from 'experimental-a2/client'
87
+ import { useSession } from 'experimental-a2/react'
102
88
  import { orders } from '@/contracts'
103
89
 
104
- export const orderStatus = orders
105
- .reducer({ name: 'order-status', initialState: { status: 'new' } })
106
- .fold((state, event) => {
107
- switch (event.type) {
108
- case 'created':
109
- return { status: 'created' }
110
- case 'shop.notified':
111
- return { status: 'notified' }
112
- case 'cancelled':
113
- return { status: 'cancelled' }
114
- default:
115
- return state
116
- }
117
- })
118
- ```
119
-
120
- ```ts
121
- // anywhere on the server:
122
- import { ordersServer } from '@/server/orders'
123
- import { orderStatus } from '@/reducer'
90
+ const ordersClient = createClient({
91
+ contract: orders,
92
+ // SSE; for a WebSocket: { type: 'ws', url: '/api/orders' }
93
+ api: '/api/orders',
94
+ })
124
95
 
125
- const { state } = await ordersServer.session(orderId).state(orderStatus)
126
- // state → { status: 'notified' }
96
+ export function Order({ orderId }: { orderId: string }) {
97
+ const { state, push } = useSession(ordersClient, orderId)
98
+ return (
99
+ <button
100
+ onClick={() =>
101
+ void push({ type: 'order.cancelled', payload: { reason: 'customer' } })
102
+ }
103
+ >
104
+ {state.status} · cancel
105
+ </button>
106
+ )
107
+ }
127
108
  ```
128
109
 
129
- ## The browser joins the session
130
-
131
- The reducer is isomorphic, so the browser runs the same fold the server
132
- does. A session streams to the client live and takes optimistic writes,
133
- all typed by the one contract:
110
+ ## It's just an event log
134
111
 
135
- ```ts app/orders/[orderId]/session.ts
136
- 'use client'
137
- import { createReact } from 'experimental-a2/react'
138
- import { orderStatus } from '@/reducer'
112
+ ```ts
113
+ // anywhere on the server: a route, a webhook, a cron job
114
+ import { ordersServer } from '@/server/orders'
139
115
 
140
- export const { SessionProvider, useSession } = createReact({
141
- reducer: orderStatus,
116
+ const order = ordersServer.session('order-8194')
117
+ await order.append({
118
+ type: 'courier.assigned',
119
+ payload: { courierId: 'courier-7' },
142
120
  })
121
+ const events = await order.history()
122
+ // order.created, shop.notified, courier.assigned
143
123
  ```
144
124
 
145
- ```tsx app/orders/[orderId]/order-client.tsx
146
- 'use client'
147
- import { useSession } from './session'
125
+ A session is the ordered list of what happened. State is a fold over it, on
126
+ both sides of the wire. Everything else A2 keeps is a cache it can rebuild
127
+ from the log.
148
128
 
149
- export function OrderStatus() {
150
- const { state, connection, push } = useSession()
151
- return (
152
- <div>
153
- {state.status}
154
- {connection.status === 'live' ? ' · live' : ''}
155
- <button onClick={() => void push({ type: 'cancelled', payload: {} })}>
156
- Cancel order
157
- </button>
158
- </div>
159
- )
160
- }
161
- ```
129
+ ## With strong guarantees
162
130
 
163
- `push` applies instantly, validates against the contract before anything
164
- leaves the browser, and rolls back if the server says no. Mounting
165
- `SessionProvider` and the small stream route it talks to takes about
166
- twenty lines; [Live UI](/guides/react) wires it end to end.
131
+ - Appends are effectively-once.
132
+ - The log stays ordered.
133
+ - Handlers are at-least-once.
134
+ - Returned events commit with the handler's completion.
135
+ - Handlers run concurrently, unless they share a lane.
136
+ - Failures stay contained.
137
+ - A failing handler never makes `append` throw.
167
138
 
168
- ## The properties
139
+ [Guarantees](/server/guarantees) has the details and the limits.
169
140
 
170
- - **Handlers are plain async functions.** They run concurrently by default.
171
- Use a lane for selective FIFO execution.
172
- - **Handlers are optional per event type.** A history-only event settles during
173
- append and creates no reaction or scheduler work.
174
- - **History is real.** [`history()`](/concepts/state) returns what
175
- actually happened, in order. Debugging is reading, not reconstructing.
176
- - **Nothing inside a session is sacred except its log.** Snapshots, claims, queue
177
- messages: all disposable caches. Delete them and A2 rebuilds
178
- everything from the log.
141
+ ## Go further...
142
+
143
+ <CardGroup cols={2}>
144
+ <Card title="Handlers" href="/server/handlers" icon="zap">
145
+ Retries, lanes, and idempotency.
146
+ </Card>
147
+ <Card title="State" href="/contract/state" icon="layers">
148
+ Reducers and the current view.
149
+ </Card>
150
+ <Card title="History" href="/contract/state#history" icon="history">
151
+ The raw log, oldest first.
152
+ </Card>
153
+ <Card title="AI" href="/agents/introduction" icon="bot">
154
+ Agents with tools and approvals.
155
+ </Card>
156
+ <Card title="Timers" href="/server/timers" icon="clock">
157
+ Schedule an event for later.
158
+ </Card>
159
+ <Card title="Production" href="/server/production" icon="rocket">
160
+ A store and a scheduler.
161
+ </Card>
162
+ </CardGroup>
179
163
 
180
164
  ## FAQ
181
165
 
@@ -187,7 +171,7 @@ a durable event log. Events settle in their append transaction, with no drain,
187
171
  claim, or queue message. A contract can also mix handled and history-only event
188
172
  types. A2 decides per event type.
189
173
 
190
- See [Events without handlers](/concepts/handlers#events-without-handlers).
174
+ See [Events without handlers](/server/handlers#events-without-handlers).
191
175
 
192
176
  </details>
193
177
 
@@ -197,7 +181,7 @@ See [Events without handlers](/concepts/handlers#events-without-handlers).
197
181
  Configure Vercel Queues or QStash, then call
198
182
  `session.schedule(name, { delay: '30s' }, event)` or use `{ at: Date }`. The
199
183
  same scheduler route handles recovery and the delayed append. Names and omitted
200
- event ids stay stable across retries. See [Timers](/guides/timers).
184
+ event ids stay stable across retries. See [Timers](/server/timers).
201
185
 
202
186
  </details>
203
187
 
@@ -206,7 +190,7 @@ event ids stay stable across retries. See [Timers](/guides/timers).
206
190
 
207
191
  Cancellation is an event too: same route, same auth, same log. Handlers
208
192
  opt in with `abortOn` and receive a live `AbortSignal`; reducers cut the
209
- derived view exactly. See [Cancellation](/guides/cancellation).
193
+ derived view exactly. See [Cancellation](/server/cancellation).
210
194
 
211
195
  </details>
212
196
 
@@ -214,8 +198,9 @@ derived view exactly. See [Cancellation](/guides/cancellation).
214
198
  <summary>What happens when a handler keeps failing?</summary>
215
199
 
216
200
  It retries with backoff, then dead-letters after ten caught failures. Later
217
- events in the same lane wait; unlaned events and other lanes continue.
218
- [Durability](/concepts/durability) has the exact guarantees and the
201
+ events in the same lane wait until you retry or skip it; unlaned events and
202
+ other lanes continue.
203
+ [Guarantees](/server/guarantees) has the exact guarantees and the
219
204
  recovery story behind them.
220
205
 
221
206
  </details>
@@ -227,7 +212,7 @@ A durable store backend, such as Postgres or Redis. Add a queue-backed scheduler
227
212
  when the contract has handlers or calls `session.schedule`. A history-only
228
213
  contract with no timers needs no reaction infrastructure. Development needs
229
214
  neither: SQLite appears under `.a2/` and state survives restarts. See
230
- [Going to production](/guides/production).
215
+ [Production](/server/production).
231
216
 
232
217
  </details>
233
218
 
@@ -243,10 +228,10 @@ does not replicate database tables or subscribe to queries across sessions.
243
228
  <details>
244
229
  <summary>Where does my application database fit?</summary>
245
230
 
246
- A2 does not replace it. Use A2 for things with a lifecycle. Keep collections,
231
+ A2 does not replace it. Keep collections,
247
232
  relationships, constraints, search, and reporting in your application
248
233
  database. Split ownership instead of writing the same fact through both paths.
249
- See [A2 and your database](/guides/application-data).
234
+ See [Sessions and your database](/contract/sessions#sessions-and-your-database).
250
235
 
251
236
  </details>
252
237
 
@@ -256,35 +241,6 @@ See [A2 and your database](/guides/application-data).
256
241
  Yes. Every installation includes a standalone Next.js playground at
257
242
  `node_modules/experimental-a2/examples/playground`. It contains complete
258
243
  contracts, reducers, servers, route handlers, clients, and schedulers using only
259
- public package entry points. See [Complete examples](/guides/examples).
244
+ public package entry points. See [Complete examples](/examples).
260
245
 
261
246
  </details>
262
-
263
- ## Where to next
264
-
265
- <CardGroup cols={2}>
266
- <Card title="Quickstart" href="/quickstart" icon="rocket">
267
- A contract, a handler, and a durable append in five minutes.
268
- </Card>
269
- <Card title="Contracts and sessions" href="/concepts/contracts" icon="folder">
270
- The two nouns you'll use everywhere.
271
- </Card>
272
- <Card title="Durability" href="/concepts/durability" icon="wrench">
273
- What A2 guarantees, and exactly how.
274
- </Card>
275
- <Card title="Live UI with React" href="/guides/react" icon="lightbulb">
276
- Stream a session to the browser with optimistic writes.
277
- </Card>
278
- <Card title="Durable AI agents" href="/guides/ai-agents" icon="bot">
279
- Run AI SDK agents with durable messages, progress, tools, and approvals.
280
- </Card>
281
- <Card title="A2 and your database" href="/guides/application-data" icon="database">
282
- Decide what belongs in a session and what belongs in ordinary tables.
283
- </Card>
284
- <Card title="Actors" href="/actors/introduction" icon="boxes">
285
- Durable objects on the log: typed state, one message at a time.
286
- </Card>
287
- <Card title="Complete examples" href="/guides/examples" icon="code">
288
- Read or copy the standalone Next.js playground included with the package.
289
- </Card>
290
- </CardGroup>
@@ -0,0 +1,139 @@
1
+ ---
2
+ title: Core
3
+ description: "Every entry point, and the isomorphic `experimental-a2` core: contracts, reducers, IDs, and the event shape."
4
+ ---
5
+
6
+ ## Entry points
7
+
8
+ | Entry point | Ships | Peer dependency |
9
+ | --- | --- | --- |
10
+ | `experimental-a2` | `contract`, `A2Error`: isomorphic core | none |
11
+ | `experimental-a2/server` | `createServer`: implement a contract | none |
12
+ | `experimental-a2/client` | `createClient`: framework-agnostic session client | none |
13
+ | `experimental-a2/react` | `createReact` | `react` |
14
+ | `experimental-a2/ai` | `agentContract`, `handlerContext`, `inputs`, and the AI reducer: isomorphic | `ai` |
15
+ | `experimental-a2/ai/server` | `agent`: an agent's loop as an A2 server | `ai` |
16
+ | `experimental-a2/ai/fx` | `fx`: the FX harness for `agent()` | `ai`, `libfx` |
17
+ | `experimental-a2/ai/pi` | `pi`: the Pi harness for `agent()` | `ai`, `@earendil-works/pi-coding-agent`, `@earendil-works/pi-ai` |
18
+ | `experimental-a2/ai/client` | `createAgentClient`: contract-free agent client | `ai` |
19
+ | `experimental-a2/ai/react` | `useAgent` | `ai`, `react` |
20
+ | [`experimental-a2/store-postgres`](/reference/adapters#experimental-a2store-postgres) | `postgres`: Postgres store backend | `pg` (or inject a client) |
21
+ | [`experimental-a2/store-redis`](/reference/adapters#experimental-a2store-redis) | `redis`: Redis Streams store backend, push-native streaming | `ioredis` (or inject a client) |
22
+ | [`experimental-a2/store-redis-http`](/reference/adapters#experimental-a2store-redis-http) | `redisHttp`: the same Redis store over provider REST APIs (Upstash) | none |
23
+ | `experimental-a2/store-sqlite` | SQLite store backend | none |
24
+ | `experimental-a2/store-memory` | in-memory store backend | none |
25
+ | `experimental-a2/scheduler-vercel` | `vercelQueues`: recovery and timers | `@vercel/queue` |
26
+ | `experimental-a2/scheduler-qstash` | `qstash`: signed recovery and timers | `@upstash/qstash` |
27
+ | `experimental-a2/cache-indexeddb` | `indexedDb` browser cache | none |
28
+ | `experimental-a2/otel` | `otel` telemetry adapter | `@opentelemetry/api` |
29
+
30
+ `experimental-a2` imports none of the backends, and a browser-bundle test in CI
31
+ enforces it. Importing a backend's entry point, such as
32
+ `experimental-a2/store-postgres`, is what pulls that backend in; core never puts
33
+ one in your client bundle.
34
+
35
+ ## `experimental-a2`
36
+
37
+ ### `a2.contract(options)`
38
+
39
+ ```ts
40
+ a2.contract(options: {
41
+ name: string
42
+ events: Record<string, StandardSchemaV1>
43
+ presence?: Record<string, StandardSchemaV1>
44
+ reducer?: { name: string; initialState: S; stateSchema?: StandardSchemaV1; fold: (state: S, event: Event) => S }
45
+ }): Contract
46
+ ```
47
+
48
+ Defines one kind of lifecycle. The result is a plain, importable,
49
+ **isomorphic** value: the server implements it, reducers derive from it, and
50
+ the browser types its pushes off it. See [Events](/contract/events).
51
+
52
+ | Option | Meaning |
53
+ | --- | --- |
54
+ | `name` | Unique per app; identifies the contract in storage and queue messages. May not contain the control character U+001F. |
55
+ | `events` | Event type to payload schema. Types may not start with `a2.`, which A2 reserves for its own events, such as `a2.cleared`. |
56
+ | `presence` | Optional. Field to schema for one participant's ephemeral state. Replicated last-writer-wins, never stored in the log, invisible to reducers. See [Presence](/client/presence). |
57
+ | `reducer` | Optional. The one reducer the contract publishes to clients; an inline definition includes `fold`. See [`reducer(options)`](#reduceroptions). |
58
+
59
+ Schemas are [Standard Schema](https://standardschema.dev): Zod, Valibot,
60
+ ArkType, anything that implements it. Validators must be synchronous; async
61
+ ones are rejected at definition time. The validated output is what's stored.
62
+
63
+ ### `contract.batch(...events)`
64
+
65
+ Returns the same events as a readonly tuple, preserving each literal type in a
66
+ heterogeneous handler-returned array. A2 validates them when the handler
67
+ completes. See [Handlers](/server/handlers#return-what-happens-after-success).
68
+
69
+ ### `reducer(options)`
70
+
71
+ ```ts
72
+ reducer(options: {
73
+ contract: Contract
74
+ name: string // identity; keys cached snapshots
75
+ initialState: S // the seed (schema input, when stateSchema is set)
76
+ stateSchema?: StandardSchemaV1 // declares S, checks initialState, guards cached folds
77
+ }): { fold(fn: (state: S, event: Event) => S): Reducer<S> }
78
+ ```
79
+
80
+ Builds a standalone reducer for server reads or for the contract's `reducer`
81
+ field. See [State](/contract/state#reducers).
82
+
83
+ - The first call fixes the state and event types, so `.fold()` receives
84
+ concrete ones. Literal unions in your state survive with zero annotations.
85
+ - `name` keys cached snapshots, so two reducers never fight over a cache
86
+ entry. Rename it when the fold's logic changes: a rename (or a `stateSchema`
87
+ mismatch, when present) invalidates, and the next read refolds from raw
88
+ events.
89
+
90
+ ### `A2Error`
91
+
92
+ The shared base for A2 failures, discriminated by `code`. The session client
93
+ exposes its `A2ClientError` subclass. See [Errors](/reference/errors).
94
+
95
+ ### `idempotentId(...parts)`
96
+
97
+ `idempotentId(...parts: string[]): Promise<string>` derives a stable UUIDv8
98
+ from an ordered tuple of strings. It performs no I/O and runs on the server and
99
+ in the browser.
100
+
101
+ ```ts shared/request-id.ts
102
+ import { idempotentId } from 'experimental-a2'
103
+
104
+ export const id = await idempotentId('orders', 'shop-7', 'request-42')
105
+ ```
106
+
107
+ - Pass the result as an event's `id` when retries should converge on the same
108
+ event.
109
+ - The same tuple produces the same ID across runtimes and A2 versions.
110
+ - String boundaries, order, and case matter; strings are not normalized. Empty
111
+ strings and an empty tuple are valid.
112
+ - Every argument has the same role; a prefix such as `'orders'` is a namespace
113
+ by convention. Include enough context to distinguish operations across
114
+ contracts and sessions: event IDs are globally unique within a store.
115
+ - A2 preserves explicit IDs and does not change its automatic ID generation.
116
+ Changing an existing recipe changes retry identity, so retries of already
117
+ committed requests must keep their original IDs.
118
+
119
+ ### `SessionCleared`
120
+
121
+ An `Event` whose `type` is `'a2.cleared'` and whose `payload` is `null`: the
122
+ marker a [clear](/reference/server#sessionclearoptions) leaves in
123
+ `session.stream()`. It never reaches handlers or `history()`. Comparing
124
+ `event.type` with that string narrows a stream item to `SessionCleared`. The
125
+ session client handles the marker itself, so it matters only when you read the
126
+ server stream yourself.
127
+
128
+ ## Event
129
+
130
+ ```ts
131
+ type Event = {
132
+ id: string
133
+ type: string
134
+ payload: unknown // typed by the contract's schema for `type`
135
+ index: number // position in the session's log, from 1
136
+ sessionId: string
137
+ createdAt: Date
138
+ }
139
+ ```