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,30 +1,55 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const BaseChannelService = require('./base/base-channel-service');
4
- const { isProxyConfig } = require('./settings-manager');
5
- const { PATHS, NATIVE_PATHS } = require('../../config/paths');
6
- const { clearNativeOAuth } = require('./native-oauth-adapters');
7
- const { isWindowsLikePlatform } = require('../../utils/home-dir');
8
- const { normalizeGatewaySourceType } = require('./base/proxy-utils');
3
+ const BaseChannelService = require('../../../shared/base-channel-service');
4
+ const { isProxyConfig } = require('./native-config-implementation');
5
+ const { PATHS, NATIVE_PATHS } = require('../../../config/paths');
6
+ const { clearNativeOAuth, readNativeOAuth, clearClaudeChannelConfig } = require('../../native-oauth-adapters');
7
+ const { isWindowsLikePlatform } = require('../../../utils/home-dir');
8
+ const { normalizeGatewaySourceType } = require('../../../shared/proxy-utils');
9
9
  const {
10
10
  createSkippedResult,
11
11
  isLocalProxyBaseUrl,
12
12
  resolveExistingActiveChannel,
13
13
  upsertSyncedChannels
14
- } = require('./channel-sync-utils');
14
+ } = require('../../../server/services/channel-sync-utils');
15
+
16
+ let configuredNative = NATIVE_PATHS.claude;
17
+ let configuredState = {
18
+ channels: PATHS.channels?.claude,
19
+ activeChannel: PATHS.activeChannel?.claude
20
+ || path.join(path.dirname(PATHS.channels?.claude || 'active-channel.json'), 'active-channel.json')
21
+ };
22
+
23
+ function configure({ pathContext } = {}) {
24
+ const custom = pathContext?.customized === true;
25
+ configuredNative = custom && pathContext.native?.settings
26
+ ? { ...NATIVE_PATHS.claude, ...pathContext.native }
27
+ : NATIVE_PATHS.claude;
28
+ configuredState = {
29
+ channels: custom ? (pathContext.state?.channels || PATHS.channels?.claude) : PATHS.channels?.claude,
30
+ activeChannel: custom
31
+ ? (pathContext.state?.activeChannel || PATHS.activeChannel?.claude)
32
+ : PATHS.activeChannel?.claude
33
+ };
34
+ if (!configuredState.activeChannel) {
35
+ configuredState.activeChannel = path.join(path.dirname(configuredState.channels || 'active-channel.json'), 'active-channel.json');
36
+ }
37
+ require('../../native-oauth-adapters').configure?.({ pathContext });
38
+ if (service) service.channelsFilePath = configuredState.channels;
39
+ }
15
40
 
16
41
  // ── Claude 特有工具函数 ──
17
42
 
18
43
  function getActiveChannelIdPath() {
19
- const dir = path.dirname(PATHS.activeChannel.claude);
44
+ const dir = path.dirname(configuredState.activeChannel);
20
45
  if (!fs.existsSync(dir)) {
21
46
  fs.mkdirSync(dir, { recursive: true });
22
47
  }
23
- return PATHS.activeChannel.claude;
48
+ return configuredState.activeChannel;
24
49
  }
25
50
 
26
51
  function getClaudeSettingsPath() {
27
- return NATIVE_PATHS.claude.settings;
52
+ return configuredNative.settings;
28
53
  }
29
54
 
