@cloudcli-ai/cloudcli 1.36.2 → 1.37.0

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 (539) hide show
  1. package/dist/assets/index-DSlds633.css +32 -0
  2. package/dist/assets/{index-CDGzV0LN.js → index-eGqPeIEu.js} +375 -267
  3. package/dist/index.html +2 -2
  4. package/dist-server/server/constants/config.js.map +1 -1
  5. package/dist-server/server/index.js +73 -1224
  6. package/dist-server/server/index.js.map +1 -1
  7. package/dist-server/server/load-env.js +17 -4
  8. package/dist-server/server/load-env.js.map +1 -1
  9. package/dist-server/server/modules/agent/agent.module.js +37 -0
  10. package/dist-server/server/modules/agent/agent.module.js.map +1 -0
  11. package/dist-server/server/modules/agent/agent.routes.js +1161 -0
  12. package/dist-server/server/modules/agent/agent.routes.js.map +1 -0
  13. package/dist-server/server/modules/agent/index.js +3 -0
  14. package/dist-server/server/modules/agent/index.js.map +1 -0
  15. package/dist-server/server/modules/agent/tests/agent.routes.test.js +176 -0
  16. package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -0
  17. package/dist-server/server/modules/assets/assets.routes.js +56 -15
  18. package/dist-server/server/modules/assets/assets.routes.js.map +1 -1
  19. package/dist-server/server/modules/assets/index.js +2 -2
  20. package/dist-server/server/modules/assets/index.js.map +1 -1
  21. package/dist-server/server/modules/assets/services/image-assets.service.js +39 -1
  22. package/dist-server/server/modules/assets/services/image-assets.service.js.map +1 -1
  23. package/dist-server/server/modules/assets/tests/image-assets.service.test.js +21 -1
  24. package/dist-server/server/modules/assets/tests/image-assets.service.test.js.map +1 -1
  25. package/dist-server/server/{middleware/auth.js → modules/auth/auth.middleware.js} +30 -8
  26. package/dist-server/server/modules/auth/auth.middleware.js.map +1 -0
  27. package/dist-server/server/modules/auth/auth.module.js +29 -0
  28. package/dist-server/server/modules/auth/auth.module.js.map +1 -0
  29. package/dist-server/server/modules/auth/auth.routes.js +45 -0
  30. package/dist-server/server/modules/auth/auth.routes.js.map +1 -0
  31. package/dist-server/server/modules/auth/auth.service.js +113 -0
  32. package/dist-server/server/modules/auth/auth.service.js.map +1 -0
  33. package/dist-server/server/modules/auth/index.js +9 -0
  34. package/dist-server/server/modules/auth/index.js.map +1 -0
  35. package/dist-server/server/modules/auth/tests/auth.service.test.js +80 -0
  36. package/dist-server/server/modules/auth/tests/auth.service.test.js.map +1 -0
  37. package/dist-server/server/{browser-use-mcp.js → modules/browser-use/browser-use-mcp.js} +3 -1
  38. package/dist-server/server/modules/browser-use/browser-use-mcp.js.map +1 -0
  39. package/dist-server/server/modules/browser-use/browser-use.service.js +3 -4
  40. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
  41. package/dist-server/server/modules/browser-use/index.js +9 -0
  42. package/dist-server/server/modules/browser-use/index.js.map +1 -0
  43. package/dist-server/server/modules/cli/cli.js +11 -0
  44. package/dist-server/server/modules/cli/cli.js.map +1 -0
  45. package/dist-server/server/modules/cli/cli.module.js +86 -0
  46. package/dist-server/server/modules/cli/cli.module.js.map +1 -0
  47. package/dist-server/server/modules/cli/cli.service.js +244 -0
  48. package/dist-server/server/modules/cli/cli.service.js.map +1 -0
  49. package/dist-server/server/modules/cli/index.js +3 -0
  50. package/dist-server/server/modules/cli/index.js.map +1 -0
  51. package/dist-server/server/modules/cli/sandbox.service.js +332 -0
  52. package/dist-server/server/modules/cli/sandbox.service.js.map +1 -0
  53. package/dist-server/server/modules/cli/tests/cli.service.test.js +78 -0
  54. package/dist-server/server/modules/cli/tests/cli.service.test.js.map +1 -0
  55. package/dist-server/server/modules/cli/tests/sandbox.service.test.js +55 -0
  56. package/dist-server/server/modules/cli/tests/sandbox.service.test.js.map +1 -0
  57. package/dist-server/server/modules/commands/commands.module.js +20 -0
  58. package/dist-server/server/modules/commands/commands.module.js.map +1 -0
  59. package/dist-server/server/modules/commands/commands.routes.js +497 -0
  60. package/dist-server/server/modules/commands/commands.routes.js.map +1 -0
  61. package/dist-server/server/modules/commands/index.js +3 -0
  62. package/dist-server/server/modules/commands/index.js.map +1 -0
  63. package/dist-server/server/modules/commands/tests/commands.test.js +96 -0
  64. package/dist-server/server/modules/commands/tests/commands.test.js.map +1 -0
  65. package/dist-server/server/modules/database/index.js +1 -0
  66. package/dist-server/server/modules/database/index.js.map +1 -1
  67. package/dist-server/server/modules/database/migrations.js +13 -0
  68. package/dist-server/server/modules/database/migrations.js.map +1 -1
  69. package/dist-server/server/modules/database/repositories/sessions.db.js +14 -1
  70. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  71. package/dist-server/server/modules/database/schema.js +4 -0
  72. package/dist-server/server/modules/database/schema.js.map +1 -1
  73. package/dist-server/server/modules/file-tree/file-tree.module.js +91 -0
  74. package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -0
  75. package/dist-server/server/modules/file-tree/file-tree.routes.js +208 -0
  76. package/dist-server/server/modules/file-tree/file-tree.routes.js.map +1 -0
  77. package/dist-server/server/modules/file-tree/file-tree.service.js +544 -0
  78. package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -0
  79. package/dist-server/server/modules/file-tree/index.js +3 -0
  80. package/dist-server/server/modules/file-tree/index.js.map +1 -0
  81. package/dist-server/server/modules/file-tree/tests/file-tree.routes.test.js +123 -0
  82. package/dist-server/server/modules/file-tree/tests/file-tree.routes.test.js.map +1 -0
  83. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +184 -0
  84. package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -0
  85. package/dist-server/server/modules/git/git-parsing.service.js +61 -0
  86. package/dist-server/server/modules/git/git-parsing.service.js.map +1 -0
  87. package/dist-server/server/modules/git/git.module.js +14 -0
  88. package/dist-server/server/modules/git/git.module.js.map +1 -0
  89. package/dist-server/server/modules/git/git.routes.js +1339 -0
  90. package/dist-server/server/modules/git/git.routes.js.map +1 -0
  91. package/dist-server/server/modules/git/index.js +3 -0
  92. package/dist-server/server/modules/git/index.js.map +1 -0
  93. package/dist-server/server/modules/git/tests/git-init.routes.test.js +48 -0
  94. package/dist-server/server/modules/git/tests/git-init.routes.test.js.map +1 -0
  95. package/dist-server/server/{routes → modules/git/tests}/git.test.js +1 -1
  96. package/dist-server/server/modules/git/tests/git.test.js.map +1 -0
  97. package/dist-server/server/modules/notifications/index.js +15 -1
  98. package/dist-server/server/modules/notifications/index.js.map +1 -1
  99. package/dist-server/server/modules/notifications/tests/notification-orchestrator.integration.test.js +44 -0
  100. package/dist-server/server/modules/notifications/tests/notification-orchestrator.integration.test.js.map +1 -0
  101. package/dist-server/server/{services/vapid-keys.js → modules/notifications/vapid-keys.service.js} +3 -2
  102. package/dist-server/server/modules/notifications/vapid-keys.service.js.map +1 -0
  103. package/dist-server/server/modules/plugins/index.js +9 -0
  104. package/dist-server/server/modules/plugins/index.js.map +1 -0
  105. package/dist-server/server/{utils/plugin-process-manager.js → modules/plugins/plugin-process.service.js} +3 -2
  106. package/dist-server/server/modules/plugins/plugin-process.service.js.map +1 -0
  107. package/dist-server/server/{utils/plugin-loader.js → modules/plugins/plugin-registry.service.js} +2 -1
  108. package/dist-server/server/modules/plugins/plugin-registry.service.js.map +1 -0
  109. package/dist-server/server/modules/plugins/plugins.module.js +30 -0
  110. package/dist-server/server/modules/plugins/plugins.module.js.map +1 -0
  111. package/dist-server/server/modules/plugins/plugins.routes.js +70 -0
  112. package/dist-server/server/modules/plugins/plugins.routes.js.map +1 -0
  113. package/dist-server/server/modules/plugins/plugins.service.js +123 -0
  114. package/dist-server/server/modules/plugins/plugins.service.js.map +1 -0
  115. package/dist-server/server/modules/plugins/tests/plugins.service.test.js +28 -0
  116. package/dist-server/server/modules/plugins/tests/plugins.service.test.js.map +1 -0
  117. package/dist-server/server/modules/projects/index.js +5 -0
  118. package/dist-server/server/modules/projects/index.js.map +1 -1
  119. package/dist-server/server/modules/providers/index.js +3 -0
  120. package/dist-server/server/modules/providers/index.js.map +1 -1
  121. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +6 -0
  122. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
  123. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +1 -4
  124. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
  125. package/dist-server/server/{claude-sdk.js → modules/providers/list/claude/claude-runtime.provider.js} +62 -41
  126. package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -0
  127. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +6 -4
  128. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
  129. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +23 -4
  130. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  131. package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
  132. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
  133. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +1 -4
  134. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  135. package/dist-server/server/{openai-codex.js → modules/providers/list/codex/codex-runtime.provider.js} +48 -34
  136. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -0
  137. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +19 -1
  138. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
  139. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +290 -6
  140. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  141. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +5 -0
  142. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -1
  143. package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
  144. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
  145. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +1 -4
  146. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -1
  147. package/dist-server/server/{cursor-cli.js → modules/providers/list/cursor/cursor-runtime.provider.js} +40 -28
  148. package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -0
  149. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +21 -14
  150. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
  151. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +2 -0
  152. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
  153. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +7 -5
  154. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
  155. package/dist-server/server/{opencode-cli.js → modules/providers/list/opencode/opencode-runtime.provider.js} +38 -25
  156. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js.map +1 -0
  157. package/dist-server/server/{opencode-cli.test.js → modules/providers/list/opencode/opencode-runtime.provider.test.js} +27 -4
  158. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js.map +1 -0
  159. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +11 -5
  160. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -1
  161. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js +2 -0
  162. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js.map +1 -1
  163. package/dist-server/server/modules/providers/provider.routes.js +33 -9
  164. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  165. package/dist-server/server/modules/providers/services/provider-capabilities.service.js +5 -1
  166. package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
  167. package/dist-server/server/modules/providers/services/provider-models.service.js +110 -15
  168. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  169. package/dist-server/server/modules/providers/services/provider-runtime.service.js +66 -0
  170. package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -0
  171. package/dist-server/server/modules/providers/services/provider-token-usage.service.js +268 -0
  172. package/dist-server/server/modules/providers/services/provider-token-usage.service.js.map +1 -0
  173. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +2 -0
  174. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  175. package/dist-server/server/modules/providers/services/sessions.service.js +54 -0
  176. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  177. package/dist-server/server/modules/providers/shared/base/abstract.provider.js +2 -3
  178. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
  179. package/dist-server/server/modules/providers/tests/claude-auth.test.js +122 -0
  180. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -0
  181. package/dist-server/server/modules/providers/tests/claude-sessions.test.js +44 -0
  182. package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -0
  183. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +70 -0
  184. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
  185. package/dist-server/server/modules/providers/tests/{provider-image-history.test.js → provider-attachment-history.test.js} +60 -2
  186. package/dist-server/server/modules/providers/tests/provider-attachment-history.test.js.map +1 -0
  187. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +148 -61
  188. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
  189. package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js +130 -0
  190. package/dist-server/server/modules/providers/tests/provider-runtime.service.test.js.map +1 -0
  191. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +165 -0
  192. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js.map +1 -0
  193. package/dist-server/server/modules/providers/tests/sessions-details.test.js +62 -0
  194. package/dist-server/server/modules/providers/tests/sessions-details.test.js.map +1 -0
  195. package/dist-server/server/modules/providers/tests/skills.test.js +4 -2
  196. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  197. package/dist-server/server/modules/settings/index.js +3 -0
  198. package/dist-server/server/modules/settings/index.js.map +1 -0
  199. package/dist-server/server/modules/settings/settings.module.js +35 -0
  200. package/dist-server/server/modules/settings/settings.module.js.map +1 -0
  201. package/dist-server/server/modules/settings/settings.routes.js +34 -0
  202. package/dist-server/server/modules/settings/settings.routes.js.map +1 -0
  203. package/dist-server/server/modules/settings/settings.service.js +116 -0
  204. package/dist-server/server/modules/settings/settings.service.js.map +1 -0
  205. package/dist-server/server/modules/settings/tests/settings.service.test.js +48 -0
  206. package/dist-server/server/modules/settings/tests/settings.service.test.js.map +1 -0
  207. package/dist-server/server/modules/system/index.js +3 -0
  208. package/dist-server/server/modules/system/index.js.map +1 -0
  209. package/dist-server/server/modules/system/system.module.js +44 -0
  210. package/dist-server/server/modules/system/system.module.js.map +1 -0
  211. package/dist-server/server/modules/system/system.routes.js +16 -0
  212. package/dist-server/server/modules/system/system.routes.js.map +1 -0
  213. package/dist-server/server/modules/system/system.service.js +45 -0
  214. package/dist-server/server/modules/system/system.service.js.map +1 -0
  215. package/dist-server/server/modules/system/tests/system.service.test.js +100 -0
  216. package/dist-server/server/modules/system/tests/system.service.test.js.map +1 -0
  217. package/dist-server/server/modules/taskmaster/index.js +3 -0
  218. package/dist-server/server/modules/taskmaster/index.js.map +1 -0
  219. package/dist-server/server/modules/taskmaster/taskmaster.module.js +20 -0
  220. package/dist-server/server/modules/taskmaster/taskmaster.module.js.map +1 -0
  221. package/dist-server/server/modules/taskmaster/taskmaster.routes.js +1372 -0
  222. package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -0
  223. package/dist-server/server/modules/taskmaster/taskmaster.service.js +107 -0
  224. package/dist-server/server/modules/taskmaster/taskmaster.service.js.map +1 -0
  225. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js +132 -0
  226. package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js.map +1 -0
  227. package/dist-server/server/modules/taskmaster/tests/taskmaster.service.test.js +85 -0
  228. package/dist-server/server/modules/taskmaster/tests/taskmaster.service.test.js.map +1 -0
  229. package/dist-server/server/modules/user/index.js +3 -0
  230. package/dist-server/server/modules/user/index.js.map +1 -0
  231. package/dist-server/server/modules/user/tests/user.service.test.js +53 -0
  232. package/dist-server/server/modules/user/tests/user.service.test.js.map +1 -0
  233. package/dist-server/server/modules/user/user.module.js +47 -0
  234. package/dist-server/server/modules/user/user.module.js.map +1 -0
  235. package/dist-server/server/modules/user/user.routes.js +44 -0
  236. package/dist-server/server/modules/user/user.routes.js.map +1 -0
  237. package/dist-server/server/modules/user/user.service.js +59 -0
  238. package/dist-server/server/modules/user/user.service.js.map +1 -0
  239. package/dist-server/server/modules/voice/index.js +3 -0
  240. package/dist-server/server/modules/voice/index.js.map +1 -0
  241. package/dist-server/server/modules/voice/tests/voice.service.test.js +86 -0
  242. package/dist-server/server/modules/voice/tests/voice.service.test.js.map +1 -0
  243. package/dist-server/server/modules/voice/voice.module.js +44 -0
  244. package/dist-server/server/modules/voice/voice.module.js.map +1 -0
  245. package/dist-server/server/modules/voice/voice.routes.js +87 -0
  246. package/dist-server/server/modules/voice/voice.routes.js.map +1 -0
  247. package/dist-server/server/modules/voice/voice.service.js +148 -0
  248. package/dist-server/server/modules/voice/voice.service.js.map +1 -0
  249. package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +2 -2
  250. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +40 -29
  251. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  252. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +76 -8
  253. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  254. package/dist-server/server/modules/websocket/services/websocket-server.service.js +51 -20
  255. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -1
  256. package/dist-server/server/modules/websocket/tests/{chat-image-filter.test.js → chat-attachment-filter.test.js} +10 -3
  257. package/dist-server/server/modules/websocket/tests/chat-attachment-filter.test.js.map +1 -0
  258. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +97 -0
  259. package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -0
  260. package/dist-server/server/modules/websocket/tests/websocket-heartbeat.service.test.js +61 -0
  261. package/dist-server/server/modules/websocket/tests/websocket-heartbeat.service.test.js.map +1 -0
  262. package/dist-server/server/modules/worktrees/index.js +3 -0
  263. package/dist-server/server/modules/worktrees/index.js.map +1 -0
  264. package/dist-server/server/modules/worktrees/services/worktree-create-and-open.service.js +37 -0
  265. package/dist-server/server/modules/worktrees/services/worktree-create-and-open.service.js.map +1 -0
  266. package/dist-server/server/modules/worktrees/services/worktree-create.service.js +67 -0
  267. package/dist-server/server/modules/worktrees/services/worktree-create.service.js.map +1 -0
  268. package/dist-server/server/modules/worktrees/services/worktree-git.service.js +172 -0
  269. package/dist-server/server/modules/worktrees/services/worktree-git.service.js.map +1 -0
  270. package/dist-server/server/modules/worktrees/services/worktree-list.service.js +91 -0
  271. package/dist-server/server/modules/worktrees/services/worktree-list.service.js.map +1 -0
  272. package/dist-server/server/modules/worktrees/services/worktree-merge.service.js +118 -0
  273. package/dist-server/server/modules/worktrees/services/worktree-merge.service.js.map +1 -0
  274. package/dist-server/server/modules/worktrees/services/worktree-open.service.js +58 -0
  275. package/dist-server/server/modules/worktrees/services/worktree-open.service.js.map +1 -0
  276. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js +65 -0
  277. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js.map +1 -0
  278. package/dist-server/server/modules/worktrees/tests/worktree-create-and-open.service.test.js +58 -0
  279. package/dist-server/server/modules/worktrees/tests/worktree-create-and-open.service.test.js.map +1 -0
  280. package/dist-server/server/modules/worktrees/tests/worktree-create.service.test.js +85 -0
  281. package/dist-server/server/modules/worktrees/tests/worktree-create.service.test.js.map +1 -0
  282. package/dist-server/server/modules/worktrees/tests/worktree-git.service.test.js +58 -0
  283. package/dist-server/server/modules/worktrees/tests/worktree-git.service.test.js.map +1 -0
  284. package/dist-server/server/modules/worktrees/tests/worktree-list.service.test.js +34 -0
  285. package/dist-server/server/modules/worktrees/tests/worktree-list.service.test.js.map +1 -0
  286. package/dist-server/server/modules/worktrees/tests/worktree-merge.service.test.js +137 -0
  287. package/dist-server/server/modules/worktrees/tests/worktree-merge.service.test.js.map +1 -0
  288. package/dist-server/server/modules/worktrees/tests/worktree-open.service.test.js +99 -0
  289. package/dist-server/server/modules/worktrees/tests/worktree-open.service.test.js.map +1 -0
  290. package/dist-server/server/modules/worktrees/tests/worktree-remove.service.test.js +157 -0
  291. package/dist-server/server/modules/worktrees/tests/worktree-remove.service.test.js.map +1 -0
  292. package/dist-server/server/modules/worktrees/tests/worktrees.routes.test.js +167 -0
  293. package/dist-server/server/modules/worktrees/tests/worktrees.routes.test.js.map +1 -0
  294. package/dist-server/server/modules/worktrees/worktrees.module.js +97 -0
  295. package/dist-server/server/modules/worktrees/worktrees.module.js.map +1 -0
  296. package/dist-server/server/modules/worktrees/worktrees.routes.js +84 -0
  297. package/dist-server/server/modules/worktrees/worktrees.routes.js.map +1 -0
  298. package/dist-server/server/shared/image-attachments.js +90 -17
  299. package/dist-server/server/shared/image-attachments.js.map +1 -1
  300. package/dist-server/server/shared/tests/image-attachments.test.js +43 -1
  301. package/dist-server/server/shared/tests/image-attachments.test.js.map +1 -1
  302. package/dist-server/server/shared/utils.js +66 -142
  303. package/dist-server/server/shared/utils.js.map +1 -1
  304. package/electron/localServer.js +1 -2
  305. package/package.json +8 -4
  306. package/server/index.ts +401 -0
  307. package/server/{load-env.js → load-env.ts} +18 -5
  308. package/server/modules/agent/agent.module.ts +51 -0
  309. package/server/modules/agent/agent.routes.ts +1287 -0
  310. package/server/modules/agent/index.ts +2 -0
  311. package/server/modules/agent/tests/agent.routes.test.ts +205 -0
  312. package/server/modules/assets/assets.routes.ts +63 -16
  313. package/server/modules/assets/index.ts +2 -2
  314. package/server/modules/assets/services/image-assets.service.ts +46 -1
  315. package/server/modules/assets/tests/image-assets.service.test.ts +28 -0
  316. package/server/{middleware/auth.js → modules/auth/auth.middleware.ts} +38 -7
  317. package/server/modules/auth/auth.module.ts +38 -0
  318. package/server/modules/auth/auth.routes.ts +57 -0
  319. package/server/modules/auth/auth.service.ts +155 -0
  320. package/server/modules/auth/index.ts +9 -0
  321. package/server/modules/auth/tests/auth.service.test.ts +95 -0
  322. package/server/{browser-use-mcp.ts → modules/browser-use/browser-use-mcp.ts} +3 -1
  323. package/server/modules/browser-use/browser-use.service.ts +3 -4
  324. package/server/modules/browser-use/index.ts +8 -0
  325. package/server/modules/cli/cli.module.ts +96 -0
  326. package/server/modules/cli/cli.service.ts +281 -0
  327. package/server/modules/cli/cli.ts +13 -0
  328. package/server/modules/cli/index.ts +2 -0
  329. package/server/modules/cli/sandbox.service.ts +413 -0
  330. package/server/modules/cli/tests/cli.service.test.ts +91 -0
  331. package/server/modules/cli/tests/sandbox.service.test.ts +61 -0
  332. package/server/modules/commands/commands.module.ts +22 -0
  333. package/server/{routes/commands.js → modules/commands/commands.routes.ts} +44 -36
  334. package/server/modules/commands/index.ts +2 -0
  335. package/server/modules/commands/tests/commands.test.ts +119 -0
  336. package/server/modules/database/index.ts +1 -0
  337. package/server/modules/database/migrations.ts +15 -0
  338. package/server/modules/database/repositories/sessions.db.ts +19 -1
  339. package/server/modules/database/schema.ts +4 -0
  340. package/server/modules/file-tree/file-tree.module.ts +112 -0
  341. package/server/modules/file-tree/file-tree.routes.ts +258 -0
  342. package/server/modules/file-tree/file-tree.service.ts +616 -0
  343. package/server/modules/file-tree/index.ts +2 -0
  344. package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -0
  345. package/server/modules/file-tree/tests/file-tree.service.test.ts +220 -0
  346. package/server/modules/git/git-parsing.service.ts +66 -0
  347. package/server/modules/git/git.module.ts +22 -0
  348. package/server/{routes/git.js → modules/git/git.routes.ts} +91 -132
  349. package/server/modules/git/index.ts +2 -0
  350. package/server/modules/git/tests/git-init.routes.test.ts +52 -0
  351. package/server/{routes/git.test.js → modules/git/tests/git.test.ts} +3 -3
  352. package/server/modules/notifications/index.ts +9 -0
  353. package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -0
  354. package/server/{services/vapid-keys.js → modules/notifications/vapid-keys.service.ts} +3 -1
  355. package/server/modules/plugins/index.ts +9 -0
  356. package/server/{utils/plugin-process-manager.js → modules/plugins/plugin-process.service.ts} +3 -1
  357. package/server/{utils/plugin-loader.js → modules/plugins/plugin-registry.service.ts} +1 -0
  358. package/server/modules/plugins/plugins.module.ts +33 -0
  359. package/server/modules/plugins/plugins.routes.ts +66 -0
  360. package/server/modules/plugins/plugins.service.ts +147 -0
  361. package/server/modules/plugins/tests/plugins.service.test.ts +32 -0
  362. package/server/modules/projects/index.ts +5 -0
  363. package/server/modules/providers/README.md +41 -9
  364. package/server/modules/providers/index.ts +4 -0
  365. package/server/modules/providers/list/claude/claude-auth.provider.ts +8 -0
  366. package/server/modules/providers/list/claude/claude-models.provider.ts +1 -12
  367. package/server/{claude-sdk.js → modules/providers/list/claude/claude-runtime.provider.js} +66 -44
  368. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +6 -4
  369. package/server/modules/providers/list/claude/claude-sessions.provider.ts +27 -4
  370. package/server/modules/providers/list/claude/claude.provider.ts +3 -0
  371. package/server/modules/providers/list/codex/codex-models.provider.ts +0 -9
  372. package/server/{openai-codex.js → modules/providers/list/codex/codex-runtime.provider.js} +54 -36
  373. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +21 -1
  374. package/server/modules/providers/list/codex/codex-sessions.provider.ts +331 -7
  375. package/server/modules/providers/list/codex/codex-skills.provider.ts +5 -0
  376. package/server/modules/providers/list/codex/codex.provider.ts +3 -0
  377. package/server/modules/providers/list/cursor/cursor-models.provider.ts +0 -9
  378. package/server/{cursor-cli.js → modules/providers/list/cursor/cursor-runtime.provider.js} +58 -27
  379. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +26 -15
  380. package/server/modules/providers/list/cursor/cursor.provider.ts +3 -0
  381. package/server/modules/providers/list/opencode/opencode-models.provider.ts +7 -10
  382. package/server/{opencode-cli.js → modules/providers/list/opencode/opencode-runtime.provider.js} +56 -28
  383. package/server/{opencode-cli.test.js → modules/providers/list/opencode/opencode-runtime.provider.test.js} +41 -3
  384. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +13 -5
  385. package/server/modules/providers/list/opencode/opencode.provider.ts +3 -0
  386. package/server/modules/providers/provider.routes.ts +47 -10
  387. package/server/modules/providers/services/provider-capabilities.service.ts +7 -1
  388. package/server/modules/providers/services/provider-models.service.ts +131 -23
  389. package/server/modules/providers/services/provider-runtime.service.ts +109 -0
  390. package/server/modules/providers/services/provider-token-usage.service.ts +357 -0
  391. package/server/modules/providers/services/sessions-watcher.service.ts +2 -0
  392. package/server/modules/providers/services/sessions.service.ts +79 -0
  393. package/server/modules/providers/shared/base/abstract.provider.ts +4 -3
  394. package/server/modules/providers/tests/claude-auth.test.ts +150 -0
  395. package/server/modules/providers/tests/claude-sessions.test.ts +61 -0
  396. package/server/modules/providers/tests/codex-sessions.test.ts +81 -0
  397. package/server/modules/providers/tests/{provider-image-history.test.ts → provider-attachment-history.test.ts} +68 -1
  398. package/server/modules/providers/tests/provider-models.service.test.ts +450 -349
  399. package/server/modules/providers/tests/provider-runtime.service.test.ts +142 -0
  400. package/server/modules/providers/tests/provider-token-usage.service.test.ts +185 -0
  401. package/server/modules/providers/tests/sessions-details.test.ts +73 -0
  402. package/server/modules/providers/tests/skills.test.ts +9 -2
  403. package/server/modules/settings/index.ts +2 -0
  404. package/server/modules/settings/settings.module.ts +50 -0
  405. package/server/modules/settings/settings.routes.ts +51 -0
  406. package/server/modules/settings/settings.service.ts +186 -0
  407. package/server/modules/settings/tests/settings.service.test.ts +54 -0
  408. package/server/modules/system/index.ts +2 -0
  409. package/server/modules/system/system.module.ts +62 -0
  410. package/server/modules/system/system.routes.ts +21 -0
  411. package/server/modules/system/system.service.ts +76 -0
  412. package/server/modules/system/tests/system.service.test.ts +118 -0
  413. package/server/modules/taskmaster/index.ts +2 -0
  414. package/server/modules/taskmaster/taskmaster.module.ts +24 -0
  415. package/server/modules/taskmaster/taskmaster.routes.ts +1482 -0
  416. package/server/modules/taskmaster/taskmaster.service.ts +132 -0
  417. package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +144 -0
  418. package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -0
  419. package/server/modules/user/index.ts +2 -0
  420. package/server/modules/user/tests/user.service.test.ts +61 -0
  421. package/server/modules/user/user.module.ts +58 -0
  422. package/server/modules/user/user.routes.ts +50 -0
  423. package/server/modules/user/user.service.ts +85 -0
  424. package/server/modules/voice/index.ts +2 -0
  425. package/server/modules/voice/tests/voice.service.test.ts +98 -0
  426. package/server/modules/voice/voice.module.ts +47 -0
  427. package/server/modules/voice/voice.routes.ts +113 -0
  428. package/server/modules/voice/voice.service.ts +192 -0
  429. package/server/modules/websocket/README.md +7 -7
  430. package/server/modules/websocket/services/chat-session-writer.service.ts +2 -2
  431. package/server/modules/websocket/services/chat-websocket.service.ts +73 -61
  432. package/server/modules/websocket/services/shell-websocket.service.ts +88 -12
  433. package/server/modules/websocket/services/websocket-server.service.ts +63 -19
  434. package/server/modules/websocket/tests/{chat-image-filter.test.ts → chat-attachment-filter.test.ts} +17 -2
  435. package/server/modules/websocket/tests/shell-websocket.service.test.ts +119 -0
  436. package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -0
  437. package/server/modules/worktrees/index.ts +2 -0
  438. package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -0
  439. package/server/modules/worktrees/services/worktree-create.service.ts +104 -0
  440. package/server/modules/worktrees/services/worktree-git.service.ts +207 -0
  441. package/server/modules/worktrees/services/worktree-list.service.ts +143 -0
  442. package/server/modules/worktrees/services/worktree-merge.service.ts +157 -0
  443. package/server/modules/worktrees/services/worktree-open.service.ts +85 -0
  444. package/server/modules/worktrees/services/worktree-remove.service.ts +88 -0
  445. package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -0
  446. package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -0
  447. package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -0
  448. package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -0
  449. package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -0
  450. package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -0
  451. package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -0
  452. package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -0
  453. package/server/modules/worktrees/worktrees.module.ts +113 -0
  454. package/server/modules/worktrees/worktrees.routes.ts +116 -0
  455. package/server/shared/image-attachments.ts +112 -18
  456. package/server/shared/interfaces.ts +29 -19
  457. package/server/shared/tests/image-attachments.test.ts +55 -0
  458. package/server/shared/types.ts +658 -21
  459. package/server/shared/utils.ts +77 -212
  460. package/dist/assets/index-DLmhQ15L.css +0 -32
  461. package/dist-server/server/browser-use-mcp.js.map +0 -1
  462. package/dist-server/server/claude-sdk.js.map +0 -1
  463. package/dist-server/server/cli.js +0 -647
  464. package/dist-server/server/cli.js.map +0 -1
  465. package/dist-server/server/cursor-cli.js.map +0 -1
  466. package/dist-server/server/middleware/auth.js.map +0 -1
  467. package/dist-server/server/modules/providers/tests/provider-image-history.test.js.map +0 -1
  468. package/dist-server/server/modules/websocket/tests/chat-image-filter.test.js.map +0 -1
  469. package/dist-server/server/openai-codex.js.map +0 -1
  470. package/dist-server/server/opencode-cli.js.map +0 -1
  471. package/dist-server/server/opencode-cli.test.js.map +0 -1
  472. package/dist-server/server/routes/agent.js +0 -1155
  473. package/dist-server/server/routes/agent.js.map +0 -1
  474. package/dist-server/server/routes/auth.js +0 -119
  475. package/dist-server/server/routes/auth.js.map +0 -1
  476. package/dist-server/server/routes/commands.js +0 -492
  477. package/dist-server/server/routes/commands.js.map +0 -1
  478. package/dist-server/server/routes/cursor.js +0 -49
  479. package/dist-server/server/routes/cursor.js.map +0 -1
  480. package/dist-server/server/routes/git.js +0 -1389
  481. package/dist-server/server/routes/git.js.map +0 -1
  482. package/dist-server/server/routes/git.test.js.map +0 -1
  483. package/dist-server/server/routes/mcp-utils.js +0 -29
  484. package/dist-server/server/routes/mcp-utils.js.map +0 -1
  485. package/dist-server/server/routes/plugins.js +0 -266
  486. package/dist-server/server/routes/plugins.js.map +0 -1
  487. package/dist-server/server/routes/settings.js +0 -249
  488. package/dist-server/server/routes/settings.js.map +0 -1
  489. package/dist-server/server/routes/taskmaster.js +0 -1362
  490. package/dist-server/server/routes/taskmaster.js.map +0 -1
  491. package/dist-server/server/routes/tests/commands.test.js +0 -76
  492. package/dist-server/server/routes/tests/commands.test.js.map +0 -1
  493. package/dist-server/server/routes/user.js +0 -116
  494. package/dist-server/server/routes/user.js.map +0 -1
  495. package/dist-server/server/services/notification-orchestrator.js +0 -2
  496. package/dist-server/server/services/notification-orchestrator.js.map +0 -1
  497. package/dist-server/server/services/tests/notification-orchestrator.test.js +0 -64
  498. package/dist-server/server/services/tests/notification-orchestrator.test.js.map +0 -1
  499. package/dist-server/server/services/vapid-keys.js.map +0 -1
  500. package/dist-server/server/utils/colors.js +0 -20
  501. package/dist-server/server/utils/colors.js.map +0 -1
  502. package/dist-server/server/utils/commandParser.js +0 -255
  503. package/dist-server/server/utils/commandParser.js.map +0 -1
  504. package/dist-server/server/utils/gitConfig.js +0 -37
  505. package/dist-server/server/utils/gitConfig.js.map +0 -1
  506. package/dist-server/server/utils/mcp-detector.js +0 -134
  507. package/dist-server/server/utils/mcp-detector.js.map +0 -1
  508. package/dist-server/server/utils/plugin-loader.js.map +0 -1
  509. package/dist-server/server/utils/plugin-process-manager.js.map +0 -1
  510. package/dist-server/server/utils/runtime-paths.js +0 -30
  511. package/dist-server/server/utils/runtime-paths.js.map +0 -1
  512. package/dist-server/server/utils/taskmaster-websocket.js +0 -124
  513. package/dist-server/server/utils/taskmaster-websocket.js.map +0 -1
  514. package/dist-server/server/utils/url-detection.js +0 -58
  515. package/dist-server/server/utils/url-detection.js.map +0 -1
  516. package/dist-server/server/voice-proxy.js +0 -226
  517. package/dist-server/server/voice-proxy.js.map +0 -1
  518. package/server/cli.js +0 -695
  519. package/server/index.js +0 -1651
  520. package/server/routes/agent.js +0 -1257
  521. package/server/routes/auth.js +0 -137
  522. package/server/routes/cursor.js +0 -52
  523. package/server/routes/mcp-utils.js +0 -31
  524. package/server/routes/plugins.js +0 -307
  525. package/server/routes/settings.js +0 -282
  526. package/server/routes/taskmaster.js +0 -1470
  527. package/server/routes/tests/commands.test.js +0 -82
  528. package/server/routes/user.js +0 -124
  529. package/server/services/notification-orchestrator.js +0 -7
  530. package/server/services/tests/notification-orchestrator.test.js +0 -80
  531. package/server/utils/colors.js +0 -21
  532. package/server/utils/commandParser.js +0 -305
  533. package/server/utils/gitConfig.js +0 -35
  534. package/server/utils/mcp-detector.js +0 -147
  535. package/server/utils/runtime-paths.js +0 -37
  536. package/server/utils/taskmaster-websocket.js +0 -135
  537. package/server/utils/url-detection.js +0 -71
  538. package/server/voice-proxy.js +0 -224
  539. /package/server/constants/{config.js → config.ts} +0 -0
