@copilotkit/runtime 1.55.0-next.8 → 1.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/agent/index.cjs +101 -12
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts.map +1 -1
  5. package/dist/agent/index.d.mts.map +1 -1
  6. package/dist/agent/index.mjs +102 -13
  7. package/dist/agent/index.mjs.map +1 -1
  8. package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs.map +1 -1
  9. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts +4 -841
  10. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts.map +1 -1
  11. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts +4 -841
  12. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts.map +1 -1
  13. package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs.map +1 -1
  14. package/dist/lib/runtime/copilot-runtime.cjs +3 -2
  15. package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
  16. package/dist/lib/runtime/copilot-runtime.d.cts +1 -1
  17. package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
  18. package/dist/lib/runtime/copilot-runtime.d.mts +3 -3
  19. package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
  20. package/dist/lib/runtime/copilot-runtime.mjs +3 -2
  21. package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
  22. package/dist/package.cjs +70 -47
  23. package/dist/package.mjs +70 -47
  24. package/dist/v2/express.cjs +8 -0
  25. package/dist/v2/express.d.cts +5 -0
  26. package/dist/v2/express.d.mts +5 -0
  27. package/dist/v2/express.mjs +5 -0
  28. package/dist/v2/hono.cjs +9 -0
  29. package/dist/v2/hono.d.cts +5 -0
  30. package/dist/v2/hono.d.mts +5 -0
  31. package/dist/v2/hono.mjs +5 -0
  32. package/dist/v2/index.cjs +8 -3
  33. package/dist/v2/index.d.cts +8 -5
  34. package/dist/v2/index.d.mts +8 -5
  35. package/dist/v2/index.mjs +5 -4
  36. package/dist/v2/node.cjs +8 -0
  37. package/dist/v2/node.d.cts +5 -0
  38. package/dist/v2/node.d.mts +5 -0
  39. package/dist/v2/node.mjs +5 -0
  40. package/dist/v2/runtime/core/fetch-cors.cjs +72 -0
  41. package/dist/v2/runtime/core/fetch-cors.cjs.map +1 -0
  42. package/dist/v2/runtime/core/fetch-cors.d.cts +20 -0
  43. package/dist/v2/runtime/core/fetch-cors.d.cts.map +1 -0
  44. package/dist/v2/runtime/core/fetch-cors.d.mts +20 -0
  45. package/dist/v2/runtime/core/fetch-cors.d.mts.map +1 -0
  46. package/dist/v2/runtime/core/fetch-cors.mjs +70 -0
  47. package/dist/v2/runtime/core/fetch-cors.mjs.map +1 -0
  48. package/dist/v2/runtime/core/fetch-handler.cjs +232 -0
  49. package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -0
  50. package/dist/v2/runtime/core/fetch-handler.d.cts +40 -0
  51. package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -0
  52. package/dist/v2/runtime/core/fetch-handler.d.mts +40 -0
  53. package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -0
  54. package/dist/v2/runtime/core/fetch-handler.mjs +231 -0
  55. package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -0
  56. package/dist/v2/runtime/core/fetch-router.cjs +68 -0
  57. package/dist/v2/runtime/core/fetch-router.cjs.map +1 -0
  58. package/dist/v2/runtime/core/fetch-router.mjs +67 -0
  59. package/dist/v2/runtime/core/fetch-router.mjs.map +1 -0
  60. package/dist/v2/runtime/core/hooks.cjs +29 -0
  61. package/dist/v2/runtime/core/hooks.cjs.map +1 -0
  62. package/dist/v2/runtime/core/hooks.d.cts +78 -0
  63. package/dist/v2/runtime/core/hooks.d.cts.map +1 -0
  64. package/dist/v2/runtime/core/hooks.d.mts +78 -0
  65. package/dist/v2/runtime/core/hooks.d.mts.map +1 -0
  66. package/dist/v2/runtime/core/hooks.mjs +25 -0
  67. package/dist/v2/runtime/core/hooks.mjs.map +1 -0
  68. package/dist/v2/runtime/{middleware-sse-parser.cjs → core/middleware-sse-parser.cjs} +2 -2
  69. package/dist/v2/runtime/core/middleware-sse-parser.cjs.map +1 -0
  70. package/dist/v2/runtime/{middleware-sse-parser.d.cts → core/middleware-sse-parser.d.cts} +1 -1
  71. package/dist/v2/runtime/core/middleware-sse-parser.d.cts.map +1 -0
  72. package/dist/v2/runtime/{middleware-sse-parser.d.mts → core/middleware-sse-parser.d.mts} +1 -1
  73. package/dist/v2/runtime/core/middleware-sse-parser.d.mts.map +1 -0
  74. package/dist/v2/runtime/{middleware-sse-parser.mjs → core/middleware-sse-parser.mjs} +1 -1
  75. package/dist/v2/runtime/core/middleware-sse-parser.mjs.map +1 -0
  76. package/dist/v2/runtime/{middleware.cjs → core/middleware.cjs} +2 -2
  77. package/dist/v2/runtime/core/middleware.cjs.map +1 -0
  78. package/dist/v2/runtime/{middleware.d.cts → core/middleware.d.cts} +1 -1
  79. package/dist/v2/runtime/core/middleware.d.cts.map +1 -0
  80. package/dist/v2/runtime/{middleware.d.mts → core/middleware.d.mts} +1 -1
  81. package/dist/v2/runtime/core/middleware.d.mts.map +1 -0
  82. package/dist/v2/runtime/{middleware.mjs → core/middleware.mjs} +1 -1
  83. package/dist/v2/runtime/core/middleware.mjs.map +1 -0
  84. package/dist/v2/runtime/{runtime.cjs → core/runtime.cjs} +35 -10
  85. package/dist/v2/runtime/core/runtime.cjs.map +1 -0
  86. package/dist/v2/runtime/{runtime.d.cts → core/runtime.d.cts} +41 -7
  87. package/dist/v2/runtime/core/runtime.d.cts.map +1 -0
  88. package/dist/v2/runtime/{runtime.d.mts → core/runtime.d.mts} +42 -8
  89. package/dist/v2/runtime/core/runtime.d.mts.map +1 -0
  90. package/dist/v2/runtime/{runtime.mjs → core/runtime.mjs} +36 -11
  91. package/dist/v2/runtime/core/runtime.mjs.map +1 -0
  92. package/dist/v2/runtime/endpoints/express-fetch-bridge.cjs +83 -0
  93. package/dist/v2/runtime/endpoints/express-fetch-bridge.cjs.map +1 -0
  94. package/dist/v2/runtime/endpoints/express-fetch-bridge.mjs +82 -0
  95. package/dist/v2/runtime/endpoints/express-fetch-bridge.mjs.map +1 -0
  96. package/dist/v2/runtime/endpoints/express-single.cjs +35 -181
  97. package/dist/v2/runtime/endpoints/express-single.cjs.map +1 -1
  98. package/dist/v2/runtime/endpoints/express-single.d.cts +35 -2
  99. package/dist/v2/runtime/endpoints/express-single.d.cts.map +1 -1
  100. package/dist/v2/runtime/endpoints/express-single.d.mts +35 -2
  101. package/dist/v2/runtime/endpoints/express-single.d.mts.map +1 -1
  102. package/dist/v2/runtime/endpoints/express-single.mjs +35 -178
  103. package/dist/v2/runtime/endpoints/express-single.mjs.map +1 -1
  104. package/dist/v2/runtime/endpoints/express.cjs +41 -195
  105. package/dist/v2/runtime/endpoints/express.cjs.map +1 -1
  106. package/dist/v2/runtime/endpoints/express.d.cts +26 -4
  107. package/dist/v2/runtime/endpoints/express.d.cts.map +1 -1
  108. package/dist/v2/runtime/endpoints/express.d.mts +26 -4
  109. package/dist/v2/runtime/endpoints/express.d.mts.map +1 -1
  110. package/dist/v2/runtime/endpoints/express.mjs +41 -195
  111. package/dist/v2/runtime/endpoints/express.mjs.map +1 -1
  112. package/dist/v2/runtime/endpoints/hono-single.cjs +11 -123
  113. package/dist/v2/runtime/endpoints/hono-single.cjs.map +1 -1
  114. package/dist/v2/runtime/endpoints/hono-single.d.cts +14 -11
  115. package/dist/v2/runtime/endpoints/hono-single.d.cts.map +1 -1
  116. package/dist/v2/runtime/endpoints/hono-single.d.mts +14 -11
  117. package/dist/v2/runtime/endpoints/hono-single.d.mts.map +1 -1
  118. package/dist/v2/runtime/endpoints/hono-single.mjs +11 -123
  119. package/dist/v2/runtime/endpoints/hono-single.mjs.map +1 -1
  120. package/dist/v2/runtime/endpoints/hono.cjs +23 -237
  121. package/dist/v2/runtime/endpoints/hono.cjs.map +1 -1
  122. package/dist/v2/runtime/endpoints/hono.d.cts +29 -120
  123. package/dist/v2/runtime/endpoints/hono.d.cts.map +1 -1
  124. package/dist/v2/runtime/endpoints/hono.d.mts +29 -120
  125. package/dist/v2/runtime/endpoints/hono.d.mts.map +1 -1
  126. package/dist/v2/runtime/endpoints/hono.mjs +22 -238
  127. package/dist/v2/runtime/endpoints/hono.mjs.map +1 -1
  128. package/dist/v2/runtime/endpoints/index.d.cts +2 -2
  129. package/dist/v2/runtime/endpoints/index.d.mts +2 -2
  130. package/dist/v2/runtime/endpoints/node-fetch-handler.cjs +26 -0
  131. package/dist/v2/runtime/endpoints/node-fetch-handler.cjs.map +1 -0
  132. package/dist/v2/runtime/endpoints/node-fetch-handler.d.cts +12 -0
  133. package/dist/v2/runtime/endpoints/node-fetch-handler.d.cts.map +1 -0
  134. package/dist/v2/runtime/endpoints/node-fetch-handler.d.mts +12 -0
  135. package/dist/v2/runtime/endpoints/node-fetch-handler.d.mts.map +1 -0
  136. package/dist/v2/runtime/endpoints/node-fetch-handler.mjs +24 -0
  137. package/dist/v2/runtime/endpoints/node-fetch-handler.mjs.map +1 -0
  138. package/dist/v2/runtime/endpoints/node.cjs +30 -0
  139. package/dist/v2/runtime/endpoints/node.cjs.map +1 -0
  140. package/dist/v2/runtime/endpoints/node.d.cts +27 -0
  141. package/dist/v2/runtime/endpoints/node.d.cts.map +1 -0
  142. package/dist/v2/runtime/endpoints/node.d.mts +27 -0
  143. package/dist/v2/runtime/endpoints/node.d.mts.map +1 -0
  144. package/dist/v2/runtime/endpoints/node.mjs +30 -0
  145. package/dist/v2/runtime/endpoints/node.mjs.map +1 -0
  146. package/dist/v2/runtime/express.d.cts +3 -0
  147. package/dist/v2/runtime/express.d.mts +3 -0
  148. package/dist/v2/runtime/handlers/get-runtime-info.cjs +2 -1
  149. package/dist/v2/runtime/handlers/get-runtime-info.cjs.map +1 -1
  150. package/dist/v2/runtime/handlers/get-runtime-info.mjs +2 -1
  151. package/dist/v2/runtime/handlers/get-runtime-info.mjs.map +1 -1
  152. package/dist/v2/runtime/handlers/handle-connect.cjs +6 -3
  153. package/dist/v2/runtime/handlers/handle-connect.cjs.map +1 -1
  154. package/dist/v2/runtime/handlers/handle-connect.mjs +6 -3
  155. package/dist/v2/runtime/handlers/handle-connect.mjs.map +1 -1
  156. package/dist/v2/runtime/handlers/handle-run.cjs +6 -3
  157. package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
  158. package/dist/v2/runtime/handlers/handle-run.mjs +6 -3
  159. package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
  160. package/dist/v2/runtime/handlers/handle-stop.cjs.map +1 -1
  161. package/dist/v2/runtime/handlers/handle-stop.mjs.map +1 -1
  162. package/dist/v2/runtime/handlers/handle-transcribe.cjs.map +1 -1
  163. package/dist/v2/runtime/handlers/handle-transcribe.mjs.map +1 -1
  164. package/dist/v2/runtime/handlers/intelligence/connect.cjs.map +1 -1
  165. package/dist/v2/runtime/handlers/intelligence/connect.mjs.map +1 -1
  166. package/dist/v2/runtime/handlers/intelligence/run.cjs +22 -1
  167. package/dist/v2/runtime/handlers/intelligence/run.cjs.map +1 -1
  168. package/dist/v2/runtime/handlers/intelligence/run.mjs +22 -1
  169. package/dist/v2/runtime/handlers/intelligence/run.mjs.map +1 -1
  170. package/dist/v2/runtime/handlers/intelligence/thread-names.cjs +1 -1
  171. package/dist/v2/runtime/handlers/intelligence/thread-names.cjs.map +1 -1
  172. package/dist/v2/runtime/handlers/intelligence/thread-names.mjs +1 -1
  173. package/dist/v2/runtime/handlers/intelligence/thread-names.mjs.map +1 -1
  174. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +21 -6
  175. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
  176. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +21 -6
  177. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
  178. package/dist/v2/runtime/handlers/shared/json-response.cjs +4 -1
  179. package/dist/v2/runtime/handlers/shared/json-response.cjs.map +1 -1
  180. package/dist/v2/runtime/handlers/shared/json-response.mjs +4 -1
  181. package/dist/v2/runtime/handlers/shared/json-response.mjs.map +1 -1
  182. package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs.map +1 -1
  183. package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs.map +1 -1
  184. package/dist/v2/runtime/handlers/sse/connect.cjs.map +1 -1
  185. package/dist/v2/runtime/handlers/sse/connect.mjs.map +1 -1
  186. package/dist/v2/runtime/handlers/sse/run.cjs.map +1 -1
  187. package/dist/v2/runtime/handlers/sse/run.mjs.map +1 -1
  188. package/dist/v2/runtime/hono.d.cts +3 -0
  189. package/dist/v2/runtime/hono.d.mts +3 -0
  190. package/dist/v2/runtime/index.d.cts +16 -4
  191. package/dist/v2/runtime/index.d.cts.map +1 -0
  192. package/dist/v2/runtime/index.d.mts +16 -4
  193. package/dist/v2/runtime/index.d.mts.map +1 -0
  194. package/dist/v2/runtime/intelligence-platform/client.cjs +10 -1
  195. package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
  196. package/dist/v2/runtime/intelligence-platform/client.d.cts +22 -0
  197. package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
  198. package/dist/v2/runtime/intelligence-platform/client.d.mts +22 -0
  199. package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
  200. package/dist/v2/runtime/intelligence-platform/client.mjs +10 -1
  201. package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
  202. package/dist/v2/runtime/node.d.cts +3 -0
  203. package/dist/v2/runtime/node.d.mts +3 -0
  204. package/dist/v2/runtime/open-generative-ui-middleware.cjs +282 -0
  205. package/dist/v2/runtime/open-generative-ui-middleware.cjs.map +1 -0
  206. package/dist/v2/runtime/open-generative-ui-middleware.mjs +280 -0
  207. package/dist/v2/runtime/open-generative-ui-middleware.mjs.map +1 -0
  208. package/dist/v2/runtime/runner/intelligence.cjs +4 -4
  209. package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
  210. package/dist/v2/runtime/runner/intelligence.d.cts +6 -2
  211. package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
  212. package/dist/v2/runtime/runner/intelligence.d.mts +6 -2
  213. package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
  214. package/dist/v2/runtime/runner/intelligence.mjs +4 -4
  215. package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
  216. package/dist/v2/runtime/telemetry/telemetry-client.cjs +37 -0
  217. package/dist/v2/runtime/telemetry/telemetry-client.cjs.map +1 -1
  218. package/dist/v2/runtime/telemetry/telemetry-client.mjs +36 -0
  219. package/dist/v2/runtime/telemetry/telemetry-client.mjs.map +1 -1
  220. package/dist/v2/runtime/telemetry/utils.cjs +15 -0
  221. package/dist/v2/runtime/telemetry/utils.cjs.map +1 -0
  222. package/dist/v2/runtime/telemetry/utils.mjs +14 -0
  223. package/dist/v2/runtime/telemetry/utils.mjs.map +1 -0
  224. package/package.json +81 -48
  225. package/src/agent/__tests__/multimodal.test.ts +176 -0
  226. package/src/agent/index.ts +130 -19
  227. package/src/lib/runtime/agent-integrations/langgraph/agent.ts +3 -3
  228. package/src/lib/runtime/copilot-runtime.ts +1 -0
  229. package/src/v2/express.ts +1 -0
  230. package/src/v2/hono.ts +1 -0
  231. package/src/v2/node.ts +1 -0
  232. package/src/v2/runtime/__tests__/backward-compat.test.ts +261 -0
  233. package/src/v2/runtime/__tests__/code-review-fixes.test.ts +500 -0
  234. package/src/v2/runtime/__tests__/cors-credentials.test.ts +2 -2
  235. package/src/v2/runtime/__tests__/express-adapter.test.ts +188 -0
  236. package/src/v2/runtime/__tests__/express-body-order.test.ts +1 -1
  237. package/src/v2/runtime/__tests__/express-fetch-bridge.test.ts +344 -0
  238. package/src/v2/runtime/__tests__/express-single-sse.test.ts +1 -1
  239. package/src/v2/runtime/__tests__/fetch-cors.test.ts +205 -0
  240. package/src/v2/runtime/__tests__/fetch-handler-validation.test.ts +372 -0
  241. package/src/v2/runtime/__tests__/fetch-handler.test.ts +456 -0
  242. package/src/v2/runtime/__tests__/fetch-router.test.ts +132 -0
  243. package/src/v2/runtime/__tests__/get-runtime-info.test.ts +4 -1
  244. package/src/v2/runtime/__tests__/handle-connect.test.ts +15 -13
  245. package/src/v2/runtime/__tests__/handle-run.test.ts +21 -17
  246. package/src/v2/runtime/__tests__/handle-threads.test.ts +1 -1
  247. package/src/v2/runtime/__tests__/handle-transcribe.test.ts +1 -1
  248. package/src/v2/runtime/__tests__/hono-adapter.test.ts +150 -0
  249. package/src/v2/runtime/__tests__/hooks-edge-cases.test.ts +457 -0
  250. package/src/v2/runtime/__tests__/hooks.test.ts +557 -0
  251. package/src/v2/runtime/__tests__/integration/bun/bun-servers.integration.test.ts +27 -0
  252. package/src/v2/runtime/__tests__/integration/bun/elysia-multi.ts +32 -0
  253. package/src/v2/runtime/__tests__/integration/bun/elysia-single.ts +33 -0
  254. package/src/v2/runtime/__tests__/integration/bun/hono-bun-multi.ts +25 -0
  255. package/src/v2/runtime/__tests__/integration/bun/hono-bun-single.ts +32 -0
  256. package/src/v2/runtime/__tests__/integration/helpers/create-test-runtime.ts +15 -0
  257. package/src/v2/runtime/__tests__/integration/helpers/sse-reader.ts +45 -0
  258. package/src/v2/runtime/__tests__/integration/helpers/test-agent.ts +58 -0
  259. package/src/v2/runtime/__tests__/integration/node-servers.integration.test.ts +39 -0
  260. package/src/v2/runtime/__tests__/integration/servers/express-multi.ts +35 -0
  261. package/src/v2/runtime/__tests__/integration/servers/express-single.ts +36 -0
  262. package/src/v2/runtime/__tests__/integration/servers/fetch-direct.ts +39 -0
  263. package/src/v2/runtime/__tests__/integration/servers/hono-multi.ts +30 -0
  264. package/src/v2/runtime/__tests__/integration/servers/hono-single.ts +37 -0
  265. package/src/v2/runtime/__tests__/integration/servers/node-multi.ts +45 -0
  266. package/src/v2/runtime/__tests__/integration/servers/node-single.ts +46 -0
  267. package/src/v2/runtime/__tests__/integration/servers/types.ts +18 -0
  268. package/src/v2/runtime/__tests__/integration/suites/multi-endpoint.suite.ts +358 -0
  269. package/src/v2/runtime/__tests__/integration/suites/single-endpoint.suite.ts +363 -0
  270. package/src/v2/runtime/__tests__/middleware-express.test.ts +25 -23
  271. package/src/v2/runtime/__tests__/middleware-single-express.test.ts +25 -23
  272. package/src/v2/runtime/__tests__/middleware-single.test.ts +1 -1
  273. package/src/v2/runtime/__tests__/middleware-sse-parser.test.ts +1 -1
  274. package/src/v2/runtime/__tests__/middleware.test.ts +1 -2
  275. package/src/v2/runtime/__tests__/node-fetch-handler.test.ts +157 -0
  276. package/src/v2/runtime/__tests__/open-generative-ui-middleware.e2e.test.ts +728 -0
  277. package/src/v2/runtime/__tests__/router-edge-cases.test.ts +217 -0
  278. package/src/v2/runtime/__tests__/routing-express.test.ts +1 -1
  279. package/src/v2/runtime/__tests__/routing-single-express.test.ts +1 -1
  280. package/src/v2/runtime/__tests__/routing-single.test.ts +1 -1
  281. package/src/v2/runtime/__tests__/routing.test.ts +1 -1
  282. package/src/v2/runtime/__tests__/runtime.test.ts +110 -1
  283. package/src/v2/runtime/__tests__/telemetry.test.ts +62 -1
  284. package/src/v2/runtime/core/fetch-cors.ts +136 -0
  285. package/src/v2/runtime/core/fetch-handler.ts +415 -0
  286. package/src/v2/runtime/core/fetch-router.ts +112 -0
  287. package/src/v2/runtime/core/hooks.ts +151 -0
  288. package/src/v2/runtime/{runtime.ts → core/runtime.ts} +79 -10
  289. package/src/v2/runtime/endpoints/express-fetch-bridge.ts +137 -0
  290. package/src/v2/runtime/endpoints/express-single.ts +42 -219
  291. package/src/v2/runtime/endpoints/express.ts +128 -230
  292. package/src/v2/runtime/endpoints/hono-single.ts +19 -171
  293. package/src/v2/runtime/endpoints/hono.ts +45 -270
  294. package/src/v2/runtime/endpoints/node-fetch-handler.ts +48 -0
  295. package/src/v2/runtime/endpoints/node.ts +28 -0
  296. package/src/v2/runtime/handlers/get-runtime-info.ts +3 -2
  297. package/src/v2/runtime/handlers/handle-connect.ts +7 -4
  298. package/src/v2/runtime/handlers/handle-run.ts +7 -4
  299. package/src/v2/runtime/handlers/handle-stop.ts +1 -1
  300. package/src/v2/runtime/handlers/handle-transcribe.ts +1 -1
  301. package/src/v2/runtime/handlers/intelligence/connect.ts +1 -1
  302. package/src/v2/runtime/handlers/intelligence/run.ts +31 -1
  303. package/src/v2/runtime/handlers/intelligence/thread-names.ts +2 -2
  304. package/src/v2/runtime/handlers/intelligence/threads.ts +1 -1
  305. package/src/v2/runtime/handlers/shared/agent-utils.ts +29 -10
  306. package/src/v2/runtime/handlers/shared/json-response.ts +4 -1
  307. package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +1 -1
  308. package/src/v2/runtime/handlers/sse/connect.ts +1 -1
  309. package/src/v2/runtime/handlers/sse/run.ts +1 -1
  310. package/src/v2/runtime/hono.ts +2 -0
  311. package/src/v2/runtime/index.ts +27 -1
  312. package/src/v2/runtime/intelligence-platform/client.ts +50 -1
  313. package/src/v2/runtime/node.ts +6 -0
  314. package/src/v2/runtime/open-generative-ui-middleware.ts +373 -0
  315. package/src/v2/runtime/runner/intelligence.ts +14 -4
  316. package/src/v2/runtime/telemetry/telemetry-client.ts +56 -0
  317. package/src/v2/runtime/telemetry/utils.ts +15 -0
  318. package/tsdown.config.ts +8 -1
  319. package/vitest.config.mjs +2 -5
  320. package/.eslintrc.js +0 -7
  321. package/dist/v2/runtime/endpoints/express-utils.cjs +0 -119
  322. package/dist/v2/runtime/endpoints/express-utils.cjs.map +0 -1
  323. package/dist/v2/runtime/endpoints/express-utils.mjs +0 -117
  324. package/dist/v2/runtime/endpoints/express-utils.mjs.map +0 -1
  325. package/dist/v2/runtime/handlers/intelligence/threads.cjs +0 -159
  326. package/dist/v2/runtime/handlers/intelligence/threads.cjs.map +0 -1
  327. package/dist/v2/runtime/handlers/intelligence/threads.mjs +0 -154
  328. package/dist/v2/runtime/handlers/intelligence/threads.mjs.map +0 -1
  329. package/dist/v2/runtime/middleware-sse-parser.cjs.map +0 -1
  330. package/dist/v2/runtime/middleware-sse-parser.d.cts.map +0 -1
  331. package/dist/v2/runtime/middleware-sse-parser.d.mts.map +0 -1
  332. package/dist/v2/runtime/middleware-sse-parser.mjs.map +0 -1
  333. package/dist/v2/runtime/middleware.cjs.map +0 -1
  334. package/dist/v2/runtime/middleware.d.cts.map +0 -1
  335. package/dist/v2/runtime/middleware.d.mts.map +0 -1
  336. package/dist/v2/runtime/middleware.mjs.map +0 -1
  337. package/dist/v2/runtime/runtime.cjs.map +0 -1
  338. package/dist/v2/runtime/runtime.d.cts.map +0 -1
  339. package/dist/v2/runtime/runtime.d.mts.map +0 -1
  340. package/dist/v2/runtime/runtime.mjs.map +0 -1
  341. package/src/v2/runtime/__tests__/express-abort-signal.test.ts +0 -25
  342. package/src/v2/runtime/endpoints/express-utils.ts +0 -182
  343. package/src/v2/runtime/handler.ts +0 -3
  344. /package/src/v2/runtime/{middleware-sse-parser.ts → core/middleware-sse-parser.ts} +0 -0
  345. /package/src/v2/runtime/{middleware.ts → core/middleware.ts} +0 -0
