coding-tool-x 3.8.4 → 3.8.6

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 (434) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +86 -15
  3. package/dist/web/assets/AgentsDrawer-Db9wAyaZ.js +1 -0
  4. package/dist/web/assets/AgentsDrawer-Pw2k-ZAa.css +1 -0
  5. package/dist/web/assets/Analytics-C4gMzv7g.js +1 -0
  6. package/dist/web/assets/Analytics-CyHhR126.css +1 -0
  7. package/dist/web/assets/AssetPathField-Bd_nMFu3.js +1 -0
  8. package/dist/web/assets/ChatHistoryDrawer-B2qBQs9L.css +1 -0
  9. package/dist/web/assets/ChatHistoryDrawer-CwzJHyNP.js +1 -0
  10. package/dist/web/assets/CollapseItem-CTCfSiue.js +1 -0
  11. package/dist/web/assets/CommandsDrawer-BZJxlPvV.css +1 -0
  12. package/dist/web/assets/CommandsDrawer-vDghB1U9.js +1 -0
  13. package/dist/web/assets/ConfigExportDrawer-C-XDvlHc.js +1 -0
  14. package/dist/web/assets/ConfigExportDrawer-dwruRKWr.css +1 -0
  15. package/dist/web/assets/ConfigTemplates-CYY8XRED.js +1 -0
  16. package/dist/web/assets/ConfigTemplatesDrawer-BfDi8yO3.css +1 -0
  17. package/dist/web/assets/ConfigTemplatesDrawer-CbsJp76X.js +1 -0
  18. package/dist/web/assets/ConfigTemplatesPanel-CWyPtk67.css +1 -0
  19. package/dist/web/assets/ConfigTemplatesPanel-liMSTh7s.js +1 -0
  20. package/dist/web/assets/Divider-D28g1gwj.js +1 -0
  21. package/dist/web/assets/DrawerContent-ChXgZ1Xm.js +1 -0
  22. package/dist/web/assets/FavoritesDrawer-CG9eI9Ay.css +1 -0
  23. package/dist/web/assets/FavoritesDrawer-D6QSiYaL.js +1 -0
  24. package/dist/web/assets/GatewayConvertDrawer-CuNlf7AC.css +1 -0
  25. package/dist/web/assets/GatewayConvertDrawer-RvET6iNG.js +1 -0
  26. package/dist/web/assets/Home-CSuFuJ9Y.css +1 -0
  27. package/dist/web/assets/Home-P8eseZcf.js +1 -0
  28. package/dist/web/assets/MarkdownEditor-CYmLGYju.js +1 -0
  29. package/dist/web/assets/MarkdownEditor-qfVgSre_.css +1 -0
  30. package/dist/web/assets/McpDrawer-C0dnsZhQ.css +1 -0
  31. package/dist/web/assets/McpDrawer-Ch3bkKIq.js +1 -0
  32. package/dist/web/assets/McpFormDrawer-BRbDcawn.css +1 -0
  33. package/dist/web/assets/McpFormDrawer-BcTlgSpN.js +1 -0
  34. package/dist/web/assets/PluginManager-Dh2o0xkZ.js +1 -0
  35. package/dist/web/assets/PluginsDrawer-DM3QjprE.css +1 -0
  36. package/dist/web/assets/PluginsDrawer-deKQ5u3I.js +1 -0
  37. package/dist/web/assets/PluginsPanel-BofsgQgj.js +1 -0
  38. package/dist/web/assets/PluginsPanel-D6ZqITcR.css +1 -0
  39. package/dist/web/assets/ProjectList-677RLZ8O.css +1 -0
  40. package/dist/web/assets/ProjectList-DhSWJHTA.js +1 -0
  41. package/dist/web/assets/PromptsDrawer-BIgiYCEQ.css +1 -0
  42. package/dist/web/assets/PromptsDrawer-Cfb2FeeU.js +1 -0
  43. package/dist/web/assets/RecentSessionsDrawer-3eXamJhr.js +1 -0
  44. package/dist/web/assets/RecentSessionsDrawer-CKFsOYDM.css +1 -0
  45. package/dist/web/assets/SessionCard-CW0eHURI.js +1 -0
  46. package/dist/web/assets/SessionCard-aM2NHu6i.css +1 -0
  47. package/dist/web/assets/SessionList-BpYRz1cX.css +1 -0
  48. package/dist/web/assets/SessionList-DQfyDGWU.js +1 -0
  49. package/dist/web/assets/SettingsDrawer-Dw5NUgHC.css +1 -0
  50. package/dist/web/assets/SettingsDrawer-u_vwUuPS.js +1 -0
  51. package/dist/web/assets/SkillManager-C0GCT2Kb.css +1 -0
  52. package/dist/web/assets/SkillManager-DHMprJLA.js +1 -0
  53. package/dist/web/assets/SkillsDrawer-BCNme-aJ.css +1 -0
  54. package/dist/web/assets/SkillsDrawer-CkF3BpyC.js +1 -0
  55. package/dist/web/assets/SkillsPanel-B3Nm5j32.css +1 -0
  56. package/dist/web/assets/SkillsPanel-DWE4pFGx.js +1 -0
  57. package/dist/web/assets/SpeedTestDrawer-BgfG1Ked.js +1 -0
  58. package/dist/web/assets/SpeedTestDrawer-Dc0WToJ_.css +1 -0
  59. package/dist/web/assets/Upload-CNwaGOws.js +1 -0
  60. package/dist/web/assets/WorkspaceDrawer-Br5CeCzL.js +1 -0
  61. package/dist/web/assets/WorkspaceDrawer-CGnMu9p1.css +1 -0
  62. package/dist/web/assets/WorkspaceManager-B2O8-qIw.js +1 -0
  63. package/dist/web/assets/WorkspacePanel-5oDKit3c.js +1 -0
  64. package/dist/web/assets/WorkspacePanel-D0-zHTHP.css +1 -0
  65. package/dist/web/assets/_plugin-vue_export-helper-BeLZJZij.js +1 -0
  66. package/dist/web/assets/client-UDwXBP9i.js +1 -0
  67. package/dist/web/assets/clipboard-B46yyoz_.js +1 -0
  68. package/dist/web/assets/headers-cf-QapUq.js +1 -0
  69. package/dist/web/assets/icons-B2Vg-IOC.js +1 -0
  70. package/dist/web/assets/index-BMAUPq5K.js +2 -0
  71. package/dist/web/assets/index-Bi1MQHYX.css +1 -0
  72. package/dist/web/assets/light-Cp0t7v32.js +1 -0
  73. package/dist/web/assets/markdown-u082bbtj.js +1 -0
  74. package/dist/web/assets/platforms-CBkB45JP.js +1 -0
  75. package/dist/web/assets/platforms-FTpjxAT6.js +1 -0
  76. package/dist/web/assets/project-config-B2baPzYL.js +1 -0
  77. package/dist/web/assets/sessions-Cmy31slD.js +1 -0
  78. package/dist/web/assets/sessions-yC_oVVh8.js +1 -0
  79. package/dist/web/assets/skill-repo-input-B_fkGlUK.js +1 -0
  80. package/dist/web/assets/use-lock-html-scroll-DXIqmUW4.js +1 -0
  81. package/dist/web/assets/use-message-DoLM8C1C.js +1 -0
  82. package/dist/web/assets/useResponsiveDrawer-jbmqZuJs.js +1 -0
  83. package/dist/web/assets/vendors-D0c_0KLP.js +1 -0
  84. package/dist/web/assets/vue-vendor-BqZbbXHA.js +1 -0
  85. package/dist/web/assets/workspaces-mjyPVGS8.js +1 -0
  86. package/dist/web/assets/xml-CgY3RMlX.js +1 -0
  87. package/dist/web/index.html +12 -8
  88. package/docs/native-log-memory-2026-09-16.md +43 -0
  89. package/docs/superpowers/plans/2026-08-26-configuration-driven-cli-platform.md +1578 -0
  90. package/docs/superpowers/plans/2026-08-30-project-scoped-config-control.md +1260 -0
  91. package/docs/superpowers/plans/2026-09-01-omp-skill-refresh-boundary.md +213 -0
  92. package/docs/superpowers/plans/2026-09-01-realtime-logs-panel.md +125 -0
  93. package/docs/superpowers/plans/2026-09-02-config-driven-platform-boundary.md +86 -0
  94. package/docs/superpowers/plans/2026-09-02-platform-implementation-drivers.md +508 -0
  95. package/docs/superpowers/plans/2026-09-03-cli-platform-correctness-boundary.md +760 -0
  96. package/docs/superpowers/plans/2026-09-03-dependency-security-remediation.md +133 -0
  97. package/docs/superpowers/plans/2026-09-04-model-catalog-pricing-sync.md +1078 -0
  98. package/docs/superpowers/plans/2026-09-05-codex-project-scan-500.md +128 -0
  99. package/docs/superpowers/plans/2026-09-06-project-skill-path-fix.md +97 -0
  100. package/docs/superpowers/specs/2026-08-26-configuration-driven-cli-platform-design.md +408 -0
  101. package/docs/superpowers/specs/2026-08-30-project-scoped-config-control-design.md +467 -0
  102. package/docs/superpowers/specs/2026-09-01-claude-session-content-repair-design.md +111 -0
  103. package/docs/superpowers/specs/2026-09-01-omp-skill-refresh-boundary-design.md +83 -0
  104. package/docs/superpowers/specs/2026-09-01-realtime-logs-panel-design.md +27 -0
  105. package/docs/superpowers/specs/2026-09-02-config-driven-platform-boundary-design.md +64 -0
  106. package/docs/superpowers/specs/2026-09-02-platform-implementation-driver-boundary-design.md +123 -0
  107. package/docs/superpowers/specs/2026-09-03-cli-platform-correctness-boundary-design.md +249 -0
  108. package/docs/superpowers/specs/2026-09-03-dependency-security-remediation-design.md +87 -0
  109. package/docs/superpowers/specs/2026-09-04-model-catalog-pricing-sync-design.md +301 -0
  110. package/docs/superpowers/specs/2026-09-05-codex-project-scan-500-design.md +24 -0
  111. package/package.json +8 -4
  112. package/src/commands/channels.js +88 -191
  113. package/src/commands/cli-type.js +19 -11
  114. package/src/commands/daemon.js +104 -32
  115. package/src/commands/doctor.js +16 -9
  116. package/src/commands/export-config.js +23 -5
  117. package/src/commands/list.js +130 -52
  118. package/src/commands/logs.js +44 -27
  119. package/src/commands/platform-command-registry.js +78 -0
  120. package/src/commands/plugin.js +11 -5
  121. package/src/commands/port-config.js +34 -52
  122. package/src/commands/proxy-control.js +207 -145
  123. package/src/commands/proxy.js +2 -2
  124. package/src/commands/resume.js +87 -91
  125. package/src/commands/search.js +137 -67
  126. package/src/commands/stats.js +30 -22
  127. package/src/commands/switch.js +1 -1
  128. package/src/commands/toggle-proxy.js +94 -111
  129. package/src/commands/ui.js +67 -6
  130. package/src/commands/workspace.js +90 -8
  131. package/src/config/default.js +6 -53
  132. package/src/config/loader.js +61 -24
  133. package/src/config/model-metadata.js +49 -59
  134. package/src/config/model-metadata.json +4095 -99
  135. package/src/config/paths.js +181 -8
  136. package/src/index.js +134 -71
  137. package/src/platforms/access.js +196 -0
  138. package/src/{server/services → platforms}/agents-service.js +354 -197
  139. package/src/platforms/channel-auth-registry.js +165 -0
  140. package/src/platforms/channel-auth-service.js +107 -0
  141. package/src/{server/services → platforms}/commands-service.js +195 -115
  142. package/src/platforms/driver-registry.js +59 -0
  143. package/src/platforms/drivers/claude/api-operations.js +62 -0
  144. package/src/{server/services/channels.js → platforms/drivers/claude/channels-implementation.js} +131 -33
  145. package/src/platforms/drivers/claude/channels.js +39 -0
  146. package/src/{server/services/config-sync-service.js → platforms/drivers/claude/config-sync.js} +29 -5
  147. package/src/{server/services → platforms/drivers/claude}/health-check.js +4 -4
  148. package/src/platforms/drivers/claude/health.js +22 -0
  149. package/src/platforms/drivers/claude/mcp.js +9 -0
  150. package/src/{server/services/settings-manager.js → platforms/drivers/claude/native-config-implementation.js} +13 -4
  151. package/src/platforms/drivers/claude/native-config.js +46 -0
  152. package/src/platforms/drivers/claude/native-logs.js +72 -0
  153. package/src/{server/services/claude-openai-gateway.js → platforms/drivers/claude/openai-gateway.js} +8 -65
  154. package/src/platforms/drivers/claude/project-config.js +21 -0
  155. package/src/platforms/drivers/claude/projects.js +62 -0
  156. package/src/platforms/drivers/claude/prompts.js +9 -0
  157. package/src/{server/proxy-server.js → platforms/drivers/claude/proxy-implementation.js} +41 -278
  158. package/src/platforms/drivers/claude/proxy.js +16 -0
  159. package/src/platforms/drivers/claude/resource-sync.js +9 -0
  160. package/src/platforms/drivers/claude/session-history-adapter.js +313 -0
  161. package/src/{server/services/sessions.js → platforms/drivers/claude/sessions-implementation.js} +145 -35
  162. package/src/platforms/drivers/claude/sessions.js +76 -0
  163. package/src/{server/services/claude-statistics-service.js → platforms/drivers/claude/statistics-implementation.js} +2 -2
  164. package/src/platforms/drivers/claude/statistics.js +16 -0
  165. package/src/{server/services/claude-wire.js → platforms/drivers/claude/wire.js} +1 -1
  166. package/src/platforms/drivers/codex/api-operations.js +9 -0
  167. package/src/{server/services/codex-channels.js → platforms/drivers/codex/channels-implementation.js} +149 -14
  168. package/src/platforms/drivers/codex/channels.js +45 -0
  169. package/src/{server/services/codex-config.js → platforms/drivers/codex/config.js} +12 -2
  170. package/src/{server/services/codex-env-manager.js → platforms/drivers/codex/env-manager.js} +1 -1
  171. package/src/platforms/drivers/codex/mcp.js +9 -0
  172. package/src/{server/services/codex-settings-manager.js → platforms/drivers/codex/native-config-implementation.js} +15 -6
  173. package/src/platforms/drivers/codex/native-config.js +47 -0
  174. package/src/platforms/drivers/codex/native-logs.js +166 -0
  175. package/src/platforms/drivers/codex/project-config.js +21 -0
  176. package/src/platforms/drivers/codex/projects.js +26 -0
  177. package/src/platforms/drivers/codex/prompts.js +9 -0
  178. package/src/{server/codex-proxy-server.js → platforms/drivers/codex/proxy-implementation.js} +30 -233
  179. package/src/platforms/drivers/codex/proxy.js +16 -0
  180. package/src/platforms/drivers/codex/resource-sync.js +9 -0
  181. package/src/{server/services/session-history-adapters/codex.js → platforms/drivers/codex/session-history-adapter.js} +37 -23
  182. package/src/{server/services/codex-sessions.js → platforms/drivers/codex/sessions-implementation.js} +81 -75
  183. package/src/platforms/drivers/codex/sessions.js +36 -0
  184. package/src/{server/services/codex-statistics-service.js → platforms/drivers/codex/statistics-implementation.js} +2 -2
  185. package/src/platforms/drivers/codex/statistics.js +16 -0
  186. package/src/platforms/drivers/gemini/api-operations.js +9 -0
  187. package/src/{server/services/gemini-channels.js → platforms/drivers/gemini/channels-implementation.js} +202 -37
  188. package/src/platforms/drivers/gemini/channels.js +39 -0
  189. package/src/{server/services/gemini-config.js → platforms/drivers/gemini/config.js} +12 -2
  190. package/src/platforms/drivers/gemini/mcp.js +9 -0
  191. package/src/{server/services/gemini-settings-manager.js → platforms/drivers/gemini/native-config-implementation.js} +14 -5
  192. package/src/platforms/drivers/gemini/native-config.js +39 -0
  193. package/src/platforms/drivers/gemini/native-logs.js +180 -0
  194. package/src/platforms/drivers/gemini/project-config.js +21 -0
  195. package/src/platforms/drivers/gemini/projects.js +26 -0
  196. package/src/platforms/drivers/gemini/prompts.js +9 -0
  197. package/src/{server/gemini-proxy-server.js → platforms/drivers/gemini/proxy-implementation.js} +36 -267
  198. package/src/platforms/drivers/gemini/proxy.js +16 -0
  199. package/src/platforms/drivers/gemini/resource-sync.js +9 -0
  200. package/src/{server/services/session-history-adapters/gemini.js → platforms/drivers/gemini/session-history-adapter.js} +70 -18
  201. package/src/{server/services/gemini-sessions.js → platforms/drivers/gemini/sessions-implementation.js} +53 -37
  202. package/src/platforms/drivers/gemini/sessions.js +47 -0
  203. package/src/{server/services/gemini-statistics-service.js → platforms/drivers/gemini/statistics-implementation.js} +2 -2
  204. package/src/platforms/drivers/gemini/statistics.js +16 -0
  205. package/src/{server/services/gemini-wire.js → platforms/drivers/gemini/wire.js} +1 -1
  206. package/src/platforms/drivers/generic-filesystem.js +166 -0
  207. package/src/platforms/drivers/generic-jsonl.js +141 -0
  208. package/src/platforms/drivers/generic-mcp.js +44 -0
  209. package/src/platforms/drivers/generic-openai-compatible.js +45 -0
  210. package/src/platforms/drivers/generic-prompt.js +41 -0
  211. package/src/platforms/drivers/legacy.js +677 -0
  212. package/src/platforms/drivers/native-config-snapshot.js +125 -0
  213. package/src/platforms/drivers/native-log-utils.js +1292 -0
  214. package/src/platforms/drivers/notification-hooks.js +578 -0
  215. package/src/{server/api/omp-config.js → platforms/drivers/omp/api-operations.js} +52 -64
  216. package/src/{server/services/omp-auth-provider-worker.js → platforms/drivers/omp/auth-provider-worker.js} +1 -1
  217. package/src/{server/services/omp-auth-providers.js → platforms/drivers/omp/auth-providers.js} +1 -1
  218. package/src/{server/services/omp-channels.js → platforms/drivers/omp/channels-implementation.js} +166 -39
  219. package/src/platforms/drivers/omp/channels.js +58 -0
  220. package/src/{server/services/omp-config.js → platforms/drivers/omp/config.js} +53 -13
  221. package/src/{server/services/omp-gateway-routing.js → platforms/drivers/omp/gateway-routing.js} +14 -7
  222. package/src/{server/services/omp-gateway.js → platforms/drivers/omp/gateway.js} +4 -262
  223. package/src/platforms/drivers/omp/mcp.js +9 -0
  224. package/src/{server/services/omp-settings-manager.js → platforms/drivers/omp/native-config-implementation.js} +75 -10
  225. package/src/platforms/drivers/omp/native-config.js +46 -0
  226. package/src/platforms/drivers/omp/native-logs.js +52 -0
  227. package/src/{server/services/omp-native-plugin-adapter.js → platforms/drivers/omp/native-plugin-adapter.js} +91 -4
  228. package/src/platforms/drivers/omp/project-config.js +29 -0
  229. package/src/platforms/drivers/omp/projects.js +20 -0
  230. package/src/platforms/drivers/omp/prompts.js +9 -0
  231. package/src/{server/omp-proxy-server.js → platforms/drivers/omp/proxy-implementation.js} +6 -15
  232. package/src/platforms/drivers/omp/proxy.js +16 -0
  233. package/src/platforms/drivers/omp/resource-sync.js +9 -0
  234. package/src/{server/services/session-history-adapters/omp.js → platforms/drivers/omp/session-history-adapter.js} +42 -18
  235. package/src/{server/services/omp-sessions.js → platforms/drivers/omp/sessions-implementation.js} +130 -94
  236. package/src/platforms/drivers/omp/sessions.js +36 -0
  237. package/src/{server/services/omp-skill-discovery.js → platforms/drivers/omp/skill-discovery.js} +159 -32
  238. package/src/{server/services/omp-skill-settings-service.js → platforms/drivers/omp/skill-settings.js} +1 -1
  239. package/src/{server/services/omp-statistics-service.js → platforms/drivers/omp/statistics-implementation.js} +3 -3
  240. package/src/platforms/drivers/omp/statistics.js +16 -0
  241. package/src/platforms/drivers/opencode/api-operations.js +9 -0
  242. package/src/{server/services/opencode-channels.js → platforms/drivers/opencode/channels-implementation.js} +28 -9
  243. package/src/platforms/drivers/opencode/channels.js +40 -0
  244. package/src/platforms/drivers/opencode/conversion.js +41 -0
  245. package/src/{server/services/opencode-gateway-converter.js → platforms/drivers/opencode/gateway-converter.js} +1 -1
  246. package/src/platforms/drivers/opencode/mcp.js +9 -0
  247. package/src/{server/services/opencode-settings-manager.js → platforms/drivers/opencode/native-config-implementation.js} +17 -6
  248. package/src/platforms/drivers/opencode/native-config.js +26 -0
  249. package/src/platforms/drivers/opencode/native-logs.js +133 -0
  250. package/src/platforms/drivers/opencode/project-config.js +98 -0
  251. package/src/platforms/drivers/opencode/projects.js +20 -0
  252. package/src/platforms/drivers/opencode/prompts.js +9 -0
  253. package/src/{server/opencode-proxy-server.js → platforms/drivers/opencode/proxy-implementation.js} +27 -362
  254. package/src/platforms/drivers/opencode/proxy.js +16 -0
  255. package/src/platforms/drivers/opencode/resource-sync.js +9 -0
  256. package/src/{server/services/opencode-sessions.js → platforms/drivers/opencode/sessions-implementation.js} +211 -64
  257. package/src/platforms/drivers/opencode/sessions.js +48 -0
  258. package/src/{server/services/opencode-statistics-service.js → platforms/drivers/opencode/statistics-implementation.js} +2 -2
  259. package/src/platforms/drivers/opencode/statistics.js +16 -0
  260. package/src/platforms/drivers/secure-file-driver.js +272 -0
  261. package/src/platforms/drivers/unsupported.js +7 -0
  262. package/src/platforms/manifest-schema.js +398 -0
  263. package/src/platforms/manifests/claude.json +489 -0
  264. package/src/platforms/manifests/codex.json +448 -0
  265. package/src/platforms/manifests/gemini.json +447 -0
  266. package/src/platforms/manifests/omp.json +496 -0
  267. package/src/platforms/manifests/opencode.json +422 -0
  268. package/src/{server/services → platforms}/native-oauth-adapters.js +98 -418
  269. package/src/{server/services → platforms}/notification-hooks.js +190 -1023
  270. package/src/platforms/oauth-credentials-service.js +635 -0
  271. package/src/platforms/path-resolver.js +179 -0
  272. package/src/platforms/platform-path-context.js +305 -0
  273. package/src/platforms/registry.js +248 -0
  274. package/src/platforms/remote-notification-providers.js +678 -0
  275. package/src/platforms/runtime.js +259 -0
  276. package/src/{server/services/session-history-adapters/index.js → platforms/session-history-adapters.js} +8 -1
  277. package/src/plugins/plugin-loader.js +2 -2
  278. package/src/plugins/plugin-manager.js +2 -2
  279. package/src/plugins/registry.js +27 -10
  280. package/src/reset-config.js +21 -5
  281. package/src/server/api/agents.js +46 -72
  282. package/src/server/api/commands.js +16 -6
  283. package/src/server/api/config-registry.js +206 -59
  284. package/src/server/api/config-sync.js +3 -2
  285. package/src/server/api/config-templates.js +20 -4
  286. package/src/server/api/config.js +111 -102
  287. package/src/server/api/convert.js +54 -178
  288. package/src/server/api/dashboard.js +168 -102
  289. package/src/server/api/hooks.js +1 -1
  290. package/src/server/api/mcp.js +224 -84
  291. package/src/server/api/platform-api-config.js +102 -0
  292. package/src/server/api/platform-route-factory.js +215 -0
  293. package/src/server/api/platform-routes.js +26 -0
  294. package/src/server/api/platforms.js +110 -0
  295. package/src/server/api/plugins.js +57 -57
  296. package/src/server/api/project-config.js +168 -0
  297. package/src/server/api/prompts.js +58 -45
  298. package/src/server/api/settings.js +55 -8
  299. package/src/server/api/skills.js +262 -133
  300. package/src/server/api/ui-config.js +2 -2
  301. package/src/server/api/validation-errors.js +18 -4
  302. package/src/server/api/workspaces.js +47 -12
  303. package/src/server/index.js +164 -213
  304. package/src/server/platform-context.js +81 -0
  305. package/src/server/services/channel-balance.js +133 -24
  306. package/src/server/services/channel-health.js +21 -6
  307. package/src/server/services/channel-scheduler.js +29 -39
  308. package/src/server/services/channel-sync-utils.js +23 -13
  309. package/src/server/services/config-export-service.js +350 -319
  310. package/src/server/services/config-registry-service.js +280 -54
  311. package/src/server/services/config-sync-manager.js +172 -944
  312. package/src/server/services/config-templates-service.js +419 -353
  313. package/src/server/services/control-manifest-store.js +206 -0
  314. package/src/server/services/dashboard-snapshot-worker.js +656 -100
  315. package/src/server/services/effective-control-service.js +557 -0
  316. package/src/server/services/local-resource-index.js +314 -0
  317. package/src/server/services/mcp-service.js +607 -977
  318. package/src/server/services/model-detector.js +15 -10
  319. package/src/server/services/native-log-channel-resolver.js +214 -0
  320. package/src/server/services/native-log-observer.js +291 -0
  321. package/src/server/services/network-access.js +12 -2
  322. package/src/server/services/platform-catalog.js +82 -0
  323. package/src/server/services/platform-resolution.js +32 -29
  324. package/src/server/services/plugins-service.js +376 -122
  325. package/src/server/services/project-config-service.js +550 -0
  326. package/src/server/services/project-path-validation.js +31 -0
  327. package/src/server/services/prompts-service.js +267 -233
  328. package/src/server/services/proxy-runtime.js +7 -4
  329. package/src/server/services/remote-credential-cache.js +43 -0
  330. package/src/server/services/repo-scanner-base.js +182 -75
  331. package/src/server/services/request-logger.js +7 -4
  332. package/src/server/services/session-history-index.js +876 -214
  333. package/src/server/services/session-history-worker.js +228 -33
  334. package/src/server/services/session-snapshot-worker.js +124 -34
  335. package/src/server/services/session-snapshots.js +4 -2
  336. package/src/server/services/skill-artifact-store.js +355 -0
  337. package/src/server/services/skill-format-adapters.js +65 -0
  338. package/src/server/services/skill-projection-service.js +323 -0
  339. package/src/server/services/skill-refresh-task-service.js +275 -0
  340. package/src/server/services/skill-service.js +2020 -677
  341. package/src/server/services/snapshot-cache.js +30 -8
  342. package/src/server/services/speed-test.js +8 -8
  343. package/src/server/services/sqlite-connection.js +19 -3
  344. package/src/server/services/statistics-service.js +240 -57
  345. package/src/server/services/ui-config.js +107 -76
  346. package/src/server/services/usage-log-utils.js +98 -0
  347. package/src/server/services/web-build.js +1 -1
  348. package/src/server/services/workspace-service.js +59 -29
  349. package/src/server/utils/pricing.js +10 -19
  350. package/src/server/websocket-server.js +153 -28
  351. package/src/{server/services/base → shared}/base-channel-service.js +156 -28
  352. package/src/shared/capability-driver.js +104 -0
  353. package/src/shared/channel-auth-policy.js +27 -0
  354. package/src/shared/channel-driver.js +161 -0
  355. package/src/shared/driver-factories/api.js +180 -0
  356. package/src/shared/driver-factories/mcp.js +244 -0
  357. package/src/shared/driver-factories/projects.js +121 -0
  358. package/src/shared/driver-factories/prompts.js +58 -0
  359. package/src/shared/driver-factories/resource-sync.js +375 -0
  360. package/src/shared/driver-result.js +78 -0
  361. package/src/shared/mcp-format.js +189 -0
  362. package/src/shared/platforms.js +104 -167
  363. package/src/shared/project-config.js +512 -0
  364. package/src/shared/proxy-driver.js +57 -0
  365. package/src/{server/services/base → shared}/response-usage-parser.js +8 -4
  366. package/src/ui/menu.js +91 -67
  367. package/src/utils/port-helper.js +35 -19
  368. package/src/utils/session.js +1 -1
  369. package/dist/web/assets/Analytics-COEUXmd4.js +0 -25
  370. package/dist/web/assets/Analytics-RNn1BUbG.css +0 -1
  371. package/dist/web/assets/ConfigTemplates-DLLkS53H.js +0 -1
  372. package/dist/web/assets/Home-DCEyLzwX.js +0 -1
  373. package/dist/web/assets/Home-DYVy4cGZ.css +0 -1
  374. package/dist/web/assets/PluginManager-Oe1ZHoMO.js +0 -1
  375. package/dist/web/assets/ProjectList-CWjuAFof.js +0 -1
  376. package/dist/web/assets/ProjectList-VeMNXfgO.css +0 -1
  377. package/dist/web/assets/SessionList-C4chCPxK.css +0 -1
  378. package/dist/web/assets/SessionList-v3ehGg9U.js +0 -1
  379. package/dist/web/assets/SkillManager-BsX8Qpj0.css +0 -1
  380. package/dist/web/assets/SkillManager-DUF_qP5S.js +0 -1
  381. package/dist/web/assets/WorkspaceManager-CjAWBosO.js +0 -1
  382. package/dist/web/assets/icons-nGdSKQn2.js +0 -1
  383. package/dist/web/assets/index-D5hyHPj7.js +0 -2
  384. package/dist/web/assets/index-bJRG3RXH.css +0 -1
  385. package/dist/web/assets/markdown-BNJfEgCA.js +0 -1
  386. package/dist/web/assets/markdown-BfC0goYb.css +0 -10
  387. package/dist/web/assets/naive-ui-BALVpMgd.js +0 -1
  388. package/dist/web/assets/vendors-DQA4Hw9v.js +0 -7
  389. package/dist/web/assets/vue-vendor-B5RqjEjQ.js +0 -45
  390. package/src/config/model-pricing.js +0 -35
  391. package/src/server/api/channels.js +0 -439
  392. package/src/server/api/claude-hooks.js +0 -56
  393. package/src/server/api/claude-statistics.js +0 -57
  394. package/src/server/api/codex-channels.js +0 -491
  395. package/src/server/api/codex-projects.js +0 -117
  396. package/src/server/api/codex-proxy.js +0 -293
  397. package/src/server/api/codex-sessions.js +0 -652
  398. package/src/server/api/codex-statistics.js +0 -57
  399. package/src/server/api/gemini-channels.js +0 -392
  400. package/src/server/api/gemini-projects.js +0 -103
  401. package/src/server/api/gemini-proxy.js +0 -231
  402. package/src/server/api/gemini-sessions.js +0 -550
  403. package/src/server/api/gemini-statistics.js +0 -57
  404. package/src/server/api/health-check.js +0 -31
  405. package/src/server/api/oauth-credentials.js +0 -198
  406. package/src/server/api/omp-channels.js +0 -575
  407. package/src/server/api/omp-projects.js +0 -88
  408. package/src/server/api/omp-proxy.js +0 -125
  409. package/src/server/api/omp-sessions.js +0 -386
  410. package/src/server/api/omp-statistics.js +0 -40
  411. package/src/server/api/opencode-channels.js +0 -471
  412. package/src/server/api/opencode-projects.js +0 -110
  413. package/src/server/api/opencode-proxy.js +0 -354
  414. package/src/server/api/opencode-sessions.js +0 -466
  415. package/src/server/api/opencode-statistics.js +0 -57
  416. package/src/server/api/projects.js +0 -120
  417. package/src/server/api/proxy.js +0 -330
  418. package/src/server/api/sessions.js +0 -810
  419. package/src/server/services/oauth-credentials-service.js +0 -945
  420. package/src/server/services/omp-session-log-observer.js +0 -138
  421. package/src/server/services/opencode-gateway-adapters.js +0 -43
  422. package/src/server/services/project-snapshots.js +0 -59
  423. package/src/server/services/proxy-log-helper.js +0 -298
  424. package/src/server/services/session-cache.js +0 -127
  425. package/src/server/services/session-converter.js +0 -582
  426. package/src/server/services/session-history-adapters/claude.js +0 -235
  427. /package/src/{server/services/claude-token-recovery.js → platforms/drivers/claude/token-recovery.js} +0 -0
  428. /package/src/{server/services/codex-parser.js → platforms/drivers/codex/parser.js} +0 -0
  429. /package/src/{server/services/codex-speed-test-template.json → platforms/drivers/codex/speed-test-template.json} +0 -0
  430. /package/src/{server/services/codex-wire.js → platforms/drivers/codex/wire.js} +0 -0
  431. /package/src/{server/services/omp-auth-gateway-client.js → platforms/drivers/omp/auth-gateway-client.js} +0 -0
  432. /package/src/{server/services/opencode-normalization.js → platforms/drivers/opencode/normalization.js} +0 -0
  433. /package/src/{server/services → shared}/config-artifact-paths.js +0 -0
  434. /package/src/{server/services/base → shared}/proxy-utils.js +0 -0