30
55
  function saveActiveChannelId(channelId) {
@@ -129,6 +154,63 @@ function updateClaudeSettingsWithModelConfig(channel) {
129
154
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
130
155
  }
131
156
 
157
+ function createClaudeOAuthError(message, code, statusCode) {
158
+ const error = new Error(message);
159
+ error.code = code;
160
+ error.statusCode = statusCode;
161
+ return error;
162
+ }
163
+
164
+ function isClaudeProxyRunning() {
165
+ if (isProxyConfig()) {
166
+ return true;
167
+ }
168
+ try {
169
+ return require('./proxy-implementation').getProxyStatus().running === true;
170
+ } catch {
171
+ return false;
172
+ }
173
+ }
174
+
175
+
176
+ function assertClaudeOAuthIsNativeOnly() {
177
+ if (isClaudeProxyRunning()) {
178
+ throw createClaudeOAuthError(
179
+ 'Claude OAuth channels are native-only',
180
+ 'claude_oauth_proxy_unsupported',
181
+ 409
182
+ );
183
+ }
184
+ }
185
+
186
+ function assertNativeClaudeOAuthAvailable() {
187
+ if (!readNativeOAuth('claude')) {
188
+ throw createClaudeOAuthError(
189
+ 'Claude native OAuth credential is unavailable',
190
+ 'claude_oauth_credential_unavailable',
191
+ 422
192
+ );
193
+ }
194
+ }
195
+
196
+ function applyNativeClaudeOAuth() {
197
+ assertClaudeOAuthIsNativeOnly();
198
+ assertNativeClaudeOAuthAvailable();
199
+ clearClaudeChannelConfig();
200
+ }
201
+
202
+ function validateClaudeOAuthMutation(channel, operation) {
203
+ if (channel?.authMode !== 'oauth') {
204
+ return;
205
+ }
206
+ if (operation !== 'apply' && channel.enabled === false) {
207
+ return;
208
+ }
209
+ assertClaudeOAuthIsNativeOnly();
210
+ assertNativeClaudeOAuthAvailable();
211
+ }
212
+
213
+
132
214
  function updateClaudeSettings(baseUrl, apiKey) {
133
215
  const settingsPath = getClaudeSettingsPath();
134
216
  fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
@@ -194,15 +276,21 @@ class ClaudeChannelService extends BaseChannelService {
194
276
  constructor() {
195
277
  super({
196
278
  platform: 'claude',
197
- channelsFilePath: PATHS.channels.claude,
279
+ channelsFilePath: configuredState.channels,
198
280
  defaultGatewaySource: 'claude',
199
- isProxyRunning: () => isProxyConfig(),
281
+ isProxyRunning: () => isClaudeProxyRunning(),
282
+ oauthChannelPolicy: 'single-enabled',
200
283
  });
201
284
  // Claude 特有:文件监听缓存
202
285
  this._cache = null;
203
286
  this._cacheInitialized = false;
287
+ this._watchRegistered = false;
288
+ }
289
+ _validateBeforeChannelMutation(channel, _allChannels, context = {}) {
290
+ validateClaudeOAuthMutation(channel, context.operation);
204
291
  }
205
292
 
293
+
206
294
  _generateId() {
207
295
  return `channel-${Date.now()}`;
208
296
  }
@@ -221,25 +309,21 @@ class ClaudeChannelService extends BaseChannelService {
221
309
  return normalized;
222
310
  }
223
311
 
224
- // Claude 使用缓存 + fs.watchFile
225
312
  loadChannels() {
226
- if (this._cacheInitialized && this._cache) {
227
- return { channels: this._cache.channels.map(ch => this._applyDefaults(ch)) };
228
- }
229
-
230
313
  const data = super.loadChannels();
231
314
  this._cache = data;
232
315
  this._cacheInitialized = true;
233
316
 
234
- // 设置文件监听
235
- try {
236
- fs.watchFile(this.channelsFilePath, { interval: 2000 }, () => {
237
- try {
317
+ if (!this._watchRegistered) {
318
+ try {
319
+ fs.watchFile(this.channelsFilePath, { interval: 2000 }, () => {
320
+ this.invalidate();
238
321
  this._cache = null;
239
322
  this._cacheInitialized = false;
240
- } catch (_) {}
241
- });
242
- } catch (_) {}
323
+ });
324
+ this._watchRegistered = true;
325
+ } catch (_) {}
326
+ }
243
327
 
244
328
  return data;
245
329
  }
@@ -251,13 +335,13 @@ class ClaudeChannelService extends BaseChannelService {
251
335
  }
252
336
 
253
337
  _onAfterCreate(channel, _allChannels) {
254
- if (!isProxyConfig() && channel.enabled !== false && !isOpenAiCompatibleGateway(channel)) {
338
+ if (!isClaudeProxyRunning() && channel.enabled !== false && !isOpenAiCompatibleGateway(channel)) {
255
339
  this._applyToNativeSettings(channel);
256
340
  }
257
341
  }
258
342
 
259
343
  _onAfterUpdate(oldChannel, nextChannel, allChannels) {
260
- if (isProxyConfig()) {
344
+ if (isClaudeProxyRunning()) {
261
345
  return;
262
346
  }
263
347
 
@@ -279,7 +363,7 @@ class ClaudeChannelService extends BaseChannelService {
279
363
  }
280
364
 
281
365
  _onAfterDelete(_channel, allChannels) {
282
- if (isProxyConfig()) {
366
+ if (isClaudeProxyRunning()) {
283
367
  return;
284
368
  }
285
369
 
@@ -301,11 +385,14 @@ class ClaudeChannelService extends BaseChannelService {
301
385
  error.statusCode = 400;
302
386
  throw error;
303
387
  }
304
-
305
388
  return super.applyChannelToSettings(channelId);
306
389
  }
307
390
 
308
391
  _applyToNativeSettings(channel) {
392
+ if (channel.authMode === 'oauth') {
393
+ applyNativeClaudeOAuth(channel);
394
+ return;
395
+ }
309
396
  updateClaudeSettingsWithModelConfig(channel);
310
397
  }
311
398
 
@@ -318,13 +405,22 @@ class ClaudeChannelService extends BaseChannelService {
318
405
 
319
406
  const service = new ClaudeChannelService();
320
407
 
408
+
409
+ function getClaudeProxyExcludedChannelIds(channels = null) {
410
+ const candidates = Array.isArray(channels) ? channels : service.getEnabledChannels();
411
+ return [...new Set(
412
+ candidates
413
+ .filter(channel => channel?.enabled !== false && channel?.authMode === 'oauth')
414
+ .map(channel => channel.id)
415
+ .filter(Boolean)
416
+ )];
417
+ }
321
418
  function getAllChannels() {
322
419
  const data = service.loadChannels();
323
420
  return data.channels;
324
421
  }
325
422
 
326
- function getCurrentChannel() {
327
- const channels = getAllChannels();
423
+ function getCurrentChannel(channels = getAllChannels()) {
328
424
  const activeId = loadActiveChannelId();
329
425
  if (activeId) {
330
426
  const active = channels.find(ch => ch.id === activeId);
@@ -333,8 +429,8 @@ function getCurrentChannel() {
333
429
  return channels.find(ch => ch.enabled !== false) || channels[0] || null;
334
430
  }
335
431
 
336
- function getCurrentSettings() {
337
- const channel = getCurrentChannel();
432
+ function getCurrentSettings(channels) {
433
+ const channel = getCurrentChannel(channels);
338
434
  if (!channel) return null;
339
435
  return {
340
436
  baseUrl: channel.baseUrl,
@@ -358,7 +454,7 @@ function readClaudeNativeSettings() {
358
454
 
359
455
  function readClaudeNativeOAuth() {
360
456
  try {
361
- const adapters = require('./native-oauth-adapters');
457
+ const adapters = require('../../native-oauth-adapters');
362
458
  return typeof adapters.readNativeOAuth === 'function'
363
459
  ? adapters.readNativeOAuth('claude')
364
460
  : null;
@@ -498,11 +594,13 @@ function disableAllChannels() {
498
594
  }
499
595
 
500
596
  module.exports = {
597
+ configure,
501
598
  getAllChannels,
502
599
  getCurrentChannel,
503
600
  getCurrentSettings,
504
601
  createChannel,
505
602
  updateChannel,
603
+ getClaudeProxyExcludedChannelIds,
506
604
  markChannelAsRecentlyUsed,
507
605
  deleteChannel,
508
606
  applyChannelToSettings,
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const { createChannelDriver } = require('../../../shared/channel-driver');
4
+
5
+ function createDriver(context = {}) {
6
+ const driver = createChannelDriver({
7
+ ...context,
8
+ platform: 'claude',
9
+ servicePath: './claude/channels-implementation',
10
+ localServicePath: '../platforms/drivers/claude/channels-implementation',
11
+ listMethod: 'getAllChannels',
12
+ syncMethod: 'syncCurrentClaudeChannel',
13
+ createArgs: (input, rest) => typeof input === 'object'
14
+ ? (() => {
15
+ const { name, baseUrl, apiKey, websiteUrl, extra, ...channelExtra } = input;
16
+ return [name, baseUrl, apiKey, websiteUrl, { ...channelExtra, ...extra }];
17
+ })()
18
+ : [input, ...rest],
19
+ cliMetadata: { supportsCliCreate: true, supportsCliToggle: true, defaultPort: 20088 },
20
+ dashboardChannelShape: 'array'
21
+ });
22
+ const callLegacy = (name, args) => driver._service()[name](...args);
23
+ const auth = require('../../channel-auth-service');
24
+ driver.getAuth = context => auth.getChannelAuth('claude', { channelId: context?.params?.channelId || context?.query?.channelId || '' });
25
+ driver.syncLocalAuth = context => auth.syncLocalChannelAuth('claude', { channelId: context?.body?.channelId || context?.params?.channelId || context?.query?.channelId || '' });
26
+ driver.getAuthQuota = context => auth.fetchChannelAuthQuota('claude', context?.params?.channelId, { refresh: context?.query?.refresh === 'true' });
27
+ for (const name of [
28
+ 'getAllChannels', 'getCurrentChannel', 'getCurrentSettings', 'createChannel',
29
+ 'updateChannel', 'markChannelAsRecentlyUsed', 'deleteChannel',
30
+ 'applyChannelToSettings', 'getBestChannelForRestore', 'updateClaudeSettings',
31
+ 'updateClaudeSettingsWithModelConfig', 'extractApiKeyFromHelper',
32
+ 'syncCurrentClaudeChannel'
33
+ ]) {
34
+ driver[name] = (...args) => callLegacy(name, args);
35
+ }
36
+ return driver;
37
+ }
38
+
39
+ module.exports = { createDriver };
@@ -15,7 +15,7 @@
15
15
 
16
16
  const fs = require('fs');
17
17
  const path = require('path');
18
- const { HOME_DIR, NATIVE_PATHS } = require('../../config/paths');
18
+ const { HOME_DIR, NATIVE_PATHS } = require('../../../config/paths');
19
19
 
20
20
  // 全局配置目录
21
21
  const GLOBAL_CONFIG_DIR = NATIVE_PATHS.claude.dir
@@ -76,11 +76,35 @@ function copyDirRecursive(src, dest) {
76
76
  * 配置同步服务类
77
77
  */
78
78
  class ConfigSyncService {
79
- constructor() {
79
+ constructor({ registry = null } = {}) {
80
+ this.registry = registry;
80
81
  this.globalConfigDir = GLOBAL_CONFIG_DIR;
82
+ this.globalConfigDirs = {
83
+ skills: path.join(this.globalConfigDir, CONFIG_TYPES.skills.globalDir),
84
+ agents: path.join(this.globalConfigDir, CONFIG_TYPES.agents.globalDir),
85
+ commands: path.join(this.globalConfigDir, CONFIG_TYPES.commands.globalDir)
86
+ };
87
+
88
+ try {
89
+ const pathContext = this.registry?.resolvePathContext?.('claude');
90
+ if (pathContext?.customized) {
91
+ this.globalConfigDir = pathContext.native?.dir || this.globalConfigDir;
92
+ this.globalConfigDirs = {
93
+ skills: pathContext.native?.skills || path.join(this.globalConfigDir, CONFIG_TYPES.skills.globalDir),
94
+ agents: pathContext.native?.agents || path.join(this.globalConfigDir, CONFIG_TYPES.agents.globalDir),
95
+ commands: pathContext.native?.commands || path.join(this.globalConfigDir, CONFIG_TYPES.commands.globalDir)
96
+ };
97
+ }
98
+ } catch (_) {
99
+ // Keep legacy defaults when an injected registry cannot resolve paths.
100
+ }
81
101
  ensureDir(this.globalConfigDir);
82
102
  }
83
103
 
104
+ _getGlobalConfigDir(type) {
105
+ return this.globalConfigDirs[type] || path.join(this.globalConfigDir, CONFIG_TYPES[type]?.globalDir || type);
106
+ }
107
+
84
108
  /**
85
109
  * 获取可用的配置项列表
86
110
  * @param {string} source - 'global' 或 'workspace'
@@ -98,7 +122,7 @@ class ConfigSyncService {
98
122
  let dir;
99
123
 
100
124
  if (source === 'global') {
101
- dir = path.join(this.globalConfigDir, config.globalDir);
125
+ dir = this._getGlobalConfigDir(type);
102
126
  } else if (source === 'workspace' && projectPath) {
103
127
  if (!config.projectDir) {
104
128
  // skills 不支持项目级
@@ -363,7 +387,7 @@ class ConfigSyncService {
363
387
  let baseDir;
364
388
 
365
389
  if (target === 'global') {
366
- baseDir = path.join(this.globalConfigDir, config.globalDir);
390
+ baseDir = this._getGlobalConfigDir(type);
367
391
  } else {
368
392
  baseDir = path.join(projectPath, '.claude', config.projectDir);
369
393
  }
@@ -463,7 +487,7 @@ class ConfigSyncService {
463
487
  let baseDir;
464
488
 
465
489
  if (source === 'global') {
466
- baseDir = path.join(this.globalConfigDir, config.globalDir);
490
+ baseDir = this._getGlobalConfigDir(type);
467
491
  } else {
468
492
  baseDir = path.join(projectPath, '.claude', config.projectDir);
469
493
  }
@@ -47,8 +47,8 @@ function ensureProjectClaudeDir(projectPath) {
47
47
  * @param {Array} projects - 项目列表
48
48
  * @returns {Object} 汇总结果
49
49
  */
50
- function healthCheckAllProjects(projects) {
51
- const results = [];
50
+ function healthCheckAllProjects(projects, { includeResults = true } = {}) {
51
+ const results = includeResults ? [] : null;
52
52
  let checkedCount = 0;
53
53
  let createdCount = 0;
54
54
  let errorCount = 0;
@@ -57,7 +57,7 @@ function healthCheckAllProjects(projects) {
57
57
  if (!project.fullPath) continue;
58
58
 
59
59
  const result = ensureProjectClaudeDir(project.fullPath);
60
- results.push(result);
60
+ if (results) results.push(result);
61
61
  checkedCount++;
62
62
 
63
63
  if (result.created) {
@@ -75,7 +75,7 @@ function healthCheckAllProjects(projects) {
75
75
  errors: errorCount,
76
76
  healthy: checkedCount - errorCount
77
77
  },
78
- results
78
+ ...(results ? { results } : {})
79
79
  };
80
80
  }
81
81
 
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const { healthCheckAllProjects } = require('./health-check');
4
+
5
+ function createDriver(context = {}) {
6
+ return {
7
+ platform: context.platform,
8
+ capability: 'health',
9
+ async healthCheck({ detail = true } = {}) {
10
+ const projects = context.sessionHistoryIndex
11
+ ? await context.sessionHistoryIndex.listProjects(context.platform, { consistency: 'stale-ok' })
12
+ : [];
13
+ return {
14
+ success: true,
15
+ timestamp: new Date().toISOString(),
16
+ ...healthCheckAllProjects(projects, { includeResults: detail })
17
+ };
18
+ }
19
+ };
20
+ }
21
+
22
+ module.exports = { createDriver };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ const { createMcpDriver } = require('../../../shared/driver-factories/mcp');
4
+
5
+ function createDriver(context = {}) {
6
+ return createMcpDriver({ ...context, platform: 'claude' });
7
+ }
8
+
9
+ module.exports = { createDriver };
@@ -1,6 +1,14 @@
1
1
  const fs = require('fs');
2
- const { NATIVE_PATHS } = require('../../config/paths');
3
- const { isWindowsLikePlatform } = require('../../utils/home-dir');
2
+ const { NATIVE_PATHS } = require('../../../config/paths');
3
+ const { isWindowsLikePlatform } = require('../../../utils/home-dir');
4
+ const DEFAULT_NATIVE_PATHS = NATIVE_PATHS.claude;
5
+ let nativePaths = DEFAULT_NATIVE_PATHS;
6
+
7
+ function configure({ pathContext } = {}) {
8
+ nativePaths = pathContext?.customized && pathContext.native?.settings
9
+ ? { ...DEFAULT_NATIVE_PATHS, ...pathContext.native }
10
+ : DEFAULT_NATIVE_PATHS;
11
+ }
4
12
 
5
13
  function buildEchoCommand(value) {
6
14
  if (isWindowsLikePlatform(process.platform, process.env)) {
@@ -11,12 +19,12 @@ function buildEchoCommand(value) {
11
19
 
12
20
  // Claude Code 配置文件路径
13
21
  function getSettingsPath() {
14
- return NATIVE_PATHS.claude.settings;
22
+ return nativePaths.settings;
15
23
  }
16
24
 
17
25
  // 备份文件路径
18
26
  function getBackupPath() {
19
- return NATIVE_PATHS.claude.settingsBackup;
27
+ return nativePaths.settingsBackup;
20
28
  }
21
29
 
22
30
  // 检查配置文件是否存在
@@ -168,6 +176,7 @@ function getCurrentProxyPort() {
168
176
  }
169
177
 
170
178
  module.exports = {
179
+ configure,
171
180
  getSettingsPath,
172
181
  getBackupPath,
173
182
  settingsExists,
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const implementation = require('./native-config-implementation');
5
+ const { PATHS } = require('../../../config/paths');
6
+ const { createNativeSnapshotMethods } = require('../native-config-snapshot');
7
+
8
+ function createDriver({ requireImpl, ...context } = {}) {
9
+ const configuredPaths = context.pathContext?.native;
10
+ const currentNativePaths = context.pathContext?.customized && configuredPaths?.settings
11
+ ? configuredPaths
12
+ : require('../../../config/paths').NATIVE_PATHS.claude;
13
+ const settings = requireImpl
14
+ ? requireImpl('./claude/native-config-implementation')
15
+ : implementation;
16
+ settings.configure?.({ pathContext: context.pathContext });
17
+ const snapshotMethods = createNativeSnapshotMethods({
18
+ settings: { path: currentNativePaths.settings, format: 'json' }
19
+ }, { platform: 'claude', runtime: context.runtime });
20
+ return {
21
+ platform: 'claude',
22
+ capability: 'nativeConfig',
23
+ ...context,
24
+ ...settings,
25
+ ...snapshotMethods,
26
+ clearNativeOAuth: () => {
27
+ const adapters = require('../../native-oauth-adapters');
28
+ adapters.configure?.(context);
29
+ return adapters.clearNativeOAuth('claude');
30
+ },
31
+ preserveNativeOAuthOnProxyStart: true,
32
+ restoreNativeSettingsOnProxyStop: true,
33
+ clearActiveChannelMarker() {
34
+ try {
35
+ const markerPath = context.pathContext?.customized
36
+ ? (context.pathContext.state?.activeChannel || PATHS.activeChannel.claude)
37
+ : PATHS.activeChannel.claude;
38
+ fs.unlinkSync(markerPath);
39
+ } catch (error) {
40
+ if (error.code !== 'ENOENT') throw error;
41
+ }
42
+ }
43
+ };
44
+ }
45
+
46
+ module.exports = { createDriver };
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { NATIVE_PATHS } = require('../../../config/paths');
6
+ const {
7
+ normalizeUsage,
8
+ normalizeCost,
9
+ usageFieldPaths,
10
+ createSelectiveJsonLineParser,
11
+ walkFiles,
12
+ createIncrementalJsonlCursor
13
+ } = require('../native-log-utils');
14
+ const { calculateUsageCost } = require('../../../server/services/usage-log-utils');
15
+
16
+ const CLAUDE_SELECTED_FIELDS = [
17
+ 'type', 'role', 'uuid', 'id', 'model', 'timestamp', 'provider', 'cost', 'channelId', 'channel',
18
+ 'message.role', 'message.id', 'message.uuid', 'message.model', 'message.timestamp',
19
+ 'message.provider', 'message.cost', 'message.channelId', 'message.channel',
20
+ ...usageFieldPaths('usage'),
21
+ ...usageFieldPaths('message.usage')
22
+ ];
23
+
24
+ function createDriver({ nativeRoot, pathContext, fsImpl = fs } = {}) {
25
+ const resolvedNativeRoot = pathContext?.customized
26
+ ? (pathContext.native?.projects || nativeRoot || NATIVE_PATHS.claude.projects)
27
+ : (nativeRoot || NATIVE_PATHS.claude.projects);
28
+ return {
29
+ platform: 'claude',
30
+ capability: 'nativeLogs',
31
+ createNativeLogCursor({ fs: cursorFs = fsImpl, skipInitialParse = false, onDiagnostic } = {}) {
32
+ const scanFiles = () => walkFiles(resolvedNativeRoot, name => name.endsWith('.jsonl') && !name.startsWith('agent-'), cursorFs);
33
+ const parseLine = (filePath, record) => {
34
+ const message = record.message && typeof record.message === 'object' ? record.message : {};
35
+ const role = record.role || message.role || (record.type === 'assistant' ? 'assistant' : null);
36
+ if (role !== 'assistant') return null;
37
+ const usage = record.usage || message.usage;
38
+ const messageId = record.uuid || record.id || message.id;
39
+ if (!usage || typeof usage !== 'object' || !messageId) return null;
40
+ const tokens = normalizeUsage(usage);
41
+ const model = record.model || message.model || '';
42
+ return {
43
+ id: `${path.basename(filePath)}:${messageId}`,
44
+ source: 'claude',
45
+ sessionId: path.basename(filePath, '.jsonl'),
46
+ timestamp: record.timestamp || message.timestamp,
47
+ provider: record.provider || message.provider || '',
48
+ model,
49
+ tokens,
50
+ cost: normalizeCost(record.cost ?? message.cost ?? usage.cost)
51
+ || calculateUsageCost('claude', model, tokens),
52
+ channelId: record.channelId || message.channelId,
53
+ channel: record.channel || message.channel
54
+ };
55
+ };
56
+ return createIncrementalJsonlCursor({
57
+ scanFiles,
58
+ parseLine,
59
+ fsImpl: cursorFs,
60
+ skipInitialParse,
61
+ createLongLineParser: () => createSelectiveJsonLineParser(CLAUDE_SELECTED_FIELDS),
62
+ onDiagnostic,
63
+ onError: (error, filePath) => {
64
+ console.warn('[Claude Native Logs] Failed to read changed usage events:', filePath, error.message);
65
+ }
66
+ });
67
+ },
68
+ createCursor(options) { return this.createNativeLogCursor(options); }
69
+ };
70
+ }
71
+
72
+ module.exports = { createDriver };