@trigger.dev/sdk 0.0.0-python-preview-20250226140121 → 0.0.0-rc-4-8-0-20261021151928

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 (732) hide show
  1. package/README.md +29 -9
  2. package/dist/commonjs/imports/ai-runtime-cjs.cjs.map +1 -0
  3. package/dist/commonjs/imports/ai-runtime.d.ts +1 -0
  4. package/dist/commonjs/imports/ai-runtime.js +31 -0
  5. package/dist/commonjs/imports/uncrypto.js +4 -4
  6. package/dist/commonjs/package.json +2 -1
  7. package/dist/commonjs/v3/agentSkillsRuntime.d.ts +28 -0
  8. package/dist/commonjs/v3/agentSkillsRuntime.js +173 -0
  9. package/dist/commonjs/v3/agentSkillsRuntime.js.map +1 -0
  10. package/dist/commonjs/v3/ai-shared.d.ts +156 -0
  11. package/dist/commonjs/v3/ai-shared.js +215 -0
  12. package/dist/commonjs/v3/ai-shared.js.map +1 -0
  13. package/dist/commonjs/v3/ai.d.ts +4225 -0
  14. package/dist/commonjs/v3/ai.js +11569 -0
  15. package/dist/commonjs/v3/ai.js.map +1 -0
  16. package/dist/commonjs/v3/aiAutoTelemetry.d.ts +2 -0
  17. package/dist/commonjs/v3/aiAutoTelemetry.js +81 -0
  18. package/dist/commonjs/v3/aiAutoTelemetry.js.map +1 -0
  19. package/dist/commonjs/v3/auth.d.ts +71 -10
  20. package/dist/commonjs/v3/auth.js +85 -19
  21. package/dist/commonjs/v3/auth.js.map +1 -1
  22. package/dist/commonjs/v3/batch.d.ts +3 -3
  23. package/dist/commonjs/v3/batch.js.map +1 -1
  24. package/dist/commonjs/v3/cache.js.map +1 -1
  25. package/dist/commonjs/v3/chat-client.d.ts +324 -0
  26. package/dist/commonjs/v3/chat-client.js +774 -0
  27. package/dist/commonjs/v3/chat-client.js.map +1 -0
  28. package/dist/commonjs/v3/chat-react.d.ts +244 -0
  29. package/dist/commonjs/v3/chat-react.js +463 -0
  30. package/dist/commonjs/v3/chat-react.js.map +1 -0
  31. package/dist/commonjs/v3/chat-server.d.ts +350 -0
  32. package/dist/commonjs/v3/chat-server.js +965 -0
  33. package/dist/commonjs/v3/chat-server.js.map +1 -0
  34. package/dist/commonjs/v3/chat-tab-coordinator.d.ts +65 -0
  35. package/dist/commonjs/v3/chat-tab-coordinator.js +235 -0
  36. package/dist/commonjs/v3/chat-tab-coordinator.js.map +1 -0
  37. package/dist/commonjs/v3/chat.d.ts +792 -0
  38. package/dist/commonjs/v3/chat.js +1662 -0
  39. package/dist/commonjs/v3/chat.js.map +1 -0
  40. package/dist/commonjs/v3/chatRouteWait.d.ts +21 -0
  41. package/dist/commonjs/v3/chatRouteWait.js +43 -0
  42. package/dist/commonjs/v3/chatRouteWait.js.map +1 -0
  43. package/dist/commonjs/v3/chatSnapshotIo.d.ts +2 -0
  44. package/dist/commonjs/v3/chatSnapshotIo.js +173 -0
  45. package/dist/commonjs/v3/chatSnapshotIo.js.map +1 -0
  46. package/dist/commonjs/v3/chatVersionSkew.d.ts +12 -0
  47. package/dist/commonjs/v3/chatVersionSkew.js +30 -0
  48. package/dist/commonjs/v3/chatVersionSkew.js.map +1 -0
  49. package/dist/commonjs/v3/compactionResponse.d.ts +9 -0
  50. package/dist/commonjs/v3/compactionResponse.js +37 -0
  51. package/dist/commonjs/v3/compactionResponse.js.map +1 -0
  52. package/dist/commonjs/v3/concurrency-shared.d.ts +13 -0
  53. package/dist/commonjs/v3/concurrency-shared.js +35 -0
  54. package/dist/commonjs/v3/concurrency-shared.js.map +1 -0
  55. package/dist/commonjs/v3/concurrencyLimits.d.ts +103 -0
  56. package/dist/commonjs/v3/concurrencyLimits.js +134 -0
  57. package/dist/commonjs/v3/concurrencyLimits.js.map +1 -0
  58. package/dist/commonjs/v3/config.js.map +1 -1
  59. package/dist/commonjs/v3/deployments.d.ts +25 -0
  60. package/dist/commonjs/v3/deployments.js +37 -0
  61. package/dist/commonjs/v3/deployments.js.map +1 -0
  62. package/dist/commonjs/v3/envvars.d.ts +5 -5
  63. package/dist/commonjs/v3/envvars.js.map +1 -1
  64. package/dist/commonjs/v3/externalDeploymentId.d.ts +23 -0
  65. package/dist/commonjs/v3/externalDeploymentId.js +43 -0
  66. package/dist/commonjs/v3/externalDeploymentId.js.map +1 -0
  67. package/dist/commonjs/v3/heartbeats.d.ts +37 -0
  68. package/dist/commonjs/v3/heartbeats.js +45 -0
  69. package/dist/commonjs/v3/heartbeats.js.map +1 -0
  70. package/dist/commonjs/v3/hooks.d.ts +26 -0
  71. package/dist/commonjs/v3/hooks.js +79 -0
  72. package/dist/commonjs/v3/hooks.js.map +1 -0
  73. package/dist/commonjs/v3/idempotencyKeys.d.ts +2 -1
  74. package/dist/commonjs/v3/idempotencyKeys.js +1 -0
  75. package/dist/commonjs/v3/idempotencyKeys.js.map +1 -1
  76. package/dist/commonjs/v3/index.d.ts +20 -5
  77. package/dist/commonjs/v3/index.js +56 -20
  78. package/dist/commonjs/v3/index.js.map +1 -1
  79. package/dist/commonjs/v3/locals.d.ts +3 -0
  80. package/dist/commonjs/v3/locals.js +6 -0
  81. package/dist/commonjs/v3/locals.js.map +1 -0
  82. package/dist/commonjs/v3/managedChatResponse.d.ts +44 -0
  83. package/dist/commonjs/v3/managedChatResponse.js +221 -0
  84. package/dist/commonjs/v3/managedChatResponse.js.map +1 -0
  85. package/dist/commonjs/v3/metadata.d.ts +5 -2
  86. package/dist/commonjs/v3/metadata.js +8 -1
  87. package/dist/commonjs/v3/metadata.js.map +1 -1
  88. package/dist/commonjs/v3/modelFileDownload.d.ts +10 -0
  89. package/dist/commonjs/v3/modelFileDownload.js +164 -0
  90. package/dist/commonjs/v3/modelFileDownload.js.map +1 -0
  91. package/dist/commonjs/v3/otel.d.ts +4 -0
  92. package/dist/commonjs/v3/otel.js +12 -0
  93. package/dist/commonjs/v3/otel.js.map +1 -0
  94. package/dist/commonjs/v3/prompt.d.ts +38 -0
  95. package/dist/commonjs/v3/prompt.js +146 -0
  96. package/dist/commonjs/v3/prompt.js.map +1 -0
  97. package/dist/commonjs/v3/promptManagement.d.ts +26 -0
  98. package/dist/commonjs/v3/promptManagement.js +180 -0
  99. package/dist/commonjs/v3/promptManagement.js.map +1 -0
  100. package/dist/commonjs/v3/prompts.d.ts +3 -0
  101. package/dist/commonjs/v3/prompts.js +15 -0
  102. package/dist/commonjs/v3/prompts.js.map +1 -0
  103. package/dist/commonjs/v3/query.d.ts +545 -0
  104. package/dist/commonjs/v3/query.js +163 -0
  105. package/dist/commonjs/v3/query.js.map +1 -0
  106. package/dist/commonjs/v3/queues.d.ts +107 -0
  107. package/dist/commonjs/v3/queues.js +225 -0
  108. package/dist/commonjs/v3/queues.js.map +1 -0
  109. package/dist/commonjs/v3/retry.d.ts +6 -2
  110. package/dist/commonjs/v3/retry.js +34 -23
  111. package/dist/commonjs/v3/retry.js.map +1 -1
  112. package/dist/commonjs/v3/runs.d.ts +182 -101
  113. package/dist/commonjs/v3/runs.js +99 -5
  114. package/dist/commonjs/v3/runs.js.map +1 -1
  115. package/dist/commonjs/v3/schedules/api.d.ts +8 -1
  116. package/dist/commonjs/v3/schedules/index.d.ts +29 -9
  117. package/dist/commonjs/v3/schedules/index.js +5 -1
  118. package/dist/commonjs/v3/schedules/index.js.map +1 -1
  119. package/dist/commonjs/v3/schemas.d.ts +1 -0
  120. package/dist/commonjs/{integrations.js → v3/schemas.js} +1 -1
  121. package/dist/commonjs/v3/schemas.js.map +1 -0
  122. package/dist/commonjs/v3/sessionTracing.d.ts +7 -0
  123. package/dist/commonjs/v3/sessionTracing.js +44 -0
  124. package/dist/commonjs/v3/sessionTracing.js.map +1 -0
  125. package/dist/commonjs/v3/sessions.d.ts +268 -0
  126. package/dist/commonjs/v3/sessions.js +776 -0
  127. package/dist/commonjs/v3/sessions.js.map +1 -0
  128. package/dist/commonjs/v3/shared.d.ts +129 -24
  129. package/dist/commonjs/v3/shared.js +1527 -689
  130. package/dist/commonjs/v3/shared.js.map +1 -1
  131. package/dist/commonjs/v3/skill.d.ts +99 -0
  132. package/dist/commonjs/v3/skill.js +165 -0
  133. package/dist/commonjs/v3/skill.js.map +1 -0
  134. package/dist/commonjs/v3/skills.d.ts +2 -0
  135. package/dist/commonjs/v3/skills.js +6 -0
  136. package/dist/commonjs/v3/skills.js.map +1 -0
  137. package/dist/commonjs/v3/steeringContext.d.ts +41 -0
  138. package/dist/commonjs/v3/steeringContext.js +118 -0
  139. package/dist/commonjs/v3/steeringContext.js.map +1 -0
  140. package/dist/commonjs/v3/streams.d.ts +298 -0
  141. package/dist/commonjs/v3/streams.js +584 -0
  142. package/dist/commonjs/v3/streams.js.map +1 -0
  143. package/dist/commonjs/v3/tasks.d.ts +19 -4
  144. package/dist/commonjs/v3/tasks.js +15 -1
  145. package/dist/commonjs/v3/tasks.js.map +1 -1
  146. package/dist/commonjs/v3/test/index.d.ts +5 -0
  147. package/dist/commonjs/v3/test/index.js +23 -0
  148. package/dist/commonjs/v3/test/index.js.map +1 -0
  149. package/dist/commonjs/v3/test/mock-channel-connector.d.ts +172 -0
  150. package/dist/commonjs/v3/test/mock-channel-connector.js +173 -0
  151. package/dist/commonjs/v3/test/mock-channel-connector.js.map +1 -0
  152. package/dist/commonjs/v3/test/mock-chat-agent.d.ts +388 -0
  153. package/dist/commonjs/v3/test/mock-chat-agent.js +689 -0
  154. package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -0
  155. package/dist/commonjs/v3/test/setup-catalog.d.ts +1 -0
  156. package/dist/commonjs/v3/test/setup-catalog.js +18 -0
  157. package/dist/commonjs/v3/test/setup-catalog.js.map +1 -0
  158. package/dist/commonjs/v3/test/test-session-handle.d.ts +24 -0
  159. package/dist/commonjs/v3/test/test-session-handle.js +271 -0
  160. package/dist/commonjs/v3/test/test-session-handle.js.map +1 -0
  161. package/dist/commonjs/v3/test/transcript-storage-tests.d.ts +40 -0
  162. package/dist/commonjs/v3/test/transcript-storage-tests.js +258 -0
  163. package/dist/commonjs/v3/test/transcript-storage-tests.js.map +1 -0
  164. package/dist/commonjs/v3/toolResultOrder.d.ts +15 -0
  165. package/dist/commonjs/v3/toolResultOrder.js +58 -0
  166. package/dist/commonjs/v3/toolResultOrder.js.map +1 -0
  167. package/dist/commonjs/v3/transcriptStorage.d.ts +307 -0
  168. package/dist/commonjs/v3/transcriptStorage.js +445 -0
  169. package/dist/commonjs/v3/transcriptStorage.js.map +1 -0
  170. package/dist/commonjs/v3/triggerClient.d.ts +45 -0
  171. package/dist/commonjs/v3/triggerClient.js +114 -0
  172. package/dist/commonjs/v3/triggerClient.js.map +1 -0
  173. package/dist/commonjs/v3/uiMessageChunks.d.ts +1 -0
  174. package/dist/commonjs/v3/uiMessageChunks.js +119 -0
  175. package/dist/commonjs/v3/uiMessageChunks.js.map +1 -0
  176. package/dist/commonjs/v3/usage.js +7 -6
  177. package/dist/commonjs/v3/usage.js.map +1 -1
  178. package/dist/commonjs/v3/wait.d.ts +218 -3
  179. package/dist/commonjs/v3/wait.js +433 -7
  180. package/dist/commonjs/v3/wait.js.map +1 -1
  181. package/dist/commonjs/v3/waitUntil.js.map +1 -1
  182. package/dist/commonjs/v3/webhookWaiters.d.ts +80 -0
  183. package/dist/commonjs/v3/webhookWaiters.js +156 -0
  184. package/dist/commonjs/v3/webhookWaiters.js.map +1 -0
  185. package/dist/commonjs/v3/webhooks.d.ts +192 -2
  186. package/dist/commonjs/v3/webhooks.js +340 -2
  187. package/dist/commonjs/v3/webhooks.js.map +1 -1
  188. package/dist/commonjs/version.js +1 -1
  189. package/dist/esm/imports/ai-runtime.d.ts +2 -0
  190. package/dist/esm/imports/ai-runtime.js +16 -0
  191. package/dist/esm/imports/ai-runtime.js.map +1 -0
  192. package/dist/esm/package.json +2 -1
  193. package/dist/esm/v3/agentSkillsRuntime.d.ts +28 -0
  194. package/dist/esm/v3/agentSkillsRuntime.js +136 -0
  195. package/dist/esm/v3/agentSkillsRuntime.js.map +1 -0
  196. package/dist/esm/v3/ai-shared.d.ts +156 -0
  197. package/dist/esm/v3/ai-shared.js +208 -0
  198. package/dist/esm/v3/ai-shared.js.map +1 -0
  199. package/dist/esm/v3/ai.d.ts +4225 -0
  200. package/dist/esm/v3/ai.js +11550 -0
  201. package/dist/esm/v3/ai.js.map +1 -0
  202. package/dist/esm/v3/aiAutoTelemetry.d.ts +2 -0
  203. package/dist/esm/v3/aiAutoTelemetry.js +78 -0
  204. package/dist/esm/v3/aiAutoTelemetry.js.map +1 -0
  205. package/dist/esm/v3/auth.d.ts +71 -10
  206. package/dist/esm/v3/auth.js +83 -17
  207. package/dist/esm/v3/auth.js.map +1 -1
  208. package/dist/esm/v3/batch.d.ts +3 -3
  209. package/dist/esm/v3/batch.js +2 -2
  210. package/dist/esm/v3/batch.js.map +1 -1
  211. package/dist/esm/v3/chat-client.d.ts +324 -0
  212. package/dist/esm/v3/chat-client.js +769 -0
  213. package/dist/esm/v3/chat-client.js.map +1 -0
  214. package/dist/esm/v3/chat-react.d.ts +244 -0
  215. package/dist/esm/v3/chat-react.js +455 -0
  216. package/dist/esm/v3/chat-react.js.map +1 -0
  217. package/dist/esm/v3/chat-server.d.ts +350 -0
  218. package/dist/esm/v3/chat-server.js +962 -0
  219. package/dist/esm/v3/chat-server.js.map +1 -0
  220. package/dist/esm/v3/chat-tab-coordinator.d.ts +65 -0
  221. package/dist/esm/v3/chat-tab-coordinator.js +231 -0
  222. package/dist/esm/v3/chat-tab-coordinator.js.map +1 -0
  223. package/dist/esm/v3/chat.d.ts +792 -0
  224. package/dist/esm/v3/chat.js +1655 -0
  225. package/dist/esm/v3/chat.js.map +1 -0
  226. package/dist/esm/v3/chatRouteWait.d.ts +21 -0
  227. package/dist/esm/v3/chatRouteWait.js +40 -0
  228. package/dist/esm/v3/chatRouteWait.js.map +1 -0
  229. package/dist/esm/v3/chatSnapshotIo.d.ts +2 -0
  230. package/dist/esm/v3/chatSnapshotIo.js +165 -0
  231. package/dist/esm/v3/chatSnapshotIo.js.map +1 -0
  232. package/dist/esm/v3/chatVersionSkew.d.ts +12 -0
  233. package/dist/esm/v3/chatVersionSkew.js +27 -0
  234. package/dist/esm/v3/chatVersionSkew.js.map +1 -0
  235. package/dist/esm/v3/compactionResponse.d.ts +9 -0
  236. package/dist/esm/v3/compactionResponse.js +34 -0
  237. package/dist/esm/v3/compactionResponse.js.map +1 -0
  238. package/dist/esm/v3/concurrency-shared.d.ts +13 -0
  239. package/dist/esm/v3/concurrency-shared.js +31 -0
  240. package/dist/esm/v3/concurrency-shared.js.map +1 -0
  241. package/dist/esm/v3/concurrencyLimits.d.ts +103 -0
  242. package/dist/esm/v3/concurrencyLimits.js +126 -0
  243. package/dist/esm/v3/concurrencyLimits.js.map +1 -0
  244. package/dist/esm/v3/deployments.d.ts +25 -0
  245. package/dist/esm/v3/deployments.js +34 -0
  246. package/dist/esm/v3/deployments.js.map +1 -0
  247. package/dist/esm/v3/envvars.d.ts +5 -5
  248. package/dist/esm/v3/envvars.js.map +1 -1
  249. package/dist/esm/v3/externalDeploymentId.d.ts +23 -0
  250. package/dist/esm/v3/externalDeploymentId.js +38 -0
  251. package/dist/esm/v3/externalDeploymentId.js.map +1 -0
  252. package/dist/esm/v3/heartbeats.d.ts +37 -0
  253. package/dist/esm/v3/heartbeats.js +42 -0
  254. package/dist/esm/v3/heartbeats.js.map +1 -0
  255. package/dist/esm/v3/hooks.d.ts +26 -0
  256. package/dist/esm/v3/hooks.js +66 -0
  257. package/dist/esm/v3/hooks.js.map +1 -0
  258. package/dist/esm/v3/idempotencyKeys.d.ts +2 -1
  259. package/dist/esm/v3/idempotencyKeys.js +2 -1
  260. package/dist/esm/v3/idempotencyKeys.js.map +1 -1
  261. package/dist/esm/v3/index.d.ts +20 -5
  262. package/dist/esm/v3/index.js +16 -2
  263. package/dist/esm/v3/index.js.map +1 -1
  264. package/dist/esm/v3/locals.d.ts +3 -0
  265. package/dist/esm/v3/locals.js +3 -0
  266. package/dist/esm/v3/locals.js.map +1 -0
  267. package/dist/esm/v3/managedChatResponse.d.ts +44 -0
  268. package/dist/esm/v3/managedChatResponse.js +216 -0
  269. package/dist/esm/v3/managedChatResponse.js.map +1 -0
  270. package/dist/esm/v3/metadata.d.ts +5 -2
  271. package/dist/esm/v3/metadata.js +8 -1
  272. package/dist/esm/v3/metadata.js.map +1 -1
  273. package/dist/esm/v3/modelFileDownload.d.ts +10 -0
  274. package/dist/esm/v3/modelFileDownload.js +161 -0
  275. package/dist/esm/v3/modelFileDownload.js.map +1 -0
  276. package/dist/esm/v3/otel.d.ts +4 -0
  277. package/dist/esm/v3/otel.js +9 -0
  278. package/dist/esm/v3/otel.js.map +1 -0
  279. package/dist/esm/v3/prompt.d.ts +38 -0
  280. package/dist/esm/v3/prompt.js +143 -0
  281. package/dist/esm/v3/prompt.js.map +1 -0
  282. package/dist/esm/v3/promptManagement.d.ts +26 -0
  283. package/dist/esm/v3/promptManagement.js +170 -0
  284. package/dist/esm/v3/promptManagement.js.map +1 -0
  285. package/dist/esm/v3/prompts.d.ts +3 -0
  286. package/dist/esm/v3/prompts.js +3 -0
  287. package/dist/esm/v3/prompts.js.map +1 -0
  288. package/dist/esm/v3/query.d.ts +545 -0
  289. package/dist/esm/v3/query.js +160 -0
  290. package/dist/esm/v3/query.js.map +1 -0
  291. package/dist/esm/v3/queues.d.ts +107 -0
  292. package/dist/esm/v3/queues.js +217 -0
  293. package/dist/esm/v3/queues.js.map +1 -0
  294. package/dist/esm/v3/retry.d.ts +6 -2
  295. package/dist/esm/v3/retry.js +27 -19
  296. package/dist/esm/v3/retry.js.map +1 -1
  297. package/dist/esm/v3/runs.d.ts +179 -98
  298. package/dist/esm/v3/runs.js +99 -5
  299. package/dist/esm/v3/runs.js.map +1 -1
  300. package/dist/esm/v3/schedules/api.d.ts +8 -1
  301. package/dist/esm/v3/schedules/index.d.ts +29 -9
  302. package/dist/esm/v3/schedules/index.js +6 -2
  303. package/dist/esm/v3/schedules/index.js.map +1 -1
  304. package/dist/esm/v3/schemas.d.ts +1 -0
  305. package/dist/esm/v3/schemas.js +2 -0
  306. package/dist/esm/v3/schemas.js.map +1 -0
  307. package/dist/esm/v3/sessionTracing.d.ts +7 -0
  308. package/dist/esm/v3/sessionTracing.js +40 -0
  309. package/dist/esm/v3/sessionTracing.js.map +1 -0
  310. package/dist/esm/v3/sessions.d.ts +268 -0
  311. package/dist/esm/v3/sessions.js +767 -0
  312. package/dist/esm/v3/sessions.js.map +1 -0
  313. package/dist/esm/v3/shared.d.ts +129 -24
  314. package/dist/esm/v3/shared.js +1521 -688
  315. package/dist/esm/v3/shared.js.map +1 -1
  316. package/dist/esm/v3/skill.d.ts +99 -0
  317. package/dist/esm/v3/skill.js +128 -0
  318. package/dist/esm/v3/skill.js.map +1 -0
  319. package/dist/esm/v3/skills.d.ts +2 -0
  320. package/dist/esm/v3/skills.js +2 -0
  321. package/dist/esm/v3/skills.js.map +1 -0
  322. package/dist/esm/v3/steeringContext.d.ts +41 -0
  323. package/dist/esm/v3/steeringContext.js +113 -0
  324. package/dist/esm/v3/steeringContext.js.map +1 -0
  325. package/dist/esm/v3/streams.d.ts +298 -0
  326. package/dist/esm/v3/streams.js +580 -0
  327. package/dist/esm/v3/streams.js.map +1 -0
  328. package/dist/esm/v3/tasks.d.ts +19 -4
  329. package/dist/esm/v3/tasks.js +16 -2
  330. package/dist/esm/v3/tasks.js.map +1 -1
  331. package/dist/esm/v3/test/index.d.ts +5 -0
  332. package/dist/esm/v3/test/index.js +15 -0
  333. package/dist/esm/v3/test/index.js.map +1 -0
  334. package/dist/esm/v3/test/mock-channel-connector.d.ts +172 -0
  335. package/dist/esm/v3/test/mock-channel-connector.js +170 -0
  336. package/dist/esm/v3/test/mock-channel-connector.js.map +1 -0
  337. package/dist/esm/v3/test/mock-chat-agent.d.ts +388 -0
  338. package/dist/esm/v3/test/mock-chat-agent.js +685 -0
  339. package/dist/esm/v3/test/mock-chat-agent.js.map +1 -0
  340. package/dist/esm/v3/test/setup-catalog.d.ts +1 -0
  341. package/dist/esm/v3/test/setup-catalog.js +16 -0
  342. package/dist/esm/v3/test/setup-catalog.js.map +1 -0
  343. package/dist/esm/v3/test/test-session-handle.d.ts +24 -0
  344. package/dist/esm/v3/test/test-session-handle.js +268 -0
  345. package/dist/esm/v3/test/test-session-handle.js.map +1 -0
  346. package/dist/esm/v3/test/transcript-storage-tests.d.ts +40 -0
  347. package/dist/esm/v3/test/transcript-storage-tests.js +255 -0
  348. package/dist/esm/v3/test/transcript-storage-tests.js.map +1 -0
  349. package/dist/esm/v3/toolResultOrder.d.ts +15 -0
  350. package/dist/esm/v3/toolResultOrder.js +55 -0
  351. package/dist/esm/v3/toolResultOrder.js.map +1 -0
  352. package/dist/esm/v3/transcriptStorage.d.ts +307 -0
  353. package/dist/esm/v3/transcriptStorage.js +431 -0
  354. package/dist/esm/v3/transcriptStorage.js.map +1 -0
  355. package/dist/esm/v3/triggerClient.d.ts +45 -0
  356. package/dist/esm/v3/triggerClient.js +77 -0
  357. package/dist/esm/v3/triggerClient.js.map +1 -0
  358. package/dist/esm/v3/uiMessageChunks.d.ts +1 -0
  359. package/dist/esm/v3/uiMessageChunks.js +116 -0
  360. package/dist/esm/v3/uiMessageChunks.js.map +1 -0
  361. package/dist/esm/v3/usage.js +7 -6
  362. package/dist/esm/v3/usage.js.map +1 -1
  363. package/dist/esm/v3/wait.d.ts +218 -3
  364. package/dist/esm/v3/wait.js +431 -7
  365. package/dist/esm/v3/wait.js.map +1 -1
  366. package/dist/esm/v3/webhookWaiters.d.ts +80 -0
  367. package/dist/esm/v3/webhookWaiters.js +149 -0
  368. package/dist/esm/v3/webhookWaiters.js.map +1 -0
  369. package/dist/esm/v3/webhooks.d.ts +192 -2
  370. package/dist/esm/v3/webhooks.js +336 -2
  371. package/dist/esm/v3/webhooks.js.map +1 -1
  372. package/dist/esm/version.js +1 -1
  373. package/docs/ai/observability.mdx +174 -0
  374. package/docs/ai/prompts.mdx +426 -0
  375. package/docs/ai-chat/actions.mdx +148 -0
  376. package/docs/ai-chat/anatomy.mdx +87 -0
  377. package/docs/ai-chat/backend.mdx +933 -0
  378. package/docs/ai-chat/background-injection.mdx +320 -0
  379. package/docs/ai-chat/changelog.mdx +958 -0
  380. package/docs/ai-chat/chat-local.mdx +170 -0
  381. package/docs/ai-chat/client-protocol.mdx +1091 -0
  382. package/docs/ai-chat/compaction.mdx +413 -0
  383. package/docs/ai-chat/custom-agents.mdx +545 -0
  384. package/docs/ai-chat/error-handling.mdx +379 -0
  385. package/docs/ai-chat/fast-starts.mdx +764 -0
  386. package/docs/ai-chat/frontend.mdx +634 -0
  387. package/docs/ai-chat/how-it-works.mdx +226 -0
  388. package/docs/ai-chat/lifecycle-hooks.mdx +532 -0
  389. package/docs/ai-chat/mcp.mdx +97 -0
  390. package/docs/ai-chat/migrating-from-a-route-handler.mdx +594 -0
  391. package/docs/ai-chat/migrating-from-hydrate-messages.mdx +299 -0
  392. package/docs/ai-chat/overview.mdx +86 -0
  393. package/docs/ai-chat/patterns/branching-conversations.mdx +145 -0
  394. package/docs/ai-chat/patterns/code-sandbox.mdx +122 -0
  395. package/docs/ai-chat/patterns/database-persistence.mdx +425 -0
  396. package/docs/ai-chat/patterns/human-in-the-loop.mdx +281 -0
  397. package/docs/ai-chat/patterns/large-payloads.mdx +165 -0
  398. package/docs/ai-chat/patterns/native-compaction.mdx +310 -0
  399. package/docs/ai-chat/patterns/oom-resilience.mdx +116 -0
  400. package/docs/ai-chat/patterns/persistence-and-replay.mdx +218 -0
  401. package/docs/ai-chat/patterns/recovery-boot.mdx +233 -0
  402. package/docs/ai-chat/patterns/redacting-telemetry.mdx +117 -0
  403. package/docs/ai-chat/patterns/skills.mdx +214 -0
  404. package/docs/ai-chat/patterns/sub-agents.mdx +412 -0
  405. package/docs/ai-chat/patterns/tool-result-auditing.mdx +145 -0
  406. package/docs/ai-chat/patterns/trusted-edge-signals.mdx +333 -0
  407. package/docs/ai-chat/patterns/version-upgrades.mdx +261 -0
  408. package/docs/ai-chat/pending-messages.mdx +363 -0
  409. package/docs/ai-chat/prompt-caching.mdx +204 -0
  410. package/docs/ai-chat/quick-start.mdx +163 -0
  411. package/docs/ai-chat/reference.mdx +1071 -0
  412. package/docs/ai-chat/server-chat.mdx +259 -0
  413. package/docs/ai-chat/sessions.mdx +334 -0
  414. package/docs/ai-chat/side-channels.mdx +172 -0
  415. package/docs/ai-chat/testing.mdx +691 -0
  416. package/docs/ai-chat/tools.mdx +192 -0
  417. package/docs/ai-chat/transcript-storage.mdx +247 -0
  418. package/docs/ai-chat/types.mdx +242 -0
  419. package/docs/ai-chat/upgrade-guide.mdx +511 -0
  420. package/docs/apikeys.mdx +170 -0
  421. package/docs/billing-limits.mdx +73 -0
  422. package/docs/building-with-ai.mdx +261 -0
  423. package/docs/bulk-actions.mdx +77 -0
  424. package/docs/changelog.mdx +6 -0
  425. package/docs/cli-deploy-commands.mdx +9 -0
  426. package/docs/cli-dev-commands.mdx +9 -0
  427. package/docs/cli-env-commands.mdx +115 -0
  428. package/docs/cli-init-commands.mdx +84 -0
  429. package/docs/cli-introduction.mdx +25 -0
  430. package/docs/cli-list-profiles-commands.mdx +42 -0
  431. package/docs/cli-login-commands.mdx +53 -0
  432. package/docs/cli-logout-commands.mdx +33 -0
  433. package/docs/cli-preview-archive.mdx +59 -0
  434. package/docs/cli-projects-commands.mdx +74 -0
  435. package/docs/cli-promote-commands.mdx +9 -0
  436. package/docs/cli-runs-commands.mdx +95 -0
  437. package/docs/cli-switch.mdx +43 -0
  438. package/docs/cli-tasks-commands.mdx +95 -0
  439. package/docs/cli-update-commands.mdx +48 -0
  440. package/docs/cli-whoami-commands.mdx +45 -0
  441. package/docs/community.mdx +6 -0
  442. package/docs/concurrency.mdx +416 -0
  443. package/docs/config/config-file.mdx +662 -0
  444. package/docs/config/extensions/additionalFiles.mdx +38 -0
  445. package/docs/config/extensions/additionalPackages.mdx +40 -0
  446. package/docs/config/extensions/aptGet.mdx +34 -0
  447. package/docs/config/extensions/audioWaveform.mdx +23 -0
  448. package/docs/config/extensions/custom.mdx +393 -0
  449. package/docs/config/extensions/emitDecoratorMetadata.mdx +52 -0
  450. package/docs/config/extensions/esbuildPlugin.mdx +31 -0
  451. package/docs/config/extensions/ffmpeg.mdx +45 -0
  452. package/docs/config/extensions/lightpanda.mdx +56 -0
  453. package/docs/config/extensions/overview.mdx +69 -0
  454. package/docs/config/extensions/playwright.mdx +195 -0
  455. package/docs/config/extensions/prismaExtension.mdx +1013 -0
  456. package/docs/config/extensions/puppeteer.mdx +28 -0
  457. package/docs/config/extensions/pythonExtension.mdx +190 -0
  458. package/docs/config/extensions/syncEnvVars.mdx +330 -0
  459. package/docs/context.mdx +235 -0
  460. package/docs/database-connections.mdx +213 -0
  461. package/docs/deploy-environment-variables.mdx +466 -0
  462. package/docs/deployment/atomic-deployment.mdx +470 -0
  463. package/docs/deployment/dev-branches.mdx +92 -0
  464. package/docs/deployment/overview.mdx +260 -0
  465. package/docs/deployment/preview-branches.mdx +227 -0
  466. package/docs/errors-retrying.mdx +383 -0
  467. package/docs/github-actions.mdx +260 -0
  468. package/docs/github-integration.mdx +148 -0
  469. package/docs/github-repo.mdx +8 -0
  470. package/docs/help-email.mdx +6 -0
  471. package/docs/help-slack.mdx +12 -0
  472. package/docs/hidden-tasks.mdx +56 -0
  473. package/docs/how-it-works.mdx +454 -0
  474. package/docs/how-to-reduce-your-spend.mdx +211 -0
  475. package/docs/idempotency.mdx +542 -0
  476. package/docs/introduction.mdx +135 -0
  477. package/docs/limits.mdx +284 -0
  478. package/docs/logging.mdx +195 -0
  479. package/docs/machines.mdx +952 -0
  480. package/docs/manual-setup.mdx +632 -0
  481. package/docs/mcp-agent-rules.mdx +41 -0
  482. package/docs/mcp-introduction.mdx +386 -0
  483. package/docs/mcp-tools.mdx +425 -0
  484. package/docs/migrating-from-v3.mdx +332 -0
  485. package/docs/observability/dashboards.mdx +166 -0
  486. package/docs/observability/query.mdx +614 -0
  487. package/docs/open-source-contributing.mdx +16 -0
  488. package/docs/private-networking/aws-console-setup.mdx +304 -0
  489. package/docs/private-networking/overview.mdx +144 -0
  490. package/docs/private-networking/troubleshooting.mdx +78 -0
  491. package/docs/queues.mdx +271 -0
  492. package/docs/quick-start.mdx +60 -0
  493. package/docs/realtime/auth.mdx +228 -0
  494. package/docs/realtime/backend/input-streams.mdx +159 -0
  495. package/docs/realtime/backend/overview.mdx +45 -0
  496. package/docs/realtime/backend/streams.mdx +433 -0
  497. package/docs/realtime/backend/subscribe.mdx +225 -0
  498. package/docs/realtime/how-it-works.mdx +94 -0
  499. package/docs/realtime/overview.mdx +63 -0
  500. package/docs/realtime/react-hooks/overview.mdx +73 -0
  501. package/docs/realtime/react-hooks/session-stream.mdx +126 -0
  502. package/docs/realtime/react-hooks/streams.mdx +517 -0
  503. package/docs/realtime/react-hooks/subscribe.mdx +690 -0
  504. package/docs/realtime/react-hooks/swr.mdx +87 -0
  505. package/docs/realtime/react-hooks/triggering.mdx +194 -0
  506. package/docs/realtime/react-hooks/use-wait-token.mdx +34 -0
  507. package/docs/realtime/run-object.mdx +197 -0
  508. package/docs/replaying.mdx +97 -0
  509. package/docs/reports.mdx +159 -0
  510. package/docs/request-feature.mdx +6 -0
  511. package/docs/roadmap.mdx +6 -0
  512. package/docs/run-tests.mdx +21 -0
  513. package/docs/run-usage.mdx +113 -0
  514. package/docs/runs/bulk-actions.mdx +183 -0
  515. package/docs/runs/heartbeats.mdx +38 -0
  516. package/docs/runs/list-best-practices.mdx +234 -0
  517. package/docs/runs/max-duration.mdx +143 -0
  518. package/docs/runs/metadata.mdx +731 -0
  519. package/docs/runs/priority.mdx +8 -0
  520. package/docs/runs.mdx +406 -0
  521. package/docs/self-hosting/docker.mdx +512 -0
  522. package/docs/self-hosting/env/supervisor.mdx +78 -0
  523. package/docs/self-hosting/env/webapp.mdx +305 -0
  524. package/docs/self-hosting/kubernetes.mdx +725 -0
  525. package/docs/self-hosting/overview.mdx +145 -0
  526. package/docs/self-hosting/security.mdx +67 -0
  527. package/docs/skills.mdx +85 -0
  528. package/docs/tags.mdx +126 -0
  529. package/docs/tasks/overview.mdx +695 -0
  530. package/docs/tasks/scheduled.mdx +479 -0
  531. package/docs/tasks/schemaTask.mdx +413 -0
  532. package/docs/tasks/streams.mdx +887 -0
  533. package/docs/triggering.mdx +1340 -0
  534. package/docs/troubleshooting-alerts.mdx +607 -0
  535. package/docs/troubleshooting-debugging-in-vscode.mdx +9 -0
  536. package/docs/troubleshooting-github-issues.mdx +6 -0
  537. package/docs/troubleshooting-uptime-status.mdx +7 -0
  538. package/docs/troubleshooting-zod.mdx +158 -0
  539. package/docs/troubleshooting.mdx +414 -0
  540. package/docs/upgrading-packages.mdx +80 -0
  541. package/docs/vercel-integration.mdx +250 -0
  542. package/docs/versioning.mdx +58 -0
  543. package/docs/video-walkthrough.mdx +23 -0
  544. package/docs/wait-for-token.mdx +540 -0
  545. package/docs/wait-for.mdx +42 -0
  546. package/docs/wait-until.mdx +53 -0
  547. package/docs/wait.mdx +18 -0
  548. package/docs/webhooks/channels.mdx +154 -0
  549. package/docs/webhooks/connect.mdx +91 -0
  550. package/docs/webhooks/deliveries.mdx +99 -0
  551. package/docs/webhooks/filters.mdx +146 -0
  552. package/docs/webhooks/human-in-the-loop.mdx +158 -0
  553. package/docs/webhooks/linear.mdx +186 -0
  554. package/docs/webhooks/overview.mdx +115 -0
  555. package/docs/webhooks/session-routing.mdx +141 -0
  556. package/docs/webhooks/slack.mdx +393 -0
  557. package/docs/webhooks/sources.mdx +250 -0
  558. package/docs/webhooks/waiters.mdx +190 -0
  559. package/docs/writing-tasks-introduction.mdx +34 -0
  560. package/package.json +143 -42
  561. package/skills/trigger-authoring-chat-agent/SKILL.md +308 -0
  562. package/skills/trigger-authoring-tasks/SKILL.md +254 -0
  563. package/skills/trigger-chat-agent-advanced/SKILL.md +403 -0
  564. package/skills/trigger-cost-savings/SKILL.md +116 -0
  565. package/skills/trigger-realtime-and-frontend/SKILL.md +276 -0
  566. package/dist/commonjs/apiClient.d.ts +0 -727
  567. package/dist/commonjs/apiClient.js +0 -692
  568. package/dist/commonjs/apiClient.js.map +0 -1
  569. package/dist/commonjs/concurrencyLimit.d.ts +0 -10
  570. package/dist/commonjs/concurrencyLimit.js +0 -17
  571. package/dist/commonjs/concurrencyLimit.js.map +0 -1
  572. package/dist/commonjs/errors.d.ts +0 -66
  573. package/dist/commonjs/errors.js +0 -109
  574. package/dist/commonjs/errors.js.map +0 -1
  575. package/dist/commonjs/httpEndpoint.d.ts +0 -87
  576. package/dist/commonjs/httpEndpoint.js +0 -130
  577. package/dist/commonjs/httpEndpoint.js.map +0 -1
  578. package/dist/commonjs/index.d.ts +0 -23
  579. package/dist/commonjs/index.js +0 -55
  580. package/dist/commonjs/index.js.map +0 -1
  581. package/dist/commonjs/integrations.d.ts +0 -11
  582. package/dist/commonjs/integrations.js.map +0 -1
  583. package/dist/commonjs/io.d.ts +0 -441
  584. package/dist/commonjs/io.js +0 -1165
  585. package/dist/commonjs/io.js.map +0 -1
  586. package/dist/commonjs/ioWithIntegrations.d.ts +0 -4
  587. package/dist/commonjs/ioWithIntegrations.js +0 -32
  588. package/dist/commonjs/ioWithIntegrations.js.map +0 -1
  589. package/dist/commonjs/job.d.ts +0 -96
  590. package/dist/commonjs/job.js +0 -210
  591. package/dist/commonjs/job.js.map +0 -1
  592. package/dist/commonjs/retry.d.ts +0 -20
  593. package/dist/commonjs/retry.js +0 -22
  594. package/dist/commonjs/retry.js.map +0 -1
  595. package/dist/commonjs/runLocalStorage.d.ts +0 -8
  596. package/dist/commonjs/runLocalStorage.js +0 -6
  597. package/dist/commonjs/runLocalStorage.js.map +0 -1
  598. package/dist/commonjs/security.d.ts +0 -18
  599. package/dist/commonjs/security.js +0 -41
  600. package/dist/commonjs/security.js.map +0 -1
  601. package/dist/commonjs/status.d.ts +0 -19
  602. package/dist/commonjs/status.js +0 -38
  603. package/dist/commonjs/status.js.map +0 -1
  604. package/dist/commonjs/store/keyValueStore.d.ts +0 -17
  605. package/dist/commonjs/store/keyValueStore.js +0 -138
  606. package/dist/commonjs/store/keyValueStore.js.map +0 -1
  607. package/dist/commonjs/store/keyValueStoreClient.d.ts +0 -19
  608. package/dist/commonjs/store/keyValueStoreClient.js +0 -65
  609. package/dist/commonjs/store/keyValueStoreClient.js.map +0 -1
  610. package/dist/commonjs/triggerClient.d.ts +0 -290
  611. package/dist/commonjs/triggerClient.js +0 -1366
  612. package/dist/commonjs/triggerClient.js.map +0 -1
  613. package/dist/commonjs/triggers/dynamic.d.ts +0 -56
  614. package/dist/commonjs/triggers/dynamic.js +0 -97
  615. package/dist/commonjs/triggers/dynamic.js.map +0 -1
  616. package/dist/commonjs/triggers/eventTrigger.d.ts +0 -58
  617. package/dist/commonjs/triggers/eventTrigger.js +0 -69
  618. package/dist/commonjs/triggers/eventTrigger.js.map +0 -1
  619. package/dist/commonjs/triggers/externalSource.d.ts +0 -148
  620. package/dist/commonjs/triggers/externalSource.js +0 -106
  621. package/dist/commonjs/triggers/externalSource.js.map +0 -1
  622. package/dist/commonjs/triggers/invokeTrigger.d.ts +0 -39
  623. package/dist/commonjs/triggers/invokeTrigger.js +0 -58
  624. package/dist/commonjs/triggers/invokeTrigger.js.map +0 -1
  625. package/dist/commonjs/triggers/notifications.d.ts +0 -111
  626. package/dist/commonjs/triggers/notifications.js +0 -101
  627. package/dist/commonjs/triggers/notifications.js.map +0 -1
  628. package/dist/commonjs/triggers/scheduled.d.ts +0 -145
  629. package/dist/commonjs/triggers/scheduled.js +0 -208
  630. package/dist/commonjs/triggers/scheduled.js.map +0 -1
  631. package/dist/commonjs/triggers/webhook.d.ts +0 -143
  632. package/dist/commonjs/triggers/webhook.js +0 -133
  633. package/dist/commonjs/triggers/webhook.js.map +0 -1
  634. package/dist/commonjs/typed-emitter.d.ts +0 -37
  635. package/dist/commonjs/typed-emitter.js +0 -3
  636. package/dist/commonjs/typed-emitter.js.map +0 -1
  637. package/dist/commonjs/types.d.ts +0 -204
  638. package/dist/commonjs/types.js +0 -23
  639. package/dist/commonjs/types.js.map +0 -1
  640. package/dist/commonjs/utils/formatSchemaErrors.d.ts +0 -3
  641. package/dist/commonjs/utils/formatSchemaErrors.js +0 -10
  642. package/dist/commonjs/utils/formatSchemaErrors.js.map +0 -1
  643. package/dist/commonjs/utils/typedAsyncLocalStorage.d.ts +0 -6
  644. package/dist/commonjs/utils/typedAsyncLocalStorage.js +0 -18
  645. package/dist/commonjs/utils/typedAsyncLocalStorage.js.map +0 -1
  646. package/dist/commonjs/utils.d.ts +0 -1
  647. package/dist/commonjs/utils.js +0 -11
  648. package/dist/commonjs/utils.js.map +0 -1
  649. package/dist/esm/apiClient.d.ts +0 -727
  650. package/dist/esm/apiClient.js +0 -687
  651. package/dist/esm/apiClient.js.map +0 -1
  652. package/dist/esm/concurrencyLimit.d.ts +0 -10
  653. package/dist/esm/concurrencyLimit.js +0 -13
  654. package/dist/esm/concurrencyLimit.js.map +0 -1
  655. package/dist/esm/errors.d.ts +0 -66
  656. package/dist/esm/errors.js +0 -95
  657. package/dist/esm/errors.js.map +0 -1
  658. package/dist/esm/httpEndpoint.d.ts +0 -87
  659. package/dist/esm/httpEndpoint.js +0 -125
  660. package/dist/esm/httpEndpoint.js.map +0 -1
  661. package/dist/esm/index.d.ts +0 -23
  662. package/dist/esm/index.js +0 -35
  663. package/dist/esm/index.js.map +0 -1
  664. package/dist/esm/integrations.d.ts +0 -11
  665. package/dist/esm/integrations.js +0 -2
  666. package/dist/esm/integrations.js.map +0 -1
  667. package/dist/esm/io.d.ts +0 -441
  668. package/dist/esm/io.js +0 -1159
  669. package/dist/esm/io.js.map +0 -1
  670. package/dist/esm/ioWithIntegrations.d.ts +0 -4
  671. package/dist/esm/ioWithIntegrations.js +0 -29
  672. package/dist/esm/ioWithIntegrations.js.map +0 -1
  673. package/dist/esm/job.d.ts +0 -96
  674. package/dist/esm/job.js +0 -206
  675. package/dist/esm/job.js.map +0 -1
  676. package/dist/esm/retry.d.ts +0 -20
  677. package/dist/esm/retry.js +0 -19
  678. package/dist/esm/retry.js.map +0 -1
  679. package/dist/esm/runLocalStorage.d.ts +0 -8
  680. package/dist/esm/runLocalStorage.js +0 -3
  681. package/dist/esm/runLocalStorage.js.map +0 -1
  682. package/dist/esm/security.d.ts +0 -18
  683. package/dist/esm/security.js +0 -34
  684. package/dist/esm/security.js.map +0 -1
  685. package/dist/esm/status.d.ts +0 -19
  686. package/dist/esm/status.js +0 -34
  687. package/dist/esm/status.js.map +0 -1
  688. package/dist/esm/store/keyValueStore.d.ts +0 -17
  689. package/dist/esm/store/keyValueStore.js +0 -134
  690. package/dist/esm/store/keyValueStore.js.map +0 -1
  691. package/dist/esm/store/keyValueStoreClient.d.ts +0 -19
  692. package/dist/esm/store/keyValueStoreClient.js +0 -61
  693. package/dist/esm/store/keyValueStoreClient.js.map +0 -1
  694. package/dist/esm/triggerClient.d.ts +0 -288
  695. package/dist/esm/triggerClient.js +0 -1359
  696. package/dist/esm/triggerClient.js.map +0 -1
  697. package/dist/esm/triggers/dynamic.d.ts +0 -56
  698. package/dist/esm/triggers/dynamic.js +0 -93
  699. package/dist/esm/triggers/dynamic.js.map +0 -1
  700. package/dist/esm/triggers/eventTrigger.d.ts +0 -58
  701. package/dist/esm/triggers/eventTrigger.js +0 -64
  702. package/dist/esm/triggers/eventTrigger.js.map +0 -1
  703. package/dist/esm/triggers/externalSource.d.ts +0 -148
  704. package/dist/esm/triggers/externalSource.js +0 -100
  705. package/dist/esm/triggers/externalSource.js.map +0 -1
  706. package/dist/esm/triggers/invokeTrigger.d.ts +0 -39
  707. package/dist/esm/triggers/invokeTrigger.js +0 -53
  708. package/dist/esm/triggers/invokeTrigger.js.map +0 -1
  709. package/dist/esm/triggers/notifications.d.ts +0 -111
  710. package/dist/esm/triggers/notifications.js +0 -94
  711. package/dist/esm/triggers/notifications.js.map +0 -1
  712. package/dist/esm/triggers/scheduled.d.ts +0 -145
  713. package/dist/esm/triggers/scheduled.js +0 -197
  714. package/dist/esm/triggers/scheduled.js.map +0 -1
  715. package/dist/esm/triggers/webhook.d.ts +0 -143
  716. package/dist/esm/triggers/webhook.js +0 -128
  717. package/dist/esm/triggers/webhook.js.map +0 -1
  718. package/dist/esm/typed-emitter.d.ts +0 -37
  719. package/dist/esm/typed-emitter.js +0 -2
  720. package/dist/esm/typed-emitter.js.map +0 -1
  721. package/dist/esm/types.d.ts +0 -204
  722. package/dist/esm/types.js +0 -19
  723. package/dist/esm/types.js.map +0 -1
  724. package/dist/esm/utils/formatSchemaErrors.d.ts +0 -3
  725. package/dist/esm/utils/formatSchemaErrors.js +0 -7
  726. package/dist/esm/utils/formatSchemaErrors.js.map +0 -1
  727. package/dist/esm/utils/typedAsyncLocalStorage.d.ts +0 -6
  728. package/dist/esm/utils/typedAsyncLocalStorage.js +0 -14
  729. package/dist/esm/utils/typedAsyncLocalStorage.js.map +0 -1
  730. package/dist/esm/utils.d.ts +0 -1
  731. package/dist/esm/utils.js +0 -8
  732. package/dist/esm/utils.js.map +0 -1
