@tanstack/ai 0.42.0 → 0.43.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 (272) hide show
  1. package/README.md +15 -1
  2. package/dist/esm/activities/chat/adapter.js +23 -16
  3. package/dist/esm/activities/chat/adapter.js.map +1 -1
  4. package/dist/esm/activities/chat/agent-loop-strategies.d.ts +5 -36
  5. package/dist/esm/activities/chat/agent-loop-strategies.js +75 -21
  6. package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -1
  7. package/dist/esm/activities/chat/cancel.d.ts +40 -0
  8. package/dist/esm/activities/chat/cancel.js +54 -0
  9. package/dist/esm/activities/chat/cancel.js.map +1 -0
  10. package/dist/esm/activities/chat/index.d.ts +28 -21
  11. package/dist/esm/activities/chat/index.js +2100 -1813
  12. package/dist/esm/activities/chat/index.js.map +1 -1
  13. package/dist/esm/activities/chat/mcp/manager.d.ts +2 -2
  14. package/dist/esm/activities/chat/mcp/manager.js +90 -77
  15. package/dist/esm/activities/chat/mcp/manager.js.map +1 -1
  16. package/dist/esm/activities/chat/mcp/types.d.ts +2 -2
  17. package/dist/esm/activities/chat/messages.js +397 -346
  18. package/dist/esm/activities/chat/messages.js.map +1 -1
  19. package/dist/esm/activities/chat/middleware/builder.js +17 -15
  20. package/dist/esm/activities/chat/middleware/builder.js.map +1 -1
  21. package/dist/esm/activities/chat/middleware/capabilities.js +78 -43
  22. package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -1
  23. package/dist/esm/activities/chat/middleware/compose.d.ts +94 -1
  24. package/dist/esm/activities/chat/middleware/compose.js +623 -531
  25. package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
  26. package/dist/esm/activities/chat/middleware/define.js +12 -5
  27. package/dist/esm/activities/chat/middleware/define.js.map +1 -1
  28. package/dist/esm/activities/chat/middleware/index.d.ts +5 -1
  29. package/dist/esm/activities/chat/middleware/locks.d.ts +50 -0
  30. package/dist/esm/activities/chat/middleware/locks.js +71 -0
  31. package/dist/esm/activities/chat/middleware/locks.js.map +1 -0
  32. package/dist/esm/activities/chat/middleware/pending-turn.d.ts +15 -0
  33. package/dist/esm/activities/chat/middleware/pending-turn.js +35 -0
  34. package/dist/esm/activities/chat/middleware/pending-turn.js.map +1 -0
  35. package/dist/esm/activities/chat/middleware/run-disconnect.d.ts +23 -0
  36. package/dist/esm/activities/chat/middleware/run-disconnect.js +42 -0
  37. package/dist/esm/activities/chat/middleware/run-disconnect.js.map +1 -0
  38. package/dist/esm/activities/chat/middleware/run-store.d.ts +283 -0
  39. package/dist/esm/activities/chat/middleware/run-store.js +176 -0
  40. package/dist/esm/activities/chat/middleware/run-store.js.map +1 -0
  41. package/dist/esm/activities/chat/middleware/sandbox-runtime.js +14 -8
  42. package/dist/esm/activities/chat/middleware/sandbox-runtime.js.map +1 -1
  43. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +79 -70
  44. package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -1
  45. package/dist/esm/activities/chat/middleware/types.d.ts +59 -2
  46. package/dist/esm/activities/chat/middleware/validate.js +23 -28
  47. package/dist/esm/activities/chat/middleware/validate.js.map +1 -1
  48. package/dist/esm/activities/chat/stream/json-parser.js +39 -25
  49. package/dist/esm/activities/chat/stream/json-parser.js.map +1 -1
  50. package/dist/esm/activities/chat/stream/message-updaters.js +275 -234
  51. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  52. package/dist/esm/activities/chat/stream/processor.d.ts +24 -4
  53. package/dist/esm/activities/chat/stream/processor.js +1341 -1542
  54. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  55. package/dist/esm/activities/chat/stream/strategies.js +69 -53
  56. package/dist/esm/activities/chat/stream/strategies.js.map +1 -1
  57. package/dist/esm/activities/chat/tools/approval-schema.d.ts +19 -0
  58. package/dist/esm/activities/chat/tools/approval-schema.js +117 -0
  59. package/dist/esm/activities/chat/tools/approval-schema.js.map +1 -0
  60. package/dist/esm/activities/chat/tools/lazy-tool-manager.js +164 -191
  61. package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -1
  62. package/dist/esm/activities/chat/tools/lazy-tools.js +24 -12
  63. package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -1
  64. package/dist/esm/activities/chat/tools/schema-converter.js +293 -146
  65. package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
  66. package/dist/esm/activities/chat/tools/tool-calls.d.ts +18 -2
  67. package/dist/esm/activities/chat/tools/tool-calls.js +522 -531
  68. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  69. package/dist/esm/activities/chat/tools/tool-definition.d.ts +75 -16
  70. package/dist/esm/activities/chat/tools/tool-definition.js +95 -23
  71. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
  72. package/dist/esm/activities/error-payload.js +85 -47
  73. package/dist/esm/activities/error-payload.js.map +1 -1
  74. package/dist/esm/activities/generateAudio/adapter.js +22 -15
  75. package/dist/esm/activities/generateAudio/adapter.js.map +1 -1
  76. package/dist/esm/activities/generateAudio/index.d.ts +4 -0
  77. package/dist/esm/activities/generateAudio/index.js +141 -105
  78. package/dist/esm/activities/generateAudio/index.js.map +1 -1
  79. package/dist/esm/activities/generateImage/adapter.js +22 -15
  80. package/dist/esm/activities/generateImage/adapter.js.map +1 -1
  81. package/dist/esm/activities/generateImage/index.d.ts +4 -0
  82. package/dist/esm/activities/generateImage/index.js +155 -111
  83. package/dist/esm/activities/generateImage/index.js.map +1 -1
  84. package/dist/esm/activities/generateSpeech/adapter.js +22 -15
  85. package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
  86. package/dist/esm/activities/generateSpeech/index.d.ts +4 -0
  87. package/dist/esm/activities/generateSpeech/index.js +159 -110
  88. package/dist/esm/activities/generateSpeech/index.js.map +1 -1
  89. package/dist/esm/activities/generateTranscription/adapter.js +22 -15
  90. package/dist/esm/activities/generateTranscription/adapter.js.map +1 -1
  91. package/dist/esm/activities/generateTranscription/index.d.ts +4 -0
  92. package/dist/esm/activities/generateTranscription/index.js +159 -100
  93. package/dist/esm/activities/generateTranscription/index.js.map +1 -1
  94. package/dist/esm/activities/generateVideo/adapter.js +36 -29
  95. package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
  96. package/dist/esm/activities/generateVideo/index.d.ts +143 -19
  97. package/dist/esm/activities/generateVideo/index.js +456 -279
  98. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  99. package/dist/esm/activities/generateVideo/snap.js +60 -48
  100. package/dist/esm/activities/generateVideo/snap.js.map +1 -1
  101. package/dist/esm/activities/index.js +8 -34
  102. package/dist/esm/activities/middleware/index.d.ts +1 -1
  103. package/dist/esm/activities/middleware/run.d.ts +10 -0
  104. package/dist/esm/activities/middleware/run.js +53 -29
  105. package/dist/esm/activities/middleware/run.js.map +1 -1
  106. package/dist/esm/activities/middleware/types.d.ts +44 -6
  107. package/dist/esm/activities/stream-generation-result.d.ts +4 -1
  108. package/dist/esm/activities/stream-generation-result.js +79 -44
  109. package/dist/esm/activities/stream-generation-result.js.map +1 -1
  110. package/dist/esm/activities/summarize/adapter.js +22 -15
  111. package/dist/esm/activities/summarize/adapter.js.map +1 -1
  112. package/dist/esm/activities/summarize/chat-stream-summarize.js +252 -202
  113. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
  114. package/dist/esm/activities/summarize/index.d.ts +27 -0
  115. package/dist/esm/activities/summarize/index.js +268 -102
  116. package/dist/esm/activities/summarize/index.js.map +1 -1
  117. package/dist/esm/adapter-internals.d.ts +2 -1
  118. package/dist/esm/adapter-internals.js +4 -11
  119. package/dist/esm/client.d.ts +25 -3
  120. package/dist/esm/client.js +131 -64
  121. package/dist/esm/client.js.map +1 -1
  122. package/dist/esm/custom-events.d.ts +76 -0
  123. package/dist/esm/custom-events.js +37 -0
  124. package/dist/esm/custom-events.js.map +1 -0
  125. package/dist/esm/delivery-detach.d.ts +50 -0
  126. package/dist/esm/delivery-detach.js +71 -0
  127. package/dist/esm/delivery-detach.js.map +1 -0
  128. package/dist/esm/delivery-disconnect.d.ts +62 -0
  129. package/dist/esm/delivery-disconnect.js +81 -0
  130. package/dist/esm/delivery-disconnect.js.map +1 -0
  131. package/dist/esm/extend-adapter.js +19 -17
  132. package/dist/esm/extend-adapter.js.map +1 -1
  133. package/dist/esm/index.d.ts +24 -6
  134. package/dist/esm/index.js +30 -98
  135. package/dist/esm/interrupt-resume.d.ts +71 -0
  136. package/dist/esm/interrupt-resume.js +438 -0
  137. package/dist/esm/interrupt-resume.js.map +1 -0
  138. package/dist/esm/interrupt-serialization.d.ts +12 -0
  139. package/dist/esm/interrupt-serialization.js +178 -0
  140. package/dist/esm/interrupt-serialization.js.map +1 -0
  141. package/dist/esm/interrupts.d.ts +84 -0
  142. package/dist/esm/interrupts.js +31 -0
  143. package/dist/esm/interrupts.js.map +1 -0
  144. package/dist/esm/locks.d.ts +10 -0
  145. package/dist/esm/locks.js +2 -0
  146. package/dist/esm/logger/console-logger.js +101 -78
  147. package/dist/esm/logger/console-logger.js.map +1 -1
  148. package/dist/esm/logger/internal-logger.js +104 -89
  149. package/dist/esm/logger/internal-logger.js.map +1 -1
  150. package/dist/esm/logger/resolve.js +54 -49
  151. package/dist/esm/logger/resolve.js.map +1 -1
  152. package/dist/esm/logger/types.d.ts +1 -1
  153. package/dist/esm/middlewares/content-guard.js +142 -148
  154. package/dist/esm/middlewares/content-guard.js.map +1 -1
  155. package/dist/esm/middlewares/index.js +2 -6
  156. package/dist/esm/middlewares/otel.js +598 -732
  157. package/dist/esm/middlewares/otel.js.map +1 -1
  158. package/dist/esm/middlewares/usage-attributes.js +47 -40
  159. package/dist/esm/middlewares/usage-attributes.js.map +1 -1
  160. package/dist/esm/realtime/event-emitter.js +24 -25
  161. package/dist/esm/realtime/event-emitter.js.map +1 -1
  162. package/dist/esm/realtime/index.d.ts +5 -9
  163. package/dist/esm/realtime/index.js +29 -6
  164. package/dist/esm/realtime/index.js.map +1 -1
  165. package/dist/esm/scope.d.ts +47 -0
  166. package/dist/esm/stream-durability.d.ts +171 -0
  167. package/dist/esm/stream-durability.js +295 -0
  168. package/dist/esm/stream-durability.js.map +1 -0
  169. package/dist/esm/stream-to-response.d.ts +178 -13
  170. package/dist/esm/stream-to-response.js +663 -115
  171. package/dist/esm/stream-to-response.js.map +1 -1
  172. package/dist/esm/strip-to-spec-middleware.js +30 -16
  173. package/dist/esm/strip-to-spec-middleware.js.map +1 -1
  174. package/dist/esm/system-prompts.js +27 -21
  175. package/dist/esm/system-prompts.js.map +1 -1
  176. package/dist/esm/tool-registry.js +72 -45
  177. package/dist/esm/tool-registry.js.map +1 -1
  178. package/dist/esm/tools/provider-tool.js +14 -5
  179. package/dist/esm/tools/provider-tool.js.map +1 -1
  180. package/dist/esm/types.d.ts +321 -42
  181. package/dist/esm/types.js +2 -0
  182. package/dist/esm/utilities/ag-ui-wire.js +79 -93
  183. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  184. package/dist/esm/utilities/chat-params.d.ts +26 -4
  185. package/dist/esm/utilities/chat-params.js +218 -92
  186. package/dist/esm/utilities/chat-params.js.map +1 -1
  187. package/dist/esm/utilities/errors.js +28 -18
  188. package/dist/esm/utilities/errors.js.map +1 -1
  189. package/dist/esm/utilities/media-prompt.js +46 -41
  190. package/dist/esm/utilities/media-prompt.js.map +1 -1
  191. package/dist/esm/utilities/numbers.js +13 -10
  192. package/dist/esm/utilities/numbers.js.map +1 -1
  193. package/dist/esm/utilities/provider-executed.js +20 -11
  194. package/dist/esm/utilities/provider-executed.js.map +1 -1
  195. package/dist/esm/utilities/sampling-keys.js +31 -19
  196. package/dist/esm/utilities/sampling-keys.js.map +1 -1
  197. package/dist/esm/utilities/tool-result.js +42 -30
  198. package/dist/esm/utilities/tool-result.js.map +1 -1
  199. package/dist/esm/utilities/usage.js +27 -9
  200. package/dist/esm/utilities/usage.js.map +1 -1
  201. package/dist/esm/utils.js +26 -18
  202. package/dist/esm/utils.js.map +1 -1
  203. package/package.json +10 -6
  204. package/skills/ai-core/SKILL.md +69 -18
  205. package/skills/ai-core/adapter-configuration/SKILL.md +44 -21
  206. package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +1 -3
  207. package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +148 -0
  208. package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +2 -6
  209. package/skills/ai-core/adapter-configuration/references/groq-adapter.md +2 -6
  210. package/skills/ai-core/adapter-configuration/references/openai-adapter.md +1 -3
  211. package/skills/ai-core/ag-ui-protocol/SKILL.md +1 -1
  212. package/skills/ai-core/chat-experience/SKILL.md +98 -11
  213. package/skills/ai-core/client-persistence/SKILL.md +277 -0
  214. package/skills/ai-core/custom-backend-integration/SKILL.md +1 -1
  215. package/skills/ai-core/debug-logging/SKILL.md +1 -1
  216. package/skills/ai-core/locks/SKILL.md +143 -0
  217. package/skills/ai-core/media-generation/SKILL.md +144 -12
  218. package/skills/ai-core/middleware/SKILL.md +258 -33
  219. package/skills/ai-core/structured-outputs/SKILL.md +1 -1
  220. package/skills/ai-core/tool-calling/SKILL.md +54 -61
  221. package/src/activities/chat/agent-loop-strategies.ts +5 -39
  222. package/src/activities/chat/cancel.ts +81 -0
  223. package/src/activities/chat/index.ts +1091 -200
  224. package/src/activities/chat/mcp/manager.ts +4 -4
  225. package/src/activities/chat/mcp/types.ts +2 -2
  226. package/src/activities/chat/messages.ts +5 -3
  227. package/src/activities/chat/middleware/builder.ts +1 -1
  228. package/src/activities/chat/middleware/compose.ts +186 -9
  229. package/src/activities/chat/middleware/index.ts +26 -0
  230. package/src/activities/chat/middleware/locks.ts +102 -0
  231. package/src/activities/chat/middleware/pending-turn.ts +47 -0
  232. package/src/activities/chat/middleware/run-disconnect.ts +62 -0
  233. package/src/activities/chat/middleware/run-store.ts +412 -0
  234. package/src/activities/chat/middleware/types.ts +62 -1
  235. package/src/activities/chat/stream/processor.ts +189 -5
  236. package/src/activities/chat/tools/approval-schema.ts +205 -0
  237. package/src/activities/chat/tools/tool-calls.ts +106 -13
  238. package/src/activities/chat/tools/tool-definition.ts +210 -39
  239. package/src/activities/generateAudio/index.ts +20 -3
  240. package/src/activities/generateImage/index.ts +20 -3
  241. package/src/activities/generateSpeech/index.ts +25 -3
  242. package/src/activities/generateTranscription/index.ts +26 -3
  243. package/src/activities/generateVideo/index.ts +345 -82
  244. package/src/activities/middleware/index.ts +2 -0
  245. package/src/activities/middleware/run.ts +31 -0
  246. package/src/activities/middleware/types.ts +49 -5
  247. package/src/activities/stream-generation-result.ts +30 -2
  248. package/src/activities/summarize/chat-stream-summarize.ts +5 -0
  249. package/src/activities/summarize/index.ts +200 -10
  250. package/src/adapter-internals.ts +10 -1
  251. package/src/client.ts +244 -0
  252. package/src/custom-events.ts +107 -0
  253. package/src/delivery-detach.ts +72 -0
  254. package/src/delivery-disconnect.ts +84 -0
  255. package/src/index.ts +138 -1
  256. package/src/interrupt-resume.ts +824 -0
  257. package/src/interrupt-serialization.ts +183 -0
  258. package/src/interrupts.ts +146 -0
  259. package/src/locks.ts +17 -0
  260. package/src/logger/types.ts +1 -1
  261. package/src/middlewares/otel.ts +1 -0
  262. package/src/realtime/index.ts +5 -9
  263. package/src/scope.ts +47 -0
  264. package/src/stream-durability.ts +598 -0
  265. package/src/stream-to-response.ts +1051 -95
  266. package/src/strip-to-spec-middleware.ts +3 -3
  267. package/src/types.ts +405 -45
  268. package/src/utilities/chat-params.ts +245 -55
  269. package/dist/esm/activities/index.js.map +0 -1
  270. package/dist/esm/adapter-internals.js.map +0 -1
  271. package/dist/esm/index.js.map +0 -1
  272. package/dist/esm/middlewares/index.js.map +0 -1
