| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- import { z } from "zod"
- import { modelInfoSchema, reasoningEffortWithMinimalSchema, verbosityLevelsSchema } from "./model.js"
- import { codebaseIndexProviderSchema } from "./codebase-index.js"
- import {
- anthropicModels,
- bedrockModels,
- cerebrasModels,
- chutesModels,
- claudeCodeModels,
- deepSeekModels,
- doubaoModels,
- featherlessModels,
- fireworksModels,
- geminiModels,
- groqModels,
- ioIntelligenceModels,
- mistralModels,
- moonshotModels,
- openAiNativeModels,
- qwenCodeModels,
- rooModels,
- sambaNovaModels,
- vertexModels,
- vscodeLlmModels,
- xaiModels,
- internationalZAiModels,
- } from "./providers/index.js"
- /**
- * ProviderName
- */
- export const providerNames = [
- "anthropic",
- "claude-code",
- "glama",
- "openrouter",
- "bedrock",
- "vertex",
- "openai",
- "ollama",
- "vscode-lm",
- "lmstudio",
- "gemini",
- "gemini-cli",
- "openai-native",
- "mistral",
- "moonshot",
- "deepseek",
- "doubao",
- "qwen-code",
- "unbound",
- "requesty",
- "human-relay",
- "fake-ai",
- "xai",
- "groq",
- "chutes",
- "litellm",
- "huggingface",
- "cerebras",
- "sambanova",
- "zai",
- "fireworks",
- "featherless",
- "io-intelligence",
- "roo",
- ] as const
- export const providerNamesSchema = z.enum(providerNames)
- export type ProviderName = z.infer<typeof providerNamesSchema>
- /**
- * ProviderSettingsEntry
- */
- export const providerSettingsEntrySchema = z.object({
- id: z.string(),
- name: z.string(),
- apiProvider: providerNamesSchema.optional(),
- })
- export type ProviderSettingsEntry = z.infer<typeof providerSettingsEntrySchema>
- /**
- * ProviderSettings
- */
- /**
- * Default value for consecutive mistake limit
- */
- export const DEFAULT_CONSECUTIVE_MISTAKE_LIMIT = 3
- const baseProviderSettingsSchema = z.object({
- includeMaxTokens: z.boolean().optional(),
- diffEnabled: z.boolean().optional(),
- todoListEnabled: z.boolean().optional(),
- fuzzyMatchThreshold: z.number().optional(),
- modelTemperature: z.number().nullish(),
- rateLimitSeconds: z.number().optional(),
- consecutiveMistakeLimit: z.number().min(0).optional(),
- // Model reasoning.
- enableReasoningEffort: z.boolean().optional(),
- reasoningEffort: reasoningEffortWithMinimalSchema.optional(),
- modelMaxTokens: z.number().optional(),
- modelMaxThinkingTokens: z.number().optional(),
- // Model verbosity.
- verbosity: verbosityLevelsSchema.optional(),
- })
- // Several of the providers share common model config properties.
- const apiModelIdProviderModelSchema = baseProviderSettingsSchema.extend({
- apiModelId: z.string().optional(),
- })
- const anthropicSchema = apiModelIdProviderModelSchema.extend({
- apiKey: z.string().optional(),
- anthropicBaseUrl: z.string().optional(),
- anthropicUseAuthToken: z.boolean().optional(),
- anthropicBeta1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window
- })
- const claudeCodeSchema = apiModelIdProviderModelSchema.extend({
- claudeCodePath: z.string().optional(),
- claudeCodeMaxOutputTokens: z.number().int().min(1).max(200000).optional(),
- })
- const glamaSchema = baseProviderSettingsSchema.extend({
- glamaModelId: z.string().optional(),
- glamaApiKey: z.string().optional(),
- })
- const openRouterSchema = baseProviderSettingsSchema.extend({
- openRouterApiKey: z.string().optional(),
- openRouterModelId: z.string().optional(),
- openRouterBaseUrl: z.string().optional(),
- openRouterSpecificProvider: z.string().optional(),
- openRouterUseMiddleOutTransform: z.boolean().optional(),
- })
- const bedrockSchema = apiModelIdProviderModelSchema.extend({
- awsAccessKey: z.string().optional(),
- awsSecretKey: z.string().optional(),
- awsSessionToken: z.string().optional(),
- awsRegion: z.string().optional(),
- awsUseCrossRegionInference: z.boolean().optional(),
- awsUsePromptCache: z.boolean().optional(),
- awsProfile: z.string().optional(),
- awsUseProfile: z.boolean().optional(),
- awsApiKey: z.string().optional(),
- awsUseApiKey: z.boolean().optional(),
- awsCustomArn: z.string().optional(),
- awsModelContextWindow: z.number().optional(),
- awsBedrockEndpointEnabled: z.boolean().optional(),
- awsBedrockEndpoint: z.string().optional(),
- awsBedrock1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window
- })
- const vertexSchema = apiModelIdProviderModelSchema.extend({
- vertexKeyFile: z.string().optional(),
- vertexJsonCredentials: z.string().optional(),
- vertexProjectId: z.string().optional(),
- vertexRegion: z.string().optional(),
- enableUrlContext: z.boolean().optional(),
- enableGrounding: z.boolean().optional(),
- })
- const openAiSchema = baseProviderSettingsSchema.extend({
- openAiBaseUrl: z.string().optional(),
- openAiApiKey: z.string().optional(),
- openAiLegacyFormat: z.boolean().optional(),
- openAiR1FormatEnabled: z.boolean().optional(),
- openAiModelId: z.string().optional(),
- openAiCustomModelInfo: modelInfoSchema.nullish(),
- openAiUseAzure: z.boolean().optional(),
- azureApiVersion: z.string().optional(),
- openAiStreamingEnabled: z.boolean().optional(),
- openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration.
- openAiHeaders: z.record(z.string(), z.string()).optional(),
- })
- const ollamaSchema = baseProviderSettingsSchema.extend({
- ollamaModelId: z.string().optional(),
- ollamaBaseUrl: z.string().optional(),
- })
- const vsCodeLmSchema = baseProviderSettingsSchema.extend({
- vsCodeLmModelSelector: z
- .object({
- vendor: z.string().optional(),
- family: z.string().optional(),
- version: z.string().optional(),
- id: z.string().optional(),
- })
- .optional(),
- })
- const lmStudioSchema = baseProviderSettingsSchema.extend({
- lmStudioModelId: z.string().optional(),
- lmStudioBaseUrl: z.string().optional(),
- lmStudioDraftModelId: z.string().optional(),
- lmStudioSpeculativeDecodingEnabled: z.boolean().optional(),
- })
- const geminiSchema = apiModelIdProviderModelSchema.extend({
- geminiApiKey: z.string().optional(),
- googleGeminiBaseUrl: z.string().optional(),
- enableUrlContext: z.boolean().optional(),
- enableGrounding: z.boolean().optional(),
- })
- const geminiCliSchema = apiModelIdProviderModelSchema.extend({
- geminiCliOAuthPath: z.string().optional(),
- geminiCliProjectId: z.string().optional(),
- })
- const openAiNativeSchema = apiModelIdProviderModelSchema.extend({
- openAiNativeApiKey: z.string().optional(),
- openAiNativeBaseUrl: z.string().optional(),
- })
- const mistralSchema = apiModelIdProviderModelSchema.extend({
- mistralApiKey: z.string().optional(),
- mistralCodestralUrl: z.string().optional(),
- })
- const deepSeekSchema = apiModelIdProviderModelSchema.extend({
- deepSeekBaseUrl: z.string().optional(),
- deepSeekApiKey: z.string().optional(),
- })
- const doubaoSchema = apiModelIdProviderModelSchema.extend({
- doubaoBaseUrl: z.string().optional(),
- doubaoApiKey: z.string().optional(),
- })
- const moonshotSchema = apiModelIdProviderModelSchema.extend({
- moonshotBaseUrl: z
- .union([z.literal("https://api.moonshot.ai/v1"), z.literal("https://api.moonshot.cn/v1")])
- .optional(),
- moonshotApiKey: z.string().optional(),
- })
- const unboundSchema = baseProviderSettingsSchema.extend({
- unboundApiKey: z.string().optional(),
- unboundModelId: z.string().optional(),
- })
- const requestySchema = baseProviderSettingsSchema.extend({
- requestyBaseUrl: z.string().optional(),
- requestyApiKey: z.string().optional(),
- requestyModelId: z.string().optional(),
- })
- const humanRelaySchema = baseProviderSettingsSchema
- const fakeAiSchema = baseProviderSettingsSchema.extend({
- fakeAi: z.unknown().optional(),
- })
- const xaiSchema = apiModelIdProviderModelSchema.extend({
- xaiApiKey: z.string().optional(),
- })
- const groqSchema = apiModelIdProviderModelSchema.extend({
- groqApiKey: z.string().optional(),
- })
- const huggingFaceSchema = baseProviderSettingsSchema.extend({
- huggingFaceApiKey: z.string().optional(),
- huggingFaceModelId: z.string().optional(),
- huggingFaceInferenceProvider: z.string().optional(),
- })
- const chutesSchema = apiModelIdProviderModelSchema.extend({
- chutesApiKey: z.string().optional(),
- })
- const litellmSchema = baseProviderSettingsSchema.extend({
- litellmBaseUrl: z.string().optional(),
- litellmApiKey: z.string().optional(),
- litellmModelId: z.string().optional(),
- litellmUsePromptCache: z.boolean().optional(),
- })
- const cerebrasSchema = apiModelIdProviderModelSchema.extend({
- cerebrasApiKey: z.string().optional(),
- })
- const sambaNovaSchema = apiModelIdProviderModelSchema.extend({
- sambaNovaApiKey: z.string().optional(),
- })
- const zaiSchema = apiModelIdProviderModelSchema.extend({
- zaiApiKey: z.string().optional(),
- zaiApiLine: z.union([z.literal("china"), z.literal("international")]).optional(),
- })
- const fireworksSchema = apiModelIdProviderModelSchema.extend({
- fireworksApiKey: z.string().optional(),
- })
- const featherlessSchema = apiModelIdProviderModelSchema.extend({
- featherlessApiKey: z.string().optional(),
- })
- const ioIntelligenceSchema = apiModelIdProviderModelSchema.extend({
- ioIntelligenceModelId: z.string().optional(),
- ioIntelligenceApiKey: z.string().optional(),
- })
- const qwenCodeSchema = apiModelIdProviderModelSchema.extend({
- qwenCodeOauthPath: z.string().optional(),
- })
- const rooSchema = apiModelIdProviderModelSchema.extend({
- // No additional fields needed - uses cloud authentication
- })
- const defaultSchema = z.object({
- apiProvider: z.undefined(),
- })
- export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProvider", [
- anthropicSchema.merge(z.object({ apiProvider: z.literal("anthropic") })),
- claudeCodeSchema.merge(z.object({ apiProvider: z.literal("claude-code") })),
- glamaSchema.merge(z.object({ apiProvider: z.literal("glama") })),
- openRouterSchema.merge(z.object({ apiProvider: z.literal("openrouter") })),
- bedrockSchema.merge(z.object({ apiProvider: z.literal("bedrock") })),
- vertexSchema.merge(z.object({ apiProvider: z.literal("vertex") })),
- openAiSchema.merge(z.object({ apiProvider: z.literal("openai") })),
- ollamaSchema.merge(z.object({ apiProvider: z.literal("ollama") })),
- vsCodeLmSchema.merge(z.object({ apiProvider: z.literal("vscode-lm") })),
- lmStudioSchema.merge(z.object({ apiProvider: z.literal("lmstudio") })),
- geminiSchema.merge(z.object({ apiProvider: z.literal("gemini") })),
- geminiCliSchema.merge(z.object({ apiProvider: z.literal("gemini-cli") })),
- openAiNativeSchema.merge(z.object({ apiProvider: z.literal("openai-native") })),
- mistralSchema.merge(z.object({ apiProvider: z.literal("mistral") })),
- deepSeekSchema.merge(z.object({ apiProvider: z.literal("deepseek") })),
- doubaoSchema.merge(z.object({ apiProvider: z.literal("doubao") })),
- moonshotSchema.merge(z.object({ apiProvider: z.literal("moonshot") })),
- unboundSchema.merge(z.object({ apiProvider: z.literal("unbound") })),
- requestySchema.merge(z.object({ apiProvider: z.literal("requesty") })),
- humanRelaySchema.merge(z.object({ apiProvider: z.literal("human-relay") })),
- fakeAiSchema.merge(z.object({ apiProvider: z.literal("fake-ai") })),
- xaiSchema.merge(z.object({ apiProvider: z.literal("xai") })),
- groqSchema.merge(z.object({ apiProvider: z.literal("groq") })),
- huggingFaceSchema.merge(z.object({ apiProvider: z.literal("huggingface") })),
- chutesSchema.merge(z.object({ apiProvider: z.literal("chutes") })),
- litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })),
- cerebrasSchema.merge(z.object({ apiProvider: z.literal("cerebras") })),
- sambaNovaSchema.merge(z.object({ apiProvider: z.literal("sambanova") })),
- zaiSchema.merge(z.object({ apiProvider: z.literal("zai") })),
- fireworksSchema.merge(z.object({ apiProvider: z.literal("fireworks") })),
- featherlessSchema.merge(z.object({ apiProvider: z.literal("featherless") })),
- ioIntelligenceSchema.merge(z.object({ apiProvider: z.literal("io-intelligence") })),
- qwenCodeSchema.merge(z.object({ apiProvider: z.literal("qwen-code") })),
- rooSchema.merge(z.object({ apiProvider: z.literal("roo") })),
- defaultSchema,
- ])
- export const providerSettingsSchema = z.object({
- apiProvider: providerNamesSchema.optional(),
- ...anthropicSchema.shape,
- ...claudeCodeSchema.shape,
- ...glamaSchema.shape,
- ...openRouterSchema.shape,
- ...bedrockSchema.shape,
- ...vertexSchema.shape,
- ...openAiSchema.shape,
- ...ollamaSchema.shape,
- ...vsCodeLmSchema.shape,
- ...lmStudioSchema.shape,
- ...geminiSchema.shape,
- ...geminiCliSchema.shape,
- ...openAiNativeSchema.shape,
- ...mistralSchema.shape,
- ...deepSeekSchema.shape,
- ...doubaoSchema.shape,
- ...moonshotSchema.shape,
- ...unboundSchema.shape,
- ...requestySchema.shape,
- ...humanRelaySchema.shape,
- ...fakeAiSchema.shape,
- ...xaiSchema.shape,
- ...groqSchema.shape,
- ...huggingFaceSchema.shape,
- ...chutesSchema.shape,
- ...litellmSchema.shape,
- ...cerebrasSchema.shape,
- ...sambaNovaSchema.shape,
- ...zaiSchema.shape,
- ...fireworksSchema.shape,
- ...featherlessSchema.shape,
- ...ioIntelligenceSchema.shape,
- ...qwenCodeSchema.shape,
- ...rooSchema.shape,
- ...codebaseIndexProviderSchema.shape,
- })
- export type ProviderSettings = z.infer<typeof providerSettingsSchema>
- export const providerSettingsWithIdSchema = providerSettingsSchema.extend({ id: z.string().optional() })
- export const discriminatedProviderSettingsWithIdSchema = providerSettingsSchemaDiscriminated.and(
- z.object({ id: z.string().optional() }),
- )
- export type ProviderSettingsWithId = z.infer<typeof providerSettingsWithIdSchema>
- export const PROVIDER_SETTINGS_KEYS = providerSettingsSchema.keyof().options
- export const MODEL_ID_KEYS: Partial<keyof ProviderSettings>[] = [
- "apiModelId",
- "glamaModelId",
- "openRouterModelId",
- "openAiModelId",
- "ollamaModelId",
- "lmStudioModelId",
- "lmStudioDraftModelId",
- "unboundModelId",
- "requestyModelId",
- "litellmModelId",
- "huggingFaceModelId",
- "ioIntelligenceModelId",
- ]
- export const getModelId = (settings: ProviderSettings): string | undefined => {
- const modelIdKey = MODEL_ID_KEYS.find((key) => settings[key])
- return modelIdKey ? (settings[modelIdKey] as string) : undefined
- }
- // Providers that use Anthropic-style API protocol.
- export const ANTHROPIC_STYLE_PROVIDERS: ProviderName[] = ["anthropic", "claude-code", "bedrock"]
- export const getApiProtocol = (provider: ProviderName | undefined, modelId?: string): "anthropic" | "openai" => {
- if (provider && ANTHROPIC_STYLE_PROVIDERS.includes(provider)) {
- return "anthropic"
- }
- if (provider && provider === "vertex" && modelId && modelId.toLowerCase().includes("claude")) {
- return "anthropic"
- }
- return "openai"
- }
- export const MODELS_BY_PROVIDER: Record<
- Exclude<ProviderName, "fake-ai" | "human-relay" | "gemini-cli" | "lmstudio" | "openai" | "ollama">,
- { id: ProviderName; label: string; models: string[] }
- > = {
- anthropic: {
- id: "anthropic",
- label: "Anthropic",
- models: Object.keys(anthropicModels),
- },
- bedrock: {
- id: "bedrock",
- label: "Amazon Bedrock",
- models: Object.keys(bedrockModels),
- },
- cerebras: {
- id: "cerebras",
- label: "Cerebras",
- models: Object.keys(cerebrasModels),
- },
- chutes: {
- id: "chutes",
- label: "Chutes AI",
- models: Object.keys(chutesModels),
- },
- "claude-code": { id: "claude-code", label: "Claude Code", models: Object.keys(claudeCodeModels) },
- deepseek: {
- id: "deepseek",
- label: "DeepSeek",
- models: Object.keys(deepSeekModels),
- },
- doubao: { id: "doubao", label: "Doubao", models: Object.keys(doubaoModels) },
- featherless: {
- id: "featherless",
- label: "Featherless",
- models: Object.keys(featherlessModels),
- },
- fireworks: {
- id: "fireworks",
- label: "Fireworks",
- models: Object.keys(fireworksModels),
- },
- gemini: {
- id: "gemini",
- label: "Google Gemini",
- models: Object.keys(geminiModels),
- },
- groq: { id: "groq", label: "Groq", models: Object.keys(groqModels) },
- "io-intelligence": {
- id: "io-intelligence",
- label: "IO Intelligence",
- models: Object.keys(ioIntelligenceModels),
- },
- mistral: {
- id: "mistral",
- label: "Mistral",
- models: Object.keys(mistralModels),
- },
- moonshot: {
- id: "moonshot",
- label: "Moonshot",
- models: Object.keys(moonshotModels),
- },
- "openai-native": {
- id: "openai-native",
- label: "OpenAI",
- models: Object.keys(openAiNativeModels),
- },
- "qwen-code": { id: "qwen-code", label: "Qwen Code", models: Object.keys(qwenCodeModels) },
- roo: { id: "roo", label: "Roo", models: Object.keys(rooModels) },
- sambanova: {
- id: "sambanova",
- label: "SambaNova",
- models: Object.keys(sambaNovaModels),
- },
- vertex: {
- id: "vertex",
- label: "GCP Vertex AI",
- models: Object.keys(vertexModels),
- },
- "vscode-lm": {
- id: "vscode-lm",
- label: "VS Code LM API",
- models: Object.keys(vscodeLlmModels),
- },
- xai: { id: "xai", label: "xAI (Grok)", models: Object.keys(xaiModels) },
- zai: { id: "zai", label: "Zai", models: Object.keys(internationalZAiModels) },
- // Dynamic providers; models pulled from the respective APIs.
- glama: { id: "glama", label: "Glama", models: [] },
- huggingface: { id: "huggingface", label: "Hugging Face", models: [] },
- litellm: { id: "litellm", label: "LiteLLM", models: [] },
- openrouter: { id: "openrouter", label: "OpenRouter", models: [] },
- requesty: { id: "requesty", label: "Requesty", models: [] },
- unbound: { id: "unbound", label: "Unbound", models: [] },
- }
- export const dynamicProviders = [
- "glama",
- "huggingface",
- "litellm",
- "openrouter",
- "requesty",
- "unbound",
- ] as const satisfies readonly ProviderName[]
- export type DynamicProvider = (typeof dynamicProviders)[number]
- export const isDynamicProvider = (key: string): key is DynamicProvider =>
- dynamicProviders.includes(key as DynamicProvider)
|