@rudderhq/server 0.4.5 → 0.4.6-canary.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 (327) hide show
  1. package/dist/app.d.ts.map +1 -1
  2. package/dist/app.js +2 -0
  3. package/dist/app.js.map +1 -1
  4. package/dist/auth/better-auth.d.ts +15 -3
  5. package/dist/auth/better-auth.d.ts.map +1 -1
  6. package/dist/auth/better-auth.js.map +1 -1
  7. package/dist/bootstrap/plugin-host-runtime.d.ts +8 -8
  8. package/dist/bootstrap/register-api-routes.d.ts.map +1 -1
  9. package/dist/bootstrap/register-api-routes.js +2 -0
  10. package/dist/bootstrap/register-api-routes.js.map +1 -1
  11. package/dist/bundled-plugins/plugin-linear/dist/worker.js +27 -32
  12. package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +2 -2
  13. package/dist/bundled-plugins/plugin-linear/package.json +1 -1
  14. package/dist/config.d.ts +0 -8
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +1 -30
  17. package/dist/config.js.map +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +0 -18
  20. package/dist/index.js.map +1 -1
  21. package/dist/local-runtime.d.ts +0 -3
  22. package/dist/local-runtime.d.ts.map +1 -1
  23. package/dist/local-runtime.js +0 -34
  24. package/dist/local-runtime.js.map +1 -1
  25. package/dist/middleware/auth.d.ts.map +1 -1
  26. package/dist/middleware/auth.js +14 -2
  27. package/dist/middleware/auth.js.map +1 -1
  28. package/dist/onboarding-assets/ceo/SOUL.md +8 -5
  29. package/dist/routes/access-onboarding.helpers.d.ts.map +1 -1
  30. package/dist/routes/access-onboarding.helpers.js +2 -24
  31. package/dist/routes/access-onboarding.helpers.js.map +1 -1
  32. package/dist/routes/access.helpers.d.ts +1 -1
  33. package/dist/routes/approvals.d.ts.map +1 -1
  34. package/dist/routes/approvals.js +1 -89
  35. package/dist/routes/approvals.js.map +1 -1
  36. package/dist/routes/browser.d.ts +30 -0
  37. package/dist/routes/browser.d.ts.map +1 -0
  38. package/dist/routes/browser.js +263 -0
  39. package/dist/routes/browser.js.map +1 -0
  40. package/dist/routes/chats.d.ts.map +1 -1
  41. package/dist/routes/chats.js +13 -232
  42. package/dist/routes/chats.js.map +1 -1
  43. package/dist/routes/chats.stream-routes.d.ts.map +1 -1
  44. package/dist/routes/chats.stream-routes.js +46 -227
  45. package/dist/routes/chats.stream-routes.js.map +1 -1
  46. package/dist/routes/instance-settings.d.ts.map +1 -1
  47. package/dist/routes/instance-settings.js +26 -146
  48. package/dist/routes/instance-settings.js.map +1 -1
  49. package/dist/routes/onboarding.d.ts.map +1 -1
  50. package/dist/routes/onboarding.js +33 -31
  51. package/dist/routes/onboarding.js.map +1 -1
  52. package/dist/routes/plugin-ui-static.d.ts.map +1 -1
  53. package/dist/routes/plugin-ui-static.js +2 -4
  54. package/dist/routes/plugin-ui-static.js.map +1 -1
  55. package/dist/routes/plugins.d.ts.map +1 -1
  56. package/dist/routes/plugins.js +2 -4
  57. package/dist/routes/plugins.js.map +1 -1
  58. package/dist/services/access.d.ts +23 -23
  59. package/dist/services/activity-log.d.ts.map +1 -1
  60. package/dist/services/activity-log.js +2 -40
  61. package/dist/services/activity-log.js.map +1 -1
  62. package/dist/services/activity.d.ts +13 -13
  63. package/dist/services/agent-run-context.d.ts +2 -1
  64. package/dist/services/agent-run-context.d.ts.map +1 -1
  65. package/dist/services/agent-run-context.js +29 -4
  66. package/dist/services/agent-run-context.js.map +1 -1
  67. package/dist/services/agents.d.ts +36 -36
  68. package/dist/services/approvals.d.ts +18 -18
  69. package/dist/services/assets.d.ts +6 -6
  70. package/dist/services/automation-chat-output.d.ts +1 -1
  71. package/dist/services/automations.d.ts +37 -37
  72. package/dist/services/automations.d.ts.map +1 -1
  73. package/dist/services/automations.js +2 -6
  74. package/dist/services/automations.js.map +1 -1
  75. package/dist/services/board-auth.d.ts +38 -38
  76. package/dist/services/browser-broker.d.ts +43 -0
  77. package/dist/services/browser-broker.d.ts.map +1 -0
  78. package/dist/services/browser-broker.js +173 -0
  79. package/dist/services/browser-broker.js.map +1 -0
  80. package/dist/services/browser-broker.test.d.ts +2 -0
  81. package/dist/services/browser-broker.test.d.ts.map +1 -0
  82. package/dist/services/browser-broker.test.js +154 -0
  83. package/dist/services/browser-broker.test.js.map +1 -0
  84. package/dist/services/browser-capability.d.ts +20 -0
  85. package/dist/services/browser-capability.d.ts.map +1 -0
  86. package/dist/services/browser-capability.js +29 -0
  87. package/dist/services/browser-capability.js.map +1 -0
  88. package/dist/services/calendar.d.ts +34 -34
  89. package/dist/services/chat-agent-runs.d.ts.map +1 -1
  90. package/dist/services/chat-agent-runs.js +2 -4
  91. package/dist/services/chat-agent-runs.js.map +1 -1
  92. package/dist/services/chat-assistant.d.ts.map +1 -1
  93. package/dist/services/chat-assistant.js +6 -4
  94. package/dist/services/chat-assistant.js.map +1 -1
  95. package/dist/services/chat-assistant.runtime-batch.d.ts +3 -0
  96. package/dist/services/chat-assistant.runtime-batch.d.ts.map +1 -0
  97. package/dist/services/chat-assistant.runtime-batch.js +16 -0
  98. package/dist/services/chat-assistant.runtime-batch.js.map +1 -0
  99. package/dist/services/chat-work-manifest.d.ts +7 -0
  100. package/dist/services/chat-work-manifest.d.ts.map +1 -0
  101. package/dist/services/chat-work-manifest.js +235 -0
  102. package/dist/services/chat-work-manifest.js.map +1 -0
  103. package/dist/services/chats.d.ts +64 -64
  104. package/dist/services/chats.d.ts.map +1 -1
  105. package/dist/services/chats.js +2 -4
  106. package/dist/services/chats.js.map +1 -1
  107. package/dist/services/costs.d.ts +2 -2
  108. package/dist/services/costs.d.ts.map +1 -1
  109. package/dist/services/costs.js +0 -32
  110. package/dist/services/costs.js.map +1 -1
  111. package/dist/services/finance.d.ts +11 -11
  112. package/dist/services/goals.d.ts +20 -20
  113. package/dist/services/heartbeat.d.ts +1 -1
  114. package/dist/services/heartbeat.d.ts.map +1 -1
  115. package/dist/services/heartbeat.js +1 -1
  116. package/dist/services/heartbeat.js.map +1 -1
  117. package/dist/services/instance-settings.d.ts +3 -1
  118. package/dist/services/instance-settings.d.ts.map +1 -1
  119. package/dist/services/instance-settings.js +30 -1
  120. package/dist/services/instance-settings.js.map +1 -1
  121. package/dist/services/integrations/agent-integrations.d.ts +8 -8
  122. package/dist/services/integrations/custom-integrations.d.ts +3 -3
  123. package/dist/services/integrations/feishu/inbound-dispatcher-db.d.ts.map +1 -1
  124. package/dist/services/integrations/feishu/inbound-dispatcher-db.js +10 -11
  125. package/dist/services/integrations/feishu/inbound-dispatcher-db.js.map +1 -1
  126. package/dist/services/integrations/feishu/user-bindings.d.ts.map +1 -1
  127. package/dist/services/integrations/feishu/user-bindings.js +2 -4
  128. package/dist/services/integrations/feishu/user-bindings.js.map +1 -1
  129. package/dist/services/issue-approvals.d.ts +3 -3
  130. package/dist/services/issues.comments-attachments.d.ts +8 -8
  131. package/dist/services/issues.d.ts +19 -19
  132. package/dist/services/issues.helpers.d.ts.map +1 -1
  133. package/dist/services/issues.helpers.js +2 -6
  134. package/dist/services/issues.helpers.js.map +1 -1
  135. package/dist/services/knowledge-portability/organization-skills.d.ts +2 -1
  136. package/dist/services/knowledge-portability/organization-skills.d.ts.map +1 -1
  137. package/dist/services/knowledge-portability/organization-skills.js +16 -6
  138. package/dist/services/knowledge-portability/organization-skills.js.map +1 -1
  139. package/dist/services/messenger.d.ts +3 -3
  140. package/dist/services/messenger.d.ts.map +1 -1
  141. package/dist/services/messenger.js +3 -0
  142. package/dist/services/messenger.js.map +1 -1
  143. package/dist/services/organization-intelligence-profiles.d.ts.map +1 -1
  144. package/dist/services/organization-intelligence-profiles.js +2 -0
  145. package/dist/services/organization-intelligence-profiles.js.map +1 -1
  146. package/dist/services/orgs.d.ts +1 -1
  147. package/dist/services/orgs.d.ts.map +1 -1
  148. package/dist/services/orgs.js +2 -10
  149. package/dist/services/orgs.js.map +1 -1
  150. package/dist/services/plugin-job-scheduler.d.ts.map +1 -1
  151. package/dist/services/plugin-job-scheduler.js +20 -132
  152. package/dist/services/plugin-job-scheduler.js.map +1 -1
  153. package/dist/services/plugin-registry.d.ts +71 -71
  154. package/dist/services/plugin-registry.d.ts.map +1 -1
  155. package/dist/services/plugin-registry.js +2 -5
  156. package/dist/services/plugin-registry.js.map +1 -1
  157. package/dist/services/postgres-errors.d.ts +6 -0
  158. package/dist/services/postgres-errors.d.ts.map +1 -0
  159. package/dist/services/postgres-errors.js +30 -0
  160. package/dist/services/postgres-errors.js.map +1 -0
  161. package/dist/services/projects.d.ts +2 -2
  162. package/dist/services/run-intelligence.d.ts +0 -5
  163. package/dist/services/run-intelligence.d.ts.map +1 -1
  164. package/dist/services/run-intelligence.js +1 -11
  165. package/dist/services/run-intelligence.js.map +1 -1
  166. package/dist/services/runtime-kernel/heartbeat.core.d.ts +1 -34
  167. package/dist/services/runtime-kernel/heartbeat.core.d.ts.map +1 -1
  168. package/dist/services/runtime-kernel/heartbeat.core.js +0 -35
  169. package/dist/services/runtime-kernel/heartbeat.core.js.map +1 -1
  170. package/dist/services/runtime-kernel/heartbeat.d.ts +29 -29
  171. package/dist/services/runtime-kernel/heartbeat.d.ts.map +1 -1
  172. package/dist/services/runtime-kernel/heartbeat.execute.d.ts.map +1 -1
  173. package/dist/services/runtime-kernel/heartbeat.execute.js +849 -950
  174. package/dist/services/runtime-kernel/heartbeat.execute.js.map +1 -1
  175. package/dist/services/runtime-kernel/heartbeat.js +2 -119
  176. package/dist/services/runtime-kernel/heartbeat.js.map +1 -1
  177. package/dist/services/runtime-kernel/heartbeat.sessions.d.ts.map +1 -1
  178. package/dist/services/runtime-kernel/heartbeat.sessions.js +1 -1
  179. package/dist/services/runtime-kernel/heartbeat.sessions.js.map +1 -1
  180. package/dist/services/runtime-kernel/model-fallback.d.ts +2 -0
  181. package/dist/services/runtime-kernel/model-fallback.d.ts.map +1 -1
  182. package/dist/services/runtime-kernel/model-fallback.js +108 -9
  183. package/dist/services/runtime-kernel/model-fallback.js.map +1 -1
  184. package/dist/services/secrets.d.ts +20 -20
  185. package/dist/services/workspace-operations.d.ts.map +1 -1
  186. package/dist/services/workspace-operations.js +48 -74
  187. package/dist/services/workspace-operations.js.map +1 -1
  188. package/dist/services/workspace-runtime.services.d.ts +3 -3
  189. package/package.json +19 -23
  190. package/resources/bundled-skills/browser/SKILL.md +49 -0
  191. package/resources/bundled-skills/browser/agents/openai.yaml +4 -0
  192. package/resources/bundled-skills/browser/references/tool-contract.md +73 -0
  193. package/resources/bundled-skills/rudder/SKILL.md +5 -2
  194. package/resources/bundled-skills/rudder/references/cli-reference.md +17 -0
  195. package/skills/browser/SKILL.md +49 -0
  196. package/skills/browser/agents/openai.yaml +4 -0
  197. package/skills/browser/references/tool-contract.md +73 -0
  198. package/skills/rudder/SKILL.md +5 -2
  199. package/skills/rudder/references/cli-reference.md +17 -0
  200. package/ui-dist/assets/abnfDiagram-VRR7QNED-UdnRjOt5.js +1 -0
  201. package/ui-dist/assets/arc-DqWAOCPb.js +1 -0
  202. package/ui-dist/assets/architectureDiagram-ZJ3FMSHR-C0BVszD_.js +36 -0
  203. package/ui-dist/assets/blockDiagram-677ZJIJ3-jI1GYvsK.js +132 -0
  204. package/ui-dist/assets/c4Diagram-LMCZKHZV-BUskTH8O.js +10 -0
  205. package/ui-dist/assets/channel-DuVz3zrR.js +1 -0
  206. package/ui-dist/assets/{chunk-QZHKN3VN-CoUe43bE.js → chunk-2Q5K7J3B-DnXbkSRv.js} +1 -1
  207. package/ui-dist/assets/{chunk-JSJVCQXG-CGWgDKBb.js → chunk-32BRIVSS-CItDm5nZ.js} +1 -1
  208. package/ui-dist/assets/{chunk-FMBD7UC4-D_yZ_WmF.js → chunk-5VM5RSS4-DDWOtVg4.js} +1 -1
  209. package/ui-dist/assets/chunk-EX3LRPZG-3P2vrzg-.js +231 -0
  210. package/ui-dist/assets/{chunk-4BX2VUAB-Cd0jMFjT.js → chunk-JWPE2WC7-Cddilj_R.js} +1 -1
  211. package/ui-dist/assets/chunk-MOJQB5TN-lFfFNAzo.js +88 -0
  212. package/ui-dist/assets/chunk-RYQCIY6F-Bx6usdO8.js +1 -0
  213. package/ui-dist/assets/chunk-V7JOEXUC-DJJZibRk.js +206 -0
  214. package/ui-dist/assets/{chunk-KX2RTZJC-PgfQ6Dqz.js → chunk-VR4S4FIN-JsA7MsJ2.js} +1 -1
  215. package/ui-dist/assets/{chunk-55IACEB6-C-AmshGj.js → chunk-XXDRQBXY-ieRhxMcL.js} +1 -1
  216. package/ui-dist/assets/classDiagram-OUVF2IWQ-CPg_NswG.js +1 -0
  217. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CPg_NswG.js +1 -0
  218. package/ui-dist/assets/{cose-bilkent-S5V4N54A-jsoDVyK9.js → cose-bilkent-JH36ORCC-C8RKSRW3.js} +1 -1
  219. package/ui-dist/assets/cynefin-VYW2F7L2-BpLH3NYF.js +178 -0
  220. package/ui-dist/assets/cynefinDiagram-TSTJHNR4-BE910bVh.js +62 -0
  221. package/ui-dist/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  222. package/ui-dist/assets/dagre-VKFMJZFB-Y3oEC2I7.js +4 -0
  223. package/ui-dist/assets/diagram-FQU43EPY-CRR8acur.js +3 -0
  224. package/ui-dist/assets/diagram-G47NLZAW-CYMkvxPa.js +24 -0
  225. package/ui-dist/assets/diagram-NH7WQ7WH-5pDqjsg8.js +24 -0
  226. package/ui-dist/assets/diagram-OA4YK3LP-BLftqX4w.js +30 -0
  227. package/ui-dist/assets/diagram-WEI45ONY-C8Wlpiya.js +41 -0
  228. package/ui-dist/assets/ebnfDiagram-CCIWWBDH-BkNqh_K_.js +1 -0
  229. package/ui-dist/assets/erDiagram-Q63AITRT-BMii4oU_.js +85 -0
  230. package/ui-dist/assets/flowDiagram-23GEKE2U-DDZzMurM.js +156 -0
  231. package/ui-dist/assets/ganttDiagram-NO4QXBWP-CAVNlZo_.js +292 -0
  232. package/ui-dist/assets/gitGraphDiagram-IHSO6WYX-CnVqJTno.js +106 -0
  233. package/ui-dist/assets/graph-UuBzmM6i.js +1 -0
  234. package/ui-dist/assets/{index-BBL80GJ3.js → index-B8KTqTd-.js} +1 -1
  235. package/ui-dist/assets/{index-BSRzECfZ.js → index-BCFDdipt.js} +1 -1
  236. package/ui-dist/assets/{index-Be_UUduv.js → index-BCRNL8Ur.js} +1 -1
  237. package/ui-dist/assets/{index-DgfqS5r-.js → index-BoYg6lnD.js} +1 -1
  238. package/ui-dist/assets/{index-LKZoMmLm.js → index-ByMcYjRc.js} +1 -1
  239. package/ui-dist/assets/index-C0SZ-iPk.css +1 -0
  240. package/ui-dist/assets/{index-DDvz8goz.js → index-CE8o_odr.js} +1 -1
  241. package/ui-dist/assets/{index-C2Ne_Flh.js → index-CUD9_zON.js} +1 -1
  242. package/ui-dist/assets/{index-Cd5DOkgF.js → index-CfJwloTV.js} +1 -1
  243. package/ui-dist/assets/{index-CMRK9PUO.js → index-Cps6JXnH.js} +1 -1
  244. package/ui-dist/assets/{index-CkdLQ1A4.js → index-DFFkOhH6.js} +1 -1
  245. package/ui-dist/assets/{index-ipqs2akW.js → index-DLcjSOvN.js} +1 -1
  246. package/ui-dist/assets/{index-B-4En24L.js → index-D_zjkSK9.js} +1 -1
  247. package/ui-dist/assets/{index-CjLYHamo.js → index-DhkpIEG5.js} +1 -1
  248. package/ui-dist/assets/{index-B4KMgdrI.js → index-HkHmJ1SI.js} +1 -1
  249. package/ui-dist/assets/{index-Dxe3o4t_.js → index-QU8L2MDH.js} +1 -1
  250. package/ui-dist/assets/{index-1Ubio04r.js → index-QXiy-HtS.js} +1 -1
  251. package/ui-dist/assets/{index-BXbeltXq.js → index-XYoWwmC5.js} +1 -1
  252. package/ui-dist/assets/{index-BL10wT_h.js → index-eXis7jEz.js} +454 -470
  253. package/ui-dist/assets/infoDiagram-FWYZ7A6U-zHkiZLiR.js +2 -0
  254. package/ui-dist/assets/{ishikawaDiagram-PHBUUO56-C08ZUJEU.js → ishikawaDiagram-FXEZZL3T-Box-AMwH.js} +3 -3
  255. package/ui-dist/assets/journeyDiagram-5HDEW3XC-CFIzHPs2.js +139 -0
  256. package/ui-dist/assets/{kanban-definition-K7BYSVSG-BcJd4-9s.js → kanban-definition-HUTT4EX6-DHqpBUqM.js} +8 -8
  257. package/ui-dist/assets/katex-C5jXJg4s.js +257 -0
  258. package/ui-dist/assets/layout-C-yC2nBc.js +1 -0
  259. package/ui-dist/assets/{linear-CqN63wCD.js → linear-DUNXAcN5.js} +1 -1
  260. package/ui-dist/assets/map-BercEElL.js +1 -0
  261. package/ui-dist/assets/mermaid.core-Nehb2FR-.js +314 -0
  262. package/ui-dist/assets/mindmap-definition-LN4V7U3C-D0zryK2s.js +96 -0
  263. package/ui-dist/assets/pegDiagram-2B236MQR-C5vq9Ju0.js +1 -0
  264. package/ui-dist/assets/pieDiagram-ENE6RG2P-D0VOjPBZ.js +39 -0
  265. package/ui-dist/assets/quadrantDiagram-ABIIQ3AL-B8xuixyw.js +7 -0
  266. package/ui-dist/assets/railroadDiagram-RFXS5EU6-Bf9YgNO5.js +1 -0
  267. package/ui-dist/assets/requirementDiagram-TGXJPOKE-CDEqlFZu.js +84 -0
  268. package/ui-dist/assets/sankeyDiagram-HTMAVEWB-C7PsAz-L.js +40 -0
  269. package/ui-dist/assets/sequenceDiagram-DBY2YBRQ-DzvSiGUe.js +162 -0
  270. package/ui-dist/assets/sizeCapture-X5ZJPWSS-DSGNUJ8t.js +1 -0
  271. package/ui-dist/assets/stateDiagram-2N3HPSRC-BZtTZHzp.js +1 -0
  272. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-BGgjQnDH.js +1 -0
  273. package/ui-dist/assets/swimlanes-5IMT3BWC-DV7m1IAS.js +2 -0
  274. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-QL5BklQV.js +8 -0
  275. package/ui-dist/assets/timeline-definition-FHXFAJF6-BMOmWJRu.js +120 -0
  276. package/ui-dist/assets/vennDiagram-L72KCM5P-DS6i029a.js +34 -0
  277. package/ui-dist/assets/wardleyDiagram-EHGQE667-Ai7opcM1.js +78 -0
  278. package/ui-dist/assets/xychartDiagram-FW5EYKEG-BlA47Exk.js +7 -0
  279. package/ui-dist/index.html +2 -2
  280. package/dist/langfuse-transcript.d.ts +0 -33
  281. package/dist/langfuse-transcript.d.ts.map +0 -1
  282. package/dist/langfuse-transcript.js +0 -401
  283. package/dist/langfuse-transcript.js.map +0 -1
  284. package/dist/langfuse.d.ts +0 -93
  285. package/dist/langfuse.d.ts.map +0 -1
  286. package/dist/langfuse.js +0 -420
  287. package/dist/langfuse.js.map +0 -1
  288. package/ui-dist/assets/_basePickBy-Cniq5QAz.js +0 -1
  289. package/ui-dist/assets/_baseUniq-aSj0wr7H.js +0 -1
  290. package/ui-dist/assets/arc-C4Mg91_a.js +0 -1
  291. package/ui-dist/assets/architectureDiagram-2XIMDMQ5-DfqLRajq.js +0 -36
  292. package/ui-dist/assets/blockDiagram-WCTKOSBZ-BbefXkmh.js +0 -132
  293. package/ui-dist/assets/c4Diagram-IC4MRINW-BVPjmrfV.js +0 -10
  294. package/ui-dist/assets/channel-B-bxwuub.js +0 -1
  295. package/ui-dist/assets/chunk-NQ4KR5QH-D78Rqvef.js +0 -220
  296. package/ui-dist/assets/chunk-WL4C6EOR-CaI2CXRo.js +0 -189
  297. package/ui-dist/assets/classDiagram-VBA2DB6C-oNkrSzge.js +0 -1
  298. package/ui-dist/assets/classDiagram-v2-RAHNMMFH-oNkrSzge.js +0 -1
  299. package/ui-dist/assets/clone-D1LQw6bn.js +0 -1
  300. package/ui-dist/assets/cytoscape.esm-BQaXIfA_.js +0 -331
  301. package/ui-dist/assets/dagre-KLK3FWXG-Cedmep7r.js +0 -4
  302. package/ui-dist/assets/diagram-E7M64L7V-BWIKKX1f.js +0 -24
  303. package/ui-dist/assets/diagram-IFDJBPK2-De8ij4wb.js +0 -43
  304. package/ui-dist/assets/diagram-P4PSJMXO-DfqKc5zd.js +0 -24
  305. package/ui-dist/assets/erDiagram-INFDFZHY-CacJL_tU.js +0 -70
  306. package/ui-dist/assets/flowDiagram-PKNHOUZH-CQbuZmQW.js +0 -162
  307. package/ui-dist/assets/ganttDiagram-A5KZAMGK-uMPy8GwP.js +0 -292
  308. package/ui-dist/assets/gitGraphDiagram-K3NZZRJ6-D10Ck-1y.js +0 -65
  309. package/ui-dist/assets/graph-DMAYpSbz.js +0 -1
  310. package/ui-dist/assets/index-yhZee3iu.css +0 -1
  311. package/ui-dist/assets/infoDiagram-LFFYTUFH-WdYfk1ti.js +0 -2
  312. package/ui-dist/assets/journeyDiagram-4ABVD52K-A3rlVmO2.js +0 -139
  313. package/ui-dist/assets/katex-B1X10hvy.js +0 -261
  314. package/ui-dist/assets/layout-BjkotBZ2.js +0 -1
  315. package/ui-dist/assets/mermaid.core-D3iDEDQJ.js +0 -255
  316. package/ui-dist/assets/mindmap-definition-YRQLILUH-Cm-NQlLA.js +0 -68
  317. package/ui-dist/assets/pieDiagram-SKSYHLDU-BaDPvveA.js +0 -30
  318. package/ui-dist/assets/quadrantDiagram-337W2JSQ-0dX4kokb.js +0 -7
  319. package/ui-dist/assets/requirementDiagram-Z7DCOOCP-BdbJFOUK.js +0 -73
  320. package/ui-dist/assets/sankeyDiagram-WA2Y5GQK-ZMXNjh7n.js +0 -10
  321. package/ui-dist/assets/sequenceDiagram-2WXFIKYE-DfR6JqDW.js +0 -145
  322. package/ui-dist/assets/stateDiagram-RAJIS63D-BcGX6JIu.js +0 -1
  323. package/ui-dist/assets/stateDiagram-v2-FVOUBMTO-D1SMoFW3.js +0 -1
  324. package/ui-dist/assets/timeline-definition-YZTLITO2-DrIAH8-G.js +0 -61
  325. package/ui-dist/assets/treemap-KZPCXAKY-DEopGTtM.js +0 -162
  326. package/ui-dist/assets/vennDiagram-LZ73GAT5-CM3yysPE.js +0 -34
  327. package/ui-dist/assets/xychartDiagram-JWTSCODW-C34pUeNV.js +0 -7