@@ -1,4 +1,10 @@
1
+ import { LockStore } from './activities/chat/middleware/locks.js';
2
+ import { RunStore } from './activities/chat/middleware/run-store.js';
3
+ import { InternalLogger } from './logger/internal-logger.js';
4
+ import { DebugOption } from './logger/types.js';
5
+ import { StreamDurability } from './stream-durability.js';
1
6
  import { StreamChunk } from './types.js';
7
+ export { resolveResumeRunId } from './stream-durability.js';
2
8
  /**
3
9
  * Collect all text content from a StreamChunk async iterable and return as a string.
4
10
  *
@@ -11,8 +17,7 @@ import { StreamChunk } from './types.js';
11
17
  * @example
12
18
  * ```typescript
13
19
  * const stream = chat({
14
- * adapter: openaiText(),
15
- * model: 'gpt-4o',
20
+ * adapter: openaiText('gpt-5.5'),
16
21
  * messages: [{ role: 'user', content: 'Hello!' }]
17
22
  * });
18
23
  * const text = await streamToText(stream);
@@ -30,9 +35,30 @@ export declare function streamToText(stream: AsyncIterable<StreamChunk>): Promis
30
35
  *
31
36
  * @param stream - AsyncIterable of StreamChunks from chat()
32
37
  * @param abortController - Optional AbortController to abort when stream is cancelled
38
+ * @param getId - Optional per-chunk durability offset; when present, each event gets an `id:` line
33
39
  * @returns ReadableStream in Server-Sent Events format
34
40
  */
