From 16620b544a1e536025510e330ba55107d78c2a06 Mon Sep 17 00:00:00 2001 From: sasidhar Date: Tue, 15 Jul 2025 14:17:13 +0530 Subject: [PATCH 1/6] Add Vertex AI model name conversion support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add convertModelNameForVertex function to convert hyphen-date format to @date format - Add getClaudeCodeModelId helper function with useVertex parameter - Add comprehensive tests for both utility functions - Enables proper model name formatting when CLAUDE_CODE_USE_VERTEX is true 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../providers/__tests__/claude-code.spec.ts | 41 +++++++++++++++++++ packages/types/src/providers/claude-code.ts | 11 +++++ 2 files changed, 52 insertions(+) create mode 100644 packages/types/src/providers/__tests__/claude-code.spec.ts diff --git a/packages/types/src/providers/__tests__/claude-code.spec.ts b/packages/types/src/providers/__tests__/claude-code.spec.ts new file mode 100644 index 00000000000..a98805412b9 --- /dev/null +++ b/packages/types/src/providers/__tests__/claude-code.spec.ts @@ -0,0 +1,41 @@ +import { describe, test, expect } from "vitest" +import { convertModelNameForVertex, getClaudeCodeModelId } from "../claude-code" + +describe("convertModelNameForVertex", () => { + test("should convert hyphen-date format to @date format", () => { + expect(convertModelNameForVertex("claude-sonnet-4-20250514")).toBe("claude-sonnet-4@20250514") + expect(convertModelNameForVertex("claude-opus-4-20250514")).toBe("claude-opus-4@20250514") + expect(convertModelNameForVertex("claude-3-7-sonnet-20250219")).toBe("claude-3-7-sonnet@20250219") + expect(convertModelNameForVertex("claude-3-5-sonnet-20241022")).toBe("claude-3-5-sonnet@20241022") + expect(convertModelNameForVertex("claude-3-5-haiku-20241022")).toBe("claude-3-5-haiku@20241022") + }) + + test("should not modify models without date pattern", () => { + expect(convertModelNameForVertex("some-other-model")).toBe("some-other-model") + expect(convertModelNameForVertex("claude-model")).toBe("claude-model") + expect(convertModelNameForVertex("model-with-short-date-123")).toBe("model-with-short-date-123") + }) + + test("should only convert 8-digit date patterns at the end", () => { + expect(convertModelNameForVertex("claude-20250514-sonnet")).toBe("claude-20250514-sonnet") + expect(convertModelNameForVertex("model-20250514-with-more")).toBe("model-20250514-with-more") + }) +}) + +describe("getClaudeCodeModelId", () => { + test("should return original model when useVertex is false", () => { + expect(getClaudeCodeModelId("claude-sonnet-4-20250514", false)).toBe("claude-sonnet-4-20250514") + expect(getClaudeCodeModelId("claude-opus-4-20250514", false)).toBe("claude-opus-4-20250514") + expect(getClaudeCodeModelId("claude-3-7-sonnet-20250219", false)).toBe("claude-3-7-sonnet-20250219") + }) + + test("should return converted model when useVertex is true", () => { + expect(getClaudeCodeModelId("claude-sonnet-4-20250514", true)).toBe("claude-sonnet-4@20250514") + expect(getClaudeCodeModelId("claude-opus-4-20250514", true)).toBe("claude-opus-4@20250514") + expect(getClaudeCodeModelId("claude-3-7-sonnet-20250219", true)).toBe("claude-3-7-sonnet@20250219") + }) + + test("should default to useVertex false when parameter not provided", () => { + expect(getClaudeCodeModelId("claude-sonnet-4-20250514")).toBe("claude-sonnet-4-20250514") + }) +}) \ No newline at end of file diff --git a/packages/types/src/providers/claude-code.ts b/packages/types/src/providers/claude-code.ts index b623d943f85..5012041980a 100644 --- a/packages/types/src/providers/claude-code.ts +++ b/packages/types/src/providers/claude-code.ts @@ -1,10 +1,21 @@ import type { ModelInfo } from "../model.js" import { anthropicModels } from "./anthropic.js" +// Utility function to convert model names for Vertex AI format +export function convertModelNameForVertex(modelName: string): string { + // Convert hyphen-date format to @date format for Vertex AI + return modelName.replace(/-(\d{8})$/, "@$1") +} + // Claude Code export type ClaudeCodeModelId = keyof typeof claudeCodeModels export const claudeCodeDefaultModelId: ClaudeCodeModelId = "claude-sonnet-4-20250514" export const CLAUDE_CODE_DEFAULT_MAX_OUTPUT_TOKENS = 8000 +// Helper function to get model ID based on environment +export function getClaudeCodeModelId(baseModelId: ClaudeCodeModelId, useVertex = false): string { + return useVertex ? convertModelNameForVertex(baseModelId) : baseModelId +} + export const claudeCodeModels = { "claude-sonnet-4-20250514": { ...anthropicModels["claude-sonnet-4-20250514"], From 68fd714bb155639f2ce3a283a87e8bdba8e88244 Mon Sep 17 00:00:00 2001 From: sasidhar Date: Tue, 15 Jul 2025 14:30:34 +0530 Subject: [PATCH 2/6] Integrate Vertex AI model name conversion into Claude Code provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Import and use getClaudeCodeModelId function in Claude Code handler - Check CLAUDE_CODE_USE_VERTEX environment variable at runtime - Convert model names to @date format when Vertex AI is enabled - Ensures proper model name formatting for Vertex AI compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/api/providers/claude-code.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts index 9ce23a28424..1c30c5e708a 100644 --- a/src/api/providers/claude-code.ts +++ b/src/api/providers/claude-code.ts @@ -1,5 +1,5 @@ import type { Anthropic } from "@anthropic-ai/sdk" -import { claudeCodeDefaultModelId, type ClaudeCodeModelId, claudeCodeModels, type ModelInfo } from "@roo-code/types" +import { claudeCodeDefaultModelId, type ClaudeCodeModelId, claudeCodeModels, type ModelInfo, getClaudeCodeModelId } from "@roo-code/types" import { type ApiHandler } from ".." import { ApiStreamUsageChunk, type ApiStream } from "../transform/stream" import { runClaudeCode } from "../../integrations/claude-code/run" @@ -20,11 +20,12 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { // Filter out image blocks since Claude Code doesn't support them const filteredMessages = filterMessagesForClaudeCode(messages) + const useVertex = process.env.CLAUDE_CODE_USE_VERTEX === "true" const claudeProcess = runClaudeCode({ systemPrompt, messages: filteredMessages, path: this.options.claudeCodePath, - modelId: this.getModel().id, + modelId: getClaudeCodeModelId(this.getModel().id as ClaudeCodeModelId, useVertex), maxOutputTokens: this.options.claudeCodeMaxOutputTokens, }) From 0ee605b3c4a788407ceabf27c3235b2a99f012ba Mon Sep 17 00:00:00 2001 From: sasidhar Date: Tue, 15 Jul 2025 15:26:54 +0530 Subject: [PATCH 3/6] fix --- packages/types/src/providers/__tests__/claude-code.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/providers/__tests__/claude-code.spec.ts b/packages/types/src/providers/__tests__/claude-code.spec.ts index a98805412b9..8f997068f2a 100644 --- a/packages/types/src/providers/__tests__/claude-code.spec.ts +++ b/packages/types/src/providers/__tests__/claude-code.spec.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from "vitest" -import { convertModelNameForVertex, getClaudeCodeModelId } from "../claude-code" +import { convertModelNameForVertex, getClaudeCodeModelId } from "../claude-code.js" describe("convertModelNameForVertex", () => { test("should convert hyphen-date format to @date format", () => { @@ -38,4 +38,4 @@ describe("getClaudeCodeModelId", () => { test("should default to useVertex false when parameter not provided", () => { expect(getClaudeCodeModelId("claude-sonnet-4-20250514")).toBe("claude-sonnet-4-20250514") }) -}) \ No newline at end of file +}) From a4f70c31bdd062a73be0bf51f0d26eb644dcbc87 Mon Sep 17 00:00:00 2001 From: sasidhar Date: Tue, 15 Jul 2025 15:50:11 +0530 Subject: [PATCH 4/6] use-case-insensitive-matching --- src/api/providers/claude-code.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts index 1c30c5e708a..1d63ca0b1b1 100644 --- a/src/api/providers/claude-code.ts +++ b/src/api/providers/claude-code.ts @@ -1,5 +1,11 @@ import type { Anthropic } from "@anthropic-ai/sdk" -import { claudeCodeDefaultModelId, type ClaudeCodeModelId, claudeCodeModels, type ModelInfo, getClaudeCodeModelId } from "@roo-code/types" +import { + claudeCodeDefaultModelId, + type ClaudeCodeModelId, + claudeCodeModels, + type ModelInfo, + getClaudeCodeModelId, +} from "@roo-code/types" import { type ApiHandler } from ".." import { ApiStreamUsageChunk, type ApiStream } from "../transform/stream" import { runClaudeCode } from "../../integrations/claude-code/run" @@ -20,7 +26,7 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { // Filter out image blocks since Claude Code doesn't support them const filteredMessages = filterMessagesForClaudeCode(messages) - const useVertex = process.env.CLAUDE_CODE_USE_VERTEX === "true" + const useVertex = process.env.CLAUDE_CODE_USE_VERTEX?.toLowerCase() === "true" const claudeProcess = runClaudeCode({ systemPrompt, messages: filteredMessages, From b1ad2d5653d1f1e1b02c450930c7c5ce6ba25aa6 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Tue, 15 Jul 2025 12:44:26 -0500 Subject: [PATCH 5/6] fix: add validation for model ID type assertion and improve code documentation - Add validation before type assertion in claude-code.ts to ensure model ID is valid - Add comprehensive JSDoc comments for convertModelNameForVertex and getClaudeCodeModelId functions - Extract regex pattern as named constant VERTEX_DATE_PATTERN for better maintainability --- packages/types/src/providers/claude-code.ts | 29 ++++++++++++++++++--- src/api/providers/claude-code.ts | 7 ++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/types/src/providers/claude-code.ts b/packages/types/src/providers/claude-code.ts index 5012041980a..df8b3d302a2 100644 --- a/packages/types/src/providers/claude-code.ts +++ b/packages/types/src/providers/claude-code.ts @@ -1,17 +1,40 @@ import type { ModelInfo } from "../model.js" import { anthropicModels } from "./anthropic.js" -// Utility function to convert model names for Vertex AI format +// Regex pattern to match 8-digit date at the end of model names +const VERTEX_DATE_PATTERN = /-(\d{8})$/ + +/** + * Converts Claude model names from hyphen-date format to Vertex AI's @-date format. + * + * @param modelName - The original model name (e.g., "claude-sonnet-4-20250514") + * @returns The converted model name for Vertex AI (e.g., "claude-sonnet-4@20250514") + * + * @example + * convertModelNameForVertex("claude-sonnet-4-20250514") // returns "claude-sonnet-4@20250514" + * convertModelNameForVertex("claude-model") // returns "claude-model" (no change) + */ export function convertModelNameForVertex(modelName: string): string { // Convert hyphen-date format to @date format for Vertex AI - return modelName.replace(/-(\d{8})$/, "@$1") + return modelName.replace(VERTEX_DATE_PATTERN, "@$1") } // Claude Code export type ClaudeCodeModelId = keyof typeof claudeCodeModels export const claudeCodeDefaultModelId: ClaudeCodeModelId = "claude-sonnet-4-20250514" export const CLAUDE_CODE_DEFAULT_MAX_OUTPUT_TOKENS = 8000 -// Helper function to get model ID based on environment + +/** + * Gets the appropriate model ID based on whether Vertex AI is being used. + * + * @param baseModelId - The base Claude Code model ID + * @param useVertex - Whether to format the model ID for Vertex AI (default: false) + * @returns The model ID, potentially formatted for Vertex AI + * + * @example + * getClaudeCodeModelId("claude-sonnet-4-20250514", true) // returns "claude-sonnet-4@20250514" + * getClaudeCodeModelId("claude-sonnet-4-20250514", false) // returns "claude-sonnet-4-20250514" + */ export function getClaudeCodeModelId(baseModelId: ClaudeCodeModelId, useVertex = false): string { return useVertex ? convertModelNameForVertex(baseModelId) : baseModelId } diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts index 1d63ca0b1b1..12fc0f08644 100644 --- a/src/api/providers/claude-code.ts +++ b/src/api/providers/claude-code.ts @@ -27,11 +27,16 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { const filteredMessages = filterMessagesForClaudeCode(messages) const useVertex = process.env.CLAUDE_CODE_USE_VERTEX?.toLowerCase() === "true" + const model = this.getModel() + + // Validate that the model ID is a valid ClaudeCodeModelId + const modelId = model.id in claudeCodeModels ? (model.id as ClaudeCodeModelId) : claudeCodeDefaultModelId + const claudeProcess = runClaudeCode({ systemPrompt, messages: filteredMessages, path: this.options.claudeCodePath, - modelId: getClaudeCodeModelId(this.getModel().id as ClaudeCodeModelId, useVertex), + modelId: getClaudeCodeModelId(modelId, useVertex), maxOutputTokens: this.options.claudeCodeMaxOutputTokens, }) From 756bb5a3c8955452206951350fa5535aa3b7bf46 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Tue, 15 Jul 2025 12:58:13 -0500 Subject: [PATCH 6/6] fix: correct CLAUDE_CODE_USE_VERTEX check to match documentation According to Claude Code docs, the env variable should be checked for value '1', not 'true' Reference: https://docs.anthropic.com/en/docs/claude-code/google-vertex-ai#4-configure-claude-code --- src/api/providers/claude-code.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts index 12fc0f08644..dfafb78aaba 100644 --- a/src/api/providers/claude-code.ts +++ b/src/api/providers/claude-code.ts @@ -26,7 +26,7 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { // Filter out image blocks since Claude Code doesn't support them const filteredMessages = filterMessagesForClaudeCode(messages) - const useVertex = process.env.CLAUDE_CODE_USE_VERTEX?.toLowerCase() === "true" + const useVertex = process.env.CLAUDE_CODE_USE_VERTEX === "1" const model = this.getModel() // Validate that the model ID is a valid ClaudeCodeModelId