experimental-a2 0.3.0 → 0.5.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.
Files changed (205) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/dist/ai-CFNeCrRl.d.ts +334 -0
  3. package/dist/ai-CFNeCrRl.d.ts.map +1 -0
  4. package/dist/ai-server.browser.js +2 -0
  5. package/dist/ai-server.browser.js.map +1 -0
  6. package/dist/ai-server.d.ts +49 -9
  7. package/dist/ai-server.d.ts.map +1 -0
  8. package/dist/ai-server.js +123 -49
  9. package/dist/ai-server.js.map +1 -0
  10. package/dist/ai.d.ts +2 -303
  11. package/dist/ai.js +233 -86
  12. package/dist/ai.js.map +1 -0
  13. package/dist/cli-B3VuxoDe.js +599 -0
  14. package/dist/cli-B3VuxoDe.js.map +1 -0
  15. package/dist/cli-bin.d.ts +1 -0
  16. package/dist/cli-bin.js +7 -0
  17. package/dist/cli-bin.js.map +1 -0
  18. package/dist/cli.d.ts +20 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +2 -0
  21. package/dist/client-BKlyLiOU.js +1008 -0
  22. package/dist/client-BKlyLiOU.js.map +1 -0
  23. package/dist/client-D7mvIXrF.d.ts +191 -0
  24. package/dist/client-D7mvIXrF.d.ts.map +1 -0
  25. package/dist/client.d.ts +2 -90
  26. package/dist/client.js +1 -409
  27. package/dist/{contract-CG_adnu_.js → contract-48bUMgcL.js} +12 -2
  28. package/dist/contract-48bUMgcL.js.map +1 -0
  29. package/dist/{contract-C_3dIIEU.d.ts → contract-jIfaR085.d.ts} +63 -8
  30. package/dist/contract-jIfaR085.d.ts.map +1 -0
  31. package/dist/devtools-J_jZ2vQf.d.ts +152 -0
  32. package/dist/devtools-J_jZ2vQf.d.ts.map +1 -0
  33. package/dist/devtools-kJJaORn-.js +340 -0
  34. package/dist/devtools-kJJaORn-.js.map +1 -0
  35. package/dist/devtools-server.browser.js +3 -1
  36. package/dist/devtools-server.browser.js.map +1 -0
  37. package/dist/devtools-server.d.ts +4 -3
  38. package/dist/devtools-server.d.ts.map +1 -0
  39. package/dist/devtools-server.js +226 -43
  40. package/dist/devtools-server.js.map +1 -0
  41. package/dist/devtools.d.ts +2 -0
  42. package/dist/devtools.js +2 -0
  43. package/dist/{errors-BJRMd-h6.js → errors-BQuJpe82.js} +6 -4
  44. package/dist/errors-BQuJpe82.js.map +1 -0
  45. package/dist/{errors-xL_JTXsY.d.ts → errors-W6nwJ-fm.d.ts} +3 -2
  46. package/dist/errors-W6nwJ-fm.d.ts.map +1 -0
  47. package/dist/http.d.ts +135 -28
  48. package/dist/http.d.ts.map +1 -0
  49. package/dist/http.js +647 -61
  50. package/dist/http.js.map +1 -0
  51. package/dist/{idempotent-replay-BMyHrP0L.js → idempotent-replay-DuqEkYA7.js} +4 -2
  52. package/dist/idempotent-replay-DuqEkYA7.js.map +1 -0
  53. package/dist/index.d.ts +5 -5
  54. package/dist/index.js +2 -2
  55. package/dist/{inspection-E7qbD0Xj.js → inspection-DaxB5jM2.js} +4 -1
  56. package/dist/inspection-DaxB5jM2.js.map +1 -0
  57. package/dist/internal-DstsI6Re.js +211 -0
  58. package/dist/internal-DstsI6Re.js.map +1 -0
  59. package/dist/otel.d.ts +3 -2
  60. package/dist/otel.d.ts.map +1 -0
  61. package/dist/otel.js +2 -0
  62. package/dist/otel.js.map +1 -0
  63. package/dist/platform-B4TnJtWu.js +34 -0
  64. package/dist/platform-B4TnJtWu.js.map +1 -0
  65. package/dist/react.d.ts +47 -15
  66. package/dist/react.d.ts.map +1 -0
  67. package/dist/react.js +30 -15
  68. package/dist/react.js.map +1 -0
  69. package/dist/retryable-lazy-DZWmHpii.js +2 -0
  70. package/dist/retryable-lazy-DZWmHpii.js.map +1 -0
  71. package/dist/scheduler-qstash.d.ts +79 -0
  72. package/dist/scheduler-qstash.d.ts.map +1 -0
  73. package/dist/scheduler-qstash.js +501 -0
  74. package/dist/scheduler-qstash.js.map +1 -0
  75. package/dist/scheduler-task-BpzhPnRS.js +56 -0
  76. package/dist/scheduler-task-BpzhPnRS.js.map +1 -0
  77. package/dist/{recovery-vercel.d.ts → scheduler-vercel.d.ts} +18 -24
  78. package/dist/scheduler-vercel.d.ts.map +1 -0
  79. package/dist/scheduler-vercel.js +228 -0
  80. package/dist/scheduler-vercel.js.map +1 -0
  81. package/dist/server-C72KOw51.js +1457 -0
  82. package/dist/server-C72KOw51.js.map +1 -0
  83. package/dist/server-DUF9pjsx.d.ts +261 -0
  84. package/dist/server-DUF9pjsx.d.ts.map +1 -0
  85. package/dist/server.browser.js +2 -0
  86. package/dist/server.browser.js.map +1 -0
  87. package/dist/server.d.ts +4 -155
  88. package/dist/server.js +2 -2
  89. package/dist/{log-ldf5g8Cx.d.ts → store-DysUkTH3.d.ts} +120 -35
  90. package/dist/store-DysUkTH3.d.ts.map +1 -0
  91. package/dist/{log-yJbXUf72.js → store-N8PXxDAS.js} +3 -1
  92. package/dist/store-N8PXxDAS.js.map +1 -0
  93. package/dist/store-codec-DTG0Ftek.js +10 -0
  94. package/dist/store-codec-DTG0Ftek.js.map +1 -0
  95. package/dist/store-memory.d.ts +12 -0
  96. package/dist/store-memory.d.ts.map +1 -0
  97. package/dist/{log-memory.js → store-memory.js} +145 -34
  98. package/dist/store-memory.js.map +1 -0
  99. package/dist/{log-polling-DZ1MiKLg.js → store-polling-dSeLxzfb.js} +7 -5
  100. package/dist/store-polling-dSeLxzfb.js.map +1 -0
  101. package/dist/{log-postgres.d.ts → store-postgres.d.ts} +7 -6
  102. package/dist/store-postgres.d.ts.map +1 -0
  103. package/dist/{log-postgres.js → store-postgres.js} +214 -24
  104. package/dist/store-postgres.js.map +1 -0
  105. package/dist/{log-redis-core-CyJ5L8yR.js → store-redis-core-BFLwz0Wj.js} +271 -66
  106. package/dist/store-redis-core-BFLwz0Wj.js.map +1 -0
  107. package/dist/{log-redis-http.d.ts → store-redis-http.d.ts} +8 -7
  108. package/dist/store-redis-http.d.ts.map +1 -0
  109. package/dist/{log-redis-http.js → store-redis-http.js} +22 -12
  110. package/dist/store-redis-http.js.map +1 -0
  111. package/dist/{log-redis.d.ts → store-redis.d.ts} +7 -6
  112. package/dist/store-redis.d.ts.map +1 -0
  113. package/dist/{log-redis.js → store-redis.js} +101 -39
  114. package/dist/store-redis.js.map +1 -0
  115. package/dist/{log-sqlite.d.ts → store-sqlite.d.ts} +7 -6
  116. package/dist/store-sqlite.d.ts.map +1 -0
  117. package/dist/{log-sqlite.js → store-sqlite.js} +118 -22
  118. package/dist/store-sqlite.js.map +1 -0
  119. package/dist/{telemetry-Cso0qyHQ.d.ts → telemetry-BjYHTfh2.d.ts} +3 -2
  120. package/dist/telemetry-BjYHTfh2.d.ts.map +1 -0
  121. package/dist/testing.browser.d.ts +1 -0
  122. package/dist/testing.browser.js +6 -0
  123. package/dist/testing.browser.js.map +1 -0
  124. package/dist/testing.d.ts +32 -0
  125. package/dist/testing.d.ts.map +1 -0
  126. package/dist/testing.js +103 -0
  127. package/dist/testing.js.map +1 -0
  128. package/dist/validate-XKT4FSNn.js +2 -0
  129. package/dist/validate-XKT4FSNn.js.map +1 -0
  130. package/dist/wire-BFQmSJ-9.js +284 -0
  131. package/dist/wire-BFQmSJ-9.js.map +1 -0
  132. package/docs/01-quickstart.mdx +3 -3
  133. package/docs/concepts/01-contracts.mdx +18 -13
  134. package/docs/concepts/02-handlers.mdx +7 -7
  135. package/docs/concepts/03-durability.mdx +21 -21
  136. package/docs/concepts/04-state.mdx +18 -21
  137. package/docs/guides/01-timers.mdx +154 -49
  138. package/docs/guides/02-cancellation.mdx +30 -4
  139. package/docs/guides/03-react.mdx +76 -57
  140. package/docs/guides/04-local-first.mdx +1 -1
  141. package/docs/guides/05-production.mdx +310 -61
  142. package/docs/guides/06-ai-agents.mdx +252 -74
  143. package/docs/guides/07-devtools.mdx +137 -12
  144. package/docs/guides/08-application-data.mdx +1 -1
  145. package/docs/guides/09-presence.mdx +263 -0
  146. package/docs/guides/10-transports.mdx +140 -0
  147. package/docs/index.mdx +18 -14
  148. package/docs/reference/01-api.mdx +839 -110
  149. package/docs/reference/02-errors.mdx +13 -6
  150. package/package.json +24 -7
  151. package/src/ai-coordinator.ts +358 -0
  152. package/src/ai-projector.ts +524 -0
  153. package/src/ai-sdk-step.ts +261 -0
  154. package/src/ai-server.browser.ts +5 -0
  155. package/src/ai-server.ts +1719 -0
  156. package/src/ai.ts +2155 -0
  157. package/src/cache-indexeddb.ts +10 -0
  158. package/src/cli-bin.ts +5 -0
  159. package/src/cli.ts +1046 -0
  160. package/src/client.ts +1826 -0
  161. package/src/contract.ts +206 -0
  162. package/src/deterministic-id.ts +72 -0
  163. package/src/devtools-app.ts +989 -0
  164. package/src/devtools-server.browser.ts +5 -0
  165. package/src/devtools-server.ts +604 -0
  166. package/src/devtools.ts +716 -0
  167. package/src/errors.ts +50 -0
  168. package/src/http.ts +394 -0
  169. package/src/idempotent-replay.ts +53 -0
  170. package/src/index.ts +37 -0
  171. package/src/inspection.ts +39 -0
  172. package/src/internal.ts +426 -0
  173. package/src/otel.ts +59 -0
  174. package/src/platform.ts +60 -0
  175. package/src/push-envelope.ts +137 -0
  176. package/src/react.ts +284 -0
  177. package/src/reducer.ts +108 -0
  178. package/src/retryable-lazy.ts +27 -0
  179. package/src/scheduler-qstash.ts +915 -0
  180. package/src/scheduler-task.ts +106 -0
  181. package/src/scheduler-vercel.ts +437 -0
  182. package/src/server.browser.ts +12 -0
  183. package/src/server.ts +2700 -0
  184. package/src/session-socket.ts +548 -0
  185. package/src/sse.ts +141 -0
  186. package/src/standard-schema.ts +77 -0
  187. package/src/store-codec.ts +10 -0
  188. package/src/store-memory.ts +788 -0
  189. package/src/store-polling.ts +102 -0
  190. package/src/store-postgres.ts +1212 -0
  191. package/src/store-redis-core.ts +1494 -0
  192. package/src/store-redis-http.ts +116 -0
  193. package/src/store-redis.ts +458 -0
  194. package/src/store-sqlite.ts +1108 -0
  195. package/src/store.ts +385 -0
  196. package/src/telemetry.ts +47 -0
  197. package/src/testing.browser.ts +5 -0
  198. package/src/testing.ts +185 -0
  199. package/src/validate.ts +39 -0
  200. package/src/wire.ts +454 -0
  201. package/dist/internal-gCd5qMry.js +0 -44
  202. package/dist/log-memory.d.ts +0 -11
  203. package/dist/recovery-vercel.js +0 -119
  204. package/dist/server-BcLa4RFL.js +0 -877
  205. package/dist/wire-BVsgR8o9.js +0 -62