35
- export declare function toServerSentEventsStream(stream: AsyncIterable<StreamChunk>, abortController?: AbortController): ReadableStream<Uint8Array>;
41
+ export declare function toServerSentEventsStream(stream: AsyncIterable<StreamChunk>, abortController?: AbortController, getId?: (chunk: StreamChunk, index: number) => string | undefined): ReadableStream<Uint8Array>;
42
+ /**
43
+ * Name of the synthetic `CUSTOM` chunk a fresh durable producer appends to its
44
+ * log before pulling the first real chunk.
45
+ *
46
+ * Flushing `RUN_STARTED` (above) makes a run joinable from the instant the
47
+ * stream EMITS something — but a `chat()` whose middleware boots a sandbox
48
+ * (create a container, install a CLI) legitimately emits nothing for minutes,
49
+ * and during that window the log is empty. Every joiner's empty-log fail-fast
50
+ * (`memoryStream`'s first-chunk deadline, the client's rejoin connect deadline)
51
+ * then reads the run as gone — and the client clears its resume pointer, so a
52
+ * reload during the boot window permanently orphans a run that is still going.
53
+ *
54
+ * This marker closes the window: it is appended (and flushed) before the
55
+ * producer stream is first pulled, so a join always finds a first chunk within
56
+ * milliseconds of the run being accepted. Takeover alignment is unaffected — a
57
+ * journal replay cannot reproduce the marker, and alignment already skips
58
+ * stored `CUSTOM` chunks as out-of-band for exactly that reason (see
59
+ * `isBridgeCustomChunk` in `@tanstack/ai-sandbox`).
60
+ */
61
+ export declare const RUN_ACCEPTED_EVENT = "run.accepted";
36
62
  /**
37
63
  * Convert a StreamChunk async iterable to a Response in Server-Sent Events format
38
64
  *
@@ -41,19 +67,113 @@ export declare function toServerSentEventsStream(stream: AsyncIterable<StreamChu
41
67
  * - Each chunk is followed by "\n\n"
42
68
  * - Stream ends when the underlying iterable is exhausted (RUN_FINISHED is the terminal event)
43
69
  *
70
+ * Pass a `durability` sink (`memoryStream(request)` / `durableStream(request)`)
71
+ * to make the stream resumable: fresh runs are appended to the log and each SSE
72
+ * event is tagged with an `id:` offset; a reconnect (native `Last-Event-ID`) or
73
+ * a `?offset` join replays from the log without re-running the producer. `batch`
74
+ * controls how many chunks are buffered per `append` (default 32).
75
+ *
44
76
  * @param stream - AsyncIterable of StreamChunks from chat()
45
- * @param init - Optional Response initialization options (including `abortController`)
77
+ * @param init - Optional Response initialization options (including `abortController`, `durability` with its optional `batch`, and `debug`)
46
78
  * @returns Response in Server-Sent Events format
47
79
  *
48
80
  * @example
49
81
  * ```typescript
50
- * const stream = chat({ adapter: openaiText(), model: "gpt-4o", messages: [...] });
51
- * return toServerSentEventsResponse(stream, { abortController });
82
+ * export async function POST(request: Request) {
83
+ * const stream = chat({ adapter: openaiText('gpt-5.5'), messages: [...] });
84
+ * return toServerSentEventsResponse(stream, { durability: { adapter: memoryStream(request) } });
85
+ * }
52
86
  * ```
53
87
  */
