Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export const SECRET_STATE_KEYS = [
"featherlessApiKey",
"ioIntelligenceApiKey",
"vercelAiGatewayApiKey",
"basetenApiKey",
] as const

// Global secrets that are part of GlobalSettings (not ProviderSettings)
Expand Down
10 changes: 10 additions & 0 deletions packages/types/src/provider-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { modelInfoSchema, reasoningEffortSettingSchema, verbosityLevelsSchema, s
import { codebaseIndexProviderSchema } from "./codebase-index.js"
import {
anthropicModels,
basetenModels,
bedrockModels,
cerebrasModels,
claudeCodeModels,
Expand Down Expand Up @@ -120,6 +121,7 @@ export const providerNames = [
...fauxProviders,
"anthropic",
"bedrock",
"baseten",
"cerebras",
"claude-code",
"doubao",
Expand Down Expand Up @@ -424,6 +426,10 @@ const vercelAiGatewaySchema = baseProviderSettingsSchema.extend({
vercelAiGatewayModelId: z.string().optional(),
})

const basetenSchema = apiModelIdProviderModelSchema.extend({
basetenApiKey: z.string().optional(),
})

const defaultSchema = z.object({
apiProvider: z.undefined(),
})
Expand Down Expand Up @@ -454,6 +460,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
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") })),
basetenSchema.merge(z.object({ apiProvider: z.literal("baseten") })),
huggingFaceSchema.merge(z.object({ apiProvider: z.literal("huggingface") })),
chutesSchema.merge(z.object({ apiProvider: z.literal("chutes") })),
litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })),
Expand Down Expand Up @@ -496,6 +503,7 @@ export const providerSettingsSchema = z.object({
...fakeAiSchema.shape,
...xaiSchema.shape,
...groqSchema.shape,
...basetenSchema.shape,
...huggingFaceSchema.shape,
...chutesSchema.shape,
...litellmSchema.shape,
Expand Down Expand Up @@ -583,6 +591,7 @@ export const modelIdKeysByProvider: Record<TypicalProvider, ModelIdKey> = {
requesty: "requestyModelId",
xai: "apiModelId",
groq: "apiModelId",
baseten: "apiModelId",
chutes: "apiModelId",
litellm: "litellmModelId",
huggingface: "huggingFaceModelId",
Expand Down Expand Up @@ -715,6 +724,7 @@ export const MODELS_BY_PROVIDER: Record<
},
xai: { id: "xai", label: "xAI (Grok)", models: Object.keys(xaiModels) },
zai: { id: "zai", label: "Zai", models: Object.keys(internationalZAiModels) },
baseten: { id: "baseten", label: "BaseTen", models: Object.keys(basetenModels) },

// Dynamic providers; models pulled from remote APIs.
glama: { id: "glama", label: "Glama", models: [] },
Expand Down
127 changes: 127 additions & 0 deletions packages/types/src/providers/baseten.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import type { ModelInfo } from "../model.js"

// Baseten
// https://baseten.co/products/model-apis/

export const basetenModels = {
"moonshotai/Kimi-K2-Thinking": {
maxTokens: 163_800,
contextWindow: 262_000,
supportsImages: false,
supportsPromptCache: false,
supportsNativeTools: true,
defaultToolProtocol: "native",
inputPrice: 0.6,
outputPrice: 2.5,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Kimi K2 Thinking - A model with enhanced reasoning capabilities from Kimi K2",
},
"zai-org/GLM-4.6": {
maxTokens: 200_000,
contextWindow: 200_000,
supportsImages: false,
supportsPromptCache: false,
supportsNativeTools: true,
inputPrice: 0.6,
outputPrice: 2.2,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Frontier open model with advanced agentic, reasoning and coding capabilities",
},
"deepseek-ai/DeepSeek-R1": {
maxTokens: 131_072,
contextWindow: 163_840,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 2.55,
outputPrice: 5.95,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "DeepSeek's first-generation reasoning model",
},
"deepseek-ai/DeepSeek-R1-0528": {
maxTokens: 131_072,
contextWindow: 163_840,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 2.55,
outputPrice: 5.95,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "The latest revision of DeepSeek's first-generation reasoning model",
},
"deepseek-ai/DeepSeek-V3-0324": {
maxTokens: 131_072,
contextWindow: 163_840,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0.77,
outputPrice: 0.77,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Fast general-purpose LLM with enhanced reasoning capabilities",
},
"deepseek-ai/DeepSeek-V3.1": {
maxTokens: 131_072,
contextWindow: 163_840,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0.5,
outputPrice: 1.5,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description:
"Extremely capable general-purpose LLM with hybrid reasoning capabilities and advanced tool calling",
},
"Qwen/Qwen3-235B-A22B-Instruct-2507": {
maxTokens: 262_144,
contextWindow: 262_144,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0.22,
outputPrice: 0.8,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Mixture-of-experts LLM with math and reasoning capabilities",
},
"Qwen/Qwen3-Coder-480B-A35B-Instruct": {
maxTokens: 262_144,
contextWindow: 262_144,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0.38,
outputPrice: 1.53,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Mixture-of-experts LLM with advanced coding and reasoning capabilities",
},
"openai/gpt-oss-120b": {
maxTokens: 128_072,
contextWindow: 128_072,
supportsImages: false,
supportsPromptCache: false,
supportsNativeTools: true,
inputPrice: 0.1,
outputPrice: 0.5,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "Extremely capable general-purpose LLM with strong, controllable reasoning capabilities",
},
"moonshotai/Kimi-K2-Instruct-0905": {
maxTokens: 168_000,
contextWindow: 262_000,
supportsImages: false,
supportsPromptCache: false,
supportsNativeTools: true,
inputPrice: 0.6,
outputPrice: 2.5,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "State of the art language model for agentic and coding tasks. September Update.",
},
} as const satisfies Record<string, ModelInfo>

export type BasetenModelId = keyof typeof basetenModels

export const basetenDefaultModelId = "moonshotai/Kimi-K2-Thinking" satisfies BasetenModelId
4 changes: 4 additions & 0 deletions packages/types/src/providers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./anthropic.js"
export * from "./baseten.js"
export * from "./bedrock.js"
export * from "./cerebras.js"
export * from "./chutes.js"
Expand Down Expand Up @@ -33,6 +34,7 @@ export * from "./deepinfra.js"
export * from "./minimax.js"

import { anthropicDefaultModelId } from "./anthropic.js"
import { basetenDefaultModelId } from "./baseten.js"
import { bedrockDefaultModelId } from "./bedrock.js"
import { cerebrasDefaultModelId } from "./cerebras.js"
import { chutesDefaultModelId } from "./chutes.js"
Expand Down Expand Up @@ -93,6 +95,8 @@ export function getProviderDefaultModelId(
return "meta-llama/Llama-3.3-70B-Instruct"
case "chutes":
return chutesDefaultModelId
case "baseten":
return basetenDefaultModelId
case "bedrock":
return bedrockDefaultModelId
case "vertex":
Expand Down
3 changes: 3 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
VercelAiGatewayHandler,
DeepInfraHandler,
MiniMaxHandler,
BasetenHandler,
} from "./providers"
import { NativeOllamaHandler } from "./providers/native-ollama"

Expand Down Expand Up @@ -190,6 +191,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
return new VercelAiGatewayHandler(options)
case "minimax":
return new MiniMaxHandler(options)
case "baseten":
return new BasetenHandler(options)
default:
apiProvider satisfies "gemini-cli" | undefined
return new AnthropicHandler(options)
Expand Down
18 changes: 18 additions & 0 deletions src/api/providers/baseten.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type BasetenModelId, basetenDefaultModelId, basetenModels } from "@roo-code/types"

import type { ApiHandlerOptions } from "../../shared/api"
import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"

export class BasetenHandler extends BaseOpenAiCompatibleProvider<BasetenModelId> {
constructor(options: ApiHandlerOptions) {
super({
...options,
providerName: "Baseten",
baseURL: "https://inference.baseten.co/v1",
apiKey: options.basetenApiKey,
defaultProviderModelId: basetenDefaultModelId,
providerModels: basetenModels,
defaultTemperature: 0.5,
})
}
}
1 change: 1 addition & 0 deletions src/api/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ export { FeatherlessHandler } from "./featherless"
export { VercelAiGatewayHandler } from "./vercel-ai-gateway"
export { DeepInfraHandler } from "./deepinfra"
export { MiniMaxHandler } from "./minimax"
export { BasetenHandler } from "./baseten"
8 changes: 8 additions & 0 deletions webview-ui/src/components/settings/ApiOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
groqDefaultModelId,
cerebrasDefaultModelId,
chutesDefaultModelId,
basetenDefaultModelId,
bedrockDefaultModelId,
vertexDefaultModelId,
sambaNovaDefaultModelId,
Expand Down Expand Up @@ -67,6 +68,7 @@ import {

import {
Anthropic,
Baseten,
Bedrock,
Cerebras,
Chutes,
Expand Down Expand Up @@ -274,6 +276,7 @@ const ApiOptions = ({

const selectedProviderModels = useMemo(() => {
const models = MODELS_BY_PROVIDER[selectedProvider]

if (!models) return []

const filteredModels = filterModels(models, selectedProvider, organizationAllowList)
Expand Down Expand Up @@ -355,6 +358,7 @@ const ApiOptions = ({
xai: { field: "apiModelId", default: xaiDefaultModelId },
groq: { field: "apiModelId", default: groqDefaultModelId },
chutes: { field: "apiModelId", default: chutesDefaultModelId },
baseten: { field: "apiModelId", default: basetenDefaultModelId },
bedrock: { field: "apiModelId", default: bedrockDefaultModelId },
vertex: { field: "apiModelId", default: vertexDefaultModelId },
sambanova: { field: "apiModelId", default: sambaNovaDefaultModelId },
Expand Down Expand Up @@ -564,6 +568,10 @@ const ApiOptions = ({
<Mistral apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
)}

{selectedProvider === "baseten" && (
<Baseten apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
)}

{selectedProvider === "bedrock" && (
<Bedrock
apiConfiguration={apiConfiguration}
Expand Down
3 changes: 3 additions & 0 deletions webview-ui/src/components/settings/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
fireworksModels,
featherlessModels,
minimaxModels,
basetenModels,
} from "@roo-code/types"

export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, ModelInfo>>> = {
Expand All @@ -42,6 +43,7 @@ export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, Mod
fireworks: fireworksModels,
featherless: featherlessModels,
minimax: minimaxModels,
baseten: basetenModels,
}

export const PROVIDERS = [
Expand Down Expand Up @@ -80,4 +82,5 @@ export const PROVIDERS = [
{ value: "roo", label: "Roo Code Cloud" },
{ value: "vercel-ai-gateway", label: "Vercel AI Gateway" },
{ value: "minimax", label: "MiniMax" },
{ value: "baseten", label: "Baseten" },
].sort((a, b) => a.label.localeCompare(b.label))
50 changes: 50 additions & 0 deletions webview-ui/src/components/settings/providers/Baseten.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useCallback } from "react"
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"

import type { ProviderSettings } from "@roo-code/types"

import { useAppTranslation } from "@src/i18n/TranslationContext"
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"

import { inputEventTransform } from "../transforms"

type BasetenProps = {
apiConfiguration: ProviderSettings
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
}

export const Baseten = ({ apiConfiguration, setApiConfigurationField }: BasetenProps) => {
const { t } = useAppTranslation()

const handleInputChange = useCallback(
<K extends keyof ProviderSettings, E>(
field: K,
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
) =>
(event: E | Event) => {
setApiConfigurationField(field, transform(event as E))
},
[setApiConfigurationField],
)

return (
<>
<VSCodeTextField
value={apiConfiguration?.basetenApiKey || ""}
type="password"
onInput={handleInputChange("basetenApiKey")}
placeholder={t("settings:placeholders.apiKey")}
className="w-full">
<label className="block font-medium mb-1">{t("settings:providers.basetenApiKey")}</label>
</VSCodeTextField>
<div className="text-sm text-vscode-descriptionForeground -mt-2">
{t("settings:providers.apiKeyStorageNotice")}
</div>
{!apiConfiguration?.basetenApiKey && (
<VSCodeButtonLink href="https://app.baseten.co/settings/api_keys" appearance="secondary">
{t("settings:providers.getBasetenApiKey")}
</VSCodeButtonLink>
)}
</>
)
}
1 change: 1 addition & 0 deletions webview-ui/src/components/settings/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ export { Featherless } from "./Featherless"
export { VercelAiGateway } from "./VercelAiGateway"
export { DeepInfra } from "./DeepInfra"
export { MiniMax } from "./MiniMax"
export { Baseten } from "./Baseten"
6 changes: 6 additions & 0 deletions webview-ui/src/components/ui/hooks/useSelectedModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
fireworksModels,
featherlessModels,
ioIntelligenceModels,
basetenModels,
qwenCodeModels,
BEDROCK_1M_CONTEXT_MODEL_IDS,
isDynamicProvider,
Expand Down Expand Up @@ -196,6 +197,11 @@ function getSelectedModel({
const info = routerModels.chutes?.[id]
return { id, info }
}
case "baseten": {
const id = apiConfiguration.apiModelId ?? defaultModelId
const info = basetenModels[id as keyof typeof basetenModels]
return { id, info }
}
case "bedrock": {
const id = apiConfiguration.apiModelId ?? defaultModelId
const baseInfo = bedrockModels[id as keyof typeof bedrockModels]
Expand Down
Loading
Loading