package/CHANGELOG.md CHANGED
@@ -1,5 +1,212 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 38de9de: Add `handle(server, options?)`, the one call that exposes a session over
8
+ HTTP: it returns a `{ GET, POST }` route pair where `GET` serves the live
9
+ stream, websocket upgrades, and bounded history slices, and `POST` appends.
10
+ The library parses every request into a typed intent (`'ws-upgrade' |
11
+ 'stream' | 'history' | 'push'`) before any policy runs; hooks are where
12
+ apps decide. `before` sees each parsed intent and refuses by returning a
13
+ Response, `after` decorates or replaces HTTP responses (`outcome.covered`
14
+ on a history read marks an immutable slice, safe to cache), `upgrade`
15
+ supplies the runtime's websocket upgrade, `presence: true` enables the
16
+ presence plane, and `deadline` caps request handling. Parse failures
17
+ answer `INVALID_PAYLOAD` before hooks run, on every lane.
18
+
19
+ The `experimental-a2/http` surface shrinks around it: `sseResponse`,
20
+ `parsePushBody`, `sessionsSocket`, `sessionSocket`, `historyResponse`,
21
+ and `createSessionRoutes` are removed as exports — `handle` composes
22
+ them internally. `schedulerHandler`, `errorResponse`, `deserializeError`,
23
+ `A2Socket`, and the new `A2Intent`, `A2Outcome`, `UpgradeFn`, and
24
+ `HandleOptions` types remain the whole module.
25
+
26
+ - 38de9de: Add `loadHistory` backscroll to the client and React bindings. A client
27
+ session (and `useSession()`) exposes `loadHistory({ before?, limit? })`,
28
+ which fetches a bounded slice of the log below the stream frontier over
29
+ the same route (`gte`/`lte` query parameters) and merges it into
30
+ `events`: deduped, ordered, shared across every handle of the session,
31
+ never touching folded state or the optimistic overlay. Calls serialize
32
+ per session, and by default each walks backward 50 events from the
33
+ oldest one loaded. `useSession()` also gains `history`, the backscroll
34
+ progress: `{ loading, complete, oldestLoaded }`, where `complete` means
35
+ the feed reaches index 1 or the log is empty.
36
+ - 38de9de: Coalesce same-tick state reads into one store round trip. Concurrent
37
+ `session.state()` calls that land in the same microtask window — a
38
+ `Promise.all` over sessions, a burst of parallel requests — are batched
39
+ into a single backend read, with no caching across ticks and no change
40
+ in results: every caller still gets its own independently folded state.
41
+ Custom store adapters can opt in by implementing the optional
42
+ `readStates(requests)` batch method (the built-in Postgres store does,
43
+ as one statement); without it, reads fall back to per-session
44
+ `readState` unchanged.
45
+ - 38de9de: Multiplex every session of a client over one websocket. A `ws` client
46
+ now opens a single socket per `createClient` and subscribes sessions
47
+ onto it with tagged wire frames (subscribe/unsubscribe, per-session
48
+ acks), instead of one connection per session; the server side accepts
49
+ the multiplexed protocol on the same `handle` route. Push retries over
50
+ a live socket are also floored at the HTTP pacing clock: an error ack
51
+ arriving at wire speed no longer re-fires instantly, so a shedding
52
+ server is not re-hammered by its own healthy connections.
53
+
54
+ ## 0.4.0
55
+
56
+ ### Minor Changes
57
+
58
+ - 0640425: Replace the A2 `tool()` wrapper with ambient handler context for plain AI SDK
59
+ tools. Tools are now ordinary `tool()` definitions from `ai`; inside a local
60
+ `execute`, `handlerContext(agent)` from `experimental-a2/ai` returns the
61
+ durable `AgentToolContext` (verified against the executing server's contract),
62
+ and `runWithHandlerContext(ctx, fn)` from `experimental-a2/ai/server` makes
63
+ tools directly testable. `tool()`, `AgentToolOptions`, and the agent-binding
64
+ construction checks are removed, and the model-phase option bans are lifted:
65
+ `contextSchema`, dynamic `description`, `needsApproval` predicates, input
66
+ lifecycle callbacks, and generation `toolsContext` now pass through to the AI
67
+ SDK untouched. Approval predicates are re-evaluated on recovery for the same
68
+ durable tool call, so they must be deterministic over the tool input.
69
+ - d0c5323: Add a typed `messageMetadata` mapper to the default AI SDK generator so
70
+ assistant stream metadata, including final usage, can be durably projected.
71
+ - 870dbd5: Add agent-bound `tool()` definitions whose local executors receive the current
72
+ durable A2 handler context. The playground agent now demonstrates the API by
73
+ scheduling reminders that return as new user messages.
74
+ - 4c11535: Add indexed `gte` and `lte` history ranges and rename the exclusive stream
75
+ cursor from `startAt` to `startAfter`.
76
+ - 0c3d861: Rename the configured storage and delivery primitives across the public API.
77
+ `log` is now `store`, `recovery` is now `scheduler`, built-in adapter entry
78
+ points move to `experimental-a2/store-*` and
79
+ `experimental-a2/scheduler-vercel`, and the corresponding public types and
80
+ error codes use `Store` and `Scheduler` names. This is a breaking rename with
81
+ no persisted storage or queue-message format change.
82
+ - 2a1743a: Add versioned Devtools captures, the `a2 devtools` read-only CLI, offline reducer replay helpers, conservative authorization that opens without a callback only when `NODE_ENV` is exactly `development`, and fixed-frontier pagination that keeps Redis reads, reducer state, session summaries, detail, and exports complete beyond provider range limits.
83
+ - 589c361: Fence the public AI projection against stale lifecycle events after generation
84
+ failure, interruption, and attempt supersession. Interrupted responses now keep
85
+ only the exact visible frontier across post-step tool, approval, and
86
+ application-input barriers and across failure races, preserve terminal tool
87
+ results, restore the committed message and compaction base for retries, and
88
+ clear failed pending inputs without allowing delayed events to corrupt a later
89
+ model step.
90
+ Clients identify a requested response with its active `requestId` and a
91
+ started response with its exact `generationId`. A request-owned interruption
92
+ remains valid if that same request starts before the interruption commits.
93
+ The response message and owner IDs must identify the same work.
94
+ `AIState` exposes optional terminal request and generation ownership maps. The
95
+ built-in public and coordinator reducers use new versioned names so stored
96
+ snapshots refold under these semantics.
97
+ - 75bf51a: Fence handler appends by attempt currency and abort superseded runs. A
98
+ `ctx.session.append` from an attempt a recovery claim has replaced now
99
+ rejects with `SUPERSEDED_ATTEMPT` instead of landing stale events —
100
+ atomically, in the store's append operation — while exact retries of
101
+ already-committed batches still replay idempotently. `ctx.signal` is now
102
+ live for every handler and aborts with a `SUPERSEDED_ATTEMPT` reason when
103
+ the claim heartbeat learns a newer attempt owns the event; `abortOn`
104
+ remains the additional user-cancellation source. Custom store adapters:
105
+ `append` must implement the fence, and `renewClaims` now takes
106
+ `{ index, attempt }` pairs and returns `{ renewed, superseded }`.
107
+ - 22534c2: Self-fence at local lease lapse and retry failed renewals promptly. A
108
+ handler whose claim lapses without renewal now gets its `ctx.signal`
109
+ aborted with a `CLAIM_EXPIRED` reason, decided by the local clock with
110
+ zero I/O — so it fires during store outages and in the first tick after
111
+ an event-loop stall, before any round trip could report back. A failed
112
+ heartbeat renewal retries after a short jittered delay while the lease
113
+ can still be saved instead of waiting out the next scheduled beat. A
114
+ lapsed-but-unsuperseded attempt that returns normally still completes;
115
+ proven supersession remains what releases the drain.
116
+ - a7a3818: Add passive user messages with `inputs.message(message, { generate: false })`
117
+ and make `inputs.seed()` record context without scheduling a user turn.
118
+ Passive user messages join the prompt when a later generating message advances
119
+ the ordered conversation frontier.
120
+ - f84cbe8: Presence: the ephemeral plane. Contracts grow an optional `presence`
121
+ field-schema map; sessions gain `setPresence(patch)`, `presence()`, and
122
+ `stream({ presence: true })` (one snapshot frame, then live patches
123
+ interleaved with events); `useSession` gains `presence`/`setPresence`,
124
+ typed from the contract with no type arguments and existing only on
125
+ presence-declaring contracts. Per-participant state replicates
126
+ last-writer-wins per field, stamped with the sender's stream frontier
127
+ (`seen`), and never touches the log: no index, no history, no folds, no
128
+ scheduler arm, no browser cache. Backed by an optional `A2Store.presence`
129
+ capability: push tier on `store-redis` (pub/sub beside the notify
130
+ channel) and `store-memory`; degraded poll-merge tier on `store-postgres`,
131
+ `store-sqlite`, and `store-redis-http`. `parsePushBody` accepts a branded
132
+ `presence` sibling (presence-only pushes valid); `sseResponse` rides it
133
+ as named SSE frames old clients skip. New error codes:
134
+ `UNKNOWN_PRESENCE_FIELD`, `PRESENCE_NOT_SUPPORTED`. Also fixes a latent
135
+ `store-redis` subscriber-handshake race (channel commands could beat the
136
+ ready check).
137
+ - 817d636: Make `qstash()` zero-config in local Node.js development by inferring its
138
+ conventional localhost callback and enabling the QStash SDK development server.
139
+ Infer Vercel production and preview callbacks, and disable SDK development mode
140
+ in production. For inferred previews, opportunistically forward a fresh-enough
141
+ invocation identity for Vercel Trusted Sources and request redaction from the
142
+ QStash dashboard and API.
143
+ Allow static callback headers with automatic provider redaction, or a configured
144
+ QStash publishing client while A2 keeps the default signature receiver.
145
+ Require `@upstash/qstash` 2.11.0 or newer so both redaction and zero-config local
146
+ development are enforced by the peer range.
147
+ - 1d0aa9c: Add first-party delayed events with `session.schedule()`. Configured scheduler
148
+ adapters now deliver both recovery watchdogs and named, typed timer events.
149
+ Scheduler routes use `schedulerHandler(...)`, which rejects mismatched adapter
150
+ wiring before accepting deliveries.
151
+ - ac007ed: Drop the pre-versioning kindless drain envelope: scheduler routes now accept
152
+ only the versioned task union, and `dueAt` is required on `SchedulerDrainTask`.
153
+ The `DrainMessage` type exports and the `delaySeconds` fallback options are
154
+ removed from both scheduler adapters (`vercelQueues` keeps its documented
155
+ unsettled-redelivery backoff with a fixed base). In-flight kindless watchdogs
156
+ from earlier versions are rejected at delivery; affected sessions heal on
157
+ their next append or explicit drain.
158
+ - d3b3f8d: Remove the default agent response step limit. Set `maxSteps` to a positive
159
+ integer when a response needs an explicit bound.
160
+ - c446705: Add `experimental-a2/scheduler-qstash`, a QStash-backed scheduler adapter with
161
+ authenticated callback delivery, delayed watchdogs, and deterministic publish
162
+ deduplication.
163
+ - 62018f1: Transports: the `ws` wire. `createClient`'s `api` becomes the
164
+ documented `ClientApi` union — a string (one route: GET SSE + POST
165
+ push), `{ type: 'http', push, stream }` (split routes for per-route
166
+ duration limits), or `{ type: 'ws', url }` (one WebSocket, both
167
+ directions: the stream down, pushes and presence up, each presence
168
+ send a socket frame instead of a route invocation). Everything above
169
+ the wire seam — optimistic pushes with ack and `confirmed`,
170
+ frontier-resumed reads, reconnect with backoff, the stall watchdog,
171
+ the presence throttle and re-send — is transport-agnostic and behaves
172
+ identically on every wire. `experimental-a2/http` gains
173
+ `sessionSocket(session, socket, { startAfter?, presence?, deadline? })`,
174
+ which speaks the frame protocol (event / presence / presence-snapshot
175
+ / ack / ping down; push / presence up) against any structurally
176
+ `ws`-shaped socket and validates pushes exactly as `parsePushBody`
177
+ does — same brands, same per-plane `validatePush` calls; the platform
178
+ upgrade API stays out of the library. `createClient` gains a
179
+ `webSocket` injectable mirroring `fetch`. In-flight pushes that lose
180
+ their socket reject retryably as `STORE_UNAVAILABLE`; client-generated
181
+ event ids make retries idempotent.
182
+
183
+ ### Patch Changes
184
+
185
+ - 0664146: Harden the lease machinery against three adversarial-review findings. A
186
+ drain that re-claims its own lapsed event now fences the old attempt's
187
+ slot before the new one takes it, and continuations are
188
+ identity-guarded, so a settling zombie can no longer orphan the live
189
+ attempt from heartbeat coverage. A handler throw that is the signal's
190
+ own abort reason (object identity, never an error code) surrenders the
191
+ attempt — no completion, no failure budget — which makes passing
192
+ `ctx.signal` to `fetch` the correct default wiring; every other throw,
193
+ including store fence rejections, is adjudicated by the already-fenced
194
+ `failAttempt` instead of an in-process error-code check. The postgres
195
+ and sqlite `renewClaims` now require the listed attempt to match, so a
196
+ stale heartbeat can never extend or mask a successor's claim (the
197
+ conformance kit pins same-holder supersession on every backend). The
198
+ `a2.event` telemetry outcome set gains `surrendered`.
199
+ - a80ec55: Preserve invocation order when one session client makes overlapping
200
+ optimistic pushes.
201
+ - ae1fab7: Close SSE responses cleanly one second before an ambient Vercel invocation
202
+ deadline so clients reconnect from their last frontier without a
203
+ platform-timeout failure.
204
+ - 2181989: Pin Vercel Queue recovery and scheduled appends to their publishing deployment
205
+ by default, with an explicit `scheduledAppends: 'deploymentless'` opt-out for
206
+ applications that maintain cross-deployment timer compatibility.
207
+ - ef9b60e: Harden scheduler delivery across provider limits, deployment rollouts, retries,
208
+ and AI tool approval contexts.
209
+
3
210
  ## 0.3.0