@@ -0,0 +1,217 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { matchRoute } from "../core/fetch-router";
3
+
4
+ /* ------------------------------------------------------------------------------------------------
5
+ * basePath = "/"
6
+ * --------------------------------------------------------------------------------------------- */
7
+
8
+ describe("matchRoute — basePath is /", () => {
9
+ it("matches /info", () => {
10
+ const result = matchRoute("/info", "/");
11
+ expect(result).toEqual({ method: "info" });
12
+ });
13
+
14
+ it("matches /agent/:id/run", () => {
15
+ const result = matchRoute("/agent/myAgent/run", "/");
16
+ expect(result).toEqual({ method: "agent/run", agentId: "myAgent" });
17
+ });
18
+
19
+ it("matches /agent/:id/connect", () => {
20
+ const result = matchRoute("/agent/myAgent/connect", "/");
21
+ expect(result).toEqual({ method: "agent/connect", agentId: "myAgent" });
22
+ });
23
+
24
+ it("matches /agent/:id/stop/:threadId", () => {
25
+ const result = matchRoute("/agent/myAgent/stop/t1", "/");
26
+ expect(result).toEqual({
27
+ method: "agent/stop",
28
+ agentId: "myAgent",
29
+ threadId: "t1",
30
+ });
31
+ });
32
+
33
+ it("matches /transcribe", () => {
34
+ const result = matchRoute("/transcribe", "/");
35
+ expect(result).toEqual({ method: "transcribe" });
36
+ });
37
+
38
+ it("returns null for unknown path", () => {
39
+ const result = matchRoute("/unknown", "/");
40
+ expect(result).toBeNull();
41
+ });
42
+ });
43
+
44
+ /* ------------------------------------------------------------------------------------------------
45
+ * Trailing slash normalization
46
+ * --------------------------------------------------------------------------------------------- */
47
+
48
+ describe("matchRoute — trailing slash normalization", () => {
49
+ it("basePath with trailing slash matches", () => {
50
+ const result = matchRoute("/api/copilotkit/info", "/api/copilotkit/");
51
+ expect(result).toEqual({ method: "info" });
52
+ });
53
+
54
+ it("basePath without trailing slash matches", () => {
55
+ const result = matchRoute("/api/copilotkit/info", "/api/copilotkit");
56
+ expect(result).toEqual({ method: "info" });
57
+ });
58
+ });
59
+
60
+ /* ------------------------------------------------------------------------------------------------
61
+ * URL decoding
62
+ * --------------------------------------------------------------------------------------------- */
63
+
64
+ describe("matchRoute — URL decoding", () => {
65
+ it("decodes URL-encoded agentId", () => {
66
+ const result = matchRoute("/api/agent/my%20agent/run", "/api");
67
+ expect(result).toEqual({ method: "agent/run", agentId: "my agent" });
68
+ });
69
+
70
+ it("decodes URL-encoded threadId", () => {
71
+ const result = matchRoute("/api/agent/myAgent/stop/thread%2F123", "/api");
72
+ expect(result).toEqual({
73
+ method: "agent/stop",
74
+ agentId: "myAgent",
75
+ threadId: "thread/123",
76
+ });
77
+ });
78
+
79
+ it("handles agentId with special characters", () => {
80
+ const result = matchRoute("/api/agent/agent%40domain.com/run", "/api");
81
+ expect(result).toEqual({
82
+ method: "agent/run",
83
+ agentId: "agent@domain.com",
84
+ });
85
+ });
86
+
87
+ it("handles already-decoded agentId", () => {
88
+ const result = matchRoute("/api/agent/simple-agent/run", "/api");
89
+ expect(result).toEqual({ method: "agent/run", agentId: "simple-agent" });
90
+ });
91
+ });
92
+
93
+ /* ------------------------------------------------------------------------------------------------
94
+ * Suffix matching (no basePath)
95
+ * --------------------------------------------------------------------------------------------- */
96
+
97
+ describe("matchRoute — suffix matching (no basePath)", () => {
98
+ it("matches info as last segment of any path", () => {
99
+ const result = matchRoute("/some/deeply/nested/prefix/info");
100
+ expect(result).toEqual({ method: "info" });
101
+ });
102
+
103
+ it("matches transcribe as last segment", () => {
104
+ const result = matchRoute("/prefix/transcribe");
105
+ expect(result).toEqual({ method: "transcribe" });
106
+ });
107
+
108
+ it("matches agent/:id/run as trailing pattern", () => {
109
+ const result = matchRoute("/prefix/agent/myAgent/run");
110
+ expect(result).toEqual({ method: "agent/run", agentId: "myAgent" });
111
+ });
112
+
113
+ it("matches agent/:id/connect as trailing pattern", () => {
114
+ const result = matchRoute("/prefix/agent/myAgent/connect");
115
+ expect(result).toEqual({ method: "agent/connect", agentId: "myAgent" });
116
+ });
117
+
118
+ it("matches agent/:id/stop/:threadId as trailing pattern", () => {
119
+ const result = matchRoute("/prefix/agent/myAgent/stop/t1");
120
+ expect(result).toEqual({
121
+ method: "agent/stop",
122
+ agentId: "myAgent",
123
+ threadId: "t1",
124
+ });
125
+ });
126
+
127
+ it("returns null for no matching suffix", () => {
128
+ const result = matchRoute("/some/random/path/here");
129
+ expect(result).toBeNull();
130
+ });
131
+
132
+ it("returns null for empty path", () => {
133
+ const result = matchRoute("/");
134
+ expect(result).toBeNull();
135
+ });
136
+ });
137
+
138
+ /* ------------------------------------------------------------------------------------------------
139
+ * basePath boundary matching
140
+ * --------------------------------------------------------------------------------------------- */
141
+
142
+ describe("matchRoute — basePath boundary", () => {
143
+ it("does not match if basePath is a prefix but not at segment boundary", () => {
144
+ // /apicopilotkit/info should NOT match basePath /api
145
+ const result = matchRoute("/apicopilotkit/info", "/api");
146
+ expect(result).toBeNull();
147
+ });
148
+
149
+ it("matches when basePath is exact prefix at segment boundary", () => {
150
+ const result = matchRoute("/api/info", "/api");
151
+ expect(result).toEqual({ method: "info" });
152
+ });
153
+
154
+ it("basePath matches exactly with no trailing path", () => {
155
+ // /api with basePath /api → remainder is "/" → no match (no known route for /)
156
+ const result = matchRoute("/api", "/api");
157
+ expect(result).toBeNull();
158
+ });
159
+
160
+ it("returns null when path does not start with basePath", () => {
161
+ const result = matchRoute("/other/info", "/api");
162
+ expect(result).toBeNull();
163
+ });
164
+ });
165
+
166
+ /* ------------------------------------------------------------------------------------------------
167
+ * Edge cases: segments and special patterns
168
+ * --------------------------------------------------------------------------------------------- */
169
+
170
+ describe("matchRoute — segment edge cases", () => {
171
+ it("handles double slashes by filtering empty segments", () => {
172
+ // /api//info → segments: ["api", "info"] after filter(Boolean)
173
+ const result = matchRoute("/api//info", "/api");
174
+ expect(result).toEqual({ method: "info" });
175
+ });
176
+
177
+ it("handles path with only basePath + slash", () => {
178
+ const result = matchRoute("/api/", "/api");
179
+ expect(result).toBeNull();
180
+ });
181
+
182
+ it("matches with deep basePath", () => {
183
+ const result = matchRoute("/v1/api/copilotkit/info", "/v1/api/copilotkit");
184
+ expect(result).toEqual({ method: "info" });
185
+ });
186
+
187
+ it("matches agent route with deep basePath", () => {
188
+ const result = matchRoute(
189
+ "/v1/api/copilotkit/agent/default/run",
190
+ "/v1/api/copilotkit",
191
+ );
192
+ expect(result).toEqual({ method: "agent/run", agentId: "default" });
193
+ });
194
+
195
+ it("agentId with hyphens, underscores, and dots", () => {
196
+ const result = matchRoute("/api/agent/my-agent_v2.0/run", "/api");
197
+ expect(result).toEqual({
198
+ method: "agent/run",
199
+ agentId: "my-agent_v2.0",
200
+ });
201
+ });
202
+
203
+ it("single segment path without basePath matches info", () => {
204
+ const result = matchRoute("/info");
205
+ expect(result).toEqual({ method: "info" });
206
+ });
207
+
208
+ it("case-sensitive matching (INFO does not match info)", () => {
209
+ const result = matchRoute("/api/INFO", "/api");
210
+ expect(result).toBeNull();
211
+ });
212
+
213
+ it("case-sensitive matching (Agent vs agent)", () => {
214
+ const result = matchRoute("/api/Agent/default/run", "/api");
215
+ expect(result).toBeNull();
216
+ });
217
+ });
@@ -5,7 +5,7 @@ import type { AbstractAgent } from "@ag-ui/client";
5
5
  import { Observable, of } from "rxjs";