@@ -5,8 +5,6 @@ import { createLocalAgentJwt } from "../../agent-auth-jwt.js";
5
5
  import { findServerAdapter, getServerAdapter } from "../../agent-runtimes/index.js";
6
6
  import { parseObject } from "../../agent-runtimes/utils.js";
7
7
  import { resolveDefaultAgentWorkspaceDir, } from "../../home-paths.js";
8
- import { emitExecutionTranscriptTree } from "../../langfuse-transcript.js";
9
- import { updateExecutionObservation, updateExecutionTraceIO, updateExecutionTraceName, updateExecutionTraceSession, withExecutionObservation } from "../../langfuse.js";
10
8
  import { redactCurrentUserText } from "../../log-redaction.js";
11
9
  import { logger } from "../../middleware/logger.js";
12
10
  import { publishAutomationRunOutputToChat } from "../automation-chat-output.js";
@@ -19,7 +17,7 @@ import { executeAdapterWithModelFallbacks } from "./model-fallback.js";
19
17
  export { prioritizeProjectWorkspaceCandidatesForRun } from "../agent-run-context.js";
20
18
  import * as heartbeatCore from "./heartbeat.core.js";
21
19
  import * as heartbeatSessions from "./heartbeat.sessions.js";
22
- const { MAX_LIVE_LOG_CHUNK_BYTES, HEARTBEAT_MAX_CONCURRENT_RUNS_DEFAULT, HEARTBEAT_MAX_CONCURRENT_RUNS_MIN, HEARTBEAT_MAX_CONCURRENT_RUNS_MAX, DEFERRED_WAKE_CONTEXT_KEY, DETACHED_PROCESS_ERROR_CODE, ORPHANED_PROCESS_TERMINATION_GRACE_MS, ORPHANED_PROCESS_KILL_WAIT_MS, ORPHANED_PROCESS_POLL_INTERVAL_MS, startLocksByAgent, MAX_RECOVERY_CHAIN_DEPTH, ISSUE_PASSIVE_FOLLOWUP_REASON, ISSUE_PASSIVE_FOLLOWUP_WAKE_SOURCE, ISSUE_PASSIVE_FOLLOWUP_FAILURE_REASON, ISSUE_PASSIVE_FOLLOWUP_MAX_ATTEMPTS, ISSUE_REVIEW_CLOSEOUT_REASON, ISSUE_REVIEW_CLOSEOUT_FAILURE_REASON, ISSUE_REVIEW_CLOSEOUT_MAX_ATTEMPTS, ISSUE_PASSIVE_FOLLOWUP_COOLDOWN_MS_BY_ATTEMPT, ISSUE_PASSIVE_FOLLOWUP_TIMER_CONTINUITY_MAX_WINDOW_MS, SESSIONED_LOCAL_ADAPTERS, heartbeatRunListColumns, appendExcerpt, appendTranscriptEntriesFromChunk, normalizeMaxConcurrentRuns, withAgentStartLock, readNonEmptyString, resolveHeartbeatObservabilitySurface, buildHeartbeatObservationName, compactTraceText, buildIssueRunTraceName, buildHeartbeatRuntimeTraceMetadata, buildHeartbeatAdapterInvokePayload, sanitizeStartupContextContextForPersistence, sanitizeStartupContextPromptForPersistence, buildRecentDateKeys, buildDateKeysBetween, fallbackSkillLabel, normalizeLoadedSkill, normalizeLoadedSkillForPayload, emptySkillEvidenceCounts, incrementSkillEvidenceCount, strongestSkillEvidence, resolveSkillEvidence, readSkillEvidenceFromPayload, extractSkillSlugFromPath, collectSkillPathsFromText, collectStringValues, normalizeSkillUseFromPath, dedupeSkillUses, collectSkillUsesFromText, readToolCommandInput, isCommandTranscriptTool, isReadTranscriptTool, inferUsedSkillsFromTranscript, normalizeSkillCandidate, addSkillCandidate, readSkillReferenceSlug, collectSkillReferences, inferUsedSkillsFromPrompt, resolveForbiddenRuntimeSkillMarkers, detectForbiddenRuntimeSkillMarker, normalizeLedgerBillingType, resolveLedgerBiller, normalizeBilledCostCents, resolveLedgerScopeForRun } = heartbeatCore;
20
+ const { MAX_LIVE_LOG_CHUNK_BYTES, HEARTBEAT_MAX_CONCURRENT_RUNS_DEFAULT, HEARTBEAT_MAX_CONCURRENT_RUNS_MIN, HEARTBEAT_MAX_CONCURRENT_RUNS_MAX, DEFERRED_WAKE_CONTEXT_KEY, DETACHED_PROCESS_ERROR_CODE, ORPHANED_PROCESS_TERMINATION_GRACE_MS, ORPHANED_PROCESS_KILL_WAIT_MS, ORPHANED_PROCESS_POLL_INTERVAL_MS, startLocksByAgent, MAX_RECOVERY_CHAIN_DEPTH, ISSUE_PASSIVE_FOLLOWUP_REASON, ISSUE_PASSIVE_FOLLOWUP_WAKE_SOURCE, ISSUE_PASSIVE_FOLLOWUP_FAILURE_REASON, ISSUE_PASSIVE_FOLLOWUP_MAX_ATTEMPTS, ISSUE_REVIEW_CLOSEOUT_REASON, ISSUE_REVIEW_CLOSEOUT_FAILURE_REASON, ISSUE_REVIEW_CLOSEOUT_MAX_ATTEMPTS, ISSUE_PASSIVE_FOLLOWUP_COOLDOWN_MS_BY_ATTEMPT, ISSUE_PASSIVE_FOLLOWUP_TIMER_CONTINUITY_MAX_WINDOW_MS, SESSIONED_LOCAL_ADAPTERS, heartbeatRunListColumns, appendExcerpt, appendTranscriptEntriesFromChunk, normalizeMaxConcurrentRuns, withAgentStartLock, readNonEmptyString, buildHeartbeatAdapterInvokePayload, sanitizeStartupContextContextForPersistence, sanitizeStartupContextPromptForPersistence, buildRecentDateKeys, buildDateKeysBetween, fallbackSkillLabel, normalizeLoadedSkill, normalizeLoadedSkillForPayload, emptySkillEvidenceCounts, incrementSkillEvidenceCount, strongestSkillEvidence, resolveSkillEvidence, readSkillEvidenceFromPayload, extractSkillSlugFromPath, collectSkillPathsFromText, collectStringValues, normalizeSkillUseFromPath, dedupeSkillUses, collectSkillUsesFromText, readToolCommandInput, isCommandTranscriptTool, isReadTranscriptTool, inferUsedSkillsFromTranscript, normalizeSkillCandidate, addSkillCandidate, readSkillReferenceSlug, collectSkillReferences, inferUsedSkillsFromPrompt, resolveForbiddenRuntimeSkillMarkers, detectForbiddenRuntimeSkillMarker, normalizeLedgerBillingType, resolveLedgerBiller, normalizeBilledCostCents, resolveLedgerScopeForRun } = heartbeatCore;
23
21
  const { buildExplicitResumeSessionOverride, normalizeUsageTotals, readRawUsageTotals, deriveNormalizedUsageDelta, formatCount, parseSessionCompactionPolicy, resolveRuntimeSessionParamsForWorkspace, parseIssueAssigneeAgentRuntimeOverrides, deriveTaskKey, shouldResetTaskSessionForWake, formatRuntimeWorkspaceWarningLog, describeSessionResetReason, deriveCommentId, enrichWakeContextSnapshot, mergeCoalescedContextSnapshot, issueCommentAuthorKind, issueCommentAuthorLabel, buildDeferredWakePayload, readDeferredWakeContext, readDeferredWakePayload, deriveDeferredWakeTaskKey, hydrateWakeContextSnapshot, firstNonEmptyLine, deriveRecoveryFailureKind, deriveRecoveryFailureSummary, mergeMissingRecoveryContextFields, hydrateRecoveryBaseContextSnapshot, buildRecoveryContextSnapshot, normalizePassiveFollowupContext, normalizeReviewCloseoutContext, passiveFollowupCooldownMs, issueHasReviewer, isAgentEligibleForTimerContinuation, hasCredibleTimerContinuation, buildPassiveFollowupContextSnapshot, runTaskKey, isSameTaskScope, isTrackedLocalChildProcessAdapter, isProcessAlive, waitForProcessExit, terminateOrphanedProcess, truncateDisplayId, normalizeAgentNameKey, defaultSessionCodec, getAgentRuntimeSessionCodec, normalizeSessionParams, resolveNextSessionState } = heartbeatSessions;
