experimental-a2 0.16.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +352 -0
- package/dist/{actor-ohPC-81x.d.ts → actor-DBbe5xeE.d.ts} +21 -11
- package/dist/actor-DBbe5xeE.d.ts.map +1 -0
- package/dist/actor-client.d.ts +2 -5
- package/dist/actor-client.d.ts.map +1 -1
- package/dist/actor-client.js +13 -4
- package/dist/actor-client.js.map +1 -1
- package/dist/actor-react.d.ts +5 -3
- package/dist/actor-react.d.ts.map +1 -1
- package/dist/actor-react.js +20 -10
- package/dist/actor-react.js.map +1 -1
- package/dist/{actor-shared-B5tJfzt-.js → actor-shared-t7w8xIKP.js} +12 -7
- package/dist/actor-shared-t7w8xIKP.js.map +1 -0
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +42 -23
- package/dist/actor.js.map +1 -1
- package/dist/{ai-DgOBltJ_.js → ai-UrWfKeuv.js} +621 -216
- package/dist/ai-UrWfKeuv.js.map +1 -0
- package/dist/ai-client.d.ts +27 -0
- package/dist/ai-client.d.ts.map +1 -0
- package/dist/ai-client.js +29 -0
- package/dist/ai-client.js.map +1 -0
- package/dist/ai-react.d.ts +96 -0
- package/dist/ai-react.d.ts.map +1 -0
- package/dist/ai-react.js +142 -0
- package/dist/ai-react.js.map +1 -0
- package/dist/ai-server.browser.js +2 -2
- package/dist/ai-server.browser.js.map +1 -1
- package/dist/ai-server.d.ts +80 -36
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +432 -258
- package/dist/ai-server.js.map +1 -1
- package/dist/{ai-CrEf6p_W.d.ts → ai-vpGtcaCB.d.ts} +114 -100
- package/dist/ai-vpGtcaCB.d.ts.map +1 -0
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +2 -2
- package/dist/{client-BYzHjkwU.js → client-COaiaDub.js} +447 -80
- package/dist/client-COaiaDub.js.map +1 -0
- package/dist/{client-CzyacQpJ.d.ts → client-qRnRUzBS.d.ts} +14 -13
- package/dist/client-qRnRUzBS.d.ts.map +1 -0
- package/dist/client.d.ts +4 -2
- package/dist/client.js +1 -1
- package/dist/{contract-CKRg_E4q.js → contract-BYKASlCV.js} +12 -21
- package/dist/contract-BYKASlCV.js.map +1 -0
- package/dist/{idempotent-replay-DVOlyYbx.js → idempotent-replay-JdgMQRRm.js} +2 -2
- package/dist/{idempotent-replay-DVOlyYbx.js.map → idempotent-replay-JdgMQRRm.js.map} +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/{errors-DvhSXnxk.d.ts → initial-snapshot-BrLso5x_.d.ts} +7 -3
- package/dist/initial-snapshot-BrLso5x_.d.ts.map +1 -0
- package/dist/{internal-Dq2qYxou.js → internal-CbVvEwad.js} +23 -2
- package/dist/internal-CbVvEwad.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/react-BbJ-g6Uu.d.ts +86 -0
- package/dist/react-BbJ-g6Uu.d.ts.map +1 -0
- package/dist/react.d.ts +2 -122
- package/dist/react.js +107 -100
- package/dist/react.js.map +1 -1
- package/dist/reducer-BAXc8JyF.js +87 -0
- package/dist/reducer-BAXc8JyF.js.map +1 -0
- package/dist/{reducer-otzHjuJj.d.ts → reducer-BYu6DT7h.d.ts} +45 -29
- package/dist/reducer-BYu6DT7h.d.ts.map +1 -0
- package/dist/reducer-runtime-DQwz_J59.js +28 -0
- package/dist/reducer-runtime-DQwz_J59.js.map +1 -0
- package/dist/scheduler-qstash.d.ts +3 -3
- package/dist/scheduler-qstash.d.ts.map +1 -1
- package/dist/scheduler-qstash.js +33 -10
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/{scheduler-task-BpzhPnRS.js → scheduler-task-X1SToDjP.js} +18 -3
- package/dist/scheduler-task-X1SToDjP.js.map +1 -0
- package/dist/scheduler-vercel.d.ts +4 -9
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +25 -44
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-DbD7IJVK.d.ts → server-CGM8WzRG.d.ts} +87 -26
- package/dist/server-CGM8WzRG.d.ts.map +1 -0
- package/dist/{server-BD5ckxZb.js → server-Rj64fNvX.js} +854 -202
- package/dist/server-Rj64fNvX.js.map +1 -0
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/{errors-DCk6ch5n.js → session-clear-DGI4jTQ5.js} +17 -2
- package/dist/session-clear-DGI4jTQ5.js.map +1 -0
- package/dist/session-clear-Dshpuhff.d.ts +12 -0
- package/dist/session-clear-Dshpuhff.d.ts.map +1 -0
- package/dist/{store-DyZM6fS5.d.ts → store-Gpkq7WBo.d.ts} +44 -3
- package/dist/store-Gpkq7WBo.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.d.ts.map +1 -1
- package/dist/store-memory.js +182 -69
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-CmxUbV93.js → store-polling-4_y8lETm.js} +21 -4
- package/dist/store-polling-4_y8lETm.js.map +1 -0
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +399 -108
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-C7-XZyW9.js → store-presence-polling-Q1C-k2dd.js} +3 -3
- package/dist/{store-presence-polling-C7-XZyW9.js.map → store-presence-polling-Q1C-k2dd.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.d.ts.map +1 -1
- package/dist/store-redis-http.js +293 -11
- package/dist/store-redis-http.js.map +1 -1
- package/dist/store-redis-notify-tqWNnMRu.js +2374 -0
- package/dist/store-redis-notify-tqWNnMRu.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.d.ts.map +1 -1
- package/dist/store-redis.js +11 -11
- package/dist/store-redis.js.map +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.d.ts.map +1 -1
- package/dist/store-sqlite.js +166 -32
- package/dist/store-sqlite.js.map +1 -1
- package/dist/stream-buffer-Cx7AAPGq.js +23 -0
- package/dist/stream-buffer-Cx7AAPGq.js.map +1 -0
- package/dist/{telemetry-B5jzpy6y.d.ts → telemetry-cZH-cibj.d.ts} +2 -2
- package/dist/telemetry-cZH-cibj.d.ts.map +1 -0
- package/dist/{wire-BO5wWCb1.js → wire-DjfHOvdW.js} +132 -10
- package/dist/wire-DjfHOvdW.js.map +1 -0
- package/docs/01-quickstart.mdx +2 -2
- package/docs/actors/01-introduction.mdx +4 -0
- package/docs/actors/04-routes.mdx +14 -1
- package/docs/concepts/01-contracts.mdx +95 -0
- package/docs/concepts/04-state.mdx +3 -3
- package/docs/guides/01-timers.mdx +22 -14
- package/docs/guides/02-cancellation.mdx +1 -1
- package/docs/guides/03-react.mdx +268 -328
- package/docs/guides/04-local-first.mdx +32 -73
- package/docs/guides/05-production.mdx +40 -27
- package/docs/guides/06-ai-agents.mdx +671 -581
- package/docs/guides/09-presence.mdx +3 -7
- package/docs/guides/10-transports.mdx +5 -5
- package/docs/index.mdx +10 -18
- package/docs/reference/01-api.mdx +656 -194
- package/docs/reference/02-errors.mdx +2 -1
- package/examples/playground/DEPLOY.md +52 -6
- package/examples/playground/app/a0/[appId]/loading.tsx +16 -0
- package/examples/playground/app/a0/[appId]/page.tsx +48 -0
- package/examples/playground/app/a0/a0.css +818 -0
- package/examples/playground/app/a0/app-list.tsx +211 -0
- package/examples/playground/app/a0/app-view.tsx +55 -0
- package/examples/playground/app/a0/apps/[appId]/preview/route.ts +27 -0
- package/examples/playground/app/a0/apps/[appId]/route.ts +23 -0
- package/examples/playground/app/a0/apps.test.ts +116 -0
- package/examples/playground/app/a0/apps.ts +87 -0
- package/examples/playground/app/a0/chat.tsx +364 -0
- package/examples/playground/app/a0/columns.tsx +109 -0
- package/examples/playground/app/a0/context-menu.tsx +116 -0
- package/examples/playground/app/a0/cookies.ts +46 -0
- package/examples/playground/app/a0/crash-on-request.ts +72 -0
- package/examples/playground/app/a0/crashes/route.ts +3 -0
- package/examples/playground/app/a0/crashes.test.ts +33 -0
- package/examples/playground/app/a0/crashes.ts +28 -0
- package/examples/playground/app/a0/devtools.tsx +164 -0
- package/examples/playground/app/a0/events/route.ts +6 -0
- package/examples/playground/app/a0/flags.ts +30 -0
- package/examples/playground/app/a0/layout.tsx +38 -0
- package/examples/playground/app/a0/list/route.ts +10 -0
- package/examples/playground/app/a0/model.test.ts +56 -0
- package/examples/playground/app/a0/model.ts +58 -0
- package/examples/playground/app/a0/page.tsx +14 -0
- package/examples/playground/app/a0/preview-pane.tsx +145 -0
- package/examples/playground/app/a0/preview.test.ts +53 -0
- package/examples/playground/app/a0/preview.ts +26 -0
- package/examples/playground/app/a0/sandbox-log.ts +69 -0
- package/examples/playground/app/a0/sandbox.ts +191 -0
- package/examples/playground/app/a0/sandboxes/scheduler/route.ts +6 -0
- package/examples/playground/app/a0/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/server.ts +158 -0
- package/examples/playground/app/a0/session.ts +47 -0
- package/examples/playground/app/a0/shell.tsx +150 -0
- package/examples/playground/app/a0/short/events/route.ts +9 -0
- package/examples/playground/app/a0/splitter.tsx +120 -0
- package/examples/playground/app/agent/[agentId]/agent-client.tsx +144 -174
- package/examples/playground/app/agent/[agentId]/command-receipt.test.tsx +65 -0
- package/examples/playground/app/agent/[agentId]/command-receipt.tsx +27 -0
- package/examples/playground/app/agent/[agentId]/compaction-event.tsx +25 -24
- package/examples/playground/app/agent/[agentId]/compaction-panel.test.tsx +119 -0
- package/examples/playground/app/agent/[agentId]/compaction-panel.tsx +208 -165
- package/examples/playground/app/agent/[agentId]/page.tsx +2 -16
- package/examples/playground/app/agent/events/route.ts +5 -2
- package/examples/playground/app/agent/ingress.test.ts +98 -0
- package/examples/playground/app/agent/model-input.test.tsx +58 -0
- package/examples/playground/app/agent/model-input.tsx +115 -0
- package/examples/playground/app/agent/model.test.ts +73 -0
- package/examples/playground/app/agent/model.ts +58 -26
- package/examples/playground/app/agent/new-agent-session.tsx +37 -19
- package/examples/playground/app/agent/page.tsx +4 -4
- package/examples/playground/app/agent/server.ts +15 -14
- package/examples/playground/app/agent/session.ts +5 -6
- package/examples/playground/app/agent/telemetry.test.ts +168 -0
- package/examples/playground/app/agent/telemetry.ts +30 -0
- package/examples/playground/app/agent/trace.test.ts +23 -0
- package/examples/playground/app/agent/trace.ts +18 -0
- package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +11 -11
- package/examples/playground/app/canvas/[canvasId]/page.tsx +1 -2
- package/examples/playground/app/canvas/[canvasId]/session.ts +2 -2
- package/examples/playground/app/canvas/model.ts +53 -53
- package/examples/playground/app/chat/[chatId]/agent-state.test.ts +176 -0
- package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +16 -1
- package/examples/playground/app/chat/[chatId]/chat-client.tsx +55 -77
- package/examples/playground/app/chat/[chatId]/chat-view.ts +37 -3
- package/examples/playground/app/chat/[chatId]/page.tsx +7 -15
- package/examples/playground/app/chat/[chatId]/session.ts +2 -19
- package/examples/playground/app/chat/agent/route.ts +9 -0
- package/examples/playground/app/chat/model.test.ts +46 -119
- package/examples/playground/app/chat/model.ts +82 -128
- package/examples/playground/app/chat/scheduler/route.ts +2 -2
- package/examples/playground/app/chat/server.test.ts +108 -0
- package/examples/playground/app/chat/server.ts +69 -73
- package/examples/playground/app/components/activity-feed.tsx +30 -1
- package/examples/playground/app/components/activity-history.test.tsx +35 -0
- package/examples/playground/app/components/demo-icons.tsx +89 -0
- package/examples/playground/app/components/demos.tsx +33 -0
- package/examples/playground/app/components/fast-link.test.tsx +58 -0
- package/examples/playground/app/components/fast-link.tsx +55 -0
- package/examples/playground/app/components/site-header.tsx +96 -0
- package/examples/playground/app/counter/counter-client.tsx +3 -3
- package/examples/playground/app/counter/model.test.ts +3 -3
- package/examples/playground/app/counter/model.ts +11 -21
- package/examples/playground/app/counter/page.tsx +2 -15
- package/examples/playground/app/counter/session.ts +2 -2
- package/examples/playground/app/documents/[documentId]/code-editor.tsx +12 -1
- package/examples/playground/app/documents/[documentId]/document-client.tsx +10 -11
- package/examples/playground/app/documents/[documentId]/page.tsx +1 -2
- package/examples/playground/app/documents/[documentId]/session.ts +2 -2
- package/examples/playground/app/documents/model.ts +27 -27
- package/examples/playground/app/globals.css +420 -207
- package/examples/playground/app/initial-state.test.tsx +54 -0
- package/examples/playground/app/layout.tsx +7 -23
- package/examples/playground/app/orders/[orderId]/page.tsx +1 -2
- package/examples/playground/app/orders/[orderId]/session.ts +2 -2
- package/examples/playground/app/orders/model.ts +49 -49
- package/examples/playground/app/page.tsx +13 -102
- package/examples/playground/app/recovery/[recoveryId]/page.tsx +1 -2
- package/examples/playground/app/recovery/[recoveryId]/session.ts +2 -2
- package/examples/playground/app/recovery/model.ts +30 -30
- package/examples/playground/instrumentation.ts +5 -0
- package/examples/playground/package.json +10 -2
- package/examples/playground/scripts/a0-template.ts +77 -0
- package/examples/playground/vercel.json +18 -0
- package/package.json +3 -1
- package/src/actor-client.ts +16 -4
- package/src/actor-react.ts +25 -11
- package/src/actor-shared.ts +21 -6
- package/src/actor.ts +76 -31
- package/src/ai-agent-actions.ts +219 -0
- package/src/ai-agent.ts +2343 -0
- package/src/ai-app-state.ts +91 -0
- package/src/ai-client-state.ts +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-message-base.ts +209 -0
- package/src/ai-message-projection.ts +262 -64
- package/src/ai-progress-batches.ts +26 -0
- package/src/ai-projector.ts +95 -14
- package/src/ai-react.ts +146 -0
- package/src/ai-server.browser.ts +2 -2
- package/src/ai-server.ts +20 -1964
- 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 +45 -0
- package/src/postgres-notification-scope.ts +14 -3
- package/src/react.ts +171 -206
- package/src/redis-http-reply.ts +256 -0
- package/src/redis-http-stream.ts +73 -0
- package/src/redis-http-subscriptions.ts +13 -5
- package/src/reducer-runtime.ts +52 -0
- package/src/reducer.ts +92 -10
- package/src/scheduler-qstash.ts +49 -20
- package/src/scheduler-task.ts +34 -2
- package/src/scheduler-vercel.ts +32 -84
- package/src/server-fetch.ts +139 -35
- package/src/server.ts +957 -237
- package/src/session-clear.ts +23 -0
- package/src/session-socket.ts +154 -49
- package/src/sse.ts +71 -4
- package/src/store-memory.ts +220 -78
- package/src/store-polling.ts +18 -4
- package/src/store-postgres.ts +461 -114
- package/src/store-redis-core.ts +1260 -434
- package/src/store-redis-http.ts +18 -2
- package/src/store-redis-notify.ts +260 -85
- package/src/store-redis.ts +19 -9
- package/src/store-sqlite.ts +259 -45
- package/src/store.ts +46 -1
- package/src/stream-buffer.ts +43 -0
- package/src/telemetry.ts +13 -1
- package/src/wire.ts +241 -13
- package/dist/actor-ohPC-81x.d.ts.map +0 -1
- package/dist/actor-shared-B5tJfzt-.js.map +0 -1
- package/dist/ai-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/examples/playground/app/agent/[agentId]/compaction/route.ts +0 -14
- package/examples/playground/app/agent/compaction-settings.test.ts +0 -144
- package/examples/playground/app/agent/compaction-settings.ts +0 -49
- package/examples/playground/app/agent/compaction-timeline.test.ts +0 -377
- package/examples/playground/app/agent/compaction-timeline.ts +0 -208
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
restoreMessageBase,
|
|
3
|
+
updateMessageBase,
|
|
4
|
+
type MessageBase,
|
|
5
|
+
} from './ai-message-base.ts'
|
|
1
6
|
import type { UIMessage, UIMessageChunk } from 'ai'
|
|
2
7
|
import type {
|
|
3
8
|
ActiveGenerationProjection,
|
|
4
9
|
AIState,
|
|
10
|
+
CompactionPart,
|
|
11
|
+
CompactionPartData,
|
|
12
|
+
CompactionRequestedPayload,
|
|
5
13
|
ApprovalRequestedPayload,
|
|
6
14
|
ApprovalRespondedPayload,
|
|
7
15
|
ToolCalledPayload,
|
|
@@ -10,6 +18,7 @@ import type {
|
|
|
10
18
|
} from './ai.ts'
|
|
11
19
|
import {
|
|
12
20
|
type UIMessageCursor,
|
|
21
|
+
type ProjectionChunk,
|
|
13
22
|
projectUIMessageStream,
|
|
14
23
|
interruptUIMessage,
|
|
15
24
|
} from './ai-projector.ts'
|
|
@@ -20,23 +29,26 @@ import {
|
|
|
20
29
|
type ProgressBatches,
|
|
21
30
|
} from './ai-progress-batches.ts'
|
|
22
31
|
|
|
23
|
-
export type MessageProjection
|
|
24
|
-
ActiveGenerationProjection<M>,
|
|
25
|
-
'baseTools'
|
|
26
|
-
>
|
|
32
|
+
export type MessageProjection = Omit<ActiveGenerationProjection, 'baseTools'>
|
|
27
33
|
|
|
28
34
|
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
29
35
|
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
30
36
|
|
|
37
|
+
const positionOf = (messages: readonly UIMessage[], id: string): number =>
|
|
38
|
+
messages.findLastIndex((message) => message.id === id)
|
|
39
|
+
|
|
40
|
+
export const findMessage = <M extends UIMessage>(
|
|
41
|
+
messages: M[],
|
|
42
|
+
id: string,
|
|
43
|
+
): M | undefined => messages.findLast((message) => message.id === id)
|
|
44
|
+
|
|
31
45
|
export const upsertMessage = <M extends UIMessage>(
|
|
32
46
|
messages: M[],
|
|
33
47
|
message: M,
|
|
34
48
|
): M[] => {
|
|
35
|
-
const index = messages
|
|
49
|
+
const index = positionOf(messages, message.id)
|
|
36
50
|
if (index === -1) return [...messages, message]
|
|
37
|
-
|
|
38
|
-
next[index] = message
|
|
39
|
-
return next
|
|
51
|
+
return messages[index] === message ? messages : messages.with(index, message)
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
export const upsertResponse = <M extends UIMessage>(options: {
|
|
@@ -45,15 +57,11 @@ export const upsertResponse = <M extends UIMessage>(options: {
|
|
|
45
57
|
inputId: string
|
|
46
58
|
}): M[] => {
|
|
47
59
|
const { messages, message, inputId } = options
|
|
48
|
-
if (messages
|
|
60
|
+
if (positionOf(messages, message.id) !== -1)
|
|
49
61
|
return upsertMessage(messages, message)
|
|
50
|
-
const inputIndex = messages
|
|
51
|
-
|
|
52
|
-
return [
|
|
53
|
-
...messages.slice(0, inputIndex + 1),
|
|
54
|
-
message,
|
|
55
|
-
...messages.slice(inputIndex + 1),
|
|
56
|
-
]
|
|
62
|
+
const inputIndex = positionOf(messages, inputId)
|
|
63
|
+
const position = inputIndex === -1 ? messages.length : inputIndex + 1
|
|
64
|
+
return [...messages.slice(0, position), message, ...messages.slice(position)]
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
export const answerApproval = <M extends UIMessage>(
|
|
@@ -108,6 +116,10 @@ export const approvalRespondedChunk = (
|
|
|
108
116
|
...(payload.reason === undefined ? {} : { reason: payload.reason }),
|
|
109
117
|
})
|
|
110
118
|
|
|
119
|
+
export const toolCalledChunk = (
|
|
120
|
+
payload: ToolCalledPayload,
|
|
121
|
+
): ProjectionChunk => ({ type: 'a2-tool-called', call: payload })
|
|
122
|
+
|
|
111
123
|
export const toolResultChunk = (payload: ToolResultPayload): UIMessageChunk => {
|
|
112
124
|
if (payload.phase === 'input') {
|
|
113
125
|
return {
|
|
@@ -171,17 +183,27 @@ export const toolResultChunk = (payload: ToolResultPayload): UIMessageChunk => {
|
|
|
171
183
|
} as UIMessageChunk
|
|
172
184
|
}
|
|
173
185
|
|
|
174
|
-
export const projectedMessageStream = <M extends UIMessage>(
|
|
175
|
-
projection
|
|
176
|
-
|
|
177
|
-
|
|
186
|
+
export const projectedMessageStream = <M extends UIMessage>({
|
|
187
|
+
projection,
|
|
188
|
+
current,
|
|
189
|
+
}: {
|
|
190
|
+
projection: MessageProjection
|
|
191
|
+
current: M | undefined
|
|
192
|
+
}): { message: M; cursor: UIMessageCursor; throughIndex: number } => {
|
|
193
|
+
const base = restoreMessageBase({ current, base: projection.base })
|
|
194
|
+
const projectionEvents: Array<{
|
|
195
|
+
index: number
|
|
196
|
+
chunks: readonly ProjectionChunk[]
|
|
197
|
+
}> = flattenProgressBatches(projection.batches)
|
|
178
198
|
for (const event of projection.toolEvents) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
projectionEvents.push({
|
|
200
|
+
index: event.index,
|
|
201
|
+
chunks: [
|
|
202
|
+
event.type === 'ai.tool.called'
|
|
203
|
+
? toolCalledChunk(event.payload)
|
|
204
|
+
: toolResultChunk(event.payload),
|
|
205
|
+
],
|
|
206
|
+
})
|
|
185
207
|
}
|
|
186
208
|
for (const event of projection.approvalEvents) {
|
|
187
209
|
projectionEvents.push({
|
|
@@ -193,20 +215,23 @@ export const projectedMessageStream = <M extends UIMessage>(
|
|
|
193
215
|
],
|
|
194
216
|
})
|
|
195
217
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
.flatMap((event) => event.chunks),
|
|
204
|
-
|
|
218
|
+
const ordered = projectionEvents.toSorted(
|
|
219
|
+
(left, right) => left.index - right.index,
|
|
220
|
+
)
|
|
221
|
+
return {
|
|
222
|
+
...projectUIMessageStream<M>({
|
|
223
|
+
messageId: projection.responseMessageId,
|
|
224
|
+
...(base === undefined ? {} : { base }),
|
|
225
|
+
chunks: ordered.flatMap((event) => event.chunks),
|
|
226
|
+
}),
|
|
227
|
+
throughIndex: ordered.at(-1)?.index ?? 0,
|
|
228
|
+
}
|
|
205
229
|
}
|
|
206
230
|
|
|
207
|
-
export const projectedMessage = <M extends UIMessage>(
|
|
208
|
-
projection: MessageProjection
|
|
209
|
-
|
|
231
|
+
export const projectedMessage = <M extends UIMessage>(options: {
|
|
232
|
+
projection: MessageProjection
|
|
233
|
+
current: M | undefined
|
|
234
|
+
}): M => projectedMessageStream(options).message
|
|
210
235
|
|
|
211
236
|
export const reduceToolActivity = (
|
|
212
237
|
tools: ToolActivity[],
|
|
@@ -216,12 +241,17 @@ export const reduceToolActivity = (
|
|
|
216
241
|
): ToolActivity[] => {
|
|
217
242
|
if (event.type === 'ai.tool.called') {
|
|
218
243
|
const payload = event.payload
|
|
219
|
-
const { providerMetadata, ...called } = payload
|
|
220
244
|
const activity: ToolActivity = {
|
|
221
|
-
|
|
222
|
-
|
|
245
|
+
requestId: payload.requestId,
|
|
246
|
+
messageId: payload.messageId,
|
|
247
|
+
generationId: payload.generationId,
|
|
248
|
+
toolCallId: payload.toolCallId,
|
|
249
|
+
toolName: payload.toolName,
|
|
250
|
+
...(payload.dynamic === undefined ? {} : { dynamic: payload.dynamic }),
|
|
251
|
+
...(payload.providerExecuted === undefined
|
|
223
252
|
? {}
|
|
224
|
-
: {
|
|
253
|
+
: { providerExecuted: payload.providerExecuted }),
|
|
254
|
+
...(payload.title === undefined ? {} : { title: payload.title }),
|
|
225
255
|
status: 'running',
|
|
226
256
|
}
|
|
227
257
|
return [
|
|
@@ -241,22 +271,15 @@ export const reduceToolActivity = (
|
|
|
241
271
|
candidate.toolCallId === payload.toolCallId,
|
|
242
272
|
)
|
|
243
273
|
const toolName = payload.toolName ?? existing?.toolName
|
|
244
|
-
const input = payload.input === undefined ? existing?.input : payload.input
|
|
245
274
|
const dynamic = payload.dynamic ?? existing?.dynamic
|
|
246
275
|
const providerExecuted =
|
|
247
276
|
payload.providerExecuted ?? existing?.providerExecuted
|
|
248
|
-
const toolMetadata = payload.toolMetadata ?? existing?.toolMetadata
|
|
249
|
-
const resultProviderMetadata =
|
|
250
|
-
payload.providerMetadata ?? existing?.resultProviderMetadata
|
|
251
277
|
const activity: ToolActivity = {
|
|
252
278
|
requestId: payload.requestId,
|
|
253
279
|
messageId: payload.messageId,
|
|
254
280
|
generationId: payload.generationId,
|
|
255
281
|
toolCallId: payload.toolCallId,
|
|
256
282
|
...(toolName === undefined ? {} : { toolName }),
|
|
257
|
-
...(input === undefined ? {} : { input }),
|
|
258
|
-
...(payload.rawInput === undefined ? {} : { rawInput: payload.rawInput }),
|
|
259
|
-
...(payload.output === undefined ? {} : { output: payload.output }),
|
|
260
283
|
...(payload.error === undefined ? {} : { error: payload.error }),
|
|
261
284
|
...(payload.preliminary === undefined
|
|
262
285
|
? {}
|
|
@@ -264,11 +287,6 @@ export const reduceToolActivity = (
|
|
|
264
287
|
...(payload.phase === undefined ? {} : { phase: payload.phase }),
|
|
265
288
|
...(dynamic === undefined ? {} : { dynamic }),
|
|
266
289
|
...(providerExecuted === undefined ? {} : { providerExecuted }),
|
|
267
|
-
...(existing?.callProviderMetadata === undefined
|
|
268
|
-
? {}
|
|
269
|
-
: { callProviderMetadata: existing.callProviderMetadata }),
|
|
270
|
-
...(resultProviderMetadata === undefined ? {} : { resultProviderMetadata }),
|
|
271
|
-
...(toolMetadata === undefined ? {} : { toolMetadata }),
|
|
272
290
|
...(existing?.title === undefined ? {} : { title: existing.title }),
|
|
273
291
|
status: payload.denied
|
|
274
292
|
? 'denied'
|
|
@@ -294,14 +312,14 @@ export const advanceProjection = <M extends UIMessage>({
|
|
|
294
312
|
chunks,
|
|
295
313
|
index,
|
|
296
314
|
}: {
|
|
297
|
-
projection: MessageProjection
|
|
315
|
+
projection: MessageProjection
|
|
298
316
|
base: M | undefined
|
|
299
317
|
chunks: UIMessageChunk[]
|
|
300
318
|
index: number
|
|
301
319
|
}): {
|
|
302
320
|
message: M
|
|
303
321
|
batches: ProgressBatches
|
|
304
|
-
cursor: NonNullable<MessageProjection
|
|
322
|
+
cursor: NonNullable<MessageProjection['cursor']>
|
|
305
323
|
} => {
|
|
306
324
|
const ordered = index > (projection.batches.tail.at(-1)?.index ?? -1)
|
|
307
325
|
const batches = ordered
|
|
@@ -328,7 +346,10 @@ export const advanceProjection = <M extends UIMessage>({
|
|
|
328
346
|
cursor: projection.cursor!.stream,
|
|
329
347
|
chunks,
|
|
330
348
|
})
|
|
331
|
-
: projectedMessageStream({
|
|
349
|
+
: projectedMessageStream({
|
|
350
|
+
projection: { ...projection, batches },
|
|
351
|
+
current: base,
|
|
352
|
+
})
|
|
332
353
|
return {
|
|
333
354
|
message: projected.message,
|
|
334
355
|
batches,
|
|
@@ -352,8 +373,8 @@ export const advanceProjection = <M extends UIMessage>({
|
|
|
352
373
|
}
|
|
353
374
|
}
|
|
354
375
|
|
|
355
|
-
export const projectedTools =
|
|
356
|
-
projection: ActiveGenerationProjection
|
|
376
|
+
export const projectedTools = (
|
|
377
|
+
projection: ActiveGenerationProjection,
|
|
357
378
|
): ToolActivity[] =>
|
|
358
379
|
projection.toolEvents.reduce(
|
|
359
380
|
(tools, event) => reduceToolActivity(tools, event),
|
|
@@ -370,12 +391,22 @@ export const restoreGenerationBase = <M extends UIMessage>(
|
|
|
370
391
|
state.activeProjection?.generationId === generationId
|
|
371
392
|
? state.activeProjection
|
|
372
393
|
: null
|
|
394
|
+
const restored = restoreMessageBase({
|
|
395
|
+
current: findMessage(state.messages, responseMessageId),
|
|
396
|
+
base: projection?.base,
|
|
397
|
+
})
|
|
398
|
+
// A superseded attempt's unfinished compaction reruns in its replacement;
|
|
399
|
+
// a completed one stays in effect, and so does its part.
|
|
400
|
+
const base =
|
|
401
|
+
restored !== undefined && reason === 'superseded'
|
|
402
|
+
? withoutRunningCompactionPart(restored, generationId)
|
|
403
|
+
: restored
|
|
373
404
|
return {
|
|
374
405
|
...state,
|
|
375
406
|
messages:
|
|
376
|
-
|
|
407
|
+
base === undefined
|
|
377
408
|
? state.messages.filter((message) => message.id !== responseMessageId)
|
|
378
|
-
: upsertMessage(state.messages,
|
|
409
|
+
: upsertMessage(state.messages, base),
|
|
379
410
|
tools:
|
|
380
411
|
projection === null
|
|
381
412
|
? state.tools.filter(
|
|
@@ -429,7 +460,7 @@ export const interruptGenerationProjection = <M extends UIMessage>(
|
|
|
429
460
|
? state.activeProjection
|
|
430
461
|
: null
|
|
431
462
|
if (projection === null) return null
|
|
432
|
-
const retained: ActiveGenerationProjection
|
|
463
|
+
const retained: ActiveGenerationProjection = {
|
|
433
464
|
...projection,
|
|
434
465
|
batches: progressBatches(
|
|
435
466
|
flattenProgressBatches(projection.batches).filter(
|
|
@@ -444,7 +475,7 @@ export const interruptGenerationProjection = <M extends UIMessage>(
|
|
|
444
475
|
),
|
|
445
476
|
}
|
|
446
477
|
const shouldProject =
|
|
447
|
-
retained.
|
|
478
|
+
retained.base !== undefined || retained.batches.length > 0
|
|
448
479
|
const restored = restoreGenerationBase(
|
|
449
480
|
state,
|
|
450
481
|
generationId,
|
|
@@ -456,7 +487,12 @@ export const interruptGenerationProjection = <M extends UIMessage>(
|
|
|
456
487
|
messages: shouldProject
|
|
457
488
|
? upsertMessage(
|
|
458
489
|
state.messages,
|
|
459
|
-
interruptUIMessage(
|
|
490
|
+
interruptUIMessage(
|
|
491
|
+
projectedMessage({
|
|
492
|
+
projection: retained,
|
|
493
|
+
current: findMessage(state.messages, responseMessageId),
|
|
494
|
+
}),
|
|
495
|
+
),
|
|
460
496
|
)
|
|
461
497
|
: restored.messages,
|
|
462
498
|
tools: stopGenerationTools(
|
|
@@ -472,3 +508,165 @@ export const interruptGenerationProjection = <M extends UIMessage>(
|
|
|
472
508
|
: restored.usage.filter((entry) => entry.generationId !== generationId),
|
|
473
509
|
}
|
|
474
510
|
}
|
|
511
|
+
|
|
512
|
+
export const retainMessageBase = <
|
|
513
|
+
S extends {
|
|
514
|
+
messages: UIMessage[]
|
|
515
|
+
activeProjection: { responseMessageId: string; base?: MessageBase } | null
|
|
516
|
+
},
|
|
517
|
+
>(options: {
|
|
518
|
+
before: S
|
|
519
|
+
after: S
|
|
520
|
+
}): S => {
|
|
521
|
+
const { before, after } = options
|
|
522
|
+
const projection = after.activeProjection
|
|
523
|
+
if (
|
|
524
|
+
before.messages === after.messages ||
|
|
525
|
+
!projection?.base ||
|
|
526
|
+
projection.base !== before.activeProjection?.base
|
|
527
|
+
)
|
|
528
|
+
return after
|
|
529
|
+
const previous = findMessage(before.messages, projection.responseMessageId)
|
|
530
|
+
const current = findMessage(after.messages, projection.responseMessageId)
|
|
531
|
+
if (previous !== undefined && previous === current) return after
|
|
532
|
+
// A response removed or rewritten outside this tracking (for example, by an
|
|
533
|
+
// extension's own transition) cannot be restored, so a later re-created
|
|
534
|
+
// message must not inherit the stale recovery.
|
|
535
|
+
const base =
|
|
536
|
+
previous &&
|
|
537
|
+
current &&
|
|
538
|
+
updateMessageBase({
|
|
539
|
+
base: projection.base,
|
|
540
|
+
before: previous,
|
|
541
|
+
after: current,
|
|
542
|
+
})
|
|
543
|
+
const { base: _stale, ...unrecoverable } = projection
|
|
544
|
+
return {
|
|
545
|
+
...after,
|
|
546
|
+
activeProjection: base ? { ...unrecoverable, base } : unrecoverable,
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export const isCompactionPart = (part: {
|
|
551
|
+
type: string
|
|
552
|
+
}): part is CompactionPart => part.type === 'data-a2-compaction'
|
|
553
|
+
|
|
554
|
+
const compactionPartOf = (message: UIMessage, generationId: string): number =>
|
|
555
|
+
message.parts.findIndex(
|
|
556
|
+
(part) => isCompactionPart(part) && part.id === generationId,
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
const withoutRunningCompactionPart = <M extends UIMessage>(
|
|
560
|
+
message: M,
|
|
561
|
+
generationId: string,
|
|
562
|
+
): M => {
|
|
563
|
+
const index = compactionPartOf(message, generationId)
|
|
564
|
+
const part = message.parts[index]
|
|
565
|
+
return part !== undefined &&
|
|
566
|
+
isCompactionPart(part) &&
|
|
567
|
+
part.data.status === 'running'
|
|
568
|
+
? { ...message, parts: message.parts.toSpliced(index, 1) }
|
|
569
|
+
: message
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Compaction runs before its model step streams, so the part lands between
|
|
574
|
+
* the response's earlier steps and this one. Counting it in the step's base
|
|
575
|
+
* keeps it through Stop cutoffs, failures, and retries of that step.
|
|
576
|
+
*/
|
|
577
|
+
export const addCompactionPart = <M extends UIMessage>(
|
|
578
|
+
state: AIState<M>,
|
|
579
|
+
payload: CompactionRequestedPayload,
|
|
580
|
+
): AIState<M> => {
|
|
581
|
+
const projection = state.activeProjection
|
|
582
|
+
if (projection?.generationId !== payload.generationId) return state
|
|
583
|
+
const current = findMessage(state.messages, projection.responseMessageId)
|
|
584
|
+
if (
|
|
585
|
+
current === undefined
|
|
586
|
+
? projection.base !== undefined
|
|
587
|
+
: projection.base?.partCount !== current.parts.length
|
|
588
|
+
)
|
|
589
|
+
return state
|
|
590
|
+
const inputTokens = payload.inputTokens ?? payload.inputTokenEstimate
|
|
591
|
+
const part: CompactionPart = {
|
|
592
|
+
type: 'data-a2-compaction',
|
|
593
|
+
id: payload.generationId,
|
|
594
|
+
data: {
|
|
595
|
+
status: 'running',
|
|
596
|
+
...(inputTokens === undefined ? {} : { inputTokens }),
|
|
597
|
+
...(payload.thresholdTokens === undefined
|
|
598
|
+
? {}
|
|
599
|
+
: { thresholdTokens: payload.thresholdTokens }),
|
|
600
|
+
},
|
|
601
|
+
}
|
|
602
|
+
const message = (
|
|
603
|
+
current === undefined
|
|
604
|
+
? { id: projection.responseMessageId, role: 'assistant', parts: [part] }
|
|
605
|
+
: { ...current, parts: [...current.parts, part] }
|
|
606
|
+
) as M
|
|
607
|
+
return {
|
|
608
|
+
...state,
|
|
609
|
+
messages: upsertResponse({
|
|
610
|
+
messages: state.messages,
|
|
611
|
+
message,
|
|
612
|
+
inputId: state.activeGeneration?.messageId ?? message.id,
|
|
613
|
+
}),
|
|
614
|
+
activeProjection: {
|
|
615
|
+
...projection,
|
|
616
|
+
cursor: null,
|
|
617
|
+
base:
|
|
618
|
+
projection.base === undefined
|
|
619
|
+
? { partCount: 1 }
|
|
620
|
+
: { ...projection.base, partCount: projection.base.partCount + 1 },
|
|
621
|
+
},
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export const settleCompactionPart = <M extends UIMessage>(options: {
|
|
626
|
+
state: AIState<M>
|
|
627
|
+
generationId: string
|
|
628
|
+
data: Partial<CompactionPartData>
|
|
629
|
+
}): AIState<M> => {
|
|
630
|
+
const { state, generationId, data } = options
|
|
631
|
+
const position = state.messages.findLastIndex(
|
|
632
|
+
(message) => compactionPartOf(message, generationId) !== -1,
|
|
633
|
+
)
|
|
634
|
+
if (position === -1) return state
|
|
635
|
+
const message = state.messages[position]!
|
|
636
|
+
const index = compactionPartOf(message, generationId)
|
|
637
|
+
const part = message.parts[index] as unknown as CompactionPart
|
|
638
|
+
return {
|
|
639
|
+
...state,
|
|
640
|
+
messages: state.messages.with(position, {
|
|
641
|
+
...message,
|
|
642
|
+
parts: message.parts.with(index, {
|
|
643
|
+
...part,
|
|
644
|
+
data: { ...part.data, ...data },
|
|
645
|
+
} as unknown as M['parts'][number]),
|
|
646
|
+
}),
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/** A running compaction whose state reverted without completing was abandoned. */
|
|
651
|
+
export const settleAbandonedCompaction = <M extends UIMessage>(
|
|
652
|
+
before: AIState<M>,
|
|
653
|
+
after: AIState<M>,
|
|
654
|
+
): AIState<M> => {
|
|
655
|
+
const running = before.compaction
|
|
656
|
+
if (
|
|
657
|
+
running?.status !== 'running' ||
|
|
658
|
+
after.compaction === running ||
|
|
659
|
+
(after.compaction?.status === 'completed' &&
|
|
660
|
+
after.compaction.generationId === running.generationId)
|
|
661
|
+
)
|
|
662
|
+
return after
|
|
663
|
+
const interrupted =
|
|
664
|
+
after.status === 'closed' ||
|
|
665
|
+
after.pausedGenerationIds?.[running.generationId] === true ||
|
|
666
|
+
after.terminalGenerations?.[running.generationId] === 'interrupted'
|
|
667
|
+
return settleCompactionPart({
|
|
668
|
+
state: after,
|
|
669
|
+
generationId: running.generationId,
|
|
670
|
+
data: { status: interrupted ? 'interrupted' : 'failed' },
|
|
671
|
+
})
|
|
672
|
+
}
|
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
import type { UIMessageChunk } from 'ai'
|
|
2
|
+
import type { GenerationProgressPayload } from './ai.ts'
|
|
3
|
+
|
|
4
|
+
/** Progress already in a log may name its generation by ids instead of `startIndex`. */
|
|
5
|
+
export type StoredProgressPayload =
|
|
6
|
+
| GenerationProgressPayload
|
|
7
|
+
| {
|
|
8
|
+
requestId: string
|
|
9
|
+
generationId: string
|
|
10
|
+
responseMessageId: string
|
|
11
|
+
chunks: UIMessageChunk[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const progressOwnedBy = ({
|
|
15
|
+
payload,
|
|
16
|
+
owner,
|
|
17
|
+
startIndex,
|
|
18
|
+
}: {
|
|
19
|
+
payload: StoredProgressPayload
|
|
20
|
+
owner: { requestId: string; generationId: string; responseMessageId: string }
|
|
21
|
+
startIndex: number
|
|
22
|
+
}): boolean =>
|
|
23
|
+
'startIndex' in payload
|
|
24
|
+
? payload.startIndex === startIndex
|
|
25
|
+
: payload.requestId === owner.requestId &&
|
|
26
|
+
payload.generationId === owner.generationId &&
|
|
27
|
+
payload.responseMessageId === owner.responseMessageId
|
|
2
28
|
|
|
3
29
|
export type ProgressBatch = { index: number; chunks: UIMessageChunk[] }
|
|
4
30
|
type BatchBlock = ProgressBatch[] | { left: BatchBlock; right: BatchBlock }
|