4
211
 
5
212
  ### Minor Changes
@@ -0,0 +1,334 @@
1
+ import { a as EventDefs, h as StandardSchemaV1, n as Contract, p as Reducer, t as AppendInput } from "./contract-jIfaR085.js";
2
+ import { s as HandlerContext } from "./server-DUF9pjsx.js";
3
+ import { FinishReason, JSONValue, LanguageModelUsage, UIMessage as UIMessage$1, UIMessageChunk as UIMessageChunk$1 } from "ai";
4
+ //#region src/ai.d.ts
5
+ type AgentStatus = "idle" | "generating" | "waiting" | "failed" | "closed";
6
+ type GenerationReason = "message" | "tool" | "input" | "retry";
7
+ type SessionCreatedPayload = {
8
+ metadata?: JSONValue;
9
+ };
10
+ type SessionClosedPayload = {
11
+ reason?: string;
12
+ };
13
+ type MessageCreatedPayload<M extends UIMessage$1> = {
14
+ message: M;
15
+ /** For user messages, false records passive context. Omission or true schedules. */
16
+ generate?: boolean;
17
+ };
18
+ type MessageCompletedPayload = {
19
+ messageId: string;
20
+ };
21
+ type MessageInterruption = {
22
+ messageId: string;
23
+ reason?: string;
24
+ /** Last confirmed event-log index visible to the interrupter. */
25
+ lastSeenIndex?: number;
26
+ };
27
+ type MessageInterruptedPayload = MessageInterruption & ({
28
+ generationId: string;
29
+ requestId?: never;
30
+ } | {
31
+ requestId: string;
32
+ generationId?: never;
33
+ });
34
+ type GenerationRequestedPayload = {
35
+ messageId: string;
36
+ reason: GenerationReason;
37
+ responseMessageId?: string;
38
+ };
39
+ type RetryGenerationOptions = {
40
+ messageId: string;
41
+ responseMessageId: string;
42
+ retryId: string;
43
+ };
44
+ type RetryRequestedPayload = RetryGenerationOptions;
45
+ type GenerationStartedPayload = {
46
+ requestId: string;
47
+ messageId: string;
48
+ generationId: string;
49
+ responseMessageId: string;
50
+ attempt: number;
51
+ model: string;
52
+ };
53
+ type GenerationProgressPayload = {
54
+ requestId: string;
55
+ messageId: string;
56
+ generationId: string;
57
+ responseMessageId: string;
58
+ sequence: number;
59
+ chunks: UIMessageChunk$1[];
60
+ };
61
+ type GenerationCompletedPayload = {
62
+ requestId: string;
63
+ messageId: string;
64
+ generationId: string;
65
+ responseMessageId: string;
66
+ finishReason?: FinishReason;
67
+ usage?: LanguageModelUsage;
68
+ };
69
+ type GenerationFailedPayload = {
70
+ requestId: string;
71
+ messageId: string;
72
+ generationId: string;
73
+ responseMessageId: string;
74
+ error: string;
75
+ /** True when a later attempt replaced an incomplete attempt. */
76
+ superseded?: boolean;
77
+ stepLimit?: boolean;
78
+ };
79
+ type ToolCalledPayload = {
80
+ requestId: string;
81
+ messageId: string;
82
+ generationId: string;
83
+ toolCallId: string;
84
+ toolName: string;
85
+ input: unknown;
86
+ dynamic?: boolean;
87
+ providerExecuted?: boolean;
88
+ supportsDeferredResults?: boolean;
89
+ providerMetadata?: unknown;
90
+ toolMetadata?: unknown;
91
+ title?: string;
92
+ };
93
+ type ToolResultPayload = {
94
+ requestId: string;
95
+ messageId: string;
96
+ generationId: string;
97
+ toolCallId: string;
98
+ toolName?: string;
99
+ input?: unknown;
100
+ rawInput?: unknown;
101
+ output?: unknown;
102
+ error?: string;
103
+ denied?: boolean;
104
+ preliminary?: boolean;
105
+ phase?: "input" | "execution";
106
+ dynamic?: boolean;
107
+ providerExecuted?: boolean;
108
+ providerMetadata?: unknown;
109
+ toolMetadata?: unknown;
110
+ };
111
+ type ApprovalRequestedPayload = {
112
+ messageId: string;
113
+ generationId: string;
114
+ approvalId: string;
115
+ toolCallId: string;
116
+ isAutomatic?: boolean;
117
+ signature?: string;
118
+ };
119
+ type ApprovalRespondedPayload = {
120
+ messageId: string;
121
+ generationId: string;
122
+ approvalId: string;
123
+ approved: boolean;
124
+ reason?: string;
125
+ };
126
+ type InputRequestedPayload = {
127
+ messageId: string;
128
+ generationId: string;
129
+ inputId: string;
130
+ name: string;
131
+ question?: JSONValue;
132
+ };
133
+ type InputRespondedPayload = {
134
+ messageId: string;
135
+ generationId: string;
136
+ inputId: string;
137
+ name: string;
138
+ value: JSONValue;
139
+ };
140
+ type CompactionRequestedPayload = {
141
+ generationId: string;
142
+ throughMessageId: string;
143
+ };
144
+ type CompactionCompletedPayload<M extends UIMessage$1> = {
145
+ generationId: string;
146
+ throughMessageId: string;
147
+ messages: M[];
148
+ retainedMessageIds?: string[];
149
+ };
150
+ type AIEventDefs<M extends UIMessage$1 = UIMessage$1> = {
151
+ "ai.session.created": StandardSchemaV1<SessionCreatedPayload>;
152
+ "ai.session.closed": StandardSchemaV1<SessionClosedPayload>;
153
+ "ai.message.created": StandardSchemaV1<MessageCreatedPayload<M>>;
154
+ "ai.message.completed": StandardSchemaV1<MessageCompletedPayload>;
155
+ "ai.message.interrupted": StandardSchemaV1<MessageInterruptedPayload>;
156
+ "ai.generation.requested": StandardSchemaV1<GenerationRequestedPayload>;
157
+ "ai.retry.requested": StandardSchemaV1<RetryRequestedPayload>;
158
+ "ai.generation.started": StandardSchemaV1<GenerationStartedPayload>;
159
+ "ai.generation.progress": StandardSchemaV1<GenerationProgressPayload>;
160
+ "ai.generation.completed": StandardSchemaV1<GenerationCompletedPayload>;
161
+ "ai.generation.failed": StandardSchemaV1<GenerationFailedPayload>;
162
+ "ai.tool.called": StandardSchemaV1<ToolCalledPayload>;
163
+ "ai.tool.result": StandardSchemaV1<ToolResultPayload>;
164
+ "ai.approval.requested": StandardSchemaV1<ApprovalRequestedPayload>;
165
+ "ai.approval.responded": StandardSchemaV1<ApprovalRespondedPayload>;
166
+ "ai.input.requested": StandardSchemaV1<InputRequestedPayload>;
167
+ "ai.input.responded": StandardSchemaV1<InputRespondedPayload>;
168
+ "ai.compaction.requested": StandardSchemaV1<CompactionRequestedPayload>;
169
+ "ai.compaction.completed": StandardSchemaV1<CompactionCompletedPayload<M>>;
170
+ };
171
+ type ActiveGeneration = GenerationStartedPayload;
172
+ type ActiveGenerationProjection<M extends UIMessage$1 = UIMessage$1> = {
173
+ generationId: string;
174
+ responseMessageId: string;
175
+ /** Log index of the completed model step while its response remains interruptible. */
176
+ completionIndex?: number;
177
+ baseMessage?: M;
178
+ baseCompaction?: CompactionState<M> | null;
179
+ batches: Array<{
180
+ index: number;
181
+ chunks: UIMessageChunk$1[];
182
+ }>;
183
+ baseTools: ToolActivity[];
184
+ toolEvents: Array<{
185
+ index: number;
186
+ type: "ai.tool.called";
187
+ payload: ToolCalledPayload;
188
+ } | {
189
+ index: number;
190
+ type: "ai.tool.result";
191
+ payload: ToolResultPayload;
192
+ }>;
193
+ approvalEvents: Array<{
194
+ index: number;
195
+ type: "ai.approval.requested";
196
+ payload: ApprovalRequestedPayload;
197
+ } | {
198
+ index: number;
199
+ type: "ai.approval.responded";
200
+ payload: ApprovalRespondedPayload;
201
+ }>;
202
+ };
203
+ type PendingApproval = ApprovalRequestedPayload;
204
+ type PendingInput = InputRequestedPayload;
205
+ type ToolActivity = {
206
+ requestId: string;
207
+ messageId: string;
208
+ generationId: string;
209
+ toolCallId: string;
210
+ toolName?: string;
211
+ input?: unknown;
212
+ rawInput?: unknown;
213
+ output?: unknown;
214
+ error?: string;
215
+ preliminary?: boolean;
216
+ phase?: "input" | "execution";
217
+ dynamic?: boolean;
218
+ providerExecuted?: boolean;
219
+ callProviderMetadata?: unknown;
220
+ resultProviderMetadata?: unknown;
221
+ toolMetadata?: unknown;
222
+ title?: string;
223
+ status: "running" | "completed" | "failed" | "denied";
224
+ };
225
+ type CompactionState<M extends UIMessage$1> = {
226
+ status: "running" | "completed";
227
+ generationId: string;
228
+ throughMessageId: string;
229
+ messages?: M[];
230
+ retainedMessageIds?: string[];
231
+ };
232
+ type GenerationUsage = {
233
+ generationId: string;
234
+ usage: LanguageModelUsage;
235
+ };
236
+ type AIState<M extends UIMessage$1 = UIMessage$1> = {
237
+ session: {
238
+ created: boolean;
239
+ metadata?: JSONValue;
240
+ };
241
+ messages: M[];
242
+ status: AgentStatus;
243
+ activeGeneration: ActiveGeneration | null;
244
+ activeRequestId: string | null;
245
+ activeResponseMessageId: string | null;
246
+ activeProjection: ActiveGenerationProjection<M> | null;
247
+ responseGenerationIds: Record<string, string>;
248
+ terminalRequestIds?: Record<string, true>;
249
+ terminalGenerations?: Record<string, "completed" | "failed" | "interrupted" | "superseded">;
250
+ pendingApprovals: PendingApproval[];
251
+ pendingInputs: PendingInput[];
252
+ tools: ToolActivity[];
253
+ compaction: CompactionState<M> | null;
254
+ usage: GenerationUsage[];
255
+ error: string | null;
256
+ };
257
+ type AgentDefinition<M extends UIMessage$1 = UIMessage$1, D extends EventDefs = AIEventDefs<M>> = {
258
+ readonly contract: Contract<D>;
259
+ readonly reducer: Reducer<D, AIState<M>>;
260
+ };
261
+ type AgentToolEventDefs = EventDefs & Pick<AIEventDefs, "ai.tool.called" | "ai.approval.responded">;
262
+ /** The durable handler context supplied when A2 executes a local AI tool. */
263
+ type AgentToolContext<D extends AgentToolEventDefs> = HandlerContext<D, "ai.tool.called"> | HandlerContext<D, "ai.approval.responded">;
264
+ type AgentOptions<M extends UIMessage$1, E extends EventDefs> = {
265
+ name: string;
266
+ events?: E;
267
+ /** Optional stricter schema for custom UIMessage metadata/data/tool types. */
268
+ messageSchema?: StandardSchemaV1<M>;
269
+ /** Snapshot identity. Bump when application-level projection semantics change. */
270
+ reducerName?: string;
271
+ };
272
+ type AIMessageFrom<D extends EventDefs> = D extends Record<"ai.message.created", infer S extends StandardSchemaV1> ? StandardSchemaV1.InferOutput<S> extends MessageCreatedPayload<infer M extends UIMessage$1> ? M : UIMessage$1 : UIMessage$1;
273
+ declare function createEvents<M extends UIMessage$1 = UIMessage$1>(options?: {
274
+ messageSchema?: StandardSchemaV1<M>;
275
+ }): AIEventDefs<M>;
276
+ declare const events: AIEventDefs<UIMessage$1>;
277
+ /** Pure projection of the built-in AI protocol. Unknown extension events are ignored. */
278
+ declare function reduceAIState<M extends UIMessage$1>(state: AIState<M>, event: {
279
+ type: string;
280
+ payload: unknown;
281
+ index: number;
282
+ id?: string;
283
+ }): AIState<M>;
284
+ /** Derive AI SDK UI messages directly from an A2 event history. */
285
+ declare function deriveUIMessages<M extends UIMessage$1 = UIMessage$1>(history: readonly {
286
+ type: string;
287
+ payload: unknown;
288
+ index: number;
289
+ }[]): M[];
290
+ /** Build the standard AI state projection for any contract containing the protocol. */
291
+ declare function createReducer<D extends EventDefs>(options: {
292
+ contract: Contract<D>;
293
+ name?: string;
294
+ }): Reducer<D, AIState<AIMessageFrom<D>>>;
295
+ type ProtocolInput<M extends UIMessage$1, K extends keyof AIEventDefs<M> & string> = AppendInput<Pick<AIEventDefs<M>, K>>;
296
+ type AIInputs = {
297
+ /** Record a message. User messages schedule unless generate is false. */
298
+ message<M extends UIMessage$1>(message: M, options?: {
299
+ generate?: boolean;
300
+ }): ProtocolInput<M, "ai.message.created">[];
301
+ /** Record a message without requesting a generation. */
302
+ seed<M extends UIMessage$1>(message: M): ProtocolInput<M, "ai.message.created">[];
303
+ /** Answer an AI SDK tool approval. The tool barrier owns continuation. */
304
+ approval(response: ApprovalRespondedPayload): ProtocolInput<UIMessage$1, "ai.approval.responded">[];
305
+ /** Answer an application-defined input request. */
306
+ input(response: InputRespondedPayload): ProtocolInput<UIMessage$1, "ai.input.responded">[];
307
+ /** Record an application-defined request for input. */
308
+ requestInput(request: InputRequestedPayload): ProtocolInput<UIMessage$1, "ai.input.requested">[];
309
+ /** Request a fresh attempt for a failed response. */
310
+ retry(options: RetryGenerationOptions): ProtocolInput<UIMessage$1, "ai.retry.requested">[];
311
+ /** Interrupt the active response for a message. */
312
+ interrupt(interruption: MessageInterruptedPayload): ProtocolInput<UIMessage$1, "ai.message.interrupted">[];
313
+ };
314
+ /** Pure append inputs for the built-in AI protocol. */
315
+ declare const inputs: AIInputs;
316
+ /**
317
+ * Read the durable handler context ambient to the current AI tool
318
+ * execution. A2 runs each local tool's `execute` inside this scope, so
319
+ * plain AI SDK `tool()` definitions reach their `event`, `attempt`,
320
+ * `session`, and `signal` without an A2-specific wrapper. The agent (or
321
+ * contract) argument carries the event types and is verified against
322
+ * the executing server's contract.
323
+ */
324
+ declare function handlerContext<D extends AgentToolEventDefs>(agentOrContract: Contract<D> | {
325
+ readonly contract: Contract<D>;
326
+ }): AgentToolContext<D>;
327
+ /**
328
+ * Define an agent: built-in AI protocol + application events and one state
329
+ * reducer. The result is isomorphic.
330
+ */
331
+ declare function agent<M extends UIMessage$1 = UIMessage$1, E extends EventDefs = Record<never, never>>(options: AgentOptions<M, E>): AgentDefinition<M, AIEventDefs<M> & E>;
332
+ //#endregion
333
+ export { MessageInterruptedPayload as A, UIMessage$1 as B, GenerationUsage as C, LanguageModelUsage as D, JSONValue as E, SessionClosedPayload as F, deriveUIMessages as G, agent as H, SessionCreatedPayload as I, inputs as J, events as K, ToolActivity as L, PendingInput as M, RetryGenerationOptions as N, MessageCompletedPayload as O, RetryRequestedPayload as P, ToolCalledPayload as R, GenerationStartedPayload as S, InputRespondedPayload as T, createEvents as U, UIMessageChunk$1 as V, createReducer as W, reduceAIState as Y, GenerationCompletedPayload as _, ActiveGenerationProjection as a, GenerationReason as b, AgentStatus as c, ApprovalRequestedPayload as d, ApprovalRespondedPayload as f, FinishReason as g, CompactionState as h, ActiveGeneration as i, PendingApproval as j, MessageCreatedPayload as k, AgentToolContext as l, CompactionRequestedPayload as m, AIInputs as n, AgentDefinition as o, CompactionCompletedPayload as p, handlerContext as q, AIState as r, AgentOptions as s, AIEventDefs as t, AgentToolEventDefs as u, GenerationFailedPayload as v, InputRequestedPayload as w, GenerationRequestedPayload as x, GenerationProgressPayload as y, ToolResultPayload as z };
334
+ //# sourceMappingURL=ai-CFNeCrRl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-CFNeCrRl.d.ts","names":[],"sources":["../src/ai.ts"],"mappings":"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"}
@@ -2,3 +2,5 @@
2
2
  /** experimental-a2/ai/server is server-only; agent definitions live in experimental-a2/ai. */
