experimental-a2 0.20.0 → 0.22.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 (309) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +1 -1
  3. package/dist/{actor-C7b-1arn.d.ts → actor-CqibLgjQ.d.ts} +15 -7
  4. package/dist/actor-CqibLgjQ.d.ts.map +1 -0
  5. package/dist/actor-client.d.ts +1 -1
  6. package/dist/actor-client.js +2 -2
  7. package/dist/actor-react.d.ts +3 -3
  8. package/dist/actor-react.js +5 -5
  9. package/dist/{actor-shared-t7w8xIKP.js → actor-shared-DFET5q16.js} +3 -3
  10. package/dist/actor-shared-DFET5q16.js.map +1 -0
  11. package/dist/actor.d.ts +1 -1
  12. package/dist/actor.js +54 -43
  13. package/dist/actor.js.map +1 -1
  14. package/dist/{ai-Cz3hqVhk.d.ts → ai-DAu77CDr.d.ts} +8 -8
  15. package/dist/{ai-Cz3hqVhk.d.ts.map → ai-DAu77CDr.d.ts.map} +1 -1
  16. package/dist/{ai-mMiWul1T.js → ai-EEfKyc-z.js} +9 -9
  17. package/dist/ai-EEfKyc-z.js.map +1 -0
  18. package/dist/ai-client.d.ts +2 -2
  19. package/dist/ai-client.js +2 -2
  20. package/dist/ai-fx.d.ts +4 -2
  21. package/dist/ai-fx.d.ts.map +1 -1
  22. package/dist/ai-fx.js +214 -67
  23. package/dist/ai-fx.js.map +1 -1
  24. package/dist/{ai-harness-CV6rXbB3.d.ts → ai-harness-DTjkAr2T.d.ts} +2 -2
  25. package/dist/{ai-harness-CV6rXbB3.d.ts.map → ai-harness-DTjkAr2T.d.ts.map} +1 -1
  26. package/dist/{ai-harness-Clbg5ei7.js → ai-harness-dQeJaR1t.js} +7 -3
  27. package/dist/ai-harness-dQeJaR1t.js.map +1 -0
  28. package/dist/ai-pi.d.ts +1 -1
  29. package/dist/ai-pi.js +3 -3
  30. package/dist/ai-pi.js.map +1 -1
  31. package/dist/ai-react.d.ts +5 -5
  32. package/dist/ai-react.js +2 -2
  33. package/dist/ai-server.d.ts +14 -17
  34. package/dist/ai-server.d.ts.map +1 -1
  35. package/dist/ai-server.js +86 -73
  36. package/dist/ai-server.js.map +1 -1
  37. package/dist/ai.d.ts +2 -2
  38. package/dist/ai.js +2 -2
  39. package/dist/{client-BhHLoNKF.js → client-BQS4i_V9.js} +29 -6
  40. package/dist/client-BQS4i_V9.js.map +1 -0
  41. package/dist/{client-h_DKFAjj.d.ts → client-CUMbS_38.d.ts} +3 -3
  42. package/dist/{client-h_DKFAjj.d.ts.map → client-CUMbS_38.d.ts.map} +1 -1
  43. package/dist/client.d.ts +3 -3
  44. package/dist/client.js +1 -1
  45. package/dist/{contract-BYKASlCV.js → contract-CWukt01d.js} +2 -2
  46. package/dist/contract-CWukt01d.js.map +1 -0
  47. package/dist/index.d.ts +5 -5
  48. package/dist/index.js +3 -3
  49. package/dist/{initial-snapshot-Bx-c0pDP.d.ts → initial-snapshot-D3Lve43o.d.ts} +4 -4
  50. package/dist/initial-snapshot-D3Lve43o.d.ts.map +1 -0
  51. package/dist/{internal-CscSY7K_.js → internal-CvsrprnU.js} +40 -16
  52. package/dist/internal-CvsrprnU.js.map +1 -0
  53. package/dist/otel.d.ts +1 -1
  54. package/dist/otel.js +1 -1
  55. package/dist/otel.js.map +1 -1
  56. package/dist/{react-BBXgHWFc.d.ts → react-BoHvC3v9.d.ts} +4 -4
  57. package/dist/{react-BBXgHWFc.d.ts.map → react-BoHvC3v9.d.ts.map} +1 -1
  58. package/dist/react.d.ts +1 -1
  59. package/dist/react.js +1 -1
  60. package/dist/{reducer-CqA59Q6U.d.ts → reducer-CYPHsSmd.d.ts} +2 -2
  61. package/dist/{reducer-CqA59Q6U.d.ts.map → reducer-CYPHsSmd.d.ts.map} +1 -1
  62. package/dist/{reducer-BAXc8JyF.js → reducer-CjmvZSAb.js} +2 -2
  63. package/dist/{reducer-BAXc8JyF.js.map → reducer-CjmvZSAb.js.map} +1 -1
  64. package/dist/runtime-consumer-CIeL33wj.js +12 -0
  65. package/dist/runtime-consumer-CIeL33wj.js.map +1 -0
  66. package/dist/scheduler-qstash.d.ts +2 -2
  67. package/dist/scheduler-qstash.js +3 -3
  68. package/dist/scheduler-task-X1SToDjP.js.map +1 -1
  69. package/dist/scheduler-vercel.d.ts +2 -2
  70. package/dist/scheduler-vercel.js +3 -3
  71. package/dist/scheduler-vercel.js.map +1 -1
  72. package/dist/{server-qyb5aJJG.js → server-DtFrWxi3.js} +412 -116
  73. package/dist/server-DtFrWxi3.js.map +1 -0
  74. package/dist/{server-DYAATFuT.d.ts → server-qgez0Xny.d.ts} +108 -41
  75. package/dist/server-qgez0Xny.d.ts.map +1 -0
  76. package/dist/server.browser.js +1 -1
  77. package/dist/server.browser.js.map +1 -1
  78. package/dist/server.d.ts +4 -4
  79. package/dist/server.js +2 -2
  80. package/dist/{session-clear-C-QwTXV1.d.ts → session-clear-D1PFe7xl.d.ts} +2 -2
  81. package/dist/session-clear-D1PFe7xl.d.ts.map +1 -0
  82. package/dist/{session-clear-DGI4jTQ5.js → session-clear-wHd5GCpZ.js} +5 -4
  83. package/dist/session-clear-wHd5GCpZ.js.map +1 -0
  84. package/dist/store-D0MhBvg6.d.ts +532 -0
  85. package/dist/store-D0MhBvg6.d.ts.map +1 -0
  86. package/dist/store-N8PXxDAS.js.map +1 -1
  87. package/dist/store-codec-DwrWlgQx.js +65 -0
  88. package/dist/store-codec-DwrWlgQx.js.map +1 -0
  89. package/dist/store-memory.d.ts +1 -1
  90. package/dist/store-memory.d.ts.map +1 -1
  91. package/dist/store-memory.js +406 -225
  92. package/dist/store-memory.js.map +1 -1
  93. package/dist/{store-polling-7WJV0YWP.js → store-polling-BZt2Rf3D.js} +2 -2
  94. package/dist/{store-polling-7WJV0YWP.js.map → store-polling-BZt2Rf3D.js.map} +1 -1
  95. package/dist/store-postgres.d.ts +1 -1
  96. package/dist/store-postgres.d.ts.map +1 -1
  97. package/dist/store-postgres.js +1598 -587
  98. package/dist/store-postgres.js.map +1 -1
  99. package/dist/store-presence-polling-JuAy2Ck2.js +111 -0
  100. package/dist/store-presence-polling-JuAy2Ck2.js.map +1 -0
  101. package/dist/store-redis-http.d.ts +1 -1
  102. package/dist/store-redis-http.js +4 -4
  103. package/dist/store-redis-notify-CsJw_hfD.js +3060 -0
  104. package/dist/store-redis-notify-CsJw_hfD.js.map +1 -0
  105. package/dist/store-redis.d.ts +1 -1
  106. package/dist/store-redis.d.ts.map +1 -1
  107. package/dist/store-redis.js +4 -5
  108. package/dist/store-redis.js.map +1 -1
  109. package/dist/store-sqlite.d.ts +1 -1
  110. package/dist/store-sqlite.d.ts.map +1 -1
  111. package/dist/store-sqlite.js +527 -299
  112. package/dist/store-sqlite.js.map +1 -1
  113. package/dist/stream-buffer-DrTyiIuo.js +57 -0
  114. package/dist/stream-buffer-DrTyiIuo.js.map +1 -0
  115. package/dist/{telemetry-Cyfqo6Qt.d.ts → telemetry-CWwsh-Gx.d.ts} +3 -3
  116. package/dist/telemetry-CWwsh-Gx.d.ts.map +1 -0
  117. package/dist/{wire-BKxH1vbP.js → wire-CV-Z7wz-.js} +6 -5
  118. package/dist/wire-CV-Z7wz-.js.map +1 -0
  119. package/docs/01-quickstart.mdx +21 -15
  120. package/docs/02-examples.mdx +1 -1
  121. package/docs/actors/01-introduction.mdx +13 -2
  122. package/docs/actors/02-concurrency.mdx +1 -1
  123. package/docs/agents/01-introduction.mdx +1 -1
  124. package/docs/agents/02-tools.mdx +12 -11
  125. package/docs/agents/03-conversations.mdx +36 -25
  126. package/docs/agents/04-harnesses.mdx +14 -7
  127. package/docs/client/03-presence.mdx +18 -14
  128. package/docs/contract/01-events.mdx +2 -2
  129. package/docs/contract/02-state.mdx +18 -14
  130. package/docs/contract/03-sessions.mdx +32 -25
  131. package/docs/index.mdx +29 -24
  132. package/docs/reference/01-core.mdx +7 -6
  133. package/docs/reference/02-server.mdx +250 -191
  134. package/docs/reference/04-ai.mdx +33 -23
  135. package/docs/reference/05-telemetry.mdx +27 -13
  136. package/docs/reference/06-errors.mdx +25 -19
  137. package/docs/reference/meta.ts +1 -1
  138. package/docs/schedulers/01-overview.mdx +8 -8
  139. package/docs/schedulers/02-vercel-queues.mdx +2 -2
  140. package/docs/schedulers/03-qstash.mdx +4 -4
  141. package/docs/server/01-consumers.mdx +418 -0
  142. package/docs/server/02-timers.mdx +31 -21
  143. package/docs/server/03-cancellation.mdx +52 -44
  144. package/docs/server/04-routes.mdx +4 -1
  145. package/docs/server/05-sql-projections.mdx +391 -0
  146. package/docs/server/06-guarantees.mdx +61 -51
  147. package/docs/stores/01-overview.mdx +3 -3
  148. package/docs/stores/02-redis.mdx +24 -10
  149. package/docs/stores/03-redis-http.mdx +8 -6
  150. package/docs/stores/04-postgres.mdx +65 -14
  151. package/docs/stores/05-sqlite.mdx +5 -3
  152. package/docs/upgrades/01-overview.mdx +31 -0
  153. package/docs/upgrades/78-0-22.mdx +115 -0
  154. package/docs/upgrades/79-0-21.mdx +165 -0
  155. package/docs/upgrades/80-0-20.mdx +43 -0
  156. package/docs/upgrades/81-0-19.mdx +33 -0
  157. package/docs/upgrades/82-0-18.mdx +33 -0
  158. package/docs/upgrades/83-0-17.mdx +69 -0
  159. package/docs/upgrades/meta.ts +3 -0
  160. package/examples/playground/DEPLOY.md +39 -7
  161. package/examples/playground/app/a0/chat.test.tsx +2 -2
  162. package/examples/playground/app/a0/sandbox-log.ts +17 -15
  163. package/examples/playground/app/a0/sandbox.ts +58 -13
  164. package/examples/playground/app/a0/server.ts +4 -4
  165. package/examples/playground/app/a2slack/a2slack.css +1067 -0
  166. package/examples/playground/app/a2slack/c/[channel]/page.tsx +20 -0
  167. package/examples/playground/app/a2slack/consumers/agent.ts +63 -0
  168. package/examples/playground/app/a2slack/consumers/feed.ts +164 -0
  169. package/examples/playground/app/a2slack/consumers/notify.ts +116 -0
  170. package/examples/playground/app/a2slack/consumers/search.ts +37 -0
  171. package/examples/playground/app/a2slack/consumers/triage.ts +31 -0
  172. package/examples/playground/app/a2slack/consumers/welcome.ts +25 -0
  173. package/examples/playground/app/a2slack/db/a2.ts +209 -0
  174. package/examples/playground/app/a2slack/db/index.ts +73 -0
  175. package/examples/playground/app/a2slack/db/migrations/0000_extensions.sql +4 -0
  176. package/examples/playground/app/a2slack/db/migrations/0001_workspace.sql +74 -0
  177. package/examples/playground/app/a2slack/db/migrations/0002_a2.sql +215 -0
  178. package/examples/playground/app/a2slack/db/migrations/0003_a2_batch.sql +67 -0
  179. package/examples/playground/app/a2slack/db/migrations/0004_a2_session_event_ids.sql +2 -0
  180. package/examples/playground/app/a2slack/db/migrations/meta/0000_snapshot.json +18 -0
  181. package/examples/playground/app/a2slack/db/migrations/meta/0001_snapshot.json +500 -0
  182. package/examples/playground/app/a2slack/db/migrations/meta/0002_snapshot.json +1159 -0
  183. package/examples/playground/app/a2slack/db/migrations/meta/0003_snapshot.json +1159 -0
  184. package/examples/playground/app/a2slack/db/migrations/meta/0004_snapshot.json +1165 -0
  185. package/examples/playground/app/a2slack/db/migrations/meta/_journal.json +41 -0
  186. package/examples/playground/app/a2slack/db/queries.ts +263 -0
  187. package/examples/playground/app/a2slack/db/schema.ts +145 -0
  188. package/examples/playground/app/a2slack/drills/a2slack.drill.ts +708 -0
  189. package/examples/playground/app/a2slack/drills/harness.ts +244 -0
  190. package/examples/playground/app/a2slack/events/route.ts +36 -0
  191. package/examples/playground/app/a2slack/identity.ts +44 -0
  192. package/examples/playground/app/a2slack/inbox/route.ts +8 -0
  193. package/examples/playground/app/a2slack/lag/data/route.ts +8 -0
  194. package/examples/playground/app/a2slack/lag/page.tsx +101 -0
  195. package/examples/playground/app/a2slack/lag.ts +73 -0
  196. package/examples/playground/app/a2slack/layout.tsx +43 -0
  197. package/examples/playground/app/a2slack/messages/route.ts +17 -0
  198. package/examples/playground/app/a2slack/model.test.ts +208 -0
  199. package/examples/playground/app/a2slack/model.ts +369 -0
  200. package/examples/playground/app/a2slack/models.test.ts +72 -0
  201. package/examples/playground/app/a2slack/page.tsx +10 -0
  202. package/examples/playground/app/a2slack/scheduler/route.ts +5 -0
  203. package/examples/playground/app/a2slack/search/route.ts +40 -0
  204. package/examples/playground/app/a2slack/search-index.ts +108 -0
  205. package/examples/playground/app/a2slack/server.test.ts +315 -0
  206. package/examples/playground/app/a2slack/server.ts +55 -0
  207. package/examples/playground/app/a2slack/sessions.ts +50 -0
  208. package/examples/playground/app/a2slack/thread/route.ts +8 -0
  209. package/examples/playground/app/a2slack/ui/ChannelView.tsx +87 -0
  210. package/examples/playground/app/a2slack/ui/Composer.tsx +117 -0
  211. package/examples/playground/app/a2slack/ui/DotsShadow.tsx +42 -0
  212. package/examples/playground/app/a2slack/ui/Feed.tsx +157 -0
  213. package/examples/playground/app/a2slack/ui/InboxContext.tsx +63 -0
  214. package/examples/playground/app/a2slack/ui/InboxView.tsx +82 -0
  215. package/examples/playground/app/a2slack/ui/Menu.tsx +128 -0
  216. package/examples/playground/app/a2slack/ui/MessageRow.tsx +314 -0
  217. package/examples/playground/app/a2slack/ui/NameGate.tsx +35 -0
  218. package/examples/playground/app/a2slack/ui/SearchContext.tsx +146 -0
  219. package/examples/playground/app/a2slack/ui/SearchResults.tsx +97 -0
  220. package/examples/playground/app/a2slack/ui/Shell.tsx +34 -0
  221. package/examples/playground/app/a2slack/ui/Sidebar.tsx +199 -0
  222. package/examples/playground/app/a2slack/ui/ThreadPanel.tsx +134 -0
  223. package/examples/playground/app/a2slack/ui/useInbox.ts +71 -0
  224. package/examples/playground/app/agent/server.ts +3 -3
  225. package/examples/playground/app/chat/[chatId]/chat-client.tsx +1 -1
  226. package/examples/playground/app/chat/server.ts +45 -35
  227. package/examples/playground/app/components/demo-icons.tsx +7 -0
  228. package/examples/playground/app/components/demos.tsx +7 -0
  229. package/examples/playground/app/orders/[orderId]/order-client.tsx +2 -2
  230. package/examples/playground/app/orders/page.tsx +1 -1
  231. package/examples/playground/app/orders/server.ts +49 -30
  232. package/examples/playground/app/recovery/[recoveryId]/recovery-client.tsx +14 -15
  233. package/examples/playground/app/recovery/page.tsx +4 -4
  234. package/examples/playground/app/recovery/server.ts +23 -32
  235. package/examples/playground/drizzle.config.ts +14 -0
  236. package/examples/playground/lib/store.ts +1 -1
  237. package/examples/playground/next.config.ts +6 -1
  238. package/examples/playground/package.json +12 -1
  239. package/examples/playground/scripts/migrate.mjs +31 -0
  240. package/examples/playground/vercel.json +9 -0
  241. package/examples/playground/vitest.drills.config.ts +32 -0
  242. package/package.json +5 -2
  243. package/sql/postgres/drizzle-schema.ts +209 -0
  244. package/sql/postgres/schema.sql +227 -67
  245. package/src/actor-shared.ts +10 -2
  246. package/src/actor.ts +101 -71
  247. package/src/ai-agent.ts +162 -111
  248. package/src/ai-control-server.ts +8 -8
  249. package/src/ai-fx.ts +324 -82
  250. package/src/ai-harness.ts +17 -2
  251. package/src/ai-pi.ts +2 -2
  252. package/src/ai-server.ts +2 -2
  253. package/src/ai.ts +7 -7
  254. package/src/client.ts +19 -2
  255. package/src/contract.ts +1 -1
  256. package/src/deterministic-id.ts +27 -4
  257. package/src/errors.ts +8 -5
  258. package/src/idempotent-replay.ts +0 -1
  259. package/src/index.ts +1 -1
  260. package/src/internal.ts +57 -16
  261. package/src/otel.ts +1 -1
  262. package/src/postgres-schema.ts +98 -57
  263. package/src/presence-recovery.ts +18 -11
  264. package/src/presence-tombstones.ts +52 -0
  265. package/src/push-envelope.ts +20 -0
  266. package/src/runtime-consumer.ts +10 -0
  267. package/src/scheduler-task.ts +2 -2
  268. package/src/scheduler-vercel.ts +1 -1
  269. package/src/server.browser.ts +1 -1
  270. package/src/server.ts +819 -218
  271. package/src/session-socket.ts +1 -1
  272. package/src/store-codec.ts +66 -0
  273. package/src/store-memory.ts +604 -286
  274. package/src/store-postgres.ts +2006 -857
  275. package/src/store-presence-polling.ts +59 -34
  276. package/src/store-redis-core.ts +1961 -1333
  277. package/src/store-redis-notify.ts +76 -26
  278. package/src/store-redis.ts +2 -3
  279. package/src/store-sqlite.ts +915 -516
  280. package/src/store.ts +241 -102
  281. package/src/telemetry.ts +2 -1
  282. package/src/wire.ts +1 -0
  283. package/dist/actor-C7b-1arn.d.ts.map +0 -1
  284. package/dist/actor-shared-t7w8xIKP.js.map +0 -1
  285. package/dist/ai-harness-Clbg5ei7.js.map +0 -1
  286. package/dist/ai-mMiWul1T.js.map +0 -1
  287. package/dist/client-BhHLoNKF.js.map +0 -1
  288. package/dist/contract-BYKASlCV.js.map +0 -1
  289. package/dist/idempotent-replay-JdgMQRRm.js +0 -21
  290. package/dist/idempotent-replay-JdgMQRRm.js.map +0 -1
  291. package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +0 -1
  292. package/dist/internal-CscSY7K_.js.map +0 -1
  293. package/dist/server-DYAATFuT.d.ts.map +0 -1
  294. package/dist/server-qyb5aJJG.js.map +0 -1
  295. package/dist/session-clear-C-QwTXV1.d.ts.map +0 -1
  296. package/dist/session-clear-DGI4jTQ5.js.map +0 -1
  297. package/dist/store-CyLUy86v.d.ts +0 -404
  298. package/dist/store-CyLUy86v.d.ts.map +0 -1
  299. package/dist/store-codec-DTG0Ftek.js +0 -10
  300. package/dist/store-codec-DTG0Ftek.js.map +0 -1
  301. package/dist/store-presence-polling-B1ixeqIS.js +0 -94
  302. package/dist/store-presence-polling-B1ixeqIS.js.map +0 -1
  303. package/dist/store-redis-notify-CM0AfLY0.js +0 -2544
  304. package/dist/store-redis-notify-CM0AfLY0.js.map +0 -1
  305. package/dist/stream-buffer-Cx7AAPGq.js +0 -23
  306. package/dist/stream-buffer-Cx7AAPGq.js.map +0 -1
  307. package/dist/telemetry-Cyfqo6Qt.d.ts.map +0 -1
  308. package/dist/wire-BKxH1vbP.js.map +0 -1
  309. package/docs/server/01-handlers.mdx +0 -227
