experimental-a2 0.17.0 → 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 (211) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/dist/{actor-DBbe5xeE.d.ts → actor-Bjce9_5U.d.ts} +5 -5
  4. package/dist/{actor-DBbe5xeE.d.ts.map → actor-Bjce9_5U.d.ts.map} +1 -1
  5. package/dist/actor-client.d.ts +1 -1
  6. package/dist/actor-react.d.ts +3 -3
  7. package/dist/actor-react.js +1 -1
  8. package/dist/actor.d.ts +1 -1
  9. package/dist/actor.js +2 -2
  10. package/dist/{ai-UrWfKeuv.js → ai-BpOGm-zB.js} +2 -2
  11. package/dist/{ai-UrWfKeuv.js.map → ai-BpOGm-zB.js.map} +1 -1
  12. package/dist/{ai-vpGtcaCB.d.ts → ai-DrUaMyRt.d.ts} +3 -3
  13. package/dist/{ai-vpGtcaCB.d.ts.map → ai-DrUaMyRt.d.ts.map} +1 -1
  14. package/dist/ai-client.d.ts +2 -2
  15. package/dist/ai-client.js +2 -2
  16. package/dist/ai-fx.browser.d.ts +1 -0
  17. package/dist/ai-fx.browser.js +6 -0
  18. package/dist/ai-fx.browser.js.map +1 -0
  19. package/dist/ai-fx.d.ts +10 -0
  20. package/dist/ai-fx.d.ts.map +1 -0
  21. package/dist/ai-fx.js +634 -0
  22. package/dist/ai-fx.js.map +1 -0
  23. package/dist/ai-harness-BuLh_EYi.js +273 -0
  24. package/dist/ai-harness-BuLh_EYi.js.map +1 -0
  25. package/dist/ai-harness-DvsPeJeB.d.ts +26 -0
  26. package/dist/ai-harness-DvsPeJeB.d.ts.map +1 -0
  27. package/dist/ai-pi.browser.d.ts +1 -0
  28. package/dist/ai-pi.browser.js +6 -0
  29. package/dist/ai-pi.browser.js.map +1 -0
  30. package/dist/ai-pi.d.ts +17 -0
  31. package/dist/ai-pi.d.ts.map +1 -0
  32. package/dist/ai-pi.js +904 -0
  33. package/dist/ai-pi.js.map +1 -0
  34. package/dist/ai-react.d.ts +5 -5
  35. package/dist/ai-react.js +2 -2
  36. package/dist/ai-server.d.ts +47 -25
  37. package/dist/ai-server.d.ts.map +1 -1
  38. package/dist/ai-server.js +106 -37
  39. package/dist/ai-server.js.map +1 -1
  40. package/dist/ai.d.ts +1 -1
  41. package/dist/ai.js +1 -1
  42. package/dist/bounded-cache-CPHWF-8h.js +41 -0
  43. package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
  44. package/dist/{client-COaiaDub.js → client-BReKqwZC.js} +3 -3
  45. package/dist/{client-COaiaDub.js.map → client-BReKqwZC.js.map} +1 -1
  46. package/dist/{client-qRnRUzBS.d.ts → client-h_DKFAjj.d.ts} +3 -3
  47. package/dist/{client-qRnRUzBS.d.ts.map → client-h_DKFAjj.d.ts.map} +1 -1
  48. package/dist/client.d.ts +3 -3
  49. package/dist/client.js +1 -1
  50. package/dist/index.d.ts +5 -5
  51. package/dist/{initial-snapshot-BrLso5x_.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +2 -2
  52. package/dist/{initial-snapshot-BrLso5x_.d.ts.map → initial-snapshot-Bx-c0pDP.d.ts.map} +1 -1
  53. package/dist/{internal-CbVvEwad.js → internal-B2T3U4Rq.js} +8 -2
  54. package/dist/internal-B2T3U4Rq.js.map +1 -0
  55. package/dist/otel.d.ts +1 -1
  56. package/dist/{react-BbJ-g6Uu.d.ts → react-BBXgHWFc.d.ts} +4 -4
  57. package/dist/{react-BbJ-g6Uu.d.ts.map → react-BBXgHWFc.d.ts.map} +1 -1
  58. package/dist/react.d.ts +1 -1
  59. package/dist/react.js +1 -1
  60. package/dist/reducer-BAXc8JyF.js.map +1 -1
  61. package/dist/{reducer-BYu6DT7h.d.ts → reducer-CqA59Q6U.d.ts} +2 -2
  62. package/dist/{reducer-BYu6DT7h.d.ts.map → reducer-CqA59Q6U.d.ts.map} +1 -1
  63. package/dist/scheduler-qstash.d.ts +2 -2
  64. package/dist/scheduler-qstash.js +2 -2
  65. package/dist/scheduler-vercel.d.ts +2 -2
  66. package/dist/scheduler-vercel.js +2 -2
  67. package/dist/{server-Rj64fNvX.js → server-Dw_k_7kO.js} +93 -60
  68. package/dist/server-Dw_k_7kO.js.map +1 -0
  69. package/dist/{server-CGM8WzRG.d.ts → server-En7cbi3v.d.ts} +36 -7
  70. package/dist/server-En7cbi3v.d.ts.map +1 -0
  71. package/dist/server.d.ts +4 -4
  72. package/dist/server.js +1 -1
  73. package/dist/{session-clear-Dshpuhff.d.ts → session-clear-Bo-XTFEy.d.ts} +2 -2
  74. package/dist/session-clear-Bo-XTFEy.d.ts.map +1 -0
  75. package/dist/{store-Gpkq7WBo.d.ts → store-Djdv0bnZ.d.ts} +31 -2
  76. package/dist/store-Djdv0bnZ.d.ts.map +1 -0
  77. package/dist/store-N8PXxDAS.js.map +1 -1
  78. package/dist/store-memory.d.ts +1 -1
  79. package/dist/store-memory.js +32 -6
  80. package/dist/store-memory.js.map +1 -1
  81. package/dist/{store-polling-4_y8lETm.js → store-polling-B5FcwJfo.js} +2 -2
  82. package/dist/{store-polling-4_y8lETm.js.map → store-polling-B5FcwJfo.js.map} +1 -1
  83. package/dist/store-postgres.d.ts +1 -1
  84. package/dist/store-postgres.js +54 -3
  85. package/dist/store-postgres.js.map +1 -1
  86. package/dist/{store-presence-polling-Q1C-k2dd.js → store-presence-polling-BAwS8RWn.js} +3 -3
  87. package/dist/{store-presence-polling-Q1C-k2dd.js.map → store-presence-polling-BAwS8RWn.js.map} +1 -1
  88. package/dist/store-redis-http.d.ts +1 -1
  89. package/dist/store-redis-http.js +3 -3
  90. package/dist/{store-redis-notify-tqWNnMRu.js → store-redis-notify-BRITti_o.js} +187 -68
  91. package/dist/store-redis-notify-BRITti_o.js.map +1 -0
  92. package/dist/store-redis.d.ts +1 -1
  93. package/dist/store-redis.js +1 -1
  94. package/dist/store-sqlite.d.ts +1 -1
  95. package/dist/store-sqlite.js +32 -2
  96. package/dist/store-sqlite.js.map +1 -1
  97. package/dist/{telemetry-cZH-cibj.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
  98. package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
  99. package/dist/{wire-DjfHOvdW.js → wire-rSUglYo8.js} +2 -2
  100. package/dist/{wire-DjfHOvdW.js.map → wire-rSUglYo8.js.map} +1 -1
  101. package/docs/01-quickstart.mdx +49 -83
  102. package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
  103. package/docs/actors/01-introduction.mdx +48 -86
  104. package/docs/actors/02-concurrency.mdx +43 -70
  105. package/docs/actors/03-timers.mdx +28 -42
  106. package/docs/actors/04-routes.mdx +110 -150
  107. package/docs/actors/meta.ts +1 -1
  108. package/docs/agents/01-introduction.mdx +257 -0
  109. package/docs/agents/02-tools.mdx +247 -0
  110. package/docs/agents/03-conversations.mdx +538 -0
  111. package/docs/agents/04-harnesses.mdx +136 -0
  112. package/docs/agents/meta.ts +1 -0
  113. package/docs/client/01-react.mdx +294 -0
  114. package/docs/client/02-transports.mdx +86 -0
  115. package/docs/client/03-presence.mdx +224 -0
  116. package/docs/client/meta.ts +1 -0
  117. package/docs/contract/01-events.mdx +57 -0
  118. package/docs/contract/02-state.mdx +142 -0
  119. package/docs/contract/03-sessions.mdx +175 -0
  120. package/docs/index.mdx +108 -144
  121. package/docs/reference/01-core.mdx +139 -0
  122. package/docs/reference/02-server.mdx +855 -0
  123. package/docs/reference/03-client.mdx +301 -0
  124. package/docs/reference/04-ai.mdx +722 -0
  125. package/docs/reference/05-adapters.mdx +351 -0
  126. package/docs/reference/06-errors.mdx +138 -0
  127. package/docs/reference/meta.ts +1 -1
  128. package/docs/server/01-handlers.mdx +200 -0
  129. package/docs/server/02-timers.mdx +130 -0
  130. package/docs/server/03-cancellation.mdx +141 -0
  131. package/docs/server/04-routes.mdx +243 -0
  132. package/docs/server/05-production.mdx +322 -0
  133. package/docs/server/06-guarantees.mdx +123 -0
  134. package/examples/playground/DEPLOY.md +1 -1
  135. package/examples/playground/app/a0/[appId]/page.tsx +11 -6
  136. package/examples/playground/app/a0/app-list.tsx +9 -2
  137. package/examples/playground/app/a0/app-view.tsx +9 -1
  138. package/examples/playground/app/a0/apps/[appId]/route.ts +10 -5
  139. package/examples/playground/app/a0/apps.test.ts +12 -0
  140. package/examples/playground/app/a0/apps.ts +22 -7
  141. package/examples/playground/app/a0/chat.tsx +47 -1
  142. package/examples/playground/app/a0/fx/events/route.ts +9 -0
  143. package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
  144. package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
  145. package/examples/playground/app/a0/model.test.ts +18 -1
  146. package/examples/playground/app/a0/model.ts +47 -10
  147. package/examples/playground/app/a0/no-photon.cjs +4 -0
  148. package/examples/playground/app/a0/no-quickjs.cjs +3 -0
  149. package/examples/playground/app/a0/pi/events/route.ts +9 -0
  150. package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
  151. package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
  152. package/examples/playground/app/a0/sandbox-log.ts +10 -4
  153. package/examples/playground/app/a0/sandbox-session.ts +152 -0
  154. package/examples/playground/app/a0/scheduler/route.ts +2 -2
  155. package/examples/playground/app/a0/server.ts +100 -45
  156. package/examples/playground/app/a0/session.ts +17 -5
  157. package/examples/playground/app/a0/shell.tsx +11 -3
  158. package/examples/playground/app/agent/ingress.test.ts +6 -3
  159. package/examples/playground/app/agent/server.ts +9 -6
  160. package/examples/playground/app/agent/telemetry.test.ts +71 -50
  161. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +1 -1
  162. package/examples/playground/app/chat/server.test.ts +30 -26
  163. package/examples/playground/app/chat/server.ts +46 -46
  164. package/examples/playground/next.config.ts +17 -5
  165. package/examples/playground/package.json +4 -1
  166. package/examples/playground/vercel.json +18 -0
  167. package/package.json +27 -3
  168. package/src/ai-agent.ts +261 -87
  169. package/src/ai-fx.browser.ts +5 -0
  170. package/src/ai-fx.ts +833 -0
  171. package/src/ai-harness.ts +518 -0
  172. package/src/ai-model-metadata.ts +11 -6
  173. package/src/ai-pi.browser.ts +5 -0
  174. package/src/ai-pi.ts +1263 -0
  175. package/src/ai-sdk-step.ts +2 -2
  176. package/src/ai-server.ts +3 -1
  177. package/src/internal.ts +7 -0
  178. package/src/libfx.d.ts +34 -0
  179. package/src/reducer.ts +1 -1
  180. package/src/server.ts +177 -19
  181. package/src/store-memory.ts +42 -7
  182. package/src/store-postgres.ts +80 -0
  183. package/src/store-redis-core.ts +210 -79
  184. package/src/store-redis-notify.ts +2 -0
  185. package/src/store-sqlite.ts +60 -0
  186. package/src/store.ts +33 -0
  187. package/src/telemetry.ts +1 -0
  188. package/dist/internal-CbVvEwad.js.map +0 -1
  189. package/dist/server-CGM8WzRG.d.ts.map +0 -1
  190. package/dist/server-Rj64fNvX.js.map +0 -1
  191. package/dist/session-clear-Dshpuhff.d.ts.map +0 -1
  192. package/dist/store-Gpkq7WBo.d.ts.map +0 -1
  193. package/dist/store-redis-notify-tqWNnMRu.js.map +0 -1
  194. package/dist/telemetry-cZH-cibj.d.ts.map +0 -1
  195. package/docs/concepts/01-contracts.mdx +0 -237
  196. package/docs/concepts/02-handlers.mdx +0 -284
  197. package/docs/concepts/03-durability.mdx +0 -314
  198. package/docs/concepts/04-state.mdx +0 -209
  199. package/docs/guides/01-timers.mdx +0 -193
  200. package/docs/guides/02-cancellation.mdx +0 -161
  201. package/docs/guides/03-react.mdx +0 -324
  202. package/docs/guides/04-local-first.mdx +0 -47
  203. package/docs/guides/05-production.mdx +0 -534
  204. package/docs/guides/06-ai-agents.mdx +0 -1408
  205. package/docs/guides/08-application-data.mdx +0 -113
  206. package/docs/guides/09-presence.mdx +0 -262
  207. package/docs/guides/10-transports.mdx +0 -221
  208. package/docs/reference/01-api.mdx +0 -2358
  209. package/docs/reference/02-errors.mdx +0 -150
  210. /package/docs/{concepts → contract}/meta.ts +0 -0
  211. /package/docs/{guides → server}/meta.ts +0 -0
@@ -1,5 +1,5 @@
1
- import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, o as AppendInput, p as PresencePatch, s as Contract, t as Reducer, u as EventDefs } from "./reducer-BYu6DT7h.js";
2
- import { n as A2Error, r as A2ErrorCode, t as InitialSnapshot } from "./initial-snapshot-BrLso5x_.js";
1
+ import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, o as AppendInput, p as PresencePatch, s as Contract, t as Reducer, u as EventDefs } from "./reducer-CqA59Q6U.js";
2
+ import { n as A2Error, r as A2ErrorCode, t as InitialSnapshot } from "./initial-snapshot-Bx-c0pDP.js";
3
3
  //#region src/client-errors.d.ts
