@cloudcli-ai/cloudcli 1.37.3 → 1.37.4

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 (295) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/{abnfDiagram-N423BO3Z-CJntskwA.js → abnfDiagram-N423BO3Z-Dmkwx38H.js} +1 -1
  3. package/dist/assets/{arc-CIfH4uMN.js → arc-DLe9AYuO.js} +1 -1
  4. package/dist/assets/{architectureDiagram-T3A2C74G-_IpEkukg.js → architectureDiagram-T3A2C74G-CBbbbNUW.js} +1 -1
  5. package/dist/assets/{blockDiagram-VBNYF7ZC-BttxrpgZ.js → blockDiagram-VBNYF7ZC-CaMEaWu4.js} +1 -1
  6. package/dist/assets/{c4Diagram-5PPSVZJV-g51dSRr1.js → c4Diagram-5PPSVZJV-DhjMgNnR.js} +1 -1
  7. package/dist/assets/channel-CWrmwsir.js +1 -0
  8. package/dist/assets/{chunk-2GRJ4B5K-D_-LbQUa.js → chunk-2GRJ4B5K-yjl3-F-i.js} +1 -1
  9. package/dist/assets/{chunk-2Q5K7J3B-BtlHzwaO.js → chunk-2Q5K7J3B-DsAYaWEP.js} +1 -1
  10. package/dist/assets/{chunk-5RXB4S5H-UzkpvpAT.js → chunk-5RXB4S5H-Bt5qmqOX.js} +1 -1
  11. package/dist/assets/{chunk-5VM5RSS4-BKwx5Gag.js → chunk-5VM5RSS4-yWrWVvUt.js} +1 -1
  12. package/dist/assets/{chunk-6Q2QTUOP-D_KEBH5f.js → chunk-6Q2QTUOP-Dt66K5xb.js} +1 -1
  13. package/dist/assets/{chunk-GF5L2VYU-rK2DGyto.js → chunk-GF5L2VYU-DA0vzaj4.js} +1 -1
  14. package/dist/assets/{chunk-JWPE2WC7-CeBl_N9i.js → chunk-JWPE2WC7-CUkbx96V.js} +1 -1
  15. package/dist/assets/{chunk-KBJHAD2P-BiQLWVIr.js → chunk-KBJHAD2P-DWKxx1WH.js} +1 -1
  16. package/dist/assets/{chunk-RYQCIY6F-C1knVGV5.js → chunk-RYQCIY6F-BqluplN0.js} +1 -1
  17. package/dist/assets/{chunk-XXDRQBXY-CtKbJkvF.js → chunk-XXDRQBXY-DelKg3Xf.js} +1 -1
  18. package/dist/assets/classDiagram-JCYQIIEL-COAGCC6w.js +1 -0
  19. package/dist/assets/classDiagram-v2-OCEON4UE-COAGCC6w.js +1 -0
  20. package/dist/assets/{cose-bilkent-JH36ORCC-DjX8y40Z.js → cose-bilkent-JH36ORCC-DHV93-Em.js} +1 -1
  21. package/dist/assets/{cynefin-VYW2F7L2-DM6YeRba.js → cynefin-VYW2F7L2-B9HZgoGX.js} +1 -1
  22. package/dist/assets/{cynefinDiagram-MW4NZA55-wZJ-vy5B.js → cynefinDiagram-MW4NZA55-hFjjEQg8.js} +1 -1
  23. package/dist/assets/{dagre-VZM6K2ZE-BzP0ejkH.js → dagre-VZM6K2ZE-CpeVOC7V.js} +1 -1
  24. package/dist/assets/{diagram-7IWD3JNH-BTL_j23J.js → diagram-7IWD3JNH-D0H1UoRA.js} +1 -1
  25. package/dist/assets/{diagram-B4RE2ZJO-Cf1Norgu.js → diagram-B4RE2ZJO-6Y7BQUup.js} +1 -1
  26. package/dist/assets/{diagram-LBJQPF4R-DPiUEKr-.js → diagram-LBJQPF4R-C0nNOwht.js} +1 -1
  27. package/dist/assets/{diagram-Q27KOJAE-CTcTpiz5.js → diagram-Q27KOJAE-En6QlOVX.js} +1 -1
  28. package/dist/assets/{diagram-UB23O5K3-DPMSdYm0.js → diagram-UB23O5K3-CmPiNeGD.js} +1 -1
  29. package/dist/assets/{ebnfDiagram-BXEA7PRR-7yvD6uiF.js → ebnfDiagram-BXEA7PRR-Bygzp1Qt.js} +1 -1
  30. package/dist/assets/{erDiagram-JOGREHBK-CfgeDoV6.js → erDiagram-JOGREHBK-CwScRfzl.js} +1 -1
  31. package/dist/assets/{flowDiagram-UKHOOZJN-B27ng5zu.js → flowDiagram-UKHOOZJN-bKX-0xP6.js} +1 -1
  32. package/dist/assets/{ganttDiagram-PKOTCBZU-CcC6b_7t.js → ganttDiagram-PKOTCBZU-DtZPKXGd.js} +1 -1
  33. package/dist/assets/{gitGraphDiagram-DS77QQ5N-BX5kPGrO.js → gitGraphDiagram-DS77QQ5N-CUOtdL1o.js} +1 -1
  34. package/dist/assets/index-CdjIFxM2.js +5004 -0
  35. package/dist/assets/index-DgafhGTF.css +32 -0
  36. package/dist/assets/{infoDiagram-6WML65LV-CUP-SlN4.js → infoDiagram-6WML65LV-ciRQTS0h.js} +1 -1
  37. package/dist/assets/{ishikawaDiagram-WSZJBQD7-BTTDhOpX.js → ishikawaDiagram-WSZJBQD7-CgjhQZ84.js} +1 -1
  38. package/dist/assets/{journeyDiagram-NVQOT4AX-ARXcc61m.js → journeyDiagram-NVQOT4AX-BsbQSeIW.js} +1 -1
  39. package/dist/assets/{kanban-definition-27J2QSJJ-BieMpqMA.js → kanban-definition-27J2QSJJ-CrwzY9Jw.js} +1 -1
  40. package/dist/assets/{linear-61vxjRnP.js → linear-BUaCDr6l.js} +1 -1
  41. package/dist/assets/{mermaid.core-nhnwkfQx.js → mermaid.core-ClgdUU0j.js} +5 -5
  42. package/dist/assets/{mindmap-definition-FAOFIHXS-Cm6x5vT1.js → mindmap-definition-FAOFIHXS-BictljY1.js} +1 -1
  43. package/dist/assets/{pegDiagram-VL7TDLO6-CcYBq_9H.js → pegDiagram-VL7TDLO6-BXdByy_U.js} +1 -1
  44. package/dist/assets/{pieDiagram-7S7Q4E2Y-CfvIjfzo.js → pieDiagram-7S7Q4E2Y-uZsMfkRX.js} +1 -1
  45. package/dist/assets/{quadrantDiagram-CIZ2JOQS-SgYoWPNb.js → quadrantDiagram-CIZ2JOQS-7lCv4QIj.js} +1 -1
  46. package/dist/assets/{railroadDiagram-AXF67PYL-D2Mu5E_f.js → railroadDiagram-AXF67PYL-07dxIWbi.js} +1 -1
  47. package/dist/assets/{requirementDiagram-LRYGKXZP-Azwe_k4Q.js → requirementDiagram-LRYGKXZP-Cb31Yv1_.js} +1 -1
  48. package/dist/assets/{sankeyDiagram-W5VNT64P-DN1Ju3PA.js → sankeyDiagram-W5VNT64P-X0YPSyF9.js} +1 -1
  49. package/dist/assets/{sequenceDiagram-SI44F4Z6-Bj4qC34S.js → sequenceDiagram-SI44F4Z6-BdBxSIlP.js} +1 -1
  50. package/dist/assets/{sizeCapture-X5ZJPWSS-Co4PdklG.js → sizeCapture-X5ZJPWSS-DQM5xAyD.js} +1 -1
  51. package/dist/assets/{stateDiagram-OKZ733FA-nOvL9dRC.js → stateDiagram-OKZ733FA-DJ3xkLUF.js} +1 -1
  52. package/dist/assets/{stateDiagram-v2-UEYNNEHI-DNv8ppw7.js → stateDiagram-v2-UEYNNEHI-vAaE4zNo.js} +1 -1
  53. package/dist/assets/{swimlanes-SLNWSIFB-CCK3wMid.js → swimlanes-SLNWSIFB-rjfYdW0w.js} +2 -2
  54. package/dist/assets/swimlanesDiagram-ULZ7WXOC-TV2IF4Nq.js +8 -0
  55. package/dist/assets/{timeline-definition-Z64GVDOM-BC29RNFm.js → timeline-definition-Z64GVDOM-DZMra5do.js} +1 -1
  56. package/dist/assets/{vennDiagram-T6HMQDX7-pZlZCtEo.js → vennDiagram-T6HMQDX7-BevD8uu0.js} +1 -1
  57. package/dist/assets/{wardleyDiagram-T6FBY63Y-De8k2-zM.js → wardleyDiagram-T6FBY63Y-DsIyXB7z.js} +1 -1
  58. package/dist/assets/{xychartDiagram-ELKLHX3M-Bk8ykH0w.js → xychartDiagram-ELKLHX3M-G3PlF3ko.js} +1 -1
  59. package/dist/index.html +2 -2
  60. package/dist-server/server/index.js +4 -1
  61. package/dist-server/server/index.js.map +1 -1
  62. package/dist-server/server/modules/agent/agent.module.js +9 -2
  63. package/dist-server/server/modules/agent/agent.module.js.map +1 -1
  64. package/dist-server/server/modules/agent/agent.routes.js +175 -128
  65. package/dist-server/server/modules/agent/agent.routes.js.map +1 -1
  66. package/dist-server/server/modules/agent/tests/agent-run-registration.test.js +306 -0
  67. package/dist-server/server/modules/agent/tests/agent-run-registration.test.js.map +1 -0
  68. package/dist-server/server/modules/agent/tests/agent.routes.test.js +18 -1
  69. package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -1
  70. package/dist-server/server/modules/database/migrations.js +13 -0
  71. package/dist-server/server/modules/database/migrations.js.map +1 -1
  72. package/dist-server/server/modules/database/repositories/provider-models.js +60 -6
  73. package/dist-server/server/modules/database/repositories/provider-models.js.map +1 -1
  74. package/dist-server/server/modules/database/repositories/sessions.db.js +7 -0
  75. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  76. package/dist-server/server/modules/database/schema.js +7 -0
  77. package/dist-server/server/modules/database/schema.js.map +1 -1
  78. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +99 -0
  79. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js.map +1 -1
  80. package/dist-server/server/modules/file-tree/file-tree.module.js +2 -1
  81. package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -1
  82. package/dist-server/server/modules/file-tree/file-tree.service.js +44 -7
  83. package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -1
  84. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +126 -1
  85. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -1
  86. package/dist-server/server/modules/git/git-branch-diff.service.js +142 -0
  87. package/dist-server/server/modules/git/git-branch-diff.service.js.map +1 -0
  88. package/dist-server/server/modules/git/git-branch.service.js.map +1 -1
  89. package/dist-server/server/modules/git/git.routes.js +92 -5
  90. package/dist-server/server/modules/git/git.routes.js.map +1 -1
  91. package/dist-server/server/modules/git/tests/git-branch-diff.service.test.js +160 -0
  92. package/dist-server/server/modules/git/tests/git-branch-diff.service.test.js.map +1 -0
  93. package/dist-server/server/modules/projects/project-clone.routes.js +108 -0
  94. package/dist-server/server/modules/projects/project-clone.routes.js.map +1 -0
  95. package/dist-server/server/modules/projects/projects.routes.js +13 -66
  96. package/dist-server/server/modules/projects/projects.routes.js.map +1 -1
  97. package/dist-server/server/modules/projects/services/project-clone-request.service.js +36 -0
  98. package/dist-server/server/modules/projects/services/project-clone-request.service.js.map +1 -0
  99. package/dist-server/server/modules/projects/services/project-clone.service.js +86 -32
  100. package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -1
  101. package/dist-server/server/modules/projects/tests/project-clone.routes.test.js +191 -0
  102. package/dist-server/server/modules/projects/tests/project-clone.routes.test.js.map +1 -0
  103. package/dist-server/server/modules/projects/tests/project-clone.service.test.js +275 -0
  104. package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -1
  105. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +42 -8
  106. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
  107. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +6 -16
  108. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  109. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js +305 -16
  110. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -1
  111. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +38 -11
  112. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
  113. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +686 -77
  114. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  115. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +31 -0
  116. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  117. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js +11 -4
  118. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -1
  119. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +57 -0
  120. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  121. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +9 -2
  122. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -1
  123. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js +8 -2
  124. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -1
  125. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +16 -3
  126. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
  127. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +5 -2
  128. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js.map +1 -1
  129. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +19 -2
  130. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
  131. package/dist-server/server/modules/providers/provider.routes.js +110 -2
  132. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  133. package/dist-server/server/modules/providers/services/claude-cli-liveness.service.js +100 -0
  134. package/dist-server/server/modules/providers/services/claude-cli-liveness.service.js.map +1 -0
  135. package/dist-server/server/modules/providers/services/claude-settings-permissions.service.js +97 -0
  136. package/dist-server/server/modules/providers/services/claude-settings-permissions.service.js.map +1 -0
  137. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +9 -1
  138. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
  139. package/dist-server/server/modules/providers/services/provider-models.service.js +59 -5
  140. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  141. package/dist-server/server/modules/providers/services/provider-runtime.service.js +8 -0
  142. package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -1
  143. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +2 -4
  144. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
  145. package/dist-server/server/modules/providers/services/session-history-cache.service.js +4 -0
  146. package/dist-server/server/modules/providers/services/session-history-cache.service.js.map +1 -1
  147. package/dist-server/server/modules/providers/services/sessions.service.js +73 -3
  148. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  149. package/dist-server/server/modules/providers/tests/claude-auth.test.js +131 -0
  150. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -1
  151. package/dist-server/server/modules/providers/tests/claude-background-work.test.js +172 -0
  152. package/dist-server/server/modules/providers/tests/claude-background-work.test.js.map +1 -0
  153. package/dist-server/server/modules/providers/tests/claude-compaction.test.js +84 -0
  154. package/dist-server/server/modules/providers/tests/claude-compaction.test.js.map +1 -0
  155. package/dist-server/server/modules/providers/tests/claude-message-model.test.js +123 -0
  156. package/dist-server/server/modules/providers/tests/claude-message-model.test.js.map +1 -0
  157. package/dist-server/server/modules/providers/tests/claude-runtime-hold.test.js +265 -0
  158. package/dist-server/server/modules/providers/tests/claude-runtime-hold.test.js.map +1 -0
  159. package/dist-server/server/modules/providers/tests/claude-sessions.test.js +1368 -12
  160. package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -1
  161. package/dist-server/server/modules/providers/tests/claude-settings-permissions.test.js +228 -0
  162. package/dist-server/server/modules/providers/tests/claude-settings-permissions.test.js.map +1 -0
  163. package/dist-server/server/modules/providers/tests/codex-models.test.js +25 -0
  164. package/dist-server/server/modules/providers/tests/codex-models.test.js.map +1 -0
  165. package/dist-server/server/modules/providers/tests/codex-runtime.test.js +32 -0
  166. package/dist-server/server/modules/providers/tests/codex-runtime.test.js.map +1 -1
  167. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +50 -0
  168. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
  169. package/dist-server/server/modules/providers/tests/cursor-auth.test.js +167 -0
  170. package/dist-server/server/modules/providers/tests/cursor-auth.test.js.map +1 -0
  171. package/dist-server/server/modules/providers/tests/opencode-models.test.js +79 -0
  172. package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
  173. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +19 -1
  174. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
  175. package/dist-server/server/modules/providers/tests/provider-capabilities.service.test.js +30 -0
  176. package/dist-server/server/modules/providers/tests/provider-capabilities.service.test.js.map +1 -0
  177. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +79 -1
  178. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
  179. package/dist-server/server/modules/providers/tests/provider.routes.test.js +190 -1
  180. package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -1
  181. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js +19 -0
  182. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js.map +1 -1
  183. package/dist-server/server/modules/providers/tests/sessions.service.test.js +175 -1
  184. package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -1
  185. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js +13 -1
  186. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js.map +1 -1
  187. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js +36 -1
  188. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js.map +1 -1
  189. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +27 -5
  190. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -1
  191. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +38 -1
  192. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  193. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +230 -20
  194. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  195. package/dist-server/server/modules/websocket/tests/chat-background-subscribe.test.js +137 -0
  196. package/dist-server/server/modules/websocket/tests/chat-background-subscribe.test.js.map +1 -0
  197. package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js +96 -0
  198. package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js.map +1 -0
  199. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +420 -0
  200. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -1
  201. package/dist-server/server/shared/message-unification.js +1 -1
  202. package/dist-server/server/shared/message-unification.js.map +1 -1
  203. package/dist-server/server/shared/tests/read-only-roots.test.js +124 -0
  204. package/dist-server/server/shared/tests/read-only-roots.test.js.map +1 -0
  205. package/dist-server/server/shared/tests/strip-ansi-sequences.test.js +31 -0
  206. package/dist-server/server/shared/tests/strip-ansi-sequences.test.js.map +1 -0
  207. package/dist-server/server/shared/utils.js +126 -0
  208. package/dist-server/server/shared/utils.js.map +1 -1
  209. package/electron/desktopWindow.js +6 -0
  210. package/electron/viewHost.js +25 -2
  211. package/package.json +4 -4
  212. package/server/index.ts +5 -1
  213. package/server/modules/agent/agent.module.ts +11 -1
  214. package/server/modules/agent/agent.routes.ts +198 -140
  215. package/server/modules/agent/tests/agent-run-registration.test.ts +348 -0
  216. package/server/modules/agent/tests/agent.routes.test.ts +18 -1
  217. package/server/modules/database/migrations.ts +14 -0
  218. package/server/modules/database/repositories/provider-models.ts +79 -6
  219. package/server/modules/database/repositories/sessions.db.ts +8 -0
  220. package/server/modules/database/schema.ts +7 -0
  221. package/server/modules/database/tests/provider-models.db.integration.test.ts +113 -0
  222. package/server/modules/file-tree/file-tree.module.ts +2 -1
  223. package/server/modules/file-tree/file-tree.service.ts +49 -7
  224. package/server/modules/file-tree/tests/file-tree.service.test.ts +163 -1
  225. package/server/modules/git/git-branch-diff.service.ts +204 -0
  226. package/server/modules/git/git-branch.service.ts +2 -12
  227. package/server/modules/git/git.routes.ts +100 -6
  228. package/server/modules/git/tests/git-branch-diff.service.test.ts +210 -0
  229. package/server/modules/projects/project-clone.routes.ts +142 -0
  230. package/server/modules/projects/projects.routes.ts +16 -81
  231. package/server/modules/projects/services/project-clone-request.service.ts +56 -0
  232. package/server/modules/projects/services/project-clone.service.ts +102 -34
  233. package/server/modules/projects/tests/project-clone.routes.test.ts +246 -0
  234. package/server/modules/projects/tests/project-clone.service.test.ts +376 -0
  235. package/server/modules/providers/list/claude/claude-auth.provider.ts +60 -10
  236. package/server/modules/providers/list/claude/claude-models.provider.ts +10 -22
  237. package/server/modules/providers/list/claude/claude-runtime.provider.js +322 -15
  238. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +40 -14
  239. package/server/modules/providers/list/claude/claude-sessions.provider.ts +796 -88
  240. package/server/modules/providers/list/codex/codex-models.provider.ts +31 -0
  241. package/server/modules/providers/list/codex/codex-runtime.provider.ts +12 -4
  242. package/server/modules/providers/list/codex/codex-sessions.provider.ts +63 -0
  243. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +10 -2
  244. package/server/modules/providers/list/cursor/cursor-runtime.provider.js +9 -2
  245. package/server/modules/providers/list/opencode/opencode-models.provider.ts +18 -3
  246. package/server/modules/providers/list/opencode/opencode-runtime.provider.js +5 -2
  247. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +30 -2
  248. package/server/modules/providers/provider.routes.ts +131 -2
  249. package/server/modules/providers/services/claude-cli-liveness.service.ts +121 -0
  250. package/server/modules/providers/services/claude-settings-permissions.service.ts +127 -0
  251. package/server/modules/providers/services/provider-capabilities.service.ts +17 -1
  252. package/server/modules/providers/services/provider-models.service.ts +71 -4
  253. package/server/modules/providers/services/provider-runtime.service.ts +11 -0
  254. package/server/modules/providers/services/session-conversations-search.service.ts +2 -5
  255. package/server/modules/providers/services/session-history-cache.service.ts +13 -2
  256. package/server/modules/providers/services/sessions.service.ts +108 -8
  257. package/server/modules/providers/tests/claude-auth.test.ts +150 -0
  258. package/server/modules/providers/tests/claude-background-work.test.ts +213 -0
  259. package/server/modules/providers/tests/claude-compaction.test.ts +101 -0
  260. package/server/modules/providers/tests/claude-message-model.test.ts +160 -0
  261. package/server/modules/providers/tests/claude-runtime-hold.test.ts +309 -0
  262. package/server/modules/providers/tests/claude-sessions.test.ts +1630 -12
  263. package/server/modules/providers/tests/claude-settings-permissions.test.ts +271 -0
  264. package/server/modules/providers/tests/codex-models.test.ts +37 -0
  265. package/server/modules/providers/tests/codex-runtime.test.ts +36 -0
  266. package/server/modules/providers/tests/codex-sessions.test.ts +59 -0
  267. package/server/modules/providers/tests/cursor-auth.test.ts +187 -0
  268. package/server/modules/providers/tests/opencode-models.test.ts +100 -0
  269. package/server/modules/providers/tests/opencode-sessions.test.ts +40 -1
  270. package/server/modules/providers/tests/provider-capabilities.service.test.ts +37 -0
  271. package/server/modules/providers/tests/provider-models.service.test.ts +99 -1
  272. package/server/modules/providers/tests/provider.routes.test.ts +230 -1
  273. package/server/modules/providers/tests/session-history-cache.service.test.ts +22 -0
  274. package/server/modules/providers/tests/sessions.service.test.ts +237 -1
  275. package/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.ts +14 -1
  276. package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +45 -1
  277. package/server/modules/websocket/README.md +4 -2
  278. package/server/modules/websocket/services/chat-run-registry.service.ts +29 -5
  279. package/server/modules/websocket/services/chat-websocket.service.ts +58 -1
  280. package/server/modules/websocket/services/shell-websocket.service.ts +269 -22
  281. package/server/modules/websocket/tests/chat-background-subscribe.test.ts +167 -0
  282. package/server/modules/websocket/tests/chat-stop-task.test.ts +127 -0
  283. package/server/modules/websocket/tests/shell-websocket.service.test.ts +521 -0
  284. package/server/shared/interfaces.ts +29 -0
  285. package/server/shared/message-unification.ts +1 -1
  286. package/server/shared/tests/read-only-roots.test.ts +139 -0
  287. package/server/shared/tests/strip-ansi-sequences.test.ts +42 -0
  288. package/server/shared/types.ts +261 -7
  289. package/server/shared/utils.ts +136 -0
  290. package/dist/assets/channel-C5xU9jMw.js +0 -1
  291. package/dist/assets/classDiagram-JCYQIIEL-CRrL3vp7.js +0 -1
  292. package/dist/assets/classDiagram-v2-OCEON4UE-CRrL3vp7.js +0 -1
  293. package/dist/assets/index-BTDHQ6Id.css +0 -32
  294. package/dist/assets/index-sFfz8iBR.js +0 -4931
  295. package/dist/assets/swimlanesDiagram-ULZ7WXOC-DnfbNQEp.js +0 -8
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  AnyRecord,
3
+ BackgroundTaskSummary,
3
4
  FetchHistoryOptions,