@@ -1,7 +1,7 @@
1
- import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, r as RegisteredReducer, s as Contract, t as Reducer, u as EventDefs } from "./reducer-CqA59Q6U.js";
2
- import { t as A2Store } from "./store-CyLUy86v.js";
3
- import { t as SessionCleared } from "./session-clear-C-QwTXV1.js";
4
- import { i as A2Telemetry } from "./telemetry-Cyfqo6Qt.js";
1
+ import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, r as RegisteredReducer, s as Contract, t as Reducer, u as EventDefs } from "./reducer-CYPHsSmd.js";
2
+ import { t as A2Store } from "./store-D0MhBvg6.js";
3
+ import { t as SessionCleared } from "./session-clear-D1PFe7xl.js";
4
+ import { i as A2Telemetry } from "./telemetry-CWwsh-Gx.js";
5
5
  //#region src/session-socket.d.ts
6
6
  /**
7
7
  * The structural socket `sessionsSocket` speaks against — satisfied
@@ -69,7 +69,7 @@ type ScheduledEvent = {
69
69
  type: string;
70
70
  payload: unknown;
71
71
  };
72
- /** A durable wake-up for pending handler work. */
72
+ /** A durable wake-up for pending consumer work. */
73
73
  type SchedulerDrainTask = {
74
74
  version: 1;
75
75
  kind: "drain";
@@ -89,7 +89,7 @@ type SchedulerAppendTask = {
89
89
  /** Earliest useful delivery as epoch milliseconds. */
90
90
  dueAt: number;
91
91
  events: readonly ScheduledEvent[];
92
- /** The scheduling handler's event; delivery skips once it is cleared. */
92
+ /** The scheduling consumer's event; delivery skips once it is cleared. */
93
93
  originIndex?: number;
94
94
  };
95
95
  /** A durable conditional clear. */
@@ -112,31 +112,35 @@ type SchedulerTask = SchedulerDrainTask | SchedulerAppendTask | SchedulerClearTa
112
112
  type PublicState<R> = undefined extends R ? never : R extends {
113
113
  initialState: infer S;
114
114
  } ? S : never;
115
- /** What every handler receives. */
116
- type HandlerContext<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = {
115
+ /** What every consumer's `run` receives. */
116
+ type ConsumerContext<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = {
117
117
  /** The triggering event. */
118
118
  event: ContractEvent<D, K>;
119
119
  /** Durable, 1-based dispatch ordinal for this event. */
120
120
  attempt: number;
121
- /** This session, with handler-scoped idempotent append. */
122
- session: Session<D, HandlerAppend<D>, P, S>;
121
+ /** This session, with consumer-scoped idempotent append. */
122
+ session: Session<D, ConsumerAppend<D>, P, S>;
123
123
  /** Fires on `abortOn` events (cancellation slice); dormant otherwise. */
124
124
  signal: AbortSignal;
125
125
  };
126
- type Handler<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = (ctx: HandlerContext<D, K, P, S>) => Promise<void | AppendInput<D> | readonly AppendInput<D>[]>;
127
126
  type LaneContext<D extends EventDefs, K extends keyof D & string = keyof D & string> = {
128
127
  sessionId: string;
129
128
  event: Pick<ContractEvent<D, K>, "type" | "payload"> & {
130
129
  id?: string;
131
130
  };
132
131
  };
133
- type Lane<D extends EventDefs, K extends keyof D & string = keyof D & string> = string | ((context: LaneContext<D, K>) => string);
132
+ /**
133
+ * A consumer's lane: a string runs every event it takes in log order on one
134
+ * cursor; a function returns each event's lane, or null to run it
135
+ * concurrently.
136
+ */
137
+ type ConsumerLane<D extends EventDefs, K extends keyof D & string = keyof D & string> = string | ((context: LaneContext<D, K>) => string | null);
134
138
  type SessionDispatch<D extends EventDefs> = (...events: AppendInput<D>[]) => Promise<ContractEvent<D>[]>;
135
139
  type SessionAppend<D extends EventDefs> = SessionDispatch<D> & {
136
140
  /** Commit, then hand pending work directly to configured scheduler. */
137
141
  dispatch: SessionDispatch<D>;
138
142
  };
139
- type HandlerAppend<D extends EventDefs> = (name: string, ...events: AppendInput<D>[]) => Promise<ContractEvent<D>[]>;
143
+ type ConsumerAppend<D extends EventDefs> = (name: string, ...events: AppendInput<D>[]) => Promise<ContractEvent<D>[]>;
140
144
  type ScheduleDelay = `${number}${"ms" | "s" | "m" | "h" | "d"}`;
141
145
  type ScheduleTiming = {
142
146
  delay: ScheduleDelay;
@@ -168,25 +172,41 @@ type SessionClearResult = {
168
172
  index: number;
169
173
  };
170
174
  type SessionRedriveOptions = {
171
- /** `retry` runs the handler again with a fresh failure budget; `skip` settles the event without running it. */
175
+ /** `retry` runs the consumer again with a fresh failure budget; `skip` settles the event without running it. */
172
176
  action: "retry" | "skip";
173
177
  };
174
178
  type SessionRedriveResult = {
175
179
  /** Whether the event was dead-lettered and is now resolved. */
176
180
  redriven: boolean;
177
181
  };
182
+ type SessionConsumeOptions = {
183
+ /**
184
+ * Run until the consumer has handled every event it takes through this
185
+ * index. Default: the session's head when the call starts. An index past
186
+ * the head counts as the head.
187
+ */
188
+ through?: number;
189
+ /** Stops waiting: the call throws the signal's reason. */
190
+ signal?: AbortSignal;
191
+ };
192
+ type SessionConsumeResult = {
193
+ /** The consumer has handled every event it takes through this index. */
194
+ index: number;
195
+ };
178
196
  /** A dead-lettered event, with what an operator needs to resolve it. */
179
197
  type DeadLetter<D extends EventDefs> = ContractEvent<D> & {
198
+ /** The consumer this event is dead for; it may be done for others. */
199
+ consumer: string;
180
200
  lane: string | null;
181
201
  /** Durable dispatch claims, including claims abandoned by hard kills. */
182
202
  attemptCount: number;
183
203
  /**
184
204
  * Failed attempts since the event was appended or last retried: caught
185
- * handler failures, and attempts that ended before they finished.
205
+ * consumer failures, and attempts that ended before they finished.
186
206
  */
187
207
  failureCount: number;
188
208
  /**
189
- * The last error a handler threw, stringified; null when every failed
209
+ * The last error the consumer threw, stringified; null when every failed
190
210
  * attempt ended before it finished.
191
211
  */
192
212
  lastError: string | null;
@@ -200,7 +220,10 @@ type SessionDeadLetters<D extends EventDefs> = {
200
220
  * Atomically resolve one dead-lettered event, then wake the session like
201
221
  * an append. Any other event is left alone and reports `redriven: false`.
202
222
  */
203
- redrive(index: number, options: SessionRedriveOptions): Promise<SessionRedriveResult>;
223
+ redrive(target: {
224
+ consumer: string;
225
+ index: number;
226
+ }, options: SessionRedriveOptions): Promise<SessionRedriveResult>;
204
227
  };
205
228
  /**
206
229
  * The presence members of a session — intersected in via
@@ -248,6 +271,14 @@ type Session<D extends EventDefs, Append = SessionAppend<D>, P extends PresenceD
248
271
  gte?: number;
249
272
  lte?: number;
250
273
  }): Promise<ContractEvent<D>[]>;
274
+ /**
275
+ * Run a consumer with a string lane on this session, here, until it has
276
+ * handled every event it takes through `through`. The server's own
277
+ * consumer shares its cursor with background work, so this waits for
278
+ * whichever invocation holds it. A consumer the server doesn't run is
279
+ * pulled only by `consume`, and keeps its place between calls.
280
+ */
281
+ consume(consumer: Consumer<D>, options?: SessionConsumeOptions): Promise<SessionConsumeResult>;
251
282
  state: {
252
283
  <T>(reducer: Reducer<D, T, Record<never, never>>, options?: StateOptions): Promise<{
253
284
  state: T;
@@ -271,7 +302,7 @@ type Session<D extends EventDefs, Append = SessionAppend<D>, P extends PresenceD
271
302
  }): AsyncIterable<ContractEvent<D> | SessionCleared>;
272
303
  };
273
304
  /**
274
- * The public server shape scheduler handlers accept. It stays structural so
305
+ * The public server shape scheduler consumers accept. It stays structural so
275
306
  * servers of any contract mix in one route; A2's private server internals add
276
307
  * delayed-append delivery without exposing an untyped append method here.
277
308
  */
@@ -327,29 +358,66 @@ declare function deliverSchedulerAppend(server: DrainableServer, task: Scheduler
327
358
  */
328
359
  declare function deliverSchedulerClear(server: DrainableServer, task: SchedulerClearTask): Promise<void>;
329
360
  /**
330
- * Which events fire `ctx.signal` while a handler runs — the preemption
361
+ * Which events fire `ctx.signal` while a consumer runs — the preemption
331
362
  * channel for user cancellation. The array form matches by type; the
332
363
  * object form takes per-type predicates for targeted cancellation
333
- * (`(event, trigger) => event.payload.of === trigger.id`). Handlers
334
- * without `abortOn` pay nothing. An aborted handler should catch and
364
+ * (`(event, trigger) => event.payload.of === trigger.id`). Consumers
365
+ * without `abortOn` pay nothing. An aborted consumer should catch and
335
366
  * return normally; throwing means "retry me".
336
367
  */
337
368
  type AbortSpec<D extends EventDefs, K extends keyof D & string> = Array<keyof D & string> | { [T in keyof D & string]?: true | ((event: ContractEvent<D, T>, trigger: ContractEvent<D, K>, context: {
338
369
  attempt: number;
339
370
  }) => boolean); };
340
- type HandlerEntry<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = Handler<D, K, P, S> | {
371
+ /** What a consumer's `run` returns: nothing, one event, or a batch. */
372
+ type ConsumerResult<D extends EventDefs> = Promise<void | AppendInput<D> | readonly AppendInput<D>[]>;
373
+ /** How `createServer` runs a consumer. Built by `consumer().run()`. */
374
+ type ConsumerSpec<D extends EventDefs> = {
375
+ readonly types: readonly (keyof D & string)[] | null;
376
+ readonly lane: ConsumerLane<D> | null;
377
+ readonly backfill: boolean;
378
+ readonly abortOn: AbortSpec<D, keyof D & string> | null;
379
+ readonly run: (ctx: ConsumerContext<D>) => ConsumerResult<D>;
380
+ };
381
+ /** A named reader of a session's log with its own durable cursors. */
382
+ type Consumer<D extends EventDefs> = {
383
+ readonly name: string;
384
+ readonly contract: {
385
+ readonly name: string;
386
+ };
387
+ readonly spec: ConsumerSpec<D>;
388
+ };
389
+ type ConsumerOptions<D extends EventDefs, P extends PresenceDefs, R extends RegisteredReducer<D, P> | undefined, K extends keyof D & string> = {
390
+ /** The contract whose events it reads. */
391
+ contract: Contract<D, P, R>;
392
+ /** Its identity, unique per server. A new name is a new consumer. */
393
+ name: string;
394
+ /** The event types it runs on; default every type. */
395
+ types?: readonly K[];
396
+ /** Omitted: concurrent. A string: one ordered lane. A function: per event. */
397
+ lane?: ConsumerLane<D, K>;
398
+ /** A new consumer starts at the beginning of the log. Needs a string lane. */
399
+ backfill?: boolean;
341
400
  abortOn?: AbortSpec<D, K>;
342
- /** Session-scoped FIFO key, resolved and persisted when the event lands. */
343
- lane?: Lane<D, K>;
344
- handler: Handler<D, K, P, S>;
345
- };
346
- type HandlerFunction = (ctx: never) => Promise<unknown>;
347
- declare function handler<H extends HandlerFunction | {
348
- handler: HandlerFunction;
349
- }>(entry: H): H extends HandlerFunction ? {
350
- handler: H;
351
- } : H;
352
- type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined> = {
401
+ };
402
+ /**
403
+ * A consumer written in `createServer({ consumers })`: `consumer()`'s
404
+ * options without the contract, which is the server's, and its `run`.
405
+ */
406
+ type InlineConsumer<D extends EventDefs, P extends PresenceDefs, R extends RegisteredReducer<D, P> | undefined, K extends keyof D & string> = Omit<ConsumerOptions<D, P, R, K>, "contract"> & {
407
+ run: (ctx: ConsumerContext<D, K, P, PublicState<R>>) => ConsumerResult<D>;
408
+ };
409
+ /** The types an inline consumer takes: the ones it lists, or every type. */
410
+ type InlineTypes<D extends EventDefs, X> = unknown extends X ? keyof D & string : Extract<X, keyof D & string>;
411
+ /**
412
+ * `createServer`'s consumers: each a `consumer()` or written inline. `C` is
413
+ * inferred per entry, so an inline `run` sees only the types it lists.
414
+ */
415
+ type ServerConsumers<D extends EventDefs, P extends PresenceDefs, R extends RegisteredReducer<D, P> | undefined, C extends readonly unknown[]> = { readonly [I in keyof C]: InlineConsumer<D, P, R, InlineTypes<D, C[I]>> | Extract<C[I], Consumer<D>>; };
416
+ /** Define a consumer: a named reader of each session's log. */
417
+ declare function consumer<D extends EventDefs, P extends PresenceDefs, R extends RegisteredReducer<D, P> | undefined, const K extends keyof D & string = keyof D & string>(options: ConsumerOptions<D, P, R, K>): {
418
+ run(fn: (ctx: ConsumerContext<D, K, P, PublicState<R>>) => ConsumerResult<D>): Consumer<D>;
419
+ };
420
+ type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined, C extends readonly unknown[] = readonly Consumer<D>[]> = {
353
421
  /** The contract this server implements (see `a2.contract`). */
354
422
  contract: Contract<D, P, R>;
355
423
  /** Where events live. Defaults: sqlite in dev, memory in tests, required in prod. */
@@ -372,15 +440,14 @@ type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, n
372
440
  ttlMs?: number;
373
441
  };
374
442
  /**
375
- * The reactions, keyed by event type — all present at construction,
376
- * so a handler can never be silently missing because its module
377
- * wasn't imported. Compose across files by spreading objects (note:
378
- * a duplicate key under spread silently last-wins).
443
+ * The consumers, each a named reader of every session's log with its own
444
+ * cursors: a `consumer()`, or its options and `run` written inline, on this
445
+ * contract. Names are unique; a duplicate throws.
379
446
  */
380
- handlers?: { [K in keyof D & string]?: HandlerEntry<D, K, P, PublicState<R>>; };
447
+ consumers?: ServerConsumers<D, P, R, C> | readonly Consumer<D>[];
381
448
  };
382
449
  /** Implement a contract: bind its vocabulary to storage and reactions. */
383
- declare function createServer<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined>(options: ServerOptions<D, P, R>): A2Server<D, P, R>;
450
+ declare function createServer<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined, const C extends readonly unknown[] = readonly Consumer<D>[]>(options: ServerOptions<D, P, R, C>): A2Server<D, P, R>;
384
451
  //#endregion
385
- export { ScheduledEvent as A, A2Socket as B, SessionRedriveResult as C, deliverSchedulerAppend as D, createServer as E, A2Operation as F, A2PushEvent as I, A2PushPresence as L, SchedulerClearTask as M, SchedulerDrainTask as N, deliverSchedulerClear as O, SchedulerTask as P, ServerFetchOptions as R, SessionRedriveOptions as S, StateOptions as T, SessionClearOptions as _, DrainableServer as a, SessionDispatch as b, HandlerContext as c, LaneContext as d, ScheduleDelay as f, SessionAppend as g, Session as h, DeadLetter as i, SchedulerAppendTask as j, handler as k, HandlerEntry as l, ServerOptions as m, A2Server as n, Handler as o, ScheduleTiming as p, AbortSpec as r, HandlerAppend as s, A2Scheduler as t, Lane as u, SessionClearResult as v, SessionSchedule as w, SessionPresence as x, SessionDeadLetters as y, UpgradeWebSocket as z };
386
- //# sourceMappingURL=server-DYAATFuT.d.ts.map
452
+ export { SessionSchedule as A, SchedulerTask as B, SessionConsumeOptions as C, SessionPresence as D, SessionDispatch as E, deliverSchedulerClear as F, UpgradeWebSocket as G, A2PushEvent as H, ScheduledEvent as I, A2Socket as K, SchedulerAppendTask as L, consumer as M, createServer as N, SessionRedriveOptions as O, deliverSchedulerAppend as P, SchedulerClearTask as R, SessionClearResult as S, SessionDeadLetters as T, A2PushPresence as U, A2Operation as V, ServerFetchOptions as W, ServerConsumers as _, ConsumerAppend as a, SessionAppend as b, ConsumerOptions as c, DeadLetter as d, DrainableServer as f, ScheduleTiming as g, ScheduleDelay as h, Consumer as i, StateOptions as j, SessionRedriveResult as k, ConsumerResult as l, LaneContext as m, A2Server as n, ConsumerContext as o, InlineConsumer as p, AbortSpec as r, ConsumerLane as s, A2Scheduler as t, ConsumerSpec as u, ServerOptions as v, SessionConsumeResult as w, SessionClearOptions as x, Session as y, SchedulerDrainTask as z };
453
+ //# sourceMappingURL=server-qgez0Xny.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-qgez0Xny.d.ts","names":[],"sources":["../src/session-socket.ts","../src/server-fetch.ts","../src/scheduler-task.ts","../src/server.ts"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * The browser build of experimental-a2/server. There isn't one — on purpose.
4
4
  * Contracts and reducers (from `experimental-a2`) and the session client (from
5
5
  * `experimental-a2/client` / `experimental-a2/react`) are the isomorphic surface; the server is
6
- * where handlers and storage live. This module existing in a client
6
+ * where consumers and storage live. This module existing in a client
7
7
  * bundle means a `'use client'` file (or something it imports)
8
8
  * value-imported your server module.
9
9
  */
@@ -1 +1 @@
1
- {"version":3,"file":"server.browser.js","names":[],"sources":["../src/server.browser.ts"],"sourcesContent":["/**\n * The browser build of experimental-a2/server. There isn't one — on purpose.\n * Contracts and reducers (from `experimental-a2`) and the session client (from\n * `experimental-a2/client` / `experimental-a2/react`) are the isomorphic surface; the server is\n * where handlers and storage live. This module existing in a client\n * bundle means a `'use client'` file (or something it imports)\n * value-imported your server module.\n */\nthrow new Error(\n 'experimental-a2/server is server-only — a client bundle imported it. Import the contract (a2) or the session client (experimental-a2/client, experimental-a2/react) in browser code instead.',\n)\nexport {}\n"],"mappings":";;;;;;;;;AAQA,MAAM,IAAI,MACR,8LACF"}
1
+ {"version":3,"file":"server.browser.js","names":[],"sources":["../src/server.browser.ts"],"sourcesContent":["/**\n * The browser build of experimental-a2/server. There isn't one — on purpose.\n * Contracts and reducers (from `experimental-a2`) and the session client (from\n * `experimental-a2/client` / `experimental-a2/react`) are the isomorphic surface; the server is\n * where consumers and storage live. This module existing in a client\n * bundle means a `'use client'` file (or something it imports)\n * value-imported your server module.\n */\nthrow new Error(\n 'experimental-a2/server is server-only — a client bundle imported it. Import the contract (a2) or the session client (experimental-a2/client, experimental-a2/react) in browser code instead.',\n)\nexport {}\n"],"mappings":";;;;;;;;;AAQA,MAAM,IAAI,MACR,8LACF"}
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, s as Contract, u as EventDefs } from "./reducer-CqA59Q6U.js";
2
- import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-CyLUy86v.js";
3
- import { A as ScheduledEvent, B as A2Socket, C as SessionRedriveResult, D as deliverSchedulerAppend, E as createServer, F as A2Operation, I as A2PushEvent, L as A2PushPresence, M as SchedulerClearTask, N as SchedulerDrainTask, O as deliverSchedulerClear, P as SchedulerTask, R as ServerFetchOptions, S as SessionRedriveOptions, T as StateOptions, _ as SessionClearOptions, a as DrainableServer, b as SessionDispatch, c as HandlerContext, d as LaneContext, f as ScheduleDelay, g as SessionAppend, h as Session, i as DeadLetter, j as SchedulerAppendTask, k as handler, l as HandlerEntry, m as ServerOptions, n as A2Server, o as Handler, p as ScheduleTiming, r as AbortSpec, s as HandlerAppend, t as A2Scheduler, u as Lane, v as SessionClearResult, w as SessionSchedule, x as SessionPresence, y as SessionDeadLetters, z as UpgradeWebSocket } from "./server-DYAATFuT.js";
4
- export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, type Contract, type ContractEvent, DeadLetter, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, Handler, HandlerAppend, HandlerContext, HandlerEntry, type IdSource, Lane, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerClearTask, type SchedulerDrainTask, type SchedulerTask, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionClearOptions, SessionClearResult, SessionDeadLetters, SessionDispatch, SessionPresence, SessionRedriveOptions, SessionRedriveResult, SessionSchedule, StateOptions, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, createServer, deliverSchedulerAppend, deliverSchedulerClear, handler };
1
+ import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, s as Contract, u as EventDefs } from "./reducer-CYPHsSmd.js";
2
+ import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-D0MhBvg6.js";
3
+ import { A as SessionSchedule, B as SchedulerTask, C as SessionConsumeOptions, D as SessionPresence, E as SessionDispatch, F as deliverSchedulerClear, G as UpgradeWebSocket, H as A2PushEvent, I as ScheduledEvent, K as A2Socket, L as SchedulerAppendTask, M as consumer, N as createServer, O as SessionRedriveOptions, P as deliverSchedulerAppend, R as SchedulerClearTask, S as SessionClearResult, T as SessionDeadLetters, U as A2PushPresence, V as A2Operation, W as ServerFetchOptions, _ as ServerConsumers, a as ConsumerAppend, b as SessionAppend, c as ConsumerOptions, d as DeadLetter, f as DrainableServer, g as ScheduleTiming, h as ScheduleDelay, i as Consumer, j as StateOptions, k as SessionRedriveResult, l as ConsumerResult, m as LaneContext, n as A2Server, o as ConsumerContext, p as InlineConsumer, r as AbortSpec, s as ConsumerLane, t as A2Scheduler, u as ConsumerSpec, v as ServerOptions, w as SessionConsumeResult, x as SessionClearOptions, y as Session, z as SchedulerDrainTask } from "./server-qgez0Xny.js";
4
+ export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, Consumer, ConsumerAppend, ConsumerContext, ConsumerLane, ConsumerOptions, ConsumerResult, ConsumerSpec, type Contract, type ContractEvent, DeadLetter, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, type IdSource, InlineConsumer, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerClearTask, type SchedulerDrainTask, type SchedulerTask, ServerConsumers, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionClearOptions, SessionClearResult, SessionConsumeOptions, SessionConsumeResult, SessionDeadLetters, SessionDispatch, SessionPresence, SessionRedriveOptions, SessionRedriveResult, SessionSchedule, StateOptions, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, consumer, createServer, deliverSchedulerAppend, deliverSchedulerClear };
package/dist/server.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as handler, n as deliverSchedulerAppend, r as deliverSchedulerClear, t as createServer } from "./server-qyb5aJJG.js";
2
- export { createServer, deliverSchedulerAppend, deliverSchedulerClear, handler };
1
+ import { i as deliverSchedulerClear, n as createServer, r as deliverSchedulerAppend, t as consumer } from "./server-DtFrWxi3.js";
2
+ export { consumer, createServer, deliverSchedulerAppend, deliverSchedulerClear };
@@ -1,4 +1,4 @@
1
- import { i as Event } from "./store-CyLUy86v.js";
1
+ import { i as Event } from "./store-D0MhBvg6.js";
2
2
  //#region src/session-clear.d.ts