4
4
  type A2ClientErrorOptions = {
5
5
  details?: unknown;
@@ -241,4 +241,4 @@ type CreateClientOptions<D extends EventDefs, S, P extends PresenceDefs = Record
241
241
  declare function createClient<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>>(options: CreateClientOptions<D, S, P>): A2Client<D, S, P>;
242
242
  //#endregion
243
243
  export { createClient as _, Connection as a, HistoryState as c, ReconnectPolicy as d, SessionClient as f, SessionUrl as g, SessionSnapshot as h, ClientWebSocketConstructor as i, LoadHistoryOptions as l, SessionOptions as m, ClientApi as n, ConnectionStatus as o, SessionClientPresence as p, ClientWebSocket as r, CreateClientOptions as s, A2Client as t, PushResult as u, A2ClientError as v, A2ClientErrorOptions as y };
244
- //# sourceMappingURL=client-qRnRUzBS.d.ts.map
244
+ //# sourceMappingURL=client-h_DKFAjj.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-qRnRUzBS.d.ts","names":[],"sources":["../src/client-errors.ts","../src/client.ts"],"mappings":";;;KAEY;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;cAGW,sBAAsB;WACxB;WACA;WACA;WACA;WACA;EAET,YACE,MAAM,aACN,iBACA,UAAU;;;;KCmDF,mBAAmB;EAC7B;EACA,OAAO;EACP;;KAGU;;;;;;;KASA;EACN;;EAEA;;EAEA;;EAEA,OAAO;;EAEP;EAAkB;EAAoB,OAAO;;EAC7C;EAAgB;;EAChB;;;;;;;;;;KAUM,WAAW,UAAU,aAAa,QAAQ,cAAc;WACzD,WAAW,QAAQ,cAAc;;KAGhC;;;;;;EAMV;;EAEA;;;KAIU;;EAEV;;EAEA;;EAEA;;;KAIU,gBACV,UAAU,WACV,GACA,UAAU,eAAe,wBACvB,aACF;;EAGE,UAAU,YAAY;;;EAIxB,OAAO;;EAEP;;;;;EAKA,QAAQ,cAAc;;;EAGtB;;EAEA,SAAS;EACT,YAAY;;;;;;;KAQF,sBAAsB,UAAU;;;;;;;;;;EAU1C,YAAY,QAAQ,cAAc;;KAGxB,cACV,UAAU,WACV,GACA,UAAU,eAAe,wBACvB,aAAa,GAAG,sBAAsB;WAC/B;EACT,UAAU;EACV,eAAe,gBAAgB,GAAG,GAAG;;;;;;;;;;EAUrC,QAAQ,QAAQ,YAAY,OAAO,WAAW;;;;;;;;;;;EAW9C,YAAY,UAAU,qBAAqB,QAAQ,cAAc;;;;;;;;;;EAUjE;;;EAGA;;;;;;EAMA;;KAGU,eAAe,UAAU,WAAW;EAC9C,UAAU,gBAAgB;;EAE1B,gBAAgB,cAAc;;;EAG9B;;KAiCU,SACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,QACE,mBACA,UAAU,eAAe,GAAG,KAC3B,cAAc,GAAG,GAAG;;;;;;;;;KAUb,wBAAwB;KAExB,YACR;EACE;EAAc,MAAM;EAAY,QAAQ;;EAExC;EAAY,KAAK;EAAY;;EAE7B;EAAY;EAAa;;;;;;;KAOnB;WACD;EACT,KAAK;EACL,MAAM,eAAe;EACrB,iBAAiB,cAAc;EAC/B,iBACE,iBACA,WAAW;IAAS;;EAEtB,iBACE,eACA,WAAW;IAAS;IAAc;;EAEpC,iBAAiB,eAAe;;KAGtB,kCAAkC,gBAAgB;KAElD,oBACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,UAAU,SAAS,GAAG,GAAG,QAAQ,GAAG,GAAG;;EAEvC,KAAK;;EAEL,YAAY;;EAEZ,eAAe,WAAW;;;EAG1B,YAAY;;;EAGZ;;;;;;;;EAQA;;iBA8lCc,aACd,UAAU,WACV,GACA,UAAU,eAAe,sBACzB,SAAS,oBAAoB,GAAG,GAAG,KAAK,SAAS,GAAG,GAAG"}
1
+ {"version":3,"file":"client-h_DKFAjj.d.ts","names":[],"sources":["../src/client-errors.ts","../src/client.ts"],"mappings":";;;KAEY;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;cAGW,sBAAsB;WACxB;WACA;WACA;WACA;WACA;EAET,YACE,MAAM,aACN,iBACA,UAAU;;;;KCmDF,mBAAmB;EAC7B;EACA,OAAO;EACP;;KAGU;;;;;;;KASA;EACN;;EAEA;;EAEA;;EAEA,OAAO;;EAEP;EAAkB;EAAoB,OAAO;;EAC7C;EAAgB;;EAChB;;;;;;;;;;KAUM,WAAW,UAAU,aAAa,QAAQ,cAAc;WACzD,WAAW,QAAQ,cAAc;;KAGhC;;;;;;EAMV;;EAEA;;;KAIU;;EAEV;;EAEA;;EAEA;;;KAIU,gBACV,UAAU,WACV,GACA,UAAU,eAAe,wBACvB,aACF;;EAGE,UAAU,YAAY;;;EAIxB,OAAO;;EAEP;;;;;EAKA,QAAQ,cAAc;;;EAGtB;;EAEA,SAAS;EACT,YAAY;;;;;;;KAQF,sBAAsB,UAAU;;;;;;;;;;EAU1C,YAAY,QAAQ,cAAc;;KAGxB,cACV,UAAU,WACV,GACA,UAAU,eAAe,wBACvB,aAAa,GAAG,sBAAsB;WAC/B;EACT,UAAU;EACV,eAAe,gBAAgB,GAAG,GAAG;;;;;;;;;;EAUrC,QAAQ,QAAQ,YAAY,OAAO,WAAW;;;;;;;;;;;EAW9C,YAAY,UAAU,qBAAqB,QAAQ,cAAc;;;;;;;;;;EAUjE;;;EAGA;;;;;;EAMA;;KAGU,eAAe,UAAU,WAAW;EAC9C,UAAU,gBAAgB;;EAE1B,gBAAgB,cAAc;;;EAG9B;;KAiCU,SACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,QACE,mBACA,UAAU,eAAe,GAAG,KAC3B,cAAc,GAAG,GAAG;;;;;;;;;KAUb,wBAAwB;KAExB,YACR;EACE;EAAc,MAAM;EAAY,QAAQ;;EAExC;EAAY,KAAK;EAAY;;EAE7B;EAAY;EAAa;;;;;;;KAOnB;WACD;EACT,KAAK;EACL,MAAM,eAAe;EACrB,iBAAiB,cAAc;EAC/B,iBACE,iBACA,WAAW;IAAS;;EAEtB,iBACE,eACA,WAAW;IAAS;IAAc;;EAEpC,iBAAiB,eAAe;;KAGtB,kCAAkC,gBAAgB;KAElD,oBACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,UAAU,SAAS,GAAG,GAAG,QAAQ,GAAG,GAAG;;EAEvC,KAAK;;EAEL,YAAY;;EAEZ,eAAe,WAAW;;;EAG1B,YAAY;;;EAGZ;;;;;;;;EAQA;;iBA8lCc,aACd,UAAU,WACV,GACA,UAAU,eAAe,sBACzB,SAAS,oBAAoB,GAAG,GAAG,KAAK,SAAS,GAAG,GAAG"}
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as StateSnapshot } from "./reducer-BYu6DT7h.js";
2
- import { t as InitialSnapshot } from "./initial-snapshot-BrLso5x_.js";
3
- import { _ as createClient, a as Connection, c as HistoryState, d as ReconnectPolicy, f as SessionClient, g as SessionUrl, h as SessionSnapshot, i as ClientWebSocketConstructor, l as LoadHistoryOptions, m as SessionOptions, n as ClientApi, o as ConnectionStatus, p as SessionClientPresence, r as ClientWebSocket, s as CreateClientOptions, t as A2Client, u as PushResult, v as A2ClientError, y as A2ClientErrorOptions } from "./client-qRnRUzBS.js";
1
+ import { i as StateSnapshot } from "./reducer-CqA59Q6U.js";
2
+ import { t as InitialSnapshot } from "./initial-snapshot-Bx-c0pDP.js";
3
+ import { _ as createClient, a as Connection, c as HistoryState, d as ReconnectPolicy, f as SessionClient, g as SessionUrl, h as SessionSnapshot, i as ClientWebSocketConstructor, l as LoadHistoryOptions, m as SessionOptions, n as ClientApi, o as ConnectionStatus, p as SessionClientPresence, r as ClientWebSocket, s as CreateClientOptions, t as A2Client, u as PushResult, v as A2ClientError, y as A2ClientErrorOptions } from "./client-h_DKFAjj.js";
4
4
  export { A2Client, A2ClientError, type A2ClientErrorOptions, ClientApi, ClientWebSocket, ClientWebSocketConstructor, Connection, ConnectionStatus, CreateClientOptions, HistoryState, type InitialSnapshot, LoadHistoryOptions, PushResult, ReconnectPolicy, SessionClient, SessionClientPresence, SessionOptions, SessionSnapshot, SessionUrl, type StateSnapshot, createClient };
