From e016857e863d94e8e8a324f72fca1c9b4f63d1e5 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 21 Jul 2025 10:00:01 -0500 Subject: [PATCH 1/4] fix: simplify getApiProtocol function to remove vertex/bedrock special handling --- packages/types/src/provider-settings.ts | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index be74ae6bb4c..3b53627295e 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -303,23 +303,7 @@ export const getModelId = (settings: ProviderSettings): string | undefined => { // Providers that use Anthropic-style API protocol export const ANTHROPIC_STYLE_PROVIDERS: ProviderName[] = ["anthropic", "claude-code"] -// Helper function to determine API protocol for a provider and model -export const getApiProtocol = (provider: ProviderName | undefined, modelId?: string): "anthropic" | "openai" => { - // First check if the provider is an Anthropic-style provider - if (provider && ANTHROPIC_STYLE_PROVIDERS.includes(provider)) { - return "anthropic" - } - - // For vertex and bedrock providers, check if the model ID contains "claude" (case-insensitive) - if ( - provider && - (provider === "vertex" || provider === "bedrock") && - modelId && - modelId.toLowerCase().includes("claude") - ) { - return "anthropic" - } - - // Default to OpenAI protocol - return "openai" +// Helper function to determine API protocol for a provider +export const getApiProtocol = (provider: ProviderName | undefined): "anthropic" | "openai" => { + return provider && ANTHROPIC_STYLE_PROVIDERS.includes(provider) ? "anthropic" : "openai" } From 2a1ece06fec895fbef3c1331330fba77b5350dfa Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 21 Jul 2025 10:02:17 -0500 Subject: [PATCH 2/4] test: update getApiProtocol tests to match new function signature --- .../src/__tests__/provider-settings.test.ts | 62 +++---------------- 1 file changed, 10 insertions(+), 52 deletions(-) diff --git a/packages/types/src/__tests__/provider-settings.test.ts b/packages/types/src/__tests__/provider-settings.test.ts index 87c5bbcc1c8..8524a1562b7 100644 --- a/packages/types/src/__tests__/provider-settings.test.ts +++ b/packages/types/src/__tests__/provider-settings.test.ts @@ -5,75 +5,33 @@ describe("getApiProtocol", () => { describe("Anthropic-style providers", () => { it("should return 'anthropic' for anthropic provider", () => { expect(getApiProtocol("anthropic")).toBe("anthropic") - expect(getApiProtocol("anthropic", "gpt-4")).toBe("anthropic") }) it("should return 'anthropic' for claude-code provider", () => { expect(getApiProtocol("claude-code")).toBe("anthropic") - expect(getApiProtocol("claude-code", "some-model")).toBe("anthropic") }) }) - describe("Vertex provider with Claude models", () => { - it("should return 'anthropic' for vertex provider with claude models", () => { - expect(getApiProtocol("vertex", "claude-3-opus")).toBe("anthropic") - expect(getApiProtocol("vertex", "Claude-3-Sonnet")).toBe("anthropic") - expect(getApiProtocol("vertex", "CLAUDE-instant")).toBe("anthropic") - expect(getApiProtocol("vertex", "anthropic/claude-3-haiku")).toBe("anthropic") - }) - - it("should return 'openai' for vertex provider with non-claude models", () => { - expect(getApiProtocol("vertex", "gpt-4")).toBe("openai") - expect(getApiProtocol("vertex", "gemini-pro")).toBe("openai") - expect(getApiProtocol("vertex", "llama-2")).toBe("openai") - }) - }) - - describe("Bedrock provider with Claude models", () => { - it("should return 'anthropic' for bedrock provider with claude models", () => { - expect(getApiProtocol("bedrock", "claude-3-opus")).toBe("anthropic") - expect(getApiProtocol("bedrock", "Claude-3-Sonnet")).toBe("anthropic") - expect(getApiProtocol("bedrock", "CLAUDE-instant")).toBe("anthropic") - expect(getApiProtocol("bedrock", "anthropic.claude-v2")).toBe("anthropic") + describe("Non-Anthropic providers", () => { + it("should return 'openai' for vertex provider", () => { + expect(getApiProtocol("vertex")).toBe("openai") }) - it("should return 'openai' for bedrock provider with non-claude models", () => { - expect(getApiProtocol("bedrock", "gpt-4")).toBe("openai") - expect(getApiProtocol("bedrock", "titan-text")).toBe("openai") - expect(getApiProtocol("bedrock", "llama-2")).toBe("openai") + it("should return 'openai' for bedrock provider", () => { + expect(getApiProtocol("bedrock")).toBe("openai") }) - }) - describe("Other providers with Claude models", () => { - it("should return 'openai' for non-vertex/bedrock providers with claude models", () => { - expect(getApiProtocol("openrouter", "claude-3-opus")).toBe("openai") - expect(getApiProtocol("openai", "claude-3-sonnet")).toBe("openai") - expect(getApiProtocol("litellm", "claude-instant")).toBe("openai") - expect(getApiProtocol("ollama", "claude-model")).toBe("openai") + it("should return 'openai' for other providers", () => { + expect(getApiProtocol("openrouter")).toBe("openai") + expect(getApiProtocol("openai")).toBe("openai") + expect(getApiProtocol("litellm")).toBe("openai") + expect(getApiProtocol("ollama")).toBe("openai") }) }) describe("Edge cases", () => { it("should return 'openai' when provider is undefined", () => { expect(getApiProtocol(undefined)).toBe("openai") - expect(getApiProtocol(undefined, "claude-3-opus")).toBe("openai") - }) - - it("should return 'openai' when model is undefined", () => { - expect(getApiProtocol("openai")).toBe("openai") - expect(getApiProtocol("vertex")).toBe("openai") - expect(getApiProtocol("bedrock")).toBe("openai") - }) - - it("should handle empty strings", () => { - expect(getApiProtocol("vertex", "")).toBe("openai") - expect(getApiProtocol("bedrock", "")).toBe("openai") - }) - - it("should be case-insensitive for claude detection", () => { - expect(getApiProtocol("vertex", "CLAUDE-3-OPUS")).toBe("anthropic") - expect(getApiProtocol("bedrock", "claude-3-opus")).toBe("anthropic") - expect(getApiProtocol("vertex", "ClAuDe-InStAnT")).toBe("anthropic") }) }) }) From 86b4c1244c7678a5a4c58ca59e3a99a7b98339c7 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 21 Jul 2025 10:05:34 -0500 Subject: [PATCH 3/4] fix: update ANTHROPIC_STYLE_PROVIDERS to include 'bedrock' and adjust getApiProtocol call --- packages/types/src/provider-settings.ts | 2 +- src/core/task/Task.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 3b53627295e..5c2875ea088 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -301,7 +301,7 @@ export const getModelId = (settings: ProviderSettings): string | undefined => { } // Providers that use Anthropic-style API protocol -export const ANTHROPIC_STYLE_PROVIDERS: ProviderName[] = ["anthropic", "claude-code"] +export const ANTHROPIC_STYLE_PROVIDERS: ProviderName[] = ["anthropic", "claude-code", "bedrock"] // Helper function to determine API protocol for a provider export const getApiProtocol = (provider: ProviderName | undefined): "anthropic" | "openai" => { diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 53b8ef5b87d..53a0467b429 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -1214,7 +1214,7 @@ export class Task extends EventEmitter { // Determine API protocol based on provider and model const modelId = getModelId(this.apiConfiguration) - const apiProtocol = getApiProtocol(this.apiConfiguration.apiProvider, modelId) + const apiProtocol = getApiProtocol(this.apiConfiguration.apiProvider) await this.say( "api_req_started", From 135f6869e720fb064ed57289d2edb62ed51a46e7 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 21 Jul 2025 10:14:56 -0500 Subject: [PATCH 4/4] feat: restore Claude model checking for vertex provider while keeping bedrock in ANTHROPIC_STYLE_PROVIDERS --- .../src/__tests__/provider-settings.test.ts | 50 +++++++++++++++---- packages/types/src/provider-settings.ts | 17 +++++-- src/core/task/Task.ts | 2 +- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/packages/types/src/__tests__/provider-settings.test.ts b/packages/types/src/__tests__/provider-settings.test.ts index 8524a1562b7..8277320289b 100644 --- a/packages/types/src/__tests__/provider-settings.test.ts +++ b/packages/types/src/__tests__/provider-settings.test.ts @@ -5,33 +5,63 @@ describe("getApiProtocol", () => { describe("Anthropic-style providers", () => { it("should return 'anthropic' for anthropic provider", () => { expect(getApiProtocol("anthropic")).toBe("anthropic") + expect(getApiProtocol("anthropic", "gpt-4")).toBe("anthropic") }) it("should return 'anthropic' for claude-code provider", () => { expect(getApiProtocol("claude-code")).toBe("anthropic") + expect(getApiProtocol("claude-code", "some-model")).toBe("anthropic") + }) + + it("should return 'anthropic' for bedrock provider", () => { + expect(getApiProtocol("bedrock")).toBe("anthropic") + expect(getApiProtocol("bedrock", "gpt-4")).toBe("anthropic") + expect(getApiProtocol("bedrock", "claude-3-opus")).toBe("anthropic") }) }) - describe("Non-Anthropic providers", () => { - it("should return 'openai' for vertex provider", () => { - expect(getApiProtocol("vertex")).toBe("openai") + describe("Vertex provider with Claude models", () => { + it("should return 'anthropic' for vertex provider with claude models", () => { + expect(getApiProtocol("vertex", "claude-3-opus")).toBe("anthropic") + expect(getApiProtocol("vertex", "Claude-3-Sonnet")).toBe("anthropic") + expect(getApiProtocol("vertex", "CLAUDE-instant")).toBe("anthropic") + expect(getApiProtocol("vertex", "anthropic/claude-3-haiku")).toBe("anthropic") }) - it("should return 'openai' for bedrock provider", () => { - expect(getApiProtocol("bedrock")).toBe("openai") + it("should return 'openai' for vertex provider with non-claude models", () => { + expect(getApiProtocol("vertex", "gpt-4")).toBe("openai") + expect(getApiProtocol("vertex", "gemini-pro")).toBe("openai") + expect(getApiProtocol("vertex", "llama-2")).toBe("openai") }) - it("should return 'openai' for other providers", () => { - expect(getApiProtocol("openrouter")).toBe("openai") - expect(getApiProtocol("openai")).toBe("openai") - expect(getApiProtocol("litellm")).toBe("openai") - expect(getApiProtocol("ollama")).toBe("openai") + it("should return 'openai' for vertex provider without model", () => { + expect(getApiProtocol("vertex")).toBe("openai") + }) + }) + + describe("Other providers", () => { + it("should return 'openai' for non-anthropic providers regardless of model", () => { + expect(getApiProtocol("openrouter", "claude-3-opus")).toBe("openai") + expect(getApiProtocol("openai", "claude-3-sonnet")).toBe("openai") + expect(getApiProtocol("litellm", "claude-instant")).toBe("openai") + expect(getApiProtocol("ollama", "claude-model")).toBe("openai") }) }) describe("Edge cases", () => { it("should return 'openai' when provider is undefined", () => { expect(getApiProtocol(undefined)).toBe("openai") + expect(getApiProtocol(undefined, "claude-3-opus")).toBe("openai") + }) + + it("should handle empty strings", () => { + expect(getApiProtocol("vertex", "")).toBe("openai") + }) + + it("should be case-insensitive for claude detection", () => { + expect(getApiProtocol("vertex", "CLAUDE-3-OPUS")).toBe("anthropic") + expect(getApiProtocol("vertex", "claude-3-opus")).toBe("anthropic") + expect(getApiProtocol("vertex", "ClAuDe-InStAnT")).toBe("anthropic") }) }) }) diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 5c2875ea088..511e803cbd6 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -303,7 +303,18 @@ export const getModelId = (settings: ProviderSettings): string | undefined => { // Providers that use Anthropic-style API protocol export const ANTHROPIC_STYLE_PROVIDERS: ProviderName[] = ["anthropic", "claude-code", "bedrock"] -// Helper function to determine API protocol for a provider -export const getApiProtocol = (provider: ProviderName | undefined): "anthropic" | "openai" => { - return provider && ANTHROPIC_STYLE_PROVIDERS.includes(provider) ? "anthropic" : "openai" +// Helper function to determine API protocol for a provider and model +export const getApiProtocol = (provider: ProviderName | undefined, modelId?: string): "anthropic" | "openai" => { + // First check if the provider is an Anthropic-style provider + if (provider && ANTHROPIC_STYLE_PROVIDERS.includes(provider)) { + return "anthropic" + } + + // For vertex provider, check if the model ID contains "claude" (case-insensitive) + if (provider && provider === "vertex" && modelId && modelId.toLowerCase().includes("claude")) { + return "anthropic" + } + + // Default to OpenAI protocol + return "openai" } diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 53a0467b429..53b8ef5b87d 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -1214,7 +1214,7 @@ export class Task extends EventEmitter { // Determine API protocol based on provider and model const modelId = getModelId(this.apiConfiguration) - const apiProtocol = getApiProtocol(this.apiConfiguration.apiProvider) + const apiProtocol = getApiProtocol(this.apiConfiguration.apiProvider, modelId) await this.say( "api_req_started",