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.
- package/CHANGELOG.md +32 -0
- package/README.md +1 -1
- package/dist/{actor-DBbe5xeE.d.ts → actor-C7b-1arn.d.ts} +5 -5
- package/dist/{actor-DBbe5xeE.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
- package/dist/actor-client.d.ts +1 -1
- package/dist/actor-react.d.ts +3 -3
- package/dist/actor-react.js +1 -1
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +2 -2
- package/dist/{ai-vpGtcaCB.d.ts → ai-BMLlI2Ff.d.ts} +3 -3
- package/dist/{ai-vpGtcaCB.d.ts.map → ai-BMLlI2Ff.d.ts.map} +1 -1
- package/dist/{ai-UrWfKeuv.js → ai-D6mGlO8j.js} +2 -2
- package/dist/{ai-UrWfKeuv.js.map → ai-D6mGlO8j.js.map} +1 -1
- package/dist/ai-client.d.ts +2 -2
- package/dist/ai-client.js +2 -2
- package/dist/ai-fx.browser.d.ts +1 -0
- package/dist/ai-fx.browser.js +6 -0
- package/dist/ai-fx.browser.js.map +1 -0
- package/dist/ai-fx.d.ts +10 -0
- package/dist/ai-fx.d.ts.map +1 -0
- package/dist/ai-fx.js +692 -0
- package/dist/ai-fx.js.map +1 -0
- package/dist/ai-harness-B2suP2Qh.d.ts +26 -0
- package/dist/ai-harness-B2suP2Qh.d.ts.map +1 -0
- package/dist/ai-harness-BuLh_EYi.js +273 -0
- package/dist/ai-harness-BuLh_EYi.js.map +1 -0
- package/dist/ai-pi.browser.d.ts +1 -0
- package/dist/ai-pi.browser.js +6 -0
- package/dist/ai-pi.browser.js.map +1 -0
- package/dist/ai-pi.d.ts +17 -0
- package/dist/ai-pi.d.ts.map +1 -0
- package/dist/ai-pi.js +950 -0
- package/dist/ai-pi.js.map +1 -0
- package/dist/ai-react.d.ts +5 -5
- package/dist/ai-react.js +2 -2
- package/dist/ai-server.d.ts +47 -25
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +113 -40
- package/dist/ai-server.js.map +1 -1
- package/dist/ai-tool-input-DmSqMUQi.js +40 -0
- package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
- package/dist/ai.d.ts +1 -1
- package/dist/ai.js +1 -1
- package/dist/bounded-cache-CPHWF-8h.js +41 -0
- package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
- package/dist/{client-COaiaDub.js → client-BhHLoNKF.js} +3 -3
- package/dist/{client-COaiaDub.js.map → client-BhHLoNKF.js.map} +1 -1
- package/dist/{client-qRnRUzBS.d.ts → client-h_DKFAjj.d.ts} +3 -3
- package/dist/{client-qRnRUzBS.d.ts.map → client-h_DKFAjj.d.ts.map} +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/{initial-snapshot-BrLso5x_.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +2 -2
- package/dist/{initial-snapshot-BrLso5x_.d.ts.map → initial-snapshot-Bx-c0pDP.d.ts.map} +1 -1
- package/dist/{internal-CbVvEwad.js → internal-CscSY7K_.js} +11 -3
- package/dist/internal-CscSY7K_.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/{react-BbJ-g6Uu.d.ts → react-BBXgHWFc.d.ts} +4 -4
- package/dist/{react-BbJ-g6Uu.d.ts.map → react-BBXgHWFc.d.ts.map} +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/reducer-BAXc8JyF.js.map +1 -1
- package/dist/{reducer-BYu6DT7h.d.ts → reducer-CqA59Q6U.d.ts} +2 -2
- package/dist/{reducer-BYu6DT7h.d.ts.map → reducer-CqA59Q6U.d.ts.map} +1 -1
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.js +3 -3
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +7 -7
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +9 -10
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-Rj64fNvX.js → server-D-Y4pqwu.js} +126 -67
- package/dist/server-D-Y4pqwu.js.map +1 -0
- package/dist/{server-CGM8WzRG.d.ts → server-DYAATFuT.d.ts} +42 -7
- package/dist/server-DYAATFuT.d.ts.map +1 -0
- package/dist/server.d.ts +4 -4
- package/dist/server.js +1 -1
- package/dist/{session-clear-Dshpuhff.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
- package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
- package/dist/{store-Gpkq7WBo.d.ts → store-CyLUy86v.d.ts} +53 -5
- package/dist/store-CyLUy86v.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.js +56 -11
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-4_y8lETm.js → store-polling-7WJV0YWP.js} +2 -2
- package/dist/{store-polling-4_y8lETm.js.map → store-polling-7WJV0YWP.js.map} +1 -1
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +106 -25
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-Q1C-k2dd.js → store-presence-polling-B1ixeqIS.js} +3 -3
- package/dist/{store-presence-polling-Q1C-k2dd.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.js +3 -3
- package/dist/{store-redis-notify-tqWNnMRu.js → store-redis-notify-CM0AfLY0.js} +271 -101
- package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.js +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.js +66 -21
- package/dist/store-sqlite.js.map +1 -1
- package/dist/{telemetry-cZH-cibj.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
- package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
- package/dist/{wire-DjfHOvdW.js → wire-BKxH1vbP.js} +2 -2
- package/dist/{wire-DjfHOvdW.js.map → wire-BKxH1vbP.js.map} +1 -1
- package/docs/01-quickstart.mdx +49 -83
- package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
- package/docs/actors/01-introduction.mdx +48 -86
- package/docs/actors/02-concurrency.mdx +43 -70
- package/docs/actors/03-timers.mdx +28 -42
- package/docs/actors/04-routes.mdx +110 -150
- package/docs/actors/meta.ts +1 -1
- package/docs/agents/01-introduction.mdx +257 -0
- package/docs/agents/02-tools.mdx +247 -0
- package/docs/agents/03-conversations.mdx +538 -0
- package/docs/agents/04-harnesses.mdx +136 -0
- package/docs/agents/meta.ts +1 -0
- package/docs/client/01-react.mdx +294 -0
- package/docs/client/02-transports.mdx +86 -0
- package/docs/client/03-presence.mdx +224 -0
- package/docs/client/meta.ts +1 -0
- package/docs/contract/01-events.mdx +57 -0
- package/docs/contract/02-state.mdx +142 -0
- package/docs/contract/03-sessions.mdx +175 -0
- package/docs/index.mdx +109 -145
- package/docs/reference/01-core.mdx +139 -0
- package/docs/reference/02-server.mdx +860 -0
- package/docs/reference/03-client.mdx +301 -0
- package/docs/reference/04-ai.mdx +731 -0
- package/docs/reference/05-adapters.mdx +351 -0
- package/docs/reference/06-errors.mdx +138 -0
- package/docs/reference/meta.ts +1 -1
- package/docs/server/01-handlers.mdx +200 -0
- package/docs/server/02-timers.mdx +130 -0
- package/docs/server/03-cancellation.mdx +142 -0
- package/docs/server/04-routes.mdx +243 -0
- package/docs/server/05-production.mdx +323 -0
- package/docs/server/06-guarantees.mdx +132 -0
- package/examples/playground/DEPLOY.md +3 -5
- package/examples/playground/app/a0/[appId]/page.tsx +12 -13
- package/examples/playground/app/a0/app-list.tsx +9 -2
- package/examples/playground/app/a0/app-view.tsx +9 -1
- package/examples/playground/app/a0/apps/[appId]/route.ts +10 -5
- package/examples/playground/app/a0/apps.test.ts +12 -0
- package/examples/playground/app/a0/apps.ts +22 -7
- package/examples/playground/app/a0/chat.tsx +47 -1
- package/examples/playground/app/a0/devtools.tsx +2 -8
- package/examples/playground/app/a0/fx/events/route.ts +9 -0
- package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
- package/examples/playground/app/a0/model.test.ts +18 -1
- package/examples/playground/app/a0/model.ts +47 -10
- package/examples/playground/app/a0/no-photon.cjs +4 -0
- package/examples/playground/app/a0/no-quickjs.cjs +3 -0
- package/examples/playground/app/a0/pi/events/route.ts +9 -0
- package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
- package/examples/playground/app/a0/sandbox-log.ts +10 -4
- package/examples/playground/app/a0/sandbox-session.ts +152 -0
- package/examples/playground/app/a0/scheduler/route.ts +2 -2
- package/examples/playground/app/a0/server.ts +98 -54
- package/examples/playground/app/a0/session.ts +17 -5
- package/examples/playground/app/a0/shell.tsx +11 -3
- package/examples/playground/app/agent/ingress.test.ts +6 -3
- package/examples/playground/app/agent/server.ts +9 -6
- package/examples/playground/app/agent/telemetry.test.ts +71 -50
- package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +1 -1
- package/examples/playground/app/chat/server.test.ts +30 -26
- package/examples/playground/app/chat/server.ts +46 -46
- package/examples/playground/next.config.ts +17 -5
- package/examples/playground/package.json +4 -1
- package/examples/playground/vercel.json +18 -0
- package/package.json +27 -3
- package/src/ai-agent.ts +271 -90
- package/src/ai-fx.browser.ts +5 -0
- package/src/ai-fx.ts +912 -0
- package/src/ai-harness.ts +518 -0
- package/src/ai-model-metadata.ts +11 -6
- package/src/ai-pi.browser.ts +5 -0
- package/src/ai-pi.ts +1322 -0
- package/src/ai-sdk-step.ts +2 -2
- package/src/ai-server.ts +3 -1
- package/src/ai-tool-input.ts +45 -0
- package/src/internal.ts +13 -0
- package/src/libfx.d.ts +34 -0
- package/src/reducer.ts +1 -1
- package/src/scheduler-qstash.ts +5 -5
- package/src/scheduler-vercel.ts +14 -15
- package/src/server.ts +233 -29
- package/src/store-memory.ts +92 -16
- package/src/store-postgres.ts +156 -25
- package/src/store-redis-core.ts +322 -110
- package/src/store-redis-notify.ts +2 -0
- package/src/store-sqlite.ts +121 -28
- package/src/store.ts +55 -3
- package/src/telemetry.ts +1 -0
- package/dist/internal-CbVvEwad.js.map +0 -1
- package/dist/server-CGM8WzRG.d.ts.map +0 -1
- package/dist/server-Rj64fNvX.js.map +0 -1
- package/dist/session-clear-Dshpuhff.d.ts.map +0 -1
- package/dist/store-Gpkq7WBo.d.ts.map +0 -1
- package/dist/store-redis-notify-tqWNnMRu.js.map +0 -1
- package/dist/telemetry-cZH-cibj.d.ts.map +0 -1
- package/docs/concepts/01-contracts.mdx +0 -237
- package/docs/concepts/02-handlers.mdx +0 -284
- package/docs/concepts/03-durability.mdx +0 -314
- package/docs/concepts/04-state.mdx +0 -209
- package/docs/guides/01-timers.mdx +0 -193
- package/docs/guides/02-cancellation.mdx +0 -161
- package/docs/guides/03-react.mdx +0 -324
- package/docs/guides/04-local-first.mdx +0 -47
- package/docs/guides/05-production.mdx +0 -534
- package/docs/guides/06-ai-agents.mdx +0 -1408
- package/docs/guides/08-application-data.mdx +0 -113
- package/docs/guides/09-presence.mdx +0 -262
- package/docs/guides/10-transports.mdx +0 -221
- package/docs/reference/01-api.mdx +0 -2358
- package/docs/reference/02-errors.mdx +0 -150
- /package/docs/{concepts → contract}/meta.ts +0 -0
- /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
|