@copilotkit/runtime 1.69.0 → 1.69.1

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 (506) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +1 -15
  2. package/dist/agents/langgraph/events.cjs +1 -1
  3. package/dist/agents/langgraph/events.cjs.map +1 -1
  4. package/dist/agents/langgraph/events.mjs +1 -1
  5. package/dist/agents/langgraph/events.mjs.map +1 -1
  6. package/dist/graphql/inputs/action.input.cjs +1 -1
  7. package/dist/graphql/inputs/action.input.cjs.map +1 -1
  8. package/dist/graphql/inputs/action.input.d.cts +1 -1
  9. package/dist/graphql/inputs/action.input.d.cts.map +1 -1
  10. package/dist/graphql/inputs/action.input.d.mts +1 -1
  11. package/dist/graphql/inputs/action.input.d.mts.map +1 -1
  12. package/dist/graphql/inputs/action.input.mjs +1 -1
  13. package/dist/graphql/inputs/action.input.mjs.map +1 -1
  14. package/dist/graphql/inputs/agent-session.input.cjs +1 -1
  15. package/dist/graphql/inputs/agent-session.input.cjs.map +1 -1
  16. package/dist/graphql/inputs/agent-session.input.d.cts +1 -1
  17. package/dist/graphql/inputs/agent-session.input.d.cts.map +1 -1
  18. package/dist/graphql/inputs/agent-session.input.d.mts +1 -1
  19. package/dist/graphql/inputs/agent-session.input.d.mts.map +1 -1
  20. package/dist/graphql/inputs/agent-session.input.mjs +1 -1
  21. package/dist/graphql/inputs/agent-session.input.mjs.map +1 -1
  22. package/dist/graphql/inputs/agent-state.input.cjs +1 -1
  23. package/dist/graphql/inputs/agent-state.input.cjs.map +1 -1
  24. package/dist/graphql/inputs/agent-state.input.d.cts +1 -1
  25. package/dist/graphql/inputs/agent-state.input.d.cts.map +1 -1
  26. package/dist/graphql/inputs/agent-state.input.d.mts +1 -1
  27. package/dist/graphql/inputs/agent-state.input.d.mts.map +1 -1
  28. package/dist/graphql/inputs/agent-state.input.mjs +1 -1
  29. package/dist/graphql/inputs/agent-state.input.mjs.map +1 -1
  30. package/dist/graphql/inputs/cloud-guardrails.input.cjs +1 -1
  31. package/dist/graphql/inputs/cloud-guardrails.input.cjs.map +1 -1
  32. package/dist/graphql/inputs/cloud-guardrails.input.mjs +1 -1
  33. package/dist/graphql/inputs/cloud-guardrails.input.mjs.map +1 -1
  34. package/dist/graphql/inputs/cloud.input.cjs +1 -1
  35. package/dist/graphql/inputs/cloud.input.cjs.map +1 -1
  36. package/dist/graphql/inputs/cloud.input.mjs +1 -1
  37. package/dist/graphql/inputs/cloud.input.mjs.map +1 -1
  38. package/dist/graphql/inputs/copilot-context.input.cjs +1 -1
  39. package/dist/graphql/inputs/copilot-context.input.cjs.map +1 -1
  40. package/dist/graphql/inputs/copilot-context.input.mjs +1 -1
  41. package/dist/graphql/inputs/copilot-context.input.mjs.map +1 -1
  42. package/dist/graphql/inputs/extensions.input.cjs +1 -1
  43. package/dist/graphql/inputs/extensions.input.cjs.map +1 -1
  44. package/dist/graphql/inputs/extensions.input.d.cts +1 -1
  45. package/dist/graphql/inputs/extensions.input.d.cts.map +1 -1
  46. package/dist/graphql/inputs/extensions.input.d.mts +1 -1
  47. package/dist/graphql/inputs/extensions.input.d.mts.map +1 -1
  48. package/dist/graphql/inputs/extensions.input.mjs +1 -1
  49. package/dist/graphql/inputs/extensions.input.mjs.map +1 -1
  50. package/dist/graphql/inputs/forwarded-parameters.input.cjs +2 -3
  51. package/dist/graphql/inputs/forwarded-parameters.input.cjs.map +1 -1
  52. package/dist/graphql/inputs/forwarded-parameters.input.d.cts +2 -2
  53. package/dist/graphql/inputs/forwarded-parameters.input.d.cts.map +1 -1
  54. package/dist/graphql/inputs/forwarded-parameters.input.d.mts +2 -2
  55. package/dist/graphql/inputs/forwarded-parameters.input.d.mts.map +1 -1
  56. package/dist/graphql/inputs/forwarded-parameters.input.mjs +2 -3
  57. package/dist/graphql/inputs/forwarded-parameters.input.mjs.map +1 -1
  58. package/dist/graphql/inputs/frontend.input.cjs +1 -1
  59. package/dist/graphql/inputs/frontend.input.cjs.map +1 -1
  60. package/dist/graphql/inputs/frontend.input.mjs +1 -1
  61. package/dist/graphql/inputs/frontend.input.mjs.map +1 -1
  62. package/dist/graphql/inputs/generate-copilot-response.input.cjs +1 -1
  63. package/dist/graphql/inputs/generate-copilot-response.input.cjs.map +1 -1
  64. package/dist/graphql/inputs/generate-copilot-response.input.mjs +1 -1
  65. package/dist/graphql/inputs/generate-copilot-response.input.mjs.map +1 -1
  66. package/dist/graphql/inputs/load-agent-state.input.cjs +1 -1
  67. package/dist/graphql/inputs/load-agent-state.input.cjs.map +1 -1
  68. package/dist/graphql/inputs/load-agent-state.input.mjs +1 -1
  69. package/dist/graphql/inputs/load-agent-state.input.mjs.map +1 -1
  70. package/dist/graphql/inputs/message.input.cjs +10 -10
  71. package/dist/graphql/inputs/message.input.cjs.map +1 -1
  72. package/dist/graphql/inputs/message.input.d.cts +2 -2
  73. package/dist/graphql/inputs/message.input.d.cts.map +1 -1
  74. package/dist/graphql/inputs/message.input.d.mts +2 -2
  75. package/dist/graphql/inputs/message.input.d.mts.map +1 -1
  76. package/dist/graphql/inputs/message.input.mjs +10 -10
  77. package/dist/graphql/inputs/message.input.mjs.map +1 -1
  78. package/dist/graphql/inputs/meta-event.input.cjs +1 -1
  79. package/dist/graphql/inputs/meta-event.input.cjs.map +1 -1
  80. package/dist/graphql/inputs/meta-event.input.mjs +1 -1
  81. package/dist/graphql/inputs/meta-event.input.mjs.map +1 -1
  82. package/dist/graphql/message-conversion/agui-to-gql.cjs +1 -1
  83. package/dist/graphql/message-conversion/agui-to-gql.cjs.map +1 -1
  84. package/dist/graphql/message-conversion/agui-to-gql.mjs +1 -1
  85. package/dist/graphql/message-conversion/agui-to-gql.mjs.map +1 -1
  86. package/dist/graphql/resolvers/copilot.resolver.cjs +1 -1
  87. package/dist/graphql/resolvers/copilot.resolver.cjs.map +1 -1
  88. package/dist/graphql/resolvers/copilot.resolver.mjs +1 -1
  89. package/dist/graphql/resolvers/copilot.resolver.mjs.map +1 -1
  90. package/dist/graphql/resolvers/resolve-message-id.cjs +1 -1
  91. package/dist/graphql/resolvers/resolve-message-id.cjs.map +1 -1
  92. package/dist/graphql/resolvers/resolve-message-id.mjs +1 -1
  93. package/dist/graphql/resolvers/resolve-message-id.mjs.map +1 -1
  94. package/dist/graphql/resolvers/state.resolver.cjs +1 -1
  95. package/dist/graphql/resolvers/state.resolver.cjs.map +1 -1
  96. package/dist/graphql/resolvers/state.resolver.mjs +1 -1
  97. package/dist/graphql/resolvers/state.resolver.mjs.map +1 -1
  98. package/dist/graphql/types/agents-response.type.cjs +1 -1
  99. package/dist/graphql/types/agents-response.type.cjs.map +1 -1
  100. package/dist/graphql/types/agents-response.type.mjs +1 -1
  101. package/dist/graphql/types/agents-response.type.mjs.map +1 -1
  102. package/dist/graphql/types/base/index.cjs +1 -1
  103. package/dist/graphql/types/base/index.cjs.map +1 -1
  104. package/dist/graphql/types/base/index.d.cts +1 -1
  105. package/dist/graphql/types/base/index.d.cts.map +1 -1
  106. package/dist/graphql/types/base/index.d.mts +1 -1
  107. package/dist/graphql/types/base/index.d.mts.map +1 -1
  108. package/dist/graphql/types/base/index.mjs +1 -1
  109. package/dist/graphql/types/base/index.mjs.map +1 -1
  110. package/dist/graphql/types/converted/index.cjs +2 -2
  111. package/dist/graphql/types/converted/index.cjs.map +1 -1
  112. package/dist/graphql/types/converted/index.d.cts +1 -1
  113. package/dist/graphql/types/converted/index.d.cts.map +1 -1
  114. package/dist/graphql/types/converted/index.d.mts +1 -1
  115. package/dist/graphql/types/converted/index.d.mts.map +1 -1
  116. package/dist/graphql/types/converted/index.mjs +2 -2
  117. package/dist/graphql/types/converted/index.mjs.map +1 -1
  118. package/dist/graphql/types/copilot-response.type.cjs +1 -1
  119. package/dist/graphql/types/copilot-response.type.cjs.map +1 -1
  120. package/dist/graphql/types/copilot-response.type.d.cts +1 -1
  121. package/dist/graphql/types/copilot-response.type.d.cts.map +1 -1
  122. package/dist/graphql/types/copilot-response.type.d.mts +1 -1
  123. package/dist/graphql/types/copilot-response.type.d.mts.map +1 -1
  124. package/dist/graphql/types/copilot-response.type.mjs +1 -1
  125. package/dist/graphql/types/copilot-response.type.mjs.map +1 -1
  126. package/dist/graphql/types/enums.cjs +1 -1
  127. package/dist/graphql/types/enums.cjs.map +1 -1
  128. package/dist/graphql/types/enums.d.cts +1 -1
  129. package/dist/graphql/types/enums.d.cts.map +1 -1
  130. package/dist/graphql/types/enums.d.mts +1 -1
  131. package/dist/graphql/types/enums.d.mts.map +1 -1
  132. package/dist/graphql/types/enums.mjs +1 -1
  133. package/dist/graphql/types/enums.mjs.map +1 -1
  134. package/dist/graphql/types/extensions-response.type.cjs +1 -1
  135. package/dist/graphql/types/extensions-response.type.cjs.map +1 -1
  136. package/dist/graphql/types/extensions-response.type.d.cts +1 -1
  137. package/dist/graphql/types/extensions-response.type.d.cts.map +1 -1
  138. package/dist/graphql/types/extensions-response.type.d.mts +1 -1
  139. package/dist/graphql/types/extensions-response.type.d.mts.map +1 -1
  140. package/dist/graphql/types/extensions-response.type.mjs +1 -1
  141. package/dist/graphql/types/extensions-response.type.mjs.map +1 -1
  142. package/dist/graphql/types/load-agent-state-response.type.cjs +1 -1
  143. package/dist/graphql/types/load-agent-state-response.type.cjs.map +1 -1
  144. package/dist/graphql/types/load-agent-state-response.type.mjs +1 -1
  145. package/dist/graphql/types/load-agent-state-response.type.mjs.map +1 -1
  146. package/dist/graphql/types/message-status.type.cjs +1 -1
  147. package/dist/graphql/types/message-status.type.cjs.map +1 -1
  148. package/dist/graphql/types/message-status.type.d.cts +1 -1
  149. package/dist/graphql/types/message-status.type.d.cts.map +1 -1
  150. package/dist/graphql/types/message-status.type.d.mts +1 -1
  151. package/dist/graphql/types/message-status.type.d.mts.map +1 -1
  152. package/dist/graphql/types/message-status.type.mjs +1 -1
  153. package/dist/graphql/types/message-status.type.mjs.map +1 -1
  154. package/dist/graphql/types/meta-events.type.cjs +2 -2
  155. package/dist/graphql/types/meta-events.type.cjs.map +1 -1
  156. package/dist/graphql/types/meta-events.type.mjs +2 -2
  157. package/dist/graphql/types/meta-events.type.mjs.map +1 -1
  158. package/dist/graphql/types/response-status.type.cjs +1 -1
  159. package/dist/graphql/types/response-status.type.cjs.map +1 -1
  160. package/dist/graphql/types/response-status.type.d.cts +1 -1
  161. package/dist/graphql/types/response-status.type.d.cts.map +1 -1
  162. package/dist/graphql/types/response-status.type.d.mts +1 -1
  163. package/dist/graphql/types/response-status.type.d.mts.map +1 -1
  164. package/dist/graphql/types/response-status.type.mjs +1 -1
  165. package/dist/graphql/types/response-status.type.mjs.map +1 -1
  166. package/dist/index.d.cts +618 -4
  167. package/dist/index.d.mts +618 -4
  168. package/dist/langgraph.d.cts +54 -1
  169. package/dist/langgraph.d.mts +54 -1
  170. package/dist/lib/cloud/index.d.cts +1 -1
  171. package/dist/lib/cloud/index.d.cts.map +1 -1
  172. package/dist/lib/cloud/index.d.mts +1 -1
  173. package/dist/lib/cloud/index.d.mts.map +1 -1
  174. package/dist/lib/index.cjs +1 -1
  175. package/dist/lib/index.cjs.map +1 -1
  176. package/dist/lib/index.d.cts +2 -2
  177. package/dist/lib/index.d.cts.map +1 -1
  178. package/dist/lib/index.d.mts +2 -2
  179. package/dist/lib/index.d.mts.map +1 -1
  180. package/dist/lib/index.mjs +1 -1
  181. package/dist/lib/index.mjs.map +1 -1
  182. package/dist/lib/integrations/index.d.cts +1 -1
  183. package/dist/lib/integrations/index.d.mts +1 -1
  184. package/dist/lib/integrations/nest/index.cjs +1 -1
  185. package/dist/lib/integrations/nest/index.cjs.map +1 -1
  186. package/dist/lib/integrations/nest/index.d.cts +1 -1
  187. package/dist/lib/integrations/nest/index.d.cts.map +1 -1
  188. package/dist/lib/integrations/nest/index.d.mts +1 -1
  189. package/dist/lib/integrations/nest/index.d.mts.map +1 -1
  190. package/dist/lib/integrations/nest/index.mjs +1 -1
  191. package/dist/lib/integrations/nest/index.mjs.map +1 -1
  192. package/dist/lib/integrations/nextjs/app-router.cjs +1 -1
  193. package/dist/lib/integrations/nextjs/app-router.cjs.map +1 -1
  194. package/dist/lib/integrations/nextjs/app-router.d.cts +1 -1
  195. package/dist/lib/integrations/nextjs/app-router.d.cts.map +1 -1
  196. package/dist/lib/integrations/nextjs/app-router.d.mts +1 -1
  197. package/dist/lib/integrations/nextjs/app-router.d.mts.map +1 -1
  198. package/dist/lib/integrations/nextjs/app-router.mjs +1 -1
  199. package/dist/lib/integrations/nextjs/app-router.mjs.map +1 -1
  200. package/dist/lib/integrations/nextjs/pages-router.cjs +1 -1
  201. package/dist/lib/integrations/nextjs/pages-router.cjs.map +1 -1
  202. package/dist/lib/integrations/nextjs/pages-router.d.cts +1 -2
  203. package/dist/lib/integrations/nextjs/pages-router.d.cts.map +1 -1
  204. package/dist/lib/integrations/nextjs/pages-router.d.mts +1 -2
  205. package/dist/lib/integrations/nextjs/pages-router.d.mts.map +1 -1
  206. package/dist/lib/integrations/nextjs/pages-router.mjs +1 -1
  207. package/dist/lib/integrations/nextjs/pages-router.mjs.map +1 -1
  208. package/dist/lib/integrations/node-express/index.cjs +1 -1
  209. package/dist/lib/integrations/node-express/index.cjs.map +1 -1
  210. package/dist/lib/integrations/node-express/index.d.cts +1 -1
  211. package/dist/lib/integrations/node-express/index.d.cts.map +1 -1
  212. package/dist/lib/integrations/node-express/index.d.mts +1 -1
  213. package/dist/lib/integrations/node-express/index.d.mts.map +1 -1
  214. package/dist/lib/integrations/node-express/index.mjs +1 -1
  215. package/dist/lib/integrations/node-express/index.mjs.map +1 -1
  216. package/dist/lib/integrations/node-http/index.cjs +1 -1
  217. package/dist/lib/integrations/node-http/index.cjs.map +1 -1
  218. package/dist/lib/integrations/node-http/index.d.cts +1 -1
  219. package/dist/lib/integrations/node-http/index.d.cts.map +1 -1
  220. package/dist/lib/integrations/node-http/index.d.mts +1 -1
  221. package/dist/lib/integrations/node-http/index.d.mts.map +1 -1
  222. package/dist/lib/integrations/node-http/index.mjs +1 -1
  223. package/dist/lib/integrations/node-http/index.mjs.map +1 -1
  224. package/dist/lib/integrations/node-http/request-handler.cjs +1 -1
  225. package/dist/lib/integrations/node-http/request-handler.cjs.map +1 -1
  226. package/dist/lib/integrations/node-http/request-handler.mjs +1 -1
  227. package/dist/lib/integrations/node-http/request-handler.mjs.map +1 -1
  228. package/dist/lib/integrations/shared.cjs +1 -1
  229. package/dist/lib/integrations/shared.cjs.map +1 -1
  230. package/dist/lib/integrations/shared.d.cts +30 -4
  231. package/dist/lib/integrations/shared.d.cts.map +1 -1
  232. package/dist/lib/integrations/shared.d.mts +30 -4
  233. package/dist/lib/integrations/shared.d.mts.map +1 -1
  234. package/dist/lib/integrations/shared.mjs +1 -1
  235. package/dist/lib/integrations/shared.mjs.map +1 -1
  236. package/dist/lib/logger.cjs +1 -1
  237. package/dist/lib/logger.cjs.map +1 -1
  238. package/dist/lib/logger.d.cts +1 -1
  239. package/dist/lib/logger.d.cts.map +1 -1
  240. package/dist/lib/logger.d.mts +1 -1
  241. package/dist/lib/logger.d.mts.map +1 -1
  242. package/dist/lib/logger.mjs +1 -1
  243. package/dist/lib/logger.mjs.map +1 -1
  244. package/dist/lib/observability.d.cts +1 -1
  245. package/dist/lib/observability.d.cts.map +1 -1
  246. package/dist/lib/observability.d.mts +1 -1
  247. package/dist/lib/observability.d.mts.map +1 -1
  248. package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs +1 -1
  249. package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs.map +1 -1
  250. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts +13 -3
  251. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts.map +1 -1
  252. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts +13 -3
  253. package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts.map +1 -1
  254. package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs +1 -1
  255. package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs.map +1 -1
  256. package/dist/lib/runtime/agent-integrations/langgraph/consts.cjs +1 -1
  257. package/dist/lib/runtime/agent-integrations/langgraph/consts.cjs.map +1 -1
  258. package/dist/lib/runtime/agent-integrations/langgraph/consts.d.cts +1 -1
  259. package/dist/lib/runtime/agent-integrations/langgraph/consts.d.cts.map +1 -1
  260. package/dist/lib/runtime/agent-integrations/langgraph/consts.d.mts +1 -1
  261. package/dist/lib/runtime/agent-integrations/langgraph/consts.d.mts.map +1 -1
  262. package/dist/lib/runtime/agent-integrations/langgraph/consts.mjs +1 -1
  263. package/dist/lib/runtime/agent-integrations/langgraph/consts.mjs.map +1 -1
  264. package/dist/lib/runtime/copilot-runtime.cjs +9 -1
  265. package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
  266. package/dist/lib/runtime/copilot-runtime.d.cts +9 -1
  267. package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
  268. package/dist/lib/runtime/copilot-runtime.d.mts +9 -1
  269. package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
  270. package/dist/lib/runtime/copilot-runtime.mjs +9 -1
  271. package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
  272. package/dist/lib/runtime/mcp-tools-utils.cjs +1 -1
  273. package/dist/lib/runtime/mcp-tools-utils.cjs.map +1 -1
  274. package/dist/lib/runtime/mcp-tools-utils.d.cts +1 -1
  275. package/dist/lib/runtime/mcp-tools-utils.d.cts.map +1 -1
  276. package/dist/lib/runtime/mcp-tools-utils.d.mts +1 -1
  277. package/dist/lib/runtime/mcp-tools-utils.d.mts.map +1 -1
  278. package/dist/lib/runtime/mcp-tools-utils.mjs +1 -1
  279. package/dist/lib/runtime/mcp-tools-utils.mjs.map +1 -1
  280. package/dist/lib/runtime/telemetry-agent-runner.cjs +1 -1
  281. package/dist/lib/runtime/telemetry-agent-runner.cjs.map +1 -1
  282. package/dist/lib/runtime/telemetry-agent-runner.d.cts +1 -1
  283. package/dist/lib/runtime/telemetry-agent-runner.d.cts.map +1 -1
  284. package/dist/lib/runtime/telemetry-agent-runner.d.mts +1 -1
  285. package/dist/lib/runtime/telemetry-agent-runner.d.mts.map +1 -1
  286. package/dist/lib/runtime/telemetry-agent-runner.mjs +1 -1
  287. package/dist/lib/runtime/telemetry-agent-runner.mjs.map +1 -1
  288. package/dist/lib/runtime/types.cjs +1 -1
  289. package/dist/lib/runtime/types.cjs.map +1 -1
  290. package/dist/lib/runtime/types.d.cts +1 -1
  291. package/dist/lib/runtime/types.d.cts.map +1 -1
  292. package/dist/lib/runtime/types.d.mts +1 -1
  293. package/dist/lib/runtime/types.d.mts.map +1 -1
  294. package/dist/lib/runtime/types.mjs +1 -1
  295. package/dist/lib/runtime/types.mjs.map +1 -1
  296. package/dist/lib/telemetry-client.cjs +1 -1
  297. package/dist/lib/telemetry-client.cjs.map +1 -1
  298. package/dist/lib/telemetry-client.mjs +2 -2
  299. package/dist/lib/telemetry-client.mjs.map +1 -1
  300. package/dist/lib/telemetry-disclosure.cjs +1 -1
  301. package/dist/lib/telemetry-disclosure.cjs.map +1 -1
  302. package/dist/lib/telemetry-disclosure.mjs +1 -1
  303. package/dist/lib/telemetry-disclosure.mjs.map +1 -1
  304. package/dist/package.cjs +5 -5
  305. package/dist/{runtime/package.mjs → package.mjs} +6 -6
  306. package/dist/package.mjs.map +1 -0
  307. package/dist/service-adapters/anthropic/anthropic-adapter.cjs +1 -1
  308. package/dist/service-adapters/anthropic/anthropic-adapter.cjs.map +1 -1
  309. package/dist/service-adapters/anthropic/anthropic-adapter.d.cts +4 -4
  310. package/dist/service-adapters/anthropic/anthropic-adapter.d.cts.map +1 -1
  311. package/dist/service-adapters/anthropic/anthropic-adapter.d.mts +5 -4
  312. package/dist/service-adapters/anthropic/anthropic-adapter.d.mts.map +1 -1
  313. package/dist/service-adapters/anthropic/anthropic-adapter.mjs +1 -1
  314. package/dist/service-adapters/anthropic/anthropic-adapter.mjs.map +1 -1
  315. package/dist/service-adapters/anthropic/utils.cjs +1 -1
  316. package/dist/service-adapters/anthropic/utils.cjs.map +1 -1
  317. package/dist/service-adapters/anthropic/utils.mjs +1 -1
  318. package/dist/service-adapters/anthropic/utils.mjs.map +1 -1
  319. package/dist/service-adapters/bedrock/bedrock-adapter.cjs +1 -1
  320. package/dist/service-adapters/bedrock/bedrock-adapter.cjs.map +1 -1
  321. package/dist/service-adapters/bedrock/bedrock-adapter.d.cts +1 -1
  322. package/dist/service-adapters/bedrock/bedrock-adapter.d.cts.map +1 -1
  323. package/dist/service-adapters/bedrock/bedrock-adapter.d.mts +1 -1
  324. package/dist/service-adapters/bedrock/bedrock-adapter.d.mts.map +1 -1
  325. package/dist/service-adapters/bedrock/bedrock-adapter.mjs +1 -1
  326. package/dist/service-adapters/bedrock/bedrock-adapter.mjs.map +1 -1
  327. package/dist/service-adapters/empty/empty-adapter.cjs +1 -1
  328. package/dist/service-adapters/empty/empty-adapter.cjs.map +1 -1
  329. package/dist/service-adapters/empty/empty-adapter.d.cts +1 -1
  330. package/dist/service-adapters/empty/empty-adapter.d.cts.map +1 -1
  331. package/dist/service-adapters/empty/empty-adapter.d.mts +1 -1
  332. package/dist/service-adapters/empty/empty-adapter.d.mts.map +1 -1
  333. package/dist/service-adapters/empty/empty-adapter.mjs +1 -1
  334. package/dist/service-adapters/empty/empty-adapter.mjs.map +1 -1
  335. package/dist/service-adapters/events.cjs +1 -1
  336. package/dist/service-adapters/events.cjs.map +1 -1
  337. package/dist/service-adapters/events.d.cts +1 -1
  338. package/dist/service-adapters/events.d.cts.map +1 -1
  339. package/dist/service-adapters/events.d.mts +1 -1
  340. package/dist/service-adapters/events.d.mts.map +1 -1
  341. package/dist/service-adapters/events.mjs +1 -1
  342. package/dist/service-adapters/events.mjs.map +1 -1
  343. package/dist/service-adapters/experimental/ollama/ollama-adapter.cjs +1 -1
  344. package/dist/service-adapters/experimental/ollama/ollama-adapter.cjs.map +1 -1
  345. package/dist/service-adapters/experimental/ollama/ollama-adapter.d.cts +1 -1
  346. package/dist/service-adapters/experimental/ollama/ollama-adapter.d.cts.map +1 -1
  347. package/dist/service-adapters/experimental/ollama/ollama-adapter.d.mts +1 -1
  348. package/dist/service-adapters/experimental/ollama/ollama-adapter.d.mts.map +1 -1
  349. package/dist/service-adapters/experimental/ollama/ollama-adapter.mjs +1 -1
  350. package/dist/service-adapters/experimental/ollama/ollama-adapter.mjs.map +1 -1
  351. package/dist/service-adapters/google/google-genai-adapter.cjs +1 -1
  352. package/dist/service-adapters/google/google-genai-adapter.cjs.map +1 -1
  353. package/dist/service-adapters/google/google-genai-adapter.d.cts +1 -1
  354. package/dist/service-adapters/google/google-genai-adapter.d.cts.map +1 -1
  355. package/dist/service-adapters/google/google-genai-adapter.d.mts +1 -1
  356. package/dist/service-adapters/google/google-genai-adapter.d.mts.map +1 -1
  357. package/dist/service-adapters/google/google-genai-adapter.mjs +1 -1
  358. package/dist/service-adapters/google/google-genai-adapter.mjs.map +1 -1
  359. package/dist/service-adapters/groq/groq-adapter.cjs +1 -1
  360. package/dist/service-adapters/groq/groq-adapter.cjs.map +1 -1
  361. package/dist/service-adapters/groq/groq-adapter.d.cts +4 -4
  362. package/dist/service-adapters/groq/groq-adapter.d.cts.map +1 -1
  363. package/dist/service-adapters/groq/groq-adapter.d.mts +5 -4
  364. package/dist/service-adapters/groq/groq-adapter.d.mts.map +1 -1
  365. package/dist/service-adapters/groq/groq-adapter.mjs +1 -1
  366. package/dist/service-adapters/groq/groq-adapter.mjs.map +1 -1
  367. package/dist/service-adapters/index.d.cts +2 -2
  368. package/dist/service-adapters/index.d.mts +3 -3
  369. package/dist/service-adapters/langchain/langchain-adapter.cjs +1 -1
  370. package/dist/service-adapters/langchain/langchain-adapter.cjs.map +1 -1
  371. package/dist/service-adapters/langchain/langchain-adapter.d.cts +1 -1
  372. package/dist/service-adapters/langchain/langchain-adapter.d.cts.map +1 -1
  373. package/dist/service-adapters/langchain/langchain-adapter.d.mts +1 -1
  374. package/dist/service-adapters/langchain/langchain-adapter.d.mts.map +1 -1
  375. package/dist/service-adapters/langchain/langchain-adapter.mjs +1 -1
  376. package/dist/service-adapters/langchain/langchain-adapter.mjs.map +1 -1
  377. package/dist/service-adapters/langchain/langserve.cjs +1 -1
  378. package/dist/service-adapters/langchain/langserve.cjs.map +1 -1
  379. package/dist/service-adapters/langchain/langserve.d.cts +1 -1
  380. package/dist/service-adapters/langchain/langserve.d.cts.map +1 -1
  381. package/dist/service-adapters/langchain/langserve.d.mts +1 -1
  382. package/dist/service-adapters/langchain/langserve.d.mts.map +1 -1
  383. package/dist/service-adapters/langchain/langserve.mjs +1 -1
  384. package/dist/service-adapters/langchain/langserve.mjs.map +1 -1
  385. package/dist/service-adapters/langchain/types.d.cts +1 -1
  386. package/dist/service-adapters/langchain/types.d.cts.map +1 -1
  387. package/dist/service-adapters/langchain/types.d.mts +1 -1
  388. package/dist/service-adapters/langchain/types.d.mts.map +1 -1
  389. package/dist/service-adapters/langchain/utils.cjs +1 -1
  390. package/dist/service-adapters/langchain/utils.cjs.map +1 -1
  391. package/dist/service-adapters/langchain/utils.mjs +1 -1
  392. package/dist/service-adapters/langchain/utils.mjs.map +1 -1
  393. package/dist/service-adapters/openai/openai-adapter.cjs +1 -1
  394. package/dist/service-adapters/openai/openai-adapter.cjs.map +1 -1
  395. package/dist/service-adapters/openai/openai-adapter.d.cts +1 -1
  396. package/dist/service-adapters/openai/openai-adapter.d.cts.map +1 -1
  397. package/dist/service-adapters/openai/openai-adapter.d.mts +1 -1
  398. package/dist/service-adapters/openai/openai-adapter.d.mts.map +1 -1
  399. package/dist/service-adapters/openai/openai-adapter.mjs +1 -1
  400. package/dist/service-adapters/openai/openai-adapter.mjs.map +1 -1
  401. package/dist/service-adapters/openai/openai-assistant-adapter.cjs +1 -1
  402. package/dist/service-adapters/openai/openai-assistant-adapter.cjs.map +1 -1
  403. package/dist/service-adapters/openai/openai-assistant-adapter.d.cts +1 -1
  404. package/dist/service-adapters/openai/openai-assistant-adapter.d.cts.map +1 -1
  405. package/dist/service-adapters/openai/openai-assistant-adapter.d.mts +1 -1
  406. package/dist/service-adapters/openai/openai-assistant-adapter.d.mts.map +1 -1
  407. package/dist/service-adapters/openai/openai-assistant-adapter.mjs +1 -1
  408. package/dist/service-adapters/openai/openai-assistant-adapter.mjs.map +1 -1
  409. package/dist/service-adapters/openai/utils.cjs +1 -1
  410. package/dist/service-adapters/openai/utils.cjs.map +1 -1
  411. package/dist/service-adapters/openai/utils.mjs +1 -1
  412. package/dist/service-adapters/openai/utils.mjs.map +1 -1
  413. package/dist/service-adapters/service-adapter.d.cts +1 -1
  414. package/dist/service-adapters/service-adapter.d.cts.map +1 -1
  415. package/dist/service-adapters/service-adapter.d.mts +1 -1
  416. package/dist/service-adapters/service-adapter.d.mts.map +1 -1
  417. package/dist/service-adapters/shared/error-utils.cjs +1 -1
  418. package/dist/service-adapters/shared/error-utils.cjs.map +1 -1
  419. package/dist/service-adapters/shared/error-utils.d.cts +1 -1
  420. package/dist/service-adapters/shared/error-utils.d.cts.map +1 -1
  421. package/dist/service-adapters/shared/error-utils.d.mts +1 -1
  422. package/dist/service-adapters/shared/error-utils.d.mts.map +1 -1
  423. package/dist/service-adapters/shared/error-utils.mjs +1 -1
  424. package/dist/service-adapters/shared/error-utils.mjs.map +1 -1
  425. package/dist/service-adapters/shared/index.d.mts +1 -1
  426. package/dist/service-adapters/shared/sdk-client-utils.cjs +1 -1
  427. package/dist/service-adapters/shared/sdk-client-utils.cjs.map +1 -1
  428. package/dist/service-adapters/shared/sdk-client-utils.d.cts +21 -2
  429. package/dist/service-adapters/shared/sdk-client-utils.d.cts.map +1 -1
  430. package/dist/service-adapters/shared/sdk-client-utils.d.mts +21 -2
  431. package/dist/service-adapters/shared/sdk-client-utils.d.mts.map +1 -1
  432. package/dist/service-adapters/shared/sdk-client-utils.mjs +1 -1
  433. package/dist/service-adapters/shared/sdk-client-utils.mjs.map +1 -1
  434. package/dist/service-adapters/unify/unify-adapter.cjs +1 -1
  435. package/dist/service-adapters/unify/unify-adapter.cjs.map +1 -1
  436. package/dist/service-adapters/unify/unify-adapter.d.cts +1 -1
  437. package/dist/service-adapters/unify/unify-adapter.d.cts.map +1 -1
  438. package/dist/service-adapters/unify/unify-adapter.d.mts +1 -1
  439. package/dist/service-adapters/unify/unify-adapter.d.mts.map +1 -1
  440. package/dist/service-adapters/unify/unify-adapter.mjs +1 -1
  441. package/dist/service-adapters/unify/unify-adapter.mjs.map +1 -1
  442. package/dist/utils/failed-response-status-reasons.cjs +1 -1
  443. package/dist/utils/failed-response-status-reasons.cjs.map +1 -1
  444. package/dist/utils/failed-response-status-reasons.d.cts +1 -1
  445. package/dist/utils/failed-response-status-reasons.d.cts.map +1 -1
  446. package/dist/utils/failed-response-status-reasons.d.mts +1 -1
  447. package/dist/utils/failed-response-status-reasons.d.mts.map +1 -1
  448. package/dist/utils/failed-response-status-reasons.mjs +1 -1
  449. package/dist/utils/failed-response-status-reasons.mjs.map +1 -1
  450. package/dist/v2/runtime/core/channel-activation-config.cjs.map +1 -1
  451. package/dist/v2/runtime/core/channel-activation-config.d.cts +2 -2
  452. package/dist/v2/runtime/core/channel-activation-config.d.cts.map +1 -1
  453. package/dist/v2/runtime/core/channel-activation-config.d.mts +2 -2
  454. package/dist/v2/runtime/core/channel-activation-config.d.mts.map +1 -1
  455. package/dist/v2/runtime/core/channel-activation-config.mjs.map +1 -1
  456. package/dist/v2/runtime/core/channel-manager.cjs.map +1 -1
  457. package/dist/v2/runtime/core/channel-manager.d.cts +2 -2
  458. package/dist/v2/runtime/core/channel-manager.d.cts.map +1 -1
  459. package/dist/v2/runtime/core/channel-manager.d.mts +2 -2
  460. package/dist/v2/runtime/core/channel-manager.d.mts.map +1 -1
  461. package/dist/v2/runtime/core/channel-manager.mjs.map +1 -1
  462. package/dist/v2/runtime/core/runtime.cjs +1 -0
  463. package/dist/v2/runtime/core/runtime.cjs.map +1 -1
  464. package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
  465. package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
  466. package/dist/v2/runtime/core/runtime.mjs +2 -1
  467. package/dist/v2/runtime/core/runtime.mjs.map +1 -1
  468. package/dist/v2/runtime/handlers/intelligence/memories.cjs +1 -1
  469. package/dist/v2/runtime/handlers/intelligence/memories.cjs.map +1 -1
  470. package/dist/v2/runtime/handlers/intelligence/memories.mjs +1 -1
  471. package/dist/v2/runtime/handlers/intelligence/memories.mjs.map +1 -1
  472. package/dist/v2/runtime/handlers/intelligence/threads.cjs +1 -1
  473. package/dist/v2/runtime/handlers/intelligence/threads.cjs.map +1 -1
  474. package/dist/v2/runtime/handlers/intelligence/threads.mjs +1 -1
  475. package/dist/v2/runtime/handlers/intelligence/threads.mjs.map +1 -1
  476. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +1 -1
  477. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
  478. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +1 -1
  479. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
  480. package/dist/v2/runtime/handlers/shared/sse-response.cjs.map +1 -1
  481. package/dist/v2/runtime/handlers/shared/sse-response.mjs.map +1 -1
  482. package/dist/v2/runtime/handlers/sse/run.cjs.map +1 -1
  483. package/dist/v2/runtime/handlers/sse/run.mjs.map +1 -1
  484. package/dist/v2/runtime/intelligence-platform/client.cjs +6 -6
  485. package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
  486. package/dist/v2/runtime/intelligence-platform/client.d.cts +8 -8
  487. package/dist/v2/runtime/intelligence-platform/client.d.mts +8 -8
  488. package/dist/v2/runtime/intelligence-platform/client.mjs +6 -6
  489. package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
  490. package/dist/v2/runtime/runner/in-memory.cjs +3 -3
  491. package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
  492. package/dist/v2/runtime/runner/in-memory.d.cts +4 -4
  493. package/dist/v2/runtime/runner/in-memory.d.mts +4 -4
  494. package/dist/v2/runtime/runner/in-memory.mjs +3 -3
  495. package/dist/v2/runtime/runner/in-memory.mjs.map +1 -1
  496. package/dist/v2/runtime/telemetry/telemetry-client.mjs +1 -1
  497. package/package.json +6 -6
  498. package/skills/runtime/SKILL.md +1 -1
  499. package/skills/runtime/references/agent-runners-custom.md +1 -1
  500. package/skills/runtime/references/agent-runners.md +11 -5
  501. package/skills/runtime/references/intelligence-mode.md +1 -1
  502. package/dist/channels/dist/index.d.cts +0 -10
  503. package/dist/channels/dist/index.d.cts.map +0 -1
  504. package/dist/channels/dist/index.d.mts +0 -10
  505. package/dist/channels/dist/index.d.mts.map +0 -1
  506. package/dist/runtime/package.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","names":["#apiUrl","#runnerWsUrl","#clientWsUrl","#channelsWsUrl","#apiKey","#enterpriseLearningEnabled","#threadCreatedListeners","#threadUpdatedListeners","#threadDeletedListeners","#request","#invokeLifecycleCallback","randomUUID"],"sources":["../../../../src/v2/runtime/intelligence-platform/client.ts"],"sourcesContent":["import { logger, parseInspectorMetadataV1 } from \"@copilotkit/shared\";\nimport type { InspectorMetadataV1 } from \"@copilotkit/shared\";\nimport { randomUUID } from \"crypto\";\n\n/**\n * Header name carrying the per-call end-user identity that the CopilotKit\n * Intelligence `/mcp` endpoint requires. Internal CopilotKit machinery —\n * `attachIntelligenceEnterpriseLearning` resolves the user via `identifyUser`\n * and bakes this header onto the `MCPMiddleware`'s transport config, so every\n * outbound MCP request stamps `X-Cpki-User-Id: <userId>`. Not part of the\n * public user API.\n *\n * @internal\n */\nexport const INTELLIGENCE_USER_ID_HEADER = \"x-cpki-user-id\";\n/** Immutable user/project Memory grant forwarded to Intelligence. */\nexport const INTELLIGENCE_MEMORY_GRANT_HEADER = \"x-cpki-memory-grant\";\n\ninterface RuntimeMemoryGrant {\n readonly user: \"none\" | \"read\" | \"read-write\";\n readonly project: \"none\" | \"read\" | \"read-write\";\n}\n\nconst memoryRequestHeaders = (\n userId: string,\n grant?: RuntimeMemoryGrant,\n): Record<string, string> => ({\n [INTELLIGENCE_USER_ID_HEADER]: userId,\n ...(grant\n ? { [INTELLIGENCE_MEMORY_GRANT_HEADER]: JSON.stringify(grant) }\n : {}),\n});\n\n/**\n * REST base URL of CopilotKit's managed Intelligence platform — the default\n * when {@link CopilotKitIntelligenceConfig.apiUrl} is omitted.\n */\nconst MANAGED_INTELLIGENCE_API_URL = \"https://api.intelligence.copilotkit.ai\";\n\n/**\n * Websocket base URL of CopilotKit's managed Intelligence platform — the\n * default when {@link CopilotKitIntelligenceConfig.wsUrl} is omitted.\n *\n * A different host from {@link MANAGED_INTELLIGENCE_API_URL}: the API and\n * realtime planes are deployed separately.\n */\nconst MANAGED_INTELLIGENCE_WS_URL = \"wss://realtime.intelligence.copilotkit.ai\";\n\n/** Maximum time spent on the optional Inspector metadata provider request. */\nconst INSPECTOR_METADATA_REQUEST_TIMEOUT_MS = 5_000;\n\n/**\n * Error thrown when an Intelligence platform HTTP request returns a non-2xx\n * status. Carries the HTTP {@link status} code so callers can branch on\n * specific failures (e.g. 404 for \"not found\", 409 for \"conflict\") without\n * parsing the error message string.\n *\n * @example\n * ```ts\n * try {\n * await intelligence.getThread({ threadId, userId });\n * } catch (error) {\n * if (error instanceof PlatformRequestError && error.status === 404) {\n * // thread does not exist yet\n * }\n * }\n * ```\n */\nexport class PlatformRequestError extends Error {\n constructor(\n message: string,\n /** The HTTP status code returned by the platform (e.g. 404, 409, 500). */\n public readonly status: number,\n ) {\n super(message);\n this.name = \"PlatformRequestError\";\n }\n}\n\n/** Payload passed to `onThreadDeleted` listeners. */\nexport interface ThreadDeletedPayload {\n threadId: string;\n userId: string;\n agentId: string;\n}\n\nexport interface CopilotKitIntelligenceConfig {\n /**\n * Base URL of the intelligence platform API.\n *\n * Defaults to CopilotKit's managed platform,\n * `https://api.intelligence.copilotkit.ai`. Set it only when pointing at a\n * self-hosted or non-production deployment — and set {@link wsUrl} with it.\n */\n apiUrl?: string;\n /**\n * Intelligence websocket base URL. Runner and client socket URLs are derived\n * from this by appending `/runner` or `/client`, so pass the bare base.\n *\n * Defaults to CopilotKit's managed platform,\n * `wss://realtime.intelligence.copilotkit.ai`.\n *\n * This is a DIFFERENT host from {@link apiUrl} — the API and realtime planes are\n * deployed separately — so it cannot be derived by scheme-swapping `apiUrl`.\n * Overriding one without the other therefore points the two planes at\n * different deployments, which logs a warning.\n */\n wsUrl?: string;\n /** API key for authenticating with the intelligence platform */\n apiKey: string;\n /**\n * Enable Enterprise Learning — expose the Intelligence platform's\n * built-in tools (bash + thread/memory tools) to agent runs on an\n * intelligence runtime that resolve a user. Attached uniformly across\n * agent frameworks by `attachIntelligenceEnterpriseLearning` via\n * `@ag-ui/mcp-middleware`, with the resolved user-id and project apiKey\n * baked into the transport headers for that request's clone.\n *\n * Defaults to `false` — opt-in. Existing intelligence setups continue\n * to work without these tools unless they flip this flag.\n *\n * @deprecated Configure `memory.access` on `CopilotRuntime` so each web\n * request receives an explicit agent or client Memory grant.\n */\n enableEnterpriseLearning?: boolean;\n /**\n * Initial listener invoked after a thread is created.\n * Prefer {@link CopilotKitIntelligence.onThreadCreated} for multiple listeners.\n */\n onThreadCreated?: (thread: ThreadSummary) => void;\n /**\n * Initial listener invoked after a thread is updated.\n * Prefer {@link CopilotKitIntelligence.onThreadUpdated} for multiple listeners.\n */\n onThreadUpdated?: (thread: ThreadSummary) => void;\n /**\n * Initial listener invoked after a thread is deleted.\n * Prefer {@link CopilotKitIntelligence.onThreadDeleted} for multiple listeners.\n */\n onThreadDeleted?: (params: ThreadDeletedPayload) => void;\n}\n\n/**\n * Summary metadata for a single thread returned by the platform.\n *\n * This is the shape returned by list, get, create, and update operations.\n * It does not include the thread's message history — use\n * {@link CopilotKitIntelligence.getThreadMessages} for that.\n */\nexport interface ThreadSummary {\n /** Platform-assigned unique identifier. */\n id: string;\n /** Human-readable display name, or `null` if the thread has not been named. */\n name: string | null;\n /** ISO-8601 timestamp of the most recent agent run on this thread. */\n lastRunAt?: string;\n /** ISO-8601 timestamp of the most recent metadata update. */\n lastUpdatedAt?: string;\n /** ISO-8601 timestamp when the thread was created. */\n createdAt?: string;\n /** ISO-8601 timestamp when the thread was last updated. */\n updatedAt?: string;\n /** Whether the thread has been archived. Archived threads are excluded from default list results. */\n archived?: boolean;\n /** The agent that owns this thread. */\n agentId?: string;\n /** The user who created this thread. */\n createdById?: string;\n /** The organization this thread belongs to. */\n organizationId?: string;\n}\n\n/** Response from listing threads for a user/agent pair. */\nexport interface ListThreadsResponse {\n /** The matching threads, sorted by the platform's default ordering. */\n threads: ThreadSummary[];\n /** Join code for subscribing to realtime metadata updates for these threads. */\n joinCode: string;\n /** Short-lived token for authenticating the realtime subscription. */\n joinToken?: string;\n /** Opaque cursor for fetching the next page. `null` or absent when there are no more pages. */\n nextCursor?: string | null;\n}\n\n/**\n * A single memory as returned by the platform's list endpoint. Mirrors the\n * public projection the client memory store consumes (tenant ids stripped).\n */\nexport interface MemorySummary {\n /** Platform-assigned unique identifier. */\n id: string;\n /** Memory kind, e.g. `\"topical\"`, `\"episodic\"`, `\"operational\"`. */\n kind: string;\n /** Memory scope: `\"user\"` (private) or `\"project\"` (shared). */\n scope: string;\n /** The remembered fact, preference, or procedure. */\n content: string;\n /** Ids of the threads this memory was learned from. */\n sourceThreadIds: string[];\n /** ISO-8601 timestamp when the memory was retired, or `null` if live. */\n invalidatedAt: string | null;\n /** Relevance score from a `recall` (hybrid RAG) query. Present only on recall responses. */\n score?: number;\n}\n\n/** Response from {@link CopilotKitIntelligence.listMemories}. */\nexport interface ListMemoriesResponse {\n memories: MemorySummary[];\n}\n\n/** Response from {@link CopilotKitIntelligence.recallMemories}. */\nexport interface RecallMemoriesResponse {\n memories: MemorySummary[];\n}\n\n/**\n * Response from a create ({@link CopilotKitIntelligence.createMemory}) or\n * supersede ({@link CopilotKitIntelligence.updateMemory}) call: the stored\n * memory, plus the operation-specific marker the client store consumes.\n */\nexport interface SaveMemoryResponse extends MemorySummary {\n /** Create only: content was merged into a near-duplicate, not inserted new. */\n absorbed?: boolean;\n /** Supersede only: the id of the memory retired by this call. */\n retiredId?: string;\n}\n\n/**\n * Fields that can be updated on a thread via {@link CopilotKitIntelligence.updateThread}.\n *\n * Additional platform-specific fields can be passed as extra keys and will be\n * forwarded to the PATCH request body.\n */\nexport interface UpdateThreadRequest {\n /** New human-readable display name for the thread. */\n name?: string;\n [key: string]: unknown;\n}\n\n/** Parameters for creating a new thread via {@link CopilotKitIntelligence.createThread}. */\nexport interface CreateThreadRequest {\n /** Client-generated unique identifier for the new thread. */\n threadId: string;\n /** The user creating the thread. Used for authorization and scoping. */\n userId: string;\n /** The agent this thread belongs to. */\n agentId: string;\n /** Optional initial display name. If omitted, the thread is unnamed until explicitly renamed. */\n name?: string;\n /** Developer-set stable ID of the Learning Container for this Thread. */\n learningContainerId?: string;\n}\n\n/** Credentials returned when locking or joining a thread's realtime channel. */\nexport interface ThreadConnectionResponse {\n /** Canonical platform thread identifier for the run or connection. */\n threadId: string;\n /** Canonical platform run identifier for an active run lock. */\n runId?: string;\n /** Short-lived token for authenticating the Phoenix channel join. */\n joinToken: string;\n /** Lock metadata echoed back by the platform. */\n lock?: ThreadLockInfo;\n}\n\nexport interface SubscribeToThreadsRequest {\n userId: string;\n}\n\nexport interface SubscribeToThreadsResponse {\n joinToken: string;\n}\n\nexport interface SubscribeToMemoriesRequest {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n}\n\n/**\n * Memory subscribe returns both the token and the join code, unlike threads\n * (whose join code reaches the client via the thread-list response). Memory has\n * no list-borne code, so the code is delivered here and used to build the\n * `user_meta:memories:<joinCode>` channel topic.\n */\nexport interface SubscribeToMemoriesResponse {\n joinToken?: string;\n joinCode?: string;\n /**\n * Project-scoped realtime credentials, minted by the platform only when the\n * caller's API key resolves to a project scope. Absent when project scope is\n * unavailable — a silent-degrade contract: the client then opens only the\n * user channel. When present, the client builds the second\n * `project_meta:memories:<projectJoinCode>` channel topic from them.\n */\n projectJoinToken?: string;\n projectJoinCode?: string;\n}\n\nexport type ConnectThreadResponse = ThreadConnectionResponse | null;\n\nexport interface AcquireThreadLockResponse extends ThreadConnectionResponse {\n /** Canonical platform run identifier for the acquired lock. */\n runId: string;\n}\n\n/**\n * Parameters for annotating a thread event via\n * {@link CopilotKitIntelligence.annotate}. The runtime resolves `userId`\n * from the customer's BFF auth before calling this; the platform prefixes\n * it with the project id at write time.\n *\n * `payload` is the type-specific JSON blob for the annotation (for example, a\n * `\"user_action\"` event carries the recorded fields). The exact\n * shape per type is validated by the Intelligence backend; canonical shapes\n * are documented on the Intelligence react-core side.\n */\nexport interface AnnotateParams {\n /** The user the annotation belongs to. */\n userId: string;\n /** The thread the annotation is associated with. May be unknown to the platform. */\n threadId: string;\n /**\n * Discriminator identifying the annotation type.\n * Must match a type known to the Intelligence platform\n * (for example, `\"user_action\"`).\n */\n type: string;\n /** Type-specific payload. Shape varies by `type`. */\n payload?: unknown;\n /**\n * Caller-supplied idempotency key (any RFC-compliant UUID). When omitted,\n * a UUID is auto-generated. Every call hits the platform's idempotent\n * `PUT /connector/annotate/:clientEventId` endpoint; a retry with the\n * same id collapses to the original row.\n */\n clientEventId?: string;\n /** ISO-8601 client-asserted timestamp. Defaults to server NOW() when absent. */\n occurredAt?: string;\n}\n\n/** Response from {@link CopilotKitIntelligence.annotate}. */\nexport interface AnnotateResponse {\n /** Database id of the annotation row (BIGINT, returned as a string). */\n id: string;\n /**\n * True when the platform recognized the `clientEventId` as a retry of\n * a previous call and returned the original row id instead of inserting\n * a new one.\n */\n duplicate: boolean;\n}\n\n/** A single message within a thread's persisted history. */\nexport interface ThreadMessage {\n /** Unique identifier for this message. */\n id: string;\n /** Message role, e.g. `\"user\"`, `\"assistant\"`, `\"tool\"`. */\n role: string;\n /** Structured AG-UI content. May be absent for tool-call-only messages. */\n content?: unknown;\n /** Standard AG-UI activity type when `role` is `\"activity\"`. */\n activityType?: string;\n /** Tool calls initiated by this message (assistant role only). */\n toolCalls?: Array<{\n id: string;\n name: string;\n /** JSON-encoded arguments passed to the tool. */\n args: string;\n }>;\n /** For tool-result messages, the ID of the tool call this message responds to. */\n toolCallId?: string;\n}\n\n/** Response from {@link CopilotKitIntelligence.getThreadMessages}. */\nexport interface ThreadMessagesResponse {\n messages: ThreadMessage[];\n}\n\n/**\n * Persisted AG-UI event for the inspector's debugging views. The platform\n * stores raw events keyed by run; the `_inspect` route returns them in\n * replay order (oldest first) across every run that targeted the thread.\n */\nexport interface ThreadInspectEvent {\n type: string;\n [key: string]: unknown;\n}\n\n/**\n * Response from {@link CopilotKitIntelligence.getThreadEvents}. Mirrors the\n * `ThreadEventsResult` shape returned by the platform's\n * `GET /api/_inspect/threads/:id/events` endpoint.\n */\nexport interface ThreadEventsResponse {\n events: ThreadInspectEvent[];\n /** Row IDs the platform failed to decode (raw column corrupted). */\n decodeErrorRowIds: string[];\n /** True when the platform hit its per-thread event cap. */\n truncated: boolean;\n}\n\n/**\n * Response from {@link CopilotKitIntelligence.getThreadState}. Mirrors the\n * discriminated `ThreadStateResult` returned by the platform's\n * `GET /api/_inspect/threads/:id/state` endpoint, which folds RFC 6902\n * STATE_DELTA events on top of the latest STATE_SNAPSHOT.\n */\nexport type ThreadStateResponse =\n | { kind: \"no-snapshot\" }\n | { kind: \"snapshot-decode-error\" }\n | { kind: \"snapshot\"; state: unknown; skippedDeltas: number };\n\nexport interface AcquireThreadLockRequest {\n threadId: string;\n runId: string;\n userId: string;\n agentId: string;\n /** Developer-set stable ID to assign before the run lock is acquired. */\n learningContainerId?: string;\n /** Internal managed-Channel delivery context for shared Thread access. */\n channelDeliveryId?: string;\n /** Custom Redis key prefix for the lock (default: \"thread\"). */\n lockKeyPrefix?: string;\n /** Lock TTL in seconds. When set, the lock auto-expires after this duration. */\n ttlSeconds?: number;\n}\n\nexport interface RenewThreadLockRequest {\n threadId: string;\n runId: string;\n /** New TTL to set on the lock in seconds. */\n ttlSeconds: number;\n /** Must match the prefix used when acquiring. */\n lockKeyPrefix?: string;\n}\n\nexport interface CleanupThreadLockRequest {\n threadId: string;\n runId: string;\n}\n\nexport interface RenewThreadLockResponse {\n ttlSeconds: number;\n}\n\nexport interface ThreadLockInfo {\n key: string;\n ttlSeconds: number | null;\n}\n\ninterface ThreadEnvelope {\n thread: ThreadSummary;\n}\n\n/**\n * Client for the CopilotKit Intelligence Platform REST API.\n *\n * Construct the client once and pass it to any consumers that need it\n * (e.g. `CopilotRuntime`, `IntelligenceAgentRunner`):\n *\n * ```ts\n * import { CopilotKitIntelligence, CopilotRuntime } from \"@copilotkit/runtime\";\n *\n * const intelligence = new CopilotKitIntelligence({\n * apiKey: process.env.INTELLIGENCE_API_KEY!,\n * });\n *\n * const runtime = new CopilotRuntime({\n * agents,\n * intelligence,\n * });\n * ```\n *\n * `apiUrl` and `wsUrl` default to CopilotKit's managed Intelligence platform.\n * Override both together to target a self-hosted or non-production deployment:\n *\n * ```ts\n * const intelligence = new CopilotKitIntelligence({\n * apiUrl: \"https://intelligence.internal\",\n * wsUrl: \"wss://realtime.intelligence.internal\",\n * apiKey: process.env.INTELLIGENCE_API_KEY!,\n * });\n * ```\n */\nexport class CopilotKitIntelligence {\n #apiUrl: string;\n #runnerWsUrl: string;\n #clientWsUrl: string;\n #channelsWsUrl: string;\n #apiKey: string;\n #enterpriseLearningEnabled: boolean;\n #threadCreatedListeners = new Set<(thread: ThreadSummary) => void>();\n #threadUpdatedListeners = new Set<(thread: ThreadSummary) => void>();\n #threadDeletedListeners = new Set<(params: ThreadDeletedPayload) => void>();\n\n constructor(config: CopilotKitIntelligenceConfig) {\n const configuredApiUrl = configuredUrl(config.apiUrl);\n const configuredWsUrl = configuredUrl(config.wsUrl);\n warnOnPartialHostOverride(configuredApiUrl, configuredWsUrl);\n\n const intelligenceWsUrl = normalizeIntelligenceWsUrl(\n configuredWsUrl ?? MANAGED_INTELLIGENCE_WS_URL,\n );\n\n this.#apiUrl = (configuredApiUrl ?? MANAGED_INTELLIGENCE_API_URL).replace(\n /\\/$/,\n \"\",\n );\n this.#runnerWsUrl = deriveRunnerWsUrl(intelligenceWsUrl);\n this.#clientWsUrl = deriveClientWsUrl(intelligenceWsUrl);\n this.#channelsWsUrl = deriveChannelsWsUrl(intelligenceWsUrl);\n this.#apiKey = config.apiKey;\n this.#enterpriseLearningEnabled = config.enableEnterpriseLearning ?? false;\n\n if (config.onThreadCreated) {\n this.onThreadCreated(config.onThreadCreated);\n }\n if (config.onThreadUpdated) {\n this.onThreadUpdated(config.onThreadUpdated);\n }\n if (config.onThreadDeleted) {\n this.onThreadDeleted(config.onThreadDeleted);\n }\n }\n\n /**\n * Register a listener invoked whenever a thread is created.\n *\n * Multiple listeners can be registered. Each call returns an unsubscribe\n * function that removes the listener when called.\n *\n * @param callback - Receives the newly created {@link ThreadSummary}.\n * @returns A function that removes this listener when called.\n *\n * @example\n * ```ts\n * const unsubscribe = intelligence.onThreadCreated((thread) => {\n * console.log(\"Thread created:\", thread.id);\n * });\n * // later…\n * unsubscribe();\n * ```\n */\n onThreadCreated(callback: (thread: ThreadSummary) => void): () => void {\n this.#threadCreatedListeners.add(callback);\n return () => {\n this.#threadCreatedListeners.delete(callback);\n };\n }\n\n /**\n * Register a listener invoked whenever a thread is updated (including archive).\n *\n * Multiple listeners can be registered. Each call returns an unsubscribe\n * function that removes the listener when called.\n *\n * @param callback - Receives the updated {@link ThreadSummary}.\n * @returns A function that removes this listener when called.\n */\n onThreadUpdated(callback: (thread: ThreadSummary) => void): () => void {\n this.#threadUpdatedListeners.add(callback);\n return () => {\n this.#threadUpdatedListeners.delete(callback);\n };\n }\n\n /**\n * Register a listener invoked whenever a thread is deleted.\n *\n * Multiple listeners can be registered. Each call returns an unsubscribe\n * function that removes the listener when called.\n *\n * @param callback - Receives the {@link ThreadDeletedPayload} identifying\n * the deleted thread.\n * @returns A function that removes this listener when called.\n */\n onThreadDeleted(\n callback: (params: ThreadDeletedPayload) => void,\n ): () => void {\n this.#threadDeletedListeners.add(callback);\n return () => {\n this.#threadDeletedListeners.delete(callback);\n };\n }\n\n ɵgetApiUrl(): string {\n return this.#apiUrl;\n }\n\n ɵgetRunnerWsUrl(): string {\n return this.#runnerWsUrl;\n }\n\n ɵgetClientWsUrl(): string {\n return this.#clientWsUrl;\n }\n\n ɵgetChannelsWsUrl(): string {\n return this.#channelsWsUrl;\n }\n\n ɵgetRunnerAuthToken(): string {\n return this.#apiKey;\n }\n\n /** @internal Used by `attachIntelligenceEnterpriseLearning` to populate `Authorization`. */\n ɵgetApiKey(): string {\n return this.#apiKey;\n }\n\n /** @internal Used by `attachIntelligenceEnterpriseLearning` to gate MCP attachment. */\n ɵisEnterpriseLearningEnabled(): boolean {\n return this.#enterpriseLearningEnabled;\n }\n\n /**\n * Fetch trusted Inspector metadata for this runtime's Intelligence project.\n *\n * The request always uses the server-configured Intelligence API key. A 404\n * is treated as compatible absence so runtimes can work with older App API\n * deployments that do not expose this endpoint yet.\n *\n * @returns Sanitized V1 metadata, or `undefined` when the provider has no\n * supported metadata.\n * @throws {@link PlatformRequestError} for provider failures other than 404.\n */\n async getInspectorMetadata(): Promise<InspectorMetadataV1 | undefined> {\n const path = \"/api/inspector/metadata\";\n const abortController = new AbortController();\n const timeoutError = new Error(\n \"Intelligence inspector metadata request timed out\",\n );\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(timeoutError);\n abortController.abort(timeoutError);\n }, INSPECTOR_METADATA_REQUEST_TIMEOUT_MS);\n });\n\n try {\n const response = await Promise.race([\n fetch(`${this.#apiUrl}${path}`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.#apiKey}` },\n signal: abortController.signal,\n }),\n timeout,\n ]);\n\n if (response.status === 204 || response.status === 404) {\n return undefined;\n }\n\n if (!response.ok) {\n logger.error(\n { status: response.status, path },\n \"Intelligence platform request failed\",\n );\n throw new PlatformRequestError(\n `Intelligence platform error ${response.status}`,\n response.status,\n );\n }\n\n const body = await Promise.race([response.text(), timeout]);\n const decoded: unknown = JSON.parse(body);\n return parseInspectorMetadataV1(decoded);\n } catch (error) {\n if (error === timeoutError) {\n logger.warn(\n { path, timeoutMs: INSPECTOR_METADATA_REQUEST_TIMEOUT_MS },\n \"Intelligence inspector metadata request timed out\",\n );\n }\n throw error;\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n async #request<T>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const url = `${this.#apiUrl}${path}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.#apiKey}`,\n \"Content-Type\": \"application/json\",\n ...extraHeaders,\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n logger.error(\n { status: response.status, body: text, path },\n \"Intelligence platform request failed\",\n );\n throw new PlatformRequestError(\n `Intelligence platform error ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n\n const text = await response.text();\n if (!text) {\n return undefined as T;\n }\n return JSON.parse(text) as T;\n }\n\n #invokeLifecycleCallback(\n callbackName: \"onThreadCreated\" | \"onThreadUpdated\" | \"onThreadDeleted\",\n payload: ThreadSummary | ThreadDeletedPayload,\n ): void {\n const listeners =\n callbackName === \"onThreadCreated\"\n ? this.#threadCreatedListeners\n : callbackName === \"onThreadUpdated\"\n ? this.#threadUpdatedListeners\n : this.#threadDeletedListeners;\n\n for (const callback of listeners) {\n try {\n (callback as (p: typeof payload) => void)(payload);\n } catch (error) {\n logger.error(\n { err: error, callbackName, payload },\n \"Intelligence lifecycle callback failed\",\n );\n }\n }\n }\n\n /**\n * List all non-archived threads for a given user and agent.\n *\n * @param params.userId - User whose threads to list.\n * @param params.agentId - Agent whose threads to list.\n * @returns The thread list along with realtime subscription credentials.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async listThreads(params: {\n userId: string;\n agentId: string;\n includeArchived?: boolean;\n limit?: number;\n cursor?: string;\n }): Promise<ListThreadsResponse> {\n const query: Record<string, string> = {\n userId: params.userId,\n agentId: params.agentId,\n };\n if (params.includeArchived) query.includeArchived = \"true\";\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n\n const qs = new URLSearchParams(query).toString();\n return this.#request<ListThreadsResponse>(\"GET\", `/api/threads?${qs}`);\n }\n\n /**\n * List the given user's long-term memories, newest first.\n *\n * The platform scopes by the opaque app user supplied in the\n * `x-cpki-user-id` header (resolved by the runtime via `identifyUser`),\n * not a query param. Pass `includeInvalidated` to also return retired rows.\n *\n * @returns The `{ memories }` envelope the client memory store consumes.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async listMemories(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n includeInvalidated?: boolean;\n }): Promise<ListMemoriesResponse> {\n const qs = params.includeInvalidated ? \"?includeInvalidated=true\" : \"\";\n return this.#request<ListMemoriesResponse>(\n \"GET\",\n `/api/memories${qs}`,\n undefined,\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Create a memory for the given user (platform `POST /api/memories`).\n * @returns The stored memory; `absorbed` is true if the content was merged\n * into a near-duplicate rather than inserted as a new row.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async createMemory(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n content: string;\n kind: string;\n /** Optional: when omitted, the platform applies its default (`\"user\"`). */\n scope?: string;\n sourceThreadIds?: string[];\n }): Promise<SaveMemoryResponse> {\n return this.#request<SaveMemoryResponse>(\n \"POST\",\n `/api/memories`,\n {\n content: params.content,\n kind: params.kind,\n ...(params.scope !== undefined ? { scope: params.scope } : {}),\n sourceThreadIds: params.sourceThreadIds ?? [],\n },\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Supersede an existing memory (platform `PATCH /api/memories/:id`). The\n * `:id` row is retired and a new memory with the supplied content is\n * inserted atomically.\n * @returns The new memory plus `retiredId` (the id of the retired row).\n * @throws {@link PlatformRequestError} on non-2xx responses (e.g. 404 when\n * `:id` is not a live, same-scope memory for this user).\n */\n async updateMemory(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n id: string;\n content: string;\n kind: string;\n /** Optional: when omitted, the platform applies its default (`\"user\"`). */\n scope?: string;\n sourceThreadIds?: string[];\n }): Promise<SaveMemoryResponse> {\n return this.#request<SaveMemoryResponse>(\n \"PATCH\",\n `/api/memories/${encodeURIComponent(params.id)}`,\n {\n content: params.content,\n kind: params.kind,\n ...(params.scope !== undefined ? { scope: params.scope } : {}),\n sourceThreadIds: params.sourceThreadIds ?? [],\n },\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Non-lossily retire (forget) a memory (platform `DELETE /api/memories/:id`).\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async removeMemory(params: {\n userId: string;\n id: string;\n memoryGrant?: RuntimeMemoryGrant;\n }): Promise<void> {\n await this.#request<void>(\n \"DELETE\",\n `/api/memories/${encodeURIComponent(params.id)}`,\n undefined,\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Semantically recall the given user's memories (platform `POST\n * /api/memories/recall`, hybrid RAG). Each returned memory carries a\n * relevance `score`. `scope` narrows to `\"user\"`/`\"project\"`; omitted → platform default.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async recallMemories(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n query: string;\n limit?: number;\n scope?: string;\n }): Promise<RecallMemoriesResponse> {\n return this.#request<RecallMemoriesResponse>(\n \"POST\",\n `/api/memories/recall`,\n {\n query: params.query,\n ...(params.limit !== undefined ? { limit: params.limit } : {}),\n ...(params.scope !== undefined ? { scope: params.scope } : {}),\n },\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n async ɵsubscribeToThreads(\n params: SubscribeToThreadsRequest,\n ): Promise<SubscribeToThreadsResponse> {\n return this.#request<SubscribeToThreadsResponse>(\n \"POST\",\n \"/api/threads/subscribe\",\n {\n userId: params.userId,\n },\n );\n }\n\n /**\n * Mint memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Returns both the single-use `joinToken` and the\n * per-user `joinCode` the client needs to build the\n * `user_meta:memories:<joinCode>` channel topic. When the platform also\n * resolves a project scope it returns optional `projectJoinToken` /\n * `projectJoinCode`; both are passed through verbatim (omitted when absent,\n * the silent-degrade contract).\n *\n * The user is supplied via the `x-cpki-user-id` header — the same way every\n * other memory endpoint (`listMemories`/`createMemory`/…) identifies the app\n * user — because the platform's memory routes resolve identity from that\n * header, not the body. (This differs from `ɵsubscribeToThreads`, whose\n * platform endpoint reads `userId` from the body.)\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async ɵsubscribeToMemories(\n params: SubscribeToMemoriesRequest,\n ): Promise<SubscribeToMemoriesResponse> {\n return this.#request<SubscribeToMemoriesResponse>(\n \"POST\",\n \"/api/memories/subscribe\",\n undefined,\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Update thread metadata (e.g. name).\n *\n * Triggers the `onThreadUpdated` lifecycle callback on success.\n *\n * @returns The updated thread summary.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async updateThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n updates: UpdateThreadRequest;\n }): Promise<ThreadSummary> {\n const response = await this.#request<ThreadEnvelope>(\n \"PATCH\",\n `/api/threads/${encodeURIComponent(params.threadId)}`,\n {\n userId: params.userId,\n agentId: params.agentId,\n ...params.updates,\n },\n );\n this.#invokeLifecycleCallback(\"onThreadUpdated\", response.thread);\n return response.thread;\n }\n\n /**\n * Create a new thread on the platform.\n *\n * Triggers the `onThreadCreated` lifecycle callback on success.\n *\n * @returns The newly created thread summary.\n * @throws {@link PlatformRequestError} with status 409 if a thread with the\n * same `threadId` already exists.\n */\n async createThread(params: CreateThreadRequest): Promise<ThreadSummary> {\n const response = await this.#request<ThreadEnvelope>(\n \"POST\",\n `/api/threads`,\n {\n threadId: params.threadId,\n userId: params.userId,\n agentId: params.agentId,\n ...(params.name !== undefined ? { name: params.name } : {}),\n ...(params.learningContainerId !== undefined\n ? { learningContainerId: params.learningContainerId }\n : {}),\n },\n );\n this.#invokeLifecycleCallback(\"onThreadCreated\", response.thread);\n return response.thread;\n }\n\n /**\n * Fetch a single thread by ID.\n *\n * @returns The thread summary.\n * @throws {@link PlatformRequestError} with status 404 if the thread does\n * not exist.\n */\n async getThread(params: {\n threadId: string;\n userId: string;\n }): Promise<ThreadSummary> {\n const qs = new URLSearchParams({ userId: params.userId }).toString();\n const response = await this.#request<ThreadEnvelope>(\n \"GET\",\n `/api/threads/${encodeURIComponent(params.threadId)}?${qs}`,\n );\n return response.thread;\n }\n\n /**\n * Get an existing thread or create it if it does not exist.\n *\n * Handles the race where a concurrent request creates the thread between\n * the initial 404 and the subsequent `createThread` call by catching the\n * 409 Conflict and retrying the get.\n *\n * Triggers the `onThreadCreated` lifecycle callback when a new thread is\n * created.\n *\n * @returns An object containing the thread and a `created` flag indicating\n * whether the thread was newly created (`true`) or already existed (`false`).\n * @throws {@link PlatformRequestError} on non-2xx responses other than\n * 404 (get) and 409 (create race).\n */\n async getOrCreateThread(\n params: CreateThreadRequest,\n ): Promise<{ thread: ThreadSummary; created: boolean }> {\n try {\n const thread = await this.getThread({\n threadId: params.threadId,\n userId: params.userId,\n });\n return { thread, created: false };\n } catch (error) {\n if (!(error instanceof PlatformRequestError && error.status === 404)) {\n throw error;\n }\n }\n\n try {\n const thread = await this.createThread(params);\n return { thread, created: true };\n } catch (error) {\n // Another request created the thread between our get and create — retry get.\n if (error instanceof PlatformRequestError && error.status === 409) {\n const thread = await this.getThread({\n threadId: params.threadId,\n userId: params.userId,\n });\n return { thread, created: false };\n }\n throw error;\n }\n }\n\n /**\n * Fetch the full message history for a thread.\n *\n * @returns All persisted messages in chronological order.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async getThreadMessages(params: {\n threadId: string;\n userId: string;\n /** Internal managed-Channel delivery context for shared Thread access. */\n channelDeliveryId?: string;\n }): Promise<ThreadMessagesResponse> {\n const qs = new URLSearchParams({ userId: params.userId }).toString();\n return this.#request<ThreadMessagesResponse>(\n \"GET\",\n `/api/threads/${encodeURIComponent(params.threadId)}/messages?${qs}`,\n undefined,\n params.channelDeliveryId\n ? { \"X-Cpki-Channel-Delivery-Id\": params.channelDeliveryId }\n : undefined,\n );\n }\n\n /** @internal Fetches one authorized managed Channel asset for history hydration. */\n async ɵgetManagedChannelAsset(assetId: string): Promise<{\n bytes: Uint8Array;\n mimeType?: string;\n }> {\n const path = `/api/channels/files/${encodeURIComponent(assetId)}`;\n const response = await fetch(`${this.#apiUrl}${path}`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.#apiKey}` },\n });\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new PlatformRequestError(\n `Intelligence platform error ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n const mimeType = response.headers.get(\"content-type\") ?? undefined;\n return { bytes, ...(mimeType ? { mimeType } : {}) };\n }\n\n /**\n * Fetch the persisted AG-UI event stream for a thread.\n *\n * Backed by the platform's `GET /api/_inspect/threads/:id/events`\n * introspection endpoint (see Intelligence PR #144). Events are returned\n * in replay order across every run that targeted the thread. The\n * `_inspect/` prefix flags this as debug-only — production code paths\n * must not depend on it.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async getThreadEvents(params: {\n threadId: string;\n }): Promise<ThreadEventsResponse> {\n return this.#request<ThreadEventsResponse>(\n \"GET\",\n `/api/_inspect/threads/${encodeURIComponent(params.threadId)}/events`,\n );\n }\n\n /**\n * Fetch the current agent state for a thread.\n *\n * Backed by the platform's `GET /api/_inspect/threads/:id/state`\n * introspection endpoint (see Intelligence PR #144). The platform folds\n * RFC 6902 STATE_DELTA events on top of the latest STATE_SNAPSHOT, so\n * the returned state reflects the thread's current state — not just the\n * last snapshot. The discriminated response distinguishes \"no snapshot\n * persisted yet\" from \"snapshot present\" so consumers can render the\n * correct empty state.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async getThreadState(params: {\n threadId: string;\n }): Promise<ThreadStateResponse> {\n return this.#request<ThreadStateResponse>(\n \"GET\",\n `/api/_inspect/threads/${encodeURIComponent(params.threadId)}/state`,\n );\n }\n\n /**\n * Mark a thread as archived.\n *\n * Archived threads are excluded from {@link listThreads} results.\n * Triggers the `onThreadUpdated` lifecycle callback on success.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async archiveThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n }): Promise<void> {\n const response = await this.#request<ThreadEnvelope>(\n \"PATCH\",\n `/api/threads/${encodeURIComponent(params.threadId)}`,\n { userId: params.userId, agentId: params.agentId, archived: true },\n );\n this.#invokeLifecycleCallback(\"onThreadUpdated\", response.thread);\n }\n\n /**\n * Permanently delete a thread and its message history.\n *\n * This is irreversible. Triggers the `onThreadDeleted` lifecycle callback\n * on success.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async deleteThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n }): Promise<void> {\n await this.#request<void>(\n \"DELETE\",\n `/api/threads/${encodeURIComponent(params.threadId)}`,\n {\n userId: params.userId,\n agentId: params.agentId,\n reason: `Deleted via CopilotKit runtime (userId=${params.userId}, agentId=${params.agentId})`,\n },\n );\n this.#invokeLifecycleCallback(\"onThreadDeleted\", params);\n }\n\n /**\n * Annotate a thread event on the Intelligence platform's general annotation\n * endpoint (`PUT /connector/annotate/:clientEventId`).\n *\n * This is the generalized replacement for the old\n * `PUT /connector/user-actions/record/:clientEventId` endpoint. It supports\n * multiple annotation types via the `type` discriminator. The\n * `\"user_action\"` type records a user UI interaction for the self-learning\n * loop.\n *\n * `userId` must be resolved on the runtime side before calling this — the\n * platform prefixes it with the project id from the API key.\n *\n * Always hits the idempotent `PUT /connector/annotate/:clientEventId`\n * endpoint. A retry with the same `clientEventId` returns\n * `{ id: <original>, duplicate: true }` instead of creating a new row.\n * When `clientEventId` is omitted, a UUID is auto-generated for this call.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses, OR when the\n * platform returns an empty 2xx body (which would otherwise corrupt the\n * caller's typed result).\n */\n async annotate(params: AnnotateParams): Promise<AnnotateResponse> {\n const clientEventId = params.clientEventId ?? randomUUID();\n const path = `/connector/annotate/${encodeURIComponent(clientEventId)}`;\n const body: Record<string, unknown> = {\n type: params.type,\n userId: params.userId,\n threadId: params.threadId,\n };\n if (params.payload !== undefined) {\n body.payload = params.payload;\n }\n if (params.occurredAt !== undefined) {\n body.occurredAt = params.occurredAt;\n }\n const response = await this.#request<AnnotateResponse | null | undefined>(\n \"PUT\",\n path,\n body,\n );\n // `== null` catches both `undefined` (empty body from `#request`)\n // and JSON `null` (which would otherwise corrupt the typed result\n // and surface as a `TypeError` deep in caller code).\n if (response == null) {\n logger.error(\n { path },\n \"annotate: Intelligence platform returned 200 with empty or null body\",\n );\n throw new PlatformRequestError(\n \"annotate: empty or null response body from Intelligence platform\",\n 502,\n );\n }\n return response;\n }\n\n async ɵacquireThreadLock(\n params: AcquireThreadLockRequest,\n ): Promise<AcquireThreadLockResponse> {\n return this.#request<AcquireThreadLockResponse>(\n \"POST\",\n `/api/threads/${encodeURIComponent(params.threadId)}/lock`,\n {\n runId: params.runId,\n userId: params.userId,\n agentId: params.agentId,\n ...(params.learningContainerId !== undefined\n ? { learningContainerId: params.learningContainerId }\n : {}),\n ...(params.lockKeyPrefix !== undefined\n ? { lockKeyPrefix: params.lockKeyPrefix }\n : {}),\n ...(params.ttlSeconds !== undefined\n ? { ttlSeconds: params.ttlSeconds }\n : {}),\n },\n params.channelDeliveryId\n ? { \"X-Cpki-Channel-Delivery-Id\": params.channelDeliveryId }\n : undefined,\n );\n }\n\n async ɵcleanupThreadLock(params: CleanupThreadLockRequest): Promise<void> {\n return this.#request<void>(\n \"DELETE\",\n `/api/threads/${encodeURIComponent(params.threadId)}/lock`,\n {\n runId: params.runId,\n },\n );\n }\n\n async ɵrenewThreadLock(\n params: RenewThreadLockRequest,\n ): Promise<RenewThreadLockResponse> {\n return this.#request<RenewThreadLockResponse>(\n \"PATCH\",\n `/api/threads/${encodeURIComponent(params.threadId)}/lock`,\n {\n runId: params.runId,\n ttlSeconds: params.ttlSeconds,\n ...(params.lockKeyPrefix !== undefined\n ? { lockKeyPrefix: params.lockKeyPrefix }\n : {}),\n },\n );\n }\n\n async ɵgetActiveJoinCode(params: {\n threadId: string;\n userId: string;\n }): Promise<ThreadConnectionResponse> {\n const qs = new URLSearchParams({ userId: params.userId }).toString();\n return this.#request<ThreadConnectionResponse>(\n \"GET\",\n `/api/threads/${encodeURIComponent(params.threadId)}/join-code?${qs}`,\n );\n }\n\n async ɵconnectThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n }): Promise<ConnectThreadResponse> {\n const result = await this.#request<ThreadConnectionResponse>(\n \"POST\",\n `/api/threads/${encodeURIComponent(params.threadId)}/connect`,\n {\n userId: params.userId,\n agentId: params.agentId,\n },\n );\n\n // request() returns undefined for empty/204 responses\n return result ?? null;\n }\n}\n\n/**\n * Normalize a configured URL to \"provided\" or \"not provided\". A blank string\n * counts as not provided: these URLs are typically wired from environment\n * variables, and a declared-but-empty variable (`COPILOTKIT_INTELLIGENCE_URL=`,\n * common in generated `.env` files and container configs) arrives as `\"\"`. Left\n * as-is it would produce host-relative requests instead of falling back to the\n * managed platform.\n */\nfunction configuredUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n return trimmed ? trimmed : undefined;\n}\n\n/**\n * Warn when exactly one of `apiUrl`/`wsUrl` is configured. The API and realtime\n * planes are separate hosts, so a lone override silently leaves the other plane\n * on CopilotKit's managed platform — a self-hosted API paired with the managed\n * gateway (or vice versa), which fails as a hang rather than an error.\n */\nfunction warnOnPartialHostOverride(\n apiUrl: string | undefined,\n wsUrl: string | undefined,\n): void {\n if (apiUrl && !wsUrl) {\n logger.warn(\n `CopilotKitIntelligence: apiUrl is set to \"${apiUrl}\" but wsUrl is not, ` +\n `so wsUrl falls back to the managed default \"${MANAGED_INTELLIGENCE_WS_URL}\". ` +\n `The API and realtime planes are separate hosts — set both when pointing at a self-hosted deployment.`,\n );\n return;\n }\n\n if (wsUrl && !apiUrl) {\n logger.warn(\n `CopilotKitIntelligence: wsUrl is set to \"${wsUrl}\" but apiUrl is not, ` +\n `so apiUrl falls back to the managed default \"${MANAGED_INTELLIGENCE_API_URL}\". ` +\n `The API and realtime planes are separate hosts — set both when pointing at a self-hosted deployment.`,\n );\n }\n}\n\nfunction normalizeIntelligenceWsUrl(wsUrl: string): string {\n return wsUrl.replace(/\\/$/, \"\");\n}\n\nfunction deriveRunnerWsUrl(wsUrl: string): string {\n if (wsUrl.endsWith(\"/runner\")) {\n return wsUrl;\n }\n\n if (wsUrl.endsWith(\"/client\")) {\n return `${wsUrl.slice(0, -\"/client\".length)}/runner`;\n }\n\n if (wsUrl.endsWith(\"/channels\")) {\n return `${wsUrl.slice(0, -\"/channels\".length)}/runner`;\n }\n\n return `${wsUrl}/runner`;\n}\n\nfunction deriveClientWsUrl(wsUrl: string): string {\n if (wsUrl.endsWith(\"/client\")) {\n return wsUrl;\n }\n\n if (wsUrl.endsWith(\"/runner\")) {\n return `${wsUrl.slice(0, -\"/runner\".length)}/client`;\n }\n\n if (wsUrl.endsWith(\"/channels\")) {\n return `${wsUrl.slice(0, -\"/channels\".length)}/client`;\n }\n\n return `${wsUrl}/client`;\n}\n\nfunction deriveChannelsWsUrl(wsUrl: string): string {\n if (wsUrl.endsWith(\"/channels\")) return wsUrl;\n if (wsUrl.endsWith(\"/runner\")) {\n return `${wsUrl.slice(0, -\"/runner\".length)}/channels`;\n }\n if (wsUrl.endsWith(\"/client\")) {\n return `${wsUrl.slice(0, -\"/client\".length)}/channels`;\n }\n return `${wsUrl}/channels`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.mjs","names":["#apiUrl","#runnerWsUrl","#clientWsUrl","#channelsWsUrl","#apiKey","#enterpriseLearningEnabled","#threadCreatedListeners","#threadUpdatedListeners","#threadDeletedListeners","#request","#invokeLifecycleCallback","randomUUID"],"sources":["../../../../src/v2/runtime/intelligence-platform/client.ts"],"sourcesContent":["import { logger, parseInspectorMetadataV1 } from \"@copilotkit/shared\";\nimport type { InspectorMetadataV1 } from \"@copilotkit/shared\";\nimport { randomUUID } from \"crypto\";\n\n/**\n * Header name carrying the per-call end-user identity that the CopilotKit\n * Intelligence `/mcp` endpoint requires. Internal CopilotKit machinery —\n * `attachIntelligenceEnterpriseLearning` resolves the user via `identifyUser`\n * and bakes this header onto the `MCPMiddleware`'s transport config, so every\n * outbound MCP request stamps `X-Cpki-User-Id: <userId>`. Not part of the\n * public user API.\n *\n * @internal\n */\nexport const INTELLIGENCE_USER_ID_HEADER = \"x-cpki-user-id\";\n/** Immutable user/project Memory grant forwarded to Intelligence. */\nexport const INTELLIGENCE_MEMORY_GRANT_HEADER = \"x-cpki-memory-grant\";\n\ninterface RuntimeMemoryGrant {\n readonly user: \"none\" | \"read\" | \"read-write\";\n readonly project: \"none\" | \"read\" | \"read-write\";\n}\n\nconst memoryRequestHeaders = (\n userId: string,\n grant?: RuntimeMemoryGrant,\n): Record<string, string> => ({\n [INTELLIGENCE_USER_ID_HEADER]: userId,\n ...(grant\n ? { [INTELLIGENCE_MEMORY_GRANT_HEADER]: JSON.stringify(grant) }\n : {}),\n});\n\n/**\n * REST base URL of cloud-hosted CopilotKit Intelligence — the default\n * when {@link CopilotKitIntelligenceConfig.apiUrl} is omitted.\n */\nconst MANAGED_INTELLIGENCE_API_URL = \"https://api.intelligence.copilotkit.ai\";\n\n/**\n * Websocket base URL of cloud-hosted CopilotKit Intelligence — the\n * default when {@link CopilotKitIntelligenceConfig.wsUrl} is omitted.\n *\n * A different host from {@link MANAGED_INTELLIGENCE_API_URL}: the API and\n * realtime planes are deployed separately.\n */\nconst MANAGED_INTELLIGENCE_WS_URL = \"wss://realtime.intelligence.copilotkit.ai\";\n\n/** Maximum time spent on the optional Inspector metadata provider request. */\nconst INSPECTOR_METADATA_REQUEST_TIMEOUT_MS = 5_000;\n\n/**\n * Error thrown when a CopilotKit Intelligence HTTP request returns a non-2xx\n * status. Carries the HTTP {@link status} code so callers can branch on\n * specific failures (e.g. 404 for \"not found\", 409 for \"conflict\") without\n * parsing the error message string.\n *\n * @example\n * ```ts\n * try {\n * await intelligence.getThread({ threadId, userId });\n * } catch (error) {\n * if (error instanceof PlatformRequestError && error.status === 404) {\n * // thread does not exist yet\n * }\n * }\n * ```\n */\nexport class PlatformRequestError extends Error {\n constructor(\n message: string,\n /** The HTTP status code returned by the platform (e.g. 404, 409, 500). */\n public readonly status: number,\n ) {\n super(message);\n this.name = \"PlatformRequestError\";\n }\n}\n\n/** Payload passed to `onThreadDeleted` listeners. */\nexport interface ThreadDeletedPayload {\n threadId: string;\n userId: string;\n agentId: string;\n}\n\nexport interface CopilotKitIntelligenceConfig {\n /**\n * Base URL of the CopilotKit Intelligence API.\n *\n * Defaults to CopilotKit's managed platform,\n * `https://api.intelligence.copilotkit.ai`. Set it only when pointing at a\n * self-hosted or non-production deployment — and set {@link wsUrl} with it.\n */\n apiUrl?: string;\n /**\n * Intelligence websocket base URL. Runner and client socket URLs are derived\n * from this by appending `/runner` or `/client`, so pass the bare base.\n *\n * Defaults to CopilotKit's managed platform,\n * `wss://realtime.intelligence.copilotkit.ai`.\n *\n * This is a DIFFERENT host from {@link apiUrl} — the API and realtime planes are\n * deployed separately — so it cannot be derived by scheme-swapping `apiUrl`.\n * Overriding one without the other therefore points the two planes at\n * different deployments, which logs a warning.\n */\n wsUrl?: string;\n /** API key for authenticating with CopilotKit Intelligence */\n apiKey: string;\n /**\n * Enable Enterprise Learning — expose CopilotKit Intelligence's\n * built-in tools (bash + thread/memory tools) to agent runs on an\n * intelligence runtime that resolve a user. Attached uniformly across\n * agent frameworks by `attachIntelligenceEnterpriseLearning` via\n * `@ag-ui/mcp-middleware`, with the resolved user-id and project apiKey\n * baked into the transport headers for that request's clone.\n *\n * Defaults to `false` — opt-in. Existing intelligence setups continue\n * to work without these tools unless they flip this flag.\n *\n * @deprecated Configure `memory.access` on `CopilotRuntime` so each web\n * request receives an explicit agent or client Memory grant.\n */\n enableEnterpriseLearning?: boolean;\n /**\n * Initial listener invoked after a thread is created.\n * Prefer {@link CopilotKitIntelligence.onThreadCreated} for multiple listeners.\n */\n onThreadCreated?: (thread: ThreadSummary) => void;\n /**\n * Initial listener invoked after a thread is updated.\n * Prefer {@link CopilotKitIntelligence.onThreadUpdated} for multiple listeners.\n */\n onThreadUpdated?: (thread: ThreadSummary) => void;\n /**\n * Initial listener invoked after a thread is deleted.\n * Prefer {@link CopilotKitIntelligence.onThreadDeleted} for multiple listeners.\n */\n onThreadDeleted?: (params: ThreadDeletedPayload) => void;\n}\n\n/**\n * Summary metadata for a single thread returned by the platform.\n *\n * This is the shape returned by list, get, create, and update operations.\n * It does not include the thread's message history — use\n * {@link CopilotKitIntelligence.getThreadMessages} for that.\n */\nexport interface ThreadSummary {\n /** Platform-assigned unique identifier. */\n id: string;\n /** Human-readable display name, or `null` if the thread has not been named. */\n name: string | null;\n /** ISO-8601 timestamp of the most recent agent run on this thread. */\n lastRunAt?: string;\n /** ISO-8601 timestamp of the most recent metadata update. */\n lastUpdatedAt?: string;\n /** ISO-8601 timestamp when the thread was created. */\n createdAt?: string;\n /** ISO-8601 timestamp when the thread was last updated. */\n updatedAt?: string;\n /** Whether the thread has been archived. Archived threads are excluded from default list results. */\n archived?: boolean;\n /** The agent that owns this thread. */\n agentId?: string;\n /** The user who created this thread. */\n createdById?: string;\n /** The organization this thread belongs to. */\n organizationId?: string;\n}\n\n/** Response from listing threads for a user/agent pair. */\nexport interface ListThreadsResponse {\n /** The matching threads, sorted by the platform's default ordering. */\n threads: ThreadSummary[];\n /** Join code for subscribing to realtime metadata updates for these threads. */\n joinCode: string;\n /** Short-lived token for authenticating the realtime subscription. */\n joinToken?: string;\n /** Opaque cursor for fetching the next page. `null` or absent when there are no more pages. */\n nextCursor?: string | null;\n}\n\n/**\n * A single memory as returned by the platform's list endpoint. Mirrors the\n * public projection the client memory store consumes (tenant ids stripped).\n */\nexport interface MemorySummary {\n /** Platform-assigned unique identifier. */\n id: string;\n /** Memory kind, e.g. `\"topical\"`, `\"episodic\"`, `\"operational\"`. */\n kind: string;\n /** Memory scope: `\"user\"` (private) or `\"project\"` (shared). */\n scope: string;\n /** The remembered fact, preference, or procedure. */\n content: string;\n /** Ids of the threads this memory was learned from. */\n sourceThreadIds: string[];\n /** ISO-8601 timestamp when the memory was retired, or `null` if live. */\n invalidatedAt: string | null;\n /** Relevance score from a `recall` (hybrid RAG) query. Present only on recall responses. */\n score?: number;\n}\n\n/** Response from {@link CopilotKitIntelligence.listMemories}. */\nexport interface ListMemoriesResponse {\n memories: MemorySummary[];\n}\n\n/** Response from {@link CopilotKitIntelligence.recallMemories}. */\nexport interface RecallMemoriesResponse {\n memories: MemorySummary[];\n}\n\n/**\n * Response from a create ({@link CopilotKitIntelligence.createMemory}) or\n * supersede ({@link CopilotKitIntelligence.updateMemory}) call: the stored\n * memory, plus the operation-specific marker the client store consumes.\n */\nexport interface SaveMemoryResponse extends MemorySummary {\n /** Create only: content was merged into a near-duplicate, not inserted new. */\n absorbed?: boolean;\n /** Supersede only: the id of the memory retired by this call. */\n retiredId?: string;\n}\n\n/**\n * Fields that can be updated on a thread via {@link CopilotKitIntelligence.updateThread}.\n *\n * Additional platform-specific fields can be passed as extra keys and will be\n * forwarded to the PATCH request body.\n */\nexport interface UpdateThreadRequest {\n /** New human-readable display name for the thread. */\n name?: string;\n [key: string]: unknown;\n}\n\n/** Parameters for creating a new thread via {@link CopilotKitIntelligence.createThread}. */\nexport interface CreateThreadRequest {\n /** Client-generated unique identifier for the new thread. */\n threadId: string;\n /** The user creating the thread. Used for authorization and scoping. */\n userId: string;\n /** The agent this thread belongs to. */\n agentId: string;\n /** Optional initial display name. If omitted, the thread is unnamed until explicitly renamed. */\n name?: string;\n /** Developer-set stable ID of the Learning Container for this Thread. */\n learningContainerId?: string;\n}\n\n/** Credentials returned when locking or joining a thread's realtime channel. */\nexport interface ThreadConnectionResponse {\n /** Canonical platform thread identifier for the run or connection. */\n threadId: string;\n /** Canonical platform run identifier for an active run lock. */\n runId?: string;\n /** Short-lived token for authenticating the Phoenix channel join. */\n joinToken: string;\n /** Lock metadata echoed back by the platform. */\n lock?: ThreadLockInfo;\n}\n\nexport interface SubscribeToThreadsRequest {\n userId: string;\n}\n\nexport interface SubscribeToThreadsResponse {\n joinToken: string;\n}\n\nexport interface SubscribeToMemoriesRequest {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n}\n\n/**\n * Memory subscribe returns both the token and the join code, unlike threads\n * (whose join code reaches the client via the thread-list response). Memory has\n * no list-borne code, so the code is delivered here and used to build the\n * `user_meta:memories:<joinCode>` channel topic.\n */\nexport interface SubscribeToMemoriesResponse {\n joinToken?: string;\n joinCode?: string;\n /**\n * Project-scoped realtime credentials, minted by the platform only when the\n * caller's API key resolves to a project scope. Absent when project scope is\n * unavailable — a silent-degrade contract: the client then opens only the\n * user channel. When present, the client builds the second\n * `project_meta:memories:<projectJoinCode>` channel topic from them.\n */\n projectJoinToken?: string;\n projectJoinCode?: string;\n}\n\nexport type ConnectThreadResponse = ThreadConnectionResponse | null;\n\nexport interface AcquireThreadLockResponse extends ThreadConnectionResponse {\n /** Canonical platform run identifier for the acquired lock. */\n runId: string;\n}\n\n/**\n * Parameters for annotating a thread event via\n * {@link CopilotKitIntelligence.annotate}. The runtime resolves `userId`\n * from the customer's BFF auth before calling this; the platform prefixes\n * it with the project id at write time.\n *\n * `payload` is the type-specific JSON blob for the annotation (for example, a\n * `\"user_action\"` event carries the recorded fields). The exact\n * shape per type is validated by the Intelligence backend; canonical shapes\n * are documented on the Intelligence react-core side.\n */\nexport interface AnnotateParams {\n /** The user the annotation belongs to. */\n userId: string;\n /** The thread the annotation is associated with. May be unknown to the platform. */\n threadId: string;\n /**\n * Discriminator identifying the annotation type.\n * Must match a type known to CopilotKit Intelligence\n * (for example, `\"user_action\"`).\n */\n type: string;\n /** Type-specific payload. Shape varies by `type`. */\n payload?: unknown;\n /**\n * Caller-supplied idempotency key (any RFC-compliant UUID). When omitted,\n * a UUID is auto-generated. Every call hits the platform's idempotent\n * `PUT /connector/annotate/:clientEventId` endpoint; a retry with the\n * same id collapses to the original row.\n */\n clientEventId?: string;\n /** ISO-8601 client-asserted timestamp. Defaults to server NOW() when absent. */\n occurredAt?: string;\n}\n\n/** Response from {@link CopilotKitIntelligence.annotate}. */\nexport interface AnnotateResponse {\n /** Database id of the annotation row (BIGINT, returned as a string). */\n id: string;\n /**\n * True when the platform recognized the `clientEventId` as a retry of\n * a previous call and returned the original row id instead of inserting\n * a new one.\n */\n duplicate: boolean;\n}\n\n/** A single message within a thread's persisted history. */\nexport interface ThreadMessage {\n /** Unique identifier for this message. */\n id: string;\n /** Message role, e.g. `\"user\"`, `\"assistant\"`, `\"tool\"`. */\n role: string;\n /** Structured AG-UI content. May be absent for tool-call-only messages. */\n content?: unknown;\n /** Standard AG-UI activity type when `role` is `\"activity\"`. */\n activityType?: string;\n /** Tool calls initiated by this message (assistant role only). */\n toolCalls?: Array<{\n id: string;\n name: string;\n /** JSON-encoded arguments passed to the tool. */\n args: string;\n }>;\n /** For tool-result messages, the ID of the tool call this message responds to. */\n toolCallId?: string;\n}\n\n/** Response from {@link CopilotKitIntelligence.getThreadMessages}. */\nexport interface ThreadMessagesResponse {\n messages: ThreadMessage[];\n}\n\n/**\n * Persisted AG-UI event for the inspector's debugging views. The platform\n * stores raw events keyed by run; the `_inspect` route returns them in\n * replay order (oldest first) across every run that targeted the thread.\n */\nexport interface ThreadInspectEvent {\n type: string;\n [key: string]: unknown;\n}\n\n/**\n * Response from {@link CopilotKitIntelligence.getThreadEvents}. Mirrors the\n * `ThreadEventsResult` shape returned by the platform's\n * `GET /api/_inspect/threads/:id/events` endpoint.\n */\nexport interface ThreadEventsResponse {\n events: ThreadInspectEvent[];\n /** Row IDs the platform failed to decode (raw column corrupted). */\n decodeErrorRowIds: string[];\n /** True when the platform hit its per-thread event cap. */\n truncated: boolean;\n}\n\n/**\n * Response from {@link CopilotKitIntelligence.getThreadState}. Mirrors the\n * discriminated `ThreadStateResult` returned by the platform's\n * `GET /api/_inspect/threads/:id/state` endpoint, which folds RFC 6902\n * STATE_DELTA events on top of the latest STATE_SNAPSHOT.\n */\nexport type ThreadStateResponse =\n | { kind: \"no-snapshot\" }\n | { kind: \"snapshot-decode-error\" }\n | { kind: \"snapshot\"; state: unknown; skippedDeltas: number };\n\nexport interface AcquireThreadLockRequest {\n threadId: string;\n runId: string;\n userId: string;\n agentId: string;\n /** Developer-set stable ID to assign before the run lock is acquired. */\n learningContainerId?: string;\n /** Internal managed-Channel delivery context for shared Thread access. */\n channelDeliveryId?: string;\n /** Custom Redis key prefix for the lock (default: \"thread\"). */\n lockKeyPrefix?: string;\n /** Lock TTL in seconds. When set, the lock auto-expires after this duration. */\n ttlSeconds?: number;\n}\n\nexport interface RenewThreadLockRequest {\n threadId: string;\n runId: string;\n /** New TTL to set on the lock in seconds. */\n ttlSeconds: number;\n /** Must match the prefix used when acquiring. */\n lockKeyPrefix?: string;\n}\n\nexport interface CleanupThreadLockRequest {\n threadId: string;\n runId: string;\n}\n\nexport interface RenewThreadLockResponse {\n ttlSeconds: number;\n}\n\nexport interface ThreadLockInfo {\n key: string;\n ttlSeconds: number | null;\n}\n\ninterface ThreadEnvelope {\n thread: ThreadSummary;\n}\n\n/**\n * Client for the CopilotKit Intelligence REST API.\n *\n * Construct the client once and pass it to any consumers that need it\n * (e.g. `CopilotRuntime`, `IntelligenceAgentRunner`):\n *\n * ```ts\n * import { CopilotKitIntelligence, CopilotRuntime } from \"@copilotkit/runtime\";\n *\n * const intelligence = new CopilotKitIntelligence({\n * apiKey: process.env.INTELLIGENCE_API_KEY!,\n * });\n *\n * const runtime = new CopilotRuntime({\n * agents,\n * intelligence,\n * });\n * ```\n *\n * `apiUrl` and `wsUrl` default to cloud-hosted CopilotKit Intelligence.\n * Override both together to target a self-hosted or non-production deployment:\n *\n * ```ts\n * const intelligence = new CopilotKitIntelligence({\n * apiUrl: \"https://intelligence.internal\",\n * wsUrl: \"wss://realtime.intelligence.internal\",\n * apiKey: process.env.INTELLIGENCE_API_KEY!,\n * });\n * ```\n */\nexport class CopilotKitIntelligence {\n #apiUrl: string;\n #runnerWsUrl: string;\n #clientWsUrl: string;\n #channelsWsUrl: string;\n #apiKey: string;\n #enterpriseLearningEnabled: boolean;\n #threadCreatedListeners = new Set<(thread: ThreadSummary) => void>();\n #threadUpdatedListeners = new Set<(thread: ThreadSummary) => void>();\n #threadDeletedListeners = new Set<(params: ThreadDeletedPayload) => void>();\n\n constructor(config: CopilotKitIntelligenceConfig) {\n const configuredApiUrl = configuredUrl(config.apiUrl);\n const configuredWsUrl = configuredUrl(config.wsUrl);\n warnOnPartialHostOverride(configuredApiUrl, configuredWsUrl);\n\n const intelligenceWsUrl = normalizeIntelligenceWsUrl(\n configuredWsUrl ?? MANAGED_INTELLIGENCE_WS_URL,\n );\n\n this.#apiUrl = (configuredApiUrl ?? MANAGED_INTELLIGENCE_API_URL).replace(\n /\\/$/,\n \"\",\n );\n this.#runnerWsUrl = deriveRunnerWsUrl(intelligenceWsUrl);\n this.#clientWsUrl = deriveClientWsUrl(intelligenceWsUrl);\n this.#channelsWsUrl = deriveChannelsWsUrl(intelligenceWsUrl);\n this.#apiKey = config.apiKey;\n this.#enterpriseLearningEnabled = config.enableEnterpriseLearning ?? false;\n\n if (config.onThreadCreated) {\n this.onThreadCreated(config.onThreadCreated);\n }\n if (config.onThreadUpdated) {\n this.onThreadUpdated(config.onThreadUpdated);\n }\n if (config.onThreadDeleted) {\n this.onThreadDeleted(config.onThreadDeleted);\n }\n }\n\n /**\n * Register a listener invoked whenever a thread is created.\n *\n * Multiple listeners can be registered. Each call returns an unsubscribe\n * function that removes the listener when called.\n *\n * @param callback - Receives the newly created {@link ThreadSummary}.\n * @returns A function that removes this listener when called.\n *\n * @example\n * ```ts\n * const unsubscribe = intelligence.onThreadCreated((thread) => {\n * console.log(\"Thread created:\", thread.id);\n * });\n * // later…\n * unsubscribe();\n * ```\n */\n onThreadCreated(callback: (thread: ThreadSummary) => void): () => void {\n this.#threadCreatedListeners.add(callback);\n return () => {\n this.#threadCreatedListeners.delete(callback);\n };\n }\n\n /**\n * Register a listener invoked whenever a thread is updated (including archive).\n *\n * Multiple listeners can be registered. Each call returns an unsubscribe\n * function that removes the listener when called.\n *\n * @param callback - Receives the updated {@link ThreadSummary}.\n * @returns A function that removes this listener when called.\n */\n onThreadUpdated(callback: (thread: ThreadSummary) => void): () => void {\n this.#threadUpdatedListeners.add(callback);\n return () => {\n this.#threadUpdatedListeners.delete(callback);\n };\n }\n\n /**\n * Register a listener invoked whenever a thread is deleted.\n *\n * Multiple listeners can be registered. Each call returns an unsubscribe\n * function that removes the listener when called.\n *\n * @param callback - Receives the {@link ThreadDeletedPayload} identifying\n * the deleted thread.\n * @returns A function that removes this listener when called.\n */\n onThreadDeleted(\n callback: (params: ThreadDeletedPayload) => void,\n ): () => void {\n this.#threadDeletedListeners.add(callback);\n return () => {\n this.#threadDeletedListeners.delete(callback);\n };\n }\n\n ɵgetApiUrl(): string {\n return this.#apiUrl;\n }\n\n ɵgetRunnerWsUrl(): string {\n return this.#runnerWsUrl;\n }\n\n ɵgetClientWsUrl(): string {\n return this.#clientWsUrl;\n }\n\n ɵgetChannelsWsUrl(): string {\n return this.#channelsWsUrl;\n }\n\n ɵgetRunnerAuthToken(): string {\n return this.#apiKey;\n }\n\n /** @internal Used by `attachIntelligenceEnterpriseLearning` to populate `Authorization`. */\n ɵgetApiKey(): string {\n return this.#apiKey;\n }\n\n /** @internal Used by `attachIntelligenceEnterpriseLearning` to gate MCP attachment. */\n ɵisEnterpriseLearningEnabled(): boolean {\n return this.#enterpriseLearningEnabled;\n }\n\n /**\n * Fetch trusted Inspector metadata for this runtime's Intelligence project.\n *\n * The request always uses the server-configured Intelligence API key. A 404\n * is treated as compatible absence so runtimes can work with older App API\n * deployments that do not expose this endpoint yet.\n *\n * @returns Sanitized V1 metadata, or `undefined` when the provider has no\n * supported metadata.\n * @throws {@link PlatformRequestError} for provider failures other than 404.\n */\n async getInspectorMetadata(): Promise<InspectorMetadataV1 | undefined> {\n const path = \"/api/inspector/metadata\";\n const abortController = new AbortController();\n const timeoutError = new Error(\n \"Intelligence inspector metadata request timed out\",\n );\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(timeoutError);\n abortController.abort(timeoutError);\n }, INSPECTOR_METADATA_REQUEST_TIMEOUT_MS);\n });\n\n try {\n const response = await Promise.race([\n fetch(`${this.#apiUrl}${path}`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.#apiKey}` },\n signal: abortController.signal,\n }),\n timeout,\n ]);\n\n if (response.status === 204 || response.status === 404) {\n return undefined;\n }\n\n if (!response.ok) {\n logger.error(\n { status: response.status, path },\n \"Intelligence platform request failed\",\n );\n throw new PlatformRequestError(\n `Intelligence platform error ${response.status}`,\n response.status,\n );\n }\n\n const body = await Promise.race([response.text(), timeout]);\n const decoded: unknown = JSON.parse(body);\n return parseInspectorMetadataV1(decoded);\n } catch (error) {\n if (error === timeoutError) {\n logger.warn(\n { path, timeoutMs: INSPECTOR_METADATA_REQUEST_TIMEOUT_MS },\n \"Intelligence inspector metadata request timed out\",\n );\n }\n throw error;\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n async #request<T>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const url = `${this.#apiUrl}${path}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.#apiKey}`,\n \"Content-Type\": \"application/json\",\n ...extraHeaders,\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n logger.error(\n { status: response.status, body: text, path },\n \"Intelligence platform request failed\",\n );\n throw new PlatformRequestError(\n `Intelligence platform error ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n\n const text = await response.text();\n if (!text) {\n return undefined as T;\n }\n return JSON.parse(text) as T;\n }\n\n #invokeLifecycleCallback(\n callbackName: \"onThreadCreated\" | \"onThreadUpdated\" | \"onThreadDeleted\",\n payload: ThreadSummary | ThreadDeletedPayload,\n ): void {\n const listeners =\n callbackName === \"onThreadCreated\"\n ? this.#threadCreatedListeners\n : callbackName === \"onThreadUpdated\"\n ? this.#threadUpdatedListeners\n : this.#threadDeletedListeners;\n\n for (const callback of listeners) {\n try {\n (callback as (p: typeof payload) => void)(payload);\n } catch (error) {\n logger.error(\n { err: error, callbackName, payload },\n \"Intelligence lifecycle callback failed\",\n );\n }\n }\n }\n\n /**\n * List all non-archived threads for a given user and agent.\n *\n * @param params.userId - User whose threads to list.\n * @param params.agentId - Agent whose threads to list.\n * @returns The thread list along with realtime subscription credentials.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async listThreads(params: {\n userId: string;\n agentId: string;\n includeArchived?: boolean;\n limit?: number;\n cursor?: string;\n }): Promise<ListThreadsResponse> {\n const query: Record<string, string> = {\n userId: params.userId,\n agentId: params.agentId,\n };\n if (params.includeArchived) query.includeArchived = \"true\";\n if (params.limit != null) query.limit = String(params.limit);\n if (params.cursor) query.cursor = params.cursor;\n\n const qs = new URLSearchParams(query).toString();\n return this.#request<ListThreadsResponse>(\"GET\", `/api/threads?${qs}`);\n }\n\n /**\n * List the given user's long-term memories, newest first.\n *\n * The platform scopes by the opaque app user supplied in the\n * `x-cpki-user-id` header (resolved by the runtime via `identifyUser`),\n * not a query param. Pass `includeInvalidated` to also return retired rows.\n *\n * @returns The `{ memories }` envelope the client memory store consumes.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async listMemories(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n includeInvalidated?: boolean;\n }): Promise<ListMemoriesResponse> {\n const qs = params.includeInvalidated ? \"?includeInvalidated=true\" : \"\";\n return this.#request<ListMemoriesResponse>(\n \"GET\",\n `/api/memories${qs}`,\n undefined,\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Create a memory for the given user (platform `POST /api/memories`).\n * @returns The stored memory; `absorbed` is true if the content was merged\n * into a near-duplicate rather than inserted as a new row.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async createMemory(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n content: string;\n kind: string;\n /** Optional: when omitted, the platform applies its default (`\"user\"`). */\n scope?: string;\n sourceThreadIds?: string[];\n }): Promise<SaveMemoryResponse> {\n return this.#request<SaveMemoryResponse>(\n \"POST\",\n `/api/memories`,\n {\n content: params.content,\n kind: params.kind,\n ...(params.scope !== undefined ? { scope: params.scope } : {}),\n sourceThreadIds: params.sourceThreadIds ?? [],\n },\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Supersede an existing memory (platform `PATCH /api/memories/:id`). The\n * `:id` row is retired and a new memory with the supplied content is\n * inserted atomically.\n * @returns The new memory plus `retiredId` (the id of the retired row).\n * @throws {@link PlatformRequestError} on non-2xx responses (e.g. 404 when\n * `:id` is not a live, same-scope memory for this user).\n */\n async updateMemory(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n id: string;\n content: string;\n kind: string;\n /** Optional: when omitted, the platform applies its default (`\"user\"`). */\n scope?: string;\n sourceThreadIds?: string[];\n }): Promise<SaveMemoryResponse> {\n return this.#request<SaveMemoryResponse>(\n \"PATCH\",\n `/api/memories/${encodeURIComponent(params.id)}`,\n {\n content: params.content,\n kind: params.kind,\n ...(params.scope !== undefined ? { scope: params.scope } : {}),\n sourceThreadIds: params.sourceThreadIds ?? [],\n },\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Non-lossily retire (forget) a memory (platform `DELETE /api/memories/:id`).\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async removeMemory(params: {\n userId: string;\n id: string;\n memoryGrant?: RuntimeMemoryGrant;\n }): Promise<void> {\n await this.#request<void>(\n \"DELETE\",\n `/api/memories/${encodeURIComponent(params.id)}`,\n undefined,\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Semantically recall the given user's memories (platform `POST\n * /api/memories/recall`, hybrid RAG). Each returned memory carries a\n * relevance `score`. `scope` narrows to `\"user\"`/`\"project\"`; omitted → platform default.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async recallMemories(params: {\n userId: string;\n memoryGrant?: RuntimeMemoryGrant;\n query: string;\n limit?: number;\n scope?: string;\n }): Promise<RecallMemoriesResponse> {\n return this.#request<RecallMemoriesResponse>(\n \"POST\",\n `/api/memories/recall`,\n {\n query: params.query,\n ...(params.limit !== undefined ? { limit: params.limit } : {}),\n ...(params.scope !== undefined ? { scope: params.scope } : {}),\n },\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n async ɵsubscribeToThreads(\n params: SubscribeToThreadsRequest,\n ): Promise<SubscribeToThreadsResponse> {\n return this.#request<SubscribeToThreadsResponse>(\n \"POST\",\n \"/api/threads/subscribe\",\n {\n userId: params.userId,\n },\n );\n }\n\n /**\n * Mint memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Returns both the single-use `joinToken` and the\n * per-user `joinCode` the client needs to build the\n * `user_meta:memories:<joinCode>` channel topic. When the platform also\n * resolves a project scope it returns optional `projectJoinToken` /\n * `projectJoinCode`; both are passed through verbatim (omitted when absent,\n * the silent-degrade contract).\n *\n * The user is supplied via the `x-cpki-user-id` header — the same way every\n * other memory endpoint (`listMemories`/`createMemory`/…) identifies the app\n * user — because the platform's memory routes resolve identity from that\n * header, not the body. (This differs from `ɵsubscribeToThreads`, whose\n * platform endpoint reads `userId` from the body.)\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async ɵsubscribeToMemories(\n params: SubscribeToMemoriesRequest,\n ): Promise<SubscribeToMemoriesResponse> {\n return this.#request<SubscribeToMemoriesResponse>(\n \"POST\",\n \"/api/memories/subscribe\",\n undefined,\n memoryRequestHeaders(params.userId, params.memoryGrant),\n );\n }\n\n /**\n * Update thread metadata (e.g. name).\n *\n * Triggers the `onThreadUpdated` lifecycle callback on success.\n *\n * @returns The updated thread summary.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async updateThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n updates: UpdateThreadRequest;\n }): Promise<ThreadSummary> {\n const response = await this.#request<ThreadEnvelope>(\n \"PATCH\",\n `/api/threads/${encodeURIComponent(params.threadId)}`,\n {\n userId: params.userId,\n agentId: params.agentId,\n ...params.updates,\n },\n );\n this.#invokeLifecycleCallback(\"onThreadUpdated\", response.thread);\n return response.thread;\n }\n\n /**\n * Create a new thread on the platform.\n *\n * Triggers the `onThreadCreated` lifecycle callback on success.\n *\n * @returns The newly created thread summary.\n * @throws {@link PlatformRequestError} with status 409 if a thread with the\n * same `threadId` already exists.\n */\n async createThread(params: CreateThreadRequest): Promise<ThreadSummary> {\n const response = await this.#request<ThreadEnvelope>(\n \"POST\",\n `/api/threads`,\n {\n threadId: params.threadId,\n userId: params.userId,\n agentId: params.agentId,\n ...(params.name !== undefined ? { name: params.name } : {}),\n ...(params.learningContainerId !== undefined\n ? { learningContainerId: params.learningContainerId }\n : {}),\n },\n );\n this.#invokeLifecycleCallback(\"onThreadCreated\", response.thread);\n return response.thread;\n }\n\n /**\n * Fetch a single thread by ID.\n *\n * @returns The thread summary.\n * @throws {@link PlatformRequestError} with status 404 if the thread does\n * not exist.\n */\n async getThread(params: {\n threadId: string;\n userId: string;\n }): Promise<ThreadSummary> {\n const qs = new URLSearchParams({ userId: params.userId }).toString();\n const response = await this.#request<ThreadEnvelope>(\n \"GET\",\n `/api/threads/${encodeURIComponent(params.threadId)}?${qs}`,\n );\n return response.thread;\n }\n\n /**\n * Get an existing thread or create it if it does not exist.\n *\n * Handles the race where a concurrent request creates the thread between\n * the initial 404 and the subsequent `createThread` call by catching the\n * 409 Conflict and retrying the get.\n *\n * Triggers the `onThreadCreated` lifecycle callback when a new thread is\n * created.\n *\n * @returns An object containing the thread and a `created` flag indicating\n * whether the thread was newly created (`true`) or already existed (`false`).\n * @throws {@link PlatformRequestError} on non-2xx responses other than\n * 404 (get) and 409 (create race).\n */\n async getOrCreateThread(\n params: CreateThreadRequest,\n ): Promise<{ thread: ThreadSummary; created: boolean }> {\n try {\n const thread = await this.getThread({\n threadId: params.threadId,\n userId: params.userId,\n });\n return { thread, created: false };\n } catch (error) {\n if (!(error instanceof PlatformRequestError && error.status === 404)) {\n throw error;\n }\n }\n\n try {\n const thread = await this.createThread(params);\n return { thread, created: true };\n } catch (error) {\n // Another request created the thread between our get and create — retry get.\n if (error instanceof PlatformRequestError && error.status === 409) {\n const thread = await this.getThread({\n threadId: params.threadId,\n userId: params.userId,\n });\n return { thread, created: false };\n }\n throw error;\n }\n }\n\n /**\n * Fetch the full message history for a thread.\n *\n * @returns All persisted messages in chronological order.\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async getThreadMessages(params: {\n threadId: string;\n userId: string;\n /** Internal managed-Channel delivery context for shared Thread access. */\n channelDeliveryId?: string;\n }): Promise<ThreadMessagesResponse> {\n const qs = new URLSearchParams({ userId: params.userId }).toString();\n return this.#request<ThreadMessagesResponse>(\n \"GET\",\n `/api/threads/${encodeURIComponent(params.threadId)}/messages?${qs}`,\n undefined,\n params.channelDeliveryId\n ? { \"X-Cpki-Channel-Delivery-Id\": params.channelDeliveryId }\n : undefined,\n );\n }\n\n /** @internal Fetches one authorized managed Channel asset for history hydration. */\n async ɵgetManagedChannelAsset(assetId: string): Promise<{\n bytes: Uint8Array;\n mimeType?: string;\n }> {\n const path = `/api/channels/files/${encodeURIComponent(assetId)}`;\n const response = await fetch(`${this.#apiUrl}${path}`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.#apiKey}` },\n });\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new PlatformRequestError(\n `Intelligence platform error ${response.status}: ${text || response.statusText}`,\n response.status,\n );\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n const mimeType = response.headers.get(\"content-type\") ?? undefined;\n return { bytes, ...(mimeType ? { mimeType } : {}) };\n }\n\n /**\n * Fetch the persisted AG-UI event stream for a thread.\n *\n * Backed by the platform's `GET /api/_inspect/threads/:id/events`\n * introspection endpoint (see Intelligence PR #144). Events are returned\n * in replay order across every run that targeted the thread. The\n * `_inspect/` prefix flags this as debug-only — production code paths\n * must not depend on it.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async getThreadEvents(params: {\n threadId: string;\n }): Promise<ThreadEventsResponse> {\n return this.#request<ThreadEventsResponse>(\n \"GET\",\n `/api/_inspect/threads/${encodeURIComponent(params.threadId)}/events`,\n );\n }\n\n /**\n * Fetch the current agent state for a thread.\n *\n * Backed by the platform's `GET /api/_inspect/threads/:id/state`\n * introspection endpoint (see Intelligence PR #144). The platform folds\n * RFC 6902 STATE_DELTA events on top of the latest STATE_SNAPSHOT, so\n * the returned state reflects the thread's current state — not just the\n * last snapshot. The discriminated response distinguishes \"no snapshot\n * persisted yet\" from \"snapshot present\" so consumers can render the\n * correct empty state.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async getThreadState(params: {\n threadId: string;\n }): Promise<ThreadStateResponse> {\n return this.#request<ThreadStateResponse>(\n \"GET\",\n `/api/_inspect/threads/${encodeURIComponent(params.threadId)}/state`,\n );\n }\n\n /**\n * Mark a thread as archived.\n *\n * Archived threads are excluded from {@link listThreads} results.\n * Triggers the `onThreadUpdated` lifecycle callback on success.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async archiveThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n }): Promise<void> {\n const response = await this.#request<ThreadEnvelope>(\n \"PATCH\",\n `/api/threads/${encodeURIComponent(params.threadId)}`,\n { userId: params.userId, agentId: params.agentId, archived: true },\n );\n this.#invokeLifecycleCallback(\"onThreadUpdated\", response.thread);\n }\n\n /**\n * Permanently delete a thread and its message history.\n *\n * This is irreversible. Triggers the `onThreadDeleted` lifecycle callback\n * on success.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses.\n */\n async deleteThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n }): Promise<void> {\n await this.#request<void>(\n \"DELETE\",\n `/api/threads/${encodeURIComponent(params.threadId)}`,\n {\n userId: params.userId,\n agentId: params.agentId,\n reason: `Deleted via CopilotKit runtime (userId=${params.userId}, agentId=${params.agentId})`,\n },\n );\n this.#invokeLifecycleCallback(\"onThreadDeleted\", params);\n }\n\n /**\n * Annotate a thread event on CopilotKit Intelligence's general annotation\n * endpoint (`PUT /connector/annotate/:clientEventId`).\n *\n * This is the generalized replacement for the old\n * `PUT /connector/user-actions/record/:clientEventId` endpoint. It supports\n * multiple annotation types via the `type` discriminator. The\n * `\"user_action\"` type records a user UI interaction for the self-learning\n * loop.\n *\n * `userId` must be resolved on the runtime side before calling this — the\n * platform prefixes it with the project id from the API key.\n *\n * Always hits the idempotent `PUT /connector/annotate/:clientEventId`\n * endpoint. A retry with the same `clientEventId` returns\n * `{ id: <original>, duplicate: true }` instead of creating a new row.\n * When `clientEventId` is omitted, a UUID is auto-generated for this call.\n *\n * @throws {@link PlatformRequestError} on non-2xx responses, OR when the\n * platform returns an empty 2xx body (which would otherwise corrupt the\n * caller's typed result).\n */\n async annotate(params: AnnotateParams): Promise<AnnotateResponse> {\n const clientEventId = params.clientEventId ?? randomUUID();\n const path = `/connector/annotate/${encodeURIComponent(clientEventId)}`;\n const body: Record<string, unknown> = {\n type: params.type,\n userId: params.userId,\n threadId: params.threadId,\n };\n if (params.payload !== undefined) {\n body.payload = params.payload;\n }\n if (params.occurredAt !== undefined) {\n body.occurredAt = params.occurredAt;\n }\n const response = await this.#request<AnnotateResponse | null | undefined>(\n \"PUT\",\n path,\n body,\n );\n // `== null` catches both `undefined` (empty body from `#request`)\n // and JSON `null` (which would otherwise corrupt the typed result\n // and surface as a `TypeError` deep in caller code).\n if (response == null) {\n logger.error(\n { path },\n \"annotate: Intelligence platform returned 200 with empty or null body\",\n );\n throw new PlatformRequestError(\n \"annotate: empty or null response body from Intelligence platform\",\n 502,\n );\n }\n return response;\n }\n\n async ɵacquireThreadLock(\n params: AcquireThreadLockRequest,\n ): Promise<AcquireThreadLockResponse> {\n return this.#request<AcquireThreadLockResponse>(\n \"POST\",\n `/api/threads/${encodeURIComponent(params.threadId)}/lock`,\n {\n runId: params.runId,\n userId: params.userId,\n agentId: params.agentId,\n ...(params.learningContainerId !== undefined\n ? { learningContainerId: params.learningContainerId }\n : {}),\n ...(params.lockKeyPrefix !== undefined\n ? { lockKeyPrefix: params.lockKeyPrefix }\n : {}),\n ...(params.ttlSeconds !== undefined\n ? { ttlSeconds: params.ttlSeconds }\n : {}),\n },\n params.channelDeliveryId\n ? { \"X-Cpki-Channel-Delivery-Id\": params.channelDeliveryId }\n : undefined,\n );\n }\n\n async ɵcleanupThreadLock(params: CleanupThreadLockRequest): Promise<void> {\n return this.#request<void>(\n \"DELETE\",\n `/api/threads/${encodeURIComponent(params.threadId)}/lock`,\n {\n runId: params.runId,\n },\n );\n }\n\n async ɵrenewThreadLock(\n params: RenewThreadLockRequest,\n ): Promise<RenewThreadLockResponse> {\n return this.#request<RenewThreadLockResponse>(\n \"PATCH\",\n `/api/threads/${encodeURIComponent(params.threadId)}/lock`,\n {\n runId: params.runId,\n ttlSeconds: params.ttlSeconds,\n ...(params.lockKeyPrefix !== undefined\n ? { lockKeyPrefix: params.lockKeyPrefix }\n : {}),\n },\n );\n }\n\n async ɵgetActiveJoinCode(params: {\n threadId: string;\n userId: string;\n }): Promise<ThreadConnectionResponse> {\n const qs = new URLSearchParams({ userId: params.userId }).toString();\n return this.#request<ThreadConnectionResponse>(\n \"GET\",\n `/api/threads/${encodeURIComponent(params.threadId)}/join-code?${qs}`,\n );\n }\n\n async ɵconnectThread(params: {\n threadId: string;\n userId: string;\n agentId: string;\n }): Promise<ConnectThreadResponse> {\n const result = await this.#request<ThreadConnectionResponse>(\n \"POST\",\n `/api/threads/${encodeURIComponent(params.threadId)}/connect`,\n {\n userId: params.userId,\n agentId: params.agentId,\n },\n );\n\n // request() returns undefined for empty/204 responses\n return result ?? null;\n }\n}\n\n/**\n * Normalize a configured URL to \"provided\" or \"not provided\". A blank string\n * counts as not provided: these URLs are typically wired from environment\n * variables, and a declared-but-empty variable (`COPILOTKIT_INTELLIGENCE_URL=`,\n * common in generated `.env` files and container configs) arrives as `\"\"`. Left\n * as-is it would produce host-relative requests instead of falling back to the\n * managed platform.\n */\nfunction configuredUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n return trimmed ? trimmed : undefined;\n}\n\n/**\n * Warn when exactly one of `apiUrl`/`wsUrl` is configured. The API and realtime\n * planes are separate hosts, so a lone override silently leaves the other plane\n * on CopilotKit's managed platform — a self-hosted API paired with the managed\n * gateway (or vice versa), which fails as a hang rather than an error.\n */\nfunction warnOnPartialHostOverride(\n apiUrl: string | undefined,\n wsUrl: string | undefined,\n): void {\n if (apiUrl && !wsUrl) {\n logger.warn(\n `CopilotKitIntelligence: apiUrl is set to \"${apiUrl}\" but wsUrl is not, ` +\n `so wsUrl falls back to the managed default \"${MANAGED_INTELLIGENCE_WS_URL}\". ` +\n `The API and realtime planes are separate hosts — set both when pointing at a self-hosted deployment.`,\n );\n return;\n }\n\n if (wsUrl && !apiUrl) {\n logger.warn(\n `CopilotKitIntelligence: wsUrl is set to \"${wsUrl}\" but apiUrl is not, ` +\n `so apiUrl falls back to the managed default \"${MANAGED_INTELLIGENCE_API_URL}\". ` +\n `The API and realtime planes are separate hosts — set both when pointing at a self-hosted deployment.`,\n );\n }\n}\n\nfunction normalizeIntelligenceWsUrl(wsUrl: string): string {\n return wsUrl.replace(/\\/$/, \"\");\n}\n\nfunction deriveRunnerWsUrl(wsUrl: string): string {\n if (wsUrl.endsWith(\"/runner\")) {\n return wsUrl;\n }\n\n if (wsUrl.endsWith(\"/client\")) {\n return `${wsUrl.slice(0, -\"/client\".length)}/runner`;\n }\n\n if (wsUrl.endsWith(\"/channels\")) {\n return `${wsUrl.slice(0, -\"/channels\".length)}/runner`;\n }\n\n return `${wsUrl}/runner`;\n}\n\nfunction deriveClientWsUrl(wsUrl: string): string {\n if (wsUrl.endsWith(\"/client\")) {\n return wsUrl;\n }\n\n if (wsUrl.endsWith(\"/runner\")) {\n return `${wsUrl.slice(0, -\"/runner\".length)}/client`;\n }\n\n if (wsUrl.endsWith(\"/channels\")) {\n return `${wsUrl.slice(0, -\"/channels\".length)}/client`;\n }\n\n return `${wsUrl}/client`;\n}\n\nfunction deriveChannelsWsUrl(wsUrl: string): string {\n if (wsUrl.endsWith(\"/channels\")) return wsUrl;\n if (wsUrl.endsWith(\"/runner\")) {\n return `${wsUrl.slice(0, -\"/runner\".length)}/channels`;\n }\n if (wsUrl.endsWith(\"/client\")) {\n return `${wsUrl.slice(0, -\"/client\".length)}/channels`;\n }\n return `${wsUrl}/channels`;\n}\n"],"mappings":"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"}