@@ -32,6 +32,25 @@ type ArchivedSessionListItem = {
32
32
  isProjectArchived: boolean;
33
33
  };
34
34
 
35
+ type SessionDetails = {
36
+ /** Canonical app-facing session id (may differ from the looked-up id when a provider-native id was given). */
37
+ sessionId: string;
38
+ provider: LLMProvider;
39
+ summary: string;
40
+ createdAt: string | null;
41
+ updatedAt: string | null;
42
+ lastActivity: string | null;
43
+ isArchived: boolean;
44
+ project: {
45
+ projectId: string;
46
+ path: string;
47
+ fullPath: string;
48
+ displayName: string;
49
+ isStarred: boolean;
50
+ isArchived: boolean;
51
+ } | null;
52
+ };
53
+
35
54
  /**
36
55
  * Removes one file if it exists.
37
56
  */
@@ -100,6 +119,23 @@ export const sessionsService = {
100
119
  return chatRunRegistry.listRunningRuns();
101
120
  },
102
121
 
122
+ /**
123
+ * Resolves the provider-native session id a runtime needs for resume.
124
+ *
125
+ * Callers hand provider runtimes the stable app session id; the provider
126
+ * CLIs/SDKs only understand their own native id, which lives on the session
127
+ * row. Ids without a row are assumed to be provider-native already (direct
128
+ * API callers that reference sessions the watcher has not indexed yet).
129
+ */
130
+ resolveProviderSessionId(sessionId: string | null | undefined): string | null {
131
+ if (!sessionId) {
132
+ return null;
133
+ }
134
+
135
+ const session = sessionsDb.getSessionById(sessionId);
136
+ return session ? session.provider_session_id : sessionId;
137
+ },
138
+
103
139
  /**
104
140
  * Normalizes one provider-native event into frontend session message events.
105
141
  */
