experimental-a2 0.16.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +373 -0
- package/README.md +1 -1
- package/dist/{actor-ohPC-81x.d.ts → actor-Bjce9_5U.d.ts} +21 -11
- package/dist/actor-Bjce9_5U.d.ts.map +1 -0
- package/dist/actor-client.d.ts +2 -5
- package/dist/actor-client.d.ts.map +1 -1
- package/dist/actor-client.js +13 -4
- package/dist/actor-client.js.map +1 -1
- package/dist/actor-react.d.ts +5 -3
- package/dist/actor-react.d.ts.map +1 -1
- package/dist/actor-react.js +20 -10
- package/dist/actor-react.js.map +1 -1
- package/dist/{actor-shared-B5tJfzt-.js → actor-shared-t7w8xIKP.js} +12 -7
- package/dist/actor-shared-t7w8xIKP.js.map +1 -0
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +42 -23
- package/dist/actor.js.map +1 -1
- package/dist/{ai-DgOBltJ_.js → ai-BpOGm-zB.js} +621 -216
- package/dist/ai-BpOGm-zB.js.map +1 -0
- package/dist/{ai-CrEf6p_W.d.ts → ai-DrUaMyRt.d.ts} +114 -100
- package/dist/ai-DrUaMyRt.d.ts.map +1 -0
- package/dist/ai-client.d.ts +27 -0
- package/dist/ai-client.d.ts.map +1 -0
- package/dist/ai-client.js +29 -0
- package/dist/ai-client.js.map +1 -0
- package/dist/ai-fx.browser.d.ts +1 -0
- package/dist/ai-fx.browser.js +6 -0
- package/dist/ai-fx.browser.js.map +1 -0
- package/dist/ai-fx.d.ts +10 -0
- package/dist/ai-fx.d.ts.map +1 -0
- package/dist/ai-fx.js +634 -0
- package/dist/ai-fx.js.map +1 -0
- package/dist/ai-harness-BuLh_EYi.js +273 -0
- package/dist/ai-harness-BuLh_EYi.js.map +1 -0
- package/dist/ai-harness-DvsPeJeB.d.ts +26 -0
- package/dist/ai-harness-DvsPeJeB.d.ts.map +1 -0
- package/dist/ai-pi.browser.d.ts +1 -0
- package/dist/ai-pi.browser.js +6 -0
- package/dist/ai-pi.browser.js.map +1 -0
- package/dist/ai-pi.d.ts +17 -0
- package/dist/ai-pi.d.ts.map +1 -0
- package/dist/ai-pi.js +904 -0
- package/dist/ai-pi.js.map +1 -0
- package/dist/ai-react.d.ts +96 -0
- package/dist/ai-react.d.ts.map +1 -0
- package/dist/ai-react.js +142 -0
- package/dist/ai-react.js.map +1 -0
- package/dist/ai-server.browser.js +2 -2
- package/dist/ai-server.browser.js.map +1 -1
- package/dist/ai-server.d.ts +109 -43
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +526 -283
- package/dist/ai-server.js.map +1 -1
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +2 -2
- package/dist/bounded-cache-CPHWF-8h.js +41 -0
- package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
- package/dist/{client-BYzHjkwU.js → client-BReKqwZC.js} +447 -80
- package/dist/client-BReKqwZC.js.map +1 -0
- package/dist/{client-CzyacQpJ.d.ts → client-h_DKFAjj.d.ts} +14 -13
- package/dist/client-h_DKFAjj.d.ts.map +1 -0
- package/dist/client.d.ts +4 -2
- package/dist/client.js +1 -1
- package/dist/{contract-CKRg_E4q.js → contract-BYKASlCV.js} +12 -21
- package/dist/contract-BYKASlCV.js.map +1 -0
- package/dist/{idempotent-replay-DVOlyYbx.js → idempotent-replay-JdgMQRRm.js} +2 -2
- package/dist/{idempotent-replay-DVOlyYbx.js.map → idempotent-replay-JdgMQRRm.js.map} +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/{errors-DvhSXnxk.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +7 -3
- package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +1 -0
- package/dist/{internal-Dq2qYxou.js → internal-B2T3U4Rq.js} +29 -2
- package/dist/internal-B2T3U4Rq.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/react-BBXgHWFc.d.ts +86 -0
- package/dist/react-BBXgHWFc.d.ts.map +1 -0
- package/dist/react.d.ts +2 -122
- package/dist/react.js +107 -100
- package/dist/react.js.map +1 -1
- package/dist/reducer-BAXc8JyF.js +87 -0
- package/dist/reducer-BAXc8JyF.js.map +1 -0
- package/dist/{reducer-otzHjuJj.d.ts → reducer-CqA59Q6U.d.ts} +46 -30
- package/dist/reducer-CqA59Q6U.d.ts.map +1 -0
- package/dist/reducer-runtime-DQwz_J59.js +28 -0
- package/dist/reducer-runtime-DQwz_J59.js.map +1 -0
- package/dist/scheduler-qstash.d.ts +3 -3
- package/dist/scheduler-qstash.d.ts.map +1 -1
- package/dist/scheduler-qstash.js +33 -10
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/{scheduler-task-BpzhPnRS.js → scheduler-task-X1SToDjP.js} +18 -3
- package/dist/scheduler-task-X1SToDjP.js.map +1 -0
- package/dist/scheduler-vercel.d.ts +4 -9
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +25 -44
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-BD5ckxZb.js → server-Dw_k_7kO.js} +904 -219
- package/dist/server-Dw_k_7kO.js.map +1 -0
- package/dist/{server-DbD7IJVK.d.ts → server-En7cbi3v.d.ts} +116 -26
- package/dist/server-En7cbi3v.d.ts.map +1 -0
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/session-clear-Bo-XTFEy.d.ts +12 -0
- package/dist/session-clear-Bo-XTFEy.d.ts.map +1 -0
- package/dist/{errors-DCk6ch5n.js → session-clear-DGI4jTQ5.js} +17 -2
- package/dist/session-clear-DGI4jTQ5.js.map +1 -0
- package/dist/{store-DyZM6fS5.d.ts → store-Djdv0bnZ.d.ts} +73 -3
- package/dist/store-Djdv0bnZ.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.d.ts.map +1 -1
- package/dist/store-memory.js +205 -66
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-CmxUbV93.js → store-polling-B5FcwJfo.js} +21 -4
- package/dist/store-polling-B5FcwJfo.js.map +1 -0
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +450 -108
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-C7-XZyW9.js → store-presence-polling-BAwS8RWn.js} +3 -3
- package/dist/{store-presence-polling-C7-XZyW9.js.map → store-presence-polling-BAwS8RWn.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.d.ts.map +1 -1
- package/dist/store-redis-http.js +293 -11
- package/dist/store-redis-http.js.map +1 -1
- package/dist/store-redis-notify-BRITti_o.js +2493 -0
- package/dist/store-redis-notify-BRITti_o.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.d.ts.map +1 -1
- package/dist/store-redis.js +11 -11
- package/dist/store-redis.js.map +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.d.ts.map +1 -1
- package/dist/store-sqlite.js +197 -33
- package/dist/store-sqlite.js.map +1 -1
- package/dist/stream-buffer-Cx7AAPGq.js +23 -0
- package/dist/stream-buffer-Cx7AAPGq.js.map +1 -0
- package/dist/{telemetry-B5jzpy6y.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
- package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
- package/dist/{wire-BO5wWCb1.js → wire-rSUglYo8.js} +132 -10
- package/dist/wire-rSUglYo8.js.map +1 -0
- package/docs/01-quickstart.mdx +50 -84
- package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
- package/docs/actors/01-introduction.mdx +48 -82
- package/docs/actors/02-concurrency.mdx +43 -70
- package/docs/actors/03-timers.mdx +28 -42
- package/docs/actors/04-routes.mdx +110 -137
- package/docs/actors/meta.ts +1 -1
- package/docs/agents/01-introduction.mdx +257 -0
- package/docs/agents/02-tools.mdx +247 -0
- package/docs/agents/03-conversations.mdx +538 -0
- package/docs/agents/04-harnesses.mdx +136 -0
- package/docs/agents/meta.ts +1 -0
- package/docs/client/01-react.mdx +294 -0
- package/docs/client/02-transports.mdx +86 -0
- package/docs/client/03-presence.mdx +224 -0
- package/docs/client/meta.ts +1 -0
- package/docs/contract/01-events.mdx +57 -0
- package/docs/contract/02-state.mdx +142 -0
- package/docs/contract/03-sessions.mdx +175 -0
- package/docs/index.mdx +112 -156
- package/docs/reference/01-core.mdx +139 -0
- package/docs/reference/02-server.mdx +855 -0
- package/docs/reference/03-client.mdx +301 -0
- package/docs/reference/04-ai.mdx +722 -0
- package/docs/reference/05-adapters.mdx +351 -0
- package/docs/reference/06-errors.mdx +138 -0
- package/docs/reference/meta.ts +1 -1
- package/docs/server/01-handlers.mdx +200 -0
- package/docs/server/02-timers.mdx +130 -0
- package/docs/server/03-cancellation.mdx +141 -0
- package/docs/server/04-routes.mdx +243 -0
- package/docs/server/05-production.mdx +322 -0
- package/docs/server/06-guarantees.mdx +123 -0
- package/examples/playground/DEPLOY.md +53 -7
- package/examples/playground/app/a0/[appId]/loading.tsx +16 -0
- package/examples/playground/app/a0/[appId]/page.tsx +53 -0
- package/examples/playground/app/a0/a0.css +818 -0
- package/examples/playground/app/a0/app-list.tsx +218 -0
- package/examples/playground/app/a0/app-view.tsx +63 -0
- package/examples/playground/app/a0/apps/[appId]/preview/route.ts +27 -0
- package/examples/playground/app/a0/apps/[appId]/route.ts +28 -0
- package/examples/playground/app/a0/apps.test.ts +128 -0
- package/examples/playground/app/a0/apps.ts +102 -0
- package/examples/playground/app/a0/chat.tsx +410 -0
- package/examples/playground/app/a0/columns.tsx +109 -0
- package/examples/playground/app/a0/context-menu.tsx +116 -0
- package/examples/playground/app/a0/cookies.ts +46 -0
- package/examples/playground/app/a0/crash-on-request.ts +72 -0
- package/examples/playground/app/a0/crashes/route.ts +3 -0
- package/examples/playground/app/a0/crashes.test.ts +33 -0
- package/examples/playground/app/a0/crashes.ts +28 -0
- package/examples/playground/app/a0/devtools.tsx +164 -0
- package/examples/playground/app/a0/events/route.ts +6 -0
- package/examples/playground/app/a0/flags.ts +30 -0
- package/examples/playground/app/a0/fx/events/route.ts +9 -0
- package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
- package/examples/playground/app/a0/layout.tsx +38 -0
- package/examples/playground/app/a0/list/route.ts +10 -0
- package/examples/playground/app/a0/model.test.ts +73 -0
- package/examples/playground/app/a0/model.ts +95 -0
- package/examples/playground/app/a0/no-photon.cjs +4 -0
- package/examples/playground/app/a0/no-quickjs.cjs +3 -0
- package/examples/playground/app/a0/page.tsx +14 -0
- package/examples/playground/app/a0/pi/events/route.ts +9 -0
- package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
- package/examples/playground/app/a0/preview-pane.tsx +145 -0
- package/examples/playground/app/a0/preview.test.ts +53 -0
- package/examples/playground/app/a0/preview.ts +26 -0
- package/examples/playground/app/a0/sandbox-log.ts +75 -0
- package/examples/playground/app/a0/sandbox-session.ts +152 -0
- package/examples/playground/app/a0/sandbox.ts +191 -0
- package/examples/playground/app/a0/sandboxes/scheduler/route.ts +6 -0
- package/examples/playground/app/a0/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/server.ts +213 -0
- package/examples/playground/app/a0/session.ts +59 -0
- package/examples/playground/app/a0/shell.tsx +158 -0
- package/examples/playground/app/a0/short/events/route.ts +9 -0
- package/examples/playground/app/a0/splitter.tsx +120 -0
- package/examples/playground/app/agent/[agentId]/agent-client.tsx +144 -174
- package/examples/playground/app/agent/[agentId]/command-receipt.test.tsx +65 -0
- package/examples/playground/app/agent/[agentId]/command-receipt.tsx +27 -0
- package/examples/playground/app/agent/[agentId]/compaction-event.tsx +25 -24
- package/examples/playground/app/agent/[agentId]/compaction-panel.test.tsx +119 -0
- package/examples/playground/app/agent/[agentId]/compaction-panel.tsx +208 -165
- package/examples/playground/app/agent/[agentId]/page.tsx +2 -16
- package/examples/playground/app/agent/events/route.ts +5 -2
- package/examples/playground/app/agent/ingress.test.ts +101 -0
- package/examples/playground/app/agent/model-input.test.tsx +58 -0
- package/examples/playground/app/agent/model-input.tsx +115 -0
- package/examples/playground/app/agent/model.test.ts +73 -0
- package/examples/playground/app/agent/model.ts +58 -26
- package/examples/playground/app/agent/new-agent-session.tsx +37 -19
- package/examples/playground/app/agent/page.tsx +4 -4
- package/examples/playground/app/agent/server.ts +19 -15
- package/examples/playground/app/agent/session.ts +5 -6
- package/examples/playground/app/agent/telemetry.test.ts +189 -0
- package/examples/playground/app/agent/telemetry.ts +30 -0
- package/examples/playground/app/agent/trace.test.ts +23 -0
- package/examples/playground/app/agent/trace.ts +18 -0
- package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +12 -12
- package/examples/playground/app/canvas/[canvasId]/page.tsx +1 -2
- package/examples/playground/app/canvas/[canvasId]/session.ts +2 -2
- package/examples/playground/app/canvas/model.ts +53 -53
- package/examples/playground/app/chat/[chatId]/agent-state.test.ts +176 -0
- package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +16 -1
- package/examples/playground/app/chat/[chatId]/chat-client.tsx +55 -77
- package/examples/playground/app/chat/[chatId]/chat-view.ts +37 -3
- package/examples/playground/app/chat/[chatId]/page.tsx +7 -15
- package/examples/playground/app/chat/[chatId]/session.ts +2 -19
- package/examples/playground/app/chat/agent/route.ts +9 -0
- package/examples/playground/app/chat/model.test.ts +46 -119
- package/examples/playground/app/chat/model.ts +82 -128
- package/examples/playground/app/chat/scheduler/route.ts +2 -2
- package/examples/playground/app/chat/server.test.ts +112 -0
- package/examples/playground/app/chat/server.ts +113 -117
- package/examples/playground/app/components/activity-feed.tsx +30 -1
- package/examples/playground/app/components/activity-history.test.tsx +35 -0
- package/examples/playground/app/components/demo-icons.tsx +89 -0
- package/examples/playground/app/components/demos.tsx +33 -0
- package/examples/playground/app/components/fast-link.test.tsx +58 -0
- package/examples/playground/app/components/fast-link.tsx +55 -0
- package/examples/playground/app/components/site-header.tsx +96 -0
- package/examples/playground/app/counter/counter-client.tsx +3 -3
- package/examples/playground/app/counter/model.test.ts +3 -3
- package/examples/playground/app/counter/model.ts +11 -21
- package/examples/playground/app/counter/page.tsx +2 -15
- package/examples/playground/app/counter/session.ts +2 -2
- package/examples/playground/app/documents/[documentId]/code-editor.tsx +12 -1
- package/examples/playground/app/documents/[documentId]/document-client.tsx +10 -11
- package/examples/playground/app/documents/[documentId]/page.tsx +1 -2
- package/examples/playground/app/documents/[documentId]/session.ts +2 -2
- package/examples/playground/app/documents/model.ts +27 -27
- package/examples/playground/app/globals.css +420 -207
- package/examples/playground/app/initial-state.test.tsx +54 -0
- package/examples/playground/app/layout.tsx +7 -23
- package/examples/playground/app/orders/[orderId]/page.tsx +1 -2
- package/examples/playground/app/orders/[orderId]/session.ts +2 -2
- package/examples/playground/app/orders/model.ts +49 -49
- package/examples/playground/app/page.tsx +13 -102
- package/examples/playground/app/recovery/[recoveryId]/page.tsx +1 -2
- package/examples/playground/app/recovery/[recoveryId]/session.ts +2 -2
- package/examples/playground/app/recovery/model.ts +30 -30
- package/examples/playground/instrumentation.ts +5 -0
- package/examples/playground/next.config.ts +17 -5
- package/examples/playground/package.json +13 -2
- package/examples/playground/scripts/a0-template.ts +77 -0
- package/examples/playground/vercel.json +36 -0
- package/package.json +29 -3
- package/src/actor-client.ts +16 -4
- package/src/actor-react.ts +25 -11
- package/src/actor-shared.ts +21 -6
- package/src/actor.ts +76 -31
- package/src/ai-agent-actions.ts +219 -0
- package/src/ai-agent.ts +2517 -0
- package/src/ai-app-state.ts +91 -0
- package/src/ai-client-state.ts +6 -3
- package/src/ai-client.ts +62 -0
- package/src/ai-context-schema.ts +25 -5
- package/src/ai-context.ts +90 -40
- package/src/ai-control-server.ts +92 -72
- package/src/ai-coordinator.ts +23 -22
- package/src/ai-fx.browser.ts +5 -0
- package/src/ai-fx.ts +833 -0
- package/src/ai-harness.ts +518 -0
- package/src/ai-message-base.ts +209 -0
- package/src/ai-message-projection.ts +262 -64
- package/src/ai-model-metadata.ts +11 -6
- package/src/ai-pi.browser.ts +5 -0
- package/src/ai-pi.ts +1263 -0
- package/src/ai-progress-batches.ts +26 -0
- package/src/ai-projector.ts +95 -14
- package/src/ai-react.ts +146 -0
- package/src/ai-sdk-step.ts +2 -2
- package/src/ai-server.browser.ts +2 -2
- package/src/ai-server.ts +23 -1965
- package/src/ai-stored-state.ts +48 -163
- package/src/ai.ts +339 -155
- package/src/bootstrap-stream.ts +72 -0
- package/src/bounded-cache.ts +55 -0
- package/src/client-render-session.ts +49 -0
- package/src/client.ts +688 -151
- package/src/contract.ts +92 -42
- package/src/deterministic-id.ts +37 -0
- package/src/equal-json.ts +32 -0
- package/src/errors.ts +13 -1
- package/src/index.ts +5 -1
- package/src/initial-snapshot.ts +39 -0
- package/src/internal.ts +52 -0
- package/src/libfx.d.ts +34 -0
- package/src/postgres-notification-scope.ts +14 -3
- package/src/react.ts +171 -206
- package/src/redis-http-reply.ts +256 -0
- package/src/redis-http-stream.ts +73 -0
- package/src/redis-http-subscriptions.ts +13 -5
- package/src/reducer-runtime.ts +52 -0
- package/src/reducer.ts +93 -11
- package/src/scheduler-qstash.ts +49 -20
- package/src/scheduler-task.ts +34 -2
- package/src/scheduler-vercel.ts +32 -84
- package/src/server-fetch.ts +139 -35
- package/src/server.ts +1133 -255
- package/src/session-clear.ts +23 -0
- package/src/session-socket.ts +154 -49
- package/src/sse.ts +71 -4
- package/src/store-memory.ts +252 -75
- package/src/store-polling.ts +18 -4
- package/src/store-postgres.ts +541 -114
- package/src/store-redis-core.ts +1450 -493
- package/src/store-redis-http.ts +18 -2
- package/src/store-redis-notify.ts +262 -85
- package/src/store-redis.ts +19 -9
- package/src/store-sqlite.ts +319 -45
- package/src/store.ts +79 -1
- package/src/stream-buffer.ts +43 -0
- package/src/telemetry.ts +14 -1
- package/src/wire.ts +241 -13
- package/dist/actor-ohPC-81x.d.ts.map +0 -1
- package/dist/actor-shared-B5tJfzt-.js.map +0 -1
- package/dist/ai-CrEf6p_W.d.ts.map +0 -1
- package/dist/ai-DgOBltJ_.js.map +0 -1
- package/dist/client-BYzHjkwU.js.map +0 -1
- package/dist/client-CzyacQpJ.d.ts.map +0 -1
- package/dist/contract-CKRg_E4q.js.map +0 -1
- package/dist/errors-DCk6ch5n.js.map +0 -1
- package/dist/errors-DvhSXnxk.d.ts.map +0 -1
- package/dist/internal-Dq2qYxou.js.map +0 -1
- package/dist/react.d.ts.map +0 -1
- package/dist/reducer-DEMjEY_O.js +0 -29
- package/dist/reducer-DEMjEY_O.js.map +0 -1
- package/dist/reducer-otzHjuJj.d.ts.map +0 -1
- package/dist/scheduler-task-BpzhPnRS.js.map +0 -1
- package/dist/server-BD5ckxZb.js.map +0 -1
- package/dist/server-DbD7IJVK.d.ts.map +0 -1
- package/dist/store-DyZM6fS5.d.ts.map +0 -1
- package/dist/store-polling-CmxUbV93.js.map +0 -1
- package/dist/store-redis-notify-BVLUfI3j.js +0 -1583
- package/dist/store-redis-notify-BVLUfI3j.js.map +0 -1
- package/dist/telemetry-B5jzpy6y.d.ts.map +0 -1
- package/dist/validate-XKT4FSNn.js +0 -30
- package/dist/validate-XKT4FSNn.js.map +0 -1
- package/dist/wire-BO5wWCb1.js.map +0 -1
- package/docs/concepts/01-contracts.mdx +0 -142
- package/docs/concepts/02-handlers.mdx +0 -284
- package/docs/concepts/03-durability.mdx +0 -314
- package/docs/concepts/04-state.mdx +0 -209
- package/docs/guides/01-timers.mdx +0 -185
- package/docs/guides/02-cancellation.mdx +0 -161
- package/docs/guides/03-react.mdx +0 -384
- package/docs/guides/04-local-first.mdx +0 -88
- package/docs/guides/05-production.mdx +0 -521
- package/docs/guides/06-ai-agents.mdx +0 -1318
- package/docs/guides/08-application-data.mdx +0 -113
- package/docs/guides/09-presence.mdx +0 -266
- package/docs/guides/10-transports.mdx +0 -221
- package/docs/reference/01-api.mdx +0 -1896
- package/docs/reference/02-errors.mdx +0 -149
- package/examples/playground/app/agent/[agentId]/compaction/route.ts +0 -14
- package/examples/playground/app/agent/compaction-settings.test.ts +0 -144
- package/examples/playground/app/agent/compaction-settings.ts +0 -49
- package/examples/playground/app/agent/compaction-timeline.test.ts +0 -377
- package/examples/playground/app/agent/compaction-timeline.ts +0 -208
- /package/docs/{concepts → contract}/meta.ts +0 -0
- /package/docs/{guides → server}/meta.ts +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ReactElement } from 'react'
|
|
2
|
+
import { beforeEach, expect, it, vi } from 'vitest'
|
|
3
|
+
import AgentPage from './agent/[agentId]/page'
|
|
4
|
+
import ChatPage from './chat/[chatId]/page'
|
|
5
|
+
|
|
6
|
+
const agentReads = vi.hoisted(() => ({
|
|
7
|
+
initial: { state: { agent: true }, index: 7 },
|
|
8
|
+
state: vi.fn<() => Promise<{ state: { agent: boolean }; index: number }>>(),
|
|
9
|
+
history: vi.fn<() => never>(),
|
|
10
|
+
}))
|
|
11
|
+
const reads = vi.hoisted(() => ({
|
|
12
|
+
initial: { state: { marker: true }, index: 42 },
|
|
13
|
+
state: vi.fn<() => Promise<{ state: { marker: boolean }; index: number }>>(),
|
|
14
|
+
history: vi.fn<() => never>(),
|
|
15
|
+
}))
|
|
16
|
+
vi.mock('./agent/server', () => ({ agentServer: { session: () => reads } }))
|
|
17
|
+
vi.mock('./chat/server', () => ({
|
|
18
|
+
chatServer: { session: () => reads },
|
|
19
|
+
chatAgentServer: { session: () => agentReads },
|
|
20
|
+
}))
|
|
21
|
+
vi.mock('./agent/[agentId]/agent-client', () => ({ AgentClient: () => null }))
|
|
22
|
+
vi.mock('./chat/[chatId]/chat-client', () => ({ ChatClient: () => null }))
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
reads.state.mockReset().mockResolvedValue(reads.initial)
|
|
26
|
+
agentReads.state.mockReset().mockResolvedValue(agentReads.initial)
|
|
27
|
+
reads.history.mockReset().mockImplementation(() => {
|
|
28
|
+
throw new Error('unexpected history read')
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it.each(['agent', 'chat'] as const)(
|
|
33
|
+
'seeds %s from one state read without fetching raw history',
|
|
34
|
+
async (page) => {
|
|
35
|
+
const element = (await (page === 'agent'
|
|
36
|
+
? AgentPage({ params: Promise.resolve({ agentId: 'one' }) })
|
|
37
|
+
: ChatPage({
|
|
38
|
+
params: Promise.resolve({ chatId: 'one' }),
|
|
39
|
+
}))) as ReactElement<{ initial: unknown; initialEvents?: unknown }>
|
|
40
|
+
expect(reads.state).toHaveBeenCalledExactlyOnceWith()
|
|
41
|
+
expect(reads.history).not.toHaveBeenCalled()
|
|
42
|
+
expect(element.props.initial).toBe(reads.initial)
|
|
43
|
+
expect(element.props.initialEvents).toBeUndefined()
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
it("seeds the chat's agent session from its own state read", async () => {
|
|
48
|
+
const element = (await ChatPage({
|
|
49
|
+
params: Promise.resolve({ chatId: 'one' }),
|
|
50
|
+
})) as ReactElement<{ children: ReactElement<{ agentInitial: unknown }> }>
|
|
51
|
+
expect(agentReads.state).toHaveBeenCalledExactlyOnceWith()
|
|
52
|
+
expect(agentReads.history).not.toHaveBeenCalled()
|
|
53
|
+
expect(element.props.children.props.agentInitial).toBe(agentReads.initial)
|
|
54
|
+
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { Metadata } from 'next'
|
|
1
|
+
import type { Metadata, Viewport } from 'next'
|
|
2
2
|
import type { ReactNode } from 'react'
|
|
3
|
-
import
|
|
3
|
+
import { GeistMono } from 'geist/font/mono'
|
|
4
|
+
import { SiteHeader } from './components/site-header'
|
|
4
5
|
import './globals.css'
|
|
5
6
|
|
|
6
7
|
export const metadata: Metadata = {
|
|
@@ -9,35 +10,18 @@ export const metadata: Metadata = {
|
|
|
9
10
|
'A durable event log for serverless apps — counters, agents, orders, streaming, cancellation, multiplayer documents, and a shared canvas.',
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
export const viewport: Viewport = { colorScheme: 'light dark' }
|
|
14
|
+
|
|
12
15
|
export default function RootLayout({
|
|
13
16
|
children,
|
|
14
17
|
}: {
|
|
15
18
|
children: ReactNode
|
|
16
19
|
}): ReactNode {
|
|
17
20
|
return (
|
|
18
|
-
<html lang="en">
|
|
21
|
+
<html lang="en" className={GeistMono.variable}>
|
|
19
22
|
<body>
|
|
20
|
-
<
|
|
21
|
-
<nav>
|
|
22
|
-
<Link href="/" className="brand">
|
|
23
|
-
a2 <span>example</span>
|
|
24
|
-
</Link>
|
|
25
|
-
<Link href="/orders">Orders</Link>
|
|
26
|
-
<Link href="/chat">Chat</Link>
|
|
27
|
-
<Link href="/agent">Agent</Link>
|
|
28
|
-
<Link href="/canvas">Canvas</Link>
|
|
29
|
-
<Link href="/documents">Documents</Link>
|
|
30
|
-
<Link href="/recovery">Recovery</Link>
|
|
31
|
-
<Link href="/counter">Counter</Link>
|
|
32
|
-
</nav>
|
|
33
|
-
</header>
|
|
23
|
+
<SiteHeader />
|
|
34
24
|
<main>{children}</main>
|
|
35
|
-
<footer className="site-footer">
|
|
36
|
-
<p>
|
|
37
|
-
Everything on these pages is a fold over an append-only log — check{' '}
|
|
38
|
-
<code>.a2/dev.db</code>.
|
|
39
|
-
</p>
|
|
40
|
-
</footer>
|
|
41
25
|
</body>
|
|
42
26
|
</html>
|
|
43
27
|
)
|
|
@@ -20,8 +20,7 @@ export default async function OrderPage({
|
|
|
20
20
|
<SessionProvider
|
|
21
21
|
sessionId={decodeURIComponent(orderId)}
|
|
22
22
|
api="/orders/events"
|
|
23
|
-
|
|
24
|
-
initialIndex={index}
|
|
23
|
+
initial={{ state: state, index: index }}
|
|
25
24
|
>
|
|
26
25
|
<OrderClient sessionId={decodeURIComponent(orderId)} />
|
|
27
26
|
</SessionProvider>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* pair. Nothing in this file touches the machine module.
|
|
5
5
|
*/
|
|
6
6
|
import { createReact } from 'experimental-a2/react'
|
|
7
|
-
import {
|
|
7
|
+
import { orders } from '../model'
|
|
8
8
|
|
|
9
9
|
export const { SessionProvider, useSession } = createReact({
|
|
10
|
-
|
|
10
|
+
contract: orders,
|
|
11
11
|
})
|
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
import * as a2 from 'experimental-a2'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
|
-
export const orders = a2.contract({
|
|
5
|
-
name: 'orders',
|
|
6
|
-
events: {
|
|
7
|
-
created: z.object({
|
|
8
|
-
shopId: z.string(),
|
|
9
|
-
items: z.array(z.string()).min(1),
|
|
10
|
-
}),
|
|
11
|
-
'shop.notified': z.object({}),
|
|
12
|
-
'shop.started': z.object({}),
|
|
13
|
-
'driver.notified': z.object({ driverId: z.string() }),
|
|
14
|
-
'courier.picked_up': z.object({ etaMinutes: z.number().int().positive() }),
|
|
15
|
-
delivered: z.object({}),
|
|
16
|
-
},
|
|
17
|
-
})
|
|
18
|
-
|
|
19
4
|
const orderState = z.object({
|
|
20
5
|
status: z.enum([
|
|
21
6
|
'new',
|
|
@@ -34,8 +19,21 @@ const orderState = z.object({
|
|
|
34
19
|
|
|
35
20
|
export type OrderState = z.output<typeof orderState>
|
|
36
21
|
|
|
37
|
-
export const
|
|
38
|
-
|
|
22
|
+
export const orders = a2.contract({
|
|
23
|
+
name: 'orders',
|
|
24
|
+
events: {
|
|
25
|
+
created: z.object({
|
|
26
|
+
shopId: z.string(),
|
|
27
|
+
items: z.array(z.string()).min(1),
|
|
28
|
+
}),
|
|
29
|
+
'shop.notified': z.object({}),
|
|
30
|
+
'shop.started': z.object({}),
|
|
31
|
+
'driver.notified': z.object({ driverId: z.string() }),
|
|
32
|
+
'courier.picked_up': z.object({ etaMinutes: z.number().int().positive() }),
|
|
33
|
+
delivered: z.object({}),
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
reducer: {
|
|
39
37
|
name: 'order-status',
|
|
40
38
|
initialState: {
|
|
41
39
|
status: 'new',
|
|
@@ -45,35 +43,37 @@ export const ordersReducer = orders
|
|
|
45
43
|
etaMinutes: null,
|
|
46
44
|
},
|
|
47
45
|
stateSchema: orderState,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
}
|
|
46
|
+
fold: (state, event): OrderState => {
|
|
47
|
+
switch (event.type) {
|
|
48
|
+
case 'created':
|
|
49
|
+
return {
|
|
50
|
+
...state,
|
|
51
|
+
status: 'created',
|
|
52
|
+
shopId: event.payload.shopId,
|
|
53
|
+
items: event.payload.items,
|
|
54
|
+
}
|
|
55
|
+
case 'shop.notified':
|
|
56
|
+
return { ...state, status: 'notified' }
|
|
57
|
+
case 'shop.started':
|
|
58
|
+
return { ...state, status: 'preparing' }
|
|
59
|
+
case 'driver.notified':
|
|
60
|
+
return {
|
|
61
|
+
...state,
|
|
62
|
+
status: 'courier-assigned',
|
|
63
|
+
driverId: event.payload.driverId,
|
|
64
|
+
}
|
|
65
|
+
case 'courier.picked_up':
|
|
66
|
+
return {
|
|
67
|
+
...state,
|
|
68
|
+
status: 'delivering',
|
|
69
|
+
etaMinutes: event.payload.etaMinutes,
|
|
70
|
+
}
|
|
71
|
+
case 'delivered':
|
|
72
|
+
return { ...state, status: 'delivered', etaMinutes: null }
|
|
73
|
+
default:
|
|
74
|
+
return state
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
export const ordersReducer = orders.reducer
|
|
@@ -1,111 +1,22 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
|
-
import
|
|
2
|
+
import { FastLink } from './components/fast-link'
|
|
3
|
+
import { demos } from './components/demos'
|
|
3
4
|
|
|
4
5
|
export default function HomePage(): ReactNode {
|
|
5
6
|
return (
|
|
6
7
|
<article>
|
|
7
|
-
<h1>A durable event log
|
|
8
|
-
<p className="lede">
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<h2>Order tracker</h2>
|
|
17
|
-
<p>
|
|
18
|
-
A form appends <code>created</code>, and handlers chain the rest —
|
|
19
|
-
shop notified, courier assigned, picked up, delivered — while the
|
|
20
|
-
page watches over a live stream. One optimistic click, then the
|
|
21
|
-
order runs itself to the end.
|
|
22
|
-
</p>
|
|
23
|
-
</Link>
|
|
24
|
-
<Link className="card" href="/chat">
|
|
25
|
-
<h2>Multiplayer chat + agent</h2>
|
|
26
|
-
<p>
|
|
27
|
-
Messages, “is typing…” presence, and an AI participant share one
|
|
28
|
-
stream. Mention <code>@agent</code>, or enable ambient mode for the
|
|
29
|
-
room. The model can stay silent or call a durable <code>post</code>{' '}
|
|
30
|
-
tool; its private generation appears only as “thinking” or
|
|
31
|
-
“writing.”
|
|
32
|
-
</p>
|
|
33
|
-
</Link>
|
|
34
|
-
<Link className="card" href="/agent">
|
|
35
|
-
<h2>Agent</h2>
|
|
36
|
-
<p>
|
|
37
|
-
A durable AI agent inspects a service, records tool calls, pauses
|
|
38
|
-
for approval, runs Bash in a persistent Vercel Sandbox, and sets
|
|
39
|
-
reminders that return as new user messages. Messages, progress,
|
|
40
|
-
tools, timers, and the human decision are all ordinary A2 events.
|
|
41
|
-
</p>
|
|
42
|
-
</Link>
|
|
43
|
-
<Link className="card" href="/canvas">
|
|
44
|
-
<h2>Multiplayer canvas</h2>
|
|
45
|
-
<p>
|
|
46
|
-
Shapes are durable events you can scrub back through after the
|
|
47
|
-
server snapshot. Cursors and drag ghosts are presence: replicated
|
|
48
|
-
live, stored never.
|
|
49
|
-
</p>
|
|
50
|
-
</Link>
|
|
51
|
-
<Link className="card" href="/documents">
|
|
52
|
-
<h2>Multiplayer document</h2>
|
|
53
|
-
<p>
|
|
54
|
-
Two CodeMirror editors share one Yjs document. A2 durably orders the
|
|
55
|
-
CRDT updates while Yjs Awareness — live cursors and selections —
|
|
56
|
-
rides the session's presence plane, never touching the log.
|
|
57
|
-
</p>
|
|
58
|
-
</Link>
|
|
59
|
-
<Link className="card" href="/recovery">
|
|
60
|
-
<h2>Cross-invocation recovery</h2>
|
|
61
|
-
<p>
|
|
62
|
-
Chain four 8-second handlers under a 20-second function limit, then
|
|
63
|
-
watch Vercel stop one mid-handler and A2 retry that pending event
|
|
64
|
-
under a fresh claim.
|
|
65
|
-
</p>
|
|
66
|
-
</Link>
|
|
67
|
-
<Link className="card" href="/vault">
|
|
68
|
-
<h2>Vault (actor)</h2>
|
|
69
|
-
<p>
|
|
70
|
-
A durable actor: send messages to one vault's mailbox, watch it
|
|
71
|
-
process them one at a time against its state — serialized
|
|
72
|
-
read-modify-write, refusals as answers, and the whole transcript in
|
|
73
|
-
the log. Built on <code>experimental-a2/actor</code>.
|
|
74
|
-
</p>
|
|
75
|
-
</Link>
|
|
76
|
-
<Link className="card" href="/counter">
|
|
77
|
-
<h2>Counter</h2>
|
|
78
|
-
<p>
|
|
79
|
-
Increment and decrement one shared value. Every click is a durable
|
|
80
|
-
event applied optimistically in the browser, then confirmed by the
|
|
81
|
-
stream — open two tabs and watch both folds converge.
|
|
82
|
-
</p>
|
|
83
|
-
</Link>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<section>
|
|
87
|
-
<h2>Where things live</h2>
|
|
88
|
-
<ul>
|
|
89
|
-
<li>
|
|
90
|
-
Each demo owns a <code>model.ts</code> with its contract, reducer,
|
|
91
|
-
and shared types.
|
|
92
|
-
</li>
|
|
93
|
-
<li>
|
|
94
|
-
Its <code>server.ts</code> implements handlers and configures the
|
|
95
|
-
production store and scheduler it actually needs.
|
|
96
|
-
</li>
|
|
97
|
-
<li>
|
|
98
|
-
Its <code>events/route.ts</code> exposes <code>server.fetch</code>{' '}
|
|
99
|
-
directly, adding only feature-specific authorization or WebSocket
|
|
100
|
-
capabilities.
|
|
101
|
-
</li>
|
|
102
|
-
<li>
|
|
103
|
-
Demos with handlers or timers own a private{' '}
|
|
104
|
-
<code>scheduler/route.ts</code> and queue topic. Counter, canvas,
|
|
105
|
-
and documents need no scheduler.
|
|
8
|
+
<h1>A durable event log</h1>
|
|
9
|
+
<p className="lede">Every demo here is a fold over an append-only log.</p>
|
|
10
|
+
<ul className="app-grid" aria-label="Demos">
|
|
11
|
+
{demos.map((demo) => (
|
|
12
|
+
<li key={demo.href}>
|
|
13
|
+
<FastLink href={demo.href} className="app-tile">
|
|
14
|
+
<span className="app-icon">{demo.icon}</span>
|
|
15
|
+
<span>{demo.name}</span>
|
|
16
|
+
</FastLink>
|
|
106
17
|
</li>
|
|
107
|
-
|
|
108
|
-
</
|
|
18
|
+
))}
|
|
19
|
+
</ul>
|
|
109
20
|
</article>
|
|
110
21
|
)
|
|
111
22
|
}
|
|
@@ -19,8 +19,7 @@ export default async function RecoveryRunPage({
|
|
|
19
19
|
<SessionProvider
|
|
20
20
|
sessionId={sessionId}
|
|
21
21
|
api="/recovery/events"
|
|
22
|
-
|
|
23
|
-
initialIndex={index}
|
|
22
|
+
initial={{ state: state, index: index }}
|
|
24
23
|
>
|
|
25
24
|
<RecoveryClient
|
|
26
25
|
sessionId={sessionId}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { createReact } from 'experimental-a2/react'
|
|
3
|
-
import {
|
|
3
|
+
import { recovery } from '../model'
|
|
4
4
|
|
|
5
5
|
export const { SessionProvider, useSession } = createReact({
|
|
6
|
-
|
|
6
|
+
contract: recovery,
|
|
7
7
|
})
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import * as a2 from 'experimental-a2'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
|
+
const recoveryState = z.object({
|
|
5
|
+
phase: z.enum(['idle', 'running', 'completed']),
|
|
6
|
+
stepCount: z.number().int().positive().nullable(),
|
|
7
|
+
stepDurationSeconds: z.number().int().positive().nullable(),
|
|
8
|
+
completedSteps: z.number().int().nonnegative(),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
export type RecoveryState = z.output<typeof recoveryState>
|
|
12
|
+
|
|
4
13
|
export const recovery = a2.contract({
|
|
5
14
|
name: 'recovery',
|
|
6
15
|
events: {
|
|
@@ -14,19 +23,8 @@ export const recovery = a2.contract({
|
|
|
14
23
|
}),
|
|
15
24
|
'pipeline.completed': z.object({ stepCount: z.literal(4) }),
|
|
16
25
|
},
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
const recoveryState = z.object({
|
|
20
|
-
phase: z.enum(['idle', 'running', 'completed']),
|
|
21
|
-
stepCount: z.number().int().positive().nullable(),
|
|
22
|
-
stepDurationSeconds: z.number().int().positive().nullable(),
|
|
23
|
-
completedSteps: z.number().int().nonnegative(),
|
|
24
|
-
})
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export const recoveryReducer = recovery
|
|
29
|
-
.reducer({
|
|
27
|
+
reducer: {
|
|
30
28
|
name: 'recovery',
|
|
31
29
|
initialState: {
|
|
32
30
|
phase: 'idle',
|
|
@@ -35,21 +33,23 @@ export const recoveryReducer = recovery
|
|
|
35
33
|
completedSteps: 0,
|
|
36
34
|
},
|
|
37
35
|
stateSchema: recoveryState,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
}
|
|
36
|
+
fold: (state, event): RecoveryState => {
|
|
37
|
+
switch (event.type) {
|
|
38
|
+
case 'pipeline.started':
|
|
39
|
+
return {
|
|
40
|
+
...state,
|
|
41
|
+
phase: 'running',
|
|
42
|
+
stepCount: event.payload.stepCount,
|
|
43
|
+
stepDurationSeconds: event.payload.stepDurationSeconds,
|
|
44
|
+
}
|
|
45
|
+
case 'step.completed':
|
|
46
|
+
return { ...state, completedSteps: event.payload.step }
|
|
47
|
+
case 'pipeline.completed':
|
|
48
|
+
return { ...state, phase: 'completed' }
|
|
49
|
+
default:
|
|
50
|
+
return state
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
export const recoveryReducer = recovery.reducer
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// output tracing stays scoped without externalizing anything; and
|
|
1
|
+
// experimental-a2/server is a separate server-only entry point, so client
|
|
2
|
+
// bundles never reach a store backend; the sqlite dev default carries its own
|
|
3
|
+
// turbopackIgnore annotation in a2's dist, so output tracing stays scoped; and
|
|
5
4
|
// Next 16 transpiles this file with the TS7 (tsgo) compiler.
|
|
6
5
|
import type { NextConfig } from 'next'
|
|
7
6
|
|
|
8
|
-
const nextConfig: NextConfig = {
|
|
7
|
+
const nextConfig: NextConfig = {
|
|
8
|
+
// libfx loads a native binary for the platform, falling back to its
|
|
9
|
+
// WebAssembly, by paths the bundler cannot follow; Node loads both from
|
|
10
|
+
// node_modules at runtime.
|
|
11
|
+
serverExternalPackages: ['libfx'],
|
|
12
|
+
turbopack: {
|
|
13
|
+
// WebAssembly Pi's code reaches that the bundler cannot trace.
|
|
14
|
+
resolveAlias: {
|
|
15
|
+
'@silvia-odwyer/photon-node': './app/a0/no-photon.cjs',
|
|
16
|
+
'quickjs-wasi': './app/a0/no-quickjs.cjs',
|
|
17
|
+
'quickjs-wasi/quickjs.wasm': './app/a0/no-quickjs.cjs',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
}
|
|
9
21
|
|
|
10
22
|
export default nextConfig
|
|
@@ -12,18 +12,27 @@
|
|
|
12
12
|
"dev": "next dev",
|
|
13
13
|
"build": "next build",
|
|
14
14
|
"test": "vitest run",
|
|
15
|
-
"typecheck": "tsc --noEmit"
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"a0:template": "node --env-file-if-exists=.env.local scripts/a0-template.ts"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
19
|
+
"@ai-sdk/otel": "1.0.58",
|
|
18
20
|
"@codemirror/state": "^6.7.1",
|
|
19
21
|
"@codemirror/view": "^6.43.8",
|
|
22
|
+
"@earendil-works/pi-ai": "1.0.3",
|
|
23
|
+
"@earendil-works/pi-coding-agent": "1.0.2",
|
|
24
|
+
"@opentelemetry/api": "^1.9.0",
|
|
20
25
|
"@vercel/functions": "^3.9.3",
|
|
26
|
+
"@vercel/otel": "^2.1.0",
|
|
21
27
|
"@vercel/queue": "^0.2.0",
|
|
22
28
|
"@vercel/sandbox": "^3.0.0",
|
|
23
29
|
"ai": "^7.0.58",
|
|
24
30
|
"codemirror": "^6.0.2",
|
|
25
|
-
"experimental-a2": "0.
|
|
31
|
+
"experimental-a2": "0.18.0",
|
|
32
|
+
"geist": "^1.7.2",
|
|
26
33
|
"ioredis": "^5.9.0",
|
|
34
|
+
"libfx": "0.0.12",
|
|
35
|
+
"lucide-react": "^1.34.0",
|
|
27
36
|
"next": "^16.3.0",
|
|
28
37
|
"pg": "^8.16.0",
|
|
29
38
|
"react": "^19.0.0",
|
|
@@ -36,6 +45,8 @@
|
|
|
36
45
|
"zod": "^4.4.3"
|
|
37
46
|
},
|
|
38
47
|
"devDependencies": {
|
|
48
|
+
"@opentelemetry/context-async-hooks": "^2.0.0",
|
|
49
|
+
"@opentelemetry/sdk-trace-base": "^2.0.0",
|
|
39
50
|
"@testing-library/react": "^16.1.0",
|
|
40
51
|
"jsdom": "^26.0.0",
|
|
41
52
|
"@types/node": "^24.0.0",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds A0's template: a sandbox with a blank Next.js app, its
|
|
3
|
+
* dependencies installed and its dev cache warm, snapshotted with no
|
|
4
|
+
* expiry. Prints the snapshot id to set as A0_TEMPLATE_SNAPSHOT_ID.
|
|
5
|
+
*
|
|
6
|
+
* pnpm --filter playground a0:template
|
|
7
|
+
*
|
|
8
|
+
* Run it again when the recipe changes, then update the variable.
|
|
9
|
+
*/
|
|
10
|
+
import { Sandbox } from '@vercel/sandbox'
|
|
11
|
+
|
|
12
|
+
const appDir = '/vercel/app'
|
|
13
|
+
const appPort = 3000
|
|
14
|
+
|
|
15
|
+
const RECIPE = `set -e
|
|
16
|
+
cd /vercel
|
|
17
|
+
npx --yes create-next-app@latest app --yes --use-npm --disable-git
|
|
18
|
+
cd ${appDir}
|
|
19
|
+
rm -f public/*.svg
|
|
20
|
+
cat > next.config.ts <<'EOF'
|
|
21
|
+
import type { NextConfig } from 'next'
|
|
22
|
+
|
|
23
|
+
// The preview is served from the sandbox's public *.vercel.run host.
|
|
24
|
+
const nextConfig: NextConfig = { allowedDevOrigins: ['*.vercel.run'] }
|
|
25
|
+
|
|
26
|
+
export default nextConfig
|
|
27
|
+
EOF
|
|
28
|
+
cat > app/globals.css <<'EOF'
|
|
29
|
+
@import 'tailwindcss';
|
|
30
|
+
EOF
|
|
31
|
+
cat > app/layout.tsx <<'EOF'
|
|
32
|
+
import type { Metadata } from 'next'
|
|
33
|
+
import './globals.css'
|
|
34
|
+
|
|
35
|
+
export const metadata: Metadata = { title: 'App' }
|
|
36
|
+
|
|
37
|
+
export default function RootLayout({
|
|
38
|
+
children,
|
|
39
|
+
}: Readonly<{ children: React.ReactNode }>) {
|
|
40
|
+
return (
|
|
41
|
+
<html lang="en">
|
|
42
|
+
<body>{children}</body>
|
|
43
|
+
</html>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
EOF
|
|
47
|
+
cat > app/page.tsx <<'EOF'
|
|
48
|
+
export default function Home() {
|
|
49
|
+
return <main />
|
|
50
|
+
}
|
|
51
|
+
EOF
|
|
52
|
+
# Warms the dev cache: next dev compiles the page once, then stops with the
|
|
53
|
+
# snapshot. setsid -f keeps the command from waiting on the server.
|
|
54
|
+
setsid -f npm run dev -- --port ${appPort} > /tmp/next.log 2>&1 < /dev/null
|
|
55
|
+
timeout 120 bash -c 'until curl -sf localhost:${appPort} > /dev/null; do sleep 1; done'`
|
|
56
|
+
|
|
57
|
+
// The snapshot outlives its builder, so nothing but the snapshot stays.
|
|
58
|
+
const builder = await Sandbox.create({
|
|
59
|
+
persistent: false,
|
|
60
|
+
timeout: 10 * 60 * 1000,
|
|
61
|
+
})
|
|
62
|
+
try {
|
|
63
|
+
const result = await builder.runCommand({
|
|
64
|
+
cmd: 'bash',
|
|
65
|
+
args: ['-lc', RECIPE],
|
|
66
|
+
})
|
|
67
|
+
if (result.exitCode !== 0) {
|
|
68
|
+
const output = await result.output('both')
|
|
69
|
+
throw new Error(
|
|
70
|
+
`The template didn't build (exit ${result.exitCode}):\n${output.slice(-2000)}`,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
const { snapshotId } = await builder.snapshot({ expiration: 0 })
|
|
74
|
+
process.stdout.write(`A0_TEMPLATE_SNAPSHOT_ID=${snapshotId}\n`)
|
|
75
|
+
} finally {
|
|
76
|
+
await builder.delete().catch(() => {})
|
|
77
|
+
}
|
|
@@ -35,6 +35,42 @@
|
|
|
35
35
|
"retryAfterSeconds": 30
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
|
+
},
|
|
39
|
+
"app/a0/scheduler/route.ts": {
|
|
40
|
+
"experimentalTriggers": [
|
|
41
|
+
{
|
|
42
|
+
"type": "queue/v2beta",
|
|
43
|
+
"topic": "a2-a0",
|
|
44
|
+
"retryAfterSeconds": 30
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"app/a0/fx/scheduler/route.ts": {
|
|
49
|
+
"experimentalTriggers": [
|
|
50
|
+
{
|
|
51
|
+
"type": "queue/v2beta",
|
|
52
|
+
"topic": "a2-a0-fx",
|
|
53
|
+
"retryAfterSeconds": 30
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"app/a0/pi/scheduler/route.ts": {
|
|
58
|
+
"experimentalTriggers": [
|
|
59
|
+
{
|
|
60
|
+
"type": "queue/v2beta",
|
|
61
|
+
"topic": "a2-a0-pi",
|
|
62
|
+
"retryAfterSeconds": 30
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"app/a0/sandboxes/scheduler/route.ts": {
|
|
67
|
+
"experimentalTriggers": [
|
|
68
|
+
{
|
|
69
|
+
"type": "queue/v2beta",
|
|
70
|
+
"topic": "a2-a0-sandboxes",
|
|
71
|
+
"retryAfterSeconds": 30
|
|
72
|
+
}
|
|
73
|
+
]
|
|
38
74
|
}
|
|
39
75
|
}
|
|
40
76
|
}
|