@cloudcli-ai/cloudcli 1.37.1 → 1.37.3

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 (402) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/abnfDiagram-N423BO3Z-CJntskwA.js +1 -0
  3. package/dist/assets/arc-CIfH4uMN.js +1 -0
  4. package/dist/assets/architectureDiagram-T3A2C74G-_IpEkukg.js +36 -0
  5. package/dist/assets/blockDiagram-VBNYF7ZC-BttxrpgZ.js +132 -0
  6. package/dist/assets/c4Diagram-5PPSVZJV-g51dSRr1.js +10 -0
  7. package/dist/assets/channel-C5xU9jMw.js +1 -0
  8. package/dist/assets/chunk-2GRJ4B5K-D_-LbQUa.js +1 -0
  9. package/dist/assets/chunk-2Q5K7J3B-BtlHzwaO.js +1 -0
  10. package/dist/assets/chunk-5RXB4S5H-UzkpvpAT.js +231 -0
  11. package/dist/assets/chunk-5VM5RSS4-BKwx5Gag.js +15 -0
  12. package/dist/assets/chunk-6Q2QTUOP-D_KEBH5f.js +88 -0
  13. package/dist/assets/chunk-GF5L2VYU-rK2DGyto.js +206 -0
  14. package/dist/assets/chunk-JWPE2WC7-CeBl_N9i.js +1 -0
  15. package/dist/assets/chunk-KBJHAD2P-BiQLWVIr.js +1 -0
  16. package/dist/assets/chunk-RYQCIY6F-C1knVGV5.js +1 -0
  17. package/dist/assets/chunk-XXDRQBXY-CtKbJkvF.js +1 -0
  18. package/dist/assets/classDiagram-JCYQIIEL-CRrL3vp7.js +1 -0
  19. package/dist/assets/classDiagram-v2-OCEON4UE-CRrL3vp7.js +1 -0
  20. package/dist/assets/cose-bilkent-JH36ORCC-DjX8y40Z.js +1 -0
  21. package/dist/assets/cynefin-VYW2F7L2-DM6YeRba.js +178 -0
  22. package/dist/assets/cynefinDiagram-MW4NZA55-wZJ-vy5B.js +62 -0
  23. package/dist/assets/cytoscape.esm-C10L9Icf.js +331 -0
  24. package/dist/assets/dagre-VZM6K2ZE-BzP0ejkH.js +4 -0
  25. package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  26. package/dist/assets/diagram-7IWD3JNH-BTL_j23J.js +30 -0
  27. package/dist/assets/diagram-B4RE2ZJO-Cf1Norgu.js +3 -0
  28. package/dist/assets/diagram-LBJQPF4R-DPiUEKr-.js +24 -0
  29. package/dist/assets/diagram-Q27KOJAE-CTcTpiz5.js +24 -0
  30. package/dist/assets/diagram-UB23O5K3-DPMSdYm0.js +41 -0
  31. package/dist/assets/ebnfDiagram-BXEA7PRR-7yvD6uiF.js +1 -0
  32. package/dist/assets/erDiagram-JOGREHBK-CfgeDoV6.js +85 -0
  33. package/dist/assets/flowDiagram-UKHOOZJN-B27ng5zu.js +156 -0
  34. package/dist/assets/ganttDiagram-PKOTCBZU-CcC6b_7t.js +292 -0
  35. package/dist/assets/gitGraphDiagram-DS77QQ5N-BX5kPGrO.js +106 -0
  36. package/dist/assets/graph-Cx-EqisW.js +1 -0
  37. package/dist/assets/index-BTDHQ6Id.css +32 -0
  38. package/dist/assets/index-sFfz8iBR.js +4931 -0
  39. package/dist/assets/infoDiagram-6WML65LV-CUP-SlN4.js +2 -0
  40. package/dist/assets/init-Gi6I4Gst.js +1 -0
  41. package/dist/assets/ishikawaDiagram-WSZJBQD7-BTTDhOpX.js +70 -0
  42. package/dist/assets/journeyDiagram-NVQOT4AX-ARXcc61m.js +139 -0
  43. package/dist/assets/kanban-definition-27J2QSJJ-BieMpqMA.js +89 -0
  44. package/dist/assets/layout-D6BstSzF.js +1 -0
  45. package/dist/assets/linear-61vxjRnP.js +1 -0
  46. package/dist/assets/map-CV9uif0g.js +1 -0
  47. package/dist/assets/mermaid.core-nhnwkfQx.js +312 -0
  48. package/dist/assets/mindmap-definition-FAOFIHXS-Cm6x5vT1.js +96 -0
  49. package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  50. package/dist/assets/pegDiagram-VL7TDLO6-CcYBq_9H.js +1 -0
  51. package/dist/assets/pieDiagram-7S7Q4E2Y-CfvIjfzo.js +39 -0
  52. package/dist/assets/quadrantDiagram-CIZ2JOQS-SgYoWPNb.js +7 -0
  53. package/dist/assets/railroadDiagram-AXF67PYL-D2Mu5E_f.js +1 -0
  54. package/dist/assets/requirementDiagram-LRYGKXZP-Azwe_k4Q.js +84 -0
  55. package/dist/assets/sankeyDiagram-W5VNT64P-DN1Ju3PA.js +40 -0
  56. package/dist/assets/sequenceDiagram-SI44F4Z6-Bj4qC34S.js +162 -0
  57. package/dist/assets/server.browser-CtX3Hdl5.js +27 -0
  58. package/dist/assets/sizeCapture-X5ZJPWSS-Co4PdklG.js +1 -0
  59. package/dist/assets/stateDiagram-OKZ733FA-nOvL9dRC.js +1 -0
  60. package/dist/assets/stateDiagram-v2-UEYNNEHI-DNv8ppw7.js +1 -0
  61. package/dist/assets/swimlanes-SLNWSIFB-CCK3wMid.js +2 -0
  62. package/dist/assets/swimlanesDiagram-ULZ7WXOC-DnfbNQEp.js +8 -0
  63. package/dist/assets/timeline-definition-Z64GVDOM-BC29RNFm.js +120 -0
  64. package/dist/assets/{vendor-codemirror-OwyKSvPE.js → vendor-codemirror-CYrSt7-U.js} +18 -18
  65. package/dist/assets/vennDiagram-T6HMQDX7-pZlZCtEo.js +34 -0
  66. package/dist/assets/wardleyDiagram-T6FBY63Y-De8k2-zM.js +78 -0
  67. package/dist/assets/xychartDiagram-ELKLHX3M-Bk8ykH0w.js +7 -0
  68. package/dist/index.html +3 -3
  69. package/dist-server/server/index.js +8 -5
  70. package/dist-server/server/index.js.map +1 -1
  71. package/dist-server/server/modules/agent/agent.module.js +2 -1
  72. package/dist-server/server/modules/agent/agent.module.js.map +1 -1
  73. package/dist-server/server/modules/agent/agent.routes.js +2 -2
  74. package/dist-server/server/modules/agent/agent.routes.js.map +1 -1
  75. package/dist-server/server/modules/agent/tests/agent.routes.test.js +30 -1
  76. package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -1
  77. package/dist-server/server/modules/auth/auth.middleware.js +1 -1
  78. package/dist-server/server/modules/auth/auth.middleware.js.map +1 -1
  79. package/dist-server/server/modules/browser-use/browser-use-runtime.js +10 -0
  80. package/dist-server/server/modules/browser-use/browser-use-runtime.js.map +1 -0
  81. package/dist-server/server/modules/browser-use/browser-use.routes.js +39 -33
  82. package/dist-server/server/modules/browser-use/browser-use.routes.js.map +1 -1
  83. package/dist-server/server/modules/browser-use/browser-use.service.js +3 -6
  84. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
  85. package/dist-server/server/modules/browser-use/index.js +2 -0
  86. package/dist-server/server/modules/browser-use/index.js.map +1 -1
  87. package/dist-server/server/modules/cli/cli.js +9 -3
  88. package/dist-server/server/modules/cli/cli.js.map +1 -1
  89. package/dist-server/server/modules/cli/cli.module.js +0 -1
  90. package/dist-server/server/modules/cli/cli.module.js.map +1 -1
  91. package/dist-server/server/modules/cli/cli.service.js +0 -18
  92. package/dist-server/server/modules/cli/cli.service.js.map +1 -1
  93. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +154 -0
  94. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js.map +1 -0
  95. package/dist-server/server/modules/cli/tests/cli.service.test.js +0 -3
  96. package/dist-server/server/modules/cli/tests/cli.service.test.js.map +1 -1
  97. package/dist-server/server/modules/database/connection.js +1 -1
  98. package/dist-server/server/modules/database/connection.js.map +1 -1
  99. package/dist-server/server/modules/database/index.js +5 -0
  100. package/dist-server/server/modules/database/index.js.map +1 -1
  101. package/dist-server/server/modules/database/migrations.js +32 -1
  102. package/dist-server/server/modules/database/migrations.js.map +1 -1
  103. package/dist-server/server/modules/database/repositories/scheduled-messages.db.js +71 -0
  104. package/dist-server/server/modules/database/repositories/scheduled-messages.db.js.map +1 -0
  105. package/dist-server/server/modules/database/repositories/session-drafts.db.js +105 -0
  106. package/dist-server/server/modules/database/repositories/session-drafts.db.js.map +1 -0
  107. package/dist-server/server/modules/database/repositories/sessions.db.js +137 -5
  108. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  109. package/dist-server/server/modules/database/repositories/user-preferences.db.js +65 -0
  110. package/dist-server/server/modules/database/repositories/user-preferences.db.js.map +1 -0
  111. package/dist-server/server/modules/database/schema.js +92 -0
  112. package/dist-server/server/modules/database/schema.js.map +1 -1
  113. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js +39 -0
  114. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -1
  115. package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js +105 -0
  116. package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js.map +1 -0
  117. package/dist-server/server/modules/file-tree/file-tree.service.js +18 -10
  118. package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -1
  119. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +62 -11
  120. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -1
  121. package/dist-server/server/modules/git/git-branch.service.js +15 -0
  122. package/dist-server/server/modules/git/git-branch.service.js.map +1 -0
  123. package/dist-server/server/modules/git/git.routes.js +15 -7
  124. package/dist-server/server/modules/git/git.routes.js.map +1 -1
  125. package/dist-server/server/modules/git/tests/git-branch.service.test.js +52 -0
  126. package/dist-server/server/modules/git/tests/git-branch.service.test.js.map +1 -0
  127. package/dist-server/server/modules/git/tests/git-init.routes.test.js +84 -0
  128. package/dist-server/server/modules/git/tests/git-init.routes.test.js.map +1 -1
  129. package/dist-server/server/modules/notifications/index.js +3 -1
  130. package/dist-server/server/modules/notifications/index.js.map +1 -1
  131. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +22 -1
  132. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -1
  133. package/dist-server/server/modules/projects/services/project-delete.service.js +12 -1
  134. package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -1
  135. package/dist-server/server/modules/projects/services/project-star.service.js +2 -2
  136. package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -1
  137. package/dist-server/server/modules/providers/index.js +3 -0
  138. package/dist-server/server/modules/providers/index.js.map +1 -1
  139. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +20 -1
  140. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
  141. package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js +46 -0
  142. package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js.map +1 -0
  143. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +35 -6
  144. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  145. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js +422 -86
  146. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -1
  147. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +388 -50
  148. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  149. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +4 -1
  150. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -1
  151. package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
  152. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
  153. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js +204 -0
  154. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js.map +1 -0
  155. package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js +32 -0
  156. package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js.map +1 -0
  157. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +16 -0
  158. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  159. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js +60 -49
  160. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -1
  161. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +8 -0
  162. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
  163. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +1565 -432
  164. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  165. package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
  166. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
  167. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js +8 -6
  168. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -1
  169. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -1
  170. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +258 -6
  171. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
  172. package/dist-server/server/modules/providers/provider.routes.js +29 -0
  173. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  174. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +14 -0
  175. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
  176. package/dist-server/server/modules/providers/services/provider-token-usage.service.js +139 -35
  177. package/dist-server/server/modules/providers/services/provider-token-usage.service.js.map +1 -1
  178. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +63 -7
  179. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
  180. package/dist-server/server/modules/providers/services/session-history-cache.service.js +87 -0
  181. package/dist-server/server/modules/providers/services/session-history-cache.service.js.map +1 -0
  182. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +105 -32
  183. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -1
  184. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +3 -60
  185. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  186. package/dist-server/server/modules/providers/services/sessions.service.js +179 -9
  187. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  188. package/dist-server/server/modules/providers/tests/claude-auth.test.js +52 -0
  189. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -1
  190. package/dist-server/server/modules/providers/tests/claude-models.test.js +39 -0
  191. package/dist-server/server/modules/providers/tests/claude-models.test.js.map +1 -0
  192. package/dist-server/server/modules/providers/tests/claude-sessions.test.js +465 -39
  193. package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -1
  194. package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js +16 -0
  195. package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js.map +1 -0
  196. package/dist-server/server/modules/providers/tests/claude-token-budget.test.js +85 -0
  197. package/dist-server/server/modules/providers/tests/claude-token-budget.test.js.map +1 -0
  198. package/dist-server/server/modules/providers/tests/codex-message-editing.test.js +338 -0
  199. package/dist-server/server/modules/providers/tests/codex-message-editing.test.js.map +1 -0
  200. package/dist-server/server/modules/providers/tests/codex-runtime.test.js +51 -0
  201. package/dist-server/server/modules/providers/tests/codex-runtime.test.js.map +1 -0
  202. package/dist-server/server/modules/providers/tests/codex-session-fork.test.js +54 -0
  203. package/dist-server/server/modules/providers/tests/codex-session-fork.test.js.map +1 -0
  204. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +304 -15
  205. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
  206. package/dist-server/server/modules/providers/tests/opencode-models.test.js +117 -4
  207. package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
  208. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +164 -1
  209. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js.map +1 -1
  210. package/dist-server/server/modules/providers/tests/provider.routes.test.js +35 -0
  211. package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -1
  212. package/dist-server/server/modules/providers/tests/session-fork.test.js +113 -0
  213. package/dist-server/server/modules/providers/tests/session-fork.test.js.map +1 -0
  214. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js +120 -0
  215. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js.map +1 -0
  216. package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js +90 -0
  217. package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js.map +1 -0
  218. package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js +122 -0
  219. package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js.map +1 -0
  220. package/dist-server/server/modules/providers/tests/sessions.service.test.js +45 -1
  221. package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -1
  222. package/dist-server/server/modules/providers/tests/skills.test.js +15 -3
  223. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  224. package/dist-server/server/modules/scheduled-messages/index.js +5 -0
  225. package/dist-server/server/modules/scheduled-messages/index.js.map +1 -0
  226. package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js +47 -0
  227. package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js.map +1 -0
  228. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js +163 -0
  229. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js.map +1 -0
  230. package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js +95 -0
  231. package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js.map +1 -0
  232. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js +255 -0
  233. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js.map +1 -0
  234. package/dist-server/server/modules/taskmaster/taskmaster.routes.js +23 -23
  235. package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -1
  236. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js +48 -0
  237. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js.map +1 -1
  238. package/dist-server/server/modules/user/tests/user.service.test.js +70 -0
  239. package/dist-server/server/modules/user/tests/user.service.test.js.map +1 -1
  240. package/dist-server/server/modules/user/user.module.js +10 -1
  241. package/dist-server/server/modules/user/user.module.js.map +1 -1
  242. package/dist-server/server/modules/user/user.routes.js +44 -0
  243. package/dist-server/server/modules/user/user.routes.js.map +1 -1
  244. package/dist-server/server/modules/user/user.service.js +75 -0
  245. package/dist-server/server/modules/user/user.service.js.map +1 -1
  246. package/dist-server/server/modules/voice/tests/voice.service.test.js +3 -2
  247. package/dist-server/server/modules/voice/tests/voice.service.test.js.map +1 -1
  248. package/dist-server/server/modules/websocket/index.js +7 -0
  249. package/dist-server/server/modules/websocket/index.js.map +1 -1
  250. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +10 -44
  251. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -1
  252. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +35 -5
  253. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -1
  254. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +166 -9
  255. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  256. package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js +94 -0
  257. package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js.map +1 -0
  258. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +9 -3
  259. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  260. package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js +263 -0
  261. package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js.map +1 -0
  262. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +29 -3
  263. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -1
  264. package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js +106 -0
  265. package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js.map +1 -0
  266. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +80 -0
  267. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -1
  268. package/dist-server/server/shared/claude-cli-path.js +22 -5
  269. package/dist-server/server/shared/claude-cli-path.js.map +1 -1
  270. package/dist-server/server/shared/index.js +3 -0
  271. package/dist-server/server/shared/index.js.map +1 -0
  272. package/dist-server/server/shared/message-unification.js +376 -0
  273. package/dist-server/server/shared/message-unification.js.map +1 -0
  274. package/dist-server/server/shared/tests/claude-cli-path.test.js +45 -1
  275. package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -1
  276. package/dist-server/server/shared/tests/message-unification.test.js +174 -0
  277. package/dist-server/server/shared/tests/message-unification.test.js.map +1 -0
  278. package/dist-server/server/shared/utils.js +42 -0
  279. package/dist-server/server/shared/utils.js.map +1 -1
  280. package/package.json +23 -16
  281. package/scripts/promote-dist-server.mjs +50 -0
  282. package/server/index.ts +12 -6
  283. package/server/modules/agent/agent.module.ts +2 -1
  284. package/server/modules/agent/agent.routes.ts +2 -2
  285. package/server/modules/agent/tests/agent.routes.test.ts +33 -1
  286. package/server/modules/auth/auth.middleware.ts +2 -2
  287. package/server/modules/browser-use/browser-use-runtime.ts +10 -0
  288. package/server/modules/browser-use/browser-use.routes.ts +96 -33
  289. package/server/modules/browser-use/browser-use.service.ts +5 -8
  290. package/server/modules/browser-use/index.ts +3 -0
  291. package/server/modules/cli/cli.module.ts +0 -1
  292. package/server/modules/cli/cli.service.ts +0 -20
  293. package/server/modules/cli/cli.ts +9 -3
  294. package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -0
  295. package/server/modules/cli/tests/cli.service.test.ts +0 -3
  296. package/server/modules/database/connection.ts +2 -1
  297. package/server/modules/database/index.ts +10 -0
  298. package/server/modules/database/migrations.ts +37 -0
  299. package/server/modules/database/repositories/scheduled-messages.db.ts +127 -0
  300. package/server/modules/database/repositories/session-drafts.db.ts +171 -0
  301. package/server/modules/database/repositories/sessions.db.ts +196 -3
  302. package/server/modules/database/repositories/user-preferences.db.ts +80 -0
  303. package/server/modules/database/schema.ts +96 -0
  304. package/server/modules/database/tests/sessions.db.integration.test.ts +52 -0
  305. package/server/modules/database/tests/user-preferences.db.integration.test.ts +135 -0
  306. package/server/modules/file-tree/file-tree.service.ts +21 -10
  307. package/server/modules/file-tree/tests/file-tree.service.test.ts +65 -11
  308. package/server/modules/git/git-branch.service.ts +43 -0
  309. package/server/modules/git/git.routes.ts +16 -9
  310. package/server/modules/git/tests/git-branch.service.test.ts +60 -0
  311. package/server/modules/git/tests/git-init.routes.test.ts +83 -0
  312. package/server/modules/notifications/index.ts +2 -0
  313. package/server/modules/notifications/services/notification-orchestrator.service.js +24 -1
  314. package/server/modules/projects/services/project-delete.service.ts +13 -1
  315. package/server/modules/projects/services/project-star.service.ts +2 -2
  316. package/server/modules/providers/index.ts +4 -0
  317. package/server/modules/providers/list/claude/claude-auth.provider.ts +21 -1
  318. package/server/modules/providers/list/claude/claude-fork.provider.ts +57 -0
  319. package/server/modules/providers/list/claude/claude-models.provider.ts +38 -6
  320. package/server/modules/providers/list/claude/claude-runtime.provider.js +463 -93
  321. package/server/modules/providers/list/claude/claude-sessions.provider.ts +478 -54
  322. package/server/modules/providers/list/claude/claude-skills.provider.ts +4 -1
  323. package/server/modules/providers/list/claude/claude.provider.ts +3 -0
  324. package/server/modules/providers/list/codex/codex-app-server.client.ts +243 -0
  325. package/server/modules/providers/list/codex/codex-fork.provider.ts +40 -0
  326. package/server/modules/providers/list/codex/codex-models.provider.ts +16 -0
  327. package/server/modules/providers/list/codex/{codex-runtime.provider.js → codex-runtime.provider.ts} +93 -66
  328. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +9 -0
  329. package/server/modules/providers/list/codex/codex-sessions.provider.ts +1806 -477
  330. package/server/modules/providers/list/codex/codex.provider.ts +3 -0
  331. package/server/modules/providers/list/cursor/cursor-runtime.provider.js +8 -6
  332. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +0 -1
  333. package/server/modules/providers/list/opencode/opencode-models.provider.ts +279 -6
  334. package/server/modules/providers/provider.routes.ts +36 -0
  335. package/server/modules/providers/services/provider-capabilities.service.ts +23 -0
  336. package/server/modules/providers/services/provider-token-usage.service.ts +166 -39
  337. package/server/modules/providers/services/session-conversations-search.service.ts +94 -7
  338. package/server/modules/providers/services/session-history-cache.service.ts +139 -0
  339. package/server/modules/providers/services/session-synchronizer.service.ts +125 -38
  340. package/server/modules/providers/services/sessions-watcher.service.ts +3 -64
  341. package/server/modules/providers/services/sessions.service.ts +201 -9
  342. package/server/modules/providers/tests/claude-auth.test.ts +58 -0
  343. package/server/modules/providers/tests/claude-models.test.ts +87 -0
  344. package/server/modules/providers/tests/claude-sessions.test.ts +552 -40
  345. package/server/modules/providers/tests/claude-subagent-echo.test.ts +25 -0
  346. package/server/modules/providers/tests/claude-token-budget.test.ts +104 -0
  347. package/server/modules/providers/tests/codex-message-editing.test.ts +419 -0
  348. package/server/modules/providers/tests/codex-runtime.test.ts +58 -0
  349. package/server/modules/providers/tests/codex-session-fork.test.ts +59 -0
  350. package/server/modules/providers/tests/codex-sessions.test.ts +337 -15
  351. package/server/modules/providers/tests/opencode-models.test.ts +166 -8
  352. package/server/modules/providers/tests/provider-token-usage.service.test.ts +188 -1
  353. package/server/modules/providers/tests/provider.routes.test.ts +61 -0
  354. package/server/modules/providers/tests/session-fork.test.ts +173 -0
  355. package/server/modules/providers/tests/session-history-cache.service.test.ts +143 -0
  356. package/server/modules/providers/tests/session-orphan-prune.test.ts +107 -0
  357. package/server/modules/providers/tests/session-synchronizer-coalescing.test.ts +136 -0
  358. package/server/modules/providers/tests/sessions.service.test.ts +67 -1
  359. package/server/modules/providers/tests/skills.test.ts +21 -5
  360. package/server/modules/scheduled-messages/index.ts +8 -0
  361. package/server/modules/scheduled-messages/scheduled-messages.routes.ts +68 -0
  362. package/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.ts +203 -0
  363. package/server/modules/scheduled-messages/services/scheduled-messages.service.ts +121 -0
  364. package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +310 -0
  365. package/server/modules/taskmaster/taskmaster.routes.ts +23 -33
  366. package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +57 -0
  367. package/server/modules/user/tests/user.service.test.ts +90 -0
  368. package/server/modules/user/user.module.ts +10 -1
  369. package/server/modules/user/user.routes.ts +44 -0
  370. package/server/modules/user/user.service.ts +105 -0
  371. package/server/modules/voice/tests/voice.service.test.ts +3 -2
  372. package/server/modules/websocket/index.ts +8 -0
  373. package/server/modules/websocket/services/chat-run-registry.service.ts +17 -50
  374. package/server/modules/websocket/services/chat-session-writer.service.ts +36 -6
  375. package/server/modules/websocket/services/chat-websocket.service.ts +244 -15
  376. package/server/modules/websocket/services/session-upsert-broadcast.service.ts +108 -0
  377. package/server/modules/websocket/services/shell-websocket.service.ts +10 -3
  378. package/server/modules/websocket/tests/chat-edit-send.test.ts +309 -0
  379. package/server/modules/websocket/tests/chat-run-registry.test.ts +34 -3
  380. package/server/modules/websocket/tests/session-upsert-broadcast.test.ts +138 -0
  381. package/server/modules/websocket/tests/shell-websocket.service.test.ts +108 -0
  382. package/server/shared/claude-cli-path.ts +24 -6
  383. package/server/shared/index.ts +3 -0
  384. package/server/shared/interfaces.ts +62 -0
  385. package/server/shared/message-unification.ts +449 -0
  386. package/server/shared/tests/claude-cli-path.test.ts +58 -1
  387. package/server/shared/tests/message-unification.test.ts +218 -0
  388. package/server/shared/types.ts +123 -3
  389. package/server/shared/utils.ts +50 -0
  390. package/server/tsconfig.json +6 -2
  391. package/README.de.md +0 -257
  392. package/README.ja.md +0 -249
  393. package/README.ko.md +0 -249
  394. package/README.ru.md +0 -257
  395. package/README.tr.md +0 -258
  396. package/README.zh-CN.md +0 -249
  397. package/README.zh-TW.md +0 -249
  398. package/dist/assets/index-D3jfzuKN.css +0 -32
  399. package/dist/assets/index-DTMWjJj8.js +0 -1550
  400. package/dist-server/server/constants/config.js +0 -6
  401. package/dist-server/server/constants/config.js.map +0 -1
  402. package/server/constants/config.ts +0 -5
