From 9724a28fa73ed319a3dfbe27d7db8b4fdf114692 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Wed, 8 Apr 2026 11:11:54 +0000 Subject: [PATCH] fix: support custom/third-party model paths in Vertex AI provider When users specify a custom or third-party MaaS model ID (e.g. "gpt-oss-120b-maas" or "publishers/openai/models/gpt-oss-120b-maas"), the VertexHandler now passes it through as-is instead of silently falling back to the default model. This fixes 404 NOT_FOUND errors when using non-Google models on Vertex AI. Closes #12074 --- src/api/providers/__tests__/vertex.spec.ts | 51 ++++++++++++++++++++++ src/api/providers/vertex.ts | 30 ++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/api/providers/__tests__/vertex.spec.ts b/src/api/providers/__tests__/vertex.spec.ts index 3361176f1fa..9d4e80bd61c 100644 --- a/src/api/providers/__tests__/vertex.spec.ts +++ b/src/api/providers/__tests__/vertex.spec.ts @@ -163,5 +163,56 @@ describe("VertexHandler", () => { expect(excludedCount).toBe(1) expect(includedCount).toBe(1) }) + + it("should pass through custom/unknown model IDs instead of falling back to default", () => { + const testHandler = new VertexHandler({ + apiModelId: "gpt-oss-120b-maas", + vertexProjectId: "test-project", + vertexRegion: "us-central1", + }) + + const modelInfo = testHandler.getModel() + // The critical fix: custom model ID is preserved, not replaced with the default + expect(modelInfo.id).toBe("gpt-oss-120b-maas") + expect(modelInfo.info).toBeDefined() + }) + + it("should pass through publisher-qualified model paths as-is", () => { + const testHandler = new VertexHandler({ + apiModelId: "publishers/openai/models/gpt-oss-120b-maas", + vertexProjectId: "test-project", + vertexRegion: "us-central1", + }) + + const modelInfo = testHandler.getModel() + // Full publisher path is passed through unchanged + expect(modelInfo.id).toBe("publishers/openai/models/gpt-oss-120b-maas") + expect(modelInfo.info).toBeDefined() + }) + + it("should still apply edit/apply_diff tool preferences to custom models", () => { + const testHandler = new VertexHandler({ + apiModelId: "publishers/openai/models/gpt-oss-120b-maas", + vertexProjectId: "test-project", + vertexRegion: "us-central1", + }) + + const modelInfo = testHandler.getModel() + expect(modelInfo.info.excludedTools).toContain("apply_diff") + expect(modelInfo.info.includedTools).toContain("edit") + }) + + it("should fall back to default model when no model ID is provided", () => { + const testHandler = new VertexHandler({ + vertexProjectId: "test-project", + vertexRegion: "us-central1", + }) + + const modelInfo = testHandler.getModel() + // Should use the default vertex model, not crash + expect(modelInfo.id).toBeDefined() + expect(modelInfo.info).toBeDefined() + expect(modelInfo.info.maxTokens).toBeGreaterThan(0) + }) }) }) diff --git a/src/api/providers/vertex.ts b/src/api/providers/vertex.ts index fd318d9b19a..fa72ce71c82 100644 --- a/src/api/providers/vertex.ts +++ b/src/api/providers/vertex.ts @@ -14,8 +14,34 @@ export class VertexHandler extends GeminiHandler implements SingleCompletionHand override getModel() { const modelId = this.options.apiModelId - let id = modelId && modelId in vertexModels ? (modelId as VertexModelId) : vertexDefaultModelId - let info: ModelInfo = vertexModels[id] + + let id: string + let info: ModelInfo + + if (modelId && modelId in vertexModels) { + // Known Vertex model -- use its curated ModelInfo. + id = modelId as VertexModelId + info = vertexModels[id as VertexModelId] + } else if (modelId) { + // Custom / third-party MaaS model. + // Users may supply either a bare model name (e.g. "gpt-oss-120b-maas") + // or a fully-qualified publisher path + // (e.g. "publishers/openai/models/gpt-oss-120b-maas"). + // Both forms are passed through as-is; the @google/genai SDK and + // Vertex AI API accept full resource names directly. + id = modelId + info = { + maxTokens: 8192, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: false, + } + } else { + // No model specified -- fall back to the default. + id = vertexDefaultModelId + info = vertexModels[vertexDefaultModelId] + } + const params = getModelParams({ format: "gemini", modelId: id,