experimental-a2 0.19.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +1 -1
- package/dist/{actor-C7b-1arn.d.ts → actor-HnGmrOZZ.d.ts} +5 -5
- package/dist/{actor-C7b-1arn.d.ts.map → actor-HnGmrOZZ.d.ts.map} +1 -1
- package/dist/actor-client.d.ts +1 -1
- package/dist/actor-client.js +2 -2
- package/dist/actor-react.d.ts +3 -3
- package/dist/actor-react.js +5 -5
- package/dist/{actor-shared-t7w8xIKP.js → actor-shared-DFET5q16.js} +3 -3
- package/dist/{actor-shared-t7w8xIKP.js.map → actor-shared-DFET5q16.js.map} +1 -1
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +54 -43
- package/dist/actor.js.map +1 -1
- package/dist/{ai-Cz3hqVhk.d.ts → ai-CvEnqVfo.d.ts} +8 -8
- package/dist/{ai-Cz3hqVhk.d.ts.map → ai-CvEnqVfo.d.ts.map} +1 -1
- package/dist/{ai-mMiWul1T.js → ai-CzE672Q3.js} +9 -9
- package/dist/ai-CzE672Q3.js.map +1 -0
- package/dist/ai-client.d.ts +2 -2
- package/dist/ai-client.js +2 -2
- package/dist/ai-fx.d.ts +1 -1
- package/dist/ai-fx.d.ts.map +1 -1
- package/dist/ai-fx.js +36 -9
- package/dist/ai-fx.js.map +1 -1
- package/dist/{ai-harness-CV6rXbB3.d.ts → ai-harness-Bfk-Lycn.d.ts} +2 -2
- package/dist/ai-harness-Bfk-Lycn.d.ts.map +1 -0
- package/dist/{ai-harness-BuuC-gJ3.js → ai-harness-dQeJaR1t.js} +17 -4
- package/dist/ai-harness-dQeJaR1t.js.map +1 -0
- package/dist/ai-pi.d.ts +1 -1
- package/dist/ai-pi.js +4 -4
- package/dist/ai-pi.js.map +1 -1
- package/dist/ai-react.d.ts +5 -5
- package/dist/ai-react.js +2 -2
- package/dist/ai-server.d.ts +14 -17
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +84 -75
- package/dist/ai-server.js.map +1 -1
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +2 -2
- package/dist/{client-BhHLoNKF.js → client-9IeTsiAs.js} +5 -5
- package/dist/{client-BhHLoNKF.js.map → client-9IeTsiAs.js.map} +1 -1
- package/dist/{client-h_DKFAjj.d.ts → client-CUMbS_38.d.ts} +3 -3
- package/dist/{client-h_DKFAjj.d.ts.map → client-CUMbS_38.d.ts.map} +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/{contract-BYKASlCV.js → contract-CWukt01d.js} +2 -2
- package/dist/contract-CWukt01d.js.map +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/{initial-snapshot-Bx-c0pDP.d.ts → initial-snapshot-D3Lve43o.d.ts} +4 -4
- package/dist/initial-snapshot-D3Lve43o.d.ts.map +1 -0
- package/dist/{internal-CscSY7K_.js → internal-Bc4PvfHk.js} +10 -3
- package/dist/internal-Bc4PvfHk.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/otel.js +1 -1
- package/dist/otel.js.map +1 -1
- package/dist/{react-BBXgHWFc.d.ts → react-BoHvC3v9.d.ts} +4 -4
- package/dist/{react-BBXgHWFc.d.ts.map → react-BoHvC3v9.d.ts.map} +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{reducer-CqA59Q6U.d.ts → reducer-CYPHsSmd.d.ts} +2 -2
- package/dist/{reducer-CqA59Q6U.d.ts.map → reducer-CYPHsSmd.d.ts.map} +1 -1
- package/dist/{reducer-BAXc8JyF.js → reducer-CjmvZSAb.js} +2 -2
- package/dist/{reducer-BAXc8JyF.js.map → reducer-CjmvZSAb.js.map} +1 -1
- package/dist/runtime-consumer-BWmht60z.js +12 -0
- package/dist/runtime-consumer-BWmht60z.js.map +1 -0
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.d.ts.map +1 -1
- package/dist/scheduler-qstash.js +7 -7
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/scheduler-task-X1SToDjP.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +2 -2
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +5 -4
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-DYAATFuT.d.ts → server-BshFZ0eL.d.ts} +108 -41
- package/dist/server-BshFZ0eL.d.ts.map +1 -0
- package/dist/{server-D-Y4pqwu.js → server-DvIB8kj5.js} +423 -135
- package/dist/server-DvIB8kj5.js.map +1 -0
- package/dist/server.browser.js +1 -1
- package/dist/server.browser.js.map +1 -1
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/{session-clear-C-QwTXV1.d.ts → session-clear-Bk_29eEw.d.ts} +2 -2
- package/dist/session-clear-Bk_29eEw.d.ts.map +1 -0
- package/dist/{session-clear-DGI4jTQ5.js → session-clear-wHd5GCpZ.js} +5 -4
- package/dist/session-clear-wHd5GCpZ.js.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-Z2qjw50n.d.ts +523 -0
- package/dist/store-Z2qjw50n.d.ts.map +1 -0
- package/dist/store-codec-DwrWlgQx.js +65 -0
- package/dist/store-codec-DwrWlgQx.js.map +1 -0
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.d.ts.map +1 -1
- package/dist/store-memory.js +393 -210
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-7WJV0YWP.js → store-polling-DYNyxCev.js} +2 -2
- package/dist/{store-polling-7WJV0YWP.js.map → store-polling-DYNyxCev.js.map} +1 -1
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +1595 -673
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-B1ixeqIS.js → store-presence-polling-CzQ0wdtM.js} +3 -3
- package/dist/{store-presence-polling-B1ixeqIS.js.map → store-presence-polling-CzQ0wdtM.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.js +4 -4
- package/dist/store-redis-notify-IiVdlYHc.js +2919 -0
- package/dist/store-redis-notify-IiVdlYHc.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.js +2 -2
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.d.ts.map +1 -1
- package/dist/store-sqlite.js +517 -287
- package/dist/store-sqlite.js.map +1 -1
- package/dist/{telemetry-Cyfqo6Qt.d.ts → telemetry-CWwsh-Gx.d.ts} +3 -3
- package/dist/telemetry-CWwsh-Gx.d.ts.map +1 -0
- package/dist/{wire-BKxH1vbP.js → wire-CZGqNZRx.js} +5 -4
- package/dist/wire-CZGqNZRx.js.map +1 -0
- package/docs/01-quickstart.mdx +28 -19
- package/docs/02-examples.mdx +1 -1
- package/docs/actors/01-introduction.mdx +9 -1
- package/docs/actors/02-concurrency.mdx +1 -1
- package/docs/actors/meta.ts +1 -1
- package/docs/agents/01-introduction.mdx +1 -1
- package/docs/agents/02-tools.mdx +13 -12
- package/docs/agents/03-conversations.mdx +31 -21
- package/docs/agents/04-harnesses.mdx +7 -3
- package/docs/agents/meta.ts +1 -1
- package/docs/client/03-presence.mdx +18 -14
- package/docs/client/meta.ts +1 -1
- package/docs/contract/01-events.mdx +2 -2
- package/docs/contract/02-state.mdx +18 -14
- package/docs/contract/03-sessions.mdx +32 -25
- package/docs/index.mdx +31 -26
- package/docs/reference/01-core.mdx +12 -12
- package/docs/reference/02-server.mdx +247 -192
- package/docs/reference/04-ai.mdx +29 -20
- package/docs/reference/05-telemetry.mdx +146 -0
- package/docs/reference/06-errors.mdx +24 -18
- package/docs/reference/meta.ts +1 -1
- package/docs/schedulers/01-overview.mdx +112 -0
- package/docs/schedulers/02-vercel-queues.mdx +87 -0
- package/docs/schedulers/03-qstash.mdx +123 -0
- package/docs/schedulers/meta.ts +1 -0
- package/docs/server/01-consumers.mdx +415 -0
- package/docs/server/02-timers.mdx +33 -23
- package/docs/server/03-cancellation.mdx +52 -44
- package/docs/server/04-routes.mdx +4 -1
- package/docs/server/05-sql-projections.mdx +391 -0
- package/docs/server/06-guarantees.mdx +60 -50
- package/docs/stores/01-overview.mdx +37 -0
- package/docs/stores/02-redis.mdx +57 -0
- package/docs/stores/03-redis-http.mdx +56 -0
- package/docs/stores/04-postgres.mdx +172 -0
- package/docs/stores/05-sqlite.mdx +36 -0
- package/docs/stores/06-memory.mdx +22 -0
- package/docs/stores/meta.ts +1 -0
- package/docs/upgrades/01-overview.mdx +30 -0
- package/docs/upgrades/79-0-21.mdx +165 -0
- package/docs/upgrades/80-0-20.mdx +43 -0
- package/docs/upgrades/81-0-19.mdx +33 -0
- package/docs/upgrades/82-0-18.mdx +33 -0
- package/docs/upgrades/83-0-17.mdx +69 -0
- package/docs/upgrades/meta.ts +3 -0
- package/examples/playground/DEPLOY.md +48 -11
- package/examples/playground/app/a0/apps/[appId]/route.ts +6 -10
- package/examples/playground/app/a0/chat.test.tsx +421 -330
- package/examples/playground/app/a0/sandbox-log.ts +17 -15
- package/examples/playground/app/a0/server.ts +4 -4
- package/examples/playground/app/a0/shell.tsx +1 -1
- package/examples/playground/app/a0/uploads/route.test.ts +59 -0
- package/examples/playground/app/a2slack/a2slack.css +1067 -0
- package/examples/playground/app/a2slack/c/[channel]/page.tsx +20 -0
- package/examples/playground/app/a2slack/consumers/agent.ts +63 -0
- package/examples/playground/app/a2slack/consumers/feed.ts +164 -0
- package/examples/playground/app/a2slack/consumers/notify.ts +116 -0
- package/examples/playground/app/a2slack/consumers/search.ts +37 -0
- package/examples/playground/app/a2slack/consumers/triage.ts +31 -0
- package/examples/playground/app/a2slack/consumers/welcome.ts +25 -0
- package/examples/playground/app/a2slack/db/a2.ts +206 -0
- package/examples/playground/app/a2slack/db/index.ts +73 -0
- package/examples/playground/app/a2slack/db/migrations/0000_extensions.sql +4 -0
- package/examples/playground/app/a2slack/db/migrations/0001_workspace.sql +74 -0
- package/examples/playground/app/a2slack/db/migrations/0002_a2.sql +215 -0
- package/examples/playground/app/a2slack/db/migrations/0003_a2_batch.sql +67 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0000_snapshot.json +18 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0001_snapshot.json +500 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0002_snapshot.json +1159 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0003_snapshot.json +1159 -0
- package/examples/playground/app/a2slack/db/migrations/meta/_journal.json +34 -0
- package/examples/playground/app/a2slack/db/queries.ts +263 -0
- package/examples/playground/app/a2slack/db/schema.ts +145 -0
- package/examples/playground/app/a2slack/drills/a2slack.drill.ts +708 -0
- package/examples/playground/app/a2slack/drills/harness.ts +244 -0
- package/examples/playground/app/a2slack/events/route.ts +36 -0
- package/examples/playground/app/a2slack/identity.ts +44 -0
- package/examples/playground/app/a2slack/inbox/route.ts +8 -0
- package/examples/playground/app/a2slack/lag/data/route.ts +8 -0
- package/examples/playground/app/a2slack/lag/page.tsx +101 -0
- package/examples/playground/app/a2slack/lag.ts +73 -0
- package/examples/playground/app/a2slack/layout.tsx +43 -0
- package/examples/playground/app/a2slack/messages/route.ts +17 -0
- package/examples/playground/app/a2slack/model.test.ts +208 -0
- package/examples/playground/app/a2slack/model.ts +369 -0
- package/examples/playground/app/a2slack/models.test.ts +72 -0
- package/examples/playground/app/a2slack/page.tsx +10 -0
- package/examples/playground/app/a2slack/scheduler/route.ts +5 -0
- package/examples/playground/app/a2slack/search/route.ts +40 -0
- package/examples/playground/app/a2slack/search-index.ts +108 -0
- package/examples/playground/app/a2slack/server.test.ts +315 -0
- package/examples/playground/app/a2slack/server.ts +55 -0
- package/examples/playground/app/a2slack/sessions.ts +50 -0
- package/examples/playground/app/a2slack/thread/route.ts +8 -0
- package/examples/playground/app/a2slack/ui/ChannelView.tsx +87 -0
- package/examples/playground/app/a2slack/ui/Composer.tsx +117 -0
- package/examples/playground/app/a2slack/ui/DotsShadow.tsx +42 -0
- package/examples/playground/app/a2slack/ui/Feed.tsx +157 -0
- package/examples/playground/app/a2slack/ui/InboxContext.tsx +63 -0
- package/examples/playground/app/a2slack/ui/InboxView.tsx +82 -0
- package/examples/playground/app/a2slack/ui/Menu.tsx +128 -0
- package/examples/playground/app/a2slack/ui/MessageRow.tsx +314 -0
- package/examples/playground/app/a2slack/ui/NameGate.tsx +35 -0
- package/examples/playground/app/a2slack/ui/SearchContext.tsx +146 -0
- package/examples/playground/app/a2slack/ui/SearchResults.tsx +97 -0
- package/examples/playground/app/a2slack/ui/Shell.tsx +34 -0
- package/examples/playground/app/a2slack/ui/Sidebar.tsx +199 -0
- package/examples/playground/app/a2slack/ui/ThreadPanel.tsx +134 -0
- package/examples/playground/app/a2slack/ui/useInbox.ts +71 -0
- package/examples/playground/app/agent/[agentId]/agent-queue.test.tsx +116 -90
- package/examples/playground/app/agent/[agentId]/compaction-panel.test.tsx +107 -76
- package/examples/playground/app/agent/ingress.test.ts +41 -17
- package/examples/playground/app/agent/model-input.test.tsx +92 -43
- package/examples/playground/app/agent/server.ts +3 -3
- package/examples/playground/app/chat/[chatId]/agent-stream-drawer.test.tsx +2 -2
- package/examples/playground/app/chat/[chatId]/chat-client.tsx +1 -1
- package/examples/playground/app/chat/server.test.ts +38 -65
- package/examples/playground/app/chat/server.ts +45 -35
- package/examples/playground/app/components/activity-history.test.tsx +60 -18
- package/examples/playground/app/components/demo-icons.tsx +7 -0
- package/examples/playground/app/components/demos.tsx +7 -0
- package/examples/playground/app/components/fast-link.test.tsx +3 -5
- package/examples/playground/app/initial-state.test.tsx +86 -45
- package/examples/playground/app/orders/[orderId]/order-client.tsx +2 -2
- package/examples/playground/app/orders/page.tsx +1 -1
- package/examples/playground/app/orders/server.ts +49 -30
- package/examples/playground/app/recovery/[recoveryId]/recovery-client.tsx +14 -15
- package/examples/playground/app/recovery/page.tsx +4 -4
- package/examples/playground/app/recovery/server.ts +23 -32
- package/examples/playground/drizzle.config.ts +14 -0
- package/examples/playground/next.config.ts +6 -1
- package/examples/playground/package.json +13 -1
- package/examples/playground/scripts/migrate.mjs +31 -0
- package/examples/playground/test/agent.ts +35 -0
- package/examples/playground/test/model.ts +149 -0
- package/examples/playground/test/serve.ts +184 -0
- package/examples/playground/test/server-only.ts +1 -0
- package/examples/playground/vercel.json +9 -0
- package/examples/playground/vitest.config.ts +27 -0
- package/examples/playground/vitest.drills.config.ts +32 -0
- package/package.json +7 -2
- package/sql/postgres/drizzle-schema.ts +206 -0
- package/sql/postgres/notifications.sql +24 -0
- package/sql/postgres/schema.sql +276 -0
- package/src/actor.ts +101 -71
- package/src/ai-agent.ts +154 -115
- package/src/ai-control-server.ts +8 -8
- package/src/ai-fx.ts +41 -9
- package/src/ai-harness.ts +28 -2
- package/src/ai-pi.ts +2 -2
- package/src/ai-server.ts +2 -2
- package/src/ai.ts +7 -7
- package/src/contract.ts +1 -1
- package/src/deterministic-id.ts +26 -3
- package/src/errors.ts +9 -6
- package/src/idempotent-replay.ts +0 -1
- package/src/index.ts +1 -1
- package/src/internal.ts +17 -6
- package/src/otel.ts +1 -1
- package/src/postgres-notifications.ts +0 -22
- package/src/postgres-resources.ts +6 -9
- package/src/postgres-schema.ts +121 -0
- package/src/push-envelope.ts +20 -0
- package/src/runtime-consumer.ts +10 -0
- package/src/scheduler-qstash.ts +12 -5
- package/src/scheduler-task.ts +2 -2
- package/src/scheduler-vercel.ts +10 -4
- package/src/server.browser.ts +1 -1
- package/src/server.ts +839 -238
- package/src/session-socket.ts +1 -1
- package/src/store-codec.ts +66 -0
- package/src/store-memory.ts +581 -255
- package/src/store-postgres.ts +1984 -943
- package/src/store-redis-core.ts +1624 -1152
- package/src/store-redis-notify.ts +2 -0
- package/src/store-sqlite.ts +891 -486
- package/src/store.ts +227 -97
- package/src/telemetry.ts +2 -1
- package/src/wire.ts +1 -0
- package/dist/ai-harness-BuuC-gJ3.js.map +0 -1
- package/dist/ai-harness-CV6rXbB3.d.ts.map +0 -1
- package/dist/ai-mMiWul1T.js.map +0 -1
- package/dist/contract-BYKASlCV.js.map +0 -1
- package/dist/idempotent-replay-JdgMQRRm.js +0 -21
- package/dist/idempotent-replay-JdgMQRRm.js.map +0 -1
- package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +0 -1
- package/dist/internal-CscSY7K_.js.map +0 -1
- package/dist/server-D-Y4pqwu.js.map +0 -1
- package/dist/server-DYAATFuT.d.ts.map +0 -1
- package/dist/session-clear-C-QwTXV1.d.ts.map +0 -1
- package/dist/session-clear-DGI4jTQ5.js.map +0 -1
- package/dist/store-CyLUy86v.d.ts +0 -404
- package/dist/store-CyLUy86v.d.ts.map +0 -1
- package/dist/store-codec-DTG0Ftek.js +0 -10
- package/dist/store-codec-DTG0Ftek.js.map +0 -1
- package/dist/store-redis-notify-CM0AfLY0.js +0 -2544
- package/dist/store-redis-notify-CM0AfLY0.js.map +0 -1
- package/dist/telemetry-Cyfqo6Qt.d.ts.map +0 -1
- package/dist/wire-BKxH1vbP.js.map +0 -1
- package/docs/reference/05-adapters.mdx +0 -351
- package/docs/server/01-handlers.mdx +0 -200
- package/docs/server/05-production.mdx +0 -323
package/dist/actor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor.js","names":["createContract"],"sources":["../src/actor.ts"],"sourcesContent":["/**\n * experimental-a2/actor — durable actors over the log. Server-only\n * (handlers are server code); the browser condition resolves to a\n * throwing stub, and the browser surfaces are experimental-a2/actor/client\n * and experimental-a2/actor/react.\n *\n * An actor is defined over a protocol — its state shape and event\n * vocabulary, as types — and one complete `handlers` bag:\n *\n * ```ts\n * interface Counter {\n * state: { count: number }\n * events: { increment: object; add: { by: number } }\n * }\n * const counter = actor<Counter>({\n * name: 'counter',\n * state: { count: 0 },\n * handlers: {\n * increment: (ctx) => {\n * ctx.state.count++\n * },\n * add: (ctx, input) => {\n * ctx.state.count += input.by\n * },\n * },\n * })\n * ```\n *\n * Handlers are serial by default: one at a time per instance (a lane —\n * the state's write lock), `ctx.state` a mutable draft committed\n * atomically with completion. A handler holding slow I/O opts out of\n * the lane with `{ concurrent: true, handle }`: it runs in parallel,\n * reads state as a snapshot, and mutates by sending events whose\n * serial handlers decide against fresh state. `ctx.send.eventName(...)`\n * is typed by the protocol and buffered — committed atomically with\n * the handler's completion, so a reserve and its trigger can never\n * half-happen.\n *\n * A thrown `NonRetriableError` is an answer (settled, delivered to a\n * waiting caller); any other error retries like every A2 handler\n * failure; a crash re-runs against the same pre-state. Everything\n * compiles to contract + reducer + laned handlers + returned events —\n * no new store operations, no new wire.\n */\n\n// oxlint-disable no-await-in-loop -- a call awaits its answer: drain, read\n// the tail, repeat until the message settles. Sequential by nature.\n\nimport {\n ACTOR_FAILED_EVENT,\n ACTOR_LANE,\n ACTOR_STATE_EVENT,\n ActorRefusedError,\n actorFailedSchema,\n actorReducer,\n actorStateSchema,\n isJsonTree,\n openPresenceDefs,\n} from './actor-shared.ts'\nimport type {\n ActorClientEventDefs,\n ActorConcurrentContext,\n ActorContext,\n ActorFailedPayload,\n ActorPresenceOf,\n ActorProtocol,\n ActorScheduleOptions,\n ActorScheduleSend,\n ActorSend,\n ActorStatePayload,\n} from './actor-shared.ts'\nimport { parsePresenceSibling } from './push-envelope.ts'\nimport type { ParsedPushPresence } from './push-envelope.ts'\nimport { internalContract as createContract } from './contract.ts'\nimport type { PresencePatch, PresenceSnapshot } from './contract.ts'\nimport type { Contract, EventDefs } from './contract.ts'\nimport type { Reducer } from './reducer.ts'\nimport { A2Error, NonRetriableError } from './errors.ts'\nimport { serverInternals } from './internal.ts'\nimport { createServer } from './server.ts'\nimport { setServerFetchHooks } from './server-fetch.ts'\nimport { sseResponse } from './sse.ts'\nimport { isSessionCleared, sessionClearedError } from './session-clear.ts'\nimport type { SessionCleared } from './session-clear.ts'\nimport type { A2Scheduler, A2Server, HandlerEntry, Session } from './server.ts'\nimport type { A2Store } from './store.ts'\nimport type { StandardSchemaV1 } from './standard-schema.ts'\nimport type { A2Telemetry } from './telemetry.ts'\n\nexport type {\n ActorConcurrentContext,\n ActorContext,\n ActorPresenceMap,\n ActorPresenceOf,\n ActorPresenceValues,\n ActorProtocol,\n ActorScheduleOptions,\n ActorScheduleSend,\n ActorSend,\n} from './actor-shared.ts'\nexport { ActorRefusedError } from './actor-shared.ts'\n\n/**\n * One event's handler: ordinary server code. Serial by default — read\n * `ctx.state`, perform I/O, mutate `ctx.state`, one atomic commit at\n * return. `{ concurrent: true, handle }` opts the handler out of the\n * lane for slow I/O: state becomes a snapshot read and mutations\n * happen by sending events. The input is typed by the protocol; the\n * wire hands handlers parsed JSON, so a wire-exposed event guards its\n * input in its first line (`schema.parse(input)` if you like schemas —\n * userland either way).\n */\nexport type ActorHandler<D extends ActorProtocol, K extends keyof D['events']> =\n | ((ctx: ActorContext<D>, input: D['events'][K]) => void | Promise<void>)\n | {\n concurrent: true\n handle: (\n ctx: ActorConcurrentContext<D>,\n input: D['events'][K],\n ) => void | Promise<void>\n }\n\n/**\n * Mark a handler concurrent — off the lane, in parallel with the lane\n * and with other concurrent handlers, `ctx.state()` a snapshot read.\n * Sugar for the structural `{ concurrent: true, handle }` form:\n *\n * ```ts\n * handlers: {\n * transfer: concurrent(async (ctx, input) => {\n * await bank.transfer(input, { idempotencyKey: input.ref })\n * ctx.send.settle({ ref: input.ref })\n * }),\n * }\n * ```\n */\nexport function concurrent<Ctx, I>(\n handle: (ctx: Ctx, input: I) => void | Promise<void>,\n): { concurrent: true; handle: (ctx: Ctx, input: I) => void | Promise<void> } {\n return { concurrent: true, handle }\n}\n\nexport type ActorOptions<D extends ActorProtocol> = {\n /** Identity — prefixes storage keys; one contract per actor definition. */\n name: string\n /** The initial state — checked against the protocol, a plain JSON tree. */\n state: D['state']\n /**\n * One handler per declared event — completeness and payload shapes\n * are compile-checked against the protocol.\n */\n handlers: { [K in keyof D['events']]: ActorHandler<D, K> }\n store?: A2Store\n scheduler?: A2Scheduler\n telemetry?: A2Telemetry\n} & ([ActorPresenceOf<D>] extends [never]\n ? { presence?: never }\n : {\n /**\n * The wire bit for the protocol's `presence` vocabulary — types\n * erase, so the runtime needs one value to arm the presence\n * lanes (frames on GET, envelopes on POST). Required exactly\n * when the protocol declares `presence`; the vocabulary itself\n * is typed there. Values are validated to the JSON floor and\n * pass through `authorize` as `{ type: 'presence' }` operations;\n * meaning stays with your renderers — treat values as user\n * input.\n */\n presence: true\n })\n\n/**\n * One HTTP operation `handle.fetch` is about to serve — the actor\n * mirror of core's `A2Operation`. `authorize` sees it before any\n * read, write, or subscription; returning `false` answers 403.\n */\nexport type ActorOperation =\n | { readonly type: 'state'; readonly id: string }\n | {\n readonly type: 'stream'\n readonly id: string\n readonly startAfter: number\n }\n | {\n readonly type: 'call'\n readonly id: string\n readonly event: string\n readonly input: unknown\n readonly messageId?: string\n }\n | {\n readonly type: 'presence'\n readonly id: string\n readonly participant: string\n readonly values: Readonly<Record<string, unknown>>\n }\n\nexport type ActorFetchOptions<D extends ActorProtocol> = {\n /** Per-operation policy — authentication happened in your route. */\n authorize?: (operation: ActorOperation) => boolean | Promise<boolean>\n /**\n * Request-time projection: what this mount's audience sees. Applied\n * to every state frame on the stream AND to call answers (the two\n * untrusted lanes must agree, or the call lane leaks what the\n * stream hides). The definition stays audience-agnostic — different\n * routes project the same actor differently, and per-viewer views\n * are just closures over the route's auth. Output is held to the\n * JSON-tree floor like everything else. Transport-agnostic: applied\n * at frame emission, so any wire the door speaks emits projected\n * frames. Absent, the full state ships (the trusted default).\n */\n view?: (state: D['state']) => unknown\n}\n\nexport type ActorSendOptions = {\n /** Explicit message id — makes retries of this send idempotent. */\n id?: string\n}\n\nexport type ActorCallOptions = ActorSendOptions & {\n /** How long to await the answer before rejecting the wait (default 30s). */\n timeoutMs?: number\n}\n\nexport type ActorCallResult<S> = {\n /** The actor's state after this message was processed. */\n state: S\n /** Log index of the state commit that answered this message. */\n index: number\n /**\n * The clear marker this state's lifetime began at, once the actor has been\n * cleared. For a call answer it is the lifetime the handler read.\n */\n clearIndex?: number\n}\n\ntype CallMethod<\n D extends ActorProtocol,\n K extends keyof D['events'],\n> = {} extends D['events'][K]\n ? (\n input?: D['events'][K],\n options?: ActorCallOptions,\n ) => Promise<ActorCallResult<D['state']>>\n : (\n input: D['events'][K],\n options?: ActorCallOptions,\n ) => Promise<ActorCallResult<D['state']>>\n\ntype SendMethod<\n D extends ActorProtocol,\n K extends keyof D['events'],\n> = {} extends D['events'][K]\n ? (\n input?: D['events'][K],\n options?: ActorSendOptions,\n ) => Promise<{ id: string; index: number }>\n : (\n input: D['events'][K],\n options?: ActorSendOptions,\n ) => Promise<{ id: string; index: number }>\n\n/** One instance: typed calls and sends, reads, the managed door, the escape hatch. */\nexport type ActorHandle<D extends ActorProtocol> = {\n readonly id: string\n /**\n * Send the event and await its answer: the state after the handler\n * ran, or a rejection with `ActorRefusedError`. A clear before the call\n * receives its answer rejects with `A2Error('SESSION_CLEARED')`. Serial\n * events only — concurrent handlers produce no answer to await; `send`\n * them.\n */\n readonly call: { readonly [K in keyof D['events']]: CallMethod<D, K> }\n /** Cast: validate, append the event durably, return without waiting. */\n readonly send: { readonly [K in keyof D['events']]: SendMethod<D, K> }\n /** Snapshot read — never queues behind pending messages. */\n readonly state: () => Promise<ActorCallResult<D['state']>>\n /**\n * The managed door — the actor mirror of `server.fetch`, bound to\n * this instance. GET streams the state plane (`a2.actor.state`\n * commits and clear resets, `?index` resume, heartbeat, deadline\n * rotation); POST is the call lane `createActorClient` speaks\n * (`{ event, input, messageId? }` → the answer, 409 for a refusal,\n * 410 for a call cleared before its answer). Your route\n * authenticates and picks the instance; `authorize` sees every\n * operation. Custom endpoints are route code around this call.\n */\n readonly fetch: (\n request: Request,\n options?: ActorFetchOptions<D>,\n ) => Promise<Response>\n /** Escape hatch: the raw A2 session (history, stream, schedule). */\n readonly session: Session<EventDefs>\n}\n\nexport type ActorDefinition<D extends ActorProtocol> = {\n readonly name: string\n /**\n * Type-only carrier of the protocol, so clients deriving from\n * `typeof def` can see the vocabularies (`experimental-a2/actor/react`\n * types `presence` from it). Never a runtime value.\n */\n readonly protocol?: D\n /** The assembled contract — declared events plus the reserved a2.actor.* pair. */\n readonly contract: Contract<EventDefs>\n /** The underlying A2 server — `server.fetch` mounts the full session wire. */\n readonly server: A2Server<EventDefs>\n /** The state fold over commits; a clear resets it to the initial state. */\n readonly reducer: Reducer<ActorClientEventDefs<D['state']>, D['state']>\n actor(id: string): ActorHandle<D>\n}\n\n// Object-mechanics names, not surface names: events live in their own\n// bags, so nothing else is reserved.\nconst UNSAFE_EVENT_NAMES = new Set(['__proto__', 'constructor', 'prototype'])\n\nconst forbidden = (): Response =>\n Response.json({ error: 'the operation is not authorized' }, { status: 403 })\n\nconst CALL_TIMEOUT_MS = 30_000\nconst CALL_POLL_MS = 25\n\n/** Declared events accept any JSON tree; `undefined` normalizes to `{}`. */\nconst jsonInputSchema: StandardSchemaV1<unknown> = {\n '~standard': {\n version: 1,\n vendor: 'a2',\n validate(value) {\n if (value === undefined || value === null) return { value: {} }\n if (!isJsonTree(value)) {\n return {\n issues: [{ message: 'event input must be a plain JSON tree' }],\n }\n }\n return { value }\n },\n },\n}\n\nconst describeError = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms))\n\ntype NormalizedHandler<D extends ActorProtocol> =\n | {\n kind: 'serial'\n handle: (ctx: ActorContext<D>, input: unknown) => void | Promise<void>\n }\n | {\n kind: 'concurrent'\n handle: (\n ctx: ActorConcurrentContext<D>,\n input: unknown,\n ) => void | Promise<void>\n }\n\n/**\n * Define and serve an actor over its protocol: a named, durable\n * instance-per-id with serialized state handlers, concurrent I/O\n * handlers, and typed self-sends.\n */\nexport function actor<D extends ActorProtocol>(\n options: ActorOptions<D>,\n): ActorDefinition<D> {\n const { name } = options\n\n const handlersByEvent = new Map<string, NormalizedHandler<D>>()\n const events: Record<string, StandardSchemaV1> = {\n [ACTOR_STATE_EVENT]: actorStateSchema(),\n [ACTOR_FAILED_EVENT]: actorFailedSchema,\n }\n for (const [eventName, def] of Object.entries(\n options.handlers as Record<string, ActorHandler<D, keyof D['events']>>,\n )) {\n if (UNSAFE_EVENT_NAMES.has(eventName)) {\n throw new TypeError(\n `actor '${name}': '${eventName}' collides with object plumbing and cannot name an event`,\n )\n }\n if (eventName.startsWith('a2.')) {\n throw new TypeError(\n `actor '${name}': event names starting with 'a2.' are reserved`,\n )\n }\n handlersByEvent.set(\n eventName,\n typeof def === 'function'\n ? {\n kind: 'serial',\n handle: def as (\n ctx: ActorContext<D>,\n input: unknown,\n ) => void | Promise<void>,\n }\n : {\n kind: 'concurrent',\n handle: def.handle as (\n ctx: ActorConcurrentContext<D>,\n input: unknown,\n ) => void | Promise<void>,\n },\n )\n events[eventName] = jsonInputSchema\n }\n\n const reducer = actorReducer({ name, state: options.state })\n // The server's contract carries every event type; the reducer only\n // folds state commits. Same fold, same identity — the widening is a\n // typing formality.\n const serverReducer = reducer as unknown as Reducer<EventDefs, D['state']>\n\n // The typed durable-timer surface: immediate handoff to the\n // configured scheduler through the handler session, so timer\n // identity is scoped to the triggering message and re-runs address\n // the same timer (core §6). Not buffered — see ActorScheduleSend.\n const makeSchedule = (\n schedule: (\n name: string,\n timing: { delay?: string; at?: Date },\n event: { type: string; payload: unknown },\n ) => Promise<void>,\n ): ActorScheduleSend<D['events']> => {\n const surface: Record<string, unknown> = {}\n for (const eventName of handlersByEvent.keys()) {\n Object.defineProperty(surface, eventName, {\n value: (input: unknown, scheduleOptions: ActorScheduleOptions) => {\n const { name: taskName, ...timing } = scheduleOptions\n return schedule(taskName ?? eventName, timing, {\n type: eventName,\n payload: input ?? {},\n })\n },\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n return surface as ActorScheduleSend<D['events']>\n }\n\n // The typed self-send surface: per-invocation buffers behind one\n // shared method record shape. defineProperty so event names like\n // 'constructor'-adjacent identifiers can never touch prototypes.\n const makeSend = (\n buffer: { type: string; payload: unknown }[],\n ): ActorSend<D['events']> => {\n const send: Record<string, unknown> = {}\n for (const eventName of handlersByEvent.keys()) {\n Object.defineProperty(send, eventName, {\n value: (input?: unknown) => {\n buffer.push({ type: eventName, payload: input ?? {} })\n },\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n return send as ActorSend<D['events']>\n }\n\n const handlers: Record<string, HandlerEntry<EventDefs>> = {}\n for (const [eventName, def] of handlersByEvent) {\n if (def.kind === 'concurrent') {\n // No lane: concurrent handlers run in parallel — with the lane\n // and with each other. They cannot write state (no draft to\n // commit), so no serialization is needed for correctness; slow\n // I/O lives here without blocking the actor.\n handlers[eventName] = async (ctx) => {\n const sends: { type: string; payload: unknown }[] = []\n try {\n await def.handle(\n {\n id: ctx.event.id,\n attempt: ctx.attempt,\n signal: ctx.signal,\n send: makeSend(sends),\n schedule: makeSchedule((taskName, timing, event) =>\n ctx.session.schedule(\n taskName,\n timing as Parameters<typeof ctx.session.schedule>[1],\n event,\n ),\n ),\n state: async () => {\n const { state, index } = await ctx.session.state(\n serverReducer,\n { through: 'latest' },\n )\n return { state, index }\n },\n },\n ctx.event.payload,\n )\n } catch (error) {\n if (!(error instanceof NonRetriableError)) throw error\n // A terminal failure is recorded for audit; nothing awaits a\n // concurrent handler, so the marker is history, not an\n // answer. Buffered sends are discarded — refusals are total,\n // so compensate by completing (send then return), never by\n // throwing.\n const payload: ActorFailedPayload = {\n message: ctx.event.id,\n event: eventName,\n error: describeError(error),\n }\n return { type: ACTOR_FAILED_EVENT, payload }\n }\n // Sends commit atomically with settlement; re-runs converge on\n // the same deterministic message ids.\n return sends\n }\n continue\n }\n handlers[eventName] = {\n // One lane for every serial handler of one instance: the next\n // message starts only after the previous one completed, and\n // completion commits the state event atomically —\n // read-modify-write on `ctx.state` is safe by exclusion, not by\n // liveness.\n lane: ACTOR_LANE,\n handler: async (ctx) => {\n // Explicitly 'latest', not the event-relative default: prior\n // lane messages commit *after* this message was appended, so\n // their state commits carry higher indexes than the trigger —\n // an event-relative read would miss them and lose updates.\n // 'latest' is deterministic here because the lane makes this\n // attempt the only possible writer while it runs.\n const { state, clearIndex } = await ctx.session.state(serverReducer, {\n through: 'latest',\n })\n const draft = structuredClone(state)\n const sends: { type: string; payload: unknown }[] = []\n try {\n await def.handle(\n {\n state: draft,\n id: ctx.event.id,\n attempt: ctx.attempt,\n signal: ctx.signal,\n send: makeSend(sends),\n schedule: makeSchedule((taskName, timing, event) =>\n ctx.session.schedule(\n taskName,\n timing as Parameters<typeof ctx.session.schedule>[1],\n event,\n ),\n ),\n },\n ctx.event.payload,\n )\n } catch (error) {\n // A NonRetriableError is an answer: settle the message,\n // record the refusal, deliver it to the waiting caller —\n // no retry, no failure budget spent (buffered sends are\n // discarded with the draft: refusals are total). Every\n // other throw is an ordinary A2 handler failure: rethrown\n // into core's retry machinery (backoff, ten-failure\n // budget, dead letter) — including surrendered lease\n // aborts, which core recognizes by identity.\n if (!(error instanceof NonRetriableError)) throw error\n const payload: ActorFailedPayload = {\n message: ctx.event.id,\n event: eventName,\n error: describeError(error),\n }\n return { type: ACTOR_FAILED_EVENT, payload }\n }\n // One returned batch: buffered sends plus the state commit —\n // committed atomically with completion, so a reserve and its\n // trigger can never half-happen. The state event stays the\n // outcome marker a waiting call resolves on. (Unconditional\n // for now; a dirty check is a compatible later optimization.)\n const payload: ActorStatePayload<D['state']> = {\n state: draft,\n event: eventName,\n message: ctx.event.id,\n ...(clearIndex === undefined ? {} : { clearIndex }),\n }\n return [...sends, { type: ACTOR_STATE_EVENT, payload }]\n },\n }\n }\n\n const presenceEnabled = (options as { presence?: unknown }).presence === true\n // The '*' catch-all arms an open server-side vocabulary: the\n // protocol types field names at compile time, the floor validates\n // every value, and `authorize` sees every set. See openPresenceDefs.\n const contract = presenceEnabled\n ? createContract({ name, events, presence: openPresenceDefs })\n : createContract({ name, events })\n const server = createServer({\n contract,\n handlers,\n ...(options.store ? { store: options.store } : {}),\n ...(options.scheduler ? { scheduler: options.scheduler } : {}),\n ...(options.telemetry ? { telemetry: options.telemetry } : {}),\n })\n // Single-writer discipline on the underlying session wire too: if an\n // application mounts `def.server.fetch`, browsers may push declared\n // events, never authored state or failure records.\n setServerFetchHooks(server, {\n validateIngress: ({ events: pushed }) => {\n for (const event of pushed) {\n if (event.type.startsWith('a2.actor.')) {\n throw new TypeError(\n `'${event.type}' is reserved — only a handler's completion can author it`,\n )\n }\n }\n },\n })\n\n const internals = serverInternals.get(server)!\n\n const makeHandle = (id: string): ActorHandle<D> => {\n const session = server.session(id)\n\n const sendEvent = async (\n eventName: string,\n input: unknown,\n sendOptions?: ActorSendOptions,\n ): Promise<{ id: string; index: number }> => {\n const [message] = await session.append({\n type: eventName,\n payload: input ?? {},\n ...(sendOptions?.id ? { id: sendOptions.id } : {}),\n })\n if (!message) throw new Error('append returned no event')\n return { id: message.id, index: message.index }\n }\n\n const callEvent = async (\n eventName: string,\n input: unknown,\n callOptions?: ActorCallOptions,\n ): Promise<ActorCallResult<D['state']>> => {\n if (handlersByEvent.get(eventName)?.kind === 'concurrent') {\n throw new TypeError(\n `actor '${name}': '${eventName}' is concurrent — it produces no answer to await; send it instead`,\n )\n }\n const message = await sendEvent(eventName, input, callOptions)\n const deadline = Date.now() + (callOptions?.timeoutMs ?? CALL_TIMEOUT_MS)\n let cursor = message.index + 1\n for (;;) {\n // Drain participates in processing (usually answering inline in\n // this invocation); claims arbitrate if another process runs.\n await server.drain(id)\n const tail = await internals.historyWithMarkers(id, cursor)\n for (const event of tail) {\n // Reads start at the latest marker, so a clear after the message\n // arrives before any answer from the next lifetime, including one\n // from a message that reuses this id.\n if (isSessionCleared(event)) {\n throw sessionClearedError(\n `actor '${name}': '${eventName}' (message ${message.id}) was cleared before the call received its answer`,\n )\n }\n if (event.type === ACTOR_STATE_EVENT) {\n const payload = event.payload as ActorStatePayload<D['state']>\n if (payload.message === message.id) {\n return {\n state: payload.state,\n index: event.index,\n ...(payload.clearIndex === undefined\n ? {}\n : { clearIndex: payload.clearIndex }),\n }\n }\n }\n if (event.type === ACTOR_FAILED_EVENT) {\n const payload = event.payload as ActorFailedPayload\n if (payload.message === message.id) {\n throw new ActorRefusedError(eventName, message.id, payload.error)\n }\n }\n }\n const last = tail[tail.length - 1]\n if (last) cursor = last.index + 1\n if (Date.now() >= deadline) {\n throw new Error(\n `actor '${name}': timed out waiting for '${eventName}' (message ${message.id})`,\n )\n }\n await sleep(CALL_POLL_MS)\n }\n }\n\n const readState = async (): Promise<ActorCallResult<D['state']>> => {\n const { state, index, clearIndex } = await session.state(serverReducer)\n return clearIndex === undefined\n ? { state, index }\n : { state, index, clearIndex }\n }\n\n /** A snapshot or call answer through the route's view. */\n const projected = (\n result: ActorCallResult<D['state']>,\n view: ((state: D['state']) => unknown) | undefined,\n ): ActorCallResult<unknown> =>\n view ? { ...result, state: applyView(view, result.state) } : result\n\n const applyView = (\n view: (state: D['state']) => unknown,\n state: D['state'],\n ): unknown => {\n const viewed = view(state)\n if (!isJsonTree(viewed)) {\n throw new TypeError(\n `actor '${name}': the view returned a value that is not a plain JSON tree`,\n )\n }\n return viewed\n }\n\n const streamStates = async function* (\n startAfter: number,\n view?: (state: D['state']) => unknown,\n ) {\n // With presence armed, the session interleaves presence items\n // (snapshot, then patches) between log events. They are\n // ephemeral audience data, not actor state: they pass through\n // untouched — views project state, never peers — and they never\n // advance the resume frontier.\n const source: AsyncIterable<\n | Awaited<ReturnType<typeof session.history>>[number]\n | SessionCleared\n | PresencePatch\n | PresenceSnapshot\n > = presenceEnabled\n ? (\n session as unknown as {\n stream(options: {\n startAfter: number\n presence: true\n }): AsyncIterable<PresencePatch | PresenceSnapshot>\n }\n ).stream({ startAfter, presence: true })\n : session.stream({ startAfter })\n for await (const item of source) {\n if (!('type' in item)) {\n yield item\n continue\n }\n const event = item\n if (isSessionCleared(event)) {\n // The follower has no seed of its own: the marker carries the\n // actor's initial state, projected like any commit.\n const initial = structuredClone(options.state)\n yield {\n ...event,\n payload: { state: view ? applyView(view, initial) : initial },\n }\n continue\n }\n // The state plane only: subscribers see what the actor is,\n // never other callers' inputs. Refusals answer only their\n // caller (the POST 409); the full mailbox stays server-side.\n if (event.type !== ACTOR_STATE_EVENT) continue\n if (!view) {\n yield event\n continue\n }\n const payload = event.payload as ActorStatePayload<D['state']>\n yield {\n ...event,\n payload: { ...payload, state: applyView(view, payload.state) },\n }\n }\n }\n\n // The managed door — the actor mirror of `server.fetch`: GET is\n // the state-plane SSE (`a2.actor.state` commits and clear resets,\n // `?index` resume), POST is the call lane (`{ event, input,\n // messageId? }` → the answer, 409 for a refusal, 410 for a cleared\n // call). Authentication happens in the surrounding route;\n // per-operation policy in `authorize`.\n const handleFetch = async (\n request: Request,\n fetchOptions?: ActorFetchOptions<D>,\n ): Promise<Response> => {\n const authorized = async (operation: ActorOperation): Promise<boolean> =>\n (await fetchOptions?.authorize?.(Object.freeze(operation))) !== false\n\n if (request.method === 'GET') {\n const url = new URL(request.url)\n if (url.searchParams.has('snapshot')) {\n if (!(await authorized({ type: 'state', id }))) return forbidden()\n return Response.json(\n projected(await readState(), fetchOptions?.view),\n {\n headers: { 'cache-control': 'private, no-store' },\n },\n )\n }\n const raw = Number(url.searchParams.get('index'))\n const startAfter = Number.isSafeInteger(raw) && raw >= 0 ? raw : 0\n if (!(await authorized({ type: 'stream', id, startAfter }))) {\n return forbidden()\n }\n return sseResponse(streamStates(startAfter, fetchOptions?.view))\n }\n if (request.method !== 'POST') {\n return new Response(null, {\n status: 405,\n headers: { allow: 'GET, POST' },\n })\n }\n let body: unknown\n try {\n body = await request.json()\n } catch {\n return Response.json({ error: 'invalid JSON body' }, { status: 400 })\n }\n const record =\n typeof body === 'object' && body !== null\n ? (body as Record<string, unknown>)\n : {}\n if ('presence' in record) {\n // A presence envelope — what the follower client's\n // `setPresence` posts. Events never ride this lane: writes to\n // the actor are calls.\n if (!presenceEnabled) {\n return Response.json(\n { error: `actor '${name}' declares no presence` },\n { status: 400 },\n )\n }\n const pushedEvents = record['events']\n if (\n pushedEvents !== undefined &&\n (!Array.isArray(pushedEvents) || pushedEvents.length > 0)\n ) {\n return Response.json(\n { error: 'the actor wire takes calls, not event pushes' },\n { status: 400 },\n )\n }\n let patch: ParsedPushPresence\n try {\n const parsed = parsePresenceSibling(record['presence'])\n if (!parsed) throw new TypeError('presence must be an object')\n patch = parsed\n } catch (error) {\n return Response.json({ error: describeError(error) }, { status: 400 })\n }\n if (\n !(await authorized({\n type: 'presence',\n id,\n participant: patch.participant,\n values: patch.values,\n }))\n ) {\n return forbidden()\n }\n try {\n await (\n session as unknown as {\n setPresence(patch: ParsedPushPresence): Promise<void>\n }\n ).setPresence(patch)\n } catch (error) {\n if (\n error instanceof A2Error &&\n (error.code === 'INVALID_PAYLOAD' ||\n error.code === 'UNKNOWN_PRESENCE_FIELD')\n ) {\n return Response.json({ error: error.message }, { status: 400 })\n }\n throw error\n }\n return Response.json([])\n }\n const eventName = record['event']\n if (\n typeof eventName !== 'string' ||\n handlersByEvent.get(eventName)?.kind !== 'serial'\n ) {\n return Response.json({ error: 'unknown event' }, { status: 400 })\n }\n const messageId = record['messageId']\n if (messageId !== undefined && typeof messageId !== 'string') {\n return Response.json({ error: 'invalid messageId' }, { status: 400 })\n }\n const input = record['input']\n if (\n !(await authorized({\n type: 'call',\n id,\n event: eventName,\n input,\n ...(messageId === undefined ? {} : { messageId }),\n }))\n ) {\n return forbidden()\n }\n try {\n const result = await callEvent(\n eventName,\n input,\n messageId === undefined ? undefined : { id: messageId },\n )\n return Response.json(projected(result, fetchOptions?.view), {\n headers: { 'cache-control': 'private, no-store' },\n })\n } catch (error) {\n if (error instanceof ActorRefusedError) {\n return Response.json(\n {\n error: error.message,\n event: error.event,\n messageId: error.messageId,\n },\n { status: 409 },\n )\n }\n if (error instanceof A2Error && error.code === 'SESSION_CLEARED') {\n return Response.json(\n { code: error.code, error: error.message },\n { status: 410 },\n )\n }\n if (\n error instanceof A2Error &&\n (error.code === 'INVALID_PAYLOAD' ||\n error.code === 'UNKNOWN_EVENT_TYPE')\n ) {\n return Response.json({ error: error.message }, { status: 400 })\n }\n throw error\n }\n }\n\n const call: Record<string, unknown> = {}\n const send: Record<string, unknown> = {}\n for (const eventName of handlersByEvent.keys()) {\n Object.defineProperty(call, eventName, {\n value: (input?: unknown, callOptions?: ActorCallOptions) =>\n callEvent(eventName, input, callOptions),\n enumerable: true,\n configurable: true,\n writable: false,\n })\n Object.defineProperty(send, eventName, {\n value: (input?: unknown, sendOptions?: ActorSendOptions) =>\n sendEvent(eventName, input, sendOptions),\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n const handle: ActorHandle<D> = {\n id,\n session,\n call: call as ActorHandle<D>['call'],\n send: send as ActorHandle<D>['send'],\n state: readState,\n fetch: handleFetch,\n }\n return handle\n }\n\n return {\n name,\n contract,\n server,\n reducer,\n actor: makeHandle,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"actor.js","names":["createContract"],"sources":["../src/actor.ts"],"sourcesContent":["/**\n * experimental-a2/actor — durable actors over the log. Server-only\n * (handlers are server code); the browser condition resolves to a\n * throwing stub, and the browser surfaces are experimental-a2/actor/client\n * and experimental-a2/actor/react.\n *\n * An actor is defined over a protocol — its state shape and event\n * vocabulary, as types — and one complete `handlers` bag:\n *\n * ```ts\n * interface Counter {\n * state: { count: number }\n * events: { increment: object; add: { by: number } }\n * }\n * const counter = actor<Counter>({\n * name: 'counter',\n * state: { count: 0 },\n * handlers: {\n * increment: (ctx) => {\n * ctx.state.count++\n * },\n * add: (ctx, input) => {\n * ctx.state.count += input.by\n * },\n * },\n * })\n * ```\n *\n * Handlers are serial by default: one at a time per instance (a lane —\n * the state's write lock), `ctx.state` a mutable draft committed\n * atomically with completion. A handler holding slow I/O opts out of\n * the lane with `{ concurrent: true, handle }`: it runs in parallel,\n * reads state as a snapshot, and mutates by sending events whose\n * serial handlers decide against fresh state. `ctx.send.eventName(...)`\n * is typed by the protocol and buffered — committed atomically with\n * the handler's completion, so a reserve and its trigger can never\n * half-happen.\n *\n * A thrown `NonRetriableError` is an answer (settled, delivered to a\n * waiting caller); any other error retries like every A2 handler\n * failure; a crash re-runs against the same pre-state. Everything\n * compiles to contract + reducer + laned handlers + returned events —\n * no new store operations, no new wire.\n */\n\n// oxlint-disable no-await-in-loop -- a call awaits its answer: drain, read\n// the tail, repeat until the message settles. Sequential by nature.\n\nimport {\n ACTOR_FAILED_EVENT,\n ACTOR_LANE,\n ACTOR_STATE_EVENT,\n ActorRefusedError,\n actorFailedSchema,\n actorReducer,\n actorStateSchema,\n isJsonTree,\n openPresenceDefs,\n} from './actor-shared.ts'\nimport type {\n ActorClientEventDefs,\n ActorConcurrentContext,\n ActorContext,\n ActorFailedPayload,\n ActorPresenceOf,\n ActorProtocol,\n ActorScheduleOptions,\n ActorScheduleSend,\n ActorSend,\n ActorStatePayload,\n} from './actor-shared.ts'\nimport { parsePresenceSibling } from './push-envelope.ts'\nimport type { ParsedPushPresence } from './push-envelope.ts'\nimport { internalContract as createContract } from './contract.ts'\nimport type { PresencePatch, PresenceSnapshot } from './contract.ts'\nimport type { Contract, EventDefs } from './contract.ts'\nimport type { Reducer } from './reducer.ts'\nimport { A2Error, NonRetriableError } from './errors.ts'\nimport { serverInternals } from './internal.ts'\nimport { createServer } from './server.ts'\nimport { setServerFetchHooks } from './server-fetch.ts'\nimport { sseResponse } from './sse.ts'\nimport { isSessionCleared, sessionClearedError } from './session-clear.ts'\nimport type { SessionCleared } from './session-clear.ts'\nimport type {\n A2Scheduler,\n A2Server,\n ConsumerContext,\n ConsumerResult,\n Session,\n} from './server.ts'\nimport { runtimeConsumer } from './runtime-consumer.ts'\nimport type { A2Store } from './store.ts'\nimport type { StandardSchemaV1 } from './standard-schema.ts'\nimport type { A2Telemetry } from './telemetry.ts'\n\nexport type {\n ActorConcurrentContext,\n ActorContext,\n ActorPresenceMap,\n ActorPresenceOf,\n ActorPresenceValues,\n ActorProtocol,\n ActorScheduleOptions,\n ActorScheduleSend,\n ActorSend,\n} from './actor-shared.ts'\nexport { ActorRefusedError } from './actor-shared.ts'\n\n/**\n * One event's handler: ordinary server code. Serial by default — read\n * `ctx.state`, perform I/O, mutate `ctx.state`, one atomic commit at\n * return. `{ concurrent: true, handle }` opts the handler out of the\n * lane for slow I/O: state becomes a snapshot read and mutations\n * happen by sending events. The input is typed by the protocol; the\n * wire hands handlers parsed JSON, so a wire-exposed event guards its\n * input in its first line (`schema.parse(input)` if you like schemas —\n * userland either way).\n */\nexport type ActorHandler<D extends ActorProtocol, K extends keyof D['events']> =\n | ((ctx: ActorContext<D>, input: D['events'][K]) => void | Promise<void>)\n | {\n concurrent: true\n handle: (\n ctx: ActorConcurrentContext<D>,\n input: D['events'][K],\n ) => void | Promise<void>\n }\n\n/**\n * Mark a handler concurrent — off the lane, in parallel with the lane\n * and with other concurrent handlers, `ctx.state()` a snapshot read.\n * Sugar for the structural `{ concurrent: true, handle }` form:\n *\n * ```ts\n * handlers: {\n * transfer: concurrent(async (ctx, input) => {\n * await bank.transfer(input, { idempotencyKey: input.ref })\n * ctx.send.settle({ ref: input.ref })\n * }),\n * }\n * ```\n */\nexport function concurrent<Ctx, I>(\n handle: (ctx: Ctx, input: I) => void | Promise<void>,\n): { concurrent: true; handle: (ctx: Ctx, input: I) => void | Promise<void> } {\n return { concurrent: true, handle }\n}\n\nexport type ActorOptions<D extends ActorProtocol> = {\n /** Identity — prefixes storage keys; one contract per actor definition. */\n name: string\n /** The initial state — checked against the protocol, a plain JSON tree. */\n state: D['state']\n /**\n * One handler per declared event — completeness and payload shapes\n * are compile-checked against the protocol.\n */\n handlers: { [K in keyof D['events']]: ActorHandler<D, K> }\n store?: A2Store\n scheduler?: A2Scheduler\n telemetry?: A2Telemetry\n} & ([ActorPresenceOf<D>] extends [never]\n ? { presence?: never }\n : {\n /**\n * The wire bit for the protocol's `presence` vocabulary — types\n * erase, so the runtime needs one value to arm the presence\n * lanes (frames on GET, envelopes on POST). Required exactly\n * when the protocol declares `presence`; the vocabulary itself\n * is typed there. Values are validated to the JSON floor and\n * pass through `authorize` as `{ type: 'presence' }` operations;\n * meaning stays with your renderers — treat values as user\n * input.\n */\n presence: true\n })\n\n/**\n * One HTTP operation `handle.fetch` is about to serve — the actor\n * mirror of core's `A2Operation`. `authorize` sees it before any\n * read, write, or subscription; returning `false` answers 403.\n */\nexport type ActorOperation =\n | { readonly type: 'state'; readonly id: string }\n | {\n readonly type: 'stream'\n readonly id: string\n readonly startAfter: number\n }\n | {\n readonly type: 'call'\n readonly id: string\n readonly event: string\n readonly input: unknown\n readonly messageId?: string\n }\n | {\n readonly type: 'presence'\n readonly id: string\n readonly participant: string\n readonly values: Readonly<Record<string, unknown>>\n }\n\nexport type ActorFetchOptions<D extends ActorProtocol> = {\n /** Per-operation policy — authentication happened in your route. */\n authorize?: (operation: ActorOperation) => boolean | Promise<boolean>\n /**\n * Request-time projection: what this mount's audience sees. Applied\n * to every state frame on the stream AND to call answers (the two\n * untrusted lanes must agree, or the call lane leaks what the\n * stream hides). The definition stays audience-agnostic — different\n * routes project the same actor differently, and per-viewer views\n * are just closures over the route's auth. Output is held to the\n * JSON-tree floor like everything else. Transport-agnostic: applied\n * at frame emission, so any wire the door speaks emits projected\n * frames. Absent, the full state ships (the trusted default).\n */\n view?: (state: D['state']) => unknown\n}\n\nexport type ActorSendOptions = {\n /** Explicit message id — makes retries of this send idempotent. */\n id?: string\n}\n\nexport type ActorCallOptions = ActorSendOptions & {\n /** How long to await the answer before rejecting the wait (default 30s). */\n timeoutMs?: number\n}\n\nexport type ActorCallResult<S> = {\n /** The actor's state after this message was processed. */\n state: S\n /** Log index of the state commit that answered this message. */\n index: number\n /**\n * The clear marker this state's lifetime began at, once the actor has been\n * cleared. For a call answer it is the lifetime the handler read.\n */\n clearIndex?: number\n}\n\ntype CallMethod<\n D extends ActorProtocol,\n K extends keyof D['events'],\n> = {} extends D['events'][K]\n ? (\n input?: D['events'][K],\n options?: ActorCallOptions,\n ) => Promise<ActorCallResult<D['state']>>\n : (\n input: D['events'][K],\n options?: ActorCallOptions,\n ) => Promise<ActorCallResult<D['state']>>\n\ntype SendMethod<\n D extends ActorProtocol,\n K extends keyof D['events'],\n> = {} extends D['events'][K]\n ? (\n input?: D['events'][K],\n options?: ActorSendOptions,\n ) => Promise<{ id: string; index: number }>\n : (\n input: D['events'][K],\n options?: ActorSendOptions,\n ) => Promise<{ id: string; index: number }>\n\n/** One instance: typed calls and sends, reads, the managed door, the escape hatch. */\nexport type ActorHandle<D extends ActorProtocol> = {\n readonly id: string\n /**\n * Send the event and await its answer: the state after the handler\n * ran, or a rejection with `ActorRefusedError`. A clear before the call\n * receives its answer rejects with `A2Error('SESSION_CLEARED')`. Serial\n * events only — concurrent handlers produce no answer to await; `send`\n * them.\n */\n readonly call: { readonly [K in keyof D['events']]: CallMethod<D, K> }\n /** Cast: validate, append the event durably, return without waiting. */\n readonly send: { readonly [K in keyof D['events']]: SendMethod<D, K> }\n /** Snapshot read — never queues behind pending messages. */\n readonly state: () => Promise<ActorCallResult<D['state']>>\n /**\n * The managed door — the actor mirror of `server.fetch`, bound to\n * this instance. GET streams the state plane (`a2.actor.state`\n * commits and clear resets, `?index` resume, heartbeat, deadline\n * rotation); POST is the call lane `createActorClient` speaks\n * (`{ event, input, messageId? }` → the answer, 409 for a refusal,\n * 410 for a call cleared before its answer). Your route\n * authenticates and picks the instance; `authorize` sees every\n * operation. Custom endpoints are route code around this call.\n */\n readonly fetch: (\n request: Request,\n options?: ActorFetchOptions<D>,\n ) => Promise<Response>\n /** Escape hatch: the raw A2 session (history, stream, schedule). */\n readonly session: Session<EventDefs>\n}\n\nexport type ActorDefinition<D extends ActorProtocol> = {\n readonly name: string\n /**\n * Type-only carrier of the protocol, so clients deriving from\n * `typeof def` can see the vocabularies (`experimental-a2/actor/react`\n * types `presence` from it). Never a runtime value.\n */\n readonly protocol?: D\n /** The assembled contract — declared events plus the reserved a2.actor.* pair. */\n readonly contract: Contract<EventDefs>\n /** The underlying A2 server — `server.fetch` mounts the full session wire. */\n readonly server: A2Server<EventDefs>\n /** The state fold over commits; a clear resets it to the initial state. */\n readonly reducer: Reducer<ActorClientEventDefs<D['state']>, D['state']>\n actor(id: string): ActorHandle<D>\n}\n\n// Object-mechanics names, not surface names: events live in their own\n// bags, so nothing else is reserved.\nconst UNSAFE_EVENT_NAMES = new Set(['__proto__', 'constructor', 'prototype'])\n\nconst forbidden = (): Response =>\n Response.json({ error: 'the operation is not authorized' }, { status: 403 })\n\nconst CALL_TIMEOUT_MS = 30_000\nconst CALL_POLL_MS = 25\n\n/** Declared events accept any JSON tree; `undefined` normalizes to `{}`. */\nconst jsonInputSchema: StandardSchemaV1<unknown> = {\n '~standard': {\n version: 1,\n vendor: 'a2',\n validate(value) {\n if (value === undefined || value === null) return { value: {} }\n if (!isJsonTree(value)) {\n return {\n issues: [{ message: 'event input must be a plain JSON tree' }],\n }\n }\n return { value }\n },\n },\n}\n\nconst describeError = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms))\n\ntype NormalizedHandler<D extends ActorProtocol> =\n | {\n kind: 'serial'\n handle: (ctx: ActorContext<D>, input: unknown) => void | Promise<void>\n }\n | {\n kind: 'concurrent'\n handle: (\n ctx: ActorConcurrentContext<D>,\n input: unknown,\n ) => void | Promise<void>\n }\n\n/**\n * Define and serve an actor over its protocol: a named, durable\n * instance-per-id with serialized state handlers, concurrent I/O\n * handlers, and typed self-sends.\n */\nexport function actor<D extends ActorProtocol>(\n options: ActorOptions<D>,\n): ActorDefinition<D> {\n const { name } = options\n\n const handlersByEvent = new Map<string, NormalizedHandler<D>>()\n const events: Record<string, StandardSchemaV1> = {\n [ACTOR_STATE_EVENT]: actorStateSchema(),\n [ACTOR_FAILED_EVENT]: actorFailedSchema,\n }\n for (const [eventName, def] of Object.entries(\n options.handlers as Record<string, ActorHandler<D, keyof D['events']>>,\n )) {\n if (UNSAFE_EVENT_NAMES.has(eventName)) {\n throw new TypeError(\n `actor '${name}': '${eventName}' collides with object plumbing and cannot name an event`,\n )\n }\n if (eventName.startsWith('a2.')) {\n throw new TypeError(\n `actor '${name}': event names starting with 'a2.' are reserved`,\n )\n }\n handlersByEvent.set(\n eventName,\n typeof def === 'function'\n ? {\n kind: 'serial',\n handle: def as (\n ctx: ActorContext<D>,\n input: unknown,\n ) => void | Promise<void>,\n }\n : {\n kind: 'concurrent',\n handle: def.handle as (\n ctx: ActorConcurrentContext<D>,\n input: unknown,\n ) => void | Promise<void>,\n },\n )\n events[eventName] = jsonInputSchema\n }\n\n const reducer = actorReducer({ name, state: options.state })\n // The server's contract carries every event type; the reducer only\n // folds state commits. Same fold, same identity — the widening is a\n // typing formality.\n const serverReducer = reducer as unknown as Reducer<EventDefs, D['state']>\n\n // The typed durable-timer surface: immediate handoff to the\n // configured scheduler through the handler session, so timer\n // identity is scoped to the triggering message and re-runs address\n // the same timer (core §6). Not buffered — see ActorScheduleSend.\n const makeSchedule = (\n schedule: (\n name: string,\n timing: { delay?: string; at?: Date },\n event: { type: string; payload: unknown },\n ) => Promise<void>,\n ): ActorScheduleSend<D['events']> => {\n const surface: Record<string, unknown> = {}\n for (const eventName of handlersByEvent.keys()) {\n Object.defineProperty(surface, eventName, {\n value: (input: unknown, scheduleOptions: ActorScheduleOptions) => {\n const { name: taskName, ...timing } = scheduleOptions\n return schedule(taskName ?? eventName, timing, {\n type: eventName,\n payload: input ?? {},\n })\n },\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n return surface as ActorScheduleSend<D['events']>\n }\n\n // The typed self-send surface: per-invocation buffers behind one\n // shared method record shape. defineProperty so event names like\n // 'constructor'-adjacent identifiers can never touch prototypes.\n const makeSend = (\n buffer: { type: string; payload: unknown }[],\n ): ActorSend<D['events']> => {\n const send: Record<string, unknown> = {}\n for (const eventName of handlersByEvent.keys()) {\n Object.defineProperty(send, eventName, {\n value: (input?: unknown) => {\n buffer.push({ type: eventName, payload: input ?? {} })\n },\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n return send as ActorSend<D['events']>\n }\n\n type Run = (ctx: ConsumerContext<EventDefs>) => ConsumerResult<EventDefs>\n const concurrentRuns = new Map<string, Run>()\n const serialRuns = new Map<string, Run>()\n for (const [eventName, def] of handlersByEvent) {\n if (def.kind === 'concurrent') {\n // No lane: concurrent handlers run in parallel — with the lane\n // and with each other. They cannot write state (no draft to\n // commit), so no serialization is needed for correctness; slow\n // I/O lives here without blocking the actor.\n concurrentRuns.set(eventName, async (ctx) => {\n const sends: { type: string; payload: unknown }[] = []\n try {\n await def.handle(\n {\n id: ctx.event.id,\n attempt: ctx.attempt,\n signal: ctx.signal,\n send: makeSend(sends),\n schedule: makeSchedule((taskName, timing, event) =>\n ctx.session.schedule(\n taskName,\n timing as Parameters<typeof ctx.session.schedule>[1],\n event,\n ),\n ),\n state: async () => {\n const { state, index } = await ctx.session.state(\n serverReducer,\n { through: 'latest' },\n )\n return { state, index }\n },\n },\n ctx.event.payload,\n )\n } catch (error) {\n if (!(error instanceof NonRetriableError)) throw error\n // A terminal failure is recorded for audit; nothing awaits a\n // concurrent handler, so the marker is history, not an\n // answer. Buffered sends are discarded — refusals are total,\n // so compensate by completing (send then return), never by\n // throwing.\n const payload: ActorFailedPayload = {\n message: ctx.event.id,\n event: eventName,\n error: describeError(error),\n }\n return { type: ACTOR_FAILED_EVENT, payload }\n }\n // Sends commit atomically with settlement; re-runs converge on\n // the same deterministic message ids.\n return sends as never\n })\n continue\n }\n serialRuns.set(eventName, async (ctx) => {\n // Explicitly 'latest', not the event-relative default: prior\n // lane messages commit *after* this message was appended, so\n // their state commits carry higher indexes than the trigger —\n // an event-relative read would miss them and lose updates.\n // 'latest' is deterministic here because the lane makes this\n // attempt the only possible writer while it runs.\n const { state, clearIndex } = await ctx.session.state(serverReducer, {\n through: 'latest',\n })\n const draft = structuredClone(state)\n const sends: { type: string; payload: unknown }[] = []\n try {\n await def.handle(\n {\n state: draft,\n id: ctx.event.id,\n attempt: ctx.attempt,\n signal: ctx.signal,\n send: makeSend(sends),\n schedule: makeSchedule((taskName, timing, event) =>\n ctx.session.schedule(\n taskName,\n timing as Parameters<typeof ctx.session.schedule>[1],\n event,\n ),\n ),\n },\n ctx.event.payload,\n )\n } catch (error) {\n // A NonRetriableError is an answer: settle the message,\n // record the refusal, deliver it to the waiting caller —\n // no retry, no failure budget spent (buffered sends are\n // discarded with the draft: refusals are total). Every\n // other throw is an ordinary A2 handler failure: rethrown\n // into core's retry machinery (backoff, ten-failure\n // budget, dead letter) — including surrendered lease\n // aborts, which core recognizes by identity.\n if (!(error instanceof NonRetriableError)) throw error\n const payload: ActorFailedPayload = {\n message: ctx.event.id,\n event: eventName,\n error: describeError(error),\n }\n return { type: ACTOR_FAILED_EVENT, payload }\n }\n // One returned batch: buffered sends plus the state commit —\n // committed atomically with completion, so a reserve and its\n // trigger can never half-happen. The state event stays the\n // outcome marker a waiting call resolves on. (Unconditional\n // for now; a dirty check is a compatible later optimization.)\n const payload: ActorStatePayload<D['state']> = {\n state: draft,\n event: eventName,\n message: ctx.event.id,\n ...(clearIndex === undefined ? {} : { clearIndex }),\n }\n return [...sends, { type: ACTOR_STATE_EVENT, payload }] as never\n })\n }\n\n const presenceEnabled = (options as { presence?: unknown }).presence === true\n // The '*' catch-all arms an open server-side vocabulary: the\n // protocol types field names at compile time, the floor validates\n // every value, and `authorize` sees every set. See openPresenceDefs.\n const contract = presenceEnabled\n ? createContract({ name, events, presence: openPresenceDefs })\n : createContract({ name, events })\n // Serial messages share one lane per instance: the next starts only after\n // the previous one completed, and completion commits the state event\n // atomically, so read-modify-write on `ctx.state` is safe by exclusion,\n // not by liveness. The lane is a function, so each message is queued on\n // it as it's appended. Concurrent messages run alongside it and each\n // other: they write no state.\n const serialTypes = [...serialRuns.keys()]\n const concurrentTypes = [...concurrentRuns.keys()]\n const consumers = [\n ...(serialTypes.length === 0\n ? []\n : [\n runtimeConsumer({\n contract,\n name: 'a2.actor',\n types: serialTypes,\n lane: () => ACTOR_LANE,\n }).run((ctx) => serialRuns.get(ctx.event.type)!(ctx as never)),\n ]),\n ...(concurrentTypes.length === 0\n ? []\n : [\n runtimeConsumer({\n contract,\n name: 'a2.actor.concurrent',\n types: concurrentTypes,\n }).run((ctx) => concurrentRuns.get(ctx.event.type)!(ctx as never)),\n ]),\n ]\n const server = createServer({\n contract,\n consumers,\n ...(options.store ? { store: options.store } : {}),\n ...(options.scheduler ? { scheduler: options.scheduler } : {}),\n ...(options.telemetry ? { telemetry: options.telemetry } : {}),\n })\n // Single-writer discipline on the underlying session wire too: if an\n // application mounts `def.server.fetch`, browsers may push declared\n // events, never authored state or failure records.\n setServerFetchHooks(server, {\n validateIngress: ({ events: pushed }) => {\n for (const event of pushed) {\n if (event.type.startsWith('a2.actor.')) {\n throw new TypeError(\n `'${event.type}' is reserved — only a handler's completion can author it`,\n )\n }\n }\n },\n })\n\n const internals = serverInternals.get(server)!\n\n const makeHandle = (id: string): ActorHandle<D> => {\n const session = server.session(id)\n\n const sendEvent = async (\n eventName: string,\n input: unknown,\n sendOptions?: ActorSendOptions,\n ): Promise<{ id: string; index: number }> => {\n const [message] = await session.append({\n type: eventName,\n payload: input ?? {},\n ...(sendOptions?.id ? { id: sendOptions.id } : {}),\n })\n if (!message) throw new Error('append returned no event')\n return { id: message.id, index: message.index }\n }\n\n const callEvent = async (\n eventName: string,\n input: unknown,\n callOptions?: ActorCallOptions,\n ): Promise<ActorCallResult<D['state']>> => {\n if (handlersByEvent.get(eventName)?.kind === 'concurrent') {\n throw new TypeError(\n `actor '${name}': '${eventName}' is concurrent — it produces no answer to await; send it instead`,\n )\n }\n const message = await sendEvent(eventName, input, callOptions)\n const deadline = Date.now() + (callOptions?.timeoutMs ?? CALL_TIMEOUT_MS)\n let cursor = message.index + 1\n for (;;) {\n // Drain participates in processing (usually answering inline in\n // this invocation); claims arbitrate if another process runs.\n await server.drain(id)\n const tail = await internals.historyWithMarkers(id, cursor)\n for (const event of tail) {\n // Reads start at the latest marker, so a clear after the message\n // arrives before any answer from the next lifetime, including one\n // from a message that reuses this id.\n if (isSessionCleared(event)) {\n throw sessionClearedError(\n `actor '${name}': '${eventName}' (message ${message.id}) was cleared before the call received its answer`,\n )\n }\n if (event.type === ACTOR_STATE_EVENT) {\n const payload = event.payload as ActorStatePayload<D['state']>\n if (payload.message === message.id) {\n return {\n state: payload.state,\n index: event.index,\n ...(payload.clearIndex === undefined\n ? {}\n : { clearIndex: payload.clearIndex }),\n }\n }\n }\n if (event.type === ACTOR_FAILED_EVENT) {\n const payload = event.payload as ActorFailedPayload\n if (payload.message === message.id) {\n throw new ActorRefusedError(eventName, message.id, payload.error)\n }\n }\n }\n const last = tail[tail.length - 1]\n if (last) cursor = last.index + 1\n if (Date.now() >= deadline) {\n throw new Error(\n `actor '${name}': timed out waiting for '${eventName}' (message ${message.id})`,\n )\n }\n await sleep(CALL_POLL_MS)\n }\n }\n\n const readState = async (): Promise<ActorCallResult<D['state']>> => {\n const { state, index, clearIndex } = await session.state(serverReducer)\n return clearIndex === undefined\n ? { state, index }\n : { state, index, clearIndex }\n }\n\n /** A snapshot or call answer through the route's view. */\n const projected = (\n result: ActorCallResult<D['state']>,\n view: ((state: D['state']) => unknown) | undefined,\n ): ActorCallResult<unknown> =>\n view ? { ...result, state: applyView(view, result.state) } : result\n\n const applyView = (\n view: (state: D['state']) => unknown,\n state: D['state'],\n ): unknown => {\n const viewed = view(state)\n if (!isJsonTree(viewed)) {\n throw new TypeError(\n `actor '${name}': the view returned a value that is not a plain JSON tree`,\n )\n }\n return viewed\n }\n\n const streamStates = async function* (\n startAfter: number,\n view?: (state: D['state']) => unknown,\n ) {\n // With presence armed, the session interleaves presence items\n // (snapshot, then patches) between log events. They are\n // ephemeral audience data, not actor state: they pass through\n // untouched — views project state, never peers — and they never\n // advance the resume frontier.\n const source: AsyncIterable<\n | Awaited<ReturnType<typeof session.history>>[number]\n | SessionCleared\n | PresencePatch\n | PresenceSnapshot\n > = presenceEnabled\n ? (\n session as unknown as {\n stream(options: {\n startAfter: number\n presence: true\n }): AsyncIterable<PresencePatch | PresenceSnapshot>\n }\n ).stream({ startAfter, presence: true })\n : session.stream({ startAfter })\n for await (const item of source) {\n if (!('type' in item)) {\n yield item\n continue\n }\n const event = item\n if (isSessionCleared(event)) {\n // The follower has no seed of its own: the marker carries the\n // actor's initial state, projected like any commit.\n const initial = structuredClone(options.state)\n yield {\n ...event,\n payload: { state: view ? applyView(view, initial) : initial },\n }\n continue\n }\n // The state plane only: subscribers see what the actor is,\n // never other callers' inputs. Refusals answer only their\n // caller (the POST 409); the full mailbox stays server-side.\n if (event.type !== ACTOR_STATE_EVENT) continue\n if (!view) {\n yield event\n continue\n }\n const payload = event.payload as ActorStatePayload<D['state']>\n yield {\n ...event,\n payload: { ...payload, state: applyView(view, payload.state) },\n }\n }\n }\n\n // The managed door — the actor mirror of `server.fetch`: GET is\n // the state-plane SSE (`a2.actor.state` commits and clear resets,\n // `?index` resume), POST is the call lane (`{ event, input,\n // messageId? }` → the answer, 409 for a refusal, 410 for a cleared\n // call). Authentication happens in the surrounding route;\n // per-operation policy in `authorize`.\n const handleFetch = async (\n request: Request,\n fetchOptions?: ActorFetchOptions<D>,\n ): Promise<Response> => {\n const authorized = async (operation: ActorOperation): Promise<boolean> =>\n (await fetchOptions?.authorize?.(Object.freeze(operation))) !== false\n\n if (request.method === 'GET') {\n const url = new URL(request.url)\n if (url.searchParams.has('snapshot')) {\n if (!(await authorized({ type: 'state', id }))) return forbidden()\n return Response.json(\n projected(await readState(), fetchOptions?.view),\n {\n headers: { 'cache-control': 'private, no-store' },\n },\n )\n }\n const raw = Number(url.searchParams.get('index'))\n const startAfter = Number.isSafeInteger(raw) && raw >= 0 ? raw : 0\n if (!(await authorized({ type: 'stream', id, startAfter }))) {\n return forbidden()\n }\n return sseResponse(streamStates(startAfter, fetchOptions?.view))\n }\n if (request.method !== 'POST') {\n return new Response(null, {\n status: 405,\n headers: { allow: 'GET, POST' },\n })\n }\n let body: unknown\n try {\n body = await request.json()\n } catch {\n return Response.json({ error: 'invalid JSON body' }, { status: 400 })\n }\n const record =\n typeof body === 'object' && body !== null\n ? (body as Record<string, unknown>)\n : {}\n if ('presence' in record) {\n // A presence envelope — what the follower client's\n // `setPresence` posts. Events never ride this lane: writes to\n // the actor are calls.\n if (!presenceEnabled) {\n return Response.json(\n { error: `actor '${name}' declares no presence` },\n { status: 400 },\n )\n }\n const pushedEvents = record['events']\n if (\n pushedEvents !== undefined &&\n (!Array.isArray(pushedEvents) || pushedEvents.length > 0)\n ) {\n return Response.json(\n { error: 'the actor wire takes calls, not event pushes' },\n { status: 400 },\n )\n }\n let patch: ParsedPushPresence\n try {\n const parsed = parsePresenceSibling(record['presence'])\n if (!parsed) throw new TypeError('presence must be an object')\n patch = parsed\n } catch (error) {\n return Response.json({ error: describeError(error) }, { status: 400 })\n }\n if (\n !(await authorized({\n type: 'presence',\n id,\n participant: patch.participant,\n values: patch.values,\n }))\n ) {\n return forbidden()\n }\n try {\n await (\n session as unknown as {\n setPresence(patch: ParsedPushPresence): Promise<void>\n }\n ).setPresence(patch)\n } catch (error) {\n if (\n error instanceof A2Error &&\n (error.code === 'INVALID_PAYLOAD' ||\n error.code === 'UNKNOWN_PRESENCE_FIELD')\n ) {\n return Response.json({ error: error.message }, { status: 400 })\n }\n throw error\n }\n return Response.json([])\n }\n const eventName = record['event']\n if (\n typeof eventName !== 'string' ||\n handlersByEvent.get(eventName)?.kind !== 'serial'\n ) {\n return Response.json({ error: 'unknown event' }, { status: 400 })\n }\n const messageId = record['messageId']\n if (messageId !== undefined && typeof messageId !== 'string') {\n return Response.json({ error: 'invalid messageId' }, { status: 400 })\n }\n const input = record['input']\n if (\n !(await authorized({\n type: 'call',\n id,\n event: eventName,\n input,\n ...(messageId === undefined ? {} : { messageId }),\n }))\n ) {\n return forbidden()\n }\n try {\n const result = await callEvent(\n eventName,\n input,\n messageId === undefined ? undefined : { id: messageId },\n )\n return Response.json(projected(result, fetchOptions?.view), {\n headers: { 'cache-control': 'private, no-store' },\n })\n } catch (error) {\n if (error instanceof ActorRefusedError) {\n return Response.json(\n {\n error: error.message,\n event: error.event,\n messageId: error.messageId,\n },\n { status: 409 },\n )\n }\n if (error instanceof A2Error && error.code === 'SESSION_CLEARED') {\n return Response.json(\n { code: error.code, error: error.message },\n { status: 410 },\n )\n }\n if (\n error instanceof A2Error &&\n (error.code === 'INVALID_PAYLOAD' ||\n error.code === 'UNKNOWN_EVENT_TYPE')\n ) {\n return Response.json({ error: error.message }, { status: 400 })\n }\n throw error\n }\n }\n\n const call: Record<string, unknown> = {}\n const send: Record<string, unknown> = {}\n for (const eventName of handlersByEvent.keys()) {\n Object.defineProperty(call, eventName, {\n value: (input?: unknown, callOptions?: ActorCallOptions) =>\n callEvent(eventName, input, callOptions),\n enumerable: true,\n configurable: true,\n writable: false,\n })\n Object.defineProperty(send, eventName, {\n value: (input?: unknown, sendOptions?: ActorSendOptions) =>\n sendEvent(eventName, input, sendOptions),\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n const handle: ActorHandle<D> = {\n id,\n session,\n call: call as ActorHandle<D>['call'],\n send: send as ActorHandle<D>['send'],\n state: readState,\n fetch: handleFetch,\n }\n return handle\n }\n\n return {\n name,\n contract,\n server,\n reducer,\n actor: makeHandle,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as ContractEvent, s as Contract, t as Reducer, u as EventDefs, v as StandardSchemaV1 } from "./reducer-
|
|
2
|
-
import {
|
|
1
|
+
import { c as ContractEvent, s as Contract, t as Reducer, u as EventDefs, v as StandardSchemaV1 } from "./reducer-CYPHsSmd.js";
|
|
2
|
+
import { o as ConsumerContext } from "./server-BshFZ0eL.js";
|
|
3
3
|
import { FinishReason, JSONValue as JSONValue$1, LanguageModelCallOptions, LanguageModelUsage, UIMessage, UIMessage as UIMessage$1, UIMessageChunk, UIMessageChunk as UIMessageChunk$1 } from "ai";
|
|
4
4
|
//#region src/ai-message-base.d.ts
|
|
5
5
|
type FieldUndo = {
|
|
@@ -542,8 +542,8 @@ type AIMessageOf<D> = D extends {
|
|
|
542
542
|
/** What `agentContract()` returns: the AI protocol, with `X` as application state. */
|
|
543
543
|
type AgentContract<M extends UIMessage$1 = UIMessage$1, D extends EventDefs = AIEventDefs<M>, X extends object = Record<never, never>> = Contract<D, Record<never, never>, AgentReducer<M, D, X>>;
|
|
544
544
|
type AgentToolEventDefs = EventDefs & Pick<AIEventDefs, "ai.tool.execution.requested">;
|
|
545
|
-
/** The durable
|
|
546
|
-
type AgentToolContext<D extends AgentToolEventDefs> =
|
|
545
|
+
/** The durable consumer context supplied when A2 executes a local AI tool. */
|
|
546
|
+
type AgentToolContext<D extends AgentToolEventDefs> = ConsumerContext<D, "ai.tool.execution.requested">;
|
|
547
547
|
/** Application state folded after the AI protocol, on the server and in clients. */
|
|
548
548
|
/** Rejects application state keys that would shadow `AIState`'s. */
|
|
549
549
|
type OwnKeys<X> = { [K in Extract<keyof X, keyof AIState>]: never; };
|
|
@@ -648,14 +648,14 @@ type AIInputs = {
|
|
|
648
648
|
/** Pure append inputs for the built-in AI protocol. */
|
|
649
649
|
declare const inputs: AIInputs;
|
|
650
650
|
/**
|
|
651
|
-
* Read the durable
|
|
651
|
+
* Read the durable consumer context ambient to the current AI tool
|
|
652
652
|
* execution. A2 runs each local tool's `execute` inside this scope, so
|
|
653
653
|
* plain AI SDK `tool()` definitions reach their `event`, `attempt`,
|
|
654
654
|
* `session`, and `signal` without an A2-specific wrapper. Pass the
|
|
655
655
|
* agent's contract to type application events; it is verified against
|
|
656
656
|
* the executing agent.
|
|
657
657
|
*/
|
|
658
|
-
declare function
|
|
658
|
+
declare function consumerContext<D extends AgentToolEventDefs = AIEventDefs>(contract?: Contract<D>): AgentToolContext<D>;
|
|
659
659
|
/** The built-in AI reducer's name, and so its checkpoint identity. */
|
|
660
660
|
declare const AI_STATE_REDUCER = "a2.ai.state.v27";
|
|
661
661
|
/**
|
|
@@ -666,5 +666,5 @@ declare const AI_STATE_REDUCER = "a2.ai.state.v27";
|
|
|
666
666
|
*/
|
|
667
667
|
declare function agentContract<M extends UIMessage$1 = UIMessage$1, E extends EventDefs = Record<never, never>, X extends object = Record<never, never>>(options: AgentContractOptions<M, E, X>): AgentContract<M, AIEventDefs<M> & E, X>;
|
|
668
668
|
//#endregion
|
|
669
|
-
export { agentContract as $, InputRespondedPayload as A, PendingApproval as B, GenerationFailedPayload as C, GenerationStartedPayload as D, GenerationRequestedPayload as E, MessageInterruptedPayload as F, SessionClosedPayload as G, ReasoningLevel as H, ModelLimits as I, ToolCalledPayload as J, SessionCreatedPayload as K, ModelMetadataRequestedPayload as L, LanguageModelUsage as M, MessageCompletedPayload as N, GenerationUsage as O, MessageCreatedPayload as P, UIMessageChunk$1 as Q, ModelMetadataResolvedPayload as R, GenerationCompletedPayload as S, GenerationReason as T, RetryGenerationOptions as U, PendingInput as V, RetryRequestedPayload as W, TranscriptMessage as X, ToolResultPayload as Y, UIMessage$1 as Z, CompactionPart as _, AI_STATE_REDUCER as a, reasoningLevels as at, CompactionState as b, AgentContract as c, PendingQueueCommand as ct, AgentStatus as d, ControlReceipt as dt,
|
|
670
|
-
//# sourceMappingURL=ai-
|
|
669
|
+
export { agentContract as $, InputRespondedPayload as A, PendingApproval as B, GenerationFailedPayload as C, GenerationStartedPayload as D, GenerationRequestedPayload as E, MessageInterruptedPayload as F, SessionClosedPayload as G, ReasoningLevel as H, ModelLimits as I, ToolCalledPayload as J, SessionCreatedPayload as K, ModelMetadataRequestedPayload as L, LanguageModelUsage as M, MessageCompletedPayload as N, GenerationUsage as O, MessageCreatedPayload as P, UIMessageChunk$1 as Q, ModelMetadataResolvedPayload as R, GenerationCompletedPayload as S, GenerationReason as T, RetryGenerationOptions as U, PendingInput as V, RetryRequestedPayload as W, TranscriptMessage as X, ToolResultPayload as Y, UIMessage$1 as Z, CompactionPart as _, AI_STATE_REDUCER as a, reasoningLevels as at, CompactionState as b, AgentContract as c, PendingQueueCommand as ct, AgentStatus as d, ControlReceipt as dt, consumerContext as et, AgentToolContext as f, InboxItem as ft, CompactionCompletedPayload as g, ApprovalRespondedPayload as h, AIState as i, inputs as it, JSONValue$1 as j, InputRequestedPayload as k, AgentContractOptions as l, ActiveTurn as lt, ApprovalRequestedPayload as m, AIInputs as n, deriveUIMessages as nt, ActiveGeneration as o, reduceAIState as ot, AgentToolEventDefs as p, InputRef as pt, ToolActivity as q, AIMessageOf as r, events as rt, ActiveGenerationProjection as s, isCompactionPart as st, AIEventDefs as t, createEvents as tt, AgentReducer as u, ControlCommand as ut, CompactionPartData as v, GenerationProgressPayload as w, FinishReason as x, CompactionRequestedPayload as y, ModelMetadataState as z };
|
|
670
|
+
//# sourceMappingURL=ai-CvEnqVfo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-
|
|
1
|
+
{"version":3,"file":"ai-CvEnqVfo.d.ts","names":[],"sources":["../src/ai-message-base.ts","../src/ai-control.ts","../src/ai-client-state.ts","../src/ai-projector.ts","../src/ai-progress-batches.ts","../src/ai-message-projection.ts","../src/ai.ts"],"mappings":";;;;KAGK;EAAc;;EAAsB;;EAAmB;;KACvD,aAAa,eAAe;KAC5B;EAAa,OAAO;;EAAiC,QAAQ;;KAEtD;EACV;EACA,SAAS;EACT,QAAQ,eAAe;;;;;;;;KCQb;EACV;EACA,MAAM;EACN;EACA;;;KAIU,UAAU,UAAU,YAAY,aAAa;EACvD,SAAS;;KAGC,eAAe,UAAU,YAAY;EAC3C;EAAgB,SAAS;EAAG;;EAC5B;EAAgB,SAAS;;EACzB;EAAgB;EAAiB;;EACjC;EAAkB;;EAElB;EACA;EACA;EACA;;EAEA;EAAgB;EAAgB;;EAChC;EAAiB;EAAgB,SAAS;EAAG;;EAC7C;EAAiB;;EACjB;;EACA;EAAuB,QAAQ;;EAC/B;EAAoB,UAAU;;EAC9B;EAAiB,UAAU;;EAC3B;EAAyB,SAAS;;EAClC;EAAiB,SAAS;;EAC1B;EAAqB,SAAS;;KAExB;EACV;EACA;EACA;EACA;;KAUU;EACV;EACA,OAAO;EACP;;KA+BU;EAAa;EAAc;EAAY;;KACvC;EACV;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;;KAGE;EACV;EACA;EACA,MAAM;EACN,YAAY;;KAoDF;EACV;EACA;EACA;EACA;IAAW;IAAe;IAAqB;;EAC/C;IAAS;IAAc;;;KAGb;EACV,SAAS;EACT;IACE;IACA;IACA,OAAO;IACP;IACA;IACA;IACA,eAAe;IACf;IACA;;;;;KC7KQ,aAAa,UAAU,aAAa,QAC9C,eAAe;EAEb;;KAYQ,oBAAoB,UAAU;EACxC;EACA,SAAS,aAAa;;;;KCpBnB;EACH;EACA;EACA;EACA;EACA;EACA;EACA;;KAwJU;EACV,MAAM;EACN,WAAW;EACX,OAAO,eAAe;;;;KChJZ;EAAkB;EAAe,QAAQ;;KAChD,aAAa;EAAoB,MAAM;EAAY,OAAO;;KAEnD;EACV;EACA,MAAM;EACN,QAAQ,MAAM;;;;cCmgBH,mBAAoB;EAC/B;MACE,QAAQ;;;KCncA;KAGA;KAEA,iBAAiB,YAAY;cAE5B,0BAA0B;KAU3B;EACV;EACA;EACA;EACA;EACA,QAAQ;;;KAIE;EACV;EACA;EACA,MAAM;;;;;;KASI,kBAAkB,UAAU,eAAa,KAAK;EACxD,OAAO,MAAM,qBAAqB;;KAGxB;EAA0B,WAAW;;KACrC;EAAyB;;;;;;KAKzB;EACV;EACA,MAAM;;EAEN;;KAEU;EAA4B;;KACnC;EACH;EACA;;EAEA;;KAEU,4BAA4B;EAEhC;EAAsB;;EACtB;EAAmB;;KAEf;EACV;IAAY;IAAgB;;EAC5B;EACA,QAAQ;EACR;EACA;;KAEU;EACV;EACA;EACA;;KAEU,wBAAwB;KACxB;EACV;EACA;EACA;EACA;EACA;;EAEA;EACA;;KAEU;;EAEV;EACA,QAAQ;;KAEE;EACV;EACA;EACA;EACA;EACA,eAAe;EACf,QAAQ;EACR;;KAEU;EACV;EACA;EACA;EACA;EACA;;EAEA;EACA;;KAEU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAEU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAEU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;KAEU;EACV;EACA;EACA;EACA;EACA;EACA;;KAEU;EACV;EACA;EACA;EACA;EACA;EACA,WAAW;;KAED;EACV;EACA;EACA;EACA;EACA;EACA,OAAO;;KAEG;EACV;EACA;;KAEU;EAAkC;;KAClC;EACV;EACA,QAAQ;;KAEE;EACN;;EACA;EAAoB,QAAQ;;EAC5B;;KAEM;EACV;EACA;EACA;EACA;EACA;EACA;;KAEU,2BAA2B,UAAU;EAC/C;EACA;EACA;EACA,UAAU;EACV;EACA;EACA,QAAQ;;KAGE,YAAY,UAAU,cAAY;EAC5C,wBAAwB,iBAAiB,eAAe;EACxD,wBAAwB,iBAAiB;EACzC,sBAAsB,iBAAiB;EACvC,oBAAoB,iBAAiB;EACrC,+BAA+B,iBAAiB;EAChD,wBAAwB;IACtB;IACA;;EAEF,sBAAsB,iBAAiB;EACvC,qBAAqB,iBAAiB;EACtC,sBAAsB,iBAAiB;EACvC,wBAAwB,iBAAiB;EACzC,0BAA0B,iBAAiB;EAC3C,2BAA2B,iBAAiB;EAC5C,sBAAsB,iBAAiB;EACvC,yBAAyB,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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as reducer, o as assertSyncSchema, s as validateSync } from "./reducer-
|
|
2
|
-
import { t as contract } from "./contract-
|
|
1
|
+
import { a as reducer, o as assertSyncSchema, s as validateSync } from "./reducer-CjmvZSAb.js";
|
|
2
|
+
import { t as contract } from "./contract-CWukt01d.js";
|
|
3
3
|
import { t as idempotentId } from "./idempotent-id-BRJVeylj.js";
|
|
4
4
|
import { i as withReducerRuntime } from "./reducer-runtime-DQwz_J59.js";
|
|
5
|
-
import { u as ambientToolScopeStorage } from "./internal-
|
|
5
|
+
import { u as ambientToolScopeStorage } from "./internal-Bc4PvfHk.js";
|
|
6
6
|
import { a as unexplainedAdmission, i as steersOn, r as steeringEnd, t as STEERED_REASON } from "./ai-control-CvLbW10B.js";
|
|
7
7
|
//#region src/equal-json.ts
|
|
8
8
|
const sameValue = (left, right) => {
|
|
@@ -2829,17 +2829,17 @@ const inputs = {
|
|
|
2829
2829
|
}]
|
|
2830
2830
|
};
|
|
2831
2831
|
/**
|
|
2832
|
-
* Read the durable
|
|
2832
|
+
* Read the durable consumer context ambient to the current AI tool
|
|
2833
2833
|
* execution. A2 runs each local tool's `execute` inside this scope, so
|
|
2834
2834
|
* plain AI SDK `tool()` definitions reach their `event`, `attempt`,
|
|
2835
2835
|
* `session`, and `signal` without an A2-specific wrapper. Pass the
|
|
2836
2836
|
* agent's contract to type application events; it is verified against
|
|
2837
2837
|
* the executing agent.
|
|
2838
2838
|
*/
|
|
2839
|
-
function
|
|
2839
|
+
function consumerContext(contract) {
|
|
2840
2840
|
const scope = ambientToolScopeStorage()?.getStore();
|
|
2841
|
-
if (scope === void 0) throw new TypeError("
|
|
2842
|
-
if (contract !== void 0 && scope.contract !== void 0 && scope.contract.name !== contract.name) throw new TypeError(`
|
|
2841
|
+
if (scope === void 0) throw new TypeError("consumerContext() requires an ambient A2 tool execution: call it inside a local tool's execute, or wrap direct tool tests with runWithConsumerContext");
|
|
2842
|
+
if (contract !== void 0 && scope.contract !== void 0 && scope.contract.name !== contract.name) throw new TypeError(`consumerContext('${contract.name}') was called during a tool execution for agent '${scope.contract.name}'`);
|
|
2843
2843
|
return scope.context;
|
|
2844
2844
|
}
|
|
2845
2845
|
/** The built-in AI reducer's name, and so its checkpoint identity. */
|
|
@@ -2890,6 +2890,6 @@ function agentContract(options) {
|
|
|
2890
2890
|
return shared;
|
|
2891
2891
|
}
|
|
2892
2892
|
//#endregion
|
|
2893
|
-
export { interruptUIMessage as A, reduceToolActivity as C, flattenProgressBatches as D, upsertResponse as E, assertMessageBase as M, restoreMessageBase as N, progressBatches as O, projectedMessage as S, upsertMessage as T, applyControlChanges as _,
|
|
2893
|
+
export { interruptUIMessage as A, reduceToolActivity as C, flattenProgressBatches as D, upsertResponse as E, assertMessageBase as M, restoreMessageBase as N, progressBatches as O, projectedMessage as S, upsertMessage as T, applyControlChanges as _, deriveUIMessages as a, findMessage as b, reasoningLevels as c, appSlice as d, isAgentContract as f, isUIMessage as g, aiEventId as h, createEvents as i, pauseUIMessage as j, progressOwnedBy as k, reduceAIState as l, AI_EVENT_ID_PREFIX as m, agentContract as n, events as o, withAIStorage as p, consumerContext as r, inputs as s, AI_STATE_REDUCER as t, appReducerOf as u, controlCommit as v, retainMessageBase as w, isCompactionPart as x, advanceProjection as y };
|
|
2894
2894
|
|
|
2895
|
-
//# sourceMappingURL=ai-
|
|
2895
|
+
//# sourceMappingURL=ai-CzE672Q3.js.map
|