@@ -50,3 +50,86 @@ test('git init does not run when repository validation fails for an execution er
50
50
 
51
51
  assert.deepEqual(commands, [['rev-parse', '--is-inside-work-tree']]);
52
52
  });
53
+
54
+ test('delete branch parses force and uses Git force deletion', async () => {
55
+ const commands: string[][] = [];
56
+ const spawnProcess = ((_command: string, args: string[]) => {
57
+ commands.push(args);
58
+ const child = new EventEmitter() as EventEmitter & { stdout: PassThrough; stderr: PassThrough };
59
+ child.stdout = new PassThrough();
60
+ child.stderr = new PassThrough();
61
+ process.nextTick(() => {
62
+ if (args.includes('--is-inside-work-tree')) child.stdout.write('true\n');
63
+ if (args.includes('--show-toplevel')) child.stdout.write('/workspace/repo\n');
64
+ if (args.includes('--show-current')) child.stdout.write('main\n');
65
+ if (args.includes('-D')) child.stdout.write('Deleted branch feature/unmerged.\n');
66
+ child.stdout.end();
67
+ child.stderr.end();
68
+ child.emit('close', 0);
69
+ });
70
+ return child;
71
+ }) as Parameters<typeof createGitRouter>[0]['spawnProcess'];
72
+ const unexpectedProvider = async (): Promise<never> => { throw new Error('unexpected provider call'); };
73
+ const router = createGitRouter({
74
+ fileSystem: { access: async () => undefined } as unknown as Parameters<typeof createGitRouter>[0]['fileSystem'],
75
+ spawnProcess,
76
+ resolveProjectPathById: () => '/workspace/repo',
77
+ queryClaude: unexpectedProvider,
78
+ queryCursor: unexpectedProvider,
79
+ });
80
+ const app = express();
81
+ app.use(express.json());
82
+ app.use('/api/git', router);
83
+ const server = app.listen(0, '127.0.0.1');
84
+ await once(server, 'listening');
85
+
86
+ try {
87
+ const address = server.address() as AddressInfo;
88
+ const response = await fetch(`http://127.0.0.1:${address.port}/api/git/delete-branch`, {
89
+ method: 'POST',
90
+ headers: { 'content-type': 'application/json' },
91
+ body: JSON.stringify({ project: 'project-1', branch: 'feature/unmerged', force: true }),
92
+ });
93
+ const body = await response.json() as { success: boolean; output: string };
94
+ assert.equal(response.status, 200);
95
+ assert.equal(body.success, true);
96
+ assert.match(body.output, /Deleted branch/);
97
+ } finally {
98
+ await new Promise<void>((resolve) => server.close(() => resolve()));
99
+ }
100
+
101
+ assert.deepEqual(commands.at(-1), ['branch', '-D', '--', 'feature/unmerged']);
102
+ });
103
+
104
+ test('delete branch rejects a non-boolean force value before running Git', async () => {
105
+ const spawnProcess = (() => {
106
+ throw new Error('Git must not run for invalid input');
107
+ }) as Parameters<typeof createGitRouter>[0]['spawnProcess'];
108
+ const unexpectedProvider = async (): Promise<never> => { throw new Error('unexpected provider call'); };
109
+ const router = createGitRouter({
110
+ fileSystem: { access: async () => undefined } as unknown as Parameters<typeof createGitRouter>[0]['fileSystem'],
111
+ spawnProcess,
112
+ resolveProjectPathById: () => '/workspace/repo',
113
+ queryClaude: unexpectedProvider,
114
+ queryCursor: unexpectedProvider,
115
+ });
116
+ const app = express();
117
+ app.use(express.json());
118
+ app.use('/api/git', router);
119
+ const server = app.listen(0, '127.0.0.1');
120
+ await once(server, 'listening');
121
+
122
+ try {
123
+ const address = server.address() as AddressInfo;
124
+ const response = await fetch(`http://127.0.0.1:${address.port}/api/git/delete-branch`, {
125
+ method: 'POST',
126
+ headers: { 'content-type': 'application/json' },
127
+ body: JSON.stringify({ project: 'project-1', branch: 'feature/unmerged', force: 'yes' }),
128
+ });
129
+ const body = await response.json() as { error: string };
130
+ assert.equal(response.status, 400);
131
+ assert.equal(body.error, 'force must be a boolean');
132
+ } finally {
133
+ await new Promise<void>((resolve) => server.close(() => resolve()));
134
+ }
135
+ });
@@ -9,6 +9,8 @@ export {
9
9
  notifyRunFailed,
10
10
  // Used by provider runtimes to report stopped or completed agent runs.
11
11
  notifyRunStopped,
12
+ // Used by provider runtimes to report background work that finished after its turn ended.
13
+ notifyBackgroundWorkCompleted,
12
14
  } from '@/modules/notifications/services/notification-orchestrator.service.js';
