Skip to content
Draft
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
2 changes: 1 addition & 1 deletion webview-ui/src/components/settings/ModelInfoView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const ModelInfoView = ({
supportsLabel={t("settings:modelInfo.supportsPromptCache")}
doesNotSupportLabel={t("settings:modelInfo.noPromptCache")}
/>,
apiProvider === "gemini" && (
apiProvider === providerIdentifiers.gemini && (
<span className="italic">
{selectedModelId.includes("pro-preview")
? t("settings:modelInfo.gemini.billingEstimate")
Expand Down
10 changes: 8 additions & 2 deletions webview-ui/src/components/settings/ModelPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import { Trans } from "react-i18next"
import { ChevronsUpDown, Check, X, Info } from "lucide-react"

import { type ProviderSettings, type ModelInfo, type OrganizationAllowList, isRetiredProvider } from "@roo-code/types"
import {
type ProviderSettings,
type ModelInfo,
type OrganizationAllowList,
isRetiredProvider,
providerIdentifiers,
} from "@roo-code/types"

import { useAppTranslation } from "@src/i18n/TranslationContext"
import { useSelectedModel } from "@/components/ui/hooks/useSelectedModel"
Expand Down Expand Up @@ -305,7 +311,7 @@ export const ModelPicker = ({
hidePricing={hidePricing}
/>
)}
{!hidePricing && apiConfiguration.apiProvider !== "mimo" && (
{!hidePricing && apiConfiguration.apiProvider !== providerIdentifiers.mimo && (
<div className="text-sm text-vscode-descriptionForeground" data-testid="automatic-fetch-hint">
<Trans
i18nKey="settings:modelPicker.automaticFetch"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ const getPricingRowValues = (tier: string) => {
}

describe("ModelInfoView service tier pricing", () => {
it("shows Gemini billing guidance for the canonical Gemini provider", () => {
render(
<ModelInfoView
{...defaultProps}
apiProvider={providerIdentifiers.gemini}
selectedModelId="gemini-3-pro-preview"
modelInfo={baseModelInfo}
/>,
)

expect(screen.getByText("settings:modelInfo.gemini.billingEstimate")).toBeInTheDocument()
})

it("shows OpenAI Native tier prices with per-field fallback to Standard pricing", () => {
const modelInfo: ModelInfo = {
...baseModelInfo,
Expand Down
103 changes: 52 additions & 51 deletions webview-ui/src/components/settings/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
type ProviderName,
type ModelInfo,
providerIdentifiers,
anthropicModels,
bedrockModels,
deepSeekModels,
Expand All @@ -22,57 +23,57 @@ import {
} from "@roo-code/types"

export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, ModelInfo>>> = {
anthropic: anthropicModels,
bedrock: bedrockModels,
deepseek: deepSeekModels,
moonshot: moonshotModels,
gemini: geminiModels,
mistral: mistralModels,
"openai-native": openAiNativeModels,
"openai-codex": openAiCodexModels,
"qwen-code": qwenCodeModels,
vertex: vertexModels,
xai: xaiModels,
sambanova: sambaNovaModels,
zai: internationalZAiModels,
fireworks: fireworksModels,
friendli: friendliModels,
minimax: minimaxModels,
mimo: mimoModels,
baseten: basetenModels,
[providerIdentifiers.anthropic]: anthropicModels,
[providerIdentifiers.bedrock]: bedrockModels,
[providerIdentifiers.deepseek]: deepSeekModels,
[providerIdentifiers.moonshot]: moonshotModels,
[providerIdentifiers.gemini]: geminiModels,
[providerIdentifiers.mistral]: mistralModels,
[providerIdentifiers.openaiNative]: openAiNativeModels,
[providerIdentifiers.openaiCodex]: openAiCodexModels,
[providerIdentifiers.qwenCode]: qwenCodeModels,
[providerIdentifiers.vertex]: vertexModels,
[providerIdentifiers.xai]: xaiModels,
[providerIdentifiers.sambanova]: sambaNovaModels,
[providerIdentifiers.zai]: internationalZAiModels,
[providerIdentifiers.fireworks]: fireworksModels,
[providerIdentifiers.friendli]: friendliModels,
[providerIdentifiers.minimax]: minimaxModels,
[providerIdentifiers.mimo]: mimoModels,
[providerIdentifiers.baseten]: basetenModels,
}

export const PROVIDERS = [
{ value: "openrouter", label: "OpenRouter", proxy: false },
{ value: "anthropic", label: "Anthropic", proxy: false },
{ value: "gemini", label: "Google Gemini", proxy: false },
{ value: "deepseek", label: "DeepSeek", proxy: false },
{ value: "moonshot", label: "Moonshot", proxy: false },
{ value: "kimi-code", label: "Kimi Code", proxy: false },
{ value: "openai-native", label: "OpenAI", proxy: false },
{ value: "openai-codex", label: "OpenAI - ChatGPT Plus/Pro", proxy: false },
{ value: "openai", label: "OpenAI Compatible", proxy: true },
{ value: "qwen-code", label: "Qwen Code", proxy: false },
{ value: "vertex", label: "GCP Vertex AI", proxy: false },
{ value: "bedrock", label: "Amazon Bedrock", proxy: false },
{ value: "vscode-lm", label: "VS Code LM API", proxy: false },
{ value: "mistral", label: "Mistral", proxy: false },
{ value: "lmstudio", label: "LM Studio", proxy: true },
{ value: "ollama", label: "Ollama", proxy: true },
{ value: "requesty", label: "Requesty", proxy: false },
{ value: "xai", label: "xAI (Grok)", proxy: false },
{ value: "litellm", label: "LiteLLM", proxy: true },
{ value: "sambanova", label: "SambaNova", proxy: false },
{ value: "zai", label: "Z.ai", proxy: false },
{ value: "fireworks", label: "Fireworks AI", proxy: false },
{ value: "friendli", label: "Friendli", proxy: false },
{ value: "vercel-ai-gateway", label: "Vercel AI Gateway", proxy: false },
{ value: "opencode-go", label: "Opencode Go", proxy: false },
{ value: "kenari", label: "Kenari", proxy: false },
{ value: "zoo-gateway", label: "Zoo Gateway", proxy: false },
{ value: "minimax", label: "MiniMax", proxy: false },
{ value: "mimo", label: "Xiaomi MiMo", proxy: false },
{ value: "baseten", label: "Baseten", proxy: false },
{ value: "unbound", label: "Unbound", proxy: false },
{ value: "poe", label: "Poe", proxy: false },
export const PROVIDERS: Array<{ value: string; label: string; proxy: boolean }> = [
{ value: providerIdentifiers.openrouter, label: "OpenRouter", proxy: false },
{ value: providerIdentifiers.anthropic, label: "Anthropic", proxy: false },
{ value: providerIdentifiers.gemini, label: "Google Gemini", proxy: false },
{ value: providerIdentifiers.deepseek, label: "DeepSeek", proxy: false },
{ value: providerIdentifiers.moonshot, label: "Moonshot", proxy: false },
{ value: providerIdentifiers.kimiCode, label: "Kimi Code", proxy: false },
{ value: providerIdentifiers.openaiNative, label: "OpenAI", proxy: false },
{ value: providerIdentifiers.openaiCodex, label: "OpenAI - ChatGPT Plus/Pro", proxy: false },
{ value: providerIdentifiers.openai, label: "OpenAI Compatible", proxy: true },
{ value: providerIdentifiers.qwenCode, label: "Qwen Code", proxy: false },
{ value: providerIdentifiers.vertex, label: "GCP Vertex AI", proxy: false },
{ value: providerIdentifiers.bedrock, label: "Amazon Bedrock", proxy: false },
{ value: providerIdentifiers.vscodeLm, label: "VS Code LM API", proxy: false },
{ value: providerIdentifiers.mistral, label: "Mistral", proxy: false },
{ value: providerIdentifiers.lmstudio, label: "LM Studio", proxy: true },
{ value: providerIdentifiers.ollama, label: "Ollama", proxy: true },
{ value: providerIdentifiers.requesty, label: "Requesty", proxy: false },
{ value: providerIdentifiers.xai, label: "xAI (Grok)", proxy: false },
{ value: providerIdentifiers.litellm, label: "LiteLLM", proxy: true },
{ value: providerIdentifiers.sambanova, label: "SambaNova", proxy: false },
{ value: providerIdentifiers.zai, label: "Z.ai", proxy: false },
{ value: providerIdentifiers.fireworks, label: "Fireworks AI", proxy: false },
{ value: providerIdentifiers.friendli, label: "Friendli", proxy: false },
{ value: providerIdentifiers.vercelAiGateway, label: "Vercel AI Gateway", proxy: false },
{ value: providerIdentifiers.opencodeGo, label: "Opencode Go", proxy: false },
{ value: providerIdentifiers.kenari, label: "Kenari", proxy: false },
{ value: providerIdentifiers.zooGateway, label: "Zoo Gateway", proxy: false },
{ value: providerIdentifiers.minimax, label: "MiniMax", proxy: false },
{ value: providerIdentifiers.mimo, label: "Xiaomi MiMo", proxy: false },
{ value: providerIdentifiers.baseten, label: "Baseten", proxy: false },
{ value: providerIdentifiers.unbound, label: "Unbound", proxy: false },
{ value: providerIdentifiers.poe, label: "Poe", proxy: false },
].sort((a, b) => a.label.localeCompare(b.label))
Loading