experimental-a2 0.17.0 → 0.18.1

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 (221) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +1 -1
  3. package/dist/{actor-DBbe5xeE.d.ts → actor-C7b-1arn.d.ts} +5 -5
  4. package/dist/{actor-DBbe5xeE.d.ts.map → actor-C7b-1arn.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-vpGtcaCB.d.ts → ai-BMLlI2Ff.d.ts} +3 -3
  11. package/dist/{ai-vpGtcaCB.d.ts.map → ai-BMLlI2Ff.d.ts.map} +1 -1
  12. package/dist/{ai-UrWfKeuv.js → ai-D6mGlO8j.js} +2 -2
  13. package/dist/{ai-UrWfKeuv.js.map → ai-D6mGlO8j.js.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 +692 -0
  22. package/dist/ai-fx.js.map +1 -0
  23. package/dist/ai-harness-B2suP2Qh.d.ts +26 -0
  24. package/dist/ai-harness-B2suP2Qh.d.ts.map +1 -0
  25. package/dist/ai-harness-BuLh_EYi.js +273 -0
  26. package/dist/ai-harness-BuLh_EYi.js.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 +950 -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 +113 -40
  39. package/dist/ai-server.js.map +1 -1
  40. package/dist/ai-tool-input-DmSqMUQi.js +40 -0
  41. package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
  42. package/dist/ai.d.ts +1 -1
  43. package/dist/ai.js +1 -1
  44. package/dist/bounded-cache-CPHWF-8h.js +41 -0
  45. package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
  46. package/dist/{client-COaiaDub.js → client-BhHLoNKF.js} +3 -3
  47. package/dist/{client-COaiaDub.js.map → client-BhHLoNKF.js.map} +1 -1
  48. package/dist/{client-qRnRUzBS.d.ts → client-h_DKFAjj.d.ts} +3 -3
  49. package/dist/{client-qRnRUzBS.d.ts.map → client-h_DKFAjj.d.ts.map} +1 -1
  50. package/dist/client.d.ts +3 -3
  51. package/dist/client.js +1 -1
  52. package/dist/index.d.ts +5 -5
  53. package/dist/{initial-snapshot-BrLso5x_.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +2 -2
  54. package/dist/{initial-snapshot-BrLso5x_.d.ts.map → initial-snapshot-Bx-c0pDP.d.ts.map} +1 -1
  55. package/dist/{internal-CbVvEwad.js → internal-CscSY7K_.js} +11 -3
  56. package/dist/internal-CscSY7K_.js.map +1 -0
  57. package/dist/otel.d.ts +1 -1
  58. package/dist/{react-BbJ-g6Uu.d.ts → react-BBXgHWFc.d.ts} +4 -4
  59. package/dist/{react-BbJ-g6Uu.d.ts.map → react-BBXgHWFc.d.ts.map} +1 -1
  60. package/dist/react.d.ts +1 -1
  61. package/dist/react.js +1 -1
  62. package/dist/reducer-BAXc8JyF.js.map +1 -1
  63. package/dist/{reducer-BYu6DT7h.d.ts → reducer-CqA59Q6U.d.ts} +2 -2
  64. package/dist/{reducer-BYu6DT7h.d.ts.map → reducer-CqA59Q6U.d.ts.map} +1 -1
  65. package/dist/scheduler-qstash.d.ts +2 -2
  66. package/dist/scheduler-qstash.js +3 -3
  67. package/dist/scheduler-qstash.js.map +1 -1
  68. package/dist/scheduler-vercel.d.ts +7 -7
  69. package/dist/scheduler-vercel.d.ts.map +1 -1
  70. package/dist/scheduler-vercel.js +9 -10
  71. package/dist/scheduler-vercel.js.map +1 -1
  72. package/dist/{server-Rj64fNvX.js → server-D-Y4pqwu.js} +126 -67
  73. package/dist/server-D-Y4pqwu.js.map +1 -0
  74. package/dist/{server-CGM8WzRG.d.ts → server-DYAATFuT.d.ts} +42 -7
  75. package/dist/server-DYAATFuT.d.ts.map +1 -0
  76. package/dist/server.d.ts +4 -4
  77. package/dist/server.js +1 -1
  78. package/dist/{session-clear-Dshpuhff.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
  79. package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
  80. package/dist/{store-Gpkq7WBo.d.ts → store-CyLUy86v.d.ts} +53 -5
  81. package/dist/store-CyLUy86v.d.ts.map +1 -0
  82. package/dist/store-N8PXxDAS.js.map +1 -1
  83. package/dist/store-memory.d.ts +1 -1
  84. package/dist/store-memory.js +56 -11
  85. package/dist/store-memory.js.map +1 -1
  86. package/dist/{store-polling-4_y8lETm.js → store-polling-7WJV0YWP.js} +2 -2
  87. package/dist/{store-polling-4_y8lETm.js.map → store-polling-7WJV0YWP.js.map} +1 -1
  88. package/dist/store-postgres.d.ts +1 -1
  89. package/dist/store-postgres.d.ts.map +1 -1
  90. package/dist/store-postgres.js +106 -25
  91. package/dist/store-postgres.js.map +1 -1
  92. package/dist/{store-presence-polling-Q1C-k2dd.js → store-presence-polling-B1ixeqIS.js} +3 -3
  93. package/dist/{store-presence-polling-Q1C-k2dd.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
  94. package/dist/store-redis-http.d.ts +1 -1
  95. package/dist/store-redis-http.js +3 -3
  96. package/dist/{store-redis-notify-tqWNnMRu.js → store-redis-notify-CM0AfLY0.js} +271 -101
  97. package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
  98. package/dist/store-redis.d.ts +1 -1
  99. package/dist/store-redis.js +1 -1
  100. package/dist/store-sqlite.d.ts +1 -1
  101. package/dist/store-sqlite.js +66 -21
  102. package/dist/store-sqlite.js.map +1 -1
  103. package/dist/{telemetry-cZH-cibj.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
  104. package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
  105. package/dist/{wire-DjfHOvdW.js → wire-BKxH1vbP.js} +2 -2
  106. package/dist/{wire-DjfHOvdW.js.map → wire-BKxH1vbP.js.map} +1 -1
  107. package/docs/01-quickstart.mdx +49 -83
  108. package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
  109. package/docs/actors/01-introduction.mdx +48 -86
  110. package/docs/actors/02-concurrency.mdx +43 -70
  111. package/docs/actors/03-timers.mdx +28 -42
  112. package/docs/actors/04-routes.mdx +110 -150
  113. package/docs/actors/meta.ts +1 -1
  114. package/docs/agents/01-introduction.mdx +257 -0
  115. package/docs/agents/02-tools.mdx +247 -0
  116. package/docs/agents/03-conversations.mdx +538 -0
  117. package/docs/agents/04-harnesses.mdx +136 -0
  118. package/docs/agents/meta.ts +1 -0
  119. package/docs/client/01-react.mdx +294 -0
  120. package/docs/client/02-transports.mdx +86 -0
  121. package/docs/client/03-presence.mdx +224 -0
  122. package/docs/client/meta.ts +1 -0
  123. package/docs/contract/01-events.mdx +57 -0
  124. package/docs/contract/02-state.mdx +142 -0
  125. package/docs/contract/03-sessions.mdx +175 -0
  126. package/docs/index.mdx +109 -145
  127. package/docs/reference/01-core.mdx +139 -0
  128. package/docs/reference/02-server.mdx +860 -0
  129. package/docs/reference/03-client.mdx +301 -0
  130. package/docs/reference/04-ai.mdx +731 -0
  131. package/docs/reference/05-adapters.mdx +351 -0
  132. package/docs/reference/06-errors.mdx +138 -0
  133. package/docs/reference/meta.ts +1 -1
  134. package/docs/server/01-handlers.mdx +200 -0
  135. package/docs/server/02-timers.mdx +130 -0
  136. package/docs/server/03-cancellation.mdx +142 -0
  137. package/docs/server/04-routes.mdx +243 -0
  138. package/docs/server/05-production.mdx +323 -0
  139. package/docs/server/06-guarantees.mdx +132 -0
  140. package/examples/playground/DEPLOY.md +3 -5
  141. package/examples/playground/app/a0/[appId]/page.tsx +12 -13
  142. package/examples/playground/app/a0/app-list.tsx +9 -2
  143. package/examples/playground/app/a0/app-view.tsx +9 -1
  144. package/examples/playground/app/a0/apps/[appId]/route.ts +10 -5
  145. package/examples/playground/app/a0/apps.test.ts +12 -0
  146. package/examples/playground/app/a0/apps.ts +22 -7
  147. package/examples/playground/app/a0/chat.tsx +47 -1
  148. package/examples/playground/app/a0/devtools.tsx +2 -8
  149. package/examples/playground/app/a0/fx/events/route.ts +9 -0
  150. package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
  151. package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
  152. package/examples/playground/app/a0/model.test.ts +18 -1
  153. package/examples/playground/app/a0/model.ts +47 -10
  154. package/examples/playground/app/a0/no-photon.cjs +4 -0
  155. package/examples/playground/app/a0/no-quickjs.cjs +3 -0
  156. package/examples/playground/app/a0/pi/events/route.ts +9 -0
  157. package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
  158. package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
  159. package/examples/playground/app/a0/sandbox-log.ts +10 -4
  160. package/examples/playground/app/a0/sandbox-session.ts +152 -0
  161. package/examples/playground/app/a0/scheduler/route.ts +2 -2
  162. package/examples/playground/app/a0/server.ts +98 -54
  163. package/examples/playground/app/a0/session.ts +17 -5
  164. package/examples/playground/app/a0/shell.tsx +11 -3
  165. package/examples/playground/app/agent/ingress.test.ts +6 -3
  166. package/examples/playground/app/agent/server.ts +9 -6
  167. package/examples/playground/app/agent/telemetry.test.ts +71 -50
  168. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +1 -1
  169. package/examples/playground/app/chat/server.test.ts +30 -26
  170. package/examples/playground/app/chat/server.ts +46 -46
  171. package/examples/playground/next.config.ts +17 -5
  172. package/examples/playground/package.json +4 -1
  173. package/examples/playground/vercel.json +18 -0
  174. package/package.json +27 -3
  175. package/src/ai-agent.ts +271 -90
  176. package/src/ai-fx.browser.ts +5 -0
  177. package/src/ai-fx.ts +912 -0
  178. package/src/ai-harness.ts +518 -0
  179. package/src/ai-model-metadata.ts +11 -6
  180. package/src/ai-pi.browser.ts +5 -0
  181. package/src/ai-pi.ts +1322 -0
  182. package/src/ai-sdk-step.ts +2 -2
  183. package/src/ai-server.ts +3 -1
  184. package/src/ai-tool-input.ts +45 -0
  185. package/src/internal.ts +13 -0
  186. package/src/libfx.d.ts +34 -0
  187. package/src/reducer.ts +1 -1
  188. package/src/scheduler-qstash.ts +5 -5
  189. package/src/scheduler-vercel.ts +14 -15
  190. package/src/server.ts +233 -29
  191. package/src/store-memory.ts +92 -16
  192. package/src/store-postgres.ts +156 -25
  193. package/src/store-redis-core.ts +322 -110
  194. package/src/store-redis-notify.ts +2 -0
  195. package/src/store-sqlite.ts +121 -28
  196. package/src/store.ts +55 -3
  197. package/src/telemetry.ts +1 -0
  198. package/dist/internal-CbVvEwad.js.map +0 -1
  199. package/dist/server-CGM8WzRG.d.ts.map +0 -1
  200. package/dist/server-Rj64fNvX.js.map +0 -1
  201. package/dist/session-clear-Dshpuhff.d.ts.map +0 -1
  202. package/dist/store-Gpkq7WBo.d.ts.map +0 -1
  203. package/dist/store-redis-notify-tqWNnMRu.js.map +0 -1
  204. package/dist/telemetry-cZH-cibj.d.ts.map +0 -1
  205. package/docs/concepts/01-contracts.mdx +0 -237
  206. package/docs/concepts/02-handlers.mdx +0 -284
  207. package/docs/concepts/03-durability.mdx +0 -314
  208. package/docs/concepts/04-state.mdx +0 -209
  209. package/docs/guides/01-timers.mdx +0 -193
  210. package/docs/guides/02-cancellation.mdx +0 -161
  211. package/docs/guides/03-react.mdx +0 -324
  212. package/docs/guides/04-local-first.mdx +0 -47
  213. package/docs/guides/05-production.mdx +0 -534
  214. package/docs/guides/06-ai-agents.mdx +0 -1408
  215. package/docs/guides/08-application-data.mdx +0 -113
  216. package/docs/guides/09-presence.mdx +0 -262
  217. package/docs/guides/10-transports.mdx +0 -221
  218. package/docs/reference/01-api.mdx +0 -2358
  219. package/docs/reference/02-errors.mdx +0 -150
  220. /package/docs/{concepts → contract}/meta.ts +0 -0
  221. /package/docs/{guides → server}/meta.ts +0 -0
@@ -1,150 +0,0 @@
1
- ---
2
- title: Errors
3
- description: Stable server and client error codes, transport details, and append guarantees.
4
- ---
5
-
6
- ## `A2Error`
7
-
8
- A2 failures carry an `A2Error` with a stable `code`. The session client exposes
9
- `A2ClientError`, which extends `A2Error`, for both server failures and failures
10
- observed locally. Existing `instanceof A2Error` checks also match client errors.
11
-
12
- ```ts
13
- // e.g. in a route handler:
14
- import { A2Error } from 'experimental-a2'
15
-
16
- export async function POST(req: Request) {
17
- const { orderId, payload } = await req.json()
18
- try {
19
- const events = await ordersServer
20
- .session(orderId)
21
- .append({ type: 'created', payload })
22
- return Response.json(events)
23
- } catch (err) {
24
- if (err instanceof A2Error && err.code === 'INVALID_PAYLOAD') {
25
- // err.details carries the schema issues, in Standard Schema format
26
- return Response.json({ issues: err.details }, { status: 400 })
27
- }
28
- throw err
29
- }
30
- }
31
- ```
32
-
33
- ## The codes
34
-
35
- | Code | Thrown when | Retryable |
36
- | ------------------------- | ------------------------------------------------------------------ | --------- |
37
- | `INVALID_PAYLOAD` | a payload fails its schema; nothing was written, and `details` carries the issues ([Standard Schema](https://standardschema.dev) format) | no |
38
- | `FORBIDDEN` | `server.fetch` authorization denies a parsed stream, history read, push, or presence update | no |
39
- | `UNKNOWN_EVENT_TYPE` | an event type isn't in the contract's `events` map | no |
40
- | `UNKNOWN_PRESENCE_FIELD` | a presence field isn't in the contract's `presence` map | no |
41
- | `PRESENCE_NOT_SUPPORTED` | the contract declares `presence` but the configured store has no presence capability (thrown at construction; for environment-resolved stores, deferred to the first store use) | no |
42
- | `PARTIAL_DUPLICATE_BATCH` | a batch mixed already-appended and fresh events | no |
43
- | `SUPERSEDED_ATTEMPT` | a handler append or clear from an attempt that a recovery claim or a session clear has replaced; nothing was written. Also the abort reason on that handler's `ctx.signal` | no |
44
- | `SESSION_CLEARED` | a state read reached below the latest clear, a handler read state past a clear of its event, or an actor call was cleared before it received its answer | no |
45
- | `CLAIM_EXPIRED` | never thrown; only the `ctx.signal` abort reason when the attempt's lease lapsed without renewal (assumed loss, decided locally, not proof) | no |
46
- | `STORE_UNAVAILABLE` | the store backend failed; nothing was written, original error as `cause` | **yes** |
47
- | `STORE_NOT_CONFIGURED` | production boot with no `store` configured (during `next build` page collection, deferred to first use) | no |
48
-
49
- Of these server codes, only `STORE_UNAVAILABLE` is automatically retried by
50
- client pushes. Reconnection has its own caller-configurable policy.
51
-
52
- ## `A2ClientError`
53
-
54
- Import `A2ClientError` from `experimental-a2/client`. Connection failures,
55
- push failures, history read failures, and local A2 validation failures use
56
- this class. Server failures keep their `code`, `message`, and `details`.
57
- Unexpected thrown values are retained as `cause`. Invalid API arguments can
58
- still throw native `TypeError` or `RangeError` exceptions.
59
-
60
- | Client code | Meaning |
61
- | --- | --- |
62
- | `TIMEOUT` | A2 detected a stream stall or an unconfirmed subscription. `phase` is `stream` or `subscribe`; `timeoutMs` is the expired deadline. |
63
- | `HTTP_ERROR` | An unsuccessful HTTP response without a recognized A2 error body. `status` carries the HTTP status. |
64
- | `CONNECTION_FAILED` | The transport could not establish or retain a connection. WebSocket close events preserve `closeCode` and `closeReason` when available. |
65
- | `UNKNOWN` | An unexpected client failure. The original value is available as `cause`. |
66
-
67
- HTTP failures retain `status` even when they carry a recognized server code.
68
- A browser WebSocket handshake rejection has no readable HTTP status or body;
69
- it remains `CONNECTION_FAILED`. A2 does not infer an authorization failure or
70
- a timeout from an opaque socket error.
71
-
72
- The stream watchdog detects 35 seconds of silence after connection. A
73
- multiplexed subscription also has 35 seconds to receive confirmation. There
74
- is no A2-owned initial connection deadline for HTTP or single-session
75
- WebSockets. Clean stream termination has no error: the reconnection callback
76
- and connection snapshot carry `null`.
77
-
78
- Pushes retain their three-attempt budget for `STORE_UNAVAILABLE` and client
79
- transport failures. The reconnection callback controls only the live stream.
80
- Pausing that stream preserves the writer; it does not guarantee that a push
81
- can succeed while its WebSocket is unavailable.
82
-
83
- On `PARTIAL_DUPLICATE_BATCH`: retrying an *identical* batch is not an
84
- error. It's an idempotent success, and you get the previously appended
85
- events back. Mixing already-sent events with fresh ones in a single batch
86
- is always a caller bug, so A2 refuses it rather than quietly reinterpret
87
- what "atomic" meant. The same code covers two adjacent bugs: a batch that
88
- contains the same id twice, and an id that was already used in a
89
- *different* session (event ids are globally unique). In every case,
90
- nothing is written.
91
-
92
- ## NonRetriableError
93
-
94
- Throw it (or a subclass, matched by
95
- `instanceof`) from a handler when the failure is deterministic: the
96
- event dead-letters immediately instead of consuming the ten-failure
97
- retry budget, because a guard that refuses this attempt will refuse
98
- every retry identically. Any other thrown error keeps the ordinary
99
- retry contract.
100
-
101
- ```ts
102
- import { z } from 'zod'
103
- import * as a2 from 'experimental-a2'
104
- import { NonRetriableError } from 'experimental-a2'
105
- import { createServer } from 'experimental-a2/server'
106
-
107
- const orders = a2.contract({
108
- name: 'orders',
109
- events: { created: z.object({ chargeable: z.boolean() }) },
110
- })
111
-
112
- export const ordersServer = createServer({
113
- contract: orders,
114
- handlers: {
115
- created: async ({ event }) => {
116
- if (!event.payload.chargeable) {
117
- throw new NonRetriableError('this order cannot be charged')
118
- }
119
- // transient failures below retry as usual
120
- },
121
- },
122
- })
123
- ```
124
-
125
- ## What append never throws for
126
-
127
- - **A failing handler.** Appends always land; handler failures are retried
128
- and, if persistent, [dead-letter the event](/concepts/durability#when-a-handler-keeps-failing).
129
- `append` never fails because a downstream handler is failing.
130
- - **A duplicate of an identical batch.** That's a lost ack, not a bug.
131
-
132
- ## Over the wire
133
-
134
- The push route serializes an `A2Error` as:
135
-
136
- ```json
137
- { "error": { "code": "INVALID_PAYLOAD", "message": "...", "details": [] } }
138
- ```
139
-
140
- with a mapped status: `INVALID_PAYLOAD`, `UNKNOWN_EVENT_TYPE`, and
141
- `PARTIAL_DUPLICATE_BATCH` are 400; `FORBIDDEN` is 403;
142
- `SUPERSEDED_ATTEMPT` is 409; `STORE_UNAVAILABLE` is 503.
143
-
144
- The session client deserializes the body into an `A2ClientError`, so client
145
- and server code branch on identical server codes. `server.fetch` owns HTTP
146
- serialization. Multiplexed WebSocket subscription failures carry the same
147
- error envelope in their `unsubscribed` frame, alongside the legacy `reason`
148
- string. Older reason-only frames remain readable as `CONNECTION_FAILED`.
149
- Unknown server exceptions become `STORE_UNAVAILABLE`; their private causes
150
- are not sent to clients.
File without changes
File without changes