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,16 +10,93 @@ const toml = require('toml');
|
|
|
10
10
|
const tomlStringify = require('@iarna/toml').stringify;
|
|
11
11
|
const yaml = require('js-yaml');
|
|
12
12
|
const configTemplatesService = require('./config-templates-service');
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const geminiChannelsService = require('./gemini-channels');
|
|
16
|
-
const opencodeChannelsService = require('./opencode-channels');
|
|
17
|
-
const ompChannelsService = require('./omp-channels');
|
|
18
|
-
const { AgentsService } = require('./agents-service');
|
|
19
|
-
const { CommandsService } = require('./commands-service');
|
|
13
|
+
const { AgentsService } = require('../../platforms/agents-service');
|
|
14
|
+
const { CommandsService } = require('../../platforms/commands-service');
|
|
20
15
|
const { SkillService } = require('./skill-service');
|
|
21
16
|
const { PluginsService } = require('./plugins-service');
|
|
22
17
|
const { PATHS, NATIVE_PATHS } = require('../../config/paths');
|
|
18
|
+
const { getPlatformCatalog } = require('./platform-catalog');
|
|
19
|
+
const { getPlatformContext } = require('../platform-context');
|
|
20
|
+
|
|
21
|
+
function getChannelDriver(platform) {
|
|
22
|
+
return getPlatformCatalog().driver(platform, 'channels');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getExportRegistry() {
|
|
26
|
+
try {
|
|
27
|
+
return getPlatformContext().registry;
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getPlatformPathContext(platform, registry = getExportRegistry()) {
|
|
34
|
+
try {
|
|
35
|
+
return registry?.resolvePathContext?.(platform) || null;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getConfiguredNativePaths(platform, registry = getExportRegistry()) {
|
|
42
|
+
const pathContext = getPlatformPathContext(platform, registry);
|
|
43
|
+
return pathContext?.customized ? (pathContext.native || {}) : (NATIVE_PATHS[platform] || {});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getConfiguredStatePath(category, platform, registry = getExportRegistry()) {
|
|
47
|
+
const pathContext = getPlatformPathContext(platform, registry);
|
|
48
|
+
if (pathContext?.customized && pathContext.state?.[category]) {
|
|
49
|
+
return pathContext.state[category];
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const pathsModule = require('../../config/paths');
|
|
53
|
+
if (typeof pathsModule.getPlatformStatePath === 'function') {
|
|
54
|
+
return pathsModule.getPlatformStatePath(category, platform);
|
|
55
|
+
}
|
|
56
|
+
} catch {
|
|
57
|
+
// Fall back to the built-in maps for isolated tests.
|
|
58
|
+
}
|
|
59
|
+
return PATHS[category]?.[platform];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getPlatformPluginPaths(platform, registry = getExportRegistry()) {
|
|
63
|
+
const native = getConfiguredNativePaths(platform, registry);
|
|
64
|
+
if (platform === 'claude') {
|
|
65
|
+
const pluginsDir = native.plugins
|
|
66
|
+
|| path.join(native.dir || path.dirname(native.settings || CLAUDE_SETTINGS_PATH), 'plugins');
|
|
67
|
+
return {
|
|
68
|
+
pluginsDir,
|
|
69
|
+
installedRegistry: path.join(pluginsDir, 'installed_plugins.json'),
|
|
70
|
+
marketplacesRegistry: path.join(pluginsDir, 'known_marketplaces.json'),
|
|
71
|
+
cacheDir: path.join(pluginsDir, 'cache')
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (platform === 'codex') {
|
|
75
|
+
const pluginsDir = path.join(native.dir || path.dirname(native.config || NATIVE_PATHS.codex.config), 'plugins');
|
|
76
|
+
return {
|
|
77
|
+
pluginsDir,
|
|
78
|
+
cacheDir: path.join(pluginsDir, 'cache'),
|
|
79
|
+
configPath: native.config || NATIVE_PATHS.codex.config
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (platform === 'opencode') {
|
|
83
|
+
const pluginsDir = path.join(native.config || NATIVE_PATHS.opencode.config, 'plugins');
|
|
84
|
+
return {
|
|
85
|
+
pluginsDir,
|
|
86
|
+
legacyPluginsDir: path.join(native.config || NATIVE_PATHS.opencode.config, 'plugin'),
|
|
87
|
+
configDir: native.config || NATIVE_PATHS.opencode.config
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (platform === 'omp') {
|
|
91
|
+
const root = native.dir || NATIVE_PATHS.omp.dir;
|
|
92
|
+
return {
|
|
93
|
+
extensionsDir: native.extensions || path.join(root, 'extensions'),
|
|
94
|
+
settingsPath: native.settings || native.config || path.join(root, 'config.yml')
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
|
|
23
100
|
|
|
24
101
|
const CONFIG_VERSION = '1.4.0';
|
|
25
102
|
const SKILL_FILE_ENCODING = 'base64';
|
|
@@ -52,12 +129,50 @@ const CC_UI_CONFIG_PATH = PATHS.uiConfig;
|
|
|
52
129
|
const CC_PROMPTS_PATH = PATHS.prompts;
|
|
53
130
|
const CC_SECURITY_PATH = PATHS.security;
|
|
54
131
|
const LEGACY_UI_CONFIG_PATH = PATHS.uiConfig;
|
|
55
|
-
const LEGACY_NOTIFY_HOOK_PATH = PATHS.notifyHook;
|
|
56
132
|
const GEMINI_SETTINGS_PATH = path.join(path.dirname(NATIVE_PATHS.gemini.env), 'settings.json');
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
133
|
+
const LEGACY_NOTIFY_HOOK_PATH = PATHS.notifyHook;
|
|
134
|
+
function getPlatformKeysForType(type, registry) {
|
|
135
|
+
if (registry && typeof registry.list === 'function') {
|
|
136
|
+
return registry.list({ enabledOnly: true })
|
|
137
|
+
.filter(platform => platform && platform.key && platform.capabilities?.resourceSync !== 'unsupported')
|
|
138
|
+
.filter(platform => platform.resourceTypes?.[type] !== false)
|
|
139
|
+
.map(platform => platform.key);
|
|
140
|
+
}
|
|
141
|
+
return getPlatformCatalog().keys({ resourceType: type });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function getAgentPlatforms(registry = getExportRegistry()) {
|
|
145
|
+
return getPlatformKeysForType('agents', registry);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function getCommandPlatforms(registry = getExportRegistry()) {
|
|
149
|
+
return getPlatformKeysForType('commands', registry);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function getSkillPlatforms(registry = getExportRegistry()) {
|
|
153
|
+
return getPlatformKeysForType('skills', registry);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getPluginPlatforms(registry = getExportRegistry()) {
|
|
157
|
+
if (registry && typeof registry.list === 'function') {
|
|
158
|
+
return registry.list({ enabledOnly: true })
|
|
159
|
+
.filter(platform => platform && platform.key && platform.capabilities?.resourceSync !== 'unsupported')
|
|
160
|
+
.map(platform => platform.key);
|
|
161
|
+
}
|
|
162
|
+
return getPlatformCatalog().keys({ capability: 'resourceSync' });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function exportPlatformSnapshots({ registry, exportByPlatform } = {}) {
|
|
166
|
+
if (typeof exportByPlatform !== 'function') return {};
|
|
167
|
+
const platforms = registry && typeof registry.list === 'function'
|
|
168
|
+
? registry.list({ enabledOnly: true })
|
|
169
|
+
: getPlatformCatalog().list({ enabledOnly: true });
|
|
170
|
+
return Object.fromEntries(
|
|
171
|
+
platforms
|
|
172
|
+
.filter(platform => platform && platform.key)
|
|
173
|
+
.map(platform => [platform.key, exportByPlatform(platform.key)])
|
|
174
|
+
);
|
|
175
|
+
}
|
|
61
176
|
const CLAUDE_MARKETPLACES_REGISTRY = path.join(CLAUDE_PLUGINS_DIR, 'known_marketplaces.json');
|
|
62
177
|
const CODEX_PLUGINS_DIR = path.join(path.dirname(NATIVE_PATHS.codex.config), 'plugins');
|
|
63
178
|
const CODEX_PLUGINS_CACHE_DIR = path.join(CODEX_PLUGINS_DIR, 'cache');
|
|
@@ -111,7 +226,7 @@ function normalizeOmpResourceTypes(input = []) {
|
|
|
111
226
|
|
|
112
227
|
function getOpenCodeConfigPaths() {
|
|
113
228
|
try {
|
|
114
|
-
const { CONFIG_PATHS } = require('
|
|
229
|
+
const { CONFIG_PATHS } = require('../../platforms/drivers/opencode/native-config-implementation');
|
|
115
230
|
return CONFIG_PATHS || {};
|
|
116
231
|
} catch (err) {
|
|
117
232
|
return {};
|
|
@@ -120,52 +235,13 @@ function getOpenCodeConfigPaths() {
|
|
|
120
235
|
|
|
121
236
|
function getOpenCodeNotificationPluginPath() {
|
|
122
237
|
try {
|
|
123
|
-
const { getOpenCodeManagedPluginPath } = require('
|
|
238
|
+
const { getOpenCodeManagedPluginPath } = require('../../platforms/notification-hooks');
|
|
124
239
|
return typeof getOpenCodeManagedPluginPath === 'function' ? getOpenCodeManagedPluginPath() : '';
|
|
125
240
|
} catch (err) {
|
|
126
241
|
return '';
|
|
127
242
|
}
|
|
128
243
|
}
|
|
129
244
|
|
|
130
|
-
function getNativeConfigSpecs() {
|
|
131
|
-
const openCodeConfigPaths = getOpenCodeConfigPaths();
|
|
132
|
-
const openCodeNotificationPluginPath = getOpenCodeNotificationPluginPath();
|
|
133
|
-
const ompDir = NATIVE_PATHS.omp.dir || path.dirname(NATIVE_PATHS.omp.settings);
|
|
134
|
-
return {
|
|
135
|
-
claude: {
|
|
136
|
-
settings: { path: NATIVE_PATHS.claude.settings, format: 'json' }
|
|
137
|
-
},
|
|
138
|
-
codex: {
|
|
139
|
-
config: { path: NATIVE_PATHS.codex.config, format: 'text' },
|
|
140
|
-
auth: { path: NATIVE_PATHS.codex.auth, format: 'json', mode: 0o600 }
|
|
141
|
-
},
|
|
142
|
-
gemini: {
|
|
143
|
-
env: { path: NATIVE_PATHS.gemini.env, format: 'text', mode: 0o600 },
|
|
144
|
-
settings: { path: GEMINI_SETTINGS_PATH, format: 'json' }
|
|
145
|
-
},
|
|
146
|
-
opencode: {
|
|
147
|
-
opencodeJsonc: { path: openCodeConfigPaths.opencodec, format: 'text' },
|
|
148
|
-
opencodeJson: { path: openCodeConfigPaths.opencode, format: 'text' },
|
|
149
|
-
configJson: { path: openCodeConfigPaths.config, format: 'text' },
|
|
150
|
-
...(openCodeNotificationPluginPath
|
|
151
|
-
? { codingToolNotifyPlugin: { path: openCodeNotificationPluginPath, format: 'text' } }
|
|
152
|
-
: {})
|
|
153
|
-
},
|
|
154
|
-
omp: {
|
|
155
|
-
settings: { path: NATIVE_PATHS.omp.settings, format: 'yaml' },
|
|
156
|
-
auth: { path: NATIVE_PATHS.omp.auth, format: 'json', mode: 0o600 },
|
|
157
|
-
models: { path: NATIVE_PATHS.omp.models, format: 'yaml' },
|
|
158
|
-
commands: { path: NATIVE_PATHS.omp.commands || path.join(ompDir, 'commands'), format: 'directory' },
|
|
159
|
-
prompts: { path: NATIVE_PATHS.omp.prompts, format: 'directory' },
|
|
160
|
-
skills: { path: NATIVE_PATHS.omp.skills, format: 'directory' },
|
|
161
|
-
extensions: { path: NATIVE_PATHS.omp.extensions, format: 'directory' },
|
|
162
|
-
themes: { path: NATIVE_PATHS.omp.themes || path.join(ompDir, 'themes'), format: 'directory' },
|
|
163
|
-
packages: { path: NATIVE_PATHS.omp.packages || path.join(ompDir, 'packages'), format: 'directory' },
|
|
164
|
-
npmPackages: { path: path.join(ompDir, 'npm'), format: 'directory' },
|
|
165
|
-
gitPackages: { path: path.join(ompDir, 'git'), format: 'directory' }
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
245
|
|
|
170
246
|
function ensureDir(dirPath) {
|
|
171
247
|
if (!fs.existsSync(dirPath)) {
|
|
@@ -531,29 +607,41 @@ function buildCommandExportItem(command, platform) {
|
|
|
531
607
|
};
|
|
532
608
|
}
|
|
533
609
|
|
|
534
|
-
function exportAgentsSnapshotByPlatform() {
|
|
535
|
-
return
|
|
610
|
+
function exportAgentsSnapshotByPlatform(registry = getExportRegistry()) {
|
|
611
|
+
return getAgentPlatforms(registry).reduce((result, platform) => {
|
|
612
|
+
let agentsService;
|
|
536
613
|
try {
|
|
537
|
-
|
|
614
|
+
agentsService = new AgentsService(platform, { registry });
|
|
538
615
|
const { agents: rawAgents = [] } = agentsService.listAgents();
|
|
539
|
-
result[platform] = rawAgents.map(agent =>
|
|
616
|
+
result[platform] = rawAgents.map(agent => {
|
|
617
|
+
const detail = typeof agentsService.getAgent === 'function' ? (agentsService.getAgent(agent.fileName, agent.scope || 'user') || agent) : agent;
|
|
618
|
+
return buildAgentExportItem({ ...agent, ...detail }, platform);
|
|
619
|
+
});
|
|
540
620
|
} catch (err) {
|
|
541
621
|
console.warn(`[ConfigExport] Failed to export agents for ${platform}:`, err.message);
|
|
542
622
|
result[platform] = [];
|
|
623
|
+
} finally {
|
|
624
|
+
agentsService?.dispose?.();
|
|
543
625
|
}
|
|
544
626
|
return result;
|
|
545
627
|
}, {});
|
|
546
628
|
}
|
|
547
629
|
|
|
548
|
-
function exportCommandsSnapshotByPlatform() {
|
|
549
|
-
return
|
|
630
|
+
function exportCommandsSnapshotByPlatform(registry = getExportRegistry()) {
|
|
631
|
+
return getCommandPlatforms(registry).reduce((result, platform) => {
|
|
632
|
+
let commandsService;
|
|
550
633
|
try {
|
|
551
|
-
|
|
634
|
+
commandsService = new CommandsService(platform, { registry });
|
|
552
635
|
const { commands: rawCommands = [] } = commandsService.listCommands();
|
|
553
|
-
result[platform] = rawCommands.map(command =>
|
|
636
|
+
result[platform] = rawCommands.map(command => {
|
|
637
|
+
const detail = typeof commandsService.getCommand === 'function' ? (commandsService.getCommand(command.name, command.scope || 'user', null, command.namespace) || command) : command;
|
|
638
|
+
return buildCommandExportItem({ ...command, ...detail }, platform);
|
|
639
|
+
});
|
|
554
640
|
} catch (err) {
|
|
555
641
|
console.warn(`[ConfigExport] Failed to export commands for ${platform}:`, err.message);
|
|
556
642
|
result[platform] = [];
|
|
643
|
+
} finally {
|
|
644
|
+
commandsService?.dispose?.();
|
|
557
645
|
}
|
|
558
646
|
return result;
|
|
559
647
|
}, {});
|
|
@@ -716,71 +804,33 @@ function buildOpenCodeNativeConfig(channels = []) {
|
|
|
716
804
|
}
|
|
717
805
|
|
|
718
806
|
function syncImportedChannelsToNativeConfigs(importChannelsByType, nativeConfigs, overwrite) {
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (
|
|
723
|
-
|
|
724
|
-
const persistedClaudeChannel = findMatchingPersistedChannel(
|
|
725
|
-
channelsService.getAllChannels?.() || [],
|
|
726
|
-
primaryClaudeChannel,
|
|
727
|
-
[
|
|
728
|
-
(channel, imported) => channel.name === imported.name && channel.baseUrl === imported.baseUrl
|
|
729
|
-
]
|
|
730
|
-
);
|
|
731
|
-
if (persistedClaudeChannel?.id) {
|
|
732
|
-
ensureDir(path.dirname(NATIVE_PATHS.claude.settings));
|
|
733
|
-
channelsService.applyChannelToSettings(persistedClaudeChannel.id);
|
|
734
|
-
}
|
|
807
|
+
const catalog = getPlatformCatalog();
|
|
808
|
+
for (const platform of catalog.keys({ capability: 'channels' })) {
|
|
809
|
+
const channels = importChannelsByType?.[platform] || [];
|
|
810
|
+
if (channels.length === 0 || (nativeConfigs?.[platform] && Object.keys(nativeConfigs[platform]).length > 0)) {
|
|
811
|
+
continue;
|
|
735
812
|
}
|
|
736
|
-
} catch (err) {
|
|
737
|
-
console.warn('[ConfigImport] Claude native sync fallback failed:', err.message);
|
|
738
|
-
}
|
|
739
813
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
814
|
+
try {
|
|
815
|
+
const nativeDriver = catalog.driver(platform, 'nativeConfig');
|
|
816
|
+
if (typeof nativeDriver?.syncChannels === 'function') {
|
|
817
|
+
nativeDriver.syncChannels(channels, { overwrite });
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
747
820
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
geminiChannelsService.getChannels?.().channels || [],
|
|
753
|
-
primaryGeminiChannel,
|
|
754
|
-
[
|
|
755
|
-
(channel, imported) => channel.name === imported.name && channel.baseUrl === imported.baseUrl
|
|
756
|
-
]
|
|
757
|
-
);
|
|
758
|
-
if (persistedGeminiChannel?.id) {
|
|
759
|
-
geminiChannelsService.applyChannelToSettings(persistedGeminiChannel.id);
|
|
821
|
+
const channelDriver = catalog.driver(platform, 'channels');
|
|
822
|
+
if (typeof channelDriver?.writeMultiChannelConfig === 'function') {
|
|
823
|
+
channelDriver.writeMultiChannelConfig(channels);
|
|
824
|
+
continue;
|
|
760
825
|
}
|
|
761
|
-
}
|
|
762
|
-
} catch (err) {
|
|
763
|
-
console.warn('[ConfigImport] Gemini native sync fallback failed:', err.message);
|
|
764
|
-
}
|
|
765
826
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
const preferredSpec = [
|
|
770
|
-
openCodeSpecs.opencodeJsonc,
|
|
771
|
-
openCodeSpecs.opencodeJson,
|
|
772
|
-
openCodeSpecs.configJson
|
|
773
|
-
].find(spec => spec?.path && fs.existsSync(spec.path))
|
|
774
|
-
|| openCodeSpecs.opencodeJson
|
|
775
|
-
|| openCodeSpecs.configJson;
|
|
776
|
-
|
|
777
|
-
if (preferredSpec?.path) {
|
|
778
|
-
const payload = buildOpenCodeNativeConfig(importChannelsByType.opencode || []);
|
|
779
|
-
writeTextFileAbsolute(preferredSpec.path, JSON.stringify(payload, null, 2), overwrite);
|
|
827
|
+
if (typeof channelDriver?.applyChannelToSettings === 'function') {
|
|
828
|
+
const primary = pickPrimaryChannel(channels);
|
|
829
|
+
if (primary?.id) channelDriver.applyChannelToSettings(primary.id);
|
|
780
830
|
}
|
|
831
|
+
} catch (err) {
|
|
832
|
+
console.warn(`[ConfigImport] ${platform} native sync fallback failed:`, err.message);
|
|
781
833
|
}
|
|
782
|
-
} catch (err) {
|
|
783
|
-
console.warn('[ConfigImport] OpenCode native sync fallback failed:', err.message);
|
|
784
834
|
}
|
|
785
835
|
}
|
|
786
836
|
|
|
@@ -968,8 +1018,8 @@ function readJsonConfigSnapshot(filePath) {
|
|
|
968
1018
|
|
|
969
1019
|
function exportPluginControlSnapshot(platform, service) {
|
|
970
1020
|
const snapshot = {};
|
|
971
|
-
const reposPath =
|
|
972
|
-
const marketCachePath =
|
|
1021
|
+
const reposPath = service?.getReposConfigPath?.() || getConfiguredStatePath('pluginRepos', platform, service?.registry);
|
|
1022
|
+
const marketCachePath = service?.marketCachePath || getConfiguredStatePath('pluginMarketCache', platform, service?.registry);
|
|
973
1023
|
const repos = readJsonConfigSnapshot(reposPath);
|
|
974
1024
|
const marketCache = readJsonConfigSnapshot(marketCachePath);
|
|
975
1025
|
|
|
@@ -993,12 +1043,15 @@ function exportPluginControlSnapshot(platform, service) {
|
|
|
993
1043
|
}
|
|
994
1044
|
|
|
995
1045
|
function exportClaudePluginsByPlatform(service) {
|
|
1046
|
+
const pluginsDir = service.claudePluginsDir || CLAUDE_PLUGINS_DIR;
|
|
1047
|
+
const installedRegistryPath = service.claudeInstalledFile || NATIVE_PLUGINS_REGISTRY;
|
|
1048
|
+
const marketplacesRegistryPath = service.claudeMarketplacesFile || CLAUDE_MARKETPLACES_REGISTRY;
|
|
996
1049
|
const installedPlugins = service.listPlugins().plugins || [];
|
|
997
1050
|
const plugins = [];
|
|
998
1051
|
|
|
999
1052
|
for (const plugin of installedPlugins) {
|
|
1000
1053
|
if (plugin.installPath && fs.existsSync(plugin.installPath)) {
|
|
1001
|
-
const pluginDir = assertPathInside(
|
|
1054
|
+
const pluginDir = assertPathInside(pluginsDir, plugin.installPath)
|
|
1002
1055
|
|| assertPathInside(LEGACY_PLUGINS_DIR, plugin.installPath);
|
|
1003
1056
|
if (pluginDir) {
|
|
1004
1057
|
const { manifest, manifestPath } = detectPluginManifest(pluginDir, [
|
|
@@ -1018,7 +1071,7 @@ function exportClaudePluginsByPlatform(service) {
|
|
|
1018
1071
|
version: manifest.version || plugin.version || '1.0.0',
|
|
1019
1072
|
description: manifest.description || plugin.description || '',
|
|
1020
1073
|
author: manifest.author || plugin.author || '',
|
|
1021
|
-
directory: path.relative(
|
|
1074
|
+
directory: path.relative(pluginsDir, pluginDir),
|
|
1022
1075
|
enabled: plugin.enabled !== false,
|
|
1023
1076
|
installedAt: plugin.installedAt,
|
|
1024
1077
|
scope: plugin.scope,
|
|
@@ -1050,8 +1103,8 @@ function exportClaudePluginsByPlatform(service) {
|
|
|
1050
1103
|
}
|
|
1051
1104
|
|
|
1052
1105
|
const control = exportPluginControlSnapshot('claude', service);
|
|
1053
|
-
const installedRegistry = readJsonConfigSnapshot(
|
|
1054
|
-
const knownMarketplaces = readJsonConfigSnapshot(
|
|
1106
|
+
const installedRegistry = readJsonConfigSnapshot(installedRegistryPath);
|
|
1107
|
+
const knownMarketplaces = readJsonConfigSnapshot(marketplacesRegistryPath);
|
|
1055
1108
|
const legacyRegistry = readJsonConfigSnapshot(LEGACY_PLUGINS_REGISTRY);
|
|
1056
1109
|
if (installedRegistry) control.installedRegistry = installedRegistry;
|
|
1057
1110
|
if (knownMarketplaces) control.knownMarketplaces = knownMarketplaces;
|
|
@@ -1062,14 +1115,16 @@ function exportClaudePluginsByPlatform(service) {
|
|
|
1062
1115
|
|
|
1063
1116
|
function exportCodexPluginsByPlatform(service) {
|
|
1064
1117
|
const plugins = (service.listPlugins().plugins || [])
|
|
1065
|
-
.map(plugin => buildManagedPluginExportItem(plugin, 'codex', CODEX_PLUGINS_CACHE_DIR, {
|
|
1118
|
+
.map(plugin => buildManagedPluginExportItem(plugin, 'codex', service.codexPluginsCacheDir || CODEX_PLUGINS_CACHE_DIR, {
|
|
1066
1119
|
type: 'codex-cache',
|
|
1067
1120
|
pluginType: 'cache',
|
|
1068
1121
|
manifestCandidates: ['.codex-plugin/plugin.json', 'plugin.json', 'package.json']
|
|
1069
1122
|
}))
|
|
1070
1123
|
.filter(Boolean);
|
|
1071
1124
|
const control = exportPluginControlSnapshot('codex', service);
|
|
1072
|
-
const codexConfig = readNativeConfigSnapshot({ path:
|
|
1125
|
+
const codexConfig = readNativeConfigSnapshot({ path: service.pathContext?.customized
|
|
1126
|
+
? service.pathContext.native?.config
|
|
1127
|
+
: NATIVE_PATHS.codex.config, format: 'text' });
|
|
1073
1128
|
if (codexConfig) {
|
|
1074
1129
|
control.nativeConfig = codexConfig;
|
|
1075
1130
|
}
|
|
@@ -1077,7 +1132,7 @@ function exportCodexPluginsByPlatform(service) {
|
|
|
1077
1132
|
}
|
|
1078
1133
|
|
|
1079
1134
|
function exportOpenCodePluginsByPlatform(service) {
|
|
1080
|
-
const pluginsDir = getOpenCodePluginsDir();
|
|
1135
|
+
const pluginsDir = service._getOpenCodePluginsDir?.() || getOpenCodePluginsDir();
|
|
1081
1136
|
const plugins = (service.listPlugins().plugins || [])
|
|
1082
1137
|
.map((plugin) => {
|
|
1083
1138
|
if (plugin.pluginType === 'npm' || plugin.source === 'opencode-config') {
|
|
@@ -1109,6 +1164,9 @@ function exportOpenCodePluginsByPlatform(service) {
|
|
|
1109
1164
|
}
|
|
1110
1165
|
|
|
1111
1166
|
function exportOmpPluginsByPlatform(service) {
|
|
1167
|
+
const extensionsDir = service.pathContext?.customized
|
|
1168
|
+
? (service.pathContext.native?.extensions || path.join(service.pathContext.native?.dir || '', 'extensions'))
|
|
1169
|
+
: OMP_EXTENSIONS_DIR;
|
|
1112
1170
|
const plugins = (service.listPlugins().plugins || [])
|
|
1113
1171
|
.map((plugin) => {
|
|
1114
1172
|
if (plugin.pluginType === 'package' || plugin.source === 'omp-settings') {
|
|
@@ -1126,7 +1184,7 @@ function exportOmpPluginsByPlatform(service) {
|
|
|
1126
1184
|
source: plugin.source || 'omp-settings'
|
|
1127
1185
|
};
|
|
1128
1186
|
}
|
|
1129
|
-
return buildManagedPluginExportItem(plugin, 'omp',
|
|
1187
|
+
return buildManagedPluginExportItem(plugin, 'omp', extensionsDir, {
|
|
1130
1188
|
type: 'omp-extension',
|
|
1131
1189
|
pluginType: plugin.pluginType || 'extension',
|
|
1132
1190
|
pluginKind: plugin.pluginKind || 'extension',
|
|
@@ -1138,10 +1196,10 @@ function exportOmpPluginsByPlatform(service) {
|
|
|
1138
1196
|
return { plugins, control };
|
|
1139
1197
|
}
|
|
1140
1198
|
|
|
1141
|
-
function exportPluginsSnapshotByPlatform() {
|
|
1142
|
-
return
|
|
1199
|
+
function exportPluginsSnapshotByPlatform(registry = getExportRegistry()) {
|
|
1200
|
+
return getPluginPlatforms(registry).reduce((result, platform) => {
|
|
1143
1201
|
try {
|
|
1144
|
-
const service = new PluginsService(platform);
|
|
1202
|
+
const service = new PluginsService(platform, { registry });
|
|
1145
1203
|
if (platform === 'claude') {
|
|
1146
1204
|
result[platform] = exportClaudePluginsByPlatform(service);
|
|
1147
1205
|
} else if (platform === 'codex') {
|
|
@@ -1164,8 +1222,8 @@ function exportPluginsSnapshotByPlatform() {
|
|
|
1164
1222
|
}, {});
|
|
1165
1223
|
}
|
|
1166
1224
|
|
|
1167
|
-
function exportSkillsSnapshot(platform = 'claude') {
|
|
1168
|
-
const skillService = new SkillService(platform);
|
|
1225
|
+
function exportSkillsSnapshot(platform = 'claude', registry = getExportRegistry()) {
|
|
1226
|
+
const skillService = new SkillService(platform, { registry });
|
|
1169
1227
|
const installedSkills = skillService.getInstalledSkills();
|
|
1170
1228
|
const baseDir = skillService.installDir;
|
|
1171
1229
|
|
|
@@ -1185,10 +1243,10 @@ function exportSkillsSnapshot(platform = 'claude') {
|
|
|
1185
1243
|
}).filter(Boolean);
|
|
1186
1244
|
}
|
|
1187
1245
|
|
|
1188
|
-
function exportSkillsSnapshotByPlatform() {
|
|
1189
|
-
return
|
|
1246
|
+
function exportSkillsSnapshotByPlatform(registry = getExportRegistry()) {
|
|
1247
|
+
return getSkillPlatforms(registry).reduce((result, platform) => {
|
|
1190
1248
|
try {
|
|
1191
|
-
result[platform] = exportSkillsSnapshot(platform);
|
|
1249
|
+
result[platform] = exportSkillsSnapshot(platform, registry);
|
|
1192
1250
|
} catch (err) {
|
|
1193
1251
|
console.warn(`[ConfigExport] Failed to export skills for ${platform}:`, err.message);
|
|
1194
1252
|
result[platform] = [];
|
|
@@ -1197,22 +1255,20 @@ function exportSkillsSnapshotByPlatform() {
|
|
|
1197
1255
|
}, {});
|
|
1198
1256
|
}
|
|
1199
1257
|
|
|
1200
|
-
function exportNativeConfigs() {
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
if (Object.keys(
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
return result;
|
|
1215
|
-
}, {});
|
|
1258
|
+
function exportNativeConfigs(registry = getExportRegistry()) {
|
|
1259
|
+
const result = {};
|
|
1260
|
+
const platforms = registry && typeof registry.list === 'function'
|
|
1261
|
+
? registry.list({ enabledOnly: true })
|
|
1262
|
+
.filter(platform => platform?.key && platform.capabilities?.nativeConfig !== 'unsupported')
|
|
1263
|
+
.map(platform => platform.key)
|
|
1264
|
+
: getPlatformCatalog().keys({ capability: 'nativeConfig' });
|
|
1265
|
+
for (const platform of platforms) {
|
|
1266
|
+
const driver = getPlatformCatalog().driver(platform, 'nativeConfig');
|
|
1267
|
+
if (!driver || typeof driver.exportSnapshot !== 'function') continue;
|
|
1268
|
+
const snapshot = driver.exportSnapshot();
|
|
1269
|
+
if (snapshot && Object.keys(snapshot).length > 0) result[platform] = snapshot;
|
|
1270
|
+
}
|
|
1271
|
+
return result;
|
|
1216
1272
|
}
|
|
1217
1273
|
|
|
1218
1274
|
function exportLegacyPlugins() {
|
|
@@ -1322,14 +1378,15 @@ function exportPluginsSnapshot() {
|
|
|
1322
1378
|
return [...legacyPlugins, ...nativePlugins];
|
|
1323
1379
|
}
|
|
1324
1380
|
|
|
1325
|
-
function getPluginsByPlatformItems(plugins = [], pluginsByPlatform = {}) {
|
|
1326
|
-
const
|
|
1381
|
+
function getPluginsByPlatformItems(plugins = [], pluginsByPlatform = {}, registry = getExportRegistry()) {
|
|
1382
|
+
const supportedPlatforms = getPluginPlatforms(registry);
|
|
1383
|
+
const result = Object.fromEntries(supportedPlatforms.map(platform => [platform, []]));
|
|
1327
1384
|
const hasStructuredPlugins = pluginsByPlatform
|
|
1328
1385
|
&& typeof pluginsByPlatform === 'object'
|
|
1329
1386
|
&& Object.keys(pluginsByPlatform).length > 0;
|
|
1330
1387
|
|
|
1331
1388
|
if (hasStructuredPlugins) {
|
|
1332
|
-
for (const platform of
|
|
1389
|
+
for (const platform of supportedPlatforms) {
|
|
1333
1390
|
const platformSnapshot = pluginsByPlatform[platform];
|
|
1334
1391
|
const platformPlugins = Array.isArray(platformSnapshot?.plugins)
|
|
1335
1392
|
? platformSnapshot.plugins
|
|
@@ -1343,7 +1400,10 @@ function getPluginsByPlatformItems(plugins = [], pluginsByPlatform = {}) {
|
|
|
1343
1400
|
|
|
1344
1401
|
if (!hasStructuredPlugins && Array.isArray(plugins)) {
|
|
1345
1402
|
for (const plugin of plugins) {
|
|
1346
|
-
const platform =
|
|
1403
|
+
const platform = supportedPlatforms.includes(plugin?.platform)
|
|
1404
|
+
? plugin.platform
|
|
1405
|
+
: (supportedPlatforms.includes('claude') ? 'claude' : null);
|
|
1406
|
+
if (!platform) continue;
|
|
1347
1407
|
result[platform].push({ ...plugin, platform });
|
|
1348
1408
|
}
|
|
1349
1409
|
}
|
|
@@ -1439,9 +1499,9 @@ function mergeTomlFile(filePath, updates = {}, overwrite = true) {
|
|
|
1439
1499
|
return 'success';
|
|
1440
1500
|
}
|
|
1441
1501
|
|
|
1442
|
-
function mergePluginRepoConfig(platform, snapshot = {}, overwrite = true) {
|
|
1443
|
-
const reposPath =
|
|
1444
|
-
const marketCachePath =
|
|
1502
|
+
function mergePluginRepoConfig(platform, snapshot = {}, overwrite = true, registry = getExportRegistry()) {
|
|
1503
|
+
const reposPath = getConfiguredStatePath('pluginRepos', platform, registry);
|
|
1504
|
+
const marketCachePath = getConfiguredStatePath('pluginMarketCache', platform, registry);
|
|
1445
1505
|
let changed = 0;
|
|
1446
1506
|
let skipped = 0;
|
|
1447
1507
|
let failed = 0;
|
|
@@ -1465,10 +1525,10 @@ function mergePluginRepoConfig(platform, snapshot = {}, overwrite = true) {
|
|
|
1465
1525
|
return { changed, skipped, failed };
|
|
1466
1526
|
}
|
|
1467
1527
|
|
|
1468
|
-
function mergeCodexPluginConfig(snapshot = {}, plugins = [], overwrite = true) {
|
|
1528
|
+
function mergeCodexPluginConfig(snapshot = {}, plugins = [], overwrite = true, configPath = NATIVE_PATHS.codex.config) {
|
|
1469
1529
|
const nativeConfig = snapshot.control?.nativeConfig;
|
|
1470
1530
|
if (nativeConfig?.content !== undefined) {
|
|
1471
|
-
return writeNativeConfigAbsolute({ path:
|
|
1531
|
+
return writeNativeConfigAbsolute({ path: configPath, format: 'text' }, nativeConfig, overwrite);
|
|
1472
1532
|
}
|
|
1473
1533
|
|
|
1474
1534
|
const pluginEntries = {};
|
|
@@ -1490,13 +1550,13 @@ function mergeCodexPluginConfig(snapshot = {}, plugins = [], overwrite = true) {
|
|
|
1490
1550
|
return 'skipped';
|
|
1491
1551
|
}
|
|
1492
1552
|
|
|
1493
|
-
return mergeTomlFile(
|
|
1553
|
+
return mergeTomlFile(configPath, {
|
|
1494
1554
|
...(Object.keys(pluginEntries).length > 0 ? { plugins: pluginEntries } : {}),
|
|
1495
1555
|
...(Object.keys(marketplaces).length > 0 ? { marketplaces } : {})
|
|
1496
1556
|
}, overwrite);
|
|
1497
1557
|
}
|
|
1498
1558
|
|
|
1499
|
-
function writeOpenCodePluginConfig(packages = [], overwrite = true) {
|
|
1559
|
+
function writeOpenCodePluginConfig(packages = [], overwrite = true, configDir = NATIVE_PATHS.opencode.config) {
|
|
1500
1560
|
if (packages.length === 0) return 'skipped';
|
|
1501
1561
|
const openCodePaths = getOpenCodeConfigPaths();
|
|
1502
1562
|
const configPath = [
|
|
@@ -1505,7 +1565,7 @@ function writeOpenCodePluginConfig(packages = [], overwrite = true) {
|
|
|
1505
1565
|
openCodePaths.config
|
|
1506
1566
|
].find(filePath => filePath && fs.existsSync(filePath))
|
|
1507
1567
|
|| openCodePaths.opencode
|
|
1508
|
-
|| path.join(
|
|
1568
|
+
|| path.join(configDir, 'opencode.json');
|
|
1509
1569
|
const existing = readJsonFileSafe(configPath) || {};
|
|
1510
1570
|
if (fs.existsSync(configPath) && !overwrite) {
|
|
1511
1571
|
return 'skipped';
|
|
@@ -1515,17 +1575,17 @@ function writeOpenCodePluginConfig(packages = [], overwrite = true) {
|
|
|
1515
1575
|
return writeJsonFileAbsolute(configPath, { ...existing, plugin: mergedPlugins }, true);
|
|
1516
1576
|
}
|
|
1517
1577
|
|
|
1518
|
-
function writeOmpPluginSettings(plugins = [], snapshot = {}, overwrite = true) {
|
|
1578
|
+
function writeOmpPluginSettings(plugins = [], snapshot = {}, overwrite = true, settingsPath = OMP_SETTINGS_PATH) {
|
|
1519
1579
|
const nativeSettings = snapshot.control?.nativeSettings;
|
|
1520
1580
|
if (nativeSettings?.content !== undefined) {
|
|
1521
|
-
return writeNativeConfigAbsolute({ path:
|
|
1581
|
+
return writeNativeConfigAbsolute({ path: settingsPath, format: 'yaml' }, {
|
|
1522
1582
|
...nativeSettings,
|
|
1523
1583
|
format: 'yaml'
|
|
1524
1584
|
}, overwrite);
|
|
1525
1585
|
}
|
|
1526
1586
|
|
|
1527
|
-
const settings = readYamlFileSafe(
|
|
1528
|
-
if (fs.existsSync(
|
|
1587
|
+
const settings = readYamlFileSafe(settingsPath) || {};
|
|
1588
|
+
if (fs.existsSync(settingsPath) && !overwrite) {
|
|
1529
1589
|
return 'skipped';
|
|
1530
1590
|
}
|
|
1531
1591
|
const existingPackages = Array.isArray(settings.packages) ? settings.packages : [];
|
|
@@ -1573,14 +1633,14 @@ function writeOmpPluginSettings(plugins = [], snapshot = {}, overwrite = true) {
|
|
|
1573
1633
|
return 'skipped';
|
|
1574
1634
|
}
|
|
1575
1635
|
|
|
1576
|
-
return writeYamlFileAbsolute(
|
|
1636
|
+
return writeYamlFileAbsolute(settingsPath, {
|
|
1577
1637
|
...settings,
|
|
1578
1638
|
packages: mergePackageEntries(existingPackages, packages),
|
|
1579
1639
|
disabledPackages: mergePackageEntries(existingDisabled, disabledPackages)
|
|
1580
1640
|
}, true);
|
|
1581
1641
|
}
|
|
1582
1642
|
|
|
1583
|
-
function importPluginToDirectory(platform, plugin, baseDir, overwrite) {
|
|
1643
|
+
function importPluginToDirectory(platform, plugin, baseDir, overwrite, options = {}) {
|
|
1584
1644
|
const files = Array.isArray(plugin.files) ? plugin.files : [];
|
|
1585
1645
|
if (files.length === 0) {
|
|
1586
1646
|
return 'skipped';
|
|
@@ -1623,7 +1683,7 @@ function importPluginToDirectory(platform, plugin, baseDir, overwrite) {
|
|
|
1623
1683
|
}
|
|
1624
1684
|
|
|
1625
1685
|
if (platform === 'claude') {
|
|
1626
|
-
updateClaudePluginRegistry(plugin, pluginDir);
|
|
1686
|
+
updateClaudePluginRegistry(plugin, pluginDir, options);
|
|
1627
1687
|
}
|
|
1628
1688
|
|
|
1629
1689
|
return 'success';
|
|
@@ -1639,14 +1699,15 @@ function applyImportStatus(results, status) {
|
|
|
1639
1699
|
}
|
|
1640
1700
|
}
|
|
1641
1701
|
|
|
1642
|
-
function importPluginsByPlatformSnapshot(snapshotByPlatform = {}, legacyPlugins = [], overwrite = true, results) {
|
|
1643
|
-
const pluginsByPlatform = getPluginsByPlatformItems(legacyPlugins, snapshotByPlatform);
|
|
1702
|
+
function importPluginsByPlatformSnapshot(snapshotByPlatform = {}, legacyPlugins = [], overwrite = true, results, registry = getExportRegistry()) {
|
|
1703
|
+
const pluginsByPlatform = getPluginsByPlatformItems(legacyPlugins, snapshotByPlatform, registry);
|
|
1644
1704
|
|
|
1645
|
-
for (const platform of
|
|
1705
|
+
for (const platform of getPluginPlatforms(registry)) {
|
|
1706
|
+
const pluginPaths = getPlatformPluginPaths(platform, registry);
|
|
1646
1707
|
const snapshot = snapshotByPlatform?.[platform] && typeof snapshotByPlatform[platform] === 'object'
|
|
1647
1708
|
? snapshotByPlatform[platform]
|
|
1648
1709
|
: {};
|
|
1649
|
-
const repoStatus = mergePluginRepoConfig(platform, snapshot, overwrite);
|
|
1710
|
+
const repoStatus = mergePluginRepoConfig(platform, snapshot, overwrite, registry);
|
|
1650
1711
|
results.plugins.success += repoStatus.changed;
|
|
1651
1712
|
results.plugins.skipped += repoStatus.skipped;
|
|
1652
1713
|
results.plugins.failed += repoStatus.failed;
|
|
@@ -1655,38 +1716,45 @@ function importPluginsByPlatformSnapshot(snapshotByPlatform = {}, legacyPlugins
|
|
|
1655
1716
|
const hasControl = snapshot?.control && Object.keys(snapshot.control).length > 0;
|
|
1656
1717
|
|
|
1657
1718
|
if (platform === 'codex' && (hasControl || plugins.length > 0)) {
|
|
1658
|
-
applyImportStatus(results, mergeCodexPluginConfig(snapshot, plugins, overwrite));
|
|
1719
|
+
applyImportStatus(results, mergeCodexPluginConfig(snapshot, plugins, overwrite, pluginPaths.configPath));
|
|
1659
1720
|
} else if (platform === 'opencode' && (hasControl || plugins.length > 0)) {
|
|
1660
1721
|
const packages = plugins
|
|
1661
1722
|
.filter(plugin => plugin.type === 'opencode-package' || plugin.pluginType === 'npm')
|
|
1662
1723
|
.map(plugin => plugin.name || plugin.directory)
|
|
1663
1724
|
.filter(Boolean);
|
|
1664
|
-
applyImportStatus(results, writeOpenCodePluginConfig(packages, overwrite));
|
|
1725
|
+
applyImportStatus(results, writeOpenCodePluginConfig(packages, overwrite, pluginPaths.configDir));
|
|
1665
1726
|
} else if (platform === 'omp' && (hasControl || plugins.length > 0)) {
|
|
1666
|
-
applyImportStatus(results, writeOmpPluginSettings(plugins, snapshot, overwrite));
|
|
1727
|
+
applyImportStatus(results, writeOmpPluginSettings(plugins, snapshot, overwrite, pluginPaths.settingsPath));
|
|
1667
1728
|
}
|
|
1668
1729
|
|
|
1669
1730
|
for (const plugin of plugins) {
|
|
1670
1731
|
try {
|
|
1671
1732
|
if (platform === 'codex') {
|
|
1672
|
-
applyImportStatus(results, importPluginToDirectory(platform, plugin, CODEX_PLUGINS_CACHE_DIR, overwrite));
|
|
1733
|
+
applyImportStatus(results, importPluginToDirectory(platform, plugin, pluginPaths.cacheDir || CODEX_PLUGINS_CACHE_DIR, overwrite));
|
|
1673
1734
|
} else if (platform === 'opencode') {
|
|
1674
1735
|
if (plugin.type === 'opencode-package' || plugin.pluginType === 'npm') {
|
|
1675
1736
|
continue;
|
|
1676
1737
|
}
|
|
1677
|
-
|
|
1738
|
+
const openCodePluginsDir = fs.existsSync(pluginPaths.legacyPluginsDir) && !fs.existsSync(pluginPaths.pluginsDir)
|
|
1739
|
+
? pluginPaths.legacyPluginsDir
|
|
1740
|
+
: pluginPaths.pluginsDir;
|
|
1741
|
+
applyImportStatus(results, importPluginToDirectory(platform, plugin, openCodePluginsDir || getOpenCodePluginsDir(), overwrite));
|
|
1678
1742
|
} else if (platform === 'omp') {
|
|
1679
1743
|
if (plugin.type === 'omp-package' || plugin.pluginType === 'package') {
|
|
1680
1744
|
continue;
|
|
1681
1745
|
}
|
|
1682
|
-
applyImportStatus(results, importPluginToDirectory(platform, plugin, OMP_EXTENSIONS_DIR, overwrite));
|
|
1746
|
+
applyImportStatus(results, importPluginToDirectory(platform, plugin, pluginPaths.extensionsDir || OMP_EXTENSIONS_DIR, overwrite));
|
|
1683
1747
|
} else if (platform === 'claude') {
|
|
1684
1748
|
const isLegacy = plugin.type === 'legacy';
|
|
1685
1749
|
applyImportStatus(results, importPluginToDirectory(
|
|
1686
1750
|
platform,
|
|
1687
1751
|
plugin,
|
|
1688
|
-
isLegacy ? LEGACY_PLUGINS_DIR : CLAUDE_PLUGINS_DIR,
|
|
1689
|
-
overwrite
|
|
1752
|
+
isLegacy ? LEGACY_PLUGINS_DIR : (pluginPaths.pluginsDir || CLAUDE_PLUGINS_DIR),
|
|
1753
|
+
overwrite,
|
|
1754
|
+
isLegacy ? {} : {
|
|
1755
|
+
installedRegistryPath: pluginPaths.installedRegistry,
|
|
1756
|
+
settingsPath: claudeSettingsPath
|
|
1757
|
+
}
|
|
1690
1758
|
));
|
|
1691
1759
|
}
|
|
1692
1760
|
} catch (err) {
|
|
@@ -1697,11 +1765,11 @@ function importPluginsByPlatformSnapshot(snapshotByPlatform = {}, legacyPlugins
|
|
|
1697
1765
|
}
|
|
1698
1766
|
}
|
|
1699
1767
|
|
|
1700
|
-
function updateClaudePluginRegistry(plugin, pluginDir) {
|
|
1768
|
+
function updateClaudePluginRegistry(plugin, pluginDir, { installedRegistryPath = NATIVE_PLUGINS_REGISTRY, settingsPath = CLAUDE_SETTINGS_PATH } = {}) {
|
|
1701
1769
|
const pluginName = plugin.name || path.basename(pluginDir);
|
|
1702
1770
|
const marketplace = plugin.marketplace || '';
|
|
1703
1771
|
const nativeKey = marketplace ? `${pluginName}@${marketplace}` : pluginName;
|
|
1704
|
-
const installed = readJsonFileSafe(
|
|
1772
|
+
const installed = readJsonFileSafe(installedRegistryPath) || { version: 2, plugins: {} };
|
|
1705
1773
|
installed.version = installed.version || 2;
|
|
1706
1774
|
installed.plugins = installed.plugins && typeof installed.plugins === 'object' ? installed.plugins : {};
|
|
1707
1775
|
installed.plugins[nativeKey] = [{
|
|
@@ -1722,14 +1790,14 @@ function updateClaudePluginRegistry(plugin, pluginDir) {
|
|
|
1722
1790
|
...(plugin.repoLocalPath ? { repoLocalPath: plugin.repoLocalPath } : {}),
|
|
1723
1791
|
...(plugin.repoId ? { repoId: plugin.repoId } : {})
|
|
1724
1792
|
}];
|
|
1725
|
-
writeJsonFileAbsolute(
|
|
1793
|
+
writeJsonFileAbsolute(installedRegistryPath, installed, true);
|
|
1726
1794
|
|
|
1727
|
-
const settings = readJsonFileSafe(
|
|
1795
|
+
const settings = readJsonFileSafe(settingsPath) || {};
|
|
1728
1796
|
settings.enabledPlugins = settings.enabledPlugins && typeof settings.enabledPlugins === 'object'
|
|
1729
1797
|
? settings.enabledPlugins
|
|
1730
1798
|
: {};
|
|
1731
1799
|
settings.enabledPlugins[nativeKey] = plugin.enabled !== false;
|
|
1732
|
-
writeJsonFileAbsolute(
|
|
1800
|
+
writeJsonFileAbsolute(settingsPath, settings, true);
|
|
1733
1801
|
}
|
|
1734
1802
|
|
|
1735
1803
|
function writeTextFile(baseDir, relativePath, content, overwrite) {
|
|
@@ -1745,21 +1813,23 @@ function writeTextFile(baseDir, relativePath, content, overwrite) {
|
|
|
1745
1813
|
return 'success';
|
|
1746
1814
|
}
|
|
1747
1815
|
|
|
1748
|
-
function
|
|
1749
|
-
const
|
|
1750
|
-
const
|
|
1751
|
-
|
|
1752
|
-
const opencode = opencodeChannelsService.getChannels()?.channels || [];
|
|
1753
|
-
const omp = ompChannelsService.getChannels()?.channels || [];
|
|
1754
|
-
return { claude, codex, gemini, opencode, omp };
|
|
1816
|
+
function readDriverChannels(driver) {
|
|
1817
|
+
const result = typeof driver?.list === 'function' ? driver.list() : null;
|
|
1818
|
+
const data = result?.status === 'ok' ? result.data : result;
|
|
1819
|
+
return Array.isArray(data) ? data : data?.channels || [];
|
|
1755
1820
|
}
|
|
1756
1821
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1822
|
+
function getAllChannelsByType() {
|
|
1823
|
+
return Object.fromEntries(
|
|
1824
|
+
getPlatformCatalog().keys({ capability: 'channels' })
|
|
1825
|
+
.map(platform => [platform, readDriverChannels(getChannelDriver(platform))])
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1761
1828
|
function exportAllConfigs() {
|
|
1762
1829
|
try {
|
|
1830
|
+
const registry = getExportRegistry();
|
|
1831
|
+
const claudeNative = getConfiguredNativePaths('claude', registry);
|
|
1832
|
+
const claudeSettingsPath = claudeNative.settings || CLAUDE_SETTINGS_PATH;
|
|
1763
1833
|
// 获取所有配置模板(只导出自定义模板)
|
|
1764
1834
|
const allConfigTemplates = configTemplatesService.getAllTemplates();
|
|
1765
1835
|
const customConfigTemplates = allConfigTemplates.filter(t => !t.isBuiltin);
|
|
@@ -1777,9 +1847,9 @@ function exportAllConfigs() {
|
|
|
1777
1847
|
const favorites = favoritesService.loadFavorites();
|
|
1778
1848
|
|
|
1779
1849
|
// 获取 Agents / Skills / Commands 配置(多平台)
|
|
1780
|
-
const agentsByPlatform = exportAgentsSnapshotByPlatform();
|
|
1781
|
-
const skillsByPlatform = exportSkillsSnapshotByPlatform();
|
|
1782
|
-
const commandsByPlatform = exportCommandsSnapshotByPlatform();
|
|
1850
|
+
const agentsByPlatform = exportAgentsSnapshotByPlatform(registry);
|
|
1851
|
+
const skillsByPlatform = exportSkillsSnapshotByPlatform(registry);
|
|
1852
|
+
const commandsByPlatform = exportCommandsSnapshotByPlatform(registry);
|
|
1783
1853
|
const agents = agentsByPlatform.claude || [];
|
|
1784
1854
|
const skills = skillsByPlatform.claude || [];
|
|
1785
1855
|
const commands = commandsByPlatform.claude || [];
|
|
@@ -1789,9 +1859,10 @@ function exportAllConfigs() {
|
|
|
1789
1859
|
const mcpServers = mcpService.getAllServers();
|
|
1790
1860
|
|
|
1791
1861
|
// 获取 Plugins 配置
|
|
1792
|
-
const
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1862
|
+
const pluginsByPlatform = exportPluginsSnapshotByPlatform(registry);
|
|
1863
|
+
const plugins = Object.values(pluginsByPlatform)
|
|
1864
|
+
.flatMap(snapshot => Array.isArray(snapshot?.plugins) ? snapshot.plugins : []);
|
|
1865
|
+
const nativeConfigs = exportNativeConfigs(registry);
|
|
1795
1866
|
const oauthCredentials = readJsonFileSafe(PATHS.oauthCredentials);
|
|
1796
1867
|
|
|
1797
1868
|
// 读取 Markdown 配置文件
|
|
@@ -1819,7 +1890,7 @@ function exportAllConfigs() {
|
|
|
1819
1890
|
const security = readJsonFileSafe(CC_SECURITY_PATH);
|
|
1820
1891
|
const appConfig = loadConfig();
|
|
1821
1892
|
|
|
1822
|
-
const claudeSettings = readJsonFileSafe(
|
|
1893
|
+
const claudeSettings = readJsonFileSafe(claudeSettingsPath);
|
|
1823
1894
|
const claudeHooks = {
|
|
1824
1895
|
uiConfig: readJsonFileSafe(LEGACY_UI_CONFIG_PATH),
|
|
1825
1896
|
notifyScript: readTextFileSafe(LEGACY_NOTIFY_HOOK_PATH),
|
|
@@ -1900,6 +1971,10 @@ function exportAllConfigsZip() {
|
|
|
1900
1971
|
*/
|
|
1901
1972
|
async function importConfigs(importData, options = {}) {
|
|
1902
1973
|
const { overwrite = true } = options; // 默认覆盖模式
|
|
1974
|
+
const registry = options.registry || getExportRegistry();
|
|
1975
|
+
const claudeNative = getConfiguredNativePaths('claude', registry);
|
|
1976
|
+
const claudeSettingsPath = claudeNative.settings || CLAUDE_SETTINGS_PATH;
|
|
1977
|
+
const claudePluginPaths = getPlatformPluginPaths('claude', registry);
|
|
1903
1978
|
const results = {
|
|
1904
1979
|
configTemplates: { success: 0, failed: 0, skipped: 0 },
|
|
1905
1980
|
channels: { success: 0, failed: 0, skipped: 0 },
|
|
@@ -1951,20 +2026,18 @@ async function importConfigs(importData, options = {}) {
|
|
|
1951
2026
|
claudeHooks = null
|
|
1952
2027
|
} = importData.data;
|
|
1953
2028
|
|
|
1954
|
-
const importAgentsByPlatform = normalizePlatformItems(agents, agentsByPlatform,
|
|
1955
|
-
const importSkillsByPlatform = normalizePlatformItems(skills, skillsByPlatform,
|
|
1956
|
-
const importCommandsByPlatform = normalizePlatformItems(commands, commandsByPlatform,
|
|
2029
|
+
const importAgentsByPlatform = normalizePlatformItems(agents, agentsByPlatform, getAgentPlatforms(registry));
|
|
2030
|
+
const importSkillsByPlatform = normalizePlatformItems(skills, skillsByPlatform, getSkillPlatforms(registry));
|
|
2031
|
+
const importCommandsByPlatform = normalizePlatformItems(commands, commandsByPlatform, getCommandPlatforms(registry));
|
|
1957
2032
|
|
|
2033
|
+
const channelPlatforms = getPlatformCatalog().keys({ capability: 'channels' });
|
|
1958
2034
|
const hasTypedChannels = channelsByType && typeof channelsByType === 'object';
|
|
1959
|
-
const importChannelsByType =
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
opencode: hasTypedChannels && Array.isArray(channelsByType.opencode) ? channelsByType.opencode : [],
|
|
1966
|
-
omp: hasTypedChannels && Array.isArray(channelsByType.omp) ? channelsByType.omp: []
|
|
1967
|
-
};
|
|
2035
|
+
const importChannelsByType = Object.fromEntries(channelPlatforms.map(platform => [
|
|
2036
|
+
platform,
|
|
2037
|
+
hasTypedChannels && Array.isArray(channelsByType[platform])
|
|
2038
|
+
? channelsByType[platform]
|
|
2039
|
+
: (platform === 'claude' && Array.isArray(channels) ? channels : [])
|
|
2040
|
+
]));
|
|
1968
2041
|
|
|
1969
2042
|
// 导入配置模板
|
|
1970
2043
|
for (const template of configTemplates) {
|
|
@@ -1994,16 +2067,23 @@ async function importConfigs(importData, options = {}) {
|
|
|
1994
2067
|
}
|
|
1995
2068
|
|
|
1996
2069
|
// 导入频道配置(兼容旧结构 channels 和新结构 channelsByType)
|
|
1997
|
-
const importTypedChannels = (
|
|
1998
|
-
const
|
|
2070
|
+
const importTypedChannels = (platform) => {
|
|
2071
|
+
const driver = getChannelDriver(platform);
|
|
2072
|
+
const sourceChannels = importChannelsByType[platform] || [];
|
|
2073
|
+
if (!driver) {
|
|
2074
|
+
results.channels.skipped += sourceChannels.length;
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
1999
2077
|
for (const channel of sourceChannels) {
|
|
2000
2078
|
try {
|
|
2001
|
-
const existingChannels =
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2079
|
+
const existingChannels = readDriverChannels(driver);
|
|
2080
|
+
const existing = existingChannels.find(candidate => (
|
|
2081
|
+
(channel.id && candidate.id === channel.id)
|
|
2082
|
+
|| (channel.providerKey && candidate.providerKey === channel.providerKey)
|
|
2083
|
+
|| (channel.name && channel.baseUrl
|
|
2084
|
+
&& candidate.name === channel.name
|
|
2085
|
+
&& candidate.baseUrl === channel.baseUrl)
|
|
2086
|
+
));
|
|
2007
2087
|
|
|
2008
2088
|
if (existing && !overwrite) {
|
|
2009
2089
|
results.channels.skipped++;
|
|
@@ -2011,68 +2091,28 @@ async function importConfigs(importData, options = {}) {
|
|
|
2011
2091
|
}
|
|
2012
2092
|
|
|
2013
2093
|
if (existing && overwrite) {
|
|
2014
|
-
|
|
2094
|
+
driver.update(existing.id, { ...channel, id: existing.id });
|
|
2015
2095
|
} else {
|
|
2016
|
-
|
|
2096
|
+
driver.create(channel);
|
|
2017
2097
|
}
|
|
2018
2098
|
results.channels.success++;
|
|
2019
2099
|
} catch (err) {
|
|
2020
|
-
console.error(`[ConfigImport] 导入${
|
|
2100
|
+
console.error(`[ConfigImport] 导入${platform}频道失败: ${channel.name}`, err);
|
|
2021
2101
|
results.channels.failed++;
|
|
2022
2102
|
}
|
|
2023
2103
|
}
|
|
2024
2104
|
};
|
|
2025
2105
|
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
apiKey,
|
|
2037
|
-
wireApi,
|
|
2038
|
-
...extraConfig
|
|
2039
|
-
} = channel;
|
|
2040
|
-
codexChannelsService.createChannel(name, providerKey, baseUrl, apiKey, wireApi, extraConfig);
|
|
2041
|
-
}, (existingChannels, channel) => existingChannels.find(c =>
|
|
2042
|
-
(channel.id && c.id === channel.id) ||
|
|
2043
|
-
(channel.providerKey && c.providerKey === channel.providerKey)
|
|
2044
|
-
));
|
|
2045
|
-
|
|
2046
|
-
importTypedChannels('gemini', geminiChannelsService, channel => {
|
|
2047
|
-
const { name, baseUrl, apiKey, model, ...extraConfig } = channel;
|
|
2048
|
-
geminiChannelsService.createChannel(name, baseUrl, apiKey, model, extraConfig);
|
|
2049
|
-
}, (existingChannels, channel) => existingChannels.find(c =>
|
|
2050
|
-
(channel.id && c.id === channel.id) ||
|
|
2051
|
-
(channel.name && c.name === channel.name)
|
|
2052
|
-
));
|
|
2053
|
-
|
|
2054
|
-
importTypedChannels('opencode', opencodeChannelsService, channel => {
|
|
2055
|
-
const { name, baseUrl, apiKey, ...extraConfig } = channel;
|
|
2056
|
-
opencodeChannelsService.createChannel(name, baseUrl, apiKey, extraConfig);
|
|
2057
|
-
}, (existingChannels, channel) => existingChannels.find(c =>
|
|
2058
|
-
(channel.id && c.id === channel.id) ||
|
|
2059
|
-
(channel.providerKey && c.providerKey === channel.providerKey) ||
|
|
2060
|
-
(channel.name && channel.baseUrl && c.name === channel.name && c.baseUrl === channel.baseUrl)
|
|
2061
|
-
));
|
|
2062
|
-
|
|
2063
|
-
importTypedChannels('omp', ompChannelsService, channel => {
|
|
2064
|
-
const { name, baseUrl, apiKey, ...extraConfig } = channel;
|
|
2065
|
-
ompChannelsService.createChannel(name, baseUrl, apiKey, extraConfig);
|
|
2066
|
-
}, (existingChannels, channel) => existingChannels.find(c =>
|
|
2067
|
-
(channel.id && c.id === channel.id) ||
|
|
2068
|
-
(channel.providerKey && c.providerKey === channel.providerKey) ||
|
|
2069
|
-
(channel.name && channel.baseUrl && c.name === channel.name && c.baseUrl === channel.baseUrl)
|
|
2070
|
-
));
|
|
2071
|
-
if ((importChannelsByType.omp || []).length > 0 && typeof ompChannelsService.syncManagedProviderExtension === 'function') {
|
|
2072
|
-
ompChannelsService.syncManagedProviderExtension();
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
// 导入工作区配置
|
|
2106
|
+
for (const platform of channelPlatforms) {
|
|
2107
|
+
importTypedChannels(platform);
|
|
2108
|
+
}
|
|
2109
|
+
for (const platform of channelPlatforms) {
|
|
2110
|
+
const driver = getChannelDriver(platform);
|
|
2111
|
+
const imported = importChannelsByType[platform] || [];
|
|
2112
|
+
if (imported.length > 0 && typeof driver?.syncManagedProviderExtension === 'function') {
|
|
2113
|
+
driver.syncManagedProviderExtension(imported);
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2076
2116
|
if (workspaces && overwrite) {
|
|
2077
2117
|
try {
|
|
2078
2118
|
const workspaceService = require('./workspace-service');
|
|
@@ -2098,13 +2138,13 @@ async function importConfigs(importData, options = {}) {
|
|
|
2098
2138
|
}
|
|
2099
2139
|
|
|
2100
2140
|
// 导入 Agents(多平台)
|
|
2101
|
-
if (
|
|
2141
|
+
if (getAgentPlatforms(registry).some(platform => importAgentsByPlatform[platform]?.length > 0)) {
|
|
2102
2142
|
try {
|
|
2103
|
-
for (const platform of
|
|
2143
|
+
for (const platform of getAgentPlatforms(registry)) {
|
|
2104
2144
|
const platformAgents = importAgentsByPlatform[platform] || [];
|
|
2105
2145
|
if (platformAgents.length === 0) continue;
|
|
2106
2146
|
|
|
2107
|
-
const agentsService = new AgentsService(platform);
|
|
2147
|
+
const agentsService = new AgentsService(platform, { registry });
|
|
2108
2148
|
const baseDir = agentsService.userAgentsDir;
|
|
2109
2149
|
|
|
2110
2150
|
for (const agent of platformAgents) {
|
|
@@ -2127,13 +2167,13 @@ async function importConfigs(importData, options = {}) {
|
|
|
2127
2167
|
}
|
|
2128
2168
|
|
|
2129
2169
|
// 导入 Skills(多平台)
|
|
2130
|
-
if (
|
|
2170
|
+
if (getSkillPlatforms(registry).some(platform => importSkillsByPlatform[platform]?.length > 0)) {
|
|
2131
2171
|
try {
|
|
2132
|
-
for (const platform of
|
|
2172
|
+
for (const platform of getSkillPlatforms(registry)) {
|
|
2133
2173
|
const platformSkills = importSkillsByPlatform[platform] || [];
|
|
2134
2174
|
if (platformSkills.length === 0) continue;
|
|
2135
2175
|
|
|
2136
|
-
const skillService = new SkillService(platform);
|
|
2176
|
+
const skillService = new SkillService(platform, { registry });
|
|
2137
2177
|
const baseDir = skillService.installDir;
|
|
2138
2178
|
ensureDir(baseDir);
|
|
2139
2179
|
|
|
@@ -2190,7 +2230,7 @@ async function importConfigs(importData, options = {}) {
|
|
|
2190
2230
|
|
|
2191
2231
|
// 导入 Plugins(优先使用多平台结构,兼容旧结构 plugins)
|
|
2192
2232
|
if (pluginsByPlatform && typeof pluginsByPlatform === 'object' && Object.keys(pluginsByPlatform).length > 0) {
|
|
2193
|
-
importPluginsByPlatformSnapshot(pluginsByPlatform, plugins, overwrite, results);
|
|
2233
|
+
importPluginsByPlatformSnapshot(pluginsByPlatform, plugins, overwrite, results, registry);
|
|
2194
2234
|
}
|
|
2195
2235
|
|
|
2196
2236
|
// 导入旧版 Plugins 结构。新包已经通过 pluginsByPlatform 处理过,避免重复写入。
|
|
@@ -2221,8 +2261,8 @@ async function importConfigs(importData, options = {}) {
|
|
|
2221
2261
|
results.plugins.failed++;
|
|
2222
2262
|
continue;
|
|
2223
2263
|
}
|
|
2224
|
-
targetDir = path.join(CLAUDE_PLUGINS_DIR, pluginId);
|
|
2225
|
-
registryPath = NATIVE_PLUGINS_REGISTRY;
|
|
2264
|
+
targetDir = path.join(claudePluginPaths.pluginsDir || CLAUDE_PLUGINS_DIR, pluginId);
|
|
2265
|
+
registryPath = claudePluginPaths.installedRegistry || NATIVE_PLUGINS_REGISTRY;
|
|
2226
2266
|
} else {
|
|
2227
2267
|
console.warn(`[ConfigImport] Unknown plugin type: ${pluginType}`);
|
|
2228
2268
|
results.plugins.failed++;
|
|
@@ -2335,13 +2375,13 @@ async function importConfigs(importData, options = {}) {
|
|
|
2335
2375
|
}
|
|
2336
2376
|
|
|
2337
2377
|
// 导入 Commands(多平台)
|
|
2338
|
-
if (
|
|
2378
|
+
if (getCommandPlatforms(registry).some(platform => importCommandsByPlatform[platform]?.length > 0)) {
|
|
2339
2379
|
try {
|
|
2340
|
-
for (const platform of
|
|
2380
|
+
for (const platform of getCommandPlatforms(registry)) {
|
|
2341
2381
|
const platformCommands = importCommandsByPlatform[platform] || [];
|
|
2342
2382
|
if (platformCommands.length === 0) continue;
|
|
2343
2383
|
|
|
2344
|
-
const commandsService = new CommandsService(platform);
|
|
2384
|
+
const commandsService = new CommandsService(platform, { registry });
|
|
2345
2385
|
const baseDir = commandsService.userCommandsDir;
|
|
2346
2386
|
|
|
2347
2387
|
for (const command of platformCommands) {
|
|
@@ -2482,34 +2522,23 @@ async function importConfigs(importData, options = {}) {
|
|
|
2482
2522
|
|
|
2483
2523
|
// 导入各平台原生配置
|
|
2484
2524
|
if (nativeConfigs && typeof nativeConfigs === 'object' && Object.keys(nativeConfigs).length > 0) {
|
|
2485
|
-
const
|
|
2486
|
-
|
|
2525
|
+
const catalog = getPlatformCatalog();
|
|
2487
2526
|
for (const [platform, platformEntries] of Object.entries(nativeConfigs)) {
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
}
|
|
2492
|
-
|
|
2493
|
-
for (const [key, entry] of Object.entries(platformEntries)) {
|
|
2494
|
-
const spec = platformSpecs[key];
|
|
2495
|
-
if (!spec) {
|
|
2496
|
-
continue;
|
|
2497
|
-
}
|
|
2498
|
-
|
|
2527
|
+
if (!platformEntries || typeof platformEntries !== 'object') continue;
|
|
2528
|
+
const driver = catalog.driver(platform, 'nativeConfig');
|
|
2529
|
+
if (typeof driver?.importSnapshot === 'function') {
|
|
2499
2530
|
try {
|
|
2500
|
-
const
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
results.nativeConfigs.skipped++;
|
|
2505
|
-
} else {
|
|
2506
|
-
results.nativeConfigs.failed++;
|
|
2507
|
-
}
|
|
2531
|
+
const imported = driver.importSnapshot(platformEntries, { overwrite });
|
|
2532
|
+
results.nativeConfigs.success += imported?.imported ?? imported?.success ?? 0;
|
|
2533
|
+
results.nativeConfigs.skipped += imported?.skipped || 0;
|
|
2534
|
+
results.nativeConfigs.failed += imported?.failed || 0;
|
|
2508
2535
|
} catch (err) {
|
|
2509
|
-
console.error(`[ConfigImport] 导入 ${platform}
|
|
2510
|
-
results.nativeConfigs.failed
|
|
2536
|
+
console.error(`[ConfigImport] 导入 ${platform} 原生配置失败:`, err);
|
|
2537
|
+
results.nativeConfigs.failed += Object.keys(platformEntries).length;
|
|
2511
2538
|
}
|
|
2539
|
+
continue;
|
|
2512
2540
|
}
|
|
2541
|
+
results.nativeConfigs.skipped += Object.keys(platformEntries).length;
|
|
2513
2542
|
}
|
|
2514
2543
|
}
|
|
2515
2544
|
|
|
@@ -2551,10 +2580,10 @@ async function importConfigs(importData, options = {}) {
|
|
|
2551
2580
|
}
|
|
2552
2581
|
|
|
2553
2582
|
if (claudeHooks.stopHook !== undefined) {
|
|
2554
|
-
if (!overwrite && fs.existsSync(
|
|
2583
|
+
if (!overwrite && fs.existsSync(claudeSettingsPath)) {
|
|
2555
2584
|
didSkip = true;
|
|
2556
2585
|
} else {
|
|
2557
|
-
const settings = readJsonFileSafe(
|
|
2586
|
+
const settings = readJsonFileSafe(claudeSettingsPath) || {};
|
|
2558
2587
|
settings.hooks = settings.hooks || {};
|
|
2559
2588
|
if (claudeHooks.stopHook) {
|
|
2560
2589
|
settings.hooks.Stop = claudeHooks.stopHook;
|
|
@@ -2564,7 +2593,7 @@ async function importConfigs(importData, options = {}) {
|
|
|
2564
2593
|
delete settings.hooks;
|
|
2565
2594
|
}
|
|
2566
2595
|
}
|
|
2567
|
-
writeJsonFileAbsolute(
|
|
2596
|
+
writeJsonFileAbsolute(claudeSettingsPath, settings, true);
|
|
2568
2597
|
didWrite = true;
|
|
2569
2598
|
}
|
|
2570
2599
|
}
|
|
@@ -2647,5 +2676,7 @@ function generateImportSummary(results) {
|
|
|
2647
2676
|
module.exports = {
|
|
2648
2677
|
exportAllConfigs,
|
|
2649
2678
|
exportAllConfigsZip,
|
|
2650
|
-
importConfigs
|
|
2679
|
+
importConfigs,
|
|
2680
|
+
exportPlatformSnapshots,
|
|
2681
|
+
getPlatformKeysForType
|
|
2651
2682
|
};
|