@rudderhq/server 0.4.6-canary.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/dist/agent-runtimes/http/execute.d.ts.map +1 -1
  2. package/dist/agent-runtimes/http/execute.js +8 -2
  3. package/dist/agent-runtimes/http/execute.js.map +1 -1
  4. package/dist/agent-runtimes/process/execute.d.ts.map +1 -1
  5. package/dist/agent-runtimes/process/execute.js +3 -1
  6. package/dist/agent-runtimes/process/execute.js.map +1 -1
  7. package/dist/agent-runtimes/utils.d.ts +6 -1
  8. package/dist/agent-runtimes/utils.d.ts.map +1 -1
  9. package/dist/agent-runtimes/utils.js +1 -1
  10. package/dist/agent-runtimes/utils.js.map +1 -1
  11. package/dist/app.d.ts +3 -3
  12. package/dist/app.d.ts.map +1 -1
  13. package/dist/app.js +17 -8
  14. package/dist/app.js.map +1 -1
  15. package/dist/bootstrap/create-http-app.d.ts +6 -1
  16. package/dist/bootstrap/create-http-app.d.ts.map +1 -1
  17. package/dist/bootstrap/create-http-app.js +122 -46
  18. package/dist/bootstrap/create-http-app.js.map +1 -1
  19. package/dist/bootstrap/plugin-host-runtime.d.ts.map +1 -1
  20. package/dist/bootstrap/plugin-host-runtime.js +89 -31
  21. package/dist/bootstrap/plugin-host-runtime.js.map +1 -1
  22. package/dist/bootstrap/register-api-routes.d.ts +3 -1
  23. package/dist/bootstrap/register-api-routes.d.ts.map +1 -1
  24. package/dist/bootstrap/register-api-routes.js +3 -3
  25. package/dist/bootstrap/register-api-routes.js.map +1 -1
  26. package/dist/bootstrap/types.d.ts +1 -0
  27. package/dist/bootstrap/types.d.ts.map +1 -1
  28. package/dist/bundled-plugins/plugin-linear/dist/worker.js +351 -174
  29. package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +3 -3
  30. package/dist/config.d.ts +2 -0
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +23 -0
  33. package/dist/config.js.map +1 -1
  34. package/dist/home-paths.d.ts.map +1 -1
  35. package/dist/home-paths.js +79 -7
  36. package/dist/home-paths.js.map +1 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +112 -119
  39. package/dist/index.js.map +1 -1
  40. package/dist/realtime/live-events-ws.d.ts +4 -20
  41. package/dist/realtime/live-events-ws.d.ts.map +1 -1
  42. package/dist/realtime/live-events-ws.js +68 -8
  43. package/dist/realtime/live-events-ws.js.map +1 -1
  44. package/dist/routes/access-onboarding.helpers.js +3 -3
  45. package/dist/routes/access-onboarding.helpers.js.map +1 -1
  46. package/dist/routes/access.helpers.d.ts.map +1 -1
  47. package/dist/routes/access.helpers.js +3 -2
  48. package/dist/routes/access.helpers.js.map +1 -1
  49. package/dist/routes/access.js +1 -1
  50. package/dist/routes/access.js.map +1 -1
  51. package/dist/routes/activity.d.ts.map +1 -1
  52. package/dist/routes/activity.js +5 -1
  53. package/dist/routes/activity.js.map +1 -1
  54. package/dist/routes/agents.management-routes.d.ts.map +1 -1
  55. package/dist/routes/agents.management-routes.js +15 -15
  56. package/dist/routes/agents.management-routes.js.map +1 -1
  57. package/dist/routes/assets.d.ts.map +1 -1
  58. package/dist/routes/assets.js +9 -2
  59. package/dist/routes/assets.js.map +1 -1
  60. package/dist/routes/chat-background-runtime.d.ts +19 -0
  61. package/dist/routes/chat-background-runtime.d.ts.map +1 -0
  62. package/dist/routes/chat-background-runtime.js +129 -0
  63. package/dist/routes/chat-background-runtime.js.map +1 -0
  64. package/dist/routes/chats.d.ts +2 -1
  65. package/dist/routes/chats.d.ts.map +1 -1
  66. package/dist/routes/chats.js +944 -24
  67. package/dist/routes/chats.js.map +1 -1
  68. package/dist/routes/chats.stream-routes.d.ts.map +1 -1
  69. package/dist/routes/chats.stream-routes.js +552 -76
  70. package/dist/routes/chats.stream-routes.js.map +1 -1
  71. package/dist/routes/issues.comments-attachments.d.ts.map +1 -1
  72. package/dist/routes/issues.comments-attachments.js +14 -31
  73. package/dist/routes/issues.comments-attachments.js.map +1 -1
  74. package/dist/routes/onboarding.js +1 -1
  75. package/dist/routes/onboarding.js.map +1 -1
  76. package/dist/routes/orgs.d.ts +2 -1
  77. package/dist/routes/orgs.d.ts.map +1 -1
  78. package/dist/routes/orgs.js +32 -3
  79. package/dist/routes/orgs.js.map +1 -1
  80. package/dist/routes/run-intelligence.d.ts.map +1 -1
  81. package/dist/routes/run-intelligence.js +109 -25
  82. package/dist/routes/run-intelligence.js.map +1 -1
  83. package/dist/runtime/runtime-supervisor.d.ts +21 -0
  84. package/dist/runtime/runtime-supervisor.d.ts.map +1 -0
  85. package/dist/runtime/runtime-supervisor.js +66 -0
  86. package/dist/runtime/runtime-supervisor.js.map +1 -0
  87. package/dist/services/activity-log.d.ts +4 -1
  88. package/dist/services/activity-log.d.ts.map +1 -1
  89. package/dist/services/activity-log.js +12 -4
  90. package/dist/services/activity-log.js.map +1 -1
  91. package/dist/services/activity.d.ts +11 -394
  92. package/dist/services/activity.d.ts.map +1 -1
  93. package/dist/services/activity.js +24 -18
  94. package/dist/services/activity.js.map +1 -1
  95. package/dist/services/agents.d.ts +799 -137
  96. package/dist/services/agents.d.ts.map +1 -1
  97. package/dist/services/approvals.d.ts +3 -3
  98. package/dist/services/automation-chat-output.d.ts.map +1 -1
  99. package/dist/services/automation-chat-output.js +115 -94
  100. package/dist/services/automation-chat-output.js.map +1 -1
  101. package/dist/services/budgets.d.ts.map +1 -1
  102. package/dist/services/budgets.js +38 -36
  103. package/dist/services/budgets.js.map +1 -1
  104. package/dist/services/chat-agent-runs.d.ts +3 -1
  105. package/dist/services/chat-agent-runs.d.ts.map +1 -1
  106. package/dist/services/chat-agent-runs.js +97 -34
  107. package/dist/services/chat-agent-runs.js.map +1 -1
  108. package/dist/services/chat-assistant.d.ts.map +1 -1
  109. package/dist/services/chat-assistant.helpers.d.ts +27 -4
  110. package/dist/services/chat-assistant.helpers.d.ts.map +1 -1
  111. package/dist/services/chat-assistant.helpers.js +66 -2
  112. package/dist/services/chat-assistant.helpers.js.map +1 -1
  113. package/dist/services/chat-assistant.inline-visuals.test.d.ts +2 -0
  114. package/dist/services/chat-assistant.inline-visuals.test.d.ts.map +1 -0
  115. package/dist/services/chat-assistant.inline-visuals.test.js +86 -0
  116. package/dist/services/chat-assistant.inline-visuals.test.js.map +1 -0
  117. package/dist/services/chat-assistant.js +115 -22
  118. package/dist/services/chat-assistant.js.map +1 -1
  119. package/dist/services/chat-generation-locks.d.ts +85 -0
  120. package/dist/services/chat-generation-locks.d.ts.map +1 -1
  121. package/dist/services/chat-generation-locks.js +371 -9
  122. package/dist/services/chat-generation-locks.js.map +1 -1
  123. package/dist/services/chat-generation-locks.test.d.ts +2 -0
  124. package/dist/services/chat-generation-locks.test.d.ts.map +1 -0
  125. package/dist/services/chat-generation-locks.test.js +324 -0
  126. package/dist/services/chat-generation-locks.test.js.map +1 -0
  127. package/dist/services/chat-generation-protocol.d.ts +674 -0
  128. package/dist/services/chat-generation-protocol.d.ts.map +1 -0
  129. package/dist/services/chat-generation-protocol.js +1571 -0
  130. package/dist/services/chat-generation-protocol.js.map +1 -0
  131. package/dist/services/chat-generation-protocol.test.d.ts +2 -0
  132. package/dist/services/chat-generation-protocol.test.d.ts.map +1 -0
  133. package/dist/services/chat-generation-protocol.test.js +1156 -0
  134. package/dist/services/chat-generation-protocol.test.js.map +1 -0
  135. package/dist/services/chat-title-generation.d.ts +0 -3
  136. package/dist/services/chat-title-generation.d.ts.map +1 -1
  137. package/dist/services/chat-title-generation.js +2 -32
  138. package/dist/services/chat-title-generation.js.map +1 -1
  139. package/dist/services/chat-work-manifest.d.ts.map +1 -1
  140. package/dist/services/chat-work-manifest.js +5 -1
  141. package/dist/services/chat-work-manifest.js.map +1 -1
  142. package/dist/services/chats.d.ts +1451 -272
  143. package/dist/services/chats.d.ts.map +1 -1
  144. package/dist/services/chats.js +1372 -35
  145. package/dist/services/chats.js.map +1 -1
  146. package/dist/services/costs.d.ts +34 -7
  147. package/dist/services/costs.d.ts.map +1 -1
  148. package/dist/services/costs.js +129 -61
  149. package/dist/services/costs.js.map +1 -1
  150. package/dist/services/finance.d.ts +3 -3
  151. package/dist/services/goals.d.ts +2 -2
  152. package/dist/services/heartbeat-run-summary.d.ts.map +1 -1
  153. package/dist/services/heartbeat-run-summary.js +16 -1
  154. package/dist/services/heartbeat-run-summary.js.map +1 -1
  155. package/dist/services/heartbeat.d.ts +1 -1
  156. package/dist/services/heartbeat.d.ts.map +1 -1
  157. package/dist/services/heartbeat.js +1 -1
  158. package/dist/services/heartbeat.js.map +1 -1
  159. package/dist/services/index.d.ts +1 -0
  160. package/dist/services/index.d.ts.map +1 -1
  161. package/dist/services/index.js +1 -0
  162. package/dist/services/index.js.map +1 -1
  163. package/dist/services/integrations/agent-integrations.d.ts +1 -1
  164. package/dist/services/integrations/custom-integrations.d.ts +1 -1
  165. package/dist/services/integrations/feishu/runtime.d.ts.map +1 -1
  166. package/dist/services/integrations/feishu/runtime.js +16 -0
  167. package/dist/services/integrations/feishu/runtime.js.map +1 -1
  168. package/dist/services/issues.comments-attachments.d.ts +111 -0
  169. package/dist/services/issues.comments-attachments.d.ts.map +1 -1
  170. package/dist/services/issues.comments-attachments.js +138 -66
  171. package/dist/services/issues.comments-attachments.js.map +1 -1
  172. package/dist/services/issues.d.ts +56 -0
  173. package/dist/services/issues.d.ts.map +1 -1
  174. package/dist/services/issues.helpers.d.ts.map +1 -1
  175. package/dist/services/issues.helpers.js +2 -2
  176. package/dist/services/issues.helpers.js.map +1 -1
  177. package/dist/services/issues.js +5 -2
  178. package/dist/services/issues.js.map +1 -1
  179. package/dist/services/knowledge-portability/organization-skills.catalog.d.ts.map +1 -1
  180. package/dist/services/knowledge-portability/organization-skills.catalog.js +7 -1
  181. package/dist/services/knowledge-portability/organization-skills.catalog.js.map +1 -1
  182. package/dist/services/messenger.d.ts.map +1 -1
  183. package/dist/services/messenger.js +11 -9
  184. package/dist/services/messenger.js.map +1 -1
  185. package/dist/services/organization-workspace-browser.d.ts +1 -1
  186. package/dist/services/organization-workspace-browser.d.ts.map +1 -1
  187. package/dist/services/organization-workspace-browser.js +49 -5
  188. package/dist/services/organization-workspace-browser.js.map +1 -1
  189. package/dist/services/orgs.d.ts.map +1 -1
  190. package/dist/services/orgs.js +36 -12
  191. package/dist/services/orgs.js.map +1 -1
  192. package/dist/services/plugin-dev-watcher.d.ts +19 -2
  193. package/dist/services/plugin-dev-watcher.d.ts.map +1 -1
  194. package/dist/services/plugin-dev-watcher.js +45 -11
  195. package/dist/services/plugin-dev-watcher.js.map +1 -1
  196. package/dist/services/plugin-registry.d.ts +28 -28
  197. package/dist/services/projects.d.ts +1 -1
  198. package/dist/services/run-events.d.ts +20 -0
  199. package/dist/services/run-events.d.ts.map +1 -0
  200. package/dist/services/run-events.js +34 -0
  201. package/dist/services/run-events.js.map +1 -0
  202. package/dist/services/run-intelligence.d.ts +66 -4
  203. package/dist/services/run-intelligence.d.ts.map +1 -1
  204. package/dist/services/run-intelligence.js +391 -42
  205. package/dist/services/run-intelligence.js.map +1 -1
  206. package/dist/services/run-log-store.d.ts.map +1 -1
  207. package/dist/services/run-log-store.js +26 -3
  208. package/dist/services/run-log-store.js.map +1 -1
  209. package/dist/services/runtime-kernel/heartbeat.core.d.ts +24 -1
  210. package/dist/services/runtime-kernel/heartbeat.core.d.ts.map +1 -1
  211. package/dist/services/runtime-kernel/heartbeat.core.js +2 -1
  212. package/dist/services/runtime-kernel/heartbeat.core.js.map +1 -1
  213. package/dist/services/runtime-kernel/heartbeat.d.ts +98 -37
  214. package/dist/services/runtime-kernel/heartbeat.d.ts.map +1 -1
  215. package/dist/services/runtime-kernel/heartbeat.execute.d.ts +3 -1
  216. package/dist/services/runtime-kernel/heartbeat.execute.d.ts.map +1 -1
  217. package/dist/services/runtime-kernel/heartbeat.execute.js +394 -219
  218. package/dist/services/runtime-kernel/heartbeat.execute.js.map +1 -1
  219. package/dist/services/runtime-kernel/heartbeat.js +603 -205
  220. package/dist/services/runtime-kernel/heartbeat.js.map +1 -1
  221. package/dist/services/runtime-kernel/heartbeat.misc.d.ts.map +1 -1
  222. package/dist/services/runtime-kernel/heartbeat.misc.js +34 -24
  223. package/dist/services/runtime-kernel/heartbeat.misc.js.map +1 -1
  224. package/dist/services/runtime-kernel/heartbeat.recovery.d.ts.map +1 -1
  225. package/dist/services/runtime-kernel/heartbeat.recovery.js +56 -6
  226. package/dist/services/runtime-kernel/heartbeat.recovery.js.map +1 -1
  227. package/dist/services/runtime-kernel/heartbeat.release.d.ts +3 -1
  228. package/dist/services/runtime-kernel/heartbeat.release.d.ts.map +1 -1
  229. package/dist/services/runtime-kernel/heartbeat.release.js +276 -44
  230. package/dist/services/runtime-kernel/heartbeat.release.js.map +1 -1
  231. package/dist/services/runtime-kernel/heartbeat.sessions.d.ts +42 -1
  232. package/dist/services/runtime-kernel/heartbeat.sessions.d.ts.map +1 -1
  233. package/dist/services/runtime-kernel/heartbeat.sessions.js +110 -8
  234. package/dist/services/runtime-kernel/heartbeat.sessions.js.map +1 -1
  235. package/dist/services/runtime-kernel/heartbeat.terminal.d.ts +575 -0
  236. package/dist/services/runtime-kernel/heartbeat.terminal.d.ts.map +1 -0
  237. package/dist/services/runtime-kernel/heartbeat.terminal.js +589 -0
  238. package/dist/services/runtime-kernel/heartbeat.terminal.js.map +1 -0
  239. package/dist/services/runtime-kernel/heartbeat.wakeup.d.ts.map +1 -1
  240. package/dist/services/runtime-kernel/heartbeat.wakeup.js +238 -92
  241. package/dist/services/runtime-kernel/heartbeat.wakeup.js.map +1 -1
  242. package/dist/services/runtime-kernel/model-fallback.d.ts.map +1 -1
  243. package/dist/services/runtime-kernel/model-fallback.js +11 -0
  244. package/dist/services/runtime-kernel/model-fallback.js.map +1 -1
  245. package/dist/services/side-chats.d.ts +212 -0
  246. package/dist/services/side-chats.d.ts.map +1 -0
  247. package/dist/services/side-chats.js +379 -0
  248. package/dist/services/side-chats.js.map +1 -0
  249. package/dist/services/workspace-runtime.services.d.ts +1 -1
  250. package/dist/services/workspace-web-preview.d.ts +36 -0
  251. package/dist/services/workspace-web-preview.d.ts.map +1 -0
  252. package/dist/services/workspace-web-preview.js +566 -0
  253. package/dist/services/workspace-web-preview.js.map +1 -0
  254. package/package.json +13 -13
  255. package/resources/bundled-skills/rudder-docs/SKILL.md +161 -0
  256. package/resources/bundled-skills/rudder-docs/evals/trigger-evals.json +82 -0
  257. package/{skills/rudder → resources/bundled-skills/rudder-docs}/references/api-reference.md +17 -1
  258. package/{skills/rudder → resources/bundled-skills/rudder-docs}/references/cli-reference.md +52 -97
  259. package/resources/bundled-skills/rudder-docs/references/control-plane-practices.md +231 -0
  260. package/{skills/rudder → resources/bundled-skills/rudder-docs}/references/organization-skills.md +15 -1
  261. package/resources/bundled-skills/rudder-docs/references/source-map.md +138 -0
  262. package/resources/bundled-skills/visualize/SKILL.md +132 -0
  263. package/resources/bundled-skills/visualize/agents/openai.yaml +7 -0
  264. package/resources/bundled-skills/visualize/assets/example-chart.html +89 -0
  265. package/resources/bundled-skills/visualize/references/runtime-contract.md +114 -0
  266. package/skills/rudder-docs/SKILL.md +161 -0
  267. package/skills/rudder-docs/evals/trigger-evals.json +82 -0
  268. package/{resources/bundled-skills/rudder → skills/rudder-docs}/references/api-reference.md +17 -1
  269. package/{resources/bundled-skills/rudder → skills/rudder-docs}/references/cli-reference.md +52 -97
  270. package/skills/rudder-docs/references/control-plane-practices.md +231 -0
  271. package/{resources/bundled-skills/rudder → skills/rudder-docs}/references/organization-skills.md +15 -1
  272. package/skills/rudder-docs/references/source-map.md +138 -0
  273. package/skills/visualize/SKILL.md +132 -0
  274. package/skills/visualize/agents/openai.yaml +7 -0
  275. package/skills/visualize/assets/example-chart.html +89 -0
  276. package/skills/visualize/references/runtime-contract.md +114 -0
  277. package/ui-dist/assets/{abnfDiagram-VRR7QNED-C4e_AuJm.js → abnfDiagram-VRR7QNED-Dpnx79fp.js} +1 -1
  278. package/ui-dist/assets/{arc-3OG5_qjR.js → arc-Cpvh_rCf.js} +1 -1
  279. package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-CJz3inSs.js → architectureDiagram-ZJ3FMSHR-sDD_mBAI.js} +1 -1
  280. package/ui-dist/assets/{blockDiagram-677ZJIJ3-CpBIok39.js → blockDiagram-677ZJIJ3-4O4wWti1.js} +1 -1
  281. package/ui-dist/assets/{c4Diagram-LMCZKHZV-BbQrD6Fx.js → c4Diagram-LMCZKHZV-BkGODE4P.js} +1 -1
  282. package/ui-dist/assets/channel-CM4Myg_6.js +1 -0
  283. package/ui-dist/assets/{chunk-2Q5K7J3B-BkoT6fZL.js → chunk-2Q5K7J3B-DsDQQpID.js} +1 -1
  284. package/ui-dist/assets/{chunk-32BRIVSS-DecBtqTH.js → chunk-32BRIVSS-Bzx_VnIw.js} +1 -1
  285. package/ui-dist/assets/{chunk-5VM5RSS4-SFFAgh5q.js → chunk-5VM5RSS4-D4LoPCni.js} +1 -1
  286. package/ui-dist/assets/{chunk-EX3LRPZG-CxUndf0S.js → chunk-EX3LRPZG-BO0R-mS4.js} +3 -3
  287. package/ui-dist/assets/{chunk-JWPE2WC7-BbEXuDLm.js → chunk-JWPE2WC7-B4Nr8KRL.js} +1 -1
  288. package/ui-dist/assets/{chunk-MOJQB5TN-MOCGQpRH.js → chunk-MOJQB5TN--uaDDrYM.js} +1 -1
  289. package/ui-dist/assets/{chunk-RYQCIY6F-CUuwDB4L.js → chunk-RYQCIY6F-CyBY2w_j.js} +1 -1
  290. package/ui-dist/assets/{chunk-V7JOEXUC-D5H80ZpL.js → chunk-V7JOEXUC-BMid_x8S.js} +3 -3
  291. package/ui-dist/assets/{chunk-VR4S4FIN-Cg5d82yb.js → chunk-VR4S4FIN-DVqdPKuG.js} +1 -1
  292. package/ui-dist/assets/{chunk-XXDRQBXY-Bu7DXS_3.js → chunk-XXDRQBXY-vy03lLSS.js} +1 -1
  293. package/ui-dist/assets/classDiagram-OUVF2IWQ-CtlIEzTt.js +1 -0
  294. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CtlIEzTt.js +1 -0
  295. package/ui-dist/assets/{cose-bilkent-JH36ORCC-LCobsJkA.js → cose-bilkent-JH36ORCC-jQDZmrG3.js} +1 -1
  296. package/ui-dist/assets/{cynefin-VYW2F7L2-CxDfvhGJ.js → cynefin-VYW2F7L2-BxBj6aea.js} +1 -1
  297. package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-BbebJ96a.js → cynefinDiagram-TSTJHNR4-BuUubF5I.js} +1 -1
  298. package/ui-dist/assets/{dagre-VKFMJZFB-BNQ0fvpl.js → dagre-VKFMJZFB-B8HipJ3a.js} +1 -1
  299. package/ui-dist/assets/{diagram-FQU43EPY-B9vCEyLD.js → diagram-FQU43EPY-r7gkbKSt.js} +2 -2
  300. package/ui-dist/assets/{diagram-G47NLZAW-Z7Hg_sXF.js → diagram-G47NLZAW-CxClRsxD.js} +1 -1
  301. package/ui-dist/assets/{diagram-NH7WQ7WH-B_TZ5-gD.js → diagram-NH7WQ7WH-C8HYTLlq.js} +1 -1
  302. package/ui-dist/assets/{diagram-OA4YK3LP-qe-twEnv.js → diagram-OA4YK3LP-CjwqqLKz.js} +1 -1
  303. package/ui-dist/assets/{diagram-WEI45ONY-D8ufoJVE.js → diagram-WEI45ONY-2IWfCqZb.js} +1 -1
  304. package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-BXXAFqU6.js → ebnfDiagram-CCIWWBDH-DVGZkgjy.js} +1 -1
  305. package/ui-dist/assets/{erDiagram-Q63AITRT-uXmIG2c_.js → erDiagram-Q63AITRT-C_-u3Gmw.js} +1 -1
  306. package/ui-dist/assets/{flowDiagram-23GEKE2U-3eiT6gWx.js → flowDiagram-23GEKE2U-BvGg0NCq.js} +4 -4
  307. package/ui-dist/assets/{ganttDiagram-NO4QXBWP-CiVmqV02.js → ganttDiagram-NO4QXBWP-U3CZUUUR.js} +1 -1
  308. package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-DmIrlFHc.js → gitGraphDiagram-IHSO6WYX-CIWuEBIo.js} +1 -1
  309. package/ui-dist/assets/{graph-BpS6eOIF.js → graph-D3P5q-7m.js} +1 -1
  310. package/ui-dist/assets/index-B1rLBtZ1.js +1875 -0
  311. package/ui-dist/assets/{index-Dlx6uy7_.js → index-BAMXpiI5.js} +1 -1
  312. package/ui-dist/assets/{index-CUHGsSRd.js → index-BAgtKYR1.js} +1 -1
  313. package/ui-dist/assets/{index--YRaLrzl.js → index-CBOr9F6w.js} +1 -1
  314. package/ui-dist/assets/{index-cHC60zXl.js → index-CbHqnWUe.js} +1 -1
  315. package/ui-dist/assets/{index-DeWKDYpk.js → index-CjztBLJi.js} +1 -1
  316. package/ui-dist/assets/{index-T2PpfhXU.js → index-Cu1iMhjl.js} +1 -1
  317. package/ui-dist/assets/{index-Dgj1-Gzi.js → index-D7ycf1qU.js} +1 -1
  318. package/ui-dist/assets/{index-Dpvu2aoc.js → index-DAYlwxsg.js} +1 -1
  319. package/ui-dist/assets/{index-BAU4CU-l.js → index-DCFf9dps.js} +4 -4
  320. package/ui-dist/assets/{index-CWaZ_rS8.js → index-DOPIV8vd.js} +1 -1
  321. package/ui-dist/assets/{index-C-TZf854.js → index-DRxLJD40.js} +1 -1
  322. package/ui-dist/assets/{index-CUI9Uyvz.js → index-DYMtCDKT.js} +1 -1
  323. package/ui-dist/assets/index-DekHKOsL.css +1 -0
  324. package/ui-dist/assets/{index-BncN7e-4.js → index-DidCCw78.js} +1 -1
  325. package/ui-dist/assets/{index-Cl27pPic.js → index-Ds_qma4-.js} +1 -1
  326. package/ui-dist/assets/{index-CF3Fjm4r.js → index-HkQRx1D6.js} +1 -1
  327. package/ui-dist/assets/{index-Cp12taja.js → index-ikpL--zj.js} +1 -1
  328. package/ui-dist/assets/{index-BzDB5XYN.js → index-mnl55Stn.js} +1 -1
  329. package/ui-dist/assets/{infoDiagram-FWYZ7A6U-B_e34a6A.js → infoDiagram-FWYZ7A6U-Cx8Fa-I4.js} +1 -1
  330. package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-C_h8nqRS.js → ishikawaDiagram-FXEZZL3T-Cmuz1QUN.js} +1 -1
  331. package/ui-dist/assets/{journeyDiagram-5HDEW3XC-CrxAvEMf.js → journeyDiagram-5HDEW3XC-CJgkiVXG.js} +1 -1
  332. package/ui-dist/assets/{kanban-definition-HUTT4EX6-Zp6LAKss.js → kanban-definition-HUTT4EX6-RAWpefOB.js} +1 -1
  333. package/ui-dist/assets/layout-DyWQv0Rr.js +1 -0
  334. package/ui-dist/assets/{linear-_N4Odhfh.js → linear-D5pdgIf9.js} +1 -1
  335. package/ui-dist/assets/{map-CYGuJtD3.js → map-bVSzNLl2.js} +1 -1
  336. package/ui-dist/assets/mermaid.core-CeaXGD6B.js +312 -0
  337. package/ui-dist/assets/{mindmap-definition-LN4V7U3C-C-J9N_o_.js → mindmap-definition-LN4V7U3C-B8B8AX5C.js} +1 -1
  338. package/ui-dist/assets/{pegDiagram-2B236MQR-B9Mlsk91.js → pegDiagram-2B236MQR-C4Sv-ua6.js} +1 -1
  339. package/ui-dist/assets/{pieDiagram-ENE6RG2P-BY7DU2f8.js → pieDiagram-ENE6RG2P-CLARlOHx.js} +1 -1
  340. package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-CdCl_yc0.js → quadrantDiagram-ABIIQ3AL-DPCXQmeT.js} +1 -1
  341. package/ui-dist/assets/{railroadDiagram-RFXS5EU6-C5w2LKAD.js → railroadDiagram-RFXS5EU6-BpqRuKUQ.js} +1 -1
  342. package/ui-dist/assets/{requirementDiagram-TGXJPOKE-fRb_n-yH.js → requirementDiagram-TGXJPOKE-Dd-h62HZ.js} +1 -1
  343. package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-CYjb1HUH.js → sankeyDiagram-HTMAVEWB-DylT_pqq.js} +1 -1
  344. package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-CS95ySsI.js → sequenceDiagram-DBY2YBRQ-RiCF1REj.js} +1 -1
  345. package/ui-dist/assets/{sizeCapture-X5ZJPWSS-DPXTC0TI.js → sizeCapture-X5ZJPWSS-DXW4JQz2.js} +1 -1
  346. package/ui-dist/assets/{stateDiagram-2N3HPSRC-C4VFIMBR.js → stateDiagram-2N3HPSRC-6U3ESIGT.js} +1 -1
  347. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-KQTrcZvp.js +1 -0
  348. package/ui-dist/assets/{swimlanes-5IMT3BWC-UvxkQ8RD.js → swimlanes-5IMT3BWC-CeNHVNCi.js} +2 -2
  349. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-CcxS1c6r.js +8 -0
  350. package/ui-dist/assets/{timeline-definition-FHXFAJF6-BKotSwXW.js → timeline-definition-FHXFAJF6-Vlwoe_1b.js} +1 -1
  351. package/ui-dist/assets/{vennDiagram-L72KCM5P-TmXc-aFs.js → vennDiagram-L72KCM5P-DBP7D3HE.js} +6 -6
  352. package/ui-dist/assets/{wardleyDiagram-EHGQE667-aTINQKt9.js → wardleyDiagram-EHGQE667-DG-wzqpy.js} +1 -1
  353. package/ui-dist/assets/{xychartDiagram-FW5EYKEG-CZ86hWNQ.js → xychartDiagram-FW5EYKEG-BAq3mbha.js} +1 -1
  354. package/ui-dist/index.html +2 -2
  355. package/resources/bundled-skills/rudder/SKILL.md +0 -314
  356. package/skills/rudder/SKILL.md +0 -314
  357. package/ui-dist/assets/channel-roHkdL27.js +0 -1
  358. package/ui-dist/assets/classDiagram-OUVF2IWQ-CKZLREY1.js +0 -1
  359. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CKZLREY1.js +0 -1
  360. package/ui-dist/assets/index-BTW19O7e.js +0 -1808
  361. package/ui-dist/assets/index-DOlmbVZk.css +0 -1
  362. package/ui-dist/assets/layout-DlHAdVX4.js +0 -1
  363. package/ui-dist/assets/mermaid.core-B8dXcSSK.js +0 -314
  364. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-CF5IY4p0.js +0 -1
  365. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BVLEg2fG.js +0 -8
