Explorar el Código

fix: resolve claude-code provider image hang (#5100) (#5105)

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Daniel <[email protected]>
Hannes Rudolph hace 6 meses
padre
commit
83c19ce2c8

+ 72 - 0
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)
+		})
+	})
 })

+ 8 - 0
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":