@@ -1,66 +1,225 @@
1
1
  'use strict';
2
2
 
3
- const { fork } = require('child_process');
3
+ const childProcess = require('child_process');
4
4
  const path = require('path');
5
5
 
6
6
  const WORKER_TIMEOUT_MS = 180000;
7
+ const MAX_SERIALIZED_ERROR_TEXT_LENGTH = 4096;
8
+
9
+ function _safeErrorText(value, fallback = '') {
10
+ const text = value == null || value === '' ? fallback : String(value);
11
+ return text.length > MAX_SERIALIZED_ERROR_TEXT_LENGTH
12
+ ? `${text.slice(0, MAX_SERIALIZED_ERROR_TEXT_LENGTH)}…`
13
+ : text;
14
+ }
15
+
16
+ function _safeCode(value) {
17
+ return typeof value === 'string' || typeof value === 'number' ? value : undefined;
18
+ }
19
+
20
+ const MAX_SERIALIZED_OBJECT_DEPTH = 6;
21
+ const MAX_SERIALIZED_OBJECT_KEYS = 32;
22
+ const MAX_SERIALIZED_ARRAY_LENGTH = 64;
23
+
24
+ function _safeStructuredValue(value, depth = 0) {
25
+ if (value == null || typeof value === 'boolean' || typeof value === 'number') {
26
+ return Number.isFinite(value) || typeof value !== 'number' ? value : undefined;
27
+ }
28
+ if (typeof value === 'string') {
29
+ return _safeErrorText(value);
30
+ }
31
+ if (typeof value !== 'object') {
32
+ return undefined;
33
+ }
34
+ if (depth >= MAX_SERIALIZED_OBJECT_DEPTH) {
35
+ return undefined;
36
+ }
37
+ if (Array.isArray(value)) {
38
+ const items = [];
39
+ for (const item of value.slice(0, MAX_SERIALIZED_ARRAY_LENGTH)) {
40
+ const safeItem = _safeStructuredValue(item, depth + 1);
41
+ if (safeItem !== undefined) {
42
+ items.push(safeItem);
43
+ }
44
+ }
45
+ return items;
46
+ }
47
+
48
+ const result = {};
49
+ let count = 0;
50
+ for (const [key, item] of Object.entries(value)) {
51
+ if (count >= MAX_SERIALIZED_OBJECT_KEYS) break;
52
+ const safeItem = _safeStructuredValue(item, depth + 1);
53
+ if (safeItem !== undefined) {
54
+ result[_safeErrorText(key)] = safeItem;
55
+ count += 1;
56
+ }
57
+ }
58
+ return result;
59
+ }
60
+
61
+
62
+
63
+ function _serializeCause(cause) {
64
+ if (!cause) {
65
+ return null;
66
+ }
67
+ const serialized = {
68
+ name: _safeErrorText(cause.name, 'Error'),
69
+ message: _safeErrorText(cause && cause.message ? cause.message : cause, 'Error')
70
+ };
71
+ const code = _safeCode(cause.code);
72
+ if (code !== undefined) {
73
+ serialized.code = code;
74
+ }
75
+ return serialized;
76
+ }
77
+
78
+ function _serializeWorkerError(error) {
79
+ if (!error || typeof error !== 'object') {
80
+ return { message: _safeErrorText(error, 'Inventory worker failed') };
81
+ }
82
+ const serialized = {
83
+ message: _safeErrorText(error.message ? error.message : error, 'Inventory worker failed')
84
+ };
85
+ if (typeof error.platform === 'string') serialized.platform = _safeErrorText(error.platform);
86
+ if (typeof error.capability === 'string') serialized.capability = _safeErrorText(error.capability);
87
+ if (typeof error.operation === 'string') serialized.operation = _safeErrorText(error.operation);
88
+ const code = _safeCode(error.code);
89
+ if (code !== undefined) serialized.code = code;
90
+ if (typeof error.status === 'string') serialized.status = _safeErrorText(error.status);
91
+ const failure = _safeStructuredValue(error.failure);
92
+ if (failure && typeof failure === 'object' && !Array.isArray(failure)) serialized.failure = failure;
93
+ const context = _safeStructuredValue(error.context);
94
+ if (context && typeof context === 'object' && !Array.isArray(context)) serialized.context = context;
95
+ const cause = _serializeCause(error.cause);
96
+ if (cause) {
97
+ serialized.cause = cause;
98
+ }
99
+ return serialized;
100
+ }
101
+
102
+ function _deserializeCause(cause) {
103
+ if (!cause) {
104
+ return null;
105
+ }
106
+ if (cause instanceof Error) {
107
+ return cause;
108
+ }
109
+ const error = new Error(_safeErrorText(cause.message ? cause.message : cause, 'Error'));
110
+ if (cause.name) {
111
+ error.name = _safeErrorText(cause.name, 'Error');
112
+ }
113
+ const code = _safeCode(cause.code);
114
+ if (code !== undefined) {
115
+ error.code = code;
116
+ }
117
+ return error;
118
+ }
119
+
120
+ function _deserializeWorkerError(payload, fallbackMessage = 'Inventory worker failed') {
121
+ if (payload instanceof Error) {
122
+ return payload;
123
+ }
124
+ if (!payload || typeof payload !== 'object') {
125
+ return new Error(_safeErrorText(payload, fallbackMessage));
126
+ }
127
+ const error = new Error(_safeErrorText(payload.message ? payload.message : fallbackMessage, fallbackMessage));
128
+ if (typeof payload.platform === 'string') error.platform = _safeErrorText(payload.platform);
129
+ if (typeof payload.capability === 'string') error.capability = _safeErrorText(payload.capability);
130
+ if (typeof payload.operation === 'string') error.operation = _safeErrorText(payload.operation);
131
+ const code = _safeCode(payload.code);
132
+ if (code !== undefined) error.code = code;
133
+ if (typeof payload.status === 'string') error.status = _safeErrorText(payload.status);
134
+ const failure = _safeStructuredValue(payload.failure);
135
+ if (failure && typeof failure === 'object' && !Array.isArray(failure)) error.failure = failure;
136
+ const context = _safeStructuredValue(payload.context);
137
+ if (context && typeof context === 'object' && !Array.isArray(context)) error.context = context;
138
+ const cause = _deserializeCause(payload.cause);
139
+ if (cause) {
140
+ error.cause = cause;
141
+ }
142
+ return error;
143
+ }
144
+
7
145
 
