experimental-a2 0.16.0 → 0.17.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.
- package/CHANGELOG.md +360 -0
- package/dist/{actor-ohPC-81x.d.ts → actor-DBbe5xeE.d.ts} +21 -11
- package/dist/actor-DBbe5xeE.d.ts.map +1 -0
- package/dist/actor-client.d.ts +2 -5
- package/dist/actor-client.d.ts.map +1 -1
- package/dist/actor-client.js +13 -4
- package/dist/actor-client.js.map +1 -1
- package/dist/actor-react.d.ts +5 -3
- package/dist/actor-react.d.ts.map +1 -1
- package/dist/actor-react.js +20 -10
- package/dist/actor-react.js.map +1 -1
- package/dist/{actor-shared-B5tJfzt-.js → actor-shared-t7w8xIKP.js} +12 -7
- package/dist/actor-shared-t7w8xIKP.js.map +1 -0
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +42 -23
- package/dist/actor.js.map +1 -1
- package/dist/{ai-CrLYwNEx.js → ai-UrWfKeuv.js} +966 -541
- package/dist/ai-UrWfKeuv.js.map +1 -0
- package/dist/ai-client.d.ts +27 -0
- package/dist/ai-client.d.ts.map +1 -0
- package/dist/ai-client.js +29 -0
- package/dist/ai-client.js.map +1 -0
- package/dist/ai-react.d.ts +96 -0
- package/dist/ai-react.d.ts.map +1 -0
- package/dist/ai-react.js +142 -0
- package/dist/ai-react.js.map +1 -0
- package/dist/ai-server.browser.js +2 -2
- package/dist/ai-server.browser.js.map +1 -1
- package/dist/ai-server.d.ts +80 -36
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +466 -265
- package/dist/ai-server.js.map +1 -1
- package/dist/{ai-HJ9fHfYI.d.ts → ai-vpGtcaCB.d.ts} +115 -101
- package/dist/ai-vpGtcaCB.d.ts.map +1 -0
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +2 -2
- package/dist/{client-BYzHjkwU.js → client-COaiaDub.js} +447 -80
- package/dist/client-COaiaDub.js.map +1 -0
- package/dist/{client-CzyacQpJ.d.ts → client-qRnRUzBS.d.ts} +14 -13
- package/dist/client-qRnRUzBS.d.ts.map +1 -0
- package/dist/client.d.ts +4 -2
- package/dist/client.js +1 -1
- package/dist/{contract-CKRg_E4q.js → contract-BYKASlCV.js} +12 -21
- package/dist/contract-BYKASlCV.js.map +1 -0
- package/dist/{idempotent-replay-DVOlyYbx.js → idempotent-replay-JdgMQRRm.js} +2 -2
- package/dist/{idempotent-replay-DVOlyYbx.js.map → idempotent-replay-JdgMQRRm.js.map} +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/{errors-DvhSXnxk.d.ts → initial-snapshot-BrLso5x_.d.ts} +7 -3
- package/dist/initial-snapshot-BrLso5x_.d.ts.map +1 -0
- package/dist/{internal-Dq2qYxou.js → internal-CbVvEwad.js} +23 -2
- package/dist/internal-CbVvEwad.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/react-BbJ-g6Uu.d.ts +86 -0
- package/dist/react-BbJ-g6Uu.d.ts.map +1 -0
- package/dist/react.d.ts +2 -122
- package/dist/react.js +107 -100
- package/dist/react.js.map +1 -1
- package/dist/reducer-BAXc8JyF.js +87 -0
- package/dist/reducer-BAXc8JyF.js.map +1 -0
- package/dist/{reducer-otzHjuJj.d.ts → reducer-BYu6DT7h.d.ts} +45 -29
- package/dist/reducer-BYu6DT7h.d.ts.map +1 -0
- package/dist/reducer-runtime-DQwz_J59.js +28 -0
- package/dist/reducer-runtime-DQwz_J59.js.map +1 -0
- package/dist/scheduler-qstash.d.ts +3 -3
- package/dist/scheduler-qstash.d.ts.map +1 -1
- package/dist/scheduler-qstash.js +33 -10
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/{scheduler-task-BpzhPnRS.js → scheduler-task-X1SToDjP.js} +18 -3
- package/dist/scheduler-task-X1SToDjP.js.map +1 -0
- package/dist/scheduler-vercel.d.ts +4 -9
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +25 -44
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-DbD7IJVK.d.ts → server-CGM8WzRG.d.ts} +87 -26
- package/dist/server-CGM8WzRG.d.ts.map +1 -0
- package/dist/{server-BD5ckxZb.js → server-Rj64fNvX.js} +854 -202
- package/dist/server-Rj64fNvX.js.map +1 -0
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/{errors-DCk6ch5n.js → session-clear-DGI4jTQ5.js} +17 -2
- package/dist/session-clear-DGI4jTQ5.js.map +1 -0
- package/dist/session-clear-Dshpuhff.d.ts +12 -0
- package/dist/session-clear-Dshpuhff.d.ts.map +1 -0
- package/dist/{store-DyZM6fS5.d.ts → store-Gpkq7WBo.d.ts} +44 -3
- package/dist/store-Gpkq7WBo.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.d.ts.map +1 -1
- package/dist/store-memory.js +182 -69
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-CmxUbV93.js → store-polling-4_y8lETm.js} +21 -4
- package/dist/store-polling-4_y8lETm.js.map +1 -0
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +399 -108
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-C7-XZyW9.js → store-presence-polling-Q1C-k2dd.js} +3 -3
- package/dist/{store-presence-polling-C7-XZyW9.js.map → store-presence-polling-Q1C-k2dd.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.d.ts.map +1 -1
- package/dist/store-redis-http.js +293 -11
- package/dist/store-redis-http.js.map +1 -1
- package/dist/store-redis-notify-tqWNnMRu.js +2374 -0
- package/dist/store-redis-notify-tqWNnMRu.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.d.ts.map +1 -1
- package/dist/store-redis.js +11 -11
- package/dist/store-redis.js.map +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.d.ts.map +1 -1
- package/dist/store-sqlite.js +166 -32
- package/dist/store-sqlite.js.map +1 -1
- package/dist/stream-buffer-Cx7AAPGq.js +23 -0
- package/dist/stream-buffer-Cx7AAPGq.js.map +1 -0
- package/dist/{telemetry-B5jzpy6y.d.ts → telemetry-cZH-cibj.d.ts} +2 -2
- package/dist/telemetry-cZH-cibj.d.ts.map +1 -0
- package/dist/{wire-BO5wWCb1.js → wire-DjfHOvdW.js} +132 -10
- package/dist/wire-DjfHOvdW.js.map +1 -0
- package/docs/01-quickstart.mdx +2 -2
- package/docs/actors/01-introduction.mdx +4 -0
- package/docs/actors/04-routes.mdx +14 -1
- package/docs/concepts/01-contracts.mdx +95 -0
- package/docs/concepts/04-state.mdx +3 -3
- package/docs/guides/01-timers.mdx +22 -14
- package/docs/guides/02-cancellation.mdx +1 -1
- package/docs/guides/03-react.mdx +268 -328
- package/docs/guides/04-local-first.mdx +32 -73
- package/docs/guides/05-production.mdx +40 -27
- package/docs/guides/06-ai-agents.mdx +680 -580
- package/docs/guides/09-presence.mdx +3 -7
- package/docs/guides/10-transports.mdx +5 -5
- package/docs/index.mdx +10 -18
- package/docs/reference/01-api.mdx +662 -195
- package/docs/reference/02-errors.mdx +2 -1
- package/examples/playground/DEPLOY.md +52 -6
- package/examples/playground/app/a0/[appId]/loading.tsx +16 -0
- package/examples/playground/app/a0/[appId]/page.tsx +48 -0
- package/examples/playground/app/a0/a0.css +818 -0
- package/examples/playground/app/a0/app-list.tsx +211 -0
- package/examples/playground/app/a0/app-view.tsx +55 -0
- package/examples/playground/app/a0/apps/[appId]/preview/route.ts +27 -0
- package/examples/playground/app/a0/apps/[appId]/route.ts +23 -0
- package/examples/playground/app/a0/apps.test.ts +116 -0
- package/examples/playground/app/a0/apps.ts +87 -0
- package/examples/playground/app/a0/chat.tsx +364 -0
- package/examples/playground/app/a0/columns.tsx +109 -0
- package/examples/playground/app/a0/context-menu.tsx +116 -0
- package/examples/playground/app/a0/cookies.ts +46 -0
- package/examples/playground/app/a0/crash-on-request.ts +72 -0
- package/examples/playground/app/a0/crashes/route.ts +3 -0
- package/examples/playground/app/a0/crashes.test.ts +33 -0
- package/examples/playground/app/a0/crashes.ts +28 -0
- package/examples/playground/app/a0/devtools.tsx +164 -0
- package/examples/playground/app/a0/events/route.ts +6 -0
- package/examples/playground/app/a0/flags.ts +30 -0
- package/examples/playground/app/a0/layout.tsx +38 -0
- package/examples/playground/app/a0/list/route.ts +10 -0
- package/examples/playground/app/a0/model.test.ts +56 -0
- package/examples/playground/app/a0/model.ts +58 -0
- package/examples/playground/app/a0/page.tsx +14 -0
- package/examples/playground/app/a0/preview-pane.tsx +145 -0
- package/examples/playground/app/a0/preview.test.ts +53 -0
- package/examples/playground/app/a0/preview.ts +26 -0
- package/examples/playground/app/a0/sandbox-log.ts +69 -0
- package/examples/playground/app/a0/sandbox.ts +191 -0
- package/examples/playground/app/a0/sandboxes/scheduler/route.ts +6 -0
- package/examples/playground/app/a0/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/server.ts +158 -0
- package/examples/playground/app/a0/session.ts +47 -0
- package/examples/playground/app/a0/shell.tsx +150 -0
- package/examples/playground/app/a0/short/events/route.ts +9 -0
- package/examples/playground/app/a0/splitter.tsx +120 -0
- package/examples/playground/app/agent/[agentId]/agent-client.tsx +144 -174
- package/examples/playground/app/agent/[agentId]/command-receipt.test.tsx +65 -0
- package/examples/playground/app/agent/[agentId]/command-receipt.tsx +27 -0
- package/examples/playground/app/agent/[agentId]/compaction-event.tsx +25 -24
- package/examples/playground/app/agent/[agentId]/compaction-panel.test.tsx +119 -0
- package/examples/playground/app/agent/[agentId]/compaction-panel.tsx +208 -165
- package/examples/playground/app/agent/[agentId]/page.tsx +2 -16
- package/examples/playground/app/agent/events/route.ts +5 -2
- package/examples/playground/app/agent/ingress.test.ts +98 -0
- package/examples/playground/app/agent/model-input.test.tsx +58 -0
- package/examples/playground/app/agent/model-input.tsx +115 -0
- package/examples/playground/app/agent/model.test.ts +73 -0
- package/examples/playground/app/agent/model.ts +58 -26
- package/examples/playground/app/agent/new-agent-session.tsx +37 -19
- package/examples/playground/app/agent/page.tsx +4 -4
- package/examples/playground/app/agent/server.ts +15 -14
- package/examples/playground/app/agent/session.ts +5 -6
- package/examples/playground/app/agent/telemetry.test.ts +168 -0
- package/examples/playground/app/agent/telemetry.ts +30 -0
- package/examples/playground/app/agent/trace.test.ts +23 -0
- package/examples/playground/app/agent/trace.ts +18 -0
- package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +11 -11
- package/examples/playground/app/canvas/[canvasId]/page.tsx +1 -2
- package/examples/playground/app/canvas/[canvasId]/session.ts +2 -2
- package/examples/playground/app/canvas/model.ts +53 -53
- package/examples/playground/app/chat/[chatId]/agent-state.test.ts +176 -0
- package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +16 -1
- package/examples/playground/app/chat/[chatId]/chat-client.tsx +55 -77
- package/examples/playground/app/chat/[chatId]/chat-view.ts +37 -3
- package/examples/playground/app/chat/[chatId]/page.tsx +7 -15
- package/examples/playground/app/chat/[chatId]/session.ts +2 -19
- package/examples/playground/app/chat/agent/route.ts +9 -0
- package/examples/playground/app/chat/model.test.ts +46 -119
- package/examples/playground/app/chat/model.ts +82 -128
- package/examples/playground/app/chat/scheduler/route.ts +2 -2
- package/examples/playground/app/chat/server.test.ts +108 -0
- package/examples/playground/app/chat/server.ts +69 -73
- package/examples/playground/app/components/activity-feed.tsx +30 -1
- package/examples/playground/app/components/activity-history.test.tsx +35 -0
- package/examples/playground/app/components/demo-icons.tsx +89 -0
- package/examples/playground/app/components/demos.tsx +33 -0
- package/examples/playground/app/components/fast-link.test.tsx +58 -0
- package/examples/playground/app/components/fast-link.tsx +55 -0
- package/examples/playground/app/components/site-header.tsx +96 -0
- package/examples/playground/app/counter/counter-client.tsx +3 -3
- package/examples/playground/app/counter/model.test.ts +3 -3
- package/examples/playground/app/counter/model.ts +11 -21
- package/examples/playground/app/counter/page.tsx +2 -15
- package/examples/playground/app/counter/session.ts +2 -2
- package/examples/playground/app/documents/[documentId]/code-editor.tsx +12 -1
- package/examples/playground/app/documents/[documentId]/document-client.tsx +10 -11
- package/examples/playground/app/documents/[documentId]/page.tsx +1 -2
- package/examples/playground/app/documents/[documentId]/session.ts +2 -2
- package/examples/playground/app/documents/model.ts +27 -27
- package/examples/playground/app/globals.css +420 -207
- package/examples/playground/app/initial-state.test.tsx +54 -0
- package/examples/playground/app/layout.tsx +7 -23
- package/examples/playground/app/orders/[orderId]/page.tsx +1 -2
- package/examples/playground/app/orders/[orderId]/session.ts +2 -2
- package/examples/playground/app/orders/model.ts +49 -49
- package/examples/playground/app/page.tsx +13 -102
- package/examples/playground/app/recovery/[recoveryId]/page.tsx +1 -2
- package/examples/playground/app/recovery/[recoveryId]/session.ts +2 -2
- package/examples/playground/app/recovery/model.ts +30 -30
- package/examples/playground/instrumentation.ts +5 -0
- package/examples/playground/package.json +10 -2
- package/examples/playground/scripts/a0-template.ts +77 -0
- package/examples/playground/vercel.json +18 -0
- package/package.json +3 -1
- package/src/actor-client.ts +16 -4
- package/src/actor-react.ts +25 -11
- package/src/actor-shared.ts +21 -6
- package/src/actor.ts +76 -31
- package/src/ai-agent-actions.ts +219 -0
- package/src/ai-agent.ts +2343 -0
- package/src/ai-app-state.ts +91 -0
- package/src/ai-client-state.ts +39 -2
- package/src/ai-client.ts +62 -0
- package/src/ai-context-schema.ts +25 -5
- package/src/ai-context.ts +90 -40
- package/src/ai-control-server.ts +94 -55
- package/src/ai-control.ts +2 -0
- package/src/ai-coordinator.ts +23 -22
- package/src/ai-message-base.ts +209 -0
- package/src/ai-message-projection.ts +382 -58
- package/src/ai-progress-batches.ts +26 -0
- package/src/ai-projector.ts +95 -14
- package/src/ai-react.ts +146 -0
- package/src/ai-server.browser.ts +2 -2
- package/src/ai-server.ts +20 -1951
- package/src/ai-stored-state.ts +48 -163
- package/src/ai.ts +343 -276
- package/src/bootstrap-stream.ts +72 -0
- package/src/bounded-cache.ts +55 -0
- package/src/client-render-session.ts +49 -0
- package/src/client.ts +688 -151
- package/src/contract.ts +92 -42
- package/src/deterministic-id.ts +37 -0
- package/src/equal-json.ts +32 -0
- package/src/errors.ts +13 -1
- package/src/index.ts +5 -1
- package/src/initial-snapshot.ts +39 -0
- package/src/internal.ts +45 -0
- package/src/postgres-notification-scope.ts +14 -3
- package/src/react.ts +171 -206
- package/src/redis-http-reply.ts +256 -0
- package/src/redis-http-stream.ts +73 -0
- package/src/redis-http-subscriptions.ts +13 -5
- package/src/reducer-runtime.ts +52 -0
- package/src/reducer.ts +92 -10
- package/src/scheduler-qstash.ts +49 -20
- package/src/scheduler-task.ts +34 -2
- package/src/scheduler-vercel.ts +32 -84
- package/src/server-fetch.ts +139 -35
- package/src/server.ts +957 -237
- package/src/session-clear.ts +23 -0
- package/src/session-socket.ts +154 -49
- package/src/sse.ts +71 -4
- package/src/store-memory.ts +220 -78
- package/src/store-polling.ts +18 -4
- package/src/store-postgres.ts +461 -114
- package/src/store-redis-core.ts +1260 -434
- package/src/store-redis-http.ts +18 -2
- package/src/store-redis-notify.ts +260 -85
- package/src/store-redis.ts +19 -9
- package/src/store-sqlite.ts +259 -45
- package/src/store.ts +46 -1
- package/src/stream-buffer.ts +43 -0
- package/src/telemetry.ts +13 -1
- package/src/wire.ts +241 -13
- package/dist/actor-ohPC-81x.d.ts.map +0 -1
- package/dist/actor-shared-B5tJfzt-.js.map +0 -1
- package/dist/ai-CrLYwNEx.js.map +0 -1
- package/dist/ai-HJ9fHfYI.d.ts.map +0 -1
- package/dist/client-BYzHjkwU.js.map +0 -1
- package/dist/client-CzyacQpJ.d.ts.map +0 -1
- package/dist/contract-CKRg_E4q.js.map +0 -1
- package/dist/errors-DCk6ch5n.js.map +0 -1
- package/dist/errors-DvhSXnxk.d.ts.map +0 -1
- package/dist/internal-Dq2qYxou.js.map +0 -1
- package/dist/react.d.ts.map +0 -1
- package/dist/reducer-DEMjEY_O.js +0 -29
- package/dist/reducer-DEMjEY_O.js.map +0 -1
- package/dist/reducer-otzHjuJj.d.ts.map +0 -1
- package/dist/scheduler-task-BpzhPnRS.js.map +0 -1
- package/dist/server-BD5ckxZb.js.map +0 -1
- package/dist/server-DbD7IJVK.d.ts.map +0 -1
- package/dist/store-DyZM6fS5.d.ts.map +0 -1
- package/dist/store-polling-CmxUbV93.js.map +0 -1
- package/dist/store-redis-notify-BVLUfI3j.js +0 -1583
- package/dist/store-redis-notify-BVLUfI3j.js.map +0 -1
- package/dist/telemetry-B5jzpy6y.d.ts.map +0 -1
- package/dist/validate-XKT4FSNn.js +0 -30
- package/dist/validate-XKT4FSNn.js.map +0 -1
- package/dist/wire-BO5wWCb1.js.map +0 -1
- package/examples/playground/app/agent/[agentId]/compaction/route.ts +0 -14
- package/examples/playground/app/agent/compaction-settings.test.ts +0 -144
- package/examples/playground/app/agent/compaction-settings.ts +0 -49
- package/examples/playground/app/agent/compaction-timeline.test.ts +0 -377
- package/examples/playground/app/agent/compaction-timeline.ts +0 -208
|
@@ -1,88 +1,47 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description: "
|
|
2
|
+
title: Client lifetime
|
|
3
|
+
description: "Share an in-memory session, control idle eviction, and resume its event stream."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Reuse a client
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Keep the client in a module so components share session identity, state,
|
|
9
|
+
raw events, pending writes, and connection ownership:
|
|
10
|
+
|
|
11
|
+
```ts app/session-client.ts
|
|
9
12
|
'use client'
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { ordersReducer } from '@/reducer'
|
|
13
|
+
import { createClient } from 'experimental-a2/client'
|
|
14
|
+
import { orders } from '@/contracts'
|
|
13
15
|
|
|
14
|
-
export const
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export const ordersClient = createClient({
|
|
17
|
+
contract: orders,
|
|
18
|
+
api: '/api/order-events',
|
|
19
|
+
gcTime: 5 * 60 * 1_000,
|
|
17
20
|
})
|
|
18
21
|
```
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exactly as before; nothing crosses the server boundary.
|
|
24
|
-
|
|
25
|
-
With `cache` set:
|
|
26
|
-
|
|
27
|
-
- **Revisits paint instantly.** State folds from the local copy before the
|
|
28
|
-
network says a word. Works offline too.
|
|
29
|
-
- **The stream resumes from the cached frontier.** Reconnects fetch only
|
|
30
|
-
what this browser hasn't seen, no matter how long it's been.
|
|
31
|
-
- **Pushes queue while offline**, and replay, in order, when the
|
|
32
|
-
connection returns.
|
|
33
|
-
|
|
34
|
-
Without it, nothing changes; the provider behaves exactly as before.
|
|
35
|
-
|
|
36
|
-
## Why this is safe
|
|
37
|
-
|
|
38
|
-
Local-first is usually hard because it means syncing state, and state
|
|
39
|
-
needs merging. A2 caches an append-only log with server-assigned positions
|
|
40
|
-
instead. A cached event can never be *wrong*; this browser can only be
|
|
41
|
-
*behind*. Catching up is fetching events after an index, which is what
|
|
42
|
-
`stream({ startAfter })` does anyway. There's no merge function because
|
|
43
|
-
there's nothing to merge.
|
|
44
|
-
|
|
45
|
-
## What gets stored
|
|
23
|
+
`gcTime` is the idle eviction delay, five minutes by default. Active
|
|
24
|
+
connections, listeners, and pending work keep the runtime alive. Another
|
|
25
|
+
client instance has a separate cache even when it uses the same URL.
|
|
46
26
|
|
|
47
|
-
|
|
27
|
+
## Startup and reconnect
|
|
48
28
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| pending pushes | the server's ack |
|
|
29
|
+
A new unseeded session receives a snapshot on its event subscription.
|
|
30
|
+
A supplied state/index pair skips that read. A cached session keeps its
|
|
31
|
+
state and resumes after its delivered event position. See
|
|
32
|
+
[Live UI](/guides/react).
|
|
54
33
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
string, both sides of the wire.
|
|
34
|
+
State snapshots bound replay work, not the size of the reducer state or
|
|
35
|
+
raw event collection. Choose reducer contents that fit the application.
|
|
58
36
|
|
|
59
|
-
|
|
60
|
-
already saw; the log on the server stays the only authority.
|
|
37
|
+
## Persistence
|
|
61
38
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`
|
|
65
|
-
applies them optimistically, same as always. On reconnect they replay in
|
|
66
|
-
order. The replay is idempotent by construction: an identical batch is an
|
|
67
|
-
idempotent success, so a flaky reconnect, or a second tab replaying the
|
|
68
|
-
same queue, causes no duplicates. Rejections refold without the event,
|
|
69
|
-
exactly like an online push the server refused.
|
|
70
|
-
|
|
71
|
-
What this is *not*: local execution. Handlers run on the server, when the
|
|
72
|
-
events arrive. An offline push is a queued intent, not a completed
|
|
73
|
-
action. Design the UI accordingly ("sending…" is honest; "sent" is not).
|
|
74
|
-
|
|
75
|
-
## Logout
|
|
76
|
-
|
|
77
|
-
Cached events outlive the session cookie. If your app authenticates,
|
|
78
|
-
clear the cache when the user leaves:
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
// in the browser, wherever your logout flow runs:
|
|
82
|
-
await cache.clear() // everything, or cache.clear(sessionId) for one session
|
|
83
|
-
```
|
|
39
|
+
This cache is in memory. Reloading the page discards it. A2 does not ship
|
|
40
|
+
an IndexedDB adapter or a persistent offline write queue. The
|
|
41
|
+
`experimental-a2/cache-indexeddb` entry point currently has no implementation.
|
|
84
42
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
43
|
+
Pushes have bounded retries and optimistic rollback when they fail.
|
|
44
|
+
Application-owned persistence can restore a state/index pair through the
|
|
45
|
+
normal hydration options. Only restore data belonging to the same session
|
|
46
|
+
and reducer version, and keep authentication and retained-data policy in
|
|
47
|
+
the application.
|
|
@@ -77,11 +77,13 @@ from another client can take up to the idle interval plus query latency to
|
|
|
77
77
|
arrive after a quiet period.
|
|
78
78
|
|
|
79
79
|
Prefer Redis? `redis({ url })` from `experimental-a2/store-redis` stores each
|
|
80
|
-
session as a Redis Stream and streams push-natively:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
session as a Redis Stream and streams push-natively: every write publishes a
|
|
81
|
+
disposable wake-up, one shared subscriber connection per process serves every
|
|
82
|
+
connected viewer, and a safety re-read covers a lost wake-up within ten
|
|
83
|
+
seconds. Connections scale with your processes, not with your audience. On
|
|
84
|
+
providers that bill per command, such as Upstash, each command a script runs
|
|
85
|
+
counts: appending an event with a handler and running it takes 24 commands,
|
|
86
|
+
and an idle live stream takes 6 a minute.
|
|
85
87
|
`ioredis` is an optional peer dependency; pass `url`, or inject a client.
|
|
86
88
|
Works on single instances and non-cluster providers such as Upstash, where
|
|
87
89
|
durability is on by default. When only a REST API is available,
|
|
@@ -89,8 +91,12 @@ durability is on by default. When only a REST API is available,
|
|
|
89
91
|
same storage over `fetch`. Live events and presence use Upstash’s HTTP
|
|
90
92
|
`SUBSCRIBE` endpoint (SSE), with the same URL and token. Each active channel
|
|
91
93
|
holds one outbound HTTP subscription per store instance, shared by its local
|
|
92
|
-
viewers and closed when the last viewer leaves. Writes
|
|
93
|
-
|
|
94
|
+
viewers and closed when the last viewer leaves. Writes publish wake-ups inside
|
|
95
|
+
the same Redis script as the append, and each wake-up carries the new events so
|
|
96
|
+
live streams deliver them without another read. Live streams trust those
|
|
97
|
+
messages, so a Redis identity that can publish to the `:notify` channels can add
|
|
98
|
+
or hide live events: grant publish access only to identities that can also
|
|
99
|
+
write the store. Presence writes
|
|
94
100
|
also publish their applied fields inside the script. A rejected notification
|
|
95
101
|
does not fail the applied write. Idle event streams
|
|
96
102
|
read once every ten seconds to recover missed notifications. Subscriptions reconnect automatically and catch up from
|
|
@@ -172,29 +178,30 @@ route's protection boundary: Vercel makes the function private, and only queue
|
|
|
172
178
|
infrastructure can invoke it. Do not expose the callback as an ordinary public
|
|
173
179
|
route or add a second authentication scheme around it.
|
|
174
180
|
|
|
175
|
-
The adapter
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
The adapter uses one queue client for recovery watchdogs, scheduled appends,
|
|
182
|
+
and scheduled clears. Its `deploymentId` setting applies to sends, payload
|
|
183
|
+
fetches, acknowledgements, and visibility changes. Omit it to use the publishing
|
|
184
|
+
deployment, pass a deployment ID to target that deployment, or pass `null` for
|
|
185
|
+
deploymentless delivery. Publishing and consuming clients must use the same
|
|
186
|
+
deployment scope.
|
|
178
187
|
|
|
179
|
-
|
|
188
|
+
Promoting a new deployment does not move pinned tasks. Older deployments keep
|
|
189
|
+
receiving their own work until it is acknowledged or expires. Upgrading does
|
|
190
|
+
not repair an older deployment's callback handler.
|
|
180
191
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
export const scheduler = vercelQueues({
|
|
186
|
-
scheduledAppends: 'deploymentless',
|
|
187
|
-
})
|
|
188
|
-
```
|
|
192
|
+
With `deploymentId: null`, Vercel chooses an eligible deploymentless consumer;
|
|
193
|
+
this does not select the latest production deployment. Every eligible consumer
|
|
194
|
+
must use `deploymentId: null` and remain compatible with pending tasks and
|
|
195
|
+
session work.
|
|
189
196
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
versioned.
|
|
197
|
+
Changing the setting does not move already queued tasks. Keep consumers for
|
|
198
|
+
their original deployment scope until those tasks finish. The former
|
|
199
|
+
`scheduledAppends: 'deploymentless'` option affected only timers; its replacement,
|
|
200
|
+
`deploymentId: null`, also makes recovery deploymentless.
|
|
195
201
|
|
|
196
202
|
Vercel Queues defaults to 24-hour message retention. The adapter sets retention
|
|
197
|
-
to 7 days and accepts scheduled appends through 6 days, reserving
|
|
203
|
+
to 7 days and accepts scheduled appends and clears through 6 days, reserving
|
|
204
|
+
the final day
|
|
198
205
|
for delivery and retries. Recovery watchdogs are measured in seconds.
|
|
199
206
|
|
|
200
207
|
### QStash
|
|
@@ -446,8 +453,11 @@ identity, stale-timer guards, and the full provider limits.
|
|
|
446
453
|
:::warning
|
|
447
454
|
Do not roll back to an A2 version without timer delivery while scheduled tasks
|
|
448
455
|
are outstanding. New routes accept old recovery messages, but an old route can
|
|
449
|
-
acknowledge a new append task without writing its events.
|
|
450
|
-
|
|
456
|
+
acknowledge a new append task without writing its events. The same applies to
|
|
457
|
+
scheduled clears and a version without them: an old Vercel Queues route keeps
|
|
458
|
+
failing a clear task until retention ends, and an old QStash route rejects it
|
|
459
|
+
as non-retryable, so QStash moves it to its dead-letter queue. Roll forward, or
|
|
460
|
+
wait for those tasks to deliver or remove them through the provider first.
|
|
451
461
|
:::
|
|
452
462
|
|
|
453
463
|
## 3. When an event dead-letters
|
|
@@ -494,6 +504,9 @@ alert on when an event [needs manual
|
|
|
494
504
|
resolution](#3-when-an-event-dead-letters). See the
|
|
495
505
|
[API reference](/reference/api#a2otel) for the span catalogue.
|
|
496
506
|
|
|
507
|
+
Agent servers use the same telemetry for `a2.ai.*` spans. Core and AI operations
|
|
508
|
+
can nest and overlap, so their durations do not add up to separate layer totals.
|
|
509
|
+
|
|
497
510
|
## Running without a scheduler
|
|
498
511
|
|
|
499
512
|
If none of a contract's event types have handlers and the app never calls
|