@@ -189,6 +225,49 @@ export const sessionsService = {
189
225
  };
190
226
  },
191
227
 
228
+ /**
229
+ * Resolves one session (by app id, falling back to the provider-native id)
230
+ * to its metadata plus the owning project.
231
+ *
232
+ * This backs deep links like `/session/:sessionId`: the frontend's paginated
233
+ * project payloads only carry each project's first session page, so a
234
+ * session opened directly by URL may not be present client-side at all —
235
+ * this lookup is the authoritative way to learn which project owns it.
236
+ */
237
+ getSessionDetailsById(sessionId: string): SessionDetails {
238
+ const session =
239
+ sessionsDb.getSessionById(sessionId) ?? sessionsDb.getSessionByProviderSessionId(sessionId);
240
+ if (!session) {
241
+ throw new AppError(`Session "${sessionId}" was not found.`, {
242
+ code: 'SESSION_NOT_FOUND',
243
+ statusCode: 404,
244
+ });
245
+ }
246
+
247
+ const projectPath = session.project_path?.trim() ? session.project_path : null;
248
+ const project = projectPath ? projectsDb.getProjectPath(projectPath) : null;
249
+
250
+ return {
251
+ sessionId: session.session_id,
252
+ provider: session.provider as LLMProvider,
253
+ summary: session.custom_name?.trim() || '',
254
+ createdAt: session.created_at ?? null,
255
+ updatedAt: session.updated_at ?? null,
256
+ lastActivity: session.updated_at ?? session.created_at ?? null,
257
+ isArchived: Boolean(session.isArchived),
258
+ project: project && projectPath
259
+ ? {
260
+ projectId: project.project_id,
261
+ path: projectPath,
262
+ fullPath: projectPath,
263
+ displayName: resolveProjectDisplayName(projectPath, project.custom_project_name),
264
+ isStarred: Boolean(project.isStarred),
265
+ isArchived: Boolean(project.isArchived),
266
+ }
267
+ : null,
268
+ };
269
+ },
270
+
192
271
  /**
193
272
  * Returns archived sessions with enough project metadata for the sidebar to
194
273
  * group, filter, open, and restore them without a per-row follow-up query.
@@ -3,6 +3,7 @@ import type {
3
3
  IProviderAuth,
4
4
  IProviderMcp,
5
5
  IProviderModels,
6
+ IProviderRuntime,
6
7
  IProviderSessionSynchronizer,
7
8
  IProviderSkills,
8
9
  IProviderSessions,
@@ -12,12 +13,12 @@ import type { LLMProvider } from '@/shared/types.js';
12
13
  /**
13
14
  * Shared provider base.
14
15
  *
15
- * Concrete providers must expose auth/MCP handlers and implement message
16
- * normalization/history loading because those behaviors depend on native
17
- * SDK/CLI formats.
16
+ * Concrete providers expose their live runtime plus model, auth, MCP, skill,
17
+ * session, and synchronization facets behind one registry-owned object.
18
18
  */