8
146
  function runInventoryWorker(source, indexDbPath, options = {}) {
9
147
  return new Promise((resolve, reject) => {
10
148
  const timeoutMs = options.timeoutMs || WORKER_TIMEOUT_MS;
11
149
  const workerPath = path.resolve(__dirname, 'session-history-worker.js');
12
150
 
13
- const child = fork(workerPath, [], {
151
+ let stderr = '';
152
+ const child = childProcess.fork(workerPath, [], {
14
153
  env: {
15
154
  ...process.env,
16
155
  CC_TOOL_SESSION_HISTORY_WORKER: '1',
156
+ CC_TOOL_SESSION_HISTORY_CHILD: '1',
17
157
  CC_TOOL_SESSION_HISTORY_SOURCE: source,
18
158
  CC_TOOL_SESSION_HISTORY_DB: indexDbPath,
19
159
  CC_TOOL_SESSION_HISTORY_FORCE: options.force === true ? '1' : '0',
20
- CC_TOOL_SESSION_HISTORY_CHILD: '1'
160
+ CC_TOOL_SESSION_HISTORY_PROJECTS_DIR: options.projectsDir || ''
21
161
  },
22
162
  silent: true,
23
163
  stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
24
164
  windowsHide: true
25
165
  });
26
166
 
167
+ if (child.stdout && typeof child.stdout.resume === 'function') {
168
+ child.stdout.resume();
169
+ }
170
+ if (child.stderr) {
171
+ if (typeof child.stderr.on === 'function') {
172
+ child.stderr.on('data', (chunk) => {
173
+ stderr = `${stderr}${chunk.toString()}`.slice(-MAX_SERIALIZED_ERROR_TEXT_LENGTH);
174
+ });
175
+ }
176
+ if (typeof child.stderr.resume === 'function') child.stderr.resume();
177
+ }
178
+
27
179
  let settled = false;
28
- const timer = setTimeout(() => {
180
+ let timer = null;
181
+
182
+ const finish = (error) => {
29
183
  if (settled) return;
30
184
  settled = true;
31
- child.kill('SIGTERM');
32
- reject(new Error(`Inventory worker for ${source} timed out after ${timeoutMs}ms`));
185
+ clearTimeout(timer);
186
+ child.removeAllListeners();
187
+ if (!child.killed) {
188
+ child.kill('SIGTERM');
189
+ }
190
+ if (error) {
191
+ reject(error);
192
+ } else {
193
+ resolve();
194
+ }
195
+ };
196
+
197
+ timer = setTimeout(() => {
198
+ finish(new Error(`Inventory worker for ${source} timed out after ${timeoutMs}ms`));
33
199
  }, timeoutMs);
34
200
 
35
201
  child.on('message', (msg) => {
36
- if (settled) return;
37
- settled = true;
38
- clearTimeout(timer);
39
202
  if (msg && msg.type === 'done') {
40
- resolve();
203
+ finish();
41
204
  } else if (msg && msg.type === 'error') {
42
- reject(new Error(msg.message || 'Inventory worker failed'));
205
+ finish(_deserializeWorkerError(msg.error || { message: msg.message }, 'Inventory worker failed'));
43
206
  } else {
44
- resolve();
207
+ finish(new Error(`Inventory worker protocol error: unknown message from ${source}`));
45
208
  }
46
209
  });
47
210
 
48
211
  child.on('exit', (code) => {
49
212
  if (settled) return;
50
- settled = true;
51
- clearTimeout(timer);
213
+ const suffix = stderr.trim() ? `: ${stderr.trim()}` : '';
52
214
  if (code === 0) {
53
- resolve();
215
+ finish(new Error(`Inventory worker protocol error: exited before done for ${source}${suffix}`));
54
216
  } else {
55
- reject(new Error(`Inventory worker exited with code ${code}`));
217
+ finish(new Error(`Inventory worker exited with code ${code}${suffix}`));
56
218
  }
57
219
  });
58
220
 
59
221
  child.on('error', (err) => {
60
- if (settled) return;
61
- settled = true;
62
- clearTimeout(timer);
63
- reject(err);
222
+ finish(err);
64
223
  });
65
224
  });
66
225
  }
@@ -68,32 +227,68 @@ function runInventoryWorker(source, indexDbPath, options = {}) {
68
227
  function attachWorkerHandler() {
69
228
  const source = process.env.CC_TOOL_SESSION_HISTORY_SOURCE;
70
229
  const dbPath = process.env.CC_TOOL_SESSION_HISTORY_DB;
230
+ const projectsDir = process.env.CC_TOOL_SESSION_HISTORY_PROJECTS_DIR || undefined;
71
231
  const force = process.env.CC_TOOL_SESSION_HISTORY_FORCE === '1';
72
-
73
232
  if (!source || !dbPath) {
74
233
  process.exit(1);
234
+ return;
75
235
  }
76
236
 
77
237
  const { createSessionHistoryIndex } = require('./session-history-index');
78
- const index = createSessionHistoryIndex({ dbPath });
238
+ const index = createSessionHistoryIndex({ dbPath, projectsDir });
239
+ const finishWorker = (message, exitCode) => {
240
+ try {
241
+ index.closeSessionHistoryIndex();
242
+ } catch (_err) {
243
+ // The inventory result/error is more useful to the parent than a
244
+ // best-effort checkpoint failure during worker teardown.
245
+ }
246
+ _sendWorkerMessage(message, exitCode);
247
+ };
79
248
 
80
249
  index.ensureSourceIndexed(source, { consistency: 'complete', force })
81
- .then(() => {
82
- if (process.send) {
83
- process.send({ type: 'done' });
84
- }
85
- process.exit(0);
86
- })
87
- .catch((err) => {
88
- if (process.send) {
89
- process.send({ type: 'error', message: err.message });
250
+ .then(() => finishWorker({ type: 'done' }, 0))
251
+ .catch((err) => finishWorker({ type: 'error', error: _serializeWorkerError(err) }, 1));
252
+ }
253
+
254
+ function _sendWorkerMessage(message, exitCode, send, exit = process.exit) {
255
+ let exited = false;
256
+ const finish = (code) => {
257
+ if (exited) return;
258
+ exited = true;
259
+ exit(code);
260
+ };
261
+
262
+ const sendImpl = send || (typeof process.send === 'function' ? process.send.bind(process) : null);
263
+ if (!sendImpl) {
264
+ finish(exitCode);
265
+ return;
266
+ }
267
+
268
+ try {
269
+ sendImpl(message, (callbackError) => {
270
+ if (callbackError) {
271
+ finish(exitCode || 1);
272
+ return;
90
273
  }
91
- process.exit(1);
274
+ finish(exitCode);
92
275
  });
276
+ } catch (_error) {
277
+ finish(exitCode || 1);
278
+ }
93
279
  }
94
280
 
95
281
  if (process.env.CC_TOOL_SESSION_HISTORY_WORKER === '1' || require.main === module) {
96
282
  attachWorkerHandler();
97
283
  }
98
284
 
99
- module.exports = { runInventoryWorker };
285
+ module.exports = {
286
+ runInventoryWorker,
287
+ attachWorkerHandler,
288
+ _test: {
289
+ serializeWorkerError: _serializeWorkerError,
290
+ deserializeWorkerError: _deserializeWorkerError,
291
+ sendWorkerMessage: _sendWorkerMessage,
292
+ createSessionHistoryIndex: (...args) => require('./session-history-index').createSessionHistoryIndex(...args)
293
+ }
294
+ };
@@ -1,6 +1,36 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('path');
4
+ const { getPlatformContext } = require('../platform-context');
5
+
6
+ function invokeSessionDriver(platform, capability, operation, args = [], runtime = null) {
7
+ const resolvedRuntime = runtime || getPlatformContext().runtime;
8
+ const driver = resolvedRuntime?.getDriver?.(platform, capability);
9
+ if (!driver || typeof driver[operation] !== 'function') {
10
+ const error = new Error(`平台 ${platform} 未声明 ${capability}.${operation} capability`);
11
+ error.status = 404;
12
+ error.code = 'unsupported';
13
+ error.platform = platform;
14
+ error.capability = capability;
15
+ error.operation = operation;
16
+ throw error;
17
+ }
18
+ const result = driver[operation](...args);
19
+ const unwrap = value => {
20
+ if (!value || typeof value !== 'object' || !value.status) return value;
21
+ if (value.status === 'ok') return value.data;
22
+ if (value.cause instanceof Error) throw value.cause;
23
+ const error = new Error(value.error || `平台 ${platform} 的 ${capability}.${operation} 失败`);
24
+ Object.assign(error, {
25
+ status: value.status,
26
+ platform: value.platform || platform,
27
+ capability: value.capability || capability,
28
+ operation: value.operation || operation
29
+ });
30
+ throw error;
31
+ };
32
+ return result && typeof result.then === 'function' ? result.then(unwrap) : unwrap(result);
33
+ }
4
34
 
5
35
  function totalSizeOf(sessions) {
6
36
  return sessions.reduce((sum, session) => sum + (Number(session.size) || 0), 0);
@@ -11,14 +41,30 @@ function getAliases() {
11
41
  return loadAliases();
12
42
  }
13
43
 
14
- async function buildClaudePayload(projectName, config, options = {}) {
15
- const {
16
- getSessionsForProject,
17
- parseRealProjectPath
18
- } = require('./sessions');
44
+ function indexedReadOptions(options = {}, config) {
45
+ const force = options.force === true;
46
+ return {
47
+ force,
48
+ ...(force ? { consistency: 'complete' } : {}),
49
+ ...(config ? { config } : {})
50
+ };
51
+ }
19
52
 
20
- const result = await getSessionsForProject(config, projectName, { force: options.force === true });
21
- const { fullPath, projectName: displayName } = parseRealProjectPath(projectName);
53
+ async function buildClaudePayload(projectName, config, options = {}, runtime = null) {
54
+ const result = await invokeSessionDriver(
55
+ 'claude',
56
+ 'sessions',
57
+ 'listSessions',
58
+ [projectName, indexedReadOptions(options, config)],
59
+ runtime
60
+ );
61
+ const { fullPath, projectName: displayName } = invokeSessionDriver(
62
+ 'claude',
63
+ 'sessions',
64
+ 'parseRealProjectPath',
65
+ [projectName],
66
+ runtime
67
+ );
22
68
 
23
69
  return {
24
70
  sessions: result.sessions,
@@ -32,9 +78,15 @@ async function buildClaudePayload(projectName, config, options = {}) {
32
78
  };
33
79
  }
34
80
 
35
- async function buildCodexPayload(projectName, options = {}) {
36
- const { getSessionsByProject } = require('./codex-sessions');
37
- const sessions = await getSessionsByProject(projectName, { force: options.force === true });
81
+ async function buildCodexPayload(projectName, options = {}, runtime = null) {
82
+ const sessions = await invokeSessionDriver(
83
+ 'codex',
84
+ 'sessions',
85
+ 'listSessions',
86
+ [projectName, indexedReadOptions(options)],
87
+ runtime
88
+ );
89
+ const projectFullPath = sessions.find(session => session.projectFullPath)?.projectFullPath || projectName;
38
90
 
39
91
  return {
40
92
  sessions,
@@ -42,18 +94,31 @@ async function buildCodexPayload(projectName, options = {}) {
42
94
  aliases: getAliases(),
43
95
  projectInfo: {
44
96
  name: projectName,
45
- fullPath: projectName,
46
- path: projectName,
97
+ fullPath: projectFullPath,
98
+ path: projectFullPath,
47
99
  displayName: projectName
48
100
  }
49
101
  };
50
102
  }
51
103
 
52
- async function buildGeminiPayload(projectHash, options = {}) {
53
- const { getProjectSessions, getProjectPath } = require('./gemini-sessions');
54
- const sessions = await getProjectSessions(projectHash, { force: options.force === true });
55
- const realPath = getProjectPath(projectHash, { force: options.force === true });
56
- const displayName = realPath ? path.basename(realPath) : `Project ${projectHash.substring(0, 8)}`;
104
+ async function buildGeminiPayload(projectHash, options = {}, runtime = null) {
105
+ const sessions = await invokeSessionDriver(
106
+ 'gemini',
107
+ 'sessions',
108
+ 'listSessions',
109
+ [projectHash, indexedReadOptions(options)],
110
+ runtime
111
+ );
112
+ const realPath = await invokeSessionDriver(
113
+ 'gemini',
114
+ 'sessions',
115
+ 'getProjectPath',
116
+ [projectHash, indexedReadOptions(options)],
117
+ runtime
118
+ );
119
+ const indexedPath = sessions.find(session => session.projectRoot || session.projectFullPath);
120
+ const fullPath = realPath || indexedPath?.projectRoot || indexedPath?.projectFullPath || projectHash;
121
+ const displayName = fullPath !== projectHash ? path.basename(fullPath) : `Project ${projectHash.substring(0, 8)}`;
57
122
 
58
123
  return {
59
124
  sessions,
@@ -61,19 +126,33 @@ async function buildGeminiPayload(projectHash, options = {}) {
61
126
  aliases: getAliases(),
62
127
  projectInfo: {
63
128
  name: projectHash,
64
- fullPath: realPath || projectHash,
65
- path: realPath || projectHash,
129
+ fullPath,
130
+ path: fullPath,
66
131
  displayName
67
132
  }
68
133
  };
69
134
  }
70
135
 
71
- function buildOpenCodePayload(projectName, options = {}) {
72
- const { getSessionsByProject, getProjects } = require('./opencode-sessions');
73
- const sessions = getSessionsByProject(projectName, { force: options.force === true });
136
+ async function buildOpenCodePayload(projectName, options = {}, runtime = null) {
137
+ const sessions = await invokeSessionDriver(
138
+ 'opencode',
139
+ 'sessions',
140
+ 'listSessions',
141
+ [projectName, indexedReadOptions(options)],
142
+ runtime
143
+ );
144
+ const projects = await invokeSessionDriver(
145
+ 'opencode',
146
+ 'sessions',
147
+ 'getProjects',
148
+ [indexedReadOptions(options)],
149
+ runtime
150
+ );
74
151
  const firstDirectory = sessions.find(session => session.directory)?.directory;
75
- const project = firstDirectory ? null : getProjects({ force: options.force === true }).find(p => p.name === projectName);
76
- const fullPath = firstDirectory || project?.fullPath || projectName;
152
+ const project = projects.find(p => p.name === projectName) || null;
153
+ const projectPath = [project?.fullPath, project?.path]
154
+ .find(value => value && value !== '/');
155
+ const fullPath = projectPath || firstDirectory || project?.fullPath || project?.path || projectName;
77
156
 
78
157
  return {
79
158
  sessions,
@@ -88,13 +167,24 @@ function buildOpenCodePayload(projectName, options = {}) {
88
167
  };
89
168
  }
90
169
 
91
- async function buildOmpPayload(projectName, options = {}) {
92
- const { getProjects, getSessionsByProject } = require('./omp-sessions');
93
- const sessions = await getSessionsByProject(projectName, { force: options.force === true });
170
+ async function buildOmpPayload(projectName, options = {}, runtime = null) {
171
+ const sessions = await invokeSessionDriver(
172
+ 'omp',
173
+ 'sessions',
174
+ 'listSessions',
175
+ [projectName, indexedReadOptions(options)],
176
+ runtime
177
+ );
94
178
  const firstDirectory = sessions.find(session => session.directory)?.directory;
95
179
  let project = null;
96
180
  try {
97
- project = (await getProjects({ force: options.force === true })).find(p => p.name === projectName) || null;
181
+ project = (await invokeSessionDriver(
182
+ 'omp',
183
+ 'sessions',
184
+ 'getProjects',
185
+ [indexedReadOptions(options)],
186
+ runtime
187
+ )).find(p => p.name === projectName) || null;
98
188
  } catch {
99
189
  project = null;
100
190
  }
@@ -113,19 +203,19 @@ async function buildOmpPayload(projectName, options = {}) {
113
203
  };
114
204
  }
115
205
 
116
- async function buildPayload({ source, projectName, config, options }) {
206
+ async function buildPayload({ source, projectName, config, options, runtime }) {
117
207
  const snapshotOptions = options || {};
118
208
  switch (source) {
119
209
  case 'claude':
120
- return buildClaudePayload(projectName, config || {}, snapshotOptions);
210
+ return buildClaudePayload(projectName, config || {}, snapshotOptions, runtime);
121
211
  case 'codex':
122
- return buildCodexPayload(projectName, snapshotOptions);
212
+ return buildCodexPayload(projectName, snapshotOptions, runtime);
123
213
  case 'gemini':
124
- return buildGeminiPayload(projectName, snapshotOptions);
214
+ return buildGeminiPayload(projectName, snapshotOptions, runtime);
125
215
  case 'opencode':
126
- return buildOpenCodePayload(projectName, snapshotOptions);
216
+ return buildOpenCodePayload(projectName, snapshotOptions, runtime);
127
217
  case 'omp':
128
- return buildOmpPayload(projectName, snapshotOptions);
218
+ return buildOmpPayload(projectName, snapshotOptions, runtime);
129
219
  default:
130
220
  throw new Error(`Unsupported session snapshot source: ${source}`);
131
221
  }
@@ -4,7 +4,8 @@ const path = require('path');
4
4
  const { fork } = require('child_process');
5
5
  const {
6
6
  getSnapshot,
7
- invalidateSnapshot
7
+ invalidateSnapshot,
8
+ invalidateDashboardSourceSnapshot
8
9
  } = require('./snapshot-cache');
9
10
 
10
11
  const SESSION_SNAPSHOT_TTL_MS = 60 * 1000;
@@ -122,14 +123,15 @@ async function getSessionListSnapshot(source, projectName, {
122
123
  deferMs: SESSION_SNAPSHOT_DEFER_MS
123
124
  });
124
125
  }
125
-
126
126
  function invalidateSessionSnapshots(source, projectName = null) {
127
127
  if (!source) return;
128
128
  if (projectName) {
129
129
  invalidateSnapshot(sessionListKey(source, projectName));
130
+ invalidateDashboardSourceSnapshot(source);
130
131
  return;
131
132
  }
132
133
  invalidateSnapshot(`sessions:list:${source}:`);
134
+ invalidateDashboardSourceSnapshot(source);
133
135
  }
134
136
 
135
137
  module.exports = {