@@ -1,17 +1,45 @@
1
- import { addChatMessageSchema, convertChatToIssueSchema, createChatAttachmentMetadataSchema, createChatContextLinkSchema, resolveChatOperationProposalSchema, setChatProjectContextSchema, updateChatConversationUserStateSchema } from "@rudderhq/shared";
1
+ import { addChatMessageSchema, chatClientCheckpointSchema, convertChatToIssueSchema, createChatAttachmentMetadataSchema, createChatContextLinkSchema, resolveChatOperationProposalSchema, setChatProjectContextSchema, stopChatGenerationSchema, updateChatConversationUserStateSchema } from "@rudderhq/shared";
2
2
  import multer from "multer";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { isAllowedContentType, MAX_ATTACHMENT_BYTES } from "../attachment-types.js";
5
+ import { conflict } from "../errors.js";
5
6
  import { logger } from "../middleware/logger.js";
6
7
  import { validate } from "../middleware/validate.js";
8
+ import { createAssistantTextAccumulator } from "../services/chat-assistant.helpers.js";
7
9
  import { CHAT_ASSISTANT_USER_ERROR_MESSAGE, ChatAssistantStreamError, userVisiblePartialBodyFromError } from "../services/chat-assistant.js";
8
- import { cancelActiveChatGeneration, claimChatGeneration, getActiveChatGeneration, setActiveChatGenerationId, } from "../services/chat-generation-locks.js";
10
+ import { cancelActiveChatGeneration, claimChatGeneration, createChatRuntimeControlCoordinator, getActiveChatGeneration, setActiveChatGenerationId, } from "../services/chat-generation-locks.js";
11
+ import { hashChatGenerationBody } from "../services/chat-generation-protocol.js";
9
12
  import { logActivity } from "../services/index.js";