6
6
 
7
7
  import { createCopilotEndpointExpress } from "../express";
8
- import { CopilotRuntime } from "../runtime";
8
+ import { CopilotRuntime } from "../core/runtime";
9
9
 
10
10
  vi.mock("../handlers/handle-run", () => ({
11
11
  handleRunAgent: vi
@@ -5,7 +5,7 @@ import type { AbstractAgent } from "@ag-ui/client";
5
5
  import { Observable, of } from "rxjs";
6
6
 
7
7
  import { createCopilotEndpointSingleRouteExpress } from "../express";
8
- import { CopilotRuntime } from "../runtime";
8
+ import { CopilotRuntime } from "../core/runtime";
9
9
 
10
10
  vi.mock("../handlers/handle-run", () => ({
11
11
  handleRunAgent: vi
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
2
2
  import type { AbstractAgent } from "@ag-ui/client";
3
3
 
4
4
  import { createCopilotEndpointSingleRoute } from "../endpoints";
5
- import { CopilotRuntime } from "../runtime";
5
+ import { CopilotRuntime } from "../core/runtime";
6
6
 
7
7
  describe("CopilotEndpointSingleRoute routing", () => {
8
8
  const createMockRuntime = () => {
@@ -1,5 +1,5 @@
1
1
  import { createCopilotEndpoint } from "../endpoints";
2
- import { CopilotRuntime } from "../runtime";
2
+ import { CopilotRuntime } from "../core/runtime";
3
3
  import { describe, it, expect } from "vitest";
4
4
  import type { AbstractAgent } from "@ag-ui/client";
5
5
 
@@ -4,7 +4,7 @@ import {
4
4
  CopilotIntelligenceRuntime,
5
5
  CopilotRuntime,
6
6
  CopilotSseRuntime,
7
- } from "../runtime";
7
+ } from "../core/runtime";
8
8
  import type { CopilotKitIntelligence } from "../intelligence-platform";
9
9
  import { InMemoryAgentRunner } from "../runner/in-memory";
10
10
  import { IntelligenceAgentRunner } from "../runner/intelligence";
@@ -120,4 +120,113 @@ describe("runtime construction", () => {
120
120
  .identifyUser,
121
121
  ).toBeUndefined();
122
122
  });
123
+
124
+ it("defaults lockTtlSeconds to 20 and lockHeartbeatIntervalSeconds to 15", () => {
125
+ const sdk = createMockIntelligence();
126
+
127
+ const runtime = new CopilotIntelligenceRuntime({
128
+ agents,
129
+ intelligence: sdk,
130
+ identifyUser,
131
+ });
132
+
133
+ expect(runtime.lockTtlSeconds).toBe(20);
134
+ expect(runtime.lockHeartbeatIntervalSeconds).toBe(15);
135
+ });
136
+
137
+ it("clamps lockTtlSeconds to a maximum of 3600 (1 hour)", () => {
138
+ const sdk = createMockIntelligence();
139
+
140
+ const runtime = new CopilotIntelligenceRuntime({
141
+ agents,
142
+ intelligence: sdk,
143
+ identifyUser,
144
+ lockTtlSeconds: 7200,
145
+ });
146
+
147
+ expect(runtime.lockTtlSeconds).toBe(3600);
148
+ });
149
+
150
+ it("clamps lockHeartbeatIntervalSeconds to a maximum of 3000 (50 minutes)", () => {
151
+ const sdk = createMockIntelligence();
152
+
153
+ const runtime = new CopilotIntelligenceRuntime({
154
+ agents,
155
+ intelligence: sdk,
156
+ identifyUser,
157
+ lockHeartbeatIntervalSeconds: 5000,
158
+ });
159
+
160
+ expect(runtime.lockHeartbeatIntervalSeconds).toBe(3000);
161
+ });
162
+
163
+ it("uses provided values when they are within allowed range", () => {
164
+ const sdk = createMockIntelligence();
165
+
166
+ const runtime = new CopilotIntelligenceRuntime({
167
+ agents,
168
+ intelligence: sdk,
169
+ identifyUser,
170
+ lockTtlSeconds: 30,
171
+ });
172
+
173
+ expect(runtime.lockTtlSeconds).toBe(30);
174
+ expect(runtime.lockHeartbeatIntervalSeconds).toBe(15);
175
+ });
176
+
177
+ it("stores lock config on CopilotIntelligenceRuntime", () => {
178
+ const sdk = createMockIntelligence();
179
+
180
+ const runtime = new CopilotIntelligenceRuntime({
181
+ agents,
182
+ intelligence: sdk,
183
+ identifyUser,
184
+ lockTtlSeconds: 30,
185
+ lockKeyPrefix: "custom",
186
+ lockHeartbeatIntervalSeconds: 10,
187
+ });
188
+
189
+ expect(runtime.lockTtlSeconds).toBe(30);
190
+ expect(runtime.lockKeyPrefix).toBe("custom");
191
+ expect(runtime.lockHeartbeatIntervalSeconds).toBe(10);
192
+ });
193
+
194
+ it("forwards lock config through the CopilotRuntime intelligence shim", () => {
195
+ const sdk = createMockIntelligence();
196
+
197
+ const runtime = new CopilotRuntime({
198
+ agents,
199
+ intelligence: sdk,
200
+ identifyUser,
201
+ lockTtlSeconds: 60,
202
+ lockKeyPrefix: "agent",
203
+ lockHeartbeatIntervalSeconds: 20,
204
+ });
205
+
206
+ expect(
207
+ (runtime as CopilotRuntime & { lockTtlSeconds?: number }).lockTtlSeconds,
208
+ ).toBe(60);
209
+ expect(
210
+ (runtime as CopilotRuntime & { lockKeyPrefix?: string }).lockKeyPrefix,
211
+ ).toBe("agent");
212
+ expect(
213
+ (runtime as CopilotRuntime & { lockHeartbeatIntervalSeconds?: number })
214
+ .lockHeartbeatIntervalSeconds,
215
+ ).toBe(20);
216
+ });
217
+
218
+ it("exposes lock config as undefined for SSE runtimes", () => {
219
+ const runtime = new CopilotRuntime({ agents });
220
+
221
+ expect(
222
+ (runtime as CopilotRuntime & { lockTtlSeconds?: number }).lockTtlSeconds,
223
+ ).toBeUndefined();
224
+ expect(
225
+ (runtime as CopilotRuntime & { lockKeyPrefix?: string }).lockKeyPrefix,
226
+ ).toBeUndefined();
227
+ expect(
228
+ (runtime as CopilotRuntime & { lockHeartbeatIntervalSeconds?: number })
229
+ .lockHeartbeatIntervalSeconds,
230
+ ).toBeUndefined();
231
+ });
123
232
  });
@@ -2,15 +2,27 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
2
  import { TelemetryClient } from "../telemetry/telemetry-client";
3
3
  import scarfClient from "../telemetry/scarf-client";
4
4
 
5
+ const { segmentTrackMock } = vi.hoisted(() => ({
6
+ segmentTrackMock: vi.fn(),
7
+ }));
8
+
9
+ vi.mock("@segment/analytics-node", () => ({
10
+ Analytics: vi.fn().mockImplementation(() => ({
11
+ track: segmentTrackMock,
12
+ })),
13
+ }));
14
+
5
15
  describe("TelemetryClient", () => {
6
16
  let scarfSpy: ReturnType<typeof vi.spyOn>;
7
17
 
8
18
  beforeEach(() => {
9
19
  scarfSpy = vi.spyOn(scarfClient, "logEvent").mockResolvedValue(undefined);
20
+ segmentTrackMock.mockClear();
10
21
  });
11
22
 
12
23
  afterEach(() => {
13
- vi.restoreAllMocks();
24
+ scarfSpy.mockRestore();
25
+ segmentTrackMock.mockClear();
14
26
  });
15
27
 
16
28
  it("sends event to scarf when sampled in", async () => {
@@ -32,6 +44,33 @@ describe("TelemetryClient", () => {
32
44
  });
33
45
  });
34
46
 
47
+ it("sends event with properties to segment when sampled in", async () => {
48
+ vi.spyOn(Math, "random").mockReturnValue(0);
49
+ const client = new TelemetryClient({
50
+ telemetryDisabled: false,
51
+ sampleRate: 1,
52
+ });
53
+
54
+ await client.capture("oss.runtime.instance_created", {
55
+ actionsAmount: 5,
56
+ endpointTypes: ["rest"],
57
+ endpointsAmount: 2,
58
+ "cloud.api_key_provided": true,
59
+ "cloud.public_api_key": "pk_test_123",
60
+ });
61
+
62
+ expect(segmentTrackMock).toHaveBeenCalledTimes(1);
63
+ const call = segmentTrackMock.mock.calls[0][0];
64
+ expect(call.event).toBe("oss.runtime.instance_created");
65
+ expect(call.anonymousId).toMatch(/^anon_/);
66
+ expect(call.properties).toMatchObject({
67
+ actionsAmount: 5,
68
+ endpointsAmount: 2,
69
+ "cloud.api_key_provided": true,
70
+ "cloud.public_api_key": "pk_test_123",
71
+ });
72
+ });
73
+
35
74
  it("only sends event name to scarf, not properties", async () => {
36
75
  const client = new TelemetryClient({
37
76
  telemetryDisabled: false,
@@ -67,6 +106,7 @@ describe("TelemetryClient", () => {
67
106
  });
68
107
 
69
108
  expect(scarfSpy).not.toHaveBeenCalled();
109
+ expect(segmentTrackMock).not.toHaveBeenCalled();
70
110
  });
71
111
 
72
112
  it("does not send events when sampled out", async () => {
@@ -84,6 +124,7 @@ describe("TelemetryClient", () => {
84
124
  });
85
125
 
86
126
  expect(scarfSpy).not.toHaveBeenCalled();
127
+ expect(segmentTrackMock).not.toHaveBeenCalled();
87
128
  });
88
129
 
89
130
  it("respects sample rate boundary", async () => {
@@ -98,6 +139,26 @@ describe("TelemetryClient", () => {
98
139
  expect(scarfSpy).toHaveBeenCalled();
99
140
  });
100
141
 
142
+ it("includes global properties in segment track call", async () => {
143
+ vi.spyOn(Math, "random").mockReturnValue(0);
144
+ const client = new TelemetryClient({
145
+ telemetryDisabled: false,
146
+ sampleRate: 1,
147
+ });
148
+
149
+ client.setGlobalProperties({ "copilotkit.package.name": "test-pkg" });
150
+
151
+ await client.capture("oss.runtime.instance_created", {
152
+ actionsAmount: 1,
153
+ endpointTypes: [],
154
+ endpointsAmount: 0,
155
+ "cloud.api_key_provided": false,
156
+ });
157
+
158
+ const call = segmentTrackMock.mock.calls[0][0];
159
+ expect(call.properties["copilotkit.package.name"]).toBe("test-pkg");
160
+ });
161
+
101
162
  it("throws when sample rate is out of range", () => {
102
163
  expect(() => new TelemetryClient({ sampleRate: 1.5 })).toThrow(
103
164
  "Sample rate must be between 0 and 1",
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Built-in CORS utility for framework-agnostic CopilotKit runtime handler.
3
+ *
4
+ * This is a lightweight CORS implementation for web-standard
5
+ * Request/Response. It's optional — if your framework already handles CORS,
6
+ * pass `cors: false` or omit it.
7
+ */
8
+
9
+ export interface CopilotCorsConfig {
10
+ origin?: string | string[] | ((origin: string) => string | null);
11
+ credentials?: boolean;
12
+ allowMethods?: string[];
13
+ allowHeaders?: string[];
14
+ exposeHeaders?: string[];
15
+ maxAge?: number;
16
+ }
17
+
18
+ const DEFAULT_METHODS = [
19
+ "GET",
20
+ "HEAD",
21
+ "PUT",
22
+ "POST",
23
+ "DELETE",
24
+ "PATCH",
25
+ "OPTIONS",
26
+ ];
27
+ const DEFAULT_HEADERS = ["*"];
28
+
29
+ function resolveOrigin(
30
+ config: CopilotCorsConfig,
31
+ requestOrigin: string | null,
32
+ ): string | null {
33
+ const { origin } = config;
34
+ if (!origin) return "*";
35
+
36
+ if (typeof origin === "string") return origin;
37
+
38
+ if (Array.isArray(origin)) {
39
+ if (!requestOrigin) return null;
40
+ return origin.includes(requestOrigin) ? requestOrigin : null;
41
+ }
42
+
43
+ if (typeof origin === "function") {
44
+ return requestOrigin ? origin(requestOrigin) : null;
45
+ }
46
+
47
+ return "*";
48
+ }
49
+
50
+ function setCorsHeaders(
51
+ headers: Headers,
52
+ config: CopilotCorsConfig,
53
+ requestOrigin: string | null,
54
+ ): void {
55
+ let allowedOrigin = resolveOrigin(config, requestOrigin);
56
+ if (!allowedOrigin) return;
57
+
58
+ // Per the Fetch spec, Access-Control-Allow-Origin: * combined with
59
+ // Access-Control-Allow-Credentials: true causes browsers to reject the
60
+ // response. Auto-resolve wildcard to the request origin when credentials
61
+ // are enabled; if there is no request origin, skip CORS entirely.
62
+ if (config.credentials && allowedOrigin === "*") {
63
+ if (requestOrigin) {
64
+ allowedOrigin = requestOrigin;
65
+ } else {
66
+ return;
67
+ }
68
+ }
69
+
70
+ headers.set("Access-Control-Allow-Origin", allowedOrigin);
71
+
72
+ if (config.credentials) {
73
+ headers.set("Access-Control-Allow-Credentials", "true");
74
+ }
75
+
76
+ if (config.exposeHeaders?.length) {
77
+ headers.set(
78
+ "Access-Control-Expose-Headers",
79
+ config.exposeHeaders.join(", "),
80
+ );
81
+ }
82
+
83
+ // Vary on Origin when it's not a fixed wildcard
84
+ if (allowedOrigin !== "*") {
85
+ headers.append("Vary", "Origin");
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Handle CORS preflight (OPTIONS) requests.
91
+ * Returns a 204 Response if it's a preflight, or null if not.
92
+ */
93
+ export function handleCors(
94
+ request: Request,
95
+ config: CopilotCorsConfig,
96
+ ): Response | null {
97
+ if (request.method !== "OPTIONS") return null;
98
+
99
+ const requestOrigin = request.headers.get("origin");
100
+ const headers = new Headers();
101
+
102
+ setCorsHeaders(headers, config, requestOrigin);
103
+
104
+ const methods = config.allowMethods ?? DEFAULT_METHODS;
105
+ headers.set("Access-Control-Allow-Methods", methods.join(", "));
106
+
107
+ const allowHeaders = config.allowHeaders ?? DEFAULT_HEADERS;
108
+ headers.set("Access-Control-Allow-Headers", allowHeaders.join(", "));
109
+
110
+ if (config.maxAge != null) {
111
+ headers.set("Access-Control-Max-Age", String(config.maxAge));
112
+ }
113
+
114
+ // Vary headers for correct CDN caching of preflight responses
115
+ headers.append("Vary", "Access-Control-Request-Headers");
116
+ headers.append("Vary", "Access-Control-Request-Method");
117
+
118
+ return new Response(null, { status: 204, headers });
119
+ }
120
+
121
+ /**
122
+ * Add CORS headers to an existing response.
123
+ */
124
+ export function addCorsHeaders(
125
+ response: Response,
126
+ config: CopilotCorsConfig,
127
+ requestOrigin: string | null,
128
+ ): Response {
129
+ const headers = new Headers(response.headers);
130
+ setCorsHeaders(headers, config, requestOrigin);
131
+ return new Response(response.body, {
132
+ status: response.status,
133
+ statusText: response.statusText,
134
+ headers,
135
+ });
136
+ }