coding-tool-x 3.8.4 → 3.8.5

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-BG6P3DX-.js +1 -0
  4. package/dist/web/assets/AgentsDrawer-Pw2k-ZAa.css +1 -0
  5. package/dist/web/assets/Analytics--z_FmL5P.js +1 -0
  6. package/dist/web/assets/Analytics-CyHhR126.css +1 -0
  7. package/dist/web/assets/AssetPathField-CrJtRKHy.js +1 -0
  8. package/dist/web/assets/ChatHistoryDrawer-B2qBQs9L.css +1 -0
  9. package/dist/web/assets/ChatHistoryDrawer-BiuEryJj.js +1 -0
  10. package/dist/web/assets/CollapseItem-BAYEsL_Q.js +1 -0
  11. package/dist/web/assets/CommandsDrawer-BZJxlPvV.css +1 -0
  12. package/dist/web/assets/CommandsDrawer-YJ-U7BXN.js +1 -0
  13. package/dist/web/assets/ConfigExportDrawer-Ce_hAknW.js +1 -0
  14. package/dist/web/assets/ConfigExportDrawer-dwruRKWr.css +1 -0
  15. package/dist/web/assets/ConfigTemplates-Bvr1NN6K.js +1 -0
  16. package/dist/web/assets/ConfigTemplatesDrawer-BfDi8yO3.css +1 -0
  17. package/dist/web/assets/ConfigTemplatesDrawer-BjIeHfF-.js +1 -0
  18. package/dist/web/assets/ConfigTemplatesPanel-AV00tm_D.js +1 -0
  19. package/dist/web/assets/ConfigTemplatesPanel-CWyPtk67.css +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-Cz95o4CD.js +1 -0
  24. package/dist/web/assets/GatewayConvertDrawer-CuNlf7AC.css +1 -0
  25. package/dist/web/assets/GatewayConvertDrawer-DLlbMz27.js +1 -0
  26. package/dist/web/assets/Home-CSuFuJ9Y.css +1 -0
  27. package/dist/web/assets/Home-D7CCOFQC.js +1 -0
  28. package/dist/web/assets/MarkdownEditor-qfVgSre_.css +1 -0
  29. package/dist/web/assets/MarkdownEditor-rEZ-c72L.js +1 -0
  30. package/dist/web/assets/McpDrawer-C0dnsZhQ.css +1 -0
  31. package/dist/web/assets/McpDrawer-DfoCyxU2.js +1 -0
  32. package/dist/web/assets/McpFormDrawer-BRbDcawn.css +1 -0
  33. package/dist/web/assets/McpFormDrawer-SKu8HNUR.js +1 -0
  34. package/dist/web/assets/PluginManager-BbeK-3rV.js +1 -0
  35. package/dist/web/assets/PluginsDrawer-CWVJ7yjS.js +1 -0
  36. package/dist/web/assets/PluginsDrawer-DM3QjprE.css +1 -0
  37. package/dist/web/assets/PluginsPanel-Cm2N3StG.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-CsjnsNPv.js +1 -0
  41. package/dist/web/assets/PromptsDrawer-BIgiYCEQ.css +1 -0
  42. package/dist/web/assets/PromptsDrawer-EGd3djFa.js +1 -0
  43. package/dist/web/assets/RecentSessionsDrawer-CKFsOYDM.css +1 -0
  44. package/dist/web/assets/RecentSessionsDrawer-D1vtoLAs.js +1 -0
  45. package/dist/web/assets/SessionCard-BgLg49U3.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-TRiTklWk.js +1 -0
  49. package/dist/web/assets/SettingsDrawer-d5liXjHq.css +1 -0
  50. package/dist/web/assets/SettingsDrawer-rz2WejGY.js +1 -0
  51. package/dist/web/assets/SkillManager-BTjTUbHq.js +1 -0
  52. package/dist/web/assets/SkillManager-C0GCT2Kb.css +1 -0
  53. package/dist/web/assets/SkillsDrawer-BCNme-aJ.css +1 -0
  54. package/dist/web/assets/SkillsDrawer-pN0hbkK3.js +1 -0
  55. package/dist/web/assets/SkillsPanel-B3Nm5j32.css +1 -0
  56. package/dist/web/assets/SkillsPanel-gmBWEoiF.js +1 -0
  57. package/dist/web/assets/SpeedTestDrawer-Dc0WToJ_.css +1 -0
  58. package/dist/web/assets/SpeedTestDrawer-DcNzuVJk.js +1 -0
  59. package/dist/web/assets/Upload-v5rV0qTT.js +1 -0
  60. package/dist/web/assets/WorkspaceDrawer-CGnMu9p1.css +1 -0
  61. package/dist/web/assets/WorkspaceDrawer-DxmicM4U.js +1 -0
  62. package/dist/web/assets/WorkspaceManager-CJHCjARN.js +1 -0
  63. package/dist/web/assets/WorkspacePanel-D0-zHTHP.css +1 -0
  64. package/dist/web/assets/WorkspacePanel-D8_Zq-du.js +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-C0EHRym0.css +1 -0
  71. package/dist/web/assets/index-DnEocV0M.js +2 -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-B3uojyvV.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 +94 -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 +162 -0
  140. package/src/platforms/channel-auth-service.js +82 -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 +87 -417
  269. package/src/{server/services → platforms}/notification-hooks.js +140 -1023
  270. package/src/platforms/oauth-credentials-service.js +506 -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 +11 -20
  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 +1 -1
  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 +780 -213
  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
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ const { createCapabilityDriver } = require('../../../shared/capability-driver');
4
+
5
+ function createDriver(context = {}) {
6
+ return createCapabilityDriver({
7
+ ...context,
8
+ platform: 'claude',
9
+ capability: 'statistics',
10
+ servicePath: './claude/statistics-implementation',
11
+ localServicePath: '../platforms/drivers/claude/statistics-implementation',
12
+ methods: {"getStatistics":"getStatistics","getDailyStatistics":"getDailyStatistics","getTodayStatistics":"getTodayStatistics","recordRequest":"recordRequest","resetStatistics":"resetStatistics"}
13
+ });
14
+ }
15
+
16
+ module.exports = { createDriver };
@@ -5,7 +5,7 @@ const crypto = require('crypto');
5
5
  const {
6
6
  normalizeOpenCodeMessages,
7
7
  normalizeStopSequences
8
- } = require('./opencode-normalization');
8
+ } = require('../opencode/normalization');
9
9
 