3
3
  /** Reserved type of the marker a clear appends. */
4
4
  declare const CLEAR_EVENT_TYPE = "a2.cleared";
@@ -9,4 +9,4 @@ type SessionCleared = Event & {
9
9
  };
10
10
  //#endregion
11
11
  export { SessionCleared as t };
12
- //# sourceMappingURL=session-clear-C-QwTXV1.d.ts.map
12
+ //# sourceMappingURL=session-clear-D1PFe7xl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-clear-D1PFe7xl.d.ts","names":[],"sources":["../src/session-clear.ts"],"mappings":";;;cAOa;;KAGD,iBAAiB;EAC3B,aAAa;EACb"}
@@ -10,9 +10,10 @@ var A2Error = class extends Error {
10
10
  this.details = options?.details;
11
11
  }
12
12
  };
13
- /** A handler write whose attempt no longer owns its triggering event. */
13
+ /** A consumer write whose attempt no longer owns its triggering event. */
14
14
  function supersededAttemptError(sessionId, cause) {
15
- return new A2Error("SUPERSEDED_ATTEMPT", `attempt ${cause.attempt} no longer owns event ${cause.index} in session '${sessionId}'`);
15
+ const of = cause.consumer === void 0 ? "" : ` for consumer '${cause.consumer}'`;
16
+ return new A2Error("SUPERSEDED_ATTEMPT", `attempt ${cause.attempt} no longer owns event ${cause.index}${of} in session '${sessionId}'`);
16
17
  }
