@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
@@ -0,0 +1,243 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { stat } from 'node:fs/promises';
3
+ import { createRequire } from 'node:module';
4
+ import readline from 'node:readline';
5
+
6
+ import { AppError } from '@/shared/utils.js';
7
+
8
+ /**
9
+ * Minimal JSON-RPC client for `codex app-server`.
10
+ *
11
+ * Codex ships two entry points and they expose different things. The
12
+ * `@openai/codex-sdk` this app runs conversations through is a wrapper around
13
+ * `codex exec`, and its whole surface is `startThread` and `resumeThread` —
14
+ * there is no way to branch a thread or to resume one partway. The same
15
+ * binary's `app-server` subcommand speaks JSON-RPC and does have that
16
+ * primitive, `thread/fork`, which is what the Codex IDE clients build their
17
+ * own "fork" and "edit an earlier message" on top of.
18
+ *
19
+ * So this is a second transport to the same CLI, opened only for the
20
+ * operations the SDK cannot express. Everything else still goes through the
21
+ * SDK.
22
+ */
23
+
24
+ /** How long a single request may take before the child is killed. */
25
+ const REQUEST_TIMEOUT_MS = 30_000;
26
+
27
+ type JsonRpcResponse = {
28
+ id?: number;
29
+ result?: unknown;
30
+ error?: { code?: number; message?: string };
31
+ };
32
+
33
+ /**
34
+ * One fork of a Codex thread.
35
+ *
36
+ * `path` is returned by the server rather than reconstructed: the rollout
37
+ * lands in today's date directory, not next to the file it was copied from,
38
+ * so deriving it from the source path would be wrong roughly every day.
39
+ */
40
+ export type CodexThreadFork = {
41
+ threadId: string;
42
+ path: string;
43
+ };
44
+
45
+ /**
46
+ * Resolves the `codex` launcher shipped in node_modules.
47
+ *
48
+ * Deliberately not the `codex` on PATH: a machine can have a second, older
49
+ * install, and the protocol this speaks is only guaranteed against the
50
+ * version this package depends on.
51
+ */
52
+ function resolveCodexLauncher(): string {
53
+ const require_ = createRequire(import.meta.url);
54
+ try {
55
+ return require_.resolve('@openai/codex/bin/codex.js');
56
+ } catch {
57
+ throw new AppError('The Codex CLI package is not installed, so Codex conversations cannot be branched.', {
58
+ code: 'CODEX_APP_SERVER_UNAVAILABLE',
59
+ statusCode: 501,
60
+ });
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Runs one exchange against a freshly spawned `codex app-server`.
66
+ *
67
+ * A process per operation rather than a pooled long-lived one: the handshake
68
+ * costs a fraction of a second, forking happens at most once per user action,
69
+ * and a shared child would need lifecycle handling — restarts, back-pressure,
70
+ * a crash taking every pending fork with it — for no measurable gain next to
71
+ * the model turn that follows.
72
+ */
73
+ async function withAppServer<T>(
74
+ run: (call: (method: string, params: unknown) => Promise<unknown>) => Promise<T>,
75
+ ): Promise<T> {
76
+ const launcher = resolveCodexLauncher();
77
+ const child = spawn(process.execPath, [launcher, 'app-server'], {
78
+ env: process.env,
79
+ stdio: ['pipe', 'pipe', 'pipe'],
80
+ });
81
+
82
+ // The server logs sandbox and skill warnings to stderr on every start. They
83
+ // are not failures and drowning the app log in them helps nobody, so stderr
84
+ // is only kept around to explain a spawn that dies.
85
+ let stderr = '';
86
+ child.stderr?.on('data', (chunk) => {
87
+ stderr = (stderr + String(chunk)).slice(-2000);
88
+ });
89
+
90
+ let nextRequestId = 1;
91
+ const pending = new Map<number, (response: JsonRpcResponse) => void>();
92
+ let exitReason: string | null = null;
93
+
94
+ const reader = readline.createInterface({ input: child.stdout });
95
+ reader.on('line', (line) => {
96
+ if (!line.trim()) {
97
+ return;
98
+ }
99
+ let message: JsonRpcResponse;
100
+ try {
101
+ message = JSON.parse(line) as JsonRpcResponse;
102
+ } catch {
103
+ // Server-to-client notifications and any non-JSON banner are not
104
+ // replies to anything this client asked for.
105
+ return;
106
+ }
107
+ if (typeof message.id !== 'number') {
108
+ return;
109
+ }
110
+ pending.get(message.id)?.(message);
111
+ pending.delete(message.id);
112
+ });
113
+
114
+ const failPending = (reason: string) => {
115
+ exitReason = reason;
116
+ for (const resolve of pending.values()) {
117
+ resolve({ error: { message: reason } });
118
+ }
119
+ pending.clear();
120
+ };
121
+
122
+ child.on('error', (error) => failPending(error.message));
123
+ child.on('exit', (code, signal) => {
124
+ failPending(`codex app-server exited (code ${code ?? 'null'}, signal ${signal ?? 'null'})`);
125
+ });
126
+ // A child that dies mid-request leaves its pipes broken, and the next write
127
+ // raises EPIPE on the stream rather than at the call site. Without a
128
+ // listener that is an unhandled 'error' event, which takes the whole server
129
+ // down over one failed fork.
130
+ child.stdin?.on('error', (error) => failPending(error.message));
131
+ child.stdout?.on('error', (error) => failPending(error.message));
132
+ child.stderr?.on('error', () => {});
133
+
134
+ const call = (method: string, params: unknown): Promise<unknown> =>
135
+ new Promise((resolve, reject) => {
136
+ if (exitReason) {
137
+ reject(new AppError(`Codex app-server is not running: ${exitReason}`, {
138
+ code: 'CODEX_APP_SERVER_UNAVAILABLE',
139
+ statusCode: 502,
140
+ }));
141
+ return;
142
+ }
143
+
144
+ const id = nextRequestId++;
145
+ const timer = setTimeout(() => {
146
+ pending.delete(id);
147
+ reject(new AppError(`Codex app-server did not answer "${method}" within ${REQUEST_TIMEOUT_MS}ms.`, {
148
+ code: 'CODEX_APP_SERVER_TIMEOUT',
149
+ statusCode: 504,
150
+ }));
151
+ }, REQUEST_TIMEOUT_MS);
152
+
153
+ pending.set(id, (response) => {
154
+ clearTimeout(timer);
155
+ if (response.error) {
156
+ reject(new AppError(response.error.message || `Codex app-server rejected "${method}".`, {
157
+ code: 'CODEX_APP_SERVER_ERROR',
158
+ statusCode: 502,
159
+ details: { method, rpcCode: response.error.code },
160
+ }));
161
+ return;
162
+ }
163
+ resolve(response.result);
164
+ });
165
+
166
+ child.stdin?.write(`${JSON.stringify({ jsonrpc: '2.0', id, method, params })}\n`);
167
+ });
168
+
169
+ try {
170
+ // `capabilities` is deliberately empty. `thread/fork` with `lastTurnId` is
171
+ // in the stable protocol; only `beforeTurnId` and the turn-listing methods
172
+ // are gated behind `experimentalApi`, and neither is needed here.
173
+ await call('initialize', {
174
+ clientInfo: { name: 'cloudcli', title: 'CloudCLI', version: '1' },
175
+ capabilities: {},
176
+ });
177
+ child.stdin?.write(`${JSON.stringify({ jsonrpc: '2.0', method: 'initialized', params: {} })}\n`);
178
+
179
+ return await run(call);
180
+ } catch (error) {
181
+ if (error instanceof AppError && exitReason) {
182
+ throw new AppError(`${error.message}${stderr ? ` — ${stderr.trim().split('\n').slice(-1)[0]}` : ''}`, {
183
+ code: error.code,
184
+ statusCode: error.statusCode,
185
+ });
186
+ }
187
+ throw error;
188
+ } finally {
189
+ reader.close();
190
+ child.kill();
191
+ }
192
+ }
193
+
194
+ export const codexAppServer = {
195
+ /**
196
+ * Copies a thread into a new one that ends at `lastTurnId`, or copies the
197
+ * whole thread when it is omitted.
198
+ *
199
+ * `lastTurnId` is inclusive of the turn it names, which is the same
200
+ * convention the app's edit anchor uses ("the last row to keep").
201
+ *
202
+ * `cwd` decides the working directory recorded in the copy's `session_meta`,
203
+ * and that field is what the session indexer keys a session's project off —
204
+ * omitting it would file every fork under whatever directory this server
205
+ * happens to be running from.
206
+ */
207
+ async forkThread(input: {
208
+ threadId: string;
209
+ lastTurnId?: string;
210
+ cwd: string;
211
+ }): Promise<CodexThreadFork> {
212
+ return withAppServer(async (call) => {
213
+ const result = await call('thread/fork', {
214
+ threadId: input.threadId,
215
+ ...(input.lastTurnId ? { lastTurnId: input.lastTurnId } : {}),
216
+ ...(input.cwd ? { cwd: input.cwd } : {}),
217
+ }) as { thread?: { id?: unknown; path?: unknown } } | undefined;
218
+
219
+ const threadId = typeof result?.thread?.id === 'string' ? result.thread.id : '';
220
+ const path = typeof result?.thread?.path === 'string' ? result.thread.path : '';
221
+ if (!threadId || !path) {
222
+ throw new AppError('Codex reported a fork without a thread id or transcript path.', {
223
+ code: 'FORK_FAILED',
224
+ statusCode: 502,
225
+ });
226
+ }
227
+
228
+ // Confirmed rather than trusted: both callers are about to point a
229
+ // database row at this file, and a row naming a transcript that is not
230
+ // there is a session that can never be opened.
231
+ try {
232
+ await stat(path);
233
+ } catch {
234
+ throw new AppError('Codex reported a fork but wrote no transcript for it.', {
235
+ code: 'FORK_FAILED',
236
+ statusCode: 502,
237
+ });
238
+ }
239
+
240
+ return { threadId, path };
241
+ });
242
+ },
243
+ };
@@ -0,0 +1,40 @@
1
+ import { codexAppServer } from '@/modules/providers/list/codex/codex-app-server.client.js';
2
+ import type { IProviderFork } from '@/shared/interfaces.js';
3
+
4
+ /**
5
+ * Branches a Codex conversation into an independent thread.
6
+ *
7
+ * `thread/fork` writes a real rollout with its own thread id and a
8
+ * `forked_from_id` back-reference, which is what makes the copy resumable
9
+ * rather than an inert duplicate of the file.
10
+ *
11
+ * One difference from the Claude fork worth knowing about: Codex's unit is a
12
+ * turn, not a row. `upToAnchorId` names the turn a user message belongs to and
13
+ * the cut is inclusive of it, so forking from a message keeps that message
14
+ * *and the answer it got*. Claude's `upToMessageId` can stop at the prompt
15
+ * itself. There is no way to express the finer cut here — a turn is written as
16
+ * one thing — and the coarser one is the more useful of the two anyway.
17
+ */
18
+ export class CodexForkProvider implements IProviderFork {
19
+ async forkSession(input: {
20
+ providerSessionId: string;
21
+ jsonlPath: string;
22
+ projectPath: string;
23
+ upToAnchorId?: string;
24
+ title?: string;
25
+ }): Promise<{ providerSessionId: string; jsonlPath: string }> {
26
+ // `title` is deliberately not forwarded. The sidebar name lives in this
27
+ // app's own session row, and naming the thread inside Codex would mean a
28
+ // second call that could fail after the fork already succeeded.
29
+ const fork = await codexAppServer.forkThread({
30
+ threadId: input.providerSessionId,
31
+ lastTurnId: input.upToAnchorId,
32
+ cwd: input.projectPath,
33
+ });
34
+
35
+ // The path is the one the server reported and already confirmed on disk,
36
+ // not one derived from the source: a fork lands in today's date directory
37
+ // rather than beside the transcript it was copied from.
38
+ return { providerSessionId: fork.threadId, jsonlPath: fork.path };
39
+ }
40
+ }
@@ -18,6 +18,22 @@ import {
18
18
  /** Curated Codex catalog shipped as immutable CloudCLI defaults. */
19
19
  export const CODEX_PREDEFINED_MODELS: ProviderModelsDefinition = {
20
20
  OPTIONS: [
21
+ {
22
+ value: 'gpt-6-astra',
23
+ label: 'GPT-6 Astra',
24
+ description: 'Our most capable model for complex, demanding work.',
25
+ effort: {
26
+ default: 'low',
27
+ values: [
28
+ { value: 'low' },
29
+ { value: 'medium' },
30
+ { value: 'high' },
31
+ { value: 'xhigh' },
32
+ { value: 'max' },
33
+ { value: 'ultra' },
34
+ ],
35
+ },
36
+ },
21
37
  {
22
38
  value: 'gpt-5.6-sol',
23
39
  label: 'GPT-5.6 Sol',
@@ -8,29 +8,44 @@
8
8
  * ## Usage
9
9
  *
10
10
  * - codexRuntime.run(command, options, writer, context) - Execute a streamed prompt
11
- * - abortCodexSession(sessionId) - Cancel an active session
12
- * - isCodexSessionActive(sessionId) - Check if a session is running
13
- * - getActiveCodexSessions() - List all active sessions
11
+ * - codexRuntime.abort(sessionId) - Cancel an active session
14
12
  */
15
13
 
16
14
  import { Codex } from '@openai/codex-sdk';
15
+ import type { ModelReasoningEffort, Thread, ThreadOptions } from '@openai/codex-sdk';
17
16
 
18
17
  import {
19
18
  appendFilesInputTag,
20
19
  buildCodexInputItems,
21
- normalizeImageDescriptors
22
- } from '@/shared/image-attachments.js';
20
+ normalizeImageDescriptors,
21
+ createCompleteMessage,
22
+ createNormalizedMessage,
23
+ } from '@/shared/index.js';
23
24
  import { notifyRunFailed, notifyRunStopped } from '@/modules/notifications/index.js';
24
- import { createCompleteMessage, createNormalizedMessage } from '@/shared/utils.js';
25
+ import type { AnyRecord, ProviderRuntimeContext, ProviderRuntimeWriter } from '@/shared/index.js';
26
+
27
+ type ActiveCodexSession = {
28
+ thread: Thread;
29
+ codex: Codex;
30
+ status: 'running' | 'aborted' | 'completed';
31
+ abortController: AbortController;
32
+ startedAt: string;
33
+ };
34
+
35
+ const activeCodexSessions = new Map<string, ActiveCodexSession>();
25
36
 
26
- const activeCodexSessions = new Map();
37
+ /**
38
+ * Item types whose in-flight updates are worth showing. These are the ones a
39
+ * user waits on — a shell command's output, an MCP call, and the running plan.
40
+ */
41
+ const PROGRESSIVE_CODEX_ITEM_TYPES = new Set(['command_execution', 'mcp_tool_call', 'todo_list']);
27
42
 
28
- function readUsageNumber(value) {
43
+ function readUsageNumber(value: unknown) {
29
44
  const parsed = Number(value);
30
45
  return Number.isFinite(parsed) ? parsed : 0;
31
46
  }
32
47
 
33
- function extractCodexTokenBudget(event) {
48
+ function extractCodexTokenBudget(event: AnyRecord) {
34
49
  const info = event?.info || event?.payload?.info || event?.usage?.info;
35
50
  const usage = info?.total_token_usage || event?.usage?.total_token_usage || event?.usage;
36
51
  if (!usage || typeof usage !== 'object') {
@@ -58,7 +73,7 @@ function extractCodexTokenBudget(event) {
58
73
  * @param {object} event - SDK event
59
74
  * @returns {object} - Transformed event for WebSocket
60
75
  */
61
- function transformCodexEvent(event) {
76
+ function transformCodexEvent(event: AnyRecord): AnyRecord {
62
77
  // Map SDK event types to a consistent format
63
78
  switch (event.type) {
64
79
  case 'item.started':
@@ -69,12 +84,16 @@ function transformCodexEvent(event) {
69
84
  return { type: event.type, item: null };
70
85
  }
71
86
 
72
- // Transform based on item type
87
+ // `itemId` is the SDK's stable per-item id. Carrying it through means an
88
+ // in-progress row and its later completion normalize to the same message
89
+ // id, so the client updates one transcript entry instead of appending a
90
+ // new one for every progress tick.
73
91
  switch (item.type) {
74
92
  case 'agent_message':
75
93
  return {
76
94
  type: 'item',
77
95
  itemType: 'agent_message',
96
+ itemId: item.id,
78
97
  message: {
79
98
  role: 'assistant',
80
99
  content: item.text
@@ -85,6 +104,7 @@ function transformCodexEvent(event) {
85
104
  return {
86
105
  type: 'item',
87
106
  itemType: 'reasoning',
107
+ itemId: item.id,
88
108
  message: {
89
109
  role: 'assistant',
90
110
  content: item.text,
@@ -96,6 +116,7 @@ function transformCodexEvent(event) {
96
116
  return {
97
117
  type: 'item',
98
118
  itemType: 'command_execution',
119
+ itemId: item.id,
99
120
  command: item.command,
100
121
  output: item.aggregated_output,
101
122
  exitCode: item.exit_code,
@@ -106,6 +127,7 @@ function transformCodexEvent(event) {
106
127
  return {
107
128
  type: 'item',
108
129
  itemType: 'file_change',
130
+ itemId: item.id,
109
131
  changes: item.changes,
110
132
  status: item.status
111
133
  };
@@ -114,6 +136,7 @@ function transformCodexEvent(event) {
114
136
  return {
115
137
  type: 'item',
116
138
  itemType: 'mcp_tool_call',
139
+ itemId: item.id,
117
140
  server: item.server,
118
141
  tool: item.tool,
119
142
  arguments: item.arguments,
@@ -126,6 +149,7 @@ function transformCodexEvent(event) {
126
149
  return {
127
150
  type: 'item',
128
151
  itemType: 'web_search',
152
+ itemId: item.id,
129
153
  query: item.query
130
154
  };
131
155
 
@@ -133,6 +157,7 @@ function transformCodexEvent(event) {
133
157
  return {
134
158
  type: 'item',
135
159
  itemType: 'todo_list',
160
+ itemId: item.id,
136
161
  items: item.items
137
162
  };
138
163
 
@@ -140,6 +165,7 @@ function transformCodexEvent(event) {
140
165
  return {
141
166
  type: 'item',
142
167
  itemType: 'error',
168
+ itemId: item.id,
143
169
  message: {
144
170
  role: 'error',
145
171
  content: item.message
@@ -150,6 +176,7 @@ function transformCodexEvent(event) {
150
176
  return {
151
177
  type: 'item',
152
178
  itemType: item.type,
179
+ itemId: item.id,
153
180
  item: item
154
181
  };
155
182
  }
@@ -196,7 +223,7 @@ function transformCodexEvent(event) {
196
223
  * @param {string} permissionMode - 'default', 'acceptEdits', or 'bypassPermissions'
197
224
  * @returns {object} - { sandboxMode, approvalPolicy }
198
225
  */
199
- function mapPermissionModeToCodexOptions(permissionMode) {
226
+ function mapPermissionModeToCodexOptions(permissionMode: string): Pick<ThreadOptions, 'sandboxMode' | 'approvalPolicy'> {
200
227
  switch (permissionMode) {
201
228
  case 'acceptEdits':
202
229
  return {
@@ -212,7 +239,9 @@ function mapPermissionModeToCodexOptions(permissionMode) {
212
239
  default:
213
240
  return {
214
241
  sandboxMode: 'workspace-write',
215
- approvalPolicy: 'untrusted'
242
+ // Current Codex CLI versions reject the retired `untrusted` policy.
243
+ // Keep sandboxing enabled; exec cannot grant interactive approval requests.
244
+ approvalPolicy: 'on-request'
216
245
  };
217
246
  }
218
247
  }
@@ -223,7 +252,12 @@ function mapPermissionModeToCodexOptions(permissionMode) {
223
252
  * @param {object} options - Options including cwd, sessionId, model, permissionMode
224
253
  * @param {WebSocket|object} ws - WebSocket connection or response writer
225
254
  */
226
- export async function queryCodex(command, options = {}, ws, context) {
255
+ async function queryCodex(
256
+ command: string,
257
+ options: AnyRecord = {},
258
+ ws: ProviderRuntimeWriter,
259
+ context: ProviderRuntimeContext,
260
+ ) {
227
261
  const {
228
262
  sessionId,
229
263
  sessionSummary,
@@ -248,16 +282,22 @@ export async function queryCodex(command, options = {}, ws, context) {
248
282
  const selectedModel = catalog.OPTIONS.find((option) => option.value === resolvedModel) || null;
249
283
  const allowedEfforts = selectedModel?.effort?.values?.map((value) => value.value) || [];
250
284
  const resolvedEffort = typeof effort === 'string' && effort !== 'default' && allowedEfforts.includes(effort)
251
- ? effort
285
+ ? effort as ModelReasoningEffort
252
286
  : undefined;
253
287
 
254
- let codex;
255
- let thread;
288
+ let codex: Codex;
289
+ let thread: Thread;
256
290
  // Provider-native thread id (starts as the resume id, or is captured from
257
291
  // the stream for brand-new sessions).
258
292
  let capturedSessionId = providerSessionId;
259
293
  let sessionCreatedSent = false;
260
- let terminalFailure = null;
294
+ let terminalFailure: { message: string } | null = null;
295
+ // Codex surfaces API failures as streamed error items/turn.failed events, and
296
+ // then the SDK also throws "Codex Exec exited with code N: <stderr>" once the
297
+ // process dies. Showing both means the rendered error is followed by a raw
298
+ // stderr dump of unrelated CLI log lines, so the thrown wrapper is dropped
299
+ // when the stream already reported the failure.
300
+ let errorSurfaced = false;
261
301
  const abortController = new AbortController();
262
302
  // Session-map key: the app session id when the caller supplied one, else
263
303
  // the provider-native thread id once captured (legacy/direct API callers).
@@ -266,7 +306,7 @@ export async function queryCodex(command, options = {}, ws, context) {
266
306
  try {
267
307
  codex = new Codex();
268
308
 
269
- const threadOptions = {
309
+ const threadOptions: ThreadOptions = {
270
310
  workingDirectory,
271
311
  skipGitRepoCheck: true,
272
312
  sandboxMode,
@@ -281,7 +321,7 @@ export async function queryCodex(command, options = {}, ws, context) {
281
321
  thread = codex.startThread(threadOptions);
282
322
  }
283
323
 
284
- const registerSession = (id) => {
324
+ const registerSession = (id: string | null) => {
285
325
  if (!id) {
286
326
  return;
287
327
  }
@@ -311,7 +351,7 @@ export async function queryCodex(command, options = {}, ws, context) {
311
351
  for await (const event of streamedTurn.events) {
312
352
  // Capture thread/session id lazily from the stream (Codex emits this asynchronously).
313
353
  if (event.type === 'thread.started') {
314
- const discoveredSessionId = event.thread_id || event.id || null;
354
+ const discoveredSessionId = event.thread_id || null;
315
355
  if (discoveredSessionId && !capturedSessionId) {
316
356
  capturedSessionId = discoveredSessionId;
317
357
  registerSession(sessionKey());
@@ -332,17 +372,29 @@ export async function queryCodex(command, options = {}, ws, context) {
332
372
  break;
333
373
  }
334
374
  if (sessionKey()) {
335
- const session = activeCodexSessions.get(sessionKey());
375
+ const session = activeCodexSessions.get(sessionKey() || '');
336
376
  if (session?.status === 'aborted') {
337
377
  break;
338
378
  }
339
379
  }
340
380
 
341
- if (event.type === 'item.started' || event.type === 'item.updated') {
381
+ // Progress events used to be dropped, so a long shell command or a
382
+ // growing plan showed nothing until it finished. They are forwarded now;
383
+ // every item carries a stable id, so the client replaces the row it
384
+ // already has rather than stacking a new one per tick. Text items are
385
+ // still skipped mid-flight because assistant prose arrives through the
386
+ // separate streaming path.
387
+ if (
388
+ (event.type === 'item.started' || event.type === 'item.updated')
389
+ && !PROGRESSIVE_CODEX_ITEM_TYPES.has(event.item?.type)
390
+ ) {
342
391
  continue;
343
392
  }
344
393
 
345
394
  const transformed = transformCodexEvent(event);
395
+ if (transformed.type === 'error' || transformed.itemType === 'error') {
396
+ errorSurfaced = true;
397
+ }
346
398
 
347
399
  // Normalize the transformed event into NormalizedMessage(s) via adapter
348
400
  const normalizedMsgs = context.normalizeMessage(transformed, capturedSessionId || sessionId || null);
@@ -352,6 +404,7 @@ export async function queryCodex(command, options = {}, ws, context) {
352
404
 
353
405
  if (event.type === 'turn.failed' && !terminalFailure) {
354
406
  terminalFailure = event.error || new Error('Turn failed');
407
+ errorSurfaced = true;
355
408
  // Notifications are app-facing, so they carry the app session id.
356
409
  notifyRunFailed({
357
410
  userId: ws?.userId || null,
@@ -373,7 +426,7 @@ export async function queryCodex(command, options = {}, ws, context) {
373
426
 
374
427
  // Send the terminal completion event — skipped for aborted runs, whose
375
428
  // terminal `complete` (aborted: true) was already sent by abort-session.
376
- const runSession = sessionKey() ? activeCodexSessions.get(sessionKey()) : null;
429
+ const runSession = activeCodexSessions.get(sessionKey() || '');
377
430
  const runAborted = runSession?.status === 'aborted' || abortController.signal.aborted;
378
431
  if (!runAborted) {
379
432
  sendMessage(ws, createCompleteMessage({
@@ -394,22 +447,25 @@ export async function queryCodex(command, options = {}, ws, context) {
394
447
  }
395
448
 
396
449
  } catch (error) {
397
- const session = sessionKey() ? activeCodexSessions.get(sessionKey()) : null;
450
+ const session = activeCodexSessions.get(sessionKey() || '');
451
+ const runError = error instanceof Error ? error : new Error(String(error));
398
452
  const wasAborted =
399
453
  session?.status === 'aborted' ||
400
- error?.name === 'AbortError' ||
401
- String(error?.message || '').toLowerCase().includes('aborted');
454
+ runError.name === 'AbortError' ||
455
+ runError.message.toLowerCase().includes('aborted');
402
456
 
403
457
  if (!wasAborted) {
404
458
  console.error('[Codex] Error:', error);
405
459
 
406
- // Check if Codex SDK is available for a clearer error message
407
- const installed = await context.isProviderInstalled();
408
- const errorContent = !installed
409
- ? 'Codex CLI is not configured. Please set up authentication first.'
410
- : error.message;
460
+ if (!errorSurfaced) {
461
+ // Check if Codex SDK is available for a clearer error message
462
+ const installed = await context.isProviderInstalled();
463
+ const errorContent = !installed
464
+ ? 'Codex CLI is not configured. Please set up authentication first.'
465
+ : runError.message;
411
466
 
412
- sendMessage(ws, createNormalizedMessage({ kind: 'error', content: errorContent, sessionId: capturedSessionId || sessionId || null, provider: 'codex' }));
467
+ sendMessage(ws, createNormalizedMessage({ kind: 'error', content: errorContent, sessionId: capturedSessionId || sessionId || null, provider: 'codex' }));
468
+ }
413
469
  sendMessage(ws, createCompleteMessage({
414
470
  provider: 'codex',
415
471
  sessionId: capturedSessionId || sessionId || null,
@@ -429,7 +485,7 @@ export async function queryCodex(command, options = {}, ws, context) {
429
485
  } finally {
430
486
  // Update session status
431
487
  if (sessionKey()) {
432
- const session = activeCodexSessions.get(sessionKey());
488
+ const session = activeCodexSessions.get(sessionKey() || '');
433
489
  if (session) {
434
490
  session.status = session.status === 'aborted' ? 'aborted' : 'completed';
435
491
  }
@@ -442,7 +498,7 @@ export async function queryCodex(command, options = {}, ws, context) {
442
498
  * @param {string} sessionId - Session ID to abort
443
499
  * @returns {boolean} - Whether abort was successful
444
500
  */
445
- export function abortCodexSession(sessionId) {
501
+ function abortCodexSession(sessionId: string) {
446
502
  const session = activeCodexSessions.get(sessionId);
447
503
 
448
504
  if (!session) {
@@ -459,36 +515,7 @@ export function abortCodexSession(sessionId) {
459
515
  return true;
460
516
  }
461
517
 
462
- /**
463
- * Check if a session is active
464
- * @param {string} sessionId - Session ID to check
465
- * @returns {boolean} - Whether session is active
466
- */
467
- export function isCodexSessionActive(sessionId) {
468
- const session = activeCodexSessions.get(sessionId);
469
- return session?.status === 'running';
470
- }
471
-
472
- /**
473
- * Get all active sessions
474
- * @returns {Array} - Array of active session info
475
- */
476
- export function getActiveCodexSessions() {
477
- const sessions = [];
478
-
479
- for (const [id, session] of activeCodexSessions.entries()) {
480
- if (session.status === 'running') {
481
- sessions.push({
482
- id,
483
- status: session.status,
484
- startedAt: session.startedAt
485
- });
486
- }
487
- }
488
-
489
- return sessions;
490
- }
491
-
518
+ /** Used by the providers module's CodexProvider to run and abort SDK turns. */
492
519
  export const codexRuntime = {
493
520
  run: queryCodex,
494
521
  abort: abortCodexSession,
@@ -499,7 +526,7 @@ export const codexRuntime = {
499
526
  * @param {WebSocket|object} ws - WebSocket or response writer
500
527
  * @param {object} data - Data to send
501
528
  */
502
- function sendMessage(ws, data) {
529
+ function sendMessage(ws: ProviderRuntimeWriter, data: unknown) {
503
530
  try {
504
531
  if (ws.isSSEStreamWriter || ws.isWebSocketWriter) {
505
532
  // Writer handles stringification (SSEStreamWriter or WebSocketWriter)