10
10
  // ---------------------------------------------------------------------------
11
11
  // Constants
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ const { createApiOperationsDriver } = require('../../../shared/driver-factories/api');
4
+
5
+ function createDriver(context = {}) {
6
+ return createApiOperationsDriver({ ...context, platform: 'codex' });
7
+ }
8
+
9
+ module.exports = { createDriver };
@@ -3,18 +3,34 @@ const path = require('path');
3
3
  const crypto = require('crypto');
4
4
  const toml = require('toml');
5
5
  const tomlStringify = require('@iarna/toml').stringify;
6
- const { PATHS } = require('../../config/paths');
7
- const { getCodexDir } = require('./codex-config');
8
- const { isProxyConfig, readConfig } = require('./codex-settings-manager');
9
- const { syncCodexUserEnvironment } = require('./codex-env-manager');
10
- const BaseChannelService = require('./base/base-channel-service');
6
+ const { PATHS } = require('../../../config/paths');
7
+ const { getCodexDir } = require('./config');
8
+ const { isProxyConfig, readConfig } = require('./native-config-implementation');
9
+ const { syncCodexUserEnvironment } = require('./env-manager');
10
+ const {
11
+ readNativeOAuth,
12
+ clearCodexChannelConfig
13
+ } = require('../../native-oauth-adapters');
14
+ const BaseChannelService = require('../../../shared/base-channel-service');
11
15
  const {
12
16
  createSkippedResult,
13
17
  isLocalProxyBaseUrl,
14
18
  resolveApiKeyValue,
15
19
  resolveExistingActiveChannel,
16
20
  upsertSyncedChannels
17
- } = require('./channel-sync-utils');
21
+ } = require('../../../server/services/channel-sync-utils');
22
+
23
+ let configuredState = { channels: PATHS.channels.codex };
24
+
25
+ function configure({ pathContext } = {}) {
26
+ configuredState = {
27
+ channels: pathContext?.customized
28
+ ? (pathContext.state?.channels || PATHS.channels?.codex)
29
+ : PATHS.channels?.codex
30
+ };
31
+ require('../../native-oauth-adapters').configure?.({ pathContext });
32
+ if (service) service.channelsFilePath = configuredState.channels;
33
+ }
18
34
 