19
19
  export abstract class AbstractProvider implements IProvider {
20
20
  readonly id: LLMProvider;
21
+ abstract readonly runtime: IProviderRuntime;
21
22
  abstract readonly models: IProviderModels;
22
23
  abstract readonly mcp: IProviderMcp;
23
24
  abstract readonly auth: IProviderAuth;
@@ -0,0 +1,150 @@
1
+ import assert from 'node:assert/strict';
2
+ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import test from 'node:test';
6
+
7
+ import { ClaudeProviderAuth } from '@/modules/providers/list/claude/claude-auth.provider.js';
8
+
9
+ // checkCredentials() is private, but unlike getStatus() it never shells out to the
10
+ // `claude` CLI — it only reads env vars and ~/.claude files. Calling it directly
11
+ // (TypeScript's `private` has no runtime effect) tests the priority order without
12
+ // depending on `claude` being installed in the test environment.
13
+ type CheckCredentialsResult = {
14
+ authenticated: boolean;
15
+ email: string | null;
16
+ method: string | null;
17
+ error?: string;
18
+ };
19
+
20
+ const checkCredentials = (auth: ClaudeProviderAuth): Promise<CheckCredentialsResult> =>
21
+ (auth as unknown as { checkCredentials: () => Promise<CheckCredentialsResult> }).checkCredentials();
22
+
23
+ const ENV_KEYS = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN'] as const;
24
+
25
+ const withEnv = async (
26
+ overrides: Partial<Record<(typeof ENV_KEYS)[number], string>>,
27
+ fn: () => Promise<void>,
28
+ ) => {
29
+ const original: Partial<Record<(typeof ENV_KEYS)[number], string>> = {};
30
+ for (const key of ENV_KEYS) {
31
+ original[key] = process.env[key];
32
+ const value = overrides[key];
33
+ if (value === undefined) {
34
+ delete process.env[key];
35
+ } else {
36
+ process.env[key] = value;
37
+ }
38
+ }
39
+ try {
40
+ await fn();
41
+ } finally {
42
+ for (const key of ENV_KEYS) {
43
+ if (original[key] === undefined) {
44
+ delete process.env[key];
45
+ } else {
46
+ process.env[key] = original[key];
47
+ }
48
+ }
49
+ }
50
+ };
51
+
52
+ const withTempHome = async (fn: (homeDir: string) => Promise<void>) => {
53
+ const homeDir = await mkdtemp(path.join(os.tmpdir(), 'claude-auth-test-'));
54
+ const originalHome = process.env.HOME;
55
+ process.env.HOME = homeDir;
56
+ try {
57
+ await fn(homeDir);
58
+ } finally {
59
+ if (originalHome === undefined) {
60
+ delete process.env.HOME;
61
+ } else {
62
+ process.env.HOME = originalHome;
63
+ }
64
+ await rm(homeDir, { recursive: true, force: true });
65
+ }
66
+ };
67
+
68
+ const writeCredentialsFile = async (homeDir: string, body: unknown) => {
69
+ const claudeDir = path.join(homeDir, '.claude');
70
+ await mkdir(claudeDir, { recursive: true });
71
+ await writeFile(path.join(claudeDir, '.credentials.json'), JSON.stringify(body));
72
+ };
73
+
74
+ const writeSettingsFile = async (homeDir: string, env: Record<string, string>) => {
75
+ const claudeDir = path.join(homeDir, '.claude');
76
+ await mkdir(claudeDir, { recursive: true });
77
+ await writeFile(path.join(claudeDir, 'settings.json'), JSON.stringify({ env }));
78
+ };
79
+
80
+ test('checkCredentials: CLAUDE_CODE_OAUTH_TOKEN set is authenticated via environment, even with a stale credentials file', async () => {
81
+ await withTempHome(async (homeDir) => {
82
+ await writeCredentialsFile(homeDir, {
83
+ claudeAiOauth: { accessToken: 'stale-token', expiresAt: 1_000_000_000_000 }, // long expired
84
+ });
85
+
86
+ await withEnv({ CLAUDE_CODE_OAUTH_TOKEN: 'test-oauth-token' }, async () => {
87
+ const status = await checkCredentials(new ClaudeProviderAuth());
88
+ assert.equal(status.authenticated, true);
89
+ assert.equal(status.method, 'environment');
90
+ });
91
+ });
92
+ });
93
+
94
+ test('checkCredentials: CLAUDE_CODE_OAUTH_TOKEN configured via settings.json env block is authenticated via environment', async () => {
95
+ await withTempHome(async (homeDir) => {
96
+ await writeSettingsFile(homeDir, { CLAUDE_CODE_OAUTH_TOKEN: 'test-oauth-token-from-settings' });
97
+ await writeCredentialsFile(homeDir, {
98
+ claudeAiOauth: { accessToken: 'stale-token', expiresAt: 1_000_000_000_000 }, // long expired
99
+ });
100
+
101
+ await withEnv({}, async () => {
102
+ const status = await checkCredentials(new ClaudeProviderAuth());
103
+ assert.equal(status.authenticated, true);
104
+ assert.equal(status.method, 'environment');
105
+ });
106
+ });
107
+ });
108
+
109
+ test('checkCredentials: no CLAUDE_CODE_OAUTH_TOKEN, valid credentials file falls back to credentials_file', async () => {
110
+ await withTempHome(async (homeDir) => {
111
+ await writeCredentialsFile(homeDir, {
112
+ claudeAiOauth: { accessToken: 'valid-token', expiresAt: Date.now() + 60 * 60 * 1000 },
113
+ email: 'someone@example.com',
114
+ });
115
+
116
+ await withEnv({}, async () => {
117
+ const status = await checkCredentials(new ClaudeProviderAuth());
118
+ assert.equal(status.authenticated, true);
119
+ assert.equal(status.method, 'credentials_file');
120
+ assert.equal(status.email, 'someone@example.com');
121
+ });
122
+ });
123
+ });
124
+
125
+ test('checkCredentials: no CLAUDE_CODE_OAUTH_TOKEN, expired credentials file reports not authenticated', async () => {
126
+ await withTempHome(async (homeDir) => {
127
+ await writeCredentialsFile(homeDir, {
128
+ claudeAiOauth: { accessToken: 'stale-token', expiresAt: 1_000_000_000_000 },
129
+ });
130
+
131
+ await withEnv({}, async () => {
132
+ const status = await checkCredentials(new ClaudeProviderAuth());
133
+ assert.equal(status.authenticated, false);
134
+ assert.match(status.error ?? '', /expired/i);
135
+ });
136
+ });
137
+ });
138
+
139
+ test('checkCredentials: ANTHROPIC_API_KEY takes precedence over CLAUDE_CODE_OAUTH_TOKEN', async () => {
140
+ await withTempHome(async () => {
141
+ await withEnv(
142
+ { ANTHROPIC_API_KEY: 'test-api-key', CLAUDE_CODE_OAUTH_TOKEN: 'test-oauth-token' },
143
+ async () => {
144
+ const status = await checkCredentials(new ClaudeProviderAuth());
145
+ assert.equal(status.authenticated, true);
146
+ assert.equal(status.method, 'api_key');
147
+ },
148
+ );
149
+ });
150
+ });
@@ -0,0 +1,61 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+
4
+ import { ClaudeSessionsProvider } from '@/modules/providers/list/claude/claude-sessions.provider.js';
5
+
6
+ const SESSION_ID = 'session-1';
7
+
8
+ const SKILL_BODY = [
9
+ 'Base directory for this skill: /tmp/claude/bundled-skills/2.1.220/abc123/claude-api',
10
+ '',
11
+ '# Building LLM-Powered Applications with Claude',
12
+ '',
13
+ 'This skill helps you build LLM-powered applications with Claude.',
14
+ ].join('\n');
15
+
16
+ test('claude: injected skill bodies are hidden even without the isMeta flag', () => {
17
+ const provider = new ClaudeSessionsProvider();
18
+
19
+ // The live SDK stream omits `isMeta`, so the payload has to be recognised by
20
+ // its content or it renders as a giant user bubble mid-run.
21
+ const live = provider.normalizeMessage(
22
+ {
23
+ uuid: 'u1',
24
+ timestamp: '2026-07-28T10:00:00.000Z',
25
+ message: { role: 'user', content: [{ type: 'text', text: SKILL_BODY }] },
26
+ },
27
+ SESSION_ID,
28
+ );
29
+ assert.deepEqual(live, []);
30
+
31
+ const persisted = provider.normalizeMessage(
32
+ {
33
+ uuid: 'u2',
34
+ timestamp: '2026-07-28T10:00:00.000Z',
35
+ isMeta: true,
36
+ message: { role: 'user', content: [{ type: 'text', text: SKILL_BODY }] },
37
+ },
38
+ SESSION_ID,
39
+ );
40
+ assert.deepEqual(persisted, []);
41
+ });
42
+
43
+ test('claude: the Skill tool result itself still reaches the UI', () => {
44
+ const provider = new ClaudeSessionsProvider();
45
+
46
+ const messages = provider.normalizeMessage(
47
+ {
48
+ uuid: 'u3',
49
+ timestamp: '2026-07-28T10:00:00.000Z',
50
+ message: {
51
+ role: 'user',
52
+ content: [{ type: 'tool_result', tool_use_id: 'toolu_1', content: 'Launching skill: claude-api' }],
53
+ },
54
+ },
55
+ SESSION_ID,
56
+ );
57
+
58
+ assert.equal(messages.length, 1);
59
+ assert.equal(messages[0].kind, 'tool_result');
60
+ assert.equal(messages[0].toolId, 'toolu_1');
61
+ });
@@ -6,6 +6,7 @@ import test from 'node:test';
6
6
 
7
7
  import { closeConnection, initializeDatabase, sessionsDb } from '@/modules/database/index.js';
8
8
  import { CodexSessionSynchronizer } from '@/modules/providers/list/codex/codex-session-synchronizer.provider.js';
9
+ import { CodexSessionsProvider } from '@/modules/providers/list/codex/codex-sessions.provider.js';
9
10
 
10
11
  const patchHomeDir = (nextHomeDir: string) => {
11
12
  const original = os.homedir;
@@ -88,6 +89,47 @@ test('Codex synchronizer titles app-created sessions from the first user message
88
89
  }
89
90
  });
