swayrouter 1.0.0
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/.env.example +43 -0
- package/CHANGELOG.md +132 -0
- package/LICENSE +30 -0
- package/README.id.md +633 -0
- package/README.md +628 -0
- package/cli/cli.js +388 -0
- package/cli/package.json +4 -0
- package/cli/src/cli/commands/xaiVideo.js +280 -0
- package/cli/src/cli/tray/SwayAvatar.svg +20 -0
- package/cli/src/cli/tray/autostart.js +351 -0
- package/cli/src/cli/tray/icon.ico +0 -0
- package/cli/src/cli/tray/icon.png +0 -0
- package/cli/src/cli/tray/tray.js +258 -0
- package/cli/src/cli/tray/tray.ps1 +129 -0
- package/cli/src/cli/tray/trayHost.js +157 -0
- package/cli/src/cli/tray/trayWin.js +83 -0
- package/cli/src/cli/utils/display.js +123 -0
- package/cli/src/cli/utils/input.js +138 -0
- package/cli/src/runtime/discover.js +153 -0
- package/cli/src/runtime/lifecycle.js +333 -0
- package/cli/src/runtime/runMenu.js +250 -0
- package/cli/src/runtime/uiAdapters.js +12 -0
- package/cli/src/runtime/update.js +130 -0
- package/dashboard/dist/assets/CliTools-Ch3gKuNw.js +24 -0
- package/dashboard/dist/assets/Combo-BBCldjWi.js +1 -0
- package/dashboard/dist/assets/ConsoleLog-wywAYcPT.js +6 -0
- package/dashboard/dist/assets/Dashboard-DxzyF41b.js +1 -0
- package/dashboard/dist/assets/Header-C_9Su9BF.js +1 -0
- package/dashboard/dist/assets/Keys-D0ufgcsc.js +1 -0
- package/dashboard/dist/assets/Login-BeKpipS_.js +1 -0
- package/dashboard/dist/assets/ManageApiKey-CVXsmW2B.js +1 -0
- package/dashboard/dist/assets/OAuthCallback-D_UZYcF6.js +1 -0
- package/dashboard/dist/assets/Provider-BU7JfTqm.js +4 -0
- package/dashboard/dist/assets/ProviderModelAccordion-BAifkfVR.js +1 -0
- package/dashboard/dist/assets/Proxy-CU15VJ--.js +1 -0
- package/dashboard/dist/assets/QuotaMonitor-HzGK7bcc.js +1 -0
- package/dashboard/dist/assets/Settings-Dt4y2dC0.js +1 -0
- package/dashboard/dist/assets/Setup-DSDUwU7N.js +1 -0
- package/dashboard/dist/assets/StatusBadge-1nAOyHU2.js +1 -0
- package/dashboard/dist/assets/SwayChat-Bup7up6D.js +10 -0
- package/dashboard/dist/assets/Usage-eWnrPQ_v.js +4 -0
- package/dashboard/dist/assets/accordion-DOOPDDgt.js +1 -0
- package/dashboard/dist/assets/admin-extras-api-CCdu5TFM.js +1 -0
- package/dashboard/dist/assets/api-keys-api-ifAC2Ok3.js +1 -0
- package/dashboard/dist/assets/card-CC0Omjcv.js +1 -0
- package/dashboard/dist/assets/chatStudio-C0zPz_Z_.js +2 -0
- package/dashboard/dist/assets/checkbox-7SZBrmbN.js +1 -0
- package/dashboard/dist/assets/connections-api-_N54UD3S.js +1 -0
- package/dashboard/dist/assets/copy-button-qBvM6H9z.js +1 -0
- package/dashboard/dist/assets/currency-api-SV9CBf5e.js +1 -0
- package/dashboard/dist/assets/flip-button-BGgkjtl0.js +1 -0
- package/dashboard/dist/assets/frame-cUiti6Lq.js +1 -0
- package/dashboard/dist/assets/icons-vendor-CUx7SB5V.js +541 -0
- package/dashboard/dist/assets/index-B6j-9zHy.js +10 -0
- package/dashboard/dist/assets/index-C-_l0yYz.css +1 -0
- package/dashboard/dist/assets/live-mode-CHShLY4E.js +1 -0
- package/dashboard/dist/assets/markdown-vendor-BY8e1gQ8.js +29 -0
- package/dashboard/dist/assets/motion-vendor-g5fpGzmJ.js +9 -0
- package/dashboard/dist/assets/oauth-callback-CqYQzyd7.js +1 -0
- package/dashboard/dist/assets/query-vendor-DVevaSVS.js +1 -0
- package/dashboard/dist/assets/react-vendor-xnYrwzsL.js +61 -0
- package/dashboard/dist/assets/ripple-button-l8aMiVVG.js +1 -0
- package/dashboard/dist/assets/segmented-CqmEnQjZ.js +1 -0
- package/dashboard/dist/assets/select-D8pUtMXp.js +1 -0
- package/dashboard/dist/assets/skeleton-7uJDiIXe.js +1 -0
- package/dashboard/dist/assets/table-D0M60Tu1.js +1 -0
- package/dashboard/dist/assets/tabs-C6YkuulG.js +1 -0
- package/dashboard/dist/assets/tunnel-api-DDPsBaDV.js +1 -0
- package/dashboard/dist/assets/ui-vendor-BuM9f2NY.js +17 -0
- package/dashboard/dist/image2/SwayAvatar.svg +20 -0
- package/dashboard/dist/index.html +32 -0
- package/dashboard/dist/logo/avatar.svg +1 -0
- package/dashboard/dist/logo/sway.svg +20 -0
- package/dashboard/dist/logo/swaychat.svg +20 -0
- package/dashboard/dist/providers/SwayCustom.svg +19 -0
- package/dashboard/dist/providers/alicode.svg +12 -0
- package/dashboard/dist/providers/anthropic.svg +11 -0
- package/dashboard/dist/providers/antigravity.svg +3 -0
- package/dashboard/dist/providers/azure.svg +5 -0
- package/dashboard/dist/providers/baidu.svg +3 -0
- package/dashboard/dist/providers/blackbox.svg +5 -0
- package/dashboard/dist/providers/byteplus.svg +3 -0
- package/dashboard/dist/providers/cerebras.svg +4 -0
- package/dashboard/dist/providers/chutes.svg +4 -0
- package/dashboard/dist/providers/claude.svg +3 -0
- package/dashboard/dist/providers/cline.svg +11 -0
- package/dashboard/dist/providers/cloudflare-ai.svg +4 -0
- package/dashboard/dist/providers/codebuddy.svg +11 -0
- package/dashboard/dist/providers/codex.svg +10 -0
- package/dashboard/dist/providers/commandcode.svg +3 -0
- package/dashboard/dist/providers/cursor.svg +3 -0
- package/dashboard/dist/providers/deepseek.svg +10 -0
- package/dashboard/dist/providers/featherless.svg +3 -0
- package/dashboard/dist/providers/fireworks.svg +3 -0
- package/dashboard/dist/providers/gemini.svg +3 -0
- package/dashboard/dist/providers/geminicli.svg +11 -0
- package/dashboard/dist/providers/github.svg +3 -0
- package/dashboard/dist/providers/grok.svg +3 -0
- package/dashboard/dist/providers/groq.svg +3 -0
- package/dashboard/dist/providers/hermesagent.svg +1 -0
- package/dashboard/dist/providers/kilocode.svg +15 -0
- package/dashboard/dist/providers/kimchi.svg +3 -0
- package/dashboard/dist/providers/kimi.svg +4 -0
- package/dashboard/dist/providers/kiro.svg +10 -0
- package/dashboard/dist/providers/meta.svg +3 -0
- package/dashboard/dist/providers/mimo.svg +10 -0
- package/dashboard/dist/providers/minimax.svg +3 -0
- package/dashboard/dist/providers/mistral.svg +3 -0
- package/dashboard/dist/providers/morph.svg +3 -0
- package/dashboard/dist/providers/nebius.svg +4 -0
- package/dashboard/dist/providers/nvidia.svg +3 -0
- package/dashboard/dist/providers/ollama.svg +3 -0
- package/dashboard/dist/providers/omp.svg +5 -0
- package/dashboard/dist/providers/openai.svg +3 -0
- package/dashboard/dist/providers/opencode.svg +3 -0
- package/dashboard/dist/providers/openrouter.svg +3 -0
- package/dashboard/dist/providers/perplexity.svg +3 -0
- package/dashboard/dist/providers/poolside.svg +36 -0
- package/dashboard/dist/providers/qoder.svg +11 -0
- package/dashboard/dist/providers/sumopod.svg +3 -0
- package/dashboard/dist/providers/tencent.svg +5 -0
- package/dashboard/dist/providers/together.svg +12 -0
- package/dashboard/dist/providers/trae.svg +3 -0
- package/dashboard/dist/providers/venice.svg +4 -0
- package/dashboard/dist/providers/vercel.svg +3 -0
- package/dashboard/dist/providers/vertex.svg +17 -0
- package/dashboard/dist/providers/windsurf.svg +10 -0
- package/dashboard/dist/providers/zai.svg +3 -0
- package/dashboard/tsconfig.json +13 -0
- package/package.json +87 -0
- package/src/config/appConstants.js +153 -0
- package/src/config/defaultThinkingSignature.js +7 -0
- package/src/config/errorConfig.js +117 -0
- package/src/config/grokCli.js +9 -0
- package/src/config/kiroConstants.js +235 -0
- package/src/config/mediaConfig.js +20 -0
- package/src/config/ollamaModels.js +18 -0
- package/src/config/providerModels.js +109 -0
- package/src/config/providers.js +17 -0
- package/src/config/runtimeConfig.js +84 -0
- package/src/dashboardGuard.js +254 -0
- package/src/executors/antigravity.js +389 -0
- package/src/executors/azure.js +49 -0
- package/src/executors/base.js +225 -0
- package/src/executors/codebuddy-cn.js +23 -0
- package/src/executors/codebuddy-intl.js +60 -0
- package/src/executors/codex.js +436 -0
- package/src/executors/commandcode.js +83 -0
- package/src/executors/cursor.js +1075 -0
- package/src/executors/default.js +294 -0
- package/src/executors/gemini-cli.js +88 -0
- package/src/executors/github.js +393 -0
- package/src/executors/grok-cli.js +510 -0
- package/src/executors/grok-web.js +342 -0
- package/src/executors/index.js +86 -0
- package/src/executors/kimchi.js +116 -0
- package/src/executors/kiro.js +1155 -0
- package/src/executors/ollama-local.js +14 -0
- package/src/executors/opencode-go.js +47 -0
- package/src/executors/opencode.js +31 -0
- package/src/executors/qoder.js +433 -0
- package/src/executors/trae.js +318 -0
- package/src/executors/vertex.js +151 -0
- package/src/executors/windsurf.js +555 -0
- package/src/executors/xiaomi-tokenplan.js +16 -0
- package/src/handlers/chatCore/nonStreamingHandler.js +370 -0
- package/src/handlers/chatCore/requestDetail.js +130 -0
- package/src/handlers/chatCore/sseToJsonHandler.js +318 -0
- package/src/handlers/chatCore/streamingHandler.js +250 -0
- package/src/handlers/chatCore.js +652 -0
- package/src/lib/auth/dashboardSession.js +83 -0
- package/src/lib/auth/loginLimiter.js +99 -0
- package/src/lib/cache/ttlCache.js +153 -0
- package/src/lib/consoleLogBuffer.js +127 -0
- package/src/lib/dataDir.js +45 -0
- package/src/lib/db/adapters/betterSqliteAdapter.js +36 -0
- package/src/lib/db/adapters/bunSqliteAdapter.js +47 -0
- package/src/lib/db/adapters/nodeSqliteAdapter.js +65 -0
- package/src/lib/db/adapters/runtimeHelpers.js +23 -0
- package/src/lib/db/adapters/sqljsAdapter.js +103 -0
- package/src/lib/db/backup.js +75 -0
- package/src/lib/db/driver.js +110 -0
- package/src/lib/db/helpers/jsonCol.js +18 -0
- package/src/lib/db/helpers/kvStore.js +48 -0
- package/src/lib/db/helpers/metaStore.js +32 -0
- package/src/lib/db/index.js +473 -0
- package/src/lib/db/migrate.js +267 -0
- package/src/lib/db/migrations/001-initial.js +12 -0
- package/src/lib/db/migrations/002-prune-headroom-pxpipe-settings.js +32 -0
- package/src/lib/db/migrations/004-request-details-trace-id.js +12 -0
- package/src/lib/db/migrations/005-request-details-payload-capture.js +11 -0
- package/src/lib/db/migrations/007-headroom-readd-settings.js +35 -0
- package/src/lib/db/migrations/008-account-model-locks.js +22 -0
- package/src/lib/db/migrations/009-warp-pool-lifecycle.js +5 -0
- package/src/lib/db/migrations/010-api-key-file-permissions.js +7 -0
- package/src/lib/db/migrations/011-remove-upstream-user-agent-profile.js +41 -0
- package/src/lib/db/migrations/012-remove-headroom-settings.js +33 -0
- package/src/lib/db/migrations/013-default-fill-first-routing.js +20 -0
- package/src/lib/db/migrations/014-normalize-fill-first-routing.js +37 -0
- package/src/lib/db/migrations/015-remove-ip-ban-tables.js +8 -0
- package/src/lib/db/migrations/016-prune-legacy-codebuddy-intl-models.js +25 -0
- package/src/lib/db/migrations/index.js +20 -0
- package/src/lib/db/nineRouterMigration.js +785 -0
- package/src/lib/db/paths.js +23 -0
- package/src/lib/db/repos/accountModelLocksRepo.js +74 -0
- package/src/lib/db/repos/aliasRepo.js +108 -0
- package/src/lib/db/repos/apiKeysRepo.js +204 -0
- package/src/lib/db/repos/combosRepo.js +85 -0
- package/src/lib/db/repos/connectionsRepo.js +522 -0
- package/src/lib/db/repos/disabledModelsRepo.js +63 -0
- package/src/lib/db/repos/nodesRepo.js +127 -0
- package/src/lib/db/repos/pricingRepo.js +108 -0
- package/src/lib/db/repos/proxyPoolsRepo.js +104 -0
- package/src/lib/db/repos/requestDetailsRepo.js +345 -0
- package/src/lib/db/repos/settingsRepo.js +135 -0
- package/src/lib/db/repos/usageRepo.js +1335 -0
- package/src/lib/db/schema.js +179 -0
- package/src/lib/db/version.js +32 -0
- package/src/lib/db/writeBehind.js +174 -0
- package/src/lib/disabledModelsDb.js +3 -0
- package/src/lib/env.ts +175 -0
- package/src/lib/errors/publicError.js +18 -0
- package/src/lib/grokBuildConfig.js +243 -0
- package/src/lib/guardRequest.js +51 -0
- package/src/lib/localDb.js +21 -0
- package/src/lib/mcp/stdioSseBridge.js +174 -0
- package/src/lib/network/connectionProxy.js +200 -0
- package/src/lib/network/proxyTest.js +158 -0
- package/src/lib/network/proxyUrl.js +76 -0
- package/src/lib/network/relay.js +71 -0
- package/src/lib/oauth/constants/oauth.js +152 -0
- package/src/lib/oauth/constants/xai.js +43 -0
- package/src/lib/oauth/kiroExternalIdp.js +167 -0
- package/src/lib/oauth/providerHelpers.js +90 -0
- package/src/lib/oauth/providers/_shared.js +12 -0
- package/src/lib/oauth/providers/antigravity.js +126 -0
- package/src/lib/oauth/providers/claude.js +60 -0
- package/src/lib/oauth/providers/cline.js +62 -0
- package/src/lib/oauth/providers/clinepass.js +62 -0
- package/src/lib/oauth/providers/codebuddy-cn.js +75 -0
- package/src/lib/oauth/providers/codebuddy-intl.js +73 -0
- package/src/lib/oauth/providers/codex.js +72 -0
- package/src/lib/oauth/providers/cursor.js +18 -0
- package/src/lib/oauth/providers/gemini-cli.js +84 -0
- package/src/lib/oauth/providers/github.js +96 -0
- package/src/lib/oauth/providers/grok-cli.js +123 -0
- package/src/lib/oauth/providers/index.js +233 -0
- package/src/lib/oauth/providers/kilocode.js +60 -0
- package/src/lib/oauth/providers/kimchi.js +79 -0
- package/src/lib/oauth/providers/kimi.js +79 -0
- package/src/lib/oauth/providers/kiro.js +147 -0
- package/src/lib/oauth/providers/qoder.js +90 -0
- package/src/lib/oauth/providers/trae.js +244 -0
- package/src/lib/oauth/providers/windsurf.js +123 -0
- package/src/lib/oauth/providers/xai.js +95 -0
- package/src/lib/oauth/providers.js +16 -0
- package/src/lib/oauth/services/cursor.js +132 -0
- package/src/lib/oauth/services/kiro.js +351 -0
- package/src/lib/oauth/services/oauth.js +135 -0
- package/src/lib/oauth/services/qoder.js +151 -0
- package/src/lib/oauth/services/xai.js +204 -0
- package/src/lib/oauth/utils/ideDetect.js +55 -0
- package/src/lib/oauth/utils/pkce.js +25 -0
- package/src/lib/oauth/utils/server.js +732 -0
- package/src/lib/oauth/utils/ui.js +43 -0
- package/src/lib/providerNormalization.js +40 -0
- package/src/lib/qoder/constants.js +1 -0
- package/src/lib/requestDetailsDb.js +3 -0
- package/src/lib/resourceProfile.ts +124 -0
- package/src/lib/runtimeSecrets.ts +130 -0
- package/src/lib/security/payloadCapture.js +87 -0
- package/src/lib/tunnel/cloudflare/cloudflared.js +436 -0
- package/src/lib/tunnel/cloudflare/config.js +8 -0
- package/src/lib/tunnel/cloudflare/healthCheck.js +37 -0
- package/src/lib/tunnel/cloudflare/manager.js +149 -0
- package/src/lib/tunnel/cloudflare/pid.js +31 -0
- package/src/lib/tunnel/cloudflare/publicUrl.js +41 -0
- package/src/lib/tunnel/cloudflare/requirements.js +12 -0
- package/src/lib/tunnel/index.js +26 -0
- package/src/lib/tunnel/shared/dnsResolver.js +16 -0
- package/src/lib/tunnel/shared/internetCheck.js +30 -0
- package/src/lib/tunnel/shared/state.js +45 -0
- package/src/lib/tunnel/shared/watchdogConfig.js +6 -0
- package/src/lib/update/installer.js +52 -0
- package/src/lib/update/version.js +116 -0
- package/src/lib/usageDb.js +6 -0
- package/src/lib/usageRefresh.js +88 -0
- package/src/lifecycle/appLifecycle.ts +99 -0
- package/src/models.js +36 -0
- package/src/next/headers.js +12 -0
- package/src/next/server.js +74 -0
- package/src/observability/metrics.js +439 -0
- package/src/observability/tracing.js +107 -0
- package/src/open-sse-index.js +70 -0
- package/src/providers/capabilities.js +299 -0
- package/src/providers/display.ts +142 -0
- package/src/providers/index.js +27 -0
- package/src/providers/models/helpers.js +19 -0
- package/src/providers/models/namePatterns.js +27 -0
- package/src/providers/models/schema.js +32 -0
- package/src/providers/pricing.js +248 -0
- package/src/providers/registry/agentrouter.js +52 -0
- package/src/providers/registry/alicode-intl.js +32 -0
- package/src/providers/registry/alicode.js +33 -0
- package/src/providers/registry/alims-intl.js +30 -0
- package/src/providers/registry/anthropic.js +29 -0
- package/src/providers/registry/antigravity.js +139 -0
- package/src/providers/registry/azure.js +23 -0
- package/src/providers/registry/baidu.js +35 -0
- package/src/providers/registry/blackbox.js +41 -0
- package/src/providers/registry/byteplus.js +36 -0
- package/src/providers/registry/cerebras.js +33 -0
- package/src/providers/registry/chutes.js +26 -0
- package/src/providers/registry/claude.js +80 -0
- package/src/providers/registry/cline.js +53 -0
- package/src/providers/registry/clinepass.js +62 -0
- package/src/providers/registry/cloudflare-ai.js +84 -0
- package/src/providers/registry/codebuddy-cn.js +95 -0
- package/src/providers/registry/codebuddy-intl.js +91 -0
- package/src/providers/registry/codex.js +145 -0
- package/src/providers/registry/commandcode.js +45 -0
- package/src/providers/registry/cursor.js +61 -0
- package/src/providers/registry/deepseek.js +55 -0
- package/src/providers/registry/featherless.js +36 -0
- package/src/providers/registry/fireworks.js +34 -0
- package/src/providers/registry/gemini-cli.js +59 -0
- package/src/providers/registry/gemini.js +76 -0
- package/src/providers/registry/github.js +131 -0
- package/src/providers/registry/glm-cn.js +35 -0
- package/src/providers/registry/glm.js +58 -0
- package/src/providers/registry/grok-cli.js +87 -0
- package/src/providers/registry/grok-web.js +41 -0
- package/src/providers/registry/groq.js +38 -0
- package/src/providers/registry/index.js +77 -0
- package/src/providers/registry/kilo-gateway.js +34 -0
- package/src/providers/registry/kilocode.js +48 -0
- package/src/providers/registry/kimchi.js +49 -0
- package/src/providers/registry/kimi.js +82 -0
- package/src/providers/registry/kiro.js +132 -0
- package/src/providers/registry/meta.js +34 -0
- package/src/providers/registry/minimax-cn.js +90 -0
- package/src/providers/registry/minimax.js +90 -0
- package/src/providers/registry/mistral.js +36 -0
- package/src/providers/registry/morph.js +31 -0
- package/src/providers/registry/nebius.js +26 -0
- package/src/providers/registry/nvidia.js +55 -0
- package/src/providers/registry/ollama-local.js +18 -0
- package/src/providers/registry/ollama.js +38 -0
- package/src/providers/registry/openai.js +114 -0
- package/src/providers/registry/opencode-go.js +41 -0
- package/src/providers/registry/opencode.js +26 -0
- package/src/providers/registry/openrouter.js +36 -0
- package/src/providers/registry/perplexity.js +56 -0
- package/src/providers/registry/poolside.js +30 -0
- package/src/providers/registry/qoder.js +58 -0
- package/src/providers/registry/sumopod.js +84 -0
- package/src/providers/registry/tencent.js +29 -0
- package/src/providers/registry/together.js +38 -0
- package/src/providers/registry/trae.js +71 -0
- package/src/providers/registry/venice.js +69 -0
- package/src/providers/registry/vercel-ai-gateway.js +37 -0
- package/src/providers/registry/vertex-partner.js +31 -0
- package/src/providers/registry/vertex.js +33 -0
- package/src/providers/registry/windsurf.js +129 -0
- package/src/providers/registry/xai.js +46 -0
- package/src/providers/registry/xiaomi-mimo.js +66 -0
- package/src/providers/registry/xiaomi-tokenplan.js +58 -0
- package/src/providers/registryEntry.js +3 -0
- package/src/providers/schema.js +33 -0
- package/src/providers/shared.js +114 -0
- package/src/providers/thinkingLevels.js +49 -0
- package/src/routes/api/auth/login/route.js +82 -0
- package/src/routes/api/auth/logout/route.js +9 -0
- package/src/routes/api/auth/reset-password/route.js +12 -0
- package/src/routes/api/auth/status/route.js +33 -0
- package/src/routes/api/auth/verify-password/route.js +39 -0
- package/src/routes/api/chat/tools/curl/route.js +100 -0
- package/src/routes/api/chat/tools/router/route.js +215 -0
- package/src/routes/api/chat/tools/search/route.js +362 -0
- package/src/routes/api/chat/tools/shell/route.js +228 -0
- package/src/routes/api/cli-tools/all-statuses/route.js +37 -0
- package/src/routes/api/cli-tools/claude-settings/route.js +261 -0
- package/src/routes/api/cli-tools/codex-settings/route.js +220 -0
- package/src/routes/api/cli-tools/cowork-mcp-registry/route.js +80 -0
- package/src/routes/api/cli-tools/cowork-mcp-tools/route.js +96 -0
- package/src/routes/api/cli-tools/cowork-settings/route.js +380 -0
- package/src/routes/api/cli-tools/grok-build-settings/route.js +152 -0
- package/src/routes/api/cli-tools/hermes-settings/route.js +169 -0
- package/src/routes/api/cli-tools/kilo-settings/route.js +131 -0
- package/src/routes/api/cli-tools/model-mappings/route.js +43 -0
- package/src/routes/api/cli-tools/omp-settings/route.js +266 -0
- package/src/routes/api/cli-tools/opencode-settings/route.js +243 -0
- package/src/routes/api/combos/[id]/route.js +73 -0
- package/src/routes/api/combos/route.js +43 -0
- package/src/routes/api/health/live/route.js +7 -0
- package/src/routes/api/health/ready/route.js +19 -0
- package/src/routes/api/health/route.js +17 -0
- package/src/routes/api/inflight/stream/route.js +24 -0
- package/src/routes/api/init/route.js +3 -0
- package/src/routes/api/keys/[id]/route.js +71 -0
- package/src/routes/api/keys/route.js +41 -0
- package/src/routes/api/logs/route.js +19 -0
- package/src/routes/api/mcp/[plugin]/message/route.js +23 -0
- package/src/routes/api/mcp/[plugin]/sse/route.js +35 -0
- package/src/routes/api/models/availability/route.js +104 -0
- package/src/routes/api/models/custom/route.js +58 -0
- package/src/routes/api/models/disabled/route.js +47 -0
- package/src/routes/api/models/route.js +64 -0
- package/src/routes/api/models/test/ping.js +236 -0
- package/src/routes/api/models/test/route.js +14 -0
- package/src/routes/api/oauth/[provider]/[action]/route.js +491 -0
- package/src/routes/api/oauth/codex/bulk-import/route.js +105 -0
- package/src/routes/api/oauth/codex/import-token/route.js +82 -0
- package/src/routes/api/oauth/cursor/auto-import/route.js +250 -0
- package/src/routes/api/oauth/cursor/import/route.js +86 -0
- package/src/routes/api/oauth/kiro/api-key/route.js +60 -0
- package/src/routes/api/oauth/kiro/auto-import/route.js +120 -0
- package/src/routes/api/oauth/kiro/import/route.js +72 -0
- package/src/routes/api/oauth/kiro/import-cli-proxy/route.js +42 -0
- package/src/routes/api/oauth/kiro/social-authorize/route.js +40 -0
- package/src/routes/api/oauth/kiro/social-exchange/route.js +62 -0
- package/src/routes/api/pricing/route.js +96 -0
- package/src/routes/api/provider-nodes/[id]/route.js +106 -0
- package/src/routes/api/provider-nodes/route.js +110 -0
- package/src/routes/api/provider-nodes/validate/route.js +197 -0
- package/src/routes/api/providers/[id]/models/route.js +716 -0
- package/src/routes/api/providers/[id]/route.js +195 -0
- package/src/routes/api/providers/[id]/test/route.js +27 -0
- package/src/routes/api/providers/[id]/test/testUtils.js +912 -0
- package/src/routes/api/providers/[id]/test-models/route.js +211 -0
- package/src/routes/api/providers/catalog/route.js +58 -0
- package/src/routes/api/providers/client/route.js +133 -0
- package/src/routes/api/providers/counts/route.js +43 -0
- package/src/routes/api/providers/kilo/free-models/route.js +58 -0
- package/src/routes/api/providers/route.js +361 -0
- package/src/routes/api/providers/suggested-models/filters.js +24 -0
- package/src/routes/api/providers/suggested-models/route.js +34 -0
- package/src/routes/api/providers/test-batch/route.js +145 -0
- package/src/routes/api/providers/validate/route.js +633 -0
- package/src/routes/api/proxy-pools/[id]/route.js +129 -0
- package/src/routes/api/proxy-pools/[id]/test/route.js +64 -0
- package/src/routes/api/proxy-pools/cloudflare-deploy/route.js +183 -0
- package/src/routes/api/proxy-pools/route.js +85 -0
- package/src/routes/api/proxy-pools/vercel-deploy/route.js +181 -0
- package/src/routes/api/settings/currency/route.js +29 -0
- package/src/routes/api/settings/database/path/route.js +8 -0
- package/src/routes/api/settings/database/route.js +89 -0
- package/src/routes/api/settings/migrate-9router/route.js +81 -0
- package/src/routes/api/settings/require-login/route.js +14 -0
- package/src/routes/api/settings/route.js +186 -0
- package/src/routes/api/shutdown/route.js +25 -0
- package/src/routes/api/tags/route.js +17 -0
- package/src/routes/api/translator/console-logs/route.js +28 -0
- package/src/routes/api/translator/console-logs/stream/route.js +95 -0
- package/src/routes/api/tunnel/disable/route.js +18 -0
- package/src/routes/api/tunnel/enable/route.js +32 -0
- package/src/routes/api/tunnel/status/route.js +23 -0
- package/src/routes/api/update/route.js +42 -0
- package/src/routes/api/usage/[connectionId]/codex-reset-credits/route.js +169 -0
- package/src/routes/api/usage/[connectionId]/route.js +222 -0
- package/src/routes/api/usage/chart/route.js +27 -0
- package/src/routes/api/usage/history/route.js +94 -0
- package/src/routes/api/usage/logs/route.js +14 -0
- package/src/routes/api/usage/providers/route.js +36 -0
- package/src/routes/api/usage/request-details/route.js +61 -0
- package/src/routes/api/usage/request-logs/route.js +15 -0
- package/src/routes/api/usage/stats/route.js +23 -0
- package/src/routes/api/usage/stream/route.js +78 -0
- package/src/routes/api/v1/api/chat/route.js +36 -0
- package/src/routes/api/v1/chat/completions/route.js +28 -0
- package/src/routes/api/v1/images/edits/route.js +70 -0
- package/src/routes/api/v1/images/generations/route.js +50 -0
- package/src/routes/api/v1/images/imageValidation.js +45 -0
- package/src/routes/api/v1/messages/count_tokens/route.js +87 -0
- package/src/routes/api/v1/messages/route.js +26 -0
- package/src/routes/api/v1/models/route.js +440 -0
- package/src/routes/api/v1/responses/compact/route.js +34 -0
- package/src/routes/api/v1/responses/route.js +26 -0
- package/src/routes/api/v1/route.js +1 -0
- package/src/routes/api/version/route.js +11 -0
- package/src/routes/table.js +1141 -0
- package/src/rtk/applyFilter.js +13 -0
- package/src/rtk/autodetect.js +104 -0
- package/src/rtk/caveman.js +6 -0
- package/src/rtk/cavemanPrompts.js +107 -0
- package/src/rtk/constants.js +51 -0
- package/src/rtk/filters/buildOutput.js +120 -0
- package/src/rtk/filters/dedupLog.js +43 -0
- package/src/rtk/filters/find.js +47 -0
- package/src/rtk/filters/gitDiff.js +90 -0
- package/src/rtk/filters/gitLog.js +88 -0
- package/src/rtk/filters/gitStatus.js +101 -0
- package/src/rtk/filters/grep.js +45 -0
- package/src/rtk/filters/ls.js +73 -0
- package/src/rtk/filters/readNumbered.js +22 -0
- package/src/rtk/filters/searchList.js +49 -0
- package/src/rtk/filters/smartTruncate.js +13 -0
- package/src/rtk/filters/tree.js +28 -0
- package/src/rtk/index.js +143 -0
- package/src/rtk/ponytail.js +6 -0
- package/src/rtk/ponytailPrompt.js +49 -0
- package/src/rtk/systemInject.js +89 -0
- package/src/server.ts +474 -0
- package/src/services/accountFallback.js +241 -0
- package/src/services/accountPool.js +389 -0
- package/src/services/capacityAdapter.js +140 -0
- package/src/services/cliModelMapping.js +84 -0
- package/src/services/clinepassModels.js +60 -0
- package/src/services/codebuddyModels.js +250 -0
- package/src/services/combo.js +482 -0
- package/src/services/copilotModels.js +126 -0
- package/src/services/currencyRate.js +56 -0
- package/src/services/cursorModels.js +197 -0
- package/src/services/grokCliModels.js +130 -0
- package/src/services/kimchiModels.js +175 -0
- package/src/services/kiroModels.js +246 -0
- package/src/services/model.js +83 -0
- package/src/services/oauthCredentialManager.js +153 -0
- package/src/services/projectId.js +240 -0
- package/src/services/provider.js +145 -0
- package/src/services/qoderModels.js +274 -0
- package/src/services/tokenRefresh/dedup.js +70 -0
- package/src/services/tokenRefresh/providers.js +626 -0
- package/src/services/tokenRefresh.js +274 -0
- package/src/services/usage/claude.js +134 -0
- package/src/services/usage/codebuddy-cn.js +212 -0
- package/src/services/usage/codex.js +193 -0
- package/src/services/usage/deepseek.js +103 -0
- package/src/services/usage/github.js +94 -0
- package/src/services/usage/google.js +218 -0
- package/src/services/usage/grok-cli.js +368 -0
- package/src/services/usage/grokCliQuotaFrame.js +170 -0
- package/src/services/usage/kimi.js +185 -0
- package/src/services/usage/kiro.js +172 -0
- package/src/services/usage/minimax.js +215 -0
- package/src/services/usage/misc.js +264 -0
- package/src/services/usage/shared.js +59 -0
- package/src/services/usage.js +56 -0
- package/src/shared/clineAuth.js +37 -0
- package/src/shared/constants/config.js +80 -0
- package/src/shared/constants/coworkPlugins.js +69 -0
- package/src/shared/constants/models.js +41 -0
- package/src/shared/constants/providers.js +128 -0
- package/src/shared/constants/providersDisplay.js +1 -0
- package/src/shared/qoder/constants.js +50 -0
- package/src/shared/qoder/cosy.js +134 -0
- package/src/shared/qoder/encoding.js +36 -0
- package/src/shared/services/initializeApp.js +226 -0
- package/src/shared/services/quotaAutoPing.js +310 -0
- package/src/shared/utils/apiKey.js +65 -0
- package/src/shared/utils/clineAuth.js +1 -0
- package/src/shared/utils/index.js +3 -0
- package/src/shared/utils/machineId.js +60 -0
- package/src/shared/utils/ssrfGuard.js +280 -0
- package/src/sse/handlers/chat.js +426 -0
- package/src/sse/oauthLease.js +32 -0
- package/src/sse/recovery.js +235 -0
- package/src/sse/services/auth.js +489 -0
- package/src/sse/services/backgroundTokenRefresh.js +173 -0
- package/src/sse/services/model.js +129 -0
- package/src/sse/services/requestCancellation.js +4 -0
- package/src/sse/services/tokenRefresh.js +264 -0
- package/src/sse/utils/logger.js +142 -0
- package/src/staticServe.ts +95 -0
- package/src/transformer/streamToJsonConverter.js +87 -0
- package/src/translator/canonical.js +81 -0
- package/src/translator/concerns/chunk.js +9 -0
- package/src/translator/concerns/compatFallback.js +147 -0
- package/src/translator/concerns/finishReason.js +59 -0
- package/src/translator/concerns/image.js +105 -0
- package/src/translator/concerns/json.js +4 -0
- package/src/translator/concerns/kiroConversation.js +428 -0
- package/src/translator/concerns/message.js +5 -0
- package/src/translator/concerns/modality.js +134 -0
- package/src/translator/concerns/paramSupport.js +97 -0
- package/src/translator/concerns/prefetch.js +86 -0
- package/src/translator/concerns/reasoning.js +18 -0
- package/src/translator/concerns/thinking.js +40 -0
- package/src/translator/concerns/thinkingUnified.js +319 -0
- package/src/translator/concerns/toolCall.js +134 -0
- package/src/translator/concerns/usage.js +61 -0
- package/src/translator/detection.js +42 -0
- package/src/translator/formats/claude.js +323 -0
- package/src/translator/formats/gemini.js +366 -0
- package/src/translator/formats/maxTokens.js +19 -0
- package/src/translator/formats/openai.js +116 -0
- package/src/translator/formats/responsesApi.js +117 -0
- package/src/translator/formats.js +28 -0
- package/src/translator/index.js +237 -0
- package/src/translator/request/antigravity-to-openai.js +217 -0
- package/src/translator/request/claude-to-kiro.js +288 -0
- package/src/translator/request/claude-to-openai.js +199 -0
- package/src/translator/request/gemini-to-openai.js +142 -0
- package/src/translator/request/openai-responses.js +373 -0
- package/src/translator/request/openai-to-claude.js +260 -0
- package/src/translator/request/openai-to-commandcode.js +161 -0
- package/src/translator/request/openai-to-cursor.js +175 -0
- package/src/translator/request/openai-to-gemini.js +422 -0
- package/src/translator/request/openai-to-kiro.js +360 -0
- package/src/translator/request/openai-to-ollama.js +152 -0
- package/src/translator/request/openai-to-vertex.js +36 -0
- package/src/translator/response/claude-to-openai.js +185 -0
- package/src/translator/response/commandcode-to-openai.js +164 -0
- package/src/translator/response/cursor-to-openai.js +18 -0
- package/src/translator/response/gemini-to-openai.js +127 -0
- package/src/translator/response/kiro-to-claude.js +230 -0
- package/src/translator/response/kiro-to-openai.js +136 -0
- package/src/translator/response/ollama-to-openai.js +106 -0
- package/src/translator/response/openai-responses.js +534 -0
- package/src/translator/response/openai-to-antigravity.js +107 -0
- package/src/translator/response/openai-to-claude.js +231 -0
- package/src/translator/schema/blocks.js +40 -0
- package/src/translator/schema/defaults.js +3 -0
- package/src/translator/schema/finishReasons.js +22 -0
- package/src/translator/schema/index.js +7 -0
- package/src/translator/schema/roles.js +12 -0
- package/src/transport/requestBoundary.ts +223 -0
- package/src/transport/routerAdmission.ts +380 -0
- package/src/types/provider.ts +59 -0
- package/src/utils/bypassHandler.js +272 -0
- package/src/utils/claudeCloaking.js +10 -0
- package/src/utils/claudeSignature.js +35 -0
- package/src/utils/clientDetector.js +183 -0
- package/src/utils/cursorChecksum.js +104 -0
- package/src/utils/cursorProtobuf.js +801 -0
- package/src/utils/debugLog.js +12 -0
- package/src/utils/error.js +120 -0
- package/src/utils/inflight.js +127 -0
- package/src/utils/kiroSessionReplay.js +139 -0
- package/src/utils/ollamaTransform.js +83 -0
- package/src/utils/proxyFetch.js +308 -0
- package/src/utils/reasoningContentInjector.js +71 -0
- package/src/utils/requestLogger.js +272 -0
- package/src/utils/responsesStreamHelpers.js +46 -0
- package/src/utils/sessionManager.js +205 -0
- package/src/utils/sse.js +13 -0
- package/src/utils/sseConstants.js +21 -0
- package/src/utils/stream.js +511 -0
- package/src/utils/streamHandler.js +256 -0
- package/src/utils/streamHelpers.js +113 -0
- package/src/utils/toolDeduper.js +44 -0
- package/src/utils/usageTracking.js +329 -0
- package/tsconfig.json +45 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
import { NextResponse } from "next/server";
|
|
4
|
+
import { exec } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
|
|
10
|
+
const execAsync = promisify(exec);
|
|
11
|
+
|
|
12
|
+
const getDataDir = () => path.join(os.homedir(), ".local", "share", "kilo");
|
|
13
|
+
const getAuthPath = () => path.join(getDataDir(), "auth.json");
|
|
14
|
+
const getVscodeSettingsPath = () => path.join(os.homedir(), ".config", "Code", "User", "settings.json");
|
|
15
|
+
|
|
16
|
+
const checkInstalled = async () => {
|
|
17
|
+
try {
|
|
18
|
+
const isWindows = os.platform() === "win32";
|
|
19
|
+
const command = isWindows ? "where kilo" : "which kilo";
|
|
20
|
+
const env = isWindows
|
|
21
|
+
? { ...process.env, PATH: `${process.env.APPDATA}\\npm;${process.env.PATH}` }
|
|
22
|
+
: process.env;
|
|
23
|
+
await execAsync(command, { windowsHide: true, env });
|
|
24
|
+
return true;
|
|
25
|
+
} catch {
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(getAuthPath());
|
|
28
|
+
return true;
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const readJson = async (filePath) => {
|
|
36
|
+
try {
|
|
37
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
38
|
+
|
|
39
|
+
const stripped = content.replace(/,(\s*[}\]])/g, "$1");
|
|
40
|
+
return JSON.parse(stripped);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const hasSwayRouterConfig = (auth) => {
|
|
47
|
+
if (!auth) return false;
|
|
48
|
+
const entry = auth["openai-compatible"] || auth["swayrouter"];
|
|
49
|
+
if (!entry) return false;
|
|
50
|
+
const baseUrl = entry.baseUrl || entry.baseURL || "";
|
|
51
|
+
return baseUrl.includes("localhost") || baseUrl.includes("127.0.0.1") || baseUrl.includes("swayrouter");
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export async function GET() {
|
|
55
|
+
try {
|
|
56
|
+
const installed = await checkInstalled();
|
|
57
|
+
if (!installed) {
|
|
58
|
+
return NextResponse.json({ installed: false, settings: null, message: "Kilo Code CLI is not installed" });
|
|
59
|
+
}
|
|
60
|
+
const auth = await readJson(getAuthPath());
|
|
61
|
+
return NextResponse.json({
|
|
62
|
+
installed: true,
|
|
63
|
+
settings: { auth: auth ? Object.keys(auth) : [] },
|
|
64
|
+
hasSwayRouter: hasSwayRouterConfig(auth),
|
|
65
|
+
authPath: getAuthPath(),
|
|
66
|
+
});
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.log("Error checking kilo settings:", error);
|
|
69
|
+
return NextResponse.json({ error: "Failed to check kilo settings" }, { status: 500 });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function POST(request) {
|
|
74
|
+
try {
|
|
75
|
+
const { baseUrl, apiKey, model } = await request.json();
|
|
76
|
+
if (!baseUrl || !apiKey || !model) {
|
|
77
|
+
return NextResponse.json({ error: "baseUrl, apiKey and model are required" }, { status: 400 });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await fs.mkdir(getDataDir(), { recursive: true });
|
|
81
|
+
|
|
82
|
+
const normalizedBaseUrl = baseUrl.endsWith("/v1") ? baseUrl : `${baseUrl}/v1`;
|
|
83
|
+
|
|
84
|
+
const auth = (await readJson(getAuthPath())) || {};
|
|
85
|
+
auth["openai-compatible"] = {
|
|
86
|
+
type: "api-key",
|
|
87
|
+
apiKey,
|
|
88
|
+
baseUrl: normalizedBaseUrl,
|
|
89
|
+
model,
|
|
90
|
+
};
|
|
91
|
+
await fs.writeFile(getAuthPath(), JSON.stringify(auth, null, 2));
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const vscode = (await readJson(getVscodeSettingsPath())) || {};
|
|
95
|
+
vscode["kilocode.customProvider"] = { name: "Sway Router", baseURL: normalizedBaseUrl, apiKey };
|
|
96
|
+
vscode["kilocode.defaultModel"] = model;
|
|
97
|
+
await fs.writeFile(getVscodeSettingsPath(), JSON.stringify(vscode, null, 2));
|
|
98
|
+
} catch { }
|
|
99
|
+
|
|
100
|
+
return NextResponse.json({ success: true, message: "Kilo Code settings applied successfully!", authPath: getAuthPath() });
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.log("Error updating kilo settings:", error);
|
|
103
|
+
return NextResponse.json({ error: "Failed to update kilo settings" }, { status: 500 });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function DELETE() {
|
|
108
|
+
try {
|
|
109
|
+
const auth = await readJson(getAuthPath());
|
|
110
|
+
if (!auth) {
|
|
111
|
+
return NextResponse.json({ success: true, message: "No settings file to reset" });
|
|
112
|
+
}
|
|
113
|
+
delete auth["openai-compatible"];
|
|
114
|
+
delete auth["swayrouter"];
|
|
115
|
+
await fs.writeFile(getAuthPath(), JSON.stringify(auth, null, 2));
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const vscode = await readJson(getVscodeSettingsPath());
|
|
119
|
+
if (vscode) {
|
|
120
|
+
delete vscode["kilocode.customProvider"];
|
|
121
|
+
delete vscode["kilocode.defaultModel"];
|
|
122
|
+
await fs.writeFile(getVscodeSettingsPath(), JSON.stringify(vscode, null, 2));
|
|
123
|
+
}
|
|
124
|
+
} catch { }
|
|
125
|
+
|
|
126
|
+
return NextResponse.json({ success: true, message: "Sway Router settings removed from Kilo Code" });
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.log("Error resetting kilo settings:", error);
|
|
129
|
+
return NextResponse.json({ error: "Failed to reset kilo settings" }, { status: 500 });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { getSettings, updateSettings } from "@/lib/localDb";
|
|
3
|
+
|
|
4
|
+
const TOOL_ID = /^[a-z0-9_-]{1,64}$/i;
|
|
5
|
+
|
|
6
|
+
function sanitize(value) {
|
|
7
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
8
|
+
const out = {};
|
|
9
|
+
for (const [toolId, snapshot] of Object.entries(value)) {
|
|
10
|
+
if (!TOOL_ID.test(toolId) || !snapshot || typeof snapshot !== "object") continue;
|
|
11
|
+
const entries = Array.isArray(snapshot.entries) ? snapshot.entries.map((entry) => ({
|
|
12
|
+
sourceModel: typeof entry?.sourceModel === "string" ? entry.sourceModel.trim().slice(0, 512) : "",
|
|
13
|
+
targetModel: typeof entry?.targetModel === "string" ? entry.targetModel.trim().slice(0, 512) : "",
|
|
14
|
+
enabled: entry?.enabled !== false,
|
|
15
|
+
})).filter((entry) => entry.sourceModel && entry.targetModel).slice(0, 256) : [];
|
|
16
|
+
out[toolId] = { enabled: snapshot.enabled !== false, entries };
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function GET() {
|
|
22
|
+
const settings = await getSettings();
|
|
23
|
+
return NextResponse.json({ mappings: settings.cliModelMappings || {} });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function PUT(request) {
|
|
27
|
+
try {
|
|
28
|
+
const body = await request.json();
|
|
29
|
+
const mappings = sanitize(body?.mappings);
|
|
30
|
+
await updateSettings({ cliModelMappings: mappings });
|
|
31
|
+
return NextResponse.json({ mappings });
|
|
32
|
+
} catch {
|
|
33
|
+
return NextResponse.json({ error: "Invalid model mappings" }, { status: 400 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function DELETE() {
|
|
38
|
+
await updateSettings({ cliModelMappings: {} });
|
|
39
|
+
return NextResponse.json({ mappings: {} });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const dynamic = "force-dynamic";
|
|
43
|
+
export const revalidate = 0;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
import { NextResponse } from "next/server";
|
|
4
|
+
import { exec } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
import { parseYAML, stringifyYAML } from "confbox";
|
|
10
|
+
|
|
11
|
+
const execAsync = promisify(exec);
|
|
12
|
+
|
|
13
|
+
const getOmpDir = () => path.join(os.homedir(), ".omp", "agent");
|
|
14
|
+
const getModelsPath = () => path.join(getOmpDir(), "models.yml");
|
|
15
|
+
const getOmpBinPath = () => path.join(os.homedir(), ".bun", "bin", "omp.exe");
|
|
16
|
+
|
|
17
|
+
const SWAY_ROUTER_MATCH_HOSTS = [
|
|
18
|
+
"127.0.0.1:14045",
|
|
19
|
+
"localhost:14045",
|
|
20
|
+
"localhost",
|
|
21
|
+
"127.0.0.1",
|
|
22
|
+
];
|
|
23
|
+
const SWAY_ROUTER_URL_HOST_RE = /^(?:127\.0\.0\.1|localhost)(?::14045)?$/;
|
|
24
|
+
|
|
25
|
+
function isSwayRouterBaseUrl(baseUrl) {
|
|
26
|
+
if (typeof baseUrl !== "string" || !baseUrl) return false;
|
|
27
|
+
try {
|
|
28
|
+
const u = new URL(baseUrl);
|
|
29
|
+
return (
|
|
30
|
+
u.pathname.endsWith("/v1") &&
|
|
31
|
+
(SWAY_ROUTER_URL_HOST_RE.test(u.host) || SWAY_ROUTER_MATCH_HOSTS.includes(u.host))
|
|
32
|
+
);
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const setNestedSection = (obj, dottedKey, value) => {
|
|
39
|
+
const keys = dottedKey.split(".");
|
|
40
|
+
let cur = obj;
|
|
41
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
42
|
+
if (cur[keys[i]] == null || typeof cur[keys[i]] !== "object") {
|
|
43
|
+
cur[keys[i]] = {};
|
|
44
|
+
}
|
|
45
|
+
cur = cur[keys[i]];
|
|
46
|
+
}
|
|
47
|
+
cur[keys[keys.length - 1]] = value;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const deleteNestedSection = (obj, dottedKey) => {
|
|
51
|
+
const keys = dottedKey.split(".");
|
|
52
|
+
let cur = obj;
|
|
53
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
54
|
+
cur = cur?.[keys[i]];
|
|
55
|
+
if (cur == null) return;
|
|
56
|
+
}
|
|
57
|
+
delete cur[keys[keys.length - 1]];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const checkOmpInstalled = async () => {
|
|
61
|
+
try {
|
|
62
|
+
await fs.access(getOmpBinPath());
|
|
63
|
+
return true;
|
|
64
|
+
} catch {
|
|
65
|
+
try {
|
|
66
|
+
const isWindows = os.platform() === "win32";
|
|
67
|
+
const command = isWindows ? "where omp" : "which omp";
|
|
68
|
+
await execAsync(command, { windowsHide: true });
|
|
69
|
+
return true;
|
|
70
|
+
} catch {
|
|
71
|
+
try {
|
|
72
|
+
await fs.access(getModelsPath());
|
|
73
|
+
return true;
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const readModels = async () => {
|
|
82
|
+
try {
|
|
83
|
+
const content = await fs.readFile(getModelsPath(), "utf-8");
|
|
84
|
+
const parsed = parseYAML(content);
|
|
85
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error.code === "ENOENT") return null;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
let cachedVersion;
|
|
93
|
+
|
|
94
|
+
const getOmpVersion = async () => {
|
|
95
|
+
if (cachedVersion !== undefined) return cachedVersion;
|
|
96
|
+
cachedVersion = null;
|
|
97
|
+
try {
|
|
98
|
+
const { stdout } = await execAsync("omp --version", { windowsHide: true });
|
|
99
|
+
cachedVersion = String(stdout).trim().split("\n")[0] || null;
|
|
100
|
+
} catch {
|
|
101
|
+
cachedVersion = null;
|
|
102
|
+
}
|
|
103
|
+
return cachedVersion;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const providerPointsAtRouter = (provider) => {
|
|
107
|
+
if (!provider || typeof provider !== "object") return false;
|
|
108
|
+
return isSwayRouterBaseUrl(provider.baseUrl);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const isFromCloudflare = (req) =>
|
|
112
|
+
req.headers.get("cf-connecting-ip") !== null ||
|
|
113
|
+
(req.headers.get("cf-ray") ?? "").length > 0;
|
|
114
|
+
|
|
115
|
+
const hasFamilyIpHeader = (req) => {
|
|
116
|
+
try {
|
|
117
|
+
const fwd = req.headers.get("x-forwarded-for") || "";
|
|
118
|
+
const rightmost = fwd.split(",").pop().trim();
|
|
119
|
+
if (ipHeaderIsIp(rightmost)) return true;
|
|
120
|
+
const realIp = req.headers.get("x-real-ip") || "";
|
|
121
|
+
return ipHeaderIsIp(realIp);
|
|
122
|
+
} catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const ipHeaderIsIp = (value) =>
|
|
128
|
+
/^\d+\.\d+\.\d+\.\d+$/.test(value) || /^[0-9a-f:]+$/i.test(value);
|
|
129
|
+
|
|
130
|
+
const isLocalRequest = (request) => {
|
|
131
|
+
if (isFromCloudflare(request) || hasFamilyIpHeader(request)) return false;
|
|
132
|
+
const url = request.headers.get("host") || "";
|
|
133
|
+
const host = url.split(":").shift().toLowerCase();
|
|
134
|
+
return host === "localhost" || host === "127.0.0.1" || host === "";
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export async function GET(request) {
|
|
138
|
+
try {
|
|
139
|
+
const installed = await checkOmpInstalled();
|
|
140
|
+
const config = await readModels();
|
|
141
|
+
const version = await getOmpVersion();
|
|
142
|
+
|
|
143
|
+
if (!installed) {
|
|
144
|
+
return NextResponse.json({
|
|
145
|
+
installed: false,
|
|
146
|
+
config: null,
|
|
147
|
+
models: null,
|
|
148
|
+
version,
|
|
149
|
+
message: "OMP (oh-my-pi) is not installed",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const provider = config?.providers?.swayrouter ?? null;
|
|
154
|
+
const hasSwayRouter = providerPointsAtRouter(provider);
|
|
155
|
+
|
|
156
|
+
return NextResponse.json({
|
|
157
|
+
installed: true,
|
|
158
|
+
config: config ? stringifyYAML(config) : null,
|
|
159
|
+
hasSwayRouter,
|
|
160
|
+
connected: hasSwayRouter,
|
|
161
|
+
configPath: getModelsPath(),
|
|
162
|
+
version,
|
|
163
|
+
});
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.log("Error checking omp settings:", error);
|
|
166
|
+
return NextResponse.json({ error: "Failed to check omp settings" }, { status: 500 });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export async function POST(request, { params }) {
|
|
171
|
+
try {
|
|
172
|
+
const collection = await request.json();
|
|
173
|
+
const { baseUrl, apiKey, models } = collection || {};
|
|
174
|
+
const selectedModels = Array.isArray(models)
|
|
175
|
+
? [...new Set(models.filter((value) => typeof value === "string" && value.trim()).map((value) => value.trim()))]
|
|
176
|
+
: [];
|
|
177
|
+
const configuredApiKey = typeof apiKey === "string" ? apiKey.trim() : "";
|
|
178
|
+
|
|
179
|
+
if (!isLocalRequest(request)) {
|
|
180
|
+
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!baseUrl) {
|
|
184
|
+
return NextResponse.json({ error: "baseUrl is required" }, { status: 400 });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const ompDir = getOmpDir();
|
|
188
|
+
const modelsPath = getModelsPath();
|
|
189
|
+
await fs.mkdir(ompDir, { recursive: true });
|
|
190
|
+
|
|
191
|
+
let parsed = {};
|
|
192
|
+
try {
|
|
193
|
+
const existing = await readModels();
|
|
194
|
+
parsed = existing ?? {};
|
|
195
|
+
} catch { }
|
|
196
|
+
|
|
197
|
+
const normalizedBaseUrl = baseUrl.includes("/v1")
|
|
198
|
+
? baseUrl
|
|
199
|
+
: `${baseUrl.replace(/\/$/, "")}/v1`;
|
|
200
|
+
|
|
201
|
+
const provider = {
|
|
202
|
+
baseUrl: normalizedBaseUrl,
|
|
203
|
+
api: "openai-completions",
|
|
204
|
+
...(configuredApiKey ? { apiKey: configuredApiKey } : { auth: "none" }),
|
|
205
|
+
discovery: { type: "openai-models-list" },
|
|
206
|
+
...(selectedModels.length
|
|
207
|
+
? {
|
|
208
|
+
models: selectedModels.map((id) => ({
|
|
209
|
+
id,
|
|
210
|
+
name: id,
|
|
211
|
+
})),
|
|
212
|
+
}
|
|
213
|
+
: {}),
|
|
214
|
+
};
|
|
215
|
+
setNestedSection(parsed, "providers.swayrouter", provider);
|
|
216
|
+
|
|
217
|
+
const content = stringifyYAML(parsed);
|
|
218
|
+
await fs.writeFile(modelsPath, content);
|
|
219
|
+
|
|
220
|
+
return NextResponse.json({
|
|
221
|
+
success: true,
|
|
222
|
+
message: "OMP settings applied successfully!",
|
|
223
|
+
configPath: modelsPath,
|
|
224
|
+
});
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.log("Error updating omp settings:", error);
|
|
227
|
+
return NextResponse.json({ error: "Failed to update omp settings" }, { status: 500 });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export async function DELETE(request) {
|
|
232
|
+
try {
|
|
233
|
+
const modelsPath = getModelsPath();
|
|
234
|
+
|
|
235
|
+
let parsed;
|
|
236
|
+
try {
|
|
237
|
+
parsed = await readModels();
|
|
238
|
+
} catch (error) {
|
|
239
|
+
if (error.code === "ENOENT") {
|
|
240
|
+
return NextResponse.json({ success: true, message: "No config file to reset" });
|
|
241
|
+
}
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!parsed || typeof parsed !== "object") {
|
|
246
|
+
return NextResponse.json({ success: true, message: "No config file to reset" });
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
deleteNestedSection(parsed, "providers.swayrouter");
|
|
250
|
+
|
|
251
|
+
if (parsed.providers && Object.keys(parsed.providers).length === 0) {
|
|
252
|
+
delete parsed.providers;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const content = stringifyYAML(parsed);
|
|
256
|
+
await fs.writeFile(modelsPath, content);
|
|
257
|
+
|
|
258
|
+
return NextResponse.json({
|
|
259
|
+
success: true,
|
|
260
|
+
message: "Sway Router settings removed successfully",
|
|
261
|
+
});
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.log("Error resetting omp settings:", error);
|
|
264
|
+
return NextResponse.json({ error: "Failed to reset omp settings" }, { status: 500 });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
import { NextResponse } from "next/server";
|
|
4
|
+
import { exec } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
|
|
10
|
+
const execAsync = promisify(exec);
|
|
11
|
+
|
|
12
|
+
const getConfigDir = () => path.join(os.homedir(), ".config", "opencode");
|
|
13
|
+
const getConfigPath = () => path.join(getConfigDir(), "opencode.json");
|
|
14
|
+
|
|
15
|
+
const checkOpenCodeInstalled = async () => {
|
|
16
|
+
try {
|
|
17
|
+
const isWindows = os.platform() === "win32";
|
|
18
|
+
const command = isWindows ? "where opencode" : "which opencode";
|
|
19
|
+
const env = isWindows
|
|
20
|
+
? { ...process.env, PATH: `${process.env.APPDATA}\\npm;${process.env.PATH}` }
|
|
21
|
+
: process.env;
|
|
22
|
+
await execAsync(command, { windowsHide: true, env });
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
try {
|
|
26
|
+
await fs.access(getConfigPath());
|
|
27
|
+
return true;
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const readConfig = async () => {
|
|
35
|
+
try {
|
|
36
|
+
const content = await fs.readFile(getConfigPath(), "utf-8");
|
|
37
|
+
|
|
38
|
+
const stripped = content.replace(/,(\s*[}\]])/g, "$1");
|
|
39
|
+
return JSON.parse(stripped);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (error.code === "ENOENT") return null;
|
|
42
|
+
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const hasSwayRouterConfig = (config) => {
|
|
48
|
+
if (!config?.provider) return false;
|
|
49
|
+
return !!config.provider["swayrouter"];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export async function GET() {
|
|
53
|
+
try {
|
|
54
|
+
const isInstalled = await checkOpenCodeInstalled();
|
|
55
|
+
|
|
56
|
+
if (!isInstalled) {
|
|
57
|
+
return NextResponse.json({
|
|
58
|
+
installed: false,
|
|
59
|
+
config: null,
|
|
60
|
+
message: "OpenCode CLI is not installed",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const config = await readConfig();
|
|
65
|
+
const providerConfig = config?.provider?.["swayrouter"];
|
|
66
|
+
const modelMap = providerConfig?.models || {};
|
|
67
|
+
|
|
68
|
+
return NextResponse.json({
|
|
69
|
+
installed: true,
|
|
70
|
+
config,
|
|
71
|
+
hasSwayRouter: hasSwayRouterConfig(config),
|
|
72
|
+
configPath: getConfigPath(),
|
|
73
|
+
opencode: {
|
|
74
|
+
models: Object.keys(modelMap),
|
|
75
|
+
activeModel: config?.model?.startsWith("swayrouter/") ? config.model.replace(/^swayrouter\//, "") : null,
|
|
76
|
+
baseURL: providerConfig?.options?.baseURL || null,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.log("Error checking opencode settings:", error);
|
|
81
|
+
return NextResponse.json({ error: "Failed to check opencode settings" }, { status: 500 });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function POST(request) {
|
|
86
|
+
try {
|
|
87
|
+
const { baseUrl, apiKey, model, models, activeModel, subagentModel } = await request.json();
|
|
88
|
+
|
|
89
|
+
const modelsArray = Array.isArray(models) ? models.slice() : (typeof model === "string" ? [model] : []);
|
|
90
|
+
|
|
91
|
+
if (!baseUrl) {
|
|
92
|
+
return NextResponse.json({ error: "baseUrl is required" }, { status: 400 });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const configDir = getConfigDir();
|
|
96
|
+
const configPath = getConfigPath();
|
|
97
|
+
|
|
98
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
99
|
+
|
|
100
|
+
let config = {};
|
|
101
|
+
try {
|
|
102
|
+
const existing = await fs.readFile(configPath, "utf-8");
|
|
103
|
+
config = JSON.parse(existing);
|
|
104
|
+
} catch { }
|
|
105
|
+
|
|
106
|
+
const normalizedBaseUrl = baseUrl.endsWith("/v1") ? baseUrl : `${baseUrl}/v1`;
|
|
107
|
+
const keyToUse = apiKey || "sk_swayrouter";
|
|
108
|
+
const effectiveSubagentModel = subagentModel || modelsArray[0];
|
|
109
|
+
|
|
110
|
+
if (!config.provider) config.provider = {};
|
|
111
|
+
|
|
112
|
+
const existingProvider = config.provider["swayrouter"] || { npm: "@ai-sdk/openai-compatible", options: {}, models: {} };
|
|
113
|
+
|
|
114
|
+
existingProvider.options = {
|
|
115
|
+
...existingProvider.options,
|
|
116
|
+
baseURL: normalizedBaseUrl,
|
|
117
|
+
apiKey: keyToUse,
|
|
118
|
+
};
|
|
119
|
+
existingProvider.models = existingProvider.models || {};
|
|
120
|
+
for (const m of modelsArray) {
|
|
121
|
+
if (!m || typeof m !== "string") continue;
|
|
122
|
+
existingProvider.models[m] = { name: m, modalities: { input: ["text", "image"], output: ["text"] } };
|
|
123
|
+
}
|
|
124
|
+
config.provider["swayrouter"] = existingProvider;
|
|
125
|
+
|
|
126
|
+
const finalActive = activeModel || modelsArray[0];
|
|
127
|
+
if (activeModel === "") {
|
|
128
|
+
if (config.model?.startsWith("swayrouter/")) delete config.model;
|
|
129
|
+
} else if (finalActive) {
|
|
130
|
+
config.model = `swayrouter/${finalActive}`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (effectiveSubagentModel) {
|
|
134
|
+
if (!config.agent) config.agent = {};
|
|
135
|
+
config.agent.explorer = {
|
|
136
|
+
description: "Fast explorer subagent for codebase exploration",
|
|
137
|
+
mode: "subagent",
|
|
138
|
+
model: `swayrouter/${effectiveSubagentModel}`,
|
|
139
|
+
};
|
|
140
|
+
} else if (config.agent?.explorer?.model?.startsWith("swayrouter/")) {
|
|
141
|
+
delete config.agent.explorer;
|
|
142
|
+
if (Object.keys(config.agent).length === 0) delete config.agent;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
146
|
+
|
|
147
|
+
return NextResponse.json({
|
|
148
|
+
success: true,
|
|
149
|
+
message: "OpenCode settings applied successfully!",
|
|
150
|
+
configPath,
|
|
151
|
+
});
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.log("Error applying opencode settings:", error);
|
|
154
|
+
return NextResponse.json({ error: "Failed to apply settings" }, { status: 500 });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export async function PATCH(request) {
|
|
159
|
+
try {
|
|
160
|
+
const { clearActiveModel } = await request.json();
|
|
161
|
+
const configPath = getConfigPath();
|
|
162
|
+
|
|
163
|
+
let config = {};
|
|
164
|
+
try {
|
|
165
|
+
const existing = await fs.readFile(configPath, "utf-8");
|
|
166
|
+
config = JSON.parse(existing);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (error.code === "ENOENT") {
|
|
169
|
+
return NextResponse.json({ success: true, message: "No config file found" });
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (clearActiveModel === true) {
|
|
175
|
+
|
|
176
|
+
if (config.model?.startsWith("swayrouter/")) {
|
|
177
|
+
config.model = "";
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
182
|
+
|
|
183
|
+
return NextResponse.json({
|
|
184
|
+
success: true,
|
|
185
|
+
message: "Settings updated",
|
|
186
|
+
});
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.log("Error patching opencode settings:", error);
|
|
189
|
+
return NextResponse.json({ error: "Failed to patch settings" }, { status: 500 });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export async function DELETE(request) {
|
|
194
|
+
try {
|
|
195
|
+
const { searchParams } = new URL(request.url);
|
|
196
|
+
const modelToRemove = searchParams.get("model");
|
|
197
|
+
const configPath = getConfigPath();
|
|
198
|
+
|
|
199
|
+
let config = {};
|
|
200
|
+
try {
|
|
201
|
+
const existing = await fs.readFile(configPath, "utf-8");
|
|
202
|
+
config = JSON.parse(existing);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error.code === "ENOENT") {
|
|
205
|
+
return NextResponse.json({ success: true, message: "No config file to reset" });
|
|
206
|
+
}
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (modelToRemove && config.provider?.["swayrouter"]?.models) {
|
|
211
|
+
delete config.provider["swayrouter"].models[modelToRemove];
|
|
212
|
+
|
|
213
|
+
if (Object.keys(config.provider["swayrouter"].models).length === 0) {
|
|
214
|
+
delete config.provider["swayrouter"];
|
|
215
|
+
if (config.model?.startsWith("swayrouter/")) delete config.model;
|
|
216
|
+
} else if (config.model === `swayrouter/${modelToRemove}`) {
|
|
217
|
+
|
|
218
|
+
const remainingModels = Object.keys(config.provider["swayrouter"].models);
|
|
219
|
+
config.model = `swayrouter/${remainingModels[0]}`;
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
|
|
223
|
+
if (config.provider) delete config.provider["swayrouter"];
|
|
224
|
+
if (config.model?.startsWith("swayrouter/")) delete config.model;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (config.agent?.explorer?.model?.startsWith("swayrouter/")) {
|
|
228
|
+
delete config.agent.explorer;
|
|
229
|
+
|
|
230
|
+
if (Object.keys(config.agent).length === 0) delete config.agent;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
234
|
+
|
|
235
|
+
return NextResponse.json({
|
|
236
|
+
success: true,
|
|
237
|
+
message: modelToRemove ? `Model "${modelToRemove}" removed` : "Sway Router settings removed from OpenCode",
|
|
238
|
+
});
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.log("Error resetting opencode settings:", error);
|
|
241
|
+
return NextResponse.json({ error: "Failed to reset opencode settings" }, { status: 500 });
|
|
242
|
+
}
|
|
243
|
+
}
|