13
15
  export {
14
16
  registerDesktopNotificationClient,
@@ -155,6 +155,7 @@ function buildNotificationPayload(event) {
155
155
  ? `Action Required: Tool "${normalizedEvent.meta.toolName}" needs approval`
156
156
  : 'Action Required: A tool needs your approval',
157
157
  'run.stopped': normalizedEvent.meta?.stopReason || 'Run Stopped: The run has stopped',
158
+ 'run.background_completed': 'Background work finished',
158
159
  'run.failed': normalizedEvent.meta?.error ? `Run Failed: ${normalizedEvent.meta.error}` : 'Run Failed: The run encountered an error',
159
160
  'agent.notification': normalizedEvent.meta?.message ? String(normalizedEvent.meta.message) : 'You have a new notification',
160
161
  'push.enabled': 'Push notifications are now enabled!'
@@ -261,6 +262,27 @@ function notifyRunStopped({ userId, provider, sessionId = null, stopReason = 'co
261
262
  });
262
263
  }
263
264
 
265
+ /**
266
+ * Reports background work that finished after its turn had already completed.
267
+ *
268
+ * Uses the `stop` kind so it rides the existing "run stopped" preference rather
269
+ * than needing a new opt-in that would default to off. No explicit dedupeKey, so
270
+ * the default composite key collapses repeats inside the dedupe window.
271
+ */
272
+ function notifyBackgroundWorkCompleted({ userId, provider, sessionId = null, sessionName = null }) {
273
+ notifyUserIfEnabled({
274
+ userId,
275
+ event: createNotificationEvent({
276
+ provider,
277
+ sessionId,
278
+ kind: 'stop',
279
+ code: 'run.background_completed',
280
+ meta: { sessionName },
281
+ severity: 'info'
282
+ })
283
+ });
284
+ }
285
+
264
286
  function notifyRunFailed({ userId, provider, sessionId = null, error, sessionName = null }) {
265
287
  const errorMessage = normalizeErrorMessage(error);
266
288
 
@@ -283,5 +305,6 @@ export {
283
305
  createNotificationEvent,
284
306
  notifyUserIfEnabled,
285
307
  notifyRunStopped,
286
- notifyRunFailed
308
+ notifyRunFailed,
309
+ notifyBackgroundWorkCompleted
287
310
  };
@@ -43,11 +43,23 @@ async function unlinkJsonlIfExists(filePath: string): Promise<void> {
43
43
  */
44
44
  export async function deleteSessionJsonlFilesForProjectPath(projectPath: string): Promise<void> {
45
45
  const sessions = sessionsDb.getSessionsByProjectPathIncludingArchived(projectPath);
46
- const paths = uniqueJsonlPathsFromSessions(sessions);
46
+ // Including the transcripts a session has left behind: editing a message on
47
+ // a provider that rewinds by branching moves the session onto a copy, and
48
+ // the row stops pointing at the file the replaced turns are still in.
49
+ const paths = uniqueJsonlPathsFromSessions([
50
+ ...sessions,
51
+ ...sessions.flatMap((session) => sessionsDb
52
+ .getSupersededTranscriptPaths(session.session_id)
53
+ .map((jsonl_path) => ({ jsonl_path }))),
54
+ ]);
47
55
 
48
56
  for (const filePath of paths) {
49
57
  await unlinkJsonlIfExists(filePath);
50
58
  }
59
+
60
+ for (const session of sessions) {
61
+ sessionsDb.clearSupersededProviderSessions(session.session_id);
62
+ }
51
63
  }
52
64
 
53
65
  /**
@@ -40,7 +40,7 @@ export function applyLegacyStarredProjectIds(projectIds: string[]): ApplyLegacyS
40
40
  continue;
41
41
  }
42
42
 
43
- if (Boolean(project.isStarred)) {
43
+ if (project.isStarred) {
44
44
  continue;
45
45
  }
46
46
 
@@ -71,7 +71,7 @@ export function toggleProjectStar(projectId: string): ToggleProjectStarResult {
71
71
  });
72
72
  }
73
73
 
74
- const nextStarredState = !Boolean(project.isStarred);
74
+ const nextStarredState = !project.isStarred;
75
75
  projectsDb.updateProjectIsStarredById(normalizedProjectId, nextStarredState);
76
76
 
77
77
  return { isStarred: nextStarredState };
@@ -6,5 +6,9 @@ export { providerRuntimeService } from './services/provider-runtime.service.js';
6
6
  // providerModelsService: used by Commands to list models and resolve the active session model.
7
7
  export { providerModelsService } from './services/provider-models.service.js';
8
8
 
9
+ // sessionsService: used by the websocket module's chat gateway to resolve an
10
+ // edited message's resume point, which only the providers module can read.
11
+ export { sessionsService } from './services/sessions.service.js';
12
+
9
13
  export { initializeSessionsWatcher } from './services/sessions-watcher.service.js';
10
14
  export { closeSessionsWatcher } from './services/sessions-watcher.service.js';
@@ -25,7 +25,9 @@ export class ClaudeProviderAuth implements IProviderAuth {
25
25
  * Checks whether the Claude Code CLI is available on this host.
26
26
  */
27
27
  private checkInstalled(): boolean {
28
- const cliPath = resolveClaudeCodeExecutablePath(process.env.CLAUDE_CLI_PATH);
28
+ // cross-spawn resolves shims and PATHEXT itself, so the bare command is a
29
+ // usable fallback here even where the SDK's raw spawn could not use it.
30
+ const cliPath = resolveClaudeCodeExecutablePath(process.env.CLAUDE_CLI_PATH) ?? 'claude';
29
31
  try {
30
32
  spawn.sync(cliPath, ['--version'], { stdio: 'ignore', timeout: 5000 });
31
33
  return true;
@@ -126,6 +128,24 @@ export class ClaudeProviderAuth implements IProviderAuth {
126
128
  };
127
129
  }
128
130
 
131
+ // `accessToken` is short-lived (hours). Claude Code renews it silently
132
+ // from `refreshToken` on the next CLI invocation, so an expired access
133
+ // token alongside a live refresh token is still a working login. Before
134
+ // this check, a still-signed-in account read as "login has expired"
135
+ // until something else happened to run the CLI — which is why opening
136
+ // the Shell tab and coming back made Settings flip to Connected.
137
+ const refreshToken = readOptionalString(oauth?.refreshToken);
138
+ const refreshTokenExpiresAt = typeof oauth?.refreshTokenExpiresAt === 'number'
139
+ ? oauth.refreshTokenExpiresAt
140
+ : undefined;
141
+ if (refreshToken && (!refreshTokenExpiresAt || Date.now() < refreshTokenExpiresAt)) {
142
+ return {
143
+ authenticated: true,
144
+ email,
145
+ method: 'credentials_file',
146
+ };
147
+ }
148
+
129
149
  return {
130
150
  authenticated: false,
131
151
  email: null,
@@ -0,0 +1,57 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+
4
+ import { forkSession as forkClaudeSession } from '@anthropic-ai/claude-agent-sdk';
5
+
6
+ import type { IProviderFork } from '@/shared/interfaces.js';
7
+ import { AppError } from '@/shared/utils.js';
8
+
9
+ /**
10
+ * Branches a Claude conversation by copying its transcript into a new session
11
+ * file.
12
+ *
13
+ * The SDK owns this: it remaps every message uuid and rewrites the parentUuid
14
+ * chain, which is what makes the copy resumable rather than just a duplicate
15
+ * file. `upToMessageId` is inclusive of the row it names.
16
+ */
17
+ export class ClaudeForkProvider implements IProviderFork {
18
+ async forkSession(input: {
19
+ providerSessionId: string;
20
+ jsonlPath: string;
21
+ projectPath: string;
22
+ upToAnchorId?: string;
23
+ title?: string;
24
+ }): Promise<{ providerSessionId: string; jsonlPath: string }> {
25
+ // `dir` is the session's working directory, which the SDK encodes into the
26
+ // `~/.claude/projects/<encoded>` folder name itself — passing that folder
27
+ // makes it encode an already-encoded path and find nothing.
28
+ const { sessionId } = await forkClaudeSession(input.providerSessionId, {
29
+ dir: input.projectPath,
30
+ upToMessageId: input.upToAnchorId,
31
+ title: input.title,
32
+ });
33
+
34
+ if (!sessionId) {
35
+ throw new AppError('Claude did not return a session id for the fork.', {
36
+ code: 'FORK_FAILED',
37
+ statusCode: 502,
38
+ });
39
+ }
40
+
41
+ // Confirmed rather than assumed: the caller is about to write a database
42
+ // row claiming this file exists, and a half-created row would show up in
43
+ // the sidebar as a session that can never be opened.
44
+ // The fork lands beside the transcript it was copied from.
45
+ const forkedPath = path.join(path.dirname(input.jsonlPath), `${sessionId}.jsonl`);
46
+ try {
47
+ await stat(forkedPath);
48
+ } catch {
49
+ throw new AppError('Claude reported a fork but wrote no transcript for it.', {
50
+ code: 'FORK_FAILED',
51
+ statusCode: 502,
52
+ });
53
+ }
54
+
55
+ return { providerSessionId: sessionId, jsonlPath: forkedPath };
56
+ }
57
+ }
@@ -9,6 +9,19 @@ import type {
9
9
  } from '@/shared/types.js';
10
10
  import { buildDefaultProviderCurrentActiveModel } from '@/shared/utils.js';
11
11
 
12
+ /**
13
+ * Ultracode is not one of the SDK's reasoning-effort levels. Selecting it runs the turn at
14
+ * `xhigh` effort with standing dynamic-workflow orchestration, which the Claude runtime
15
+ * translates into the session-scoped `ultracode` setting. It is therefore only offered on
16
+ * models this catalog already marks as xhigh-capable.
17
+ */
18
+ export const CLAUDE_ULTRACODE_EFFORT = 'ultracode';
19
+
20
+ const ULTRACODE_EFFORT_OPTION = {
21
+ value: CLAUDE_ULTRACODE_EFFORT,
22
+ description: 'Highest effort plus standing workflow orchestration.',
23
+ };
24
+
12
25
  export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
13
26
  OPTIONS: [
14
27
  {
@@ -37,6 +50,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
37
50
  { value: 'high' },
38
51
  { value: 'xhigh' },
39
52
  { value: 'max' },
53
+ ULTRACODE_EFFORT_OPTION,
40
54
  ],
41
55
  },
42
56
  },
@@ -52,6 +66,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
52
66
  { value: 'high' },
53
67
  { value: 'xhigh' },
54
68
  { value: 'max' },
69
+ ULTRACODE_EFFORT_OPTION,
55
70
  ],
56
71
  },
57
72
  },
@@ -67,6 +82,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
67
82
  { value: 'high' },
68
83
  { value: 'xhigh' },
69
84
  { value: 'max' },
85
+ ULTRACODE_EFFORT_OPTION,
70
86
  ],