10
13
  import { assertCompanyAccess, getActorInfo } from "./authz.js";
11
14
  import { wakeIssueAssigneeAfterChatConversion } from "./chat-issue-assignment-wakeup.js";
15
+ const startingChatGenerationGates = new Map();
16
+ function createStartingChatGenerationGate() {
17
+ let resolveGeneration;
18
+ let resolveStopApplied;
19
+ return {
20
+ generationReady: new Promise((resolve) => {
21
+ resolveGeneration = resolve;
22
+ }),
23
+ stopApplied: new Promise((resolve) => {
24
+ resolveStopApplied = resolve;
25
+ }),
26
+ stopRequested: false,
27
+ resolveGeneration,
28
+ resolveStopApplied,
29
+ };
30
+ }
31
+ function outputAdmissionClosed(error) {
32
+ return Boolean(error
33
+ && typeof error === "object"
34
+ && "status" in error
35
+ && Number(error.status) === 409
36
+ && "message" in error
37
+ && error.message === "Chat-visible output admission is closed for this generation");
38
+ }
12
39
  export function registerChatStreamRoutes(ctx) {
13
40
  const CHAT_ASSISTANT_RECOVERABLE_FAILURE_FALLBACK_MESSAGE = "The assistant reply could not be completed. Rudder saved this attempt for diagnostics; retry when ready.";
14
- const { router, db, storage, svc, assistantSvc, agentsSvc, issuesSvc, projectsSvc, goalsSvc, access, operatorProfiles, heartbeat, assertConversationAccess, assertChatLocalMutationAllowed, boardUserId, assertCanAssignTasks, runSingleFileUpload, runMessageFileUpload, isMultipartRequest, uploadedMessageFiles, validateUploadedMessageFiles, logChatMessagesAdded, assertContextLinksBelongToCompany, turnContextFromUserMessage, addUserMessage, startChatTitleGeneration, attachFilesToUserMessage, loadAssistantInput, chatReplyingAgentId, assertCanConvertIssueProposal, persistAssistantReply, linkChatRunMessages, attachGeneratedFilesToPartialMessage, persistPartialAssistantMessage, recoverableFailurePayload, recoverableFailureBody, writeStreamEvent, } = ctx;
41
+ const CHAT_ASSISTANT_STOPPED_FALLBACK_MESSAGE = "Chat run stopped before a final reply. Continue the conversation to resume from the preserved context.";
42
+ const { router, db, storage, svc, assistantSvc, agentsSvc, issuesSvc, projectsSvc, goalsSvc, access, operatorProfiles, heartbeat, assertConversationAccess, assertChatLocalMutationAllowed, assertSideChatMutationAllowed, touchSideChat, boardUserId, assertCanAssignTasks, runSingleFileUpload, runMessageFileUpload, isMultipartRequest, uploadedMessageFiles, validateUploadedMessageFiles, logChatMessagesAdded, assertContextLinksBelongToCompany, turnContextFromUserMessage, addUserMessage, startChatTitleGeneration, attachFilesToUserMessage, loadAssistantInput, chatReplyingAgentId, assertCanConvertIssueProposal, persistAssistantReply, linkChatRunMessages, attachGeneratedFilesToPartialMessage, persistPartialAssistantMessage, recoverableFailurePayload, recoverableFailureBody, writeStreamEvent, queueRequestActor, wakeServerQueue, wakeTerminalProjector, } = ctx;
15
43
  router.post("/chats/:id/messages/stream", async (req, res) => {
16
44
  if (isMultipartRequest(req)) {
17
45
  try {
@@ -46,6 +74,7 @@ export function registerChatStreamRoutes(ctx) {
46
74
  return;
47
75
  }
48
76
  assertChatLocalMutationAllowed(conversation);
77
+ await assertSideChatMutationAllowed(req, conversation);
49
78
  const actor = getActorInfo(req);
50
79
  if (actor.actorType === "agent") {
51
80
  if (parsedBody.data.editUserMessageId) {
@@ -77,6 +106,7 @@ export function registerChatStreamRoutes(ctx) {
77
106
  conversationId: conversation.id,
78
107
  clientMutationId: `stream:${randomUUID()}`,
79
108
  expectedGenerationId: getActiveChatGeneration(conversation.id)?.generationId ?? null,
109
+ requestActor: queueRequestActor(req),
80
110
  payload: {
81
111
  body: parsedBody.data.body,
82
112
  attachmentIds: [],
@@ -98,6 +128,8 @@ export function registerChatStreamRoutes(ctx) {
98
128
  res.end();
99
129
  return;
100
130
  }
131
+ const startupGate = createStartingChatGenerationGate();
132
+ startingChatGenerationGates.set(conversation.id, startupGate);
101
133
  if (queuedMessageId) {
102
134
  try {
103
135
  await svc.assertQueuedMessageClaimedForDelivery({
@@ -107,6 +139,8 @@ export function registerChatStreamRoutes(ctx) {
107
139
  });
108
140
  }
109
141
  catch (error) {
142
+ startupGate.resolveGeneration(null);
143
+ startingChatGenerationGates.delete(conversation.id);
110
144
  releaseGeneration();
111
145
  throw error;
112
146
  }
@@ -116,52 +150,116 @@ export function registerChatStreamRoutes(ctx) {
116
150
  const createdGeneration = await svc.createGeneration(conversation.orgId, conversation.id);
117
151
  generation = createdGeneration;
118
152
  setActiveChatGenerationId(conversation.id, createdGeneration.id);
153
+ startupGate.resolveGeneration(createdGeneration.id);
119
154
  }
120
155
  catch (error) {
156
+ startupGate.resolveGeneration(null);
157
+ startingChatGenerationGates.delete(conversation.id);
121
158
  releaseGeneration();
122
159
  throw error;
123
160
  }
161
+ if (abortController.signal.aborted && startupGate.stopRequested) {
162
+ await startupGate.stopApplied;
163
+ }
124
164
  let assistantConversationForPartial = null;
125
165
  let turnContextForPartial = null;
126
166
  const transcript = [];
127
- let assistantProgressMessage = null;
128
167
  let assistantProgressMessageId = null;
129
168
  let activeChatRunId = null;
130
169
  let generationTerminalStatus = "failed";
131
- let assistantDraftBody = "";
132
- const persistStreamProgress = async (progressConversation, replyingAgentId = chatReplyingAgentId(progressConversation)) => {
133
- if (!turnContextForPartial)
134
- return null;
135
- const input = {
136
- kind: "message",
137
- status: "streaming",
138
- body: assistantDraftBody,
139
- transcript,
140
- runId: activeChatRunId ?? undefined,
141
- replyingAgentId,
170
+ let admittedAssistantBody = "";
171
+ let stopCutoff = null;
172
+ let outputAdmissionTail = Promise.resolve();
173
+ const serializeOutputAdmission = (operation) => {
174
+ const result = outputAdmissionTail.then(operation, operation);
175
+ outputAdmissionTail = result.then(() => undefined, () => undefined);
176
+ return result;
177
+ };
178
+ const freezeStopCutoff = () => {
179
+ if (stopCutoff)
180
+ return;
181
+ stopCutoff = {
182
+ body: admittedAssistantBody,
183
+ transcript: [...transcript],
142
184
  };
143
- if (assistantProgressMessage) {
144
- const updated = await svc.updateMessage(progressConversation.id, assistantProgressMessage.id, input);
145
- if (updated) {
146
- assistantProgressMessage = updated;
147
- assistantProgressMessageId = assistantProgressMessage.id;
148
- return assistantProgressMessage;
185
+ };
186
+ abortController.signal.addEventListener("abort", freezeStopCutoff, { once: true });
187
+ const stoppedState = (fallbackBody) => {
188
+ if (!stopCutoff) {
189
+ return {
190
+ body: admittedAssistantBody.trim() ? admittedAssistantBody : fallbackBody,
191
+ transcript: [...transcript],
192
+ };
193
+ }
194
+ const accumulator = createAssistantTextAccumulator();
195
+ for (const entry of stopCutoff.transcript) {
196
+ if (entry.kind === "assistant") {
197
+ accumulator.push(entry.text, entry.delta === true);
149
198
  }
150
199
  }
151
- assistantProgressMessage = await svc.addMessage(progressConversation.id, {
152
- orgId: progressConversation.orgId,
153
- role: "assistant",
154
- kind: "message",
155
- status: "streaming",
156
- body: assistantDraftBody,
157
- transcript,
158
- runId: activeChatRunId ?? null,
159
- replyingAgentId,
160
- chatTurnId: turnContextForPartial.chatTurnId,
161
- turnVariant: turnContextForPartial.turnVariant,
162
- });
163
- assistantProgressMessageId = assistantProgressMessage.id;
164
- return assistantProgressMessage;
200
+ return {
201
+ body: stopCutoff.body.trim() ? stopCutoff.body : accumulator.fullText,
202
+ transcript: stopCutoff.transcript,
203
+ };
204
+ };
205
+ let stoppedPersistencePromise = null;
206
+ const persistStoppedAssistant = (stoppedConversation, replyingAgentId, fallbackBody) => {
207
+ if (stoppedPersistencePromise)
208
+ return stoppedPersistencePromise;
209
+ generationTerminalStatus = "stopped";
210
+ stoppedPersistencePromise = (async () => {
211
+ await outputAdmissionTail;
212
+ let frozen = stoppedState(fallbackBody);
213
+ if (generation) {
214
+ const durableFrozen = await svc.generationProtocol.getFrozenVisibleProjection({
215
+ orgId: conversation.orgId,
216
+ conversationId: conversation.id,
217
+ generationId: generation.id,
218
+ }).catch(() => null);
219
+ if (durableFrozen && durableFrozen.generation.acceptedThroughSeq !== null) {
220
+ frozen = {
221
+ body: durableFrozen.projection.body,
222
+ transcript: durableFrozen.projection.transcript,
223
+ };
224
+ }
225
+ }
226
+ const stoppedBody = frozen.body.trim()
227
+ ? frozen.body
228
+ : (assistantProgressMessageId ? CHAT_ASSISTANT_STOPPED_FALLBACK_MESSAGE : "");
229
+ let stoppedMessage = null;
230
+ let lastProjectionError;
231
+ for (let attempt = 1; attempt <= 3; attempt += 1) {
232
+ try {
233
+ stoppedMessage = await persistPartialAssistantMessage(stoppedConversation, stoppedBody, "stopped", turnContextForPartial, frozen.transcript, replyingAgentId, assistantProgressMessageId, activeChatRunId);
234
+ lastProjectionError = undefined;
235
+ break;
236
+ }
237
+ catch (error) {
238
+ lastProjectionError = error;
239
+ logger.warn({ err: error, conversationId: stoppedConversation.id, attempt }, "failed to project stopped chat assistant message");
240
+ await Promise.resolve();
241
+ }
242
+ }
243
+ if (lastProjectionError)
244
+ throw lastProjectionError;
245
+ await linkChatRunMessages(stoppedConversation, activeChatRunId, stoppedMessage ? [stoppedMessage] : []);
246
+ if (stoppedMessage) {
247
+ await logChatMessagesAdded(stoppedConversation, [stoppedMessage], {
248
+ actorType: "system",
249
+ actorId: "chat-assistant",
250
+ agentId: replyingAgentId,
251
+ });
252
+ }
253
+ if (!clientClosed) {
254
+ writeStreamEvent(res, {
255
+ type: "final",
256
+ messages: stoppedMessage ? [stoppedMessage] : [],
257
+ });
258
+ res.end();
259
+ }
260
+ return stoppedMessage;
261
+ })();
262
+ return stoppedPersistencePromise;
165
263
  };
166
264
  let clientClosed = false;
167
265
  const handleClosed = () => {
@@ -178,6 +276,7 @@ export function registerChatStreamRoutes(ctx) {
178
276
  res.flushHeaders();
179
277
  try {
180
278
  const userMessage = await addUserMessage(conversation, parsedBody.data.body, actor, parsedBody.data.editUserMessageId ?? null);
279
+ await touchSideChat(req, conversation);
181
280
  if (queuedMessageId) {
182
281
  await svc.markQueuedMessageRunning({
183
282
  conversationId: conversation.id,
@@ -205,7 +304,19 @@ export function registerChatStreamRoutes(ctx) {
205
304
  writeStreamEvent(res, {
206
305
  type: "ack",
207
306
  userMessage: hydratedUserMessage,
307
+ generationId: generation.id,
308
+ attemptEpoch: generation.attemptEpoch ?? 1,
309
+ generationSeq: 0,
310
+ bodyHash: hashChatGenerationBody(""),
208
311
  });
312
+ if (abortController.signal.aborted) {
313
+ generationTerminalStatus = "stopped";
314
+ if (!clientClosed) {
315
+ writeStreamEvent(res, { type: "final", messages: [] });
316
+ res.end();
317
+ }
318
+ return;
319
+ }
209
320
  {
210
321
  const assistantInput = await loadAssistantInput(conversation, actor);
211
322
  assistantConversationForPartial = assistantInput.conversation;
@@ -220,54 +331,181 @@ export function registerChatStreamRoutes(ctx) {
220
331
  activeChatRunId = runId;
221
332
  },
222
333
  abortSignal: abortController.signal,
223
- onAssistantDelta: async (delta) => {
224
- assistantDraftBody = `${assistantDraftBody}${delta}`;
225
- await persistStreamProgress(assistantInput.conversation);
226
- if (clientClosed)
334
+ controlCoordinator: createChatRuntimeControlCoordinator(conversation.id, generation.id, {
335
+ onAttemptStarted: async ({ generationId, attemptEpoch, ownerToken, attempt }) => {
336
+ await svc.beginGenerationControlAttempt({
337
+ orgId: conversation.orgId,
338
+ conversationId: conversation.id,
339
+ generationId,
340
+ attemptEpoch,
341
+ ownerToken,
342
+ runtimeType: attempt.runtimeType,
343
+ });
344
+ },
345
+ onHandleRegistered: async ({ generationId, attemptEpoch, ownerToken, handle }) => {
346
+ await svc.markGenerationControlReady({
347
+ generationId,
348
+ attemptEpoch,
349
+ ownerToken,
350
+ runtimeType: handle.runtimeType,
351
+ providerThreadId: handle.providerThreadId ?? null,
352
+ providerTurnId: handle.providerTurnId ?? null,
353
+ });
354
+ },
355
+ onAttemptLeaseRenewed: async ({ generationId, attemptEpoch, ownerToken }) => {
356
+ await svc.renewGenerationControlLease({ generationId, attemptEpoch, ownerToken });
357
+ },
358
+ onAttemptCompleted: async ({ generationId, attemptEpoch, ownerToken }) => {
359
+ await svc.markGenerationControlAttemptCompleted({
360
+ generationId,
361
+ attemptEpoch,
362
+ ownerToken,
363
+ });
364
+ },
365
+ }),
366
+ onAssistantDelta: (delta) => serializeOutputAdmission(async () => {
367
+ if (abortController.signal.aborted)
368
+ return;
369
+ const activeControl = getActiveChatGeneration(conversation.id);
370
+ const attemptEpoch = Math.max(1, activeControl?.attemptEpoch ?? generation?.attemptEpoch ?? 1);
371
+ const projectedBody = `${admittedAssistantBody}${delta}`;
372
+ let committed;
373
+ try {
374
+ committed = await svc.generationProtocol.appendVisibleEventAndProject({
375
+ orgId: conversation.orgId,
376
+ conversationId: conversation.id,
377
+ generationId: generation.id,
378
+ expectedAttemptEpoch: attemptEpoch,
379
+ eventKind: "assistant_delta",
380
+ payload: { delta },
381
+ bodyOffset: admittedAssistantBody.length,
382
+ bodyLength: delta.length,
383
+ messageId: assistantProgressMessageId,
384
+ runId: activeChatRunId,
385
+ bodyHash: hashChatGenerationBody(projectedBody),
386
+ body: projectedBody,
387
+ transcript: [...transcript],
388
+ replyingAgentId: chatReplyingAgentId(assistantInput.conversation),
389
+ chatTurnId: turnContextForPartial.chatTurnId,
390
+ turnVariant: turnContextForPartial.turnVariant,
391
+ });
392
+ }
393
+ catch (error) {
394
+ if (outputAdmissionClosed(error))
395
+ return;
396
+ throw error;
397
+ }
398
+ assistantProgressMessageId = committed.message.id;
399
+ admittedAssistantBody = projectedBody;
400
+ if (abortController.signal.aborted || clientClosed)
227
401
  return;
228
402
  writeStreamEvent(res, {
229
403
  type: "assistant_delta",
230
404
  delta,
405
+ generationId: generation.id,
406
+ attemptEpoch,
407
+ generationSeq: committed.event.generationSeq,
408
+ bodyHash: committed.event.payload.bodyHash,
231
409
  });
232
- },
233
- onAssistantState: async (state) => {
234
- await persistStreamProgress(assistantInput.conversation);
410
+ }),
411
+ onAssistantState: (state) => serializeOutputAdmission(async () => {
412
+ if (abortController.signal.aborted)
413
+ return;
235
414
  if (clientClosed)
236
415
  return;
237
416
  writeStreamEvent(res, {
238
417
  type: "assistant_state",
239
418
  state,
240
419
  });
241
- },
242
- onTranscriptEntry: async (entry) => {
420
+ }),
421
+ onTranscriptEntry: (entry) => serializeOutputAdmission(async () => {
422
+ if (abortController.signal.aborted)
423
+ return;
424
+ const activeControl = getActiveChatGeneration(conversation.id);
425
+ const attemptEpoch = Math.max(1, activeControl?.attemptEpoch ?? generation?.attemptEpoch ?? 1);
426
+ const projectedTranscript = [...transcript, entry];
427
+ let committed;
428
+ try {
429
+ committed = await svc.generationProtocol.appendVisibleEventAndProject({
430
+ orgId: conversation.orgId,
431
+ conversationId: conversation.id,
432
+ generationId: generation.id,
433
+ expectedAttemptEpoch: attemptEpoch,
434
+ eventKind: "transcript",
435
+ payload: { entry },
436
+ messageId: assistantProgressMessageId,
437
+ runId: activeChatRunId,
438
+ bodyHash: hashChatGenerationBody(admittedAssistantBody),
439
+ body: admittedAssistantBody,
440
+ transcript: projectedTranscript,
441
+ replyingAgentId: chatReplyingAgentId(assistantInput.conversation),
442
+ chatTurnId: turnContextForPartial.chatTurnId,
443
+ turnVariant: turnContextForPartial.turnVariant,
444
+ });
445
+ }
446
+ catch (error) {
447
+ if (outputAdmissionClosed(error))
448
+ return;
449
+ throw error;
450
+ }
451
+ assistantProgressMessageId = committed.message.id;
243
452
  transcript.push(entry);
244
- await persistStreamProgress(assistantInput.conversation);
245
- if (clientClosed)
453
+ if (abortController.signal.aborted || clientClosed)
246
454
  return;
247
455
  writeStreamEvent(res, {
248
456
  type: "transcript_entry",
249
457
  entry,
458
+ generationId: generation.id,
459
+ attemptEpoch,
460
+ generationSeq: committed.event.generationSeq,
461
+ bodyHash: committed.event.payload.bodyHash,
250
462
  });
251
- },
463
+ }),
252
464
  });
253
- if (streamed.outcome === "stopped") {
254
- generationTerminalStatus = "stopped";
255
- const stoppedMessage = await persistPartialAssistantMessage(assistantInput.conversation, streamed.partialBody, "stopped", turnContextForPartial, transcript, streamed.replyingAgentId, assistantProgressMessageId, activeChatRunId);
256
- await linkChatRunMessages(assistantInput.conversation, activeChatRunId, stoppedMessage ? [stoppedMessage] : []);
257
- if (stoppedMessage) {
258
- await logChatMessagesAdded(assistantInput.conversation, [stoppedMessage], {
259
- actorType: "system",
260
- actorId: "chat-assistant",
261
- agentId: streamed.replyingAgentId,
465
+ if (abortController.signal.aborted || streamed.outcome === "stopped") {
466
+ await persistStoppedAssistant(assistantInput.conversation, streamed.replyingAgentId, streamed.partialBody);
467
+ return;
468
+ }
469
+ const resultAdmission = await serializeOutputAdmission(async () => {
470
+ if (abortController.signal.aborted)
471
+ return null;
472
+ const activeControl = getActiveChatGeneration(conversation.id);
473
+ const attemptEpoch = Math.max(1, activeControl?.attemptEpoch ?? generation?.attemptEpoch ?? 1);
474
+ try {
475
+ const committed = await svc.generationProtocol.appendVisibleEventAndProject({
476
+ orgId: conversation.orgId,
477
+ conversationId: conversation.id,
478
+ generationId: generation.id,
479
+ expectedAttemptEpoch: attemptEpoch,
480
+ eventKind: "runtime_output",
481
+ payload: {
482
+ resultKind: streamed.reply.kind,
483
+ body: streamed.reply.body,
484
+ },
485
+ bodyOffset: 0,
486
+ bodyLength: streamed.reply.body.length,
487
+ messageId: assistantProgressMessageId,
488
+ runId: activeChatRunId,
489
+ bodyHash: hashChatGenerationBody(streamed.reply.body),
490
+ body: streamed.reply.body,
491
+ transcript: [...transcript],
492
+ replyingAgentId: streamed.replyingAgentId,
493
+ chatTurnId: turnContextForPartial.chatTurnId,
494
+ turnVariant: turnContextForPartial.turnVariant,
262
495
  });
496
+ assistantProgressMessageId = committed.message.id;
497
+ admittedAssistantBody = streamed.reply.body;
498
+ return committed;
263
499
  }
264
- if (!clientClosed) {
265
- writeStreamEvent(res, {
266
- type: "final",
267
- messages: stoppedMessage ? [stoppedMessage] : [],
268
- });
269
- res.end();
500
+ catch (error) {
501
+ if (outputAdmissionClosed(error))
502
+ return null;
503
+ throw error;
270
504
  }
505
+ });
506
+ if (!resultAdmission) {
507
+ freezeStopCutoff();
508
+ await persistStoppedAssistant(assistantInput.conversation, streamed.replyingAgentId, streamed.partialBody);
271
509
  return;
272
510
  }
273
511
  const createdMessages = await persistAssistantReply(req, assistantInput.conversation, actor, streamed.reply, turnContextForPartial, transcript, streamed.replyingAgentId, assistantProgressMessageId, activeChatRunId);
@@ -287,12 +525,30 @@ export function registerChatStreamRoutes(ctx) {
287
525
  }
288
526
  }
289
527
  catch (error) {
290
- generationTerminalStatus = "failed";
528
+ if (!abortController.signal.aborted) {
529
+ generationTerminalStatus = "failed";
530
+ }
291
531
  throw error;
292
532
  }
293
533
  }
294
534
  }
295
535
  catch (err) {
536
+ if (abortController.signal.aborted) {
537
+ try {
538
+ if (stoppedPersistencePromise) {
539
+ await stoppedPersistencePromise;
540
+ }
541
+ else {
542
+ await persistStoppedAssistant(assistantConversationForPartial ?? conversation, chatReplyingAgentId(assistantConversationForPartial ?? conversation), "");
543
+ }
544
+ }
545
+ catch (stopPersistenceError) {
546
+ logger.warn({ err: stopPersistenceError, conversationId: conversation.id }, "failed to persist stopped chat assistant message");
547
+ if (!clientClosed && !res.writableEnded)
548
+ res.end();
549
+ }
550
+ return;
551
+ }
296
552
  const failurePayload = recoverableFailurePayload(err, activeChatRunId);
297
553
  const partialBody = userVisiblePartialBodyFromError(err)
298
554
  || recoverableFailureBody(failurePayload)
@@ -323,11 +579,32 @@ export function registerChatStreamRoutes(ctx) {
323
579
  }
324
580
  }
325
581
  finally {
582
+ abortController.signal.removeEventListener("abort", freezeStopCutoff);
326
583
  req.off("aborted", handleClosed);
327
584
  res.off("close", handleClosed);
328
585
  if (generation) {
329
- await svc.markGenerationTerminal(generation.id, generationTerminalStatus).catch((error) => {
330
- logger.warn({ err: error, generationId: generation?.id }, "failed to mark chat generation terminal");
586
+ await (async () => {
587
+ const latestGeneration = await svc.getLatestGeneration(conversation.id);
588
+ const expectedAttemptEpoch = latestGeneration?.attemptEpoch
589
+ ?? generation?.attemptEpoch
590
+ ?? 1;
591
+ await svc.generationProtocol.recordRuntimeTerminal({
592
+ orgId: conversation.orgId,
593
+ conversationId: conversation.id,
594
+ generationId: generation.id,
595
+ expectedAttemptEpoch,
596
+ finalStatus: generationTerminalStatus,
597
+ terminalReason: generationTerminalStatus === "stopped"
598
+ ? "operator_stop"
599
+ : generationTerminalStatus,
600
+ payload: {
601
+ assistantMessageId: assistantProgressMessageId,
602
+ runId: activeChatRunId,
603
+ },
604
+ });
605
+ wakeTerminalProjector();
606
+ })().catch((error) => {
607
+ logger.warn({ err: error, generationId: generation?.id }, "failed to record chat generation terminal evidence");
331
608
  });
332
609
  }
333
610
  if (queuedMessageId) {
@@ -339,32 +616,225 @@ export function registerChatStreamRoutes(ctx) {
339
616
  logger.warn({ err: error, queuedMessageId }, "failed to mark queued chat message terminal");
340
617
  });
341
618
  }
619
+ if (startingChatGenerationGates.get(conversation.id) === startupGate) {
620
+ startingChatGenerationGates.delete(conversation.id);
621
+ }
342
622
  releaseGeneration();
623
+ wakeServerQueue();
343
624
  }
344
625
  });
626
+ router.post("/chats/:id/messages/stream/checkpoint", validate(chatClientCheckpointSchema), async (req, res) => {
627
+ const conversation = await assertConversationAccess(req, req.params.id);
628
+ if (!conversation) {
629
+ res.status(404).json({ error: "Chat conversation not found" });
630
+ return;
631
+ }
632
+ assertChatLocalMutationAllowed(conversation);
633
+ await assertSideChatMutationAllowed(req, conversation);
634
+ const checkpoint = await svc.generationProtocol.recordClientCheckpoint({
635
+ orgId: conversation.orgId,
636
+ conversationId: conversation.id,
637
+ generationId: req.body.generationId,
638
+ expectedAttemptEpoch: req.body.attemptEpoch,
639
+ generationSeq: req.body.generationSeq,
640
+ renderedBodyHash: req.body.renderedBodyHash,
641
+ });
642
+ res.json({
643
+ generationId: checkpoint.generation.id,
644
+ generationSeq: checkpoint.generation.lastClientCheckpointSeq,
645
+ advanced: checkpoint.advanced,
646
+ });
647
+ });
345
648
  router.post("/chats/:id/messages/stream/stop", async (req, res) => {
649
+ const parsed = stopChatGenerationSchema.safeParse(req.body ?? {});
650
+ if (!parsed.success) {
651
+ res.status(400).json({ error: "Invalid chat Stop request", details: parsed.error.issues });
652
+ return;
653
+ }
346
654
  const conversation = await assertConversationAccess(req, req.params.id);
347
655
  if (!conversation) {
348
656
  res.status(404).json({ error: "Chat conversation not found" });
349
657
  return;
350
658
  }
351
659
  assertChatLocalMutationAllowed(conversation);
352
- const active = getActiveChatGeneration(conversation.id);
353
- const latestActiveGeneration = active?.generationId
354
- ? null
355
- : await svc.getLatestActiveGeneration(conversation.id);
356
- const stopped = cancelActiveChatGeneration(conversation.id);
357
- const generationId = active?.generationId ?? latestActiveGeneration?.id ?? null;
358
- if (stopped || generationId) {
359
- await svc.markGenerationTerminal(generationId, "stopped");
360
- }
361
- res.json({ stopped: stopped || Boolean(generationId) });
660
+ await assertSideChatMutationAllowed(req, conversation);
661
+ const controlActionId = parsed.data.controlActionId ?? randomUUID();
662
+ const startupGate = startingChatGenerationGates.get(conversation.id) ?? null;
663
+ let startupStopRequested = false;
664
+ let startupInterruptRequested = false;
665
+ try {
666
+ let active = getActiveChatGeneration(conversation.id);
667
+ if (active && !active.generationId && startupGate) {
668
+ startupStopRequested = true;
669
+ startupGate.stopRequested = true;
670
+ startupInterruptRequested = cancelActiveChatGeneration(conversation.id);
671
+ const startupGenerationId = await startupGate.generationReady;
672
+ active = startupGenerationId ? getActiveChatGeneration(conversation.id) : null;
673
+ if (!startupGenerationId) {
674
+ res.json({
675
+ stopped: startupInterruptRequested,
676
+ controlActionId,
677
+ generationId: null,
678
+ disposition: startupInterruptRequested ? "startup_cancelled" : "interrupted_unverified",
679
+ });
680
+ return;
681
+ }
682
+ }
683
+ const latestActiveGeneration = active?.generationId
684
+ ? null
685
+ : await svc.getLatestActiveGeneration(conversation.id);
686
+ const generationId = parsed.data.expectedGenerationId
687
+ ?? active?.generationId
688
+ ?? latestActiveGeneration?.id
689
+ ?? null;
690
+ if (!generationId) {
691
+ res.json({
692
+ stopped: false,
693
+ controlActionId,
694
+ generationId: null,
695
+ disposition: "no_active_generation",
696
+ });
697
+ return;
698
+ }
699
+ let durableCheckpoint = await svc.generationProtocol.getLatestVisibleCheckpoint({
700
+ orgId: conversation.orgId,
701
+ conversationId: conversation.id,
702
+ generationId,
703
+ });
704
+ if (durableCheckpoint.generation.runtimeTerminalAt && !parsed.data.controlActionId) {
705
+ wakeTerminalProjector();
706
+ res.json({
707
+ stopped: false,
708
+ controlActionId,
709
+ generationId,
710
+ disposition: "no_active_generation",
711
+ });
712
+ return;
713
+ }
714
+ const expectedAttemptEpoch = parsed.data.expectedAttemptEpoch
715
+ ?? durableCheckpoint.generation.attemptEpoch;
716
+ const requestedRenderSeq = parsed.data.lastCommittedRenderSeq
717
+ ?? durableCheckpoint.generationSeq;
718
+ const requestedBodyHash = parsed.data.renderedBodyHash
719
+ ?? durableCheckpoint.bodyHash;
720
+ let stop = null;
721
+ for (let attempt = 0; attempt < 2 && !stop; attempt += 1) {
722
+ try {
723
+ stop = await svc.generationProtocol.beginStopAction({
724
+ orgId: conversation.orgId,
725
+ conversationId: conversation.id,
726
+ controlActionId,
727
+ expectedGenerationId: generationId,
728
+ expectedAttemptEpoch,
729
+ expectedControlVersion: parsed.data.expectedControlVersion
730
+ ?? durableCheckpoint.generation.controlVersion,
731
+ requestedRenderSeq,
732
+ requestedBodyHash,
733
+ });
734
+ }
735
+ catch (error) {
736
+ const status = error && typeof error === "object" && "status" in error
737
+ ? Number(error.status)
738
+ : null;
739
+ if (attempt > 0 || status !== 409)
740
+ throw error;
741
+ durableCheckpoint = await svc.generationProtocol.getLatestVisibleCheckpoint({
742
+ orgId: conversation.orgId,
743
+ conversationId: conversation.id,
744
+ generationId,
745
+ });
746
+ if (durableCheckpoint.generation.runtimeTerminalAt && !parsed.data.controlActionId) {
747
+ wakeTerminalProjector();
748
+ res.json({
749
+ stopped: false,
750
+ controlActionId,
751
+ generationId,
752
+ disposition: "no_active_generation",
753
+ });
754
+ return;
755
+ }
756
+ if (durableCheckpoint.generation.attemptEpoch !== expectedAttemptEpoch)
757
+ throw error;
758
+ }
759
+ }
760
+ if (!stop)
761
+ throw new Error("Failed to establish the chat Stop cutoff");
762
+ if (stop.idempotent
763
+ && parsed.data.expectedControlVersion !== undefined
764
+ && stop.action.expectedControlVersion !== parsed.data.expectedControlVersion) {
765
+ throw conflict("Control action id was already used for a different Stop request");
766
+ }
767
+ if (stop.outcome === "completion_committed") {
768
+ res.json({
769
+ stopped: false,
770
+ controlActionId,
771
+ generationId,
772
+ disposition: "completion_committed",
773
+ });
774
+ return;
775
+ }
776
+ if (stop.idempotent && stop.generation.runtimeTerminalAt) {
777
+ const terminalDisposition = stop.generation.status === "stopped"
778
+ || stop.action.localDisposition === "stopped"
779
+ ? "stopped"
780
+ : "stopping";
781
+ wakeTerminalProjector();
782
+ res.json({
783
+ stopped: true,
784
+ controlActionId,
785
+ generationId,
786
+ disposition: terminalDisposition,
787
+ acceptedThroughSeq: stop.action.acceptedThroughSeq,
788
+ frozenBodyHash: stop.action.frozenBodyHash,
789
+ });
790
+ return;
791
+ }
792
+ const localInterruptRequested = startupInterruptRequested || cancelActiveChatGeneration(conversation.id);
793
+ let disposition = "stopping";
794
+ if (startupStopRequested) {
795
+ await svc.generationProtocol.recordRuntimeTerminal({
796
+ orgId: conversation.orgId,
797
+ conversationId: conversation.id,
798
+ generationId,
799
+ expectedAttemptEpoch: stop.generation.attemptEpoch,
800
+ finalStatus: "stopped",
801
+ terminalReason: "operator_stop",
802
+ controlActionId,
803
+ });
804
+ wakeTerminalProjector();
805
+ }
806
+ else if (!localInterruptRequested) {
807
+ disposition = "interrupted_unverified";
808
+ await svc.generationProtocol.recordRuntimeTerminal({
809
+ orgId: conversation.orgId,
810
+ conversationId: conversation.id,
811
+ generationId,
812
+ expectedAttemptEpoch: stop.generation.attemptEpoch,
813
+ finalStatus: "interrupted_unverified",
814
+ terminalReason: "stop_without_local_runtime_owner",
815
+ controlActionId,
816
+ });
817
+ wakeTerminalProjector();
818
+ }
819
+ res.json({
820
+ stopped: Boolean(localInterruptRequested),
821
+ controlActionId,
822
+ generationId,
823
+ disposition,
824
+ acceptedThroughSeq: stop.action.acceptedThroughSeq,
825
+ frozenBodyHash: stop.action.frozenBodyHash,
826
+ });
827
+ }
828
+ finally {
829
+ if (startupStopRequested)
830
+ startupGate?.resolveStopApplied();
831
+ }
362
832
  });
363
833
  router.post("/orgs/:orgId/chats/:chatId/attachments", async (req, res) => {
364
834
  const orgId = req.params.orgId;
365
835
  const chatId = req.params.chatId;
366
836
  assertCompanyAccess(req, orgId);
367
- const conversation = await svc.getById(chatId);
837
+ const conversation = await assertConversationAccess(req, chatId);
368
838
  if (!conversation) {
369
839
  res.status(404).json({ error: "Chat conversation not found" });
370
840
  return;
@@ -374,6 +844,7 @@ export function registerChatStreamRoutes(ctx) {
374
844
  return;
375
845
  }
376
846
  assertChatLocalMutationAllowed(conversation);
847
+ await assertSideChatMutationAllowed(req, conversation);
377
848
  try {
378
849
  await runSingleFileUpload(req, res);
379
850
  }
@@ -453,6 +924,7 @@ export function registerChatStreamRoutes(ctx) {
453
924
  return;
454
925
  }
455
926
  assertChatLocalMutationAllowed(conversation);
927
+ await assertSideChatMutationAllowed(req, conversation);
456
928
  await assertContextLinksBelongToCompany(conversation.orgId, [req.body]);
457
929
  const linked = await svc.addContextLink(conversation.id, conversation.orgId, req.body);
458
930
  const actor = getActorInfo(req);
@@ -476,6 +948,7 @@ export function registerChatStreamRoutes(ctx) {
476
948
  return;
477
949
  }
478
950
  assertChatLocalMutationAllowed(conversation);
951
+ await assertSideChatMutationAllowed(req, conversation);
479
952
  const projectId = req.body.projectId ?? null;
480
953
  if (projectId) {
481
954
  await assertContextLinksBelongToCompany(conversation.orgId, [{
@@ -514,6 +987,7 @@ export function registerChatStreamRoutes(ctx) {
514
987
  return;
515
988
  }
516
989
  assertChatLocalMutationAllowed(conversation);
990
+ await assertSideChatMutationAllowed(req, conversation);
517
991
  const actor = getActorInfo(req);
518
992
  if (req.body.proposal?.goalId) {
519
993
  const goal = await goalsSvc.getById(req.body.proposal.goalId);
@@ -577,6 +1051,7 @@ export function registerChatStreamRoutes(ctx) {
577
1051
  return;
578
1052
  }
579
1053
  assertChatLocalMutationAllowed(conversation);
1054
+ await assertSideChatMutationAllowed(req, conversation);
580
1055
  const actor = getActorInfo(req);
581
1056
  const messageId = req.params.messageId;
582
1057
  const resolved = await svc.resolveOperationProposal(conversation.id, messageId, {
@@ -593,6 +1068,7 @@ export function registerChatStreamRoutes(ctx) {
593
1068
  return;
594
1069
  }
595
1070
  assertChatLocalMutationAllowed(conversation);
1071
+ await assertSideChatMutationAllowed(req, conversation);
596
1072
  const resolved = await svc.resolve(conversation.id);
597
1073
  const actor = getActorInfo(req);
598
1074
  await logActivity(db, {