4
5
  FetchHistoryResult,
5
6
  LLMProvider,
@@ -17,6 +18,7 @@ import type {
17
18
  ProviderRuntimePermissionGateway,
18
19
  ProviderRuntimeWriter,
19
20
  UpsertProviderMcpServerInput,
21
+ WorkflowAgentActivity,
20
22
  } from '@/shared/types.js';
21
23
 
22
24
  //----------------- PROVIDER CONTRACT INTERFACES ------------
@@ -36,6 +38,19 @@ export interface IProviderRuntime {
36
38
  ): Promise<unknown>;
37
39
  abort(sessionId: string): boolean | Promise<boolean>;
38
40
  permissions?: ProviderRuntimePermissionGateway;
41
+ /**
42
+ * Sessions with background tasks still outstanding, whether or not their
43
+ * turn has ended. Only a runtime that keeps its process open past a turn for
44
+ * such work has anything to report; the others leave this undefined and the
45
+ * running-sessions list falls back to chat runs alone.
46
+ */
47
+ listBackgroundWork?(): Array<{ sessionId: string; tasks: BackgroundTaskSummary[] }>;
48
+ /**
49
+ * Stops one outstanding background task. Resolves false when the session has
50
+ * no live process or that process is not tracking the task — it already
51
+ * settled, or the id was never one of its own.
52
+ */
53
+ stopBackgroundTask?(sessionId: string, taskId: string): Promise<boolean>;
39
54
  }
