experimental-a2 0.16.1 → 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.
- package/CHANGELOG.md +373 -0
- package/README.md +1 -1
- package/dist/{actor-ohPC-81x.d.ts → actor-Bjce9_5U.d.ts} +21 -11
- package/dist/actor-Bjce9_5U.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-DgOBltJ_.js → ai-BpOGm-zB.js} +621 -216
- package/dist/ai-BpOGm-zB.js.map +1 -0
- package/dist/{ai-CrEf6p_W.d.ts → ai-DrUaMyRt.d.ts} +114 -100
- package/dist/ai-DrUaMyRt.d.ts.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-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 +634 -0
- package/dist/ai-fx.js.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-harness-DvsPeJeB.d.ts +26 -0
- package/dist/ai-harness-DvsPeJeB.d.ts.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 +904 -0
- package/dist/ai-pi.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 +109 -43
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +526 -283
- package/dist/ai-server.js.map +1 -1
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +2 -2
- package/dist/bounded-cache-CPHWF-8h.js +41 -0
- package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
- package/dist/{client-BYzHjkwU.js → client-BReKqwZC.js} +447 -80
- package/dist/client-BReKqwZC.js.map +1 -0
- package/dist/{client-CzyacQpJ.d.ts → client-h_DKFAjj.d.ts} +14 -13
- package/dist/client-h_DKFAjj.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-Bx-c0pDP.d.ts} +7 -3
- package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +1 -0
- package/dist/{internal-Dq2qYxou.js → internal-B2T3U4Rq.js} +29 -2
- package/dist/internal-B2T3U4Rq.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/react-BBXgHWFc.d.ts +86 -0
- package/dist/react-BBXgHWFc.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-CqA59Q6U.d.ts} +46 -30
- package/dist/reducer-CqA59Q6U.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-BD5ckxZb.js → server-Dw_k_7kO.js} +904 -219
- package/dist/server-Dw_k_7kO.js.map +1 -0
- package/dist/{server-DbD7IJVK.d.ts → server-En7cbi3v.d.ts} +116 -26
- package/dist/server-En7cbi3v.d.ts.map +1 -0
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/session-clear-Bo-XTFEy.d.ts +12 -0
- package/dist/session-clear-Bo-XTFEy.d.ts.map +1 -0
- package/dist/{errors-DCk6ch5n.js → session-clear-DGI4jTQ5.js} +17 -2
- package/dist/session-clear-DGI4jTQ5.js.map +1 -0
- package/dist/{store-DyZM6fS5.d.ts → store-Djdv0bnZ.d.ts} +73 -3
- package/dist/store-Djdv0bnZ.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 +205 -66
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-CmxUbV93.js → store-polling-B5FcwJfo.js} +21 -4
- package/dist/store-polling-B5FcwJfo.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 +450 -108
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-C7-XZyW9.js → store-presence-polling-BAwS8RWn.js} +3 -3
- package/dist/{store-presence-polling-C7-XZyW9.js.map → store-presence-polling-BAwS8RWn.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-BRITti_o.js +2493 -0
- package/dist/store-redis-notify-BRITti_o.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 +197 -33
- 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-Cyfqo6Qt.d.ts} +2 -2
- package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
- package/dist/{wire-BO5wWCb1.js → wire-rSUglYo8.js} +132 -10
- package/dist/wire-rSUglYo8.js.map +1 -0
- package/docs/01-quickstart.mdx +50 -84
- package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
- package/docs/actors/01-introduction.mdx +48 -82
- package/docs/actors/02-concurrency.mdx +43 -70
- package/docs/actors/03-timers.mdx +28 -42
- package/docs/actors/04-routes.mdx +110 -137
- 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 +112 -156
- package/docs/reference/01-core.mdx +139 -0
- package/docs/reference/02-server.mdx +855 -0
- package/docs/reference/03-client.mdx +301 -0
- package/docs/reference/04-ai.mdx +722 -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 +141 -0
- package/docs/server/04-routes.mdx +243 -0
- package/docs/server/05-production.mdx +322 -0
- package/docs/server/06-guarantees.mdx +123 -0
- package/examples/playground/DEPLOY.md +53 -7
- package/examples/playground/app/a0/[appId]/loading.tsx +16 -0
- package/examples/playground/app/a0/[appId]/page.tsx +53 -0
- package/examples/playground/app/a0/a0.css +818 -0
- package/examples/playground/app/a0/app-list.tsx +218 -0
- package/examples/playground/app/a0/app-view.tsx +63 -0
- package/examples/playground/app/a0/apps/[appId]/preview/route.ts +27 -0
- package/examples/playground/app/a0/apps/[appId]/route.ts +28 -0
- package/examples/playground/app/a0/apps.test.ts +128 -0
- package/examples/playground/app/a0/apps.ts +102 -0
- package/examples/playground/app/a0/chat.tsx +410 -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/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/layout.tsx +38 -0
- package/examples/playground/app/a0/list/route.ts +10 -0
- package/examples/playground/app/a0/model.test.ts +73 -0
- package/examples/playground/app/a0/model.ts +95 -0
- 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/page.tsx +14 -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/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 +75 -0
- package/examples/playground/app/a0/sandbox-session.ts +152 -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 +213 -0
- package/examples/playground/app/a0/session.ts +59 -0
- package/examples/playground/app/a0/shell.tsx +158 -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 +101 -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 +19 -15
- package/examples/playground/app/agent/session.ts +5 -6
- package/examples/playground/app/agent/telemetry.test.ts +189 -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 +12 -12
- 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 +112 -0
- package/examples/playground/app/chat/server.ts +113 -117
- 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/next.config.ts +17 -5
- package/examples/playground/package.json +13 -2
- package/examples/playground/scripts/a0-template.ts +77 -0
- package/examples/playground/vercel.json +36 -0
- package/package.json +29 -3
- 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 +2517 -0
- package/src/ai-app-state.ts +91 -0
- package/src/ai-client-state.ts +6 -3
- 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 +92 -72
- package/src/ai-coordinator.ts +23 -22
- package/src/ai-fx.browser.ts +5 -0
- package/src/ai-fx.ts +833 -0
- package/src/ai-harness.ts +518 -0
- package/src/ai-message-base.ts +209 -0
- package/src/ai-message-projection.ts +262 -64
- package/src/ai-model-metadata.ts +11 -6
- package/src/ai-pi.browser.ts +5 -0
- package/src/ai-pi.ts +1263 -0
- 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-sdk-step.ts +2 -2
- package/src/ai-server.browser.ts +2 -2
- package/src/ai-server.ts +23 -1965
- package/src/ai-stored-state.ts +48 -163
- package/src/ai.ts +339 -155
- 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 +52 -0
- package/src/libfx.d.ts +34 -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 +93 -11
- 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 +1133 -255
- 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 +252 -75
- package/src/store-polling.ts +18 -4
- package/src/store-postgres.ts +541 -114
- package/src/store-redis-core.ts +1450 -493
- package/src/store-redis-http.ts +18 -2
- package/src/store-redis-notify.ts +262 -85
- package/src/store-redis.ts +19 -9
- package/src/store-sqlite.ts +319 -45
- package/src/store.ts +79 -1
- package/src/stream-buffer.ts +43 -0
- package/src/telemetry.ts +14 -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-CrEf6p_W.d.ts.map +0 -1
- package/dist/ai-DgOBltJ_.js.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/docs/concepts/01-contracts.mdx +0 -142
- 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 -185
- package/docs/guides/02-cancellation.mdx +0 -161
- package/docs/guides/03-react.mdx +0 -384
- package/docs/guides/04-local-first.mdx +0 -88
- package/docs/guides/05-production.mdx +0 -521
- package/docs/guides/06-ai-agents.mdx +0 -1318
- package/docs/guides/08-application-data.mdx +0 -113
- package/docs/guides/09-presence.mdx +0 -266
- package/docs/guides/10-transports.mdx +0 -221
- package/docs/reference/01-api.mdx +0 -1896
- package/docs/reference/02-errors.mdx +0 -149
- 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
- /package/docs/{concepts → contract}/meta.ts +0 -0
- /package/docs/{guides → server}/meta.ts +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as A2Store } from "./store-
|
|
3
|
-
import {
|
|
1
|
+
import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, r as RegisteredReducer, s as Contract, t as Reducer, u as EventDefs } from "./reducer-CqA59Q6U.js";
|
|
2
|
+
import { t as A2Store } from "./store-Djdv0bnZ.js";
|
|
3
|
+
import { t as SessionCleared } from "./session-clear-Bo-XTFEy.js";
|
|
4
|
+
import { i as A2Telemetry } from "./telemetry-Cyfqo6Qt.js";
|
|
4
5
|
//#region src/session-socket.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* The structural socket `sessionsSocket` speaks against — satisfied
|
|
@@ -38,6 +39,7 @@ type A2Operation<D extends EventDefs = EventDefs, P extends PresenceDefs = Recor
|
|
|
38
39
|
readonly type: "stream";
|
|
39
40
|
readonly sessionId: string;
|
|
40
41
|
readonly startAfter: number;
|
|
42
|
+
readonly bootstrap?: true;
|
|
41
43
|
readonly transport: "http" | "websocket";
|
|
42
44
|
} | {
|
|
43
45
|
readonly type: "history";
|
|
@@ -87,23 +89,41 @@ type SchedulerAppendTask = {
|
|
|
87
89
|
/** Earliest useful delivery as epoch milliseconds. */
|
|
88
90
|
dueAt: number;
|
|
89
91
|
events: readonly ScheduledEvent[];
|
|
92
|
+
/** The scheduling handler's event; delivery skips once it is cleared. */
|
|
93
|
+
originIndex?: number;
|
|
94
|
+
};
|
|
95
|
+
/** A durable conditional clear. */
|
|
96
|
+
type SchedulerClearTask = {
|
|
97
|
+
version: 1;
|
|
98
|
+
kind: "clear";
|
|
99
|
+
/** Stable identity for provider-level deduplication. */
|
|
100
|
+
id: string;
|
|
101
|
+
contract: string;
|
|
102
|
+
sessionId: string;
|
|
103
|
+
/** Earliest useful delivery as epoch milliseconds. */
|
|
104
|
+
dueAt: number;
|
|
105
|
+
/** Clear only while this is still the head. */
|
|
106
|
+
ifLastIndex: number;
|
|
90
107
|
};
|
|
91
108
|
/** The versioned message protocol shared by scheduler adapters. */
|
|
92
|
-
type SchedulerTask = SchedulerDrainTask | SchedulerAppendTask;
|
|
109
|
+
type SchedulerTask = SchedulerDrainTask | SchedulerAppendTask | SchedulerClearTask;
|
|
93
110
|
//#endregion
|
|
94
111
|
//#region src/server.d.ts
|
|
112
|
+
type PublicState<R> = undefined extends R ? never : R extends {
|
|
113
|
+
initialState: infer S;
|
|
114
|
+
} ? S : never;
|
|
95
115
|
/** What every handler receives. */
|
|
96
|
-
type HandlerContext<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never
|
|
116
|
+
type HandlerContext<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = {
|
|
97
117
|
/** The triggering event. */
|
|
98
118
|
event: ContractEvent<D, K>;
|
|
99
119
|
/** Durable, 1-based dispatch ordinal for this event. */
|
|
100
120
|
attempt: number;
|
|
101
121
|
/** This session, with handler-scoped idempotent append. */
|
|
102
|
-
session: Session<D, HandlerAppend<D>, P>;
|
|
122
|
+
session: Session<D, HandlerAppend<D>, P, S>;
|
|
103
123
|
/** Fires on `abortOn` events (cancellation slice); dormant otherwise. */
|
|
104
124
|
signal: AbortSignal;
|
|
105
125
|
};
|
|
106
|
-
type Handler<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never
|
|
126
|
+
type Handler<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = (ctx: HandlerContext<D, K, P, S>) => Promise<void | AppendInput<D> | readonly AppendInput<D>[]>;
|
|
107
127
|
type LaneContext<D extends EventDefs, K extends keyof D & string = keyof D & string> = {
|
|
108
128
|
sessionId: string;
|
|
109
129
|
event: Pick<ContractEvent<D, K>, "type" | "payload"> & {
|
|
@@ -125,10 +145,57 @@ type ScheduleTiming = {
|
|
|
125
145
|
at: Date;
|
|
126
146
|
delay?: never;
|
|
127
147
|
};
|
|
128
|
-
type SessionSchedule<D extends EventDefs> =
|
|
148
|
+
type SessionSchedule<D extends EventDefs> = {
|
|
149
|
+
(name: string, timing: ScheduleTiming, ...events: AppendInput<D>[]): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Publish a durable conditional clear. Delivery clears only while
|
|
152
|
+
* `ifLastIndex` is still the head, and finishes deleting before it
|
|
153
|
+
* acknowledges.
|
|
154
|
+
*/
|
|
155
|
+
clear(name: string, options: ScheduleTiming & {
|
|
156
|
+
ifLastIndex: number;
|
|
157
|
+
}): Promise<void>;
|
|
158
|
+
};
|
|
129
159
|
type StateOptions = {
|
|
130
160
|
through?: number | "latest";
|
|
131
161
|
};
|
|
162
|
+
type SessionClearOptions = {
|
|
163
|
+
/** Clear only while this is the head; a mismatch changes nothing. */
|
|
164
|
+
ifLastIndex?: number;
|
|
165
|
+
};
|
|
166
|
+
type SessionClearResult = {
|
|
167
|
+
cleared: boolean;
|
|
168
|
+
index: number;
|
|
169
|
+
};
|
|
170
|
+
type SessionRedriveOptions = {
|
|
171
|
+
/** `retry` runs the handler again with a fresh failure budget; `skip` settles the event without running it. */
|
|
172
|
+
action: "retry" | "skip";
|
|
173
|
+
};
|
|
174
|
+
type SessionRedriveResult = {
|
|
175
|
+
/** Whether the event was dead-lettered and is now resolved. */
|
|
176
|
+
redriven: boolean;
|
|
177
|
+
};
|
|
178
|
+
/** A dead-lettered event, with what an operator needs to resolve it. */
|
|
179
|
+
type DeadLetter<D extends EventDefs> = ContractEvent<D> & {
|
|
180
|
+
lane: string | null;
|
|
181
|
+
/** Durable dispatch claims, including claims abandoned by hard kills. */
|
|
182
|
+
attemptCount: number;
|
|
183
|
+
/** Caught handler failures since the event was appended or last retried. */
|
|
184
|
+
failureCount: number;
|
|
185
|
+
/** The last handler failure, stringified. */
|
|
186
|
+
lastError: string | null;
|
|
187
|
+
failedAt: Date;
|
|
188
|
+
};
|
|
189
|
+
/** Dead-letter resolution; root sessions only. */
|
|
190
|
+
type SessionDeadLetters<D extends EventDefs> = {
|
|
191
|
+
/** The session's dead-lettered events, oldest first. */
|
|
192
|
+
deadLetters(): Promise<DeadLetter<D>[]>;
|
|
193
|
+
/**
|
|
194
|
+
* Atomically resolve one dead-lettered event, then wake the session like
|
|
195
|
+
* an append. Any other event is left alone and reports `redriven: false`.
|
|
196
|
+
*/
|
|
197
|
+
redrive(index: number, options: SessionRedriveOptions): Promise<SessionRedriveResult>;
|
|
198
|
+
};
|
|
132
199
|
/**
|
|
133
200
|
* The presence members of a session — intersected in via
|
|
134
201
|
* `WithPresence`, so they exist exactly when the contract declares
|
|
@@ -145,7 +212,7 @@ type SessionPresence<D extends EventDefs, P extends PresenceDefs> = {
|
|
|
145
212
|
stream(opts: {
|
|
146
213
|
startAfter?: number;
|
|
147
214
|
presence: true;
|
|
148
|
-
}): AsyncIterable<ContractEvent<D> | PresencePatch<P> | PresenceSnapshot<P>>;
|
|
215
|
+
}): AsyncIterable<ContractEvent<D> | SessionCleared | PresencePatch<P> | PresenceSnapshot<P>>;
|
|
149
216
|
/**
|
|
150
217
|
* Validate against the contract's presence schemas, then broadcast.
|
|
151
218
|
* Never an append: no log row, no dispatch, no scheduler arm. `at`
|
|
@@ -162,25 +229,40 @@ type SessionPresence<D extends EventDefs, P extends PresenceDefs> = {
|
|
|
162
229
|
presence(): Promise<PresenceMap<P>>;
|
|
163
230
|
};
|
|
164
231
|
/** A handle on one instance of the machine. Creating it does no I/O. */
|
|
165
|
-
type Session<D extends EventDefs, Append = SessionAppend<D>, P extends PresenceDefs = Record<never, never
|
|
232
|
+
type Session<D extends EventDefs, Append = SessionAppend<D>, P extends PresenceDefs = Record<never, never>, S = never> = WithPresence<P, SessionPresence<D, P>> & {
|
|
166
233
|
readonly id: string;
|
|
167
234
|
append: Append;
|
|
168
235
|
schedule: SessionSchedule<D>;
|
|
236
|
+
/**
|
|
237
|
+
* End the current lifetime: atomically append a clear marker, then
|
|
238
|
+
* delete the history below it. Indexes never restart.
|
|
239
|
+
*/
|
|
240
|
+
clear(options?: SessionClearOptions): Promise<SessionClearResult>;
|
|
169
241
|
history(options?: {
|
|
170
242
|
gte?: number;
|
|
171
243
|
lte?: number;
|
|
172
244
|
}): Promise<ContractEvent<D>[]>;
|
|
173
|
-
state
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
245
|
+
state: {
|
|
246
|
+
<T>(reducer: Reducer<D, T, Record<never, never>>, options?: StateOptions): Promise<{
|
|
247
|
+
state: T;
|
|
248
|
+
index: number;
|
|
249
|
+
clearIndex?: number;
|
|
250
|
+
}>;
|
|
251
|
+
} & ([S] extends [never] ? unknown : {
|
|
252
|
+
(): Promise<{
|
|
253
|
+
state: S;
|
|
254
|
+
index: number;
|
|
255
|
+
clearIndex?: number;
|
|
256
|
+
}>;
|
|
257
|
+
});
|
|
177
258
|
/**
|
|
178
259
|
* A live feed of this session's events, starting after `startAfter`
|
|
179
260
|
* (exclusive). Server-side only. `server.fetch` exposes it over SSE.
|
|
261
|
+
* A clear arrives as a `SessionCleared` marker.
|
|
180
262
|
*/
|
|
181
263
|
stream(opts?: {
|
|
182
264
|
startAfter?: number;
|
|
183
|
-
}): AsyncIterable<ContractEvent<D
|
|
265
|
+
}): AsyncIterable<ContractEvent<D> | SessionCleared>;
|
|
184
266
|
};
|
|
185
267
|
/**
|
|
186
268
|
* The public server shape scheduler handlers accept. It stays structural so
|
|
@@ -208,14 +290,14 @@ type A2Scheduler = {
|
|
|
208
290
|
schedule(task: SchedulerTask): Promise<void>;
|
|
209
291
|
handler(...servers: DrainableServer[]): (req: Request) => Promise<Response>;
|
|
210
292
|
};
|
|
211
|
-
type A2Server<D extends EventDefs, P extends PresenceDefs = Record<never, never
|
|
293
|
+
type A2Server<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined> = {
|
|
212
294
|
/** The contract this server implements. */
|
|
213
|
-
readonly contract: Contract<D, P>;
|
|
295
|
+
readonly contract: Contract<D, P, R>;
|
|
214
296
|
readonly fetch: {
|
|
215
297
|
(request: Request): Promise<Response>;
|
|
216
298
|
(request: Request, options: ServerFetchOptions<D, P>): Promise<Response>;
|
|
217
299
|
};
|
|
218
|
-
session(id: string): Session<D, SessionAppend<D>, P>;
|
|
300
|
+
session(id: string): Session<D, SessionAppend<D>, P, PublicState<R>> & SessionDeadLetters<D>;
|
|
219
301
|
/**
|
|
220
302
|
* Process every currently eligible event. `settled` means nothing
|
|
221
303
|
* actionable remains, including work blocked behind a dead letter.
|
|
@@ -230,6 +312,14 @@ type A2Server<D extends EventDefs, P extends PresenceDefs = Record<never, never>
|
|
|
230
312
|
* their transport envelope; application code normally uses `session.schedule`.
|
|
231
313
|
*/
|
|
232
314
|
declare function deliverSchedulerAppend(server: DrainableServer, task: SchedulerAppendTask): Promise<void>;
|
|
315
|
+
/**
|
|
316
|
+
* Deliver one authenticated scheduler clear: a conditional
|
|
317
|
+
* `clear({ ifLastIndex })` that resolves after its deletion finishes, so a
|
|
318
|
+
* provider retry resumes an interrupted deletion. Custom scheduler adapters
|
|
319
|
+
* call this after validating their transport envelope; application code uses
|
|
320
|
+
* `session.schedule.clear`.
|
|
321
|
+
*/
|
|
322
|
+
declare function deliverSchedulerClear(server: DrainableServer, task: SchedulerClearTask): Promise<void>;
|
|
233
323
|
/**
|
|
234
324
|
* Which events fire `ctx.signal` while a handler runs — the preemption
|
|
235
325
|
* channel for user cancellation. The array form matches by type; the
|
|
@@ -241,11 +331,11 @@ declare function deliverSchedulerAppend(server: DrainableServer, task: Scheduler
|
|
|
241
331
|
type AbortSpec<D extends EventDefs, K extends keyof D & string> = Array<keyof D & string> | { [T in keyof D & string]?: true | ((event: ContractEvent<D, T>, trigger: ContractEvent<D, K>, context: {
|
|
242
332
|
attempt: number;
|
|
243
333
|
}) => boolean); };
|
|
244
|
-
type HandlerEntry<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never
|
|
334
|
+
type HandlerEntry<D extends EventDefs, K extends keyof D & string = keyof D & string, P extends PresenceDefs = Record<never, never>, S = never> = Handler<D, K, P, S> | {
|
|
245
335
|
abortOn?: AbortSpec<D, K>;
|
|
246
336
|
/** Session-scoped FIFO key, resolved and persisted when the event lands. */
|
|
247
337
|
lane?: Lane<D, K>;
|
|
248
|
-
handler: Handler<D, K, P>;
|
|
338
|
+
handler: Handler<D, K, P, S>;
|
|
249
339
|
};
|
|
250
340
|
type HandlerFunction = (ctx: never) => Promise<unknown>;
|
|
251
341
|
declare function handler<H extends HandlerFunction | {
|
|
@@ -253,9 +343,9 @@ declare function handler<H extends HandlerFunction | {
|
|
|
253
343
|
}>(entry: H): H extends HandlerFunction ? {
|
|
254
344
|
handler: H;
|
|
255
345
|
} : H;
|
|
256
|
-
type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, never
|
|
346
|
+
type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined> = {
|
|
257
347
|
/** The contract this server implements (see `a2.contract`). */
|
|
258
|
-
contract: Contract<D, P>;
|
|
348
|
+
contract: Contract<D, P, R>;
|
|
259
349
|
/** Where events live. Defaults: sqlite in dev, memory in tests, required in prod. */
|
|
260
350
|
store?: A2Store;
|
|
261
351
|
/**
|
|
@@ -281,10 +371,10 @@ type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, n
|
|
|
281
371
|
* wasn't imported. Compose across files by spreading objects (note:
|
|
282
372
|
* a duplicate key under spread silently last-wins).
|
|
283
373
|
*/
|
|
284
|
-
handlers?: { [K in keyof D & string]?: HandlerEntry<D, K, P
|
|
374
|
+
handlers?: { [K in keyof D & string]?: HandlerEntry<D, K, P, PublicState<R>>; };
|
|
285
375
|
};
|
|
286
376
|
/** Implement a contract: bind its vocabulary to storage and reactions. */
|
|
287
|
-
declare function createServer<D extends EventDefs, P extends PresenceDefs = Record<never, never
|
|
377
|
+
declare function createServer<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined>(options: ServerOptions<D, P, R>): A2Server<D, P, R>;
|
|
288
378
|
//#endregion
|
|
289
|
-
export {
|
|
290
|
-
//# sourceMappingURL=server-
|
|
379
|
+
export { ScheduledEvent as A, A2Socket as B, SessionRedriveResult as C, deliverSchedulerAppend as D, createServer as E, A2Operation as F, A2PushEvent as I, A2PushPresence as L, SchedulerClearTask as M, SchedulerDrainTask as N, deliverSchedulerClear as O, SchedulerTask as P, ServerFetchOptions as R, SessionRedriveOptions as S, StateOptions as T, SessionClearOptions as _, DrainableServer as a, SessionDispatch as b, HandlerContext as c, LaneContext as d, ScheduleDelay as f, SessionAppend as g, Session as h, DeadLetter as i, SchedulerAppendTask as j, handler as k, HandlerEntry as l, ServerOptions as m, A2Server as n, Handler as o, ScheduleTiming as p, AbortSpec as r, HandlerAppend as s, A2Scheduler as t, Lane as u, SessionClearResult as v, SessionSchedule as w, SessionPresence as x, SessionDeadLetters as y, UpgradeWebSocket as z };
|
|
380
|
+
//# sourceMappingURL=server-En7cbi3v.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-En7cbi3v.d.ts","names":[],"sources":["../src/session-socket.ts","../src/server-fetch.ts","../src/scheduler-task.ts","../src/server.ts"],"mappings":";;;;;;;;;;;;KA2CY;EACV,KAAK;EACL,GAAG,kBAAkB,WAAW;EAChC,GAAG,gBAAgB;EACnB,GAAG,gBAAgB,WAAW;EAC9B,MAAM,eAAe;;;EAGrB;;;;KCjBG,mBAAmB,UAAU,oBACzB,wBAAwB;KAE5B,wBAAwB,UAAU,gBAAgB,YAClD,WAAW,2BAA0B;KAG9B,YAAY,UAAU,YAAY;WACnC,MAAM,mBAAmB;WACzB;WACA;;KAGC,eAAe,UAAU,eAAe;WACzC;WACA,QAAQ,wBAAwB;WAChC;WACA;;KAGC,YACV,UAAU,YAAY,WACtB,UAAU,eAAe;WAGZ;WACA;WACA;WACA;WACA;;WAGA;WACA;WACA;WACA;WACA;;WAGA;WACA;WACA,iBAAiB,YAAY;WAC7B,WAAW,eAAe;WAC1B;;KAGH,oBACV,SAAS,QAAQ,sBACd,WAAW,QAAQ;KAEZ,mBACV,UAAU,YAAY,WACtB,UAAU,eAAe;EAEzB,aAAa,WAAW,YAAY,GAAG,iBAAiB;EACxD,mBAAmB;;EAEnB;;;;;KC1FU;EACV;EACA;EACA;;;KAIU;EACV;EACA;EACA;EACA;;EAEA;;;KAIU;EACV;EACA;;EAEA;EACA;EACA;;EAEA;EACA,iBAAiB;;EAEjB;;;KAIU;EACV;EACA;;EAEA;EACA;EACA;;EAEA;;EAEA;;;KAIU,gBACV,qBAAqB,sBAAsB;;;KCuBxC,YAAY,uBAAuB,YAEpC;EAAY,oBAAoB;IAC9B;;KAiCM,eACV,UAAU,WACV,gBAAgB,mBAAmB,YACnC,UAAU,eAAe,sBACzB;;EAGA,OAAO,cAAc,GAAG;;EAExB;;EAEA,SAAS,QAAQ,GAAG,cAAc,IAAI,GAAG;;EAEzC,QAAQ;;KAGE,QACV,UAAU,WACV,gBAAgB,mBAAmB,YACnC,UAAU,eAAe,sBACzB,cAEA,KAAK,eAAe,GAAG,GAAG,GAAG,OAC1B,eAAe,YAAY,cAAc,YAAY;KAE9C,YACV,UAAU,WACV,gBAAgB,mBAAmB;EAEnC;EACA,OAAO,KAAK,cAAc,GAAG;IAA4B;;;KAG/C,KACV,UAAU,WACV,gBAAgB,mBAAmB,yBACtB,SAAS,YAAY,GAAG;KAE3B,gBAAgB,UAAU,iBACjC,QAAQ,YAAY,SACpB,QAAQ,cAAc;KAEf,cAAc,UAAU,aAAa,gBAAgB;;EAE/D,UAAU,gBAAgB;;KAGhB,cAAc,UAAU,cAClC,iBACG,QAAQ,YAAY,SACpB,QAAQ,cAAc;KAEf;KAEA;EACR,OAAO;EAAe;;EAAiB,IAAI;EAAM;;KAEzC,gBAAgB,UAAU;GAElC,cACA,QAAQ,mBACL,QAAQ,YAAY,OACtB;;;;;;EAMH,MACE,cACA,SAAS;IAAmB;MAC3B;;KAGO;EACV;;KAGU;;EAEV;;KAGU;EAAuB;EAAkB;;KAEzC;;EAEV;;KAGU;;EAEV;;;KAIU,WAAW,UAAU,aAAa,cAAc;EAC1D;;EAEA;;EAEA;;EAEA;EACA,UAAU;;;KAIA,mBAAmB,UAAU;;EAEvC,eAAe,QAAQ,WAAW;;;;;EAKlC,QACE,eACA,SAAS,wBACR,QAAQ;;;;;;;;;KAUD,gBAAgB,UAAU,WAAW,UAAU;;;;;;EAMzD,OAAO;IACL;IACA;MACE,cACF,cAAc,KAAK,iBAAiB,cAAc,KAAK,iBAAiB;;;;;;;EAQ1E,YAAY;IACV;IACA,QAAQ,cAAc;IACtB;IACA;MACE;;EAEJ,YAAY,QAAQ,YAAY;;;KAItB,QACV,UAAU,WACV,SAAS,cAAc,IACvB,UAAU,eAAe,sBACzB,aACE,aAAa,GAAG,gBAAgB,GAAG;WAC5B;EACT,QAAQ;EACR,UAAU,gBAAgB;;;;;EAK1B,MAAM,UAAU,sBAAsB,QAAQ;EAC9C,QAAQ;IAAY;IAAc;MAAiB,QAAQ,cAAc;EACzE;KACG,GACC,SAAS,QAAQ,GAAG,GAAG,uBACvB,UAAU,eACT;MAAU,OAAO;MAAG;MAAe;;QAClC;QAEI;MAAU,OAAO;MAAG;MAAe;;;;;;;;EAM7C,OAAO;IACL;MACE,cAAc,cAAc,KAAK;;;;;;;KAQ3B;WACD;aAAqB;;EAC9B,MAAM,oBAAoB;IAAU;;;;;;;;;;;;KAY1B;EACV,SAAS,MAAM,gBAAgB;EAC/B,WAAW,SAAS,qBAAqB,KAAK,YAAY,QAAQ;;KAGxD,SACV,UAAU,WACV,UAAU,eAAe,sBACzB,UAAU,kBAAkB,GAAG,iBAC7B,kBAAkB,GAAG;;WAGd,UAAU,SAAS,GAAG,GAAG;WACzB;KACN,SAAS,UAAU,QAAQ;KAC3B,SAAS,SAAS,SAAS,mBAAmB,GAAG,KAAK,QAAQ;;EAEjE,QACE,aACC,QAAQ,GAAG,cAAc,IAAI,GAAG,YAAY,MAAM,mBAAmB;;;;;EAKxE,MAAM,oBAAoB;IAAU;;;;;;;;iBAiBhB,uBACpB,QAAQ,iBACR,MAAM,sBACL;;;;;;;;iBAgCmB,sBACpB,QAAQ,iBACR,MAAM,qBACL;;;;;;;;;KAiCS,UAAU,UAAU,WAAW,gBAAgB,cACvD,YAAY,iBAET,WAAW,uBAGN,OAAO,cAAc,GAAG,IACxB,SAAS,cAAc,GAAG,IAC1B;EAAW;;KAIX,aACV,UAAU,WACV,gBAAgB,mBAAmB,YACnC,UAAU,eAAe,sBACzB,aAEE,QAAQ,GAAG,GAAG,GAAG;EAEf,UAAU,UAAU,GAAG;;EAEvB,OAAO,KAAK,GAAG;EACf,SAAS,QAAQ,GAAG,GAAG,GAAG;;KAG3B,mBAAmB,eAAe;iBAEvB,QACd,UAAU;EAAoB,SAAS;GACvC,OAAO,IAAI,UAAU;EAAoB,SAAS;IAAM;KAO9C,cACV,UAAU,WACV,UAAU,eAAe,sBACzB,UAAU,kBAAkB,GAAG,iBAC7B,kBAAkB,GAAG;;EAGvB,UAAU,SAAS,GAAG,GAAG;;EAEzB,QAAQ;;;;;;;EAOR,YAAY;;EAEZ,YAAY;;;;;;EAMZ;IAAa;;;;;;;;EAOb,cAAc,WAAW,cAAc,aAAa,GAAG,GAAG,GAAG,YAAY;;;iBAuO3D,aACd,UAAU,WACV,UAAU,eAAe,sBACzB,UAAU,kBAAkB,GAAG,iBAC7B,kBAAkB,GAAG,gBACvB,SAAS,cAAc,GAAG,GAAG,KAAK,SAAS,GAAG,GAAG"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-
|
|
3
|
-
import { A as
|
|
4
|
-
export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, type Contract, type ContractEvent, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, Handler, HandlerAppend, HandlerContext, HandlerEntry, type IdSource, Lane, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerDrainTask, type SchedulerTask, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionDispatch, SessionPresence, SessionSchedule, StateOptions, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, createServer, deliverSchedulerAppend, handler };
|
|
1
|
+
import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, s as Contract, u as EventDefs } from "./reducer-CqA59Q6U.js";
|
|
2
|
+
import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-Djdv0bnZ.js";
|
|
3
|
+
import { A as ScheduledEvent, B as A2Socket, C as SessionRedriveResult, D as deliverSchedulerAppend, E as createServer, F as A2Operation, I as A2PushEvent, L as A2PushPresence, M as SchedulerClearTask, N as SchedulerDrainTask, O as deliverSchedulerClear, P as SchedulerTask, R as ServerFetchOptions, S as SessionRedriveOptions, T as StateOptions, _ as SessionClearOptions, a as DrainableServer, b as SessionDispatch, c as HandlerContext, d as LaneContext, f as ScheduleDelay, g as SessionAppend, h as Session, i as DeadLetter, j as SchedulerAppendTask, k as handler, l as HandlerEntry, m as ServerOptions, n as A2Server, o as Handler, p as ScheduleTiming, r as AbortSpec, s as HandlerAppend, t as A2Scheduler, u as Lane, v as SessionClearResult, w as SessionSchedule, x as SessionPresence, y as SessionDeadLetters, z as UpgradeWebSocket } from "./server-En7cbi3v.js";
|
|
4
|
+
export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, type Contract, type ContractEvent, DeadLetter, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, Handler, HandlerAppend, HandlerContext, HandlerEntry, type IdSource, Lane, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerClearTask, type SchedulerDrainTask, type SchedulerTask, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionClearOptions, SessionClearResult, SessionDeadLetters, SessionDispatch, SessionPresence, SessionRedriveOptions, SessionRedriveResult, SessionSchedule, StateOptions, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, createServer, deliverSchedulerAppend, deliverSchedulerClear, handler };
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as deliverSchedulerAppend, r as
|
|
2
|
-
export { createServer, deliverSchedulerAppend, handler };
|
|
1
|
+
import { i as handler, n as deliverSchedulerAppend, r as deliverSchedulerClear, t as createServer } from "./server-Dw_k_7kO.js";
|
|
2
|
+
export { createServer, deliverSchedulerAppend, deliverSchedulerClear, handler };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { i as Event } from "./store-Djdv0bnZ.js";
|
|
2
|
+
//#region src/session-clear.d.ts
|
|
3
|
+
/** Reserved type of the marker a clear appends. */
|
|
4
|
+
declare const CLEAR_EVENT_TYPE = "a2.cleared";
|
|
5
|
+
/** The marker `session.stream()` yields where a clear ended a lifetime. */
|
|
6
|
+
type SessionCleared = Event & {
|
|
7
|
+
type: typeof CLEAR_EVENT_TYPE;
|
|
8
|
+
payload: null;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SessionCleared as t };
|
|
12
|
+
//# sourceMappingURL=session-clear-Bo-XTFEy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-clear-Bo-XTFEy.d.ts","names":[],"sources":["../src/session-clear.ts"],"mappings":";;;cAOa;;KAGD,iBAAiB;EAC3B,aAAa;EACb"}
|
|
@@ -10,6 +10,10 @@ var A2Error = class extends Error {
|
|
|
10
10
|
this.details = options?.details;
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
|
+
/** A handler write whose attempt no longer owns its triggering event. */
|
|
14
|
+
function supersededAttemptError(sessionId, cause) {
|
|
15
|
+
return new A2Error("SUPERSEDED_ATTEMPT", `attempt ${cause.attempt} no longer owns event ${cause.index} in session '${sessionId}'`);
|
|
16
|
+
}
|
|
13
17
|
/**
|
|
14
18
|
* Wrap an arbitrary thrown value as STORE_UNAVAILABLE, preserving the
|
|
15
19
|
* original as `cause`. A2Errors pass through untouched — they already
|
|
@@ -34,6 +38,17 @@ var NonRetriableError = class extends Error {
|
|
|
34
38
|
}
|
|
35
39
|
};
|
|
36
40
|
//#endregion
|
|
37
|
-
|
|
41
|
+
//#region src/session-clear.ts
|
|
42
|
+
/** Reserved type of the marker a clear appends. */
|
|
43
|
+
const CLEAR_EVENT_TYPE = "a2.cleared";
|
|
44
|
+
/** Accepts any stream item, including presence patches and snapshots. */
|
|
45
|
+
function isSessionCleared(item) {
|
|
46
|
+
return item.type === CLEAR_EVENT_TYPE;
|
|
47
|
+
}
|
|
48
|
+
function sessionClearedError(message) {
|
|
49
|
+
return new A2Error("SESSION_CLEARED", message);
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { NonRetriableError as a, A2Error as i, isSessionCleared as n, asStoreUnavailable as o, sessionClearedError as r, supersededAttemptError as s, CLEAR_EVENT_TYPE as t };
|
|
38
53
|
|
|
39
|
-
//# sourceMappingURL=
|
|
54
|
+
//# sourceMappingURL=session-clear-DGI4jTQ5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-clear-DGI4jTQ5.js","names":[],"sources":["../src/errors.ts","../src/session-clear.ts"],"sourcesContent":["export type A2ServerErrorCode =\n | 'INVALID_PAYLOAD' // schema validation failed — thrown before anything is written\n | 'FORBIDDEN' // external ingress was denied by server.fetch authorization\n | 'UNKNOWN_EVENT_TYPE' // event type not in the machine's `events` map\n | 'PARTIAL_DUPLICATE_BATCH' // batch mixed already-appended and fresh events\n | 'SUPERSEDED_ATTEMPT' // handler append from an attempt a recovery claim or a clear replaced\n | 'SESSION_CLEARED' // a read or call reached across the session's latest clear\n | 'CLAIM_EXPIRED' // ctx.signal abort reason: the attempt's lease lapsed without renewal\n | 'STORE_UNAVAILABLE' // store backend failure — retryable, nothing was written\n | 'STORE_NOT_CONFIGURED' // production boot with no `store` passed\n | 'UNKNOWN_PRESENCE_FIELD' // presence field not in the contract's `presence` map\n | 'PRESENCE_NOT_SUPPORTED' // contract declares presence but the store lacks the capability\n\nexport type A2ErrorCode =\n A2ServerErrorCode | 'TIMEOUT' | 'HTTP_ERROR' | 'CONNECTION_FAILED' | 'UNKNOWN'\n\nexport class A2Error extends Error {\n readonly code: A2ErrorCode\n /** e.g. the Standard Schema issues for INVALID_PAYLOAD */\n readonly details: unknown\n\n constructor(\n code: A2ErrorCode,\n message: string,\n options?: { details?: unknown; cause?: unknown },\n ) {\n super(\n message,\n options && 'cause' in options ? { cause: options.cause } : undefined,\n )\n this.name = 'A2Error'\n this.code = code\n this.details = options?.details\n }\n}\n\n/** A handler write whose attempt no longer owns its triggering event. */\nexport function supersededAttemptError(\n sessionId: string,\n cause: { index: number; attempt: number },\n): A2Error {\n return new A2Error(\n 'SUPERSEDED_ATTEMPT',\n `attempt ${cause.attempt} no longer owns event ${cause.index} in session '${sessionId}'`,\n )\n}\n\n/**\n * Wrap an arbitrary thrown value as STORE_UNAVAILABLE, preserving the\n * original as `cause`. A2Errors pass through untouched — they already\n * carry their own meaning.\n */\nexport function asStoreUnavailable(err: unknown): A2Error {\n if (err instanceof A2Error) return err\n return new A2Error('STORE_UNAVAILABLE', 'the store backend failed', {\n cause: err,\n })\n}\n\n/**\n * Throw from a handler to reject retrying: the failure is adjudicated\n * terminal immediately (dead-lettered on the first throw) instead of\n * consuming the ten-failure retry budget. For deterministic failures —\n * a guard that will refuse identically on every attempt — retrying is\n * waste and dead-lettering is the honest outcome. Matched by\n * `instanceof`, so subclasses carry domain meaning.\n */\nexport class NonRetriableError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = 'NonRetriableError'\n }\n}\n","import { A2Error } from './errors.ts'\nimport type { Event } from './store.ts'\n\n/** A2's own event types start with this; application contracts cannot. */\nexport const RESERVED_EVENT_PREFIX = 'a2.'\n\n/** Reserved type of the marker a clear appends. */\nexport const CLEAR_EVENT_TYPE = 'a2.cleared'\n\n/** The marker `session.stream()` yields where a clear ended a lifetime. */\nexport type SessionCleared = Event & {\n type: typeof CLEAR_EVENT_TYPE\n payload: null\n}\n\n/** Accepts any stream item, including presence patches and snapshots. */\nexport function isSessionCleared(item: object): item is SessionCleared {\n return (item as { type?: unknown }).type === CLEAR_EVENT_TYPE\n}\n\nexport function sessionClearedError(message: string): A2Error {\n return new A2Error('SESSION_CLEARED', message)\n}\n"],"mappings":";AAgBA,IAAa,UAAb,cAA6B,MAAM;CACjC;;CAEA;CAEA,YACE,MACA,SACA,SACA;EACA,MACE,SACA,WAAW,WAAW,UAAU,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA,CAC7D;EACA,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,UAAU,SAAS;CAC1B;AACF;;AAGA,SAAgB,uBACd,WACA,OACS;CACT,OAAO,IAAI,QACT,sBACA,WAAW,MAAM,QAAQ,wBAAwB,MAAM,MAAM,eAAe,UAAU,EACxF;AACF;;;;;;AAOA,SAAgB,mBAAmB,KAAuB;CACxD,IAAI,eAAe,SAAS,OAAO;CACnC,OAAO,IAAI,QAAQ,qBAAqB,4BAA4B,EAClE,OAAO,IACT,CAAC;AACH;;;;;;;;;AAUA,IAAa,oBAAb,cAAuC,MAAM;CAC3C,YAAY,SAAiB,SAA+B;EAC1D,MAAM,SAAS,OAAO;EACtB,KAAK,OAAO;CACd;AACF;;;;ACjEA,MAAa,mBAAmB;;AAShC,SAAgB,iBAAiB,MAAsC;CACrE,OAAQ,KAA4B,SAAS;AAC/C;AAEA,SAAgB,oBAAoB,SAA0B;CAC5D,OAAO,IAAI,QAAQ,mBAAmB,OAAO;AAC/C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { p as PresencePatch } from "./reducer-CqA59Q6U.js";
|
|
2
2
|
//#region src/store.d.ts
|
|
3
3
|
/** A stored event, as the public API exposes it. */
|
|
4
4
|
type Event = {
|
|
@@ -53,6 +53,8 @@ type StoredEvent = Event & {
|
|
|
53
53
|
lastError: string | null;
|
|
54
54
|
/** Adapter clock time recorded when dead-lettered; null otherwise. */
|
|
55
55
|
failedAt: Date | null;
|
|
56
|
+
/** Latest clear marker, on claimed events of a cleared session. */
|
|
57
|
+
clearIndex?: number;
|
|
56
58
|
};
|
|
57
59
|
/**
|
|
58
60
|
* One live presence value, as `A2Store.presence.read` returns it. The
|
|
@@ -80,6 +82,8 @@ type StoreStateRead = {
|
|
|
80
82
|
} | null;
|
|
81
83
|
/** Immutable events strictly after `snapshot.index`, or the full log on a miss. */
|
|
82
84
|
events: Event[];
|
|
85
|
+
/** Latest clear marker; omitted when the session was never cleared. */
|
|
86
|
+
clearIndex?: number;
|
|
83
87
|
};
|
|
84
88
|
type StoreSnapshotWrite = {
|
|
85
89
|
index: number;
|
|
@@ -144,6 +148,35 @@ type StoreAppendResult = {
|
|
|
144
148
|
/** Whether the session contains an event without a completion marker. */
|
|
145
149
|
hasPending: boolean;
|
|
146
150
|
};
|
|
151
|
+
type StoreClearOptions = {
|
|
152
|
+
sessionId: string;
|
|
153
|
+
ifLastIndex?: number;
|
|
154
|
+
/** The clearing handler's dispatch, fenced like a handler append. */
|
|
155
|
+
cause?: EventCause;
|
|
156
|
+
};
|
|
157
|
+
type StoreClearResult = {
|
|
158
|
+
cleared: boolean;
|
|
159
|
+
/** The head after the operation. */
|
|
160
|
+
index: number;
|
|
161
|
+
/** The latest clear marker after the operation, or 0. */
|
|
162
|
+
clearIndex: number;
|
|
163
|
+
};
|
|
164
|
+
type StoreReclaimResult = {
|
|
165
|
+
deleted: number;
|
|
166
|
+
done: boolean;
|
|
167
|
+
};
|
|
168
|
+
type StoreRedriveOptions = {
|
|
169
|
+
sessionId: string;
|
|
170
|
+
index: number;
|
|
171
|
+
/** `retry` clears the dead letter; `skip` settles it without a handler. */
|
|
172
|
+
action: "retry" | "skip";
|
|
173
|
+
};
|
|
174
|
+
type StoreRedriveResult = {
|
|
175
|
+
/** Whether the event was dead-lettered and this operation resolved it. */
|
|
176
|
+
redriven: boolean;
|
|
177
|
+
/** Whether the session contains an event without a completion marker. */
|
|
178
|
+
hasPending: boolean;
|
|
179
|
+
};
|
|
147
180
|
/**
|
|
148
181
|
* An injectable clock. Adapters take one so tests can drive claim
|
|
149
182
|
* expiry, failure timestamps, and (later) stuck-session detection
|
|
@@ -176,8 +209,45 @@ interface A2Store {
|
|
|
176
209
|
* `claimAvailable` — an unlocked read of the parent admits write skew.
|
|
177
210
|
* The idempotent-replay path runs first, so a batch whose ids all exist
|
|
178
211
|
* replays regardless of the current attempt.
|
|
212
|
+
*
|
|
213
|
+
* Clearing stores (a2-implementation.md §17.2) fence one level earlier:
|
|
214
|
+
* a `cause` at or below the latest clear marker throws
|
|
215
|
+
* `SUPERSEDED_ATTEMPT`, an `originIndex` there throws `SESSION_CLEARED`,
|
|
216
|
+
* and ids whose rows lie below the marker are free to reuse.
|
|
217
|
+
*/
|
|
218
|
+
append(sessionId: string, events: AppendEvent[], options?: {
|
|
219
|
+
originIndex?: number;
|
|
220
|
+
}): Promise<StoreAppendResult>;
|
|
221
|
+
/**
|
|
222
|
+
* Optional with `reclaim`. Serialized with `append`: checks
|
|
223
|
+
* `ifLastIndex` against the head and the latest marker, then appends a
|
|
224
|
+
* settled clear marker at the next index without touching existing
|
|
225
|
+
* rows. Afterwards every event at or below the marker is superseded.
|
|
226
|
+
*/
|
|
227
|
+
clear?(options: StoreClearOptions): Promise<StoreClearResult>;
|
|
228
|
+
/**
|
|
229
|
+
* Deletes one bounded batch of rows below the latest clear marker, with
|
|
230
|
+
* their bookkeeping, id records, and cached folds. `done` once nothing
|
|
231
|
+
* remains below it. Never waits on a lock that other operations hold.
|
|
232
|
+
*/
|
|
233
|
+
reclaim?(sessionId: string): Promise<StoreReclaimResult>;
|
|
234
|
+
/**
|
|
235
|
+
* Optional with `redrive`. The session's dead-lettered events above the
|
|
236
|
+
* latest clear marker, oldest first.
|
|
237
|
+
*/
|
|
238
|
+
deadLetters?(sessionId: string): Promise<StoredEvent[]>;
|
|
239
|
+
/**
|
|
240
|
+
* Optional with `deadLetters`. Atomically resolves one dead-lettered event
|
|
241
|
+
* above the latest clear marker; any other event is untouched and reports
|
|
242
|
+
* `redriven: false`. `retry` clears `failedAt` and `failureCount`, so the
|
|
243
|
+
* event is claimable again with a fresh failure budget, keeping its claim
|
|
244
|
+
* history and last failure. `skip` records `processedAt` with no
|
|
245
|
+
* `processedByAttempt` or `returnedEventIds` and exposes the next event in
|
|
246
|
+
* its lane. Both serialize with `claimAvailable` and the handler-append
|
|
247
|
+
* parent fence; `skip` also serializes with lane promotion in `append` and
|
|
248
|
+
* `completeAttempt`. `hasPending` is read in the same step.
|
|
179
249
|
*/
|
|
180
|
-
|
|
250
|
+
redrive?(options: StoreRedriveOptions): Promise<StoreRedriveResult>;
|
|
181
251
|
/** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */
|
|
182
252
|
read(sessionId: string, opts?: {
|
|
183
253
|
afterIndex?: number;
|
|
@@ -312,4 +382,4 @@ interface A2Store {
|
|
|
312
382
|
}
|
|
313
383
|
//#endregion
|
|
314
384
|
export { EventCause as a, PresenceRow as c, StoreStateRead as d, StoredEvent as f, Event as i, StoreAppendResult as l, AppendEvent as n, FailAttemptResult as o, Clock as r, IdSource as s, A2Store as t, StoreClaimAvailableResult as u };
|
|
315
|
-
//# sourceMappingURL=store-
|
|
385
|
+
//# sourceMappingURL=store-Djdv0bnZ.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-Djdv0bnZ.d.ts","names":[],"sources":["../src/store.ts"],"mappings":";;;KAaY;EACV;EACA;EACA;;EAEA;EACA;EACA,WAAW;;;KAID;EACV;EACA;;EAEA;;;;;;;KAQU,cAAc;;EAExB,OAAO;;EAEP;;EAEA,aAAa;;EAEb;;EAEA;;EAEA,gBAAgB;;EAEhB,eAAe;;EAEf;;EAEA;;EAEA,gBAAgB;;EAEhB;;EAEA,cAAc;;EAEd;;EAEA;;EAEA,UAAU;;EAEV;;;;;;;;;KAUU;EACV;EACA;EACA;EACA;EACA,IAAI;EACJ,WAAW;;;KAID;;EAEV;;EAEA;IAAY;IAAe;;;EAE3B,QAAQ;;EAER;;KAGU;EACV;EACA;;EAEA;;KAGU;EACV;EACA;EACA;;;KAGU;EACN;EAAoB,QAAQ;;EAC5B;EAAiB,SAAS;;EAC1B;;;KAGM;EACR;EAAsB,QAAQ;;EAAoB;;;KAG1C;;EAEV;;EAEA;;;KAIU;EACV;EACA;;;KAIU;EACV;EACA;;EAEA;;EAEA,QAAQ;;EAER;;EAEA;;;KAIU,gBAAgB;EAAgB;;;KAGhC;EACV,QAAQ;;EAER;;KAGU;EACV;EACA;;EAEA,QAAQ;;KAGE;EACV;;EAEA;;EAEA;;KAGU;EAAuB;EAAiB;;KAExC;EACV;EACA;;EAEA;;KAGU;;EAEV;;EAEA;;;;;;;KAQU;EACV,OAAO;;;KAIG;UAQK;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4Bf,OACE,mBACA,QAAQ,eACR;IAAY;MACX,QAAQ;;;;;;;EAQX,OAAO,SAAS,oBAAoB,QAAQ;;;;;;EAO5C,SAAS,oBAAoB,QAAQ;;;;;EAMrC,aAAa,oBAAoB,QAAQ;;;;;;;;;;;;EAazC,SAAS,SAAS,sBAAsB,QAAQ;;EAGhD,KACE,mBACA;IAAS;IAAqB;MAC7B,QAAQ;;EAGX,aACE,mBACA;IAAS;IAAqB;MAC7B,QAAQ;;;;;;;;EASX,eAAe;IACb;IACA;IACA;IACA;IACA;MACE,QAAQ;;;;;;;;;;EAWZ,YAAY;IACV;IACA;IACA;MAAmB;MAAe;;IAClC;IACA;MACE,QAAQ;;;;;;EAOZ,gBAAgB;IACd;IACA;IACA;IACA,QAAQ;MACN,QAAQ;;;;;;EAOZ,YAAY;IACV;IACA;IACA;IACA;IACA;MACE,QAAQ;;;;;;;;EASZ,UACE,mBACA,qBACA;IAAY;IAAuB;MAClC,QAAQ;;;;;;;;EASX,YACE,mBAAmB,yBACnB,sBACC,QAAQ;;;;;;;EAQX,aACE,mBACA,qBACA,oBAAoB,uBACnB;;;;;;;EAQH;;;;;;;;;IASE,IACE,YACA,qBACA,QAAQ,gCACR;MAAQ;MAAc,IAAI;MAAM;QAC/B;;IAGH,KAAK,aAAa,QAAQ;;;;;;IAO1B,WAAW,YAAY,UAAU,OAAO;;;;;;;;;EAU1C,OACE,mBACA;IAAS;MACR,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-N8PXxDAS.js","names":[],"sources":["../src/store.ts"],"sourcesContent":["/**\n * The A2Store interface — the storage contract every store backend\n * implements. See specs/a2-implementation.md §2–3.\n *\n * This is the whole storage contract: append, read, dispatch claims,\n * failure markers, snapshots, and the live stream. The scheduler\n * needs nothing extra — the armed queue message is its own state, and\n * the store is the only thing it consults.\n */\n\nimport type { PresencePatch } from './contract.ts'\n\n/** A stored event, as the public API exposes it. */\nexport type Event = {\n id: string\n type: string\n payload: unknown\n /** Position in the session's event log, from 1. */\n index: number\n sessionId: string\n createdAt: Date\n}\n\n/** The handler dispatch whose append first persisted a child event. */\nexport type EventCause = {\n index: number\n attempt: number\n /** Size of one named handler append, used to reject truncated retries. */\n batchSize?: number\n}\n\n/**\n * What the store persists: immutable event history, including its causal edge,\n * plus derived dispatch and failure bookkeeping. The bookkeeping is disposable;\n * the event and its cause are not.\n */\nexport type StoredEvent = Event & {\n /** Same-session handler dispatch that appended this event; null means root. */\n cause: EventCause | null\n /** Session-scoped serial execution key resolved when the event is appended. */\n lane: string | null\n /** Adapter clock time recorded by append settlement, completion, or manual skip; null while pending. */\n processedAt: Date | null\n /** Dispatch attempt that completed this event; null without dispatch or while pending. */\n processedByAttempt: number | null\n /** Exact ordered child ids atomically returned by the completing attempt. */\n returnedEventIds: string[] | null\n /** Adapter clock time recorded by the first durable dispatch claim. */\n firstClaimedAt: Date | null\n /** Adapter clock time recorded by the most recent durable dispatch claim. */\n lastClaimedAt: Date | null\n /** Durable dispatch claims, including claims abandoned by hard kills. */\n attemptCount: number\n /** Current dispatch holder; null when the event is not claimed. */\n claimHolder: string | null\n /** Adapter clock expiry for the current dispatch claim. */\n claimExpiresAt: Date | null\n /** Caught handler failures. This alone drives dead-lettering. */\n failureCount: number\n /** Adapter clock time recorded by the most recent caught handler failure. */\n lastFailedAt: Date | null\n /** Dispatch attempt that produced the most recent caught handler failure. */\n lastFailedAttempt: number | null\n /** The last handler failure, stringified. */\n lastError: string | null\n /** Adapter clock time recorded when dead-lettered; null otherwise. */\n failedAt: Date | null\n}\n\n/**\n * One live presence value, as `A2Store.presence.read` returns it. The\n * row is the LWW unit — one participant's one field. `at` is the\n * sender's stamp, the LWW comparator. `expiresAt` is the storage's\n * own clock at the applied set plus its `ttlMs` — never derived from\n * the sender stamp; a row is live strictly before it.\n */\nexport type PresenceRow = {\n participant: string\n field: string\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\n/** One consistent cache-plus-tail read for a reducer fold. */\nexport type StoreStateRead = {\n /** The current head checkpoint, even when an older historical snapshot is selected. */\n headIndex: number | null\n /** The greatest cached fold at or before the requested snapshot frontier. */\n snapshot: { index: number; state: unknown } | null\n /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */\n events: Event[]\n}\n\nexport type StoreSnapshotWrite = {\n index: number\n state: unknown\n /** Unfinished trigger events that durably retain this exact checkpoint. */\n pinEventIndexes?: readonly number[]\n}\n\nexport type StoreStateReadRequest = {\n sessionId: string\n throughIndex?: number\n snapshotThroughIndex?: number\n}\n/** The result of atomically claiming every currently eligible event. */\nexport type StoreClaimAvailableResult =\n | { outcome: 'claimed'; events: StoredEvent[] }\n | { outcome: 'busy'; retryAt: Date }\n | { outcome: 'settled' }\n\n/** A completion may lose to a newer claim or an earlier completion. */\nexport type CompleteAttemptResult =\n { outcome: 'completed'; events: StoredEvent[] } | { outcome: 'superseded' }\n\n/** The result of one claim-renewal heartbeat, both lists in append order. */\nexport type RenewClaimsResult = {\n /** Listed claims that remain owned by the holder. */\n renewed: number[]\n /** Listed claims whose event a newer attempt has durably taken. */\n superseded: number[]\n}\n\n/** The result of atomically recording a caught handler failure. */\nexport type FailAttemptResult = {\n outcome: 'failed' | 'dead_lettered' | 'superseded'\n failureCount: number\n}\n\n/** Input to `A2Store.append` — already validated by the machine. */\nexport type AppendEvent = {\n type: string\n payload: unknown\n /** Caller-supplied idempotency key; generated when absent. */\n id?: string\n /** Internal causal edge supplied atomically by handler `session.append`. */\n cause?: EventCause\n /** Session-scoped serial execution key resolved before persistence. */\n lane?: string\n /** Internal hint: settle this event in the append transaction; no handler is registered. */\n settled?: true\n}\n\n/** A handler-returned event with the deterministic id retries require. */\nexport type ReturnedEvent = AppendEvent & { id: string }\n\n/** The rows written by an append and the session's pending state. */\nexport type StoreAppendResult = {\n events: StoredEvent[]\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\n/**\n * An injectable clock. Adapters take one so tests can drive claim\n * expiry, failure timestamps, and (later) stuck-session detection\n * deterministically — against real storage, no mocking.\n */\nexport type Clock = {\n now(): Date\n}\n\n/** An injectable id source for generated event ids. */\nexport type IdSource = () => string\n\nexport const SYSTEM_CLOCK: Clock = {\n now: () => new Date(),\n}\n\nexport const RANDOM_IDS: IdSource = () => crypto.randomUUID()\n\nexport interface A2Store {\n /**\n * Accepts a batch; the batch is atomic — one transaction, consecutive\n * `index`es, all-or-nothing. The idempotency key covers the whole\n * operation, not each item: if *every* event's `id` already exists in\n * this session, this is a retry of a committed batch whose ack was\n * lost — return the existing rows as success. If only *some* ids\n * exist, the caller mixed an already-sent batch with fresh events —\n * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.\n * Events carrying `settled: true` get `processedAt` in this same atomic\n * operation, with no dispatch claim or `processedByAttempt`. The result's\n * `hasPending` reflects the whole session in the same atomic operation,\n * including older events and idempotent retries.\n *\n * An event carrying `cause` is a handler append, fenced by attempt\n * currency: accept it only while `cause.attempt` is still the parent\n * event's latest attempt and the parent is not dead-lettered; otherwise\n * throw `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is\n * part of this atomic operation and must serialize against a concurrent\n * `claimAvailable` — an unlocked read of the parent admits write skew.\n * The idempotent-replay path runs first, so a batch whose ids all exist\n * replays regardless of the current attempt.\n */\n append(sessionId: string, events: AppendEvent[]): Promise<StoreAppendResult>\n\n /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */\n read(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<StoredEvent[]>\n\n /** Public history without dispatch metadata; core falls back to read when absent. */\n readHistory?(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<Event[]>\n\n /**\n * Atomically claims every eligible pending event. Unlaned events are all\n * independently eligible. Within a lane, only the lowest-index unfinished\n * event is eligible. A live claim produces `busy` only when it is the sole\n * remaining obstacle to actionable work. Claimed events are returned in event-log\n * order. Excluded rows remain lane barriers.\n */\n claimAvailable(options: {\n sessionId: string\n holder: string\n ttlMs: number\n expiresAtMs?: number\n excludeIndexes?: readonly number[]\n }): Promise<StoreClaimAvailableResult>\n\n /**\n * Renews the listed live claims still owned by `holder`. Each listed claim\n * carries the attempt ordinal the holder owns. `renewed` lists the claims\n * that remain owned after the operation; `superseded` lists the claims\n * whose event's `attemptCount` has durably passed the listed attempt. An\n * expired claim no successor has taken appears in neither list — its\n * attempt may still complete (`completeAttempt` is the fence), so it is\n * not reported as lost. Renewal never revives an expired claim.\n */\n renewClaims(options: {\n sessionId: string\n holder: string\n claims: readonly { index: number; attempt: number }[]\n ttlMs: number\n expiresAtMs?: number\n }): Promise<RenewClaimsResult>\n\n /**\n * Atomically completes one current attempt and appends its returned events.\n * Retrying a committed completion with the same attempt and deterministic\n * child ids returns the existing children. A stale attempt never appends.\n */\n completeAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n events: ReturnedEvent[]\n }): Promise<CompleteAttemptResult>\n\n /**\n * Atomically records a caught failure for one claimed attempt. A stale\n * attempt cannot poison a processed event or a newer dispatch. Accepted\n * failures record the operation's clock time.\n */\n failAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n error: string\n maxFailures: number\n }): Promise<FailAttemptResult>\n\n /**\n * Reads a reducer snapshot and its event tail as one consistent adapter\n * operation. On a cache miss, `snapshot` is null and `events` is the full\n * log. The snapshot is untrusted; core may reject it and issue a full\n * `read()` when its state schema no longer accepts the cached value.\n * Operational failures propagate without falling back to a full-log read.\n */\n readState(\n sessionId: string,\n reducerName: string,\n options?: { throughIndex?: number; snapshotThroughIndex?: number },\n ): Promise<StoreStateRead>\n\n /**\n * Optional batched `readState` — one consistent snapshot-plus-tail read\n * per session id, aligned positionally with the input (duplicates\n * allowed). Each element has its own frontier; the batch makes no\n * cross-session consistency claim. Core falls back to parallel\n * `readState` calls when absent.\n */\n readStates?(\n requests: readonly StoreStateReadRequest[],\n reducerName: string,\n ): Promise<StoreStateRead[]>\n\n /**\n * Atomically writes disposable reducer checkpoints. The greatest index\n * advances the head cache. Older checkpoints survive only when at least one\n * listed trigger event is still unfinished; completion and dead-lettering\n * release that event's pins and collect unreferenced historical checkpoints.\n */\n putSnapshots(\n sessionId: string,\n reducerName: string,\n snapshots: readonly StoreSnapshotWrite[],\n ): Promise<void>\n\n /**\n * Optional ephemeral-plane capability (specs/a2-implementation.md\n * §15.1) — optional like snapshots are. Values arrive already\n * validated by core; adapters store them opaquely. Presence never\n * touches the event log: no index, no history row, no recovery arm.\n */\n presence?: {\n /**\n * Field-wise last-writer-wins merge of one participant's values:\n * a field whose existing row has a strictly newer `at` (the\n * sender's stamp) is left untouched; `null` deletes the row. Every\n * applied write refreshes that field's expiry to the storage's own\n * clock plus `ttlMs` — the sender stamp orders writes but never\n * anchors their lifetime.\n */\n set(\n ns: string,\n participant: string,\n values: Record<string, unknown | null>,\n meta: { seen: number; at: Date; ttlMs: number },\n ): Promise<void>\n\n /** The current map, pruned of rows at or past their `expiresAt`. */\n read(ns: string): Promise<PresenceRow[]>\n\n /**\n * Adapter-managed patch delivery. Without it, live feeds re-read\n * presence on their poll cadence. HTTP Redis uses adaptive polling\n * here when its endpoint does not support subscriptions.\n */\n subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void\n }\n\n /**\n * A live feed of one session's events, starting after `startAfter`\n * (exclusive). Transport is the backend's choice — in-process pub/sub,\n * polling, LISTEN/NOTIFY — callers never branch on which. The iterable\n * ends when the consumer calls `return()` (e.g. a disconnecting SSE\n * client) and must deliver events appended after subscription.\n */\n stream(\n sessionId: string,\n opts?: { startAfter?: number },\n ): AsyncIterable<Event>\n}\n"],"mappings":";AAuKA,MAAa,eAAsB,EACjC,2BAAW,IAAI,KAAK,EACtB;AAEA,MAAa,mBAA6B,OAAO,WAAW"}
|
|
1
|
+
{"version":3,"file":"store-N8PXxDAS.js","names":[],"sources":["../src/store.ts"],"sourcesContent":["/**\n * The A2Store interface — the storage contract every store backend\n * implements. See specs/a2-implementation.md §2–3.\n *\n * This is the whole storage contract: append, read, dispatch claims,\n * failure markers, snapshots, and the live stream. The scheduler\n * needs nothing extra — the armed queue message is its own state, and\n * the store is the only thing it consults.\n */\n\nimport type { PresencePatch } from './contract.ts'\n\n/** A stored event, as the public API exposes it. */\nexport type Event = {\n id: string\n type: string\n payload: unknown\n /** Position in the session's event log, from 1. */\n index: number\n sessionId: string\n createdAt: Date\n}\n\n/** The handler dispatch whose append first persisted a child event. */\nexport type EventCause = {\n index: number\n attempt: number\n /** Size of one named handler append, used to reject truncated retries. */\n batchSize?: number\n}\n\n/**\n * What the store persists: immutable event history, including its causal edge,\n * plus derived dispatch and failure bookkeeping. The bookkeeping is disposable;\n * the event and its cause are not.\n */\nexport type StoredEvent = Event & {\n /** Same-session handler dispatch that appended this event; null means root. */\n cause: EventCause | null\n /** Session-scoped serial execution key resolved when the event is appended. */\n lane: string | null\n /** Adapter clock time recorded by append settlement, completion, or manual skip; null while pending. */\n processedAt: Date | null\n /** Dispatch attempt that completed this event; null without dispatch or while pending. */\n processedByAttempt: number | null\n /** Exact ordered child ids atomically returned by the completing attempt. */\n returnedEventIds: string[] | null\n /** Adapter clock time recorded by the first durable dispatch claim. */\n firstClaimedAt: Date | null\n /** Adapter clock time recorded by the most recent durable dispatch claim. */\n lastClaimedAt: Date | null\n /** Durable dispatch claims, including claims abandoned by hard kills. */\n attemptCount: number\n /** Current dispatch holder; null when the event is not claimed. */\n claimHolder: string | null\n /** Adapter clock expiry for the current dispatch claim. */\n claimExpiresAt: Date | null\n /** Caught handler failures. This alone drives dead-lettering. */\n failureCount: number\n /** Adapter clock time recorded by the most recent caught handler failure. */\n lastFailedAt: Date | null\n /** Dispatch attempt that produced the most recent caught handler failure. */\n lastFailedAttempt: number | null\n /** The last handler failure, stringified. */\n lastError: string | null\n /** Adapter clock time recorded when dead-lettered; null otherwise. */\n failedAt: Date | null\n /** Latest clear marker, on claimed events of a cleared session. */\n clearIndex?: number\n}\n\n/**\n * One live presence value, as `A2Store.presence.read` returns it. The\n * row is the LWW unit — one participant's one field. `at` is the\n * sender's stamp, the LWW comparator. `expiresAt` is the storage's\n * own clock at the applied set plus its `ttlMs` — never derived from\n * the sender stamp; a row is live strictly before it.\n */\nexport type PresenceRow = {\n participant: string\n field: string\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\n/** One consistent cache-plus-tail read for a reducer fold. */\nexport type StoreStateRead = {\n /** The current head checkpoint, even when an older historical snapshot is selected. */\n headIndex: number | null\n /** The greatest cached fold at or before the requested snapshot frontier. */\n snapshot: { index: number; state: unknown } | null\n /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */\n events: Event[]\n /** Latest clear marker; omitted when the session was never cleared. */\n clearIndex?: number\n}\n\nexport type StoreSnapshotWrite = {\n index: number\n state: unknown\n /** Unfinished trigger events that durably retain this exact checkpoint. */\n pinEventIndexes?: readonly number[]\n}\n\nexport type StoreStateReadRequest = {\n sessionId: string\n throughIndex?: number\n snapshotThroughIndex?: number\n}\n/** The result of atomically claiming every currently eligible event. */\nexport type StoreClaimAvailableResult =\n | { outcome: 'claimed'; events: StoredEvent[] }\n | { outcome: 'busy'; retryAt: Date }\n | { outcome: 'settled' }\n\n/** A completion may lose to a newer claim or an earlier completion. */\nexport type CompleteAttemptResult =\n { outcome: 'completed'; events: StoredEvent[] } | { outcome: 'superseded' }\n\n/** The result of one claim-renewal heartbeat, both lists in append order. */\nexport type RenewClaimsResult = {\n /** Listed claims that remain owned by the holder. */\n renewed: number[]\n /** Listed claims whose event a newer attempt has durably taken. */\n superseded: number[]\n}\n\n/** The result of atomically recording a caught handler failure. */\nexport type FailAttemptResult = {\n outcome: 'failed' | 'dead_lettered' | 'superseded'\n failureCount: number\n}\n\n/** Input to `A2Store.append` — already validated by the machine. */\nexport type AppendEvent = {\n type: string\n payload: unknown\n /** Caller-supplied idempotency key; generated when absent. */\n id?: string\n /** Internal causal edge supplied atomically by handler `session.append`. */\n cause?: EventCause\n /** Session-scoped serial execution key resolved before persistence. */\n lane?: string\n /** Internal hint: settle this event in the append transaction; no handler is registered. */\n settled?: true\n}\n\n/** A handler-returned event with the deterministic id retries require. */\nexport type ReturnedEvent = AppendEvent & { id: string }\n\n/** The rows written by an append and the session's pending state. */\nexport type StoreAppendResult = {\n events: StoredEvent[]\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\nexport type StoreClearOptions = {\n sessionId: string\n ifLastIndex?: number\n /** The clearing handler's dispatch, fenced like a handler append. */\n cause?: EventCause\n}\n\nexport type StoreClearResult = {\n cleared: boolean\n /** The head after the operation. */\n index: number\n /** The latest clear marker after the operation, or 0. */\n clearIndex: number\n}\n\nexport type StoreReclaimResult = { deleted: number; done: boolean }\n\nexport type StoreRedriveOptions = {\n sessionId: string\n index: number\n /** `retry` clears the dead letter; `skip` settles it without a handler. */\n action: 'retry' | 'skip'\n}\n\nexport type StoreRedriveResult = {\n /** Whether the event was dead-lettered and this operation resolved it. */\n redriven: boolean\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\n/**\n * An injectable clock. Adapters take one so tests can drive claim\n * expiry, failure timestamps, and (later) stuck-session detection\n * deterministically — against real storage, no mocking.\n */\nexport type Clock = {\n now(): Date\n}\n\n/** An injectable id source for generated event ids. */\nexport type IdSource = () => string\n\nexport const SYSTEM_CLOCK: Clock = {\n now: () => new Date(),\n}\n\nexport const RANDOM_IDS: IdSource = () => crypto.randomUUID()\n\nexport interface A2Store {\n /**\n * Accepts a batch; the batch is atomic — one transaction, consecutive\n * `index`es, all-or-nothing. The idempotency key covers the whole\n * operation, not each item: if *every* event's `id` already exists in\n * this session, this is a retry of a committed batch whose ack was\n * lost — return the existing rows as success. If only *some* ids\n * exist, the caller mixed an already-sent batch with fresh events —\n * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.\n * Events carrying `settled: true` get `processedAt` in this same atomic\n * operation, with no dispatch claim or `processedByAttempt`. The result's\n * `hasPending` reflects the whole session in the same atomic operation,\n * including older events and idempotent retries.\n *\n * An event carrying `cause` is a handler append, fenced by attempt\n * currency: accept it only while `cause.attempt` is still the parent\n * event's latest attempt and the parent is not dead-lettered; otherwise\n * throw `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is\n * part of this atomic operation and must serialize against a concurrent\n * `claimAvailable` — an unlocked read of the parent admits write skew.\n * The idempotent-replay path runs first, so a batch whose ids all exist\n * replays regardless of the current attempt.\n *\n * Clearing stores (a2-implementation.md §17.2) fence one level earlier:\n * a `cause` at or below the latest clear marker throws\n * `SUPERSEDED_ATTEMPT`, an `originIndex` there throws `SESSION_CLEARED`,\n * and ids whose rows lie below the marker are free to reuse.\n */\n append(\n sessionId: string,\n events: AppendEvent[],\n options?: { originIndex?: number },\n ): Promise<StoreAppendResult>\n\n /**\n * Optional with `reclaim`. Serialized with `append`: checks\n * `ifLastIndex` against the head and the latest marker, then appends a\n * settled clear marker at the next index without touching existing\n * rows. Afterwards every event at or below the marker is superseded.\n */\n clear?(options: StoreClearOptions): Promise<StoreClearResult>\n\n /**\n * Deletes one bounded batch of rows below the latest clear marker, with\n * their bookkeeping, id records, and cached folds. `done` once nothing\n * remains below it. Never waits on a lock that other operations hold.\n */\n reclaim?(sessionId: string): Promise<StoreReclaimResult>\n\n /**\n * Optional with `redrive`. The session's dead-lettered events above the\n * latest clear marker, oldest first.\n */\n deadLetters?(sessionId: string): Promise<StoredEvent[]>\n\n /**\n * Optional with `deadLetters`. Atomically resolves one dead-lettered event\n * above the latest clear marker; any other event is untouched and reports\n * `redriven: false`. `retry` clears `failedAt` and `failureCount`, so the\n * event is claimable again with a fresh failure budget, keeping its claim\n * history and last failure. `skip` records `processedAt` with no\n * `processedByAttempt` or `returnedEventIds` and exposes the next event in\n * its lane. Both serialize with `claimAvailable` and the handler-append\n * parent fence; `skip` also serializes with lane promotion in `append` and\n * `completeAttempt`. `hasPending` is read in the same step.\n */\n redrive?(options: StoreRedriveOptions): Promise<StoreRedriveResult>\n\n /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */\n read(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<StoredEvent[]>\n\n /** Public history without dispatch metadata; core falls back to read when absent. */\n readHistory?(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<Event[]>\n\n /**\n * Atomically claims every eligible pending event. Unlaned events are all\n * independently eligible. Within a lane, only the lowest-index unfinished\n * event is eligible. A live claim produces `busy` only when it is the sole\n * remaining obstacle to actionable work. Claimed events are returned in event-log\n * order. Excluded rows remain lane barriers.\n */\n claimAvailable(options: {\n sessionId: string\n holder: string\n ttlMs: number\n expiresAtMs?: number\n excludeIndexes?: readonly number[]\n }): Promise<StoreClaimAvailableResult>\n\n /**\n * Renews the listed live claims still owned by `holder`. Each listed claim\n * carries the attempt ordinal the holder owns. `renewed` lists the claims\n * that remain owned after the operation; `superseded` lists the claims\n * whose event's `attemptCount` has durably passed the listed attempt. An\n * expired claim no successor has taken appears in neither list — its\n * attempt may still complete (`completeAttempt` is the fence), so it is\n * not reported as lost. Renewal never revives an expired claim.\n */\n renewClaims(options: {\n sessionId: string\n holder: string\n claims: readonly { index: number; attempt: number }[]\n ttlMs: number\n expiresAtMs?: number\n }): Promise<RenewClaimsResult>\n\n /**\n * Atomically completes one current attempt and appends its returned events.\n * Retrying a committed completion with the same attempt and deterministic\n * child ids returns the existing children. A stale attempt never appends.\n */\n completeAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n events: ReturnedEvent[]\n }): Promise<CompleteAttemptResult>\n\n /**\n * Atomically records a caught failure for one claimed attempt. A stale\n * attempt cannot poison a processed event or a newer dispatch. Accepted\n * failures record the operation's clock time.\n */\n failAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n error: string\n maxFailures: number\n }): Promise<FailAttemptResult>\n\n /**\n * Reads a reducer snapshot and its event tail as one consistent adapter\n * operation. On a cache miss, `snapshot` is null and `events` is the full\n * log. The snapshot is untrusted; core may reject it and issue a full\n * `read()` when its state schema no longer accepts the cached value.\n * Operational failures propagate without falling back to a full-log read.\n */\n readState(\n sessionId: string,\n reducerName: string,\n options?: { throughIndex?: number; snapshotThroughIndex?: number },\n ): Promise<StoreStateRead>\n\n /**\n * Optional batched `readState` — one consistent snapshot-plus-tail read\n * per session id, aligned positionally with the input (duplicates\n * allowed). Each element has its own frontier; the batch makes no\n * cross-session consistency claim. Core falls back to parallel\n * `readState` calls when absent.\n */\n readStates?(\n requests: readonly StoreStateReadRequest[],\n reducerName: string,\n ): Promise<StoreStateRead[]>\n\n /**\n * Atomically writes disposable reducer checkpoints. The greatest index\n * advances the head cache. Older checkpoints survive only when at least one\n * listed trigger event is still unfinished; completion and dead-lettering\n * release that event's pins and collect unreferenced historical checkpoints.\n */\n putSnapshots(\n sessionId: string,\n reducerName: string,\n snapshots: readonly StoreSnapshotWrite[],\n ): Promise<void>\n\n /**\n * Optional ephemeral-plane capability (specs/a2-implementation.md\n * §15.1) — optional like snapshots are. Values arrive already\n * validated by core; adapters store them opaquely. Presence never\n * touches the event log: no index, no history row, no recovery arm.\n */\n presence?: {\n /**\n * Field-wise last-writer-wins merge of one participant's values:\n * a field whose existing row has a strictly newer `at` (the\n * sender's stamp) is left untouched; `null` deletes the row. Every\n * applied write refreshes that field's expiry to the storage's own\n * clock plus `ttlMs` — the sender stamp orders writes but never\n * anchors their lifetime.\n */\n set(\n ns: string,\n participant: string,\n values: Record<string, unknown | null>,\n meta: { seen: number; at: Date; ttlMs: number },\n ): Promise<void>\n\n /** The current map, pruned of rows at or past their `expiresAt`. */\n read(ns: string): Promise<PresenceRow[]>\n\n /**\n * Adapter-managed patch delivery. Without it, live feeds re-read\n * presence on their poll cadence. HTTP Redis uses adaptive polling\n * here when its endpoint does not support subscriptions.\n */\n subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void\n }\n\n /**\n * A live feed of one session's events, starting after `startAfter`\n * (exclusive). Transport is the backend's choice — in-process pub/sub,\n * polling, LISTEN/NOTIFY — callers never branch on which. The iterable\n * ends when the consumer calls `return()` (e.g. a disconnecting SSE\n * client) and must deliver events appended after subscription.\n */\n stream(\n sessionId: string,\n opts?: { startAfter?: number },\n ): AsyncIterable<Event>\n}\n"],"mappings":";AA0MA,MAAa,eAAsB,EACjC,2BAAW,IAAI,KAAK,EACtB;AAEA,MAAa,mBAA6B,OAAO,WAAW"}
|
package/dist/store-memory.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as Clock, s as IdSource, t as A2Store } from "./store-
|
|
1
|
+
import { r as Clock, s as IdSource, t as A2Store } from "./store-Djdv0bnZ.js";
|
|
2
2
|
//#region src/store-memory.d.ts
|
|
3
3
|
type MemoryStoreOptions = {
|
|
4
4
|
/** Injectable clock — every stored timestamp comes from here. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-memory.d.ts","names":[],"sources":["../src/store-memory.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"store-memory.d.ts","names":[],"sources":["../src/store-memory.ts"],"mappings":";;KA2BY;;EAEV,QAAQ;;EAER,MAAM;;iBA6FQ,OAAO,UAAS,qBAA0B"}
|