3
3
  throw new Error("experimental-a2/ai/server is server-only — a client bundle imported it. Import agent from experimental-a2/ai in browser code instead.");
4
4
  //#endregion
5
+
6
+ //# sourceMappingURL=ai-server.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-server.browser.js","names":[],"sources":["../src/ai-server.browser.ts"],"sourcesContent":["/** experimental-a2/ai/server is server-only; agent definitions live in experimental-a2/ai. */\nthrow new Error(\n 'experimental-a2/ai/server is server-only — a client bundle imported it. Import agent from experimental-a2/ai in browser code instead.',\n)\nexport {}\n"],"mappings":";;AACA,MAAM,IAAI,MACR,uIACF"}
@@ -1,14 +1,40 @@
1
- import { a as EventDefs, r as ContractEvent } from "./contract-C_3dIIEU.js";
2
- import { AIEventDefs, AIState, AgentDefinition } from "./ai.js";
3
- import { A2Server, PushValidationContext, ServerOptions } from "./server.js";
4
- import { Instructions, LanguageModel, ToolSet, ToolSet as ToolSet$1, UIMessage, UIMessageChunk, streamText } from "ai";
1
+ import { a as EventDefs, r as ContractEvent } from "./contract-jIfaR085.js";
2
+ import { d as PushValidationContext, g as ServerOptions, n as A2Server } from "./server-DUF9pjsx.js";
3
+ import { l as AgentToolContext, o as AgentDefinition, r as AIState, t as AIEventDefs, u as AgentToolEventDefs } from "./ai-CFNeCrRl.js";
4
+ import { Instructions, LanguageModel, TextStreamPart, ToolSet, ToolSet as ToolSet$1, UIMessage, UIMessageChunk, streamText } from "ai";
5
5
  //#region src/ai-sdk-step.d.ts