40
55
 
41
56
  /**
@@ -216,6 +231,20 @@ export interface IProviderSessions {
216
231
  * gateway branches on.
217
232
  */
218
233
  rewindSession?(sessionId: string, keepThroughId: string | null): Promise<void>;
234
+
235
+ /**
236
+ * Reads what one agent of a workflow run did, from the transcript the run
237
+ * wrote for it, with the status its journal gives it. Returns `null` when the
238
+ * run left no transcript for that agent.
239
+ *
240
+ * Implemented only by providers whose runtime spawns workflow agents; its
241
+ * absence is what makes an agent's timeline unavailable in the card.
242
+ */
243
+ readWorkflowAgentActivity?(
244
+ sessionId: string,
245
+ runId: string,
246
+ agentId: string,
247
+ ): Promise<WorkflowAgentActivity | null>;
219
248
  }
220
249
 
221
250
  // ---------------------------
@@ -322,7 +322,7 @@ function truncateOutput(value: string): string {
322
322
  * only a single oversized string — a file body or an encoded image — is ever
323
323
  * the thing making it large.
324
324
  */
325
- function truncateNestedOutput(value: unknown): unknown {
325
+ export function truncateNestedOutput(value: unknown): unknown {
326
326
  if (typeof value === 'string') {
327
327
  return truncateOutput(value);
328
328
  }
@@ -0,0 +1,139 @@
1
+ import assert from 'node:assert/strict';
2
+ import { mkdir, mkdtemp, realpath, rm, symlink, writeFile } from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import test, { after } from 'node:test';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ // The Claude projects root is derived from `os.homedir()` when the utils module
9
+ // is first imported, so HOME has to point at the fixture home *before* that
10
+ // import runs. The fixture lives beside this file rather than under the temp
11
+ // directory: a home under `/tmp` would put everything under a read-only root
12
+ // and make the escape tests pass for the wrong reason.
13
+ const testDirectory = path.dirname(fileURLToPath(import.meta.url));
14
+ const fixtureRoot = await realpath(await mkdtemp(path.join(testDirectory, 'read-only-roots-fixture-')));
15
+ const fixtureHome = path.join(fixtureRoot, 'home');
16
+ const claudeProjectsRoot = path.join(fixtureHome, '.claude', 'projects');
17
+ // Under no read-only root: not the temp directory, not the Claude projects dir.
18
+ const outsideDirectory = path.join(fixtureRoot, 'outside');
19
+ await mkdir(claudeProjectsRoot, { recursive: true });
20
+ await mkdir(outsideDirectory);
21
+
22
+ const previousHome = process.env.HOME;
23
+ const previousUserProfile = process.env.USERPROFILE;
24
+ process.env.HOME = fixtureHome;
25
+ process.env.USERPROFILE = fixtureHome;
26
+
27
+ const { resolvePathUnderRoots, resolveReadOnlyRootPath, validateWorkspacePath } = await import('@/shared/utils.js');
28
+
29
+ after(async () => {
30
+ if (previousHome === undefined) {
31
+ delete process.env.HOME;
32
+ } else {
33
+ process.env.HOME = previousHome;
34
+ }
35
+ if (previousUserProfile === undefined) {
36
+ delete process.env.USERPROFILE;
37
+ } else {
38
+ process.env.USERPROFILE = previousUserProfile;
39
+ }
40
+ await rm(fixtureRoot, { recursive: true, force: true });
41
+ });
42
+
43
+ test('a path under the system temp directory resolves as readable', async () => {
44
+ const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
45
+
46
+ try {
47
+ const filePath = path.join(temporaryDirectory, 'agent.output');
48
+ await writeFile(filePath, 'agent output', 'utf8');
49
+
50
+ // A background command's log is quoted straight out of the transcript, so
51
+ // this exact shape has to resolve.
52
+ const resolvedDirectory = await resolveReadOnlyRootPath(temporaryDirectory);
53
+ assert.ok(resolvedDirectory);
54
+ assert.equal(await resolveReadOnlyRootPath(filePath), path.join(resolvedDirectory, 'agent.output'));
55
+ } finally {
56
+ await rm(temporaryDirectory, { recursive: true, force: true });
57
+ }
58
+ });
59
+
60
+ test('a background agent output link resolves to its transcript under the Claude projects directory', async () => {
61
+ const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
62
+
63
+ try {
64
+ // Claude writes `/tmp/claude-<uid>/<project>/<session>/tasks/<task>.output`
65
+ // as a symlink to the agent's transcript under `~/.claude/projects`.
66
+ const transcriptDirectory = path.join(claudeProjectsRoot, '-home-user-project', 'session-1', 'subagents');
67
+ await mkdir(transcriptDirectory, { recursive: true });
68
+ const transcriptPath = path.join(transcriptDirectory, 'agent-1.jsonl');
69
+ await writeFile(transcriptPath, '{"type":"assistant"}\n', 'utf8');
70
+
71
+ const tasksDirectory = path.join(temporaryDirectory, 'tasks');
72
+ await mkdir(tasksDirectory);
73
+ const outputLink = path.join(tasksDirectory, 'task-1.output');
74
+ await symlink(transcriptPath, outputLink);
75
+
76
+ assert.equal(await resolveReadOnlyRootPath(outputLink), transcriptPath);
77
+ assert.equal(await resolveReadOnlyRootPath(transcriptPath), transcriptPath);
78
+ } finally {
79
+ await rm(temporaryDirectory, { recursive: true, force: true });
80
+ }
81
+ });
82
+
83
+ test('the temp directory stays read-only: it is still not a valid workspace location', async () => {
84
+ const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
85
+
86
+ try {
87
+ // Being browsable must not make it writable — the write policy is
88
+ // `validateWorkspacePath` and it does not consult the read-only roots.
89
+ const validation = await validateWorkspacePath(temporaryDirectory);
90
+ assert.equal(validation.valid, false);
91
+ } finally {
92
+ await rm(temporaryDirectory, { recursive: true, force: true });
93
+ }
94
+ });
95
+
96
+ test('paths outside the read-only roots do not resolve', async () => {
97
+ assert.equal(await resolveReadOnlyRootPath(outsideDirectory), null);
98
+ assert.equal(await resolveReadOnlyRootPath('/etc/passwd'), null);
99
+ assert.equal(await resolveReadOnlyRootPath('relative/path'), null);
100
+ assert.equal(await resolveReadOnlyRootPath(''), null);
101
+ });
102
+
103
+ test('a symlink planted in the temp directory cannot read outside every root', async () => {
104
+ const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
105
+
106
+ try {
107
+ await writeFile(path.join(outsideDirectory, 'secret.txt'), 'secret', 'utf8');
108
+ const escapeLink = path.join(temporaryDirectory, 'escape');
109
+ await symlink(outsideDirectory, escapeLink);
110
+
111
+ // The name is under a read-only root but the file is not, so resolving the
112
+ // link before comparing is what keeps this closed.
113
+ assert.equal(await resolveReadOnlyRootPath(escapeLink), null);
114
+ assert.equal(await resolveReadOnlyRootPath(path.join(escapeLink, 'secret.txt')), null);
115
+ } finally {
116
+ await rm(temporaryDirectory, { recursive: true, force: true });
117
+ }
118
+ });
119
+
120
+ test('a root that does not exist does not stop later roots from matching', async () => {
121
+ const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
122
+
123
+ try {
124
+ // `/tmp` does not exist on Windows; the temp directory listed after it
125
+ // must still be checked rather than the whole search giving up.
126
+ const missingRoot = path.join(fixtureRoot, 'missing');
127
+ assert.equal(await resolvePathUnderRoots(temporaryDirectory, [missingRoot]), null);
128
+ assert.equal(
129
+ await resolvePathUnderRoots(temporaryDirectory, [missingRoot, os.tmpdir()]),
130
+ await realpath(temporaryDirectory),
131
+ );
132
+ } finally {
133
+ await rm(temporaryDirectory, { recursive: true, force: true });
134
+ }
135
+ });
136
+
137
+ test('traversal out of the temp directory does not resolve', async () => {
138
+ assert.equal(await resolveReadOnlyRootPath(`${os.tmpdir()}/../etc/passwd`), null);
139
+ });
@@ -0,0 +1,42 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+
4
+ import { stripAnsiSequences } from '@/shared/utils.js';
5
+
6
+ test('strips the SGR colors a CLI writes around its own warnings', () => {
7
+ const styled = '\u001B[93m\u001B[1m! \u001B[0m\u001B[0mpermission requested: external_directory';
8
+ assert.equal(stripAnsiSequences(styled), '! permission requested: external_directory');
9
+ });
10
+
11
+ test('strips CSI cursor control, including the 8-bit introducer', () => {
12
+ assert.equal(stripAnsiSequences('a\u001B[2Kb\u001B[?25lc'), 'abc');
13
+ assert.equal(stripAnsiSequences('a\u009B31mb'), 'ab');
14
+ });
15
+
16
+ test('strips an OSC sequence with either terminator, without eating the rest', () => {
17
+ assert.equal(stripAnsiSequences('\u001B]0;title\u0007done'), 'done');
18
+ assert.equal(stripAnsiSequences('\u001B]8;;https://example.com\u001B\\link'), 'link');
19
+ });
20
+
21
+ test('strips other ECMA-48 escape sequences such as charset selection', () => {
22
+ assert.equal(stripAnsiSequences('\u001B(Bplain'), 'plain');
23
+ });
24
+
25
+ test('leaves text without escape sequences untouched', () => {
26
+ assert.equal(stripAnsiSequences('plain [93m-looking text'), 'plain [93m-looking text');
27
+ });
28
+
29
+ test('strips a CSI sequence that carries a private parameter byte', () => {
30
+ assert.equal(stripAnsiSequences('a\u001B[>cb'), 'ab');
31
+ });
32
+
33
+ test('stops an unterminated OSC at the next escape, so later styling still strips', () => {
34
+ assert.equal(
35
+ stripAnsiSequences('\u001B]0;unterminated\u001B[31mred\u001B[0m'),
36
+ '0;unterminatedred',
37
+ );
38
+ });
39
+
40
+ test('reduces a styling-only chunk to an empty string', () => {
41
+ assert.equal(stripAnsiSequences('\u001B[0m\u001B[2K'), '');
42
+ });
@@ -94,6 +94,13 @@ export type ProviderModelOption = {
94
94
  export type ProviderModelsDefinition = {
95
95
  OPTIONS: ProviderModelOption[];
96
96
  DEFAULT: string;
97
+ /**
98
+ * Reasoning-effort levels a custom entry of this catalog may declare, weakest
99
+ * first; empty for providers without effort support. The Providers service
100
+ * sets it on merged catalogs from the capability matrix, so the model
101
+ * library offers the same levels on every machine. Adapter catalogs omit it.
102
+ */
103
+ EFFORT_LEVELS?: string[];
97
104
  };
98
105
 
99
106
  /**
@@ -110,6 +117,22 @@ export type CustomProviderModelRecord = {
110
117
  modelId: string;
111
118
  model: string;
112
119
  sortOrder: number;
120
+ /** NULL for rows that never declared effort levels, including pre-existing rows. */
121
+ effort: CustomProviderModelEffort | null;
122
+ };
123
+
124
+ /**
125
+ * Reasoning-effort levels a user declared for one custom model.
126
+ *
127
+ * `values` holds unique, non-empty level ids drawn from the levels the
128
+ * provider's predefined models declare, and is never empty (an empty
129
+ * declaration is stored as NULL). `default`, when present, is one of `values`
130
+ * and documents the level the provider applies when the composer sends
131
+ * `Default`, mirroring `ProviderModelOption['effort'].default`.
132
+ */
133
+ export type CustomProviderModelEffort = {
134
+ values: string[];
135
+ default?: string;
113
136
  };
114
137
 
115
138
  /**
@@ -122,6 +145,12 @@ export type CustomProviderModelRecord = {
122
145
  export type CustomProviderModelInput = {
123
146
  id: string;
124
147
  model: string;
148
+ /**
149
+ * Optional reasoning-effort declaration. `undefined` leaves stored metadata
150
+ * untouched on update (and stores none on create) so clients that predate
151
+ * effort metadata keep working; `null` clears it.
152
+ */
153
+ effort?: CustomProviderModelEffort | null;
125
154
  };
126
155
 
127
156
  // ---------------------------
@@ -190,7 +219,8 @@ export type MessageKind =
190
219
  | 'permission_cancelled'
191
220
  | 'session_created'
192
221
  | 'history_truncated'
193
- | 'task_notification';
222
+ | 'task_notification'
223
+ | 'task_status';
194
224
 
195
225
  /**
196
226
  * Event kinds added by the chat gateway layer on top of provider message kinds.
@@ -258,6 +288,24 @@ export type SessionUpsertedEvent = {
258
288
  * Every provider-specific message must be converted into this shape before being
259
289
  * emitted outside provider-specific modules.
260
290
  */
291
+ /**
292
+ * A compaction, as the transcript records it.
293
+ *
294
+ * `running` is the status the CLI sends when it starts compacting, `done` the
295
+ * boundary it sends when it has, `failed` a compaction that did not finish.
296
+ * The token counts and duration only come with a boundary.
297
+ */
298
+ export type CompactionInfo = {
299
+ phase: 'running' | 'done' | 'failed';
300
+ /** Whether the user asked for it or the context window did. */
301
+ trigger?: 'manual' | 'auto';
302
+ /** Tokens the conversation held before and after, when the boundary reports them. */
303
+ preTokens?: number;
304
+ postTokens?: number;
305
+ durationMs?: number;
306
+ error?: string | null;
307
+ };
308
+
261
309
  export type NormalizedMessage = {
262
310
  id: string;
263
311
  /**
@@ -280,6 +328,15 @@ export type NormalizedMessage = {
280
328
  seq?: number;
281
329
  role?: 'user' | 'assistant';
282
330
  content?: string;
331
+ /**
332
+ * The model that produced this assistant message, as the provider reported
333
+ * it on the transcript row (today: Claude's `message.model`, e.g.
334
+ * `claude-opus-5`). Absent on user turns — no provider records which model a
335
+ * request went out with — and absent when the provider named a placeholder
336
+ * such as `<synthetic>`, so a locally-fabricated notice is never labelled
337
+ * with a model it did not run on.
338
+ */
339
+ model?: string;
283
340
  /**
284
341
  * Optional display-oriented metadata used by providers that need to expose
285
342
  * richer transcript artifacts without introducing a brand-new message kind.
@@ -295,6 +352,8 @@ export type NormalizedMessage = {
295
352
  isLocalCommand?: boolean;
296
353
  isLocalCommandStdout?: boolean;
297
354
  isCompactSummary?: boolean;
355
+ /** Set on the row that stands in for a compaction, so the UI can draw it as one. */
356
+ compact?: CompactionInfo;
298
357
  images?: unknown;
299
358
  /** Non-image files attached to a user turn after provider history normalization. */
300
359
  files?: unknown;
@@ -326,14 +385,149 @@ export type NormalizedMessage = {
326
385
  subagentTools?: SubagentActivity[];
327
386
  /** Identity and lifecycle of the subagent this `tool_use` spawned. */
328
387
  subagent?: SubagentInfo;
388
+ /** The workflow run this `tool_use` launched, read from its journal on disk. */
389
+ workflow?: WorkflowInfo;
329
390
  /** Stored memory the reply drew on, when the provider reports it. */
330
391
  memoryCitations?: MemoryCitation[];
331
392
  toolUseResult?: unknown;
332
393
  sequence?: number;
333
394
  rowid?: number;
395
+ /**
396
+ * `task_status` fields: one lifecycle event of a background task the live
397
+ * run is tracking. `taskId` is the provider's task handle; `toolUseId` names
398
+ * the call that launched it and is absent on `updated`, which the SDK keys by
399
+ * task id alone. `status` and `summary` above carry the event's own.
400
+ */
401
+ event?: 'started' | 'progress' | 'updated' | 'notification';
402
+ taskId?: string;
403
+ toolUseId?: string;
404
+ taskType?: string;
405
+ workflowName?: string;
406
+ description?: string;
407
+ usage?: TaskUsage;
408
+ outputFile?: string;
409
+ /** A workflow's `progress` only: where each agent the run spawned stands. */
410
+ agents?: WorkflowAgentProgress[];
334
411
  [key: string]: unknown;
335
412
  };
336
413
 
414
+ /**
415
+ * What a background task has spent so far, as the CLI reports it on
416
+ * `task_progress` and `task_notification`.
417
+ */
418
+ export type TaskUsage = {
419
+ totalTokens: number;
420
+ toolUses: number;
421
+ durationMs: number;
422
+ };
423
+
424
+ /**
425
+ * One background task a live session still has outstanding — a spawned
426
+ * agent, a workflow run or a backgrounded command — as the runtime tracks it
427
+ * from the stream's `task_started` until the event that settles it.
428
+ *
429
+ * `taskId` is the handle a stop request names; `toolUseId` is the call that
430
+ * launched it, which is how the client pairs the task with its card.
431
+ * `startedAt` is the server clock at `task_started`, so a session whose turn
432
+ * has ended can still report how long its work has been going.
433
+ */
434
+ export type BackgroundTaskSummary = {
435
+ taskId: string;
436
+ toolUseId: string;
437
+ taskType: string;
438
+ description: string;
439
+ workflowName?: string;
440
+ startedAt: number;
441
+ /**
442
+ * The task was launched by a subagent or workflow agent, not by the
443
+ * session's own turn: its `toolUseId` names a call in that agent's
444
+ * transcript, so no card in this session's transcript matches it. Listed so
445
+ * it can still be stopped; not counted as the session's own work.
446
+ */
447
+ nested?: boolean;
448
+ };
449
+
450
+ /**
451
+ * Where one agent of a running workflow stands, as the SDK reports it on the
452
+ * run's `task_progress` events.
453
+ *
454
+ * An entry the script has queued but not yet started has no `agentId` and is
455
+ * identified by `index` alone; once the agent runs, `agentId` names the
456
+ * transcript it writes. `lastToolName` and `lastToolSummary` are the agent's
457
+ * own latest tool call — unlike the event's task-level `last_tool_name`, which
458
+ * for a workflow is the current agent's label.
459
+ */
460
+ export type WorkflowAgentProgress = {
461
+ index: number;
462
+ label?: string;
463
+ /** The title of the script phase the agent runs under, when it has one. */
464
+ phase?: string;
465
+ agentId?: string;
466
+ model?: string;
467
+ state: 'queued' | 'running' | 'done' | 'failed';
468
+ startedAt?: number;
469
+ lastToolName?: string;
470
+ lastToolSummary?: string;
471
+ promptPreview?: string;
472
+ tokens?: number;
473
+ toolCalls?: number;
474
+ durationMs?: number;
475
+ resultPreview?: string;
476
+ };
477
+
478
+ /**
479
+ * One workflow agent's recorded timeline, read from its transcript on demand
480
+ * when the card is opened — the SDK never streams an agent's own rows to the
481
+ * parent session, so this is the only way to see what it did.
482
+ *
483
+ * `activityCount` is the full length of the timeline; `activity` is capped
484
+ * for transport like a subagent's `subagentTools`.
485
+ */
486
+ export type WorkflowAgentActivity = {
487
+ agent: {
488
+ id: string;
489
+ label?: string;
490
+ model?: string;
491
+ status: 'running' | 'completed' | 'failed' | 'stopped';
492
+ };
493
+ activity: SubagentActivity[];
494
+ activityCount: number;
495
+ };
496
+
497
+ /**
498
+ * One agent a workflow run spawned, as its journal records it.
499
+ *
500
+ * `label` and `phase` are whatever the script passed when it spawned the
501
+ * agent; older scripts passed neither. An agent with a `started` record and no
502
+ * `result` or `failed` one is still running as far as the journal knows.
503
+ */
504
+ export type WorkflowAgentInfo = {
505
+ id: string;
506
+ label?: string;
507
+ phase?: string;
508
+ /** `stopped` is an agent the journal never settled although the run itself has — abandoned by a stop or a resume that re-ran the step. */
509
+ status: 'running' | 'completed' | 'failed' | 'stopped';
510
+ };
511
+
512
+ /**
513
+ * A `Workflow` tool call's run, attached to the `tool_use` that launched it.
514
+ *
515
+ * `status` follows the same rule as a background agent's: the task
516
+ * notification's word when one exists, else `running` only while the process
517
+ * that launched it is still up, else `stopped`. The agent list and counts come
518
+ * from `<transcriptDir>/journal.jsonl`; both are empty when the run left no
519
+ * journal behind (a fork copies only the parent's transcript).
520
+ */
521
+ export type WorkflowInfo = {
522
+ runId: string;
523
+ name: string;
524
+ description?: string;
525
+ status: 'running' | 'completed' | 'failed' | 'stopped';
526
+ agents: WorkflowAgentInfo[];
527
+ agentCounts: { total: number; completed: number; failed: number; running: number; stopped: number };
528
+ scriptPath?: string;
529
+ };
530
+
337
531
  /**
338
532
  * One stored memory an assistant reply drew on.
339
533
  *
@@ -380,7 +574,8 @@ export type SubagentActivity = {
380
574
  * that it is whatever the provider reported — Claude's task notification
381
575
  * carries one — and `completed` when the provider reported nothing. A failed
382
576
  * tool call *inside* the agent is not a failed agent, so it is never inferred
383
- * from the transcript.
577
+ * from the transcript. A background agent whose session process ended before
578
+ * it reported is `stopped`: no outcome exists and none is coming.
384
579
  */
385
580
  export type SubagentInfo = {
386
581
  /** Provider-native agent id — Claude `agentId`, Codex `agent_thread_id`. */
@@ -391,7 +586,7 @@ export type SubagentInfo = {
391
586
  type?: string;
392
587
  /** One-line task summary shown in the collapsed header. */
393
588
  description?: string;
394
- status: 'running' | 'completed' | 'failed';
589
+ status: 'running' | 'completed' | 'failed' | 'stopped';
395
590
  /** Model the subagent ran on, when the provider records it. */
396
591
  model?: string;
397
592
  /**
@@ -413,7 +608,6 @@ export type ProviderRuntimeWriter = {
413
608
  setSessionId?(sessionId: string): void;
414
609
  userId?: string | number | null;
415
610
  isWebSocketWriter?: boolean;
416
- isSSEStreamWriter?: boolean;
417
611
  };
418
612
 
419
613
  export type ProviderPermissionDecision = {
@@ -443,6 +637,15 @@ export type ProviderRuntimeContext = {
443
637
  getProviderModels(): Promise<ProviderModelsDefinition>;
444
638
  normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
445
639
  isProviderInstalled(): Promise<boolean>;
640
+ /**
641
+ * Builds the SDK query for a run. Production leaves this unset and the
642
+ * runtime uses the SDK's own; tests supply a scripted stream so the hold
643
+ * and background-work paths can be driven without a CLI process.
644
+ */
645
+ createQuery?: (input: { prompt: AsyncIterable<unknown>; options: AnyRecord }) => AsyncIterable<unknown> & {
646
+ interrupt(): Promise<void>;
647
+ stopTask?(taskId: string): Promise<void>;
648
+ };
446
649
  };
447
650
 
448
651
  export type ProviderRunFunction = (
@@ -667,6 +870,29 @@ export type UpsertProviderMcpServerInput = {
667
870
 
668
871
  // ---------------------------
669
872
  //----------------- PROVIDER AUTH TYPES ------------
873
+ /**
874
+ * Records that an API-key style credential is taking precedence over a
875
+ * still-valid subscription login in `~/.claude/.credentials.json`.
876
+ *
877
+ * Claude Code always prefers `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_API_KEY` over
878
+ * the OAuth login written by `claude /login`, so when both exist every request
879
+ * is billed to the key (pay-as-you-go) rather than the subscription — usually
880
+ * without the user realising it. The Claude auth provider fills this in so the
881
+ * settings UI can say which variable won and where it was found; the fix
882
+ * differs per source (unset the variable and restart the server for
883
+ * `process_env`, edit the `env` block of `~/.claude/settings.json` for
884
+ * `settings_file`). It is never set when the login in the credentials file is
885
+ * missing or expired, because then nothing is being bypassed.
886
+ */
887
+ export type ProviderAuthSubscriptionOverride = {
888
+ /** The environment variable Claude Code is using instead of the login. */
889
+ variable: 'ANTHROPIC_API_KEY' | 'ANTHROPIC_AUTH_TOKEN';
890
+ /** Where that variable was found: the server process env or the settings.json env block. */
891
+ source: 'process_env' | 'settings_file';
892
+ /** Email recorded in the credentials file for the bypassed login, when known. */
893
+ subscriptionEmail: string | null;
894
+ };
895
+
670
896
  /**
671
897
  * Authentication status result returned by provider health checks.
672
898
  *
@@ -680,6 +906,12 @@ export type ProviderAuthStatus = {
680
906
  email: string | null;
681
907
  method: string | null;
682
908
  error?: string;
909
+ /**
910
+ * Present only when `method` is `api_key` and a valid subscription login is
911
+ * being bypassed; see ProviderAuthSubscriptionOverride. Omitted otherwise so
912
+ * existing consumers that never look for it are unaffected.
913
+ */
914
+ subscriptionOverride?: ProviderAuthSubscriptionOverride;
683
915
  };
684
916
 
685
917
  // ---------------------------
@@ -763,12 +995,13 @@ export type WorkspacePathValidationResult = {
763
995
  };
764
996
 
765
997
  // ---------------------------
766
- //----------------- GIT WORKTREE MANAGEMENT ------------
998
+ //----------------- GIT COMMAND EXECUTION AND WORKTREE MANAGEMENT ------------
767
999
  /**
768
1000
  * Captured output of one completed `git` invocation.
769
1001
  *
770
- * Returned by `GitCommandRunner` implementations so worktree services can read
771
- * both streams without caring about process plumbing.
1002
+ * Returned by `GitCommandRunner` and `GitProcessRunner` implementations so the
1003
+ * git and worktree services can read both streams without caring about
1004
+ * process plumbing.
772
1005
  */
773
1006
  export type GitCommandResult = {
774
1007
  stdout: string;
@@ -785,6 +1018,20 @@ export type GitCommandResult = {
785
1018
  */
786
1019
  export type GitCommandRunner = (args: string[], cwd: string) => Promise<GitCommandResult>;
787
1020
 
1021
+ /**
1022
+ * Executes `command args...` inside `options.cwd` and resolves with the captured output.
1023
+ *
1024
+ * This is the `spawnAsync` shape the Git routes module injects into its typed
1025
+ * services (branch deletion, branch compare) so their tests can substitute a
1026
+ * fake runner. Like `GitCommandRunner`, the promise must reject on a non-zero
1027
+ * exit code, with `stderr` attached to the error when available.
1028
+ */
1029
+ export type GitProcessRunner = (
1030
+ command: string,
1031
+ args: string[],
1032
+ options: { cwd: string },
1033
+ ) => Promise<GitCommandResult>;
1034
+
788
1035
  /**
789
1036
  * One entry parsed from `git worktree list --porcelain`.
790
1037
  *
@@ -1108,6 +1355,13 @@ export type FileTreeProjectGateway = {
1108
1355
  export type FileTreeWorkspaceGateway = {
1109
1356
  rootPath: string;
1110
1357
  validatePath(candidatePath: string): Promise<WorkspacePathValidationResult>;
1358
+ /**
1359
+ * Resolves a path readable outside the workspace root — the system temp
1360
+ * directory and the Claude projects directory — or `null` when it is not
1361
+ * one. Read-only: the write policy is `validatePath` and it does not consult
1362
+ * this.
1363
+ */
1364
+ resolveReadOnlyRootPath(candidatePath: string): Promise<string | null>;
1111
1365
  };
1112
1366
 
1113
1367
  /**