diff --git a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts index 0d58268d14..fd5950bf35 100644 --- a/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts +++ b/webview-ui/src/components/ui/hooks/__tests__/useSelectedModel.spec.ts @@ -369,4 +369,76 @@ describe("useSelectedModel", () => { expect(result.current.info).toBeUndefined() }) }) + + describe("claude-code provider", () => { + it("should return claude-code model with supportsImages disabled", () => { + mockUseRouterModels.mockReturnValue({ + data: { + openrouter: {}, + requesty: {}, + glama: {}, + unbound: {}, + litellm: {}, + }, + isLoading: false, + isError: false, + } as any) + + mockUseOpenRouterModelProviders.mockReturnValue({ + data: {}, + isLoading: false, + isError: false, + } as any) + + const apiConfiguration: ProviderSettings = { + apiProvider: "claude-code", + apiModelId: "claude-sonnet-4-20250514", + } + + const wrapper = createWrapper() + const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper }) + + expect(result.current.provider).toBe("claude-code") + expect(result.current.id).toBe("claude-sonnet-4-20250514") + expect(result.current.info).toBeDefined() + expect(result.current.info?.supportsImages).toBe(false) + expect(result.current.info?.supportsPromptCache).toBe(false) + // Verify it inherits other properties from anthropic models + expect(result.current.info?.maxTokens).toBe(64_000) + expect(result.current.info?.contextWindow).toBe(200_000) + expect(result.current.info?.supportsComputerUse).toBe(true) + }) + + it("should use default claude-code model when no modelId is specified", () => { + mockUseRouterModels.mockReturnValue({ + data: { + openrouter: {}, + requesty: {}, + glama: {}, + unbound: {}, + litellm: {}, + }, + isLoading: false, + isError: false, + } as any) + + mockUseOpenRouterModelProviders.mockReturnValue({ + data: {}, + isLoading: false, + isError: false, + } as any) + + const apiConfiguration: ProviderSettings = { + apiProvider: "claude-code", + } + + const wrapper = createWrapper() + const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper }) + + expect(result.current.provider).toBe("claude-code") + expect(result.current.id).toBe("claude-sonnet-4-20250514") // Default model + expect(result.current.info).toBeDefined() + expect(result.current.info?.supportsImages).toBe(false) + }) + }) }) diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index 09cae03e5d..40c1ff2431 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -30,6 +30,8 @@ import { glamaDefaultModelId, unboundDefaultModelId, litellmDefaultModelId, + claudeCodeDefaultModelId, + claudeCodeModels, } from "@roo-code/types" import type { RouterModels } from "@roo/api" @@ -199,6 +201,12 @@ function getSelectedModel({ const info = vscodeLlmModels[modelFamily as keyof typeof vscodeLlmModels] return { id, info: { ...openAiModelInfoSaneDefaults, ...info, supportsImages: false } } // VSCode LM API currently doesn't support images. } + case "claude-code": { + // Claude Code models extend anthropic models but with images and prompt caching disabled + const id = apiConfiguration.apiModelId ?? claudeCodeDefaultModelId + const info = claudeCodeModels[id as keyof typeof claudeCodeModels] + return { id, info: { ...openAiModelInfoSaneDefaults, ...info } } + } // case "anthropic": // case "human-relay": // case "fake-ai":