17
18
  /**
18
19
  * Wrap an arbitrary thrown value as STORE_UNAVAILABLE, preserving the
@@ -24,7 +25,7 @@ function asStoreUnavailable(err) {
24
25
  return new A2Error("STORE_UNAVAILABLE", "the store backend failed", { cause: err });
25
26
  }
26
27
  /**
27
- * Throw from a handler to reject retrying: the failure is adjudicated
28
+ * Throw from a consumer to reject retrying: the failure is adjudicated
28
29
  * terminal immediately (dead-lettered on the first throw) instead of
29
30
  * consuming the ten-failure retry budget. For deterministic failures —
30
31
  * a guard that will refuse identically on every attempt — retrying is
@@ -51,4 +52,4 @@ function sessionClearedError(message) {
51
52
  //#endregion
52
53
  export { NonRetriableError as a, A2Error as i, isSessionCleared as n, asStoreUnavailable as o, sessionClearedError as r, supersededAttemptError as s, CLEAR_EVENT_TYPE as t };
53
54
 
54
- //# sourceMappingURL=session-clear-DGI4jTQ5.js.map
55
+ //# sourceMappingURL=session-clear-wHd5GCpZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-clear-wHd5GCpZ.js","names":[],"sources":["../src/errors.ts","../src/session-clear.ts"],"sourcesContent":["export type A2ServerErrorCode =\n | 'INVALID_PAYLOAD' // schema validation failed — thrown before anything is written\n | 'FORBIDDEN' // external ingress was denied by server.fetch authorization\n | 'UNKNOWN_EVENT_TYPE' // event type not in the machine's `events` map\n | 'PARTIAL_DUPLICATE_BATCH' // batch mixed already-appended and fresh events\n | 'SUPERSEDED_ATTEMPT' // consumer append from an attempt a recovery claim or a clear replaced\n | 'SESSION_CLEARED' // a read or call reached across the session's latest clear\n | 'CLAIM_EXPIRED' // ctx.signal abort reason: the attempt's lease lapsed without renewal\n | 'STORE_UNAVAILABLE' // store backend failure — retryable, nothing was written\n | 'STORE_NOT_CONFIGURED' // no `store` in production, a missing peer dependency, or Postgres lacks A2's tables\n | 'UNKNOWN_PRESENCE_FIELD' // presence field not in the contract's `presence` map\n | 'PRESENCE_NOT_SUPPORTED' // contract declares presence but the store lacks the capability\n | 'CONSUMER_DEAD_LETTERED' // session.consume reached a head that dead-lettered for that consumer\n\nexport type A2ErrorCode =\n A2ServerErrorCode | 'TIMEOUT' | 'HTTP_ERROR' | 'CONNECTION_FAILED' | 'UNKNOWN'\n\nexport class A2Error extends Error {\n readonly code: A2ErrorCode\n /** e.g. the Standard Schema issues for INVALID_PAYLOAD */\n readonly details: unknown\n\n constructor(\n code: A2ErrorCode,\n message: string,\n options?: { details?: unknown; cause?: unknown },\n ) {\n super(\n message,\n options && 'cause' in options ? { cause: options.cause } : undefined,\n )\n this.name = 'A2Error'\n this.code = code\n this.details = options?.details\n }\n}\n\n/** A consumer write whose attempt no longer owns its triggering event. */\nexport function supersededAttemptError(\n sessionId: string,\n cause: { consumer?: string; index: number; attempt: number },\n): A2Error {\n const of =\n cause.consumer === undefined ? '' : ` for consumer '${cause.consumer}'`\n return new A2Error(\n 'SUPERSEDED_ATTEMPT',\n `attempt ${cause.attempt} no longer owns event ${cause.index}${of} in session '${sessionId}'`,\n )\n}\n\n/**\n * Wrap an arbitrary thrown value as STORE_UNAVAILABLE, preserving the\n * original as `cause`. A2Errors pass through untouched — they already\n * carry their own meaning.\n */\nexport function asStoreUnavailable(err: unknown): A2Error {\n if (err instanceof A2Error) return err\n return new A2Error('STORE_UNAVAILABLE', 'the store backend failed', {\n cause: err,\n })\n}\n\n/**\n * Throw from a consumer to reject retrying: the failure is adjudicated\n * terminal immediately (dead-lettered on the first throw) instead of\n * consuming the ten-failure retry budget. For deterministic failures —\n * a guard that will refuse identically on every attempt — retrying is\n * waste and dead-lettering is the honest outcome. Matched by\n * `instanceof`, so subclasses carry domain meaning.\n */\nexport class NonRetriableError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = 'NonRetriableError'\n }\n}\n","import { A2Error } from './errors.ts'\nimport type { Event } from './store.ts'\n\n/** A2's own event types start with this; application contracts cannot. */\nexport const RESERVED_EVENT_PREFIX = 'a2.'\n\n/** Reserved type of the marker a clear appends. */\nexport const CLEAR_EVENT_TYPE = 'a2.cleared'\n\n/** The marker `session.stream()` yields where a clear ended a lifetime. */\nexport type SessionCleared = Event & {\n type: typeof CLEAR_EVENT_TYPE\n payload: null\n}\n\n/** Accepts any stream item, including presence patches and snapshots. */\nexport function isSessionCleared(item: object): item is SessionCleared {\n return (item as { type?: unknown }).type === CLEAR_EVENT_TYPE\n}\n\nexport function sessionClearedError(message: string): A2Error {\n return new A2Error('SESSION_CLEARED', message)\n}\n"],"mappings":";AAiBA,IAAa,UAAb,cAA6B,MAAM;CACjC;;CAEA;CAEA,YACE,MACA,SACA,SACA;EACA,MACE,SACA,WAAW,WAAW,UAAU,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA,CAC7D;EACA,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,UAAU,SAAS;CAC1B;AACF;;AAGA,SAAgB,uBACd,WACA,OACS;CACT,MAAM,KACJ,MAAM,aAAa,KAAA,IAAY,KAAK,kBAAkB,MAAM,SAAS;CACvE,OAAO,IAAI,QACT,sBACA,WAAW,MAAM,QAAQ,wBAAwB,MAAM,QAAQ,GAAG,eAAe,UAAU,EAC7F;AACF;;;;;;AAOA,SAAgB,mBAAmB,KAAuB;CACxD,IAAI,eAAe,SAAS,OAAO;CACnC,OAAO,IAAI,QAAQ,qBAAqB,4BAA4B,EAClE,OAAO,IACT,CAAC;AACH;;;;;;;;;AAUA,IAAa,oBAAb,cAAuC,MAAM;CAC3C,YAAY,SAAiB,SAA+B;EAC1D,MAAM,SAAS,OAAO;EACtB,KAAK,OAAO;CACd;AACF;;;;ACpEA,MAAa,mBAAmB;;AAShC,SAAgB,iBAAiB,MAAsC;CACrE,OAAQ,KAA4B,SAAS;AAC/C;AAEA,SAAgB,oBAAoB,SAA0B;CAC5D,OAAO,IAAI,QAAQ,mBAAmB,OAAO;AAC/C"}