Skip to content
8 changes: 3 additions & 5 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import OpenAI from "openai"

import { isRetiredProvider, type ProviderSettings, type ModelInfo } from "@roo-code/types"

import type { RooMessage } from "../core/task-persistence/rooMessage"

import { ApiStream } from "./transform/stream"

import {
Expand Down Expand Up @@ -89,11 +91,7 @@ export interface ApiHandlerCreateMessageMetadata {
}

export interface ApiHandler {
createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
metadata?: ApiHandlerCreateMessageMetadata,
): ApiStream
createMessage(systemPrompt: string, messages: RooMessage[], metadata?: ApiHandlerCreateMessageMetadata): ApiStream

getModel(): { id: string; info: ModelInfo }

Expand Down
12 changes: 9 additions & 3 deletions src/api/providers/__tests__/anthropic-vertex.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// npx vitest run src/api/providers/__tests__/anthropic-vertex.spec.ts

import { AnthropicVertexHandler } from "../anthropic-vertex"
Expand Down Expand Up @@ -184,7 +185,7 @@ describe("AnthropicVertexHandler", () => {
})

describe("createMessage", () => {
const mockMessages: Anthropic.Messages.MessageParam[] = [
const mockMessages: RooMessage[] = [
{
role: "user",
content: "Hello",
Expand Down Expand Up @@ -244,15 +245,20 @@ describe("AnthropicVertexHandler", () => {
)
})

it("should call convertToAiSdkMessages with the messages", async () => {
it("should pass messages directly to streamText as ModelMessage[]", async () => {
mockStreamText.mockReturnValue(createMockStreamResult([]))

const stream = handler.createMessage(systemPrompt, mockMessages)
for await (const _chunk of stream) {
// consume
}

expect(convertToAiSdkMessages).toHaveBeenCalledWith(mockMessages)
// Messages are now already in ModelMessage format, passed directly to streamText
expect(mockStreamText).toHaveBeenCalledWith(
expect.objectContaining({
messages: mockMessages,
}),
)
})

it("should pass tools through AI SDK conversion pipeline", async () => {
Expand Down
5 changes: 3 additions & 2 deletions src/api/providers/__tests__/azure.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// Use vi.hoisted to define mock functions that can be referenced in hoisted vi.mock() calls
const { mockStreamText, mockGenerateText, mockCreateAzure } = vi.hoisted(() => ({
mockStreamText: vi.fn(),
Expand Down Expand Up @@ -132,7 +133,7 @@ describe("AzureHandler", () => {

describe("createMessage", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [
Expand Down Expand Up @@ -376,7 +377,7 @@ describe("AzureHandler", () => {

describe("tools", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [{ type: "text" as const, text: "Use a tool" }],
Expand Down
3 changes: 2 additions & 1 deletion src/api/providers/__tests__/base-provider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
import { Anthropic } from "@anthropic-ai/sdk"

import type { ModelInfo } from "@roo-code/types"
Expand All @@ -7,7 +8,7 @@ import type { ApiStream } from "../../transform/stream"

// Create a concrete implementation for testing
class TestProvider extends BaseProvider {
createMessage(_systemPrompt: string, _messages: Anthropic.Messages.MessageParam[]): ApiStream {
createMessage(_systemPrompt: string, _messages: RooMessage[]): ApiStream {
throw new Error("Not implemented")
}

Expand Down
7 changes: 4 additions & 3 deletions src/api/providers/__tests__/baseten.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// npx vitest run src/api/providers/__tests__/baseten.spec.ts

// Use vi.hoisted to define mock functions that can be referenced in hoisted vi.mock() calls
Expand Down Expand Up @@ -101,7 +102,7 @@ describe("BasetenHandler", () => {

describe("createMessage", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [
Expand Down Expand Up @@ -281,7 +282,7 @@ describe("BasetenHandler", () => {

describe("tool handling", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [{ type: "text" as const, text: "Hello!" }],
Expand Down Expand Up @@ -389,7 +390,7 @@ describe("BasetenHandler", () => {

describe("error handling", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [{ type: "text" as const, text: "Hello!" }],
Expand Down
48 changes: 20 additions & 28 deletions src/api/providers/__tests__/bedrock.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// Mock TelemetryService before other imports
const mockCaptureException = vi.fn()

Expand Down Expand Up @@ -490,17 +491,14 @@ describe("AwsBedrockHandler", () => {
it("should properly pass image content through to streamText via AI SDK messages", async () => {
setupMockStreamText()

const messages: Anthropic.Messages.MessageParam[] = [
const messages: any[] = [
{
role: "user",
content: [
{
type: "image",
source: {
type: "base64",
data: mockImageData,
media_type: "image/jpeg",
},
image: `data:image/jpeg;base64,${mockImageData}`,
mimeType: "image/jpeg",
},
{
type: "text",
Expand Down Expand Up @@ -530,7 +528,7 @@ describe("AwsBedrockHandler", () => {
expect(userMsg).toBeDefined()
expect(Array.isArray(userMsg.content)).toBe(true)

// The AI SDK convertToAiSdkMessages converts images to { type: "image", image: "data:...", mimeType: "..." }
// Messages are already in AI SDK ImagePart format
const imagePart = userMsg.content.find((p: { type: string }) => p.type === "image")
expect(imagePart).toBeDefined()
expect(imagePart.image).toContain("data:image/jpeg;base64,")
Expand All @@ -544,29 +542,23 @@ describe("AwsBedrockHandler", () => {
it("should handle multiple images in a single message", async () => {
setupMockStreamText()

const messages: Anthropic.Messages.MessageParam[] = [
const messages: any[] = [
{
role: "user",
content: [
{
type: "image",
source: {
type: "base64",
data: mockImageData,
media_type: "image/jpeg",
},
image: `data:image/jpeg;base64,${mockImageData}`,
mimeType: "image/jpeg",
},
{
type: "text",
text: "First image",
},
{
type: "image",
source: {
type: "base64",
data: mockImageData,
media_type: "image/png",
},
image: `data:image/png;base64,${mockImageData}`,
mimeType: "image/png",
},
{
type: "text",
Expand Down Expand Up @@ -761,7 +753,7 @@ describe("AwsBedrockHandler", () => {
awsBedrock1MContext: true,
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -794,7 +786,7 @@ describe("AwsBedrockHandler", () => {
awsBedrock1MContext: false,
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -828,7 +820,7 @@ describe("AwsBedrockHandler", () => {
awsBedrock1MContext: true,
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -881,7 +873,7 @@ describe("AwsBedrockHandler", () => {
awsBedrock1MContext: true,
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -1013,7 +1005,7 @@ describe("AwsBedrockHandler", () => {
awsBedrockServiceTier: "PRIORITY",
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -1050,7 +1042,7 @@ describe("AwsBedrockHandler", () => {
awsBedrockServiceTier: "FLEX",
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -1087,7 +1079,7 @@ describe("AwsBedrockHandler", () => {
awsBedrockServiceTier: "PRIORITY", // Try to apply PRIORITY tier
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -1122,7 +1114,7 @@ describe("AwsBedrockHandler", () => {
// No awsBedrockServiceTier specified
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Test message",
Expand Down Expand Up @@ -1192,7 +1184,7 @@ describe("AwsBedrockHandler", () => {
awsRegion: "us-east-1",
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Hello",
Expand Down Expand Up @@ -1267,7 +1259,7 @@ describe("AwsBedrockHandler", () => {
awsRegion: "us-east-1",
})

const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Hello",
Expand Down
7 changes: 4 additions & 3 deletions src/api/providers/__tests__/deepseek.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// Use vi.hoisted to define mock functions that can be referenced in hoisted vi.mock() calls
const { mockStreamText, mockGenerateText } = vi.hoisted(() => ({
mockStreamText: vi.fn(),
Expand Down Expand Up @@ -173,7 +174,7 @@ describe("DeepSeekHandler", () => {

describe("createMessage", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [
Expand Down Expand Up @@ -400,7 +401,7 @@ describe("DeepSeekHandler", () => {

describe("reasoning content with deepseek-reasoner", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [
Expand Down Expand Up @@ -570,7 +571,7 @@ describe("DeepSeekHandler", () => {

describe("tool handling", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [{ type: "text" as const, text: "Hello!" }],
Expand Down
5 changes: 3 additions & 2 deletions src/api/providers/__tests__/fireworks.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// npx vitest run src/api/providers/__tests__/fireworks.spec.ts

// Use vi.hoisted to define mock functions that can be referenced in hoisted vi.mock() calls
Expand Down Expand Up @@ -363,7 +364,7 @@ describe("FireworksHandler", () => {

describe("createMessage", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [
Expand Down Expand Up @@ -730,7 +731,7 @@ describe("FireworksHandler", () => {

describe("tool handling", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: [{ type: "text" as const, text: "Hello!" }],
Expand Down
5 changes: 3 additions & 2 deletions src/api/providers/__tests__/gemini.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// npx vitest run src/api/providers/__tests__/gemini.spec.ts

import { NoOutputGeneratedError } from "ai"
Expand Down Expand Up @@ -102,7 +103,7 @@ describe("GeminiHandler", () => {
})

describe("createMessage", () => {
const mockMessages: Anthropic.Messages.MessageParam[] = [
const mockMessages: RooMessage[] = [
{
role: "user",
content: "Hello",
Expand Down Expand Up @@ -377,7 +378,7 @@ describe("GeminiHandler", () => {
})

describe("error telemetry", () => {
const mockMessages: Anthropic.Messages.MessageParam[] = [
const mockMessages: RooMessage[] = [
{
role: "user",
content: "Hello",
Expand Down
3 changes: 2 additions & 1 deletion src/api/providers/__tests__/lite-llm.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
const { mockStreamText, mockGenerateText } = vi.hoisted(() => ({
mockStreamText: vi.fn(),
mockGenerateText: vi.fn(),
Expand Down Expand Up @@ -257,7 +258,7 @@ describe("LiteLLMHandler", () => {
})

const systemPrompt = "You are a helpful assistant"
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
const messages: RooMessage[] = [{ role: "user", content: "Hello" }]

const generator = handler.createMessage(systemPrompt, messages)
for await (const _chunk of generator) {
Expand Down
3 changes: 2 additions & 1 deletion src/api/providers/__tests__/lmstudio.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RooMessage } from "../../../core/task-persistence/rooMessage"
// Use vi.hoisted to define mock functions that can be referenced in hoisted vi.mock() calls
const { mockStreamText, mockGenerateText, mockWrapLanguageModel } = vi.hoisted(() => ({
mockStreamText: vi.fn(),
Expand Down Expand Up @@ -60,7 +61,7 @@ describe("LmStudioHandler", () => {

describe("createMessage", () => {
const systemPrompt = "You are a helpful assistant."
const messages: Anthropic.Messages.MessageParam[] = [
const messages: RooMessage[] = [
{
role: "user",
content: "Hello!",
Expand Down
Loading
Loading