90
91
 
92
+ test('Codex synchronizer skips sub-agent rollout files', { concurrency: false }, async () => {
93
+ const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-subagent-'));
94
+ const workspacePath = path.join(tempRoot, 'workspace');
95
+ await mkdir(workspacePath, { recursive: true });
96
+ const restoreHomeDir = patchHomeDir(tempRoot);
97
+
98
+ try {
99
+ // Codex >=0.144 spawn_agent threads write their own rollout files into the
100
+ // same sessions tree, marked via thread_source/source in session_meta.
101
+ const sessionsDir = path.join(tempRoot, '.codex', 'sessions', '2026', '07', '07');
102
+ await mkdir(sessionsDir, { recursive: true });
103
+ await writeFile(
104
+ path.join(sessionsDir, 'rollout-codex-subagent-1.jsonl'),
105
+ `${JSON.stringify({
106
+ type: 'session_meta',
107
+ payload: {
108
+ id: 'codex-subagent-1',
109
+ cwd: workspacePath,
110
+ thread_source: 'subagent',
111
+ parent_thread_id: 'codex-parent-1',
112
+ source: { subagent: { thread_spawn: { parent_thread_id: 'codex-parent-1', depth: 1 } } },
113
+ },
114
+ })}\n`,
115
+ 'utf8'
116
+ );
117
+ await writeCodexTranscript(tempRoot, 'codex-parent-1', workspacePath);
118
+
119
+ await withIsolatedDatabase(async () => {
120
+ const synchronizer = new CodexSessionSynchronizer();
121
+ const processed = await synchronizer.synchronize();
122
+
123
+ assert.equal(processed, 1);
124
+ assert.ok(sessionsDb.getSessionById('codex-parent-1'));
125
+ assert.equal(sessionsDb.getSessionById('codex-subagent-1'), null);
126
+ });
127
+ } finally {
128
+ restoreHomeDir();
129
+ await rm(tempRoot, { recursive: true, force: true });
130
+ }
131
+ });
132
+
91
133
  test('Codex synchronizer leaves indexed sessions untitled when no name is available', { concurrency: false }, async () => {
92
134
  const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-indexed-'));
93
135
  const workspacePath = path.join(tempRoot, 'workspace');
@@ -109,3 +151,42 @@ test('Codex synchronizer leaves indexed sessions untitled when no name is availa
109
151
  await rm(tempRoot, { recursive: true, force: true });
110
152
  }
111
153
  });
