@copilotkit/runtime 1.57.3 → 1.58.0-canary.thread-id-propagation

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 (346) hide show
  1. package/dist/lib/observability.d.cts +1 -1
  2. package/dist/lib/observability.d.cts.map +1 -1
  3. package/dist/lib/observability.d.mts +1 -1
  4. package/dist/lib/observability.d.mts.map +1 -1
  5. package/dist/lib/runtime/copilot-runtime.cjs +2 -0
  6. package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
  7. package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
  8. package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
  9. package/dist/lib/runtime/copilot-runtime.mjs +2 -0
  10. package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
  11. package/dist/package.cjs +5 -8
  12. package/dist/package.mjs +5 -8
  13. package/dist/v2/runtime/core/runtime.cjs +4 -1
  14. package/dist/v2/runtime/core/runtime.cjs.map +1 -1
  15. package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
  16. package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
  17. package/dist/v2/runtime/core/runtime.mjs +4 -1
  18. package/dist/v2/runtime/core/runtime.mjs.map +1 -1
  19. package/dist/v2/runtime/handlers/get-runtime-info.cjs +1 -1
  20. package/dist/v2/runtime/handlers/get-runtime-info.mjs +1 -1
  21. package/dist/v2/runtime/handlers/handle-connect.cjs +1 -1
  22. package/dist/v2/runtime/handlers/handle-connect.mjs +1 -1
  23. package/dist/v2/runtime/handlers/handle-run.cjs +1 -1
  24. package/dist/v2/runtime/handlers/handle-run.mjs +1 -1
  25. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +1 -1
  26. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
  27. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +1 -1
  28. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
  29. package/dist/v2/runtime/telemetry/telemetry-client.cjs +22 -6
  30. package/dist/v2/runtime/telemetry/telemetry-client.cjs.map +1 -1
  31. package/dist/v2/runtime/telemetry/telemetry-client.mjs +27 -11
  32. package/dist/v2/runtime/telemetry/telemetry-client.mjs.map +1 -1
  33. package/package.json +9 -19
  34. package/skills/runtime/SKILL.md +98 -0
  35. package/skills/runtime/references/agent-runners-custom.md +161 -0
  36. package/skills/runtime/references/agent-runners-in-memory.md +64 -0
  37. package/skills/runtime/references/agent-runners-sqlite.md +90 -0
  38. package/skills/runtime/references/agent-runners.md +304 -0
  39. package/skills/runtime/references/built-in-agent-factory-modes.md +232 -0
  40. package/skills/runtime/references/built-in-agent-helper-utilities.md +123 -0
  41. package/skills/runtime/references/built-in-agent-model-identifiers.md +59 -0
  42. package/skills/runtime/references/built-in-agent.md +523 -0
  43. package/skills/runtime/references/intelligence-mode.md +336 -0
  44. package/skills/runtime/references/middleware.md +376 -0
  45. package/skills/runtime/references/server-side-tools.md +414 -0
  46. package/skills/runtime/references/setup-endpoint.md +503 -0
  47. package/skills/runtime/references/transcription.md +287 -0
  48. package/skills/runtime/references/wiring-a2a.md +40 -0
  49. package/skills/runtime/references/wiring-adk.md +45 -0
  50. package/skills/runtime/references/wiring-ag2.md +41 -0
  51. package/skills/runtime/references/wiring-agno.md +39 -0
  52. package/skills/runtime/references/wiring-aws-strands.md +59 -0
  53. package/skills/runtime/references/wiring-crewai-crews.md +51 -0
  54. package/skills/runtime/references/wiring-crewai-flows.md +45 -0
  55. package/skills/runtime/references/wiring-external-agents.md +348 -0
  56. package/skills/runtime/references/wiring-langgraph.md +50 -0
  57. package/skills/runtime/references/wiring-llamaindex.md +39 -0
  58. package/skills/runtime/references/wiring-mastra.md +70 -0
  59. package/skills/runtime/references/wiring-mcp-apps-middleware.md +68 -0
  60. package/skills/runtime/references/wiring-ms-agent-framework.md +41 -0
  61. package/skills/runtime/references/wiring-pydantic-ai.md +45 -0
  62. package/CHANGELOG.md +0 -3624
  63. package/__snapshots__/schema/schema.graphql +0 -371
  64. package/dist/v2/runtime/telemetry/scarf-client.cjs +0 -32
  65. package/dist/v2/runtime/telemetry/scarf-client.cjs.map +0 -1
  66. package/dist/v2/runtime/telemetry/scarf-client.mjs +0 -32
  67. package/dist/v2/runtime/telemetry/scarf-client.mjs.map +0 -1
  68. package/scripts/generate-gql-schema.ts +0 -16
  69. package/src/agent/__tests__/agent-test-helpers.ts +0 -476
  70. package/src/agent/__tests__/agent.test.ts +0 -593
  71. package/src/agent/__tests__/ai-sdk-v6-compat.test.ts +0 -116
  72. package/src/agent/__tests__/basic-agent.test.ts +0 -1698
  73. package/src/agent/__tests__/capabilities.test.ts +0 -81
  74. package/src/agent/__tests__/config-tools-execution.test.ts +0 -516
  75. package/src/agent/__tests__/converter-aisdk.test.ts +0 -692
  76. package/src/agent/__tests__/converter-custom.test.ts +0 -319
  77. package/src/agent/__tests__/converter-tanstack-input.test.ts +0 -211
  78. package/src/agent/__tests__/converter-tanstack.test.ts +0 -594
  79. package/src/agent/__tests__/mcp-clients.test.ts +0 -246
  80. package/src/agent/__tests__/mcp-servers-integration.test.ts +0 -373
  81. package/src/agent/__tests__/multimodal-tanstack.test.ts +0 -284
  82. package/src/agent/__tests__/multimodal.test.ts +0 -176
  83. package/src/agent/__tests__/property-overrides.test.ts +0 -598
  84. package/src/agent/__tests__/provider-id-collision.test.ts +0 -195
  85. package/src/agent/__tests__/standard-schema-tools.test.ts +0 -313
  86. package/src/agent/__tests__/standard-schema-types.test.ts +0 -158
  87. package/src/agent/__tests__/state-tools.test.ts +0 -436
  88. package/src/agent/__tests__/test-helpers.ts +0 -197
  89. package/src/agent/__tests__/utils.test.ts +0 -536
  90. package/src/agent/__tests__/zod-regression.test.ts +0 -350
  91. package/src/agent/converters/aisdk.ts +0 -326
  92. package/src/agent/converters/index.ts +0 -7
  93. package/src/agent/converters/tanstack.ts +0 -451
  94. package/src/agent/index.ts +0 -1743
  95. package/src/agents/langgraph/__tests__/event-source.test.ts +0 -256
  96. package/src/agents/langgraph/event-source.ts +0 -365
  97. package/src/agents/langgraph/events.ts +0 -394
  98. package/src/graphql/inputs/action.input.ts +0 -16
  99. package/src/graphql/inputs/agent-session.input.ts +0 -13
  100. package/src/graphql/inputs/agent-state.input.ts +0 -13
  101. package/src/graphql/inputs/cloud-guardrails.input.ts +0 -16
  102. package/src/graphql/inputs/cloud.input.ts +0 -8
  103. package/src/graphql/inputs/context-property.input.ts +0 -10
  104. package/src/graphql/inputs/copilot-context.input.ts +0 -10
  105. package/src/graphql/inputs/custom-property.input.ts +0 -15
  106. package/src/graphql/inputs/extensions.input.ts +0 -21
  107. package/src/graphql/inputs/forwarded-parameters.input.ts +0 -22
  108. package/src/graphql/inputs/frontend.input.ts +0 -14
  109. package/src/graphql/inputs/generate-copilot-response.input.ts +0 -59
  110. package/src/graphql/inputs/load-agent-state.input.ts +0 -10
  111. package/src/graphql/inputs/message.input.ts +0 -110
  112. package/src/graphql/inputs/meta-event.input.ts +0 -18
  113. package/src/graphql/message-conversion/agui-to-gql.test.ts +0 -1384
  114. package/src/graphql/message-conversion/agui-to-gql.ts +0 -384
  115. package/src/graphql/message-conversion/gql-to-agui.test.ts +0 -1653
  116. package/src/graphql/message-conversion/gql-to-agui.ts +0 -297
  117. package/src/graphql/message-conversion/index.ts +0 -2
  118. package/src/graphql/message-conversion/roundtrip-conversion.test.ts +0 -561
  119. package/src/graphql/resolvers/__tests__/resolve-message-id.test.ts +0 -25
  120. package/src/graphql/resolvers/copilot.resolver.ts +0 -785
  121. package/src/graphql/resolvers/resolve-message-id.ts +0 -14
  122. package/src/graphql/resolvers/state.resolver.ts +0 -30
  123. package/src/graphql/types/agents-response.type.ts +0 -19
  124. package/src/graphql/types/base/index.ts +0 -10
  125. package/src/graphql/types/converted/index.ts +0 -183
  126. package/src/graphql/types/copilot-response.type.ts +0 -141
  127. package/src/graphql/types/enums.ts +0 -38
  128. package/src/graphql/types/extensions-response.type.ts +0 -23
  129. package/src/graphql/types/guardrails-result.type.ts +0 -20
  130. package/src/graphql/types/load-agent-state-response.type.ts +0 -17
  131. package/src/graphql/types/message-status.type.ts +0 -48
  132. package/src/graphql/types/meta-events.type.ts +0 -78
  133. package/src/graphql/types/response-status.type.ts +0 -77
  134. package/src/index.ts +0 -3
  135. package/src/langgraph.ts +0 -1
  136. package/src/lib/__tests__/telemetry-disclosure.test.ts +0 -55
  137. package/src/lib/cloud/index.ts +0 -4
  138. package/src/lib/error-messages.ts +0 -211
  139. package/src/lib/index.ts +0 -52
  140. package/src/lib/integrations/index.ts +0 -6
  141. package/src/lib/integrations/nest/index.ts +0 -21
  142. package/src/lib/integrations/nextjs/app-router.ts +0 -47
  143. package/src/lib/integrations/nextjs/pages-router.ts +0 -45
  144. package/src/lib/integrations/node-express/index.ts +0 -21
  145. package/src/lib/integrations/node-http/__tests__/request-duck-type.test.ts +0 -66
  146. package/src/lib/integrations/node-http/index.ts +0 -187
  147. package/src/lib/integrations/node-http/request-handler.ts +0 -128
  148. package/src/lib/integrations/shared.ts +0 -112
  149. package/src/lib/logger.ts +0 -31
  150. package/src/lib/observability.ts +0 -167
  151. package/src/lib/runtime/__tests__/copilot-runtime-error.test.ts +0 -183
  152. package/src/lib/runtime/__tests__/handle-service-adapter.test.ts +0 -108
  153. package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +0 -499
  154. package/src/lib/runtime/__tests__/on-after-request.test.ts +0 -122
  155. package/src/lib/runtime/__tests__/retry-utils.test.ts +0 -137
  156. package/src/lib/runtime/__tests__/v1-agent-factory.test.ts +0 -109
  157. package/src/lib/runtime/agent-integrations/langgraph/__tests__/dispatch-event-filtering.test.ts +0 -345
  158. package/src/lib/runtime/agent-integrations/langgraph/__tests__/run-message-filtering.test.ts +0 -156
  159. package/src/lib/runtime/agent-integrations/langgraph/agent.ts +0 -263
  160. package/src/lib/runtime/agent-integrations/langgraph/consts.ts +0 -37
  161. package/src/lib/runtime/agent-integrations/langgraph/index.ts +0 -2
  162. package/src/lib/runtime/copilot-runtime.ts +0 -863
  163. package/src/lib/runtime/mcp-tools-utils.ts +0 -313
  164. package/src/lib/runtime/retry-utils.ts +0 -141
  165. package/src/lib/runtime/telemetry-agent-runner.ts +0 -151
  166. package/src/lib/runtime/types.ts +0 -48
  167. package/src/lib/runtime/utils.ts +0 -93
  168. package/src/lib/streaming.ts +0 -220
  169. package/src/lib/telemetry-client.ts +0 -66
  170. package/src/lib/telemetry-disclosure.ts +0 -53
  171. package/src/service-adapters/anthropic/anthropic-adapter.ts +0 -532
  172. package/src/service-adapters/anthropic/utils.ts +0 -219
  173. package/src/service-adapters/bedrock/bedrock-adapter.ts +0 -73
  174. package/src/service-adapters/conversion.test.ts +0 -56
  175. package/src/service-adapters/conversion.ts +0 -69
  176. package/src/service-adapters/empty/empty-adapter.ts +0 -38
  177. package/src/service-adapters/events.ts +0 -337
  178. package/src/service-adapters/experimental/ollama/ollama-adapter.ts +0 -84
  179. package/src/service-adapters/google/google-genai-adapter.test.ts +0 -151
  180. package/src/service-adapters/google/google-genai-adapter.ts +0 -95
  181. package/src/service-adapters/groq/groq-adapter.ts +0 -229
  182. package/src/service-adapters/index.ts +0 -18
  183. package/src/service-adapters/langchain/langchain-adapter.ts +0 -113
  184. package/src/service-adapters/langchain/langserve.ts +0 -88
  185. package/src/service-adapters/langchain/types.ts +0 -20
  186. package/src/service-adapters/langchain/utils.ts +0 -330
  187. package/src/service-adapters/openai/__tests__/openai-v5-compat.test.ts +0 -177
  188. package/src/service-adapters/openai/openai-adapter.ts +0 -324
  189. package/src/service-adapters/openai/openai-assistant-adapter.ts +0 -385
  190. package/src/service-adapters/openai/utils.ts +0 -305
  191. package/src/service-adapters/service-adapter.ts +0 -50
  192. package/src/service-adapters/shared/error-utils.ts +0 -64
  193. package/src/service-adapters/shared/index.ts +0 -2
  194. package/src/service-adapters/shared/sdk-client-utils.ts +0 -19
  195. package/src/service-adapters/unify/unify-adapter.ts +0 -165
  196. package/src/utils/failed-response-status-reasons.ts +0 -70
  197. package/src/utils/index.ts +0 -1
  198. package/src/v2/express.ts +0 -1
  199. package/src/v2/hono.ts +0 -1
  200. package/src/v2/index.ts +0 -5
  201. package/src/v2/node.ts +0 -1
  202. package/src/v2/runtime/__tests__/agents-factory.test.ts +0 -136
  203. package/src/v2/runtime/__tests__/backward-compat.test.ts +0 -261
  204. package/src/v2/runtime/__tests__/code-review-fixes.test.ts +0 -500
  205. package/src/v2/runtime/__tests__/cors-credentials.test.ts +0 -320
  206. package/src/v2/runtime/__tests__/debug-sse-response.test.ts +0 -302
  207. package/src/v2/runtime/__tests__/express-adapter.test.ts +0 -188
  208. package/src/v2/runtime/__tests__/express-body-order.test.ts +0 -76
  209. package/src/v2/runtime/__tests__/express-fetch-bridge.test.ts +0 -344
  210. package/src/v2/runtime/__tests__/express-single-sse.test.ts +0 -122
  211. package/src/v2/runtime/__tests__/express-single-telemetry.integration.test.ts +0 -65
  212. package/src/v2/runtime/__tests__/express-telemetry.integration.test.ts +0 -101
  213. package/src/v2/runtime/__tests__/fetch-cors.test.ts +0 -205
  214. package/src/v2/runtime/__tests__/fetch-handler-validation.test.ts +0 -440
  215. package/src/v2/runtime/__tests__/fetch-handler.test.ts +0 -456
  216. package/src/v2/runtime/__tests__/fetch-router.test.ts +0 -276
  217. package/src/v2/runtime/__tests__/get-runtime-info.test.ts +0 -335
  218. package/src/v2/runtime/__tests__/handle-connect.test.ts +0 -585
  219. package/src/v2/runtime/__tests__/handle-run.test.ts +0 -1388
  220. package/src/v2/runtime/__tests__/handle-threads.test.ts +0 -930
  221. package/src/v2/runtime/__tests__/handle-transcribe.test.ts +0 -301
  222. package/src/v2/runtime/__tests__/header-utils.test.ts +0 -88
  223. package/src/v2/runtime/__tests__/hono-adapter.test.ts +0 -150
  224. package/src/v2/runtime/__tests__/hono-single-telemetry.integration.test.ts +0 -46
  225. package/src/v2/runtime/__tests__/hono-telemetry.integration.test.ts +0 -99
  226. package/src/v2/runtime/__tests__/hooks-edge-cases.test.ts +0 -457
  227. package/src/v2/runtime/__tests__/hooks.test.ts +0 -557
  228. package/src/v2/runtime/__tests__/in-process-agent-runner-messages.test.ts +0 -230
  229. package/src/v2/runtime/__tests__/in-process-agent-runner.test.ts +0 -1030
  230. package/src/v2/runtime/__tests__/integration/bun/bun-servers.integration.test.ts +0 -27
  231. package/src/v2/runtime/__tests__/integration/bun/elysia-multi.ts +0 -32
  232. package/src/v2/runtime/__tests__/integration/bun/elysia-single.ts +0 -33
  233. package/src/v2/runtime/__tests__/integration/bun/hono-bun-multi.ts +0 -25
  234. package/src/v2/runtime/__tests__/integration/bun/hono-bun-single.ts +0 -32
  235. package/src/v2/runtime/__tests__/integration/helpers/create-test-runtime.ts +0 -15
  236. package/src/v2/runtime/__tests__/integration/helpers/sse-reader.ts +0 -45
  237. package/src/v2/runtime/__tests__/integration/helpers/test-agent.ts +0 -58
  238. package/src/v2/runtime/__tests__/integration/node-servers.integration.test.ts +0 -58
  239. package/src/v2/runtime/__tests__/integration/servers/express-multi.ts +0 -35
  240. package/src/v2/runtime/__tests__/integration/servers/express-single.ts +0 -36
  241. package/src/v2/runtime/__tests__/integration/servers/fetch-direct.ts +0 -39
  242. package/src/v2/runtime/__tests__/integration/servers/hono-multi.ts +0 -30
  243. package/src/v2/runtime/__tests__/integration/servers/hono-single.ts +0 -37
  244. package/src/v2/runtime/__tests__/integration/servers/node-multi.ts +0 -45
  245. package/src/v2/runtime/__tests__/integration/servers/node-single.ts +0 -46
  246. package/src/v2/runtime/__tests__/integration/servers/types.ts +0 -18
  247. package/src/v2/runtime/__tests__/integration/suites/debug-events.suite.ts +0 -253
  248. package/src/v2/runtime/__tests__/integration/suites/multi-endpoint.suite.ts +0 -358
  249. package/src/v2/runtime/__tests__/integration/suites/single-endpoint.suite.ts +0 -363
  250. package/src/v2/runtime/__tests__/intelligence-run-telemetry.test.ts +0 -194
  251. package/src/v2/runtime/__tests__/mcp-apps-middleware-integration.test.ts +0 -275
  252. package/src/v2/runtime/__tests__/middleware-express.test.ts +0 -208
  253. package/src/v2/runtime/__tests__/middleware-single-express.test.ts +0 -213
  254. package/src/v2/runtime/__tests__/middleware-single.test.ts +0 -225
  255. package/src/v2/runtime/__tests__/middleware-sse-parser.test.ts +0 -237
  256. package/src/v2/runtime/__tests__/middleware.test.ts +0 -250
  257. package/src/v2/runtime/__tests__/node-fetch-handler.test.ts +0 -157
  258. package/src/v2/runtime/__tests__/open-generative-ui-middleware.e2e.test.ts +0 -728
  259. package/src/v2/runtime/__tests__/router-edge-cases.test.ts +0 -217
  260. package/src/v2/runtime/__tests__/routing-express.test.ts +0 -174
  261. package/src/v2/runtime/__tests__/routing-single-express.test.ts +0 -168
  262. package/src/v2/runtime/__tests__/routing-single.test.ts +0 -193
  263. package/src/v2/runtime/__tests__/routing.test.ts +0 -257
  264. package/src/v2/runtime/__tests__/runtime.test.ts +0 -234
  265. package/src/v2/runtime/__tests__/sse-response-telemetry.test.ts +0 -108
  266. package/src/v2/runtime/__tests__/telemetry.test.ts +0 -167
  267. package/src/v2/runtime/__tests__/thread-names.test.ts +0 -188
  268. package/src/v2/runtime/core/__tests__/debug-event-bus.test.ts +0 -156
  269. package/src/v2/runtime/core/debug-event-bus.ts +0 -45
  270. package/src/v2/runtime/core/fetch-cors.ts +0 -136
  271. package/src/v2/runtime/core/fetch-handler.ts +0 -492
  272. package/src/v2/runtime/core/fetch-router.ts +0 -203
  273. package/src/v2/runtime/core/hooks.ts +0 -160
  274. package/src/v2/runtime/core/middleware-sse-parser.ts +0 -210
  275. package/src/v2/runtime/core/middleware.ts +0 -115
  276. package/src/v2/runtime/core/runtime.ts +0 -432
  277. package/src/v2/runtime/endpoints/express-fetch-bridge.ts +0 -137
  278. package/src/v2/runtime/endpoints/express-single.ts +0 -54
  279. package/src/v2/runtime/endpoints/express.ts +0 -179
  280. package/src/v2/runtime/endpoints/hono-single.ts +0 -60
  281. package/src/v2/runtime/endpoints/hono.ts +0 -89
  282. package/src/v2/runtime/endpoints/index.ts +0 -4
  283. package/src/v2/runtime/endpoints/node-fetch-handler.ts +0 -48
  284. package/src/v2/runtime/endpoints/node.ts +0 -28
  285. package/src/v2/runtime/endpoints/single-route-helpers.ts +0 -125
  286. package/src/v2/runtime/express.ts +0 -2
  287. package/src/v2/runtime/handlers/__tests__/handle-debug-events.test.ts +0 -176
  288. package/src/v2/runtime/handlers/get-runtime-info.ts +0 -101
  289. package/src/v2/runtime/handlers/handle-connect.ts +0 -80
  290. package/src/v2/runtime/handlers/handle-debug-events.ts +0 -52
  291. package/src/v2/runtime/handlers/handle-run.ts +0 -111
  292. package/src/v2/runtime/handlers/handle-stop.ts +0 -77
  293. package/src/v2/runtime/handlers/handle-threads.ts +0 -11
  294. package/src/v2/runtime/handlers/handle-transcribe.ts +0 -269
  295. package/src/v2/runtime/handlers/header-utils.ts +0 -24
  296. package/src/v2/runtime/handlers/intelligence/connect.ts +0 -102
  297. package/src/v2/runtime/handlers/intelligence/run.ts +0 -351
  298. package/src/v2/runtime/handlers/intelligence/thread-names.ts +0 -246
  299. package/src/v2/runtime/handlers/intelligence/threads.ts +0 -420
  300. package/src/v2/runtime/handlers/shared/agent-utils.ts +0 -154
  301. package/src/v2/runtime/handlers/shared/intelligence-utils.ts +0 -41
  302. package/src/v2/runtime/handlers/shared/json-response.ts +0 -9
  303. package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +0 -28
  304. package/src/v2/runtime/handlers/shared/sse-response.ts +0 -215
  305. package/src/v2/runtime/handlers/sse/__tests__/sse-connect-agent-id.test.ts +0 -71
  306. package/src/v2/runtime/handlers/sse/connect.ts +0 -30
  307. package/src/v2/runtime/handlers/sse/run.ts +0 -40
  308. package/src/v2/runtime/hono.ts +0 -2
  309. package/src/v2/runtime/index.ts +0 -51
  310. package/src/v2/runtime/intelligence-platform/__tests__/client.test.ts +0 -601
  311. package/src/v2/runtime/intelligence-platform/__tests__/intelligence-mcp-helper.test.ts +0 -246
  312. package/src/v2/runtime/intelligence-platform/client.ts +0 -818
  313. package/src/v2/runtime/intelligence-platform/index.ts +0 -10
  314. package/src/v2/runtime/node.ts +0 -6
  315. package/src/v2/runtime/open-generative-ui-middleware.ts +0 -373
  316. package/src/v2/runtime/runner/__tests__/finalize-events.test.ts +0 -109
  317. package/src/v2/runtime/runner/__tests__/in-memory-runner.e2e.test.ts +0 -775
  318. package/src/v2/runtime/runner/__tests__/in-memory-runner.test.ts +0 -777
  319. package/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts +0 -1039
  320. package/src/v2/runtime/runner/agent-runner.ts +0 -35
  321. package/src/v2/runtime/runner/in-memory.ts +0 -467
  322. package/src/v2/runtime/runner/index.ts +0 -4
  323. package/src/v2/runtime/runner/intelligence.ts +0 -498
  324. package/src/v2/runtime/telemetry/__tests__/instance-created.test.ts +0 -96
  325. package/src/v2/runtime/telemetry/events.ts +0 -35
  326. package/src/v2/runtime/telemetry/index.ts +0 -7
  327. package/src/v2/runtime/telemetry/instance-created.ts +0 -44
  328. package/src/v2/runtime/telemetry/scarf-client.ts +0 -39
  329. package/src/v2/runtime/telemetry/telemetry-client.ts +0 -70
  330. package/src/v2/runtime/transcription-service/transcription-service.ts +0 -11
  331. package/tests/global.d.ts +0 -1
  332. package/tests/service-adapters/anthropic/allowlist-approach.test.ts +0 -259
  333. package/tests/service-adapters/anthropic/anthropic-adapter-language-model.test.ts +0 -101
  334. package/tests/service-adapters/anthropic/anthropic-adapter.test.ts +0 -645
  335. package/tests/service-adapters/anthropic/utils-token-trimming.test.ts +0 -301
  336. package/tests/service-adapters/groq/groq-adapter-language-model.test.ts +0 -102
  337. package/tests/service-adapters/openai/allowlist-approach.test.ts +0 -294
  338. package/tests/service-adapters/openai/openai-adapter-language-model.test.ts +0 -122
  339. package/tests/service-adapters/openai/openai-adapter.test.ts +0 -291
  340. package/tests/service-adapters/shared/sdk-client-utils.test.ts +0 -36
  341. package/tests/setup.vitest.ts +0 -8
  342. package/tests/tsconfig.json +0 -10
  343. package/tsconfig.json +0 -20
  344. package/tsdown.config.ts +0 -45
  345. package/typedoc.json +0 -4
  346. package/vitest.config.mjs +0 -13
