coding-tool-x 3.8.4 → 3.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +86 -15
- package/dist/web/assets/AgentsDrawer-BG6P3DX-.js +1 -0
- package/dist/web/assets/AgentsDrawer-Pw2k-ZAa.css +1 -0
- package/dist/web/assets/Analytics--z_FmL5P.js +1 -0
- package/dist/web/assets/Analytics-CyHhR126.css +1 -0
- package/dist/web/assets/AssetPathField-CrJtRKHy.js +1 -0
- package/dist/web/assets/ChatHistoryDrawer-B2qBQs9L.css +1 -0
- package/dist/web/assets/ChatHistoryDrawer-BiuEryJj.js +1 -0
- package/dist/web/assets/CollapseItem-BAYEsL_Q.js +1 -0
- package/dist/web/assets/CommandsDrawer-BZJxlPvV.css +1 -0
- package/dist/web/assets/CommandsDrawer-YJ-U7BXN.js +1 -0
- package/dist/web/assets/ConfigExportDrawer-Ce_hAknW.js +1 -0
- package/dist/web/assets/ConfigExportDrawer-dwruRKWr.css +1 -0
- package/dist/web/assets/ConfigTemplates-Bvr1NN6K.js +1 -0
- package/dist/web/assets/ConfigTemplatesDrawer-BfDi8yO3.css +1 -0
- package/dist/web/assets/ConfigTemplatesDrawer-BjIeHfF-.js +1 -0
- package/dist/web/assets/ConfigTemplatesPanel-AV00tm_D.js +1 -0
- package/dist/web/assets/ConfigTemplatesPanel-CWyPtk67.css +1 -0
- package/dist/web/assets/Divider-D28g1gwj.js +1 -0
- package/dist/web/assets/DrawerContent-ChXgZ1Xm.js +1 -0
- package/dist/web/assets/FavoritesDrawer-CG9eI9Ay.css +1 -0
- package/dist/web/assets/FavoritesDrawer-Cz95o4CD.js +1 -0
- package/dist/web/assets/GatewayConvertDrawer-CuNlf7AC.css +1 -0
- package/dist/web/assets/GatewayConvertDrawer-DLlbMz27.js +1 -0
- package/dist/web/assets/Home-CSuFuJ9Y.css +1 -0
- package/dist/web/assets/Home-D7CCOFQC.js +1 -0
- package/dist/web/assets/MarkdownEditor-qfVgSre_.css +1 -0
- package/dist/web/assets/MarkdownEditor-rEZ-c72L.js +1 -0
- package/dist/web/assets/McpDrawer-C0dnsZhQ.css +1 -0
- package/dist/web/assets/McpDrawer-DfoCyxU2.js +1 -0
- package/dist/web/assets/McpFormDrawer-BRbDcawn.css +1 -0
- package/dist/web/assets/McpFormDrawer-SKu8HNUR.js +1 -0
- package/dist/web/assets/PluginManager-BbeK-3rV.js +1 -0
- package/dist/web/assets/PluginsDrawer-CWVJ7yjS.js +1 -0
- package/dist/web/assets/PluginsDrawer-DM3QjprE.css +1 -0
- package/dist/web/assets/PluginsPanel-Cm2N3StG.js +1 -0
- package/dist/web/assets/PluginsPanel-D6ZqITcR.css +1 -0
- package/dist/web/assets/ProjectList-677RLZ8O.css +1 -0
- package/dist/web/assets/ProjectList-CsjnsNPv.js +1 -0
- package/dist/web/assets/PromptsDrawer-BIgiYCEQ.css +1 -0
- package/dist/web/assets/PromptsDrawer-EGd3djFa.js +1 -0
- package/dist/web/assets/RecentSessionsDrawer-CKFsOYDM.css +1 -0
- package/dist/web/assets/RecentSessionsDrawer-D1vtoLAs.js +1 -0
- package/dist/web/assets/SessionCard-BgLg49U3.js +1 -0
- package/dist/web/assets/SessionCard-aM2NHu6i.css +1 -0
- package/dist/web/assets/SessionList-BpYRz1cX.css +1 -0
- package/dist/web/assets/SessionList-TRiTklWk.js +1 -0
- package/dist/web/assets/SettingsDrawer-d5liXjHq.css +1 -0
- package/dist/web/assets/SettingsDrawer-rz2WejGY.js +1 -0
- package/dist/web/assets/SkillManager-BTjTUbHq.js +1 -0
- package/dist/web/assets/SkillManager-C0GCT2Kb.css +1 -0
- package/dist/web/assets/SkillsDrawer-BCNme-aJ.css +1 -0
- package/dist/web/assets/SkillsDrawer-pN0hbkK3.js +1 -0
- package/dist/web/assets/SkillsPanel-B3Nm5j32.css +1 -0
- package/dist/web/assets/SkillsPanel-gmBWEoiF.js +1 -0
- package/dist/web/assets/SpeedTestDrawer-Dc0WToJ_.css +1 -0
- package/dist/web/assets/SpeedTestDrawer-DcNzuVJk.js +1 -0
- package/dist/web/assets/Upload-v5rV0qTT.js +1 -0
- package/dist/web/assets/WorkspaceDrawer-CGnMu9p1.css +1 -0
- package/dist/web/assets/WorkspaceDrawer-DxmicM4U.js +1 -0
- package/dist/web/assets/WorkspaceManager-CJHCjARN.js +1 -0
- package/dist/web/assets/WorkspacePanel-D0-zHTHP.css +1 -0
- package/dist/web/assets/WorkspacePanel-D8_Zq-du.js +1 -0
- package/dist/web/assets/_plugin-vue_export-helper-BeLZJZij.js +1 -0
- package/dist/web/assets/client-UDwXBP9i.js +1 -0
- package/dist/web/assets/clipboard-B46yyoz_.js +1 -0
- package/dist/web/assets/headers-cf-QapUq.js +1 -0
- package/dist/web/assets/icons-B2Vg-IOC.js +1 -0
- package/dist/web/assets/index-C0EHRym0.css +1 -0
- package/dist/web/assets/index-DnEocV0M.js +2 -0
- package/dist/web/assets/light-Cp0t7v32.js +1 -0
- package/dist/web/assets/markdown-u082bbtj.js +1 -0
- package/dist/web/assets/platforms-CBkB45JP.js +1 -0
- package/dist/web/assets/platforms-FTpjxAT6.js +1 -0
- package/dist/web/assets/project-config-B2baPzYL.js +1 -0
- package/dist/web/assets/sessions-Cmy31slD.js +1 -0
- package/dist/web/assets/sessions-yC_oVVh8.js +1 -0
- package/dist/web/assets/skill-repo-input-B_fkGlUK.js +1 -0
- package/dist/web/assets/use-lock-html-scroll-DXIqmUW4.js +1 -0
- package/dist/web/assets/use-message-DoLM8C1C.js +1 -0
- package/dist/web/assets/useResponsiveDrawer-B3uojyvV.js +1 -0
- package/dist/web/assets/vendors-D0c_0KLP.js +1 -0
- package/dist/web/assets/vue-vendor-BqZbbXHA.js +1 -0
- package/dist/web/assets/workspaces-mjyPVGS8.js +1 -0
- package/dist/web/assets/xml-CgY3RMlX.js +1 -0
- package/dist/web/index.html +12 -8
- package/docs/native-log-memory-2026-09-16.md +43 -0
- package/docs/superpowers/plans/2026-08-26-configuration-driven-cli-platform.md +1578 -0
- package/docs/superpowers/plans/2026-08-30-project-scoped-config-control.md +1260 -0
- package/docs/superpowers/plans/2026-09-01-omp-skill-refresh-boundary.md +213 -0
- package/docs/superpowers/plans/2026-09-01-realtime-logs-panel.md +125 -0
- package/docs/superpowers/plans/2026-09-02-config-driven-platform-boundary.md +86 -0
- package/docs/superpowers/plans/2026-09-02-platform-implementation-drivers.md +508 -0
- package/docs/superpowers/plans/2026-09-03-cli-platform-correctness-boundary.md +760 -0
- package/docs/superpowers/plans/2026-09-03-dependency-security-remediation.md +133 -0
- package/docs/superpowers/plans/2026-09-04-model-catalog-pricing-sync.md +1078 -0
- package/docs/superpowers/plans/2026-09-05-codex-project-scan-500.md +128 -0
- package/docs/superpowers/plans/2026-09-06-project-skill-path-fix.md +97 -0
- package/docs/superpowers/specs/2026-08-26-configuration-driven-cli-platform-design.md +408 -0
- package/docs/superpowers/specs/2026-08-30-project-scoped-config-control-design.md +467 -0
- package/docs/superpowers/specs/2026-09-01-claude-session-content-repair-design.md +111 -0
- package/docs/superpowers/specs/2026-09-01-omp-skill-refresh-boundary-design.md +83 -0
- package/docs/superpowers/specs/2026-09-01-realtime-logs-panel-design.md +27 -0
- package/docs/superpowers/specs/2026-09-02-config-driven-platform-boundary-design.md +64 -0
- package/docs/superpowers/specs/2026-09-02-platform-implementation-driver-boundary-design.md +123 -0
- package/docs/superpowers/specs/2026-09-03-cli-platform-correctness-boundary-design.md +249 -0
- package/docs/superpowers/specs/2026-09-03-dependency-security-remediation-design.md +87 -0
- package/docs/superpowers/specs/2026-09-04-model-catalog-pricing-sync-design.md +301 -0
- package/docs/superpowers/specs/2026-09-05-codex-project-scan-500-design.md +24 -0
- package/package.json +8 -4
- package/src/commands/channels.js +88 -191
- package/src/commands/cli-type.js +19 -11
- package/src/commands/daemon.js +94 -32
- package/src/commands/doctor.js +16 -9
- package/src/commands/export-config.js +23 -5
- package/src/commands/list.js +130 -52
- package/src/commands/logs.js +44 -27
- package/src/commands/platform-command-registry.js +78 -0
- package/src/commands/plugin.js +11 -5
- package/src/commands/port-config.js +34 -52
- package/src/commands/proxy-control.js +207 -145
- package/src/commands/proxy.js +2 -2
- package/src/commands/resume.js +87 -91
- package/src/commands/search.js +137 -67
- package/src/commands/stats.js +30 -22
- package/src/commands/switch.js +1 -1
- package/src/commands/toggle-proxy.js +94 -111
- package/src/commands/ui.js +67 -6
- package/src/commands/workspace.js +90 -8
- package/src/config/default.js +6 -53
- package/src/config/loader.js +61 -24
- package/src/config/model-metadata.js +49 -59
- package/src/config/model-metadata.json +4095 -99
- package/src/config/paths.js +181 -8
- package/src/index.js +134 -71
- package/src/platforms/access.js +196 -0
- package/src/{server/services → platforms}/agents-service.js +354 -197
- package/src/platforms/channel-auth-registry.js +162 -0
- package/src/platforms/channel-auth-service.js +82 -0
- package/src/{server/services → platforms}/commands-service.js +195 -115
- package/src/platforms/driver-registry.js +59 -0
- package/src/platforms/drivers/claude/api-operations.js +62 -0
- package/src/{server/services/channels.js → platforms/drivers/claude/channels-implementation.js} +131 -33
- package/src/platforms/drivers/claude/channels.js +39 -0
- package/src/{server/services/config-sync-service.js → platforms/drivers/claude/config-sync.js} +29 -5
- package/src/{server/services → platforms/drivers/claude}/health-check.js +4 -4
- package/src/platforms/drivers/claude/health.js +22 -0
- package/src/platforms/drivers/claude/mcp.js +9 -0
- package/src/{server/services/settings-manager.js → platforms/drivers/claude/native-config-implementation.js} +13 -4
- package/src/platforms/drivers/claude/native-config.js +46 -0
- package/src/platforms/drivers/claude/native-logs.js +72 -0
- package/src/{server/services/claude-openai-gateway.js → platforms/drivers/claude/openai-gateway.js} +8 -65
- package/src/platforms/drivers/claude/project-config.js +21 -0
- package/src/platforms/drivers/claude/projects.js +62 -0
- package/src/platforms/drivers/claude/prompts.js +9 -0
- package/src/{server/proxy-server.js → platforms/drivers/claude/proxy-implementation.js} +41 -278
- package/src/platforms/drivers/claude/proxy.js +16 -0
- package/src/platforms/drivers/claude/resource-sync.js +9 -0
- package/src/platforms/drivers/claude/session-history-adapter.js +313 -0
- package/src/{server/services/sessions.js → platforms/drivers/claude/sessions-implementation.js} +145 -35
- package/src/platforms/drivers/claude/sessions.js +76 -0
- package/src/{server/services/claude-statistics-service.js → platforms/drivers/claude/statistics-implementation.js} +2 -2
- package/src/platforms/drivers/claude/statistics.js +16 -0
- package/src/{server/services/claude-wire.js → platforms/drivers/claude/wire.js} +1 -1
- package/src/platforms/drivers/codex/api-operations.js +9 -0
- package/src/{server/services/codex-channels.js → platforms/drivers/codex/channels-implementation.js} +149 -14
- package/src/platforms/drivers/codex/channels.js +45 -0
- package/src/{server/services/codex-config.js → platforms/drivers/codex/config.js} +12 -2
- package/src/{server/services/codex-env-manager.js → platforms/drivers/codex/env-manager.js} +1 -1
- package/src/platforms/drivers/codex/mcp.js +9 -0
- package/src/{server/services/codex-settings-manager.js → platforms/drivers/codex/native-config-implementation.js} +15 -6
- package/src/platforms/drivers/codex/native-config.js +47 -0
- package/src/platforms/drivers/codex/native-logs.js +166 -0
- package/src/platforms/drivers/codex/project-config.js +21 -0
- package/src/platforms/drivers/codex/projects.js +26 -0
- package/src/platforms/drivers/codex/prompts.js +9 -0
- package/src/{server/codex-proxy-server.js → platforms/drivers/codex/proxy-implementation.js} +30 -233
- package/src/platforms/drivers/codex/proxy.js +16 -0
- package/src/platforms/drivers/codex/resource-sync.js +9 -0
- package/src/{server/services/session-history-adapters/codex.js → platforms/drivers/codex/session-history-adapter.js} +37 -23
- package/src/{server/services/codex-sessions.js → platforms/drivers/codex/sessions-implementation.js} +81 -75
- package/src/platforms/drivers/codex/sessions.js +36 -0
- package/src/{server/services/codex-statistics-service.js → platforms/drivers/codex/statistics-implementation.js} +2 -2
- package/src/platforms/drivers/codex/statistics.js +16 -0
- package/src/platforms/drivers/gemini/api-operations.js +9 -0
- package/src/{server/services/gemini-channels.js → platforms/drivers/gemini/channels-implementation.js} +202 -37
- package/src/platforms/drivers/gemini/channels.js +39 -0
- package/src/{server/services/gemini-config.js → platforms/drivers/gemini/config.js} +12 -2
- package/src/platforms/drivers/gemini/mcp.js +9 -0
- package/src/{server/services/gemini-settings-manager.js → platforms/drivers/gemini/native-config-implementation.js} +14 -5
- package/src/platforms/drivers/gemini/native-config.js +39 -0
- package/src/platforms/drivers/gemini/native-logs.js +180 -0
- package/src/platforms/drivers/gemini/project-config.js +21 -0
- package/src/platforms/drivers/gemini/projects.js +26 -0
- package/src/platforms/drivers/gemini/prompts.js +9 -0
- package/src/{server/gemini-proxy-server.js → platforms/drivers/gemini/proxy-implementation.js} +36 -267
- package/src/platforms/drivers/gemini/proxy.js +16 -0
- package/src/platforms/drivers/gemini/resource-sync.js +9 -0
- package/src/{server/services/session-history-adapters/gemini.js → platforms/drivers/gemini/session-history-adapter.js} +70 -18
- package/src/{server/services/gemini-sessions.js → platforms/drivers/gemini/sessions-implementation.js} +53 -37
- package/src/platforms/drivers/gemini/sessions.js +47 -0
- package/src/{server/services/gemini-statistics-service.js → platforms/drivers/gemini/statistics-implementation.js} +2 -2
- package/src/platforms/drivers/gemini/statistics.js +16 -0
- package/src/{server/services/gemini-wire.js → platforms/drivers/gemini/wire.js} +1 -1
- package/src/platforms/drivers/generic-filesystem.js +166 -0
- package/src/platforms/drivers/generic-jsonl.js +141 -0
- package/src/platforms/drivers/generic-mcp.js +44 -0
- package/src/platforms/drivers/generic-openai-compatible.js +45 -0
- package/src/platforms/drivers/generic-prompt.js +41 -0
- package/src/platforms/drivers/legacy.js +677 -0
- package/src/platforms/drivers/native-config-snapshot.js +125 -0
- package/src/platforms/drivers/native-log-utils.js +1292 -0
- package/src/platforms/drivers/notification-hooks.js +578 -0
- package/src/{server/api/omp-config.js → platforms/drivers/omp/api-operations.js} +52 -64
- package/src/{server/services/omp-auth-provider-worker.js → platforms/drivers/omp/auth-provider-worker.js} +1 -1
- package/src/{server/services/omp-auth-providers.js → platforms/drivers/omp/auth-providers.js} +1 -1
- package/src/{server/services/omp-channels.js → platforms/drivers/omp/channels-implementation.js} +166 -39
- package/src/platforms/drivers/omp/channels.js +58 -0
- package/src/{server/services/omp-config.js → platforms/drivers/omp/config.js} +53 -13
- package/src/{server/services/omp-gateway-routing.js → platforms/drivers/omp/gateway-routing.js} +14 -7
- package/src/{server/services/omp-gateway.js → platforms/drivers/omp/gateway.js} +4 -262
- package/src/platforms/drivers/omp/mcp.js +9 -0
- package/src/{server/services/omp-settings-manager.js → platforms/drivers/omp/native-config-implementation.js} +75 -10
- package/src/platforms/drivers/omp/native-config.js +46 -0
- package/src/platforms/drivers/omp/native-logs.js +52 -0
- package/src/{server/services/omp-native-plugin-adapter.js → platforms/drivers/omp/native-plugin-adapter.js} +91 -4
- package/src/platforms/drivers/omp/project-config.js +29 -0
- package/src/platforms/drivers/omp/projects.js +20 -0
- package/src/platforms/drivers/omp/prompts.js +9 -0
- package/src/{server/omp-proxy-server.js → platforms/drivers/omp/proxy-implementation.js} +6 -15
- package/src/platforms/drivers/omp/proxy.js +16 -0
- package/src/platforms/drivers/omp/resource-sync.js +9 -0
- package/src/{server/services/session-history-adapters/omp.js → platforms/drivers/omp/session-history-adapter.js} +42 -18
- package/src/{server/services/omp-sessions.js → platforms/drivers/omp/sessions-implementation.js} +130 -94
- package/src/platforms/drivers/omp/sessions.js +36 -0
- package/src/{server/services/omp-skill-discovery.js → platforms/drivers/omp/skill-discovery.js} +159 -32
- package/src/{server/services/omp-skill-settings-service.js → platforms/drivers/omp/skill-settings.js} +1 -1
- package/src/{server/services/omp-statistics-service.js → platforms/drivers/omp/statistics-implementation.js} +3 -3
- package/src/platforms/drivers/omp/statistics.js +16 -0
- package/src/platforms/drivers/opencode/api-operations.js +9 -0
- package/src/{server/services/opencode-channels.js → platforms/drivers/opencode/channels-implementation.js} +28 -9
- package/src/platforms/drivers/opencode/channels.js +40 -0
- package/src/platforms/drivers/opencode/conversion.js +41 -0
- package/src/{server/services/opencode-gateway-converter.js → platforms/drivers/opencode/gateway-converter.js} +1 -1
- package/src/platforms/drivers/opencode/mcp.js +9 -0
- package/src/{server/services/opencode-settings-manager.js → platforms/drivers/opencode/native-config-implementation.js} +17 -6
- package/src/platforms/drivers/opencode/native-config.js +26 -0
- package/src/platforms/drivers/opencode/native-logs.js +133 -0
- package/src/platforms/drivers/opencode/project-config.js +98 -0
- package/src/platforms/drivers/opencode/projects.js +20 -0
- package/src/platforms/drivers/opencode/prompts.js +9 -0
- package/src/{server/opencode-proxy-server.js → platforms/drivers/opencode/proxy-implementation.js} +27 -362
- package/src/platforms/drivers/opencode/proxy.js +16 -0
- package/src/platforms/drivers/opencode/resource-sync.js +9 -0
- package/src/{server/services/opencode-sessions.js → platforms/drivers/opencode/sessions-implementation.js} +211 -64
- package/src/platforms/drivers/opencode/sessions.js +48 -0
- package/src/{server/services/opencode-statistics-service.js → platforms/drivers/opencode/statistics-implementation.js} +2 -2
- package/src/platforms/drivers/opencode/statistics.js +16 -0
- package/src/platforms/drivers/secure-file-driver.js +272 -0
- package/src/platforms/drivers/unsupported.js +7 -0
- package/src/platforms/manifest-schema.js +398 -0
- package/src/platforms/manifests/claude.json +489 -0
- package/src/platforms/manifests/codex.json +448 -0
- package/src/platforms/manifests/gemini.json +447 -0
- package/src/platforms/manifests/omp.json +496 -0
- package/src/platforms/manifests/opencode.json +422 -0
- package/src/{server/services → platforms}/native-oauth-adapters.js +87 -417
- package/src/{server/services → platforms}/notification-hooks.js +140 -1023
- package/src/platforms/oauth-credentials-service.js +506 -0
- package/src/platforms/path-resolver.js +179 -0
- package/src/platforms/platform-path-context.js +305 -0
- package/src/platforms/registry.js +248 -0
- package/src/platforms/remote-notification-providers.js +678 -0
- package/src/platforms/runtime.js +259 -0
- package/src/{server/services/session-history-adapters/index.js → platforms/session-history-adapters.js} +8 -1
- package/src/plugins/plugin-loader.js +2 -2
- package/src/plugins/plugin-manager.js +2 -2
- package/src/plugins/registry.js +27 -10
- package/src/reset-config.js +21 -5
- package/src/server/api/agents.js +46 -72
- package/src/server/api/commands.js +16 -6
- package/src/server/api/config-registry.js +206 -59
- package/src/server/api/config-sync.js +3 -2
- package/src/server/api/config-templates.js +20 -4
- package/src/server/api/config.js +111 -102
- package/src/server/api/convert.js +54 -178
- package/src/server/api/dashboard.js +168 -102
- package/src/server/api/hooks.js +1 -1
- package/src/server/api/mcp.js +224 -84
- package/src/server/api/platform-api-config.js +102 -0
- package/src/server/api/platform-route-factory.js +215 -0
- package/src/server/api/platform-routes.js +26 -0
- package/src/server/api/platforms.js +110 -0
- package/src/server/api/plugins.js +57 -57
- package/src/server/api/project-config.js +168 -0
- package/src/server/api/prompts.js +58 -45
- package/src/server/api/settings.js +55 -8
- package/src/server/api/skills.js +262 -133
- package/src/server/api/ui-config.js +2 -2
- package/src/server/api/validation-errors.js +18 -4
- package/src/server/api/workspaces.js +47 -12
- package/src/server/index.js +164 -213
- package/src/server/platform-context.js +81 -0
- package/src/server/services/channel-balance.js +11 -20
- package/src/server/services/channel-health.js +21 -6
- package/src/server/services/channel-scheduler.js +29 -39
- package/src/server/services/channel-sync-utils.js +23 -13
- package/src/server/services/config-export-service.js +350 -319
- package/src/server/services/config-registry-service.js +280 -54
- package/src/server/services/config-sync-manager.js +172 -944
- package/src/server/services/config-templates-service.js +419 -353
- package/src/server/services/control-manifest-store.js +206 -0
- package/src/server/services/dashboard-snapshot-worker.js +656 -100
- package/src/server/services/effective-control-service.js +557 -0
- package/src/server/services/local-resource-index.js +314 -0
- package/src/server/services/mcp-service.js +607 -977
- package/src/server/services/model-detector.js +15 -10
- package/src/server/services/native-log-channel-resolver.js +214 -0
- package/src/server/services/native-log-observer.js +291 -0
- package/src/server/services/network-access.js +1 -1
- package/src/server/services/platform-catalog.js +82 -0
- package/src/server/services/platform-resolution.js +32 -29
- package/src/server/services/plugins-service.js +376 -122
- package/src/server/services/project-config-service.js +550 -0
- package/src/server/services/project-path-validation.js +31 -0
- package/src/server/services/prompts-service.js +267 -233
- package/src/server/services/proxy-runtime.js +7 -4
- package/src/server/services/remote-credential-cache.js +43 -0
- package/src/server/services/repo-scanner-base.js +182 -75
- package/src/server/services/request-logger.js +7 -4
- package/src/server/services/session-history-index.js +780 -213
- package/src/server/services/session-history-worker.js +228 -33
- package/src/server/services/session-snapshot-worker.js +124 -34
- package/src/server/services/session-snapshots.js +4 -2
- package/src/server/services/skill-artifact-store.js +355 -0
- package/src/server/services/skill-format-adapters.js +65 -0
- package/src/server/services/skill-projection-service.js +323 -0
- package/src/server/services/skill-refresh-task-service.js +275 -0
- package/src/server/services/skill-service.js +2020 -677
- package/src/server/services/snapshot-cache.js +30 -8
- package/src/server/services/speed-test.js +8 -8
- package/src/server/services/sqlite-connection.js +19 -3
- package/src/server/services/statistics-service.js +240 -57
- package/src/server/services/ui-config.js +107 -76
- package/src/server/services/usage-log-utils.js +98 -0
- package/src/server/services/web-build.js +1 -1
- package/src/server/services/workspace-service.js +59 -29
- package/src/server/utils/pricing.js +10 -19
- package/src/server/websocket-server.js +153 -28
- package/src/{server/services/base → shared}/base-channel-service.js +156 -28
- package/src/shared/capability-driver.js +104 -0
- package/src/shared/channel-auth-policy.js +27 -0
- package/src/shared/channel-driver.js +161 -0
- package/src/shared/driver-factories/api.js +180 -0
- package/src/shared/driver-factories/mcp.js +244 -0
- package/src/shared/driver-factories/projects.js +121 -0
- package/src/shared/driver-factories/prompts.js +58 -0
- package/src/shared/driver-factories/resource-sync.js +375 -0
- package/src/shared/driver-result.js +78 -0
- package/src/shared/mcp-format.js +189 -0
- package/src/shared/platforms.js +104 -167
- package/src/shared/project-config.js +512 -0
- package/src/shared/proxy-driver.js +57 -0
- package/src/{server/services/base → shared}/response-usage-parser.js +8 -4
- package/src/ui/menu.js +91 -67
- package/src/utils/port-helper.js +35 -19
- package/src/utils/session.js +1 -1
- package/dist/web/assets/Analytics-COEUXmd4.js +0 -25
- package/dist/web/assets/Analytics-RNn1BUbG.css +0 -1
- package/dist/web/assets/ConfigTemplates-DLLkS53H.js +0 -1
- package/dist/web/assets/Home-DCEyLzwX.js +0 -1
- package/dist/web/assets/Home-DYVy4cGZ.css +0 -1
- package/dist/web/assets/PluginManager-Oe1ZHoMO.js +0 -1
- package/dist/web/assets/ProjectList-CWjuAFof.js +0 -1
- package/dist/web/assets/ProjectList-VeMNXfgO.css +0 -1
- package/dist/web/assets/SessionList-C4chCPxK.css +0 -1
- package/dist/web/assets/SessionList-v3ehGg9U.js +0 -1
- package/dist/web/assets/SkillManager-BsX8Qpj0.css +0 -1
- package/dist/web/assets/SkillManager-DUF_qP5S.js +0 -1
- package/dist/web/assets/WorkspaceManager-CjAWBosO.js +0 -1
- package/dist/web/assets/icons-nGdSKQn2.js +0 -1
- package/dist/web/assets/index-D5hyHPj7.js +0 -2
- package/dist/web/assets/index-bJRG3RXH.css +0 -1
- package/dist/web/assets/markdown-BNJfEgCA.js +0 -1
- package/dist/web/assets/markdown-BfC0goYb.css +0 -10
- package/dist/web/assets/naive-ui-BALVpMgd.js +0 -1
- package/dist/web/assets/vendors-DQA4Hw9v.js +0 -7
- package/dist/web/assets/vue-vendor-B5RqjEjQ.js +0 -45
- package/src/config/model-pricing.js +0 -35
- package/src/server/api/channels.js +0 -439
- package/src/server/api/claude-hooks.js +0 -56
- package/src/server/api/claude-statistics.js +0 -57
- package/src/server/api/codex-channels.js +0 -491
- package/src/server/api/codex-projects.js +0 -117
- package/src/server/api/codex-proxy.js +0 -293
- package/src/server/api/codex-sessions.js +0 -652
- package/src/server/api/codex-statistics.js +0 -57
- package/src/server/api/gemini-channels.js +0 -392
- package/src/server/api/gemini-projects.js +0 -103
- package/src/server/api/gemini-proxy.js +0 -231
- package/src/server/api/gemini-sessions.js +0 -550
- package/src/server/api/gemini-statistics.js +0 -57
- package/src/server/api/health-check.js +0 -31
- package/src/server/api/oauth-credentials.js +0 -198
- package/src/server/api/omp-channels.js +0 -575
- package/src/server/api/omp-projects.js +0 -88
- package/src/server/api/omp-proxy.js +0 -125
- package/src/server/api/omp-sessions.js +0 -386
- package/src/server/api/omp-statistics.js +0 -40
- package/src/server/api/opencode-channels.js +0 -471
- package/src/server/api/opencode-projects.js +0 -110
- package/src/server/api/opencode-proxy.js +0 -354
- package/src/server/api/opencode-sessions.js +0 -466
- package/src/server/api/opencode-statistics.js +0 -57
- package/src/server/api/projects.js +0 -120
- package/src/server/api/proxy.js +0 -330
- package/src/server/api/sessions.js +0 -810
- package/src/server/services/oauth-credentials-service.js +0 -945
- package/src/server/services/omp-session-log-observer.js +0 -138
- package/src/server/services/opencode-gateway-adapters.js +0 -43
- package/src/server/services/project-snapshots.js +0 -59
- package/src/server/services/proxy-log-helper.js +0 -298
- package/src/server/services/session-cache.js +0 -127
- package/src/server/services/session-converter.js +0 -582
- package/src/server/services/session-history-adapters/claude.js +0 -235
- /package/src/{server/services/claude-token-recovery.js → platforms/drivers/claude/token-recovery.js} +0 -0
- /package/src/{server/services/codex-parser.js → platforms/drivers/codex/parser.js} +0 -0
- /package/src/{server/services/codex-speed-test-template.json → platforms/drivers/codex/speed-test-template.json} +0 -0
- /package/src/{server/services/codex-wire.js → platforms/drivers/codex/wire.js} +0 -0
- /package/src/{server/services/omp-auth-gateway-client.js → platforms/drivers/omp/auth-gateway-client.js} +0 -0
- /package/src/{server/services/opencode-normalization.js → platforms/drivers/opencode/normalization.js} +0 -0
- /package/src/{server/services → shared}/config-artifact-paths.js +0 -0
- /package/src/{server/services/base → shared}/proxy-utils.js +0 -0
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const { PATHS, NATIVE_PATHS } = require('../../config/paths');
|
|
13
|
+
const { getPlatformContext } = require('../platform-context');
|
|
14
|
+
const { ControlManifestStore } = require('./control-manifest-store');
|
|
15
|
+
const { EffectiveControlService } = require('./effective-control-service');
|
|
16
|
+
const { SkillArtifactStore } = require('./skill-artifact-store');
|
|
17
|
+
const { SkillFormatAdapter } = require('./skill-format-adapters');
|
|
13
18
|
|
|
14
19
|
// Configuration paths
|
|
15
20
|
const CC_TOOL_DIR = PATHS.base;
|
|
@@ -24,33 +29,57 @@ const CLAUDE_DIRS = {
|
|
|
24
29
|
agents: NATIVE_PATHS.claude.agents || path.join(CLAUDE_HOME_DIR, 'agents'),
|
|
25
30
|
plugins: NATIVE_PATHS.claude.plugins || path.join(CLAUDE_HOME_DIR, 'plugins')
|
|
26
31
|
};
|
|
27
|
-
|
|
28
32
|
// Valid config types
|
|
29
33
|
const CONFIG_TYPES = ['skills', 'commands', 'agents', 'plugins'];
|
|
30
|
-
const SUPPORTED_PLATFORMS = ['claude', 'codex', 'gemini', 'opencode', 'omp'];
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
35
|
+
function getSupportedPlatforms(registry = getPlatformContext().registry) {
|
|
36
|
+
if (!registry || typeof registry.list !== 'function') return [];
|
|
37
|
+
return registry.list()
|
|
38
|
+
.map(platform => platform && platform.key)
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function buildPlatformSupport(registry = getPlatformContext().registry) {
|
|
43
|
+
const support = Object.fromEntries(CONFIG_TYPES.map(type => [type, {}]));
|
|
44
|
+
for (const platform of (registry?.list?.() || [])) {
|
|
45
|
+
const key = platform && platform.key;
|
|
46
|
+
if (!key) continue;
|
|
47
|
+
const resourceDriver = platform.capabilities?.resourceSync;
|
|
48
|
+
for (const type of CONFIG_TYPES) {
|
|
49
|
+
const typeCapability = platform.capabilities && Object.prototype.hasOwnProperty.call(platform.capabilities, type)
|
|
50
|
+
? platform.capabilities[type]
|
|
51
|
+
: null;
|
|
52
|
+
const declared = resourceDriver && resourceDriver !== 'unsupported' && typeCapability !== 'unsupported';
|
|
53
|
+
const typeDeclared = platform.resourceTypes && Object.prototype.hasOwnProperty.call(platform.resourceTypes, type)
|
|
54
|
+
? platform.resourceTypes[type]
|
|
55
|
+
: declared;
|
|
56
|
+
support[type][key] = declared && typeDeclared !== false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return support;
|
|
60
|
+
}
|
|
38
61
|
|
|
39
62
|
function normalizePlatforms(type, platforms = {}) {
|
|
40
|
-
const
|
|
63
|
+
const supportedPlatforms = getSupportedPlatforms();
|
|
64
|
+
const support = buildPlatformSupport();
|
|
41
65
|
const normalized = {};
|
|
42
66
|
|
|
43
|
-
for (const platform of
|
|
67
|
+
for (const platform of supportedPlatforms) {
|
|
44
68
|
normalized[platform] = !!platforms?.[platform];
|
|
45
69
|
}
|
|
46
70
|
|
|
47
|
-
for (const platform of
|
|
48
|
-
if (support[platform] === false)
|
|
49
|
-
|
|
71
|
+
for (const platform of supportedPlatforms) {
|
|
72
|
+
if (support[type]?.[platform] === false) normalized[platform] = false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Preserve historical flags for platforms absent from the current registry.
|
|
76
|
+
for (const [platform, enabled] of Object.entries(platforms || {})) {
|
|
77
|
+
if (!Object.prototype.hasOwnProperty.call(normalized, platform)) {
|
|
78
|
+
normalized[platform] = !!enabled;
|
|
50
79
|
}
|
|
51
80
|
}
|
|
52
81
|
|
|
53
|
-
// Default to Claude enabled when no platform explicitly configured
|
|
82
|
+
// Default to Claude enabled when no platform explicitly configured.
|
|
54
83
|
if (!platforms || Object.keys(platforms).length === 0) {
|
|
55
84
|
normalized.claude = true;
|
|
56
85
|
}
|
|
@@ -58,6 +87,8 @@ function normalizePlatforms(type, platforms = {}) {
|
|
|
58
87
|
return normalized;
|
|
59
88
|
}
|
|
60
89
|
|
|
90
|
+
const RESERVED_CONFIG_NAMES = new Set(['__proto__', 'constructor', 'prototype']);
|
|
91
|
+
|
|
61
92
|
function normalizeRelativeConfigName(name) {
|
|
62
93
|
const raw = String(name || '').replace(/\\/g, '/').trim();
|
|
63
94
|
if (!raw || raw.includes('\0')) {
|
|
@@ -72,6 +103,9 @@ function normalizeRelativeConfigName(name) {
|
|
|
72
103
|
if (path.isAbsolute(raw) || raw.startsWith('/')) {
|
|
73
104
|
throw new Error('Absolute path is not allowed');
|
|
74
105
|
}
|
|
106
|
+
if (RESERVED_CONFIG_NAMES.has(normalized)) {
|
|
107
|
+
throw new Error('Invalid config name');
|
|
108
|
+
}
|
|
75
109
|
|
|
76
110
|
return normalized;
|
|
77
111
|
}
|
|
@@ -94,13 +128,67 @@ function ensureDir(dirPath) {
|
|
|
94
128
|
}
|
|
95
129
|
}
|
|
96
130
|
|
|
131
|
+
function collectSkillFiles(rootDir) {
|
|
132
|
+
const files = [];
|
|
133
|
+
const visit = currentDir => {
|
|
134
|
+
if (fs.lstatSync(currentDir).isSymbolicLink()) {
|
|
135
|
+
throw new Error(`Skill artifact contains symlink: ${currentDir}`);
|
|
136
|
+
}
|
|
137
|
+
for (const entry of fs.readdirSync(currentDir, { withFileTypes: true })) {
|
|
138
|
+
const sourcePath = path.join(currentDir, entry.name);
|
|
139
|
+
if (entry.isSymbolicLink()) {
|
|
140
|
+
throw new Error(`Skill artifact contains symlink: ${sourcePath}`);
|
|
141
|
+
}
|
|
142
|
+
if (entry.isDirectory()) {
|
|
143
|
+
visit(sourcePath);
|
|
144
|
+
} else if (entry.isFile()) {
|
|
145
|
+
files.push({
|
|
146
|
+
relativePath: path.relative(rootDir, sourcePath).replace(/\\/g, '/'),
|
|
147
|
+
content: fs.readFileSync(sourcePath)
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
visit(rootDir);
|
|
153
|
+
return files;
|
|
154
|
+
}
|
|
155
|
+
|
|
97
156
|
/**
|
|
98
157
|
* Config Registry Service
|
|
99
158
|
*/
|
|
100
159
|
class ConfigRegistryService {
|
|
101
|
-
constructor() {
|
|
160
|
+
constructor({ controlService = null, artifactStore = null, formatAdapter = null, registry = getPlatformContext().registry } = {}) {
|
|
161
|
+
this.registry = registry;
|
|
102
162
|
this.registryPath = REGISTRY_FILE;
|
|
103
163
|
this.configsDir = CONFIGS_DIR;
|
|
164
|
+
let native = NATIVE_PATHS.claude || {};
|
|
165
|
+
try {
|
|
166
|
+
const pathContext = this.registry?.resolvePathContext?.('claude');
|
|
167
|
+
if (pathContext?.customized) native = pathContext.native || native;
|
|
168
|
+
} catch {
|
|
169
|
+
// Keep the compatibility defaults when the registry is unavailable.
|
|
170
|
+
}
|
|
171
|
+
const claudeHomeDir = native.dir || path.dirname(native.settings || CLAUDE_HOME_DIR);
|
|
172
|
+
this.claudeDirs = {
|
|
173
|
+
skills: native.skills || path.join(claudeHomeDir, 'skills'),
|
|
174
|
+
commands: native.commands || path.join(claudeHomeDir, 'commands'),
|
|
175
|
+
agents: native.agents || path.join(claudeHomeDir, 'agents'),
|
|
176
|
+
plugins: native.plugins || path.join(claudeHomeDir, 'plugins')
|
|
177
|
+
};
|
|
178
|
+
this.artifactStore = artifactStore || (
|
|
179
|
+
PATHS.skillArtifacts ? new SkillArtifactStore({ root: PATHS.skillArtifacts }) : null
|
|
180
|
+
);
|
|
181
|
+
this.formatAdapter = formatAdapter || new SkillFormatAdapter();
|
|
182
|
+
this.controlService = controlService || (
|
|
183
|
+
PATHS.effectiveControlManifest
|
|
184
|
+
? new EffectiveControlService({
|
|
185
|
+
store: new ControlManifestStore({
|
|
186
|
+
userPath: PATHS.effectiveControlManifest,
|
|
187
|
+
projectPathResolver: ({ projectPath }) => path.join(projectPath, '.ctx-control.json')
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
: null
|
|
191
|
+
);
|
|
104
192
|
|
|
105
193
|
// Ensure directories exist
|
|
106
194
|
this._ensureDirs();
|
|
@@ -120,6 +208,141 @@ class ConfigRegistryService {
|
|
|
120
208
|
}
|
|
121
209
|
}
|
|
122
210
|
|
|
211
|
+
migrateSkillControls() {
|
|
212
|
+
if (!this.controlService) return { migrated: 0, skipped: 0, migrationVersion: 0 };
|
|
213
|
+
const registry = this._readRegistry();
|
|
214
|
+
let migrated = 0;
|
|
215
|
+
let skipped = 0;
|
|
216
|
+
for (const [name, item] of Object.entries(registry.skills || {})) {
|
|
217
|
+
let safeName;
|
|
218
|
+
try {
|
|
219
|
+
safeName = normalizeRelativeConfigName(name);
|
|
220
|
+
} catch {
|
|
221
|
+
skipped++;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (!item || typeof item !== 'object') continue;
|
|
225
|
+
const platforms = Object.keys(item.platforms || {});
|
|
226
|
+
for (const platform of platforms.length > 0 ? platforms : ['claude']) {
|
|
227
|
+
const sourceKey = `local:${platform}:${safeName}`;
|
|
228
|
+
const controlKey = `skill:${platform}:user:user:${sourceKey}`;
|
|
229
|
+
if (this.controlService.getSkill(controlKey, { scope: 'user' })) {
|
|
230
|
+
skipped++;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const legacyRoot = path.join(this.configsDir, 'skills', safeName);
|
|
235
|
+
const legacySkillPath = path.join(legacyRoot, 'SKILL.md');
|
|
236
|
+
const legacyReady = fs.existsSync(legacySkillPath);
|
|
237
|
+
let artifactRoot = legacyReady ? legacyRoot : null;
|
|
238
|
+
let artifactFormat = null;
|
|
239
|
+
let artifactHash = null;
|
|
240
|
+
let artifactState = legacyReady ? 'ready' : 'metadata_only';
|
|
241
|
+
let lastError = null;
|
|
242
|
+
|
|
243
|
+
if (legacyReady && this.artifactStore) {
|
|
244
|
+
try {
|
|
245
|
+
const normalized = this.formatAdapter.normalize({
|
|
246
|
+
platform,
|
|
247
|
+
files: collectSkillFiles(legacyRoot),
|
|
248
|
+
sourceMetadata: { name: safeName }
|
|
249
|
+
});
|
|
250
|
+
const published = this.artifactStore.publishSkill({
|
|
251
|
+
platform,
|
|
252
|
+
sourceKey,
|
|
253
|
+
format: normalized.format,
|
|
254
|
+
files: normalized.files,
|
|
255
|
+
metadata: {
|
|
256
|
+
name: safeName,
|
|
257
|
+
directory: safeName,
|
|
258
|
+
sourceProvider: 'local',
|
|
259
|
+
sourceScope: 'user',
|
|
260
|
+
revision: null
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
artifactRoot = published.root;
|
|
264
|
+
artifactFormat = published.format || normalized.format;
|
|
265
|
+
artifactHash = published.contentHash || null;
|
|
266
|
+
artifactState = published.state || 'ready';
|
|
267
|
+
} catch (error) {
|
|
268
|
+
artifactRoot = null;
|
|
269
|
+
artifactState = 'missing';
|
|
270
|
+
lastError = error.message;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const platformEnabled = platforms.length === 0
|
|
275
|
+
? platform === 'claude'
|
|
276
|
+
: item.platforms?.[platform] === true;
|
|
277
|
+
const enabled = artifactState !== 'metadata_only'
|
|
278
|
+
&& artifactState !== 'missing'
|
|
279
|
+
&& item.enabled !== false
|
|
280
|
+
&& platformEnabled;
|
|
281
|
+
const registered = this.controlService.registerSkill({
|
|
282
|
+
kind: 'skill',
|
|
283
|
+
controlKey,
|
|
284
|
+
platform,
|
|
285
|
+
scope: 'user',
|
|
286
|
+
projectPath: null,
|
|
287
|
+
sourceKey,
|
|
288
|
+
source: {
|
|
289
|
+
kind: 'local',
|
|
290
|
+
repoId: null,
|
|
291
|
+
fullDirectory: safeName,
|
|
292
|
+
revision: null
|
|
293
|
+
},
|
|
294
|
+
artifact: {
|
|
295
|
+
root: artifactRoot,
|
|
296
|
+
format: artifactFormat,
|
|
297
|
+
contentHash: artifactHash,
|
|
298
|
+
state: artifactState,
|
|
299
|
+
fetchedAt: null
|
|
300
|
+
},
|
|
301
|
+
targetDirectory: safeName,
|
|
302
|
+
cached: Boolean(artifactRoot) && artifactState !== 'missing',
|
|
303
|
+
enabled,
|
|
304
|
+
trust: enabled ? 'approved' : (artifactState === 'missing' ? 'needs_review' : 'pending'),
|
|
305
|
+
projection: {
|
|
306
|
+
mode: 'native-copy',
|
|
307
|
+
state: enabled ? 'enabled' : 'disabled',
|
|
308
|
+
sourceKey,
|
|
309
|
+
path: null,
|
|
310
|
+
updatedAt: null
|
|
311
|
+
},
|
|
312
|
+
managed: true,
|
|
313
|
+
lastError,
|
|
314
|
+
createdAt: Date.now(),
|
|
315
|
+
updatedAt: Date.now()
|
|
316
|
+
});
|
|
317
|
+
if (!enabled && this.controlService.setSkillEnabled) {
|
|
318
|
+
try {
|
|
319
|
+
this.controlService.setSkillEnabled({
|
|
320
|
+
platform,
|
|
321
|
+
controlKey: registered.controlKey,
|
|
322
|
+
scope: 'user',
|
|
323
|
+
projectPath: null,
|
|
324
|
+
enabled: false
|
|
325
|
+
});
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.warn(`[ConfigRegistry] Failed to disable migrated Skill ${safeName}:`, error.message);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
migrated++;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const store = this.controlService.store;
|
|
335
|
+
if (store?.read && store?.write) {
|
|
336
|
+
const scope = { scope: 'user', projectPath: null };
|
|
337
|
+
const manifest = store.read(scope);
|
|
338
|
+
if (manifest.migrationVersion !== 1) {
|
|
339
|
+
manifest.migrationVersion = 1;
|
|
340
|
+
store.write(scope, manifest);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return { migrated, skipped, migrationVersion: 1 };
|
|
344
|
+
}
|
|
345
|
+
|
|
123
346
|
/**
|
|
124
347
|
* Read registry from file
|
|
125
348
|
* @returns {Object} Registry data
|
|
@@ -180,9 +403,11 @@ class ConfigRegistryService {
|
|
|
180
403
|
if (!CONFIG_TYPES.includes(type)) {
|
|
181
404
|
throw new Error(`Invalid config type: ${type}`);
|
|
182
405
|
}
|
|
183
|
-
|
|
406
|
+
const safeName = normalizeRelativeConfigName(name);
|
|
184
407
|
const registry = this._readRegistry();
|
|
185
|
-
return registry[type]
|
|
408
|
+
return Object.prototype.hasOwnProperty.call(registry[type], safeName)
|
|
409
|
+
? registry[type][safeName]
|
|
410
|
+
: null;
|
|
186
411
|
}
|
|
187
412
|
|
|
188
413
|
/**
|
|
@@ -190,17 +415,18 @@ class ConfigRegistryService {
|
|
|
190
415
|
* @param {string} type - Config type
|
|
191
416
|
* @param {string} name - Item name/key
|
|
192
417
|
* @param {Object} data - Item data
|
|
193
|
-
* @returns {Object} Updated entry
|
|
194
418
|
*/
|
|
195
419
|
setItem(type, name, data) {
|
|
196
420
|
if (!CONFIG_TYPES.includes(type)) {
|
|
197
421
|
throw new Error(`Invalid config type: ${type}`);
|
|
198
422
|
}
|
|
199
|
-
|
|
423
|
+
const safeName = normalizeRelativeConfigName(name);
|
|
200
424
|
const registry = this._readRegistry();
|
|
201
425
|
const now = new Date().toISOString();
|
|
202
426
|
|
|
203
|
-
const existing = registry[type]
|
|
427
|
+
const existing = Object.prototype.hasOwnProperty.call(registry[type], safeName)
|
|
428
|
+
? registry[type][safeName]
|
|
429
|
+
: null;
|
|
204
430
|
const entry = {
|
|
205
431
|
...data,
|
|
206
432
|
enabled: data.enabled !== undefined ? data.enabled : true,
|
|
@@ -210,7 +436,7 @@ class ConfigRegistryService {
|
|
|
210
436
|
source: data.source || 'local'
|
|
211
437
|
};
|
|
212
438
|
|
|
213
|
-
registry[type][
|
|
439
|
+
registry[type][safeName] = entry;
|
|
214
440
|
this._writeRegistry(registry);
|
|
215
441
|
|
|
216
442
|
return entry;
|
|
@@ -226,18 +452,18 @@ class ConfigRegistryService {
|
|
|
226
452
|
if (!CONFIG_TYPES.includes(type)) {
|
|
227
453
|
throw new Error(`Invalid config type: ${type}`);
|
|
228
454
|
}
|
|
229
|
-
|
|
455
|
+
const safeName = normalizeRelativeConfigName(name);
|
|
230
456
|
const registry = this._readRegistry();
|
|
231
457
|
|
|
232
|
-
if (!registry[type]
|
|
458
|
+
if (!Object.prototype.hasOwnProperty.call(registry[type], safeName)) {
|
|
233
459
|
return false;
|
|
234
460
|
}
|
|
235
461
|
|
|
236
|
-
delete registry[type][
|
|
462
|
+
delete registry[type][safeName];
|
|
237
463
|
this._writeRegistry(registry);
|
|
238
464
|
|
|
239
465
|
// Also remove the actual config files
|
|
240
|
-
const configPath = this.getConfigPath(type,
|
|
466
|
+
const configPath = this.getConfigPath(type, safeName);
|
|
241
467
|
if (fs.existsSync(configPath)) {
|
|
242
468
|
try {
|
|
243
469
|
const stats = fs.statSync(configPath);
|
|
@@ -247,7 +473,7 @@ class ConfigRegistryService {
|
|
|
247
473
|
fs.unlinkSync(configPath);
|
|
248
474
|
}
|
|
249
475
|
} catch (err) {
|
|
250
|
-
console.error(`[ConfigRegistry] Failed to remove config files for ${type}/${
|
|
476
|
+
console.error(`[ConfigRegistry] Failed to remove config files for ${type}/${safeName}:`, err.message);
|
|
251
477
|
}
|
|
252
478
|
}
|
|
253
479
|
|
|
@@ -279,9 +505,11 @@ class ConfigRegistryService {
|
|
|
279
505
|
if (!CONFIG_TYPES.includes(type)) {
|
|
280
506
|
throw new Error(`Invalid config type: ${type}`);
|
|
281
507
|
}
|
|
282
|
-
|
|
508
|
+
const safeName = normalizeRelativeConfigName(name);
|
|
283
509
|
const registry = this._readRegistry();
|
|
284
|
-
const entry = registry[type]
|
|
510
|
+
const entry = Object.prototype.hasOwnProperty.call(registry[type], safeName)
|
|
511
|
+
? registry[type][safeName]
|
|
512
|
+
: null;
|
|
285
513
|
|
|
286
514
|
if (!entry) {
|
|
287
515
|
throw new Error(`Item "${name}" not found in ${type}`);
|
|
@@ -301,23 +529,25 @@ class ConfigRegistryService {
|
|
|
301
529
|
* @param {string} name - Item name/key
|
|
302
530
|
* @param {string} platform - Platform name (claude, codex, gemini, opencode)
|
|
303
531
|
* @param {boolean} enabled - New platform status
|
|
304
|
-
* @returns {Object} Updated entry
|
|
305
532
|
*/
|
|
306
533
|
togglePlatform(type, name, platform, enabled) {
|
|
307
534
|
if (!CONFIG_TYPES.includes(type)) {
|
|
308
535
|
throw new Error(`Invalid config type: ${type}`);
|
|
309
536
|
}
|
|
310
537
|
|
|
311
|
-
if (!
|
|
538
|
+
if (!getSupportedPlatforms().includes(platform)) {
|
|
312
539
|
throw new Error(`Invalid platform: ${platform}`);
|
|
313
540
|
}
|
|
314
541
|
|
|
315
|
-
if (
|
|
542
|
+
if (buildPlatformSupport()[type]?.[platform] === false) {
|
|
316
543
|
throw new Error(`Platform "${platform}" is not supported for ${type}`);
|
|
317
544
|
}
|
|
318
545
|
|
|
546
|
+
const safeName = normalizeRelativeConfigName(name);
|
|
319
547
|
const registry = this._readRegistry();
|
|
320
|
-
const entry = registry[type]
|
|
548
|
+
const entry = Object.prototype.hasOwnProperty.call(registry[type], safeName)
|
|
549
|
+
? registry[type][safeName]
|
|
550
|
+
: null;
|
|
321
551
|
|
|
322
552
|
if (!entry) {
|
|
323
553
|
throw new Error(`Item "${name}" not found in ${type}`);
|
|
@@ -345,7 +575,7 @@ class ConfigRegistryService {
|
|
|
345
575
|
throw new Error(`Invalid config type: ${type}`);
|
|
346
576
|
}
|
|
347
577
|
|
|
348
|
-
const sourceDir =
|
|
578
|
+
const sourceDir = this.claudeDirs[type];
|
|
349
579
|
const destDir = path.join(this.configsDir, type);
|
|
350
580
|
|
|
351
581
|
if (!fs.existsSync(sourceDir)) {
|
|
@@ -555,6 +785,9 @@ class ConfigRegistryService {
|
|
|
555
785
|
* @private
|
|
556
786
|
*/
|
|
557
787
|
_copyDirRecursive(src, dest) {
|
|
788
|
+
if (fs.lstatSync(src).isSymbolicLink()) {
|
|
789
|
+
throw new Error(`Config source contains symlink: ${src}`);
|
|
790
|
+
}
|
|
558
791
|
ensureDir(dest);
|
|
559
792
|
|
|
560
793
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
@@ -562,10 +795,12 @@ class ConfigRegistryService {
|
|
|
562
795
|
for (const entry of entries) {
|
|
563
796
|
const srcPath = path.join(src, entry.name);
|
|
564
797
|
const destPath = path.join(dest, entry.name);
|
|
565
|
-
|
|
798
|
+
if (entry.isSymbolicLink()) {
|
|
799
|
+
throw new Error(`Config source contains symlink: ${srcPath}`);
|
|
800
|
+
}
|
|
566
801
|
if (entry.isDirectory()) {
|
|
567
802
|
this._copyDirRecursive(srcPath, destPath);
|
|
568
|
-
} else {
|
|
803
|
+
} else if (entry.isFile()) {
|
|
569
804
|
fs.copyFileSync(srcPath, destPath);
|
|
570
805
|
}
|
|
571
806
|
}
|
|
@@ -577,16 +812,11 @@ class ConfigRegistryService {
|
|
|
577
812
|
*/
|
|
578
813
|
getStats() {
|
|
579
814
|
const registry = this._readRegistry();
|
|
815
|
+
const supportedPlatforms = getSupportedPlatforms();
|
|
580
816
|
const stats = {
|
|
581
817
|
total: 0,
|
|
582
818
|
byType: {},
|
|
583
|
-
byPlatform:
|
|
584
|
-
claude: 0,
|
|
585
|
-
codex: 0,
|
|
586
|
-
gemini: 0,
|
|
587
|
-
opencode: 0,
|
|
588
|
-
omp: 0
|
|
589
|
-
}
|
|
819
|
+
byPlatform: Object.fromEntries(supportedPlatforms.map(platform => [platform, 0]))
|
|
590
820
|
};
|
|
591
821
|
|
|
592
822
|
for (const type of CONFIG_TYPES) {
|
|
@@ -594,21 +824,16 @@ class ConfigRegistryService {
|
|
|
594
824
|
const typeStats = {
|
|
595
825
|
total: items.length,
|
|
596
826
|
enabled: items.filter(i => i.enabled).length,
|
|
597
|
-
disabled: items.filter(i => !i.enabled).length
|
|
598
|
-
claude: items.filter(i => i.platforms?.claude).length,
|
|
599
|
-
codex: items.filter(i => i.platforms?.codex).length,
|
|
600
|
-
gemini: items.filter(i => i.platforms?.gemini).length,
|
|
601
|
-
opencode: items.filter(i => i.platforms?.opencode).length,
|
|
602
|
-
omp: items.filter(i => i.platforms?.omp).length
|
|
827
|
+
disabled: items.filter(i => !i.enabled).length
|
|
603
828
|
};
|
|
604
829
|
|
|
830
|
+
for (const platform of supportedPlatforms) {
|
|
831
|
+
typeStats[platform] = items.filter(item => item.platforms?.[platform]).length;
|
|
832
|
+
stats.byPlatform[platform] += typeStats[platform];
|
|
833
|
+
}
|
|
834
|
+
|
|
605
835
|
stats.byType[type] = typeStats;
|
|
606
836
|
stats.total += typeStats.total;
|
|
607
|
-
stats.byPlatform.claude += typeStats.claude;
|
|
608
|
-
stats.byPlatform.codex += typeStats.codex;
|
|
609
|
-
stats.byPlatform.gemini += typeStats.gemini;
|
|
610
|
-
stats.byPlatform.opencode += typeStats.opencode;
|
|
611
|
-
stats.byPlatform.omp += typeStats.omp;
|
|
612
837
|
}
|
|
613
838
|
|
|
614
839
|
return stats;
|
|
@@ -826,7 +1051,8 @@ class ConfigRegistryService {
|
|
|
826
1051
|
module.exports = {
|
|
827
1052
|
ConfigRegistryService,
|
|
828
1053
|
CONFIG_TYPES,
|
|
829
|
-
|
|
1054
|
+
getSupportedPlatforms,
|
|
1055
|
+
buildPlatformSupport,
|
|
830
1056
|
CONFIGS_DIR,
|
|
831
1057
|
REGISTRY_FILE
|
|
832
1058
|
};
|