@copilotkit/runtime 1.54.1 → 1.55.0-next.8

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 (337) hide show
  1. package/.eslintrc.js +4 -4
  2. package/CHANGELOG.md +125 -113
  3. package/dist/_virtual/_rolldown/runtime.mjs +25 -1
  4. package/dist/agent/index.cjs +654 -0
  5. package/dist/agent/index.cjs.map +1 -0
  6. package/dist/agent/index.d.cts +263 -0
  7. package/dist/agent/index.d.cts.map +1 -0
  8. package/dist/agent/index.d.mts +263 -0
  9. package/dist/agent/index.d.mts.map +1 -0
  10. package/dist/agent/index.mjs +646 -0
  11. package/dist/agent/index.mjs.map +1 -0
  12. package/dist/graphql/message-conversion/agui-to-gql.cjs.map +1 -1
  13. package/dist/graphql/message-conversion/agui-to-gql.mjs.map +1 -1
  14. package/dist/lib/integrations/nextjs/app-router.cjs +2 -2
  15. package/dist/lib/integrations/nextjs/app-router.cjs.map +1 -1
  16. package/dist/lib/integrations/nextjs/app-router.mjs +1 -1
  17. package/dist/lib/integrations/nextjs/app-router.mjs.map +1 -1
  18. package/dist/lib/integrations/node-http/index.cjs +2 -3
  19. package/dist/lib/integrations/node-http/index.cjs.map +1 -1
  20. package/dist/lib/integrations/node-http/index.mjs +1 -1
  21. package/dist/lib/integrations/node-http/index.mjs.map +1 -1
  22. package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs +1 -1
  23. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts +2 -2
  24. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts.map +1 -1
  25. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts +3 -3
  26. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts.map +1 -1
  27. package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs +1 -1
  28. package/dist/lib/runtime/copilot-runtime.cjs +7 -5
  29. package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
  30. package/dist/lib/runtime/copilot-runtime.d.cts +10 -8
  31. package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
  32. package/dist/lib/runtime/copilot-runtime.d.mts +10 -8
  33. package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
  34. package/dist/lib/runtime/copilot-runtime.mjs +7 -5
  35. package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
  36. package/dist/lib/runtime/telemetry-agent-runner.cjs +2 -2
  37. package/dist/lib/runtime/telemetry-agent-runner.cjs.map +1 -1
  38. package/dist/lib/runtime/telemetry-agent-runner.d.cts +2 -1
  39. package/dist/lib/runtime/telemetry-agent-runner.d.cts.map +1 -1
  40. package/dist/lib/runtime/telemetry-agent-runner.d.mts +2 -1
  41. package/dist/lib/runtime/telemetry-agent-runner.d.mts.map +1 -1
  42. package/dist/lib/runtime/telemetry-agent-runner.mjs +1 -1
  43. package/dist/lib/runtime/telemetry-agent-runner.mjs.map +1 -1
  44. package/dist/lib/telemetry-client.cjs +1 -1
  45. package/dist/lib/telemetry-client.mjs +1 -1
  46. package/dist/package.cjs +21 -4
  47. package/dist/package.mjs +21 -4
  48. package/dist/service-adapters/anthropic/anthropic-adapter.d.mts +1 -1
  49. package/dist/v2/index.cjs +41 -15
  50. package/dist/v2/index.d.cts +14 -2
  51. package/dist/v2/index.d.mts +14 -2
  52. package/dist/v2/index.mjs +13 -4
  53. package/dist/v2/runtime/endpoints/express-single.cjs +190 -0
  54. package/dist/v2/runtime/endpoints/express-single.cjs.map +1 -0
  55. package/dist/v2/runtime/endpoints/express-single.d.cts +16 -0
  56. package/dist/v2/runtime/endpoints/express-single.d.cts.map +1 -0
  57. package/dist/v2/runtime/endpoints/express-single.d.mts +16 -0
  58. package/dist/v2/runtime/endpoints/express-single.d.mts.map +1 -0
  59. package/dist/v2/runtime/endpoints/express-single.mjs +187 -0
  60. package/dist/v2/runtime/endpoints/express-single.mjs.map +1 -0
  61. package/dist/v2/runtime/endpoints/express-utils.cjs +119 -0
  62. package/dist/v2/runtime/endpoints/express-utils.cjs.map +1 -0
  63. package/dist/v2/runtime/endpoints/express-utils.mjs +117 -0
  64. package/dist/v2/runtime/endpoints/express-utils.mjs.map +1 -0
  65. package/dist/v2/runtime/endpoints/express.cjs +217 -0
  66. package/dist/v2/runtime/endpoints/express.cjs.map +1 -0
  67. package/dist/v2/runtime/endpoints/express.d.cts +16 -0
  68. package/dist/v2/runtime/endpoints/express.d.cts.map +1 -0
  69. package/dist/v2/runtime/endpoints/express.d.mts +16 -0
  70. package/dist/v2/runtime/endpoints/express.d.mts.map +1 -0
  71. package/dist/v2/runtime/endpoints/express.mjs +214 -0
  72. package/dist/v2/runtime/endpoints/express.mjs.map +1 -0
  73. package/dist/v2/runtime/endpoints/hono-single.cjs +141 -0
  74. package/dist/v2/runtime/endpoints/hono-single.cjs.map +1 -0
  75. package/dist/v2/runtime/endpoints/hono-single.d.cts +41 -0
  76. package/dist/v2/runtime/endpoints/hono-single.d.cts.map +1 -0
  77. package/dist/v2/runtime/endpoints/hono-single.d.mts +41 -0
  78. package/dist/v2/runtime/endpoints/hono-single.d.mts.map +1 -0
  79. package/dist/v2/runtime/endpoints/hono-single.mjs +140 -0
  80. package/dist/v2/runtime/endpoints/hono-single.mjs.map +1 -0
  81. package/dist/v2/runtime/endpoints/hono.cjs +248 -0
  82. package/dist/v2/runtime/endpoints/hono.cjs.map +1 -0
  83. package/dist/v2/runtime/endpoints/hono.d.cts +164 -0
  84. package/dist/v2/runtime/endpoints/hono.d.cts.map +1 -0
  85. package/dist/v2/runtime/endpoints/hono.d.mts +164 -0
  86. package/dist/v2/runtime/endpoints/hono.d.mts.map +1 -0
  87. package/dist/v2/runtime/endpoints/hono.mjs +247 -0
  88. package/dist/v2/runtime/endpoints/hono.mjs.map +1 -0
  89. package/dist/v2/runtime/endpoints/index.d.cts +5 -0
  90. package/dist/v2/runtime/endpoints/index.d.mts +5 -0
  91. package/dist/v2/runtime/endpoints/single-route-helpers.cjs +68 -0
  92. package/dist/v2/runtime/endpoints/single-route-helpers.cjs.map +1 -0
  93. package/dist/v2/runtime/endpoints/single-route-helpers.mjs +65 -0
  94. package/dist/v2/runtime/endpoints/single-route-helpers.mjs.map +1 -0
  95. package/dist/v2/runtime/handlers/get-runtime-info.cjs +51 -0
  96. package/dist/v2/runtime/handlers/get-runtime-info.cjs.map +1 -0
  97. package/dist/v2/runtime/handlers/get-runtime-info.mjs +51 -0
  98. package/dist/v2/runtime/handlers/get-runtime-info.mjs.map +1 -0
  99. package/dist/v2/runtime/handlers/handle-connect.cjs +49 -0
  100. package/dist/v2/runtime/handlers/handle-connect.cjs.map +1 -0
  101. package/dist/v2/runtime/handlers/handle-connect.mjs +49 -0
  102. package/dist/v2/runtime/handlers/handle-connect.mjs.map +1 -0
  103. package/dist/v2/runtime/handlers/handle-run.cjs +61 -0
  104. package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -0
  105. package/dist/v2/runtime/handlers/handle-run.mjs +61 -0
  106. package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -0
  107. package/dist/v2/runtime/handlers/handle-stop.cjs +47 -0
  108. package/dist/v2/runtime/handlers/handle-stop.cjs.map +1 -0
  109. package/dist/v2/runtime/handlers/handle-stop.mjs +46 -0
  110. package/dist/v2/runtime/handlers/handle-stop.mjs.map +1 -0
  111. package/dist/v2/runtime/handlers/handle-transcribe.cjs +112 -0
  112. package/dist/v2/runtime/handlers/handle-transcribe.cjs.map +1 -0
  113. package/dist/v2/runtime/handlers/handle-transcribe.mjs +111 -0
  114. package/dist/v2/runtime/handlers/handle-transcribe.mjs.map +1 -0
  115. package/dist/v2/runtime/handlers/header-utils.cjs +26 -0
  116. package/dist/v2/runtime/handlers/header-utils.cjs.map +1 -0
  117. package/dist/v2/runtime/handlers/header-utils.mjs +25 -0
  118. package/dist/v2/runtime/handlers/header-utils.mjs.map +1 -0
  119. package/dist/v2/runtime/handlers/intelligence/connect.cjs +37 -0
  120. package/dist/v2/runtime/handlers/intelligence/connect.cjs.map +1 -0
  121. package/dist/v2/runtime/handlers/intelligence/connect.mjs +37 -0
  122. package/dist/v2/runtime/handlers/intelligence/connect.mjs.map +1 -0
  123. package/dist/v2/runtime/handlers/intelligence/run.cjs +89 -0
  124. package/dist/v2/runtime/handlers/intelligence/run.cjs.map +1 -0
  125. package/dist/v2/runtime/handlers/intelligence/run.mjs +88 -0
  126. package/dist/v2/runtime/handlers/intelligence/run.mjs.map +1 -0
  127. package/dist/v2/runtime/handlers/intelligence/thread-names.cjs +146 -0
  128. package/dist/v2/runtime/handlers/intelligence/thread-names.cjs.map +1 -0
  129. package/dist/v2/runtime/handlers/intelligence/thread-names.mjs +145 -0
  130. package/dist/v2/runtime/handlers/intelligence/thread-names.mjs.map +1 -0
  131. package/dist/v2/runtime/handlers/intelligence/threads.cjs +159 -0
  132. package/dist/v2/runtime/handlers/intelligence/threads.cjs.map +1 -0
  133. package/dist/v2/runtime/handlers/intelligence/threads.mjs +154 -0
  134. package/dist/v2/runtime/handlers/intelligence/threads.mjs.map +1 -0
  135. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +74 -0
  136. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -0
  137. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +70 -0
  138. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -0
  139. package/dist/v2/runtime/handlers/shared/intelligence-utils.cjs +21 -0
  140. package/dist/v2/runtime/handlers/shared/intelligence-utils.cjs.map +1 -0
  141. package/dist/v2/runtime/handlers/shared/intelligence-utils.mjs +20 -0
  142. package/dist/v2/runtime/handlers/shared/intelligence-utils.mjs.map +1 -0
  143. package/dist/v2/runtime/handlers/shared/json-response.cjs +12 -0
  144. package/dist/v2/runtime/handlers/shared/json-response.cjs.map +1 -0
  145. package/dist/v2/runtime/handlers/shared/json-response.mjs +10 -0
  146. package/dist/v2/runtime/handlers/shared/json-response.mjs.map +1 -0
  147. package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs +20 -0
  148. package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs.map +1 -0
  149. package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs +20 -0
  150. package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs.map +1 -0
  151. package/dist/v2/runtime/handlers/shared/sse-response.cjs +69 -0
  152. package/dist/v2/runtime/handlers/shared/sse-response.cjs.map +1 -0
  153. package/dist/v2/runtime/handlers/shared/sse-response.mjs +68 -0
  154. package/dist/v2/runtime/handlers/shared/sse-response.mjs.map +1 -0
  155. package/dist/v2/runtime/handlers/sse/connect.cjs +18 -0
  156. package/dist/v2/runtime/handlers/sse/connect.cjs.map +1 -0
  157. package/dist/v2/runtime/handlers/sse/connect.mjs +18 -0
  158. package/dist/v2/runtime/handlers/sse/connect.mjs.map +1 -0
  159. package/dist/v2/runtime/handlers/sse/run.cjs +18 -0
  160. package/dist/v2/runtime/handlers/sse/run.cjs.map +1 -0
  161. package/dist/v2/runtime/handlers/sse/run.mjs +18 -0
  162. package/dist/v2/runtime/handlers/sse/run.mjs.map +1 -0
  163. package/dist/v2/runtime/index.d.cts +13 -0
  164. package/dist/v2/runtime/index.d.mts +14 -0
  165. package/dist/v2/runtime/intelligence-platform/client.cjs +333 -0
  166. package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -0
  167. package/dist/v2/runtime/intelligence-platform/client.d.cts +336 -0
  168. package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -0
  169. package/dist/v2/runtime/intelligence-platform/client.d.mts +336 -0
  170. package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -0
  171. package/dist/v2/runtime/intelligence-platform/client.mjs +331 -0
  172. package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -0
  173. package/dist/v2/runtime/intelligence-platform/index.d.mts +2 -0
  174. package/dist/v2/runtime/middleware-sse-parser.cjs +138 -0
  175. package/dist/v2/runtime/middleware-sse-parser.cjs.map +1 -0
  176. package/dist/v2/runtime/middleware-sse-parser.d.cts +22 -0
  177. package/dist/v2/runtime/middleware-sse-parser.d.cts.map +1 -0
  178. package/dist/v2/runtime/middleware-sse-parser.d.mts +22 -0
  179. package/dist/v2/runtime/middleware-sse-parser.d.mts.map +1 -0
  180. package/dist/v2/runtime/middleware-sse-parser.mjs +137 -0
  181. package/dist/v2/runtime/middleware-sse-parser.mjs.map +1 -0
  182. package/dist/v2/runtime/middleware.cjs +35 -0
  183. package/dist/v2/runtime/middleware.cjs.map +1 -0
  184. package/dist/v2/runtime/middleware.d.cts +32 -0
  185. package/dist/v2/runtime/middleware.d.cts.map +1 -0
  186. package/dist/v2/runtime/middleware.d.mts +32 -0
  187. package/dist/v2/runtime/middleware.d.mts.map +1 -0
  188. package/dist/v2/runtime/middleware.mjs +33 -0
  189. package/dist/v2/runtime/middleware.mjs.map +1 -0
  190. package/dist/v2/runtime/runner/agent-runner.cjs +8 -0
  191. package/dist/v2/runtime/runner/agent-runner.cjs.map +1 -0
  192. package/dist/v2/runtime/runner/agent-runner.d.cts +32 -0
  193. package/dist/v2/runtime/runner/agent-runner.d.cts.map +1 -0
  194. package/dist/v2/runtime/runner/agent-runner.d.mts +32 -0
  195. package/dist/v2/runtime/runner/agent-runner.d.mts.map +1 -0
  196. package/dist/v2/runtime/runner/agent-runner.mjs +7 -0
  197. package/dist/v2/runtime/runner/agent-runner.mjs.map +1 -0
  198. package/dist/v2/runtime/runner/in-memory.cjs +223 -0
  199. package/dist/v2/runtime/runner/in-memory.cjs.map +1 -0
  200. package/dist/v2/runtime/runner/in-memory.d.cts +15 -0
  201. package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -0
  202. package/dist/v2/runtime/runner/in-memory.d.mts +15 -0
  203. package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -0
  204. package/dist/v2/runtime/runner/in-memory.mjs +222 -0
  205. package/dist/v2/runtime/runner/in-memory.mjs.map +1 -0
  206. package/dist/v2/runtime/runner/index.d.cts +6 -0
  207. package/dist/v2/runtime/runner/index.d.mts +6 -0
  208. package/dist/v2/runtime/runner/index.mjs +7 -0
  209. package/dist/v2/runtime/runner/intelligence.cjs +246 -0
  210. package/dist/v2/runtime/runner/intelligence.cjs.map +1 -0
  211. package/dist/v2/runtime/runner/intelligence.d.cts +57 -0
  212. package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -0
  213. package/dist/v2/runtime/runner/intelligence.d.mts +57 -0
  214. package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -0
  215. package/dist/v2/runtime/runner/intelligence.mjs +245 -0
  216. package/dist/v2/runtime/runner/intelligence.mjs.map +1 -0
  217. package/dist/v2/runtime/runtime.cjs +101 -0
  218. package/dist/v2/runtime/runtime.cjs.map +1 -0
  219. package/dist/v2/runtime/runtime.d.cts +132 -0
  220. package/dist/v2/runtime/runtime.d.cts.map +1 -0
  221. package/dist/v2/runtime/runtime.d.mts +133 -0
  222. package/dist/v2/runtime/runtime.d.mts.map +1 -0
  223. package/dist/v2/runtime/runtime.mjs +97 -0
  224. package/dist/v2/runtime/runtime.mjs.map +1 -0
  225. package/dist/v2/runtime/telemetry/scarf-client.cjs +32 -0
  226. package/dist/v2/runtime/telemetry/scarf-client.cjs.map +1 -0
  227. package/dist/v2/runtime/telemetry/scarf-client.mjs +32 -0
  228. package/dist/v2/runtime/telemetry/scarf-client.mjs.map +1 -0
  229. package/dist/v2/runtime/telemetry/telemetry-client.cjs +35 -0
  230. package/dist/v2/runtime/telemetry/telemetry-client.cjs.map +1 -0
  231. package/dist/v2/runtime/telemetry/telemetry-client.mjs +35 -0
  232. package/dist/v2/runtime/telemetry/telemetry-client.mjs.map +1 -0
  233. package/dist/v2/runtime/transcription-service/transcription-service.cjs +8 -0
  234. package/dist/v2/runtime/transcription-service/transcription-service.cjs.map +1 -0
  235. package/dist/v2/runtime/transcription-service/transcription-service.d.cts +15 -0
  236. package/dist/v2/runtime/transcription-service/transcription-service.d.cts.map +1 -0
  237. package/dist/v2/runtime/transcription-service/transcription-service.d.mts +15 -0
  238. package/dist/v2/runtime/transcription-service/transcription-service.d.mts.map +1 -0
  239. package/dist/v2/runtime/transcription-service/transcription-service.mjs +7 -0
  240. package/dist/v2/runtime/transcription-service/transcription-service.mjs.map +1 -0
  241. package/package.json +24 -7
  242. package/src/agent/__tests__/ai-sdk-v6-compat.test.ts +116 -0
  243. package/src/agent/__tests__/basic-agent.test.ts +1698 -0
  244. package/src/agent/__tests__/config-tools-execution.test.ts +516 -0
  245. package/src/agent/__tests__/mcp-clients.test.ts +260 -0
  246. package/src/agent/__tests__/property-overrides.test.ts +598 -0
  247. package/src/agent/__tests__/standard-schema-tools.test.ts +313 -0
  248. package/src/agent/__tests__/standard-schema-types.test.ts +158 -0
  249. package/src/agent/__tests__/state-tools.test.ts +436 -0
  250. package/src/agent/__tests__/test-helpers.ts +193 -0
  251. package/src/agent/__tests__/utils.test.ts +536 -0
  252. package/src/agent/__tests__/zod-regression.test.ts +350 -0
  253. package/src/agent/index.ts +1329 -0
  254. package/src/graphql/message-conversion/agui-to-gql.test.ts +1 -1
  255. package/src/graphql/message-conversion/agui-to-gql.ts +1 -1
  256. package/src/graphql/message-conversion/gql-to-agui.ts +1 -1
  257. package/src/graphql/message-conversion/roundtrip-conversion.test.ts +1 -1
  258. package/src/lib/integrations/nextjs/app-router.ts +2 -2
  259. package/src/lib/integrations/node-http/index.ts +2 -2
  260. package/src/lib/runtime/copilot-runtime.ts +3 -5
  261. package/src/lib/runtime/telemetry-agent-runner.ts +1 -1
  262. package/src/service-adapters/conversion.test.ts +1 -1
  263. package/src/service-adapters/conversion.ts +1 -28
  264. package/src/v2/index.ts +5 -2
  265. package/src/v2/runtime/__tests__/cors-credentials.test.ts +320 -0
  266. package/src/v2/runtime/__tests__/express-abort-signal.test.ts +25 -0
  267. package/src/v2/runtime/__tests__/express-body-order.test.ts +76 -0
  268. package/src/v2/runtime/__tests__/express-single-sse.test.ts +122 -0
  269. package/src/v2/runtime/__tests__/get-runtime-info.test.ts +141 -0
  270. package/src/v2/runtime/__tests__/handle-connect.test.ts +423 -0
  271. package/src/v2/runtime/__tests__/handle-run.test.ts +910 -0
  272. package/src/v2/runtime/__tests__/handle-threads.test.ts +388 -0
  273. package/src/v2/runtime/__tests__/handle-transcribe.test.ts +301 -0
  274. package/src/v2/runtime/__tests__/header-utils.test.ts +88 -0
  275. package/src/v2/runtime/__tests__/in-process-agent-runner-messages.test.ts +230 -0
  276. package/src/v2/runtime/__tests__/in-process-agent-runner.test.ts +1030 -0
  277. package/src/v2/runtime/__tests__/middleware-express.test.ts +206 -0
  278. package/src/v2/runtime/__tests__/middleware-single-express.test.ts +211 -0
  279. package/src/v2/runtime/__tests__/middleware-single.test.ts +225 -0
  280. package/src/v2/runtime/__tests__/middleware-sse-parser.test.ts +187 -0
  281. package/src/v2/runtime/__tests__/middleware.test.ts +251 -0
  282. package/src/v2/runtime/__tests__/routing-express.test.ts +174 -0
  283. package/src/v2/runtime/__tests__/routing-single-express.test.ts +168 -0
  284. package/src/v2/runtime/__tests__/routing-single.test.ts +193 -0
  285. package/src/v2/runtime/__tests__/routing.test.ts +257 -0
  286. package/src/v2/runtime/__tests__/runtime.test.ts +123 -0
  287. package/src/v2/runtime/__tests__/telemetry.test.ts +167 -0
  288. package/src/v2/runtime/__tests__/thread-names.test.ts +188 -0
  289. package/src/v2/runtime/endpoints/express-single.ts +231 -0
  290. package/src/v2/runtime/endpoints/express-utils.ts +182 -0
  291. package/src/v2/runtime/endpoints/express.ts +275 -0
  292. package/src/v2/runtime/endpoints/hono-single.ts +212 -0
  293. package/src/v2/runtime/endpoints/hono.ts +314 -0
  294. package/src/v2/runtime/endpoints/index.ts +4 -0
  295. package/src/v2/runtime/endpoints/single-route-helpers.ts +125 -0
  296. package/src/v2/runtime/express.ts +2 -0
  297. package/src/v2/runtime/handler.ts +3 -0
  298. package/src/v2/runtime/handlers/get-runtime-info.ts +79 -0
  299. package/src/v2/runtime/handlers/handle-connect.ts +76 -0
  300. package/src/v2/runtime/handlers/handle-run.ts +89 -0
  301. package/src/v2/runtime/handlers/handle-stop.ts +76 -0
  302. package/src/v2/runtime/handlers/handle-threads.ts +7 -0
  303. package/src/v2/runtime/handlers/handle-transcribe.ts +256 -0
  304. package/src/v2/runtime/handlers/header-utils.ts +24 -0
  305. package/src/v2/runtime/handlers/intelligence/connect.ts +65 -0
  306. package/src/v2/runtime/handlers/intelligence/run.ts +152 -0
  307. package/src/v2/runtime/handlers/intelligence/thread-names.ts +246 -0
  308. package/src/v2/runtime/handlers/intelligence/threads.ts +233 -0
  309. package/src/v2/runtime/handlers/shared/agent-utils.ts +136 -0
  310. package/src/v2/runtime/handlers/shared/intelligence-utils.ts +21 -0
  311. package/src/v2/runtime/handlers/shared/json-response.ts +6 -0
  312. package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +25 -0
  313. package/src/v2/runtime/handlers/shared/sse-response.ts +100 -0
  314. package/src/v2/runtime/handlers/sse/connect.ts +24 -0
  315. package/src/v2/runtime/handlers/sse/run.ts +27 -0
  316. package/src/v2/runtime/index.ts +20 -0
  317. package/src/v2/runtime/intelligence-platform/__tests__/client.test.ts +605 -0
  318. package/src/v2/runtime/intelligence-platform/client.ts +659 -0
  319. package/src/v2/runtime/intelligence-platform/index.ts +10 -0
  320. package/src/v2/runtime/middleware-sse-parser.ts +200 -0
  321. package/src/v2/runtime/middleware.ts +115 -0
  322. package/src/v2/runtime/runner/__tests__/finalize-events.test.ts +109 -0
  323. package/src/v2/runtime/runner/__tests__/in-memory-runner.e2e.test.ts +775 -0
  324. package/src/v2/runtime/runner/__tests__/in-memory-runner.test.ts +363 -0
  325. package/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts +981 -0
  326. package/src/v2/runtime/runner/agent-runner.ts +36 -0
  327. package/src/v2/runtime/runner/in-memory.ts +381 -0
  328. package/src/v2/runtime/runner/index.ts +4 -0
  329. package/src/v2/runtime/runner/intelligence.ts +429 -0
  330. package/src/v2/runtime/runtime.ts +260 -0
  331. package/src/v2/runtime/telemetry/events.ts +35 -0
  332. package/src/v2/runtime/telemetry/index.ts +7 -0
  333. package/src/v2/runtime/telemetry/scarf-client.ts +39 -0
  334. package/src/v2/runtime/telemetry/telemetry-client.ts +70 -0
  335. package/src/v2/runtime/transcription-service/transcription-service.ts +11 -0
  336. package/tsconfig.json +9 -2
  337. package/tsdown.config.ts +1 -0