@@ -0,0 +1,1655 @@
1
+ /**
2
+ * @module @trigger.dev/sdk/chat
3
+ *
4
+ * Browser-safe module for AI SDK chat transport integration.
5
+ * Use this on the frontend with the AI SDK's `useChat` hook.
6
+ *
7
+ * For backend helpers (`chatAgent`, `pipeChat`), use `@trigger.dev/sdk/ai` instead.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { useChat } from "@ai-sdk/react";
12
+ * import { TriggerChatTransport } from "@trigger.dev/sdk/chat";
13
+ *
14
+ * function Chat() {
15
+ * const { messages, sendMessage, status } = useChat({
16
+ * transport: new TriggerChatTransport({
17
+ * task: "my-chat-task",
18
+ * accessToken: async ({ chatId }) => fetchSessionToken(chatId),
19
+ * startSession: async ({ chatId, taskId }) => createChatSession({ chatId, taskId }),
20
+ * }),
21
+ * });
22
+ * }
23
+ * ```
24
+ */
25
+ import { controlSubtype, headerValue, SESSION_CLOSED_HEADER, SESSION_CLOSED_REASON_HEADER, PUBLIC_ACCESS_TOKEN_HEADER, SESSION_IN_EVENT_ID_HEADER, SSEStreamSubscription, TRIGGER_CONTROL_SUBTYPE, } from "@trigger.dev/core/v3";
26
+ function byteLength(body) {
27
+ return new TextEncoder().encode(body).byteLength;
28
+ }
29
+ import { ChatTabCoordinator } from "./chat-tab-coordinator.js";
30
+ import { MAX_EOF_RESUBSCRIBES, slimSubmitMessageForWire, waitBeforeEofResubscribe, } from "./ai-shared.js";
31
+ const DEFAULT_BASE_URL = "https://api.trigger.dev";
32
+ const DEFAULT_STREAM_TIMEOUT_SECONDS = 120;
33
+ /**
34
+ * Detect 401/403 from realtime/input-stream calls without relying on `instanceof`
35
+ * (Vitest can load duplicate `@trigger.dev/core` copies, which breaks subclass checks).
36
+ */
37
+ function isAuthError(error) {
38
+ if (error === null || typeof error !== "object")
39
+ return false;
40
+ const e = error;
41
+ return e.name === "TriggerApiError" && (e.status === 401 || e.status === 403);
42
+ }
43
+ /**
44
+ * Detect the closed-session refusal from `.in/append`: HTTP 409 with the
45
+ * stable `session_closed` code. Terminal — never retried.
46
+ */
47
+ function isSessionClosedError(error) {
48
+ if (error === null || typeof error !== "object")
49
+ return false;
50
+ const e = error;
51
+ return e.name === "TriggerApiError" && e.status === 409 && e.code === "session_closed";
52
+ }
53
+ function sessionClosedReasonOf(error) {
54
+ if (error === null || typeof error !== "object")
55
+ return undefined;
56
+ const reason = error.closedReason;
57
+ return typeof reason === "string" ? reason : undefined;
58
+ }
59
+ /** The local form of the refusal, for sends the transport rejects itself. */
60
+ function sessionClosedError(chatId, reason) {
61
+ const err = new Error(reason ? `Chat session ${chatId} is closed: ${reason}` : `Chat session ${chatId} is closed`);
62
+ err.name = "TriggerApiError";
63
+ err.status = 409;
64
+ err.code = "session_closed";
65
+ if (reason)
66
+ err.closedReason = reason;
67
+ return err;
68
+ }
69
+ /**
70
+ * Detect a 404 from a session-PAT-authed call — i.e. the session doesn't
71
+ * exist in the current environment. Happens when hydrated session state
72
+ * (the `sessions` option / a customer's persisted record) was created in a
73
+ * different trigger environment, or predates the upgrade to the sessions
74
+ * model, so there's no real Session row behind the cached PAT.
75
+ */
76
+ function isSessionNotFoundError(error) {
77
+ if (error === null || typeof error !== "object")
78
+ return false;
79
+ const e = error;
80
+ return e.name === "TriggerApiError" && e.status === 404;
81
+ }
82
+ /**
83
+ * Parses an SSE byte/text stream of `data: <UIMessageChunk JSON>\n\n`
84
+ * frames back into `UIMessageChunk` objects. Used by the handover
85
+ * first-turn path to convert the customer's route handler response
86
+ * (which is AI-SDK-shaped SSE text) into the chunk form the AI SDK's
87
+ * `useChat` consumes from a transport.
88
+ *
89
+ * Spec-light parser — assumes well-formed `data:` events from our own
90
+ * `chat.handover` SSE writer. Lines starting with `:` (comments) and
91
+ * other event types are ignored.
92
+ */
93
+ function parseUIMessageSseTransform() {
94
+ let buffer = "";
95
+ return new TransformStream({
96
+ transform(chunk, controller) {
97
+ buffer += chunk;
98
+ // Frames are separated by blank lines.
99
+ let idx = buffer.indexOf("\n\n");
100
+ while (idx !== -1) {
101
+ const frame = buffer.slice(0, idx);
102
+ buffer = buffer.slice(idx + 2);
103
+ for (const line of frame.split("\n")) {
104
+ if (line.startsWith("data: ")) {
105
+ const data = line.slice(6).trim();
106
+ if (!data)
107
+ continue;
108
+ try {
109
+ controller.enqueue(JSON.parse(data));
110
+ }
111
+ catch {
112
+ /* drop malformed chunk; the response source is our own writer */
113
+ }
114
+ }
115
+ }
116
+ idx = buffer.indexOf("\n\n");
117
+ }
118
+ },
119
+ flush(controller) {
120
+ // Trailing data without a closing blank line — treat as a final frame.
121
+ if (buffer.trim().length === 0)
122
+ return;
123
+ for (const line of buffer.split("\n")) {
124
+ if (line.startsWith("data: ")) {
125
+ const data = line.slice(6).trim();
126
+ if (!data)
127
+ continue;
128
+ try {
129
+ controller.enqueue(JSON.parse(data));
130
+ }
131
+ catch {
132
+ /* drop */
133
+ }
134
+ }
135
+ }
136
+ buffer = "";
137
+ },
138
+ });
139
+ }
140
+ /**
141
+ * A custom AI SDK `ChatTransport` that runs chat completions as durable
142
+ * Trigger.dev tasks via the Sessions primitive.
143
+ *
144
+ * Lifecycle:
145
+ * 1. Customer pre-creates the session server-side OR calls
146
+ * `transport.start(chatId)` to mint a one-shot start token and
147
+ * `POST /api/v1/sessions` from the browser.
148
+ * 2. The server triggers the first run as part of session create and
149
+ * returns a session-scoped PAT.
150
+ * 3. `sendMessages` appends to `.in` and subscribes to `.out`. When a
151
+ * run dies (idle, cancel, end-and-continue), the server's
152
+ * append-time probe triggers a fresh run for the same session —
153
+ * transport keeps streaming.
154
+ * 4. `stop()` posts a `{kind:"stop"}` chunk; the agent's turn aborts
155
+ * but the run keeps reading `.in` for the next message.
156
+ * 5. PAT expiry: transport invokes `accessToken` to refresh and
157
+ * retries the failing request once.
158
+ */
159
+ export class TriggerChatTransport {
160
+ taskId;
161
+ resolveAccessToken;
162
+ resolveStartSession;
163
+ resolveBaseURLFn;
164
+ fetchOverride;
165
+ extraHeaders;
166
+ streamTimeoutSeconds;
167
+ defaultMetadata;
168
+ watchMode;
169
+ headStart;
170
+ coordinator = null;
171
+ _onSessionChange;
172
+ _onEvent;
173
+ sessions = new Map();
174
+ pendingResumeCursors = new Map();
175
+ activeStreams = new Map();
176
+ pendingStarts = new Map();
177
+ // Last turn-producing send per chat — attribution source for the
178
+ // response-side events' `messageId` / `sinceSendMs`.
179
+ lastTurnSends = new Map();
180
+ constructor(options) {
181
+ this.taskId = options.task;
182
+ this.resolveAccessToken = options.accessToken;
183
+ this.resolveStartSession = options.startSession;
184
+ const baseURLOption = options.baseURL ?? DEFAULT_BASE_URL;
185
+ const streamOverride = options.streamBaseURL;
186
+ this.resolveBaseURLFn =
187
+ typeof baseURLOption === "function"
188
+ ? (ctx) => (ctx.endpoint === "out" && streamOverride ? streamOverride : baseURLOption(ctx))
189
+ : (ctx) => (ctx.endpoint === "out" && streamOverride ? streamOverride : baseURLOption);
190
+ this.fetchOverride = options.fetch;
191
+ this.extraHeaders = options.headers ?? {};
192
+ this.streamTimeoutSeconds = options.streamTimeoutSeconds ?? DEFAULT_STREAM_TIMEOUT_SECONDS;
193
+ this.defaultMetadata = options.clientData;
194
+ this._onSessionChange = options.onSessionChange;
195
+ this._onEvent = options.onEvent;
196
+ this.watchMode = options.watch ?? false;
197
+ this.headStart = options.headStart;
198
+ if (options.multiTab && !this.watchMode) {
199
+ this.coordinator = new ChatTabCoordinator();
200
+ this.coordinator.addSessionListener((chatId, sessionUpdate) => {
201
+ const session = this.sessions.get(chatId);
202
+ if (session && sessionUpdate.lastEventId) {
203
+ session.lastEventId = sessionUpdate.lastEventId;
204
+ }
205
+ });
206
+ }
207
+ if (options.sessions) {
208
+ for (const [chatId, session] of Object.entries(options.sessions)) {
209
+ this.sessions.set(chatId, {
210
+ publicAccessToken: session.publicAccessToken,
211
+ lastEventId: session.lastEventId,
212
+ activeInputSeq: session.activeInputSeq,
213
+ isStreaming: session.isStreaming,
214
+ closed: session.closed,
215
+ closedReason: session.closedReason,
216
+ });
217
+ }
218
+ }
219
+ }
220
+ // -------------------------------------------------------------------------
221
+ // Public lifecycle
222
+ // -------------------------------------------------------------------------
223
+ /**
224
+ * Eagerly create a Session and trigger its first run. Useful as a
225
+ * "the user might be about to send a message — boot the agent now"
226
+ * preload, or to take ownership of the session before any sendMessage.
227
+ *
228
+ * Idempotent: calling `start(chatId)` twice converges to the same
229
+ * session via the `(env, externalId)` upsert. Concurrent calls
230
+ * deduplicate via an in-flight promise.
231
+ *
232
+ * Requires `getStartToken` to be configured. Customers who pre-create
233
+ * sessions server-side don't need to call this.
234
+ */
235
+ async start(chatId) {
236
+ const existing = this.sessions.get(chatId);
237
+ if (existing?.publicAccessToken) {
238
+ return this.toPersisted(existing);
239
+ }
240
+ const inflight = this.pendingStarts.get(chatId);
241
+ if (inflight)
242
+ return inflight.then(this.toPersisted);
243
+ const promise = this.doStart(chatId).finally(() => {
244
+ this.pendingStarts.delete(chatId);
245
+ });
246
+ this.pendingStarts.set(chatId, promise);
247
+ return promise.then(this.toPersisted);
248
+ }
249
+ /**
250
+ * Eagerly create the session before the user types. Same semantics as
251
+ * {@link start} — kept as a separate name for the AI SDK Chat hook,
252
+ * which calls `preload` rather than `start`.
253
+ */
254
+ async preload(chatId) {
255
+ await this.start(chatId);
256
+ }
257
+ /**
258
+ * Send a user message via the session's `.in` channel. The server
259
+ * probes `currentRunId`; if terminal/null it triggers a fresh run on
260
+ * the same session before the append lands. The returned
261
+ * `ReadableStream` carries the agent's response chunks via `.out` SSE.
262
+ */
263
+ sendMessages = async (options) => {
264
+ const { trigger, chatId, messageId, messages, abortSignal, body, metadata } = options;
265
+ const closedState = this.sessions.get(chatId);
266
+ if (closedState?.closed) {
267
+ throw sessionClosedError(chatId, closedState.closedReason);
268
+ }
269
+ if (this.coordinator) {
270
+ if (this.coordinator.isReadOnly(chatId)) {
271
+ throw new Error("This chat is active in another tab");
272
+ }
273
+ this.coordinator.claim(chatId);
274
+ }
275
+ const mergedMetadata = this.defaultMetadata || metadata
276
+ ? { ...(this.defaultMetadata ?? {}), ...(metadata ?? {}) }
277
+ : undefined;
278
+ // An action sent through `useChat`. `useChatActions` (or any caller) puts
279
+ // it in `body.action`; sending it here rather than through
280
+ // `transport.sendAction` means `useChat` owns the response stream, so an
281
+ // action that becomes a turn renders the way a message turn does.
282
+ const actionInBody = body?.action;
283
+ if (actionInBody !== undefined) {
284
+ return this.sendAction(chatId, actionInBody, { abortSignal, metadata: mergedMetadata });
285
+ }
286
+ // First-turn handover routing — when `headStart` is set AND no
287
+ // session state exists yet for this chatId, POST the wire payload
288
+ // to the customer's `chat.handover` route handler. The handler
289
+ // creates the session, triggers the agent run with
290
+ // `handover-prepare`, runs `streamText` step 1 in its warm
291
+ // process, and tees the output back as the SSE response. We
292
+ // hydrate session state from the response headers so subsequent
293
+ // turns bypass the handler and use direct `session.in` writes.
294
+ if (this.headStart && !this.sessions.has(chatId)) {
295
+ return this.sendMessagesViaHandover({
296
+ trigger,
297
+ chatId,
298
+ messageId,
299
+ messages,
300
+ abortSignal,
301
+ body,
302
+ metadata: mergedMetadata,
303
+ });
304
+ }
305
+ // Slim wire — at most ONE message per record. The agent rebuilds prior
306
+ // history from its durable S3 snapshot + session.out replay at run boot
307
+ // (or `hydrateMessages`, if registered).
308
+ //
309
+ // - "submit-message": ship the latest message (new user message OR a
310
+ // tool-approval-responded assistant message). Throw if absent.
311
+ // Assistant messages with already-resolved tool parts are slimmed
312
+ // to just their resolution payload — reasoning blobs, prior text,
313
+ // and tool `input` stay on the agent side (rebuilt from snapshot
314
+ // or `hydrateMessages`). Keeps continuation payloads under the
315
+ // `.in/append` cap on reasoning-heavy turns.
316
+ // - "regenerate-message": omit `message`; the agent slices its own
317
+ // history (drops the trailing assistant) and re-runs.
318
+ if (trigger === "submit-message" && messages.length === 0) {
319
+ throw new Error("TriggerChatTransport.sendMessages: 'submit-message' trigger requires at least one message");
320
+ }
321
+ const wirePayload = {
322
+ ...(body ?? {}),
323
+ ...(trigger === "submit-message"
324
+ ? { message: slimSubmitMessageForWire(messages.at(-1)) }
325
+ : {}),
326
+ chatId,
327
+ trigger,
328
+ messageId,
329
+ metadata: mergedMetadata,
330
+ };
331
+ const state = await this.ensureSessionState(chatId);
332
+ // Generated outside the closure so auth-retries reuse the same part id
333
+ // and the server-side dedupe sees one logical append.
334
+ const partId = crypto.randomUUID();
335
+ const serializedBody = this.serializeInputChunk({ kind: "message", payload: wirePayload });
336
+ const sendChatMessage = (token) => this.appendInputChunk(chatId, token, serializedBody, partId);
337
+ const inSeq = await this.sendWithEvents(chatId, trigger, {
338
+ messageId: messageId ?? messages.at(-1)?.id,
339
+ partId,
340
+ bodyBytes: byteLength(serializedBody),
341
+ }, () => this.callWithAuthRetry(chatId, state, sendChatMessage));
342
+ // Cancel any in-flight stream for this chat — the new turn supersedes it.
343
+ const activeStream = this.activeStreams.get(chatId);
344
+ if (activeStream) {
345
+ activeStream.abort();
346
+ this.activeStreams.delete(chatId);
347
+ }
348
+ state.activeInputSeq = inSeq;
349
+ state.isStreaming = true;
350
+ state.outstandingTurnAbandoned = false;
351
+ this.notifySessionChange(chatId, state);
352
+ // Owning turn: aborting this live send stops the turn the user drives.
353
+ return this.subscribeToSessionStream(state, abortSignal, chatId, {
354
+ sinceInSeq: inSeq,
355
+ sendStopOnAbort: true,
356
+ });
357
+ };
358
+ /**
359
+ * First-turn-only path used when `headStart` is configured. POSTs the
360
+ * wire payload to the customer's `chat.handover` route handler and
361
+ * pipes its SSE response back as a UIMessageChunk stream. Hydrates
362
+ * session state from response headers so subsequent turns bypass
363
+ * the endpoint and use the direct `session.in` path.
364
+ */
365
+ async sendMessagesViaHandover(args) {
366
+ if (!this.headStart) {
367
+ throw new Error("sendMessagesViaHandover called without headStart configured");
368
+ }
369
+ // Head-start ships full UIMessage history via `headStartMessages`. The
370
+ // route handler runs on the customer's own HTTP endpoint (NOT
371
+ // `/realtime/v1/sessions/{id}/in/append`), so the 512 KiB body cap
372
+ // doesn't apply. The agent's run boot consumes `headStartMessages` ONLY
373
+ // when no snapshot exists yet (very first turn) — see plan section B.3.
374
+ const wirePayload = {
375
+ ...(args.body ?? {}),
376
+ headStartMessages: args.messages,
377
+ chatId: args.chatId,
378
+ trigger: args.trigger,
379
+ messageId: args.messageId,
380
+ metadata: args.metadata,
381
+ };
382
+ let response;
383
+ const serializedBody = JSON.stringify(wirePayload);
384
+ await this.sendWithEvents(args.chatId, "head-start", {
385
+ messageId: args.messageId ?? args.messages.at(-1)?.id,
386
+ bodyBytes: byteLength(serializedBody),
387
+ }, async () => {
388
+ response = await fetch(this.headStart, {
389
+ method: "POST",
390
+ headers: {
391
+ "Content-Type": "application/json",
392
+ ...this.extraHeaders,
393
+ },
394
+ body: serializedBody,
395
+ signal: args.abortSignal,
396
+ });
397
+ if (!response.ok) {
398
+ const err = new Error(`chat.handover endpoint returned ${response.status} ${response.statusText}`);
399
+ err.status = response.status;
400
+ throw err;
401
+ }
402
+ });
403
+ if (!response.body) {
404
+ throw new Error("chat.handover endpoint returned no response body");
405
+ }
406
+ // Hydrate session state from response headers so subsequent turns
407
+ // skip the endpoint and write directly to session.in. Failing fast
408
+ // when the header is missing avoids a quiet degraded state where
409
+ // every later turn re-runs the handover route instead of taking
410
+ // the slim-wire path.
411
+ const accessToken = response.headers.get("X-Trigger-Chat-Access-Token");
412
+ const chatId = args.chatId;
413
+ if (!accessToken) {
414
+ throw new Error("chat.handover response is missing the X-Trigger-Chat-Access-Token header. chat.agent's handover endpoint must echo the session PAT so the transport can hydrate.");
415
+ }
416
+ const state = {
417
+ publicAccessToken: accessToken,
418
+ isStreaming: true,
419
+ };
420
+ this.sessions.set(chatId, state);
421
+ this.notifySessionChange(chatId, state);
422
+ // Step 1 streams from the warm server either way; this says the agent run that owes step 2
423
+ // is parked on an undeployed external deployment id.
424
+ if (response.headers.get("X-Trigger-Chat-Pending-Version") === "1") {
425
+ this.emitEvent({
426
+ type: "run-pending-version",
427
+ chatId,
428
+ timestamp: Date.now(),
429
+ source: "head-start",
430
+ });
431
+ }
432
+ // Filter the parsed UIMessage stream:
433
+ // - Drop control chunks (`trigger:turn-complete`,
434
+ // `trigger:session-state`) before they reach AI SDK — they
435
+ // aren't valid UIMessageChunks and the AI SDK chunk parser
436
+ // would reject them.
437
+ // - On `trigger:turn-complete`, clear `isStreaming` so the
438
+ // useChat resume / reconnectToStream path doesn't open a
439
+ // second `session.out` subscription on top of our stitched
440
+ // response.
441
+ // - On `trigger:session-state`, hydrate `state.lastEventId`
442
+ // with the agent's final S2 event id. Without this, turn 2's
443
+ // `session.out` subscribe reads from the start and replays
444
+ // turn 1's chunks back into the UI.
445
+ // - On stream end (handover-skip case — no
446
+ // `trigger:turn-complete` arrives, customer's stream just
447
+ // ends), also clear `isStreaming` for the same reason.
448
+ const sessions = this.sessions;
449
+ const notifyChange = (id, state) => this.notifySessionChange(id, state);
450
+ const TRIGGER_TURN_COMPLETE = "trigger:turn-complete";
451
+ const TRIGGER_SESSION_STATE = "trigger:session-state";
452
+ const clearStreaming = () => {
453
+ const state = sessions.get(chatId);
454
+ if (state && state.isStreaming) {
455
+ state.isStreaming = false;
456
+ notifyChange(chatId, state);
457
+ }
458
+ };
459
+ const setLastEventId = (lastEventId) => {
460
+ const state = sessions.get(chatId);
461
+ if (state) {
462
+ state.lastEventId = lastEventId;
463
+ notifyChange(chatId, state);
464
+ }
465
+ };
466
+ const emit = (event) => this.emitEvent(event);
467
+ const attribution = () => this.turnAttribution(chatId);
468
+ let sawFirstChunk = false;
469
+ emit({
470
+ type: "stream-connected",
471
+ chatId,
472
+ timestamp: Date.now(),
473
+ resumed: false,
474
+ messageId: this.lastTurnSends.get(chatId)?.messageId,
475
+ });
476
+ const piped = response.body
477
+ .pipeThrough(new TextDecoderStream())
478
+ .pipeThrough(parseUIMessageSseTransform())
479
+ .pipeThrough(new TransformStream({
480
+ transform(chunk, controller) {
481
+ if (chunk && typeof chunk === "object") {
482
+ const type = chunk.type;
483
+ if (type === TRIGGER_TURN_COMPLETE) {
484
+ clearStreaming();
485
+ emit({
486
+ type: "turn-completed",
487
+ chatId,
488
+ timestamp: Date.now(),
489
+ lastEventId: sessions.get(chatId)?.lastEventId,
490
+ ...attribution(),
491
+ });
492
+ return; // drop — not a real UIMessageChunk
493
+ }
494
+ if (type === TRIGGER_SESSION_STATE) {
495
+ const lastEventId = chunk.lastEventId;
496
+ if (typeof lastEventId === "string") {
497
+ setLastEventId(lastEventId);
498
+ }
499
+ return; // drop
500
+ }
501
+ }
502
+ if (!sawFirstChunk) {
503
+ sawFirstChunk = true;
504
+ emit({
505
+ type: "first-chunk",
506
+ chatId,
507
+ timestamp: Date.now(),
508
+ chunkType: chunk?.type,
509
+ ...attribution(),
510
+ });
511
+ }
512
+ controller.enqueue(chunk);
513
+ },
514
+ flush() {
515
+ clearStreaming();
516
+ },
517
+ }));
518
+ // Pump wrapper: a TransformStream can't observe upstream errors, so
519
+ // read here to emit stream-error (aborts close cleanly, matching the
520
+ // session subscribe path).
521
+ const pipedReader = piped.getReader();
522
+ return new ReadableStream({
523
+ async pull(controller) {
524
+ try {
525
+ const next = await pipedReader.read();
526
+ if (next.done) {
527
+ controller.close();
528
+ return;
529
+ }
530
+ controller.enqueue(next.value);
531
+ }
532
+ catch (error) {
533
+ if (error instanceof Error && error.name === "AbortError") {
534
+ try {
535
+ controller.close();
536
+ }
537
+ catch {
538
+ /* already closed */
539
+ }
540
+ return;
541
+ }
542
+ const errorStatus = error.status;
543
+ emit({
544
+ type: "stream-error",
545
+ chatId,
546
+ timestamp: Date.now(),
547
+ error: error instanceof Error ? error : new Error(String(error)),
548
+ status: typeof errorStatus === "number" ? errorStatus : undefined,
549
+ });
550
+ controller.error(error);
551
+ }
552
+ },
553
+ cancel(reason) {
554
+ return pipedReader.cancel(reason);
555
+ },
556
+ });
557
+ }
558
+ /**
559
+ * Send a steering message during an active stream without disrupting
560
+ * it. The agent's `pendingMessages` config decides whether to inject
561
+ * between tool-call steps or buffer for the next turn.
562
+ */
563
+ sendPendingMessage = async (chatId, message, metadata) => {
564
+ const state = this.sessions.get(chatId);
565
+ if (!state)
566
+ return false;
567
+ const mergedMetadata = this.defaultMetadata || metadata
568
+ ? { ...(this.defaultMetadata ?? {}), ...(metadata ?? {}) }
569
+ : undefined;
570
+ const wirePayload = {
571
+ message,
572
+ chatId,
573
+ trigger: "submit-message",
574
+ metadata: mergedMetadata,
575
+ };
576
+ const partId = crypto.randomUUID();
577
+ const serializedBody = this.serializeInputChunk({ kind: "message", payload: wirePayload });
578
+ const send = async (token) => {
579
+ await this.appendInputChunk(chatId, token, serializedBody, partId);
580
+ };
581
+ try {
582
+ await this.sendWithEvents(chatId, "steer", { messageId: message.id, partId, bodyBytes: byteLength(serializedBody) }, () => this.callWithAuthRetry(chatId, state, send));
583
+ return true;
584
+ }
585
+ catch {
586
+ return false;
587
+ }
588
+ };
589
+ /**
590
+ * Re-establish an SSE subscription to a known session. Used after a
591
+ * page refresh: the customer hydrates `sessions` in the constructor,
592
+ * the AI SDK calls `reconnectToStream` to resume the stream.
593
+ */
594
+ reconnectToStream = async (options) => {
595
+ const state = this.sessions.get(options.chatId);
596
+ if (!state)
597
+ return null;
598
+ // A closed session has no further turns to resume.
599
+ if (state.closed)
600
+ return null;
601
+ // Watch is a standing subscription: a settled session is exactly the
602
+ // state it waits in, so a completed last turn must not block the resume.
603
+ if (state.isStreaming === false && !this.watchMode)
604
+ return null;
605
+ if (this.activeStreams.has(options.chatId))
606
+ return null;
607
+ const abortController = new AbortController();
608
+ this.activeStreams.set(options.chatId, abortController);
609
+ const abortSignal = options.abortSignal
610
+ ? AbortSignal.any([options.abortSignal, abortController.signal])
611
+ : abortController.signal;
612
+ return this.subscribeToSessionStream(state, abortSignal, options.chatId, {
613
+ resumed: true,
614
+ sendStopOnAbort: options.stopOnAbort ?? false,
615
+ sinceInSeq: state.activeInputSeq,
616
+ // Reconnect-on-reload opts into the server's settled-peek shortcut
617
+ // so the SSE doesn't hang for 60s when no turn is in flight. A known
618
+ // active input must not peek because the previous turn's completion
619
+ // can remain at the tail until the current turn writes its first chunk.
620
+ // Watch mode must NOT peek: a settled peek between turns closes the
621
+ // standing subscription, so the viewer never sees the next turn.
622
+ peekSettled: !this.watchMode && state.activeInputSeq === undefined,
623
+ });
624
+ };
625
+ /**
626
+ * Stop the current generation. Sends `{kind:"stop"}` on `.in`; the
627
+ * agent aborts its `streamText` call but stays alive for the next
628
+ * message.
629
+ */
630
+ stopGeneration = async (chatId) => {
631
+ const state = this.sessions.get(chatId);
632
+ if (!state)
633
+ return false;
634
+ const partId = crypto.randomUUID();
635
+ const serializedBody = this.serializeInputChunk({ kind: "stop" });
636
+ const send = async (token) => {
637
+ await this.appendInputChunk(chatId, token, serializedBody, partId);
638
+ };
639
+ try {
640
+ await this.sendWithEvents(chatId, "stop", { partId, bodyBytes: byteLength(serializedBody) }, () => this.callWithAuthRetry(chatId, state, send));
641
+ }
642
+ catch {
643
+ return false;
644
+ }
645
+ // Only gate when a sent turn is still outstanding. A stop at a boundary has
646
+ // nothing to supersede, and gating it would swallow the next turn.
647
+ if (!state.outstandingTurnAbandoned &&
648
+ (state.isStreaming || state.activeInputSeq !== undefined)) {
649
+ state.skipToTurnComplete = true;
650
+ state.supersededInputSeq = state.activeInputSeq;
651
+ }
652
+ const activeStream = this.activeStreams.get(chatId);
653
+ if (activeStream) {
654
+ activeStream.abort();
655
+ this.activeStreams.delete(chatId);
656
+ }
657
+ // Release here, not in the stream teardown: that only releases while it
658
+ // still owns the map entry, and we just deleted it. Unlike a supersede,
659
+ // no successor stream follows a stop, so the claim would never be freed
660
+ // and other tabs would stay read-only until this one closes.
661
+ this.coordinator?.release(chatId);
662
+ // The turn won't reach its turn-complete on this client (we just
663
+ // aborted the reader), so clear the streaming flag here and persist —
664
+ // otherwise a reload resumes mid-turn and replays the chunks the user
665
+ // explicitly stopped.
666
+ state.isStreaming = false;
667
+ this.notifySessionChange(chatId, state);
668
+ return true;
669
+ };
670
+ /**
671
+ * Clear the supersede gate armed by a stop. Call this when the stopped
672
+ * turn died without ever writing its `trigger:turn-complete` boundary,
673
+ * otherwise the next turn stays gated forever.
674
+ */
675
+ clearSupersedeGate = (chatId) => {
676
+ const state = this.sessions.get(chatId);
677
+ if (!state)
678
+ return;
679
+ state.skipToTurnComplete = false;
680
+ state.supersededInputSeq = undefined;
681
+ state.outstandingTurnAbandoned = true;
682
+ };
683
+ /**
684
+ * Send a custom action chunk (for `chat.agent`'s `actionSchema` /
685
+ * `onAction` hook). An action is an edit: only `hydrateMessages` and
686
+ * `onAction` fire on the agent side, and the returned stream completes
687
+ * with `trigger:turn-complete` once the edit is persisted. When `onAction`
688
+ * returns `chat.turn()` the turn's response follows on the same stream.
689
+ * Per-action `metadata` is merged over the transport's `clientData`.
690
+ */
691
+ sendAction = async (chatId, action, options) => {
692
+ if (this.coordinator) {
693
+ if (this.coordinator.isReadOnly(chatId)) {
694
+ throw new Error("This chat is active in another tab");
695
+ }
696
+ this.coordinator.claim(chatId);
697
+ }
698
+ const state = await this.ensureSessionState(chatId);
699
+ const wirePayload = {
700
+ chatId,
701
+ trigger: "action",
702
+ action,
703
+ metadata: this.defaultMetadata || options?.metadata
704
+ ? { ...(this.defaultMetadata ?? {}), ...(options?.metadata ?? {}) }
705
+ : undefined,
706
+ };
707
+ const body = this.serializeInputChunk({ kind: "message", payload: wirePayload });
708
+ const partId = crypto.randomUUID();
709
+ const send = (token) => this.appendInputChunk(chatId, token, body, partId);
710
+ const inSeq = await this.sendWithEvents(chatId, "action", { partId, bodyBytes: byteLength(body) }, () => this.callWithAuthRetry(chatId, state, send));
711
+ // Supersede any in-flight reader before subscribing — same as
712
+ // `sendMessages`. Two concurrent readers both write `state.lastEventId`
713
+ // and the slower one can regress the cursor, replaying records on the
714
+ // next reconnect.
715
+ const activeStream = this.activeStreams.get(chatId);
716
+ if (activeStream) {
717
+ activeStream.abort();
718
+ this.activeStreams.delete(chatId);
719
+ }
720
+ // Mark streaming + persist so a reload mid-action resumes (reconnectToStream
721
+ // no-ops when the persisted session says isStreaming: false).
722
+ state.activeInputSeq = inSeq;
723
+ state.isStreaming = true;
724
+ state.outstandingTurnAbandoned = false;
725
+ this.notifySessionChange(chatId, state);
726
+ // Owning action: aborting this send stops the turn the user drives.
727
+ return this.subscribeToSessionStream(state, options?.abortSignal, chatId, {
728
+ sinceInSeq: inSeq,
729
+ sendStopOnAbort: true,
730
+ onSettled: options?.onSettled,
731
+ });
732
+ };
733
+ // -------------------------------------------------------------------------
734
+ // External-state surface
735
+ // -------------------------------------------------------------------------
736
+ getSession = (chatId) => {
737
+ const state = this.sessions.get(chatId);
738
+ if (!state)
739
+ return undefined;
740
+ return this.toPersisted(state);
741
+ };
742
+ setSession(chatId, session) {
743
+ this.sessions.set(chatId, this.applyPendingResumeCursor(chatId, {
744
+ publicAccessToken: session.publicAccessToken,
745
+ lastEventId: session.lastEventId,
746
+ activeInputSeq: session.activeInputSeq,
747
+ isStreaming: session.isStreaming,
748
+ }));
749
+ this.notifySessionChange(chatId, this.toPersisted(this.sessions.get(chatId)));
750
+ }
751
+ /**
752
+ * Seed the `.out` resume cursor from a loaded transcript. Applied to the
753
+ * session now if it exists, otherwise held until the session is created so
754
+ * the first live subscription opens past the persisted history instead of
755
+ * replaying it. Never moves an existing cursor backward: the transcript load
756
+ * is async, so a live `.out` record can already have advanced the session
757
+ * past the snapshot, and overwriting it would replay those records.
758
+ */
759
+ seedResumeCursor = (chatId, lastEventId) => {
760
+ const existing = this.sessions.get(chatId);
761
+ if (existing?.publicAccessToken) {
762
+ if (existing.lastEventId === undefined) {
763
+ existing.lastEventId = lastEventId;
764
+ this.notifySessionChange(chatId, this.toPersisted(existing));
765
+ }
766
+ this.pendingResumeCursors.delete(chatId);
767
+ return;
768
+ }
769
+ this.pendingResumeCursors.set(chatId, lastEventId);
770
+ };
771
+ applyPendingResumeCursor(chatId, state) {
772
+ const pending = this.pendingResumeCursors.get(chatId);
773
+ if (pending !== undefined && state.lastEventId === undefined) {
774
+ state.lastEventId = pending;
775
+ }
776
+ this.pendingResumeCursors.delete(chatId);
777
+ return state;
778
+ }
779
+ setOnSessionChange(callback) {
780
+ this._onSessionChange = callback;
781
+ }
782
+ /** Update the `onEvent` callback without recreating the transport. */
783
+ setOnEvent(callback) {
784
+ this._onEvent = callback;
785
+ }
786
+ emitEvent(event) {
787
+ const cb = this._onEvent;
788
+ if (!cb)
789
+ return;
790
+ try {
791
+ cb(event);
792
+ }
793
+ catch {
794
+ // observability must never break the chat
795
+ }
796
+ }
797
+ /** Run a send op, emitting the terminal message-sent / message-send-failed event. */
798
+ async sendWithEvents(chatId, source, extras, op) {
799
+ const startedAt = Date.now();
800
+ try {
801
+ const result = await op();
802
+ const turnProducing = source === "submit-message" || source === "regenerate-message" || source === "head-start";
803
+ if (turnProducing) {
804
+ this.lastTurnSends.set(chatId, { messageId: extras.messageId, at: Date.now() });
805
+ }
806
+ this.emitEvent({
807
+ type: "message-sent",
808
+ chatId,
809
+ timestamp: Date.now(),
810
+ source,
811
+ durationMs: Date.now() - startedAt,
812
+ ...extras,
813
+ });
814
+ return result;
815
+ }
816
+ catch (error) {
817
+ const status = error.status;
818
+ this.emitEvent({
819
+ type: "message-send-failed",
820
+ chatId,
821
+ timestamp: Date.now(),
822
+ source,
823
+ error: error instanceof Error ? error : new Error(String(error)),
824
+ status: typeof status === "number" ? status : undefined,
825
+ durationMs: Date.now() - startedAt,
826
+ ...extras,
827
+ });
828
+ throw error;
829
+ }
830
+ }
831
+ /** Attribution fields for response-side events. */
832
+ turnAttribution(chatId) {
833
+ const lastSend = this.lastTurnSends.get(chatId);
834
+ if (!lastSend)
835
+ return {};
836
+ return { messageId: lastSend.messageId, sinceSendMs: Date.now() - lastSend.at };
837
+ }
838
+ /**
839
+ * Update the transport's `clientData`. Used by `useTriggerChatTransport`
840
+ * to keep the latest value reachable from inside `startSession` and
841
+ * the per-turn `metadata` merge without recreating the transport.
842
+ *
843
+ * Reads always go through the live field — closures around the
844
+ * transport see the latest value the next time they fire.
845
+ */
846
+ setClientData(clientData) {
847
+ this.defaultMetadata = clientData;
848
+ }
849
+ /**
850
+ * Update the request-time callbacks. Same reason as `setClientData`:
851
+ * a host that rebuilds these per render (a dashboard navigating between
852
+ * projects) would otherwise keep hitting the endpoint captured at
853
+ * construction. Every read goes through the live field, so the next
854
+ * request uses the latest callback.
855
+ */
856
+ setAccessToken(accessToken) {
857
+ this.resolveAccessToken = accessToken;
858
+ }
859
+ setStartSession(startSession) {
860
+ this.resolveStartSession = startSession;
861
+ }
862
+ setFetch(fetchOverride) {
863
+ this.fetchOverride = fetchOverride;
864
+ }
865
+ // -------------------------------------------------------------------------
866
+ // Multi-tab coordination passthrough
867
+ // -------------------------------------------------------------------------
868
+ isReadOnly(chatId) {
869
+ return this.coordinator?.isReadOnly(chatId) ?? false;
870
+ }
871
+ hasClaim(chatId) {
872
+ return this.coordinator?.hasClaim(chatId) ?? false;
873
+ }
874
+ addReadOnlyListener(fn) {
875
+ this.coordinator?.addListener(fn);
876
+ }
877
+ removeReadOnlyListener(fn) {
878
+ this.coordinator?.removeListener(fn);
879
+ }
880
+ broadcastMessages(chatId, messages) {
881
+ this.coordinator?.broadcastMessages(chatId, messages);
882
+ }
883
+ addMessagesListener(fn) {
884
+ this.coordinator?.addMessagesListener(fn);
885
+ }
886
+ removeMessagesListener(fn) {
887
+ this.coordinator?.removeMessagesListener(fn);
888
+ }
889
+ dispose() {
890
+ // Tear down any open session.out subscriptions before the coordinator
891
+ // goes away. Otherwise controllers in `activeStreams` keep reading
892
+ // until they time out, leaking network and memory on every
893
+ // unmount/navigation.
894
+ for (const controller of this.activeStreams.values()) {
895
+ controller.abort();
896
+ }
897
+ this.activeStreams.clear();
898
+ this.coordinator?.dispose();
899
+ this.coordinator = null;
900
+ }
901
+ // -------------------------------------------------------------------------
902
+ // Internal helpers
903
+ // -------------------------------------------------------------------------
904
+ serializeInputChunk(chunk) {
905
+ return JSON.stringify(chunk);
906
+ }
907
+ toPersisted = (state) => ({
908
+ publicAccessToken: state.publicAccessToken,
909
+ lastEventId: state.lastEventId,
910
+ activeInputSeq: state.activeInputSeq,
911
+ isStreaming: state.isStreaming,
912
+ closed: state.closed,
913
+ closedReason: state.closedReason,
914
+ });
915
+ /**
916
+ * Flip a session to closed and tell listeners once. Terminal: sends and
917
+ * reconnects stop from here on, and there is no reopening.
918
+ */
919
+ markSessionClosed(chatId, state, reason, source) {
920
+ if (state.closed)
921
+ return;
922
+ state.closed = true;
923
+ if (reason)
924
+ state.closedReason = reason;
925
+ state.isStreaming = false;
926
+ state.activeInputSeq = undefined;
927
+ state.skipToTurnComplete = false;
928
+ state.supersededInputSeq = undefined;
929
+ this.emitEvent({
930
+ type: "session-closed",
931
+ chatId,
932
+ timestamp: Date.now(),
933
+ ...(reason ? { reason } : {}),
934
+ source,
935
+ });
936
+ this.notifySessionChange(chatId, state);
937
+ this.coordinator?.release(chatId);
938
+ }
939
+ /**
940
+ * Whether the conversation has been closed — by the agent via
941
+ * `chat.close()`, or from outside via `sessions.close()`. Closed is
942
+ * one-way: the transport refuses further sends and reconnects, and the
943
+ * transcript stays readable.
944
+ */
945
+ sessionStatus = (chatId) => this.sessions.get(chatId)?.closed ? "closed" : "open";
946
+ /** The reason the session was closed, when one was given. */
947
+ sessionClosedReason = (chatId) => this.sessions.get(chatId)?.closedReason;
948
+ notifySessionChange(chatId, session) {
949
+ if (!this._onSessionChange)
950
+ return;
951
+ this._onSessionChange(chatId, session ? this.toPersisted(session) : null);
952
+ }
953
+ /**
954
+ * Resolves the session state for a chatId, starting the session if
955
+ * needed (and `getStartToken` is configured). Customers who provide
956
+ * `accessToken` but no `getStartToken` are expected to have created
957
+ * the session server-side; in that case the first `accessToken` call
958
+ * returns a fresh session PAT.
959
+ */
960
+ async ensureSessionState(chatId) {
961
+ const existing = this.sessions.get(chatId);
962
+ if (existing?.publicAccessToken)
963
+ return existing;
964
+ if (this.resolveStartSession) {
965
+ // Lazily start: customer's server action creates the session and
966
+ // returns a PAT. Idempotent on `(env, externalId)` so concurrent
967
+ // tabs / repeat calls converge to the same session.
968
+ const inflight = this.pendingStarts.get(chatId);
969
+ if (inflight)
970
+ return inflight;
971
+ const promise = this.doStart(chatId).finally(() => {
972
+ this.pendingStarts.delete(chatId);
973
+ });
974
+ this.pendingStarts.set(chatId, promise);
975
+ return promise;
976
+ }
977
+ // No `startSession` configured. Customer fully manages session
978
+ // lifecycle externally — they're expected to have hydrated
979
+ // `sessions: { ... }` already, or the very first `accessToken` call
980
+ // returns a PAT for an out-of-band-created session.
981
+ const token = await this.resolveAccessToken({ chatId });
982
+ const state = this.applyPendingResumeCursor(chatId, { publicAccessToken: token });
983
+ this.sessions.set(chatId, state);
984
+ this.notifySessionChange(chatId, state);
985
+ return state;
986
+ }
987
+ async doStart(chatId) {
988
+ if (!this.resolveStartSession) {
989
+ throw new Error("TriggerChatTransport: `startSession` is required to call `start()` / `preload()`. Either provide it or pre-hydrate the session via `sessions: { ... }`.");
990
+ }
991
+ const { publicAccessToken, pendingVersion } = await this.resolveStartSession({
992
+ taskId: this.taskId,
993
+ chatId,
994
+ clientData: (this.defaultMetadata ?? {}),
995
+ });
996
+ if (pendingVersion) {
997
+ this.emitEvent({
998
+ type: "run-pending-version",
999
+ chatId,
1000
+ timestamp: Date.now(),
1001
+ source: "start",
1002
+ });
1003
+ }
1004
+ const state = this.applyPendingResumeCursor(chatId, {
1005
+ publicAccessToken,
1006
+ isStreaming: false,
1007
+ });
1008
+ this.sessions.set(chatId, state);
1009
+ this.notifySessionChange(chatId, state);
1010
+ return state;
1011
+ }
1012
+ /**
1013
+ * Run `op` with the session's stored PAT. On 401/403, refresh the PAT
1014
+ * via `accessToken` and retry once. Surfaces non-auth errors as-is.
1015
+ */
1016
+ resolveBaseURL(ctx) {
1017
+ const raw = this.resolveBaseURLFn(ctx);
1018
+ return raw.replace(/\/$/, "");
1019
+ }
1020
+ /**
1021
+ * `fetchClient` for an `out` subscription. Reads `this.fetchOverride` on
1022
+ * every call, not once per subscription: a watch-mode subscription
1023
+ * reconnects for the lifetime of the page, and `setFetch` may have swapped
1024
+ * the override in between.
1025
+ */
1026
+ sseFetchClient(ctx) {
1027
+ return ((input, init) => {
1028
+ const override = this.fetchOverride;
1029
+ if (!override)
1030
+ return fetch(input, init);
1031
+ if (typeof input === "string") {
1032
+ return override(input, init ?? {}, ctx);
1033
+ }
1034
+ if (input instanceof URL) {
1035
+ return override(input.toString(), init ?? {}, ctx);
1036
+ }
1037
+ // Request — preserve its url + intrinsic init, let any provided init
1038
+ // override on top (matches fetch(Request, init) semantics).
1039
+ return override(input.url, {
1040
+ method: input.method,
1041
+ headers: input.headers,
1042
+ signal: input.signal,
1043
+ ...(init ?? {}),
1044
+ }, ctx);
1045
+ });
1046
+ }
1047
+ async doFetch(ctx, url, init) {
1048
+ return this.fetchOverride ? this.fetchOverride(url, init, ctx) : fetch(url, init);
1049
+ }
1050
+ async appendInputChunk(chatId, token, body, partId) {
1051
+ const ctx = { endpoint: "in", chatId };
1052
+ const url = `${this.resolveBaseURL(ctx)}/realtime/v1/sessions/${encodeURIComponent(chatId)}/in/append`;
1053
+ // extraHeaders first so the fixed headers below win — a transport-wide
1054
+ // X-Part-Id must not override the per-append idempotency key.
1055
+ const headers = {
1056
+ ...this.extraHeaders,
1057
+ "Content-Type": "application/json",
1058
+ Authorization: `Bearer ${token}`,
1059
+ "x-trigger-source": "sdk",
1060
+ "X-Part-Id": partId ?? crypto.randomUUID(),
1061
+ };
1062
+ const response = await this.doFetch(ctx, url, { method: "POST", headers, body });
1063
+ if (!response.ok) {
1064
+ const text = await response.text().catch(() => "");
1065
+ const err = new Error(`appendToSessionStream failed: ${response.status} ${text}`);
1066
+ err.name = "TriggerApiError";
1067
+ err.status = response.status;
1068
+ let parsed;
1069
+ try {
1070
+ parsed = JSON.parse(text);
1071
+ }
1072
+ catch {
1073
+ parsed = undefined;
1074
+ }
1075
+ if (typeof parsed?.code === "string")
1076
+ err.code = parsed.code;
1077
+ if (typeof parsed?.closedReason === "string")
1078
+ err.closedReason = parsed.closedReason;
1079
+ throw err;
1080
+ }
1081
+ // The appended record's `.in` seq, for correlating the response stream to
1082
+ // this send. Omitted by older webapps / a lost idempotency claim.
1083
+ const data = (await response.json().catch(() => undefined));
1084
+ if (data?.pendingVersion === true) {
1085
+ this.emitEvent({
1086
+ type: "run-pending-version",
1087
+ chatId,
1088
+ timestamp: Date.now(),
1089
+ source: "send",
1090
+ });
1091
+ }
1092
+ return typeof data?.seq === "number" ? data.seq : undefined;
1093
+ }
1094
+ async callWithAuthRetry(chatId, state, op) {
1095
+ if (state.closed) {
1096
+ throw sessionClosedError(chatId, state.closedReason);
1097
+ }
1098
+ // Every attempt goes through here, so a closed-session refusal is terminal
1099
+ // on whichever one hits it. Reaching a 409 from a later attempt and not
1100
+ // marking it would leave local status open on a conversation the server
1101
+ // has already ended.
1102
+ const attempt = async (token) => {
1103
+ try {
1104
+ return await op(token);
1105
+ }
1106
+ catch (err) {
1107
+ if (isSessionClosedError(err)) {
1108
+ // Terminal. Retrying, refreshing the PAT, or recreating the session
1109
+ // would all be wrong: the conversation is over.
1110
+ this.markSessionClosed(chatId, state, sessionClosedReasonOf(err), "append");
1111
+ }
1112
+ throw err;
1113
+ }
1114
+ };
1115
+ // 1) Try with the current PAT.
1116
+ try {
1117
+ return await attempt(state.publicAccessToken);
1118
+ }
1119
+ catch (err) {
1120
+ if (isSessionClosedError(err))
1121
+ throw err;
1122
+ if (isSessionNotFoundError(err)) {
1123
+ // The cached PAT authenticated but the session doesn't exist here —
1124
+ // recreate it and retry.
1125
+ await this.recreateSession(chatId, state);
1126
+ return await attempt(state.publicAccessToken);
1127
+ }
1128
+ if (!isAuthError(err))
1129
+ throw err;
1130
+ }
1131
+ // 2) Auth error — refresh the PAT and retry. (A cross-environment cached
1132
+ // PAT fails auth here because it was signed by another env's keys.)
1133
+ const fresh = await this.resolveAccessToken({ chatId });
1134
+ state.publicAccessToken = fresh;
1135
+ this.notifySessionChange(chatId, state);
1136
+ try {
1137
+ return await attempt(fresh);
1138
+ }
1139
+ catch (err) {
1140
+ if (!isSessionNotFoundError(err))
1141
+ throw err;
1142
+ }
1143
+ // 3) PAT is now valid but the session still 404s — the hydrated session
1144
+ // state is stale (created in a different environment, or before the
1145
+ // sessions upgrade). Recreate the session and retry once.
1146
+ await this.recreateSession(chatId, state);
1147
+ return await attempt(state.publicAccessToken);
1148
+ }
1149
+ /**
1150
+ * Repair a stale/phantom hydrated session. The cached state pointed at a
1151
+ * session that doesn't exist in the current environment (404) — typically
1152
+ * because it was persisted against a different trigger environment, or
1153
+ * predates the upgrade to the sessions model. Recreate the session via
1154
+ * `startSession` and overwrite the cached state **in place** so callers
1155
+ * holding a reference (e.g. `sendMessages` before it opens the SSE) pick
1156
+ * up the new PAT. The stale `lastEventId` resume cursor is dropped — it
1157
+ * pointed at a different environment's stream.
1158
+ */
1159
+ async recreateSession(chatId, state) {
1160
+ if (!this.resolveStartSession) {
1161
+ throw new Error("TriggerChatTransport: session not found and no `startSession` configured to recreate it. The stored session state for this chat may be stale (e.g. created in a different environment) — provide `startSession` or clear the stored session so a fresh one can be created.");
1162
+ }
1163
+ const { publicAccessToken, pendingVersion } = await this.resolveStartSession({
1164
+ taskId: this.taskId,
1165
+ chatId,
1166
+ clientData: (this.defaultMetadata ?? {}),
1167
+ });
1168
+ if (pendingVersion) {
1169
+ this.emitEvent({
1170
+ type: "run-pending-version",
1171
+ chatId,
1172
+ timestamp: Date.now(),
1173
+ source: "start",
1174
+ });
1175
+ }
1176
+ state.publicAccessToken = publicAccessToken;
1177
+ state.lastEventId = undefined;
1178
+ state.isStreaming = false;
1179
+ this.sessions.set(chatId, state);
1180
+ this.notifySessionChange(chatId, state);
1181
+ }
1182
+ /**
1183
+ * Open an SSE subscription to the session's `.out` stream and pipe
1184
+ * UIMessageChunks through to the AI SDK. Trigger control records
1185
+ * (`turn-complete`, `upgrade-required` — see `trigger-control` header
1186
+ * on `client-protocol.mdx#records-on-session-out`) are routed by
1187
+ * header and never reach the consumer. `upgrade-required` is purely
1188
+ * telemetry now since the server handles the run swap inline (see
1189
+ * `end-and-continue`).
1190
+ */
1191
+ subscribeToSessionStream(state, abortSignal, chatId, options) {
1192
+ const internalAbort = new AbortController();
1193
+ let didSettle = false;
1194
+ this.activeStreams.set(chatId, internalAbort);
1195
+ const combinedSignal = abortSignal
1196
+ ? AbortSignal.any([abortSignal, internalAbort.signal])
1197
+ : internalAbort.signal;
1198
+ if (abortSignal) {
1199
+ abortSignal.addEventListener("abort", () => {
1200
+ // A late abort (unmount, or the consumer dropping a drained stream)
1201
+ // has no turn to stop: don't gate the next one, don't write a stop.
1202
+ const outstanding = !state.outstandingTurnAbandoned &&
1203
+ (state.isStreaming || state.activeInputSeq !== undefined);
1204
+ if (options?.sendStopOnAbort !== false && outstanding && !internalAbort.signal.aborted) {
1205
+ state.skipToTurnComplete = true;
1206
+ state.supersededInputSeq = state.activeInputSeq;
1207
+ this.appendInputChunk(chatId, state.publicAccessToken, this.serializeInputChunk({ kind: "stop" })).catch(() => { });
1208
+ }
1209
+ internalAbort.abort();
1210
+ }, { once: true });
1211
+ }
1212
+ const streamUrl = `${this.resolveBaseURL({ endpoint: "out", chatId })}/realtime/v1/sessions/${encodeURIComponent(chatId)}/out`;
1213
+ return new ReadableStream({
1214
+ start: async (controller) => {
1215
+ // Track the live subscription so browser wake events can act
1216
+ // on it. Three classes of wake:
1217
+ // - `online`: network came back. Existing connection might
1218
+ // be silently dead; force a fresh one.
1219
+ // - `visibilitychange` → visible after long hidden: tab
1220
+ // was backgrounded long enough that the OS likely killed
1221
+ // the TCP socket. Force reconnect.
1222
+ // - `visibilitychange` → visible after short hidden: cheap
1223
+ // wake of any in-flight backoff.
1224
+ // - `pageshow` with `event.persisted`: bfcache restore
1225
+ // (mobile Safari back/forward, app-switcher resume). The
1226
+ // socket is definitely dead. Force reconnect.
1227
+ let currentSubscription = null;
1228
+ let hiddenSince = null;
1229
+ const FORCE_RECONNECT_AFTER_HIDDEN_MS = 30_000;
1230
+ const onVisibilityChange = () => {
1231
+ if (typeof document === "undefined")
1232
+ return;
1233
+ if (document.visibilityState === "hidden") {
1234
+ hiddenSince = Date.now();
1235
+ return;
1236
+ }
1237
+ const wasHiddenForMs = hiddenSince ? Date.now() - hiddenSince : 0;
1238
+ hiddenSince = null;
1239
+ if (wasHiddenForMs >= FORCE_RECONNECT_AFTER_HIDDEN_MS) {
1240
+ currentSubscription?.forceReconnect();
1241
+ }
1242
+ else {
1243
+ currentSubscription?.retryNow();
1244
+ }
1245
+ };
1246
+ const onPageShow = (event) => {
1247
+ // PageTransitionEvent in browsers; type guard via `persisted`.
1248
+ if (event.persisted) {
1249
+ currentSubscription?.forceReconnect();
1250
+ }
1251
+ };
1252
+ const onOnline = () => currentSubscription?.forceReconnect();
1253
+ const teardownWakeListeners = typeof document !== "undefined" && typeof window !== "undefined"
1254
+ ? (() => {
1255
+ document.addEventListener("visibilitychange", onVisibilityChange);
1256
+ window.addEventListener("online", onOnline);
1257
+ window.addEventListener("pageshow", onPageShow);
1258
+ return () => {
1259
+ document.removeEventListener("visibilitychange", onVisibilityChange);
1260
+ window.removeEventListener("online", onOnline);
1261
+ window.removeEventListener("pageshow", onPageShow);
1262
+ };
1263
+ })()
1264
+ : () => { };
1265
+ const sseCtx = { endpoint: "out", chatId };
1266
+ const sseFetchClient = this.sseFetchClient(sseCtx);
1267
+ let sawFirstChunk = false;
1268
+ let sinceInSeq = options?.sinceInSeq;
1269
+ const connectSseOnce = async (token) => {
1270
+ const subscription = new SSEStreamSubscription(streamUrl, {
1271
+ headers: {
1272
+ Authorization: `Bearer ${token}`,
1273
+ ...this.extraHeaders,
1274
+ ...(options?.peekSettled ? { "X-Peek-Settled": "1" } : {}),
1275
+ },
1276
+ signal: combinedSignal,
1277
+ timeoutInSeconds: this.streamTimeoutSeconds,
1278
+ lastEventId: state.lastEventId,
1279
+ // Reconnect if no decoded record arrives for 60 seconds.
1280
+ stallTimeoutMs: 60_000,
1281
+ // Bound connected silence while preserving recovery from network failures.
1282
+ ...(!this.watchMode && {
1283
+ maxStallRetries: 5,
1284
+ retryDelayMs: 1_000,
1285
+ maxRetryDelayMs: 5_000,
1286
+ }),
1287
+ fetchClient: sseFetchClient,
1288
+ });
1289
+ currentSubscription = subscription;
1290
+ const sseStream = await subscription.subscribe();
1291
+ const reader = sseStream.getReader();
1292
+ try {
1293
+ const first = await reader.read();
1294
+ if (first.done) {
1295
+ reader.releaseLock();
1296
+ return null;
1297
+ }
1298
+ return { reader, primed: first.value, subscription };
1299
+ }
1300
+ catch (readErr) {
1301
+ reader.releaseLock();
1302
+ throw readErr;
1303
+ }
1304
+ };
1305
+ const openWithAuthRetry = async () => {
1306
+ try {
1307
+ return await connectSseOnce(state.publicAccessToken);
1308
+ }
1309
+ catch (e) {
1310
+ if (!isAuthError(e))
1311
+ throw e;
1312
+ const fresh = await this.resolveAccessToken({ chatId });
1313
+ state.publicAccessToken = fresh;
1314
+ this.notifySessionChange(chatId, state);
1315
+ return await connectSseOnce(fresh);
1316
+ }
1317
+ };
1318
+ let eofResubscribes = 0;
1319
+ const resumeAfterEof = async () => {
1320
+ // Watch mode is a standing subscription: it outlives turn-complete
1321
+ // (which clears `isStreaming`) and idle windows EOF by design, so the
1322
+ // give-up budget doesn't apply. Only abort or a settled session ends it.
1323
+ while ((this.watchMode || (state.isStreaming && eofResubscribes < MAX_EOF_RESUBSCRIBES)) &&
1324
+ !currentSubscription?.sessionSettled &&
1325
+ !combinedSignal.aborted) {
1326
+ eofResubscribes++;
1327
+ await waitBeforeEofResubscribe(eofResubscribes, combinedSignal);
1328
+ if (combinedSignal.aborted)
1329
+ break;
1330
+ const opened = await openWithAuthRetry();
1331
+ if (opened)
1332
+ return opened;
1333
+ }
1334
+ // A settled session or an abort ends the turn cleanly. Exhausting the
1335
+ // resubscribe budget while the turn is still streaming means it was cut
1336
+ // off — surface an error so the UI doesn't read a truncated reply as
1337
+ // complete. The caller's catch emits stream-error and errors the stream.
1338
+ if (state.isStreaming &&
1339
+ !currentSubscription?.sessionSettled &&
1340
+ !combinedSignal.aborted) {
1341
+ throw new Error("Chat stream ended before the turn completed (reconnect budget exhausted).");
1342
+ }
1343
+ // Settled close, or the turn is gone — tell the UI instead of
1344
+ // leaving it spinning on a stream nobody will finish.
1345
+ if (state.isStreaming && this.activeStreams.get(chatId) === internalAbort) {
1346
+ state.isStreaming = false;
1347
+ this.notifySessionChange(chatId, state);
1348
+ }
1349
+ return null;
1350
+ };
1351
+ try {
1352
+ let reader;
1353
+ let primed;
1354
+ const opened = (await openWithAuthRetry()) ?? (await resumeAfterEof());
1355
+ if (opened === null) {
1356
+ try {
1357
+ controller.close();
1358
+ }
1359
+ catch {
1360
+ /* already closed by a consumer cancel */
1361
+ }
1362
+ return;
1363
+ }
1364
+ reader = opened.reader;
1365
+ primed = opened.primed;
1366
+ this.emitEvent({
1367
+ type: "stream-connected",
1368
+ chatId,
1369
+ timestamp: Date.now(),
1370
+ resumed: options?.resumed ?? false,
1371
+ lastEventId: state.lastEventId,
1372
+ messageId: this.lastTurnSends.get(chatId)?.messageId,
1373
+ });
1374
+ while (true) {
1375
+ let value;
1376
+ if (primed !== undefined) {
1377
+ value = primed;
1378
+ primed = undefined;
1379
+ }
1380
+ else {
1381
+ const next = await reader.read();
1382
+ if (next.done) {
1383
+ const resumed = await resumeAfterEof();
1384
+ if (resumed === null) {
1385
+ try {
1386
+ controller.close();
1387
+ }
1388
+ catch {
1389
+ /* already closed by a consumer cancel */
1390
+ }
1391
+ return;
1392
+ }
1393
+ reader = resumed.reader;
1394
+ primed = resumed.primed;
1395
+ continue;
1396
+ }
1397
+ value = next.value;
1398
+ }
1399
+ if (combinedSignal.aborted) {
1400
+ internalAbort.abort();
1401
+ await reader.cancel();
1402
+ try {
1403
+ controller.close();
1404
+ }
1405
+ catch {
1406
+ /* already closed by a consumer cancel */
1407
+ }
1408
+ return;
1409
+ }
1410
+ if (value.id)
1411
+ state.lastEventId = value.id;
1412
+ // Any record — including the first of a resumed connection, which
1413
+ // arrives via `primed` — re-earns the resubscribe budget, so a long
1414
+ // turn spanning many long-poll windows keeps streaming.
1415
+ eofResubscribes = 0;
1416
+ // Trigger control record (turn-complete, upgrade-required) —
1417
+ // routed by header, body is empty. Detect via the
1418
+ // `trigger-control` header on the SSE record. Data records
1419
+ // (UIMessageChunks) fall through to the chunk path below.
1420
+ //
1421
+ // Cross-version bridge: a customer who redeploys their
1422
+ // Next.js app (new browser SDK) before their next
1423
+ // `trigger deploy` (old agent SDK still writing turn-complete
1424
+ // / upgrade-required as `chunk.type` data records) would
1425
+ // otherwise hang. Fall back to the legacy chunk-type form
1426
+ // when no header is present so the deploy-skew window
1427
+ // closes turns correctly.
1428
+ let controlValue = controlSubtype(value.headers);
1429
+ let legacyChunk;
1430
+ if (!controlValue && value.chunk && typeof value.chunk === "object") {
1431
+ const chunk = value.chunk;
1432
+ if (chunk.type === "trigger:turn-complete") {
1433
+ controlValue = TRIGGER_CONTROL_SUBTYPE.TURN_COMPLETE;
1434
+ legacyChunk = chunk;
1435
+ }
1436
+ else if (chunk.type === "trigger:upgrade-required") {
1437
+ controlValue = TRIGGER_CONTROL_SUBTYPE.UPGRADE_REQUIRED;
1438
+ }
1439
+ else if (typeof chunk.type === "string" && chunk.type.startsWith("trigger:")) {
1440
+ // Future / unknown `trigger:*` legacy control type from
1441
+ // a pre-upgrade agent — drop so it doesn't reach the AI
1442
+ // SDK as an unrecognised UIMessageChunk.
1443
+ continue;
1444
+ }
1445
+ }
1446
+ if (state.skipToTurnComplete &&
1447
+ controlValue !== TRIGGER_CONTROL_SUBTYPE.SESSION_CLOSED &&
1448
+ controlValue !== TRIGGER_CONTROL_SUBTYPE.PENDING_VERSION) {
1449
+ // Fall through on a boundary so the `sinceInSeq` check and the
1450
+ // turn-completed emit below still run; content records are skipped.
1451
+ // A close is terminal and a pending version is the gated turn's own
1452
+ // handover status, so neither is ever gated away.
1453
+ if (controlValue !== TRIGGER_CONTROL_SUBTYPE.TURN_COMPLETE)
1454
+ continue;
1455
+ // A boundary older than the superseded turn is not its boundary —
1456
+ // keep gating. A header-less boundary (legacy wire) still clears.
1457
+ const gateCursorRaw = headerValue(value.headers, SESSION_IN_EVENT_ID_HEADER);
1458
+ const gateCursor = gateCursorRaw !== undefined ? Number.parseInt(gateCursorRaw, 10) : NaN;
1459
+ if (state.supersededInputSeq !== undefined &&
1460
+ !Number.isNaN(gateCursor) &&
1461
+ gateCursor < state.supersededInputSeq) {
1462
+ continue;
1463
+ }
1464
+ state.skipToTurnComplete = false;
1465
+ state.supersededInputSeq = undefined;
1466
+ // This boundary is the new turn's own, so the gate swallowed its
1467
+ // output: fail the turn instead of completing an empty answer, and
1468
+ // leave nothing armed for the retry.
1469
+ if (sinceInSeq !== undefined &&
1470
+ !Number.isNaN(gateCursor) &&
1471
+ gateCursor >= sinceInSeq) {
1472
+ // The lost boundary may also carry the session close.
1473
+ if (headerValue(value.headers, SESSION_CLOSED_HEADER) === "true") {
1474
+ this.markSessionClosed(chatId, state, headerValue(value.headers, SESSION_CLOSED_REASON_HEADER), "stream");
1475
+ }
1476
+ state.activeInputSeq = undefined;
1477
+ state.isStreaming = false;
1478
+ this.notifySessionChange(chatId, state);
1479
+ throw new Error("The previous turn's output was lost. Try again.");
1480
+ }
1481
+ }
1482
+ if (controlValue === TRIGGER_CONTROL_SUBTYPE.UPGRADE_REQUIRED) {
1483
+ // Server has already triggered the new run via
1484
+ // `end-and-continue`; the next chunks on this same `.out`
1485
+ // stream come from v2. Filter the marker for cleanliness
1486
+ // and keep reading.
1487
+ continue;
1488
+ }
1489
+ if (controlValue === TRIGGER_CONTROL_SUBTYPE.SESSION_CLOSED) {
1490
+ this.markSessionClosed(chatId, state, headerValue(value.headers, SESSION_CLOSED_REASON_HEADER), "stream");
1491
+ internalAbort.abort();
1492
+ try {
1493
+ controller.close();
1494
+ }
1495
+ catch {
1496
+ /* already closed */
1497
+ }
1498
+ return;
1499
+ }
1500
+ if (controlValue === TRIGGER_CONTROL_SUBTYPE.PENDING_VERSION) {
1501
+ this.emitEvent({
1502
+ type: "run-pending-version",
1503
+ chatId,
1504
+ timestamp: Date.now(),
1505
+ source: "upgrade",
1506
+ });
1507
+ continue;
1508
+ }
1509
+ if (controlValue === TRIGGER_CONTROL_SUBTYPE.TURN_COMPLETE) {
1510
+ const sessionInEventId = headerValue(value.headers, SESSION_IN_EVENT_ID_HEADER);
1511
+ const lastEventId = value.id || undefined;
1512
+ // Skip a turn-complete from an earlier turn (committed `.in` cursor
1513
+ // below this send's seq), e.g. an undo action that raced this send.
1514
+ if (sinceInSeq !== undefined) {
1515
+ const cursorRaw = headerValue(value.headers, SESSION_IN_EVENT_ID_HEADER);
1516
+ const cursor = cursorRaw !== undefined ? Number.parseInt(cursorRaw, 10) : NaN;
1517
+ if (!Number.isNaN(cursor) && cursor < sinceInSeq) {
1518
+ continue;
1519
+ }
1520
+ }
1521
+ // A close decided during this turn rides out on turn-complete —
1522
+ // the last record a reader sees before it ends the stream.
1523
+ if (headerValue(value.headers, SESSION_CLOSED_HEADER) === "true") {
1524
+ this.markSessionClosed(chatId, state, headerValue(value.headers, SESSION_CLOSED_REASON_HEADER), "stream");
1525
+ }
1526
+ const refreshedToken = headerValue(value.headers, PUBLIC_ACCESS_TOKEN_HEADER) ??
1527
+ legacyChunk?.publicAccessToken;
1528
+ if (refreshedToken) {
1529
+ state.publicAccessToken = refreshedToken;
1530
+ }
1531
+ this.emitEvent({
1532
+ type: "turn-completed",
1533
+ chatId,
1534
+ timestamp: Date.now(),
1535
+ lastEventId: state.lastEventId,
1536
+ sessionInEventId: headerValue(value.headers, SESSION_IN_EVENT_ID_HEADER),
1537
+ ...this.turnAttribution(chatId),
1538
+ });
1539
+ state.activeInputSeq = undefined;
1540
+ sinceInSeq = undefined;
1541
+ state.isStreaming = false;
1542
+ this.notifySessionChange(chatId, state);
1543
+ this.coordinator?.release(chatId);
1544
+ this.coordinator?.broadcastSession(chatId, {
1545
+ lastEventId: state.lastEventId,
1546
+ });
1547
+ // Use this subscription's original append, never mutable session state.
1548
+ const inputSeq = options?.sinceInSeq;
1549
+ const settledSeq = sessionInEventId !== undefined &&
1550
+ sessionInEventId.length > 0 &&
1551
+ !/\D/.test(sessionInEventId)
1552
+ ? Number(sessionInEventId)
1553
+ : NaN;
1554
+ if (!didSettle &&
1555
+ !combinedSignal.aborted &&
1556
+ this.activeStreams.get(chatId) === internalAbort &&
1557
+ inputSeq !== undefined &&
1558
+ Number.isSafeInteger(inputSeq) &&
1559
+ inputSeq >= 0 &&
1560
+ sessionInEventId !== undefined &&
1561
+ Number.isSafeInteger(settledSeq) &&
1562
+ settledSeq >= inputSeq) {
1563
+ didSettle = true;
1564
+ try {
1565
+ options?.onSettled?.({ inputSeq, sessionInEventId, lastEventId });
1566
+ }
1567
+ catch {
1568
+ // An observer must not turn a completed action into a stream error.
1569
+ }
1570
+ }
1571
+ // Re-arm per-turn events for watch mode's next turn.
1572
+ sawFirstChunk = false;
1573
+ if (this.watchMode)
1574
+ continue;
1575
+ internalAbort.abort();
1576
+ try {
1577
+ controller.close();
1578
+ }
1579
+ catch {
1580
+ /* already closed */
1581
+ }
1582
+ return;
1583
+ }
1584
+ // Data record — `value.chunk` is the parsed UIMessageChunk
1585
+ // unwrapped from the S2 record envelope (the parser does the
1586
+ // JSON unwrap). Drop empty/malformed payloads defensively.
1587
+ if (value.chunk == null)
1588
+ continue;
1589
+ if (!sawFirstChunk) {
1590
+ sawFirstChunk = true;
1591
+ this.emitEvent({
1592
+ type: "first-chunk",
1593
+ chatId,
1594
+ timestamp: Date.now(),
1595
+ chunkType: value.chunk.type,
1596
+ lastEventId: value.id || undefined,
1597
+ ...this.turnAttribution(chatId),
1598
+ });
1599
+ }
1600
+ controller.enqueue(value.chunk);
1601
+ }
1602
+ }
1603
+ catch (error) {
1604
+ if (error instanceof Error && error.name === "AbortError") {
1605
+ try {
1606
+ controller.close();
1607
+ }
1608
+ catch {
1609
+ /* already closed */
1610
+ }
1611
+ return;
1612
+ }
1613
+ const errorStatus = error.status;
1614
+ // A superseded stream cannot settle the replacement stream.
1615
+ if (this.activeStreams.get(chatId) === internalAbort) {
1616
+ state.isStreaming = false;
1617
+ this.notifySessionChange(chatId, state);
1618
+ }
1619
+ this.emitEvent({
1620
+ type: "stream-error",
1621
+ chatId,
1622
+ timestamp: Date.now(),
1623
+ error: error instanceof Error ? error : new Error(String(error)),
1624
+ status: typeof errorStatus === "number" ? errorStatus : undefined,
1625
+ });
1626
+ controller.error(error);
1627
+ }
1628
+ finally {
1629
+ teardownWakeListeners();
1630
+ // Only clear the entry (and drop the tab claim) if it is still
1631
+ // ours — a superseding send registers its controller before this
1632
+ // teardown runs, and owns the claim from then on.
1633
+ if (this.activeStreams.get(chatId) === internalAbort) {
1634
+ this.activeStreams.delete(chatId);
1635
+ this.coordinator?.release(chatId);
1636
+ }
1637
+ }
1638
+ },
1639
+ // A consumer that stops reading without aborting (drops the reader)
1640
+ // would otherwise leave the resubscribe loop running forever.
1641
+ cancel() {
1642
+ internalAbort.abort();
1643
+ },
1644
+ });
1645
+ }
1646
+ }
1647
+ /**
1648
+ * Convenience constructor matching {@link TriggerChatTransport}.
1649
+ */
1650
+ export function createChatTransport(options) {
1651
+ return new TriggerChatTransport(options);
1652
+ }
1653
+ // Server-side agent chat re-exports.
1654
+ export { AgentChat, ChatStream, } from "./chat-client.js";
1655
+ //# sourceMappingURL=chat.js.map