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
@@ -0,0 +1,467 @@
1
+ # Project-Scoped AGENTS, Skills, and MCP Control Design
2
+
3
+ ## Goal
4
+
5
+ 在现有“项目 → 历史会话”页面中,为单个项目提供项目级配置管理:
6
+
7
+ - 管理项目指令文件,首要场景是 Codex 的 `AGENTS.md`;
8
+ - 管理项目级 Skills;
9
+ - 管理项目级 MCP 服务器;
10
+ - 保持 CLI 原生文件为事实来源,让配置可随项目进入 Git;
11
+ - 不改变现有用户级资源管理语义,也不把项目配置绑定到工作区 ID。
12
+
13
+ “工作区”在本设计中只负责项目分组、发现和路径白名单。项目配置的稳定标识是经过 `realpath` 规范化的绝对项目路径。
14
+
15
+ ## Current Context
16
+
17
+ 当前项目已经具备部分可复用能力:
18
+
19
+ - `src/server/services/workspace-service.js` 管理 `~/.cc-tool/config/workspaces.json`,工作区内包含项目目录、软链接或 Git worktree;
20
+ - `AgentsService` 和 `CommandsService` 已使用 `user/project + projectPath` 作用域模型;
21
+ - `SkillService` 已按 `cwd` 缓存列表,OMP 已实现多来源项目级 Skill 发现;
22
+ - `mcp-service.js` 主要管理中心 MCP 记录和各平台用户级配置;
23
+ - `config-templates-service.js` 能一次性把部分内容落盘到项目目录,但不是持续的项目配置管理器;
24
+ - `project-path-validation.js` 已将已登记项目、工作区和当前目录作为合法 cwd 来源;
25
+ - 平台 Manifest、Registry 和 Capability Driver 已提供平台差异的扩展接缝。
26
+
27
+ 现有 `AgentsService` 中的 Agent 是代理定义文件,不等于项目指令文件 `AGENTS.md`。两者必须保持不同模块和不同 UI 语义。
28
+
29
+ ## Scope
30
+
31
+ ### Included
32
+
33
+ - 项目级指令文件的读取、编辑、保存和存在状态;
34
+ - 项目级 Skills 的列出、详情查看、创建、从仓库安装、编辑和删除;
35
+ - 项目级 MCP 的列出、从中心目录添加、编辑、测试和移除;
36
+ - 当前平台的默认选择,以及平台能力矩阵;
37
+ - SessionList 项目页的统一“项目配置”入口;
38
+ - 复用项目路径校验、原子写入、现有远程仓库和 MCP 转换逻辑;
39
+ - 配置模板通过同一项目配置写入能力工作,而不成为项目配置的事实来源;
40
+ - 项目配置 API、服务单元测试、API 测试和前端行为测试。
41
+
42
+ ### Excluded
43
+
44
+ - 不以 `workspaceId` 保存项目配置;
45
+ - 不新增项目级中心 manifest 作为事实来源;
46
+ - 不把项目配置复制到用户级目录;
47
+ - 不把 `AGENTS.md` 接入 `AgentsService`;
48
+ - 不在首版实现“禁用继承的用户级 Skill/MCP”的项目 denylist;
49
+ - 不支持在任意项目子目录自动创建多层 `AGENTS.md`;首版只管理平台声明的项目根级指令文件;
50
+ - 不改变现有用户级 MCP `/api/mcp/servers` 的响应和写入语义;
51
+ - 不通过写入一个通用但 CLI 不识别的文件来伪造平台支持。
52
+
53
+ ## Design Decisions
54
+
55
+ ### Native project files are authoritative
56
+
57
+ 项目级配置直接写入对应 CLI 的原生项目文件。中心 `~/.cc-tool` 只继续保存:
58
+
59
+ - 用户级 Skills、Agents、Commands、Plugins;
60
+ - MCP 服务器目录和预设;
61
+ - 仓库源、缓存和 UI 配置;
62
+ - 工作区元数据。
63
+
64
+ 项目级配置读取时以磁盘内容为准。项目文件被用户或其他工具手动修改后,下一次读取必须反映磁盘状态。
65
+
66
+ ### Project path is the configuration identity
67
+
68
+ 所有来自 HTTP API 的项目配置请求接收 `projectPath`,但服务内部必须执行:
69
+
70
+ ```text
71
+ validateKnownProjectCwd(projectPath)
72
+ -> realpath(projectPath)
73
+ -> platform target resolution
74
+ -> root containment validation
75
+ ```
76
+
77
+ 项目路径不能使用显示名、历史会话路由参数或工作区名称替代。一个项目加入多个工作区时仍共享同一项目配置。
78
+
79
+ 工作区创建流程中的模板应用是受控的内部调用:`workspace-service` 只把刚创建且仍由本次创建流程持有的工作区根目录传给模板写入用例,并先完成目录、项目目标和符号链接安全校验。该内部调用不能由 HTTP 请求直接设置“绕过路径校验”选项;所有外部调用仍必须通过 `validateKnownProjectCwd`。
80
+
81
+ ### “移除项目配置”不等于“禁用用户级配置”
82
+
83
+
84
+ 第一版只管理项目目录中的实际文件:
85
+
86
+ - 删除项目 Skill 只删除项目 Skill 目录;
87
+ - 删除项目 MCP 只删除项目配置中的对应 key;
88
+ - 删除项目指令文件只删除该项目文件;
89
+ - 用户级同名配置不受影响。
90
+
91
+ 如果 CLI 会在项目级配置缺失时继续使用用户级配置,移除项目项后用户级配置重新生效。第一版 UI 使用“移除项目配置”而不是含义不明确的“禁用”。
92
+
93
+ ### Project-level state is not a second registry
94
+
95
+ `.ctx-config.json` 继续作为模板应用记录,但不能决定项目当前有哪些 Skill 或 MCP。项目配置页始终扫描原生文件;模板只调用相同的项目写入用例。
96
+
97
+ ## Domain Model
98
+
99
+ ```js
100
+ ProjectConfigSnapshot {
101
+ projectPath: string, // canonical absolute realpath
102
+ platform: string,
103
+ instruction: {
104
+ supported: boolean,
105
+ path: string | null, // project-relative path
106
+ exists: boolean,
107
+ content: string,
108
+ updatedAt: number | null
109
+ },
110
+ skills: {
111
+ supported: boolean,
112
+ project: SkillSummary[],
113
+ inherited: SkillSummary[]
114
+ },
115
+ mcp: {
116
+ supported: boolean,
117
+ path: string | null,
118
+ servers: ProjectMcpServer[]
119
+ },
120
+ capabilities: {
121
+ instruction: boolean,
122
+ skills: boolean,
123
+ mcp: boolean
124
+ }
125
+ }
126
+ ```
127
+
128
+ `SkillSummary` 和 `ProjectMcpServer` 可以携带平台特有字段,但通用字段必须包含:
129
+
130
+ - `name` 或 `id`;
131
+ - `scope` (`project` 或 `user`);
132
+ - `source`;
133
+ - `installed` / `enabled`;
134
+ - 项目相对路径或原生配置路径;
135
+ - 可展示的描述和更新时间。
136
+
137
+ `inherited` 仅用于展示用户级同名或可用配置,不代表项目配置服务拥有删除权。
138
+
139
+ ## Platform Project Mapping
140
+
141
+ 平台适配器必须声明项目文件、Skill 根目录、MCP 文件和支持状态。前端消费公开能力,不硬编码路径。
142
+
143
+ | Platform | Instruction | Project skills root | Project MCP | Initial support |
144
+ | --- | --- | --- | --- | --- |
145
+ | Claude | `CLAUDE.md` | `.claude/skills/` | `.mcp.json` | instruction / skills / MCP |
146
+ | Codex | `AGENTS.md` | `.agents/skills/` | `.codex/config.toml` 的 `[mcp_servers]` | instruction / skills / MCP |
147
+ | Gemini | `GEMINI.md` | `.gemini/skills/` | `.gemini/settings.json` 的 `mcpServers` | instruction / skills / MCP |
148
+ | OpenCode | Manifest 声明的项目指令文件,默认兼容 `.opencode/AGENTS.md` | `.opencode/skills/` | `.opencode/opencode.json` | instruction / skills / MCP |
149
+ | OMP | 无单独项目指令文件 | `.omp/skills/` | `.omp/mcp.json` | skills / MCP |
150
+
151
+ 平台适配规则:
152
+
153
+ - Codex 的项目 Skill 以官方 `.agents/skills/` 为首选;读取时兼容现有代码已经发现的 `.codex/skills/`,写入时只选择一个明确的 canonical root;
154
+ - Codex 项目 MCP 写入 `.codex/config.toml`,保留其他配置和未知字段;项目配置仅在 CLI 信任项目后生效;
155
+ - Gemini 项目 MCP 修改 `.gemini/settings.json` 的 `mcpServers`,保留其他 settings;
156
+ - OpenCode 适配器读取现有 `mcp` 结构,写入时遵循当前项目 Manifest/CLI 版本所声明的结构,不能无条件把新旧格式混合;
157
+ - OMP 没有独立项目指令文件,必须返回 `instruction: unsupported`,不能生成空的 `AGENTS.md`;
158
+ - 任何平台能力无法由当前 CLI 原生文件可靠表达时,返回 `unsupported`,不能返回空成功。
159
+
160
+ ## Architecture
161
+
162
+ ```text
163
+ SessionList / Config Template / HTTP API
164
+ |
165
+ v
166
+ ProjectConfigService
167
+ (path, scope, atomic writes,
168
+ snapshot, error normalization)
169
+ |
170
+ v
171
+ Project Config Adapter Registry
172
+ |
173
+ +------------+------------+
174
+ v v v
175
+ Instructions Skills MCP
176
+ adapter target format adapter
177
+ resolver
178
+ |
179
+ v
180
+ Platform-native project files
181
+ ```
182
+
183
+ ### ProjectConfigService
184
+
185
+ 新增 `src/server/services/project-config-service.js`,作为项目级配置的应用用例层,负责:
186
+
187
+ - 规范化项目路径并拒绝未知路径;
188
+ - 根据平台获得项目配置适配器;
189
+ - 读取聚合快照;
190
+ - 统一处理 supported/unsupported/invalid/failed 结果;
191
+ - 约束所有写入目标在项目根目录内;
192
+ - 使用临时文件加 rename 的原子写入;
193
+ - 让配置模板、项目配置 API 和未来批量操作复用同一写入入口。
194
+
195
+ 该模块的公开接口保持小而稳定:
196
+
197
+ ```text
198
+ getSnapshot(projectPath, platform)
199
+ readInstruction(projectPath, platform)
200
+ writeInstruction(projectPath, platform, content)
201
+ listProjectSkills(projectPath, platform)
202
+ installProjectSkill(projectPath, platform, input)
203
+ removeProjectSkill(projectPath, platform, name)
204
+ listProjectMcp(projectPath, platform)
205
+ upsertProjectMcp(projectPath, platform, id, spec)
206
+ removeProjectMcp(projectPath, platform, id)
207
+ testProjectMcp(projectPath, platform, id)
208
+ ```
209
+
210
+ 调用方不直接拼接 `.claude`、`.codex`、`.gemini`、`.opencode` 或 `.omp` 路径。
211
+
212
+ ### Platform adapters
213
+
214
+ 新增 `src/server/services/project-config-adapters/`。每个适配器只处理一个平台的原生差异:
215
+
216
+ - `describe()`:公开相对路径、能力和格式;
217
+ - `readInstruction()` / `writeInstruction()`;
218
+ - Skill 项目根目录和同名覆盖规则;
219
+ - MCP 配置读取、规范化、合并、写入和删除;
220
+ - 平台特有错误转换。
221
+
222
+ 适配器不访问 HTTP,不操作 UI,不修改用户级中心 MCP 记录。
223
+
224
+ ### Skills integration
225
+
226
+ 现有 `SkillService` 继续负责远程仓库扫描、下载、Skill 内容解析和通用安全校验。项目配置服务为它提供明确的安装目标:
227
+
228
+ ```js
229
+ { scope: 'project', cwd: canonicalProjectPath }
230
+ ```
231
+
232
+ 需要补齐的行为:
233
+
234
+ - 所有支持的平台均能列出项目 Skill;
235
+ - `listSkills` 的缓存 key 包含 `platform + scope + canonical cwd`;
236
+ - 项目 Skill 与用户 Skill 的列表具有明确 `scope`;
237
+ - 安装、创建、编辑和删除只对项目目标目录生效;
238
+ - `getSkillDetail`、文件读写和删除操作都接受相同作用域;
239
+ - 不能通过项目操作修改 `PATHS.localSkills` 或用户级安装目录。
240
+
241
+ 如果继续扩展 `SkillService` 会让全局实现与项目实现互相污染,可将下载逻辑提取为内部 artifact helper,但不新增第二套远程仓库协议。
242
+
243
+ ### MCP integration
244
+
245
+ 新项目 MCP 用例与现有全局 MCP 用例分开:
246
+
247
+ - 现有 `mcp-service.js` 的中心目录、`apps` 平台开关和用户级同步保持原义;
248
+ - 项目适配器读取项目原生配置并把 server spec 规范化为通用 DTO;
249
+ - 从中心目录添加只复制 server spec,不改变中心记录的 app flags;
250
+ - 编辑项目 MCP 只修改项目原生文件;
251
+ - 项目测试直接使用项目配置中的 spec,并以项目路径作为 stdio 默认 cwd;
252
+ - 返回前端的 secrets、静态 token、环境变量值和认证 headers 必须脱敏。
253
+
254
+ MCP 写入必须是结构化合并:只修改目标服务器 key,保留其他顶层字段、schema 字段和未知配置。
255
+
256
+ ## HTTP API
257
+
258
+ ### Aggregate read
259
+
260
+ ```text
261
+ GET /api/project-config?projectPath=<absolute>&platform=<platform>
262
+ ```
263
+
264
+ 返回 `ProjectConfigSnapshot`。`platform` 缺失时使用当前页面平台或服务端默认平台;服务端不能把一个平台的路径当作另一个平台的路径。
265
+
266
+ ### Instructions
267
+
268
+ ```text
269
+ GET /api/project-config/instruction?projectPath=...&platform=...
270
+ PUT /api/project-config/instruction
271
+ Body: { projectPath, platform, content }
272
+ ```
273
+
274
+ PUT 返回规范化相对路径、更新时间和是否创建文件。空内容的语义是写入空文件,不代表删除;删除需要显式 DELETE。
275
+
276
+ ### Skills
277
+
278
+ 现有 `/api/skills` 继续保持用户级默认行为,并扩展项目操作使用明确作用域:
279
+
280
+ ```text
281
+ GET /api/skills?platform=...&cwd=...&scope=project
282
+ POST /api/skills/install
283
+ { platform, cwd, scope: 'project', directory, fullDirectory, repo }
284
+ POST /api/skills/create
285
+ { platform, cwd, scope: 'project', name, directory, description, content }
286
+ POST /api/skills/uninstall
287
+ { platform, cwd, scope: 'project', directory }
288
+ ```
289
+
290
+ 详情和文件 CRUD 也必须接收 `cwd/scope`,不能只在卸载接口支持项目路径。
291
+
292
+ ### MCP
293
+
294
+ 新增明确的项目级端点:
295
+
296
+ ```text
297
+ GET /api/project-config/mcp?projectPath=...&platform=...
298
+ PUT /api/project-config/mcp/:id
299
+ { projectPath, platform, server }
300
+ DELETE /api/project-config/mcp/:id
301
+ { projectPath, platform }
302
+ POST /api/project-config/mcp/:id/test
303
+ { projectPath, platform }
304
+ ```
305
+
306
+ 添加中心目录服务器时,前端先取中心 `mcp-service` 数据,再调用项目 upsert。项目接口不接收或返回中心 `apps` 状态作为项目启用状态。
307
+
308
+ 所有接口统一:
309
+
310
+ - 使用 `validateKnownProjectCwd`;
311
+ - 对平台、scope、资源名和 server spec 做输入校验;
312
+ - `unsupported` 使用 200 加结构化状态返回,参数错误和路径越界使用 400/403;
313
+ - 错误响应不包含未经脱敏的配置值。
314
+
315
+ ## Web UI
316
+
317
+ 在 `src/web/src/views/SessionList.vue` 的项目标题区,把“项目配置”放在现有“管理”按钮旁边。
318
+
319
+ 组件建议:
320
+
321
+ ```text
322
+ ProjectConfigDrawer.vue
323
+ ProjectConfigHeader
324
+ ProjectInstructionPanel
325
+ ProjectSkillsPanel
326
+ ProjectMcpPanel
327
+ ```
328
+
329
+ 组件接收:
330
+
331
+ ```js
332
+ {
333
+ projectPath: String, // store.currentProjectInfo.fullPath
334
+ platform: String // currentChannel
335
+ }
336
+ ```
337
+
338
+ 界面规则:
339
+
340
+ - 默认平台跟随当前历史会话平台;
341
+ - 可切换到其他已启用平台;
342
+ - 每个页签显示 capability 状态和原生目标路径;
343
+ - 项目资源显示“项目级”,用户级同名资源显示“继承”;
344
+ - 对不支持的平台显示原因和只读状态,不显示可提交的假表单;
345
+ - 保存前端指令内容时显示目标文件,MCP/Skill 删除需要显式确认;
346
+ - 不在 `ProjectCard` 先复制第二个完整入口,避免与卡片点击和删除操作冲突;
347
+ - 如果将来需要从项目卡片快捷进入,只复用同一个抽屉和相同的 `projectPath`。
348
+
349
+ SessionList 目前使用 `projectName` 作为路由参数,但已有 `store.currentProjectInfo.fullPath` 作为完整路径来源。项目配置请求必须使用后者,并在数据尚未加载时等待项目解析完成。
350
+
351
+ ## Template Integration
352
+
353
+ `config-templates-service.js` 的模板仍可一次性应用项目配置,但写入必须迁移到 `ProjectConfigService`:
354
+
355
+ - AI 指令配置调用 `writeInstruction`;
356
+ - Skills 调用项目 Skill 安装用例;
357
+ - MCP 调用项目 MCP upsert;
358
+ - 模板结果保留 applied/skipped 统计;
359
+ - `.ctx-config.json` 只记录模板应用来源和结果,不作为资源列表;
360
+ - 现有用户级模板应用路径保持兼容。
361
+
362
+ 迁移期间,旧模板逻辑可保留内部转换函数,但同一项目配置不能同时由两套写入实现竞争。
363
+
364
+ ## Security and Error Handling
365
+
366
+ ### Path safety
367
+
368
+ 每个来自 HTTP API 的项目写入都必须满足:
369
+
370
+ - 输入为绝对目录;
371
+ - 目录属于 `getKnownProjectPaths()`;
372
+ - 使用 `realpath` 后仍为合法项目;
373
+ - 目标相对路径不能包含 `..`、绝对路径或 NUL;
374
+ - 目标根目录及已有路径组件不能通过符号链接逃逸;
375
+ - 服务端不接受前端传入的任意目标文件路径作为写入位置。
376
+
377
+ 工作区创建中的内部模板调用可以使用刚创建的工作区根目录,但只能由 `workspace-service` 在完成项目目标和符号链接校验后传递受控根目录;HTTP 请求不能传入绕过校验的标志或任意 target root。
378
+
379
+ 同时修复 `src/server/api/workspaces.js` 的 `/read-file`:允许文件名校验之外,必须验证文件位于已登记工作区或项目根目录内。
380
+
381
+ ### Atomic and non-destructive writes
382
+
383
+ - 文本、JSON 和 TOML 写入使用临时文件加 rename;
384
+ - JSON/TOML 修改采用读-改-写,保留未知字段;
385
+ - 项目 Skill 删除不触碰用户目录;
386
+ - 全局 MCP 删除不由项目 MCP 路由触发;
387
+ - 写入失败必须向调用方返回明确错误,不能记录成功状态或只打印日志。
388
+
389
+ ### Secrets
390
+
391
+ - 项目 MCP 配置中的环境变量值、静态 token 和 headers 只在本地文件中使用;
392
+ - API 响应默认返回是否存在和脱敏预览,不返回完整 secret;
393
+ - UI 提醒把静态 secret 写入项目文件可能进入 Git;
394
+ - 测试日志和错误对象不能打印完整 MCP spec。
395
+
396
+ ## Verification Plan
397
+
398
+ ### Service tests
399
+
400
+ 新增或扩展服务测试,覆盖:
401
+
402
+ 1. 项目路径必须来自已知项目,未知路径、文件路径、相对路径和路径穿越均失败;
403
+ 2. 指令文件按平台读写,OMP 返回 unsupported;
404
+ 3. 项目 Skills 的列表、缓存、同名覆盖和删除作用域正确;
405
+ 4. Codex 使用 `.agents/skills` canonical root,并兼容读取旧探测目录;
406
+ 5. Skills 项目安装不会写入用户级安装目录;
407
+ 6. 各平台 MCP 读写只修改目标 key,并保留未知字段;
408
+ 7. Codex 项目 MCP 写入 `.codex/config.toml` 的 `[mcp_servers]`;
409
+ 8. 项目 MCP 测试使用项目 cwd;
410
+ 9. 项目 MCP 变更不会调用全局中心记录写入,也不会修改 `apps`;
411
+ 10. secret 脱敏结果不包含原始值;
412
+ 11. 原子写入失败返回失败状态,不留下伪成功记录。
413
+
414
+ ### API tests
415
+
416
+ 覆盖:
417
+
418
+ - aggregate snapshot 的平台和 scope;
419
+ - projectPath 规范化及未知路径拒绝;
420
+ - instruction/skills/MCP 的成功、unsupported、invalid 和 failed 状态;
421
+ - MCP 项目路由不会改变旧全局 MCP API 的结果;
422
+ - `/api/workspaces/read-file` 不能读取工作区外的允许 basename 文件;
423
+ - 远程写入策略继续遵循现有服务配置。
424
+
425
+ ### Web tests
426
+
427
+ 覆盖:
428
+
429
+ - SessionList 使用 `currentProjectInfo.fullPath` 打开项目配置;
430
+ - 当前平台默认选择正确;
431
+ - 平台切换会重新加载项目快照;
432
+ - unsupported 能力不显示提交控件;
433
+ - 删除项目资源不会触发会话删除或工作区删除;
434
+ - 快速连续打开不同项目时,旧请求结果不会覆盖当前项目状态。
435
+
436
+ ### Smoke scenario
437
+
438
+ 使用临时 Git 项目和五个平台的临时配置目录执行:
439
+
440
+ 1. 从项目历史页打开“项目配置”;
441
+ 2. 创建并保存项目指令;
442
+ 3. 安装一个项目 Skill,刷新页面后仍可见;
443
+ 4. 添加、测试、移除一个项目 MCP;
444
+ 5. 手动修改原生文件,刷新页面后看到手动修改;
445
+ 6. 启动对应 CLI 的项目 cwd,确认 CLI 能读取已支持的项目文件;
446
+ 7. 检查用户级 MCP、Skill 和其他项目文件未被改动。
447
+
448
+ ## Migration and Rollout
449
+
450
+ 1. 先增加平台项目能力声明、路径校验和 `ProjectConfigService` 读快照能力;
451
+ 2. 接入 Codex `AGENTS.md` 和 Codex 项目 `.codex/config.toml`,同时完成通用适配器接口;
452
+ 3. 接入五个平台的项目 Skills,统一现有 OMP `cwd` 语义;
453
+ 4. 接入五个平台的项目 MCP;不支持的格式保持显式 unsupported;
454
+ 5. 将 SessionList 项目入口接入聚合 API;
455
+ 6. 将配置模板写入路径切换到项目配置服务;
456
+ 7. 修复工作区文件读取路径边界;
457
+ 8. 完成服务、API、Web 测试和真实 CLI smoke;
458
+ 9. 在确认新路径行为稳定后,删除旧的项目级重复写入分支。
459
+
460
+ 不需要迁移已有用户级配置,也不需要修改现有 `workspaces.json` 数据格式。
461
+
462
+ ## References
463
+
464
+ - Codex project configuration: <https://developers.openai.com/codex/config-reference>
465
+ - Codex MCP configuration: <https://developers.openai.com/codex/mcp>
466
+ - Codex project Skills: <https://developers.openai.com/codex/skills>
467
+ - Open Agent Skills specification: <https://agentskills.io/specification>
@@ -0,0 +1,111 @@
1
+ # Claude Code 会话内容读取修复设计
2
+
3
+ ## 问题
4
+
5
+ Claude Code 项目和会话列表偶发为空;进入项目后,详情提示“暂未读取到对话内容”,或所有消息为空;内容搜索也无法命中。该现象只影响 Claude Code。
6
+
7
+ ## 根因证据
8
+
9
+ Claude Code 的 JSONL 记录把实际消息放在 `json.message` 下:
10
+
11
+ - 用户消息内容位于 `json.message.content`;
12
+ - 助手消息内容、模型和消息 ID 也位于嵌套消息对象;
13
+ - 当前 `src/server/services/session-history-adapters/claude.js` 主要读取顶层 `json.content`、`json.model` 等字段。
14
+
15
+ 因此历史索引能够发现文件,却把真实消息写成空内容,导致首条消息为空、全文搜索无结果、详情索引直接返回空消息。旧的直读路径已经按嵌套字段解析,但索引快捷路径会优先截获请求。
16
+
17
+ 另外,已有索引按文件大小和 mtime 判断是否需要解析。仅修复解析器不会自动修复已经写入数据库的空消息。详情直读回退还依赖 `hasActualMessages`,该导出在索引重构后丢失。
18
+
19
+ ## 目标
20
+
21
+ 1. 正确读取当前 Claude Code JSONL 的嵌套用户和助手消息。
22
+ 2. 自动修复已有的旧格式空索引,不要求用户手工删除数据库。
23
+ 3. 保证索引未完成时不会把临时空结果当成最终空列表或空详情。
24
+ 4. 保留已有索引的快速读取和分页能力。
25
+ 5. 对索引未命中、旧文件或仅包含文件快照的会话,提供可靠的直读回退。
26
+ 6. 用回归测试锁定嵌套消息、旧索引重解析、搜索和详情行为。
27
+
28
+ ## 非目标
29
+
30
+ - 不改变 Codex、Gemini、OpenCode 或 OMP 的会话格式。
31
+ - 不重新设计项目/会话列表 UI。
32
+ - 不在启动时无条件删除整个历史数据库。
33
+ - 不改变 Claude Code 原始 JSONL 文件。
34
+
35
+ ## 设计
36
+
37
+ ### 1. 统一 Claude 消息归一化契约
38
+
39
+ 在 `src/server/services/session-history-adapters/claude.js` 中统一定义索引所需的 Claude JSONL 字段读取规则:
40
+
41
+ - envelope 的 `type` 和嵌套 `message.role` 共同确定角色;
42
+ - 内容读取 `json.content ?? json.message.content`;
43
+ - ID、模型、provider、时间戳读取顶层字段,并以嵌套消息字段作为回退;
44
+ - 字符串内容直接保留;数组内容提取文本、图片、工具调用、工具结果和思考块,保持现有 UI 可展示的文本语义;
45
+ - 用户消息的 `userMessageNumber` 只在存在实际可展示用户文本时递增;
46
+ - `firstMessage` 取第一条非空用户文本;
47
+ - 元数据记录仍跳过,不把 `summary`、`file-history-snapshot` 等非对话记录当成正常聊天内容。
48
+
49
+ 详情直读路径继续使用现有嵌套字段解析,并按相同字段优先级和可展示内容规则输出。两条路径共享同一归一化契约,避免列表、搜索、详情显示不同内容。
50
+
51
+ ### 2. 为索引行增加解析格式版本
52
+
53
+ 在 `session_file` 增加 `parser_version` 整数字段,并定义按 source 区分的当前 session parser 版本:
54
+
55
+ - 初始化旧数据库时通过 `PRAGMA table_info` 检测缺失字段,再执行兼容的 `ALTER TABLE`;旧行默认版本为 `0`;
56
+ - 新写入行记录该 source 的当前 parser 版本;
57
+ - inventory 比较文件 fingerprint 时同时比较 parser 版本;版本过旧即使 size/mtime 未变也重新解析;
58
+ - 只重解析受影响的 session 文件,不清空其他平台索引;
59
+ - 重新解析完成后再更新 source freshness,避免半成品被当成新鲜数据。
60
+
61
+ 这样用户升级后下一次访问会自动回填历史消息,且不会依赖手工清理 `session-history.sqlite`。
62
+
63
+
64
+ ### 3. 冷启动与索引回退
65
+
66
+ 保留已有数据时的 `stale-ok` 快速路径,但收紧“无数据”场景:
67
+
68
+ - list projects、list sessions、recent 和 detail 查询在发现对应数据不存在且该 source 有进行中的 inventory 时,等待同一个 in-flight inventory 完成;
69
+ - inventory 失败时向上抛出错误,不返回可缓存的空成功结果;
70
+ - 已有旧数据仍可先展示,并由后台刷新更新;真正没有会话时,只有 inventory 完成后才返回空列表;
71
+ - `getSessionStatus`、`getSessionOutline`、`getMessagePage` 在索引 miss 后允许 API 继续走原始文件回退。
72
+
73
+ 项目/会话 snapshot 只缓存已完成的有效 payload;后台刷新中的 fallback 仍带有 `refreshing`/`stale` 元数据,前端保持加载状态并继续已有轮询机制。
74
+
75
+ ### 4. 恢复 Claude 原始文件回退
76
+
77
+ 在 `src/server/services/sessions.js` 恢复并导出 `hasActualMessages(filePath)`,判断文件中是否存在真实 user/assistant 对话记录,而不是只存在文件历史快照。详情 API 在索引未命中时继续走现有直读路径;该路径读取嵌套消息内容、工具结果和分页数据。
78
+
79
+ Claude 全局搜索对 Claude source 的索引错误不再静默吞掉并伪装成“没有匹配”;其他平台仍可按现有 best-effort 规则处理。这样用户能看到实际错误,而不是误判搜索为空。
80
+
81
+ ## 数据流
82
+
83
+ ```text
84
+ Claude JSONL
85
+ -> Claude adapter(解析 json.message + 版本标记)
86
+ -> session-history.sqlite
87
+ -> projects/sessions/search/detail API
88
+ -> 前端列表、搜索结果、ChatHistoryDrawer
89
+ ```
90
+
91
+ 详情请求优先读取索引;索引 miss、文件不完整或索引读取失败时回到原始 JSONL。索引版本变更触发一次增量重解析,不改变源文件。
92
+
93
+ ## 错误处理
94
+
95
+ - 单个损坏 JSONL 行沿用跳过策略;单个文件解析失败不阻塞同 source 的其他有效文件,并记录 source error。
96
+ - 索引写入保持现有事务语义,写入失败整体回滚。
97
+ - worker、adapter 和 API 保留结构化错误上下文;不使用空数组作为失败 fallback。
98
+ - 仅文件快照的会话不会被当作有聊天内容的详情返回。
99
+
100
+ ## 测试策略
101
+
102
+ 新增或补充以下行为测试,均先写成失败测试再实现:
103
+
104
+ 1. Claude adapter 能从嵌套 `message.content` 读取用户/助手文本、ID、模型和工具块,且生成正确 `firstMessage` 与用户序号。
105
+ 2. 已有 `parser_version` 过旧的 session 在文件 size/mtime 不变时仍会重新解析,并可被搜索和详情读取。
106
+ 3. 冷启动 inventory 尚未完成时,列表/详情不会提前稳定返回空数据;inventory 完成后返回真实记录。
107
+ 4. 索引 miss 时,详情 API 的直读回退能读取嵌套消息;仅文件快照会返回明确的无对话响应。
108
+ 5. Claude 内容搜索能命中嵌套用户/助手文本,索引失败会暴露错误而不是返回空结果。
109
+ 6. 现有项目、会话分页、删除、实时状态和非 Claude 平台测试保持通过。
110
+
111
+ 验证顺序:针对性单测红灯 → 最小实现绿灯 → 受影响测试集 → 启动实际 Web API,验证项目列表、会话列表、搜索和打开详情四条路径。
@@ -0,0 +1,83 @@
1
+ # OMP Skill Refresh Boundary Design
2
+
3
+ ## Problem
4
+
5
+ Opening the OMP surface must not start a remote Skill repository refresh. A Skill panel load is a local scan; remote repository work is an explicit user action. The current source already sends `GET /api/skills` on panel load and reserves `POST /api/skills/refresh` for `handleRefresh`, but this invariant is not explicit in the component naming and lacks an OMP-specific mount regression test. A stale running process or stale packaged Web bundle can therefore look like a source regression.
6
+
7
+ Observed behavior in the current workspace:
8
+
9
+ - Entering `/cli/omp` produced `GET /api/skills?platform=omp&scope=user`.
10
+ - Opening the Skills drawer produced the same scan request.
11
+ - Neither flow produced `POST /api/skills/refresh`.
12
+ - The OMP route separately schedules `GET /api/channel-balances?source=omp`; that is a balance probe, not Skill refresh, and remains out of scope for this change.
13
+
14
+ ## Goals
15
+
16
+ - Make local Skill scanning and remote refresh separate, named operations in `SkillsPanel.vue`.
17
+ - Guarantee every lifecycle path (mount, drawer open, platform/scope change, repository update, local Skill creation, and post-settings-save reload) uses the scan-only operation.
18
+ - Keep the manual `刷新远端` button as the only UI path that enqueues a remote refresh task.
19
+ - Preserve the existing asynchronous refresh-task polling and post-task local scan.
20
+ - Lock the behavior with frontend and server regression tests.
21
+ - Rebuild the ignored production bundle as part of verification so deployment uses the current client code.
22
+
23
+ ## Non-goals
24
+
25
+ - No change to OMP channel balance probing.
26
+ - No change to plugin marketplace discovery.
27
+ - No change to refresh task persistence, scheduling, repository adapters, or Skill control semantics.
28
+ - No compatibility shim for the removed legacy `getSkills(forceRefresh, platform)` signature.
29
+
30
+ ## Design
31
+
32
+ ### Frontend boundary
33
+
34
+ Rename the current generic `loadData` operation to `scanLocalSkills`. It accepts only presentation/error options and calls `getSkills(platform, scopeOptions)`. All non-user-refresh callers use this function:
35
+
36
+ - component mount for standalone mode;
37
+ - drawer visibility transition;
38
+ - platform, scope, or project-path changes;
39
+ - repository, create, and detail update events;
40
+ - successful OMP settings save.
41
+
42
+ Keep `handleRefresh` as the only remote operation. It calls `refreshSkills(platform, scopeOptions)`, polls the returned task while queued/running, then calls `scanLocalSkills()` after the task reaches a terminal state. It must not pass a force flag to the scan function.
43
+
44
+ This is a naming and call-graph boundary, not a new abstraction layer: the existing request APIs and state remain unchanged.
45
+
46
+ ### Server boundary
47
+
48
+ Keep `GET /api/skills` scan-only. It calls `service.scanSkills(options)` and ignores any legacy `refresh` query value. Keep `POST /api/skills/refresh` as the sole route that enqueues `SkillRefreshTaskService` work. Add an OMP-specific assertion in the API tests that a GET with `refresh=1` calls `scanSkills` and never calls `refreshRemoteSkills`.
49
+
50
+ ### Data flow
51
+
52
+ ```text
53
+ panel mount/open/change
54
+ -> scanLocalSkills
55
+ -> GET /api/skills (local scan)
56
+ -> render cached/native/control state
57
+
58
+ manual 刷新远端 click
59
+ -> handleRefresh
60
+ -> POST /api/skills/refresh
61
+ -> poll GET /api/skills/refresh/:taskId
62
+ -> scanLocalSkills
63
+ -> render newly cached state
64
+ ```
65
+
66
+ ### Error handling
67
+
68
+ - Local scan errors keep the existing notification behavior and request-generation guard.
69
+ - Remote task errors keep the existing failed/partial messages.
70
+ - Switching platform/scope while a refresh is pending continues to invalidate its context and suppress stale results; no new remote task is created by the subsequent scan.
71
+ - No debug instrumentation or additional fallback network request is added.
72
+
73
+ ## Tests
74
+
75
+ 1. Frontend OMP SkillsPanel mount, both standalone and drawer-visible paths, asserts `getSkills` is called and `refreshSkills` is not called.
76
+ 2. Frontend OMP drawer visibility transition asserts opening the drawer performs only a scan and does not enqueue refresh.
77
+ 3. Existing manual refresh test continues to assert one explicit `refreshSkills` call and a post-task scan.
78
+ 4. Server Skills API test with `platform=omp&refresh=1` asserts scan-only behavior and no `refreshRemoteSkills` call.
79
+ 5. Run focused frontend/server tests and build `src/web` to verify the deployed bundle contains the scan-only request path.
80
+
81
+ ## Rollout and verification
82
+
83
+ The source change is committed separately from this design. Because `dist/` is ignored and packaged by `prepack`, deployment must rebuild the Web UI and restart the backend process; an already-running process or old package cannot be used as evidence for the new source.