@cloudcli-ai/cloudcli 1.37.2 → 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 (453) hide show
  1. package/README.md +269 -0
  2. package/dist/assets/{abnfDiagram-N423BO3Z-C4UAoHJb.js → abnfDiagram-N423BO3Z-Dmkwx38H.js} +1 -1
  3. package/dist/assets/{arc-B8jF-ja9.js → arc-DLe9AYuO.js} +1 -1
  4. package/dist/assets/{architectureDiagram-T3A2C74G-C_Wur_CU.js → architectureDiagram-T3A2C74G-CBbbbNUW.js} +1 -1
  5. package/dist/assets/{blockDiagram-VBNYF7ZC-Cq4P1i8t.js → blockDiagram-VBNYF7ZC-CaMEaWu4.js} +1 -1
  6. package/dist/assets/{c4Diagram-5PPSVZJV-C1wG4eUj.js → c4Diagram-5PPSVZJV-DhjMgNnR.js} +1 -1
  7. package/dist/assets/channel-CWrmwsir.js +1 -0
  8. package/dist/assets/{chunk-2GRJ4B5K-B8fnBG6E.js → chunk-2GRJ4B5K-yjl3-F-i.js} +1 -1
  9. package/dist/assets/{chunk-2Q5K7J3B-WdfPooPJ.js → chunk-2Q5K7J3B-DsAYaWEP.js} +1 -1
  10. package/dist/assets/{chunk-5RXB4S5H-DhZJuG2E.js → chunk-5RXB4S5H-Bt5qmqOX.js} +1 -1
  11. package/dist/assets/{chunk-5VM5RSS4-B0rjslal.js → chunk-5VM5RSS4-yWrWVvUt.js} +1 -1
  12. package/dist/assets/{chunk-6Q2QTUOP-CG2Oj4jL.js → chunk-6Q2QTUOP-Dt66K5xb.js} +1 -1
  13. package/dist/assets/{chunk-GF5L2VYU-rrl2lRxY.js → chunk-GF5L2VYU-DA0vzaj4.js} +1 -1
  14. package/dist/assets/{chunk-JWPE2WC7-CjVbrVMA.js → chunk-JWPE2WC7-CUkbx96V.js} +1 -1
  15. package/dist/assets/{chunk-KBJHAD2P-CRzKgU8S.js → chunk-KBJHAD2P-DWKxx1WH.js} +1 -1
  16. package/dist/assets/{chunk-RYQCIY6F-DBz4GTZF.js → chunk-RYQCIY6F-BqluplN0.js} +1 -1
  17. package/dist/assets/{chunk-XXDRQBXY-wHxalsXk.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-s1hygY8e.js → cose-bilkent-JH36ORCC-DHV93-Em.js} +1 -1
  21. package/dist/assets/{cynefin-VYW2F7L2-C4LGV15i.js → cynefin-VYW2F7L2-B9HZgoGX.js} +1 -1
  22. package/dist/assets/{cynefinDiagram-MW4NZA55-C5uhu7B3.js → cynefinDiagram-MW4NZA55-hFjjEQg8.js} +1 -1
  23. package/dist/assets/{dagre-VZM6K2ZE-B-OBTewm.js → dagre-VZM6K2ZE-CpeVOC7V.js} +1 -1
  24. package/dist/assets/{diagram-7IWD3JNH-BjGKQxih.js → diagram-7IWD3JNH-D0H1UoRA.js} +1 -1
  25. package/dist/assets/{diagram-B4RE2ZJO-BMKz1X2L.js → diagram-B4RE2ZJO-6Y7BQUup.js} +1 -1
  26. package/dist/assets/{diagram-LBJQPF4R-DNh-GhKC.js → diagram-LBJQPF4R-C0nNOwht.js} +1 -1
  27. package/dist/assets/{diagram-Q27KOJAE-BaTG9jPT.js → diagram-Q27KOJAE-En6QlOVX.js} +1 -1
  28. package/dist/assets/{diagram-UB23O5K3-BUwo2OvJ.js → diagram-UB23O5K3-CmPiNeGD.js} +1 -1
  29. package/dist/assets/{ebnfDiagram-BXEA7PRR-DAZgfzX2.js → ebnfDiagram-BXEA7PRR-Bygzp1Qt.js} +1 -1
  30. package/dist/assets/{erDiagram-JOGREHBK-1w1CcGEb.js → erDiagram-JOGREHBK-CwScRfzl.js} +1 -1
  31. package/dist/assets/{flowDiagram-UKHOOZJN-D4EII8Jj.js → flowDiagram-UKHOOZJN-bKX-0xP6.js} +1 -1
  32. package/dist/assets/{ganttDiagram-PKOTCBZU-ChvJZAgB.js → ganttDiagram-PKOTCBZU-DtZPKXGd.js} +1 -1
  33. package/dist/assets/{gitGraphDiagram-DS77QQ5N-DtOn41S8.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-DN_PVEJZ.js → infoDiagram-6WML65LV-ciRQTS0h.js} +1 -1
  37. package/dist/assets/{ishikawaDiagram-WSZJBQD7-DbkF1kXb.js → ishikawaDiagram-WSZJBQD7-CgjhQZ84.js} +1 -1
  38. package/dist/assets/{journeyDiagram-NVQOT4AX-pJwmhddE.js → journeyDiagram-NVQOT4AX-BsbQSeIW.js} +1 -1
  39. package/dist/assets/{kanban-definition-27J2QSJJ-PPAPgNp5.js → kanban-definition-27J2QSJJ-CrwzY9Jw.js} +1 -1
  40. package/dist/assets/{linear-iPR-J9f7.js → linear-BUaCDr6l.js} +1 -1
  41. package/dist/assets/{mermaid.core-BEUL86Z6.js → mermaid.core-ClgdUU0j.js} +5 -5
  42. package/dist/assets/{mindmap-definition-FAOFIHXS-BvZoBib7.js → mindmap-definition-FAOFIHXS-BictljY1.js} +1 -1
  43. package/dist/assets/{pegDiagram-VL7TDLO6-DhYreaUd.js → pegDiagram-VL7TDLO6-BXdByy_U.js} +1 -1
  44. package/dist/assets/{pieDiagram-7S7Q4E2Y-CrOHlyD0.js → pieDiagram-7S7Q4E2Y-uZsMfkRX.js} +1 -1
  45. package/dist/assets/{quadrantDiagram-CIZ2JOQS-D4g5yH3t.js → quadrantDiagram-CIZ2JOQS-7lCv4QIj.js} +1 -1
  46. package/dist/assets/{railroadDiagram-AXF67PYL-Dj39lHlf.js → railroadDiagram-AXF67PYL-07dxIWbi.js} +1 -1
  47. package/dist/assets/{requirementDiagram-LRYGKXZP-1AS4Zgm_.js → requirementDiagram-LRYGKXZP-Cb31Yv1_.js} +1 -1
  48. package/dist/assets/{sankeyDiagram-W5VNT64P-CKlMn19P.js → sankeyDiagram-W5VNT64P-X0YPSyF9.js} +1 -1
  49. package/dist/assets/{sequenceDiagram-SI44F4Z6-B_j3qyvo.js → sequenceDiagram-SI44F4Z6-BdBxSIlP.js} +1 -1
  50. package/dist/assets/server.browser-CtX3Hdl5.js +27 -0
  51. package/dist/assets/{sizeCapture-X5ZJPWSS-Bp2Op16v.js → sizeCapture-X5ZJPWSS-DQM5xAyD.js} +1 -1
  52. package/dist/assets/{stateDiagram-OKZ733FA-C0cN6DoY.js → stateDiagram-OKZ733FA-DJ3xkLUF.js} +1 -1
  53. package/dist/assets/stateDiagram-v2-UEYNNEHI-vAaE4zNo.js +1 -0
  54. package/dist/assets/{swimlanes-SLNWSIFB-BEvXOV9b.js → swimlanes-SLNWSIFB-rjfYdW0w.js} +2 -2
  55. package/dist/assets/swimlanesDiagram-ULZ7WXOC-TV2IF4Nq.js +8 -0
  56. package/dist/assets/{timeline-definition-Z64GVDOM-zdJQinvZ.js → timeline-definition-Z64GVDOM-DZMra5do.js} +1 -1
  57. package/dist/assets/{vendor-codemirror-OwyKSvPE.js → vendor-codemirror-CYrSt7-U.js} +18 -18
  58. package/dist/assets/{vennDiagram-T6HMQDX7-DuF1uZMY.js → vennDiagram-T6HMQDX7-BevD8uu0.js} +1 -1
  59. package/dist/assets/{wardleyDiagram-T6FBY63Y-B9AlLQup.js → wardleyDiagram-T6FBY63Y-DsIyXB7z.js} +1 -1
  60. package/dist/assets/{xychartDiagram-ELKLHX3M-DTJX48Qg.js → xychartDiagram-ELKLHX3M-G3PlF3ko.js} +1 -1
  61. package/dist/index.html +3 -3
  62. package/dist-server/server/index.js +11 -4
  63. package/dist-server/server/index.js.map +1 -1
  64. package/dist-server/server/modules/agent/agent.module.js +9 -2
  65. package/dist-server/server/modules/agent/agent.module.js.map +1 -1
  66. package/dist-server/server/modules/agent/agent.routes.js +177 -130
  67. package/dist-server/server/modules/agent/agent.routes.js.map +1 -1
  68. package/dist-server/server/modules/agent/tests/agent-run-registration.test.js +306 -0
  69. package/dist-server/server/modules/agent/tests/agent-run-registration.test.js.map +1 -0
  70. package/dist-server/server/modules/agent/tests/agent.routes.test.js +48 -2
  71. package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -1
  72. package/dist-server/server/modules/browser-use/browser-use.routes.js +39 -33
  73. package/dist-server/server/modules/browser-use/browser-use.routes.js.map +1 -1
  74. package/dist-server/server/modules/database/connection.js +1 -1
  75. package/dist-server/server/modules/database/connection.js.map +1 -1
  76. package/dist-server/server/modules/database/index.js +5 -0
  77. package/dist-server/server/modules/database/index.js.map +1 -1
  78. package/dist-server/server/modules/database/migrations.js +45 -1
  79. package/dist-server/server/modules/database/migrations.js.map +1 -1
  80. package/dist-server/server/modules/database/repositories/provider-models.js +60 -6
  81. package/dist-server/server/modules/database/repositories/provider-models.js.map +1 -1
  82. package/dist-server/server/modules/database/repositories/scheduled-messages.db.js +71 -0
  83. package/dist-server/server/modules/database/repositories/scheduled-messages.db.js.map +1 -0
  84. package/dist-server/server/modules/database/repositories/session-drafts.db.js +105 -0
  85. package/dist-server/server/modules/database/repositories/session-drafts.db.js.map +1 -0
  86. package/dist-server/server/modules/database/repositories/sessions.db.js +144 -5
  87. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  88. package/dist-server/server/modules/database/repositories/user-preferences.db.js +65 -0
  89. package/dist-server/server/modules/database/repositories/user-preferences.db.js.map +1 -0
  90. package/dist-server/server/modules/database/schema.js +99 -0
  91. package/dist-server/server/modules/database/schema.js.map +1 -1
  92. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +99 -0
  93. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js.map +1 -1
  94. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js +39 -0
  95. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -1
  96. package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js +105 -0
  97. package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js.map +1 -0
  98. package/dist-server/server/modules/file-tree/file-tree.module.js +2 -1
  99. package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -1
  100. package/dist-server/server/modules/file-tree/file-tree.service.js +44 -7
  101. package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -1
  102. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +126 -1
  103. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -1
  104. package/dist-server/server/modules/git/git-branch-diff.service.js +142 -0
  105. package/dist-server/server/modules/git/git-branch-diff.service.js.map +1 -0
  106. package/dist-server/server/modules/git/git-branch.service.js.map +1 -1
  107. package/dist-server/server/modules/git/git.routes.js +92 -5
  108. package/dist-server/server/modules/git/git.routes.js.map +1 -1
  109. package/dist-server/server/modules/git/tests/git-branch-diff.service.test.js +160 -0
  110. package/dist-server/server/modules/git/tests/git-branch-diff.service.test.js.map +1 -0
  111. package/dist-server/server/modules/projects/project-clone.routes.js +108 -0
  112. package/dist-server/server/modules/projects/project-clone.routes.js.map +1 -0
  113. package/dist-server/server/modules/projects/projects.routes.js +13 -66
  114. package/dist-server/server/modules/projects/projects.routes.js.map +1 -1
  115. package/dist-server/server/modules/projects/services/project-clone-request.service.js +36 -0
  116. package/dist-server/server/modules/projects/services/project-clone-request.service.js.map +1 -0
  117. package/dist-server/server/modules/projects/services/project-clone.service.js +86 -32
  118. package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -1
  119. package/dist-server/server/modules/projects/services/project-delete.service.js +12 -1
  120. package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -1
  121. package/dist-server/server/modules/projects/services/project-star.service.js +2 -2
  122. package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -1
  123. package/dist-server/server/modules/projects/tests/project-clone.routes.test.js +191 -0
  124. package/dist-server/server/modules/projects/tests/project-clone.routes.test.js.map +1 -0
  125. package/dist-server/server/modules/projects/tests/project-clone.service.test.js +275 -0
  126. package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -1
  127. package/dist-server/server/modules/providers/index.js +3 -0
  128. package/dist-server/server/modules/providers/index.js.map +1 -1
  129. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +62 -9
  130. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
  131. package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js +46 -0
  132. package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js.map +1 -0
  133. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +31 -12
  134. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  135. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js +472 -53
  136. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -1
  137. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +38 -11
  138. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
  139. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +1007 -60
  140. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  141. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +4 -1
  142. package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -1
  143. package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
  144. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
  145. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js +204 -0
  146. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js.map +1 -0
  147. package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js +32 -0
  148. package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js.map +1 -0
  149. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +47 -0
  150. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  151. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js +71 -53
  152. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -1
  153. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +8 -0
  154. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
  155. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +1621 -431
  156. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  157. package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
  158. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
  159. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +9 -2
  160. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -1
  161. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js +16 -8
  162. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -1
  163. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -1
  164. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +274 -9
  165. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
  166. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +5 -2
  167. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js.map +1 -1
  168. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +19 -2
  169. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
  170. package/dist-server/server/modules/providers/provider.routes.js +134 -2
  171. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  172. package/dist-server/server/modules/providers/services/claude-cli-liveness.service.js +100 -0
  173. package/dist-server/server/modules/providers/services/claude-cli-liveness.service.js.map +1 -0
  174. package/dist-server/server/modules/providers/services/claude-settings-permissions.service.js +97 -0
  175. package/dist-server/server/modules/providers/services/claude-settings-permissions.service.js.map +1 -0
  176. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +23 -1
  177. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
  178. package/dist-server/server/modules/providers/services/provider-models.service.js +59 -5
  179. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  180. package/dist-server/server/modules/providers/services/provider-runtime.service.js +8 -0
  181. package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -1
  182. package/dist-server/server/modules/providers/services/provider-token-usage.service.js +139 -35
  183. package/dist-server/server/modules/providers/services/provider-token-usage.service.js.map +1 -1
  184. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +2 -4
  185. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
  186. package/dist-server/server/modules/providers/services/session-history-cache.service.js +91 -0
  187. package/dist-server/server/modules/providers/services/session-history-cache.service.js.map +1 -0
  188. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +105 -32
  189. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -1
  190. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +3 -60
  191. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  192. package/dist-server/server/modules/providers/services/sessions.service.js +252 -12
  193. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  194. package/dist-server/server/modules/providers/tests/claude-auth.test.js +183 -0
  195. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -1
  196. package/dist-server/server/modules/providers/tests/claude-background-work.test.js +172 -0
  197. package/dist-server/server/modules/providers/tests/claude-background-work.test.js.map +1 -0
  198. package/dist-server/server/modules/providers/tests/claude-compaction.test.js +84 -0
  199. package/dist-server/server/modules/providers/tests/claude-compaction.test.js.map +1 -0
  200. package/dist-server/server/modules/providers/tests/claude-message-model.test.js +123 -0
  201. package/dist-server/server/modules/providers/tests/claude-message-model.test.js.map +1 -0
  202. package/dist-server/server/modules/providers/tests/claude-models.test.js +39 -0
  203. package/dist-server/server/modules/providers/tests/claude-models.test.js.map +1 -0
  204. package/dist-server/server/modules/providers/tests/claude-runtime-hold.test.js +265 -0
  205. package/dist-server/server/modules/providers/tests/claude-runtime-hold.test.js.map +1 -0
  206. package/dist-server/server/modules/providers/tests/claude-sessions.test.js +1815 -33
  207. package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -1
  208. package/dist-server/server/modules/providers/tests/claude-settings-permissions.test.js +228 -0
  209. package/dist-server/server/modules/providers/tests/claude-settings-permissions.test.js.map +1 -0
  210. package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js +16 -0
  211. package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js.map +1 -0
  212. package/dist-server/server/modules/providers/tests/claude-token-budget.test.js +85 -0
  213. package/dist-server/server/modules/providers/tests/claude-token-budget.test.js.map +1 -0
  214. package/dist-server/server/modules/providers/tests/codex-message-editing.test.js +338 -0
  215. package/dist-server/server/modules/providers/tests/codex-message-editing.test.js.map +1 -0
  216. package/dist-server/server/modules/providers/tests/codex-models.test.js +25 -0
  217. package/dist-server/server/modules/providers/tests/codex-models.test.js.map +1 -0
  218. package/dist-server/server/modules/providers/tests/codex-runtime.test.js +83 -0
  219. package/dist-server/server/modules/providers/tests/codex-runtime.test.js.map +1 -0
  220. package/dist-server/server/modules/providers/tests/codex-session-fork.test.js +54 -0
  221. package/dist-server/server/modules/providers/tests/codex-session-fork.test.js.map +1 -0
  222. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +354 -15
  223. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
  224. package/dist-server/server/modules/providers/tests/cursor-auth.test.js +167 -0
  225. package/dist-server/server/modules/providers/tests/cursor-auth.test.js.map +1 -0
  226. package/dist-server/server/modules/providers/tests/opencode-models.test.js +196 -4
  227. package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
  228. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +19 -1
  229. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
  230. package/dist-server/server/modules/providers/tests/provider-capabilities.service.test.js +30 -0
  231. package/dist-server/server/modules/providers/tests/provider-capabilities.service.test.js.map +1 -0
  232. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +79 -1
  233. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
  234. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +164 -1
  235. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js.map +1 -1
  236. package/dist-server/server/modules/providers/tests/provider.routes.test.js +190 -1
  237. package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -1
  238. package/dist-server/server/modules/providers/tests/session-fork.test.js +113 -0
  239. package/dist-server/server/modules/providers/tests/session-fork.test.js.map +1 -0
  240. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js +139 -0
  241. package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js.map +1 -0
  242. package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js +90 -0
  243. package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js.map +1 -0
  244. package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js +122 -0
  245. package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js.map +1 -0
  246. package/dist-server/server/modules/providers/tests/sessions.service.test.js +219 -1
  247. package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -1
  248. package/dist-server/server/modules/providers/tests/skills.test.js +15 -3
  249. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  250. package/dist-server/server/modules/scheduled-messages/index.js +5 -0
  251. package/dist-server/server/modules/scheduled-messages/index.js.map +1 -0
  252. package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js +47 -0
  253. package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js.map +1 -0
  254. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js +175 -0
  255. package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js.map +1 -0
  256. package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js +95 -0
  257. package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js.map +1 -0
  258. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js +290 -0
  259. package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js.map +1 -0
  260. package/dist-server/server/modules/taskmaster/taskmaster.routes.js +23 -23
  261. package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -1
  262. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js +48 -0
  263. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js.map +1 -1
  264. package/dist-server/server/modules/user/tests/user.service.test.js +70 -0
  265. package/dist-server/server/modules/user/tests/user.service.test.js.map +1 -1
  266. package/dist-server/server/modules/user/user.module.js +10 -1
  267. package/dist-server/server/modules/user/user.module.js.map +1 -1
  268. package/dist-server/server/modules/user/user.routes.js +44 -0
  269. package/dist-server/server/modules/user/user.routes.js.map +1 -1
  270. package/dist-server/server/modules/user/user.service.js +75 -0
  271. package/dist-server/server/modules/user/user.service.js.map +1 -1
  272. package/dist-server/server/modules/voice/tests/voice.service.test.js +3 -2
  273. package/dist-server/server/modules/voice/tests/voice.service.test.js.map +1 -1
  274. package/dist-server/server/modules/websocket/index.js +7 -0
  275. package/dist-server/server/modules/websocket/index.js.map +1 -1
  276. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +37 -49
  277. package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -1
  278. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +35 -5
  279. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -1
  280. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +204 -10
  281. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  282. package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js +94 -0
  283. package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js.map +1 -0
  284. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +236 -20
  285. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  286. package/dist-server/server/modules/websocket/tests/chat-background-subscribe.test.js +137 -0
  287. package/dist-server/server/modules/websocket/tests/chat-background-subscribe.test.js.map +1 -0
  288. package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js +263 -0
  289. package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js.map +1 -0
  290. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +29 -3
  291. package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -1
  292. package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js +96 -0
  293. package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js.map +1 -0
  294. package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js +106 -0
  295. package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js.map +1 -0
  296. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +500 -0
  297. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -1
  298. package/dist-server/server/shared/claude-cli-path.js +22 -5
  299. package/dist-server/server/shared/claude-cli-path.js.map +1 -1
  300. package/dist-server/server/shared/index.js +3 -0
  301. package/dist-server/server/shared/index.js.map +1 -0
  302. package/dist-server/server/shared/message-unification.js +376 -0
  303. package/dist-server/server/shared/message-unification.js.map +1 -0
  304. package/dist-server/server/shared/tests/claude-cli-path.test.js +45 -1
  305. package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -1
  306. package/dist-server/server/shared/tests/message-unification.test.js +174 -0
  307. package/dist-server/server/shared/tests/message-unification.test.js.map +1 -0
  308. package/dist-server/server/shared/tests/read-only-roots.test.js +124 -0
  309. package/dist-server/server/shared/tests/read-only-roots.test.js.map +1 -0
  310. package/dist-server/server/shared/tests/strip-ansi-sequences.test.js +31 -0
  311. package/dist-server/server/shared/tests/strip-ansi-sequences.test.js.map +1 -0
  312. package/dist-server/server/shared/utils.js +160 -0
  313. package/dist-server/server/shared/utils.js.map +1 -1
  314. package/electron/desktopWindow.js +6 -0
  315. package/electron/viewHost.js +25 -2
  316. package/package.json +20 -17
  317. package/server/index.ts +16 -5
  318. package/server/modules/agent/agent.module.ts +11 -1
  319. package/server/modules/agent/agent.routes.ts +200 -142
  320. package/server/modules/agent/tests/agent-run-registration.test.ts +348 -0
  321. package/server/modules/agent/tests/agent.routes.test.ts +51 -2
  322. package/server/modules/browser-use/browser-use.routes.ts +96 -33
  323. package/server/modules/database/connection.ts +2 -1
  324. package/server/modules/database/index.ts +10 -0
  325. package/server/modules/database/migrations.ts +51 -0
  326. package/server/modules/database/repositories/provider-models.ts +79 -6
  327. package/server/modules/database/repositories/scheduled-messages.db.ts +127 -0
  328. package/server/modules/database/repositories/session-drafts.db.ts +171 -0
  329. package/server/modules/database/repositories/sessions.db.ts +204 -3
  330. package/server/modules/database/repositories/user-preferences.db.ts +80 -0
  331. package/server/modules/database/schema.ts +103 -0
  332. package/server/modules/database/tests/provider-models.db.integration.test.ts +113 -0
  333. package/server/modules/database/tests/sessions.db.integration.test.ts +52 -0
  334. package/server/modules/database/tests/user-preferences.db.integration.test.ts +135 -0
  335. package/server/modules/file-tree/file-tree.module.ts +2 -1
  336. package/server/modules/file-tree/file-tree.service.ts +49 -7
  337. package/server/modules/file-tree/tests/file-tree.service.test.ts +163 -1
  338. package/server/modules/git/git-branch-diff.service.ts +204 -0
  339. package/server/modules/git/git-branch.service.ts +2 -12
  340. package/server/modules/git/git.routes.ts +100 -6
  341. package/server/modules/git/tests/git-branch-diff.service.test.ts +210 -0
  342. package/server/modules/projects/project-clone.routes.ts +142 -0
  343. package/server/modules/projects/projects.routes.ts +16 -81
  344. package/server/modules/projects/services/project-clone-request.service.ts +56 -0
  345. package/server/modules/projects/services/project-clone.service.ts +102 -34
  346. package/server/modules/projects/services/project-delete.service.ts +13 -1
  347. package/server/modules/projects/services/project-star.service.ts +2 -2
  348. package/server/modules/projects/tests/project-clone.routes.test.ts +246 -0
  349. package/server/modules/projects/tests/project-clone.service.test.ts +376 -0
  350. package/server/modules/providers/index.ts +4 -0
  351. package/server/modules/providers/list/claude/claude-auth.provider.ts +81 -11
  352. package/server/modules/providers/list/claude/claude-fork.provider.ts +57 -0
  353. package/server/modules/providers/list/claude/claude-models.provider.ts +37 -17
  354. package/server/modules/providers/list/claude/claude-runtime.provider.js +510 -54
  355. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +40 -14
  356. package/server/modules/providers/list/claude/claude-sessions.provider.ts +1195 -63
  357. package/server/modules/providers/list/claude/claude-skills.provider.ts +4 -1
  358. package/server/modules/providers/list/claude/claude.provider.ts +3 -0
  359. package/server/modules/providers/list/codex/codex-app-server.client.ts +243 -0
  360. package/server/modules/providers/list/codex/codex-fork.provider.ts +40 -0
  361. package/server/modules/providers/list/codex/codex-models.provider.ts +47 -0
  362. package/server/modules/providers/list/codex/{codex-runtime.provider.js → codex-runtime.provider.ts} +105 -70
  363. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +9 -0
  364. package/server/modules/providers/list/codex/codex-sessions.provider.ts +1847 -455
  365. package/server/modules/providers/list/codex/codex.provider.ts +3 -0
  366. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +10 -2
  367. package/server/modules/providers/list/cursor/cursor-runtime.provider.js +17 -8
  368. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +0 -1
  369. package/server/modules/providers/list/opencode/opencode-models.provider.ts +297 -9
  370. package/server/modules/providers/list/opencode/opencode-runtime.provider.js +5 -2
  371. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +30 -2
  372. package/server/modules/providers/provider.routes.ts +162 -2
  373. package/server/modules/providers/services/claude-cli-liveness.service.ts +121 -0
  374. package/server/modules/providers/services/claude-settings-permissions.service.ts +127 -0
  375. package/server/modules/providers/services/provider-capabilities.service.ts +40 -1
  376. package/server/modules/providers/services/provider-models.service.ts +71 -4
  377. package/server/modules/providers/services/provider-runtime.service.ts +11 -0
  378. package/server/modules/providers/services/provider-token-usage.service.ts +166 -39
  379. package/server/modules/providers/services/session-conversations-search.service.ts +2 -5
  380. package/server/modules/providers/services/session-history-cache.service.ts +150 -0
  381. package/server/modules/providers/services/session-synchronizer.service.ts +125 -38
  382. package/server/modules/providers/services/sessions-watcher.service.ts +3 -64
  383. package/server/modules/providers/services/sessions.service.ts +309 -17
  384. package/server/modules/providers/tests/claude-auth.test.ts +208 -0
  385. package/server/modules/providers/tests/claude-background-work.test.ts +213 -0
  386. package/server/modules/providers/tests/claude-compaction.test.ts +101 -0
  387. package/server/modules/providers/tests/claude-message-model.test.ts +160 -0
  388. package/server/modules/providers/tests/claude-models.test.ts +87 -0
  389. package/server/modules/providers/tests/claude-runtime-hold.test.ts +309 -0
  390. package/server/modules/providers/tests/claude-sessions.test.ts +2167 -37
  391. package/server/modules/providers/tests/claude-settings-permissions.test.ts +271 -0
  392. package/server/modules/providers/tests/claude-subagent-echo.test.ts +25 -0
  393. package/server/modules/providers/tests/claude-token-budget.test.ts +104 -0
  394. package/server/modules/providers/tests/codex-message-editing.test.ts +419 -0
  395. package/server/modules/providers/tests/codex-models.test.ts +37 -0
  396. package/server/modules/providers/tests/codex-runtime.test.ts +94 -0
  397. package/server/modules/providers/tests/codex-session-fork.test.ts +59 -0
  398. package/server/modules/providers/tests/codex-sessions.test.ts +396 -15
  399. package/server/modules/providers/tests/cursor-auth.test.ts +187 -0
  400. package/server/modules/providers/tests/opencode-models.test.ts +266 -8
  401. package/server/modules/providers/tests/opencode-sessions.test.ts +40 -1
  402. package/server/modules/providers/tests/provider-capabilities.service.test.ts +37 -0
  403. package/server/modules/providers/tests/provider-models.service.test.ts +99 -1
  404. package/server/modules/providers/tests/provider-token-usage.service.test.ts +188 -1
  405. package/server/modules/providers/tests/provider.routes.test.ts +230 -1
  406. package/server/modules/providers/tests/session-fork.test.ts +173 -0
  407. package/server/modules/providers/tests/session-history-cache.service.test.ts +165 -0
  408. package/server/modules/providers/tests/session-orphan-prune.test.ts +107 -0
  409. package/server/modules/providers/tests/session-synchronizer-coalescing.test.ts +136 -0
  410. package/server/modules/providers/tests/sessions.service.test.ts +303 -1
  411. package/server/modules/providers/tests/skills.test.ts +21 -5
  412. package/server/modules/scheduled-messages/index.ts +8 -0
  413. package/server/modules/scheduled-messages/scheduled-messages.routes.ts +68 -0
  414. package/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.ts +216 -0
  415. package/server/modules/scheduled-messages/services/scheduled-messages.service.ts +121 -0
  416. package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +354 -0
  417. package/server/modules/taskmaster/taskmaster.routes.ts +23 -33
  418. package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +57 -0
  419. package/server/modules/user/tests/user.service.test.ts +90 -0
  420. package/server/modules/user/user.module.ts +10 -1
  421. package/server/modules/user/user.routes.ts +44 -0
  422. package/server/modules/user/user.service.ts +105 -0
  423. package/server/modules/voice/tests/voice.service.test.ts +3 -2
  424. package/server/modules/websocket/README.md +4 -2
  425. package/server/modules/websocket/index.ts +8 -0
  426. package/server/modules/websocket/services/chat-run-registry.service.ts +45 -54
  427. package/server/modules/websocket/services/chat-session-writer.service.ts +36 -6
  428. package/server/modules/websocket/services/chat-websocket.service.ts +302 -16
  429. package/server/modules/websocket/services/session-upsert-broadcast.service.ts +108 -0
  430. package/server/modules/websocket/services/shell-websocket.service.ts +276 -22
  431. package/server/modules/websocket/tests/chat-background-subscribe.test.ts +167 -0
  432. package/server/modules/websocket/tests/chat-edit-send.test.ts +309 -0
  433. package/server/modules/websocket/tests/chat-run-registry.test.ts +34 -3
  434. package/server/modules/websocket/tests/chat-stop-task.test.ts +127 -0
  435. package/server/modules/websocket/tests/session-upsert-broadcast.test.ts +138 -0
  436. package/server/modules/websocket/tests/shell-websocket.service.test.ts +629 -0
  437. package/server/shared/claude-cli-path.ts +24 -6
  438. package/server/shared/index.ts +3 -0
  439. package/server/shared/interfaces.ts +91 -0
  440. package/server/shared/message-unification.ts +449 -0
  441. package/server/shared/tests/claude-cli-path.test.ts +58 -1
  442. package/server/shared/tests/message-unification.test.ts +218 -0
  443. package/server/shared/tests/read-only-roots.test.ts +139 -0
  444. package/server/shared/tests/strip-ansi-sequences.test.ts +42 -0
  445. package/server/shared/types.ts +382 -7
  446. package/server/shared/utils.ts +176 -0
  447. package/dist/assets/channel-_falYbU1.js +0 -1
  448. package/dist/assets/classDiagram-JCYQIIEL-Dn-3CfpR.js +0 -1
  449. package/dist/assets/classDiagram-v2-OCEON4UE-Dn-3CfpR.js +0 -1
  450. package/dist/assets/index-CzPLBvXT.css +0 -32
  451. package/dist/assets/index-DFkBBuSA.js +0 -1549
  452. package/dist/assets/stateDiagram-v2-UEYNNEHI-BvBxUUrZ.js +0 -1
  453. package/dist/assets/swimlanesDiagram-ULZ7WXOC-CsE-x4YK.js +0 -8