71
87
  },
72
88
  },
@@ -82,6 +98,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
82
98
  { value: 'high' },
83
99
  { value: 'xhigh' },
84
100
  { value: 'max' },
101
+ ULTRACODE_EFFORT_OPTION,
85
102
  ],
86
103
  },
87
104
  },
@@ -97,6 +114,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
97
114
  { value: 'high' },
98
115
  { value: 'xhigh' },
99
116
  { value: 'max' },
117
+ ULTRACODE_EFFORT_OPTION,
100
118
  ],
101
119
  },
102
120
  },
@@ -112,6 +130,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
112
130
  { value: 'high' },
113
131
  { value: 'xhigh' },
114
132
  { value: 'max' },
133
+ ULTRACODE_EFFORT_OPTION,
115
134
  ],
116
135
  },
117
136
  },
@@ -132,6 +151,7 @@ export const CLAUDE_PREDEFINED_MODELS: ProviderModelsDefinition = {
132
151
  { value: 'high' },
133
152
  { value: 'xhigh' },
134
153
  { value: 'max' },
154
+ ULTRACODE_EFFORT_OPTION,
135
155
  ],
136
156
  },
137
157
  },
@@ -166,7 +186,15 @@ const ANSI_PATTERN = new RegExp(
166
186
  'g',
167
187
  );
