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,228 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
import { execFile } from "node:child_process";
|
|
4
|
+
import fs from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
import { NextResponse } from "@/next/server";
|
|
8
|
+
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
const WORKSPACE_ROOT = path.resolve(process.env.SWAY_CHAT_WORKSPACE || process.cwd());
|
|
11
|
+
const MAX_COMMAND_LENGTH = 500;
|
|
12
|
+
const MAX_OUTPUT_LENGTH = 24_000;
|
|
13
|
+
const MAX_FILE_LENGTH = 64_000;
|
|
14
|
+
const COMMAND_TIMEOUT_MS = 8_000;
|
|
15
|
+
const MAX_CODE_LENGTH = 6_000;
|
|
16
|
+
const CODE_TIMEOUT_MS = 10_000;
|
|
17
|
+
|
|
18
|
+
class ToolInputError extends Error {}
|
|
19
|
+
|
|
20
|
+
function tokenize(command) {
|
|
21
|
+
if (typeof command !== "string" || !command.trim()) throw new ToolInputError("Command is required");
|
|
22
|
+
if (command.length > MAX_COMMAND_LENGTH) throw new ToolInputError(`Command must be ${MAX_COMMAND_LENGTH} characters or fewer`);
|
|
23
|
+
|
|
24
|
+
if (/[;&|<>`$()\\]/.test(command)) throw new ToolInputError("Shell operators, substitutions, and backslashes are not supported");
|
|
25
|
+
|
|
26
|
+
const tokens = [];
|
|
27
|
+
let token = "";
|
|
28
|
+
let quote = "";
|
|
29
|
+
for (const char of command.trim()) {
|
|
30
|
+
if (quote) {
|
|
31
|
+
if (char === quote) quote = "";
|
|
32
|
+
else token += char;
|
|
33
|
+
} else if (char === "\"" || char === "'") {
|
|
34
|
+
quote = char;
|
|
35
|
+
} else if (/\s/.test(char)) {
|
|
36
|
+
if (token) { tokens.push(token); token = ""; }
|
|
37
|
+
} else {
|
|
38
|
+
token += char;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (quote) throw new ToolInputError("Unclosed quote in command");
|
|
42
|
+
if (token) tokens.push(token);
|
|
43
|
+
if (!tokens.length) throw new ToolInputError("Command is required");
|
|
44
|
+
return tokens;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function resolveWorkspacePath(input = ".") {
|
|
48
|
+
const requested = typeof input === "string" && input.trim() ? input.trim() : ".";
|
|
49
|
+
const resolved = path.resolve(WORKSPACE_ROOT, requested);
|
|
50
|
+
const relative = path.relative(WORKSPACE_ROOT, resolved);
|
|
51
|
+
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
52
|
+
throw new ToolInputError("Path must stay inside the local workspace");
|
|
53
|
+
}
|
|
54
|
+
return resolved;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isSensitivePath(input) {
|
|
58
|
+
const normalized = input.replaceAll("\\", "/");
|
|
59
|
+
return normalized.split("/").some((part) =>
|
|
60
|
+
/^\.env(?:\.|$)/i.test(part) ||
|
|
61
|
+
/\.(?:pem|key|p12|pfx)$/i.test(part) ||
|
|
62
|
+
/^id_(?:rsa|ecdsa|ed25519)$/i.test(part),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function outputResult(command, output, extra = {}) {
|
|
67
|
+
const value = String(output || "").trimEnd();
|
|
68
|
+
return {
|
|
69
|
+
ok: true,
|
|
70
|
+
command,
|
|
71
|
+
cwd: ".",
|
|
72
|
+
output: value ? value.slice(0, MAX_OUTPUT_LENGTH) : "(no output)",
|
|
73
|
+
...(value.length > MAX_OUTPUT_LENGTH ? { truncated: true } : {}),
|
|
74
|
+
...extra,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function listDirectory(command, args) {
|
|
79
|
+
const options = args.filter((arg) => arg.startsWith("-"));
|
|
80
|
+
if (options.some((option) => !/^-{1,2}[al]+$/.test(option))) throw new ToolInputError("Only basic ls/dir display flags are supported");
|
|
81
|
+
const locations = args.filter((arg) => !arg.startsWith("-"));
|
|
82
|
+
if (locations.length > 1) throw new ToolInputError("Only one directory may be listed at a time");
|
|
83
|
+
const location = locations[0] || ".";
|
|
84
|
+
const target = resolveWorkspacePath(location);
|
|
85
|
+
const entries = await fs.readdir(target, { withFileTypes: true });
|
|
86
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
87
|
+
const output = entries.map((entry) => `${entry.isDirectory() ? "d" : "f"} ${entry.name}`).join("\n");
|
|
88
|
+
return outputResult(command, output);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function readFile(command, args) {
|
|
92
|
+
if (args.length !== 1) throw new ToolInputError("cat/type accepts exactly one workspace file");
|
|
93
|
+
if (isSensitivePath(args[0])) throw new ToolInputError("Reading credential files is not allowed");
|
|
94
|
+
const target = resolveWorkspacePath(args[0]);
|
|
95
|
+
const stat = await fs.stat(target);
|
|
96
|
+
if (!stat.isFile()) throw new ToolInputError("The requested path is not a file");
|
|
97
|
+
if (stat.size > MAX_FILE_LENGTH) throw new ToolInputError(`Files larger than ${MAX_FILE_LENGTH} bytes are not returned`);
|
|
98
|
+
return outputResult(command, await fs.readFile(target, "utf8"));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function searchFiles(command, args) {
|
|
102
|
+
if (!args.length || args[0].startsWith("-")) throw new ToolInputError("rg requires a search pattern");
|
|
103
|
+
const pattern = args[0];
|
|
104
|
+
const locations = args.slice(1);
|
|
105
|
+
if (locations.length > 8 || locations.some((location) => location.startsWith("-"))) {
|
|
106
|
+
throw new ToolInputError("rg accepts at most eight workspace paths and no flags");
|
|
107
|
+
}
|
|
108
|
+
const safeLocations = locations.map((location) => {
|
|
109
|
+
if (isSensitivePath(location)) throw new ToolInputError("Searching credential paths is not allowed");
|
|
110
|
+
const resolved = resolveWorkspacePath(location);
|
|
111
|
+
return path.relative(WORKSPACE_ROOT, resolved) || ".";
|
|
112
|
+
});
|
|
113
|
+
const rgArgs = [
|
|
114
|
+
"--no-config", "--no-heading", "--line-number", "--color", "never",
|
|
115
|
+
"--glob", "!.env*", "--glob", "!**/*.pem", "--glob", "!**/*.key", "--glob", "!**/id_rsa",
|
|
116
|
+
"--", pattern, ...safeLocations,
|
|
117
|
+
];
|
|
118
|
+
try {
|
|
119
|
+
const { stdout, stderr } = await execFileAsync("rg", rgArgs, {
|
|
120
|
+
cwd: WORKSPACE_ROOT,
|
|
121
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
122
|
+
maxBuffer: MAX_OUTPUT_LENGTH * 2,
|
|
123
|
+
windowsHide: true,
|
|
124
|
+
env: { ...process.env, RIPGREP_CONFIG_PATH: "" },
|
|
125
|
+
});
|
|
126
|
+
return outputResult(command, [stdout, stderr].filter(Boolean).join("\n"));
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error?.code === 1) return outputResult(command, "(no matches)");
|
|
129
|
+
throw new Error(error?.stderr?.trim() || error?.message || "Search failed");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function validateGitArgs(subcommand, args) {
|
|
134
|
+
const allow = {
|
|
135
|
+
status: new Set(["--short", "--porcelain", "--branch"]),
|
|
136
|
+
diff: new Set(["--stat", "--name-only", "--name-status", "--cached"]),
|
|
137
|
+
log: new Set(["--oneline", "--decorate", "--all"]),
|
|
138
|
+
show: new Set(["--stat", "--name-only"]),
|
|
139
|
+
branch: new Set(["--show-current", "--list"]),
|
|
140
|
+
};
|
|
141
|
+
if (!allow[subcommand]) throw new ToolInputError("Only read-only git status/diff/log/show/branch are supported");
|
|
142
|
+
for (const arg of args) {
|
|
143
|
+
if (allow[subcommand].has(arg)) continue;
|
|
144
|
+
if (subcommand === "show" && /^(?:HEAD(?:~\d+)?|[0-9a-f]{7,40})$/i.test(arg)) continue;
|
|
145
|
+
throw new ToolInputError(`Unsupported git ${subcommand} argument: ${arg}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function readGit(command, args) {
|
|
150
|
+
const subcommand = args.shift();
|
|
151
|
+
if (!subcommand) throw new ToolInputError("git requires a read-only subcommand");
|
|
152
|
+
validateGitArgs(subcommand, args);
|
|
153
|
+
const gitArgs = ["--no-pager", subcommand, ...(subcommand === "diff" ? ["--no-ext-diff"] : []), ...args];
|
|
154
|
+
const { stdout, stderr } = await execFileAsync("git", gitArgs, {
|
|
155
|
+
cwd: WORKSPACE_ROOT,
|
|
156
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
157
|
+
maxBuffer: MAX_OUTPUT_LENGTH * 2,
|
|
158
|
+
windowsHide: true,
|
|
159
|
+
env: { ...process.env, GIT_PAGER: "cat", GIT_TERMINAL_PROMPT: "0" },
|
|
160
|
+
});
|
|
161
|
+
return outputResult(command, [stdout, stderr].filter(Boolean).join("\n"));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function runReadOnlyCommand(command) {
|
|
165
|
+
const tokens = tokenize(command);
|
|
166
|
+
const executable = tokens[0].toLowerCase();
|
|
167
|
+
const args = tokens.slice(1);
|
|
168
|
+
if (executable === "pwd") {
|
|
169
|
+
if (args.length) throw new ToolInputError("pwd does not accept arguments");
|
|
170
|
+
return outputResult(command, ".");
|
|
171
|
+
}
|
|
172
|
+
if (executable === "ls" || executable === "dir") return listDirectory(command, args);
|
|
173
|
+
if (executable === "cat" || executable === "type") return readFile(command, args);
|
|
174
|
+
if (executable === "rg") return searchFiles(command, args);
|
|
175
|
+
if (executable === "git") return readGit(command, args);
|
|
176
|
+
throw new ToolInputError("Only pwd, ls/dir, cat/type, rg, and read-only git commands are supported");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function runApprovedJavaScript(code) {
|
|
180
|
+
if (typeof code !== "string" || !code.trim()) throw new ToolInputError("JavaScript code is required");
|
|
181
|
+
if (code.length > MAX_CODE_LENGTH) throw new ToolInputError(`JavaScript code must be ${MAX_CODE_LENGTH} characters or fewer`);
|
|
182
|
+
|
|
183
|
+
const safeEnv = {
|
|
184
|
+
PATH: process.env.PATH || process.env.Path || "",
|
|
185
|
+
Path: process.env.Path || process.env.PATH || "",
|
|
186
|
+
SystemRoot: process.env.SystemRoot || "",
|
|
187
|
+
TEMP: process.env.TEMP || "",
|
|
188
|
+
TMP: process.env.TMP || "",
|
|
189
|
+
NODE_ENV: process.env.NODE_ENV || "production",
|
|
190
|
+
};
|
|
191
|
+
try {
|
|
192
|
+
const { stdout, stderr } = await execFileAsync(process.execPath, ["--eval", code], {
|
|
193
|
+
cwd: WORKSPACE_ROOT,
|
|
194
|
+
timeout: CODE_TIMEOUT_MS,
|
|
195
|
+
maxBuffer: MAX_OUTPUT_LENGTH * 2,
|
|
196
|
+
windowsHide: true,
|
|
197
|
+
env: safeEnv,
|
|
198
|
+
});
|
|
199
|
+
return outputResult("javascript", [stdout, stderr].filter(Boolean).join("\n"), { runtime: "javascript" });
|
|
200
|
+
} catch (error) {
|
|
201
|
+
const message = error?.killed || error?.signal === "SIGTERM"
|
|
202
|
+
? "JavaScript execution timed out"
|
|
203
|
+
: (error?.stderr?.trim() || error?.message || "JavaScript execution failed");
|
|
204
|
+
throw new Error(message);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export async function POST(request) {
|
|
209
|
+
try {
|
|
210
|
+
const body = await request.json().catch(() => ({}));
|
|
211
|
+
if (body?.mode === "execute") {
|
|
212
|
+
if (body.approved !== true) {
|
|
213
|
+
return NextResponse.json({
|
|
214
|
+
ok: false,
|
|
215
|
+
requiresApproval: true,
|
|
216
|
+
action: "execute_javascript",
|
|
217
|
+
warning: "This runs JavaScript in the local Sway Router workspace.",
|
|
218
|
+
}, { status: 409 });
|
|
219
|
+
}
|
|
220
|
+
return NextResponse.json(await runApprovedJavaScript(body.code));
|
|
221
|
+
}
|
|
222
|
+
const result = await runReadOnlyCommand(body?.command);
|
|
223
|
+
return NextResponse.json(result);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
const status = error instanceof ToolInputError ? 400 : 422;
|
|
226
|
+
return NextResponse.json({ ok: false, error: error instanceof Error ? error.message : "Shell tool failed" }, { status });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
import { NextResponse } from "next/server";
|
|
4
|
+
import { GET as claudeGet } from "../claude-settings/route";
|
|
5
|
+
import { GET as codexGet } from "../codex-settings/route";
|
|
6
|
+
import { GET as opencodeGet } from "../opencode-settings/route";
|
|
7
|
+
import { GET as hermesGet } from "../hermes-settings/route";
|
|
8
|
+
import { GET as coworkGet } from "../cowork-settings/route";
|
|
9
|
+
import { GET as kiloGet } from "../kilo-settings/route";
|
|
10
|
+
import { GET as grokBuildGet } from "../grok-build-settings/route";
|
|
11
|
+
import { GET as ompGet } from "../omp-settings/route";
|
|
12
|
+
|
|
13
|
+
const STATUS_GETTERS = {
|
|
14
|
+
claude: claudeGet,
|
|
15
|
+
codex: codexGet,
|
|
16
|
+
opencode: opencodeGet,
|
|
17
|
+
hermes: hermesGet,
|
|
18
|
+
cowork: coworkGet,
|
|
19
|
+
kilo: kiloGet,
|
|
20
|
+
"grok-build": grokBuildGet,
|
|
21
|
+
omp: ompGet,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export async function GET() {
|
|
25
|
+
const entries = await Promise.all(
|
|
26
|
+
Object.entries(STATUS_GETTERS).map(async ([toolId, getter]) => {
|
|
27
|
+
try {
|
|
28
|
+
const res = await getter();
|
|
29
|
+
const data = await res.json();
|
|
30
|
+
return [toolId, data];
|
|
31
|
+
} catch {
|
|
32
|
+
return [toolId, null];
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
return NextResponse.json(Object.fromEntries(entries));
|
|
37
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
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 { DEFAULT_PLUGINS } from "@/shared/constants/coworkPlugins";
|
|
10
|
+
|
|
11
|
+
const execAsync = promisify(exec);
|
|
12
|
+
|
|
13
|
+
const EXA_PLUGIN = DEFAULT_PLUGINS.find((p) => p.name === "exa");
|
|
14
|
+
const buildExaMcpEntry = () => ({
|
|
15
|
+
type: EXA_PLUGIN.transport,
|
|
16
|
+
url: EXA_PLUGIN.url,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const getClaudeSettingsPath = () => {
|
|
20
|
+
const homeDir = os.homedir();
|
|
21
|
+
return path.join(homeDir, ".claude", "settings.json");
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const getClaudeJsonPath = () => path.join(os.homedir(), ".claude.json");
|
|
25
|
+
|
|
26
|
+
const readClaudeJson = async () => {
|
|
27
|
+
try {
|
|
28
|
+
const content = await fs.readFile(getClaudeJsonPath(), "utf-8");
|
|
29
|
+
return JSON.parse(content.replace(/,(\s*[}\]])/g, "$1"));
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const writeClaudeJsonMcp = async (mcpServers) => {
|
|
36
|
+
const filePath = getClaudeJsonPath();
|
|
37
|
+
let data = {};
|
|
38
|
+
try {
|
|
39
|
+
data = JSON.parse(await fs.readFile(filePath, "utf-8"));
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (error.code !== "ENOENT") throw error;
|
|
42
|
+
}
|
|
43
|
+
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
44
|
+
data.mcpServers = { ...(data.mcpServers || {}), ...mcpServers };
|
|
45
|
+
} else if (data.mcpServers) {
|
|
46
|
+
delete data.mcpServers.exa;
|
|
47
|
+
if (Object.keys(data.mcpServers).length === 0) delete data.mcpServers;
|
|
48
|
+
}
|
|
49
|
+
await fs.writeFile(filePath, JSON.stringify(data, null, 2));
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const checkClaudeInstalled = async () => {
|
|
53
|
+
try {
|
|
54
|
+
const isWindows = os.platform() === "win32";
|
|
55
|
+
const command = isWindows ? "where claude" : "which claude";
|
|
56
|
+
const env = isWindows
|
|
57
|
+
? { ...process.env, PATH: `${process.env.APPDATA}\\npm;${process.env.PATH}` }
|
|
58
|
+
: process.env;
|
|
59
|
+
await execAsync(command, { windowsHide: true, env });
|
|
60
|
+
return true;
|
|
61
|
+
} catch {
|
|
62
|
+
try {
|
|
63
|
+
await fs.access(getClaudeSettingsPath());
|
|
64
|
+
return true;
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const SWAY_ROUTER_MATCH_HOSTS = [
|
|
72
|
+
"127.0.0.1:14045",
|
|
73
|
+
"localhost:14045",
|
|
74
|
+
"localhost",
|
|
75
|
+
"127.0.0.1",
|
|
76
|
+
];
|
|
77
|
+
const SWAY_ROUTER_URL_HOST_RE = /^(?:127\.0\.0\.1|localhost)(?::14045)?$/;
|
|
78
|
+
|
|
79
|
+
function isSwayRouterBaseUrl(baseUrl) {
|
|
80
|
+
if (typeof baseUrl !== "string" || !baseUrl) return false;
|
|
81
|
+
try {
|
|
82
|
+
const u = new URL(baseUrl);
|
|
83
|
+
return (
|
|
84
|
+
u.pathname.endsWith("/v1") &&
|
|
85
|
+
(SWAY_ROUTER_URL_HOST_RE.test(u.host) || SWAY_ROUTER_MATCH_HOSTS.includes(u.host))
|
|
86
|
+
);
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function hasSwayRouterFromSettings(settings) {
|
|
93
|
+
return isSwayRouterBaseUrl(settings?.env?.ANTHROPIC_BASE_URL);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const readSettings = async () => {
|
|
97
|
+
try {
|
|
98
|
+
const settingsPath = getClaudeSettingsPath();
|
|
99
|
+
const content = await fs.readFile(settingsPath, "utf-8");
|
|
100
|
+
|
|
101
|
+
const stripped = content.replace(/,(\s*[}\]])/g, "$1");
|
|
102
|
+
return JSON.parse(stripped);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export async function GET() {
|
|
109
|
+
try {
|
|
110
|
+
const isInstalled = await checkClaudeInstalled();
|
|
111
|
+
|
|
112
|
+
if (!isInstalled) {
|
|
113
|
+
return NextResponse.json({
|
|
114
|
+
installed: false,
|
|
115
|
+
settings: null,
|
|
116
|
+
message: "Claude CLI is not installed",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const settings = await readSettings();
|
|
121
|
+
const hasSwayRouter = hasSwayRouterFromSettings(settings);
|
|
122
|
+
const claudeJson = await readClaudeJson();
|
|
123
|
+
|
|
124
|
+
return NextResponse.json({
|
|
125
|
+
installed: true,
|
|
126
|
+
settings: settings,
|
|
127
|
+
hasSwayRouter,
|
|
128
|
+
exaMcpEnabled: !!claudeJson?.mcpServers?.exa,
|
|
129
|
+
settingsPath: getClaudeSettingsPath(),
|
|
130
|
+
});
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.log("Error checking claude settings:", error);
|
|
133
|
+
return NextResponse.json(
|
|
134
|
+
{ error: "Failed to check claude settings" },
|
|
135
|
+
{ status: 500 }
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function POST(request) {
|
|
141
|
+
try {
|
|
142
|
+
const { env, exaMcpEnabled, maxContextTokens } = await request.json();
|
|
143
|
+
|
|
144
|
+
if (!env || typeof env !== "object") {
|
|
145
|
+
return NextResponse.json(
|
|
146
|
+
{ error: "Invalid env object" },
|
|
147
|
+
{ status: 400 }
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const settingsPath = getClaudeSettingsPath();
|
|
152
|
+
const claudeDir = path.dirname(settingsPath);
|
|
153
|
+
|
|
154
|
+
await fs.mkdir(claudeDir, { recursive: true });
|
|
155
|
+
|
|
156
|
+
let currentSettings = {};
|
|
157
|
+
try {
|
|
158
|
+
const content = await fs.readFile(settingsPath, "utf-8");
|
|
159
|
+
currentSettings = JSON.parse(content);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
if (error.code !== "ENOENT") {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (env.ANTHROPIC_BASE_URL) {
|
|
167
|
+
env.ANTHROPIC_BASE_URL = env.ANTHROPIC_BASE_URL.endsWith("/v1")
|
|
168
|
+
? env.ANTHROPIC_BASE_URL
|
|
169
|
+
: `${env.ANTHROPIC_BASE_URL}/v1`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const newSettings = {
|
|
173
|
+
...currentSettings,
|
|
174
|
+
hasCompletedOnboarding: true,
|
|
175
|
+
env: {
|
|
176
|
+
...(currentSettings.env || {}),
|
|
177
|
+
...env,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
if (maxContextTokens) {
|
|
182
|
+
newSettings.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS = String(maxContextTokens);
|
|
183
|
+
} else {
|
|
184
|
+
delete newSettings.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
await fs.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
|
|
188
|
+
|
|
189
|
+
if (EXA_PLUGIN) {
|
|
190
|
+
const shouldEnableExa = exaMcpEnabled !== false;
|
|
191
|
+
await writeClaudeJsonMcp(shouldEnableExa ? { exa: buildExaMcpEntry() } : null);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return NextResponse.json({
|
|
195
|
+
success: true,
|
|
196
|
+
message: "Settings updated successfully",
|
|
197
|
+
});
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.log("Error updating claude settings:", error);
|
|
200
|
+
return NextResponse.json(
|
|
201
|
+
{ error: "Failed to update claude settings" },
|
|
202
|
+
{ status: 500 }
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const RESET_ENV_KEYS = [
|
|
208
|
+
"ANTHROPIC_BASE_URL",
|
|
209
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
210
|
+
"ANTHROPIC_DEFAULT_FABLE_MODEL",
|
|
211
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
212
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
213
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
214
|
+
"API_TIMEOUT_MS",
|
|
215
|
+
"CLAUDE_CODE_MAX_CONTEXT_TOKENS",
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
export async function DELETE() {
|
|
219
|
+
try {
|
|
220
|
+
const settingsPath = getClaudeSettingsPath();
|
|
221
|
+
|
|
222
|
+
let currentSettings = {};
|
|
223
|
+
try {
|
|
224
|
+
const content = await fs.readFile(settingsPath, "utf-8");
|
|
225
|
+
currentSettings = JSON.parse(content);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
if (error.code === "ENOENT") {
|
|
228
|
+
return NextResponse.json({
|
|
229
|
+
success: true,
|
|
230
|
+
message: "No settings file to reset",
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (currentSettings.env) {
|
|
237
|
+
RESET_ENV_KEYS.forEach((key) => {
|
|
238
|
+
delete currentSettings.env[key];
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
if (Object.keys(currentSettings.env).length === 0) {
|
|
242
|
+
delete currentSettings.env;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
await writeClaudeJsonMcp(null);
|
|
247
|
+
|
|
248
|
+
await fs.writeFile(settingsPath, JSON.stringify(currentSettings, null, 2));
|
|
249
|
+
|
|
250
|
+
return NextResponse.json({
|
|
251
|
+
success: true,
|
|
252
|
+
message: "Settings reset successfully",
|
|
253
|
+
});
|
|
254
|
+
} catch (error) {
|
|
255
|
+
console.log("Error resetting claude settings:", error);
|
|
256
|
+
return NextResponse.json(
|
|
257
|
+
{ error: "Failed to reset claude settings" },
|
|
258
|
+
{ status: 500 }
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|