154
+
155
+ test('Codex history renders Promise.all shell wrappers as Bash activity', { concurrency: false }, async () => {
156
+ const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-exec-history-'));
157
+ const workspacePath = path.join(tempRoot, 'workspace');
158
+ await mkdir(workspacePath, { recursive: true });
159
+ const restoreHomeDir = patchHomeDir(tempRoot);
160
+
161
+ try {
162
+ const providerSessionId = 'codex-exec-1';
163
+ const transcriptPath = await writeCodexTranscript(tempRoot, providerSessionId, workspacePath);
164
+ const execInput = 'const cmds = ["echo one", "echo two"]; await Promise.all(cmds.map(command => tools.shell_command({ command })));';
165
+ const planInput = 'await tools.update_plan({ plan: [] });';
166
+ await writeFile(transcriptPath, [
167
+ JSON.stringify({ type: 'session_meta', payload: { id: providerSessionId, cwd: workspacePath } }),
168
+ JSON.stringify({ type: 'response_item', payload: { type: 'custom_tool_call', name: 'exec', call_id: 'exec-1', input: execInput } }),
169
+ JSON.stringify({ type: 'response_item', payload: { type: 'custom_tool_call_output', call_id: 'exec-1', output: 'done' } }),
170
+ JSON.stringify({ type: 'response_item', payload: { type: 'custom_tool_call', name: 'exec', call_id: 'plan-1', input: planInput } }),
171
+ JSON.stringify({ type: 'response_item', payload: { type: 'custom_tool_call_output', call_id: 'plan-1', output: 'done' } }),
172
+ ].join('\n') + '\n', 'utf8');
173
+
174
+ await withIsolatedDatabase(async () => {
175
+ sessionsDb.createAppSession('app-exec-1', 'codex', workspacePath);
176
+ sessionsDb.assignProviderSessionId('app-exec-1', providerSessionId);
177
+ await new CodexSessionSynchronizer().synchronize();
178
+
179
+ const history = await new CodexSessionsProvider().fetchHistory('app-exec-1');
180
+ const toolUses = history.messages.filter((message) => message.kind === 'tool_use');
181
+ const toolResults = history.messages.filter((message) => message.kind === 'tool_result');
182
+
183
+ assert.equal(toolUses.length, 1);
184
+ assert.equal(toolUses[0].toolName, 'Bash');
185
+ assert.equal(toolUses[0].toolInput, JSON.stringify({ command: 'echo one\necho two' }));
186
+ assert.equal(toolResults.some((message) => message.toolCallId === 'plan-1'), false);
187
+ });
188
+ } finally {
189
+ restoreHomeDir();
190
+ await rm(tempRoot, { recursive: true, force: true });
191
+ }
192
+ });
@@ -4,7 +4,7 @@ import test from 'node:test';
4
4
  import { ClaudeSessionsProvider } from '@/modules/providers/list/claude/claude-sessions.provider.js';
