Skip to content

Commit fa764ba

Browse files
AlexKerroomote[bot]mrubens
authored
(feat): Add Baseten Provider (#9461)
Co-authored-by: roomote[bot] <219738659+roomote[bot]@users.noreply.github.com> Co-authored-by: AlexKer <[email protected]> Co-authored-by: Matt Rubens <[email protected]>
1 parent 7edc86b commit fa764ba

File tree

31 files changed

+273
-0
lines changed

31 files changed

+273
-0
lines changed

packages/types/src/global-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ export const SECRET_STATE_KEYS = [
246246
"featherlessApiKey",
247247
"ioIntelligenceApiKey",
248248
"vercelAiGatewayApiKey",
249+
"basetenApiKey",
249250
] as const
250251

251252
// Global secrets that are part of GlobalSettings (not ProviderSettings)

packages/types/src/provider-settings.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { modelInfoSchema, reasoningEffortSettingSchema, verbosityLevelsSchema, s
44
import { codebaseIndexProviderSchema } from "./codebase-index.js"
55
import {
66
anthropicModels,
7+
basetenModels,
78
bedrockModels,
89
cerebrasModels,
910
claudeCodeModels,
@@ -120,6 +121,7 @@ export const providerNames = [
120121
...fauxProviders,
121122
"anthropic",
122123
"bedrock",
124+
"baseten",
123125
"cerebras",
124126
"claude-code",
125127
"doubao",
@@ -424,6 +426,10 @@ const vercelAiGatewaySchema = baseProviderSettingsSchema.extend({
424426
vercelAiGatewayModelId: z.string().optional(),
425427
})
426428

429+
const basetenSchema = apiModelIdProviderModelSchema.extend({
430+
basetenApiKey: z.string().optional(),
431+
})
432+
427433
const defaultSchema = z.object({
428434
apiProvider: z.undefined(),
429435
})
@@ -454,6 +460,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
454460
fakeAiSchema.merge(z.object({ apiProvider: z.literal("fake-ai") })),
455461
xaiSchema.merge(z.object({ apiProvider: z.literal("xai") })),
456462
groqSchema.merge(z.object({ apiProvider: z.literal("groq") })),
463+
basetenSchema.merge(z.object({ apiProvider: z.literal("baseten") })),
457464
huggingFaceSchema.merge(z.object({ apiProvider: z.literal("huggingface") })),
458465
chutesSchema.merge(z.object({ apiProvider: z.literal("chutes") })),
459466
litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })),
@@ -496,6 +503,7 @@ export const providerSettingsSchema = z.object({
496503
...fakeAiSchema.shape,
497504
...xaiSchema.shape,
498505
...groqSchema.shape,
506+
...basetenSchema.shape,
499507
...huggingFaceSchema.shape,
500508
...chutesSchema.shape,
501509
...litellmSchema.shape,
@@ -583,6 +591,7 @@ export const modelIdKeysByProvider: Record<TypicalProvider, ModelIdKey> = {
583591
requesty: "requestyModelId",
584592
xai: "apiModelId",
585593
groq: "apiModelId",
594+
baseten: "apiModelId",
586595
chutes: "apiModelId",
587596
litellm: "litellmModelId",
588597
huggingface: "huggingFaceModelId",
@@ -715,6 +724,7 @@ export const MODELS_BY_PROVIDER: Record<
715724
},
716725
xai: { id: "xai", label: "xAI (Grok)", models: Object.keys(xaiModels) },
717726
zai: { id: "zai", label: "Zai", models: Object.keys(internationalZAiModels) },
727+
baseten: { id: "baseten", label: "BaseTen", models: Object.keys(basetenModels) },
718728

719729
// Dynamic providers; models pulled from remote APIs.
720730
glama: { id: "glama", label: "Glama", models: [] },
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import type { ModelInfo } from "../model.js"
2+
3+
// Baseten
4+
// https://baseten.co/products/model-apis/
5+
6+
export const basetenModels = {
7+
"moonshotai/Kimi-K2-Thinking": {
8+
maxTokens: 163_800,
9+
contextWindow: 262_000,
10+
supportsImages: false,
11+
supportsPromptCache: false,
12+
supportsNativeTools: true,
13+
defaultToolProtocol: "native",
14+
inputPrice: 0.6,
15+
outputPrice: 2.5,
16+
cacheWritesPrice: 0,
17+
cacheReadsPrice: 0,
18+
description: "Kimi K2 Thinking - A model with enhanced reasoning capabilities from Kimi K2",
19+
},
20+
"zai-org/GLM-4.6": {
21+
maxTokens: 200_000,
22+
contextWindow: 200_000,
23+
supportsImages: false,
24+
supportsPromptCache: false,
25+
supportsNativeTools: true,
26+
inputPrice: 0.6,
27+
outputPrice: 2.2,
28+
cacheWritesPrice: 0,
29+
cacheReadsPrice: 0,
30+
description: "Frontier open model with advanced agentic, reasoning and coding capabilities",
31+
},
32+
"deepseek-ai/DeepSeek-R1": {
33+
maxTokens: 131_072,
34+
contextWindow: 163_840,
35+
supportsImages: false,
36+
supportsPromptCache: false,
37+
inputPrice: 2.55,
38+
outputPrice: 5.95,
39+
cacheWritesPrice: 0,
40+
cacheReadsPrice: 0,
41+
description: "DeepSeek's first-generation reasoning model",
42+
},
43+
"deepseek-ai/DeepSeek-R1-0528": {
44+
maxTokens: 131_072,
45+
contextWindow: 163_840,
46+
supportsImages: false,
47+
supportsPromptCache: false,
48+
inputPrice: 2.55,
49+
outputPrice: 5.95,
50+
cacheWritesPrice: 0,
51+
cacheReadsPrice: 0,
52+
description: "The latest revision of DeepSeek's first-generation reasoning model",
53+
},
54+
"deepseek-ai/DeepSeek-V3-0324": {
55+
maxTokens: 131_072,
56+
contextWindow: 163_840,
57+
supportsImages: false,
58+
supportsPromptCache: false,
59+
inputPrice: 0.77,
60+
outputPrice: 0.77,
61+
cacheWritesPrice: 0,
62+
cacheReadsPrice: 0,
63+
description: "Fast general-purpose LLM with enhanced reasoning capabilities",
64+
},
65+
"deepseek-ai/DeepSeek-V3.1": {
66+
maxTokens: 131_072,
67+
contextWindow: 163_840,
68+
supportsImages: false,
69+
supportsPromptCache: false,
70+
inputPrice: 0.5,
71+
outputPrice: 1.5,
72+
cacheWritesPrice: 0,
73+
cacheReadsPrice: 0,
74+
description:
75+
"Extremely capable general-purpose LLM with hybrid reasoning capabilities and advanced tool calling",
76+
},
77+
"Qwen/Qwen3-235B-A22B-Instruct-2507": {
78+
maxTokens: 262_144,
79+
contextWindow: 262_144,
80+
supportsImages: false,
81+
supportsPromptCache: false,
82+
inputPrice: 0.22,
83+
outputPrice: 0.8,
84+
cacheWritesPrice: 0,
85+
cacheReadsPrice: 0,
86+
description: "Mixture-of-experts LLM with math and reasoning capabilities",
87+
},
88+
"Qwen/Qwen3-Coder-480B-A35B-Instruct": {
89+
maxTokens: 262_144,
90+
contextWindow: 262_144,
91+
supportsImages: false,
92+
supportsPromptCache: false,
93+
inputPrice: 0.38,
94+
outputPrice: 1.53,
95+
cacheWritesPrice: 0,
96+
cacheReadsPrice: 0,
97+
description: "Mixture-of-experts LLM with advanced coding and reasoning capabilities",
98+
},
99+
"openai/gpt-oss-120b": {
100+
maxTokens: 128_072,
101+
contextWindow: 128_072,
102+
supportsImages: false,
103+
supportsPromptCache: false,
104+
supportsNativeTools: true,
105+
inputPrice: 0.1,
106+
outputPrice: 0.5,
107+
cacheWritesPrice: 0,
108+
cacheReadsPrice: 0,
109+
description: "Extremely capable general-purpose LLM with strong, controllable reasoning capabilities",
110+
},
111+
"moonshotai/Kimi-K2-Instruct-0905": {
112+
maxTokens: 168_000,
113+
contextWindow: 262_000,
114+
supportsImages: false,
115+
supportsPromptCache: false,
116+
supportsNativeTools: true,
117+
inputPrice: 0.6,
118+
outputPrice: 2.5,
119+
cacheWritesPrice: 0,
120+
cacheReadsPrice: 0,
121+
description: "State of the art language model for agentic and coding tasks. September Update.",
122+
},
123+
} as const satisfies Record<string, ModelInfo>
124+
125+
export type BasetenModelId = keyof typeof basetenModels
126+
127+
export const basetenDefaultModelId = "moonshotai/Kimi-K2-Thinking" satisfies BasetenModelId

packages/types/src/providers/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./anthropic.js"
2+
export * from "./baseten.js"
23
export * from "./bedrock.js"
34
export * from "./cerebras.js"
45
export * from "./chutes.js"
@@ -33,6 +34,7 @@ export * from "./deepinfra.js"
3334
export * from "./minimax.js"
3435

3536
import { anthropicDefaultModelId } from "./anthropic.js"
37+
import { basetenDefaultModelId } from "./baseten.js"
3638
import { bedrockDefaultModelId } from "./bedrock.js"
3739
import { cerebrasDefaultModelId } from "./cerebras.js"
3840
import { chutesDefaultModelId } from "./chutes.js"
@@ -93,6 +95,8 @@ export function getProviderDefaultModelId(
9395
return "meta-llama/Llama-3.3-70B-Instruct"
9496
case "chutes":
9597
return chutesDefaultModelId
98+
case "baseten":
99+
return basetenDefaultModelId
96100
case "bedrock":
97101
return bedrockDefaultModelId
98102
case "vertex":

src/api/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
VercelAiGatewayHandler,
4343
DeepInfraHandler,
4444
MiniMaxHandler,
45+
BasetenHandler,
4546
} from "./providers"
4647
import { NativeOllamaHandler } from "./providers/native-ollama"
4748

@@ -190,6 +191,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
190191
return new VercelAiGatewayHandler(options)
191192
case "minimax":
192193
return new MiniMaxHandler(options)
194+
case "baseten":
195+
return new BasetenHandler(options)
193196
default:
194197
apiProvider satisfies "gemini-cli" | undefined
195198
return new AnthropicHandler(options)

src/api/providers/baseten.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { type BasetenModelId, basetenDefaultModelId, basetenModels } from "@roo-code/types"
2+
3+
import type { ApiHandlerOptions } from "../../shared/api"
4+
import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
5+
6+
export class BasetenHandler extends BaseOpenAiCompatibleProvider<BasetenModelId> {
7+
constructor(options: ApiHandlerOptions) {
8+
super({
9+
...options,
10+
providerName: "Baseten",
11+
baseURL: "https://inference.baseten.co/v1",
12+
apiKey: options.basetenApiKey,
13+
defaultProviderModelId: basetenDefaultModelId,
14+
providerModels: basetenModels,
15+
defaultTemperature: 0.5,
16+
})
17+
}
18+
}

src/api/providers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ export { FeatherlessHandler } from "./featherless"
3535
export { VercelAiGatewayHandler } from "./vercel-ai-gateway"
3636
export { DeepInfraHandler } from "./deepinfra"
3737
export { MiniMaxHandler } from "./minimax"
38+
export { BasetenHandler } from "./baseten"

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
groqDefaultModelId,
2727
cerebrasDefaultModelId,
2828
chutesDefaultModelId,
29+
basetenDefaultModelId,
2930
bedrockDefaultModelId,
3031
vertexDefaultModelId,
3132
sambaNovaDefaultModelId,
@@ -67,6 +68,7 @@ import {
6768

6869
import {
6970
Anthropic,
71+
Baseten,
7072
Bedrock,
7173
Cerebras,
7274
Chutes,
@@ -274,6 +276,7 @@ const ApiOptions = ({
274276

275277
const selectedProviderModels = useMemo(() => {
276278
const models = MODELS_BY_PROVIDER[selectedProvider]
279+
277280
if (!models) return []
278281

279282
const filteredModels = filterModels(models, selectedProvider, organizationAllowList)
@@ -355,6 +358,7 @@ const ApiOptions = ({
355358
xai: { field: "apiModelId", default: xaiDefaultModelId },
356359
groq: { field: "apiModelId", default: groqDefaultModelId },
357360
chutes: { field: "apiModelId", default: chutesDefaultModelId },
361+
baseten: { field: "apiModelId", default: basetenDefaultModelId },
358362
bedrock: { field: "apiModelId", default: bedrockDefaultModelId },
359363
vertex: { field: "apiModelId", default: vertexDefaultModelId },
360364
sambanova: { field: "apiModelId", default: sambaNovaDefaultModelId },
@@ -564,6 +568,10 @@ const ApiOptions = ({
564568
<Mistral apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
565569
)}
566570

571+
{selectedProvider === "baseten" && (
572+
<Baseten apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
573+
)}
574+
567575
{selectedProvider === "bedrock" && (
568576
<Bedrock
569577
apiConfiguration={apiConfiguration}

webview-ui/src/components/settings/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
fireworksModels,
2121
featherlessModels,
2222
minimaxModels,
23+
basetenModels,
2324
} from "@roo-code/types"
2425

2526
export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, ModelInfo>>> = {
@@ -42,6 +43,7 @@ export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, Mod
4243
fireworks: fireworksModels,
4344
featherless: featherlessModels,
4445
minimax: minimaxModels,
46+
baseten: basetenModels,
4547
}
4648

4749
export const PROVIDERS = [
@@ -80,4 +82,5 @@ export const PROVIDERS = [
8082
{ value: "roo", label: "Roo Code Cloud" },
8183
{ value: "vercel-ai-gateway", label: "Vercel AI Gateway" },
8284
{ value: "minimax", label: "MiniMax" },
85+
{ value: "baseten", label: "Baseten" },
8386
].sort((a, b) => a.label.localeCompare(b.label))
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useCallback } from "react"
2+
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
3+
4+
import type { ProviderSettings } from "@roo-code/types"
5+
6+
import { useAppTranslation } from "@src/i18n/TranslationContext"
7+
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
8+
9+
import { inputEventTransform } from "../transforms"
10+
11+
type BasetenProps = {
12+
apiConfiguration: ProviderSettings
13+
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
14+
}
15+
16+
export const Baseten = ({ apiConfiguration, setApiConfigurationField }: BasetenProps) => {
17+
const { t } = useAppTranslation()
18+
19+
const handleInputChange = useCallback(
20+
<K extends keyof ProviderSettings, E>(
21+
field: K,
22+
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
23+
) =>
24+
(event: E | Event) => {
25+
setApiConfigurationField(field, transform(event as E))
26+
},
27+
[setApiConfigurationField],
28+
)
29+
30+
return (
31+
<>
32+
<VSCodeTextField
33+
value={apiConfiguration?.basetenApiKey || ""}
34+
type="password"
35+
onInput={handleInputChange("basetenApiKey")}
36+
placeholder={t("settings:placeholders.apiKey")}
37+
className="w-full">
38+
<label className="block font-medium mb-1">{t("settings:providers.basetenApiKey")}</label>
39+
</VSCodeTextField>
40+
<div className="text-sm text-vscode-descriptionForeground -mt-2">
41+
{t("settings:providers.apiKeyStorageNotice")}
42+
</div>
43+
{!apiConfiguration?.basetenApiKey && (
44+
<VSCodeButtonLink href="https://app.baseten.co/settings/api_keys" appearance="secondary">
45+
{t("settings:providers.getBasetenApiKey")}
46+
</VSCodeButtonLink>
47+
)}
48+
</>
49+
)
50+
}

0 commit comments

Comments
 (0)