@@ -1,1743 +0,0 @@
1
- import type {
2
- BaseEvent,
3
- RunAgentInput,
4
- Message,
5
- ReasoningEndEvent,
6
- ReasoningMessageContentEvent,
7
- ReasoningMessageEndEvent,
8
- ReasoningMessageStartEvent,
9
- ReasoningStartEvent,
10
- RunFinishedEvent,
11
- RunStartedEvent,
12
- TextMessageChunkEvent,
13
- ToolCallArgsEvent,
14
- ToolCallEndEvent,
15
- ToolCallStartEvent,
16
- ToolCallResultEvent,
17
- RunErrorEvent,
18
- StateSnapshotEvent,
19
- StateDeltaEvent,
20
- } from "@ag-ui/client";
21
- import { AbstractAgent, EventType } from "@ag-ui/client";
22
- import type { AgentCapabilities } from "@ag-ui/core";
23
- import type {
24
- LanguageModel,
25
- ModelMessage,
26
- AssistantModelMessage,
27
- UserModelMessage,
28
- ToolModelMessage,
29
- SystemModelMessage,
30
- ToolCallPart,
31
- ToolResultPart,
32
- TextPart,
33
- ImagePart,
34
- FilePart,
35
- ToolChoice,
36
- ToolSet,
37
- } from "ai";
38
- import { streamText, tool as createVercelAISDKTool, stepCountIs } from "ai";
39
- import { createMCPClient } from "@ai-sdk/mcp";
40
- import type { MCPClient } from "@ai-sdk/mcp";
41
- import { Observable } from "rxjs";
42
- import { createOpenAI } from "@ai-sdk/openai";
43
- import { createAnthropic } from "@ai-sdk/anthropic";
44
- import { createGoogleGenerativeAI } from "@ai-sdk/google";
45
- import { createVertex } from "@ai-sdk/google-vertex";
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 { convertAISDKStream } from "./converters/aisdk";
52
- import { convertTanStackStream } from "./converters/tanstack";
53
- import type { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
54
- import { INTELLIGENCE_USER_ID_HEADER } from "../v2/runtime/intelligence-platform/client";
55
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
56
- import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
57
- import { randomUUID } from "@copilotkit/shared";
58
-
59
- /**
60
- * Properties that can be overridden by forwardedProps
61
- * These match the exact parameter names in streamText
62
- */
63
- export type OverridableProperty =
64
- | "model"
65
- | "toolChoice"
66
- | "maxOutputTokens"
67
- | "temperature"
68
- | "topP"
69
- | "topK"
70
- | "presencePenalty"
71
- | "frequencyPenalty"
72
- | "stopSequences"
73
- | "seed"
74
- | "maxRetries"
75
- | "prompt"
76
- | "providerOptions";
77
-
78
- /**
79
- * Supported model identifiers for BuiltInAgent
80
- */
81
- export type BuiltInAgentModel =
82
- // OpenAI models
83
- | "openai/gpt-5"
84
- | "openai/gpt-5-mini"
85
- | "openai/gpt-4.1"
86
- | "openai/gpt-4.1-mini"
87
- | "openai/gpt-4.1-nano"
88
- | "openai/gpt-4o"
89
- | "openai/gpt-4o-mini"
90
- // OpenAI reasoning series
91
- | "openai/o3"
92
- | "openai/o3-mini"
93
- | "openai/o4-mini"
94
- // Anthropic (Claude) models
95
- | "anthropic/claude-sonnet-4.5"
96
- | "anthropic/claude-sonnet-4"
97
- | "anthropic/claude-3.7-sonnet"
98
- | "anthropic/claude-opus-4.1"
99
- | "anthropic/claude-opus-4"
100
- | "anthropic/claude-3.5-haiku"
101
- // Google (Gemini) models
102
- | "google/gemini-2.5-pro"
103
- | "google/gemini-2.5-flash"
104
- | "google/gemini-2.5-flash-lite"
105
- // Allow any LanguageModel instance
106
- | (string & {});
107
-
108
- /**
109
- * Model specifier - can be a string like "openai/gpt-4o" or a LanguageModel instance
110
- */
111
- export type ModelSpecifier = string | LanguageModel;
112
-
113
- /**
114
- * MCP Client configuration for HTTP transport
115
- */
116
- export interface MCPClientConfigHTTP {
117
- /** Type of MCP client */
118
- type: "http";
119
- /** URL of the MCP server */
120
- url: string;
121
- /**
122
- * Optional transport options for the underlying
123
- * `StreamableHTTPClientTransport`. The SDK's documented extension point
124
- * for per-request customization is `options.fetch` — pass a wrapped fetch
125
- * here if you need static + dynamic headers on outbound MCP requests.
126
- */
127
- options?: StreamableHTTPClientTransportOptions;
128
- }
129
-
130
- /**
131
- * MCP Client configuration for SSE transport
132
- */
133
- export interface MCPClientConfigSSE {
134
- /** Type of MCP client */
135
- type: "sse";
136
- /** URL of the MCP server */
137
- url: string;
138
- /** Optional HTTP headers (e.g., for authentication) */
139
- headers?: Record<string, string>;
140
- }
141
-
142
- /**
143
- * MCP Client configuration
144
- */
145
- export type MCPClientConfig = MCPClientConfigHTTP | MCPClientConfigSSE;
146
-
147
- /**
148
- * A user-managed MCP client that provides tools to the agent.
149
- * The user is responsible for creating, configuring, and closing the client.
150
- * Compatible with the return type of @ai-sdk/mcp's createMCPClient().
151
- *
152
- * Unlike mcpServers, the agent does NOT create or close these clients.
153
- * This allows persistent connections, custom auth, and tool caching.
154
- */
155
- export interface MCPClientProvider {
156
- /** Return tools to be merged into the agent's tool set. */
157
- tools(): Promise<ToolSet>;
158
- }
159
-
160
- /**
161
- * Resolves a model specifier to a LanguageModel instance
162
- * @param spec - Model string (e.g., "openai/gpt-4o") or LanguageModel instance
163
- * @param apiKey - Optional API key to use instead of environment variables
164
- * @returns LanguageModel instance
165
- */
166
- export function resolveModel(
167
- spec: ModelSpecifier,
168
- apiKey?: string,
169
- ): LanguageModel {
170
- // If already a LanguageModel instance, pass through
171
- if (typeof spec !== "string") {
172
- return spec;
173
- }
174
-
175
- // Normalize "provider/model" or "provider:model" format
176
- const normalized = spec.replace("/", ":").trim();
177
- const parts = normalized.split(":");
178
- const rawProvider = parts[0];
179
- const rest = parts.slice(1);
180
-
181
- if (!rawProvider) {
182
- throw new Error(
183
- `Invalid model string "${spec}". Use "openai/gpt-5", "anthropic/claude-sonnet-4.5", or "google/gemini-2.5-pro".`,
184
- );
185
- }
186
-
187
- const provider = rawProvider.toLowerCase();
188
- const model = rest.join(":").trim();
189
-
190
- if (!model) {
191
- throw new Error(
192
- `Invalid model string "${spec}". Use "openai/gpt-5", "anthropic/claude-sonnet-4.5", or "google/gemini-2.5-pro".`,
193
- );
194
- }
195
-
196
- switch (provider) {
197
- case "openai": {
198
- // Lazily create OpenAI provider
199
- // Use provided apiKey, or fall back to environment variable
200
- const openai = createOpenAI({
201
- apiKey: apiKey || process.env.OPENAI_API_KEY!,
202
- });
203
- // Accepts any OpenAI model id, e.g. "gpt-4o", "gpt-4.1-mini", "o3-mini"
204
- return openai(model);
205
- }
206
-
207
- case "anthropic": {
208
- // Lazily create Anthropic provider
209
- // Use provided apiKey, or fall back to environment variable
210
- const anthropic = createAnthropic({
211
- apiKey: apiKey || process.env.ANTHROPIC_API_KEY!,
212
- });
213
- // Accepts any Claude id, e.g. "claude-3.7-sonnet", "claude-3.5-haiku"
214
- return anthropic(model);
215
- }
216
-
217
- case "google":
218
- case "gemini":
219
- case "google-gemini": {
220
- // Lazily create Google provider
221
- // Use provided apiKey, or fall back to environment variable
222
- const google = createGoogleGenerativeAI({
223
- apiKey: apiKey || process.env.GOOGLE_API_KEY!,
224
- });
225
- // Accepts any Gemini id, e.g. "gemini-2.5-pro", "gemini-2.5-flash"
226
- return google(model);
227
- }
228
-
229
- case "vertex": {
230
- const vertex = createVertex();
231
- return vertex(model);
232
- }
233
-
234
- default:
235
- throw new Error(
236
- `Unknown provider "${provider}" in "${spec}". Supported: openai, anthropic, google (gemini).`,
237
- );
238
- }
239
- }
240
-
241
- /**
242
- * Tool definition for BuiltInAgent
243
- */
244
- export interface ToolDefinition<
245
- TParameters extends StandardSchemaV1 = StandardSchemaV1,
246
- > {
247
- name: string;
248
- description: string;
249
- parameters: TParameters;
250
- execute: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;
251
- }
252
-
253
- /**
254
- * Define a tool for use with BuiltInAgent
255
- * @param name - The name of the tool
256
- * @param description - Description of what the tool does
257
- * @param parameters - Schema for the tool's input parameters (any Standard Schema V1 compatible library: Zod, Valibot, ArkType, etc.)
258
- * @param execute - Function to execute the tool server-side
259
- * @returns Tool definition
260
- */
261
- export function defineTool<TParameters extends StandardSchemaV1>(config: {
262
- name: string;
263
- description: string;
264
- parameters: TParameters;
265
- execute: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;
266
- }): ToolDefinition<TParameters> {
267
- return {
268
- name: config.name,
269
- description: config.description,
270
- parameters: config.parameters,
271
- execute: config.execute,
272
- };
273
- }
274
-
275
- type AGUIUserMessage = Extract<Message, { role: "user" }>;
276
-
277
- /**
278
- * Converts AG-UI user message content to Vercel AI SDK UserContent format.
279
- * Handles plain strings, new modality-specific parts (image/audio/video/document),
280
- * and legacy BinaryInputContent for backward compatibility.
281
- */
282
- function convertUserMessageContent(
283
- content: AGUIUserMessage["content"],
284
- ): string | Array<TextPart | ImagePart | FilePart> {
285
- if (!content) {
286
- return "";
287
- }
288
-
289
- if (typeof content === "string") {
290
- return content;
291
- }
292
-
293
- const parts: Array<TextPart | ImagePart | FilePart> = [];
294
-
295
- for (const part of content) {
296
- if (!part || typeof part !== "object" || !("type" in part)) {
297
- continue;
298
- }
299
-
300
- switch (part.type) {
301
- case "text": {
302
- const text = (part as { text?: string }).text;
303
- if (text) {
304
- parts.push({ type: "text", text });
305
- }
306
- break;
307
- }
308
-
309
- case "image": {
310
- const source = (part as { source?: any }).source;
311
- if (!source) break;
312
- if (source.type === "data") {
313
- parts.push({
314
- type: "image",
315
- image: source.value,
316
- mediaType: source.mimeType,
317
- });
318
- } else if (source.type === "url") {
319
- try {
320
- parts.push({
321
- type: "image",
322
- image: new URL(source.value),
323
- mediaType: source.mimeType,
324
- });
325
- } catch {
326
- console.error(
327
- `[CopilotKit] convertUserMessageContent: invalid URL "${source.value}" in image part — skipping`,
328
- );
329
- }
330
- }
331
- break;
332
- }
333
-
334
- case "audio":
335
- case "video":
336
- case "document": {
337
- const source = (part as { source?: any }).source;
338
- if (!source) break;
339
- if (source.type === "data") {
340
- parts.push({
341
- type: "file",
342
- data: source.value,
343
- mediaType: source.mimeType,
344
- });
345
- } else if (source.type === "url") {
346
- try {
347
- parts.push({
348
- type: "file",
349
- data: new URL(source.value),
350
- mediaType: source.mimeType ?? "application/octet-stream",
351
- });
352
- } catch {
353
- console.error(
354
- `[CopilotKit] convertUserMessageContent: invalid URL "${source.value}" in ${part.type} part — skipping`,
355
- );
356
- }
357
- }
358
- break;
359
- }
360
-
361
- // Legacy BinaryInputContent backward compatibility
362
- case "binary": {
363
- const legacy = part as {
364
- mimeType?: string;
365
- data?: string;
366
- url?: string;
367
- };
368
- const mimeType = legacy.mimeType ?? "application/octet-stream";
369
- const isImage = mimeType.startsWith("image/");
370
-
371
- if (legacy.data) {
372
- if (isImage) {
373
- parts.push({
374
- type: "image",
375
- image: legacy.data,
376
- mediaType: mimeType,
377
- });
378
- } else {
379
- parts.push({
380
- type: "file",
381
- data: legacy.data,
382
- mediaType: mimeType,
383
- });
384
- }
385
- } else if (legacy.url) {
386
- try {
387
- const url = new URL(legacy.url);
388
- if (isImage) {
389
- parts.push({ type: "image", image: url, mediaType: mimeType });
390
- } else {
391
- parts.push({ type: "file", data: url, mediaType: mimeType });
392
- }
393
- } catch {
394
- console.error(
395
- `[CopilotKit] convertUserMessageContent: invalid URL "${legacy.url}" in binary part — skipping`,
396
- );
397
- }
398
- }
399
- break;
400
- }
401
-
402
- default: {
403
- console.error(
404
- `[CopilotKit] convertUserMessageContent: unrecognized content part type "${(part as { type: string }).type}" — skipping`,
405
- );
406
- break;
407
- }
408
- }
409
- }
410
-
411
- return parts.length > 0 ? parts : "";
412
- }
413
-
414
- /**
415
- * Options for converting AG-UI messages to Vercel AI SDK format
416
- */
417
- export interface MessageConversionOptions {
418
- forwardSystemMessages?: boolean;
419
- forwardDeveloperMessages?: boolean;
420
- }
421
-
422
- /**
423
- * Converts AG-UI messages to Vercel AI SDK ModelMessage format
424
- */
425
- export function convertMessagesToVercelAISDKMessages(
426
- messages: Message[],
427
- options: MessageConversionOptions = {},
428
- ): ModelMessage[] {
429
- const result: ModelMessage[] = [];
430
-
431
- for (const message of messages) {
432
- if (message.role === "system" && options.forwardSystemMessages) {
433
- const systemMsg: SystemModelMessage = {
434
- role: "system",
435
- content: message.content ?? "",
436
- };
437
- result.push(systemMsg);
438
- } else if (
439
- message.role === "developer" &&
440
- options.forwardDeveloperMessages
441
- ) {
442
- const systemMsg: SystemModelMessage = {
443
- role: "system",
444
- content: message.content ?? "",
445
- };
446
- result.push(systemMsg);
447
- } else if (message.role === "assistant") {
448
- const parts: Array<TextPart | ToolCallPart> = message.content
449
- ? [{ type: "text", text: message.content }]
450
- : [];
451
-
452
- for (const toolCall of message.toolCalls ?? []) {
453
- const toolCallPart: ToolCallPart = {
454
- type: "tool-call",
455
- toolCallId: toolCall.id,
456
- toolName: toolCall.function.name,
457
- input: safeParseToolArgs(toolCall.function.arguments),
458
- };
459
- parts.push(toolCallPart);
460
- }
461
-
462
- const assistantMsg: AssistantModelMessage = {
463
- role: "assistant",
464
- content: parts,
465
- };
466
- result.push(assistantMsg);
467
- } else if (message.role === "user") {
468
- const userMsg: UserModelMessage = {
469
- role: "user",
470
- content: convertUserMessageContent(message.content),
471
- };
472
- result.push(userMsg);
473
- } else if (message.role === "tool") {
474
- let toolName = "unknown";
475
- // Find the tool name from the corresponding tool call
476
- for (const msg of messages) {
477
- if (msg.role === "assistant") {
478
- for (const toolCall of msg.toolCalls ?? []) {
479
- if (toolCall.id === message.toolCallId) {
480
- toolName = toolCall.function.name;
481
- break;
482
- }
483
- }
484
- }
485
- }
486
-
487
- const toolResultPart: ToolResultPart = {
488
- type: "tool-result",
489
- toolCallId: message.toolCallId,
490
- toolName: toolName,
491
- output: {
492
- type: "text",
493
- value: message.content,
494
- },
495
- };
496
-
497
- const toolMsg: ToolModelMessage = {
498
- role: "tool",
499
- content: [toolResultPart],
500
- };
501
- result.push(toolMsg);
502
- }
503
- }
504
-
505
- return result;
506
- }
507
-
508
- /**
509
- * JSON Schema type definition
510
- */
511
- interface JsonSchema {
512
- type: "object" | "string" | "number" | "integer" | "boolean" | "array";
513
- description?: string;
514
- properties?: Record<string, JsonSchema>;
515
- required?: string[];
516
- items?: JsonSchema;
517
- enum?: string[];
518
- }
519
-
520
- /**
521
- * Converts JSON Schema to Zod schema
522
- */
523
- export function convertJsonSchemaToZodSchema(
524
- jsonSchema: JsonSchema,
525
- required: boolean,
526
- ): z.ZodSchema {
527
- // Handle empty schemas {} (no input required) - treat as empty object
528
- if (!jsonSchema.type) {
529
- return required ? z.object({}) : z.object({}).optional();
530
- }
531
- if (jsonSchema.type === "object") {
532
- const spec: { [key: string]: z.ZodSchema } = {};
533
-
534
- if (!jsonSchema.properties || !Object.keys(jsonSchema.properties).length) {
535
- return !required ? z.object(spec).optional() : z.object(spec);
536
- }
537
-
538
- for (const [key, value] of Object.entries(jsonSchema.properties)) {
539
- spec[key] = convertJsonSchemaToZodSchema(
540
- value,
541
- jsonSchema.required ? jsonSchema.required.includes(key) : false,
542
- );
543
- }
544
- const schema = z.object(spec).describe(jsonSchema.description ?? "");
545
- return required ? schema : schema.optional();
546
- } else if (jsonSchema.type === "string") {
547
- if (jsonSchema.enum && jsonSchema.enum.length > 0) {
548
- const schema = z
549
- .enum(jsonSchema.enum as [string, ...string[]])
550
- .describe(jsonSchema.description ?? "");
551
- return required ? schema : schema.optional();
552
- }
553
- const schema = z.string().describe(jsonSchema.description ?? "");
554
- return required ? schema : schema.optional();
555
- } else if (jsonSchema.type === "number" || jsonSchema.type === "integer") {
556
- const schema = z.number().describe(jsonSchema.description ?? "");
557
- return required ? schema : schema.optional();
558
- } else if (jsonSchema.type === "boolean") {
559
- const schema = z.boolean().describe(jsonSchema.description ?? "");
560
- return required ? schema : schema.optional();
561
- } else if (jsonSchema.type === "array") {
562
- if (!jsonSchema.items) {
563
- throw new Error("Array type must have items property");
564
- }
565
- const itemSchema = convertJsonSchemaToZodSchema(jsonSchema.items, true);
566
- const schema = z.array(itemSchema).describe(jsonSchema.description ?? "");
567
- return required ? schema : schema.optional();
568
- }
569
- console.error("Invalid JSON schema:", JSON.stringify(jsonSchema, null, 2));
570
- throw new Error("Invalid JSON schema");
571
- }
572
-
573
- /**
574
- * Converts AG-UI tools to Vercel AI SDK ToolSet
575
- */
576
- function isJsonSchema(obj: unknown): obj is JsonSchema {
577
- if (typeof obj !== "object" || obj === null) return false;
578
- const schema = obj as Record<string, unknown>;
579
- // Empty objects {} are valid JSON schemas (no input required)
580
- if (Object.keys(schema).length === 0) return true;
581
- return (
582
- typeof schema.type === "string" &&
583
- ["object", "string", "number", "integer", "boolean", "array"].includes(
584
- schema.type,
585
- )
586
- );
587
- }
588
-
589
- export function convertToolsToVercelAITools(
590
- tools: RunAgentInput["tools"],
591
- ): ToolSet {
592
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
593
- const result: Record<string, any> = {};
594
-
595
- for (const tool of tools) {
596
- if (!isJsonSchema(tool.parameters)) {
597
- throw new Error(`Invalid JSON schema for tool ${tool.name}`);
598
- }
599
- const zodSchema = convertJsonSchemaToZodSchema(tool.parameters, true);
600
- result[tool.name] = createVercelAISDKTool({
601
- description: tool.description,
602
- inputSchema: zodSchema,
603
- });
604
- }
605
-
606
- return result;
607
- }
608
-
609
- /**
610
- * Check whether a schema is a Zod schema by inspecting its Standard Schema vendor.
611
- */
612
- function isZodSchema(schema: StandardSchemaV1): boolean {
613
- return schema["~standard"]?.vendor === "zod";
614
- }
615
-
616
- /**
617
- * Converts ToolDefinition array to Vercel AI SDK ToolSet.
618
- *
619
- * For Zod schemas, passes them directly to the AI SDK (Zod satisfies FlexibleSchema).
620
- * For non-Zod schemas, converts to JSON Schema via schemaToJsonSchema() and wraps
621
- * with the AI SDK's jsonSchema() helper.
622
- */
623
- export function convertToolDefinitionsToVercelAITools(
624
- tools: ToolDefinition[],
625
- ): ToolSet {
626
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
627
- const result: Record<string, any> = {};
628
-
629
- for (const tool of tools) {
630
- if (isZodSchema(tool.parameters)) {
631
- // Zod schemas can be passed directly to AI SDK (satisfies FlexibleSchema)
632
- result[tool.name] = createVercelAISDKTool({
633
- description: tool.description,
634
- inputSchema: tool.parameters as any,
635
- execute: tool.execute,
636
- });
637
- } else {
638
- // Non-Zod: convert to JSON Schema and wrap with AI SDK's jsonSchema()
639
- const jsonSchemaObj = schemaToJsonSchema(tool.parameters);
640
- result[tool.name] = createVercelAISDKTool({
641
- description: tool.description,
642
- inputSchema: aiJsonSchema(jsonSchemaObj),
643
- execute: tool.execute,
644
- });
645
- }
646
- }
647
-
648
- return result;
649
- }
650
-
651
- /**
652
- * Context passed to the user-supplied factory function in factory mode.
653
- */
654
- export interface AgentFactoryContext {
655
- input: RunAgentInput;
656
- /**
657
- * Prefer `abortSignal` for most use cases (AI SDK, fetch, custom backends).
658
- * Provided for backends like TanStack AI that require the full AbortController.
659
- * Do NOT call `.abort()` on this controller — use `abortRun()` on the agent instead.
660
- */
661
- abortController: AbortController;
662
- abortSignal: AbortSignal;
663
- }
664
-
665
- /**
666
- * Factory config for AI SDK backend.
667
- * The factory must return an object with a `fullStream` async iterable
668
- * (compatible with the result of `streamText()` — only `fullStream` is consumed).
669
- */
670
- export interface BuiltInAgentAISDKFactoryConfig {
671
- type: "aisdk";
672
- factory: (
673
- ctx: AgentFactoryContext,
674
- ) =>
675
- | { fullStream: AsyncIterable<unknown> }
676
- | Promise<{ fullStream: AsyncIterable<unknown> }>;
677
- }
678
-
679
- /**
680
- * Factory config for TanStack AI backend.
681
- * The factory must return an async iterable of TanStack AI stream chunks.
682
- */
683
- export interface BuiltInAgentTanStackFactoryConfig {
684
- type: "tanstack";
685
- factory: (
686
- ctx: AgentFactoryContext,
687
- ) => AsyncIterable<unknown> | Promise<AsyncIterable<unknown>>;
688
- }
689
-
690
- /**
691
- * Factory config for a custom backend that directly yields AG-UI events.
692
- */
693
- export interface BuiltInAgentCustomFactoryConfig {
694
- type: "custom";
695
- factory: (
696
- ctx: AgentFactoryContext,
697
- ) => AsyncIterable<BaseEvent> | Promise<AsyncIterable<BaseEvent>>;
698
- }
699
-
700
- /**
701
- * Union of all factory-mode configurations.
702
- */
703
- export type BuiltInAgentFactoryConfig =
704
- | BuiltInAgentAISDKFactoryConfig
705
- | BuiltInAgentTanStackFactoryConfig
706
- | BuiltInAgentCustomFactoryConfig;
707
-
708
- /**
709
- * Classic config — BuiltInAgent handles streamText, tools, MCP, state tools, prompt building.
710
- */
711
- export interface BuiltInAgentClassicConfig {
712
- /**
713
- * The model to use
714
- */
715
- model: BuiltInAgentModel | LanguageModel;
716
- /**
717
- * API key for the model provider (OpenAI, Anthropic, Google)
718
- * If not provided, falls back to environment variables:
719
- * - OPENAI_API_KEY for OpenAI models
720
- * - ANTHROPIC_API_KEY for Anthropic models
721
- * - GOOGLE_API_KEY for Google models
722
- */
723
- apiKey?: string;
724
- /**
725
- * Maximum number of steps/iterations for tool calling (default: 1)
726
- */
727
- maxSteps?: number;
728
- /**
729
- * Tool choice setting - how tools are selected for execution (default: "auto")
730
- */
731
- toolChoice?: ToolChoice<Record<string, unknown>>;
732
- /**
733
- * Maximum number of tokens to generate
734
- */
735
- maxOutputTokens?: number;
736
- /**
737
- * Temperature setting (range depends on provider)
738
- */
739
- temperature?: number;
740
- /**
741
- * Nucleus sampling (topP)
742
- */
743
- topP?: number;
744
- /**
745
- * Top K sampling
746
- */
747
- topK?: number;
748
- /**
749
- * Presence penalty
750
- */
751
- presencePenalty?: number;
752
- /**
753
- * Frequency penalty
754
- */
755
- frequencyPenalty?: number;
756
- /**
757
- * Sequences that will stop the generation
758
- */
759
- stopSequences?: string[];
760
- /**
761
- * Seed for deterministic results
762
- */
763
- seed?: number;
764
- /**
765
- * Maximum number of retries
766
- */
767
- maxRetries?: number;
768
- /**
769
- * Prompt for the agent
770
- */
771
- prompt?: string;
772
- /**
773
- * List of properties that can be overridden by forwardedProps.
774
- */
775
- overridableProperties?: OverridableProperty[];
776
- /**
777
- * Optional list of MCP server configurations
778
- */
779
- mcpServers?: MCPClientConfig[];
780
- /**
781
- * Optional list of user-managed MCP clients.
782
- * Unlike mcpServers, the agent does NOT create or close these clients.
783
- * The user controls the lifecycle, persistence, auth, and caching.
784
- *
785
- * Compatible with @ai-sdk/mcp's createMCPClient() return type:
786
- * ```typescript
787
- * const client = await createMCPClient({ transport });
788
- * const agent = new BuiltInAgent({ model: "...", mcpClients: [client] });
789
- * ```
790
- */
791
- mcpClients?: MCPClientProvider[];
792
- /**
793
- * Optional tools available to the agent
794
- */
795
- tools?: ToolDefinition[];
796
- /**
797
- * Forward system-role messages from input to the LLM.
798
- * Default: false
799
- */
800
- forwardSystemMessages?: boolean;
801
- /**
802
- * Forward developer-role messages from input to the LLM (as system messages).
803
- * Default: false
804
- */
805
- forwardDeveloperMessages?: boolean;
806
- /**
807
- * Provider-specific options passed to the model (e.g., OpenAI reasoningEffort).
808
- * Example: `{ openai: { reasoningEffort: "high" } }`
809
- */
810
- providerOptions?: Record<string, any>;
811
- /**
812
- * Explicit agent capabilities. **Shallow-merged** at the category level on
813
- * top of auto-inferred defaults — providing a category (e.g. `tools`)
814
- * replaces that entire category, not individual fields within it.
815
- *
816
- * For example, `{ tools: { supported: true } }` will drop the inferred
817
- * `clientProvided` value. Include all fields for any category you override.
818
- */
819
- capabilities?: Partial<AgentCapabilities>;
820
- }
821
-
822
- /**
823
- * Configuration for BuiltInAgent.
824
- *
825
- * Two modes:
826
- * - **Classic** (model + params): BuiltInAgent handles everything — streamText, tools, MCP, state tools.
827
- * - **Factory** (type + factory): You own the LLM call. BuiltInAgent handles lifecycle only.
828
- */
829
- export type BuiltInAgentConfiguration =
830
- | BuiltInAgentClassicConfig
831
- | BuiltInAgentFactoryConfig;
832
-
833
- /**
834
- * Type guard: returns true if this is a factory-mode config.
835
- */
836
- function isFactoryConfig(
837
- config: BuiltInAgentConfiguration,
838
- ): config is BuiltInAgentFactoryConfig {
839
- return "factory" in config;
840
- }
841
-
842
- export class BuiltInAgent extends AbstractAgent {
843
- private abortController?: AbortController;
844
-
845
- constructor(private config: BuiltInAgentConfiguration) {
846
- super();
847
- }
848
-
849
- /**
850
- * Check if a property can be overridden by forwardedProps
851
- */
852
- canOverride(property: OverridableProperty): boolean {
853
- if (isFactoryConfig(this.config)) return false;
854
- return this.config?.overridableProperties?.includes(property) ?? false;
855
- }
856
-
857
- async getCapabilities(): Promise<AgentCapabilities> {
858
- const inferred: AgentCapabilities = {
859
- tools: {
860
- supported: true,
861
- clientProvided: true,
862
- },
863
- transport: {
864
- streaming: true,
865
- },
866
- };
867
-
868
- if (!this.config.capabilities) {
869
- return inferred;
870
- }
871
-
872
- // Shallow merge at the category level — explicit overrides replace
873
- // entire categories when provided, inferred defaults fill the rest.
874
- return {
875
- ...inferred,
876
- ...this.config.capabilities,
877
- };
878
- }
879
-
880
- run(input: RunAgentInput): Observable<BaseEvent> {
881
- if (isFactoryConfig(this.config)) {
882
- return this.runFactory(input, this.config);
883
- }
884
-
885
- if (this.abortController) {
886
- throw new Error(
887
- "Agent is already running. Call abortRun() first or create a new instance.",
888
- );
889
- }
890
-
891
- // Set synchronously before Observable creation to close TOCTOU window
892
- this.abortController = new AbortController();
893
- const abortController = this.abortController;
894
-
895
- return new Observable<BaseEvent>((subscriber) => {
896
- // Emit RUN_STARTED event
897
- const startEvent: RunStartedEvent = {
898
- type: EventType.RUN_STARTED,
899
- threadId: input.threadId,
900
- runId: input.runId,
901
- };
902
- subscriber.next(startEvent);
903
-
904
- // Resolve the model, passing API key if provided
905
- const model = resolveModel(this.config.model, this.config.apiKey);
906
-
907
- // Build prompt based on conditions
908
- let systemPrompt: string | undefined = undefined;
909
-
910
- // Check if we should build a prompt:
911
- // - config.prompt is set, OR
912
- // - input.context is non-empty, OR
913
- // - input.state is non-empty and not an empty object
914
- const hasPrompt = !!this.config.prompt;
915
- const hasContext = input.context && input.context.length > 0;
916
- const hasState =
917
- input.state !== undefined &&
918
- input.state !== null &&
919
- !(
920
- typeof input.state === "object" &&
921
- Object.keys(input.state).length === 0
922
- );
923
-
924
- if (hasPrompt || hasContext || hasState) {
925
- const parts: string[] = [];
926
-
927
- // First: the prompt if any
928
- if (hasPrompt) {
929
- parts.push(this.config.prompt!);
930
- }
931
-
932
- // Second: context from the application
933
- if (hasContext) {
934
- parts.push("\n## Context from the application\n");
935
- for (const ctx of input.context) {
936
- parts.push(`${ctx.description}:\n${ctx.value}\n`);
937
- }
938
- }
939
-
940
- // Third: state from the application that can be edited
941
- if (hasState) {
942
- parts.push(
943
- "\n## Application State\n" +
944
- "This is state from the application that you can edit by calling AGUISendStateSnapshot or AGUISendStateDelta.\n" +
945
- `\`\`\`json\n${JSON.stringify(input.state, null, 2)}\n\`\`\`\n`,
946
- );
947
- }
948
-
949
- systemPrompt = parts.join("");
950
- }
951
-
952
- // Convert messages and prepend system message if we have a prompt
953
- const messages = convertMessagesToVercelAISDKMessages(input.messages, {
954
- forwardSystemMessages: this.config.forwardSystemMessages,
955
- forwardDeveloperMessages: this.config.forwardDeveloperMessages,
956
- });
957
- if (systemPrompt) {
958
- messages.unshift({
959
- role: "system",
960
- content: systemPrompt,
961
- });
962
- }
963
-
964
- // Merge tools from input and config
965
- let allTools: ToolSet = convertToolsToVercelAITools(input.tools);
966
- if (this.config.tools && this.config.tools.length > 0) {
967
- const configTools = convertToolDefinitionsToVercelAITools(
968
- this.config.tools,
969
- );
970
- allTools = { ...allTools, ...configTools };
971
- }
972
-
973
- const streamTextParams: Parameters<typeof streamText>[0] = {
974
- model,
975
- messages,
976
- tools: allTools,
977
- toolChoice: this.config.toolChoice,
978
- stopWhen: this.config.maxSteps
979
- ? stepCountIs(this.config.maxSteps)
980
- : undefined,
981
- maxOutputTokens: this.config.maxOutputTokens,
982
- temperature: this.config.temperature,
983
- topP: this.config.topP,
984
- topK: this.config.topK,
985
- presencePenalty: this.config.presencePenalty,
986
- frequencyPenalty: this.config.frequencyPenalty,
987
- stopSequences: this.config.stopSequences,
988
- seed: this.config.seed,
989
- providerOptions: this.config.providerOptions,
990
- maxRetries: this.config.maxRetries,
991
- };
992
-
993
- // Apply forwardedProps overrides (if allowed)
994
- if (input.forwardedProps && typeof input.forwardedProps === "object") {
995
- const props = input.forwardedProps as Record<string, unknown>;
996
-
997
- // Check and apply each overridable property
998
- if (props.model !== undefined && this.canOverride("model")) {
999
- if (
1000
- typeof props.model === "string" ||
1001
- typeof props.model === "object"
1002
- ) {
1003
- // Accept any string or LanguageModel instance for model override
1004
- // Use the configured API key when resolving overridden models
1005
- streamTextParams.model = resolveModel(
1006
- props.model as string | LanguageModel,
1007
- this.config.apiKey,
1008
- );
1009
- }
1010
- }
1011
- if (props.toolChoice !== undefined && this.canOverride("toolChoice")) {
1012
- // ToolChoice can be 'auto', 'required', 'none', or { type: 'tool', toolName: string }
1013
- const toolChoice = props.toolChoice;
1014
- if (
1015
- toolChoice === "auto" ||
1016
- toolChoice === "required" ||
1017
- toolChoice === "none" ||
1018
- (typeof toolChoice === "object" &&
1019
- toolChoice !== null &&
1020
- "type" in toolChoice &&
1021
- toolChoice.type === "tool")
1022
- ) {
1023
- streamTextParams.toolChoice = toolChoice as ToolChoice<
1024
- Record<string, unknown>
1025
- >;
1026
- }
1027
- }
1028
- if (
1029
- typeof props.maxOutputTokens === "number" &&
1030
- this.canOverride("maxOutputTokens")
1031
- ) {
1032
- streamTextParams.maxOutputTokens = props.maxOutputTokens;
1033
- }
1034
- if (
1035
- typeof props.temperature === "number" &&
1036
- this.canOverride("temperature")
1037
- ) {
1038
- streamTextParams.temperature = props.temperature;
1039
- }
1040
- if (typeof props.topP === "number" && this.canOverride("topP")) {
1041
- streamTextParams.topP = props.topP;
1042
- }
1043
- if (typeof props.topK === "number" && this.canOverride("topK")) {
1044
- streamTextParams.topK = props.topK;
1045
- }
1046
- if (
1047
- typeof props.presencePenalty === "number" &&
1048
- this.canOverride("presencePenalty")
1049
- ) {
1050
- streamTextParams.presencePenalty = props.presencePenalty;
1051
- }
1052
- if (
1053
- typeof props.frequencyPenalty === "number" &&
1054
- this.canOverride("frequencyPenalty")
1055
- ) {
1056
- streamTextParams.frequencyPenalty = props.frequencyPenalty;
1057
- }
1058
- if (
1059
- Array.isArray(props.stopSequences) &&
1060
- this.canOverride("stopSequences")
1061
- ) {
1062
- // Validate all elements are strings
1063
- if (
1064
- props.stopSequences.every(
1065
- (item): item is string => typeof item === "string",
1066
- )
1067
- ) {
1068
- streamTextParams.stopSequences = props.stopSequences;
1069
- }
1070
- }
1071
- if (typeof props.seed === "number" && this.canOverride("seed")) {
1072
- streamTextParams.seed = props.seed;
1073
- }
1074
- if (
1075
- typeof props.maxRetries === "number" &&
1076
- this.canOverride("maxRetries")
1077
- ) {
1078
- streamTextParams.maxRetries = props.maxRetries;
1079
- }
1080
- if (
1081
- props.providerOptions !== undefined &&
1082
- this.canOverride("providerOptions")
1083
- ) {
1084
- if (
1085
- typeof props.providerOptions === "object" &&
1086
- props.providerOptions !== null
1087
- ) {
1088
- streamTextParams.providerOptions = props.providerOptions as Record<
1089
- string,
1090
- any
1091
- >;
1092
- }
1093
- }
1094
- }
1095
-
1096
- // Set up MCP clients if configured and process the stream
1097
- const mcpClients: MCPClient[] = [];
1098
-
1099
- (async () => {
1100
- let terminalEventEmitted = false;
1101
- let messageId = randomUUID();
1102
- let reasoningMessageId = randomUUID();
1103
- let isInReasoning = false;
1104
-
1105
- // Auto-close an open reasoning lifecycle.
1106
- // Some AI SDK providers (notably @ai-sdk/anthropic) never emit "reasoning-end",
1107
- // which leaves downstream state machines stuck. This helper emits the
1108
- // missing REASONING_MESSAGE_END + REASONING_END events so the stream
1109
- // can transition to text, tool-call, or finish phases.
1110
- // Declared before try/catch so it is accessible in the catch block.
1111
- const closeReasoningIfOpen = () => {
1112
- if (!isInReasoning) return;
1113
- isInReasoning = false;
1114
- const reasoningMsgEnd: ReasoningMessageEndEvent = {
1115
- type: EventType.REASONING_MESSAGE_END,
1116
- messageId: reasoningMessageId,
1117
- };
1118
- subscriber.next(reasoningMsgEnd);
1119
- const reasoningEnd: ReasoningEndEvent = {
1120
- type: EventType.REASONING_END,
1121
- messageId: reasoningMessageId,
1122
- };
1123
- subscriber.next(reasoningEnd);
1124
- };
1125
-
1126
- try {
1127
- // Add AG-UI state update tools
1128
- streamTextParams.tools = {
1129
- ...streamTextParams.tools,
1130
- AGUISendStateSnapshot: createVercelAISDKTool({
1131
- description:
1132
- "Replace the entire application state with a new snapshot",
1133
- inputSchema: z.object({
1134
- snapshot: z.any().describe("The complete new state object"),
1135
- }),
1136
- execute: async ({ snapshot }) => {
1137
- return { success: true, snapshot };
1138
- },
1139
- }),
1140
- AGUISendStateDelta: createVercelAISDKTool({
1141
- description:
1142
- "Apply incremental updates to application state using JSON Patch operations",
1143
- inputSchema: z.object({
1144
- delta: z
1145
- .array(
1146
- z.object({
1147
- op: z
1148
- .enum(["add", "replace", "remove"])
1149
- .describe("The operation to perform"),
1150
- path: z
1151
- .string()
1152
- .describe("JSON Pointer path (e.g., '/foo/bar')"),
1153
- value: z
1154
- .any()
1155
- .optional()
1156
- .describe(
1157
- "The value to set. Required for 'add' and 'replace' operations, ignored for 'remove'.",
1158
- ),
1159
- }),
1160
- )
1161
- .describe("Array of JSON Patch operations"),
1162
- }),
1163
- execute: async ({ delta }) => {
1164
- return { success: true, delta };
1165
- },
1166
- }),
1167
- };
1168
-
1169
- // Merge tools from user-managed MCP clients (user controls lifecycle)
1170
- if (this.config.mcpClients && this.config.mcpClients.length > 0) {
1171
- for (const client of this.config.mcpClients) {
1172
- const mcpTools = await client.tools();
1173
- streamTextParams.tools = {
1174
- ...streamTextParams.tools,
1175
- ...mcpTools,
1176
- } as ToolSet;
1177
- }
1178
- }
1179
-
1180
- // Initialize MCP clients and get their tools.
1181
- //
1182
- // Servers come from two sources, concatenated in order:
1183
- // - `config.mcpServers` — user-supplied static array.
1184
- // - The CopilotKit Intelligence MCP server, auto-attached when
1185
- // the runtime forwards a `copilotkitIntelligence` bag via
1186
- // `input.forwardedProps.auth`. The bag carries `userId` +
1187
- // `apiKey` + `mcpUrl`. We build a per-request
1188
- // MCPClientConfigHTTP whose `options.fetch` closes over
1189
- // `apiKey` + `userId` and stamps
1190
- // `Authorization: Bearer <apiKey>` and `X-Cpki-User-Id:
1191
- // <userId>` on every outbound MCP call. Skipped when the user
1192
- // already configured a server pointing at the same URL. The
1193
- // `auth` namespace is the convention for credentials that
1194
- // downstream redaction policies strip before durable storage
1195
- // and FE replay.
1196
- const allMcpServers: MCPClientConfig[] = [
1197
- ...(this.config.mcpServers ?? []),
1198
- ];
1199
- const auth = (
1200
- input.forwardedProps as
1201
- | { auth?: { copilotkitIntelligence?: unknown } }
1202
- | undefined
1203
- )?.auth;
1204
- const cpki = auth?.copilotkitIntelligence as
1205
- | { userId?: unknown; apiKey?: unknown; mcpUrl?: unknown }
1206
- | undefined;
1207
- const cpkiUserId =
1208
- typeof cpki?.userId === "string" ? cpki.userId : undefined;
1209
- const cpkiApiKey =
1210
- typeof cpki?.apiKey === "string" ? cpki.apiKey : undefined;
1211
- const cpkiMcpUrl =
1212
- typeof cpki?.mcpUrl === "string" ? cpki.mcpUrl : undefined;
1213
- if (
1214
- cpkiUserId &&
1215
- cpkiApiKey &&
1216
- cpkiMcpUrl &&
1217
- !allMcpServers.some(
1218
- (s) => s.type === "http" && s.url === cpkiMcpUrl,
1219
- )
1220
- ) {
1221
- allMcpServers.push({
1222
- type: "http",
1223
- url: cpkiMcpUrl,
1224
- options: {
1225
- fetch: async (req, init) => {
1226
- const headers = new Headers(init?.headers);
1227
- headers.set("Authorization", `Bearer ${cpkiApiKey}`);
1228
- headers.set(INTELLIGENCE_USER_ID_HEADER, cpkiUserId);
1229
- return globalThis.fetch(req, { ...init, headers });
1230
- },
1231
- },
1232
- });
1233
- }
1234
- if (allMcpServers.length > 0) {
1235
- for (const serverConfig of allMcpServers) {
1236
- let transport;
1237
-
1238
- if (serverConfig.type === "http") {
1239
- const url = new URL(serverConfig.url);
1240
- transport = new StreamableHTTPClientTransport(
1241
- url,
1242
- serverConfig.options,
1243
- );
1244
- } else if (serverConfig.type === "sse") {
1245
- transport = new SSEClientTransport(
1246
- new URL(serverConfig.url),
1247
- serverConfig.headers,
1248
- );
1249
- }
1250
-
1251
- if (transport) {
1252
- const mcpClient = await createMCPClient({ transport });
1253
- mcpClients.push(mcpClient);
1254
-
1255
- // Get tools from this MCP server and merge with existing tools
1256
- const mcpTools = await mcpClient.tools();
1257
- streamTextParams.tools = {
1258
- ...streamTextParams.tools,
1259
- ...mcpTools,
1260
- } as ToolSet;
1261
- }
1262
- }
1263
- }
1264
-
1265
- // Call streamText and process the stream
1266
- const response = streamText({
1267
- ...streamTextParams,
1268
- abortSignal: abortController.signal,
1269
- });
1270
-
1271
- const toolCallStates = new Map<
1272
- string,
1273
- {
1274
- started: boolean;
1275
- hasArgsDelta: boolean;
1276
- ended: boolean;
1277
- toolName?: string;
1278
- }
1279
- >();
1280
-
1281
- const ensureToolCallState = (toolCallId: string) => {
1282
- let state = toolCallStates.get(toolCallId);
1283
- if (!state) {
1284
- state = { started: false, hasArgsDelta: false, ended: false };
1285
- toolCallStates.set(toolCallId, state);
1286
- }
1287
- return state;
1288
- };
1289
-
1290
- // Process fullStream events
1291
- for await (const part of response.fullStream) {
1292
- // Close any open reasoning lifecycle on every event except
1293
- // reasoning-delta, which arrives mid-block and must not interrupt it.
1294
- if (part.type !== "reasoning-delta") {
1295
- closeReasoningIfOpen();
1296
- }
1297
-
1298
- switch (part.type) {
1299
- case "abort": {
1300
- const abortEndEvent: RunFinishedEvent = {
1301
- type: EventType.RUN_FINISHED,
1302
- threadId: input.threadId,
1303
- runId: input.runId,
1304
- };
1305
- subscriber.next(abortEndEvent);
1306
- terminalEventEmitted = true;
1307
-
1308
- // Complete the observable
1309
- subscriber.complete();
1310
- break;
1311
- }
1312
- case "reasoning-start": {
1313
- // Use SDK-provided id, or generate a fresh UUID if the id is falsy,
1314
- // "0", or matches the non-unique pattern emitted by @ai-sdk/openai-compatible
1315
- // (e.g. "txt-0", "reasoning-0", "msg-0").
1316
- const providedId = "id" in part ? part.id : undefined;
1317
- const isNonUniqueId =
1318
- !providedId ||
1319
- providedId === "0" ||
1320
- /^(txt|reasoning|msg)-0$/.test(providedId);
1321
- reasoningMessageId = isNonUniqueId
1322
- ? randomUUID()
1323
- : (providedId as typeof reasoningMessageId);
1324
- const reasoningStartEvent: ReasoningStartEvent = {
1325
- type: EventType.REASONING_START,
1326
- messageId: reasoningMessageId,
1327
- };
1328
- subscriber.next(reasoningStartEvent);
1329
- const reasoningMessageStart: ReasoningMessageStartEvent = {
1330
- type: EventType.REASONING_MESSAGE_START,
1331
- messageId: reasoningMessageId,
1332
- role: "reasoning",
1333
- };
1334
- subscriber.next(reasoningMessageStart);
1335
- isInReasoning = true;
1336
- break;
1337
- }
1338
- case "reasoning-delta": {
1339
- const delta = part.text ?? "";
1340
- if (!delta) break; // skip — @ag-ui/core schema requires delta to be non-empty
1341
- const reasoningDeltaEvent: ReasoningMessageContentEvent = {
1342
- type: EventType.REASONING_MESSAGE_CONTENT,
1343
- messageId: reasoningMessageId,
1344
- delta,
1345
- };
1346
- subscriber.next(reasoningDeltaEvent);
1347
- break;
1348
- }
1349
- case "reasoning-end": {
1350
- // closeReasoningIfOpen() already called before the switch — no-op here
1351
- // if the SDK never emits this event (e.g. @ai-sdk/anthropic).
1352
- break;
1353
- }
1354
- case "tool-input-start": {
1355
- const toolCallId = part.id;
1356
- const state = ensureToolCallState(toolCallId);
1357
- state.toolName = part.toolName;
1358
- if (!state.started) {
1359
- state.started = true;
1360
- const startEvent: ToolCallStartEvent = {
1361
- type: EventType.TOOL_CALL_START,
1362
- parentMessageId: messageId,
1363
- toolCallId,
1364
- toolCallName: part.toolName,
1365
- };
1366
- subscriber.next(startEvent);
1367
- }
1368
- break;
1369
- }
1370
-
1371
- case "tool-input-delta": {
1372
- const toolCallId = part.id;
1373
- const state = ensureToolCallState(toolCallId);
1374
- state.hasArgsDelta = true;
1375
- const argsEvent: ToolCallArgsEvent = {
1376
- type: EventType.TOOL_CALL_ARGS,
1377
- toolCallId,
1378
- delta: part.delta,
1379
- };
1380
- subscriber.next(argsEvent);
1381
- break;
1382
- }
1383
-
1384
- case "tool-input-end": {
1385
- // No direct event – the subsequent "tool-call" part marks completion.
1386
- break;
1387
- }
1388
-
1389
- case "text-start": {
1390
- // New text message starting - use the SDK-provided id
1391
- // Use randomUUID() if part.id is falsy, "0", or matches the non-unique
1392
- // pattern emitted by @ai-sdk/openai-compatible (e.g. "txt-0", "msg-0").
1393
- const providedId = "id" in part ? part.id : undefined;
1394
- const isNonUniqueTextId =
1395
- !providedId ||
1396
- providedId === "0" ||
1397
- /^(txt|reasoning|msg)-0$/.test(providedId);
1398
- messageId = isNonUniqueTextId
1399
- ? randomUUID()
1400
- : (providedId as typeof messageId);
1401
- break;
1402
- }
1403
-
1404
- case "text-delta": {
1405
- // Accumulate text content - in AI SDK 5.0, the property is 'text'
1406
- const textDelta = "text" in part ? part.text : "";
1407
- // Emit text chunk event
1408
- const textEvent: TextMessageChunkEvent = {
1409
- type: EventType.TEXT_MESSAGE_CHUNK,
1410
- role: "assistant",
1411
- messageId,
1412
- delta: textDelta,
1413
- };
1414
- subscriber.next(textEvent);
1415
- break;
1416
- }
1417
-
1418
- case "tool-call": {
1419
- const toolCallId = part.toolCallId;
1420
- const state = ensureToolCallState(toolCallId);
1421
- state.toolName = part.toolName ?? state.toolName;
1422
-
1423
- if (!state.started) {
1424
- state.started = true;
1425
- const startEvent: ToolCallStartEvent = {
1426
- type: EventType.TOOL_CALL_START,
1427
- parentMessageId: messageId,
1428
- toolCallId,
1429
- toolCallName: part.toolName,
1430
- };
1431
- subscriber.next(startEvent);
1432
- }
1433
-
1434
- if (
1435
- !state.hasArgsDelta &&
1436
- "input" in part &&
1437
- part.input !== undefined
1438
- ) {
1439
- let serializedInput = "";
1440
- if (typeof part.input === "string") {
1441
- serializedInput = part.input;
1442
- } else {
1443
- try {
1444
- serializedInput = JSON.stringify(part.input);
1445
- } catch {
1446
- serializedInput = String(part.input);
1447
- }
1448
- }
1449
-
1450
- if (serializedInput.length > 0) {
1451
- const argsEvent: ToolCallArgsEvent = {
1452
- type: EventType.TOOL_CALL_ARGS,
1453
- toolCallId,
1454
- delta: serializedInput,
1455
- };
1456
- subscriber.next(argsEvent);
1457
- state.hasArgsDelta = true;
1458
- }
1459
- }
1460
-
1461
- if (!state.ended) {
1462
- state.ended = true;
1463
- const endEvent: ToolCallEndEvent = {
1464
- type: EventType.TOOL_CALL_END,
1465
- toolCallId,
1466
- };
1467
- subscriber.next(endEvent);
1468
- }
1469
- break;
1470
- }
1471
-
1472
- case "tool-result": {
1473
- const toolResult =
1474
- "output" in part
1475
- ? part.output
1476
- : "result" in part
1477
- ? part.result
1478
- : null;
1479
- const toolName = "toolName" in part ? part.toolName : "";
1480
- toolCallStates.delete(part.toolCallId);
1481
-
1482
- // Check if this is a state update tool
1483
- if (
1484
- toolName === "AGUISendStateSnapshot" &&
1485
- toolResult &&
1486
- typeof toolResult === "object"
1487
- ) {
1488
- const snapshot = toolResult.snapshot;
1489
- if (snapshot !== undefined) {
1490
- const stateSnapshotEvent: StateSnapshotEvent = {
1491
- type: EventType.STATE_SNAPSHOT,
1492
- snapshot,
1493
- };
1494
- subscriber.next(stateSnapshotEvent);
1495
- }
1496
- } else if (
1497
- toolName === "AGUISendStateDelta" &&
1498
- toolResult &&
1499
- typeof toolResult === "object"
1500
- ) {
1501
- const delta = toolResult.delta;
1502
- if (delta !== undefined) {
1503
- const stateDeltaEvent: StateDeltaEvent = {
1504
- type: EventType.STATE_DELTA,
1505
- delta,
1506
- };
1507
- subscriber.next(stateDeltaEvent);
1508
- }
1509
- }
1510
-
1511
- // Always emit the tool result event for the LLM
1512
- let serializedResult: string;
1513
- try {
1514
- serializedResult = JSON.stringify(toolResult);
1515
- } catch {
1516
- serializedResult = `[Unserializable tool result from ${toolName || part.toolCallId}]`;
1517
- }
1518
- const resultEvent: ToolCallResultEvent = {
1519
- type: EventType.TOOL_CALL_RESULT,
1520
- role: "tool",
1521
- messageId: randomUUID(),
1522
- toolCallId: part.toolCallId,
1523
- content: serializedResult,
1524
- };
1525
- subscriber.next(resultEvent);
1526
- break;
1527
- }
1528
-
1529
- case "finish": {
1530
- // Emit run finished event
1531
- const finishedEvent: RunFinishedEvent = {
1532
- type: EventType.RUN_FINISHED,
1533
- threadId: input.threadId,
1534
- runId: input.runId,
1535
- };
1536
- subscriber.next(finishedEvent);
1537
- terminalEventEmitted = true;
1538
-
1539
- // Complete the observable
1540
- subscriber.complete();
1541
- break;
1542
- }
1543
-
1544
- case "error": {
1545
- if (abortController.signal.aborted) {
1546
- break;
1547
- }
1548
- const err = part.error ?? part.message ?? part.cause;
1549
- const runErrorEvent: RunErrorEvent = {
1550
- type: EventType.RUN_ERROR,
1551
- message:
1552
- err instanceof Error
1553
- ? err.message
1554
- : typeof err === "string"
1555
- ? err
1556
- : `AI SDK stream error: ${JSON.stringify(part)}`,
1557
- threadId: input.threadId,
1558
- runId: input.runId,
1559
- } as RunErrorEvent;
1560
- subscriber.next(runErrorEvent);
1561
- terminalEventEmitted = true;
1562
-
1563
- // Handle error
1564
- if (err instanceof Error) subscriber.error(err);
1565
- else
1566
- subscriber.error(
1567
- new Error(
1568
- typeof err === "string" ? err : `AI SDK stream error`,
1569
- ),
1570
- );
1571
- break;
1572
- }
1573
- }
1574
- }
1575
-
1576
- if (!terminalEventEmitted) {
1577
- closeReasoningIfOpen();
1578
- if (abortController.signal.aborted) {
1579
- // Let the runner finalize the stream on stop requests so it can
1580
- // inject consistent closing events and a RUN_FINISHED marker.
1581
- } else {
1582
- const finishedEvent: RunFinishedEvent = {
1583
- type: EventType.RUN_FINISHED,
1584
- threadId: input.threadId,
1585
- runId: input.runId,
1586
- };
1587
- subscriber.next(finishedEvent);
1588
- }
1589
-
1590
- terminalEventEmitted = true;
1591
- subscriber.complete();
1592
- }
1593
- } catch (error) {
1594
- closeReasoningIfOpen();
1595
- if (abortController.signal.aborted) {
1596
- subscriber.complete();
1597
- } else {
1598
- const runErrorEvent: RunErrorEvent = {
1599
- type: EventType.RUN_ERROR,
1600
- message: error instanceof Error ? error.message : String(error),
1601
- threadId: input.threadId,
1602
- runId: input.runId,
1603
- } as RunErrorEvent;
1604
- subscriber.next(runErrorEvent);
1605
- terminalEventEmitted = true;
1606
- subscriber.error(error);
1607
- }
1608
- } finally {
1609
- this.abortController = undefined;
1610
- await Promise.all(mcpClients.map((client) => client.close()));
1611
- }
1612
- })();
1613
-
1614
- // Cleanup function
1615
- return () => {
1616
- // Cleanup MCP clients if stream is unsubscribed
1617
- Promise.all(mcpClients.map((client) => client.close())).catch(() => {
1618
- // Ignore cleanup errors
1619
- });
1620
- };
1621
- });
1622
- }
1623
-
1624
- private runFactory(
1625
- input: RunAgentInput,
1626
- config: BuiltInAgentFactoryConfig,
1627
- ): Observable<BaseEvent> {
1628
- if (this.abortController) {
1629
- throw new Error(
1630
- "Agent is already running. Call abortRun() first or create a new instance.",
1631
- );
1632
- }
1633
-
1634
- // Set synchronously before Observable creation to close TOCTOU window
1635
- this.abortController = new AbortController();
1636
- const controller = this.abortController;
1637
-
1638
- return new Observable<BaseEvent>((subscriber) => {
1639
- const startEvent: RunStartedEvent = {
1640
- type: EventType.RUN_STARTED,
1641
- threadId: input.threadId,
1642
- runId: input.runId,
1643
- };
1644
- subscriber.next(startEvent);
1645
-
1646
- const ctx: AgentFactoryContext = {
1647
- input,
1648
- abortController: controller,
1649
- abortSignal: controller.signal,
1650
- };
1651
-
1652
- (async () => {
1653
- try {
1654
- let events: AsyncIterable<BaseEvent>;
1655
-
1656
- switch (config.type) {
1657
- case "aisdk": {
1658
- const result = await config.factory(ctx);
1659
- events = convertAISDKStream(result.fullStream, controller.signal);
1660
- break;
1661
- }
1662
- case "tanstack": {
1663
- const stream = await config.factory(ctx);
1664
- events = convertTanStackStream(stream, controller.signal);
1665
- break;
1666
- }
1667
- case "custom": {
1668
- events = await config.factory(ctx);
1669
- break;
1670
- }
1671
- default: {
1672
- const _exhaustive: never = config;
1673
- throw new Error(
1674
- `Unknown agent config type: ${(_exhaustive as BuiltInAgentFactoryConfig).type}`,
1675
- );
1676
- }
1677
- }
1678
-
1679
- for await (const event of events) {
1680
- subscriber.next(event);
1681
- }
1682
-
1683
- if (!controller.signal.aborted) {
1684
- const finishedEvent: RunFinishedEvent = {
1685
- type: EventType.RUN_FINISHED,
1686
- threadId: input.threadId,
1687
- runId: input.runId,
1688
- };
1689
- subscriber.next(finishedEvent);
1690
- }
1691
- subscriber.complete();
1692
- } catch (error) {
1693
- if (controller.signal.aborted) {
1694
- subscriber.complete();
1695
- } else {
1696
- const runErrorEvent: RunErrorEvent = {
1697
- type: EventType.RUN_ERROR,
1698
- message: error instanceof Error ? error.message : String(error),
1699
- threadId: input.threadId,
1700
- runId: input.runId,
1701
- } as RunErrorEvent;
1702
- subscriber.next(runErrorEvent);
1703
- subscriber.error(error);
1704
- }
1705
- } finally {
1706
- this.abortController = undefined;
1707
- }
1708
- })();
1709
-
1710
- return () => {
1711
- controller.abort();
1712
- };
1713
- });
1714
- }
1715
-
1716
- clone() {
1717
- const cloned = new BuiltInAgent(this.config);
1718
- // AbstractAgent.middlewares is private in @ag-ui/client — no public accessor exists.
1719
- // This coupling is intentional: clone() must preserve middleware chains.
1720
- // @ts-expect-error accessing private AbstractAgent.middlewares
1721
- cloned.middlewares = [...this.middlewares];
1722
- return cloned;
1723
- }
1724
-
1725
- abortRun(): void {
1726
- this.abortController?.abort();
1727
- }
1728
- }
1729
-
1730
- /**
1731
- * @deprecated Use BuiltInAgent instead
1732
- */
1733
- export class BasicAgent extends BuiltInAgent {
1734
- constructor(config: BuiltInAgentConfiguration) {
1735
- super(config);
1736
- console.warn("BasicAgent is deprecated, use BuiltInAgent instead");
1737
- }
1738
- }
1739
-
1740
- /** @deprecated Use BuiltInAgentClassicConfig instead */
1741
- export type BasicAgentConfiguration = BuiltInAgentClassicConfig;
1742
-
1743
- export * from "./converters";