package/dist/client.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as A2ClientError, t as createClient } from "./client-COaiaDub.js";
1
+ import { a as A2ClientError, t as createClient } from "./client-BReKqwZC.js";
2
2
  export { A2ClientError, createClient };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { _ as contract, a as reducer, c as ContractEvent, d as PresenceDefs, f as PresenceMap, h as ReducerOptions, i as StateSnapshot, l as EventBatchFactory, m as PresenceSnapshot, n as ReducerBuilder, o as AppendInput, p as PresencePatch, s as Contract, t as Reducer, u as EventDefs, v as StandardSchemaV1 } from "./reducer-BYu6DT7h.js";
2
- import { a as NonRetriableError, i as A2ServerErrorCode, n as A2Error, r as A2ErrorCode, t as InitialSnapshot } from "./initial-snapshot-BrLso5x_.js";
3
- import { i as Event } from "./store-Gpkq7WBo.js";
4
- import { t as SessionCleared } from "./session-clear-Dshpuhff.js";
5
- import { i as A2Telemetry, n as A2SpanHandle, r as A2SpanName, t as A2AttributeValue } from "./telemetry-cZH-cibj.js";
1
+ import { _ as contract, a as reducer, c as ContractEvent, d as PresenceDefs, f as PresenceMap, h as ReducerOptions, i as StateSnapshot, l as EventBatchFactory, m as PresenceSnapshot, n as ReducerBuilder, o as AppendInput, p as PresencePatch, s as Contract, t as Reducer, u as EventDefs, v as StandardSchemaV1 } from "./reducer-CqA59Q6U.js";
2
+ import { a as NonRetriableError, i as A2ServerErrorCode, n as A2Error, r as A2ErrorCode, t as InitialSnapshot } from "./initial-snapshot-Bx-c0pDP.js";
3
+ import { i as Event } from "./store-Djdv0bnZ.js";
4
+ import { t as SessionCleared } from "./session-clear-Bo-XTFEy.js";
5
+ import { i as A2Telemetry, n as A2SpanHandle, r as A2SpanName, t as A2AttributeValue } from "./telemetry-Cyfqo6Qt.js";
6
6
  //#region src/idempotent-id.d.ts
7
7
  declare function idempotentId(...parts: string[]): Promise<string>;
8
8
  //#endregion
@@ -1,4 +1,4 @@
1
- import { i as StateSnapshot } from "./reducer-BYu6DT7h.js";
1
+ import { i as StateSnapshot } from "./reducer-CqA59Q6U.js";
2
2
  //#region src/errors.d.ts
3
3
  type A2ServerErrorCode = "INVALID_PAYLOAD" | "FORBIDDEN" | "UNKNOWN_EVENT_TYPE" | "PARTIAL_DUPLICATE_BATCH" | "SUPERSEDED_ATTEMPT" | "SESSION_CLEARED" | "CLAIM_EXPIRED" | "STORE_UNAVAILABLE" | "STORE_NOT_CONFIGURED" | "UNKNOWN_PRESENCE_FIELD" | "PRESENCE_NOT_SUPPORTED";
4
4
  type A2ErrorCode = A2ServerErrorCode | "TIMEOUT" | "HTTP_ERROR" | "CONNECTION_FAILED" | "UNKNOWN";
