Roo-Code/webview-ui/src/components/settings/utils/providerModelConfig.ts
sonpiaz 91d500ebd0 feat: add Kyma API as built-in provider
Kyma API (kymaapi.com) is an OpenAI-compatible LLM gateway with 20+
open-source models, free credits on signup, and pay-per-token billing.

- Add KymaHandler extending BaseOpenAiCompatibleProvider
- Register 8 top models (qwen-3.6-plus, deepseek-v3/r1, kimi-k2.5,
  gemma-4-31b, llama-3.3-70b, qwen-3-32b, minimax-m2.5)
- Add kymaApiKey to provider settings schema and secret storage
- Add Kyma settings UI component with API key input
- Wire into buildApiHandler switch, PROVIDERS list, and model config
2026-04-10 17:25:05 -07:00

162 lines
5.8 KiB
TypeScript

import type { ProviderName, ModelInfo, ProviderSettings } from "@roo-code/types"
import {
anthropicDefaultModelId,
bedrockDefaultModelId,
deepSeekDefaultModelId,
moonshotDefaultModelId,
geminiDefaultModelId,
mistralDefaultModelId,
openAiNativeDefaultModelId,
qwenCodeDefaultModelId,
vertexDefaultModelId,
xaiDefaultModelId,
sambaNovaDefaultModelId,
kymaDefaultModelId,
internationalZAiDefaultModelId,
mainlandZAiDefaultModelId,
fireworksDefaultModelId,
minimaxDefaultModelId,
basetenDefaultModelId,
} from "@roo-code/types"
import { MODELS_BY_PROVIDER } from "../constants"
export interface ProviderServiceConfig {
serviceName: string
serviceUrl: string
}
export const PROVIDER_SERVICE_CONFIG: Partial<Record<ProviderName, ProviderServiceConfig>> = {
anthropic: { serviceName: "Anthropic", serviceUrl: "https://console.anthropic.com" },
bedrock: { serviceName: "Amazon Bedrock", serviceUrl: "https://aws.amazon.com/bedrock" },
deepseek: { serviceName: "DeepSeek", serviceUrl: "https://platform.deepseek.com" },
moonshot: { serviceName: "Moonshot", serviceUrl: "https://platform.moonshot.cn" },
gemini: { serviceName: "Google Gemini", serviceUrl: "https://ai.google.dev" },
mistral: { serviceName: "Mistral", serviceUrl: "https://console.mistral.ai" },
"openai-native": { serviceName: "OpenAI", serviceUrl: "https://platform.openai.com" },
"qwen-code": { serviceName: "Qwen Code", serviceUrl: "https://dashscope.console.aliyun.com" },
vertex: { serviceName: "GCP Vertex AI", serviceUrl: "https://console.cloud.google.com/vertex-ai" },
xai: { serviceName: "xAI", serviceUrl: "https://x.ai" },
sambanova: { serviceName: "SambaNova", serviceUrl: "https://sambanova.ai" },
kyma: { serviceName: "Kyma API", serviceUrl: "https://kymaapi.com" },
zai: { serviceName: "Z.ai", serviceUrl: "https://z.ai" },
fireworks: { serviceName: "Fireworks AI", serviceUrl: "https://fireworks.ai" },
minimax: { serviceName: "MiniMax", serviceUrl: "https://minimax.chat" },
baseten: { serviceName: "Baseten", serviceUrl: "https://baseten.co" },
ollama: { serviceName: "Ollama", serviceUrl: "https://ollama.ai" },
lmstudio: { serviceName: "LM Studio", serviceUrl: "https://lmstudio.ai/docs" },
"vscode-lm": {
serviceName: "VS Code LM",
serviceUrl: "https://code.visualstudio.com/api/extension-guides/language-model",
},
}
export const PROVIDER_DEFAULT_MODEL_IDS: Partial<Record<ProviderName, string>> = {
anthropic: anthropicDefaultModelId,
bedrock: bedrockDefaultModelId,
deepseek: deepSeekDefaultModelId,
moonshot: moonshotDefaultModelId,
gemini: geminiDefaultModelId,
mistral: mistralDefaultModelId,
"openai-native": openAiNativeDefaultModelId,
"qwen-code": qwenCodeDefaultModelId,
vertex: vertexDefaultModelId,
xai: xaiDefaultModelId,
sambanova: sambaNovaDefaultModelId,
kyma: kymaDefaultModelId,
zai: internationalZAiDefaultModelId,
fireworks: fireworksDefaultModelId,
minimax: minimaxDefaultModelId,
baseten: basetenDefaultModelId,
}
export const getProviderServiceConfig = (provider: ProviderName): ProviderServiceConfig => {
return PROVIDER_SERVICE_CONFIG[provider] ?? { serviceName: provider, serviceUrl: "" }
}
export const getDefaultModelIdForProvider = (provider: ProviderName, apiConfiguration?: ProviderSettings): string => {
// Handle Z.ai's China/International entrypoint distinction
if (provider === "zai" && apiConfiguration) {
return apiConfiguration.zaiApiLine === "china_coding"
? mainlandZAiDefaultModelId
: internationalZAiDefaultModelId
}
return PROVIDER_DEFAULT_MODEL_IDS[provider] ?? ""
}
export const getStaticModelsForProvider = (
provider: ProviderName,
customArnLabel?: string,
): Record<string, ModelInfo> => {
const models = MODELS_BY_PROVIDER[provider] ?? {}
// Add custom-arn option for Bedrock
if (provider === "bedrock") {
return {
...models,
"custom-arn": {
maxTokens: 0,
contextWindow: 0,
supportsPromptCache: false,
description: customArnLabel ?? "Use Custom ARN",
},
}
}
return models
}
/**
* Checks if a provider uses static models from MODELS_BY_PROVIDER
*/
export const isStaticModelProvider = (provider: ProviderName): boolean => {
return provider in MODELS_BY_PROVIDER
}
/**
* List of providers that have their own custom model selection UI
* and should not use the generic ModelPicker in ApiOptions
*/
export const PROVIDERS_WITH_CUSTOM_MODEL_UI: ProviderName[] = [
"openrouter",
"requesty",
"unbound",
"openai", // OpenAI Compatible
"openai-codex", // OpenAI Codex has custom UI with auth and rate limits
"litellm",
"vercel-ai-gateway",
"roo",
"ollama",
"lmstudio",
"vscode-lm",
]
/**
* Checks if a provider should use the generic ModelPicker
*/
export const shouldUseGenericModelPicker = (provider: ProviderName): boolean => {
return isStaticModelProvider(provider) && !PROVIDERS_WITH_CUSTOM_MODEL_UI.includes(provider)
}
/**
* Handles provider-specific side effects when a model is changed.
* Centralizes provider-specific logic to keep it out of the ApiOptions template.
*/
export const handleModelChangeSideEffects = <K extends keyof ProviderSettings>(
provider: ProviderName,
modelId: string,
setApiConfigurationField: (field: K, value: ProviderSettings[K]) => void,
): void => {
// Bedrock: Clear custom ARN if not using custom ARN option
if (provider === "bedrock" && modelId !== "custom-arn") {
setApiConfigurationField("awsCustomArn" as K, "" as ProviderSettings[K])
}
// All providers: Clear reasoning settings when switching models to allow
// the new model's defaults to take effect. Different models within the
// same provider can have different reasoning defaults/options.
setApiConfigurationField("reasoningEffort" as K, undefined as ProviderSettings[K])
setApiConfigurationField("modelMaxTokens" as K, undefined as ProviderSettings[K])
setApiConfigurationField("modelMaxThinkingTokens" as K, undefined as ProviderSettings[K])
}