5
5
  import { CodexSessionsProvider, extractCodexUserImages } from '@/modules/providers/list/codex/codex-sessions.provider.js';
6
6
  import { CursorSessionsProvider } from '@/modules/providers/list/cursor/cursor-sessions.provider.js';
7
- import { appendImagesInputTag } from '@/shared/image-attachments.js';
7
+ import { appendFilesInputTag, appendImagesInputTag } from '@/shared/image-attachments.js';
8
8
 
9
9
  const SESSION_ID = 'session-1';
10
10
 
@@ -71,6 +71,29 @@ test('claude history: plain text user turns carry no images field', () => {
71
71
  assert.equal(messages[0].images, undefined);
72
72
  });
73
73
 
74
+ test('claude history: file reference blocks restore non-image attachments', () => {
75
+ const provider = new ClaudeSessionsProvider();
76
+ const entry = {
77
+ uuid: 'u4',
78
+ timestamp: '2026-07-03T10:00:00.000Z',
79
+ message: {
80
+ role: 'user',
81
+ content: [{
82
+ type: 'text',
83
+ text: appendFilesInputTag('Summarize this', [
84
+ { path: 'C:/Users/x/.cloudcli/assets/brief.pdf', name: 'brief.pdf' },
85
+ ]),
86
+ }],
87
+ },
88
+ };
89
+
90
+ const messages = provider.normalizeMessage(entry, SESSION_ID);
91
+ assert.equal(messages[0].content, 'Summarize this');
92
+ assert.deepEqual(messages[0].files, [
93
+ { path: 'C:/Users/x/.cloudcli/assets/brief.pdf', name: 'brief.pdf' },
94
+ ]);
95
+ });
96
+
74
97
  // ---------------------------------------------------------------- Codex