@@ -29,4 +29,4 @@ declare class NonRetriableError extends Error {
29
29
  type InitialSnapshot<S> = StateSnapshot<S> | null | undefined | Promise<StateSnapshot<S> | null | undefined>;
30
30
  //#endregion
31
31
  export { NonRetriableError as a, A2ServerErrorCode as i, A2Error as n, A2ErrorCode as r, InitialSnapshot as t };
32
- //# sourceMappingURL=initial-snapshot-BrLso5x_.d.ts.map
32
+ //# sourceMappingURL=initial-snapshot-Bx-c0pDP.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initial-snapshot-BrLso5x_.d.ts","names":[],"sources":["../src/errors.ts","../src/initial-snapshot.ts"],"mappings":";;KAAY;KAaA,cACV;cAEW,gBAAgB;WAClB,MAAM;;WAEN;EAET,YACE,MAAM,aACN,iBACA;IAAY;IAAmB;;;;;;;;;;;cA2CtB,0BAA0B;EACrC,YAAY,iBAAiB;IAAY;;;;;KClE/B,gBAAgB,KACxB,cAAc,wBAGd,QAAQ,cAAc"}
1
+ {"version":3,"file":"initial-snapshot-Bx-c0pDP.d.ts","names":[],"sources":["../src/errors.ts","../src/initial-snapshot.ts"],"mappings":";;KAAY;KAaA,cACV;cAEW,gBAAgB;WAClB,MAAM;;WAEN;EAET,YACE,MAAM,aACN,iBACA;IAAY;IAAmB;;;;;;;;;;;cA2CtB,0BAA0B;EACrC,YAAY,iBAAiB;IAAY;;;;;KClE/B,gBAAgB,KACxB,cAAc,wBAGd,QAAQ,cAAc"}
@@ -28,6 +28,12 @@ const RESERVED_PARTICIPANT_IDS = /* @__PURE__ */ new Set([
28
28
  "prototype"
29
29
  ]);
30
30
  const serverInternals = /* @__PURE__ */ new WeakMap();
31
+ /**
32
+ * Handler contexts whose previous attempt ended in a failure the handler
33
+ * threw, as opposed to a claim that lapsed (a crash, a timeout, a frozen
34
+ * process). Only the attempt's own outcome is known, not how far it got.
35
+ */
36
+ const failedPreviousAttempt = /* @__PURE__ */ new WeakSet();
31
37
  const objectLike = (value) => typeof value === "object" && value !== null || typeof value === "function";
32
38
  const TOOL_SCOPE_STORAGE = Symbol.for("experimental-a2.ai.tool-scope");
33
39
  function ambientToolScopeStorage() {
@@ -204,6 +210,6 @@ const SOCKET_TIMINGS = {
204
210
  */
205
211
  const PRESENCE_TIMINGS = { sendIntervalMs: 66 };
206
212
  //#endregion
207
- export { serverInternals as _, PRESENCE_TIMINGS as a, STATE_CACHE as c, assertSchedulerTargets as d, classifySchedulerSendFailure as f, nullProtoRecord as g, markSchedulerSendFailure as h, POLL_TIMINGS as i, STREAM_TIMINGS as l, installAmbientToolScopeStorage as m, MAX_DATE_MS as n, RESERVED_PARTICIPANT_IDS as o, consumeSchedulerSendFailure as p, NOTIFY_TIMINGS as r, SOCKET_TIMINGS as s, DRAIN_TIMINGS as t, ambientToolScopeStorage as u, stateTailReaders as v };
213
+ export { nullProtoRecord as _, PRESENCE_TIMINGS as a, STATE_CACHE as c, assertSchedulerTargets as d, classifySchedulerSendFailure as f, markSchedulerSendFailure as g, installAmbientToolScopeStorage as h, POLL_TIMINGS as i, STREAM_TIMINGS as l, failedPreviousAttempt as m, MAX_DATE_MS as n, RESERVED_PARTICIPANT_IDS as o, consumeSchedulerSendFailure as p, NOTIFY_TIMINGS as r, SOCKET_TIMINGS as s, DRAIN_TIMINGS as t, ambientToolScopeStorage as u, serverInternals as v, stateTailReaders as y };
208
214
 
209
- //# sourceMappingURL=internal-CbVvEwad.js.map
215
+ //# sourceMappingURL=internal-B2T3U4Rq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-B2T3U4Rq.js","names":[],"sources":["../src/internal.ts"],"sourcesContent":["/**\n * Private seams shared by a2 entry points and a2's own tests. Not exported\n * from the package. Nothing here is public API.\n */\n\nimport type { ScheduledEvent } from './scheduler-task.ts'\nimport type { DrainableServer } from './server.ts'\nimport type { Event } from './store.ts'\n\nexport type DrainOutcome = 'busy' | 'stalled' | 'settled'\n\n/**\n * A null-prototype record for maps keyed by caller-controlled strings\n * (participant ids, presence field names). On a normal object,\n * assigning to '__proto__' rewrites the prototype instead of creating\n * an own property — the prototype-pollution class. Null-prototype\n * objects still satisfy Record types and JSON.stringify cleanly.\n */\nexport function nullProtoRecord<T extends object>(): T {\n return Object.create(null) as T\n}\n\n/**\n * ECMA-262's maximum Date value (±8.64e15 ms). A presence stamp past\n * it becomes an Invalid Date whose toISOString throws — one hostile\n * stamp would poison every subscriber's snapshot frame — so both\n * seams bound `at` to the representable range.\n */\nexport const MAX_DATE_MS = 8_640_000_000_000_000\n\n/**\n * Participant ids that collide with Object.prototype plumbing.\n * Null-prototype construction already defuses them, but they are\n * rejected at both seams (`parsePushBody`, `setPresence`) so a hostile\n * id never propagates into userland maps either.\n */\nexport const RESERVED_PARTICIPANT_IDS: ReadonlySet<string> = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n])\n\nexport type DrainResult = {\n settled: boolean\n outcome: DrainOutcome\n /** Existing successor arm a scheduler callback may join before acking. */\n schedulerArm?: Promise<void>\n}\n\nexport type ServerInternals = {\n /**\n * Await every in-flight background drain this machine has scheduled,\n * including ones scheduled while waiting. Lets tests flush the\n * fire-and-forget inline path deterministically — no sleeps.\n */\n settle(): Promise<void>\n /** The public `server.drain()` result deliberately remains `{ settled }`. */\n schedulerDrain(\n sessionId: string,\n opts?: { watchdogDueAt?: number },\n ): Promise<DrainResult>\n /** Deliver a scheduler-owned delayed append through the normal root path. */\n schedulerAppend(\n sessionId: string,\n events: readonly ScheduledEvent[],\n originIndex?: number,\n ): Promise<void>\n /** Deliver a scheduler-owned conditional clear, deletion included. */\n schedulerClear(sessionId: string, ifLastIndex: number): Promise<void>\n /** `session.history` with clear markers kept; reads start at the latest one. */\n historyWithMarkers(sessionId: string, gte: number): Promise<Event[]>\n}\n\nexport const serverInternals: WeakMap<object, ServerInternals> = new WeakMap()\n\n/**\n * Handler contexts whose previous attempt ended in a failure the handler\n * threw, as opposed to a claim that lapsed (a crash, a timeout, a frozen\n * process). Only the attempt's own outcome is known, not how far it got.\n */\nexport const failedPreviousAttempt: WeakSet<object> = new WeakSet()\n\nconst objectLike = (value: unknown): value is object =>\n (typeof value === 'object' && value !== null) || typeof value === 'function'\n\n/** The ambient value delivered to `handlerContext` during a tool execution. */\nexport type AmbientToolScope = {\n /** Executing server identity; a test scope from `runWithHandlerContext` has none. */\n contract?: { readonly name: string }\n context: unknown\n}\n\n/**\n * Structural AsyncLocalStorage surface for the ambient tool scope. The\n * instance is created by the server-only AI entry point (the only place\n * `node:async_hooks` may be imported) and shared through a global\n * symbol slot, so `handlerContext` in the isomorphic AI entry point and\n * independently bundled A2 copies all read the same scope.\n */\nexport type AmbientToolScopeStorage = {\n getStore(): AmbientToolScope | undefined\n run<R>(store: AmbientToolScope, callback: () => R): R\n}\n\nconst TOOL_SCOPE_STORAGE = Symbol.for('experimental-a2.ai.tool-scope')\n\nexport function ambientToolScopeStorage(): AmbientToolScopeStorage | undefined {\n const value = Reflect.get(globalThis, TOOL_SCOPE_STORAGE)\n if (\n !objectLike(value) ||\n typeof Reflect.get(value, 'getStore') !== 'function' ||\n typeof Reflect.get(value, 'run') !== 'function'\n ) {\n return undefined\n }\n return value as AmbientToolScopeStorage\n}\n\nexport function installAmbientToolScopeStorage(\n create: () => AmbientToolScopeStorage,\n): AmbientToolScopeStorage {\n const existing = ambientToolScopeStorage()\n if (existing !== undefined) return existing\n const storage = create()\n Reflect.set(globalThis, TOOL_SCOPE_STORAGE, storage)\n return storage\n}\n\nexport type SchedulerSendFailureDisposition = 'retryable' | 'terminal'\n\ntype SchedulerSendFailureMarker = {\n readonly version: 1\n readonly pending: SchedulerSendFailureDisposition[]\n readonly active: SchedulerSendFailureDisposition[]\n}\n\nconst SCHEDULER_SEND_FAILURE = Symbol.for(\n 'experimental-a2.scheduler.send-failure',\n)\n\nconst schedulerSendFailureMarker = (\n value: unknown,\n): SchedulerSendFailureMarker | undefined => {\n if (!objectLike(value)) return undefined\n const marker = Reflect.get(value, SCHEDULER_SEND_FAILURE)\n if (\n !objectLike(marker) ||\n Reflect.get(marker, 'version') !== 1 ||\n !Array.isArray(Reflect.get(marker, 'pending')) ||\n !Array.isArray(Reflect.get(marker, 'active'))\n ) {\n return undefined\n }\n return marker as SchedulerSendFailureMarker\n}\n\nconst schedulerFailureObject = (error: unknown): object => {\n if (\n objectLike(error) &&\n (schedulerSendFailureMarker(error) !== undefined ||\n Object.isExtensible(error))\n ) {\n return error\n }\n return new Error(String(error), { cause: error })\n}\n\nconst schedulerSendFailureState = (\n error: object,\n): SchedulerSendFailureMarker => {\n const existing = schedulerSendFailureMarker(error)\n if (existing !== undefined) return existing\n const marker: SchedulerSendFailureMarker = {\n version: 1,\n pending: [],\n active: [],\n }\n Object.defineProperty(error, SCHEDULER_SEND_FAILURE, {\n value: marker,\n enumerable: false,\n configurable: true,\n writable: false,\n })\n return marker\n}\n\nconst clearSchedulerSendFailureState = (\n error: object,\n marker: SchedulerSendFailureMarker,\n): void => {\n if (marker.pending.length === 0 && marker.active.length === 0) {\n Reflect.deleteProperty(error, SCHEDULER_SEND_FAILURE)\n }\n}\n\n/**\n * Classify an adapter error before throwing it. Unclassified adapter failures\n * are retryable because the caller cannot know whether a remote send landed.\n */\nexport function classifySchedulerSendFailure(\n error: unknown,\n disposition: SchedulerSendFailureDisposition,\n): unknown {\n const classified = schedulerFailureObject(error)\n schedulerSendFailureState(classified).pending.push(disposition)\n return classified\n}\n\n/** Consume a pending adapter classification and count this rejected send. */\nexport function markSchedulerSendFailure(error: unknown): unknown {\n const marked = schedulerFailureObject(error)\n const marker = schedulerSendFailureState(marked)\n marker.active.push(marker.pending.pop() ?? 'retryable')\n return marked\n}\n\nexport function consumeSchedulerSendFailure(\n error: unknown,\n): SchedulerSendFailureDisposition | undefined {\n if (!objectLike(error)) return undefined\n const marker = schedulerSendFailureMarker(error)\n const disposition = marker?.active.pop()\n if (marker !== undefined) clearSchedulerSendFailureState(error, marker)\n return disposition\n}\n\nconst isDrainableServer = (value: unknown): value is DrainableServer => {\n if (value === null || typeof value !== 'object') return false\n const contract = Reflect.get(value, 'contract')\n return (\n contract !== null &&\n typeof contract === 'object' &&\n typeof Reflect.get(contract, 'name') === 'string' &&\n typeof Reflect.get(value, 'drain') === 'function'\n )\n}\n\n/**\n * Validate the server list captured by a scheduler route at construction time.\n * The seam stays structural so custom scheduler integrations can supply their\n * own drainable targets.\n */\nexport function assertSchedulerTargets(\n servers: readonly unknown[],\n): asserts servers is readonly DrainableServer[] {\n const contracts = new Set<string>()\n for (const target of servers) {\n if (!isDrainableServer(target)) {\n throw new TypeError('a2 scheduler: expected a server from createServer()')\n }\n const name = target.contract.name\n if (contracts.has(name)) {\n throw new TypeError(\n `a2 scheduler: duplicate server contract '${name}' in one handler`,\n )\n }\n contracts.add(name)\n }\n}\n\n/**\n * Drain timing knobs. Mutable only as a white-box test seam. Claim\n * heartbeats run on real timers, so tests shrink these to keep suites\n * fast. Production always uses the defaults.\n */\nexport const DRAIN_TIMINGS: {\n /** How long a claim lives without renewal. */\n claimTtlMs: number\n /** Heartbeat cadence while a handler is running. */\n claimHeartbeatMs: number\n /** Base delay before retrying a failed renewal while the lease lives. */\n renewRetryMs: number\n /** Delay between a claim's expiry and its scheduler watchdog. */\n watchdogGraceMs: number\n /** Maximum time a top-level append waits for its initial scheduler arm. */\n schedulerArmTimeoutMs: number\n} = {\n claimTtlMs: 5_000,\n claimHeartbeatMs: 2_000,\n renewRetryMs: 400,\n watchdogGraceMs: 1_000,\n schedulerArmTimeoutMs: 2_000,\n}\n\n/**\n * Stream liveness knobs — the server-side SSE heartbeat and the\n * client-side stall watchdog. Paired by design: the client declares a\n * connection dead after roughly two missed heartbeats. Mutable only as\n * a white-box test seam; production always uses the defaults.\n */\n/**\n * Poll cadence for the poll-based store streams (sqlite, postgres) —\n * owned, not configurable: adaptive polling removed the operator's\n * reason to tune it (the floor keeps active streams smooth; the\n * ceiling bounds idle cost). Mutable only as a white-box test seam so\n * suites don't wait out real idle gaps.\n */\nexport const POLL_TIMINGS: {\n /** Gap between polls while a session is producing events. */\n activeFloorMs: number\n /** The idle ceiling — the longest gap between polls. */\n idleCeilingMs: number\n} = {\n activeFloorMs: 25,\n idleCeilingMs: 2_000,\n}\n\n/**\n * Safety-read cadence for the notify-driven redis live stream. A\n * parked feed re-reads the store at this interval even without a\n * pub/sub wake-up, so a lost notification (subscriber reconnect gap,\n * dropped PUBLISH) costs latency, never an event. Mutable only as a\n * white-box test seam.\n */\nexport const NOTIFY_TIMINGS: {\n safetyReadMs: number\n} = {\n safetyReadMs: 10_000,\n}\n\n/**\n * Bounds for each server instance's in-memory reducer-state cache. Sizes are\n * encoded JSON lengths, re-measured every `measureEvery` folded events, so\n * the byte budget is approximate. Mutable only as a white-box test seam.\n */\nexport const STATE_CACHE: {\n maxEntries: number\n maxBytes: number\n /** Events a cached state may advance before it writes a snapshot. */\n snapshotEvery: number\n /** Events a warm read may fold; longer tails read the stored snapshot. */\n maxTail: number\n /** Events folded between re-measuring a cached state's encoded size. */\n measureEvery: number\n} = {\n maxEntries: 1_000,\n maxBytes: 32 * 1024 * 1024,\n snapshotEvery: 128,\n maxTail: 255,\n measureEvery: 16,\n}\n\n/**\n * Warm state-read tails for stores that can serve one in a single request:\n * events from `fromIndex` (inclusive) through `throughIndex` or the newest\n * event, or null when that needs more than one request. Like every store\n * read, a tail starts no lower than the latest clear marker. Keyed by the exact\n * store object, so a wrapper built by spreading or proxying a store reads\n * through its own `readHistory` instead.\n */\nexport const stateTailReaders: WeakMap<\n object,\n (\n sessionId: string,\n fromIndex: number,\n throughIndex?: number,\n ) => Promise<Event[] | null>\n> = new WeakMap()\n\nexport const STREAM_TIMINGS: {\n /** Cadence of `: ping` comment frames from `sseResponse`. */\n sseHeartbeatMs: number\n /** How far ahead of an invocation deadline an SSE response closes. */\n sseDeadlineGraceMs: number\n /** Client: silence longer than this means the connection is dead. */\n stallTimeoutMs: number\n /** Client reconnect backoff: first retry delay, doubling per attempt. */\n reconnectBaseMs: number\n /** Client reconnect backoff ceiling. */\n reconnectMaxMs: number\n} = {\n sseHeartbeatMs: 15_000,\n sseDeadlineGraceMs: 1_000,\n stallTimeoutMs: 35_000,\n reconnectBaseMs: 500,\n reconnectMaxMs: 5_000,\n}\n\n/**\n * WebSocket down-pump backpressure — `sessionsSocket` parks its pull\n * loop while the socket reports more buffered bytes than the\n * high-water mark and re-checks on the poll cadence, so a slow reader\n * applies backpressure to the store subscription instead of buffering\n * without bound in the socket. Acks and heartbeats stay exempt: they\n * are small and correctness-relevant. Mutable only as a white-box test\n * seam.\n */\nexport const SOCKET_TIMINGS: {\n highWaterMarkBytes: number\n resumePollMs: number\n /** Up-lane bound: concurrent push/presence handlers per socket. POST\n * gets per-request platform limits for free; the socket must bring\n * its own. Over the cap, pushes are answered with a retryable error\n * ack and presence frames are shed (that plane repaints). */\n maxInFlightMessages: number\n /** Hard ceiling on `bufferedAmount`: past it the peer is a\n * non-reader (acks and pings are park-exempt, so only a peer that\n * never reads can reach it) and the socket closes 1008. */\n disconnectWaterMarkBytes: number\n} = {\n highWaterMarkBytes: 1_048_576,\n resumePollMs: 25,\n maxInFlightMessages: 32,\n disconnectWaterMarkBytes: 8_388_608,\n}\n\n/**\n * Client presence send cadence — a leading send immediately, then at\n * most one merged send per interval (~15Hz). Owned, not configurable\n * (decision #36's rule): coupling the cadence to the POST ack tied\n * remote cursor smoothness to RTT, and the ack serves no correctness\n * purpose on a fire-and-forget LWW plane. Mutable only as a white-box\n * test seam.\n */\nexport const PRESENCE_TIMINGS: {\n sendIntervalMs: number\n} = {\n sendIntervalMs: 66,\n}\n"],"mappings":"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"}
package/dist/otel.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as A2Telemetry } from "./telemetry-cZH-cibj.js";
1
+ import { i as A2Telemetry } from "./telemetry-Cyfqo6Qt.js";
2
2
  import { Tracer } from "@opentelemetry/api";
3
3
  //#region src/otel.d.ts
4
4
  type OtelOptions = {
@@ -1,6 +1,6 @@
1
- import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, o as AppendInput, p as PresencePatch, s as Contract, t as Reducer, u as EventDefs } from "./reducer-BYu6DT7h.js";
2
- import { t as InitialSnapshot } from "./initial-snapshot-BrLso5x_.js";
3
- import { a as Connection, c as HistoryState, l as LoadHistoryOptions, t as A2Client, u as PushResult } from "./client-qRnRUzBS.js";
1
+ import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, o as AppendInput, p as PresencePatch, s as Contract, t as Reducer, u as EventDefs } from "./reducer-CqA59Q6U.js";
2
+ import { t as InitialSnapshot } from "./initial-snapshot-Bx-c0pDP.js";
3
+ import { a as Connection, c as HistoryState, l as LoadHistoryOptions, t as A2Client, u as PushResult } from "./client-h_DKFAjj.js";
4
4
  import { ReactElement, ReactNode } from "react";
5
5
  //#region src/react.d.ts
6
6
  type UseSessionOptions<S> = {
@@ -83,4 +83,4 @@ declare function createReact<D extends EventDefs, S, P extends PresenceDefs = Re
83
83
  declare function useSession<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>>(client: A2Client<D, S, P>, sessionId: string, options?: UseSessionOptions<NoInfer<S>>): UseSessionResult<D, S, P>;
84
84
  //#endregion
85
85
  export { SessionProviderProps as a, UseSessionResult as c, BoundSessionProviderProps as i, createReact as l, BoundA2React as n, UseSessionOptions as o, BoundSessionOptions as r, UseSessionPresence as s, A2React as t, useSession as u };
86
- //# sourceMappingURL=react-BbJ-g6Uu.d.ts.map
86
+ //# sourceMappingURL=react-BBXgHWFc.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-BbJ-g6Uu.d.ts","names":[],"sources":["../src/react.ts"],"mappings":";;;;;KAwCY,kBAAkB;EAC5B;EACA,UAAU,gBAAgB;EAC1B;EACA;;KAGU,qBAAqB,UAAU,WAAW;EACpD;EACA;EACA,UAAU,gBAAgB;EAC1B,gBAAgB,cAAc;EAC9B;EACA,WAAW;;KAGD,0BAA0B,UAAU,WAAW,KAAK,KAC9D,qBAAqB,GAAG;KAId,mBAAmB,UAAU;;EAEvC,UAAU,YAAY;;;;;;;;EAQtB,cAAc,QAAQ,cAAc;;KAG1B,iBACV,UAAU,WACV,GACA,UAAU,eAAe,wBACvB,aAAa,GAAG,mBAAmB;;EAErC,OAAO;;EAEP;;EAEA,QAAQ,cAAc;;EAEtB;;;;;;EAMA,YAAY;;;;;;EAMZ,UAAU,QAAQ,YAAY,SAAS,WAAW;;EAElD;;;;;;EAMA,cAAc,UAAU,uBAAuB,QAAQ,cAAc;;EAErE,SAAS;;KAGC,oBACV,UAAU,WACV,GACA,UAAU,gBACR,kBAAkB;EACpB;EACA,SAAS,SAAS,GAAG,GAAG;;KAGd,QACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,kBAAkB,OAAO,qBAAqB,GAAG,OAAO;EACxD,aACE,UAAU,oBAAoB,GAAG,GAAG,OACjC,iBAAiB,GAAG,GAAG;;KAGlB,aACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,kBAAkB,OAAO,0BAA0B,GAAG,OAAO;EAC7D,aACE,UAAU,oBAAoB,GAAG,GAAG,OACjC,iBAAiB,GAAG,GAAG;;iBAGd,YACd,UAAU,WACV,GACA,UAAU,eAAe,sBACzB;EAAW,QAAQ,SAAS,GAAG,GAAG;IAAO,aAAa,GAAG,GAAG;iBAC9C,YACd,UAAU,WACV,GACA,UAAU,eAAe,sBACzB;EAAW,UAAU,SAAS,GAAG,GAAG,QAAQ,GAAG,GAAG;IAAQ,QAAQ,GAAG,GAAG;iBA4J1D,WACd,UAAU,WACV,GACA,UAAU,eAAe,sBAEzB,QAAQ,SAAS,GAAG,GAAG,IACvB,mBACA,UAAS,kBAAkB,QAAQ,MAClC,iBAAiB,GAAG,GAAG"}
1
+ {"version":3,"file":"react-BBXgHWFc.d.ts","names":[],"sources":["../src/react.ts"],"mappings":";;;;;KAwCY,kBAAkB;EAC5B;EACA,UAAU,gBAAgB;EAC1B;EACA;;KAGU,qBAAqB,UAAU,WAAW;EACpD;EACA;EACA,UAAU,gBAAgB;EAC1B,gBAAgB,cAAc;EAC9B;EACA,WAAW;;KAGD,0BAA0B,UAAU,WAAW,KAAK,KAC9D,qBAAqB,GAAG;KAId,mBAAmB,UAAU;;EAEvC,UAAU,YAAY;;;;;;;;EAQtB,cAAc,QAAQ,cAAc;;KAG1B,iBACV,UAAU,WACV,GACA,UAAU,eAAe,wBACvB,aAAa,GAAG,mBAAmB;;EAErC,OAAO;;EAEP;;EAEA,QAAQ,cAAc;;EAEtB;;;;;;EAMA,YAAY;;;;;;EAMZ,UAAU,QAAQ,YAAY,SAAS,WAAW;;EAElD;;;;;;EAMA,cAAc,UAAU,uBAAuB,QAAQ,cAAc;;EAErE,SAAS;;KAGC,oBACV,UAAU,WACV,GACA,UAAU,gBACR,kBAAkB;EACpB;EACA,SAAS,SAAS,GAAG,GAAG;;KAGd,QACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,kBAAkB,OAAO,qBAAqB,GAAG,OAAO;EACxD,aACE,UAAU,oBAAoB,GAAG,GAAG,OACjC,iBAAiB,GAAG,GAAG;;KAGlB,aACV,UAAU,WACV,GACA,UAAU,eAAe;EAEzB,kBAAkB,OAAO,0BAA0B,GAAG,OAAO;EAC7D,aACE,UAAU,oBAAoB,GAAG,GAAG,OACjC,iBAAiB,GAAG,GAAG;;iBAGd,YACd,UAAU,WACV,GACA,UAAU,eAAe,sBACzB;EAAW,QAAQ,SAAS,GAAG,GAAG;IAAO,aAAa,GAAG,GAAG;iBAC9C,YACd,UAAU,WACV,GACA,UAAU,eAAe,sBACzB;EAAW,UAAU,SAAS,GAAG,GAAG,QAAQ,GAAG,GAAG;IAAQ,QAAQ,GAAG,GAAG;iBA4J1D,WACd,UAAU,WACV,GACA,UAAU,eAAe,sBAEzB,QAAQ,SAAS,GAAG,GAAG,IACvB,mBACA,UAAS,kBAAkB,QAAQ,MAClC,iBAAiB,GAAG,GAAG"}
package/dist/react.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as SessionProviderProps, c as UseSessionResult, i as BoundSessionProviderProps, l as createReact, n as BoundA2React, o as UseSessionOptions, r as BoundSessionOptions, s as UseSessionPresence, t as A2React, u as useSession } from "./react-BbJ-g6Uu.js";
1
+ import { a as SessionProviderProps, c as UseSessionResult, i as BoundSessionProviderProps, l as createReact, n as BoundA2React, o as UseSessionOptions, r as BoundSessionOptions, s as UseSessionPresence, t as A2React, u as useSession } from "./react-BBXgHWFc.js";
2
2
  export { A2React, BoundA2React, BoundSessionOptions, BoundSessionProviderProps, SessionProviderProps, UseSessionOptions, UseSessionPresence, UseSessionResult, createReact, useSession };
package/dist/react.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { i as isInitialPromise, n as createRenderSession, r as resolveInitialForReact, t as createClient } from "./client-COaiaDub.js";
2
+ import { i as isInitialPromise, n as createRenderSession, r as resolveInitialForReact, t as createClient } from "./client-BReKqwZC.js";
3
3
  import { createContext, createElement, use, useContext, useEffect, useMemo, useSyncExternalStore } from "react";
4
4
  //#region src/react.ts
5
5
  function createReact(options) {
@@ -1 +1 @@
1
- {"version":3,"file":"reducer-BAXc8JyF.js","names":[],"sources":["../src/validate.ts","../src/reducer.ts"],"sourcesContent":["import type { StandardSchemaV1 } from './standard-schema.ts'\n\n/**\n * Run a Standard Schema validator, requiring a synchronous result.\n * Validators must be synchronous (specs/a2-api.md §1) — an async one is\n * a definition bug, rejected at definition time where possible and here\n * as a backstop. `what` names the schema in error messages, e.g.\n * \"event 'created'\" or \"the stateSchema\".\n */\nexport function validateSync<Input, Output>(\n schema: StandardSchemaV1<Input, Output>,\n value: unknown,\n what: string,\n): StandardSchemaV1.Result<Output> {\n const result = schema['~standard'].validate(value)\n if (result instanceof Promise) {\n throw new TypeError(\n `the schema for ${what} is asynchronous — a2 schemas must validate synchronously`,\n )\n }\n return result\n}\n\n/**\n * Probe a schema to reject always-async validators early. The probe\n * value is deliberately garbage — we only care whether the result is a\n * Promise, not whether it passes.\n */\nexport function assertSyncSchema(schema: StandardSchemaV1, what: string): void {\n const probe = Symbol('a2.schema-probe')\n const result = schema['~standard'].validate(probe)\n if (result instanceof Promise) {\n // Swallow the eventual rejection — the probe input was garbage.\n result.catch(() => {})\n throw new TypeError(\n `the schema for ${what} is asynchronous — a2 schemas must validate synchronously`,\n )\n }\n}\n","import type {\n ContractEvent,\n EventDefs,\n PresenceDefs,\n ReducerOptions,\n} from './contract.ts'\nimport { isSessionCleared, type SessionCleared } from './session-clear.ts'\nimport type { StandardSchemaV1 } from './standard-schema.ts'\nimport { validateSync } from './validate.ts'\n\nexport type StateSnapshot<S> = {\n state: S\n index: number\n /** The session's latest clear marker, once it has been cleared. */\n clearIndex?: number | undefined\n}\n\n/**\n * A fresh copy of a reducer's seed, so a fold that mutates in place\n * cannot corrupt the shared `initialState`. Non-cloneable seeds\n * (functions, class instances, proxies) fall back to the original.\n */\nexport function cloneInitial<S>(initial: S): S {\n try {\n return structuredClone(initial)\n } catch {\n return initial\n }\n}\n\nconst markerFolds = new WeakSet<object>()\n\n/**\n * Mark a fold that receives clear markers itself instead of resetting to its\n * `initialState`. The actor follower has no seed of its own; its stream carries\n * the reset state in the marker.\n */\nexport function foldsClearMarkers<\n F extends (state: never, event: never) => unknown,\n>(fold: F): F {\n markerFolds.add(fold)\n return fold\n}\n\n/** One fold step; a clear marker resets to the seed on server and client alike. */\nexport function foldEvent<D extends EventDefs, S>(\n source: Pick<Reducer<D, S>, 'fold' | 'initialState'>,\n state: S,\n event: ContractEvent<D> | SessionCleared,\n): S {\n if (!isSessionCleared(event)) return source.fold(state, event)\n return markerFolds.has(source.fold)\n ? source.fold(state, event as unknown as ContractEvent<D>)\n : cloneInitial(source.initialState)\n}\n\n/**\n * A pure fold over a session's events — `(state, event) => state` —\n * published inline in a contract or built with `reducer(options).fold(fn)`.\n *\n * The name is the reducer's identity. Cached folds (server snapshots,\n * the browser cache) are keyed by it, which makes it the invalidation\n * knob too: changed the fold's logic? Change the name. Snapshots under\n * the old name are ignored and the next read refolds from raw events.\n * See docs/concepts/04-state.mdx.\n */\nexport type Reducer<\n D extends EventDefs = EventDefs,\n S = unknown,\n P extends PresenceDefs = Record<never, never>,\n> = {\n /** Identity and cache key. Rename when the fold's logic changes. */\n readonly name: string\n /** The contract's vocabulary — types every event in the fold. */\n readonly events: Readonly<D>\n /**\n * The contract's presence vocabulary — carried because the reducer\n * is the client's typed handle on the contract. The fold never sees\n * presence.\n */\n readonly presence: Readonly<P>\n readonly fold: (state: S, event: ContractEvent<D>) => S\n readonly initialState: S\n /**\n * When present: `initialState` was validated against it at\n * definition, and any cached fold a2 rehydrates (server snapshots,\n * the browser cache) is checked against it — failing snapshots are\n * discarded and refolded, catching shape drift a stale name can't.\n */\n readonly stateSchema: StandardSchemaV1<unknown, S> | undefined\n}\n\n/** The second step of `reducer` — see the method's doc. */\nexport type ReducerBuilder<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = {\n fold(fold: (state: S, event: ContractEvent<D>) => S): Reducer<D, S, P>\n}\n\n/** Internal — shared validation for inline and standalone reducer definitions. */\nexport function makeReducerBuilder<\n D extends EventDefs,\n P extends PresenceDefs,\n Seed,\n S,\n>(\n events: Readonly<D>,\n presence: Readonly<P>,\n options: {\n name: string\n initialState: Seed\n stateSchema?: StandardSchemaV1<Seed, S>\n },\n): ReducerBuilder<D, S, P> {\n const { name } = options\n if (typeof name !== 'string' || name.length === 0) {\n throw new TypeError(\n 'reducer name must be a non-empty string — it identifies the reducer and keys cached snapshots',\n )\n }\n\n // Without a schema, S = Seed (the type parameter default), so the\n // seed is the state. With one, the seed is the schema's input and the\n // validated output (defaults applied) becomes the fold's actual seed.\n let initialState = options.initialState as unknown as S\n if (options.stateSchema) {\n const result = validateSync(\n options.stateSchema,\n options.initialState,\n 'the stateSchema',\n )\n if (result.issues) {\n throw new TypeError(\n `reducer initialState does not match its stateSchema: ${result.issues\n .map((issue) => issue.message)\n .join('; ')}`,\n )\n }\n initialState = result.value as S\n const restored = validateSync(\n options.stateSchema,\n initialState,\n 'the stateSchema',\n )\n if (\n restored.issues ||\n JSON.stringify(restored.value) !== JSON.stringify(initialState)\n ) {\n throw new TypeError(\n 'stateSchema must accept and preserve its own output so snapshots can be restored',\n )\n }\n }\n\n return {\n fold(fold) {\n if (typeof fold !== 'function') {\n throw new TypeError('reducer fold must be a function')\n }\n return {\n name,\n events,\n presence,\n fold,\n initialState,\n stateSchema: options.stateSchema as\n StandardSchemaV1<unknown, S> | undefined,\n }\n },\n }\n}\n\nexport type RegisteredReducer<\n D extends EventDefs,\n P extends PresenceDefs,\n> = Omit<Reducer<D, unknown, P>, 'fold'> & {\n readonly fold: (state: never, event: never) => unknown\n}\n\nexport function reducer<\n D extends EventDefs,\n P extends PresenceDefs,\n Seed,\n S = Seed,\n>(\n options: ReducerOptions<Seed, S> & {\n contract: { events: Readonly<D>; presence: Readonly<P> }\n },\n): ReducerBuilder<D, S, P> {\n return makeReducerBuilder(\n options.contract.events,\n options.contract.presence,\n options,\n )\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,aACd,QACA,OACA,MACiC;CACjC,MAAM,SAAS,OAAO,YAAY,CAAC,SAAS,KAAK;CACjD,IAAI,kBAAkB,SACpB,MAAM,IAAI,UACR,kBAAkB,KAAK,0DACzB;CAEF,OAAO;AACT;;;;;;AAOA,SAAgB,iBAAiB,QAA0B,MAAoB;CAC7E,MAAM,QAAQ,OAAO,iBAAiB;CACtC,MAAM,SAAS,OAAO,YAAY,CAAC,SAAS,KAAK;CACjD,IAAI,kBAAkB,SAAS;EAE7B,OAAO,YAAY,CAAC,CAAC;EACrB,MAAM,IAAI,UACR,kBAAkB,KAAK,0DACzB;CACF;AACF;;;;;;;;AChBA,SAAgB,aAAgB,SAAe;CAC7C,IAAI;EACF,OAAO,gBAAgB,OAAO;CAChC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAM,8BAAc,IAAI,QAAgB;;;;;;AAOxC,SAAgB,kBAEd,MAAY;CACZ,YAAY,IAAI,IAAI;CACpB,OAAO;AACT;;AAGA,SAAgB,UACd,QACA,OACA,OACG;CACH,IAAI,CAAC,iBAAiB,KAAK,GAAG,OAAO,OAAO,KAAK,OAAO,KAAK;CAC7D,OAAO,YAAY,IAAI,OAAO,IAAI,IAC9B,OAAO,KAAK,OAAO,KAAoC,IACvD,aAAa,OAAO,YAAY;AACtC;;AAgDA,SAAgB,mBAMd,QACA,UACA,SAKyB;CACzB,MAAM,EAAE,SAAS;CACjB,IAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAC9C,MAAM,IAAI,UACR,+FACF;CAMF,IAAI,eAAe,QAAQ;CAC3B,IAAI,QAAQ,aAAa;EACvB,MAAM,SAAS,aACb,QAAQ,aACR,QAAQ,cACR,iBACF;EACA,IAAI,OAAO,QACT,MAAM,IAAI,UACR,wDAAwD,OAAO,OAC5D,KAAK,UAAU,MAAM,OAAO,CAAC,CAC7B,KAAK,IAAI,GACd;EAEF,eAAe,OAAO;EACtB,MAAM,WAAW,aACf,QAAQ,aACR,cACA,iBACF;EACA,IACE,SAAS,UACT,KAAK,UAAU,SAAS,KAAK,MAAM,KAAK,UAAU,YAAY,GAE9D,MAAM,IAAI,UACR,kFACF;CAEJ;CAEA,OAAO,EACL,KAAK,MAAM;EACT,IAAI,OAAO,SAAS,YAClB,MAAM,IAAI,UAAU,iCAAiC;EAEvD,OAAO;GACL;GACA;GACA;GACA;GACA;GACA,aAAa,QAAQ;EAEvB;CACF,EACF;AACF;AASA,SAAgB,QAMd,SAGyB;CACzB,OAAO,mBACL,QAAQ,SAAS,QACjB,QAAQ,SAAS,UACjB,OACF;AACF"}
1
+ {"version":3,"file":"reducer-BAXc8JyF.js","names":[],"sources":["../src/validate.ts","../src/reducer.ts"],"sourcesContent":["import type { StandardSchemaV1 } from './standard-schema.ts'\n\n/**\n * Run a Standard Schema validator, requiring a synchronous result.\n * Validators must be synchronous (specs/a2-api.md §1) — an async one is\n * a definition bug, rejected at definition time where possible and here\n * as a backstop. `what` names the schema in error messages, e.g.\n * \"event 'created'\" or \"the stateSchema\".\n */\nexport function validateSync<Input, Output>(\n schema: StandardSchemaV1<Input, Output>,\n value: unknown,\n what: string,\n): StandardSchemaV1.Result<Output> {\n const result = schema['~standard'].validate(value)\n if (result instanceof Promise) {\n throw new TypeError(\n `the schema for ${what} is asynchronous — a2 schemas must validate synchronously`,\n )\n }\n return result\n}\n\n/**\n * Probe a schema to reject always-async validators early. The probe\n * value is deliberately garbage — we only care whether the result is a\n * Promise, not whether it passes.\n */\nexport function assertSyncSchema(schema: StandardSchemaV1, what: string): void {\n const probe = Symbol('a2.schema-probe')\n const result = schema['~standard'].validate(probe)\n if (result instanceof Promise) {\n // Swallow the eventual rejection — the probe input was garbage.\n result.catch(() => {})\n throw new TypeError(\n `the schema for ${what} is asynchronous — a2 schemas must validate synchronously`,\n )\n }\n}\n","import type {\n ContractEvent,\n EventDefs,\n PresenceDefs,\n ReducerOptions,\n} from './contract.ts'\nimport { isSessionCleared, type SessionCleared } from './session-clear.ts'\nimport type { StandardSchemaV1 } from './standard-schema.ts'\nimport { validateSync } from './validate.ts'\n\nexport type StateSnapshot<S> = {\n state: S\n index: number\n /** The session's latest clear marker, once it has been cleared. */\n clearIndex?: number | undefined\n}\n\n/**\n * A fresh copy of a reducer's seed, so a fold that mutates in place\n * cannot corrupt the shared `initialState`. Non-cloneable seeds\n * (functions, class instances, proxies) fall back to the original.\n */\nexport function cloneInitial<S>(initial: S): S {\n try {\n return structuredClone(initial)\n } catch {\n return initial\n }\n}\n\nconst markerFolds = new WeakSet<object>()\n\n/**\n * Mark a fold that receives clear markers itself instead of resetting to its\n * `initialState`. The actor follower has no seed of its own; its stream carries\n * the reset state in the marker.\n */\nexport function foldsClearMarkers<\n F extends (state: never, event: never) => unknown,\n>(fold: F): F {\n markerFolds.add(fold)\n return fold\n}\n\n/** One fold step; a clear marker resets to the seed on server and client alike. */\nexport function foldEvent<D extends EventDefs, S>(\n source: Pick<Reducer<D, S>, 'fold' | 'initialState'>,\n state: S,\n event: ContractEvent<D> | SessionCleared,\n): S {\n if (!isSessionCleared(event)) return source.fold(state, event)\n return markerFolds.has(source.fold)\n ? source.fold(state, event as unknown as ContractEvent<D>)\n : cloneInitial(source.initialState)\n}\n\n/**\n * A pure fold over a session's events — `(state, event) => state` —\n * published inline in a contract or built with `reducer(options).fold(fn)`.\n *\n * The name is the reducer's identity. Cached folds (server snapshots,\n * the browser cache) are keyed by it, which makes it the invalidation\n * knob too: changed the fold's logic? Change the name. Snapshots under\n * the old name are ignored and the next read refolds from raw events.\n * See docs/contract/02-state.mdx.\n */\nexport type Reducer<\n D extends EventDefs = EventDefs,\n S = unknown,\n P extends PresenceDefs = Record<never, never>,\n> = {\n /** Identity and cache key. Rename when the fold's logic changes. */\n readonly name: string\n /** The contract's vocabulary — types every event in the fold. */\n readonly events: Readonly<D>\n /**\n * The contract's presence vocabulary — carried because the reducer\n * is the client's typed handle on the contract. The fold never sees\n * presence.\n */\n readonly presence: Readonly<P>\n readonly fold: (state: S, event: ContractEvent<D>) => S\n readonly initialState: S\n /**\n * When present: `initialState` was validated against it at\n * definition, and any cached fold a2 rehydrates (server snapshots,\n * the browser cache) is checked against it — failing snapshots are\n * discarded and refolded, catching shape drift a stale name can't.\n */\n readonly stateSchema: StandardSchemaV1<unknown, S> | undefined\n}\n\n/** The second step of `reducer` — see the method's doc. */\nexport type ReducerBuilder<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = {\n fold(fold: (state: S, event: ContractEvent<D>) => S): Reducer<D, S, P>\n}\n\n/** Internal — shared validation for inline and standalone reducer definitions. */\nexport function makeReducerBuilder<\n D extends EventDefs,\n P extends PresenceDefs,\n Seed,\n S,\n>(\n events: Readonly<D>,\n presence: Readonly<P>,\n options: {\n name: string\n initialState: Seed\n stateSchema?: StandardSchemaV1<Seed, S>\n },\n): ReducerBuilder<D, S, P> {\n const { name } = options\n if (typeof name !== 'string' || name.length === 0) {\n throw new TypeError(\n 'reducer name must be a non-empty string — it identifies the reducer and keys cached snapshots',\n )\n }\n\n // Without a schema, S = Seed (the type parameter default), so the\n // seed is the state. With one, the seed is the schema's input and the\n // validated output (defaults applied) becomes the fold's actual seed.\n let initialState = options.initialState as unknown as S\n if (options.stateSchema) {\n const result = validateSync(\n options.stateSchema,\n options.initialState,\n 'the stateSchema',\n )\n if (result.issues) {\n throw new TypeError(\n `reducer initialState does not match its stateSchema: ${result.issues\n .map((issue) => issue.message)\n .join('; ')}`,\n )\n }\n initialState = result.value as S\n const restored = validateSync(\n options.stateSchema,\n initialState,\n 'the stateSchema',\n )\n if (\n restored.issues ||\n JSON.stringify(restored.value) !== JSON.stringify(initialState)\n ) {\n throw new TypeError(\n 'stateSchema must accept and preserve its own output so snapshots can be restored',\n )\n }\n }\n\n return {\n fold(fold) {\n if (typeof fold !== 'function') {\n throw new TypeError('reducer fold must be a function')\n }\n return {\n name,\n events,\n presence,\n fold,\n initialState,\n stateSchema: options.stateSchema as\n StandardSchemaV1<unknown, S> | undefined,\n }\n },\n }\n}\n\nexport type RegisteredReducer<\n D extends EventDefs,\n P extends PresenceDefs,\n> = Omit<Reducer<D, unknown, P>, 'fold'> & {\n readonly fold: (state: never, event: never) => unknown\n}\n\nexport function reducer<\n D extends EventDefs,\n P extends PresenceDefs,\n Seed,\n S = Seed,\n>(\n options: ReducerOptions<Seed, S> & {\n contract: { events: Readonly<D>; presence: Readonly<P> }\n },\n): ReducerBuilder<D, S, P> {\n return makeReducerBuilder(\n options.contract.events,\n options.contract.presence,\n options,\n )\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,aACd,QACA,OACA,MACiC;CACjC,MAAM,SAAS,OAAO,YAAY,CAAC,SAAS,KAAK;CACjD,IAAI,kBAAkB,SACpB,MAAM,IAAI,UACR,kBAAkB,KAAK,0DACzB;CAEF,OAAO;AACT;;;;;;AAOA,SAAgB,iBAAiB,QAA0B,MAAoB;CAC7E,MAAM,QAAQ,OAAO,iBAAiB;CACtC,MAAM,SAAS,OAAO,YAAY,CAAC,SAAS,KAAK;CACjD,IAAI,kBAAkB,SAAS;EAE7B,OAAO,YAAY,CAAC,CAAC;EACrB,MAAM,IAAI,UACR,kBAAkB,KAAK,0DACzB;CACF;AACF;;;;;;;;AChBA,SAAgB,aAAgB,SAAe;CAC7C,IAAI;EACF,OAAO,gBAAgB,OAAO;CAChC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAM,8BAAc,IAAI,QAAgB;;;;;;AAOxC,SAAgB,kBAEd,MAAY;CACZ,YAAY,IAAI,IAAI;CACpB,OAAO;AACT;;AAGA,SAAgB,UACd,QACA,OACA,OACG;CACH,IAAI,CAAC,iBAAiB,KAAK,GAAG,OAAO,OAAO,KAAK,OAAO,KAAK;CAC7D,OAAO,YAAY,IAAI,OAAO,IAAI,IAC9B,OAAO,KAAK,OAAO,KAAoC,IACvD,aAAa,OAAO,YAAY;AACtC;;AAgDA,SAAgB,mBAMd,QACA,UACA,SAKyB;CACzB,MAAM,EAAE,SAAS;CACjB,IAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAC9C,MAAM,IAAI,UACR,+FACF;CAMF,IAAI,eAAe,QAAQ;CAC3B,IAAI,QAAQ,aAAa;EACvB,MAAM,SAAS,aACb,QAAQ,aACR,QAAQ,cACR,iBACF;EACA,IAAI,OAAO,QACT,MAAM,IAAI,UACR,wDAAwD,OAAO,OAC5D,KAAK,UAAU,MAAM,OAAO,CAAC,CAC7B,KAAK,IAAI,GACd;EAEF,eAAe,OAAO;EACtB,MAAM,WAAW,aACf,QAAQ,aACR,cACA,iBACF;EACA,IACE,SAAS,UACT,KAAK,UAAU,SAAS,KAAK,MAAM,KAAK,UAAU,YAAY,GAE9D,MAAM,IAAI,UACR,kFACF;CAEJ;CAEA,OAAO,EACL,KAAK,MAAM;EACT,IAAI,OAAO,SAAS,YAClB,MAAM,IAAI,UAAU,iCAAiC;EAEvD,OAAO;GACL;GACA;GACA;GACA;GACA;GACA,aAAa,QAAQ;EAEvB;CACF,EACF;AACF;AASA,SAAgB,QAMd,SAGyB;CACzB,OAAO,mBACL,QAAQ,SAAS,QACjB,QAAQ,SAAS,UACjB,OACF;AACF"}
@@ -197,7 +197,7 @@ type StateSnapshot<S> = {
197
197
  * the browser cache) are keyed by it, which makes it the invalidation
198
198
  * knob too: changed the fold's logic? Change the name. Snapshots under
199
199
  * the old name are ignored and the next read refolds from raw events.
200
- * See docs/concepts/04-state.mdx.
200
+ * See docs/contract/02-state.mdx.
201
201
  */
202
202
  type Reducer<D extends EventDefs = EventDefs, S = unknown, P extends PresenceDefs = Record<never, never>> = {
203
203
  /** Identity and cache key. Rename when the fold's logic changes. */
@@ -235,4 +235,4 @@ declare function reducer<D extends EventDefs, P extends PresenceDefs, Seed, S =
235
235
  }): ReducerBuilder<D, S, P>;
236
236
  //#endregion
237
237
  export { contract as _, reducer as a, ContractEvent as c, PresenceDefs as d, PresenceMap as f, WithPresence as g, ReducerOptions as h, StateSnapshot as i, EventBatchFactory as l, PresenceSnapshot as m, ReducerBuilder as n, AppendInput as o, PresencePatch as p, RegisteredReducer as r, Contract as s, Reducer as t, EventDefs as u, StandardSchemaV1 as v };
238
- //# sourceMappingURL=reducer-BYu6DT7h.d.ts.map
238
+ //# sourceMappingURL=reducer-CqA59Q6U.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reducer-BYu6DT7h.d.ts","names":[],"sources":["../src/standard-schema.ts","../src/contract.ts","../src/reducer.ts"],"mappings":"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"}
1
+ {"version":3,"file":"reducer-CqA59Q6U.d.ts","names":[],"sources":["../src/standard-schema.ts","../src/contract.ts","../src/reducer.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { r as Clock } from "./store-Gpkq7WBo.js";
2
- import { A as SchedulerTask, t as A2Scheduler } from "./server-CGM8WzRG.js";
1
+ import { r as Clock } from "./store-Djdv0bnZ.js";
2
+ import { P as SchedulerTask, t as A2Scheduler } from "./server-En7cbi3v.js";
3
3
  //#region src/scheduler-qstash.d.ts
4
4
  type QStashStoreOutage = {
5
5
  version: 1;
@@ -1,7 +1,7 @@
1
1
  import { i as A2Error } from "./session-clear-DGI4jTQ5.js";
2
- import { _ as serverInternals, d as assertSchedulerTargets, f as classifySchedulerSendFailure, t as DRAIN_TIMINGS } from "./internal-CbVvEwad.js";
3
- import { n as deliverSchedulerAppend, r as deliverSchedulerClear } from "./server-Rj64fNvX.js";
2
+ import { d as assertSchedulerTargets, f as classifySchedulerSendFailure, t as DRAIN_TIMINGS, v as serverInternals } from "./internal-B2T3U4Rq.js";
4
3
  import { n as platformVercelOidcToken } from "./platform-B4TnJtWu.js";
4
+ import { n as deliverSchedulerAppend, r as deliverSchedulerClear } from "./server-Dw_k_7kO.js";
5
5
  import { t as retryableLazy } from "./retryable-lazy-DZWmHpii.js";
6
6
  import { n as SYSTEM_CLOCK } from "./store-N8PXxDAS.js";
7
7
  import { t as normalizeSchedulerTask } from "./scheduler-task-X1SToDjP.js";
@@ -1,5 +1,5 @@
1
- import { r as Clock } from "./store-Gpkq7WBo.js";
2
- import { A as SchedulerTask, t as A2Scheduler } from "./server-CGM8WzRG.js";
1
+ import { r as Clock } from "./store-Djdv0bnZ.js";
2
+ import { P as SchedulerTask, t as A2Scheduler } from "./server-En7cbi3v.js";
3
3
  //#region src/scheduler-vercel.d.ts
4
4
  /**
5
5
  * The "not settled yet" signal for a stalled handler — an expected state,
@@ -1,5 +1,5 @@
1
- import { _ as serverInternals, d as assertSchedulerTargets, f as classifySchedulerSendFailure, t as DRAIN_TIMINGS } from "./internal-CbVvEwad.js";
2
- import { n as deliverSchedulerAppend, r as deliverSchedulerClear } from "./server-Rj64fNvX.js";
1
+ import { d as assertSchedulerTargets, f as classifySchedulerSendFailure, t as DRAIN_TIMINGS, v as serverInternals } from "./internal-B2T3U4Rq.js";
2
+ import { n as deliverSchedulerAppend, r as deliverSchedulerClear } from "./server-Dw_k_7kO.js";
3
3
  import { t as retryableLazy } from "./retryable-lazy-DZWmHpii.js";
4
4
  import { n as SYSTEM_CLOCK } from "./store-N8PXxDAS.js";
5
5
  import { t as normalizeSchedulerTask } from "./scheduler-task-X1SToDjP.js";
@@ -1,50 +1,13 @@
1
1
  import { a as NonRetriableError, i as A2Error, n as isSessionCleared, o as asStoreUnavailable, r as sessionClearedError } from "./session-clear-DGI4jTQ5.js";
2
2
  import { n as foldEvent, s as validateSync, t as cloneInitial } from "./reducer-BAXc8JyF.js";
3
3
  import { n as encodeState, t as decodeState } from "./reducer-runtime-DQwz_J59.js";
4
- import { _ as serverInternals, c as STATE_CACHE, g as nullProtoRecord, h as markSchedulerSendFailure, i as POLL_TIMINGS, l as STREAM_TIMINGS, o as RESERVED_PARTICIPANT_IDS, s as SOCKET_TIMINGS, t as DRAIN_TIMINGS, v as stateTailReaders } from "./internal-CbVvEwad.js";
5
- import { i as streamActivities, r as createStreamActivity, t as defaultSleep } from "./store-polling-4_y8lETm.js";
4
+ import { _ as nullProtoRecord, c as STATE_CACHE, g as markSchedulerSendFailure, i as POLL_TIMINGS, l as STREAM_TIMINGS, m as failedPreviousAttempt, o as RESERVED_PARTICIPANT_IDS, s as SOCKET_TIMINGS, t as DRAIN_TIMINGS, v as serverInternals, y as stateTailReaders } from "./internal-B2T3U4Rq.js";
5
+ import { t as boundedCache } from "./bounded-cache-CPHWF-8h.js";
6
+ import { i as streamActivities, r as createStreamActivity, t as defaultSleep } from "./store-polling-B5FcwJfo.js";
6
7
  import { i as takeBuffered, n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-Cx7AAPGq.js";
7
8
  import { r as platformWaitUntil, t as invocationDeadlineMs } from "./platform-B4TnJtWu.js";
8
- import { A as stateSnapshotToWire, C as serializedEventToWireJson, D as socketFrameFor, E as socketEventsFor, O as socketSubscribedFor, S as presenceSnapshotToWire, T as socketErrorAckFor, b as presencePatchToWire, d as heldEventBatch, i as compactEventJson, j as wireVersion, k as socketUnsubscribedFor, m as isStreamEvent, n as SOCKET_PING_FRAME, o as errorStatus, r as asA2Error, s as errorToWire, t as EVENT_WRITE_CHARS, u as eventToWire, w as socketAckFor } from "./wire-DjfHOvdW.js";
9
+ import { A as stateSnapshotToWire, C as serializedEventToWireJson, D as socketFrameFor, E as socketEventsFor, O as socketSubscribedFor, S as presenceSnapshotToWire, T as socketErrorAckFor, b as presencePatchToWire, d as heldEventBatch, i as compactEventJson, j as wireVersion, k as socketUnsubscribedFor, m as isStreamEvent, n as SOCKET_PING_FRAME, o as errorStatus, r as asA2Error, s as errorToWire, t as EVENT_WRITE_CHARS, u as eventToWire, w as socketAckFor } from "./wire-rSUglYo8.js";
9
10
  import { t as retryableLazy } from "./retryable-lazy-DZWmHpii.js";
10
- //#region src/bounded-cache.ts
11
- function boundedCache({ maxEntries, maxBytes }) {
12
- const entries = /* @__PURE__ */ new Map();
13
- let total = 0;
14
- const remove = (key) => {
15
- const entry = entries.get(key);
16
- if (!entry) return;
17
- entries.delete(key);
18
- total -= entry.bytes;
19
- };
20
- return {
21
- get(key) {
22
- const entry = entries.get(key);
23
- if (!entry) return void 0;
24
- entries.delete(key);
25
- entries.set(key, entry);
26
- return entry.value;
27
- },
28
- set(key, value, bytes) {
29
- remove(key);
30
- if (bytes > maxBytes / 4) return;
31
- entries.set(key, {
32
- value,
33
- bytes
34
- });
35
- total += bytes;
36
- for (const oldest of entries.keys()) {
37
- if (entries.size <= maxEntries && total <= maxBytes) break;
38
- remove(oldest);
39
- }
40
- },
41
- delete: remove,
42
- deleteWhere(match) {
43
- for (const key of entries.keys()) if (match(key)) remove(key);
44
- }
45
- };
46
- }
47
- //#endregion
48
11
  //#region src/push-envelope.ts
49
12
  /**
50
13
  * The push envelope's trust boundary for `{ sessionId, events, presence? }`,
@@ -1235,6 +1198,19 @@ function currentSchedulerSlot(now) {
1235
1198
  */
1236
1199
  const NS = "";
1237
1200
  const devDefaultStore = retryableLazy(() => import("./store-sqlite.js").then((m) => m.sqlite()));
1201
+ /** Waits for a scheduler arm for at most `schedulerArmTimeoutMs`. */
1202
+ async function joinSchedulerArm(arm) {
1203
+ let timeout = null;
1204
+ try {
1205
+ await Promise.race([arm, new Promise((_, reject) => {
1206
+ timeout = setTimeout(() => {
1207
+ reject(/* @__PURE__ */ new Error(`a2 scheduler arm timed out after ${DRAIN_TIMINGS.schedulerArmTimeoutMs}ms`));
1208
+ }, DRAIN_TIMINGS.schedulerArmTimeoutMs);
1209
+ })]);
1210
+ } finally {
1211
+ if (timeout) clearTimeout(timeout);
1212
+ }
1213
+ }
1238
1214
  function environment() {
1239
1215
  const env = typeof process === "undefined" ? void 0 : process.env?.["NODE_ENV"];
1240
1216
  if (env === "test") return "test";
@@ -1483,21 +1459,12 @@ function createServer(options) {
1483
1459
  const dispatchArm = shouldHealSession && mode === "dispatch" ? startSchedulerArm(sessionId, currentSchedulerSlot(Date.now())) : null;
1484
1460
  if (shouldHealSession && mode === "inline") onAppended(appended, initialWatchdogAt);
1485
1461
  if (dispatchArm) await dispatchArm;
1486
- if (initialArm) {
1487
- let timeout = null;
1488
- try {
1489
- await Promise.race([initialArm, new Promise((_, reject) => {
1490
- timeout = setTimeout(() => {
1491
- reject(/* @__PURE__ */ new Error(`a2 scheduler arm timed out after ${DRAIN_TIMINGS.schedulerArmTimeoutMs}ms`));
1492
- }, DRAIN_TIMINGS.schedulerArmTimeoutMs);
1493
- })]);
1494
- } catch (err) {
1495
- span.setAttribute("a2.append.armed", false);
1496
- span.recordError(err);
1497
- if (requireDurableInitialArm) throw err;
1498
- } finally {
1499
- if (timeout) clearTimeout(timeout);
1500
- }
1462
+ if (initialArm) try {
1463
+ await joinSchedulerArm(initialArm);
1464
+ } catch (err) {
1465
+ span.setAttribute("a2.append.armed", false);
1466
+ span.recordError(err);
1467
+ if (requireDurableInitialArm) throw err;
1501
1468
  }
1502
1469
  return appended;
1503
1470
  });
@@ -2342,6 +2309,64 @@ function createServer(options) {
2342
2309
  index: result.index
2343
2310
  };
2344
2311
  };
2312
+ const redrivingStore = async (method) => {
2313
+ const store = await resolveStore();
2314
+ if (!store.deadLetters || !store.redrive) throw new TypeError(`session.${method} requires a store that supports redriving dead letters`);
2315
+ return store;
2316
+ };
2317
+ const listDeadLetters = async (sessionId) => {
2318
+ const store = await redrivingStore("deadLetters");
2319
+ let rows;
2320
+ try {
2321
+ rows = await store.deadLetters(nsId(sessionId));
2322
+ } catch (err) {
2323
+ throw asStoreUnavailable(err);
2324
+ }
2325
+ return rows.flatMap((row) => row.failedAt === null ? [] : [{
2326
+ ...toPublic(row),
2327
+ lane: row.lane,
2328
+ attemptCount: row.attemptCount,
2329
+ failureCount: row.failureCount,
2330
+ lastError: row.lastError,
2331
+ failedAt: row.failedAt
2332
+ }]);
2333
+ };
2334
+ const redriveEvent = async (sessionId, index, redriveOptions) => {
2335
+ assertRedriveIndex(index);
2336
+ const action = redriveOptions?.action;
2337
+ if (action !== "retry" && action !== "skip") throw new TypeError("redrive requires action 'retry' or 'skip'");
2338
+ return telemetry.span("a2.redrive", {
2339
+ "a2.contract": name,
2340
+ "a2.session_id": sessionId,
2341
+ "a2.redrive.index": index,
2342
+ "a2.redrive.action": action
2343
+ }, async (span) => {
2344
+ const store = await redrivingStore("redrive");
2345
+ let result;
2346
+ try {
2347
+ result = await store.redrive({
2348
+ sessionId: nsId(sessionId),
2349
+ index,
2350
+ action
2351
+ });
2352
+ } catch (err) {
2353
+ throw asStoreUnavailable(err);
2354
+ }
2355
+ span.setAttribute("a2.redrive.redriven", result.redriven);
2356
+ if (result.hasPending) {
2357
+ const watchdogAt = scheduler ? schedulerSlot(nextClaimWindow().watchdogAtMs) : void 0;
2358
+ const arm = watchdogAt === void 0 ? null : startSchedulerArm(sessionId, watchdogAt);
2359
+ scheduleDrain(sessionId, watchdogAt);
2360
+ if (arm) try {
2361
+ await joinSchedulerArm(arm);
2362
+ } catch (err) {
2363
+ span.setAttribute("a2.redrive.armed", false);
2364
+ span.recordError(err);
2365
+ }
2366
+ }
2367
+ return { redriven: result.redriven };
2368
+ });
2369
+ };
2345
2370
  const makeSession = (id, append, trigger, attempt) => ({
2346
2371
  id,
2347
2372
  append,
@@ -2389,7 +2414,7 @@ function createServer(options) {
2389
2414
  attempt
2390
2415
  }, generatedIds);
2391
2416
  };
2392
- return {
2417
+ const ctx = {
2393
2418
  event: toPublic(trigger),
2394
2419
  attempt,
2395
2420
  session: makeSession(publicSessionId, append, trigger, {
@@ -2402,6 +2427,8 @@ function createServer(options) {
2402
2427
  }),
2403
2428
  signal
2404
2429
  };
2430
+ if (attempt > 1 && trigger.lastFailedAttempt === attempt - 1) failedPreviousAttempt.add(ctx);
2431
+ return ctx;
2405
2432
  };
2406
2433
  const abortHubs = /* @__PURE__ */ new Map();
2407
2434
  const createAbortHub = (store, ns, startAfter) => {
@@ -2833,7 +2860,10 @@ function createServer(options) {
2833
2860
  const appendInline = async (...events) => appendExternal(id, "inline", events);
2834
2861
  const appendDispatch = async (...events) => appendExternal(id, "dispatch", events);
2835
2862
  const append = Object.assign(appendInline, { dispatch: appendDispatch });
2836
- return makeSession(id, append, null);
2863
+ return Object.assign(makeSession(id, append, null), {
2864
+ deadLetters: () => listDeadLetters(id),
2865
+ redrive: (index, redriveOptions) => redriveEvent(id, index, redriveOptions)
2866
+ });
2837
2867
  };
2838
2868
  const historyPage = async (sessionId, bounds) => {
2839
2869
  assertSessionId(sessionId);
@@ -2898,6 +2928,9 @@ function assertStreamIndex(value) {
2898
2928
  function assertStateIndex(value) {
2899
2929
  if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("state.through must be a non-negative safe integer");
2900
2930
  }
2931
+ function assertRedriveIndex(value) {
2932
+ if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("redrive requires a positive safe-integer index");
2933
+ }
2901
2934
  function assertClearIndex(value) {
2902
2935
  if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("ifLastIndex must be a non-negative safe integer");
2903
2936
  }
@@ -2988,6 +3021,6 @@ const measuredBytes = (reducer, state, index, snapshots) => JSON.stringify(snaps
2988
3021
  }))?.length ?? 0;
2989
3022
  const stateCacheKey = (sessionId, reducerName) => `${sessionId}\u0000${reducerName}`;
2990
3023
  //#endregion
2991
- export { CONSOLE_TELEMETRY as a, parsePresenceSibling as c, handler as i, boundedCache as l, deliverSchedulerAppend as n, setServerFetchHooks as o, deliverSchedulerClear as r, sseResponse as s, createServer as t };
3024
+ export { CONSOLE_TELEMETRY as a, parsePresenceSibling as c, handler as i, deliverSchedulerAppend as n, setServerFetchHooks as o, deliverSchedulerClear as r, sseResponse as s, createServer as t };
2992
3025
 
2993
- //# sourceMappingURL=server-Rj64fNvX.js.map
3026
+ //# sourceMappingURL=server-Dw_k_7kO.js.map