6
6
  type StreamTextOptions<T extends ToolSet$1> = Parameters<typeof streamText<T>>[0];
7
7
  type ModelStepTimeout<T extends ToolSet$1> = number | Omit<Exclude<StreamTextOptions<T>["timeout"], number | undefined>, "toolMs" | "tools">;
8
- type ControlledStreamTextSetting = "_internal" | "abortSignal" | "instructions" | "messages" | "model" | "onToolExecutionEnd" | "onToolExecutionStart" | "experimental_onToolCallFinish" | "experimental_onToolCallStart" | "experimental_sandbox" | "experimental_toolCallers" | "experimental_toolApprovalSecret" | "prompt" | "prepareStep" | "stopWhen" | "system" | "tools" | "toolsContext";
8
+ type ControlledStreamTextSetting = "_internal" | "abortSignal" | "instructions" | "messages" | "model" | "onToolExecutionEnd" | "onToolExecutionStart" | "experimental_onToolCallFinish" | "experimental_onToolCallStart" | "experimental_sandbox" | "experimental_toolCallers" | "experimental_toolApprovalSecret" | "prompt" | "prepareStep" | "stopWhen" | "system" | "tools";
9
+ type RetypedStreamTextSetting = "experimental_onStart" | "experimental_onStepStart" | "experimental_repairToolCall" | "experimental_transform" | "onStart" | "onStepStart" | "repairToolCall";
10
+ type ModelFacingTools<T extends ToolSet$1> = { readonly [K in keyof T]: Omit<T[K], "execute">; };
11
+ type SettingEvent<T extends ToolSet$1, K extends keyof StreamTextOptions<T>> = NonNullable<StreamTextOptions<T>[K]> extends ((event: infer EVENT) => unknown) ? EVENT : never;
12
+ type ModelPhaseStartEvent<T extends ToolSet$1> = Omit<SettingEvent<T, "onStart">, "tools"> & {
13
+ readonly tools: ModelFacingTools<T> | undefined;
14
+ };
15
+ type ModelPhaseStepStartEvent<T extends ToolSet$1> = Omit<SettingEvent<T, "onStepStart">, "tools"> & {
16
+ readonly tools: ModelFacingTools<T> | undefined;
17
+ };
18
+ type ModelPhaseCallback<EVENT> = (event: EVENT) => void | PromiseLike<void>;
19
+ type StreamTextRepairToolCall<T extends ToolSet$1> = NonNullable<StreamTextOptions<T>["repairToolCall"]>;
20
+ type ModelPhaseRepairToolCall<T extends ToolSet$1> = (options: Omit<Parameters<StreamTextRepairToolCall<T>>[0], "tools"> & {
21
+ tools: ModelFacingTools<T>;
22
+ }) => ReturnType<StreamTextRepairToolCall<T>>;
23
+ type StreamTextTransformSetting<T extends ToolSet$1> = NonNullable<StreamTextOptions<T>["experimental_transform"]>;
24
+ type StreamTextTransform<T extends ToolSet$1> = Extract<StreamTextTransformSetting<T>, (...args: never[]) => unknown>;
25
+ type ModelPhaseTransform<T extends ToolSet$1> = (options: Omit<Parameters<StreamTextTransform<T>>[0], "tools"> & {
26
+ tools: ModelFacingTools<T>;
27
+ }) => ReturnType<StreamTextTransform<T>>;
9
28
  /** AI SDK streamText settings that remain meaningful for one durable step. */