75
98
 
76
99
  test('codex history: user_message payload images become path attachments', () => {
@@ -123,6 +146,27 @@ test('codex history: normalized user entries keep their images', () => {
123
146
  assert.deepEqual(messages[0].images, [{ path: '.cloudcli/assets/a.png' }]);
124
147
  });
125
148
 
149
+ test('codex history: normalized user entries restore file reference blocks', () => {
150
+ const provider = new CodexSessionsProvider();
151
+ const messages = provider.normalizeMessage(
152
+ {
153
+ timestamp: '2026-07-03T10:00:00.000Z',
154
+ message: {
155
+ role: 'user',
156
+ content: appendFilesInputTag('Review this', [
157
+ { path: 'C:/Users/x/.cloudcli/assets/spec.docx', name: 'spec.docx' },
158
+ ]),
159
+ },
160
+ },
161
+ SESSION_ID,
162
+ );
163
+
164
+ assert.equal(messages[0].content, 'Review this');
165
+ assert.deepEqual(messages[0].files, [
166
+ { path: 'C:/Users/x/.cloudcli/assets/spec.docx', name: 'spec.docx' },
167
+ ]);
168
+ });
169
+
126
170
  // ---------------------------------------------------------------- Cursor
127
171
 
128
172
  test('cursor history: <images_input> inside user_query is stripped and attached', () => {
@@ -178,3 +222,26 @@ test('cursor history: user text without a tag keeps existing behavior', () => {
178
222
  assert.equal(messages[0].content, 'plain question');
179
223
  assert.equal(messages[0].images, undefined);
180
224
  });
225
+
226
+ test('cursor history: file reference blocks are stripped and attached', () => {
227
+ const provider = new CursorSessionsProvider();
228
+ const taggedPrompt = appendFilesInputTag('Check the data', [
229
+ { path: 'C:/Users/x/.cloudcli/assets/data.csv', name: 'data.csv' },
230
+ ]);
231
+ const messages = provider.normalizeCursorBlobs([
232
+ {
233
+ id: 'blob-file',
234
+ sequence: 1,
235
+ rowid: 1,
236
+ content: {
237
+ role: 'user',
238
+ content: `<user_query>${taggedPrompt}</user_query>`,
239
+ },
240
+ },
241
+ ], SESSION_ID);
242
+
243
+ assert.equal(messages[0].content, 'Check the data');
244
+ assert.deepEqual(messages[0].files, [
245
+ { path: 'C:/Users/x/.cloudcli/assets/data.csv', name: 'data.csv' },
246
+ ]);
247
+ });