@@ -477,9 +477,9 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
477
477
  * of the most recent run.
478
478
  *
479
479
  * This powers the local-dev fallback for `GET /threads/:threadId/messages`
480
- * when the Intelligence platform is not configured. The returned `Message[]`
480
+ * when CopilotKit Intelligence is not configured. The returned `Message[]`
481
481
  * objects come directly from the ag-ui agent, so their shape is compatible
482
- * with the Intelligence platform's `ThreadMessage` type.
482
+ * with CopilotKit Intelligence's `ThreadMessage` type.
483
483
  */
484
484
  getThreadMessages(threadId) {
485
485
  const store = sharedStore.peek(threadId);
@@ -490,7 +490,7 @@ var InMemoryAgentRunner = class extends require_agent_runner.AgentRunner {
490
490
  * Returns all AG-UI events for a thread, compacted across historic runs.
491
491
  *
492
492
  * Powers the local-dev fallback for `GET /threads/:threadId/events` when the
493
- * Intelligence platform is not configured. The compaction logic matches
493
+ * CopilotKit Intelligence is not configured. The compaction logic matches
494
494
  * the connection-replay path in {@link connect}, so the stream a
495
495
  * late-joining inspector sees matches what this method returns.
496
496
  */
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory.cjs","names":["AgentRunner","EventType","ReplaySubject"],"sources":["../../../../src/v2/runtime/runner/in-memory.ts"],"sourcesContent":["import type {\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n} from \"./agent-runner\";\nimport { AgentRunner } from \"./agent-runner\";\nimport type { AgentRunnerStopRequest } from \"./agent-runner\";\nimport type { Observable } from \"rxjs\";\nimport { ReplaySubject } from \"rxjs\";\nimport type {\n AbstractAgent,\n BaseEvent,\n Message,\n RunStartedEvent,\n StateSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { EventType, compactEvents } from \"@ag-ui/client\";\nimport { finalizeRunEvents } from \"@copilotkit/shared\";\n\nexport interface InMemoryLimits {\n /** LRU cap on distinct threads. */\n maxThreads?: number;\n /** FIFO cap on runs kept per thread. `Infinity` or `0` disables the cap. */\n maxRunsPerThread?: number;\n /**\n * Approximate byte ceiling on RETAINED thread/run history. Enforced at run\n * completion (in `appendRun`), where LRU non-running threads are evicted to\n * keep the total under this limit.\n *\n * Limitation: this bounds only history that has already been committed. A\n * single in-flight run's buffered events (`currentRunEvents` and the two\n * `ReplaySubject<BaseEvent>(Infinity)` buffers in `run()`) are NOT counted\n * until that run completes, so `maxBytes` does not bound a single runaway\n * run mid-stream.\n *\n * Limitation: byte eviction drops only other LRU non-running threads and\n * never self-evicts the active/just-appended thread, so a single dominant\n * thread's own retained history is not byte-trimmed (bounded only by\n * `maxRunsPerThread`). `maxBytes` is thus a cross-thread ceiling enforced by\n * evicting OTHER threads, not a per-thread cap.\n */\n maxBytes?: number;\n}\n\n/**\n * Constructor options for {@link InMemoryAgentRunner}.\n *\n * Extends {@link InMemoryLimits} so bounds can be passed inline alongside the\n * per-runner behavior flags. Be aware of the scope difference: the limits\n * reconfigure the process-global store shared by every runner, whereas\n * `onConcurrentRun` applies only to the runner instance it is passed to.\n */\nexport interface InMemoryAgentRunnerOptions extends InMemoryLimits {\n /**\n * How to handle a `run()` for a thread that already has an in-flight run.\n * `\"throw\"` (default) rejects with \"Thread already running\". `\"supersede\"`\n * aborts the prior run and starts the new one.\n */\n onConcurrentRun?: \"throw\" | \"supersede\";\n}\n\nexport const ɵINMEMORY_DEFAULTS: Required<InMemoryLimits> = {\n maxThreads: 1000,\n maxRunsPerThread: 100,\n maxBytes: 512 * 1024 ** 2,\n};\n\n/**\n * A limit value is well-formed iff it is a non-negative integer OR `+Infinity`.\n * `+Infinity` is the documented \"disabled/unbounded\" sentinel and `0` is the\n * documented run-cap disable sentinel; both are non-negative and pass. Every\n * enforcement site (`evictThreadsIfNeeded`, `enforceRunCap`,\n * `evictByBytesIfNeeded`) compares its counter against the limit with `>` in a\n * `while`/`if` guard, so only these shapes keep those loops finite and correct.\n * Rejected: negatives (drive `count > -1` true on an empty collection, so\n * `enforceRunCap` `shift()!`s `undefined` and throws), `-Infinity` (loops never\n * terminate their intent — always \"over\"), `NaN` (every `>` is false, silently\n * disabling the bound), and non-integer finites (fractional caps are nonsense).\n */\nfunction ɵisValidLimit(value: number): boolean {\n return value === Infinity || (Number.isInteger(value) && value >= 0);\n}\n\n/**\n * Normalize a fully-resolved limits bag so every field is well-formed before it\n * can reach an enforcement loop. Each field is validated independently against\n * {@link ɵisValidLimit}; an invalid value is CLAMPED to its\n * {@link ɵINMEMORY_DEFAULTS} floor and a single `console.warn` naming the field\n * and the received value is emitted.\n *\n * Clamp-and-warn (rather than throw) is deliberate and matches this file's\n * established posture toward bad input: `ɵestimateBytes` swallows serialization\n * failures and returns 0, the limits-clobber path warns rather than throwing,\n * and both the eviction and clobber logs are wrapped so \"logging must never\n * break construction/a run\". Constructing a bounded in-memory runner is a\n * best-effort, non-durable convenience; a typo'd bound must degrade to a safe\n * default, never abort construction or (worse) surface later as an unhandled\n * rejection from the fire-and-forget finalize path.\n */\nexport function ɵnormalizeLimits(\n limits: Required<InMemoryLimits>,\n): Required<InMemoryLimits> {\n const normalized = { ...limits };\n for (const field of Object.keys(\n ɵINMEMORY_DEFAULTS,\n ) as (keyof InMemoryLimits)[]) {\n const value = limits[field];\n if (!ɵisValidLimit(value)) {\n const fallback = ɵINMEMORY_DEFAULTS[field];\n normalized[field] = fallback;\n try {\n console.warn(\n `[CopilotKit] InMemoryAgentRunner: invalid ${field} value ` +\n `${String(value)} (expected a non-negative integer or Infinity); ` +\n `falling back to ${String(fallback)}.`,\n );\n } catch {\n // best-effort: logging must never break construction\n }\n }\n }\n return normalized;\n}\n\nconst EVICTION_GUIDANCE =\n \"[CopilotKit] InMemoryAgentRunner evicted in-memory thread history to stay \" +\n \"under memory limits. This runner is bounded and non-durable by design. For \" +\n \"durable or production threads, configure an Intelligence backend.\";\n\nconst LIMITS_CLOBBER_GUIDANCE =\n \"[CopilotKit] InMemoryAgentRunner was constructed with in-memory limits that \" +\n \"differ from the already-configured process-global store; the last-constructed \" +\n \"runner's limits apply to ALL in-memory threads (the store is shared per-process). \" +\n \"Configure a single consistent set of limits, or use an Intelligence backend for \" +\n \"isolated bounds.\";\n\n/**\n * Best-effort approximate byte size of a value, via serialized length.\n * Never throws — returns 0 when the value cannot be serialized. This is an\n * approximation (UTF-16 length, not exact heap bytes), used only for relative\n * accounting against `maxBytes`.\n */\nexport function ɵestimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value)?.length ?? 0;\n } catch {\n return 0;\n }\n}\n\n/**\n * Per-run finalize intent, captured once when a run starts and mutated (only)\n * by whoever aborts THAT run — `stop()` or a superseding `run()`. The run's own\n * teardown reads this captured holder instead of the shared, mutable\n * `store.stopRequested`, so a later run that resets store state can never cause\n * an intentionally-stopped run to be finalized as an error (or vice versa).\n */\ninterface RunFinalizeControl {\n /** True once THIS run has been asked to stop (clean stop, not an error). */\n stopRequested: boolean;\n}\n\ninterface HistoricRun {\n threadId: string;\n runId: string;\n /** ID of the agent that executed this run. */\n agentId: string;\n parentRunId: string | null;\n events: BaseEvent[];\n /**\n * Snapshot of all messages (input + generated) at the end of this run, as\n * passed in by the caller. NOTE: `BoundedThreadStore.appendRun` moves this\n * snapshot to the THREAD level (`InMemoryEventStore.messagesSnapshot`) and\n * clears this field to `[]`, so a stored HistoricRun never carries messages.\n * The thread-messages fallback reads the thread-level snapshot, not this.\n */\n messages: Message[];\n createdAt: number;\n /** Approximate retained byte size of `events`; set by BoundedThreadStore at append. */\n approxEventBytes?: number;\n /**\n * Legacy field retained for shape compatibility. `appendRun` always zeroes it\n * because message bytes are accounted at the thread level, not per run.\n */\n approxMessageBytes?: number;\n}\n\n/**\n * Lightweight thread summary returned by {@link InMemoryAgentRunner.listThreads}.\n * Shape matches the Intelligence platform's ThreadRecord so the same HTTP\n * response envelope can be used for both backends.\n */\nexport interface InMemoryThread {\n id: string;\n name: string | null;\n agentId: string;\n organizationId: \"\"; // always empty in in-memory mode\n createdById: \"\"; // always empty in in-memory mode\n archived: false; // always false in in-memory mode\n createdAt: string;\n updatedAt: string;\n}\n\nclass InMemoryEventStore {\n constructor(public threadId: string) {}\n\n /** The subject that current consumers subscribe to. */\n subject: ReplaySubject<BaseEvent> | null = null;\n\n /** True while a run is actively producing events. */\n isRunning = false;\n\n /** Current run ID */\n currentRunId: string | null = null;\n\n /** Historic completed runs */\n historicRuns: HistoricRun[] = [];\n\n /** Currently running agent instance (if any). */\n agent: AbstractAgent | null = null;\n\n /** Subject returned from run() while the run is active. */\n runSubject: ReplaySubject<BaseEvent> | null = null;\n\n /**\n * Thread-level lifecycle flag: true once a stop/supersede has been requested\n * for the currently-owning run but that run has not yet finalized. Drives\n * eviction protection, the connect() bridge, and stop() de-dup. This is NOT\n * the finalize intent read by a run's teardown — that lives per-run on\n * {@link activeFinalize}, so a superseding run resetting this field cannot\n * mislabel the run it replaced. A new run resets this to false when it takes\n * ownership.\n */\n stopRequested = false;\n\n /**\n * Finalize control of the currently-owning run. `stop()` and a superseding\n * `run()` flip the owning run's flag through this reference; each run also\n * captures the SAME object in its closure, so its teardown finalizes against\n * its own intent regardless of what a later run does to the store.\n */\n activeFinalize: RunFinalizeControl | null = null;\n\n /** Reference to the events emitted in the current run. */\n currentEvents: BaseEvent[] | null = null;\n\n /**\n * The thread's single latest NON-EMPTY message snapshot, held at the THREAD\n * level (independent of `historicRuns` lifecycle). Decoupling the snapshot\n * from per-run storage means run-cap FIFO eviction and interleaved\n * empty-snapshot runs can never drop or pin the thread's message history.\n */\n messagesSnapshot: Message[] = [];\n\n /** Approximate retained byte size of `messagesSnapshot`. */\n approxMessagesSnapshotBytes = 0;\n\n /**\n * The thread's true creation timestamp (epoch ms), captured from the FIRST\n * run ever appended and held at the THREAD level (independent of\n * `historicRuns` lifecycle). Decoupling it from per-run storage means run-cap\n * FIFO eviction — which shifts the oldest entries off `historicRuns` — can\n * never move the reported creation time forward. `null` until the first run\n * lands. Mirrors the `messagesSnapshot` thread-level decoupling.\n */\n createdAt: number | null = null;\n}\n\nexport class ɵBoundedThreadStore {\n private readonly map = new Map<string, InMemoryEventStore>();\n private totalBytes = 0;\n private warned = false;\n /** True once limits have been EXPLICITLY set (via setLimits), not just the constructor default. */\n private limitsExplicitlySet = false;\n /** Warn-once latch for the clobber warning, kept distinct from the eviction `warned` latch. */\n private clobberWarned = false;\n\n private limits: Required<InMemoryLimits>;\n\n constructor(limits: Required<InMemoryLimits>) {\n // Normalize once at construction so `this.limits` is ALWAYS well-formed,\n // regardless of entry point (direct construction or a later `setLimits`).\n this.limits = ɵnormalizeLimits(limits);\n }\n\n get byteTotal(): number {\n return this.totalBytes;\n }\n\n /**\n * The store's CURRENT effective bounds. Exposed (with the `ɵ` internal-API\n * prefix) so a partial `setLimits` can coalesce unspecified fields against the\n * live config rather than the hardcoded {@link ɵINMEMORY_DEFAULTS} — a partial\n * update must be a partial update, never a silent reset of the fields the\n * caller did not mention. Returns a copy so callers cannot mutate the store's\n * bounds through it.\n */\n get ɵlimits(): Required<InMemoryLimits> {\n return { ...this.limits };\n }\n\n /**\n * Reconfigure the process-global store's bounds. Called by the\n * {@link InMemoryAgentRunner} constructor when limits are passed. Because the\n * store is a per-process singleton, this replaces the bounds for ALL in-memory\n * threads. Emits {@link LIMITS_CLOBBER_GUIDANCE} at most ONCE per store when a\n * SECOND (or later) explicit set arrives whose resolved values differ from the\n * prior explicit set — i.e. a genuine clobber of an already-customized config.\n * The first explicit customization (defaults → custom) is the intended\n * override and never warns; identical re-sets never warn.\n */\n setLimits(limits: Required<InMemoryLimits>): void {\n // Normalize FIRST so invalid fields can never reach an enforcement loop and\n // so the clobber comparison below is against the EFFECTIVE (clamped) values,\n // not the raw ones — a typo'd bound that clamps to the current default is not\n // a genuine clobber and must not warn.\n const normalized = ɵnormalizeLimits(limits);\n if (\n this.limitsExplicitlySet &&\n !this.clobberWarned &&\n (normalized.maxThreads !== this.limits.maxThreads ||\n normalized.maxRunsPerThread !== this.limits.maxRunsPerThread ||\n normalized.maxBytes !== this.limits.maxBytes)\n ) {\n this.clobberWarned = true;\n try {\n console.warn(LIMITS_CLOBBER_GUIDANCE);\n } catch {\n // best-effort: logging must never break construction\n }\n }\n this.limitsExplicitlySet = true;\n this.limits = normalized;\n }\n\n get size(): number {\n return this.map.size;\n }\n\n /** Re-insert at the tail so Map iteration order stays LRU-first. */\n private touchOrder(threadId: string, store: InMemoryEventStore): void {\n this.map.delete(threadId);\n this.map.set(threadId, store);\n }\n\n getOrCreate(threadId: string): InMemoryEventStore {\n const existing = this.map.get(threadId);\n if (existing) {\n this.touchOrder(threadId, existing);\n return existing;\n }\n const store = new InMemoryEventStore(threadId);\n this.map.set(threadId, store);\n this.evictThreadsIfNeeded(threadId);\n return store;\n }\n\n get(\n threadId: string,\n opts: { touch: boolean },\n ): InMemoryEventStore | undefined {\n const store = this.map.get(threadId);\n if (store && opts.touch) this.touchOrder(threadId, store);\n return store;\n }\n\n peek(threadId: string): InMemoryEventStore | undefined {\n return this.map.get(threadId);\n }\n\n /**\n * Evict the least-recently-used thread that is neither running NOR\n * mid-finalization. Returns false if none evictable. The `protect` thread\n * (typically the one just created) is never evicted, so a fresh thread is not\n * immediately dropped when it is the only non-running candidate.\n *\n * A thread is skipped while `isRunning` OR `stopRequested` is set.\n * `stop()` flips `isRunning` to false the moment it aborts the agent, but the\n * run keeps finalizing asynchronously (the abort trips the `catch` in\n * `runAgent`, which later calls `appendRun`). During that window\n * `stopRequested` stays true; evicting the thread then would make the pending\n * `appendRun` hit `if (!store) return` and silently drop the aborted run's\n * history. Guarding on `stopRequested` keeps the thread alive until\n * finalization completes.\n */\n private evictOneLru(protect?: string): boolean {\n for (const [threadId, store] of this.map) {\n if (threadId === protect) continue; // never evict the just-created thread\n // never evict a running or still-finalizing (stop-requested) thread\n if (store.isRunning || store.stopRequested) continue;\n this.removeThread(threadId, store);\n this.noteEviction();\n return true;\n }\n return false;\n }\n\n appendRun(threadId: string, run: HistoricRun): void {\n const store = this.map.get(threadId);\n if (!store) return; // best-effort: nothing to append to\n\n // Thread-level creation timestamp: capture the FIRST run's createdAt once\n // and never overwrite it. Held on the store (not derived from\n // `historicRuns[0]`) so run-cap FIFO eviction of the oldest runs cannot\n // drift the thread's reported creation time forward. Mirrors the\n // thread-level `messagesSnapshot` decoupling below.\n if (store.createdAt === null) {\n store.createdAt = run.createdAt;\n }\n\n // Thread-level message snapshot: keep the single latest NON-EMPTY snapshot\n // on the store, decoupled from `historicRuns`. When the incoming run\n // carries a non-empty snapshot, replace the thread's snapshot (adjusting\n // byte accounting). When it's empty (non-array `agent.messages` or an\n // error-path run), leave the existing thread snapshot untouched so history\n // is never lost. The snapshot never lives on a HistoricRun, so run-cap FIFO\n // eviction can never drop it and an interleaved empty run can never pin it.\n if (run.messages.length > 0) {\n this.totalBytes -= store.approxMessagesSnapshotBytes;\n // Store the incoming array directly (SHALLOW, array-level copy). `run.messages`\n // is already a fresh `[...agent.messages]` array created in run(), so we own the\n // array and it is decoupled from `agent.messages` at the array level (push/splice\n // on the agent's array cannot mutate our snapshot). We deliberately do NOT deep-copy\n // here: `structuredClone` throws DataCloneError on a non-cloneable message field,\n // which would wedge the thread and hang SSE — inconsistent with `ɵestimateBytes`,\n // which tolerates the same bad-payload class. The tradeoff is that the inner\n // `Message` objects remain shared by reference with `agent.messages`, so an agent\n // that mutates its own message objects IN PLACE after the run can still be observed\n // through this snapshot. That inner-object isolation is a known limitation tracked as\n // follow-up; callers must treat returned messages as read-only. Estimate bytes on the\n // same value so accounting matches exactly what is retained.\n store.messagesSnapshot = run.messages;\n store.approxMessagesSnapshotBytes = ɵestimateBytes(run.messages);\n this.totalBytes += store.approxMessagesSnapshotBytes;\n }\n\n // Do not carry message bytes on the HistoricRun: the snapshot is now tracked\n // at the thread level, so historicRuns must never account message bytes.\n run.messages = [];\n run.approxMessageBytes = 0;\n\n // Compute this run's approximate event size once, at append time.\n run.approxEventBytes = ɵestimateBytes(run.events);\n store.historicRuns.push(run);\n this.totalBytes += run.approxEventBytes;\n this.touchOrder(threadId, store);\n\n this.enforceRunCap(store);\n this.evictByBytesIfNeeded(threadId);\n }\n\n private enforceRunCap(store: InMemoryEventStore): void {\n const cap = this.limits.maxRunsPerThread;\n if (!cap || cap === Infinity) return; // 0 or Infinity → disabled\n while (store.historicRuns.length > cap) {\n const dropped = store.historicRuns.shift()!;\n // Only event bytes live on a HistoricRun; the message snapshot is tracked\n // at the thread level and survives run-cap eviction.\n this.totalBytes -= dropped.approxEventBytes ?? 0;\n // Per-thread run-cap trimming is also eviction — history is being dropped.\n // Route it through the SAME warn-once latch as whole-thread LRU eviction so\n // this shows up in logs rather than as silent data loss. `noteEviction` is\n // latched (one warning per store, reset by `clear()`), so a hot thread that\n // trims on every subsequent append warns once, never per dropped run. The\n // loop only runs when a run is ACTUALLY over the cap, so a disabled or\n // under-cap `enforceRunCap` stays silent (it returned / never entered here).\n this.noteEviction();\n }\n }\n\n /**\n * Trim the store back under the byte ceiling by evicting LRU non-running\n * threads. `protect` (the just-appended thread) is never self-evicted, so a\n * fresh run pushes OTHER threads out rather than dropping itself.\n */\n private evictByBytesIfNeeded(protect?: string): void {\n while (this.totalBytes > this.limits.maxBytes) {\n if (!this.evictOneLru(protect)) break; // only protected/running threads left → accept overage\n }\n }\n\n private removeThread(threadId: string, store: InMemoryEventStore): void {\n for (const run of store.historicRuns) {\n this.totalBytes -= run.approxEventBytes ?? 0;\n }\n // The thread's message snapshot is tracked at the store level, so it must\n // be reclaimed here in addition to the per-run event bytes.\n this.totalBytes -= store.approxMessagesSnapshotBytes;\n this.map.delete(threadId);\n }\n\n private evictThreadsIfNeeded(protect?: string): void {\n while (this.map.size > this.limits.maxThreads) {\n if (!this.evictOneLru(protect)) break; // everything evictable is running → accept overage\n }\n }\n\n private noteEviction(): void {\n if (this.warned) return;\n this.warned = true;\n try {\n console.warn(EVICTION_GUIDANCE);\n } catch {\n // best-effort: logging must never break a run\n }\n }\n\n listThreads(): InMemoryThread[] {\n const threads: InMemoryThread[] = [];\n for (const [threadId, store] of this.map) {\n if (store.historicRuns.length === 0) continue;\n const lastRun = store.historicRuns[store.historicRuns.length - 1]!;\n // Creation time comes from the thread-level `store.createdAt` (the first\n // run ever appended), NOT `historicRuns[0]` (the oldest RETAINED run):\n // run-cap FIFO eviction drops the oldest retained runs, so deriving it\n // from `historicRuns[0]` would silently drift the timestamp forward over\n // a thread's lifetime. `updatedAt` stays on `lastRun` because FIFO\n // eviction removes from the FRONT, so the newest run is never evicted.\n // The `?? lastRun.createdAt` fallback is defensive only: any thread with\n // runs has had `store.createdAt` set by `appendRun`.\n threads.push({\n id: threadId,\n name: null,\n agentId: lastRun.agentId,\n organizationId: \"\",\n createdById: \"\",\n archived: false,\n createdAt: new Date(store.createdAt ?? lastRun.createdAt).toISOString(),\n updatedAt: new Date(lastRun.createdAt).toISOString(),\n });\n }\n return threads.sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n clear(): void {\n this.map.clear();\n this.totalBytes = 0;\n this.warned = false;\n }\n}\n\n/**\n * Process-wide singleton backing every {@link InMemoryAgentRunner}. Exported\n * (with the `ɵ` internal-API prefix) so tests can inspect the exact store the\n * runner writes to; not part of the public API.\n */\nexport const ɵGLOBAL_STORE = new ɵBoundedThreadStore(ɵINMEMORY_DEFAULTS);\nconst sharedStore = ɵGLOBAL_STORE;\n\nexport class InMemoryAgentRunner extends AgentRunner {\n readonly ɵsupportsLocalThreadEndpoints = true;\n\n /**\n * How to handle a `run()` for a thread that already has an in-flight run.\n * `\"throw\"` (default) preserves the historic behavior. `\"supersede\"` aborts\n * the prior run (mirroring `stop()`) and starts the new one — opted into by\n * the hosted-bot listener so a fast follow-up turn on the same thread cleanly\n * replaces a still-running (or wedged) prior turn instead of erroring with\n * \"Thread already running\".\n */\n private readonly onConcurrentRun: \"throw\" | \"supersede\";\n\n /**\n * @param options Per-runner behavior (`onConcurrentRun`) plus optional bounds\n * for the in-memory store ({@link InMemoryLimits}).\n *\n * Note the differing scopes: `onConcurrentRun` is per-runner instance, while\n * the limits reconfigure the PROCESS-GLOBAL store shared by every\n * `InMemoryAgentRunner`. Omit the limits for safe defaults\n * ({@link ɵINMEMORY_DEFAULTS}); passing none leaves the store untouched. When\n * multiple runners are constructed with differing limits, the last-constructed\n * wins — in practice the OSS/SSE default construction passes nothing. If a\n * second (or later) runner is constructed with limits that DIFFER from an\n * already-customized store, a one-time `console.warn` is emitted to signal that\n * the shared store's bounds are being clobbered for ALL in-memory threads.\n */\n constructor(options?: InMemoryAgentRunnerOptions) {\n super();\n const { onConcurrentRun, ...limits } = options ?? {};\n this.onConcurrentRun = onConcurrentRun ?? \"throw\";\n\n // Only reconfigure the shared store when a bound was actually supplied.\n // `new InMemoryAgentRunner({ onConcurrentRun: \"supersede\" })` must stay\n // inert with respect to limits.\n if (\n limits.maxThreads !== undefined ||\n limits.maxRunsPerThread !== undefined ||\n limits.maxBytes !== undefined\n ) {\n // Coalesce each unspecified field against the store's CURRENT effective\n // limits, NOT ɵINMEMORY_DEFAULTS. The store is process-global, so tuning\n // one bound must leave every previously-customized sibling bound intact —\n // a partial update stays a partial update instead of silently resetting the\n // fields the caller never mentioned. Passing all three (e.g.\n // ɵINMEMORY_DEFAULTS) still fully replaces the config, so the defaults-\n // restore path is unaffected.\n const current = sharedStore.ɵlimits;\n sharedStore.setLimits({\n maxThreads: limits.maxThreads ?? current.maxThreads,\n maxRunsPerThread: limits.maxRunsPerThread ?? current.maxRunsPerThread,\n maxBytes: limits.maxBytes ?? current.maxBytes,\n });\n }\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n const store = sharedStore.getOrCreate(request.threadId);\n\n // Enter the concurrency branch whenever a prior run still owns the thread —\n // either actively running OR still finalizing after a stop()/supersede.\n // `stop()` flips `isRunning` to false the instant it aborts the agent, but\n // the run keeps finalizing asynchronously (`stopRequested` stays true).\n // Gating on `isRunning` alone let a `run()` slip through that window\n // unhandled: no supersede/throw, no per-run intent capture, and a leaked\n // bridge from the dying run's subject.\n if (store.isRunning || store.stopRequested) {\n if (this.onConcurrentRun !== \"supersede\") {\n throw new Error(\"Thread already running\");\n }\n // Supersede: abort the prior (possibly wedged) run so this one can start.\n // Mirrors stop(). Record the prior run's OWN finalize intent on its\n // captured control BEFORE resetting the shared store flags for the new\n // run: a supersede is a clean stop of the prior run, so its async teardown\n // must finalize as RUN_FINISHED, never a synthetic RUN_ERROR. The prior\n // run's async finalization is prevented from clobbering this run's state\n // by the run-id guard below.\n const priorAgent = store.agent;\n const priorFinalize = store.activeFinalize;\n if (priorFinalize) {\n priorFinalize.stopRequested = true;\n }\n store.isRunning = false;\n if (priorAgent) {\n try {\n priorAgent.abortRun();\n } catch (error) {\n console.error(\"Failed to abort superseded run\", error);\n }\n }\n }\n store.isRunning = true;\n store.currentRunId = request.input.runId;\n store.agent = request.agent;\n store.stopRequested = false;\n\n // Per-run finalize control. This run's teardown reads THIS captured holder\n // (never the shared `store.stopRequested`, which a later run resets), so an\n // aborted run is always finalized against its own stop-intent.\n const finalizeControl: RunFinalizeControl = { stopRequested: false };\n store.activeFinalize = finalizeControl;\n\n // Track seen message IDs and current run events for this run\n const seenMessageIds = new Set<string>();\n const currentRunEvents: BaseEvent[] = [];\n store.currentEvents = currentRunEvents;\n\n // Get all previously seen message IDs from historic runs\n const historicMessageIds = new Set<string>();\n for (const run of store.historicRuns) {\n for (const event of run.events) {\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n historicMessageIds.add(event.messageId);\n }\n if (event.type === EventType.RUN_STARTED) {\n const runStarted = event as RunStartedEvent;\n const messages = runStarted.input?.messages ?? [];\n for (const message of messages) {\n historicMessageIds.add(message.id);\n }\n }\n }\n }\n\n const nextSubject = new ReplaySubject<BaseEvent>(Infinity);\n\n // Update the store's subject immediately. We intentionally do NOT capture\n // and bridge the previous subject: see the note before `runAgent()` below.\n store.subject = nextSubject;\n\n // Create a subject for run() return value\n const runSubject = new ReplaySubject<BaseEvent>(Infinity);\n store.runSubject = runSubject;\n\n // Helper function to run the agent and handle errors\n const runAgent = async () => {\n // Get parent run ID for chaining\n const lastRun = store.historicRuns[store.historicRuns.length - 1];\n const parentRunId = lastRun?.runId ?? null;\n\n // Shared teardown for both the success and error paths. Keeping this one\n // helper means the two paths cannot drift apart (they were near-identical\n // and must stay symmetric). `interruptionMessage` is set only on the error\n // path; its presence is what distinguishes the two.\n const finalizeRun = (opts: { interruptionMessage?: string }) => {\n const isError = opts.interruptionMessage !== undefined;\n\n // Capture the count of REAL (agent-emitted) events BEFORE finalizing.\n // `finalizeRunEvents` mutates `currentRunEvents` IN PLACE — it always\n // pushes a synthetic terminal (and any closers) when the stream ended\n // without one — so after the call `currentRunEvents.length` is never 0.\n // The persistence guard below must gate on this pre-finalize count, or\n // the \"skip an immediate throw that emitted nothing\" check is dead.\n const preFinalizeEventCount = currentRunEvents.length;\n\n // Finalize against THIS run's own captured stop-intent — never the\n // shared `store.stopRequested`, which a superseding run resets. An\n // aborted run is thus finalized as a clean RUN_FINISHED, not a synthetic\n // RUN_ERROR.\n const appendedEvents = finalizeRunEvents(currentRunEvents, {\n stopRequested: finalizeControl.stopRequested,\n ...(isError ? { interruptionMessage: opts.interruptionMessage } : {}),\n });\n for (const event of appendedEvents) {\n runSubject.next(event);\n nextSubject.next(event);\n }\n\n // Does this run still own the thread? A superseding run has changed\n // `currentRunId`, so the run it replaced no longer owns the store.\n const ownsThread = store.currentRunId === request.input.runId;\n\n // Store this run's events. Guard on the per-run id (not the shared\n // `store.currentRunId`): a superseded run no longer owns the store, so\n // it must not push history — and never under a newer run's id, which\n // would corrupt the thread's history. On the error path also require at\n // least one real (pre-finalize) event, so an immediate throw with\n // nothing emitted does not create a phantom historic run holding only\n // the synthetic terminal.\n if (ownsThread && (!isError || preFinalizeEventCount > 0)) {\n // Compact the events before storing (like SQLite does)\n const compactedEvents = compactEvents(currentRunEvents);\n sharedStore.appendRun(request.threadId, {\n threadId: request.threadId,\n runId: request.input.runId,\n agentId: request.agent.agentId ?? \"default\",\n parentRunId,\n events: compactedEvents,\n // Snapshot all messages (input + generated) for the thread-messages endpoint\n messages: Array.isArray(request.agent.messages)\n ? [...request.agent.messages]\n : [],\n createdAt: Date.now(),\n });\n }\n\n // Complete the run. Guard the shared-store reset: if a newer run has\n // superseded this one (`currentRunId` changed), that run now owns the\n // store — don't clobber its state. Always complete THIS run's subjects.\n if (ownsThread) {\n store.currentEvents = null;\n store.currentRunId = null;\n store.agent = null;\n store.runSubject = null;\n store.stopRequested = false;\n store.isRunning = false;\n store.activeFinalize = null;\n }\n runSubject.complete();\n nextSubject.complete();\n // Time-scoped release: this run's events are now in historicRuns, so its\n // infinite ReplaySubject buffer is pure duplication — drop the store's\n // reference so it becomes collectable. The identity guard is what makes\n // this correct, and it does so differently on each path:\n //\n // - Owning path: no newer run superseded this one, so store.subject is\n // still nextSubject and the guard passes. The `if (ownsThread)` block\n // above just cleared isRunning and stopRequested, so connect() — which\n // bridges store.subject only while isRunning || stopRequested — will\n // not re-subscribe; it rebuilds this run's events from historicRuns\n // instead. Nulling the reference is therefore safe.\n //\n // - Superseded path (`onConcurrentRun: \"supersede\"`): a newer run has\n // already installed ITS subject and run id on the store, so the guard\n // fails and we leave store.subject untouched. Here isRunning/\n // stopRequested describe that live run (isRunning is typically true),\n // so it is precisely the identity guard — not those flags — that\n // prevents us from nulling the live run's subject and cutting\n // connect() off from the in-flight stream. This run's own buffer is no\n // longer referenced by the store and becomes collectable regardless.\n if (store.subject === nextSubject) {\n store.subject = null;\n }\n };\n\n try {\n await request.agent.runAgent(request.input, {\n onEvent: ({ event }) => {\n let processedEvent: BaseEvent = event;\n if (event.type === EventType.RUN_STARTED) {\n const runStartedEvent = event as RunStartedEvent;\n if (!runStartedEvent.input) {\n const sanitizedMessages = request.input.messages\n ? request.input.messages.filter(\n (message) => !historicMessageIds.has(message.id),\n )\n : undefined;\n const updatedInput = {\n ...request.input,\n ...(sanitizedMessages !== undefined\n ? { messages: sanitizedMessages }\n : {}),\n };\n runStartedEvent.input = updatedInput;\n processedEvent = runStartedEvent;\n }\n }\n\n runSubject.next(processedEvent); // For run() return - only agent events\n nextSubject.next(processedEvent); // For connect() / store - all events\n currentRunEvents.push(processedEvent); // Accumulate for storage\n },\n onNewMessage: ({ message }) => {\n // Called for each new message\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n },\n onRunStartedEvent: () => {\n // Mark any messages from the input as seen so they aren't emitted twice\n if (request.input.messages) {\n for (const message of request.input.messages) {\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n }\n }\n },\n });\n\n finalizeRun({});\n } catch (error) {\n const interruptionMessage =\n error instanceof Error ? error.message : String(error);\n finalizeRun({ interruptionMessage });\n }\n };\n\n // NOTE: we deliberately do NOT bridge the previous store subject into\n // `nextSubject`. `store.subject` is nulled the moment a run fully tears down\n // (identity guard in `finalizeRun`), so the previous subject is non-null\n // ONLY when this run is superseding a prior run that is still in flight or\n // finalizing. Forwarding that dying run's subject would replay its buffered\n // RUN_STARTED and push its terminal event (RUN_FINISHED/RUN_ERROR) into THIS\n // live run's stream — an invalid AG-UI sequence on a healthy run. A\n // superseded run's stream must stay isolated: it reaches only its own\n // connect() subscribers via its own (now-detached) subject, never the\n // superseding run's.\n\n // Start the agent execution immediately (not lazily)\n runAgent();\n\n // Return the run subject (only agent events, no injected messages)\n return runSubject.asObservable();\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const store = sharedStore.get(request.threadId, { touch: true });\n const connectionSubject = new ReplaySubject<BaseEvent>(Infinity);\n\n if (!store) {\n // No store means no events\n connectionSubject.complete();\n return connectionSubject.asObservable();\n }\n\n // Collect all historic events from memory\n const allHistoricEvents: BaseEvent[] = [];\n for (const run of store.historicRuns) {\n allHistoricEvents.push(...run.events);\n }\n\n // Apply compaction to all historic events together (like SQLite)\n const compactedEvents = compactEvents(allHistoricEvents);\n\n // Emit compacted events and track message IDs\n const emittedMessageIds = new Set<string>();\n for (const event of compactedEvents) {\n connectionSubject.next(event);\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n emittedMessageIds.add(event.messageId);\n }\n }\n\n // Bridge active run to connection if exists\n if (store.subject && (store.isRunning || store.stopRequested)) {\n store.subject.subscribe({\n next: (event) => {\n // Skip message events that we've already emitted from historic\n if (\n \"messageId\" in event &&\n typeof event.messageId === \"string\" &&\n emittedMessageIds.has(event.messageId)\n ) {\n return;\n }\n connectionSubject.next(event);\n },\n complete: () => connectionSubject.complete(),\n error: (err) => connectionSubject.error(err),\n });\n } else {\n // No active run, complete after historic events\n connectionSubject.complete();\n }\n\n return connectionSubject.asObservable();\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const store = sharedStore.peek(request.threadId);\n return Promise.resolve(store?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const store = sharedStore.peek(request.threadId);\n if (!store || !store.isRunning) {\n return Promise.resolve(false);\n }\n if (request.runId !== undefined && store.currentRunId !== request.runId) {\n return Promise.resolve(false);\n }\n if (store.stopRequested) {\n return Promise.resolve(false);\n }\n\n store.stopRequested = true;\n store.isRunning = false;\n // Record the stop on the running run's OWN finalize control so its async\n // teardown finalizes as a clean RUN_FINISHED. This is the same object that\n // run's closure reads, so a later run cannot mislabel this stop.\n const finalizeControl = store.activeFinalize;\n if (finalizeControl) {\n finalizeControl.stopRequested = true;\n }\n\n const agent = store.agent;\n if (!agent) {\n store.stopRequested = false;\n store.isRunning = false;\n if (finalizeControl) {\n finalizeControl.stopRequested = false;\n }\n return Promise.resolve(false);\n }\n\n try {\n agent.abortRun();\n return Promise.resolve(true);\n } catch (error) {\n console.error(\"Failed to abort agent run\", error);\n store.stopRequested = false;\n store.isRunning = true;\n if (finalizeControl) {\n finalizeControl.stopRequested = false;\n }\n return Promise.resolve(false);\n }\n }\n\n /**\n * Returns a summary of every thread that has been run through this runner.\n *\n * This powers the local-dev fallback for `GET /threads` when the Intelligence\n * platform is not configured. Each entry mirrors the shape of a platform\n * `ThreadRecord` so the HTTP handler can use the same response envelope.\n */\n listThreads(): InMemoryThread[] {\n return sharedStore.listThreads();\n }\n\n /**\n * Returns all messages for a thread, using the snapshot captured at the end\n * of the most recent run.\n *\n * This powers the local-dev fallback for `GET /threads/:threadId/messages`\n * when the Intelligence platform is not configured. The returned `Message[]`\n * objects come directly from the ag-ui agent, so their shape is compatible\n * with the Intelligence platform's `ThreadMessage` type.\n */\n getThreadMessages(threadId: string): Message[] {\n const store = sharedStore.peek(threadId);\n if (!store) return [];\n // The thread's latest non-empty snapshot is held at the store level,\n // independent of `historicRuns` lifecycle, so run-cap eviction and\n // interleaved empty-snapshot runs can never lose it. Return a SHALLOW\n // (array-level) copy: a fresh array so a caller mutating array STRUCTURE\n // (push/splice/reassign elements) cannot affect the stored snapshot. We\n // deliberately do NOT deep-copy: `structuredClone` throws DataCloneError on a\n // non-cloneable message field, which would wedge the thread and hang SSE —\n // inconsistent with `ɵestimateBytes`, which tolerates the same bad-payload class.\n // The tradeoff is that the inner `Message` objects remain shared by reference with\n // the stored snapshot, so mutating a returned message's FIELD\n // (e.g. `getThreadMessages(t)[0].content = \"x\"`) is NOT isolated and would corrupt\n // the stored snapshot. That inner-object isolation is a known limitation tracked as\n // follow-up; callers must treat returned messages as read-only.\n return [...store.messagesSnapshot];\n }\n\n /**\n * Returns all AG-UI events for a thread, compacted across historic runs.\n *\n * Powers the local-dev fallback for `GET /threads/:threadId/events` when the\n * Intelligence platform is not configured. The compaction logic matches\n * the connection-replay path in {@link connect}, so the stream a\n * late-joining inspector sees matches what this method returns.\n */\n getThreadEvents(threadId: string): BaseEvent[] {\n const store = sharedStore.peek(threadId);\n if (!store || store.historicRuns.length === 0) return [];\n const all: BaseEvent[] = [];\n for (const run of store.historicRuns) all.push(...run.events);\n return compactEvents(all);\n }\n\n /**\n * Returns the agent state snapshot for a thread.\n *\n * Derived from the last `STATE_SNAPSHOT` in the compacted event stream. The\n * AG-UI `compactEvents` helper consolidates STATE_DELTA events and produces\n * a single trailing STATE_SNAPSHOT when state changes exist, so this is a\n * faithful view of state at the end of the most recent run.\n *\n * Returns `null` when the thread has never emitted a STATE_SNAPSHOT.\n */\n getThreadState(threadId: string): Record<string, unknown> | null {\n const events = this.getThreadEvents(threadId);\n // Walk backwards — the last snapshot wins.\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]!;\n if (event.type === EventType.STATE_SNAPSHOT) {\n const snapshot = (event as StateSnapshotEvent).snapshot;\n // Only plain objects satisfy the Record<string, unknown> contract.\n // `typeof [] === \"object\"` is true, so arrays must be rejected\n // explicitly to avoid returning an array typed as a Record.\n if (\n snapshot &&\n typeof snapshot === \"object\" &&\n !Array.isArray(snapshot)\n ) {\n // Return a defensive shallow copy so callers can't mutate the\n // snapshot object held inside the stored event (matches the\n // getThreadMessages defensive-copy approach).\n return { ...(snapshot as Record<string, unknown>) };\n }\n return null;\n }\n }\n return null;\n }\n\n /**\n * Clears all in-memory thread history.\n *\n * Powers the local-dev fallback for `POST /threads/clear`, letting consumers\n * (e.g. the demo's Clear button) reset to an empty thread list without\n * restarting the runtime. Intentionally not exposed on the Intelligence\n * platform path: there, thread history lives in a real database and must\n * not be wiped this way.\n */\n clearThreads(): void {\n sharedStore.clear();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"in-memory.cjs","names":["AgentRunner","EventType","ReplaySubject"],"sources":["../../../../src/v2/runtime/runner/in-memory.ts"],"sourcesContent":["import type {\n AgentRunnerConnectRequest,\n AgentRunnerIsRunningRequest,\n AgentRunnerRunRequest,\n} from \"./agent-runner\";\nimport { AgentRunner } from \"./agent-runner\";\nimport type { AgentRunnerStopRequest } from \"./agent-runner\";\nimport type { Observable } from \"rxjs\";\nimport { ReplaySubject } from \"rxjs\";\nimport type {\n AbstractAgent,\n BaseEvent,\n Message,\n RunStartedEvent,\n StateSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { EventType, compactEvents } from \"@ag-ui/client\";\nimport { finalizeRunEvents } from \"@copilotkit/shared\";\n\nexport interface InMemoryLimits {\n /** LRU cap on distinct threads. */\n maxThreads?: number;\n /** FIFO cap on runs kept per thread. `Infinity` or `0` disables the cap. */\n maxRunsPerThread?: number;\n /**\n * Approximate byte ceiling on RETAINED thread/run history. Enforced at run\n * completion (in `appendRun`), where LRU non-running threads are evicted to\n * keep the total under this limit.\n *\n * Limitation: this bounds only history that has already been committed. A\n * single in-flight run's buffered events (`currentRunEvents` and the two\n * `ReplaySubject<BaseEvent>(Infinity)` buffers in `run()`) are NOT counted\n * until that run completes, so `maxBytes` does not bound a single runaway\n * run mid-stream.\n *\n * Limitation: byte eviction drops only other LRU non-running threads and\n * never self-evicts the active/just-appended thread, so a single dominant\n * thread's own retained history is not byte-trimmed (bounded only by\n * `maxRunsPerThread`). `maxBytes` is thus a cross-thread ceiling enforced by\n * evicting OTHER threads, not a per-thread cap.\n */\n maxBytes?: number;\n}\n\n/**\n * Constructor options for {@link InMemoryAgentRunner}.\n *\n * Extends {@link InMemoryLimits} so bounds can be passed inline alongside the\n * per-runner behavior flags. Be aware of the scope difference: the limits\n * reconfigure the process-global store shared by every runner, whereas\n * `onConcurrentRun` applies only to the runner instance it is passed to.\n */\nexport interface InMemoryAgentRunnerOptions extends InMemoryLimits {\n /**\n * How to handle a `run()` for a thread that already has an in-flight run.\n * `\"throw\"` (default) rejects with \"Thread already running\". `\"supersede\"`\n * aborts the prior run and starts the new one.\n */\n onConcurrentRun?: \"throw\" | \"supersede\";\n}\n\nexport const ɵINMEMORY_DEFAULTS: Required<InMemoryLimits> = {\n maxThreads: 1000,\n maxRunsPerThread: 100,\n maxBytes: 512 * 1024 ** 2,\n};\n\n/**\n * A limit value is well-formed iff it is a non-negative integer OR `+Infinity`.\n * `+Infinity` is the documented \"disabled/unbounded\" sentinel and `0` is the\n * documented run-cap disable sentinel; both are non-negative and pass. Every\n * enforcement site (`evictThreadsIfNeeded`, `enforceRunCap`,\n * `evictByBytesIfNeeded`) compares its counter against the limit with `>` in a\n * `while`/`if` guard, so only these shapes keep those loops finite and correct.\n * Rejected: negatives (drive `count > -1` true on an empty collection, so\n * `enforceRunCap` `shift()!`s `undefined` and throws), `-Infinity` (loops never\n * terminate their intent — always \"over\"), `NaN` (every `>` is false, silently\n * disabling the bound), and non-integer finites (fractional caps are nonsense).\n */\nfunction ɵisValidLimit(value: number): boolean {\n return value === Infinity || (Number.isInteger(value) && value >= 0);\n}\n\n/**\n * Normalize a fully-resolved limits bag so every field is well-formed before it\n * can reach an enforcement loop. Each field is validated independently against\n * {@link ɵisValidLimit}; an invalid value is CLAMPED to its\n * {@link ɵINMEMORY_DEFAULTS} floor and a single `console.warn` naming the field\n * and the received value is emitted.\n *\n * Clamp-and-warn (rather than throw) is deliberate and matches this file's\n * established posture toward bad input: `ɵestimateBytes` swallows serialization\n * failures and returns 0, the limits-clobber path warns rather than throwing,\n * and both the eviction and clobber logs are wrapped so \"logging must never\n * break construction/a run\". Constructing a bounded in-memory runner is a\n * best-effort, non-durable convenience; a typo'd bound must degrade to a safe\n * default, never abort construction or (worse) surface later as an unhandled\n * rejection from the fire-and-forget finalize path.\n */\nexport function ɵnormalizeLimits(\n limits: Required<InMemoryLimits>,\n): Required<InMemoryLimits> {\n const normalized = { ...limits };\n for (const field of Object.keys(\n ɵINMEMORY_DEFAULTS,\n ) as (keyof InMemoryLimits)[]) {\n const value = limits[field];\n if (!ɵisValidLimit(value)) {\n const fallback = ɵINMEMORY_DEFAULTS[field];\n normalized[field] = fallback;\n try {\n console.warn(\n `[CopilotKit] InMemoryAgentRunner: invalid ${field} value ` +\n `${String(value)} (expected a non-negative integer or Infinity); ` +\n `falling back to ${String(fallback)}.`,\n );\n } catch {\n // best-effort: logging must never break construction\n }\n }\n }\n return normalized;\n}\n\nconst EVICTION_GUIDANCE =\n \"[CopilotKit] InMemoryAgentRunner evicted in-memory thread history to stay \" +\n \"under memory limits. This runner is bounded and non-durable by design. For \" +\n \"durable or production threads, configure an Intelligence backend.\";\n\nconst LIMITS_CLOBBER_GUIDANCE =\n \"[CopilotKit] InMemoryAgentRunner was constructed with in-memory limits that \" +\n \"differ from the already-configured process-global store; the last-constructed \" +\n \"runner's limits apply to ALL in-memory threads (the store is shared per-process). \" +\n \"Configure a single consistent set of limits, or use an Intelligence backend for \" +\n \"isolated bounds.\";\n\n/**\n * Best-effort approximate byte size of a value, via serialized length.\n * Never throws — returns 0 when the value cannot be serialized. This is an\n * approximation (UTF-16 length, not exact heap bytes), used only for relative\n * accounting against `maxBytes`.\n */\nexport function ɵestimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value)?.length ?? 0;\n } catch {\n return 0;\n }\n}\n\n/**\n * Per-run finalize intent, captured once when a run starts and mutated (only)\n * by whoever aborts THAT run — `stop()` or a superseding `run()`. The run's own\n * teardown reads this captured holder instead of the shared, mutable\n * `store.stopRequested`, so a later run that resets store state can never cause\n * an intentionally-stopped run to be finalized as an error (or vice versa).\n */\ninterface RunFinalizeControl {\n /** True once THIS run has been asked to stop (clean stop, not an error). */\n stopRequested: boolean;\n}\n\ninterface HistoricRun {\n threadId: string;\n runId: string;\n /** ID of the agent that executed this run. */\n agentId: string;\n parentRunId: string | null;\n events: BaseEvent[];\n /**\n * Snapshot of all messages (input + generated) at the end of this run, as\n * passed in by the caller. NOTE: `BoundedThreadStore.appendRun` moves this\n * snapshot to the THREAD level (`InMemoryEventStore.messagesSnapshot`) and\n * clears this field to `[]`, so a stored HistoricRun never carries messages.\n * The thread-messages fallback reads the thread-level snapshot, not this.\n */\n messages: Message[];\n createdAt: number;\n /** Approximate retained byte size of `events`; set by BoundedThreadStore at append. */\n approxEventBytes?: number;\n /**\n * Legacy field retained for shape compatibility. `appendRun` always zeroes it\n * because message bytes are accounted at the thread level, not per run.\n */\n approxMessageBytes?: number;\n}\n\n/**\n * Lightweight thread summary returned by {@link InMemoryAgentRunner.listThreads}.\n * Shape matches CopilotKit Intelligence's ThreadRecord so the same HTTP\n * response envelope can be used for both backends.\n */\nexport interface InMemoryThread {\n id: string;\n name: string | null;\n agentId: string;\n organizationId: \"\"; // always empty in in-memory mode\n createdById: \"\"; // always empty in in-memory mode\n archived: false; // always false in in-memory mode\n createdAt: string;\n updatedAt: string;\n}\n\nclass InMemoryEventStore {\n constructor(public threadId: string) {}\n\n /** The subject that current consumers subscribe to. */\n subject: ReplaySubject<BaseEvent> | null = null;\n\n /** True while a run is actively producing events. */\n isRunning = false;\n\n /** Current run ID */\n currentRunId: string | null = null;\n\n /** Historic completed runs */\n historicRuns: HistoricRun[] = [];\n\n /** Currently running agent instance (if any). */\n agent: AbstractAgent | null = null;\n\n /** Subject returned from run() while the run is active. */\n runSubject: ReplaySubject<BaseEvent> | null = null;\n\n /**\n * Thread-level lifecycle flag: true once a stop/supersede has been requested\n * for the currently-owning run but that run has not yet finalized. Drives\n * eviction protection, the connect() bridge, and stop() de-dup. This is NOT\n * the finalize intent read by a run's teardown — that lives per-run on\n * {@link activeFinalize}, so a superseding run resetting this field cannot\n * mislabel the run it replaced. A new run resets this to false when it takes\n * ownership.\n */\n stopRequested = false;\n\n /**\n * Finalize control of the currently-owning run. `stop()` and a superseding\n * `run()` flip the owning run's flag through this reference; each run also\n * captures the SAME object in its closure, so its teardown finalizes against\n * its own intent regardless of what a later run does to the store.\n */\n activeFinalize: RunFinalizeControl | null = null;\n\n /** Reference to the events emitted in the current run. */\n currentEvents: BaseEvent[] | null = null;\n\n /**\n * The thread's single latest NON-EMPTY message snapshot, held at the THREAD\n * level (independent of `historicRuns` lifecycle). Decoupling the snapshot\n * from per-run storage means run-cap FIFO eviction and interleaved\n * empty-snapshot runs can never drop or pin the thread's message history.\n */\n messagesSnapshot: Message[] = [];\n\n /** Approximate retained byte size of `messagesSnapshot`. */\n approxMessagesSnapshotBytes = 0;\n\n /**\n * The thread's true creation timestamp (epoch ms), captured from the FIRST\n * run ever appended and held at the THREAD level (independent of\n * `historicRuns` lifecycle). Decoupling it from per-run storage means run-cap\n * FIFO eviction — which shifts the oldest entries off `historicRuns` — can\n * never move the reported creation time forward. `null` until the first run\n * lands. Mirrors the `messagesSnapshot` thread-level decoupling.\n */\n createdAt: number | null = null;\n}\n\nexport class ɵBoundedThreadStore {\n private readonly map = new Map<string, InMemoryEventStore>();\n private totalBytes = 0;\n private warned = false;\n /** True once limits have been EXPLICITLY set (via setLimits), not just the constructor default. */\n private limitsExplicitlySet = false;\n /** Warn-once latch for the clobber warning, kept distinct from the eviction `warned` latch. */\n private clobberWarned = false;\n\n private limits: Required<InMemoryLimits>;\n\n constructor(limits: Required<InMemoryLimits>) {\n // Normalize once at construction so `this.limits` is ALWAYS well-formed,\n // regardless of entry point (direct construction or a later `setLimits`).\n this.limits = ɵnormalizeLimits(limits);\n }\n\n get byteTotal(): number {\n return this.totalBytes;\n }\n\n /**\n * The store's CURRENT effective bounds. Exposed (with the `ɵ` internal-API\n * prefix) so a partial `setLimits` can coalesce unspecified fields against the\n * live config rather than the hardcoded {@link ɵINMEMORY_DEFAULTS} — a partial\n * update must be a partial update, never a silent reset of the fields the\n * caller did not mention. Returns a copy so callers cannot mutate the store's\n * bounds through it.\n */\n get ɵlimits(): Required<InMemoryLimits> {\n return { ...this.limits };\n }\n\n /**\n * Reconfigure the process-global store's bounds. Called by the\n * {@link InMemoryAgentRunner} constructor when limits are passed. Because the\n * store is a per-process singleton, this replaces the bounds for ALL in-memory\n * threads. Emits {@link LIMITS_CLOBBER_GUIDANCE} at most ONCE per store when a\n * SECOND (or later) explicit set arrives whose resolved values differ from the\n * prior explicit set — i.e. a genuine clobber of an already-customized config.\n * The first explicit customization (defaults → custom) is the intended\n * override and never warns; identical re-sets never warn.\n */\n setLimits(limits: Required<InMemoryLimits>): void {\n // Normalize FIRST so invalid fields can never reach an enforcement loop and\n // so the clobber comparison below is against the EFFECTIVE (clamped) values,\n // not the raw ones — a typo'd bound that clamps to the current default is not\n // a genuine clobber and must not warn.\n const normalized = ɵnormalizeLimits(limits);\n if (\n this.limitsExplicitlySet &&\n !this.clobberWarned &&\n (normalized.maxThreads !== this.limits.maxThreads ||\n normalized.maxRunsPerThread !== this.limits.maxRunsPerThread ||\n normalized.maxBytes !== this.limits.maxBytes)\n ) {\n this.clobberWarned = true;\n try {\n console.warn(LIMITS_CLOBBER_GUIDANCE);\n } catch {\n // best-effort: logging must never break construction\n }\n }\n this.limitsExplicitlySet = true;\n this.limits = normalized;\n }\n\n get size(): number {\n return this.map.size;\n }\n\n /** Re-insert at the tail so Map iteration order stays LRU-first. */\n private touchOrder(threadId: string, store: InMemoryEventStore): void {\n this.map.delete(threadId);\n this.map.set(threadId, store);\n }\n\n getOrCreate(threadId: string): InMemoryEventStore {\n const existing = this.map.get(threadId);\n if (existing) {\n this.touchOrder(threadId, existing);\n return existing;\n }\n const store = new InMemoryEventStore(threadId);\n this.map.set(threadId, store);\n this.evictThreadsIfNeeded(threadId);\n return store;\n }\n\n get(\n threadId: string,\n opts: { touch: boolean },\n ): InMemoryEventStore | undefined {\n const store = this.map.get(threadId);\n if (store && opts.touch) this.touchOrder(threadId, store);\n return store;\n }\n\n peek(threadId: string): InMemoryEventStore | undefined {\n return this.map.get(threadId);\n }\n\n /**\n * Evict the least-recently-used thread that is neither running NOR\n * mid-finalization. Returns false if none evictable. The `protect` thread\n * (typically the one just created) is never evicted, so a fresh thread is not\n * immediately dropped when it is the only non-running candidate.\n *\n * A thread is skipped while `isRunning` OR `stopRequested` is set.\n * `stop()` flips `isRunning` to false the moment it aborts the agent, but the\n * run keeps finalizing asynchronously (the abort trips the `catch` in\n * `runAgent`, which later calls `appendRun`). During that window\n * `stopRequested` stays true; evicting the thread then would make the pending\n * `appendRun` hit `if (!store) return` and silently drop the aborted run's\n * history. Guarding on `stopRequested` keeps the thread alive until\n * finalization completes.\n */\n private evictOneLru(protect?: string): boolean {\n for (const [threadId, store] of this.map) {\n if (threadId === protect) continue; // never evict the just-created thread\n // never evict a running or still-finalizing (stop-requested) thread\n if (store.isRunning || store.stopRequested) continue;\n this.removeThread(threadId, store);\n this.noteEviction();\n return true;\n }\n return false;\n }\n\n appendRun(threadId: string, run: HistoricRun): void {\n const store = this.map.get(threadId);\n if (!store) return; // best-effort: nothing to append to\n\n // Thread-level creation timestamp: capture the FIRST run's createdAt once\n // and never overwrite it. Held on the store (not derived from\n // `historicRuns[0]`) so run-cap FIFO eviction of the oldest runs cannot\n // drift the thread's reported creation time forward. Mirrors the\n // thread-level `messagesSnapshot` decoupling below.\n if (store.createdAt === null) {\n store.createdAt = run.createdAt;\n }\n\n // Thread-level message snapshot: keep the single latest NON-EMPTY snapshot\n // on the store, decoupled from `historicRuns`. When the incoming run\n // carries a non-empty snapshot, replace the thread's snapshot (adjusting\n // byte accounting). When it's empty (non-array `agent.messages` or an\n // error-path run), leave the existing thread snapshot untouched so history\n // is never lost. The snapshot never lives on a HistoricRun, so run-cap FIFO\n // eviction can never drop it and an interleaved empty run can never pin it.\n if (run.messages.length > 0) {\n this.totalBytes -= store.approxMessagesSnapshotBytes;\n // Store the incoming array directly (SHALLOW, array-level copy). `run.messages`\n // is already a fresh `[...agent.messages]` array created in run(), so we own the\n // array and it is decoupled from `agent.messages` at the array level (push/splice\n // on the agent's array cannot mutate our snapshot). We deliberately do NOT deep-copy\n // here: `structuredClone` throws DataCloneError on a non-cloneable message field,\n // which would wedge the thread and hang SSE — inconsistent with `ɵestimateBytes`,\n // which tolerates the same bad-payload class. The tradeoff is that the inner\n // `Message` objects remain shared by reference with `agent.messages`, so an agent\n // that mutates its own message objects IN PLACE after the run can still be observed\n // through this snapshot. That inner-object isolation is a known limitation tracked as\n // follow-up; callers must treat returned messages as read-only. Estimate bytes on the\n // same value so accounting matches exactly what is retained.\n store.messagesSnapshot = run.messages;\n store.approxMessagesSnapshotBytes = ɵestimateBytes(run.messages);\n this.totalBytes += store.approxMessagesSnapshotBytes;\n }\n\n // Do not carry message bytes on the HistoricRun: the snapshot is now tracked\n // at the thread level, so historicRuns must never account message bytes.\n run.messages = [];\n run.approxMessageBytes = 0;\n\n // Compute this run's approximate event size once, at append time.\n run.approxEventBytes = ɵestimateBytes(run.events);\n store.historicRuns.push(run);\n this.totalBytes += run.approxEventBytes;\n this.touchOrder(threadId, store);\n\n this.enforceRunCap(store);\n this.evictByBytesIfNeeded(threadId);\n }\n\n private enforceRunCap(store: InMemoryEventStore): void {\n const cap = this.limits.maxRunsPerThread;\n if (!cap || cap === Infinity) return; // 0 or Infinity → disabled\n while (store.historicRuns.length > cap) {\n const dropped = store.historicRuns.shift()!;\n // Only event bytes live on a HistoricRun; the message snapshot is tracked\n // at the thread level and survives run-cap eviction.\n this.totalBytes -= dropped.approxEventBytes ?? 0;\n // Per-thread run-cap trimming is also eviction — history is being dropped.\n // Route it through the SAME warn-once latch as whole-thread LRU eviction so\n // this shows up in logs rather than as silent data loss. `noteEviction` is\n // latched (one warning per store, reset by `clear()`), so a hot thread that\n // trims on every subsequent append warns once, never per dropped run. The\n // loop only runs when a run is ACTUALLY over the cap, so a disabled or\n // under-cap `enforceRunCap` stays silent (it returned / never entered here).\n this.noteEviction();\n }\n }\n\n /**\n * Trim the store back under the byte ceiling by evicting LRU non-running\n * threads. `protect` (the just-appended thread) is never self-evicted, so a\n * fresh run pushes OTHER threads out rather than dropping itself.\n */\n private evictByBytesIfNeeded(protect?: string): void {\n while (this.totalBytes > this.limits.maxBytes) {\n if (!this.evictOneLru(protect)) break; // only protected/running threads left → accept overage\n }\n }\n\n private removeThread(threadId: string, store: InMemoryEventStore): void {\n for (const run of store.historicRuns) {\n this.totalBytes -= run.approxEventBytes ?? 0;\n }\n // The thread's message snapshot is tracked at the store level, so it must\n // be reclaimed here in addition to the per-run event bytes.\n this.totalBytes -= store.approxMessagesSnapshotBytes;\n this.map.delete(threadId);\n }\n\n private evictThreadsIfNeeded(protect?: string): void {\n while (this.map.size > this.limits.maxThreads) {\n if (!this.evictOneLru(protect)) break; // everything evictable is running → accept overage\n }\n }\n\n private noteEviction(): void {\n if (this.warned) return;\n this.warned = true;\n try {\n console.warn(EVICTION_GUIDANCE);\n } catch {\n // best-effort: logging must never break a run\n }\n }\n\n listThreads(): InMemoryThread[] {\n const threads: InMemoryThread[] = [];\n for (const [threadId, store] of this.map) {\n if (store.historicRuns.length === 0) continue;\n const lastRun = store.historicRuns[store.historicRuns.length - 1]!;\n // Creation time comes from the thread-level `store.createdAt` (the first\n // run ever appended), NOT `historicRuns[0]` (the oldest RETAINED run):\n // run-cap FIFO eviction drops the oldest retained runs, so deriving it\n // from `historicRuns[0]` would silently drift the timestamp forward over\n // a thread's lifetime. `updatedAt` stays on `lastRun` because FIFO\n // eviction removes from the FRONT, so the newest run is never evicted.\n // The `?? lastRun.createdAt` fallback is defensive only: any thread with\n // runs has had `store.createdAt` set by `appendRun`.\n threads.push({\n id: threadId,\n name: null,\n agentId: lastRun.agentId,\n organizationId: \"\",\n createdById: \"\",\n archived: false,\n createdAt: new Date(store.createdAt ?? lastRun.createdAt).toISOString(),\n updatedAt: new Date(lastRun.createdAt).toISOString(),\n });\n }\n return threads.sort(\n (a, b) =>\n new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n }\n\n clear(): void {\n this.map.clear();\n this.totalBytes = 0;\n this.warned = false;\n }\n}\n\n/**\n * Process-wide singleton backing every {@link InMemoryAgentRunner}. Exported\n * (with the `ɵ` internal-API prefix) so tests can inspect the exact store the\n * runner writes to; not part of the public API.\n */\nexport const ɵGLOBAL_STORE = new ɵBoundedThreadStore(ɵINMEMORY_DEFAULTS);\nconst sharedStore = ɵGLOBAL_STORE;\n\nexport class InMemoryAgentRunner extends AgentRunner {\n readonly ɵsupportsLocalThreadEndpoints = true;\n\n /**\n * How to handle a `run()` for a thread that already has an in-flight run.\n * `\"throw\"` (default) preserves the historic behavior. `\"supersede\"` aborts\n * the prior run (mirroring `stop()`) and starts the new one — opted into by\n * the hosted-bot listener so a fast follow-up turn on the same thread cleanly\n * replaces a still-running (or wedged) prior turn instead of erroring with\n * \"Thread already running\".\n */\n private readonly onConcurrentRun: \"throw\" | \"supersede\";\n\n /**\n * @param options Per-runner behavior (`onConcurrentRun`) plus optional bounds\n * for the in-memory store ({@link InMemoryLimits}).\n *\n * Note the differing scopes: `onConcurrentRun` is per-runner instance, while\n * the limits reconfigure the PROCESS-GLOBAL store shared by every\n * `InMemoryAgentRunner`. Omit the limits for safe defaults\n * ({@link ɵINMEMORY_DEFAULTS}); passing none leaves the store untouched. When\n * multiple runners are constructed with differing limits, the last-constructed\n * wins — in practice the OSS/SSE default construction passes nothing. If a\n * second (or later) runner is constructed with limits that DIFFER from an\n * already-customized store, a one-time `console.warn` is emitted to signal that\n * the shared store's bounds are being clobbered for ALL in-memory threads.\n */\n constructor(options?: InMemoryAgentRunnerOptions) {\n super();\n const { onConcurrentRun, ...limits } = options ?? {};\n this.onConcurrentRun = onConcurrentRun ?? \"throw\";\n\n // Only reconfigure the shared store when a bound was actually supplied.\n // `new InMemoryAgentRunner({ onConcurrentRun: \"supersede\" })` must stay\n // inert with respect to limits.\n if (\n limits.maxThreads !== undefined ||\n limits.maxRunsPerThread !== undefined ||\n limits.maxBytes !== undefined\n ) {\n // Coalesce each unspecified field against the store's CURRENT effective\n // limits, NOT ɵINMEMORY_DEFAULTS. The store is process-global, so tuning\n // one bound must leave every previously-customized sibling bound intact —\n // a partial update stays a partial update instead of silently resetting the\n // fields the caller never mentioned. Passing all three (e.g.\n // ɵINMEMORY_DEFAULTS) still fully replaces the config, so the defaults-\n // restore path is unaffected.\n const current = sharedStore.ɵlimits;\n sharedStore.setLimits({\n maxThreads: limits.maxThreads ?? current.maxThreads,\n maxRunsPerThread: limits.maxRunsPerThread ?? current.maxRunsPerThread,\n maxBytes: limits.maxBytes ?? current.maxBytes,\n });\n }\n }\n\n run(request: AgentRunnerRunRequest): Observable<BaseEvent> {\n const store = sharedStore.getOrCreate(request.threadId);\n\n // Enter the concurrency branch whenever a prior run still owns the thread —\n // either actively running OR still finalizing after a stop()/supersede.\n // `stop()` flips `isRunning` to false the instant it aborts the agent, but\n // the run keeps finalizing asynchronously (`stopRequested` stays true).\n // Gating on `isRunning` alone let a `run()` slip through that window\n // unhandled: no supersede/throw, no per-run intent capture, and a leaked\n // bridge from the dying run's subject.\n if (store.isRunning || store.stopRequested) {\n if (this.onConcurrentRun !== \"supersede\") {\n throw new Error(\"Thread already running\");\n }\n // Supersede: abort the prior (possibly wedged) run so this one can start.\n // Mirrors stop(). Record the prior run's OWN finalize intent on its\n // captured control BEFORE resetting the shared store flags for the new\n // run: a supersede is a clean stop of the prior run, so its async teardown\n // must finalize as RUN_FINISHED, never a synthetic RUN_ERROR. The prior\n // run's async finalization is prevented from clobbering this run's state\n // by the run-id guard below.\n const priorAgent = store.agent;\n const priorFinalize = store.activeFinalize;\n if (priorFinalize) {\n priorFinalize.stopRequested = true;\n }\n store.isRunning = false;\n if (priorAgent) {\n try {\n priorAgent.abortRun();\n } catch (error) {\n console.error(\"Failed to abort superseded run\", error);\n }\n }\n }\n store.isRunning = true;\n store.currentRunId = request.input.runId;\n store.agent = request.agent;\n store.stopRequested = false;\n\n // Per-run finalize control. This run's teardown reads THIS captured holder\n // (never the shared `store.stopRequested`, which a later run resets), so an\n // aborted run is always finalized against its own stop-intent.\n const finalizeControl: RunFinalizeControl = { stopRequested: false };\n store.activeFinalize = finalizeControl;\n\n // Track seen message IDs and current run events for this run\n const seenMessageIds = new Set<string>();\n const currentRunEvents: BaseEvent[] = [];\n store.currentEvents = currentRunEvents;\n\n // Get all previously seen message IDs from historic runs\n const historicMessageIds = new Set<string>();\n for (const run of store.historicRuns) {\n for (const event of run.events) {\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n historicMessageIds.add(event.messageId);\n }\n if (event.type === EventType.RUN_STARTED) {\n const runStarted = event as RunStartedEvent;\n const messages = runStarted.input?.messages ?? [];\n for (const message of messages) {\n historicMessageIds.add(message.id);\n }\n }\n }\n }\n\n const nextSubject = new ReplaySubject<BaseEvent>(Infinity);\n\n // Update the store's subject immediately. We intentionally do NOT capture\n // and bridge the previous subject: see the note before `runAgent()` below.\n store.subject = nextSubject;\n\n // Create a subject for run() return value\n const runSubject = new ReplaySubject<BaseEvent>(Infinity);\n store.runSubject = runSubject;\n\n // Helper function to run the agent and handle errors\n const runAgent = async () => {\n // Get parent run ID for chaining\n const lastRun = store.historicRuns[store.historicRuns.length - 1];\n const parentRunId = lastRun?.runId ?? null;\n\n // Shared teardown for both the success and error paths. Keeping this one\n // helper means the two paths cannot drift apart (they were near-identical\n // and must stay symmetric). `interruptionMessage` is set only on the error\n // path; its presence is what distinguishes the two.\n const finalizeRun = (opts: { interruptionMessage?: string }) => {\n const isError = opts.interruptionMessage !== undefined;\n\n // Capture the count of REAL (agent-emitted) events BEFORE finalizing.\n // `finalizeRunEvents` mutates `currentRunEvents` IN PLACE — it always\n // pushes a synthetic terminal (and any closers) when the stream ended\n // without one — so after the call `currentRunEvents.length` is never 0.\n // The persistence guard below must gate on this pre-finalize count, or\n // the \"skip an immediate throw that emitted nothing\" check is dead.\n const preFinalizeEventCount = currentRunEvents.length;\n\n // Finalize against THIS run's own captured stop-intent — never the\n // shared `store.stopRequested`, which a superseding run resets. An\n // aborted run is thus finalized as a clean RUN_FINISHED, not a synthetic\n // RUN_ERROR.\n const appendedEvents = finalizeRunEvents(currentRunEvents, {\n stopRequested: finalizeControl.stopRequested,\n ...(isError ? { interruptionMessage: opts.interruptionMessage } : {}),\n });\n for (const event of appendedEvents) {\n runSubject.next(event);\n nextSubject.next(event);\n }\n\n // Does this run still own the thread? A superseding run has changed\n // `currentRunId`, so the run it replaced no longer owns the store.\n const ownsThread = store.currentRunId === request.input.runId;\n\n // Store this run's events. Guard on the per-run id (not the shared\n // `store.currentRunId`): a superseded run no longer owns the store, so\n // it must not push history — and never under a newer run's id, which\n // would corrupt the thread's history. On the error path also require at\n // least one real (pre-finalize) event, so an immediate throw with\n // nothing emitted does not create a phantom historic run holding only\n // the synthetic terminal.\n if (ownsThread && (!isError || preFinalizeEventCount > 0)) {\n // Compact the events before storing (like SQLite does)\n const compactedEvents = compactEvents(currentRunEvents);\n sharedStore.appendRun(request.threadId, {\n threadId: request.threadId,\n runId: request.input.runId,\n agentId: request.agent.agentId ?? \"default\",\n parentRunId,\n events: compactedEvents,\n // Snapshot all messages (input + generated) for the thread-messages endpoint\n messages: Array.isArray(request.agent.messages)\n ? [...request.agent.messages]\n : [],\n createdAt: Date.now(),\n });\n }\n\n // Complete the run. Guard the shared-store reset: if a newer run has\n // superseded this one (`currentRunId` changed), that run now owns the\n // store — don't clobber its state. Always complete THIS run's subjects.\n if (ownsThread) {\n store.currentEvents = null;\n store.currentRunId = null;\n store.agent = null;\n store.runSubject = null;\n store.stopRequested = false;\n store.isRunning = false;\n store.activeFinalize = null;\n }\n runSubject.complete();\n nextSubject.complete();\n // Time-scoped release: this run's events are now in historicRuns, so its\n // infinite ReplaySubject buffer is pure duplication — drop the store's\n // reference so it becomes collectable. The identity guard is what makes\n // this correct, and it does so differently on each path:\n //\n // - Owning path: no newer run superseded this one, so store.subject is\n // still nextSubject and the guard passes. The `if (ownsThread)` block\n // above just cleared isRunning and stopRequested, so connect() — which\n // bridges store.subject only while isRunning || stopRequested — will\n // not re-subscribe; it rebuilds this run's events from historicRuns\n // instead. Nulling the reference is therefore safe.\n //\n // - Superseded path (`onConcurrentRun: \"supersede\"`): a newer run has\n // already installed ITS subject and run id on the store, so the guard\n // fails and we leave store.subject untouched. Here isRunning/\n // stopRequested describe that live run (isRunning is typically true),\n // so it is precisely the identity guard — not those flags — that\n // prevents us from nulling the live run's subject and cutting\n // connect() off from the in-flight stream. This run's own buffer is no\n // longer referenced by the store and becomes collectable regardless.\n if (store.subject === nextSubject) {\n store.subject = null;\n }\n };\n\n try {\n await request.agent.runAgent(request.input, {\n onEvent: ({ event }) => {\n let processedEvent: BaseEvent = event;\n if (event.type === EventType.RUN_STARTED) {\n const runStartedEvent = event as RunStartedEvent;\n if (!runStartedEvent.input) {\n const sanitizedMessages = request.input.messages\n ? request.input.messages.filter(\n (message) => !historicMessageIds.has(message.id),\n )\n : undefined;\n const updatedInput = {\n ...request.input,\n ...(sanitizedMessages !== undefined\n ? { messages: sanitizedMessages }\n : {}),\n };\n runStartedEvent.input = updatedInput;\n processedEvent = runStartedEvent;\n }\n }\n\n runSubject.next(processedEvent); // For run() return - only agent events\n nextSubject.next(processedEvent); // For connect() / store - all events\n currentRunEvents.push(processedEvent); // Accumulate for storage\n },\n onNewMessage: ({ message }) => {\n // Called for each new message\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n },\n onRunStartedEvent: () => {\n // Mark any messages from the input as seen so they aren't emitted twice\n if (request.input.messages) {\n for (const message of request.input.messages) {\n if (!seenMessageIds.has(message.id)) {\n seenMessageIds.add(message.id);\n }\n }\n }\n },\n });\n\n finalizeRun({});\n } catch (error) {\n const interruptionMessage =\n error instanceof Error ? error.message : String(error);\n finalizeRun({ interruptionMessage });\n }\n };\n\n // NOTE: we deliberately do NOT bridge the previous store subject into\n // `nextSubject`. `store.subject` is nulled the moment a run fully tears down\n // (identity guard in `finalizeRun`), so the previous subject is non-null\n // ONLY when this run is superseding a prior run that is still in flight or\n // finalizing. Forwarding that dying run's subject would replay its buffered\n // RUN_STARTED and push its terminal event (RUN_FINISHED/RUN_ERROR) into THIS\n // live run's stream — an invalid AG-UI sequence on a healthy run. A\n // superseded run's stream must stay isolated: it reaches only its own\n // connect() subscribers via its own (now-detached) subject, never the\n // superseding run's.\n\n // Start the agent execution immediately (not lazily)\n runAgent();\n\n // Return the run subject (only agent events, no injected messages)\n return runSubject.asObservable();\n }\n\n connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {\n const store = sharedStore.get(request.threadId, { touch: true });\n const connectionSubject = new ReplaySubject<BaseEvent>(Infinity);\n\n if (!store) {\n // No store means no events\n connectionSubject.complete();\n return connectionSubject.asObservable();\n }\n\n // Collect all historic events from memory\n const allHistoricEvents: BaseEvent[] = [];\n for (const run of store.historicRuns) {\n allHistoricEvents.push(...run.events);\n }\n\n // Apply compaction to all historic events together (like SQLite)\n const compactedEvents = compactEvents(allHistoricEvents);\n\n // Emit compacted events and track message IDs\n const emittedMessageIds = new Set<string>();\n for (const event of compactedEvents) {\n connectionSubject.next(event);\n if (\"messageId\" in event && typeof event.messageId === \"string\") {\n emittedMessageIds.add(event.messageId);\n }\n }\n\n // Bridge active run to connection if exists\n if (store.subject && (store.isRunning || store.stopRequested)) {\n store.subject.subscribe({\n next: (event) => {\n // Skip message events that we've already emitted from historic\n if (\n \"messageId\" in event &&\n typeof event.messageId === \"string\" &&\n emittedMessageIds.has(event.messageId)\n ) {\n return;\n }\n connectionSubject.next(event);\n },\n complete: () => connectionSubject.complete(),\n error: (err) => connectionSubject.error(err),\n });\n } else {\n // No active run, complete after historic events\n connectionSubject.complete();\n }\n\n return connectionSubject.asObservable();\n }\n\n isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {\n const store = sharedStore.peek(request.threadId);\n return Promise.resolve(store?.isRunning ?? false);\n }\n\n stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {\n const store = sharedStore.peek(request.threadId);\n if (!store || !store.isRunning) {\n return Promise.resolve(false);\n }\n if (request.runId !== undefined && store.currentRunId !== request.runId) {\n return Promise.resolve(false);\n }\n if (store.stopRequested) {\n return Promise.resolve(false);\n }\n\n store.stopRequested = true;\n store.isRunning = false;\n // Record the stop on the running run's OWN finalize control so its async\n // teardown finalizes as a clean RUN_FINISHED. This is the same object that\n // run's closure reads, so a later run cannot mislabel this stop.\n const finalizeControl = store.activeFinalize;\n if (finalizeControl) {\n finalizeControl.stopRequested = true;\n }\n\n const agent = store.agent;\n if (!agent) {\n store.stopRequested = false;\n store.isRunning = false;\n if (finalizeControl) {\n finalizeControl.stopRequested = false;\n }\n return Promise.resolve(false);\n }\n\n try {\n agent.abortRun();\n return Promise.resolve(true);\n } catch (error) {\n console.error(\"Failed to abort agent run\", error);\n store.stopRequested = false;\n store.isRunning = true;\n if (finalizeControl) {\n finalizeControl.stopRequested = false;\n }\n return Promise.resolve(false);\n }\n }\n\n /**\n * Returns a summary of every thread that has been run through this runner.\n *\n * This powers the local-dev fallback for `GET /threads` when the Intelligence\n * platform is not configured. Each entry mirrors the shape of a platform\n * `ThreadRecord` so the HTTP handler can use the same response envelope.\n */\n listThreads(): InMemoryThread[] {\n return sharedStore.listThreads();\n }\n\n /**\n * Returns all messages for a thread, using the snapshot captured at the end\n * of the most recent run.\n *\n * This powers the local-dev fallback for `GET /threads/:threadId/messages`\n * when CopilotKit Intelligence is not configured. The returned `Message[]`\n * objects come directly from the ag-ui agent, so their shape is compatible\n * with CopilotKit Intelligence's `ThreadMessage` type.\n */\n getThreadMessages(threadId: string): Message[] {\n const store = sharedStore.peek(threadId);\n if (!store) return [];\n // The thread's latest non-empty snapshot is held at the store level,\n // independent of `historicRuns` lifecycle, so run-cap eviction and\n // interleaved empty-snapshot runs can never lose it. Return a SHALLOW\n // (array-level) copy: a fresh array so a caller mutating array STRUCTURE\n // (push/splice/reassign elements) cannot affect the stored snapshot. We\n // deliberately do NOT deep-copy: `structuredClone` throws DataCloneError on a\n // non-cloneable message field, which would wedge the thread and hang SSE —\n // inconsistent with `ɵestimateBytes`, which tolerates the same bad-payload class.\n // The tradeoff is that the inner `Message` objects remain shared by reference with\n // the stored snapshot, so mutating a returned message's FIELD\n // (e.g. `getThreadMessages(t)[0].content = \"x\"`) is NOT isolated and would corrupt\n // the stored snapshot. That inner-object isolation is a known limitation tracked as\n // follow-up; callers must treat returned messages as read-only.\n return [...store.messagesSnapshot];\n }\n\n /**\n * Returns all AG-UI events for a thread, compacted across historic runs.\n *\n * Powers the local-dev fallback for `GET /threads/:threadId/events` when the\n * CopilotKit Intelligence is not configured. The compaction logic matches\n * the connection-replay path in {@link connect}, so the stream a\n * late-joining inspector sees matches what this method returns.\n */\n getThreadEvents(threadId: string): BaseEvent[] {\n const store = sharedStore.peek(threadId);\n if (!store || store.historicRuns.length === 0) return [];\n const all: BaseEvent[] = [];\n for (const run of store.historicRuns) all.push(...run.events);\n return compactEvents(all);\n }\n\n /**\n * Returns the agent state snapshot for a thread.\n *\n * Derived from the last `STATE_SNAPSHOT` in the compacted event stream. The\n * AG-UI `compactEvents` helper consolidates STATE_DELTA events and produces\n * a single trailing STATE_SNAPSHOT when state changes exist, so this is a\n * faithful view of state at the end of the most recent run.\n *\n * Returns `null` when the thread has never emitted a STATE_SNAPSHOT.\n */\n getThreadState(threadId: string): Record<string, unknown> | null {\n const events = this.getThreadEvents(threadId);\n // Walk backwards — the last snapshot wins.\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]!;\n if (event.type === EventType.STATE_SNAPSHOT) {\n const snapshot = (event as StateSnapshotEvent).snapshot;\n // Only plain objects satisfy the Record<string, unknown> contract.\n // `typeof [] === \"object\"` is true, so arrays must be rejected\n // explicitly to avoid returning an array typed as a Record.\n if (\n snapshot &&\n typeof snapshot === \"object\" &&\n !Array.isArray(snapshot)\n ) {\n // Return a defensive shallow copy so callers can't mutate the\n // snapshot object held inside the stored event (matches the\n // getThreadMessages defensive-copy approach).\n return { ...(snapshot as Record<string, unknown>) };\n }\n return null;\n }\n }\n return null;\n }\n\n /**\n * Clears all in-memory thread history.\n *\n * Powers the local-dev fallback for `POST /threads/clear`, letting consumers\n * (e.g. the demo's Clear button) reset to an empty thread list without\n * restarting the runtime. Intentionally not exposed on the Intelligence\n * platform path: there, thread history lives in a real database and must\n * not be wiped this way.\n */\n clearThreads(): void {\n sharedStore.clear();\n }\n}\n"],"mappings":"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"}