19
35
  const CODEX_MANAGED_ENV_KEY = 'CC_PROXY_KEY';
20
36
  const CODEX_PROXY_ENV_VALUE = 'PROXY_KEY';
@@ -32,7 +48,9 @@ function resolveCurrentManagedChannel(channels = []) {
32
48
  }
33
49
 
34
50
  if (currentProvider && currentProvider !== 'cc-proxy') {
35
- const matched = allChannels.find(ch => ch.providerKey === currentProvider);
51
+ const matched = allChannels.find(ch => (
52
+ ch.providerKey === currentProvider && ch.enabled !== false
53
+ ));
36
54
  if (matched) {
37
55
  return matched;
38
56
  }
@@ -41,8 +59,71 @@ function resolveCurrentManagedChannel(channels = []) {
41
59
  return allChannels.find(ch => ch.enabled !== false) || null;
42
60
  }
43
61
 
44
- function channelRequiresOpenaiAuth() {
45
- return false;
62
+ function channelRequiresOpenaiAuth(channel) {
63
+ return channel?.authMode === 'oauth';
64
+ }
65
+
66
+ function createCodexOAuthError(message, code, statusCode) {
67
+ const error = new Error(message);
68
+ error.code = code;
69
+ error.statusCode = statusCode;
70
+ return error;
71
+ }
72
+
73
+ function readNativeCodexOAuthOrThrow() {
74
+ const credential = readNativeOAuth('codex');
75
+ if (!credential) {
76
+ throw createCodexOAuthError(
77
+ 'Codex native OAuth credential is unavailable; sync local OAuth first',
78
+ 'codex_native_oauth_unavailable',
79
+ 422
80
+ );
81
+ }
82
+ return credential;
83
+ }
84
+
85
+ function assertCodexOAuthIsNativeOnly() {
86
+ if (isProxyConfig()) {
87
+ throw createCodexOAuthError(
88
+ 'Codex OAuth channels are native-only; stop the Codex proxy first',
89
+ 'codex_oauth_proxy_unsupported',
90
+ 409
91
+ );
92
+ }
93
+ }
94
+
95
+ function clearManagedCodexConfig() {
96
+ clearCodexChannelConfig();
97
+ delete process.env.CC_PROXY_KEY;
98
+ }
99
+
100
+ function applyNativeOAuthChannel(channel) {
101
+ assertCodexOAuthIsNativeOnly();
102
+ readNativeCodexOAuthOrThrow();
103
+ clearManagedCodexConfig();
104
+ console.log(`[Codex Channels] Applied native OAuth channel ${channel.name}`);
105
+ return channel;
106
+ }
107
+
108
+ function validateCodexChannelForMutation(channel, operation) {
109
+ if (channel?.authMode !== 'oauth') {
110
+ return;
111
+ }
112
+ if (operation !== 'apply' && channel.enabled === false) {
113
+ return;
114
+ }
115
+ assertCodexOAuthIsNativeOnly();
116
+ readNativeCodexOAuthOrThrow();
117
+ }
118
+
119
+ function getCodexProxyExcludedChannelIds(channels = null) {
120
+ const enabledChannels = Array.isArray(channels)
121
+ ? channels.filter(channel => channel?.enabled !== false)
122
+ : getServiceInstance().getEnabledChannels();
123
+ return enabledChannels
124
+ .filter(channel => channel?.authMode === 'oauth')
125
+ .map(channel => channel.id)
126
+ .filter(Boolean);
46
127
  }
47
128
 
48
129
  function buildManagedCodexEnvMap(channels = [], { includeProxyKey = false, activeChannel = null } = {}) {
@@ -62,9 +143,31 @@ function syncAllChannelEnvVars() {
62
143
  const svc = getServiceInstance();
63
144
  const data = svc.loadChannels();
64
145
  const proxyRunning = isProxyConfig();
146
+ const activeChannel = proxyRunning
147
+ ? null
148
+ : resolveCurrentManagedChannel(data.channels);
149
+
150
+ if (!proxyRunning && !activeChannel) {
151
+ clearManagedCodexConfig();
152
+ return;
153
+ }
154
+
155
+ if (!proxyRunning && activeChannel.authMode === 'oauth') {
156
+ try {
157
+ applyNativeOAuthChannel(activeChannel);
158
+ } catch (err) {
159
+ if (err.code !== 'codex_native_oauth_unavailable') {
160
+ throw err;
161
+ }
162
+ console.warn(`[Codex Channels] ${err.message}; cleared managed config`);
163
+ clearManagedCodexConfig();
164
+ }
165
+ return;
166
+ }
167
+
65
168
  const envMap = buildManagedCodexEnvMap(data.channels, {
66
169
  includeProxyKey: proxyRunning,
67
- activeChannel: proxyRunning ? null : resolveCurrentManagedChannel(data.channels)
170
+ activeChannel
68
171
  });
69
172
  syncCodexUserEnvironment(envMap, { replace: true });
70
173
  } catch (err) {
@@ -108,6 +211,19 @@ function writeCodexConfigForMultiChannel(channels) {
108
211
  }
109
212
 
110
213
  const enabledChannels = channels.filter(ch => ch.enabled !== false);
214
+ const oauthChannels = enabledChannels.filter(ch => ch.authMode === 'oauth');
215
+ if (oauthChannels.length > 0) {
216
+ if (oauthChannels.length !== enabledChannels.length) {
217
+ throw createCodexOAuthError(
218
+ 'Codex native OAuth cannot be mixed with managed API-key channels',
219
+ 'codex_oauth_mixed_channels',
220
+ 409
221
+ );
222
+ }
223
+ applyNativeOAuthChannel(oauthChannels[0]);
224
+ return;
225
+ }
226
+
111
227
  if (enabledChannels.length > 0) {
112
228
  const primary = enabledChannels[0];
113
229
  config.model_provider = primary.providerKey;
@@ -124,6 +240,9 @@ function writeCodexConfigForMultiChannel(channels) {
124
240
  config.model_providers[ch.providerKey].query_params = ch.queryParams;
125
241
  }
126
242
  }
243
+ } else {
244
+ clearManagedCodexConfig();
245
+ return;
127
246
  }
128
247
 
129
248
  writeAnnotatedCodexConfig(configPath, config, [
@@ -138,8 +257,9 @@ class CodexChannelService extends BaseChannelService {
138
257
  constructor() {
139
258
  super({
140
259
  platform: 'codex',
141
- channelsFilePath: PATHS.channels.codex,
260
+ channelsFilePath: configuredState.channels,
142
261
  defaultGatewaySource: 'codex',
262
+ oauthChannelPolicy: 'single-enabled',
143
263
  isProxyRunning: () => isProxyConfig(),
144
264
  });
145
265
  }
@@ -151,16 +271,25 @@ class CodexChannelService extends BaseChannelService {
151
271
  _applyDefaults(channel) {
152
272
  const ch = super._applyDefaults(channel);
153
273
  ch.providerKey = ch.providerKey || '';
154
- ch.envKey = CODEX_MANAGED_ENV_KEY;
274
+ ch.envKey = ch.authMode === 'oauth' ? '' : CODEX_MANAGED_ENV_KEY;
155
275
  ch.wireApi = ch.wireApi || 'responses';
156
276
  ch.model = ch.model || '';
157
277
  ch.speedTestModel = ch.speedTestModel || null;
158
278
  ch.modelRedirects = Array.isArray(ch.modelRedirects) ? ch.modelRedirects : [];
159
279
  ch.gatewaySourceType = ch.gatewaySourceType || 'codex';
160
- ch.requiresOpenaiAuth = false;
280
+ ch.requiresOpenaiAuth = channelRequiresOpenaiAuth(ch);
161
281
  ch.queryParams = ch.queryParams || {};
162
282
  return ch;
163
283
  }
284
+ _validateBeforeChannelMutation(channel, _allChannels, context = {}) {
285
+ validateCodexChannelForMutation(channel, context.operation);
286
+ }
287
+
288
+ disableAllChannels() {
289
+ const result = super.disableAllChannels();
290
+ syncAllChannelEnvVars();
291
+ return result;
292
+ }
164
293
 
165
294
  _validateUniqueness(channels, fields, excludeId) {
166
295
  if (!fields.providerKey) return;
@@ -207,6 +336,9 @@ class CodexChannelService extends BaseChannelService {
207
336
  }
208
337
 
209
338
  _applyToNativeSettings(channel) {
339
+ if (channel.authMode === 'oauth') {
340
+ return applyNativeOAuthChannel(channel);
341
+ }
210
342
  const codexDir = getCodexDir();
211
343
  const configPath = path.join(codexDir, 'config.toml');
212
344
 
@@ -404,6 +536,7 @@ try {
404
536
  }
405
537
 
406
538
  module.exports = {
539
+ configure,
407
540
  getChannels,
408
541
  createChannel,
409
542
  updateChannel,
@@ -416,10 +549,12 @@ module.exports = {
416
549
  applyChannelToSettings,
417
550
  getEffectiveApiKey,
418
551
  disableAllChannels,
552
+ getCodexProxyExcludedChannelIds,
419
553
  syncCurrentCodexChannel,
420
554
  _test: {
421
555
  buildManagedCodexEnvMap,
422
556
  CODEX_MANAGED_ENV_KEY,
423
- resolveCurrentManagedChannel
557
+ resolveCurrentManagedChannel,
558
+ getCodexProxyExcludedChannelIds
424
559
  }
425
560
  };
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ const { createChannelDriver } = require('../../../shared/channel-driver');
4
+
5
+ function createDriver(context = {}) {
6
+ const driver = createChannelDriver({
7
+ ...context,
8
+ platform: 'codex',
9
+ servicePath: './codex/channels-implementation',
10
+ localServicePath: '../platforms/drivers/codex/channels-implementation',
11
+ syncMethod: 'syncCurrentCodexChannel',
12
+ createArgs: (input, rest) => typeof input === 'object'
13
+ ? (() => {
14
+ const { name, providerKey, baseUrl, apiKey, wireApi, extra, ...channelExtra } = input;
15
+ return [name, providerKey, baseUrl, apiKey, wireApi, { ...channelExtra, ...extra }];
16
+ })()
17
+ : [input, ...rest],
18
+ cliMetadata: { supportsCliCreate: true, supportsCliToggle: true, defaultPort: 20089, createDefaults: { wireApi: 'responses' } },
19
+ modelListType: 'openai_compatible',
20
+ formatCliChannelDetails: channel => channel.providerKey
21
+ ? [`provider ${channel.providerKey}`]
22
+ : []
23
+ });
24
+ const auth = require('../../channel-auth-service');
25
+ driver.getAuth = context => auth.getChannelAuth('codex', { channelId: context?.params?.channelId || context?.query?.channelId || '' });
26
+ driver.syncLocalAuth = context => auth.syncLocalChannelAuth('codex', { channelId: context?.body?.channelId || context?.params?.channelId || context?.query?.channelId || '' });
27
+ driver.getAuthQuota = context => auth.fetchChannelAuthQuota('codex', context?.params?.channelId, { refresh: context?.query?.refresh === 'true' });
28
+ const callLegacy = (name, args) => driver._service()[name](...args);
29
+ for (const name of [
30
+ 'getChannels', 'getEnabledChannels', 'createChannel', 'updateChannel',
31
+ 'markChannelAsRecentlyUsed', 'deleteChannel', 'saveChannelOrder',
32
+ 'syncAllChannelEnvVars', 'writeCodexConfigForMultiChannel',
33
+ 'applyChannelToSettings', 'syncCurrentCodexChannel'
34
+ ]) {
35
+ driver[name] = (...args) => callLegacy(name, args);
36
+ }
37
+ driver.writeMultiChannelConfig = channels => {
38
+ const service = driver._service();
39
+ return service.writeCodexConfigForMultiChannel(channels);
40
+ };
41
+ return driver;
42
+ }
43
+
44
+ module.exports = { createDriver };
45
+
@@ -1,13 +1,22 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const toml = require('toml');
4
- const { NATIVE_PATHS } = require('../../config/paths');
4
+ const { NATIVE_PATHS } = require('../../../config/paths');
5
+
6
+ const DEFAULT_CODEX_DIR = NATIVE_PATHS.codex.dir;
7
+ let codexDirOverride = null;
8
+
9
+ function configure({ pathContext } = {}) {
10
+ codexDirOverride = pathContext?.customized
11
+ ? (pathContext.native?.dir || path.dirname(pathContext.native?.config || DEFAULT_CODEX_DIR))
12
+ : null;
13
+ }
5
14
 
6
15
  /**
7
16
  * 获取 Codex 配置目录
8
17
  */
9
18
  function getCodexDir() {
10
- return NATIVE_PATHS.codex.dir;
19
+ return codexDirOverride || DEFAULT_CODEX_DIR;
11
20
  }
12
21
 
13
22
  /**
@@ -82,6 +91,7 @@ function isCodexInstalled() {
82
91
  }
83
92
 
84
93
  module.exports = {
94
+ configure,
85
95
  getCodexDir,
86
96
  loadConfig,
87
97
  loadAuth,
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const { execFileSync } = require('child_process');
4
- const { PATHS, HOME_DIR } = require('../../config/paths');
4
+ const { PATHS, HOME_DIR } = require('../../../config/paths');
5
5
 
6
6
  const PROFILE_MARKER_START = '# >>> coding-tool codex env >>>';
7
7
  const PROFILE_MARKER_END = '# <<< coding-tool codex env <<<';
@@ -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: 'codex' });
7
+ }
8
+
9
+ module.exports = { createDriver };
@@ -2,25 +2,33 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const toml = require('toml');
4
4
  const tomlStringify = require('@iarna/toml').stringify;
5
- const { NATIVE_PATHS } = require('../../config/paths');
6
- const { syncCodexUserEnvironment } = require('./codex-env-manager');
5
+ const { NATIVE_PATHS } = require('../../../config/paths');
6
+ const { syncCodexUserEnvironment } = require('./env-manager');
7
+ const DEFAULT_NATIVE_PATHS = NATIVE_PATHS.codex;
8
+ let nativePaths = DEFAULT_NATIVE_PATHS;
9
+
10
+ function configure({ pathContext } = {}) {
11
+ nativePaths = pathContext?.customized && pathContext.native?.config
12
+ ? { ...DEFAULT_NATIVE_PATHS, ...pathContext.native }
13
+ : DEFAULT_NATIVE_PATHS;
14
+ }
7
15
 
8
16
  // Codex 配置文件路径
9
17
  function getConfigPath() {
10
- return NATIVE_PATHS.codex.config;
18
+ return nativePaths.config;
11
19
  }
12
20
 
13
21
  function getAuthPath() {
14
- return NATIVE_PATHS.codex.auth;
22
+ return nativePaths.auth;
15
23
  }
16
24
 
17
25
  // 备份文件路径
18
26
  function getConfigBackupPath() {
19
- return NATIVE_PATHS.codex.configBackup;
27
+ return nativePaths.configBackup;
20
28
  }
21
29
 
22
30
  function getAuthBackupPath() {
23
- return NATIVE_PATHS.codex.authBackup;
31
+ return nativePaths.authBackup;
24
32
  }
25
33
 
26
34
  // 检查配置文件是否存在
@@ -354,6 +362,7 @@ function getCurrentProxyPort() {
354
362
  }
355
363
 
356
364
  module.exports = {
365
+ configure,
357
366
  getConfigPath,
358
367
  getAuthPath,
359
368
  getConfigBackupPath,
@@ -0,0 +1,47 @@
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?.config
11
+ ? configuredPaths
12
+ : require('../../../config/paths').NATIVE_PATHS.codex;
13
+ const settings = requireImpl
14
+ ? requireImpl('./codex/native-config-implementation')
15
+ : implementation;
16
+ settings.configure?.({ pathContext: context.pathContext });
17
+ const snapshotMethods = createNativeSnapshotMethods({
18
+ config: { path: currentNativePaths.config, format: 'text' },
19
+ auth: { path: currentNativePaths.auth, format: 'json', mode: 0o600 }
20
+ }, { platform: 'codex', runtime: context.runtime });
21
+ return {
22
+ platform: 'codex',
23
+ capability: 'nativeConfig',
24
+ ...context,
25
+ ...settings,
26
+ ...snapshotMethods,
27
+ preserveNativeOAuthOnProxyStart: true,
28
+ restoreNativeSettingsOnProxyStop: true,
29
+ clearNativeOAuth: () => {
30
+ const adapters = require('../../native-oauth-adapters');
31
+ adapters.configure?.(context);
32
+ return adapters.clearNativeOAuth('codex');
33
+ },
34
+ clearActiveChannelMarker() {
35
+ try {
36
+ const markerPath = context.pathContext?.customized
37
+ ? (context.pathContext.state?.activeChannel || PATHS.activeChannel.codex)
38
+ : PATHS.activeChannel.codex;
39
+ fs.unlinkSync(markerPath);
40
+ } catch (error) {
41
+ if (error.code !== 'ENOENT') throw error;
42
+ }
43
+ }
44
+ };
45
+ }
46
+
47
+ module.exports = { createDriver };
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { NATIVE_PATHS } = require('../../../config/paths');
6
+ const {
7
+ normalizeCost,
8
+ normalizeUsage,
9
+ subtractUsage,
10
+ usageFieldPaths,
11
+ createSelectiveJsonLineParser,
12
+ visitJsonLinesForward,
13
+ visitJsonLinesReverse,
14
+ walkFiles,
15
+ createIncrementalJsonlCursor
16
+ } = require('../native-log-utils');
17
+ const { calculateUsageCost } = require('../../../server/services/usage-log-utils');
18
+
19
+ const CODEX_SELECTED_FIELDS = [
20
+ 'type',
21
+ 'timestamp',
22
+ 'payload.type',
23
+ 'payload.id',
24
+ 'payload.model_provider',
25
+ 'payload.model',
26
+ 'payload.info.cost.total',
27
+ 'payload.info.cost.usd',
28
+ 'payload.info.cost.amount',
29
+ ...usageFieldPaths('payload.info.total_token_usage')
30
+ ];
31
+
32
+ function applyCodexRecord(state, record) {
33
+ if (record?.type === 'session_meta') {
34
+ state.sessionId = record.payload?.id || state.sessionId;
35
+ state.provider = record.payload?.model_provider || state.provider;
36
+ return;
37
+ }
38
+ if (record?.type === 'turn_context') {
39
+ state.model = record.payload?.model || state.model;
40
+ return;
41
+ }
42
+ if (record?.type !== 'event_msg' || record.payload?.type !== 'token_count') return;
43
+ const usage = record.payload?.info?.total_token_usage;
44
+ if (!usage || typeof usage !== 'object') return;
45
+ state.pendingUsage = normalizeUsage(usage);
46
+ state.pendingTimestamp = record.timestamp || state.pendingTimestamp;
47
+ state.pendingCost = normalizeCost(record.payload?.info?.cost ?? usage.cost);
48
+ }
49
+
50
+ function bootstrapCodexFile(filePath, state, stat, fsImpl, stats) {
51
+ const endOffset = stat.size;
52
+ state.sessionId = path.basename(filePath, '.jsonl');
53
+ state.provider = '';
54
+ state.model = '';
55
+ state.lastUsage = null;
56
+ state.pendingUsage = null;
57
+ state.pendingTimestamp = null;
58
+ state.pendingCost = 0;
59
+ visitJsonLinesForward(filePath, (record) => {
60
+ if (record?.type === 'session_meta') {
61
+ state.sessionId = record.payload?.id || state.sessionId;
62
+ state.provider = record.payload?.model_provider || state.provider;
63
+ return false;
64
+ }
65
+ return true;
66
+ }, {
67
+ fsImpl,
68
+ endOffset,
69
+ createLongLineParser: () => createSelectiveJsonLineParser(CODEX_SELECTED_FIELDS),
70
+ stats
71
+ });
72
+
73
+ let latestUsage = null;
74
+ let foundLatestModel = false;
75
+ visitJsonLinesReverse(filePath, (record) => {
76
+ if (record?.type === 'event_msg' && record.payload?.type === 'token_count' && !latestUsage) {
77
+ const usage = record.payload?.info?.total_token_usage;
78
+ if (usage && typeof usage === 'object') {
79
+ latestUsage = normalizeUsage(usage);
80
+ state.pendingTimestamp = record.timestamp || state.pendingTimestamp;
81
+ state.pendingCost = normalizeCost(record.payload?.info?.cost ?? usage.cost);
82
+ }
83
+ }
84
+ if (record?.type === 'turn_context' && !foundLatestModel) {
85
+ const model = record.payload?.model;
86
+ if (model) {
87
+ state.model = model;
88
+ foundLatestModel = true;
89
+ }
90
+ }
91
+ return !(latestUsage && foundLatestModel);
92
+ }, {
93
+ fsImpl,
94
+ endOffset,
95
+ includeTrailingLine: false,
96
+ createLongLineParser: () => createSelectiveJsonLineParser(CODEX_SELECTED_FIELDS),
97
+ stats
98
+ });
99
+ if (latestUsage) state.lastUsage = latestUsage;
100
+ state.pendingUsage = null;
101
+ return { ok: true };
102
+ }
103
+
104
+ function createDriver({ nativeRoot, pathContext, fsImpl = fs } = {}) {
105
+ const resolvedNativeRoot = pathContext?.customized
106
+ ? (pathContext.native?.sessions || nativeRoot || NATIVE_PATHS.codex.sessions)
107
+ : (nativeRoot || NATIVE_PATHS.codex.sessions);
108
+ return {
109
+ platform: 'codex',
110
+ capability: 'nativeLogs',
111
+ createNativeLogCursor({ fs: cursorFs = fsImpl, skipInitialParse = false, onDiagnostic } = {}) {
112
+ const scanFiles = () => walkFiles(resolvedNativeRoot, name => /^rollout-.*\.jsonl$/.test(name), cursorFs);
113
+ return createIncrementalJsonlCursor({
114
+ scanFiles,
115
+ fsImpl: cursorFs,
116
+ skipInitialParse,
117
+ createFileState: (filePath, _stat, previousState) => ({
118
+ sessionId: previousState?.sessionId || path.basename(filePath, '.jsonl'),
119
+ provider: previousState?.provider || '',
120
+ model: previousState?.model || '',
121
+ lastUsage: previousState?.lastUsage || null,
122
+ pendingUsage: null,
123
+ pendingTimestamp: null,
124
+ pendingCost: 0
125
+ }),
126
+ bootstrapFile: (filePath, state, stat, stats) => bootstrapCodexFile(filePath, state, stat, cursorFs, stats),
127
+ parseLine: (_filePath, record, state) => {
128
+ applyCodexRecord(state, record);
129
+ return null;
130
+ },
131
+ afterRead: (_filePath, state) => {
132
+ if (!state.pendingUsage) return null;
133
+ const current = state.pendingUsage;
134
+ const previous = state.lastUsage;
135
+ const restarted = previous && current.total < previous.total;
136
+ const tokens = previous && !restarted ? subtractUsage(current, previous) : current;
137
+ state.lastUsage = current;
138
+ state.pendingUsage = null;
139
+ if (tokens.total <= 0) return null;
140
+ const sessionId = state.sessionId || '';
141
+ const event = {
142
+ id: `${sessionId}:token-count:${current.total}`,
143
+ source: 'codex',
144
+ sessionId,
145
+ timestamp: state.pendingTimestamp,
146
+ provider: state.provider,
147
+ model: state.model,
148
+ tokens,
149
+ cost: state.pendingCost || calculateUsageCost('codex', state.model, tokens)
150
+ };
151
+ state.pendingTimestamp = null;
152
+ state.pendingCost = 0;
153
+ return event;
154
+ },
155
+ createLongLineParser: () => createSelectiveJsonLineParser(CODEX_SELECTED_FIELDS),
156
+ onDiagnostic,
157
+ onError: (error, filePath) => {
158
+ console.warn('[Codex Native Logs] Failed to read changed usage events:', filePath, error.message);
159
+ }
160
+ });
161
+ },
162
+ createCursor(options) { return this.createNativeLogCursor(options); }
163
+ };
164
+ }
165
+
166
+ module.exports = { createDriver };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const mcpFormat = require('../../../shared/mcp-format');
4
+ const {
5
+ createProjectAdapter,
6
+ createTomlMcpHandlers
7
+ } = require('../../../shared/project-config');
8
+
9
+ function createAdapter({ manifest, fsImpl } = {}) {
10
+ const relativePath = manifest?.projectResources?.mcp?.path;
11
+ const mcpHandlers = createTomlMcpHandlers({
12
+ relativePath,
13
+ format: manifest?.projectResources?.mcp?.format || 'codex-toml',
14
+ toNative: mcpFormat.convertToCodexFormat,
15
+ fromNative: mcpFormat.convertFromCodexFormat,
16
+ fsImpl
17
+ });
18
+ return createProjectAdapter({ manifest, fsImpl, mcpHandlers });
19
+ }
20
+
21
+ module.exports = { createAdapter };