@@ -1,5 +1,6 @@
1
1
  import { AbstractProvider } from '@/modules/providers/shared/base/abstract.provider.js';
2
2
  import { CodexProviderAuth } from '@/modules/providers/list/codex/codex-auth.provider.js';
3
+ import { CodexForkProvider } from '@/modules/providers/list/codex/codex-fork.provider.js';
3
4
  import { CodexProviderModels } from '@/modules/providers/list/codex/codex-models.provider.js';
4
5
  import { codexRuntime } from '@/modules/providers/list/codex/codex-runtime.provider.js';
5
6
  import { CodexMcpProvider } from '@/modules/providers/list/codex/codex-mcp.provider.js';
@@ -8,6 +9,7 @@ import { CodexSessionsProvider } from '@/modules/providers/list/codex/codex-sess
8
9
  import { CodexSkillsProvider } from '@/modules/providers/list/codex/codex-skills.provider.js';
9
10
  import type {
10
11
  IProviderAuth,
12
+ IProviderFork,
11
13
  IProviderModels,
12
14
  IProviderRuntime,
13
15
  IProviderSessionSynchronizer,
@@ -22,6 +24,7 @@ export class CodexProvider extends AbstractProvider {
22
24
  readonly auth: IProviderAuth = new CodexProviderAuth();
23
25
  readonly skills: IProviderSkills = new CodexSkillsProvider();
24
26
  readonly sessions: IProviderSessions = new CodexSessionsProvider();
27
+ readonly fork: IProviderFork = new CodexForkProvider();
25
28
  readonly sessionSynchronizer: IProviderSessionSynchronizer = new CodexSessionSynchronizer();
26
29
 
27
30
  constructor() {
@@ -10,6 +10,12 @@ type CursorLoginStatus = {
10
10
  error?: string;
11
11
  };
12
12
 
13
+ // `cursor-agent status` decides "logged in" from the locally stored tokens, then fetches the
14
+ // account details from Cursor's API. That request cannot change the verdict (on failure the CLI
15
+ // still reports logged in), it only adds a network round trip to the CLI's startup (3-6 s on a
16
+ // busy host even when logged out). A 5 s cap reported fresh logins as "Command timeout" (#551).
17
+ const STATUS_TIMEOUT_MS = 20_000;
18
+
13
19
  export class CursorProviderAuth implements IProviderAuth {
14
20
  /**
15
21
  * Checks whether the cursor-agent CLI is available on this host.
@@ -71,7 +77,7 @@ export class CursorProviderAuth implements IProviderAuth {
71
77
  error: 'Command timeout',
72
78
  });
73
79
  }
74
- }, 5000);
80
+ }, STATUS_TIMEOUT_MS);
75
81
 
76
82
  try {
77
83
  childProcess = spawn('cursor-agent', ['status']);
@@ -112,8 +118,10 @@ export class CursorProviderAuth implements IProviderAuth {
112
118
  return;
113
119
  }
114
120
 
121
+ // e.g. "Logged in (unable to fetch user details)" when the account request failed.
122
+ // There is no email to show, so the UI uses its own fallback label.
115
123
  if (stdout.includes('Logged in')) {
116
- resolve({ authenticated: true, email: 'Logged in', method: 'cli' });
124
+ resolve({ authenticated: true, email: null, method: 'cli' });
117
125
  return;
118
126
  }
119
127
 
@@ -6,7 +6,7 @@ import {
6
6
  normalizeAttachmentDescriptors
7
7
  } from '@/shared/image-attachments.js';
8
8
  import { notifyRunFailed, notifyRunStopped } from '@/modules/notifications/index.js';
9
- import { createCompleteMessage, createNormalizedMessage, flattenPromptForWindowsShell } from '@/shared/utils.js';
9
+ import { createCompleteMessage, createNormalizedMessage, flattenPromptForWindowsShell, stripAnsiSequences } from '@/shared/utils.js';
10
10
 
11
11
  // cross-spawn resolves .cmd shims/PATHEXT on Windows and delegates to
12
12
  // child_process.spawn everywhere else.
@@ -30,22 +30,24 @@ function isWorkspaceTrustPrompt(text = '') {
30
30
  }
31
31
 
32
32
  async function spawnCursor(command, options = {}, ws, context) {
33
- return new Promise(async (resolve, reject) => {
33
+ // Callers pass the stable app session id; the CLI resumes with the
34
+ // provider-native id recorded on the session row. Both lookups run before the
35
+ // promise is created: inside an async executor a rejected `resolveResumeModel`
36
+ // would be swallowed and leave the returned promise pending forever.
37
+ const providerSessionId = context.resolveProviderSessionId(options.sessionId);
38
+ const resolvedModel = await context.resolveResumeModel(options.sessionId, options.model);
39
+
40
+ return new Promise((resolve, reject) => {
34
41
  const {
35
42
  sessionId,
36
43
  projectPath,
37
44
  cwd,
38
45
  toolsSettings,
39
46
  skipPermissions,
40
- model,
41
47
  sessionSummary,
42
48
  images,
43
49
  files
44
50
  } = options;
45
- // Callers pass the stable app session id; the CLI resumes with the
46
- // provider-native id recorded on the session row.
47
- const providerSessionId = context.resolveProviderSessionId(sessionId);
48
- const resolvedModel = await context.resolveResumeModel(sessionId, model);
49
51
  let capturedSessionId = providerSessionId; // Track the provider-native session id throughout the process
50
52
  let sessionCreatedSent = false; // Track if we've already sent session-created event
51
53
  let hasRetriedWithTrust = false;
@@ -275,7 +277,14 @@ async function spawnCursor(command, options = {}, ws, context) {
275
277
  return;
276
278
  }
277
279
 
278
- ws.send(createNormalizedMessage({ kind: 'error', content: stderrText, sessionId: capturedSessionId || sessionId || null, provider: 'cursor' }));
280
+ // The CLI styles its stderr for a terminal; the chat renders plain
281
+ // text, so the escapes have to go before the text is surfaced.
282
+ const cleanedStderrText = stripAnsiSequences(stderrText);
283
+ if (!cleanedStderrText.trim()) {
284
+ return;
285
+ }
286
+
287
+ ws.send(createNormalizedMessage({ kind: 'error', content: cleanedStderrText, sessionId: capturedSessionId || sessionId || null, provider: 'cursor' }));
279
288
  });
280
289
 
281
290
  // Handle process completion
@@ -1,4 +1,3 @@
1
- import crypto from 'node:crypto';
2
1
  import fs from 'node:fs';
3
2
  import fsp from 'node:fs/promises';
4
3
  import os from 'node:os';
@@ -1,3 +1,7 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+
1
5
  import Database from 'better-sqlite3';
2
6
 
3
7
  import { sessionsDb } from '@/modules/database/index.js';
@@ -17,9 +21,9 @@ import {
17
21
  * Curated OpenCode catalog shipped as immutable CloudCLI defaults.
18
22
  *
19
23
  * OpenCode routes by `<providerID>/<modelID>`, so this list mirrors the
20
- * providers `opencode models --verbose` reports: the OpenCode Zen gateway plus
21
- * the Anthropic and OpenAI providers OpenCode can address directly with the
22
- * user's own credentials.
24
+ * providers `opencode models --verbose` reports: the OpenCode Zen gateway, the
25
+ * OpenCode Go subscription gateway, and the Anthropic and OpenAI providers
26
+ * OpenCode can address directly with the user's own credentials.
23
27
  */
24
28
  export const OPENCODE_PREDEFINED_MODELS: ProviderModelsDefinition = {
25
29
  OPTIONS: [
@@ -77,6 +81,178 @@ export const OPENCODE_PREDEFINED_MODELS: ProviderModelsDefinition = {
77
81
  { value: 'opencode/north-mini-code-free', label: 'North Mini Code Free', description: 'OpenCode Zen · Free' },
78
82
  { value: 'opencode/nemotron-3-ultra-free', label: 'Nemotron 3 Ultra Free', description: 'OpenCode Zen · Free' },
79
83
  { value: 'opencode/deepseek-v4-flash-free', label: 'DeepSeek V4 Flash Free', description: 'OpenCode Zen · Free' },
84
+ {
85
+ value: 'opencode-go/grok-4.6',
86
+ label: 'Grok 4.6',
87
+ description: 'OpenCode Go',
88
+ effort: {
89
+ values: [{ value: 'low' }, { value: 'medium' }, { value: 'high' }, { value: 'xhigh' }],
90
+ },
91
+ },
92
+ {
93
+ value: 'opencode-go/glm-5.3-flash',
94
+ label: 'GLM 5.3 Flash',
95
+ description: 'OpenCode Go',
96
+ effort: {
97
+ values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
98
+ },
99
+ },
100
+ {
101
+ value: 'opencode-go/glm-5.3',
102
+ label: 'GLM 5.3',
103
+ description: 'OpenCode Go',
104
+ effort: {
105
+ values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
106
+ },
107
+ },
108
+ {
109
+ value: 'opencode-go/glm-5.2',
110
+ label: 'GLM 5.2',
111
+ description: 'OpenCode Go',
112
+ effort: {
113
+ values: [{ value: 'high' }, { value: 'max' }],
114
+ },
115
+ },
116
+ { value: 'opencode-go/glm-5.1', label: 'GLM 5.1', description: 'OpenCode Go' },
117
+ {
118
+ value: 'opencode-go/gpt-5.6-luna',
119
+ label: 'GPT 5.6 Luna',
120
+ description: 'OpenCode Go',
121
+ effort: {
122
+ values: [
123
+ { value: 'none' },
124
+ { value: 'low' },
125
+ { value: 'medium' },
126
+ { value: 'high' },
127
+ { value: 'xhigh' },
128
+ { value: 'max' },
129
+ ],
130
+ },
131
+ },
132
+ {
133
+ value: 'opencode-go/kimi-k3',
134
+ label: 'Kimi K3',
135
+ description: 'OpenCode Go',
136
+ effort: {
137
+ values: [{ value: 'max' }],
138
+ },
139
+ },
140
+ { value: 'opencode-go/kimi-k2.7-code', label: 'Kimi K2.7 Code', description: 'OpenCode Go' },
141
+ { value: 'opencode-go/kimi-k2.6', label: 'Kimi K2.6', description: 'OpenCode Go' },
142
+ {
143
+ value: 'opencode-go/longcat-2.0',
144
+ label: 'LongCat 2.0',
145
+ description: 'OpenCode Go',
146
+ effort: {
147
+ values: [{ value: 'low' }, { value: 'medium' }, { value: 'high' }],
148
+ },
149
+ },
150
+ { value: 'opencode-go/mimo-v2.5', label: 'MiMo V2.5', description: 'OpenCode Go' },
151
+ { value: 'opencode-go/mimo-v2.5-pro', label: 'MiMo V2.5 Pro', description: 'OpenCode Go' },
152
+ {
153
+ value: 'opencode-go/minimax-m3',
154
+ label: 'MiniMax M3',
155
+ description: 'OpenCode Go',
156
+ effort: {
157
+ values: [{ value: 'none' }, { value: 'thinking' }],
158
+ },
159
+ },
160
+ { value: 'opencode-go/minimax-m2.7', label: 'MiniMax M2.7', description: 'OpenCode Go' },
161
+ {
162
+ value: 'opencode-go/muse-spark-1.3-contributor',
163
+ label: 'Muse Spark 1.3 Contributor',
164
+ description: 'OpenCode Go',
165
+ effort: {
166
+ values: [
167
+ { value: 'minimal' },
168
+ { value: 'low' },
169
+ { value: 'medium' },
170
+ { value: 'high' },
171
+ { value: 'xhigh' },
172
+ ],
173
+ },
174
+ },
175
+ {
176
+ value: 'opencode-go/muse-spark-1.2-contributor',
177
+ label: 'Muse Spark 1.2 Contributor',
178
+ description: 'OpenCode Go',
179
+ effort: {
180
+ values: [
181
+ { value: 'minimal' },
182
+ { value: 'low' },
183
+ { value: 'medium' },
184
+ { value: 'high' },
185
+ { value: 'xhigh' },
186
+ ],
187
+ },
188
+ },
189
+ {
190
+ value: 'opencode-go/qwen3.8-max',
191
+ label: 'Qwen3.8 Max',
192
+ description: 'OpenCode Go',
193
+ effort: {
194
+ values: [{ value: 'low' }, { value: 'medium' }, { value: 'xhigh' }],
195
+ },
196
+ },
197
+ {
198
+ value: 'opencode-go/qwen3.8-flash',
199
+ label: 'Qwen3.8 Flash',
200
+ description: 'OpenCode Go',
201
+ effort: {
202
+ values: [{ value: 'low' }, { value: 'medium' }, { value: 'xhigh' }],
203
+ },
204
+ },
205
+ { value: 'opencode-go/qwen3.7-max', label: 'Qwen3.7 Max', description: 'OpenCode Go' },
206
+ { value: 'opencode-go/qwen3.7-plus', label: 'Qwen3.7 Plus', description: 'OpenCode Go' },
207
+ { value: 'opencode-go/qwen3.6-plus', label: 'Qwen3.6 Plus', description: 'OpenCode Go' },
208
+ {
209
+ value: 'opencode-go/deepseek-v4-pro',
210
+ label: 'DeepSeek V4 Pro',
211
+ description: 'OpenCode Go',
212
+ effort: {
213
+ values: [{ value: 'high' }, { value: 'max' }],
214
+ },
215
+ },
216
+ {
217
+ value: 'opencode-go/deepseek-v4-flash',
218
+ label: 'DeepSeek V4 Flash',
219
+ description: 'OpenCode Go',
220
+ effort: {
221
+ values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
222
+ },
223
+ },
224
+ {
225
+ value: 'opencode-go/deepseek-v4-flash-vision-exp',
226
+ label: 'DeepSeek V4 Flash Vision Exp',
227
+ description: 'OpenCode Go',
228
+ effort: {
229
+ values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
230
+ },
231
+ },
232
+ {
233
+ value: 'opencode-go/hy4-preview',
234
+ label: 'Hy4 Preview',
235
+ description: 'OpenCode Go',
236
+ effort: {
237
+ values: [{ value: 'none' }, { value: 'high' }],
238
+ },
239
+ },
240
+ {
241
+ value: 'opencode-go/hy3',
242
+ label: 'Hy3',
243
+ description: 'OpenCode Go',
244
+ effort: {
245
+ values: [{ value: 'none' }, { value: 'low' }, { value: 'high' }],
246
+ },
247
+ },
248
+ {
249
+ value: 'opencode-go/omen-alpha',
250
+ label: 'Omen Alpha',
251
+ description: 'OpenCode Go',
252
+ effort: {
253
+ values: [{ value: 'low' }, { value: 'high' }],
254
+ },
255
+ },
80
256
  { value: 'anthropic/claude-opus-5', label: 'Claude Opus 5', description: 'Anthropic' },
81
257
  { value: 'anthropic/claude-opus-5-fast', label: 'Claude Opus 5 Fast', description: 'Anthropic' },
82
258
  { value: 'anthropic/claude-fable-5', label: 'Claude Fable 5', description: 'Anthropic' },
@@ -117,6 +293,100 @@ export const OPENCODE_PREDEFINED_MODELS: ProviderModelsDefinition = {
117
293
  DEFAULT: 'opencode/gpt-5.6-terra',
118
294
  };
119
295
 
296
+ /** Global OpenCode config files, in the order the CLI loads them. */
297
+ const OPENCODE_CONFIG_FILES = ['config.json', 'opencode.json', 'opencode.jsonc'];
298
+
299
+ /** Provider API keys OpenCode reads straight from the environment. */
300
+ const OPENCODE_ENV_PROVIDER_IDS: Record<string, string> = {
301
+ OPENCODE_API_KEY: 'opencode',
302
+ ANTHROPIC_API_KEY: 'anthropic',
303
+ OPENAI_API_KEY: 'openai',
304
+ };
305
+
306
+ const readOpenCodeJsonFile = async (filePath: string): Promise<Record<string, unknown> | null> => {
307
+ try {
308
+ return readObjectRecord(JSON.parse(await readFile(filePath, 'utf8')));
309
+ } catch {
310
+ // Missing, unreadable, or comment-bearing (.jsonc) files simply contribute
311
+ // nothing; the auth store is the authoritative source below.
312
+ return null;
313
+ }
314
+ };
315
+
316
+ /**
317
+ * Lists the upstream providers this OpenCode install can actually route to.
318
+ *
319
+ * OpenCode resolves `<providerID>/<modelID>` against the providers the user has
320
+ * connected, and rejects anything else outright - `Model
321
+ * opencode/claude-sonnet-4-6 is not valid` is what a run gets for asking for an
322
+ * OpenCode Zen model on a machine that only has an Anthropic key. The curated
323
+ * catalog spans every provider OpenCode can address, so it has to be narrowed
324
+ * to this machine's providers before it reaches the model picker.
325
+ *
326
+ * Returns null when nothing can be read, so the caller keeps the full catalog
327
+ * rather than leaving the picker empty. Providers declared only in a
328
+ * project-level `opencode.json` are not visible here; the null fallback and the
329
+ * env-key sweep keep those installs on the full list.
330
+ */
331
+ const readConnectedOpenCodeProviderIds = async (): Promise<Set<string> | null> => {
332
+ const providerIds = new Set<string>();
333
+ const configDir = path.join(os.homedir(), '.config', 'opencode');
334
+
335
+ const auth = await readOpenCodeJsonFile(
336
+ path.join(os.homedir(), '.local', 'share', 'opencode', 'auth.json'),
337
+ );
338
+ for (const [providerId, credential] of Object.entries(auth ?? {})) {
339
+ if (readObjectRecord(credential)) {
340
+ providerIds.add(providerId);
341
+ }
342
+ }
343
+
344
+ for (const configFile of OPENCODE_CONFIG_FILES) {
345
+ const config = await readOpenCodeJsonFile(path.join(configDir, configFile));
346
+ for (const providerId of Object.keys(readObjectRecord(config?.provider) ?? {})) {
347
+ providerIds.add(providerId);
348
+ }
349
+ }
350
+
351
+ for (const [envKey, providerId] of Object.entries(OPENCODE_ENV_PROVIDER_IDS)) {
352
+ if (readOptionalString(process.env[envKey])) {
353
+ providerIds.add(providerId);
354
+ }
355
+ }
356
+
357
+ return providerIds.size > 0 ? providerIds : null;
358
+ };
359
+
360
+ /**
361
+ * Narrows the curated catalog to the providers OpenCode can route to.
362
+ *
363
+ * The default has to move with the list: leaving it on an OpenCode Zen model
364
+ * would hand every new session a model the CLI refuses to run.
365
+ */
366
+ const filterOpenCodeModelsByProvider = (
367
+ definition: ProviderModelsDefinition,
368
+ connectedProviderIds: Set<string> | null,
369
+ ): ProviderModelsDefinition => {
370
+ if (!connectedProviderIds) {
371
+ return definition;
372
+ }
373
+
374
+ const options = definition.OPTIONS.filter(
375
+ (option) => connectedProviderIds.has(option.value.split('/')[0]),
376
+ );
377
+ if (options.length === 0) {
378
+ return definition;
379
+ }
380
+
381
+ return {
382
+ ...definition,
383
+ OPTIONS: options,
384
+ DEFAULT: options.some((option) => option.value === definition.DEFAULT)
385
+ ? definition.DEFAULT
386
+ : options[0].value,
387
+ };
388
+ };
389
+
120
390
  const parseOpenCodeSessionModelValue = (rawModel: unknown): string | null => {
121
391
  if (typeof rawModel === 'string') {
122
392
  const trimmed = rawModel.trim();
@@ -136,22 +406,40 @@ const parseOpenCodeSessionModelValue = (rawModel: unknown): string | null => {
136
406
  return null;
137
407
  }
138
408
 
139
- return readOptionalString(record.id)
409
+ const modelId = readOptionalString(record.id)
140
410
  ?? readOptionalString(record.model)
141
411
  ?? readOptionalString(record.name)
142
- ?? readOptionalString(record.value)
143
- ?? null;
412
+ ?? readOptionalString(record.value);
413
+ if (!modelId) {
414
+ return null;
415
+ }
416
+
417
+ // OpenCode persists the provider and model id in separate fields (for
418
+ // example {"id":"z-ai/glm-5.3-flash","providerID":"openrouter"}), and its
419
+ // CLI's `--model` flag only accepts the composed `<providerID>/<modelID>`
420
+ // form. Compose it here so a resumed session resolves the same model
421
+ // instead of failing with an unknown-model error.
422
+ const providerId = readOptionalString(record.providerID)
423
+ ?? readOptionalString(record.providerId);
424
+ if (providerId && !modelId.startsWith(`${providerId}/`)) {
425
+ return `${providerId}/${modelId}`;
426
+ }
427
+
428
+ return modelId;
144
429
  };
145
430
 
146
431
  /** Provider registry model adapter for OpenCode predefined models and session metadata. */
147
432
  export class OpenCodeProviderModels implements IProviderModels {
148
433
  async getSupportedModels(): Promise<ProviderModelsDefinition> {
149
- return OPENCODE_PREDEFINED_MODELS;
434
+ return filterOpenCodeModelsByProvider(
435
+ OPENCODE_PREDEFINED_MODELS,
436
+ await readConnectedOpenCodeProviderIds(),
437
+ );
150
438
  }
151
439
 
152
440
  async getCurrentActiveModel(sessionId?: string): Promise<ProviderCurrentActiveModel> {
153
441
  if (!sessionId?.trim()) {
154
- return buildDefaultProviderCurrentActiveModel(OPENCODE_PREDEFINED_MODELS);
442
+ return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
155
443
  }
156
444
 
157
445
  // OpenCode's `session` table is keyed by its own session id, so the stable
@@ -198,6 +486,6 @@ export class OpenCodeProviderModels implements IProviderModels {
198
486
  // Fall through to the curated default when OpenCode session lookup fails.
199
487
  }
200
488
 
201
- return buildDefaultProviderCurrentActiveModel(OPENCODE_PREDEFINED_MODELS);
489
+ return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
202
490
  }
203
491
  }
@@ -9,7 +9,7 @@ import {
9
9
  normalizeAttachmentDescriptors
10
10
  } from '@/shared/image-attachments.js';
11
11
  import { notifyRunFailed, notifyRunStopped } from '@/modules/notifications/index.js';
12
- import { createCompleteMessage, createNormalizedMessage, flattenPromptForWindowsShell, getOpenCodeDatabasePath } from '@/shared/utils.js';
12
+ import { createCompleteMessage, createNormalizedMessage, flattenPromptForWindowsShell, getOpenCodeDatabasePath, stripAnsiSequences } from '@/shared/utils.js';
13
13
 
14
14
  // cross-spawn resolves .cmd shims/PATHEXT on Windows and delegates to
15
15
  // child_process.spawn everywhere else.
@@ -308,7 +308,10 @@ async function spawnOpenCode(command, options = {}, ws, context) {
308
308
  });
309
309
 
310
310
  opencodeProcess.stderr.on('data', (data) => {
311
- const stderrText = data.toString();
311
+ // opencode styles its stderr for a terminal; the chat renders plain
312
+ // text, so the escapes have to go before the text is surfaced. A chunk
313
+ // that was styling only cleans down to nothing and is not an error.
314
+ const stderrText = stripAnsiSequences(data.toString());
312
315
  if (!stderrText.trim()) {
313
316
  return;
314
317
  }
@@ -28,17 +28,23 @@ type SynchronizeRowsResult = {
28
28
  firstSessionId: string | null;
29
29
  };
30
30
 
31
+ type OpenCodeChildSessionRow = {
32
+ id: string;
33
+ };
34
+
31
35
  /**
32
36
  * Session indexer for OpenCode's SQLite-backed session store.
33
37
  */
34
38
  export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer {
35
39
  private readonly provider = 'opencode' as const;
40
+ private childSessionsReconciled = false;
36
41
 
37
42
  /**
38
43
  * Scans OpenCode's shared opencode.db and upserts active sessions into DB.
39
44
  */
40
45
  async synchronize(since?: Date): Promise<number> {
41
- const result = this.synchronizeRows(since);
46
+ // The first provider-wide scan also reconciles child rows indexed by older versions.
47
+ const result = this.synchronizeRows(since, undefined, !this.childSessionsReconciled);
42
48
  return result.processed;
43
49
  }
44
50
 
@@ -54,7 +60,11 @@ export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer
54
60
  return result.firstSessionId;
55
61
  }
56
62
 
57
- private synchronizeRows(since?: Date, limit?: number): SynchronizeRowsResult {
63
+ private synchronizeRows(
64
+ since?: Date,
65
+ limit?: number,
66
+ pruneChildSessions = false,
67
+ ): SynchronizeRowsResult {
58
68
  const dbPath = getOpenCodeDatabasePath();
59
69
  if (!fsSync.existsSync(dbPath)) {
60
70
  return { processed: 0, firstSessionId: null };
@@ -62,6 +72,11 @@ export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer
62
72
 
63
73
  const db = new Database(dbPath, { readonly: true, fileMustExist: true });
64
74
  try {
75
+ if (pruneChildSessions) {
76
+ this.pruneChildSessions(db);
77
+ this.childSessionsReconciled = true;
78
+ }
79
+
65
80
  const sinceMillis = since?.getTime() ?? null;
66
81
  const limitClause = limit ? 'LIMIT ?' : '';
67
82
  const params = limit ? [sinceMillis, sinceMillis, limit] : [sinceMillis, sinceMillis];
@@ -76,6 +91,7 @@ export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer
76
91
  FROM session s
77
92
  LEFT JOIN project p ON p.id = s.project_id
78
93
  WHERE s.time_archived IS NULL
94
+ AND s.parent_id IS NULL
79
95
  AND (? IS NULL OR COALESCE(s.time_updated, s.time_created, 0) >= ?)
80
96
  ORDER BY COALESCE(s.time_updated, s.time_created, 0) DESC, s.id DESC
81
97
  ${limitClause}
@@ -105,6 +121,18 @@ export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer
105
121
  }
106
122
  }
107
123
 
124
+ private pruneChildSessions(db: Database.Database): void {
125
+ const childSessions = db.prepare(`
126
+ SELECT id
127
+ FROM session
128
+ WHERE parent_id IS NOT NULL
129
+ `).all() as OpenCodeChildSessionRow[];
130
+
131
+ for (const childSession of childSessions) {
132
+ sessionsDb.deleteSessionByProviderSessionId(childSession.id, this.provider);
133
+ }
134
+ }
135
+
108
136
  private upsertSession(db: Database.Database, row: OpenCodeSessionRow): string | null {
109
137
  const sessionId = readOptionalString(row.id);
110
138
  const projectPath = readOptionalString(row.directory) ?? readOptionalString(row.worktree);