@@ -0,0 +1,1329 @@
1
+ import {
2
+ AbstractAgent,
3
+ BaseEvent,
4
+ RunAgentInput,
5
+ EventType,
6
+ Message,
7
+ ReasoningEndEvent,
8
+ ReasoningMessageContentEvent,
9
+ ReasoningMessageEndEvent,
10
+ ReasoningMessageStartEvent,
11
+ ReasoningStartEvent,
12
+ RunFinishedEvent,
13
+ RunStartedEvent,
14
+ TextMessageChunkEvent,
15
+ ToolCallArgsEvent,
16
+ ToolCallEndEvent,
17
+ ToolCallStartEvent,
18
+ ToolCallResultEvent,
19
+ RunErrorEvent,
20
+ StateSnapshotEvent,
21
+ StateDeltaEvent,
22
+ } from "@ag-ui/client";
23
+ import {
24
+ streamText,
25
+ LanguageModel,
26
+ ModelMessage,
27
+ AssistantModelMessage,
28
+ UserModelMessage,
29
+ ToolModelMessage,
30
+ SystemModelMessage,
31
+ ToolCallPart,
32
+ ToolResultPart,
33
+ TextPart,
34
+ tool as createVercelAISDKTool,
35
+ ToolChoice,
36
+ ToolSet,
37
+ stepCountIs,
38
+ } from "ai";
39
+ import { experimental_createMCPClient as createMCPClient } from "@ai-sdk/mcp";
40
+ import { Observable } from "rxjs";
41
+ import { createOpenAI } from "@ai-sdk/openai";
42
+ import { createAnthropic } from "@ai-sdk/anthropic";
43
+ import { createGoogleGenerativeAI } from "@ai-sdk/google";
44
+ import { createVertex } from "@ai-sdk/google-vertex";
45
+ import { randomUUID } from "crypto";
46
+ import { safeParseToolArgs } from "@copilotkit/shared";
47
+ import { z } from "zod";
48
+ import type { StandardSchemaV1, InferSchemaOutput } from "@copilotkit/shared";
49
+ import { schemaToJsonSchema } from "@copilotkit/shared";
50
+ import { jsonSchema as aiJsonSchema } from "ai";
51
+ import {
52
+ StreamableHTTPClientTransport,
53
+ StreamableHTTPClientTransportOptions,
54
+ } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
55
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
56
+
57
+ /**
58
+ * Properties that can be overridden by forwardedProps
59
+ * These match the exact parameter names in streamText
60
+ */
61
+ export type OverridableProperty =
62
+ | "model"
63
+ | "toolChoice"
64
+ | "maxOutputTokens"
65
+ | "temperature"
66
+ | "topP"
67
+ | "topK"
68
+ | "presencePenalty"
69
+ | "frequencyPenalty"
70
+ | "stopSequences"
71
+ | "seed"
72
+ | "maxRetries"
73
+ | "prompt"
74
+ | "providerOptions";
75
+
76
+ /**
77
+ * Supported model identifiers for BuiltInAgent
78
+ */
79
+ export type BuiltInAgentModel =
80
+ // OpenAI models
81
+ | "openai/gpt-5"
82
+ | "openai/gpt-5-mini"
83
+ | "openai/gpt-4.1"
84
+ | "openai/gpt-4.1-mini"
85
+ | "openai/gpt-4.1-nano"
86
+ | "openai/gpt-4o"
87
+ | "openai/gpt-4o-mini"
88
+ // OpenAI reasoning series
89
+ | "openai/o3"
90
+ | "openai/o3-mini"
91
+ | "openai/o4-mini"
92
+ // Anthropic (Claude) models
93
+ | "anthropic/claude-sonnet-4.5"
94
+ | "anthropic/claude-sonnet-4"
95
+ | "anthropic/claude-3.7-sonnet"
96
+ | "anthropic/claude-opus-4.1"
97
+ | "anthropic/claude-opus-4"
98
+ | "anthropic/claude-3.5-haiku"
99
+ // Google (Gemini) models
100
+ | "google/gemini-2.5-pro"
101
+ | "google/gemini-2.5-flash"
102
+ | "google/gemini-2.5-flash-lite"
103
+ // Allow any LanguageModel instance
104
+ | (string & {});
105
+
106
+ /**
107
+ * Model specifier - can be a string like "openai/gpt-4o" or a LanguageModel instance
108
+ */
109
+ export type ModelSpecifier = string | LanguageModel;
110
+
111
+ /**
112
+ * MCP Client configuration for HTTP transport
113
+ */
114
+ export interface MCPClientConfigHTTP {
115
+ /**
116
+ * Type of MCP client
117
+ */
118
+ type: "http";
119
+ /**
120
+ * URL of the MCP server
121
+ */
122
+ url: string;
123
+ /**
124
+ * Optional transport options for HTTP client
125
+ */
126
+ options?: StreamableHTTPClientTransportOptions;
127
+ }
128
+
129
+ /**
130
+ * MCP Client configuration for SSE transport
131
+ */
132
+ export interface MCPClientConfigSSE {
133
+ /**
134
+ * Type of MCP client
135
+ */
136
+ type: "sse";
137
+ /**
138
+ * URL of the MCP server
139
+ */
140
+ url: string;
141
+ /**
142
+ * Optional HTTP headers (e.g., for authentication)
143
+ */
144
+ headers?: Record<string, string>;
145
+ }
146
+
147
+ /**
148
+ * MCP Client configuration
149
+ */
150
+ export type MCPClientConfig = MCPClientConfigHTTP | MCPClientConfigSSE;
151
+
152
+ /**
153
+ * A user-managed MCP client that provides tools to the agent.
154
+ * The user is responsible for creating, configuring, and closing the client.
155
+ * Compatible with the return type of @ai-sdk/mcp's createMCPClient().
156
+ *
157
+ * Unlike mcpServers, the agent does NOT create or close these clients.
158
+ * This allows persistent connections, custom auth, and tool caching.
159
+ */
160
+ export interface MCPClientProvider {
161
+ /** Return tools to be merged into the agent's tool set. */
162
+ tools(): Promise<ToolSet>;
163
+ }
164
+
165
+ /**
166
+ * Resolves a model specifier to a LanguageModel instance
167
+ * @param spec - Model string (e.g., "openai/gpt-4o") or LanguageModel instance
168
+ * @param apiKey - Optional API key to use instead of environment variables
169
+ * @returns LanguageModel instance
170
+ */
171
+ export function resolveModel(
172
+ spec: ModelSpecifier,
173
+ apiKey?: string,
174
+ ): LanguageModel {
175
+ // If already a LanguageModel instance, pass through
176
+ if (typeof spec !== "string") {
177
+ return spec;
178
+ }
179
+
180
+ // Normalize "provider/model" or "provider:model" format
181
+ const normalized = spec.replace("/", ":").trim();
182
+ const parts = normalized.split(":");
183
+ const rawProvider = parts[0];
184
+ const rest = parts.slice(1);
185
+
186
+ if (!rawProvider) {
187
+ throw new Error(
188
+ `Invalid model string "${spec}". Use "openai/gpt-5", "anthropic/claude-sonnet-4.5", or "google/gemini-2.5-pro".`,
189
+ );
190
+ }
191
+
192
+ const provider = rawProvider.toLowerCase();
193
+ const model = rest.join(":").trim();
194
+
195
+ if (!model) {
196
+ throw new Error(
197
+ `Invalid model string "${spec}". Use "openai/gpt-5", "anthropic/claude-sonnet-4.5", or "google/gemini-2.5-pro".`,
198
+ );
199
+ }
200
+
201
+ switch (provider) {
202
+ case "openai": {
203
+ // Lazily create OpenAI provider
204
+ // Use provided apiKey, or fall back to environment variable
205
+ const openai = createOpenAI({
206
+ apiKey: apiKey || process.env.OPENAI_API_KEY!,
207
+ });
208
+ // Accepts any OpenAI model id, e.g. "gpt-4o", "gpt-4.1-mini", "o3-mini"
209
+ return openai(model);
210
+ }
211
+
212
+ case "anthropic": {
213
+ // Lazily create Anthropic provider
214
+ // Use provided apiKey, or fall back to environment variable
215
+ const anthropic = createAnthropic({
216
+ apiKey: apiKey || process.env.ANTHROPIC_API_KEY!,
217
+ });
218
+ // Accepts any Claude id, e.g. "claude-3.7-sonnet", "claude-3.5-haiku"
219
+ return anthropic(model);
220
+ }
221
+
222
+ case "google":
223
+ case "gemini":
224
+ case "google-gemini": {
225
+ // Lazily create Google provider
226
+ // Use provided apiKey, or fall back to environment variable
227
+ const google = createGoogleGenerativeAI({
228
+ apiKey: apiKey || process.env.GOOGLE_API_KEY!,
229
+ });
230
+ // Accepts any Gemini id, e.g. "gemini-2.5-pro", "gemini-2.5-flash"
231
+ return google(model);
232
+ }
233
+
234
+ case "vertex": {
235
+ const vertex = createVertex();
236
+ return vertex(model);
237
+ }
238
+
239
+ default:
240
+ throw new Error(
241
+ `Unknown provider "${provider}" in "${spec}". Supported: openai, anthropic, google (gemini).`,
242
+ );
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Tool definition for BuiltInAgent
248
+ */
249
+ export interface ToolDefinition<
250
+ TParameters extends StandardSchemaV1 = StandardSchemaV1,
251
+ > {
252
+ name: string;
253
+ description: string;
254
+ parameters: TParameters;
255
+ execute: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;
256
+ }
257
+
258
+ /**
259
+ * Define a tool for use with BuiltInAgent
260
+ * @param name - The name of the tool
261
+ * @param description - Description of what the tool does
262
+ * @param parameters - Schema for the tool's input parameters (any Standard Schema V1 compatible library: Zod, Valibot, ArkType, etc.)
263
+ * @param execute - Function to execute the tool server-side
264
+ * @returns Tool definition
265
+ */
266
+ export function defineTool<TParameters extends StandardSchemaV1>(config: {
267
+ name: string;
268
+ description: string;
269
+ parameters: TParameters;
270
+ execute: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;
271
+ }): ToolDefinition<TParameters> {
272
+ return {
273
+ name: config.name,
274
+ description: config.description,
275
+ parameters: config.parameters,
276
+ execute: config.execute,
277
+ };
278
+ }
279
+
280
+ type AGUIUserMessage = Extract<Message, { role: "user" }>;
281
+
282
+ function flattenUserMessageContent(
283
+ content?: AGUIUserMessage["content"],
284
+ ): string {
285
+ if (!content) {
286
+ return "";
287
+ }
288
+
289
+ if (typeof content === "string") {
290
+ return content;
291
+ }
292
+
293
+ return content
294
+ .map((part) => {
295
+ if (
296
+ part &&
297
+ typeof part === "object" &&
298
+ "type" in part &&
299
+ (part as { type?: unknown }).type === "text" &&
300
+ typeof (part as { text?: unknown }).text === "string"
301
+ ) {
302
+ return (part as { text: string }).text;
303
+ }
304
+ return "";
305
+ })
306
+ .filter((text) => text.length > 0)
307
+ .join("\n");
308
+ }
309
+
310
+ /**
311
+ * Options for converting AG-UI messages to Vercel AI SDK format
312
+ */
313
+ export interface MessageConversionOptions {
314
+ forwardSystemMessages?: boolean;
315
+ forwardDeveloperMessages?: boolean;
316
+ }
317
+
318
+ /**
319
+ * Converts AG-UI messages to Vercel AI SDK ModelMessage format
320
+ */
321
+ export function convertMessagesToVercelAISDKMessages(
322
+ messages: Message[],
323
+ options: MessageConversionOptions = {},
324
+ ): ModelMessage[] {
325
+ const result: ModelMessage[] = [];
326
+
327
+ for (const message of messages) {
328
+ if (message.role === "system" && options.forwardSystemMessages) {
329
+ const systemMsg: SystemModelMessage = {
330
+ role: "system",
331
+ content: message.content ?? "",
332
+ };
333
+ result.push(systemMsg);
334
+ } else if (
335
+ message.role === "developer" &&
336
+ options.forwardDeveloperMessages
337
+ ) {
338
+ const systemMsg: SystemModelMessage = {
339
+ role: "system",
340
+ content: message.content ?? "",
341
+ };
342
+ result.push(systemMsg);
343
+ } else if (message.role === "assistant") {
344
+ const parts: Array<TextPart | ToolCallPart> = message.content
345
+ ? [{ type: "text", text: message.content }]
346
+ : [];
347
+
348
+ for (const toolCall of message.toolCalls ?? []) {
349
+ const toolCallPart: ToolCallPart = {
350
+ type: "tool-call",
351
+ toolCallId: toolCall.id,
352
+ toolName: toolCall.function.name,
353
+ input: safeParseToolArgs(toolCall.function.arguments),
354
+ };
355
+ parts.push(toolCallPart);
356
+ }
357
+
358
+ const assistantMsg: AssistantModelMessage = {
359
+ role: "assistant",
360
+ content: parts,
361
+ };
362
+ result.push(assistantMsg);
363
+ } else if (message.role === "user") {
364
+ const userMsg: UserModelMessage = {
365
+ role: "user",
366
+ content: flattenUserMessageContent(message.content),
367
+ };
368
+ result.push(userMsg);
369
+ } else if (message.role === "tool") {
370
+ let toolName = "unknown";
371
+ // Find the tool name from the corresponding tool call
372
+ for (const msg of messages) {
373
+ if (msg.role === "assistant") {
374
+ for (const toolCall of msg.toolCalls ?? []) {
375
+ if (toolCall.id === message.toolCallId) {
376
+ toolName = toolCall.function.name;
377
+ break;
378
+ }
379
+ }
380
+ }
381
+ }
382
+
383
+ const toolResultPart: ToolResultPart = {
384
+ type: "tool-result",
385
+ toolCallId: message.toolCallId,
386
+ toolName: toolName,
387
+ output: {
388
+ type: "text",
389
+ value: message.content,
390
+ },
391
+ };
392
+
393
+ const toolMsg: ToolModelMessage = {
394
+ role: "tool",
395
+ content: [toolResultPart],
396
+ };
397
+ result.push(toolMsg);
398
+ }
399
+ }
400
+
401
+ return result;
402
+ }
403
+
404
+ /**
405
+ * JSON Schema type definition
406
+ */
407
+ interface JsonSchema {
408
+ type: "object" | "string" | "number" | "integer" | "boolean" | "array";
409
+ description?: string;
410
+ properties?: Record<string, JsonSchema>;
411
+ required?: string[];
412
+ items?: JsonSchema;
413
+ enum?: string[];
414
+ }
415
+
416
+ /**
417
+ * Converts JSON Schema to Zod schema
418
+ */
419
+ export function convertJsonSchemaToZodSchema(
420
+ jsonSchema: JsonSchema,
421
+ required: boolean,
422
+ ): z.ZodSchema {
423
+ // Handle empty schemas {} (no input required) - treat as empty object
424
+ if (!jsonSchema.type) {
425
+ return required ? z.object({}) : z.object({}).optional();
426
+ }
427
+ if (jsonSchema.type === "object") {
428
+ const spec: { [key: string]: z.ZodSchema } = {};
429
+
430
+ if (!jsonSchema.properties || !Object.keys(jsonSchema.properties).length) {
431
+ return !required ? z.object(spec).optional() : z.object(spec);
432
+ }
433
+
434
+ for (const [key, value] of Object.entries(jsonSchema.properties)) {
435
+ spec[key] = convertJsonSchemaToZodSchema(
436
+ value,
437
+ jsonSchema.required ? jsonSchema.required.includes(key) : false,
438
+ );
439
+ }
440
+ const schema = z.object(spec).describe(jsonSchema.description ?? "");
441
+ return required ? schema : schema.optional();
442
+ } else if (jsonSchema.type === "string") {
443
+ if (jsonSchema.enum && jsonSchema.enum.length > 0) {
444
+ const schema = z
445
+ .enum(jsonSchema.enum as [string, ...string[]])
446
+ .describe(jsonSchema.description ?? "");
447
+ return required ? schema : schema.optional();
448
+ }
449
+ const schema = z.string().describe(jsonSchema.description ?? "");
450
+ return required ? schema : schema.optional();
451
+ } else if (jsonSchema.type === "number" || jsonSchema.type === "integer") {
452
+ const schema = z.number().describe(jsonSchema.description ?? "");
453
+ return required ? schema : schema.optional();
454
+ } else if (jsonSchema.type === "boolean") {
455
+ const schema = z.boolean().describe(jsonSchema.description ?? "");
456
+ return required ? schema : schema.optional();
457
+ } else if (jsonSchema.type === "array") {
458
+ if (!jsonSchema.items) {
459
+ throw new Error("Array type must have items property");
460
+ }
461
+ const itemSchema = convertJsonSchemaToZodSchema(jsonSchema.items, true);
462
+ const schema = z.array(itemSchema).describe(jsonSchema.description ?? "");
463
+ return required ? schema : schema.optional();
464
+ }
465
+ console.error("Invalid JSON schema:", JSON.stringify(jsonSchema, null, 2));
466
+ throw new Error("Invalid JSON schema");
467
+ }
468
+
469
+ /**
470
+ * Converts AG-UI tools to Vercel AI SDK ToolSet
471
+ */
472
+ function isJsonSchema(obj: unknown): obj is JsonSchema {
473
+ if (typeof obj !== "object" || obj === null) return false;
474
+ const schema = obj as Record<string, unknown>;
475
+ // Empty objects {} are valid JSON schemas (no input required)
476
+ if (Object.keys(schema).length === 0) return true;
477
+ return (
478
+ typeof schema.type === "string" &&
479
+ ["object", "string", "number", "integer", "boolean", "array"].includes(
480
+ schema.type,
481
+ )
482
+ );
483
+ }
484
+
485
+ export function convertToolsToVercelAITools(
486
+ tools: RunAgentInput["tools"],
487
+ ): ToolSet {
488
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
489
+ const result: Record<string, any> = {};
490
+
491
+ for (const tool of tools) {
492
+ if (!isJsonSchema(tool.parameters)) {
493
+ throw new Error(`Invalid JSON schema for tool ${tool.name}`);
494
+ }
495
+ const zodSchema = convertJsonSchemaToZodSchema(tool.parameters, true);
496
+ result[tool.name] = createVercelAISDKTool({
497
+ description: tool.description,
498
+ inputSchema: zodSchema,
499
+ });
500
+ }
501
+
502
+ return result;
503
+ }
504
+
505
+ /**
506
+ * Check whether a schema is a Zod schema by inspecting its Standard Schema vendor.
507
+ */
508
+ function isZodSchema(schema: StandardSchemaV1): boolean {
509
+ return schema["~standard"]?.vendor === "zod";
510
+ }
511
+
512
+ /**
513
+ * Converts ToolDefinition array to Vercel AI SDK ToolSet.
514
+ *
515
+ * For Zod schemas, passes them directly to the AI SDK (Zod satisfies FlexibleSchema).
516
+ * For non-Zod schemas, converts to JSON Schema via schemaToJsonSchema() and wraps
517
+ * with the AI SDK's jsonSchema() helper.
518
+ */
519
+ export function convertToolDefinitionsToVercelAITools(
520
+ tools: ToolDefinition[],
521
+ ): ToolSet {
522
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
523
+ const result: Record<string, any> = {};
524
+
525
+ for (const tool of tools) {
526
+ if (isZodSchema(tool.parameters)) {
527
+ // Zod schemas can be passed directly to AI SDK (satisfies FlexibleSchema)
528
+ result[tool.name] = createVercelAISDKTool({
529
+ description: tool.description,
530
+ inputSchema: tool.parameters as any,
531
+ execute: tool.execute,
532
+ });
533
+ } else {
534
+ // Non-Zod: convert to JSON Schema and wrap with AI SDK's jsonSchema()
535
+ const jsonSchemaObj = schemaToJsonSchema(tool.parameters);
536
+ result[tool.name] = createVercelAISDKTool({
537
+ description: tool.description,
538
+ inputSchema: aiJsonSchema(jsonSchemaObj),
539
+ execute: tool.execute,
540
+ });
541
+ }
542
+ }
543
+
544
+ return result;
545
+ }
546
+
547
+ /**
548
+ * Configuration for BuiltInAgent
549
+ */
550
+ export interface BuiltInAgentConfiguration {
551
+ /**
552
+ * The model to use
553
+ */
554
+ model: BuiltInAgentModel | LanguageModel;
555
+ /**
556
+ * API key for the model provider (OpenAI, Anthropic, Google)
557
+ * If not provided, falls back to environment variables:
558
+ * - OPENAI_API_KEY for OpenAI models
559
+ * - ANTHROPIC_API_KEY for Anthropic models
560
+ * - GOOGLE_API_KEY for Google models
561
+ */
562
+ apiKey?: string;
563
+ /**
564
+ * Maximum number of steps/iterations for tool calling (default: 1)
565
+ */
566
+ maxSteps?: number;
567
+ /**
568
+ * Tool choice setting - how tools are selected for execution (default: "auto")
569
+ */
570
+ toolChoice?: ToolChoice<Record<string, unknown>>;
571
+ /**
572
+ * Maximum number of tokens to generate
573
+ */
574
+ maxOutputTokens?: number;
575
+ /**
576
+ * Temperature setting (range depends on provider)
577
+ */
578
+ temperature?: number;
579
+ /**
580
+ * Nucleus sampling (topP)
581
+ */
582
+ topP?: number;
583
+ /**
584
+ * Top K sampling
585
+ */
586
+ topK?: number;
587
+ /**
588
+ * Presence penalty
589
+ */
590
+ presencePenalty?: number;
591
+ /**
592
+ * Frequency penalty
593
+ */
594
+ frequencyPenalty?: number;
595
+ /**
596
+ * Sequences that will stop the generation
597
+ */
598
+ stopSequences?: string[];
599
+ /**
600
+ * Seed for deterministic results
601
+ */
602
+ seed?: number;
603
+ /**
604
+ * Maximum number of retries
605
+ */
606
+ maxRetries?: number;
607
+ /**
608
+ * Prompt for the agent
609
+ */
610
+ prompt?: string;
611
+ /**
612
+ * List of properties that can be overridden by forwardedProps.
613
+ */
614
+ overridableProperties?: OverridableProperty[];
615
+ /**
616
+ * Optional list of MCP server configurations
617
+ */
618
+ mcpServers?: MCPClientConfig[];
619
+ /**
620
+ * Optional list of user-managed MCP clients.
621
+ * Unlike mcpServers, the agent does NOT create or close these clients.
622
+ * The user controls the lifecycle, persistence, auth, and caching.
623
+ *
624
+ * Compatible with @ai-sdk/mcp's createMCPClient() return type:
625
+ * ```typescript
626
+ * const client = await createMCPClient({ transport });
627
+ * const agent = new BuiltInAgent({ model: "...", mcpClients: [client] });
628
+ * ```
629
+ */
630
+ mcpClients?: MCPClientProvider[];
631
+ /**
632
+ * Optional tools available to the agent
633
+ */
634
+ tools?: ToolDefinition[];
635
+ /**
636
+ * Forward system-role messages from input to the LLM.
637
+ * Default: false
638
+ */
639
+ forwardSystemMessages?: boolean;
640
+ /**
641
+ * Forward developer-role messages from input to the LLM (as system messages).
642
+ * Default: false
643
+ */
644
+ forwardDeveloperMessages?: boolean;
645
+ /**
646
+ * Provider-specific options passed to the model (e.g., OpenAI reasoningEffort).
647
+ * Example: `{ openai: { reasoningEffort: "high" } }`
648
+ */
649
+ providerOptions?: Record<string, any>;
650
+ }
651
+
652
+ export class BuiltInAgent extends AbstractAgent {
653
+ private abortController?: AbortController;
654
+
655
+ constructor(private config: BuiltInAgentConfiguration) {
656
+ super();
657
+ }
658
+
659
+ /**
660
+ * Check if a property can be overridden by forwardedProps
661
+ */
662
+ canOverride(property: OverridableProperty): boolean {
663
+ return this.config?.overridableProperties?.includes(property) ?? false;
664
+ }
665
+
666
+ run(input: RunAgentInput): Observable<BaseEvent> {
667
+ return new Observable<BaseEvent>((subscriber) => {
668
+ // Emit RUN_STARTED event
669
+ const startEvent: RunStartedEvent = {
670
+ type: EventType.RUN_STARTED,
671
+ threadId: input.threadId,
672
+ runId: input.runId,
673
+ };
674
+ subscriber.next(startEvent);
675
+
676
+ // Resolve the model, passing API key if provided
677
+ const model = resolveModel(this.config.model, this.config.apiKey);
678
+
679
+ // Build prompt based on conditions
680
+ let systemPrompt: string | undefined = undefined;
681
+
682
+ // Check if we should build a prompt:
683
+ // - config.prompt is set, OR
684
+ // - input.context is non-empty, OR
685
+ // - input.state is non-empty and not an empty object
686
+ const hasPrompt = !!this.config.prompt;
687
+ const hasContext = input.context && input.context.length > 0;
688
+ const hasState =
689
+ input.state !== undefined &&
690
+ input.state !== null &&
691
+ !(
692
+ typeof input.state === "object" &&
693
+ Object.keys(input.state).length === 0
694
+ );
695
+
696
+ if (hasPrompt || hasContext || hasState) {
697
+ const parts: string[] = [];
698
+
699
+ // First: the prompt if any
700
+ if (hasPrompt) {
701
+ parts.push(this.config.prompt!);
702
+ }
703
+
704
+ // Second: context from the application
705
+ if (hasContext) {
706
+ parts.push("\n## Context from the application\n");
707
+ for (const ctx of input.context) {
708
+ parts.push(`${ctx.description}:\n${ctx.value}\n`);
709
+ }
710
+ }
711
+
712
+ // Third: state from the application that can be edited
713
+ if (hasState) {
714
+ parts.push(
715
+ "\n## Application State\n" +
716
+ "This is state from the application that you can edit by calling AGUISendStateSnapshot or AGUISendStateDelta.\n" +
717
+ `\`\`\`json\n${JSON.stringify(input.state, null, 2)}\n\`\`\`\n`,
718
+ );
719
+ }
720
+
721
+ systemPrompt = parts.join("");
722
+ }
723
+
724
+ // Convert messages and prepend system message if we have a prompt
725
+ const messages = convertMessagesToVercelAISDKMessages(input.messages, {
726
+ forwardSystemMessages: this.config.forwardSystemMessages,
727
+ forwardDeveloperMessages: this.config.forwardDeveloperMessages,
728
+ });
729
+ if (systemPrompt) {
730
+ messages.unshift({
731
+ role: "system",
732
+ content: systemPrompt,
733
+ });
734
+ }
735
+
736
+ // Merge tools from input and config
737
+ let allTools: ToolSet = convertToolsToVercelAITools(input.tools);
738
+ if (this.config.tools && this.config.tools.length > 0) {
739
+ const configTools = convertToolDefinitionsToVercelAITools(
740
+ this.config.tools,
741
+ );
742
+ allTools = { ...allTools, ...configTools };
743
+ }
744
+
745
+ const streamTextParams: Parameters<typeof streamText>[0] = {
746
+ model,
747
+ messages,
748
+ tools: allTools,
749
+ toolChoice: this.config.toolChoice,
750
+ stopWhen: this.config.maxSteps
751
+ ? stepCountIs(this.config.maxSteps)
752
+ : undefined,
753
+ maxOutputTokens: this.config.maxOutputTokens,
754
+ temperature: this.config.temperature,
755
+ topP: this.config.topP,
756
+ topK: this.config.topK,
757
+ presencePenalty: this.config.presencePenalty,
758
+ frequencyPenalty: this.config.frequencyPenalty,
759
+ stopSequences: this.config.stopSequences,
760
+ seed: this.config.seed,
761
+ providerOptions: this.config.providerOptions,
762
+ maxRetries: this.config.maxRetries,
763
+ };
764
+
765
+ // Apply forwardedProps overrides (if allowed)
766
+ if (input.forwardedProps && typeof input.forwardedProps === "object") {
767
+ const props = input.forwardedProps as Record<string, unknown>;
768
+
769
+ // Check and apply each overridable property
770
+ if (props.model !== undefined && this.canOverride("model")) {
771
+ if (
772
+ typeof props.model === "string" ||
773
+ typeof props.model === "object"
774
+ ) {
775
+ // Accept any string or LanguageModel instance for model override
776
+ // Use the configured API key when resolving overridden models
777
+ streamTextParams.model = resolveModel(
778
+ props.model as string | LanguageModel,
779
+ this.config.apiKey,
780
+ );
781
+ }
782
+ }
783
+ if (props.toolChoice !== undefined && this.canOverride("toolChoice")) {
784
+ // ToolChoice can be 'auto', 'required', 'none', or { type: 'tool', toolName: string }
785
+ const toolChoice = props.toolChoice;
786
+ if (
787
+ toolChoice === "auto" ||
788
+ toolChoice === "required" ||
789
+ toolChoice === "none" ||
790
+ (typeof toolChoice === "object" &&
791
+ toolChoice !== null &&
792
+ "type" in toolChoice &&
793
+ toolChoice.type === "tool")
794
+ ) {
795
+ streamTextParams.toolChoice = toolChoice as ToolChoice<
796
+ Record<string, unknown>
797
+ >;
798
+ }
799
+ }
800
+ if (
801
+ typeof props.maxOutputTokens === "number" &&
802
+ this.canOverride("maxOutputTokens")
803
+ ) {
804
+ streamTextParams.maxOutputTokens = props.maxOutputTokens;
805
+ }
806
+ if (
807
+ typeof props.temperature === "number" &&
808
+ this.canOverride("temperature")
809
+ ) {
810
+ streamTextParams.temperature = props.temperature;
811
+ }
812
+ if (typeof props.topP === "number" && this.canOverride("topP")) {
813
+ streamTextParams.topP = props.topP;
814
+ }
815
+ if (typeof props.topK === "number" && this.canOverride("topK")) {
816
+ streamTextParams.topK = props.topK;
817
+ }
818
+ if (
819
+ typeof props.presencePenalty === "number" &&
820
+ this.canOverride("presencePenalty")
821
+ ) {
822
+ streamTextParams.presencePenalty = props.presencePenalty;
823
+ }
824
+ if (
825
+ typeof props.frequencyPenalty === "number" &&
826
+ this.canOverride("frequencyPenalty")
827
+ ) {
828
+ streamTextParams.frequencyPenalty = props.frequencyPenalty;
829
+ }
830
+ if (
831
+ Array.isArray(props.stopSequences) &&
832
+ this.canOverride("stopSequences")
833
+ ) {
834
+ // Validate all elements are strings
835
+ if (
836
+ props.stopSequences.every(
837
+ (item): item is string => typeof item === "string",
838
+ )
839
+ ) {
840
+ streamTextParams.stopSequences = props.stopSequences;
841
+ }
842
+ }
843
+ if (typeof props.seed === "number" && this.canOverride("seed")) {
844
+ streamTextParams.seed = props.seed;
845
+ }
846
+ if (
847
+ typeof props.maxRetries === "number" &&
848
+ this.canOverride("maxRetries")
849
+ ) {
850
+ streamTextParams.maxRetries = props.maxRetries;
851
+ }
852
+ if (
853
+ props.providerOptions !== undefined &&
854
+ this.canOverride("providerOptions")
855
+ ) {
856
+ if (
857
+ typeof props.providerOptions === "object" &&
858
+ props.providerOptions !== null
859
+ ) {
860
+ streamTextParams.providerOptions = props.providerOptions as Record<
861
+ string,
862
+ any
863
+ >;
864
+ }
865
+ }
866
+ }
867
+
868
+ // Set up MCP clients if configured and process the stream
869
+ const mcpClients: Array<{ close: () => Promise<void> }> = [];
870
+
871
+ (async () => {
872
+ const abortController = new AbortController();
873
+ this.abortController = abortController;
874
+ let terminalEventEmitted = false;
875
+ let messageId = randomUUID();
876
+ let reasoningMessageId = randomUUID();
877
+ let isInReasoning = false;
878
+
879
+ // Auto-close an open reasoning lifecycle.
880
+ // Some AI SDK providers (notably @ai-sdk/anthropic) never emit "reasoning-end",
881
+ // which leaves downstream state machines stuck. This helper emits the
882
+ // missing REASONING_MESSAGE_END + REASONING_END events so the stream
883
+ // can transition to text, tool-call, or finish phases.
884
+ // Declared before try/catch so it is accessible in the catch block.
885
+ const closeReasoningIfOpen = () => {
886
+ if (!isInReasoning) return;
887
+ isInReasoning = false;
888
+ const reasoningMsgEnd: ReasoningMessageEndEvent = {
889
+ type: EventType.REASONING_MESSAGE_END,
890
+ messageId: reasoningMessageId,
891
+ };
892
+ subscriber.next(reasoningMsgEnd);
893
+ const reasoningEnd: ReasoningEndEvent = {
894
+ type: EventType.REASONING_END,
895
+ messageId: reasoningMessageId,
896
+ };
897
+ subscriber.next(reasoningEnd);
898
+ };
899
+
900
+ try {
901
+ // Add AG-UI state update tools
902
+ streamTextParams.tools = {
903
+ ...streamTextParams.tools,
904
+ AGUISendStateSnapshot: createVercelAISDKTool({
905
+ description:
906
+ "Replace the entire application state with a new snapshot",
907
+ inputSchema: z.object({
908
+ snapshot: z.any().describe("The complete new state object"),
909
+ }),
910
+ execute: async ({ snapshot }) => {
911
+ return { success: true, snapshot };
912
+ },
913
+ }),
914
+ AGUISendStateDelta: createVercelAISDKTool({
915
+ description:
916
+ "Apply incremental updates to application state using JSON Patch operations",
917
+ inputSchema: z.object({
918
+ delta: z
919
+ .array(
920
+ z.object({
921
+ op: z
922
+ .enum(["add", "replace", "remove"])
923
+ .describe("The operation to perform"),
924
+ path: z
925
+ .string()
926
+ .describe("JSON Pointer path (e.g., '/foo/bar')"),
927
+ value: z
928
+ .any()
929
+ .optional()
930
+ .describe(
931
+ "The value to set. Required for 'add' and 'replace' operations, ignored for 'remove'.",
932
+ ),
933
+ }),
934
+ )
935
+ .describe("Array of JSON Patch operations"),
936
+ }),
937
+ execute: async ({ delta }) => {
938
+ return { success: true, delta };
939
+ },
940
+ }),
941
+ };
942
+
943
+ // Merge tools from user-managed MCP clients (user controls lifecycle)
944
+ if (this.config.mcpClients && this.config.mcpClients.length > 0) {
945
+ for (const client of this.config.mcpClients) {
946
+ const mcpTools = await client.tools();
947
+ streamTextParams.tools = {
948
+ ...streamTextParams.tools,
949
+ ...mcpTools,
950
+ } as ToolSet;
951
+ }
952
+ }
953
+
954
+ // Initialize MCP clients and get their tools
955
+ if (this.config.mcpServers && this.config.mcpServers.length > 0) {
956
+ for (const serverConfig of this.config.mcpServers) {
957
+ let transport;
958
+
959
+ if (serverConfig.type === "http") {
960
+ const url = new URL(serverConfig.url);
961
+ transport = new StreamableHTTPClientTransport(
962
+ url,
963
+ serverConfig.options,
964
+ );
965
+ } else if (serverConfig.type === "sse") {
966
+ transport = new SSEClientTransport(
967
+ new URL(serverConfig.url),
968
+ serverConfig.headers,
969
+ );
970
+ }
971
+
972
+ if (transport) {
973
+ const mcpClient = await createMCPClient({ transport });
974
+ mcpClients.push(mcpClient);
975
+
976
+ // Get tools from this MCP server and merge with existing tools
977
+ const mcpTools = await mcpClient.tools();
978
+ streamTextParams.tools = {
979
+ ...streamTextParams.tools,
980
+ ...mcpTools,
981
+ } as ToolSet;
982
+ }
983
+ }
984
+ }
985
+
986
+ // Call streamText and process the stream
987
+ const response = streamText({
988
+ ...streamTextParams,
989
+ abortSignal: abortController.signal,
990
+ });
991
+
992
+ const toolCallStates = new Map<
993
+ string,
994
+ {
995
+ started: boolean;
996
+ hasArgsDelta: boolean;
997
+ ended: boolean;
998
+ toolName?: string;
999
+ }
1000
+ >();
1001
+
1002
+ const ensureToolCallState = (toolCallId: string) => {
1003
+ let state = toolCallStates.get(toolCallId);
1004
+ if (!state) {
1005
+ state = { started: false, hasArgsDelta: false, ended: false };
1006
+ toolCallStates.set(toolCallId, state);
1007
+ }
1008
+ return state;
1009
+ };
1010
+
1011
+ // Process fullStream events
1012
+ for await (const part of response.fullStream) {
1013
+ // Close any open reasoning lifecycle on every event except
1014
+ // reasoning-delta, which arrives mid-block and must not interrupt it.
1015
+ if (part.type !== "reasoning-delta") {
1016
+ closeReasoningIfOpen();
1017
+ }
1018
+
1019
+ switch (part.type) {
1020
+ case "abort": {
1021
+ const abortEndEvent: RunFinishedEvent = {
1022
+ type: EventType.RUN_FINISHED,
1023
+ threadId: input.threadId,
1024
+ runId: input.runId,
1025
+ };
1026
+ subscriber.next(abortEndEvent);
1027
+ terminalEventEmitted = true;
1028
+
1029
+ // Complete the observable
1030
+ subscriber.complete();
1031
+ break;
1032
+ }
1033
+ case "reasoning-start": {
1034
+ // Use SDK-provided id, or generate a fresh UUID if id is falsy/"0"
1035
+ // to prevent consecutive reasoning blocks from sharing a messageId
1036
+ const providedId = "id" in part ? part.id : undefined;
1037
+ reasoningMessageId =
1038
+ providedId && providedId !== "0"
1039
+ ? (providedId as typeof reasoningMessageId)
1040
+ : randomUUID();
1041
+ const reasoningStartEvent: ReasoningStartEvent = {
1042
+ type: EventType.REASONING_START,
1043
+ messageId: reasoningMessageId,
1044
+ };
1045
+ subscriber.next(reasoningStartEvent);
1046
+ const reasoningMessageStart: ReasoningMessageStartEvent = {
1047
+ type: EventType.REASONING_MESSAGE_START,
1048
+ messageId: reasoningMessageId,
1049
+ role: "reasoning",
1050
+ };
1051
+ subscriber.next(reasoningMessageStart);
1052
+ isInReasoning = true;
1053
+ break;
1054
+ }
1055
+ case "reasoning-delta": {
1056
+ const delta = part.text ?? "";
1057
+ if (!delta) break; // skip — @ag-ui/core schema requires delta to be non-empty
1058
+ const reasoningDeltaEvent: ReasoningMessageContentEvent = {
1059
+ type: EventType.REASONING_MESSAGE_CONTENT,
1060
+ messageId: reasoningMessageId,
1061
+ delta,
1062
+ };
1063
+ subscriber.next(reasoningDeltaEvent);
1064
+ break;
1065
+ }
1066
+ case "reasoning-end": {
1067
+ // closeReasoningIfOpen() already called before the switch — no-op here
1068
+ // if the SDK never emits this event (e.g. @ai-sdk/anthropic).
1069
+ break;
1070
+ }
1071
+ case "tool-input-start": {
1072
+ const toolCallId = part.id;
1073
+ const state = ensureToolCallState(toolCallId);
1074
+ state.toolName = part.toolName;
1075
+ if (!state.started) {
1076
+ state.started = true;
1077
+ const startEvent: ToolCallStartEvent = {
1078
+ type: EventType.TOOL_CALL_START,
1079
+ parentMessageId: messageId,
1080
+ toolCallId,
1081
+ toolCallName: part.toolName,
1082
+ };
1083
+ subscriber.next(startEvent);
1084
+ }
1085
+ break;
1086
+ }
1087
+
1088
+ case "tool-input-delta": {
1089
+ const toolCallId = part.id;
1090
+ const state = ensureToolCallState(toolCallId);
1091
+ state.hasArgsDelta = true;
1092
+ const argsEvent: ToolCallArgsEvent = {
1093
+ type: EventType.TOOL_CALL_ARGS,
1094
+ toolCallId,
1095
+ delta: part.delta,
1096
+ };
1097
+ subscriber.next(argsEvent);
1098
+ break;
1099
+ }
1100
+
1101
+ case "tool-input-end": {
1102
+ // No direct event – the subsequent "tool-call" part marks completion.
1103
+ break;
1104
+ }
1105
+
1106
+ case "text-start": {
1107
+ // New text message starting - use the SDK-provided id
1108
+ // Use randomUUID() if part.id is falsy or "0" to prevent message merging issues
1109
+ const providedId = "id" in part ? part.id : undefined;
1110
+ messageId =
1111
+ providedId && providedId !== "0"
1112
+ ? (providedId as typeof messageId)
1113
+ : randomUUID();
1114
+ break;
1115
+ }
1116
+
1117
+ case "text-delta": {
1118
+ // Accumulate text content - in AI SDK 5.0, the property is 'text'
1119
+ const textDelta = "text" in part ? part.text : "";
1120
+ // Emit text chunk event
1121
+ const textEvent: TextMessageChunkEvent = {
1122
+ type: EventType.TEXT_MESSAGE_CHUNK,
1123
+ role: "assistant",
1124
+ messageId,
1125
+ delta: textDelta,
1126
+ };
1127
+ subscriber.next(textEvent);
1128
+ break;
1129
+ }
1130
+
1131
+ case "tool-call": {
1132
+ const toolCallId = part.toolCallId;
1133
+ const state = ensureToolCallState(toolCallId);
1134
+ state.toolName = part.toolName ?? state.toolName;
1135
+
1136
+ if (!state.started) {
1137
+ state.started = true;
1138
+ const startEvent: ToolCallStartEvent = {
1139
+ type: EventType.TOOL_CALL_START,
1140
+ parentMessageId: messageId,
1141
+ toolCallId,
1142
+ toolCallName: part.toolName,
1143
+ };
1144
+ subscriber.next(startEvent);
1145
+ }
1146
+
1147
+ if (
1148
+ !state.hasArgsDelta &&
1149
+ "input" in part &&
1150
+ part.input !== undefined
1151
+ ) {
1152
+ let serializedInput = "";
1153
+ if (typeof part.input === "string") {
1154
+ serializedInput = part.input;
1155
+ } else {
1156
+ try {
1157
+ serializedInput = JSON.stringify(part.input);
1158
+ } catch {
1159
+ serializedInput = String(part.input);
1160
+ }
1161
+ }
1162
+
1163
+ if (serializedInput.length > 0) {
1164
+ const argsEvent: ToolCallArgsEvent = {
1165
+ type: EventType.TOOL_CALL_ARGS,
1166
+ toolCallId,
1167
+ delta: serializedInput,
1168
+ };
1169
+ subscriber.next(argsEvent);
1170
+ state.hasArgsDelta = true;
1171
+ }
1172
+ }
1173
+
1174
+ if (!state.ended) {
1175
+ state.ended = true;
1176
+ const endEvent: ToolCallEndEvent = {
1177
+ type: EventType.TOOL_CALL_END,
1178
+ toolCallId,
1179
+ };
1180
+ subscriber.next(endEvent);
1181
+ }
1182
+ break;
1183
+ }
1184
+
1185
+ case "tool-result": {
1186
+ const toolResult = "output" in part ? part.output : null;
1187
+ const toolName = "toolName" in part ? part.toolName : "";
1188
+ toolCallStates.delete(part.toolCallId);
1189
+
1190
+ // Check if this is a state update tool
1191
+ if (
1192
+ toolName === "AGUISendStateSnapshot" &&
1193
+ toolResult &&
1194
+ typeof toolResult === "object"
1195
+ ) {
1196
+ // Emit StateSnapshotEvent
1197
+ const stateSnapshotEvent: StateSnapshotEvent = {
1198
+ type: EventType.STATE_SNAPSHOT,
1199
+ snapshot: toolResult.snapshot,
1200
+ };
1201
+ subscriber.next(stateSnapshotEvent);
1202
+ } else if (
1203
+ toolName === "AGUISendStateDelta" &&
1204
+ toolResult &&
1205
+ typeof toolResult === "object"
1206
+ ) {
1207
+ // Emit StateDeltaEvent
1208
+ const stateDeltaEvent: StateDeltaEvent = {
1209
+ type: EventType.STATE_DELTA,
1210
+ delta: toolResult.delta,
1211
+ };
1212
+ subscriber.next(stateDeltaEvent);
1213
+ }
1214
+
1215
+ // Always emit the tool result event for the LLM
1216
+ const resultEvent: ToolCallResultEvent = {
1217
+ type: EventType.TOOL_CALL_RESULT,
1218
+ role: "tool",
1219
+ messageId: randomUUID(),
1220
+ toolCallId: part.toolCallId,
1221
+ content: JSON.stringify(toolResult),
1222
+ };
1223
+ subscriber.next(resultEvent);
1224
+ break;
1225
+ }
1226
+
1227
+ case "finish": {
1228
+ // Emit run finished event
1229
+ const finishedEvent: RunFinishedEvent = {
1230
+ type: EventType.RUN_FINISHED,
1231
+ threadId: input.threadId,
1232
+ runId: input.runId,
1233
+ };
1234
+ subscriber.next(finishedEvent);
1235
+ terminalEventEmitted = true;
1236
+
1237
+ // Complete the observable
1238
+ subscriber.complete();
1239
+ break;
1240
+ }
1241
+
1242
+ case "error": {
1243
+ if (abortController.signal.aborted) {
1244
+ break;
1245
+ }
1246
+ const runErrorEvent: RunErrorEvent = {
1247
+ type: EventType.RUN_ERROR,
1248
+ message: part.error + "",
1249
+ };
1250
+ subscriber.next(runErrorEvent);
1251
+ terminalEventEmitted = true;
1252
+
1253
+ // Handle error
1254
+ subscriber.error(part.error);
1255
+ break;
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ if (!terminalEventEmitted) {
1261
+ closeReasoningIfOpen();
1262
+ if (abortController.signal.aborted) {
1263
+ // Let the runner finalize the stream on stop requests so it can
1264
+ // inject consistent closing events and a RUN_FINISHED marker.
1265
+ } else {
1266
+ const finishedEvent: RunFinishedEvent = {
1267
+ type: EventType.RUN_FINISHED,
1268
+ threadId: input.threadId,
1269
+ runId: input.runId,
1270
+ };
1271
+ subscriber.next(finishedEvent);
1272
+ }
1273
+
1274
+ terminalEventEmitted = true;
1275
+ subscriber.complete();
1276
+ }
1277
+ } catch (error) {
1278
+ closeReasoningIfOpen();
1279
+ if (abortController.signal.aborted) {
1280
+ subscriber.complete();
1281
+ } else {
1282
+ const runErrorEvent: RunErrorEvent = {
1283
+ type: EventType.RUN_ERROR,
1284
+ message: error + "",
1285
+ };
1286
+ subscriber.next(runErrorEvent);
1287
+ terminalEventEmitted = true;
1288
+ subscriber.error(error);
1289
+ }
1290
+ } finally {
1291
+ this.abortController = undefined;
1292
+ await Promise.all(mcpClients.map((client) => client.close()));
1293
+ }
1294
+ })();
1295
+
1296
+ // Cleanup function
1297
+ return () => {
1298
+ // Cleanup MCP clients if stream is unsubscribed
1299
+ Promise.all(mcpClients.map((client) => client.close())).catch(() => {
1300
+ // Ignore cleanup errors
1301
+ });
1302
+ };
1303
+ });
1304
+ }
1305
+
1306
+ clone() {
1307
+ const cloned = new BuiltInAgent(this.config);
1308
+ // Copy middlewares from parent class
1309
+ // @ts-expect-error - accessing protected property from parent
1310
+ cloned.middlewares = [...this.middlewares];
1311
+ return cloned;
1312
+ }
1313
+
1314
+ abortRun(): void {
1315
+ this.abortController?.abort();
1316
+ }
1317
+ }
1318
+
1319
+ /**
1320
+ * @deprecated Use BuiltInAgent instead
1321
+ */
1322
+ export class BasicAgent extends BuiltInAgent {
1323
+ constructor(config: BuiltInAgentConfiguration) {
1324
+ super(config);
1325
+ console.warn("BasicAgent is deprecated, use BuiltInAgent instead");
1326
+ }
1327
+ }
1328
+
1329
+ export type BasicAgentConfiguration = BuiltInAgentConfiguration;