10
- type AISDKStepSettings<T extends ToolSet$1> = Partial<Omit<StreamTextOptions<T>, ControlledStreamTextSetting | "timeout">> & {
29
+ type AISDKStepSettings<T extends ToolSet$1> = Partial<Omit<StreamTextOptions<T>, ControlledStreamTextSetting | RetypedStreamTextSetting | "timeout">> & {
11
30
  timeout?: ModelStepTimeout<T>;
31
+ onStart?: ModelPhaseCallback<ModelPhaseStartEvent<T>>;
32
+ experimental_onStart?: ModelPhaseCallback<ModelPhaseStartEvent<T>>;
33
+ onStepStart?: ModelPhaseCallback<ModelPhaseStepStartEvent<T>>;
34
+ experimental_onStepStart?: ModelPhaseCallback<ModelPhaseStepStartEvent<T>>;
35
+ repairToolCall?: ModelPhaseRepairToolCall<T>;
36
+ experimental_repairToolCall?: ModelPhaseRepairToolCall<T>;
37
+ experimental_transform?: ModelPhaseTransform<T> | Array<ModelPhaseTransform<T>>;
12
38
  };
13
39
  //#endregion
14
40
  //#region src/ai-server.d.ts
@@ -28,6 +54,10 @@ type AgentGenerateContext<M extends UIMessage, D extends AIEventDefs<M> & EventD
28
54
  generation: AgentGenerationSettings<T>;
29
55
  };