168
188
 
169
- const extractClaudeEventModel = (event: ClaudeInitEvent, sessionId: string): string | null => {
189
+ /**
190
+ * Claude Code stamps locally-synthesized rows (API-error placeholders and the
191
+ * like) with `model: "<synthetic>"`. Angle-bracketed values are placeholders,
192
+ * never real model ids, and must not be surfaced as the session's model.
193
+ */
194
+ const isPlaceholderModel = (model: string): boolean => model.startsWith('<') && model.endsWith('>');
195
+
196
+ /** Exported for tests. */
197
+ export const extractClaudeEventModel = (event: ClaudeInitEvent, sessionId: string): string | null => {
170
198
  const eventSessionId = event.sessionId ?? event.session_id;
171
199
  if (eventSessionId && eventSessionId !== sessionId) {
172
200
  return null;
@@ -178,12 +206,12 @@ const extractClaudeEventModel = (event: ClaudeInitEvent, sessionId: string): str
178
206
  }
179
207
 
180
208
  const directModel = event.model?.trim();
181
- if (directModel) {
209
+ if (directModel && !isPlaceholderModel(directModel)) {
182
210
  return directModel;
183
211
  }
184
212
 
185
213
  const messageModel = event.message?.model?.trim();
186
- return messageModel || null;
214
+ return messageModel && !isPlaceholderModel(messageModel) ? messageModel : null;
187
215
  };
188
216
 
189
217
  const stripAnsi = (value: string): string => value.replace(ANSI_PATTERN, '');
@@ -199,13 +227,15 @@ const extractClaudeModelFromTextContent = (content: string): string | null => {
199
227
  if (localCommandStdout !== null) {
200
228
  const cleanedStdout = stripAnsi(localCommandStdout).replace(/\s+/g, ' ').trim();
201
229
  const changedModel = /(?:set|changed|switched)\s+model\s+to\s+(.+?)\.?$/i.exec(cleanedStdout);
202
- if (changedModel?.[1]?.trim()) {
203
- return changedModel[1].trim();
230
+ const stdoutModel = changedModel?.[1]?.trim();
231
+ // A placeholder stdout hit must not shadow a real <model> tag further down.
232
+ if (stdoutModel && !isPlaceholderModel(stdoutModel)) {
233
+ return stdoutModel;
204
234
  }
205
235
  }
206
236
 
207
237
  const modelTag = extractTaggedContent(content, 'model')?.trim();
208
- return modelTag || null;
238
+ return modelTag && !isPlaceholderModel(modelTag) ? modelTag : null;
209
239
  };
210
240
 
211
241
  const extractClaudeModelFromMessageContent = (content: unknown): string | null => {
@@ -222,6 +252,8 @@ const extractClaudeModelFromMessageContent = (content: unknown): string | null =
222
252
  continue;
223
253
  }
224
254
 
255
+ // extractClaudeModelFromTextContent rejects placeholders, so a placeholder
256
+ // part yields null here and a later part can still supply the real model.
225
257
  const model = extractClaudeModelFromTextContent(part.text);
226
258
  if (model) {
227
259
  return model;