54
- export declare function toServerSentEventsResponse(stream: AsyncIterable<StreamChunk>, init?: ResponseInit & {
88
+ export declare function toServerSentEventsResponse<TOffset extends string = string>(stream: AsyncIterable<StreamChunk>, init?: ResponseInit & {
55
89
  abortController?: AbortController;
90
+ durability?: {
91
+ adapter: StreamDurability<TOffset>;
92
+ batch?: number;
93
+ };
94
+ /**
95
+ * Customize logging for durability failure paths (terminal-append and
96
+ * close). These failures are always logged server-side by default (the
97
+ * `errors` category is on even without `debug`, via a `ConsoleLogger`);
98
+ * pass `debug` to route them to a custom `Logger` or raise verbosity. A
99
+ * joiner replaying the log only ever sees a generic incomplete error, so
100
+ * server-side logging is where the real cause is recoverable.
101
+ */
102
+ debug?: DebugOption;
56
103
  }): Response;
104
+ /**
105
+ * Everything the resume helpers need to take a run over as a side effect of
106
+ * serving its log.
107
+ *
108
+ * `claim` and `pipe` are **injected**, not imported. The two mechanisms a
109
+ * takeover needs (`withRunClaim` and `pipeToRunLog`) live in
110
+ * `@tanstack/ai-sandbox`, and `@tanstack/ai` must not depend on that package —
111
+ * that layering inversion is exactly what moving `LockStore` into core was meant
112
+ * to prevent, and it would make core depend on the sandbox package to serve a
113
+ * plain chat run. Injecting them keeps only the *shape* of a takeover in core
114
+ * (parse the run id, read the record, skip if terminal, claim, drive) and lets a
115
+ * background-worker-driven run supply its own pair.
116
+ * `@tanstack/ai-sandbox`'s `sandboxRunDriver` fills both in.
117
+ */
118
+ export interface RunDriverOptions {
119
+ /** The attach request; its run id is read with {@link resolveResumeRunId}. */
120
+ request: Request;
121
+ runs: RunStore;
122
+ locks: LockStore;
123
+ /** Produce the run's remaining events. Called only once the claim is held. */
124
+ drive: (input: {
125
+ runId: string;
126
+ threadId: string;
127
+ signal: AbortSignal;
128
+ }) => AsyncIterable<StreamChunk>;
129
+ /** Run `fn` under exclusive ownership of the run, or reject if refused. */
130
+ claim: <T>(input: {
131
+ runs: RunStore;
132
+ locks: LockStore;
133
+ runId: string;
134
+ }, fn: (claim: {
135
+ runId: string;
136
+ epoch: number;
137
+ signal: AbortSignal;
138
+ }) => Promise<T>) => Promise<T>;
139
+ /** Persist the driven stream to the run's producer-side durability log. */
140
+ pipe: (stream: AsyncIterable<StreamChunk>, input: {
141
+ runId: string;
142
+ threadId: string;
143
+ signal: AbortSignal;
144
+ }) => Promise<unknown>;
145
+ /** Platform keep-alive (e.g. `ctx.waitUntil`) for the background drive. */
146
+ waitUntil?: (promise: Promise<unknown>) => void;
147
+ logger?: InternalLogger;
148
+ }
149
+ /** Shared options for the resume-only response helpers. */
150
+ type ResumeResponseOptions<TOffset extends string> = ResponseInit & {
151
+ adapter: StreamDurability<TOffset>;
152
+ batch?: number;
153
+ debug?: DebugOption;
154
+ /**
155
+ * Take the run over while serving its log. Omit to serve the log only —
156
+ * the response is byte-identical either way.
157
+ */
158
+ driver?: RunDriverOptions;
159
+ };
160
+ /**
161
+ * Serve a resumable run from its durability log over Server-Sent Events, without
162
+ * re-running the model. Use this in a `GET` handler so a reload or a second tab
163
+ * can re-attach to an in-flight or finished run.
164
+ *
165
+ * The adapter (`memoryStream(request)` / `durableStream(request)`) captures the
166
+ * resume offset from the request. If there is none (no `Last-Event-ID` header
167
+ * and no `?offset`), there is nothing to replay and this returns a 400.
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * export async function GET(request: Request) {
172
+ * return resumeServerSentEventsResponse({ adapter: memoryStream(request) });
173
+ * }
174
+ * ```
175
+ */
176
+ export declare function resumeServerSentEventsResponse<TOffset extends string = string>(options: ResumeResponseOptions<TOffset>): Response;
57
177
  /**
58
178
  * Convert a StreamChunk async iterable to a ReadableStream in HTTP stream format (newline-delimited JSON)
59
179
  *
@@ -63,13 +183,20 @@ export declare function toServerSentEventsResponse(stream: AsyncIterable<StreamC
63
183
  *
64
184
  * This format is compatible with `fetchHttpStream` connection adapter.
65
185
  *
186
+ * When `getId` is supplied (delivery durability), each chunk is emitted as an
187
+ * envelope `{"id":"<offset>","chunk":{…}}` instead of a bare chunk. NDJSON has
188
+ * no native event-id field like SSE's `id:` line, so the resumable offset rides
189
+ * inside the payload. Untagged chunks (no id) stay bare, so a non-durable
190
+ * stream is byte-identical to before and the client auto-detects either form.
191
+ *
66
192
  * @param stream - AsyncIterable of StreamChunks from chat()
67
193
  * @param abortController - Optional AbortController to abort when stream is cancelled
194
+ * @param getId - Optional per-chunk durability offset; when present, chunks are envelope-encoded
68
195
  * @returns ReadableStream in HTTP stream format (newline-delimited JSON)
69
196
  *
70
197
  * @example
71
198
  * ```typescript
72
- * const stream = chat({ adapter: openaiText(), model: "gpt-4o", messages: [...] });
199
+ * const stream = chat({ adapter: openaiText('gpt-5.5'), messages: [...] });
73
200
  * const readableStream = toHttpStream(stream);
74
201
  * // Use with Response for HTTP streaming (not SSE)
75
202
  * return new Response(readableStream, {
@@ -77,7 +204,7 @@ export declare function toServerSentEventsResponse(stream: AsyncIterable<StreamC
77
204
  * });
78
205
  * ```
79
206
  */
80
- export declare function toHttpStream(stream: AsyncIterable<StreamChunk>, abortController?: AbortController): ReadableStream<Uint8Array>;
207
+ export declare function toHttpStream(stream: AsyncIterable<StreamChunk>, abortController?: AbortController, getId?: (chunk: StreamChunk, index: number) => string | undefined): ReadableStream<Uint8Array>;
81
208
  /**
82
209
  * Convert a StreamChunk async iterable to a Response in HTTP stream format (newline-delimited JSON)
83
210
  *
@@ -87,16 +214,54 @@ export declare function toHttpStream(stream: AsyncIterable<StreamChunk>, abortCo
87
214
  *
88
215
  * This format is compatible with `fetchHttpStream` connection adapter.
89
216
  *
217
+ * Pass a `durability` sink (`memoryStream(request)` / `durableStream(request)`)
218
+ * to make the stream resumable: fresh runs are appended to the log and each
219
+ * NDJSON line is emitted as an `{ id, chunk }` envelope carrying an opaque
220
+ * offset; a reconnect (native `Last-Event-ID` header) or a `?offset` join
221
+ * replays from the log without re-running the producer. `batch` controls how
222
+ * many chunks are buffered per `append` (default 32). This shares the exact
223
+ * `durableStreamSource` used by `toServerSentEventsResponse` — only the wire
224
+ * encoding differs.
225
+ *
90
226
  * @param stream - AsyncIterable of StreamChunks from chat()
91
- * @param init - Optional Response initialization options (including `abortController`)
227
+ * @param init - Optional Response initialization options (including `abortController`, `durability` with its optional `batch`, and `debug`)
92
228
  * @returns Response in HTTP stream format (newline-delimited JSON)
93
229
  *
94
230
  * @example
95
231
  * ```typescript
96
- * const stream = chat({ adapter: openaiText(), model: "gpt-4o", messages: [...] });
97
- * return toHttpResponse(stream, { abortController });
232
+ * export async function POST(request: Request) {
233
+ * const stream = chat({ adapter: openaiText('gpt-5.5'), messages: [...] });
234
+ * return toHttpResponse(stream, { durability: { adapter: memoryStream(request) } });
235
+ * }
98
236
  * ```
99
237
  */
100
- export declare function toHttpResponse(stream: AsyncIterable<StreamChunk>, init?: ResponseInit & {
238
+ export declare function toHttpResponse<TOffset extends string = string>(stream: AsyncIterable<StreamChunk>, init?: ResponseInit & {
101
239
  abortController?: AbortController;
240
+ durability?: {
241
+ adapter: StreamDurability<TOffset>;
242
+ batch?: number;
243
+ };
244
+ /**
245
+ * Customize logging for durability failure paths (terminal-append and
246
+ * close). These failures are always logged server-side by default (the
247
+ * `errors` category is on even without `debug`, via a `ConsoleLogger`);
248
+ * pass `debug` to route them to a custom `Logger` or raise verbosity. A
249
+ * joiner replaying the log only ever sees a generic incomplete error, so
250
+ * server-side logging is where the real cause is recoverable.
251
+ */
252
+ debug?: DebugOption;
102
253
  }): Response;
254
+ /**
255
+ * Serve a resumable run from its durability log over NDJSON, without re-running
256
+ * the model. The NDJSON counterpart of {@link resumeServerSentEventsResponse};
257
+ * pair it with a `toHttpResponse` producer. Returns a 400 when the request
258
+ * carries no resume offset (no `Last-Event-ID` header and no `?offset`).
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * export async function GET(request: Request) {
263
+ * return resumeHttpResponse({ adapter: memoryStream(request) });
264
+ * }
265
+ * ```
266
+ */
267
+ export declare function resumeHttpResponse<TOffset extends string = string>(options: ResumeResponseOptions<TOffset>): Response;