30
56
  type AgentGenerate<M extends UIMessage, D extends AIEventDefs<M> & EventDefs, T extends ToolSet> = (context: AgentGenerateContext<M, D, T>) => ReadableStream<UIMessageChunk> | Promise<ReadableStream<UIMessageChunk>>;
57
+ type UIMessageMetadata<M extends UIMessage> = M extends UIMessage<infer Metadata> ? Metadata : unknown;
58
+ type AgentMessageMetadata<M extends UIMessage, D extends AIEventDefs<M> & EventDefs, T extends ToolSet> = (context: AgentGenerateContext<M, D, T> & {
59
+ part: TextStreamPart<T>;
60
+ }) => UIMessageMetadata<M> | undefined;
31
61
  type AgentResolverContext<M extends UIMessage, D extends AIEventDefs<M> & EventDefs> = {
32
62
  event: ContractEvent<D, "ai.generation.requested">;
33
63
  state: AIState<M>;
@@ -52,9 +82,16 @@ type CreateHandlersOptions<M extends UIMessage, D extends AIEventDefs<M> & Event
52
82
  instructions?: Resolvable<Instructions | undefined, AgentResolverContext<M, D>>;
53
83
  /** Settings for each one-step AI SDK streamText call. */
54
84
  generation?: AgentGenerationSettings<T>;
55
- /** Maximum model steps in one assistant response. Defaults to 20. */
85
+ /**
86
+ * Maximum model steps in one assistant response. Defaults to Infinity.
87
+ */
56
88
  maxSteps?: number;
57
- /** Replace model generation with an AI SDK UI message chunk stream. */
89
+ /** Map default AI SDK stream parts to typed assistant message metadata. */
90
+ messageMetadata?: AgentMessageMetadata<M, D, T>;
91
+ /**
92
+ * Replace model generation with an AI SDK UI message chunk stream.
93
+ * The custom stream owns its metadata chunks.
94
+ */
58
95
  generate?: AgentGenerate<M, D, T>;
59
96
  compaction?: CompactionPolicy<M, D>;
60
97
  /** Progress is durably flushed at either limit, whichever is reached first. */
@@ -66,6 +103,8 @@ type CreateHandlersOptions<M extends UIMessage, D extends AIEventDefs<M> & Event
66
103
  type CreateAgentServerOptions<M extends UIMessage, D extends AIEventDefs<M> & EventDefs, T extends ToolSet = ToolSet> = CreateHandlersOptions<M, D, T> & Omit<ServerOptions<D>, "contract" | "handlers" | "validatePush"> & {
67
104
  handlers?: ServerOptions<D>["handlers"];
68
105
  };
106
+ /** Run `fn` with `ctx` as the ambient tool handler context, for direct tool tests. */
107
+ declare function runWithHandlerContext<D extends AgentToolEventDefs, R>(ctx: AgentToolContext<D>, fn: () => R): R;
69
108
  /**
70
109
  * Build the ordinary A2 handler table for the built-in agent protocol.
71
110
  * Application handlers can be spread beside this table.
@@ -74,4 +113,5 @@ declare function createHandlers<M extends UIMessage, D extends AIEventDefs<M> &
74
113
  /** Assemble an A2 server with the built-in agent handlers and app extensions. */
75
114
  declare function createAgentServer<M extends UIMessage, D extends AIEventDefs<M> & EventDefs, T extends ToolSet = ToolSet>(options: CreateAgentServerOptions<M, D, T>): A2Server<D>;
76
115
  //#endregion
77
- export { AgentGenerate, AgentGenerateContext, AgentGenerationSettings, AgentResolverContext, CompactionPolicy, CreateAgentServerOptions, CreateHandlersOptions, type Instructions, type LanguageModel, Resolvable, type ToolSet, createAgentServer, createHandlers, validateAgentPush };
116
+ export { AgentGenerate, AgentGenerateContext, AgentGenerationSettings, AgentMessageMetadata, AgentResolverContext, CompactionPolicy, CreateAgentServerOptions, CreateHandlersOptions, type Instructions, type LanguageModel, Resolvable, type ToolSet, createAgentServer, createHandlers, runWithHandlerContext, validateAgentPush };
117
+ //# sourceMappingURL=ai-server.d.ts.map