24
22
  function buildPersistableHeartbeatContext(context) {
25
23
  return sanitizeStartupContextContextForPersistence(context) ?? {};
@@ -34,7 +32,7 @@ function resolveRuntimeSceneForRun(run) {
34
32
  });
35
33
  }
36
34
  export function createHeartbeatExecuteHandlers(context) {
37
- const { db, instanceSettings, getCurrentUserRedactionOptions, runLogStore, runContextSvc, issuesSvc, executionWorkspacesSvc, workspaceOperationsSvc, activeRunExecutions, budgetHooks, budgets, getAgent, getRun, getRuntimeState, getTaskSession, getLatestRunForSession, getOldestRunForSession, resolveNormalizedUsageForSession, evaluateSessionCompaction, resolveSessionBeforeForWakeup, resolveExplicitResumeSessionOverride, upsertTaskSession, clearTaskSessions, ensureRuntimeState, buildHeartbeatObservabilityContext, emitHeartbeatObservationEvent, emitHeartbeatLiveEval, setRunStatus, setWakeupStatus, updateWakeupRequestRecord, insertWakeupRequestRecord, appendRunEvent, nextRunEventSeq, persistRunProcessMetadata, clearDetachedRunWarning, enqueueRecoveryRun, enqueueProcessLossRetry, parseHeartbeatPolicy, markAgentHeartbeatChecked, evaluateTimerPreflight, runHasIssueClosureComment, runHasIssueReviewDecision, issueHasDeferredWake, passiveFollowupAlreadyRecorded, reviewerCloseoutAlreadyRecorded, issueHasRecordedBlockedReviewerDecision, evaluatePassiveIssueClosureForLockedIssue, countRunningRunsForAgent, claimQueuedRun, finalizeAgentStatus, reapOrphanedRuns, resumeQueuedRuns, updateRuntimeState, startNextQueuedRunForAgent, releaseIssueExecutionAndPromote, enqueueWakeup, resumeDeferredWakeupsForAgent, listProjectScopedRunIds, listProjectScopedWakeupIds, cancelPendingWakeupsForBudgetScope, cancelRunInternal, cancelActiveForAgentInternal, cancelBudgetScopeWork, retryRunInternal, buildSkillAnalytics } = context;
35
+ const { db, instanceSettings, getCurrentUserRedactionOptions, runLogStore, runContextSvc, issuesSvc, executionWorkspacesSvc, workspaceOperationsSvc, activeRunExecutions, budgetHooks, budgets, getAgent, getRun, getRuntimeState, getTaskSession, getLatestRunForSession, getOldestRunForSession, resolveNormalizedUsageForSession, evaluateSessionCompaction, resolveSessionBeforeForWakeup, resolveExplicitResumeSessionOverride, upsertTaskSession, clearTaskSessions, ensureRuntimeState, setRunStatus, setWakeupStatus, updateWakeupRequestRecord, insertWakeupRequestRecord, appendRunEvent, nextRunEventSeq, persistRunProcessMetadata, clearDetachedRunWarning, enqueueRecoveryRun, enqueueProcessLossRetry, parseHeartbeatPolicy, markAgentHeartbeatChecked, evaluateTimerPreflight, runHasIssueClosureComment, runHasIssueReviewDecision, issueHasDeferredWake, passiveFollowupAlreadyRecorded, reviewerCloseoutAlreadyRecorded, issueHasRecordedBlockedReviewerDecision, evaluatePassiveIssueClosureForLockedIssue, countRunningRunsForAgent, claimQueuedRun, finalizeAgentStatus, reapOrphanedRuns, resumeQueuedRuns, updateRuntimeState, startNextQueuedRunForAgent, releaseIssueExecutionAndPromote, enqueueWakeup, resumeDeferredWakeupsForAgent, listProjectScopedRunIds, listProjectScopedWakeupIds, cancelPendingWakeupsForBudgetScope, cancelRunInternal, cancelActiveForAgentInternal, cancelBudgetScopeWork, retryRunInternal, buildSkillAnalytics } = context;
38
36
  async function executeRun(runId) {
39
37
  let run = await getRun(runId);
40
38
  if (!run)
@@ -67,557 +65,596 @@ export function createHeartbeatExecuteHandlers(context) {
67
65
  await releaseIssueExecutionAndPromote(failedRun);
68
66
  return;
69
67
  }
70
- const heartbeatObservationContext = buildHeartbeatObservabilityContext(run, {
71
- runtime: agent.agentRuntimeType,
72
- metadata: {
73
- agentName: agent.name,
74
- invocationSource: run.invocationSource,
75
- triggerDetail: run.triggerDetail,
76
- },
68
+ const executionTranscript = [];
69
+ let stdoutTranscriptBuffer = "";
70
+ let stderrTranscriptBuffer = "";
71
+ let stdoutTranscriptParser = null;
72
+ let transcriptFallbackResult = null;
73
+ let latestAdapterMeta = null;
74
+ let adapterForbiddenMarkerObserved = false;
75
+ let finalRunOutput = null;
76
+ let finalRunStatus = run.status;
77
+ const runtime = await ensureRuntimeState(agent);
78
+ const context = parseObject(run.contextSnapshot);
79
+ delete context.rudderGitIdentity;
80
+ const taskKey = deriveTaskKey(context, null);
81
+ const sessionCodec = getAgentRuntimeSessionCodec(agent.agentRuntimeType);
82
+ const issueId = readNonEmptyString(context.issueId);
83
+ const issueContext = issueId
84
+ ? await db
85
+ .select({
86
+ id: issues.id,
87
+ identifier: issues.identifier,
88
+ title: issues.title,
89
+ description: issues.description,
90
+ projectId: issues.projectId,
91
+ projectWorkspaceId: issues.projectWorkspaceId,
92
+ executionWorkspaceId: issues.executionWorkspaceId,
93
+ executionWorkspacePreference: issues.executionWorkspacePreference,
94
+ assigneeAgentId: issues.assigneeAgentId,
95
+ assigneeAgentRuntimeOverrides: issues.assigneeAgentRuntimeOverrides,
96
+ executionWorkspaceSettings: issues.executionWorkspaceSettings,
97
+ })
98
+ .from(issues)
99
+ .where(and(eq(issues.id, issueId), eq(issues.orgId, agent.orgId)))
100
+ .then((rows) => rows[0] ?? null)
101
+ : null;
102
+ const issueAssigneeOverrides = issueContext && issueContext.assigneeAgentId === agent.id
103
+ ? parseIssueAssigneeAgentRuntimeOverrides(issueContext.assigneeAgentRuntimeOverrides)
104
+ : null;
105
+ const issueExecutionWorkspaceSettings = parseIssueExecutionWorkspaceSettings(issueContext?.executionWorkspaceSettings);
106
+ const contextProjectId = readNonEmptyString(context.projectId);
107
+ const executionProjectId = issueContext?.projectId ?? contextProjectId;
108
+ const projectExecutionWorkspacePolicy = executionProjectId
109
+ ? await db
110
+ .select({ executionWorkspacePolicy: projects.executionWorkspacePolicy })
111
+ .from(projects)
112
+ .where(and(eq(projects.id, executionProjectId), eq(projects.orgId, agent.orgId)))
113
+ .then((rows) => parseProjectExecutionWorkspacePolicy(rows[0]?.executionWorkspacePolicy))
114
+ : null;
115
+ const taskSession = taskKey
116
+ ? await getTaskSession(agent.orgId, agent.id, agent.agentRuntimeType, taskKey)
117
+ : null;
118
+ const resetTaskSession = shouldResetTaskSessionForWake(context);
119
+ const sessionResetReason = describeSessionResetReason(context);
120
+ const taskSessionForRun = resetTaskSession ? null : taskSession;
121
+ const explicitResumeSessionParams = normalizeSessionParams(sessionCodec.deserialize(parseObject(context.resumeSessionParams)));
122
+ const explicitResumeSessionDisplayId = truncateDisplayId(readNonEmptyString(context.resumeSessionDisplayId) ??
123
+ (sessionCodec.getDisplayId ? sessionCodec.getDisplayId(explicitResumeSessionParams) : null) ??
124
+ readNonEmptyString(explicitResumeSessionParams?.sessionId));
125
+ const previousSessionParams = explicitResumeSessionParams ??
126
+ (explicitResumeSessionDisplayId ? { sessionId: explicitResumeSessionDisplayId } : null) ??
127
+ normalizeSessionParams(sessionCodec.deserialize(taskSessionForRun?.sessionParamsJson ?? null));
128
+ const config = await runContextSvc.materializeManagedInstructionsForRun({
129
+ ...agent,
130
+ agentRuntimeConfig: parseObject(agent.agentRuntimeConfig),
77
131
  });
78
- await withExecutionObservation(heartbeatObservationContext, {
79
- name: buildHeartbeatObservationName(run, agent.name),
80
- asType: "agent",
81
- input: {
82
- agentId: agent.id,
83
- agentName: agent.name,
84
- invocationSource: run.invocationSource,
85
- triggerDetail: run.triggerDetail,
86
- issueId: readNonEmptyString(parseObject(run.contextSnapshot).issueId),
87
- },
88
- }, async (observation) => {
89
- const executionTranscript = [];
90
- let stdoutTranscriptBuffer = "";
91
- let stderrTranscriptBuffer = "";
92
- let stdoutTranscriptParser = null;
93
- let transcriptFallbackResult = null;
94
- let modelTurnInput;
95
- let latestAdapterMeta = null;
96
- let adapterForbiddenMarkerObserved = false;
97
- let finalObservationOutput = null;
98
- let finalObservationStatus = run.status;
99
- let finalObservationSessionId = heartbeatObservationContext.sessionKey ?? null;
100
- const runtime = await ensureRuntimeState(agent);
101
- const context = parseObject(run.contextSnapshot);
102
- delete context.rudderGitIdentity;
103
- const taskKey = deriveTaskKey(context, null);
104
- const sessionCodec = getAgentRuntimeSessionCodec(agent.agentRuntimeType);
105
- const issueId = readNonEmptyString(context.issueId);
106
- const issueContext = issueId
107
- ? await db
108
- .select({
109
- id: issues.id,
110
- identifier: issues.identifier,
111
- title: issues.title,
112
- description: issues.description,
113
- projectId: issues.projectId,
114
- projectWorkspaceId: issues.projectWorkspaceId,
115
- executionWorkspaceId: issues.executionWorkspaceId,
116
- executionWorkspacePreference: issues.executionWorkspacePreference,
117
- assigneeAgentId: issues.assigneeAgentId,
118
- assigneeAgentRuntimeOverrides: issues.assigneeAgentRuntimeOverrides,
119
- executionWorkspaceSettings: issues.executionWorkspaceSettings,
120
- })
121
- .from(issues)
122
- .where(and(eq(issues.id, issueId), eq(issues.orgId, agent.orgId)))
123
- .then((rows) => rows[0] ?? null)
124
- : null;
125
- const issueAssigneeOverrides = issueContext && issueContext.assigneeAgentId === agent.id
126
- ? parseIssueAssigneeAgentRuntimeOverrides(issueContext.assigneeAgentRuntimeOverrides)
127
- : null;
128
- const issueExecutionWorkspaceSettings = parseIssueExecutionWorkspaceSettings(issueContext?.executionWorkspaceSettings);
129
- const contextProjectId = readNonEmptyString(context.projectId);
130
- const executionProjectId = issueContext?.projectId ?? contextProjectId;
131
- const projectExecutionWorkspacePolicy = executionProjectId
132
- ? await db
133
- .select({ executionWorkspacePolicy: projects.executionWorkspacePolicy })
134
- .from(projects)
135
- .where(and(eq(projects.id, executionProjectId), eq(projects.orgId, agent.orgId)))
136
- .then((rows) => parseProjectExecutionWorkspacePolicy(rows[0]?.executionWorkspacePolicy))
137
- : null;
138
- const taskSession = taskKey
139
- ? await getTaskSession(agent.orgId, agent.id, agent.agentRuntimeType, taskKey)
140
- : null;
141
- const resetTaskSession = shouldResetTaskSessionForWake(context);
142
- const sessionResetReason = describeSessionResetReason(context);
143
- const taskSessionForRun = resetTaskSession ? null : taskSession;
144
- const explicitResumeSessionParams = normalizeSessionParams(sessionCodec.deserialize(parseObject(context.resumeSessionParams)));
145
- const explicitResumeSessionDisplayId = truncateDisplayId(readNonEmptyString(context.resumeSessionDisplayId) ??
146
- (sessionCodec.getDisplayId ? sessionCodec.getDisplayId(explicitResumeSessionParams) : null) ??
147
- readNonEmptyString(explicitResumeSessionParams?.sessionId));
148
- const previousSessionParams = explicitResumeSessionParams ??
149
- (explicitResumeSessionDisplayId ? { sessionId: explicitResumeSessionDisplayId } : null) ??
150
- normalizeSessionParams(sessionCodec.deserialize(taskSessionForRun?.sessionParamsJson ?? null));
151
- const config = await runContextSvc.materializeManagedInstructionsForRun({
152
- ...agent,
153
- agentRuntimeConfig: parseObject(agent.agentRuntimeConfig),
154
- });
155
- const executionWorkspaceMode = resolveExecutionWorkspaceMode({
156
- projectPolicy: projectExecutionWorkspacePolicy,
157
- issueSettings: issueExecutionWorkspaceSettings,
158
- legacyUseProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null,
159
- });
160
- const resolvedWorkspace = await runContextSvc.resolveWorkspaceForRun(agent, context, previousSessionParams, { useProjectWorkspace: executionWorkspaceMode !== "agent_default" });
161
- const workspaceManagedConfig = buildExecutionWorkspaceAdapterConfig({
162
- agentConfig: config,
163
- projectPolicy: projectExecutionWorkspacePolicy,
164
- issueSettings: issueExecutionWorkspaceSettings,
165
- mode: executionWorkspaceMode,
166
- legacyUseProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null,
167
- });
168
- const mergedConfig = issueAssigneeOverrides?.agentRuntimeConfig
169
- ? { ...workspaceManagedConfig, ...issueAssigneeOverrides.agentRuntimeConfig }
170
- : workspaceManagedConfig;
171
- const { resolvedConfig, runtimeConfig, runtimeSkillEntries, secretKeys } = await runContextSvc.prepareRuntimeConfig({
172
- scene: "heartbeat",
173
- agent,
174
- baseConfig: mergedConfig,
175
- });
176
- heartbeatObservationContext.metadata = {
177
- ...(heartbeatObservationContext.metadata ?? {}),
178
- ...buildHeartbeatRuntimeTraceMetadata({
179
- runtimeConfig,
180
- runtimeSkills: runtimeSkillEntries,
181
- }),
182
- };
183
- const issueRef = issueContext
184
- ? {
185
- id: issueContext.id,
186
- identifier: issueContext.identifier,
187
- title: issueContext.title,
188
- projectId: issueContext.projectId,
189
- projectWorkspaceId: issueContext.projectWorkspaceId,
190
- executionWorkspaceId: issueContext.executionWorkspaceId,
191
- executionWorkspacePreference: issueContext.executionWorkspacePreference,
192
- }
193
- : null;
194
- const rootObservationInput = {
195
- agentId: agent.id,
196
- agentName: agent.name,
197
- invocationSource: run.invocationSource,
198
- triggerDetail: run.triggerDetail,
199
- issue: issueRef
200
- ? {
201
- id: issueRef.id,
202
- identifier: issueRef.identifier ?? null,
203
- title: issueRef.title ?? null,
204
- }
205
- : null,
206
- };
207
- updateExecutionObservation(observation, heartbeatObservationContext, {
208
- input: rootObservationInput,
209
- });
210
- updateExecutionTraceIO(observation, { input: rootObservationInput });
211
- if (issueRef) {
212
- updateExecutionTraceName(observation, buildIssueRunTraceName({
213
- issueTitle: issueRef.title,
214
- issueId: issueRef.id,
215
- }));
132
+ const executionWorkspaceMode = resolveExecutionWorkspaceMode({
133
+ projectPolicy: projectExecutionWorkspacePolicy,
134
+ issueSettings: issueExecutionWorkspaceSettings,
135
+ legacyUseProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null,
136
+ });
137
+ const resolvedWorkspace = await runContextSvc.resolveWorkspaceForRun(agent, context, previousSessionParams, { useProjectWorkspace: executionWorkspaceMode !== "agent_default" });
138
+ const workspaceManagedConfig = buildExecutionWorkspaceAdapterConfig({
139
+ agentConfig: config,
140
+ projectPolicy: projectExecutionWorkspacePolicy,
141
+ issueSettings: issueExecutionWorkspaceSettings,
142
+ mode: executionWorkspaceMode,
143
+ legacyUseProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null,
144
+ });
145
+ const mergedConfig = issueAssigneeOverrides?.agentRuntimeConfig
146
+ ? { ...workspaceManagedConfig, ...issueAssigneeOverrides.agentRuntimeConfig }
147
+ : workspaceManagedConfig;
148
+ const { resolvedConfig, runtimeConfig, runtimeSkillEntries, secretKeys } = await runContextSvc.prepareRuntimeConfig({
149
+ scene: "heartbeat",
150
+ agent,
151
+ baseConfig: mergedConfig,
152
+ });
153
+ const issueRef = issueContext
154
+ ? {
155
+ id: issueContext.id,
156
+ identifier: issueContext.identifier,
157
+ title: issueContext.title,
158
+ projectId: issueContext.projectId,
159
+ projectWorkspaceId: issueContext.projectWorkspaceId,
160
+ executionWorkspaceId: issueContext.executionWorkspaceId,
161
+ executionWorkspacePreference: issueContext.executionWorkspacePreference,
216
162
  }
217
- const existingExecutionWorkspace = issueRef?.executionWorkspaceId ? await executionWorkspacesSvc.getById(issueRef.executionWorkspaceId) : null;
218
- const workspaceOperationRecorder = workspaceOperationsSvc.createRecorder({
163
+ : null;
164
+ const existingExecutionWorkspace = issueRef?.executionWorkspaceId ? await executionWorkspacesSvc.getById(issueRef.executionWorkspaceId) : null;
165
+ const workspaceOperationRecorder = workspaceOperationsSvc.createRecorder({
166
+ orgId: agent.orgId,
167
+ heartbeatRunId: run.id,
168
+ executionWorkspaceId: existingExecutionWorkspace?.id ?? null,
169
+ });
170
+ const executionWorkspace = await realizeExecutionWorkspace({
171
+ base: {
172
+ baseCwd: resolvedWorkspace.cwd,
173
+ source: resolvedWorkspace.source,
174
+ projectId: resolvedWorkspace.projectId,
175
+ workspaceId: resolvedWorkspace.workspaceId,
176
+ repoUrl: resolvedWorkspace.repoUrl,
177
+ repoRef: resolvedWorkspace.repoRef,
178
+ },
179
+ config: runtimeConfig,
180
+ issue: issueRef,
181
+ agent: {
182
+ id: agent.id,
183
+ name: agent.name,
219
184
  orgId: agent.orgId,
220
- heartbeatRunId: run.id,
221
- executionWorkspaceId: existingExecutionWorkspace?.id ?? null,
222
- });
223
- const executionWorkspace = await realizeExecutionWorkspace({
224
- base: {
225
- baseCwd: resolvedWorkspace.cwd,
226
- source: resolvedWorkspace.source,
227
- projectId: resolvedWorkspace.projectId,
228
- workspaceId: resolvedWorkspace.workspaceId,
229
- repoUrl: resolvedWorkspace.repoUrl,
230
- repoRef: resolvedWorkspace.repoRef,
231
- },
232
- config: runtimeConfig,
233
- issue: issueRef,
234
- agent: {
235
- id: agent.id,
236
- name: agent.name,
237
- orgId: agent.orgId,
238
- },
239
- recorder: workspaceOperationRecorder,
240
- });
241
- const resolvedProjectId = executionWorkspace.projectId ?? issueRef?.projectId ?? executionProjectId ?? null;
242
- const resolvedProjectWorkspaceId = issueRef?.projectWorkspaceId ?? resolvedWorkspace.workspaceId ?? null;
243
- const shouldReuseExisting = issueRef?.executionWorkspacePreference === "reuse_existing" &&
244
- existingExecutionWorkspace &&
245
- existingExecutionWorkspace.status !== "archived";
246
- let persistedExecutionWorkspace = null;
247
- try {
248
- persistedExecutionWorkspace = shouldReuseExisting && existingExecutionWorkspace
249
- ? await executionWorkspacesSvc.update(existingExecutionWorkspace.id, {
185
+ },
186
+ recorder: workspaceOperationRecorder,
187
+ });
188
+ const resolvedProjectId = executionWorkspace.projectId ?? issueRef?.projectId ?? executionProjectId ?? null;
189
+ const resolvedProjectWorkspaceId = issueRef?.projectWorkspaceId ?? resolvedWorkspace.workspaceId ?? null;
190
+ const shouldReuseExisting = issueRef?.executionWorkspacePreference === "reuse_existing" &&
191
+ existingExecutionWorkspace &&
192
+ existingExecutionWorkspace.status !== "archived";
193
+ let persistedExecutionWorkspace = null;
194
+ try {
195
+ persistedExecutionWorkspace = shouldReuseExisting && existingExecutionWorkspace
196
+ ? await executionWorkspacesSvc.update(existingExecutionWorkspace.id, {
197
+ cwd: executionWorkspace.cwd,
198
+ repoUrl: executionWorkspace.repoUrl,
199
+ baseRef: executionWorkspace.repoRef,
200
+ branchName: executionWorkspace.branchName,
201
+ providerType: executionWorkspace.strategy === "git_worktree" ? "git_worktree" : "local_fs",
202
+ providerRef: executionWorkspace.worktreePath,
203
+ status: "active",
204
+ lastUsedAt: new Date(),
205
+ metadata: {
206
+ ...(existingExecutionWorkspace.metadata ?? {}),
207
+ source: executionWorkspace.source,
208
+ createdByRuntime: executionWorkspace.created,
209
+ },
210
+ })
211
+ : resolvedProjectId
212
+ ? await executionWorkspacesSvc.create({
213
+ orgId: agent.orgId,
214
+ projectId: resolvedProjectId,
215
+ projectWorkspaceId: resolvedProjectWorkspaceId,
216
+ sourceIssueId: issueRef?.id ?? null,
217
+ mode: executionWorkspaceMode === "isolated_workspace"
218
+ ? "isolated_workspace"
219
+ : executionWorkspaceMode === "operator_branch"
220
+ ? "operator_branch"
221
+ : executionWorkspaceMode === "agent_default"
222
+ ? "adapter_managed"
223
+ : "shared_workspace",
224
+ strategyType: executionWorkspace.strategy === "git_worktree" ? "git_worktree" : "project_primary",
225
+ name: executionWorkspace.branchName ?? issueRef?.identifier ?? `workspace-${agent.id.slice(0, 8)}`,
226
+ status: "active",
250
227
  cwd: executionWorkspace.cwd,
251
228
  repoUrl: executionWorkspace.repoUrl,
252
229
  baseRef: executionWorkspace.repoRef,
253
230
  branchName: executionWorkspace.branchName,
254
231
  providerType: executionWorkspace.strategy === "git_worktree" ? "git_worktree" : "local_fs",
255
232
  providerRef: executionWorkspace.worktreePath,
256
- status: "active",
257
233
  lastUsedAt: new Date(),
234
+ openedAt: new Date(),
258
235
  metadata: {
259
- ...(existingExecutionWorkspace.metadata ?? {}),
260
236
  source: executionWorkspace.source,
261
237
  createdByRuntime: executionWorkspace.created,
262
238
  },
263
239
  })
264
- : resolvedProjectId
265
- ? await executionWorkspacesSvc.create({
266
- orgId: agent.orgId,
267
- projectId: resolvedProjectId,
268
- projectWorkspaceId: resolvedProjectWorkspaceId,
269
- sourceIssueId: issueRef?.id ?? null,
270
- mode: executionWorkspaceMode === "isolated_workspace"
271
- ? "isolated_workspace"
272
- : executionWorkspaceMode === "operator_branch"
273
- ? "operator_branch"
274
- : executionWorkspaceMode === "agent_default"
275
- ? "adapter_managed"
276
- : "shared_workspace",
277
- strategyType: executionWorkspace.strategy === "git_worktree" ? "git_worktree" : "project_primary",
278
- name: executionWorkspace.branchName ?? issueRef?.identifier ?? `workspace-${agent.id.slice(0, 8)}`,
279
- status: "active",
240
+ : null;
241
+ }
242
+ catch (error) {
243
+ if (executionWorkspace.created) {
244
+ try {
245
+ await cleanupExecutionWorkspaceArtifacts({
246
+ workspace: {
247
+ id: existingExecutionWorkspace?.id ?? `transient-${run.id}`,
280
248
  cwd: executionWorkspace.cwd,
281
- repoUrl: executionWorkspace.repoUrl,
282
- baseRef: executionWorkspace.repoRef,
283
- branchName: executionWorkspace.branchName,
284
249
  providerType: executionWorkspace.strategy === "git_worktree" ? "git_worktree" : "local_fs",
285
250
  providerRef: executionWorkspace.worktreePath,
286
- lastUsedAt: new Date(),
287
- openedAt: new Date(),
251
+ branchName: executionWorkspace.branchName,
252
+ repoUrl: executionWorkspace.repoUrl,
253
+ baseRef: executionWorkspace.repoRef,
254
+ projectId: resolvedProjectId,
255
+ projectWorkspaceId: resolvedProjectWorkspaceId,
256
+ sourceIssueId: issueRef?.id ?? null,
288
257
  metadata: {
258
+ createdByRuntime: true,
289
259
  source: executionWorkspace.source,
290
- createdByRuntime: executionWorkspace.created,
291
- },
292
- })
293
- : null;
294
- }
295
- catch (error) {
296
- if (executionWorkspace.created) {
297
- try {
298
- await cleanupExecutionWorkspaceArtifacts({
299
- workspace: {
300
- id: existingExecutionWorkspace?.id ?? `transient-${run.id}`,
301
- cwd: executionWorkspace.cwd,
302
- providerType: executionWorkspace.strategy === "git_worktree" ? "git_worktree" : "local_fs",
303
- providerRef: executionWorkspace.worktreePath,
304
- branchName: executionWorkspace.branchName,
305
- repoUrl: executionWorkspace.repoUrl,
306
- baseRef: executionWorkspace.repoRef,
307
- projectId: resolvedProjectId,
308
- projectWorkspaceId: resolvedProjectWorkspaceId,
309
- sourceIssueId: issueRef?.id ?? null,
310
- metadata: {
311
- createdByRuntime: true,
312
- source: executionWorkspace.source,
313
- },
314
260
  },
315
- projectWorkspace: {
316
- cwd: resolvedWorkspace.cwd,
317
- cleanupCommand: null,
318
- },
319
- teardownCommand: projectExecutionWorkspacePolicy?.workspaceStrategy?.teardownCommand ?? null,
320
- recorder: workspaceOperationRecorder,
321
- });
322
- }
323
- catch (cleanupError) {
324
- logger.warn({
325
- runId: run.id,
326
- issueId,
327
- executionWorkspaceCwd: executionWorkspace.cwd,
328
- cleanupError: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),
329
- }, "Failed to cleanup realized run workspace after persistence failure");
330
- }
261
+ },
262
+ projectWorkspace: {
263
+ cwd: resolvedWorkspace.cwd,
264
+ cleanupCommand: null,
265
+ },
266
+ teardownCommand: projectExecutionWorkspacePolicy?.workspaceStrategy?.teardownCommand ?? null,
267
+ recorder: workspaceOperationRecorder,
268
+ });
269
+ }
270
+ catch (cleanupError) {
271
+ logger.warn({
272
+ runId: run.id,
273
+ issueId,
274
+ executionWorkspaceCwd: executionWorkspace.cwd,
275
+ cleanupError: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),
276
+ }, "Failed to cleanup realized run workspace after persistence failure");
331
277
  }
332
- throw error;
333
278
  }
334
- await workspaceOperationRecorder.attachExecutionWorkspaceId(persistedExecutionWorkspace?.id ?? null);
335
- if (existingExecutionWorkspace &&
336
- persistedExecutionWorkspace &&
337
- existingExecutionWorkspace.id !== persistedExecutionWorkspace.id &&
338
- existingExecutionWorkspace.status === "active") {
339
- await executionWorkspacesSvc.update(existingExecutionWorkspace.id, {
340
- status: "idle",
341
- cleanupReason: null,
342
- });
279
+ throw error;
280
+ }
281
+ await workspaceOperationRecorder.attachExecutionWorkspaceId(persistedExecutionWorkspace?.id ?? null);
282
+ if (existingExecutionWorkspace &&
283
+ persistedExecutionWorkspace &&
284
+ existingExecutionWorkspace.id !== persistedExecutionWorkspace.id &&
285
+ existingExecutionWorkspace.status === "active") {
286
+ await executionWorkspacesSvc.update(existingExecutionWorkspace.id, {
287
+ status: "idle",
288
+ cleanupReason: null,
289
+ });
290
+ }
291
+ if (issueId && persistedExecutionWorkspace) {
292
+ const nextIssueWorkspaceMode = issueExecutionWorkspaceModeForPersistedWorkspace(persistedExecutionWorkspace.mode);
293
+ const shouldSwitchIssueToExistingWorkspace = issueRef?.executionWorkspacePreference === "reuse_existing" ||
294
+ executionWorkspaceMode === "isolated_workspace" ||
295
+ executionWorkspaceMode === "operator_branch";
296
+ const nextIssuePatch = {};
297
+ if (issueRef?.executionWorkspaceId !== persistedExecutionWorkspace.id) {
298
+ nextIssuePatch.executionWorkspaceId = persistedExecutionWorkspace.id;
343
299
  }
344
- if (issueId && persistedExecutionWorkspace) {
345
- const nextIssueWorkspaceMode = issueExecutionWorkspaceModeForPersistedWorkspace(persistedExecutionWorkspace.mode);
346
- const shouldSwitchIssueToExistingWorkspace = issueRef?.executionWorkspacePreference === "reuse_existing" ||
347
- executionWorkspaceMode === "isolated_workspace" ||
348
- executionWorkspaceMode === "operator_branch";
349
- const nextIssuePatch = {};
350
- if (issueRef?.executionWorkspaceId !== persistedExecutionWorkspace.id) {
351
- nextIssuePatch.executionWorkspaceId = persistedExecutionWorkspace.id;
352
- }
353
- if (resolvedProjectWorkspaceId && issueRef?.projectWorkspaceId !== resolvedProjectWorkspaceId) {
354
- nextIssuePatch.projectWorkspaceId = resolvedProjectWorkspaceId;
355
- }
356
- if (shouldSwitchIssueToExistingWorkspace) {
357
- nextIssuePatch.executionWorkspacePreference = "reuse_existing";
358
- nextIssuePatch.executionWorkspaceSettings = {
359
- ...(issueExecutionWorkspaceSettings ?? {}),
360
- mode: nextIssueWorkspaceMode,
361
- };
362
- }
363
- if (Object.keys(nextIssuePatch).length > 0) {
364
- await issuesSvc.update(issueId, nextIssuePatch);
365
- }
300
+ if (resolvedProjectWorkspaceId && issueRef?.projectWorkspaceId !== resolvedProjectWorkspaceId) {
301
+ nextIssuePatch.projectWorkspaceId = resolvedProjectWorkspaceId;
366
302
  }
367
- if (persistedExecutionWorkspace) {
368
- context.executionWorkspaceId = persistedExecutionWorkspace.id;
369
- await db
370
- .update(heartbeatRuns)
371
- .set({
372
- contextSnapshot: buildPersistableHeartbeatContext(context),
373
- updatedAt: new Date(),
374
- })
375
- .where(eq(heartbeatRuns.id, run.id));
303
+ if (shouldSwitchIssueToExistingWorkspace) {
304
+ nextIssuePatch.executionWorkspacePreference = "reuse_existing";
305
+ nextIssuePatch.executionWorkspaceSettings = {
306
+ ...(issueExecutionWorkspaceSettings ?? {}),
307
+ mode: nextIssueWorkspaceMode,
308
+ };
376
309
  }
377
- const runtimeSessionResolution = resolveRuntimeSessionParamsForWorkspace({
378
- orgId: agent.orgId,
379
- agent,
380
- previousSessionParams,
381
- resolvedWorkspace: {
382
- ...resolvedWorkspace,
383
- cwd: resolveDefaultAgentWorkspaceDir(agent.orgId, agent),
384
- source: "agent_home",
310
+ if (Object.keys(nextIssuePatch).length > 0) {
311
+ await issuesSvc.update(issueId, nextIssuePatch);
312
+ }
313
+ }
314
+ if (persistedExecutionWorkspace) {
315
+ context.executionWorkspaceId = persistedExecutionWorkspace.id;
316
+ await db
317
+ .update(heartbeatRuns)
318
+ .set({
319
+ contextSnapshot: buildPersistableHeartbeatContext(context),
320
+ updatedAt: new Date(),
321
+ })
322
+ .where(eq(heartbeatRuns.id, run.id));
323
+ }
324
+ const runtimeSessionResolution = resolveRuntimeSessionParamsForWorkspace({
325
+ orgId: agent.orgId,
326
+ agent,
327
+ previousSessionParams,
328
+ resolvedWorkspace: {
329
+ ...resolvedWorkspace,
330
+ cwd: resolveDefaultAgentWorkspaceDir(agent.orgId, agent),
331
+ source: "agent_home",
332
+ },
333
+ });
334
+ const runtimeSessionParams = runtimeSessionResolution.sessionParams;
335
+ const runtimeWorkspaceWarnings = [
336
+ ...resolvedWorkspace.warnings,
337
+ ...executionWorkspace.warnings,
338
+ ...(runtimeSessionResolution.warning ? [runtimeSessionResolution.warning] : []),
339
+ ...(resetTaskSession && sessionResetReason
340
+ ? [
341
+ taskKey
342
+ ? `Skipping saved session resume for task "${taskKey}" because ${sessionResetReason}.`
343
+ : `Skipping saved session resume because ${sessionResetReason}.`,
344
+ ]
345
+ : []),
346
+ ];
347
+ const runtimeScene = resolveRuntimeSceneForRun(run);
348
+ const runtimeSceneContext = await runContextSvc.buildSceneContext({
349
+ scene: runtimeScene,
350
+ agent,
351
+ resolvedWorkspace,
352
+ runtimeConfig,
353
+ issueId,
354
+ executionWorkspaceMode,
355
+ executionWorkspace: {
356
+ cwd: executionWorkspace.cwd,
357
+ source: executionWorkspace.source,
358
+ strategy: executionWorkspace.strategy,
359
+ projectId: executionWorkspace.projectId,
360
+ workspaceId: executionWorkspace.workspaceId,
361
+ repoUrl: executionWorkspace.repoUrl,
362
+ repoRef: executionWorkspace.repoRef,
363
+ branchName: executionWorkspace.branchName,
364
+ worktreePath: executionWorkspace.worktreePath,
365
+ },
366
+ });
367
+ context.rudderScene = runtimeSceneContext.rudderScene;
368
+ context.rudderWorkspace = runtimeSceneContext.rudderWorkspace;
369
+ context.rudderWorkspaces = runtimeSceneContext.rudderWorkspaces;
370
+ context.rudderStartupContext = runtimeSceneContext.rudderStartupContext;
371
+ context.rudderStartupContextMetrics = runtimeSceneContext.rudderStartupContextMetrics;
372
+ if (runtimeSceneContext.rudderRuntimeServiceIntents) {
373
+ context.rudderRuntimeServiceIntents = runtimeSceneContext.rudderRuntimeServiceIntents;
374
+ }
375
+ else {
376
+ delete context.rudderRuntimeServiceIntents;
377
+ }
378
+ if (executionWorkspace.projectId && !readNonEmptyString(context.projectId)) {
379
+ context.projectId = executionWorkspace.projectId;
380
+ }
381
+ const runtimeSessionFallback = taskKey || resetTaskSession ? null : runtime.sessionId;
382
+ let previousSessionDisplayId = truncateDisplayId(explicitResumeSessionDisplayId ??
383
+ taskSessionForRun?.sessionDisplayId ??
384
+ (sessionCodec.getDisplayId ? sessionCodec.getDisplayId(runtimeSessionParams) : null) ??
385
+ readNonEmptyString(runtimeSessionParams?.sessionId) ??
386
+ runtimeSessionFallback);
387
+ let runtimeSessionIdForAdapter = readNonEmptyString(runtimeSessionParams?.sessionId) ?? runtimeSessionFallback;
388
+ let runtimeSessionParamsForAdapter = runtimeSessionParams;
389
+ const sessionCompaction = await evaluateSessionCompaction({
390
+ agent,
391
+ sessionId: previousSessionDisplayId ?? runtimeSessionIdForAdapter,
392
+ issueId,
393
+ });
394
+ if (sessionCompaction.rotate) {
395
+ context.rudderSessionHandoffMarkdown = sessionCompaction.handoffMarkdown;
396
+ context.rudderSessionRotationReason = sessionCompaction.reason;
397
+ context.rudderPreviousSessionId = previousSessionDisplayId ?? runtimeSessionIdForAdapter;
398
+ runtimeSessionIdForAdapter = null;
399
+ runtimeSessionParamsForAdapter = null;
400
+ previousSessionDisplayId = null;
401
+ if (sessionCompaction.reason) {
402
+ runtimeWorkspaceWarnings.push(`Starting a fresh session because ${sessionCompaction.reason}.`);
403
+ }
404
+ }
405
+ else {
406
+ delete context.rudderSessionHandoffMarkdown;
407
+ delete context.rudderSessionRotationReason;
408
+ delete context.rudderPreviousSessionId;
409
+ }
410
+ const runtimeForAdapter = {
411
+ sessionId: runtimeSessionIdForAdapter,
412
+ sessionParams: runtimeSessionParamsForAdapter,
413
+ sessionDisplayId: previousSessionDisplayId,
414
+ taskKey,
415
+ };
416
+ let seq = 1;
417
+ let handle = null;
418
+ let stdoutExcerpt = "";
419
+ let stderrExcerpt = "";
420
+ let lastRunActivityTouchMs = 0;
421
+ const buildForbiddenMarkerScan = (resultJson = null) => detectForbiddenRuntimeSkillMarker({
422
+ markers: resolveForbiddenRuntimeSkillMarkers(runtimeConfig),
423
+ meta: adapterForbiddenMarkerObserved ? { forbiddenMarkerObserved: true } : latestAdapterMeta,
424
+ stdoutExcerpt,
425
+ stderrExcerpt,
426
+ resultJson,
427
+ transcript: executionTranscript,
428
+ });
429
+ const appendForbiddenMarkerEvent = async (eventRun, scan) => {
430
+ if (!scan.observed)
431
+ return;
432
+ await appendRunEvent(eventRun, seq++, {
433
+ eventType: "adapter.forbidden_marker",
434
+ stream: "system",
435
+ level: "error",
436
+ message: "forbidden runtime skill marker observed",
437
+ payload: {
438
+ source: "runtime_skill_isolation",
439
+ forbiddenMarkerObserved: true,
440
+ forbiddenMarkerCount: scan.evidence.length,
441
+ forbiddenMarkerEvidence: scan.evidence,
385
442
  },
386
443
  });
387
- const runtimeSessionParams = runtimeSessionResolution.sessionParams;
388
- const runtimeWorkspaceWarnings = [
389
- ...resolvedWorkspace.warnings,
390
- ...executionWorkspace.warnings,
391
- ...(runtimeSessionResolution.warning ? [runtimeSessionResolution.warning] : []),
392
- ...(resetTaskSession && sessionResetReason
393
- ? [
394
- taskKey
395
- ? `Skipping saved session resume for task "${taskKey}" because ${sessionResetReason}.`
396
- : `Skipping saved session resume because ${sessionResetReason}.`,
397
- ]
398
- : []),
399
- ];
400
- const runtimeScene = resolveRuntimeSceneForRun(run);
401
- const runtimeSceneContext = await runContextSvc.buildSceneContext({
402
- scene: runtimeScene,
403
- agent,
404
- resolvedWorkspace,
405
- runtimeConfig,
406
- issueId,
407
- executionWorkspaceMode,
408
- executionWorkspace: {
409
- cwd: executionWorkspace.cwd,
410
- source: executionWorkspace.source,
411
- strategy: executionWorkspace.strategy,
412
- projectId: executionWorkspace.projectId,
413
- workspaceId: executionWorkspace.workspaceId,
414
- repoUrl: executionWorkspace.repoUrl,
415
- repoRef: executionWorkspace.repoRef,
416
- branchName: executionWorkspace.branchName,
417
- worktreePath: executionWorkspace.worktreePath,
418
- },
444
+ };
445
+ try {
446
+ await preflightManagedAgentWorkspace({
447
+ agentHome: readNonEmptyString(runtimeSceneContext.rudderWorkspace.agentHome) ?? "",
448
+ instructionsDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.instructionsDir) ?? "",
449
+ memoryDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.memoryDir) ?? "",
450
+ lifeDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.lifeDir) ?? "",
451
+ skillsDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.agentSkillsDir) ?? "",
419
452
  });
420
- context.rudderScene = runtimeSceneContext.rudderScene;
421
- context.rudderWorkspace = runtimeSceneContext.rudderWorkspace;
422
- context.rudderWorkspaces = runtimeSceneContext.rudderWorkspaces;
423
- context.rudderStartupContext = runtimeSceneContext.rudderStartupContext;
424
- context.rudderStartupContextMetrics = runtimeSceneContext.rudderStartupContextMetrics;
425
- if (runtimeSceneContext.rudderRuntimeServiceIntents) {
426
- context.rudderRuntimeServiceIntents = runtimeSceneContext.rudderRuntimeServiceIntents;
427
- }
428
- else {
429
- delete context.rudderRuntimeServiceIntents;
430
- }
431
- if (executionWorkspace.projectId && !readNonEmptyString(context.projectId)) {
432
- context.projectId = executionWorkspace.projectId;
453
+ const startedAt = run.startedAt ?? new Date();
454
+ const runningWithSession = await db
455
+ .update(heartbeatRuns)
456
+ .set({
457
+ startedAt,
458
+ sessionIdBefore: runtimeForAdapter.sessionDisplayId ?? runtimeForAdapter.sessionId,
459
+ contextSnapshot: buildPersistableHeartbeatContext(context),
460
+ updatedAt: new Date(),
461
+ })
462
+ .where(eq(heartbeatRuns.id, run.id))
463
+ .returning()
464
+ .then((rows) => rows[0] ?? null);
465
+ if (runningWithSession)
466
+ run = runningWithSession;
467
+ const runningAgent = await db
468
+ .update(agents)
469
+ .set({ status: "running", updatedAt: new Date() })
470
+ .where(eq(agents.id, agent.id))
471
+ .returning()
472
+ .then((rows) => rows[0] ?? null);
473
+ if (runningAgent) {
474
+ publishLiveEvent({
475
+ orgId: runningAgent.orgId,
476
+ type: "agent.status",
477
+ payload: {
478
+ agentId: runningAgent.id,
479
+ status: runningAgent.status,
480
+ outcome: "running",
481
+ },
482
+ });
433
483
  }
434
- const runtimeSessionFallback = taskKey || resetTaskSession ? null : runtime.sessionId;
435
- let previousSessionDisplayId = truncateDisplayId(explicitResumeSessionDisplayId ??
436
- taskSessionForRun?.sessionDisplayId ??
437
- (sessionCodec.getDisplayId ? sessionCodec.getDisplayId(runtimeSessionParams) : null) ??
438
- readNonEmptyString(runtimeSessionParams?.sessionId) ??
439
- runtimeSessionFallback);
440
- let runtimeSessionIdForAdapter = readNonEmptyString(runtimeSessionParams?.sessionId) ?? runtimeSessionFallback;
441
- let runtimeSessionParamsForAdapter = runtimeSessionParams;
442
- const sessionCompaction = await evaluateSessionCompaction({
443
- agent,
444
- sessionId: previousSessionDisplayId ?? runtimeSessionIdForAdapter,
445
- issueId,
484
+ const currentRun = run;
485
+ await appendRunEvent(currentRun, seq++, {
486
+ eventType: "lifecycle",
487
+ stream: "system",
488
+ level: "info",
489
+ message: "run started",
446
490
  });
447
- if (sessionCompaction.rotate) {
448
- context.rudderSessionHandoffMarkdown = sessionCompaction.handoffMarkdown;
449
- context.rudderSessionRotationReason = sessionCompaction.reason;
450
- context.rudderPreviousSessionId = previousSessionDisplayId ?? runtimeSessionIdForAdapter;
451
- runtimeSessionIdForAdapter = null;
452
- runtimeSessionParamsForAdapter = null;
453
- previousSessionDisplayId = null;
454
- if (sessionCompaction.reason) {
455
- runtimeWorkspaceWarnings.push(`Starting a fresh session because ${sessionCompaction.reason}.`);
456
- }
457
- }
458
- else {
459
- delete context.rudderSessionHandoffMarkdown;
460
- delete context.rudderSessionRotationReason;
461
- delete context.rudderPreviousSessionId;
462
- }
463
- const runtimeForAdapter = {
464
- sessionId: runtimeSessionIdForAdapter,
465
- sessionParams: runtimeSessionParamsForAdapter,
466
- sessionDisplayId: previousSessionDisplayId,
467
- taskKey,
468
- };
469
- let seq = 1;
470
- let handle = null;
471
- let stdoutExcerpt = "";
472
- let stderrExcerpt = "";
473
- let lastRunActivityTouchMs = 0;
474
- const buildForbiddenMarkerScan = (resultJson = null) => detectForbiddenRuntimeSkillMarker({
475
- markers: resolveForbiddenRuntimeSkillMarkers(runtimeConfig),
476
- meta: adapterForbiddenMarkerObserved ? { forbiddenMarkerObserved: true } : latestAdapterMeta,
477
- stdoutExcerpt,
478
- stderrExcerpt,
479
- resultJson,
480
- transcript: executionTranscript,
491
+ handle = await runLogStore.begin({
492
+ orgId: run.orgId,
493
+ agentId: run.agentId,
494
+ runId,
481
495
  });
482
- const appendForbiddenMarkerEvent = async (eventRun, scan) => {
483
- if (!scan.observed)
484
- return;
485
- await appendRunEvent(eventRun, seq++, {
486
- eventType: "adapter.forbidden_marker",
487
- stream: "system",
488
- level: "error",
489
- message: "forbidden runtime skill marker observed",
496
+ await db
497
+ .update(heartbeatRuns)
498
+ .set({
499
+ logStore: handle.store,
500
+ logRef: handle.logRef,
501
+ updatedAt: new Date(),
502
+ })
503
+ .where(eq(heartbeatRuns.id, runId));
504
+ const adapter = getServerAdapter(agent.agentRuntimeType);
505
+ stdoutTranscriptParser = adapter.parseStdoutLine ?? null;
506
+ const currentUserRedactionOptions = await getCurrentUserRedactionOptions();
507
+ const onLog = async (stream, chunk) => {
508
+ const sanitizedChunk = redactCurrentUserText(chunk, currentUserRedactionOptions);
509
+ if (stream === "stdout")
510
+ stdoutExcerpt = appendExcerpt(stdoutExcerpt, sanitizedChunk);
511
+ if (stream === "stderr")
512
+ stderrExcerpt = appendExcerpt(stderrExcerpt, sanitizedChunk);
513
+ const ts = new Date().toISOString();
514
+ if (handle) {
515
+ await runLogStore.append(handle, {
516
+ stream,
517
+ chunk: sanitizedChunk,
518
+ ts,
519
+ });
520
+ }
521
+ const nowMs = Date.now();
522
+ if (nowMs - lastRunActivityTouchMs >= 30_000) {
523
+ lastRunActivityTouchMs = nowMs;
524
+ await db
525
+ .update(heartbeatRuns)
526
+ .set({ updatedAt: new Date(nowMs) })
527
+ .where(eq(heartbeatRuns.id, run.id));
528
+ }
529
+ const payloadChunk = sanitizedChunk.length > MAX_LIVE_LOG_CHUNK_BYTES
530
+ ? sanitizedChunk.slice(sanitizedChunk.length - MAX_LIVE_LOG_CHUNK_BYTES)
531
+ : sanitizedChunk;
532
+ publishLiveEvent({
533
+ orgId: run.orgId,
534
+ type: "heartbeat.run.log",
490
535
  payload: {
491
- source: "runtime_skill_isolation",
492
- forbiddenMarkerObserved: true,
493
- forbiddenMarkerCount: scan.evidence.length,
494
- forbiddenMarkerEvidence: scan.evidence,
536
+ runId: run.id,
537
+ agentId: run.agentId,
538
+ ts,
539
+ stream,
540
+ chunk: payloadChunk,
541
+ truncated: payloadChunk.length !== sanitizedChunk.length,
495
542
  },
496
543
  });
497
- };
498
- try {
499
- await preflightManagedAgentWorkspace({
500
- agentHome: readNonEmptyString(runtimeSceneContext.rudderWorkspace.agentHome) ?? "",
501
- instructionsDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.instructionsDir) ?? "",
502
- memoryDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.memoryDir) ?? "",
503
- lifeDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.lifeDir) ?? "",
504
- skillsDir: readNonEmptyString(runtimeSceneContext.rudderWorkspace.agentSkillsDir) ?? "",
544
+ if (stream === "stdout") {
545
+ stdoutTranscriptBuffer = appendTranscriptEntriesFromChunk({
546
+ buffer: stdoutTranscriptBuffer,
547
+ chunk: sanitizedChunk,
548
+ transcript: executionTranscript,
549
+ parser: stdoutTranscriptParser,
550
+ kind: "stdout",
551
+ });
552
+ return;
553
+ }
554
+ stderrTranscriptBuffer = appendTranscriptEntriesFromChunk({
555
+ buffer: stderrTranscriptBuffer,
556
+ chunk: sanitizedChunk,
557
+ transcript: executionTranscript,
558
+ kind: "stderr",
505
559
  });
506
- const startedAt = run.startedAt ?? new Date();
507
- const runningWithSession = await db
560
+ };
561
+ for (const warning of runtimeWorkspaceWarnings) {
562
+ const logEntry = formatRuntimeWorkspaceWarningLog(warning);
563
+ await onLog(logEntry.stream, logEntry.chunk);
564
+ }
565
+ const adapterEnv = Object.fromEntries(Object.entries(parseObject(resolvedConfig.env)).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
566
+ const runtimeServices = await ensureRuntimeServicesForRun({
567
+ db,
568
+ runId: run.id,
569
+ agent: {
570
+ id: agent.id,
571
+ name: agent.name,
572
+ orgId: agent.orgId,
573
+ },
574
+ issue: issueRef,
575
+ workspace: executionWorkspace,
576
+ executionWorkspaceId: persistedExecutionWorkspace?.id ?? issueRef?.executionWorkspaceId ?? null,
577
+ config: resolvedConfig,
578
+ adapterEnv,
579
+ onLog,
580
+ });
581
+ if (runtimeServices.length > 0) {
582
+ context.rudderRuntimeServices = runtimeServices;
583
+ context.rudderRuntimePrimaryUrl =
584
+ runtimeServices.find((service) => readNonEmptyString(service.url))?.url ?? null;
585
+ await db
508
586
  .update(heartbeatRuns)
509
587
  .set({
510
- startedAt,
511
- sessionIdBefore: runtimeForAdapter.sessionDisplayId ?? runtimeForAdapter.sessionId,
512
588
  contextSnapshot: buildPersistableHeartbeatContext(context),
513
589
  updatedAt: new Date(),
514
590
  })
515
- .where(eq(heartbeatRuns.id, run.id))
516
- .returning()
517
- .then((rows) => rows[0] ?? null);
518
- if (runningWithSession)
519
- run = runningWithSession;
520
- const runningAgent = await db
521
- .update(agents)
522
- .set({ status: "running", updatedAt: new Date() })
523
- .where(eq(agents.id, agent.id))
524
- .returning()
525
- .then((rows) => rows[0] ?? null);
526
- if (runningAgent) {
527
- publishLiveEvent({
528
- orgId: runningAgent.orgId,
529
- type: "agent.status",
530
- payload: {
531
- agentId: runningAgent.id,
532
- status: runningAgent.status,
533
- outcome: "running",
534
- },
535
- });
591
+ .where(eq(heartbeatRuns.id, run.id));
592
+ }
593
+ if (issueId && (executionWorkspace.created || runtimeServices.some((service) => !service.reused))) {
594
+ try {
595
+ await issuesSvc.addComment(issueId, buildWorkspaceReadyComment({
596
+ workspace: executionWorkspace,
597
+ runtimeServices,
598
+ }), { agentId: agent.id });
599
+ }
600
+ catch (err) {
601
+ await onLog("stderr", `[rudder] Failed to post workspace-ready comment: ${err instanceof Error ? err.message : String(err)}\n`);
602
+ }
603
+ }
604
+ const onAdapterMeta = async (meta) => {
605
+ latestAdapterMeta = meta;
606
+ adapterForbiddenMarkerObserved ||= meta.forbiddenMarkerObserved === true;
607
+ if (meta.env && secretKeys.size > 0) {
608
+ for (const key of secretKeys) {
609
+ if (key in meta.env)
610
+ meta.env[key] = "***REDACTED***";
611
+ }
536
612
  }
537
- const currentRun = run;
538
613
  await appendRunEvent(currentRun, seq++, {
539
- eventType: "lifecycle",
614
+ eventType: "adapter.invoke",
540
615
  stream: "system",
541
616
  level: "info",
542
- message: "run started",
543
- });
544
- handle = await runLogStore.begin({
545
- orgId: run.orgId,
546
- agentId: run.agentId,
547
- runId,
617
+ message: "adapter invocation",
618
+ payload: buildHeartbeatAdapterInvokePayload({
619
+ meta,
620
+ runtimeSkills: runtimeSkillEntries,
621
+ }),
548
622
  });
549
- await db
550
- .update(heartbeatRuns)
551
- .set({
552
- logStore: handle.store,
553
- logRef: handle.logRef,
554
- updatedAt: new Date(),
555
- })
556
- .where(eq(heartbeatRuns.id, runId));
557
- const adapter = getServerAdapter(agent.agentRuntimeType);
558
- stdoutTranscriptParser = adapter.parseStdoutLine ?? null;
559
- const currentUserRedactionOptions = await getCurrentUserRedactionOptions();
560
- const onLog = async (stream, chunk) => {
561
- const sanitizedChunk = redactCurrentUserText(chunk, currentUserRedactionOptions);
562
- if (stream === "stdout")
563
- stdoutExcerpt = appendExcerpt(stdoutExcerpt, sanitizedChunk);
564
- if (stream === "stderr")
565
- stderrExcerpt = appendExcerpt(stderrExcerpt, sanitizedChunk);
566
- const ts = new Date().toISOString();
567
- if (handle) {
568
- await runLogStore.append(handle, {
569
- stream,
570
- chunk: sanitizedChunk,
571
- ts,
572
- });
573
- }
574
- const nowMs = Date.now();
575
- if (nowMs - lastRunActivityTouchMs >= 30_000) {
576
- lastRunActivityTouchMs = nowMs;
577
- await db
578
- .update(heartbeatRuns)
579
- .set({ updatedAt: new Date(nowMs) })
580
- .where(eq(heartbeatRuns.id, run.id));
581
- }
582
- const payloadChunk = sanitizedChunk.length > MAX_LIVE_LOG_CHUNK_BYTES
583
- ? sanitizedChunk.slice(sanitizedChunk.length - MAX_LIVE_LOG_CHUNK_BYTES)
584
- : sanitizedChunk;
585
- publishLiveEvent({
586
- orgId: run.orgId,
587
- type: "heartbeat.run.log",
588
- payload: {
589
- runId: run.id,
590
- agentId: run.agentId,
591
- ts,
592
- stream,
593
- chunk: payloadChunk,
594
- truncated: payloadChunk.length !== sanitizedChunk.length,
595
- },
596
- });
597
- if (stream === "stdout") {
598
- stdoutTranscriptBuffer = appendTranscriptEntriesFromChunk({
599
- buffer: stdoutTranscriptBuffer,
600
- chunk: sanitizedChunk,
601
- transcript: executionTranscript,
602
- parser: stdoutTranscriptParser,
603
- kind: "stdout",
604
- });
605
- return;
606
- }
607
- stderrTranscriptBuffer = appendTranscriptEntriesFromChunk({
608
- buffer: stderrTranscriptBuffer,
609
- chunk: sanitizedChunk,
610
- transcript: executionTranscript,
611
- kind: "stderr",
612
- });
613
- };
614
- for (const warning of runtimeWorkspaceWarnings) {
615
- const logEntry = formatRuntimeWorkspaceWarningLog(warning);
616
- await onLog(logEntry.stream, logEntry.chunk);
617
- }
618
- const adapterEnv = Object.fromEntries(Object.entries(parseObject(resolvedConfig.env)).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
619
- const runtimeServices = await ensureRuntimeServicesForRun({
623
+ };
624
+ const authToken = adapter.supportsLocalAgentJwt
625
+ ? createLocalAgentJwt(agent.id, agent.orgId, agent.agentRuntimeType, run.id)
626
+ : null;
627
+ if (adapter.supportsLocalAgentJwt && !authToken) {
628
+ logger.warn({
629
+ orgId: agent.orgId,
630
+ agentId: agent.id,
631
+ runId: run.id,
632
+ agentRuntimeType: agent.agentRuntimeType,
633
+ }, "local agent jwt secret missing or invalid; running without injected RUDDER_API_KEY");
634
+ }
635
+ const adapterResult = await executeAdapterWithModelFallbacks(adapter, {
636
+ runId: run.id,
637
+ agent,
638
+ runtime: runtimeForAdapter,
639
+ config: runtimeConfig,
640
+ context,
641
+ onLog,
642
+ onMeta: onAdapterMeta,
643
+ onSpawn: async (meta) => {
644
+ await persistRunProcessMetadata(run.id, meta);
645
+ },
646
+ authToken: authToken ?? undefined,
647
+ }, {
648
+ resolveAdapter: findServerAdapter,
649
+ createAuthToken: (agentRuntimeType) => createLocalAgentJwt(agent.id, agent.orgId, agentRuntimeType, run.id) ?? undefined,
650
+ onAttemptStart: (_attempt, attemptAdapter) => {
651
+ stdoutTranscriptParser = attemptAdapter.parseStdoutLine ?? null;
652
+ },
653
+ });
654
+ const adapterManagedRuntimeServices = adapterResult.runtimeServices
655
+ ? await persistAdapterManagedRuntimeServices({
620
656
  db,
657
+ agentRuntimeType: agent.agentRuntimeType,
621
658
  runId: run.id,
622
659
  agent: {
623
660
  id: agent.id,
@@ -626,478 +663,341 @@ export function createHeartbeatExecuteHandlers(context) {
626
663
  },
627
664
  issue: issueRef,
628
665
  workspace: executionWorkspace,
629
- executionWorkspaceId: persistedExecutionWorkspace?.id ?? issueRef?.executionWorkspaceId ?? null,
630
- config: resolvedConfig,
631
- adapterEnv,
632
- onLog,
633
- });
634
- if (runtimeServices.length > 0) {
635
- context.rudderRuntimeServices = runtimeServices;
636
- context.rudderRuntimePrimaryUrl =
637
- runtimeServices.find((service) => readNonEmptyString(service.url))?.url ?? null;
638
- await db
639
- .update(heartbeatRuns)
640
- .set({
641
- contextSnapshot: buildPersistableHeartbeatContext(context),
642
- updatedAt: new Date(),
643
- })
644
- .where(eq(heartbeatRuns.id, run.id));
645
- }
646
- if (issueId && (executionWorkspace.created || runtimeServices.some((service) => !service.reused))) {
666
+ reports: adapterResult.runtimeServices,
667
+ })
668
+ : [];
669
+ if (adapterManagedRuntimeServices.length > 0) {
670
+ const combinedRuntimeServices = [
671
+ ...runtimeServices,
672
+ ...adapterManagedRuntimeServices,
673
+ ];
674
+ context.rudderRuntimeServices = combinedRuntimeServices;
675
+ context.rudderRuntimePrimaryUrl =
676
+ combinedRuntimeServices.find((service) => readNonEmptyString(service.url))?.url ?? null;
677
+ await db
678
+ .update(heartbeatRuns)
679
+ .set({
680
+ contextSnapshot: buildPersistableHeartbeatContext(context),
681
+ updatedAt: new Date(),
682
+ })
683
+ .where(eq(heartbeatRuns.id, run.id));
684
+ if (issueId) {
647
685
  try {
648
686
  await issuesSvc.addComment(issueId, buildWorkspaceReadyComment({
649
687
  workspace: executionWorkspace,
650
- runtimeServices,
688
+ runtimeServices: adapterManagedRuntimeServices,
651
689
  }), { agentId: agent.id });
652
690
  }
653
691
  catch (err) {
654
- await onLog("stderr", `[rudder] Failed to post workspace-ready comment: ${err instanceof Error ? err.message : String(err)}\n`);
692
+ await onLog("stderr", `[rudder] Failed to post adapter-managed runtime comment: ${err instanceof Error ? err.message : String(err)}\n`);
655
693
  }
656
694
  }
657
- const onAdapterMeta = async (meta) => {
658
- latestAdapterMeta = meta;
659
- adapterForbiddenMarkerObserved ||= meta.forbiddenMarkerObserved === true;
660
- if (meta.env && secretKeys.size > 0) {
661
- for (const key of secretKeys) {
662
- if (key in meta.env)
663
- meta.env[key] = "***REDACTED***";
664
- }
665
- }
666
- modelTurnInput = sanitizeStartupContextPromptForPersistence(meta.prompt);
667
- heartbeatObservationContext.metadata = {
668
- ...(heartbeatObservationContext.metadata ?? {}),
669
- ...buildHeartbeatRuntimeTraceMetadata({
670
- runtimeConfig,
671
- runtimeSkills: runtimeSkillEntries,
672
- adapterMeta: meta,
673
- }),
674
- };
675
- updateExecutionObservation(observation, heartbeatObservationContext, {
676
- input: rootObservationInput,
677
- });
678
- await appendRunEvent(currentRun, seq++, {
679
- eventType: "adapter.invoke",
680
- stream: "system",
681
- level: "info",
682
- message: "adapter invocation",
683
- payload: buildHeartbeatAdapterInvokePayload({
684
- meta,
685
- runtimeSkills: runtimeSkillEntries,
686
- }),
687
- });
688
- };
689
- const authToken = adapter.supportsLocalAgentJwt
690
- ? createLocalAgentJwt(agent.id, agent.orgId, agent.agentRuntimeType, run.id)
691
- : null;
692
- if (adapter.supportsLocalAgentJwt && !authToken) {
693
- logger.warn({
694
- orgId: agent.orgId,
695
- agentId: agent.id,
696
- runId: run.id,
697
- agentRuntimeType: agent.agentRuntimeType,
698
- }, "local agent jwt secret missing or invalid; running without injected RUDDER_API_KEY");
699
- }
700
- const adapterResult = await executeAdapterWithModelFallbacks(adapter, {
701
- runId: run.id,
702
- agent,
703
- runtime: runtimeForAdapter,
704
- config: runtimeConfig,
705
- context,
706
- onLog,
707
- onMeta: onAdapterMeta,
708
- onSpawn: async (meta) => {
709
- await persistRunProcessMetadata(run.id, meta);
710
- },
711
- authToken: authToken ?? undefined,
712
- }, {
713
- resolveAdapter: findServerAdapter,
714
- createAuthToken: (agentRuntimeType) => createLocalAgentJwt(agent.id, agent.orgId, agentRuntimeType, run.id) ?? undefined,
715
- onAttemptStart: (_attempt, attemptAdapter) => {
716
- stdoutTranscriptParser = attemptAdapter.parseStdoutLine ?? null;
717
- },
718
- });
719
- const adapterManagedRuntimeServices = adapterResult.runtimeServices
720
- ? await persistAdapterManagedRuntimeServices({
721
- db,
722
- agentRuntimeType: agent.agentRuntimeType,
723
- runId: run.id,
724
- agent: {
725
- id: agent.id,
726
- name: agent.name,
727
- orgId: agent.orgId,
728
- },
729
- issue: issueRef,
730
- workspace: executionWorkspace,
731
- reports: adapterResult.runtimeServices,
732
- })
733
- : [];
734
- if (adapterManagedRuntimeServices.length > 0) {
735
- const combinedRuntimeServices = [
736
- ...runtimeServices,
737
- ...adapterManagedRuntimeServices,
738
- ];
739
- context.rudderRuntimeServices = combinedRuntimeServices;
740
- context.rudderRuntimePrimaryUrl =
741
- combinedRuntimeServices.find((service) => readNonEmptyString(service.url))?.url ?? null;
742
- await db
743
- .update(heartbeatRuns)
744
- .set({
745
- contextSnapshot: buildPersistableHeartbeatContext(context),
746
- updatedAt: new Date(),
747
- })
748
- .where(eq(heartbeatRuns.id, run.id));
749
- if (issueId) {
750
- try {
751
- await issuesSvc.addComment(issueId, buildWorkspaceReadyComment({
752
- workspace: executionWorkspace,
753
- runtimeServices: adapterManagedRuntimeServices,
754
- }), { agentId: agent.id });
755
- }
756
- catch (err) {
757
- await onLog("stderr", `[rudder] Failed to post adapter-managed runtime comment: ${err instanceof Error ? err.message : String(err)}\n`);
758
- }
759
- }
760
- }
761
- const nextSessionState = resolveNextSessionState({
762
- codec: sessionCodec,
763
- adapterResult,
764
- previousParams: previousSessionParams,
765
- previousDisplayId: runtimeForAdapter.sessionDisplayId,
766
- previousLegacySessionId: runtimeForAdapter.sessionId,
767
- });
768
- const rawUsage = normalizeUsageTotals(adapterResult.usage);
769
- const sessionUsageResolution = await resolveNormalizedUsageForSession({
770
- agentId: agent.id,
771
- runId: run.id,
772
- sessionId: nextSessionState.displayId ?? nextSessionState.legacySessionId,
773
- rawUsage,
774
- });
775
- const normalizedUsage = sessionUsageResolution.normalizedUsage;
776
- const forbiddenMarkerScan = buildForbiddenMarkerScan(adapterResult.resultJson ?? null);
777
- let outcome;
778
- const adapterWouldHaveSucceeded = (adapterResult.exitCode ?? 0) === 0 && !adapterResult.errorMessage;
779
- const latestRun = await getRun(run.id);
780
- if (latestRun?.status === "cancelled") {
781
- outcome = "cancelled";
782
- }
783
- else if (latestRun?.status === "timed_out") {
784
- outcome = "timed_out";
785
- }
786
- else if (adapterResult.timedOut) {
787
- outcome = "timed_out";
788
- }
789
- else if (forbiddenMarkerScan.observed && adapterWouldHaveSucceeded) {
790
- outcome = "failed";
791
- }
792
- else if (adapterWouldHaveSucceeded) {
793
- outcome = "succeeded";
794
- }
795
- else {
796
- outcome = "failed";
797
- }
798
- const failureCausedByForbiddenMarker = outcome === "failed" && forbiddenMarkerScan.observed && adapterWouldHaveSucceeded;
799
- let logSummary = null;
800
- if (handle) {
801
- logSummary = await runLogStore.finalize(handle);
695
+ }
696
+ const nextSessionState = resolveNextSessionState({
697
+ codec: sessionCodec,
698
+ adapterResult,
699
+ previousParams: previousSessionParams,
700
+ previousDisplayId: runtimeForAdapter.sessionDisplayId,
701
+ previousLegacySessionId: runtimeForAdapter.sessionId,
702
+ });
703
+ const rawUsage = normalizeUsageTotals(adapterResult.usage);
704
+ const sessionUsageResolution = await resolveNormalizedUsageForSession({
705
+ agentId: agent.id,
706
+ runId: run.id,
707
+ sessionId: nextSessionState.displayId ?? nextSessionState.legacySessionId,
708
+ rawUsage,
709
+ });
710
+ const normalizedUsage = sessionUsageResolution.normalizedUsage;
711
+ const forbiddenMarkerScan = buildForbiddenMarkerScan(adapterResult.resultJson ?? null);
712
+ let outcome;
713
+ const adapterWouldHaveSucceeded = (adapterResult.exitCode ?? 0) === 0 && !adapterResult.errorMessage;
714
+ const latestRun = await getRun(run.id);
715
+ if (latestRun?.status === "cancelled") {
716
+ outcome = "cancelled";
717
+ }
718
+ else if (latestRun?.status === "timed_out") {
719
+ outcome = "timed_out";
720
+ }
721
+ else if (adapterResult.timedOut) {
722
+ outcome = "timed_out";
723
+ }
724
+ else if (forbiddenMarkerScan.observed && adapterWouldHaveSucceeded) {
725
+ outcome = "failed";
726
+ }
727
+ else if (adapterWouldHaveSucceeded) {
728
+ outcome = "succeeded";
729
+ }
730
+ else {
731
+ outcome = "failed";
732
+ }
733
+ const failureCausedByForbiddenMarker = outcome === "failed" && forbiddenMarkerScan.observed && adapterWouldHaveSucceeded;
734
+ let logSummary = null;
735
+ if (handle) {
736
+ logSummary = await runLogStore.finalize(handle);
737
+ }
738
+ const status = outcome === "succeeded"
739
+ ? "succeeded"
740
+ : outcome === "cancelled"
741
+ ? "cancelled"
742
+ : outcome === "timed_out"
743
+ ? "timed_out"
744
+ : "failed";
745
+ finalRunStatus = status;
746
+ const adapterResultSummary = summarizeHeartbeatRunResultJson(adapterResult.resultJson);
747
+ transcriptFallbackResult = {
748
+ ts: new Date().toISOString(),
749
+ model: readNonEmptyString(adapterResult.model),
750
+ output: readNonEmptyString(adapterResult.summary)
751
+ ?? readNonEmptyString(adapterResultSummary?.result)
752
+ ?? readNonEmptyString(adapterResultSummary?.summary)
753
+ ?? readNonEmptyString(adapterResultSummary?.message)
754
+ ?? null,
755
+ usage: adapterResult.usage ?? null,
756
+ costUsd: typeof adapterResult.costUsd === "number" ? adapterResult.costUsd : null,
757
+ subtype: status,
758
+ isError: outcome !== "succeeded",
759
+ errors: adapterResult.errorMessage ? [adapterResult.errorMessage] : [],
760
+ };
761
+ const usageJson = normalizedUsage || adapterResult.costUsd != null
762
+ ? {
763
+ ...(normalizedUsage ?? {}),
764
+ ...(rawUsage ? {
765
+ rawInputTokens: rawUsage.inputTokens,
766
+ rawCachedInputTokens: rawUsage.cachedInputTokens,
767
+ rawOutputTokens: rawUsage.outputTokens,
768
+ } : {}),
769
+ ...(sessionUsageResolution.derivedFromSessionTotals ? { usageSource: "session_delta" } : {}),
770
+ ...((nextSessionState.displayId ?? nextSessionState.legacySessionId)
771
+ ? { persistedSessionId: nextSessionState.displayId ?? nextSessionState.legacySessionId }
772
+ : {}),
773
+ sessionReused: runtimeForAdapter.sessionId != null || runtimeForAdapter.sessionDisplayId != null,
774
+ taskSessionReused: taskSessionForRun != null,
775
+ freshSession: runtimeForAdapter.sessionId == null && runtimeForAdapter.sessionDisplayId == null,
776
+ sessionRotated: sessionCompaction.rotate,
777
+ sessionRotationReason: sessionCompaction.reason,
778
+ provider: readNonEmptyString(adapterResult.provider) ?? "unknown",
779
+ biller: resolveLedgerBiller(adapterResult),
780
+ model: readNonEmptyString(adapterResult.model) ?? "unknown",
781
+ ...(adapterResult.costUsd != null ? { costUsd: adapterResult.costUsd } : {}),
782
+ billingType: normalizeLedgerBillingType(adapterResult.billingType),
802
783
  }
803
- const status = outcome === "succeeded"
804
- ? "succeeded"
805
- : outcome === "cancelled"
806
- ? "cancelled"
807
- : outcome === "timed_out"
808
- ? "timed_out"
809
- : "failed";
810
- heartbeatObservationContext.status = status;
811
- finalObservationStatus = status;
812
- finalObservationSessionId = nextSessionState.displayId ?? nextSessionState.legacySessionId ?? finalObservationSessionId;
813
- const adapterResultSummary = summarizeHeartbeatRunResultJson(adapterResult.resultJson);
814
- transcriptFallbackResult = {
815
- ts: new Date().toISOString(),
816
- model: readNonEmptyString(adapterResult.model),
817
- output: readNonEmptyString(adapterResult.summary)
818
- ?? readNonEmptyString(adapterResultSummary?.result)
819
- ?? readNonEmptyString(adapterResultSummary?.summary)
820
- ?? readNonEmptyString(adapterResultSummary?.message)
821
- ?? null,
822
- usage: adapterResult.usage ?? null,
823
- costUsd: typeof adapterResult.costUsd === "number" ? adapterResult.costUsd : null,
824
- subtype: status,
825
- isError: outcome !== "succeeded",
826
- errors: adapterResult.errorMessage ? [adapterResult.errorMessage] : [],
827
- };
828
- const usageJson = normalizedUsage || adapterResult.costUsd != null
829
- ? {
830
- ...(normalizedUsage ?? {}),
831
- ...(rawUsage ? {
832
- rawInputTokens: rawUsage.inputTokens,
833
- rawCachedInputTokens: rawUsage.cachedInputTokens,
834
- rawOutputTokens: rawUsage.outputTokens,
835
- } : {}),
836
- ...(sessionUsageResolution.derivedFromSessionTotals ? { usageSource: "session_delta" } : {}),
837
- ...((nextSessionState.displayId ?? nextSessionState.legacySessionId)
838
- ? { persistedSessionId: nextSessionState.displayId ?? nextSessionState.legacySessionId }
839
- : {}),
840
- sessionReused: runtimeForAdapter.sessionId != null || runtimeForAdapter.sessionDisplayId != null,
841
- taskSessionReused: taskSessionForRun != null,
842
- freshSession: runtimeForAdapter.sessionId == null && runtimeForAdapter.sessionDisplayId == null,
843
- sessionRotated: sessionCompaction.rotate,
844
- sessionRotationReason: sessionCompaction.reason,
845
- provider: readNonEmptyString(adapterResult.provider) ?? "unknown",
846
- biller: resolveLedgerBiller(adapterResult),
847
- model: readNonEmptyString(adapterResult.model) ?? "unknown",
848
- ...(adapterResult.costUsd != null ? { costUsd: adapterResult.costUsd } : {}),
849
- billingType: normalizeLedgerBillingType(adapterResult.billingType),
850
- }
851
- : null;
852
- await setRunStatus(run.id, status, {
853
- finishedAt: new Date(),
854
- error: outcome === "succeeded"
855
- ? null
856
- : redactCurrentUserText(failureCausedByForbiddenMarker
857
- ? "Forbidden runtime skill marker observed"
858
- : adapterResult.errorMessage ?? (outcome === "timed_out" ? "Timed out" : "Adapter failed"), currentUserRedactionOptions),
859
- errorCode: failureCausedByForbiddenMarker
860
- ? "runtime_skill_isolation_failed"
861
- : outcome === "timed_out"
862
- ? "timeout"
863
- : outcome === "cancelled"
864
- ? "cancelled"
865
- : outcome === "failed"
866
- ? (adapterResult.errorCode ?? "adapter_failed")
867
- : null,
868
- exitCode: adapterResult.exitCode,
869
- signal: adapterResult.signal,
870
- usageJson,
871
- resultJson: adapterResult.resultJson ?? null,
872
- sessionIdAfter: nextSessionState.displayId ?? nextSessionState.legacySessionId,
873
- stdoutExcerpt,
874
- stderrExcerpt,
875
- logBytes: logSummary?.bytes,
876
- logSha256: logSummary?.sha256,
877
- logCompressed: logSummary?.compressed ?? false,
878
- });
879
- await setWakeupStatus(run.wakeupRequestId, outcome === "succeeded" ? "completed" : status, {
880
- finishedAt: new Date(),
881
- error: failureCausedByForbiddenMarker
784
+ : null;
785
+ await setRunStatus(run.id, status, {
786
+ finishedAt: new Date(),
787
+ error: outcome === "succeeded"
788
+ ? null
789
+ : redactCurrentUserText(failureCausedByForbiddenMarker
882
790
  ? "Forbidden runtime skill marker observed"
883
- : adapterResult.errorMessage ?? null,
884
- });
885
- const finalizedRun = await getRun(run.id);
886
- if (finalizedRun) {
887
- await appendForbiddenMarkerEvent(finalizedRun, forbiddenMarkerScan);
888
- const transcriptUsedSkills = inferUsedSkillsFromTranscript(executionTranscript);
889
- if (transcriptUsedSkills.length > 0) {
890
- await appendRunEvent(finalizedRun, seq++, {
891
- eventType: "adapter.skill_usage",
892
- stream: "system",
893
- level: "info",
894
- message: "skill usage inferred from transcript",
895
- payload: {
896
- source: "transcript.skill_usage",
897
- usedSkillCount: transcriptUsedSkills.length,
898
- usedSkillKeys: transcriptUsedSkills.map((entry) => entry.key),
899
- usedSkills: transcriptUsedSkills,
900
- skillEvidenceType: "used",
901
- skillEvidenceCount: transcriptUsedSkills.length,
902
- skillEvidenceKeys: transcriptUsedSkills.map((entry) => entry.key),
903
- skillEvidenceSkills: transcriptUsedSkills,
904
- },
905
- });
906
- }
791
+ : adapterResult.errorMessage ?? (outcome === "timed_out" ? "Timed out" : "Adapter failed"), currentUserRedactionOptions),
792
+ errorCode: failureCausedByForbiddenMarker
793
+ ? "runtime_skill_isolation_failed"
794
+ : outcome === "timed_out"
795
+ ? "timeout"
796
+ : outcome === "cancelled"
797
+ ? "cancelled"
798
+ : outcome === "failed"
799
+ ? (adapterResult.errorCode ?? "adapter_failed")
800
+ : null,
801
+ exitCode: adapterResult.exitCode,
802
+ signal: adapterResult.signal,
803
+ usageJson,
804
+ resultJson: adapterResult.resultJson ?? null,
805
+ sessionIdAfter: nextSessionState.displayId ?? nextSessionState.legacySessionId,
806
+ stdoutExcerpt,
807
+ stderrExcerpt,
808
+ logBytes: logSummary?.bytes,
809
+ logSha256: logSummary?.sha256,
810
+ logCompressed: logSummary?.compressed ?? false,
811
+ });
812
+ await setWakeupStatus(run.wakeupRequestId, outcome === "succeeded" ? "completed" : status, {
813
+ finishedAt: new Date(),
814
+ error: failureCausedByForbiddenMarker
815
+ ? "Forbidden runtime skill marker observed"
816
+ : adapterResult.errorMessage ?? null,
817
+ });
818
+ const finalizedRun = await getRun(run.id);
819
+ if (finalizedRun) {
820
+ await appendForbiddenMarkerEvent(finalizedRun, forbiddenMarkerScan);
821
+ const transcriptUsedSkills = inferUsedSkillsFromTranscript(executionTranscript);
822
+ if (transcriptUsedSkills.length > 0) {
907
823
  await appendRunEvent(finalizedRun, seq++, {
908
- eventType: "lifecycle",
824
+ eventType: "adapter.skill_usage",
909
825
  stream: "system",
910
- level: outcome === "succeeded" ? "info" : "error",
911
- message: `run ${outcome}`,
826
+ level: "info",
827
+ message: "skill usage inferred from transcript",
912
828
  payload: {
913
- status,
914
- exitCode: adapterResult.exitCode,
829
+ source: "transcript.skill_usage",
830
+ usedSkillCount: transcriptUsedSkills.length,
831
+ usedSkillKeys: transcriptUsedSkills.map((entry) => entry.key),
832
+ usedSkills: transcriptUsedSkills,
833
+ skillEvidenceType: "used",
834
+ skillEvidenceCount: transcriptUsedSkills.length,
835
+ skillEvidenceKeys: transcriptUsedSkills.map((entry) => entry.key),
836
+ skillEvidenceSkills: transcriptUsedSkills,
915
837
  },
916
838
  });
917
- await releaseIssueExecutionAndPromote(finalizedRun);
918
839
  }
919
- if (finalizedRun) {
920
- await updateRuntimeState(agent, finalizedRun, adapterResult, {
921
- legacySessionId: nextSessionState.legacySessionId,
922
- }, normalizedUsage);
923
- if (taskKey) {
924
- if (adapterResult.clearSession || (!nextSessionState.params && !nextSessionState.displayId)) {
925
- await clearTaskSessions(agent.orgId, agent.id, {
926
- taskKey,
927
- agentRuntimeType: agent.agentRuntimeType,
928
- });
929
- }
930
- else {
931
- await upsertTaskSession({
932
- orgId: agent.orgId,
933
- agentId: agent.id,
934
- agentRuntimeType: agent.agentRuntimeType,
935
- taskKey,
936
- sessionParamsJson: nextSessionState.params,
937
- sessionDisplayId: nextSessionState.displayId,
938
- lastRunId: finalizedRun.id,
939
- lastError: outcome === "succeeded" ? null : (adapterResult.errorMessage ?? "run_failed"),
940
- });
941
- }
840
+ await appendRunEvent(finalizedRun, seq++, {
841
+ eventType: "lifecycle",
842
+ stream: "system",
843
+ level: outcome === "succeeded" ? "info" : "error",
844
+ message: `run ${outcome}`,
845
+ payload: {
846
+ status,
847
+ exitCode: adapterResult.exitCode,
848
+ },
849
+ });
850
+ await releaseIssueExecutionAndPromote(finalizedRun);
851
+ }
852
+ if (finalizedRun) {
853
+ await updateRuntimeState(agent, finalizedRun, adapterResult, {
854
+ legacySessionId: nextSessionState.legacySessionId,
855
+ }, normalizedUsage);
856
+ if (taskKey) {
857
+ if (adapterResult.clearSession || (!nextSessionState.params && !nextSessionState.displayId)) {
858
+ await clearTaskSessions(agent.orgId, agent.id, {
859
+ taskKey,
860
+ agentRuntimeType: agent.agentRuntimeType,
861
+ });
862
+ }
863
+ else {
864
+ await upsertTaskSession({
865
+ orgId: agent.orgId,
866
+ agentId: agent.id,
867
+ agentRuntimeType: agent.agentRuntimeType,
868
+ taskKey,
869
+ sessionParamsJson: nextSessionState.params,
870
+ sessionDisplayId: nextSessionState.displayId,
871
+ lastRunId: finalizedRun.id,
872
+ lastError: outcome === "succeeded" ? null : (adapterResult.errorMessage ?? "run_failed"),
873
+ });
942
874
  }
943
- await emitHeartbeatLiveEval(finalizedRun.id);
944
875
  }
945
- await finalizeAgentStatus(agent.id, outcome);
946
876
  }
947
- catch (err) {
948
- const isWorkspacePreflightFailure = isWorkspacePermissionPreflightError(err) ||
949
- isManagedWorkspaceConfigurationError(err);
950
- const message = redactCurrentUserText(err instanceof Error ? err.message : "Unknown adapter failure", await getCurrentUserRedactionOptions());
951
- heartbeatObservationContext.status = "failed";
952
- finalObservationStatus = "failed";
877
+ await finalizeAgentStatus(agent.id, outcome);
878
+ }
879
+ catch (err) {
880
+ const isWorkspacePreflightFailure = isWorkspacePermissionPreflightError(err) ||
881
+ isManagedWorkspaceConfigurationError(err);
882
+ const message = redactCurrentUserText(err instanceof Error ? err.message : "Unknown adapter failure", await getCurrentUserRedactionOptions());
883
+ finalRunStatus = "failed";
884
+ transcriptFallbackResult = {
885
+ ts: new Date().toISOString(),
886
+ output: message,
887
+ subtype: "failed",
888
+ isError: true,
889
+ errors: [message],
890
+ };
891
+ logger.error({ err, runId }, "heartbeat execution failed");
892
+ const latestRun = await getRun(run.id);
893
+ if (latestRun?.status === "cancelled" || latestRun?.status === "timed_out") {
894
+ const terminalStatus = latestRun.status;
895
+ finalRunStatus = terminalStatus;
953
896
  transcriptFallbackResult = {
954
897
  ts: new Date().toISOString(),
955
- output: message,
956
- subtype: "failed",
957
- isError: true,
958
- errors: [message],
898
+ output: latestRun.error ?? message,
899
+ subtype: terminalStatus,
900
+ isError: terminalStatus === "timed_out",
901
+ errors: latestRun.error ? [latestRun.error] : [],
959
902
  };
960
- logger.error({ err, runId }, "heartbeat execution failed");
961
- const latestRun = await getRun(run.id);
962
- if (latestRun?.status === "cancelled" || latestRun?.status === "timed_out") {
963
- const terminalStatus = latestRun.status;
964
- heartbeatObservationContext.status = terminalStatus;
965
- finalObservationStatus = terminalStatus;
966
- transcriptFallbackResult = {
967
- ts: new Date().toISOString(),
968
- output: latestRun.error ?? message,
969
- subtype: terminalStatus,
970
- isError: terminalStatus === "timed_out",
971
- errors: latestRun.error ? [latestRun.error] : [],
972
- };
973
- await emitHeartbeatLiveEval(latestRun.id);
974
- await finalizeAgentStatus(agent.id, terminalStatus);
975
- return;
903
+ await finalizeAgentStatus(agent.id, terminalStatus);
904
+ return;
905
+ }
906
+ let logSummary = null;
907
+ if (handle) {
908
+ try {
909
+ logSummary = await runLogStore.finalize(handle);
976
910
  }
977
- let logSummary = null;
978
- if (handle) {
979
- try {
980
- logSummary = await runLogStore.finalize(handle);
981
- }
982
- catch (finalizeErr) {
983
- logger.warn({ err: finalizeErr, runId }, "failed to finalize run log after error");
984
- }
911
+ catch (finalizeErr) {
912
+ logger.warn({ err: finalizeErr, runId }, "failed to finalize run log after error");
985
913
  }
986
- const failedRun = await setRunStatus(run.id, "failed", {
987
- error: message,
988
- errorCode: isWorkspacePreflightFailure ? err.errorCode : "adapter_failed",
989
- finishedAt: new Date(),
990
- stdoutExcerpt,
991
- stderrExcerpt,
992
- logBytes: logSummary?.bytes,
993
- logSha256: logSummary?.sha256,
994
- logCompressed: logSummary?.compressed ?? false,
995
- });
996
- await setWakeupStatus(run.wakeupRequestId, "failed", {
997
- finishedAt: new Date(),
998
- error: message,
914
+ }
915
+ const failedRun = await setRunStatus(run.id, "failed", {
916
+ error: message,
917
+ errorCode: isWorkspacePreflightFailure ? err.errorCode : "adapter_failed",
918
+ finishedAt: new Date(),
919
+ stdoutExcerpt,
920
+ stderrExcerpt,
921
+ logBytes: logSummary?.bytes,
922
+ logSha256: logSummary?.sha256,
923
+ logCompressed: logSummary?.compressed ?? false,
924
+ });
925
+ await setWakeupStatus(run.wakeupRequestId, "failed", {
926
+ finishedAt: new Date(),
927
+ error: message,
928
+ });
929
+ if (failedRun) {
930
+ await appendForbiddenMarkerEvent(failedRun, buildForbiddenMarkerScan(null));
931
+ await appendRunEvent(failedRun, seq++, {
932
+ eventType: isWorkspacePreflightFailure ? "runtime.workspace_preflight_failed" : "error",
933
+ stream: "system",
934
+ level: "error",
935
+ message,
936
+ ...(isWorkspacePreflightFailure
937
+ ? {
938
+ payload: {
939
+ errorCode: err.errorCode,
940
+ failure: err.failure,
941
+ },
942
+ }
943
+ : {}),
999
944
  });
1000
- if (failedRun) {
1001
- await appendForbiddenMarkerEvent(failedRun, buildForbiddenMarkerScan(null));
1002
- await appendRunEvent(failedRun, seq++, {
1003
- eventType: isWorkspacePreflightFailure ? "runtime.workspace_preflight_failed" : "error",
1004
- stream: "system",
1005
- level: "error",
1006
- message,
1007
- ...(isWorkspacePreflightFailure
1008
- ? {
1009
- payload: {
1010
- errorCode: err.errorCode,
1011
- failure: err.failure,
1012
- },
1013
- }
1014
- : {}),
945
+ await releaseIssueExecutionAndPromote(failedRun);
946
+ if (!isWorkspacePreflightFailure) {
947
+ await updateRuntimeState(agent, failedRun, {
948
+ exitCode: null,
949
+ signal: null,
950
+ timedOut: false,
951
+ errorMessage: message,
952
+ }, {
953
+ legacySessionId: runtimeForAdapter.sessionId,
1015
954
  });
1016
- await releaseIssueExecutionAndPromote(failedRun);
1017
- if (!isWorkspacePreflightFailure) {
1018
- await updateRuntimeState(agent, failedRun, {
1019
- exitCode: null,
1020
- signal: null,
1021
- timedOut: false,
1022
- errorMessage: message,
1023
- }, {
1024
- legacySessionId: runtimeForAdapter.sessionId,
955
+ if (taskKey && (previousSessionParams || previousSessionDisplayId || taskSession)) {
956
+ await upsertTaskSession({
957
+ orgId: agent.orgId,
958
+ agentId: agent.id,
959
+ agentRuntimeType: agent.agentRuntimeType,
960
+ taskKey,
961
+ sessionParamsJson: previousSessionParams,
962
+ sessionDisplayId: previousSessionDisplayId,
963
+ lastRunId: failedRun.id,
964
+ lastError: message,
1025
965
  });
1026
- if (taskKey && (previousSessionParams || previousSessionDisplayId || taskSession)) {
1027
- await upsertTaskSession({
1028
- orgId: agent.orgId,
1029
- agentId: agent.id,
1030
- agentRuntimeType: agent.agentRuntimeType,
1031
- taskKey,
1032
- sessionParamsJson: previousSessionParams,
1033
- sessionDisplayId: previousSessionDisplayId,
1034
- lastRunId: failedRun.id,
1035
- lastError: message,
1036
- });
1037
- }
1038
966
  }
1039
- await emitHeartbeatLiveEval(failedRun.id);
1040
967
  }
1041
- await finalizeAgentStatus(agent.id, "failed");
1042
968
  }
1043
- finally {
1044
- stdoutTranscriptBuffer = appendTranscriptEntriesFromChunk({
1045
- buffer: stdoutTranscriptBuffer,
1046
- chunk: "",
1047
- transcript: executionTranscript,
1048
- parser: stdoutTranscriptParser,
1049
- finalize: true,
1050
- kind: "stdout",
1051
- });
1052
- stderrTranscriptBuffer = appendTranscriptEntriesFromChunk({
1053
- buffer: stderrTranscriptBuffer,
1054
- chunk: "",
1055
- transcript: executionTranscript,
1056
- finalize: true,
1057
- kind: "stderr",
1058
- });
1059
- try {
1060
- const transcriptStats = emitExecutionTranscriptTree({
1061
- context: heartbeatObservationContext,
1062
- parentObservation: observation,
1063
- transcript: executionTranscript,
1064
- initialTurnInput: modelTurnInput,
1065
- fallbackResult: transcriptFallbackResult,
1066
- });
1067
- finalObservationOutput = transcriptStats.finalOutput ?? transcriptFallbackResult?.output ?? null;
1068
- finalObservationSessionId = transcriptStats.finalSessionId ?? finalObservationSessionId;
1069
- }
1070
- catch (error) {
1071
- logger.warn({
1072
- runId: run.id,
1073
- err: error instanceof Error ? error.message : String(error),
1074
- }, "Failed to export heartbeat transcript tree to Langfuse");
1075
- }
1076
- await publishAutomationRunOutputToChat(db, {
969
+ await finalizeAgentStatus(agent.id, "failed");
970
+ }
971
+ finally {
972
+ stdoutTranscriptBuffer = appendTranscriptEntriesFromChunk({
973
+ buffer: stdoutTranscriptBuffer,
974
+ chunk: "",
975
+ transcript: executionTranscript,
976
+ parser: stdoutTranscriptParser,
977
+ finalize: true,
978
+ kind: "stdout",
979
+ });
980
+ stderrTranscriptBuffer = appendTranscriptEntriesFromChunk({
981
+ buffer: stderrTranscriptBuffer,
982
+ chunk: "",
983
+ transcript: executionTranscript,
984
+ finalize: true,
985
+ kind: "stderr",
986
+ });
987
+ finalRunOutput = transcriptFallbackResult?.output ?? null;
988
+ await publishAutomationRunOutputToChat(db, {
989
+ issueId,
990
+ output: finalRunOutput,
991
+ status: finalRunStatus,
992
+ transcript: executionTranscript,
993
+ }).catch((error) => {
994
+ logger.warn({
995
+ runId: run.id,
1077
996
  issueId,
1078
- output: finalObservationOutput,
1079
- status: finalObservationStatus,
1080
- transcript: executionTranscript,
1081
- }).catch((error) => {
1082
- logger.warn({
1083
- runId: run.id,
1084
- issueId,
1085
- err: error instanceof Error ? error.message : String(error),
1086
- }, "Failed to publish automation run output to chat");
1087
- });
1088
- updateExecutionObservation(observation, heartbeatObservationContext, {
1089
- input: rootObservationInput,
1090
- output: finalObservationOutput,
1091
- level: finalObservationStatus === "failed" || finalObservationStatus === "timed_out" ? "ERROR" : "DEFAULT",
1092
- statusMessage: finalObservationStatus ?? undefined,
1093
- });
1094
- updateExecutionTraceIO(observation, {
1095
- input: rootObservationInput,
1096
- output: finalObservationOutput,
1097
- });
1098
- updateExecutionTraceSession(observation, finalObservationSessionId);
1099
- }
1100
- });
997
+ err: error instanceof Error ? error.message : String(error),
998
+ }, "Failed to publish automation run output to chat");
999
+ });
1000
+ }
1101
1001
  }
1102
1002
  catch (outerErr) {
1103
1003
  // Setup code before adapter.execute threw (e.g. ensureRuntimeState, resolveWorkspaceForRun).
@@ -1123,7 +1023,6 @@ export function createHeartbeatExecuteHandlers(context) {
1123
1023
  level: "error",
1124
1024
  message,
1125
1025
  }).catch(() => undefined);
1126
- await emitHeartbeatLiveEval(failedRun.id).catch(() => undefined);
1127
1026
  await releaseIssueExecutionAndPromote(failedRun).catch(() => undefined);
1128
1027
  }
1129
1028
  // Ensure the agent is not left stuck in "running" if the inner catch handler's