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,16 +1,15 @@
1
- const express = require('express');
1
+ 'use strict';
2
+
2
3
  const fs = require('fs');
3
4
  const path = require('path');
4
- const router = express.Router();
5
5
  const {
6
6
  getOmpPaths,
7
7
  getOmpStatus,
8
8
  readJsonFile,
9
9
  readYamlFile
10
- } = require('../services/omp-config');
11
- const {
12
- getOmpAuthProviderSnapshot
13
- } = require('../services/omp-auth-providers');
10
+ } = require('./config');
11
+ const { getOmpAuthProviderSnapshot } = require('./auth-providers');
12
+ const { createApiOperationsDriver } = require('../../../shared/driver-factories/api');
14
13
 
15
14
  function listDirEntries(dirPath, options = {}) {
16
15
  const { extensions = null, includeDirectories = true } = options;
@@ -20,8 +19,8 @@ function listDirEntries(dirPath, options = {}) {
20
19
  .filter(entry => !entry.name.startsWith('.'))
21
20
  .filter((entry) => {
22
21
  if (entry.isDirectory()) return includeDirectories;
23
- if (!Array.isArray(extensions) || extensions.length === 0) return true;
24
- return extensions.includes(path.extname(entry.name).toLowerCase());
22
+ return !Array.isArray(extensions) || extensions.length === 0
23
+ || extensions.includes(path.extname(entry.name).toLowerCase());
25
24
  })
26
25
  .map((entry) => {
27
26
  const fullPath = path.join(dirPath, entry.name);
@@ -86,11 +85,14 @@ function buildCapabilities() {
86
85
  };
87
86
  }
88
87
 
89
- router.get('/', (req, res) => {
90
- try {
91
- const paths = getOmpPaths(process.env, { resolveRuntime: false });
92
- const settings = readYamlFile(paths.settings, readJsonFile(paths.settingsJsonLegacy, {}));
93
- const resources = {
88
+ function readConfig() {
89
+ const paths = getOmpPaths(process.env, { resolveRuntime: false });
90
+ const settings = readYamlFile(paths.settings, readJsonFile(paths.settingsJsonLegacy, {}));
91
+ return {
92
+ success: true,
93
+ status: getOmpStatus(process.env, { resolveRuntime: false }),
94
+ capabilities: buildCapabilities(),
95
+ resources: {
94
96
  config: readYamlFile(paths.config, {}),
95
97
  settings: readYamlFile(paths.settings, {}),
96
98
  auth: fs.existsSync(paths.auth) ? { exists: true, path: paths.auth } : { exists: false, path: paths.auth },
@@ -104,59 +106,45 @@ router.get('/', (req, res) => {
104
106
  notes: listDirEntries(paths.notes, { extensions: ['.md'], includeDirectories: true }),
105
107
  extensions: listDirEntries(paths.extensions, { extensions: ['.js', '.mjs', '.cjs', '.ts'], includeDirectories: true }),
106
108
  sessionsDir: paths.sessions
107
- };
108
-
109
- res.json({
110
- success: true,
111
- status: getOmpStatus(process.env, { resolveRuntime: false }),
112
- capabilities: buildCapabilities(),
113
- resources
114
- });
115
- } catch (error) {
116
- console.error('[OMP Config API] Failed to read config:', error);
117
- res.status(500).json({ error: error.message });
118
- }
119
- });
109
+ }
110
+ };
111
+ }
120
112
 
121
- router.get('/capabilities', (req, res) => {
122
- res.json({
113
+ function readResources() {
114
+ const paths = getOmpPaths(process.env, { resolveRuntime: false });
115
+ const settings = readYamlFile(paths.settings, readJsonFile(paths.settingsJsonLegacy, {}));
116
+ return {
123
117
  success: true,
118
+ paths,
119
+ packages: normalizeArray(settings.packages),
120
+ skills: listDirEntries(paths.skills),
121
+ prompts: listDirEntries(paths.prompts, { extensions: ['.md'], includeDirectories: true }),
122
+ commands: listDirEntries(paths.commands, { extensions: ['.md'], includeDirectories: true }),
123
+ notes: listDirEntries(paths.notes, { extensions: ['.md'], includeDirectories: true }),
124
+ extensions: listDirEntries(paths.extensions, { extensions: ['.js', '.mjs', '.cjs', '.ts'], includeDirectories: true })
125
+ };
126
+ }
127
+
128
+ function createDriver(context = {}) {
129
+ return createApiOperationsDriver({
130
+ ...context,
124
131
  platform: 'omp',
125
- capabilities: buildCapabilities()
132
+ operationHandlers: {
133
+ getConfig: () => readConfig(),
134
+ getConfigCapabilities: () => ({
135
+ success: true,
136
+ platform: 'omp',
137
+ capabilities: buildCapabilities()
138
+ }),
139
+ getConfigAuthProviders: (requestContext) => ({
140
+ success: true,
141
+ ...getOmpAuthProviderSnapshot({
142
+ forceRefresh: requestContext.query?.forceRefresh === 'true'
143
+ })
144
+ }),
145
+ getConfigResources: () => readResources()
146
+ }
126
147
  });
127
- });
128
-
129
- router.get('/auth-providers', (req, res) => {
130
- try {
131
- const forceRefresh = req.query.forceRefresh === 'true';
132
- res.json({
133
- success: true,
134
- ...getOmpAuthProviderSnapshot({ forceRefresh })
135
- });
136
- } catch (error) {
137
- console.error('[OMP Config API] Failed to list auth providers:', error);
138
- res.status(500).json({ error: error.message });
139
- }
140
- });
141
-
142
- router.get('/resources', (req, res) => {
143
- try {
144
- const paths = getOmpPaths(process.env, { resolveRuntime: false });
145
- const settings = readYamlFile(paths.settings, readJsonFile(paths.settingsJsonLegacy, {}));
146
- res.json({
147
- success: true,
148
- paths,
149
- packages: normalizeArray(settings.packages),
150
- skills: listDirEntries(paths.skills),
151
- prompts: listDirEntries(paths.prompts, { extensions: ['.md'], includeDirectories: true }),
152
- commands: listDirEntries(paths.commands, { extensions: ['.md'], includeDirectories: true }),
153
- notes: listDirEntries(paths.notes, { extensions: ['.md'], includeDirectories: true }),
154
- extensions: listDirEntries(paths.extensions, { extensions: ['.js', '.mjs', '.cjs', '.ts'], includeDirectories: true })
155
- });
156
- } catch (error) {
157
- console.error('[OMP Config API] Failed to list resources:', error);
158
- res.status(500).json({ error: error.message });
159
- }
160
- });
148
+ }
161
149
 
162
- module.exports = router;
150
+ module.exports = { createDriver };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { getOmpAuthProviderSnapshot } = require('./omp-auth-providers');
3
+ const { getOmpAuthProviderSnapshot } = require('./auth-providers');
4
4
 
5
5
  function attachWorkerHandler() {
6
6
  process.on('message', (options = {}) => {
@@ -1,6 +1,6 @@
1
1
  const path = require('path');
2
2
  const { fork, spawnSync } = require('child_process');
3
- const ompConfig = require('./omp-config');
3
+ const ompConfig = require('./config');
4
4
 
5
5
  const COMMAND_TIMEOUT_MS = 5000;
6
6
  const TOKEN_LIST_TIMEOUT_MS = 3000;
@@ -2,9 +2,10 @@ const crypto = require('crypto');
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const { execFileSync } = require('child_process');
5
- const { PATHS, ensureStorageDirMigrated } = require('../../config/paths');
6
- const BaseChannelService = require('./base/base-channel-service');
7
- const ompConfig = require('./omp-config');
5
+ const { PATHS, ensureStorageDirMigrated } = require('../../../config/paths');
6
+ const BaseChannelService = require('../../../shared/base-channel-service');
7
+ const ompConfig = require('./config');
8
+ const { MODEL_METADATA, METADATA_SOURCE } = require('../../../config/model-metadata');
8
9
  const {
9
10
  writeManagedOmpProviders,
10
11
  removeManagedOmpProviders,
@@ -13,20 +14,36 @@ const {
13
14
  readOmpSettingsConfig,
14
15
  normalizeProviderId,
15
16
  normalizeProviderApi
16
- } = require('./omp-settings-manager');
17
+ } = require('./native-config-implementation');
17
18
  const {
18
19
  createSkippedResult,
19
20
  isLocalProxyBaseUrl,
20
21
  resolveApiKeyValue,
21
22
  resolveExistingActiveChannel,
22
23
  upsertSyncedChannels
23
- } = require('./channel-sync-utils');
24
+ } = require('../../../server/services/channel-sync-utils');
24
25
 
25
26
  const OMP_THINKING_SUFFIX_RE = /:(minimal|low|medium|high|xhigh|off)$/;
26
27
 
28
+ let configuredState = {
29
+ channels: PATHS.channels?.omp,
30
+ activeChannel: PATHS.activeChannel?.omp
31
+ };
32
+
33
+ function configure({ pathContext } = {}) {
34
+ const custom = pathContext?.customized === true;
35
+ ompConfig.configure?.({ pathContext });
36
+ configuredState = {
37
+ channels: custom ? (pathContext.state?.channels || PATHS.channels?.omp) : PATHS.channels?.omp,
38
+ activeChannel: custom ? (pathContext.state?.activeChannel || PATHS.activeChannel?.omp) : PATHS.activeChannel?.omp,
39
+ gatewaySecret: custom ? (pathContext.state?.gatewaySecret || PATHS.ompGatewaySecret) : PATHS.ompGatewaySecret
40
+ };
41
+ if (service) service.channelsFilePath = configuredState.channels;
42
+ }
43
+
27
44
  function clearOmpChannelBalanceCache(channel) {
28
45
  try {
29
- require('./channel-balance').clearChannelBalanceCache('omp', channel);
46
+ require('../../../server/services/channel-balance').clearChannelBalanceCache('omp', channel);
30
47
  } catch (_) {
31
48
  // Balance cache invalidation is an optimization; channel activation must still succeed.
32
49
  }
@@ -45,8 +62,8 @@ function selectLatestEnabledChannel(channels = []) {
45
62
  function loadManagedOmpModeState() {
46
63
  ensureStorageDirMigrated();
47
64
  try {
48
- if (!fs.existsSync(PATHS.activeChannel.omp)) return null;
49
- const data = JSON.parse(fs.readFileSync(PATHS.activeChannel.omp, 'utf8'));
65
+ if (!fs.existsSync(configuredState.activeChannel)) return null;
66
+ const data = JSON.parse(fs.readFileSync(configuredState.activeChannel, 'utf8'));
50
67
  return data && typeof data === 'object' && !Array.isArray(data) ? data : null;
51
68
  } catch {
52
69
  return null;
@@ -59,7 +76,7 @@ function loadManagedOmpActiveChannelId() {
59
76
 
60
77
  function isManagedOmpModeEnabled() {
61
78
  ensureStorageDirMigrated();
62
- return fs.existsSync(PATHS.activeChannel.omp);
79
+ return fs.existsSync(configuredState.activeChannel);
63
80
  }
64
81
 
65
82
  function writeManagedOmpModeState(filePath, state) {
@@ -77,7 +94,7 @@ function writeManagedOmpModeState(filePath, state) {
77
94
  }
78
95
 
79
96
  function getOmpGatewaySecretPath() {
80
- return PATHS.ompGatewaySecret
97
+ return configuredState.gatewaySecret || PATHS.ompGatewaySecret
81
98
  || path.join(path.dirname(PATHS.activeChannel.omp), 'omp-gateway-secret');
82
99
  }
83
100
 
@@ -126,7 +143,7 @@ function getOrCreateOmpGatewaySecret() {
126
143
 
127
144
  function enableManagedOmpMode(activeChannelId = null, gateway = null) {
128
145
  ensureStorageDirMigrated();
129
- const filePath = PATHS.activeChannel.omp;
146
+ const filePath = configuredState.activeChannel;
130
147
  const dir = path.dirname(filePath);
131
148
  if (!fs.existsSync(dir)) {
132
149
  fs.mkdirSync(dir, { recursive: true });
@@ -154,8 +171,8 @@ function enableManagedOmpMode(activeChannelId = null, gateway = null) {
154
171
 
155
172
  function disableManagedOmpMode() {
156
173
  ensureStorageDirMigrated();
157
- if (fs.existsSync(PATHS.activeChannel.omp)) {
158
- fs.unlinkSync(PATHS.activeChannel.omp);
174
+ if (fs.existsSync(configuredState.activeChannel)) {
175
+ fs.unlinkSync(configuredState.activeChannel);
159
176
  }
160
177
  }
161
178
 
@@ -163,13 +180,18 @@ class OmpChannelService extends BaseChannelService {
163
180
  constructor() {
164
181
  super({
165
182
  platform: 'omp',
166
- channelsFilePath: PATHS.channels.omp,
183
+ channelsFilePath: configuredState.channels,
167
184
  defaultGatewaySource: 'openai_compatible',
185
+ oauthChannelPolicy: 'mixed',
168
186
  isProxyRunning: () => isManagedOmpModeEnabled()
169
187
  });
170
188
  }
171
189
 
172
190
  _applyDefaults(channel) {
191
+ const isOAuthGateway = channel?.authMode === 'oauth'
192
+ && String(channel?.transport || channel?.providerConfig?.transport || '').trim() === 'pi-native';
193
+ const gatewayUrl = String(channel?.baseUrl || '').trim();
194
+ const gatewayToken = String(channel?.apiKey || '').trim();
173
195
  const normalized = super._applyDefaults(channel);
174
196
  normalized.providerKey = normalized.providerKey || normalized.provider || normalized.name || normalized.id;
175
197
  normalized.providerApi = normalizeProviderApi(
@@ -182,7 +204,15 @@ class OmpChannelService extends BaseChannelService {
182
204
  normalized.routingGroup = String(normalized.routingGroup || '').trim();
183
205
  normalized.oauthProviderId = normalized.oauthProviderId || (normalized.authMode === 'oauth' ? normalized.providerKey : '');
184
206
  if (normalized.authMode === 'oauth') {
185
- normalized.apiKey = normalized.apiKey || '';
207
+ normalized.apiKey = isOAuthGateway ? gatewayToken : '';
208
+ normalized.baseUrl = isOAuthGateway ? gatewayUrl : '';
209
+ if (isOAuthGateway) {
210
+ normalized.transport = 'pi-native';
211
+ normalized.providerConfig = {
212
+ ...(normalized.providerConfig || {}),
213
+ transport: 'pi-native'
214
+ };
215
+ }
186
216
  } else if (normalized.authMode === 'none') {
187
217
  normalized.apiKey = '';
188
218
  normalized.oauthProviderId = '';
@@ -203,6 +233,41 @@ class OmpChannelService extends BaseChannelService {
203
233
  return normalized;
204
234
  }
205
235
 
236
+ _normalizeAuthFields(fields = {}, channels = [], existing = null) {
237
+ const hasTransport = Object.prototype.hasOwnProperty.call(fields, 'transport')
238
+ const hasProviderTransport = fields.providerConfig
239
+ && Object.prototype.hasOwnProperty.call(fields.providerConfig, 'transport')
240
+ const transport = hasTransport
241
+ ? fields.transport
242
+ : (hasProviderTransport ? fields.providerConfig.transport : existing?.transport || existing?.providerConfig?.transport)
243
+ const isOAuthGateway = fields?.authMode === 'oauth'
244
+ && String(transport || '').trim() === 'pi-native';
245
+ const gatewayUrl = String(fields?.baseUrl ?? existing?.baseUrl ?? '').trim();
246
+ const gatewayToken = String(fields?.apiKey ?? existing?.apiKey ?? '').trim();
247
+ const normalized = super._normalizeAuthFields(fields, channels, existing);
248
+ if (!isOAuthGateway) return normalized;
249
+ if (!gatewayUrl) {
250
+ const error = new Error('OMP OAuth Auth Gateway URL is required');
251
+ error.code = 'oauth_auth_gateway_url_required';
252
+ error.statusCode = 400;
253
+ throw error;
254
+ }
255
+ if (!gatewayToken) {
256
+ const error = new Error('OMP OAuth Gateway Token is required');
257
+ error.code = 'oauth_auth_gateway_token_required';
258
+ error.statusCode = 400;
259
+ throw error;
260
+ }
261
+ normalized.baseUrl = gatewayUrl;
262
+ normalized.apiKey = gatewayToken;
263
+ normalized.transport = 'pi-native';
264
+ normalized.providerConfig = {
265
+ ...(normalized.providerConfig || {}),
266
+ transport: 'pi-native'
267
+ };
268
+ return normalized;
269
+ }
270
+
206
271
  _applyToNativeSettings(channel) {
207
272
  if (isManagedOmpModeEnabled()) {
208
273
  const state = loadManagedOmpModeState();
@@ -296,9 +361,6 @@ class OmpChannelService extends BaseChannelService {
296
361
  return this.syncOmpProvidersForCurrentMode(channels);
297
362
  }
298
363
 
299
- disableManagedProviderExtension() {
300
- this.disableManagedOmpProviders();
301
- }
302
364
  }
303
365
 
304
366
  const service = new OmpChannelService();
@@ -545,7 +607,7 @@ function resolveOmpAuthMode(provider = {}, sourceProvider = {}, existing = null)
545
607
  return 'api_key';
546
608
  }
547
609
 
548
- function buildOmpSyncCandidate(modelsConfig, selection, channels) {
610
+ function buildOmpSyncCandidate(modelsConfig, selection, channels, options = {}) {
549
611
  const providers = getOmpProviders(modelsConfig);
550
612
  const providerId = selection?.providerId || '';
551
613
  const provider = providers[providerId] || null;
@@ -574,7 +636,9 @@ function buildOmpSyncCandidate(modelsConfig, selection, channels) {
574
636
  )
575
637
  ? existing?.baseUrl || ''
576
638
  : providerBaseUrl || existing?.baseUrl || managedBaseUrl;
577
- const authMode = resolveOmpAuthMode(provider, sourceProvider, existing);
639
+ const authMode = options.authMode === 'oauth'
640
+ ? 'oauth'
641
+ : resolveOmpAuthMode(provider, sourceProvider, existing);
578
642
 
579
643
  let credential = resolveApiKeyValue(sourceProvider.apiKey || sourceProvider.api_key || '');
580
644
  if (!credential.value) {
@@ -598,13 +662,11 @@ function buildOmpSyncCandidate(modelsConfig, selection, channels) {
598
662
  const preferredModel = selection?.roleModelIds?.[0]
599
663
  || selectedModelIds[0]
600
664
  || existing?.model
601
- || allowedModels[0]
602
- || null;
603
- if (!baseUrl || (authMode !== 'none' && !apiKey)) {
665
+ if (authMode !== 'oauth' && (!baseUrl || (authMode !== 'none' && !apiKey))) {
604
666
  return {
605
667
  skip: true,
606
668
  channel: existing || null,
607
- warning: `OMP 当前 provider "${providerId}" 缺少可解析的上游 Base URL 或 API Key,OAuth/登录态渠道不支持同步导入。`
669
+ warning: `OMP 当前 provider "${providerId}" 缺少可解析的上游 Base URL 或 API Key;如使用本地 OAuth,请通过显式 OAuth 同步。`
608
670
  };
609
671
  }
610
672
 
@@ -627,11 +689,19 @@ function buildOmpSyncCandidate(modelsConfig, selection, channels) {
627
689
  return {
628
690
  name: existing?.name || originalProviderId || providerId,
629
691
  providerKey: originalProviderId || providerId,
630
- baseUrl,
631
- apiKey: authMode === 'none' ? '' : apiKey,
692
+ baseUrl: authMode === 'oauth' ? '' : baseUrl,
693
+ apiKey: authMode === 'oauth' || authMode === 'none' ? '' : apiKey,
632
694
  providerApi,
633
695
  wireApi: providerApi,
634
696
  authMode,
697
+ authRef: authMode === 'oauth' ? {
698
+ credentialId: '',
699
+ providerId: providerId || originalProviderId,
700
+ accountId: sourceProvider.accountId || sourceProvider.account_id || '',
701
+ identityKey: sourceProvider.identityKey || sourceProvider.identity_key || '',
702
+ accountEmail: sourceProvider.accountEmail || sourceProvider.email || ''
703
+ } : undefined,
704
+ authSource: authMode === 'oauth' ? 'synced-local' : undefined,
635
705
  oauthProviderId: authMode === 'oauth' ? (existing?.oauthProviderId || originalProviderId || providerId) : '',
636
706
  model: preferredModel,
637
707
  allowedModels,
@@ -641,7 +711,64 @@ function buildOmpSyncCandidate(modelsConfig, selection, channels) {
641
711
  };
642
712
  }
643
713
 
644
- function syncCurrentOmpChannel() {
714
+
715
+ function getCatalogMetadata({
716
+ providerKey = '',
717
+ model = '',
718
+ speedTestModel = '',
719
+ allowedModels = [],
720
+ models = [],
721
+ availableModels = []
722
+ } = {}) {
723
+ const requestedIds = [
724
+ model,
725
+ speedTestModel,
726
+ ...(Array.isArray(models)
727
+ ? models.map(item => (
728
+ item && typeof item === 'object' && !Array.isArray(item) ? item.id || item.name : item
729
+ ))
730
+ : []),
731
+ ...(Array.isArray(allowedModels)
732
+ ? allowedModels.map(item => (
733
+ item && typeof item === 'object' && !Array.isArray(item) ? item.id || item.name : item
734
+ ))
735
+ : []),
736
+ ...(Array.isArray(availableModels)
737
+ ? availableModels.map(item => (
738
+ item && typeof item === 'object' && !Array.isArray(item) ? item.value || item.id || item.name : item
739
+ ))
740
+ : [])
741
+ ]
742
+ .map(value => String(value || '').trim().toLowerCase())
743
+ .filter(Boolean);
744
+ const normalizedProviderKey = String(providerKey || '').trim().toLowerCase();
745
+
746
+ const allEntries = Object.entries(MODEL_METADATA)
747
+ .filter(([, metadata]) => Array.isArray(metadata.toolTypes) && metadata.toolTypes.includes('omp'))
748
+ .map(([id, metadata]) => ({ ...structuredClone(metadata), id }));
749
+
750
+ const matchesRequestedId = entry => requestedIds.length > 0 && requestedIds.some(requested => (
751
+ requested === entry.id.toLowerCase()
752
+ || requested === String(entry.sourceId || '').toLowerCase()
753
+ || requested === entry.id.split('/').pop().toLowerCase()
754
+ ));
755
+ const matchesProvider = entry => (
756
+ String(entry.provider || '').toLowerCase() === normalizedProviderKey
757
+ || String(entry.sourceId || '').toLowerCase().startsWith(`${normalizedProviderKey}/`)
758
+ );
759
+ const requestedEntries = requestedIds.length > 0 ? allEntries.filter(matchesRequestedId) : [];
760
+ const providerEntries = normalizedProviderKey ? allEntries.filter(matchesProvider) : [];
761
+ const entries = requestedIds.length > 0 ? requestedEntries : providerEntries;
762
+
763
+ return {
764
+ models: entries,
765
+ warnings: [],
766
+ source: { ...METADATA_SOURCE }
767
+ };
768
+ }
769
+
770
+ function syncCurrentOmpChannel(options = {}) {
771
+ const authMode = options.authMode || 'api_key';
645
772
  let modelsConfig = { providers: {} };
646
773
  let settings = {};
647
774
  try {
@@ -650,19 +777,16 @@ function syncCurrentOmpChannel() {
650
777
  } catch (error) {
651
778
  return createSkippedResult('omp', `OMP 配置读取失败:${error.message}`);
652
779
  }
653
-
654
780
  const data = service.loadChannels();
655
781
  const channels = Array.isArray(data.channels) ? data.channels : [];
656
782
  const selections = collectOmpSyncSelections(modelsConfig, settings);
657
- if (selections.length === 0) {
658
- const active = resolveExistingActiveChannel('omp', channels);
659
- if (active) {
660
- return createSkippedResult('omp', 'OMP 当前配置未明确 provider;已找到当前面板中的 active 渠道,未重复导入。', active);
661
- }
662
- return createSkippedResult('omp', 'OMP 当前配置未明确 provider,无法同步当前渠道。');
663
- }
664
- const candidates = selections.map(selection => buildOmpSyncCandidate(modelsConfig, selection, channels));
665
-
783
+ if (selections.length === 0) return createSkippedResult('omp', 'OMP 当前配置未明确 provider,无法同步当前渠道。');
784
+ const candidates = selections
785
+ .map(selection => buildOmpSyncCandidate(modelsConfig, selection, channels, { authMode }))
786
+ .filter(candidate => authMode === 'all'
787
+ || candidate.authMode === authMode
788
+ || (authMode === 'api_key' && candidate.authMode === 'none')
789
+ || candidate.skip);
666
790
  return upsertSyncedChannels({
667
791
  toolType: 'omp',
668
792
  loadChannels: () => service.loadChannels(),
@@ -670,13 +794,16 @@ function syncCurrentOmpChannel() {
670
794
  applyDefaults: channel => service._applyDefaults(channel),
671
795
  candidates,
672
796
  matchers: [
673
- (channel, current) => channel.providerKey && channel.providerKey === current.providerKey,
797
+ (channel, current) => channel.providerKey === current.providerKey
798
+ && channel.authMode === current.authMode
799
+ && (channel.model || '') === (current.model || ''),
674
800
  (channel, current) => channel.baseUrl === current.baseUrl && channel.apiKey === current.apiKey
675
801
  ]
676
802
  });
677
803
  }
678
804
 
679
805
  module.exports = {
806
+ configure,
680
807
  getChannels: () => service.getChannels(),
681
808
  createChannel: (name, baseUrl, apiKey, extra = {}) => service.createChannel({
682
809
  name,
@@ -696,7 +823,7 @@ module.exports = {
696
823
  syncManagedOmpProviders: (channels, options) => service.syncManagedOmpProviders(channels, options),
697
824
  disableManagedOmpProviders: () => service.disableManagedOmpProviders(),
698
825
  syncManagedProviderExtension: (channels) => service.syncManagedProviderExtension(channels),
699
- disableManagedProviderExtension: () => service.disableManagedProviderExtension(),
826
+ getCatalogMetadata,
700
827
  isManagedOmpModeEnabled,
701
828
  getOrCreateOmpGatewaySecret,
702
829
  enableManagedOmpMode,
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const { createChannelDriver } = require('../../../shared/channel-driver');
4
+ const { ok, failed } = require('../../../shared/driver-result');
5
+
6
+ function createDriver(context = {}) {
7
+ const driver = createChannelDriver({
8
+ ...context,
9
+ platform: 'omp',
10
+ servicePath: './omp/channels-implementation',
11
+ localServicePath: '../platforms/drivers/omp/channels-implementation',
12
+ syncMethod: 'syncCurrentOmpChannel',
13
+ createArgs: (input, rest) => typeof input === 'object'
14
+ ? (() => {
15
+ const { name, baseUrl, apiKey, extra, ...channelExtra } = input;
16
+ return [name, baseUrl, apiKey, { ...channelExtra, ...extra }];
17
+ })()
18
+ : [input, ...rest],
19
+ cliMetadata: {
20
+ supportsCliCreate: false,
21
+ supportsCliToggle: true,
22
+ managedProviderConfig: true,
23
+ defaultPort: 20092,
24
+ createUnavailableMessage: '提示: OMP 渠道请通过 Web UI 或 API 添加后,再在这里启停调度。'
25
+ },
26
+ dashboardChannelShape: 'array'
27
+ });
28
+ driver.syncManagedProviderExtension = (...args) => (
29
+ driver._service().syncManagedProviderExtension(...args)
30
+ );
31
+ driver.catalogMetadata = (input = {}) => {
32
+ const operation = 'catalogMetadata';
33
+ const body = input && typeof input === 'object' && Object.prototype.hasOwnProperty.call(input, 'body')
34
+ ? input.body || {}
35
+ : input || {};
36
+ try {
37
+ const value = driver._service().getCatalogMetadata(body);
38
+ const wrap = result => (
39
+ result && typeof result.status === 'string'
40
+ ? result
41
+ : ok('omp', 'channels', operation, result)
42
+ );
43
+ return value && typeof value.then === 'function'
44
+ ? value.then(wrap).catch(error => failed('omp', 'channels', operation, error))
45
+ : wrap(value);
46
+ } catch (error) {
47
+ return failed('omp', 'channels', operation, error);
48
+ }
49
+ };
50
+ const auth = require('../../channel-auth-service');
51
+ driver.getAuth = context => auth.getChannelAuth('omp', { channelId: context?.params?.channelId || context?.query?.channelId || '' });
52
+ driver.syncLocalAuth = context => auth.syncLocalChannelAuth('omp', { channelId: context?.body?.channelId || context?.params?.channelId || context?.query?.channelId || '' });
53
+ driver.getAuthQuota = context => auth.fetchChannelAuthQuota('omp', context?.params?.channelId, { refresh: context?.query?.refresh === 'true' });
54
+ driver.getHealthPolicy = () => ({ freezeOnFailure: false });
55
+ return driver;
56
+ }
57
+
58
+ module.exports = { createDriver };