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
This commit is contained in:
Roo Code 2026-04-08 11:11:54 +00:00
parent c3cae397a1
commit 9724a28fa7
2 changed files with 79 additions and 2 deletions

View file

@ -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)
})
})
})

View file

@ -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,