diff --git a/src/api/providers/bedrock.ts b/src/api/providers/bedrock.ts
index 8f897fda2a..3bca70338d 100644
--- a/src/api/providers/bedrock.ts
+++ b/src/api/providers/bedrock.ts
@@ -9,7 +9,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
import { ApiHandler, SingleCompletionHandler } from "../"
import { ApiHandlerOptions, BedrockModelId, ModelInfo, bedrockDefaultModelId, bedrockModels } from "../../shared/api"
import { ApiStream } from "../transform/stream"
-import { convertToBedrockConverseMessages, convertToAnthropicMessage } from "../transform/bedrock-converse-format"
+import { convertToBedrockConverseMessages } from "../transform/bedrock-converse-format"
const BEDROCK_DEFAULT_TEMPERATURE = 0.3
diff --git a/src/api/transform/__tests__/bedrock-converse-format.test.ts b/src/api/transform/__tests__/bedrock-converse-format.test.ts
index fdd29c75bf..c56b8a07fc 100644
--- a/src/api/transform/__tests__/bedrock-converse-format.test.ts
+++ b/src/api/transform/__tests__/bedrock-converse-format.test.ts
@@ -1,254 +1,167 @@
// npx jest src/api/transform/__tests__/bedrock-converse-format.test.ts
-import { convertToBedrockConverseMessages, convertToAnthropicMessage } from "../bedrock-converse-format"
+import { convertToBedrockConverseMessages } from "../bedrock-converse-format"
import { Anthropic } from "@anthropic-ai/sdk"
import { ContentBlock, ToolResultContentBlock } from "@aws-sdk/client-bedrock-runtime"
-import { StreamEvent } from "../../providers/bedrock"
-describe("bedrock-converse-format", () => {
- describe("convertToBedrockConverseMessages", () => {
- test("converts simple text messages correctly", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- { role: "user", content: "Hello" },
- { role: "assistant", content: "Hi there" },
- ]
+describe("convertToBedrockConverseMessages", () => {
+ test("converts simple text messages correctly", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ { role: "user", content: "Hello" },
+ { role: "assistant", content: "Hi there" },
+ ]
- const result = convertToBedrockConverseMessages(messages)
+ const result = convertToBedrockConverseMessages(messages)
- expect(result).toEqual([
- {
- role: "user",
- content: [{ text: "Hello" }],
- },
- {
- role: "assistant",
- content: [{ text: "Hi there" }],
- },
- ])
- })
-
- test("converts messages with images correctly", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: [
- {
- type: "text",
- text: "Look at this image:",
- },
- {
- type: "image",
- source: {
- type: "base64",
- data: "SGVsbG8=", // "Hello" in base64
- media_type: "image/jpeg" as const,
- },
- },
- ],
- },
- ]
-
- const result = convertToBedrockConverseMessages(messages)
-
- if (!result[0] || !result[0].content) {
- fail("Expected result to have content")
- return
- }
-
- expect(result[0].role).toBe("user")
- expect(result[0].content).toHaveLength(2)
- expect(result[0].content[0]).toEqual({ text: "Look at this image:" })
-
- const imageBlock = result[0].content[1] as ContentBlock
- if ("image" in imageBlock && imageBlock.image && imageBlock.image.source) {
- expect(imageBlock.image.format).toBe("jpeg")
- expect(imageBlock.image.source).toBeDefined()
- expect(imageBlock.image.source.bytes).toBeDefined()
- } else {
- fail("Expected image block not found")
- }
- })
-
- test("converts tool use messages correctly", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "assistant",
- content: [
- {
- type: "tool_use",
- id: "test-id",
- name: "read_file",
- input: {
- path: "test.txt",
- },
- },
- ],
- },
- ]
-
- const result = convertToBedrockConverseMessages(messages)
-
- if (!result[0] || !result[0].content) {
- fail("Expected result to have content")
- return
- }
-
- expect(result[0].role).toBe("assistant")
- const toolBlock = result[0].content[0] as ContentBlock
- if ("toolUse" in toolBlock && toolBlock.toolUse) {
- expect(toolBlock.toolUse).toEqual({
- toolUseId: "test-id",
- name: "read_file",
- input: "\n\ntest.txt\n\n",
- })
- } else {
- fail("Expected tool use block not found")
- }
- })
-
- test("converts tool result messages correctly", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "assistant",
- content: [
- {
- type: "tool_result",
- tool_use_id: "test-id",
- content: [{ type: "text", text: "File contents here" }],
- },
- ],
- },
- ]
-
- const result = convertToBedrockConverseMessages(messages)
-
- if (!result[0] || !result[0].content) {
- fail("Expected result to have content")
- return
- }
-
- expect(result[0].role).toBe("assistant")
- const resultBlock = result[0].content[0] as ContentBlock
- if ("toolResult" in resultBlock && resultBlock.toolResult) {
- const expectedContent: ToolResultContentBlock[] = [{ text: "File contents here" }]
- expect(resultBlock.toolResult).toEqual({
- toolUseId: "test-id",
- content: expectedContent,
- status: "success",
- })
- } else {
- fail("Expected tool result block not found")
- }
- })
-
- test("handles text content correctly", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: [
- {
- type: "text",
- text: "Hello world",
- },
- ],
- },
- ]
-
- const result = convertToBedrockConverseMessages(messages)
-
- if (!result[0] || !result[0].content) {
- fail("Expected result to have content")
- return
- }
-
- expect(result[0].role).toBe("user")
- expect(result[0].content).toHaveLength(1)
- const textBlock = result[0].content[0] as ContentBlock
- expect(textBlock).toEqual({ text: "Hello world" })
- })
+ expect(result).toEqual([
+ {
+ role: "user",
+ content: [{ text: "Hello" }],
+ },
+ {
+ role: "assistant",
+ content: [{ text: "Hi there" }],
+ },
+ ])
})
- describe("convertToAnthropicMessage", () => {
- test("converts metadata events correctly", () => {
- const event: StreamEvent = {
- metadata: {
- usage: {
- inputTokens: 10,
- outputTokens: 20,
+ test("converts messages with images correctly", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "user",
+ content: [
+ {
+ type: "text",
+ text: "Look at this image:",
},
- },
- }
-
- const result = convertToAnthropicMessage(event, "test-model")
-
- expect(result).toEqual({
- id: "",
- type: "message",
- role: "assistant",
- model: "test-model",
- usage: {
- input_tokens: 10,
- output_tokens: 20,
- cache_creation_input_tokens: null,
- cache_read_input_tokens: null,
- },
- })
- })
-
- test("converts content block start events correctly", () => {
- const event: StreamEvent = {
- contentBlockStart: {
- start: {
- text: "Hello",
+ {
+ type: "image",
+ source: {
+ type: "base64",
+ data: "SGVsbG8=", // "Hello" in base64
+ media_type: "image/jpeg" as const,
+ },
},
- },
- }
+ ],
+ },
+ ]
- const result = convertToAnthropicMessage(event, "test-model")
+ const result = convertToBedrockConverseMessages(messages)
- expect(result).toEqual({
- type: "message",
+ if (!result[0] || !result[0].content) {
+ fail("Expected result to have content")
+ return
+ }
+
+ expect(result[0].role).toBe("user")
+ expect(result[0].content).toHaveLength(2)
+ expect(result[0].content[0]).toEqual({ text: "Look at this image:" })
+
+ const imageBlock = result[0].content[1] as ContentBlock
+ if ("image" in imageBlock && imageBlock.image && imageBlock.image.source) {
+ expect(imageBlock.image.format).toBe("jpeg")
+ expect(imageBlock.image.source).toBeDefined()
+ expect(imageBlock.image.source.bytes).toBeDefined()
+ } else {
+ fail("Expected image block not found")
+ }
+ })
+
+ test("converts tool use messages correctly", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
role: "assistant",
- content: [{ type: "text", text: "Hello", citations: null }],
- model: "test-model",
- })
- })
-
- test("converts content block delta events correctly", () => {
- const event: StreamEvent = {
- contentBlockDelta: {
- delta: {
- text: " world",
+ content: [
+ {
+ type: "tool_use",
+ id: "test-id",
+ name: "read_file",
+ input: {
+ path: "test.txt",
+ },
},
- },
- }
+ ],
+ },
+ ]
- const result = convertToAnthropicMessage(event, "test-model")
+ const result = convertToBedrockConverseMessages(messages)
- expect(result).toEqual({
- type: "message",
- role: "assistant",
- content: [{ type: "text", text: " world", citations: null }],
- model: "test-model",
+ if (!result[0] || !result[0].content) {
+ fail("Expected result to have content")
+ return
+ }
+
+ expect(result[0].role).toBe("assistant")
+ const toolBlock = result[0].content[0] as ContentBlock
+ if ("toolUse" in toolBlock && toolBlock.toolUse) {
+ expect(toolBlock.toolUse).toEqual({
+ toolUseId: "test-id",
+ name: "read_file",
+ input: "\n\ntest.txt\n\n",
})
- })
+ } else {
+ fail("Expected tool use block not found")
+ }
+ })
- test("converts message stop events correctly", () => {
- const event: StreamEvent = {
- messageStop: {
- stopReason: "end_turn" as const,
- },
- }
-
- const result = convertToAnthropicMessage(event, "test-model")
-
- expect(result).toEqual({
- type: "message",
+ test("converts tool result messages correctly", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
role: "assistant",
- stop_reason: "end_turn",
- stop_sequence: null,
- model: "test-model",
+ content: [
+ {
+ type: "tool_result",
+ tool_use_id: "test-id",
+ content: [{ type: "text", text: "File contents here" }],
+ },
+ ],
+ },
+ ]
+
+ const result = convertToBedrockConverseMessages(messages)
+
+ if (!result[0] || !result[0].content) {
+ fail("Expected result to have content")
+ return
+ }
+
+ expect(result[0].role).toBe("assistant")
+ const resultBlock = result[0].content[0] as ContentBlock
+ if ("toolResult" in resultBlock && resultBlock.toolResult) {
+ const expectedContent: ToolResultContentBlock[] = [{ text: "File contents here" }]
+ expect(resultBlock.toolResult).toEqual({
+ toolUseId: "test-id",
+ content: expectedContent,
+ status: "success",
})
- })
+ } else {
+ fail("Expected tool result block not found")
+ }
+ })
+
+ test("handles text content correctly", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "user",
+ content: [
+ {
+ type: "text",
+ text: "Hello world",
+ },
+ ],
+ },
+ ]
+
+ const result = convertToBedrockConverseMessages(messages)
+
+ if (!result[0] || !result[0].content) {
+ fail("Expected result to have content")
+ return
+ }
+
+ expect(result[0].role).toBe("user")
+ expect(result[0].content).toHaveLength(1)
+ const textBlock = result[0].content[0] as ContentBlock
+ expect(textBlock).toEqual({ text: "Hello world" })
})
})
diff --git a/src/api/transform/__tests__/openai-format.test.ts b/src/api/transform/__tests__/openai-format.test.ts
index 812208acd1..f0aa5e1a56 100644
--- a/src/api/transform/__tests__/openai-format.test.ts
+++ b/src/api/transform/__tests__/openai-format.test.ts
@@ -1,281 +1,131 @@
// npx jest src/api/transform/__tests__/openai-format.test.ts
-import { convertToOpenAiMessages, convertToAnthropicMessage } from "../openai-format"
import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"
-type PartialChatCompletion = Omit & {
- choices: Array<
- Partial & {
- message: OpenAI.Chat.Completions.ChatCompletion.Choice["message"]
- finish_reason: string
- index: number
- }
- >
-}
+import { convertToOpenAiMessages } from "../openai-format"
-describe("OpenAI Format Transformations", () => {
- describe("convertToOpenAiMessages", () => {
- it("should convert simple text messages", () => {
- const anthropicMessages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: "Hello",
- },
- {
- role: "assistant",
- content: "Hi there!",
- },
- ]
-
- const openAiMessages = convertToOpenAiMessages(anthropicMessages)
- expect(openAiMessages).toHaveLength(2)
- expect(openAiMessages[0]).toEqual({
+describe("convertToOpenAiMessages", () => {
+ it("should convert simple text messages", () => {
+ const anthropicMessages: Anthropic.Messages.MessageParam[] = [
+ {
role: "user",
content: "Hello",
- })
- expect(openAiMessages[1]).toEqual({
+ },
+ {
role: "assistant",
content: "Hi there!",
- })
+ },
+ ]
+
+ const openAiMessages = convertToOpenAiMessages(anthropicMessages)
+ expect(openAiMessages).toHaveLength(2)
+ expect(openAiMessages[0]).toEqual({
+ role: "user",
+ content: "Hello",
})
-
- it("should handle messages with image content", () => {
- const anthropicMessages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: [
- {
- type: "text",
- text: "What is in this image?",
- },
- {
- type: "image",
- source: {
- type: "base64",
- media_type: "image/jpeg",
- data: "base64data",
- },
- },
- ],
- },
- ]
-
- const openAiMessages = convertToOpenAiMessages(anthropicMessages)
- expect(openAiMessages).toHaveLength(1)
- expect(openAiMessages[0].role).toBe("user")
-
- const content = openAiMessages[0].content as Array<{
- type: string
- text?: string
- image_url?: { url: string }
- }>
-
- expect(Array.isArray(content)).toBe(true)
- expect(content).toHaveLength(2)
- expect(content[0]).toEqual({ type: "text", text: "What is in this image?" })
- expect(content[1]).toEqual({
- type: "image_url",
- image_url: { url: "data:image/jpeg;base64,base64data" },
- })
- })
-
- it("should handle assistant messages with tool use", () => {
- const anthropicMessages: Anthropic.Messages.MessageParam[] = [
- {
- role: "assistant",
- content: [
- {
- type: "text",
- text: "Let me check the weather.",
- },
- {
- type: "tool_use",
- id: "weather-123",
- name: "get_weather",
- input: { city: "London" },
- },
- ],
- },
- ]
-
- const openAiMessages = convertToOpenAiMessages(anthropicMessages)
- expect(openAiMessages).toHaveLength(1)
-
- const assistantMessage = openAiMessages[0] as OpenAI.Chat.ChatCompletionAssistantMessageParam
- expect(assistantMessage.role).toBe("assistant")
- expect(assistantMessage.content).toBe("Let me check the weather.")
- expect(assistantMessage.tool_calls).toHaveLength(1)
- expect(assistantMessage.tool_calls![0]).toEqual({
- id: "weather-123",
- type: "function",
- function: {
- name: "get_weather",
- arguments: JSON.stringify({ city: "London" }),
- },
- })
- })
-
- it("should handle user messages with tool results", () => {
- const anthropicMessages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: [
- {
- type: "tool_result",
- tool_use_id: "weather-123",
- content: "Current temperature in London: 20°C",
- },
- ],
- },
- ]
-
- const openAiMessages = convertToOpenAiMessages(anthropicMessages)
- expect(openAiMessages).toHaveLength(1)
-
- const toolMessage = openAiMessages[0] as OpenAI.Chat.ChatCompletionToolMessageParam
- expect(toolMessage.role).toBe("tool")
- expect(toolMessage.tool_call_id).toBe("weather-123")
- expect(toolMessage.content).toBe("Current temperature in London: 20°C")
+ expect(openAiMessages[1]).toEqual({
+ role: "assistant",
+ content: "Hi there!",
})
})
- describe("convertToAnthropicMessage", () => {
- it("should convert simple completion", () => {
- const openAiCompletion: PartialChatCompletion = {
- id: "completion-123",
- model: "gpt-4",
- choices: [
+ it("should handle messages with image content", () => {
+ const anthropicMessages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "user",
+ content: [
{
- message: {
- role: "assistant",
- content: "Hello there!",
- refusal: null,
+ type: "text",
+ text: "What is in this image?",
+ },
+ {
+ type: "image",
+ source: {
+ type: "base64",
+ media_type: "image/jpeg",
+ data: "base64data",
},
- finish_reason: "stop",
- index: 0,
},
],
- usage: {
- prompt_tokens: 10,
- completion_tokens: 5,
- total_tokens: 15,
- },
- created: 123456789,
- object: "chat.completion",
- }
+ },
+ ]
- const anthropicMessage = convertToAnthropicMessage(
- openAiCompletion as OpenAI.Chat.Completions.ChatCompletion,
- )
- expect(anthropicMessage.id).toBe("completion-123")
- expect(anthropicMessage.role).toBe("assistant")
- expect(anthropicMessage.content).toHaveLength(1)
- expect(anthropicMessage.content[0]).toEqual({
- type: "text",
- text: "Hello there!",
- citations: null,
- })
- expect(anthropicMessage.stop_reason).toBe("end_turn")
- expect(anthropicMessage.usage).toEqual({
- input_tokens: 10,
- output_tokens: 5,
- cache_creation_input_tokens: null,
- cache_read_input_tokens: null,
- })
+ const openAiMessages = convertToOpenAiMessages(anthropicMessages)
+ expect(openAiMessages).toHaveLength(1)
+ expect(openAiMessages[0].role).toBe("user")
+
+ const content = openAiMessages[0].content as Array<{
+ type: string
+ text?: string
+ image_url?: { url: string }
+ }>
+
+ expect(Array.isArray(content)).toBe(true)
+ expect(content).toHaveLength(2)
+ expect(content[0]).toEqual({ type: "text", text: "What is in this image?" })
+ expect(content[1]).toEqual({
+ type: "image_url",
+ image_url: { url: "data:image/jpeg;base64,base64data" },
})
+ })
- it("should handle tool calls in completion", () => {
- const openAiCompletion: PartialChatCompletion = {
- id: "completion-123",
- model: "gpt-4",
- choices: [
+ it("should handle assistant messages with tool use", () => {
+ const anthropicMessages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "assistant",
+ content: [
{
- message: {
- role: "assistant",
- content: "Let me check the weather.",
- tool_calls: [
- {
- id: "weather-123",
- type: "function",
- function: {
- name: "get_weather",
- arguments: '{"city":"London"}',
- },
- },
- ],
- refusal: null,
- },
- finish_reason: "tool_calls",
- index: 0,
+ type: "text",
+ text: "Let me check the weather.",
+ },
+ {
+ type: "tool_use",
+ id: "weather-123",
+ name: "get_weather",
+ input: { city: "London" },
},
],
- usage: {
- prompt_tokens: 15,
- completion_tokens: 8,
- total_tokens: 23,
- },
- created: 123456789,
- object: "chat.completion",
- }
+ },
+ ]
- const anthropicMessage = convertToAnthropicMessage(
- openAiCompletion as OpenAI.Chat.Completions.ChatCompletion,
- )
- expect(anthropicMessage.content).toHaveLength(2)
- expect(anthropicMessage.content[0]).toEqual({
- type: "text",
- text: "Let me check the weather.",
- citations: null,
- })
- expect(anthropicMessage.content[1]).toEqual({
- type: "tool_use",
- id: "weather-123",
+ const openAiMessages = convertToOpenAiMessages(anthropicMessages)
+ expect(openAiMessages).toHaveLength(1)
+
+ const assistantMessage = openAiMessages[0] as OpenAI.Chat.ChatCompletionAssistantMessageParam
+ expect(assistantMessage.role).toBe("assistant")
+ expect(assistantMessage.content).toBe("Let me check the weather.")
+ expect(assistantMessage.tool_calls).toHaveLength(1)
+ expect(assistantMessage.tool_calls![0]).toEqual({
+ id: "weather-123",
+ type: "function",
+ function: {
name: "get_weather",
- input: { city: "London" },
- })
- expect(anthropicMessage.stop_reason).toBe("tool_use")
+ arguments: JSON.stringify({ city: "London" }),
+ },
})
+ })
- it("should handle invalid tool call arguments", () => {
- const openAiCompletion: PartialChatCompletion = {
- id: "completion-123",
- model: "gpt-4",
- choices: [
+ it("should handle user messages with tool results", () => {
+ const anthropicMessages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "user",
+ content: [
{
- message: {
- role: "assistant",
- content: "Testing invalid arguments",
- tool_calls: [
- {
- id: "test-123",
- type: "function",
- function: {
- name: "test_function",
- arguments: "invalid json",
- },
- },
- ],
- refusal: null,
- },
- finish_reason: "tool_calls",
- index: 0,
+ type: "tool_result",
+ tool_use_id: "weather-123",
+ content: "Current temperature in London: 20°C",
},
],
- created: 123456789,
- object: "chat.completion",
- }
+ },
+ ]
- const anthropicMessage = convertToAnthropicMessage(
- openAiCompletion as OpenAI.Chat.Completions.ChatCompletion,
- )
- expect(anthropicMessage.content).toHaveLength(2)
- expect(anthropicMessage.content[1]).toEqual({
- type: "tool_use",
- id: "test-123",
- name: "test_function",
- input: {}, // Should default to empty object for invalid JSON
- })
- })
+ const openAiMessages = convertToOpenAiMessages(anthropicMessages)
+ expect(openAiMessages).toHaveLength(1)
+
+ const toolMessage = openAiMessages[0] as OpenAI.Chat.ChatCompletionToolMessageParam
+ expect(toolMessage.role).toBe("tool")
+ expect(toolMessage.tool_call_id).toBe("weather-123")
+ expect(toolMessage.content).toBe("Current temperature in London: 20°C")
})
})
diff --git a/src/api/transform/__tests__/vscode-lm-format.test.ts b/src/api/transform/__tests__/vscode-lm-format.test.ts
index eb800e2b7a..eea8de7c9a 100644
--- a/src/api/transform/__tests__/vscode-lm-format.test.ts
+++ b/src/api/transform/__tests__/vscode-lm-format.test.ts
@@ -1,8 +1,8 @@
// npx jest src/api/transform/__tests__/vscode-lm-format.test.ts
import { Anthropic } from "@anthropic-ai/sdk"
-import * as vscode from "vscode"
-import { convertToVsCodeLmMessages, convertToAnthropicRole, convertToAnthropicMessage } from "../vscode-lm-format"
+
+import { convertToVsCodeLmMessages, convertToAnthropicRole } from "../vscode-lm-format"
// Mock crypto
const mockCrypto = {
@@ -29,14 +29,6 @@ interface MockLanguageModelToolResultPart {
parts: MockLanguageModelTextPart[]
}
-type MockMessageContent = MockLanguageModelTextPart | MockLanguageModelToolCallPart | MockLanguageModelToolResultPart
-
-interface MockLanguageModelChatMessage {
- role: string
- name?: string
- content: MockMessageContent[]
-}
-
// Mock vscode namespace
jest.mock("vscode", () => {
const LanguageModelChatMessageRole = {
@@ -86,174 +78,115 @@ jest.mock("vscode", () => {
}
})
-describe("vscode-lm-format", () => {
- describe("convertToVsCodeLmMessages", () => {
- it("should convert simple string messages", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- { role: "user", content: "Hello" },
- { role: "assistant", content: "Hi there" },
- ]
+describe("convertToVsCodeLmMessages", () => {
+ it("should convert simple string messages", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ { role: "user", content: "Hello" },
+ { role: "assistant", content: "Hi there" },
+ ]
- const result = convertToVsCodeLmMessages(messages)
+ const result = convertToVsCodeLmMessages(messages)
- expect(result).toHaveLength(2)
- expect(result[0].role).toBe("user")
- expect((result[0].content[0] as MockLanguageModelTextPart).value).toBe("Hello")
- expect(result[1].role).toBe("assistant")
- expect((result[1].content[0] as MockLanguageModelTextPart).value).toBe("Hi there")
- })
-
- it("should handle complex user messages with tool results", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: [
- { type: "text", text: "Here is the result:" },
- {
- type: "tool_result",
- tool_use_id: "tool-1",
- content: "Tool output",
- },
- ],
- },
- ]
-
- const result = convertToVsCodeLmMessages(messages)
-
- expect(result).toHaveLength(1)
- expect(result[0].role).toBe("user")
- expect(result[0].content).toHaveLength(2)
- const [toolResult, textContent] = result[0].content as [
- MockLanguageModelToolResultPart,
- MockLanguageModelTextPart,
- ]
- expect(toolResult.type).toBe("tool_result")
- expect(textContent.type).toBe("text")
- })
-
- it("should handle complex assistant messages with tool calls", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "assistant",
- content: [
- { type: "text", text: "Let me help you with that." },
- {
- type: "tool_use",
- id: "tool-1",
- name: "calculator",
- input: { operation: "add", numbers: [2, 2] },
- },
- ],
- },
- ]
-
- const result = convertToVsCodeLmMessages(messages)
-
- expect(result).toHaveLength(1)
- expect(result[0].role).toBe("assistant")
- expect(result[0].content).toHaveLength(2)
- const [toolCall, textContent] = result[0].content as [
- MockLanguageModelToolCallPart,
- MockLanguageModelTextPart,
- ]
- expect(toolCall.type).toBe("tool_call")
- expect(textContent.type).toBe("text")
- })
-
- it("should handle image blocks with appropriate placeholders", () => {
- const messages: Anthropic.Messages.MessageParam[] = [
- {
- role: "user",
- content: [
- { type: "text", text: "Look at this:" },
- {
- type: "image",
- source: {
- type: "base64",
- media_type: "image/png",
- data: "base64data",
- },
- },
- ],
- },
- ]
-
- const result = convertToVsCodeLmMessages(messages)
-
- expect(result).toHaveLength(1)
- const imagePlaceholder = result[0].content[1] as MockLanguageModelTextPart
- expect(imagePlaceholder.value).toContain("[Image (base64): image/png not supported by VSCode LM API]")
- })
+ expect(result).toHaveLength(2)
+ expect(result[0].role).toBe("user")
+ expect((result[0].content[0] as MockLanguageModelTextPart).value).toBe("Hello")
+ expect(result[1].role).toBe("assistant")
+ expect((result[1].content[0] as MockLanguageModelTextPart).value).toBe("Hi there")
})
- describe("convertToAnthropicRole", () => {
- it("should convert assistant role correctly", () => {
- const result = convertToAnthropicRole("assistant" as any)
- expect(result).toBe("assistant")
- })
-
- it("should convert user role correctly", () => {
- const result = convertToAnthropicRole("user" as any)
- expect(result).toBe("user")
- })
-
- it("should return null for unknown roles", () => {
- const result = convertToAnthropicRole("unknown" as any)
- expect(result).toBeNull()
- })
- })
-
- describe("convertToAnthropicMessage", () => {
- it("should convert assistant message with text content", async () => {
- const vsCodeMessage = {
- role: "assistant",
- name: "assistant",
- content: [new vscode.LanguageModelTextPart("Hello")],
- }
-
- const result = await convertToAnthropicMessage(vsCodeMessage as any)
-
- expect(result.role).toBe("assistant")
- expect(result.content).toHaveLength(1)
- expect(result.content[0]).toEqual({
- type: "text",
- text: "Hello",
- citations: null,
- })
- expect(result.id).toBe("test-uuid")
- })
-
- it("should convert assistant message with tool calls", async () => {
- const vsCodeMessage = {
- role: "assistant",
- name: "assistant",
- content: [
- new vscode.LanguageModelToolCallPart("call-1", "calculator", { operation: "add", numbers: [2, 2] }),
- ],
- }
-
- const result = await convertToAnthropicMessage(vsCodeMessage as any)
-
- expect(result.content).toHaveLength(1)
- expect(result.content[0]).toEqual({
- type: "tool_use",
- id: "call-1",
- name: "calculator",
- input: { operation: "add", numbers: [2, 2] },
- })
- expect(result.id).toBe("test-uuid")
- })
-
- it("should throw error for non-assistant messages", async () => {
- const vsCodeMessage = {
+ it("should handle complex user messages with tool results", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
role: "user",
- name: "user",
- content: [new vscode.LanguageModelTextPart("Hello")],
- }
+ content: [
+ { type: "text", text: "Here is the result:" },
+ {
+ type: "tool_result",
+ tool_use_id: "tool-1",
+ content: "Tool output",
+ },
+ ],
+ },
+ ]
- await expect(convertToAnthropicMessage(vsCodeMessage as any)).rejects.toThrow(
- "Roo Code : Only assistant messages are supported.",
- )
- })
+ const result = convertToVsCodeLmMessages(messages)
+
+ expect(result).toHaveLength(1)
+ expect(result[0].role).toBe("user")
+ expect(result[0].content).toHaveLength(2)
+ const [toolResult, textContent] = result[0].content as [
+ MockLanguageModelToolResultPart,
+ MockLanguageModelTextPart,
+ ]
+ expect(toolResult.type).toBe("tool_result")
+ expect(textContent.type).toBe("text")
+ })
+
+ it("should handle complex assistant messages with tool calls", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "assistant",
+ content: [
+ { type: "text", text: "Let me help you with that." },
+ {
+ type: "tool_use",
+ id: "tool-1",
+ name: "calculator",
+ input: { operation: "add", numbers: [2, 2] },
+ },
+ ],
+ },
+ ]
+
+ const result = convertToVsCodeLmMessages(messages)
+
+ expect(result).toHaveLength(1)
+ expect(result[0].role).toBe("assistant")
+ expect(result[0].content).toHaveLength(2)
+ const [toolCall, textContent] = result[0].content as [MockLanguageModelToolCallPart, MockLanguageModelTextPart]
+ expect(toolCall.type).toBe("tool_call")
+ expect(textContent.type).toBe("text")
+ })
+
+ it("should handle image blocks with appropriate placeholders", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "user",
+ content: [
+ { type: "text", text: "Look at this:" },
+ {
+ type: "image",
+ source: {
+ type: "base64",
+ media_type: "image/png",
+ data: "base64data",
+ },
+ },
+ ],
+ },
+ ]
+
+ const result = convertToVsCodeLmMessages(messages)
+
+ expect(result).toHaveLength(1)
+ const imagePlaceholder = result[0].content[1] as MockLanguageModelTextPart
+ expect(imagePlaceholder.value).toContain("[Image (base64): image/png not supported by VSCode LM API]")
+ })
+})
+
+describe("convertToAnthropicRole", () => {
+ it("should convert assistant role correctly", () => {
+ const result = convertToAnthropicRole("assistant" as any)
+ expect(result).toBe("assistant")
+ })
+
+ it("should convert user role correctly", () => {
+ const result = convertToAnthropicRole("user" as any)
+ expect(result).toBe("user")
+ })
+
+ it("should return null for unknown roles", () => {
+ const result = convertToAnthropicRole("unknown" as any)
+ expect(result).toBeNull()
})
})
diff --git a/src/api/transform/bedrock-converse-format.ts b/src/api/transform/bedrock-converse-format.ts
index e4dc9eecc8..68d21e4d5b 100644
--- a/src/api/transform/bedrock-converse-format.ts
+++ b/src/api/transform/bedrock-converse-format.ts
@@ -1,9 +1,7 @@
import { Anthropic } from "@anthropic-ai/sdk"
-import { MessageContent } from "../../shared/api"
import { ConversationRole, Message, ContentBlock } from "@aws-sdk/client-bedrock-runtime"
-// Import StreamEvent type from bedrock.ts
-import { StreamEvent } from "../providers/bedrock"
+import { MessageContent } from "../../shared/api"
/**
* Convert Anthropic messages to Bedrock Converse format
@@ -175,51 +173,3 @@ export function convertToBedrockConverseMessages(anthropicMessages: Anthropic.Me
}
})
}
-
-/**
- * Convert Bedrock Converse stream events to Anthropic message format
- */
-export function convertToAnthropicMessage(
- streamEvent: StreamEvent,
- modelId: string,
-): Partial {
- // Handle metadata events
- if (streamEvent.metadata?.usage) {
- return {
- id: "", // Bedrock doesn't provide message IDs
- type: "message",
- role: "assistant",
- model: modelId,
- usage: {
- input_tokens: streamEvent.metadata.usage.inputTokens || 0,
- output_tokens: streamEvent.metadata.usage.outputTokens || 0,
- cache_creation_input_tokens: null,
- cache_read_input_tokens: null,
- },
- }
- }
-
- // Handle content blocks
- const text = streamEvent.contentBlockStart?.start?.text || streamEvent.contentBlockDelta?.delta?.text
- if (text !== undefined) {
- return {
- type: "message",
- role: "assistant",
- content: [{ type: "text", text: text, citations: null }],
- model: modelId,
- }
- }
-
- // Handle message stop
- if (streamEvent.messageStop) {
- return {
- type: "message",
- role: "assistant",
- stop_reason: streamEvent.messageStop.stopReason || null,
- stop_sequence: null,
- model: modelId,
- }
- }
-
- return {}
-}
diff --git a/src/api/transform/openai-format.ts b/src/api/transform/openai-format.ts
index f421769054..134f9f2ed6 100644
--- a/src/api/transform/openai-format.ts
+++ b/src/api/transform/openai-format.ts
@@ -144,63 +144,3 @@ export function convertToOpenAiMessages(
return openAiMessages
}
-
-// Convert OpenAI response to Anthropic format
-export function convertToAnthropicMessage(
- completion: OpenAI.Chat.Completions.ChatCompletion,
-): Anthropic.Messages.Message {
- const openAiMessage = completion.choices[0].message
- const anthropicMessage: Anthropic.Messages.Message = {
- id: completion.id,
- type: "message",
- role: openAiMessage.role, // always "assistant"
- content: [
- {
- type: "text",
- text: openAiMessage.content || "",
- citations: null,
- },
- ],
- model: completion.model,
- stop_reason: (() => {
- switch (completion.choices[0].finish_reason) {
- case "stop":
- return "end_turn"
- case "length":
- return "max_tokens"
- case "tool_calls":
- return "tool_use"
- case "content_filter": // Anthropic doesn't have an exact equivalent
- default:
- return null
- }
- })(),
- stop_sequence: null, // which custom stop_sequence was generated, if any (not applicable if you don't use stop_sequence)
- usage: {
- input_tokens: completion.usage?.prompt_tokens || 0,
- output_tokens: completion.usage?.completion_tokens || 0,
- cache_creation_input_tokens: null,
- cache_read_input_tokens: null,
- },
- }
-
- if (openAiMessage.tool_calls && openAiMessage.tool_calls.length > 0) {
- anthropicMessage.content.push(
- ...openAiMessage.tool_calls.map((toolCall): Anthropic.ToolUseBlock => {
- let parsedInput = {}
- try {
- parsedInput = JSON.parse(toolCall.function.arguments || "{}")
- } catch (error) {
- console.error("Failed to parse tool arguments:", error)
- }
- return {
- type: "tool_use",
- id: toolCall.id,
- name: toolCall.function.name,
- input: parsedInput,
- }
- }),
- )
- }
- return anthropicMessage
-}
diff --git a/src/api/transform/vscode-lm-format.ts b/src/api/transform/vscode-lm-format.ts
index 85c2fc7ba5..73716cf912 100644
--- a/src/api/transform/vscode-lm-format.ts
+++ b/src/api/transform/vscode-lm-format.ts
@@ -155,50 +155,3 @@ export function convertToAnthropicRole(vsCodeLmMessageRole: vscode.LanguageModel
return null
}
}
-
-export async function convertToAnthropicMessage(
- vsCodeLmMessage: vscode.LanguageModelChatMessage,
-): Promise {
- const anthropicRole: string | null = convertToAnthropicRole(vsCodeLmMessage.role)
-
- if (anthropicRole !== "assistant") {
- throw new Error("Roo Code : Only assistant messages are supported.")
- }
-
- return {
- id: crypto.randomUUID(),
- type: "message",
- model: "vscode-lm",
- role: anthropicRole,
- content: vsCodeLmMessage.content
- .map((part): Anthropic.ContentBlock | null => {
- if (part instanceof vscode.LanguageModelTextPart) {
- return {
- type: "text",
- text: part.value,
- citations: null,
- }
- }
-
- if (part instanceof vscode.LanguageModelToolCallPart) {
- return {
- type: "tool_use",
- id: part.callId || crypto.randomUUID(),
- name: part.name,
- input: asObjectSafe(part.input),
- }
- }
-
- return null
- })
- .filter((part): part is Anthropic.ContentBlock => part !== null),
- stop_reason: null,
- stop_sequence: null,
- usage: {
- input_tokens: 0,
- output_tokens: 0,
- cache_creation_input_tokens: null,
- cache_read_input_tokens: null,
- },
- }
-}