Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/types/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const modelInfoSchema = z.object({
supportsTemperature: z.boolean().optional(),
requiredReasoningBudget: z.boolean().optional(),
supportsReasoningEffort: z.boolean().optional(),
requiredReasoningEffort: z.boolean().optional(),
supportedParameters: z.array(modelParametersSchema).optional(),
inputPrice: z.number().optional(),
outputPrice: z.number().optional(),
Expand Down
152 changes: 152 additions & 0 deletions src/api/providers/__tests__/roo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,28 @@ vitest.mock("../../../i18n", () => ({
}),
}))

// Mock model cache
vitest.mock("../../providers/fetchers/modelCache", () => ({
getModels: vitest.fn(),
flushModels: vitest.fn(),
getModelsFromCache: vitest.fn((provider: string) => {
if (provider === "roo") {
return {
"xai/grok-code-fast-1": {
maxTokens: 16_384,
contextWindow: 262_144,
supportsImages: false,
supportsReasoningEffort: true, // Enable reasoning for tests
supportsPromptCache: true,
inputPrice: 0,
outputPrice: 0,
},
}
}
return {}
}),
}))

// Import after mocks are set up
import { RooHandler } from "../roo"
import { CloudService } from "@roo-code/cloud"
Expand Down Expand Up @@ -446,4 +468,134 @@ describe("RooHandler", () => {
expect(handler).toBeInstanceOf(RooHandler)
})
})

describe("reasoning effort support", () => {
it("should not include reasoning when not enabled", async () => {
handler = new RooHandler(mockOptions)
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
model: mockOptions.apiModelId,
messages: expect.any(Array),
stream: true,
stream_options: { include_usage: true },
}),
undefined,
)
// Verify reasoning is not included
const callArgs = mockCreate.mock.calls[0][0]
expect(callArgs.reasoning).toBeUndefined()
})

it("should include reasoning with enabled: false when explicitly disabled", async () => {
handler = new RooHandler({
...mockOptions,
enableReasoningEffort: false,
})
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
reasoning: { enabled: false },
}),
undefined,
)
})

it("should include reasoning with enabled: true and effort: low", async () => {
handler = new RooHandler({
...mockOptions,
reasoningEffort: "low",
})
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
reasoning: { enabled: true, effort: "low" },
}),
undefined,
)
})

it("should include reasoning with enabled: true and effort: medium", async () => {
handler = new RooHandler({
...mockOptions,
reasoningEffort: "medium",
})
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
reasoning: { enabled: true, effort: "medium" },
}),
undefined,
)
})

it("should include reasoning with enabled: true and effort: high", async () => {
handler = new RooHandler({
...mockOptions,
reasoningEffort: "high",
})
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
reasoning: { enabled: true, effort: "high" },
}),
undefined,
)
})

it("should not include reasoning for minimal (treated as none)", async () => {
handler = new RooHandler({
...mockOptions,
reasoningEffort: "minimal",
})
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

// minimal should result in no reasoning parameter
const callArgs = mockCreate.mock.calls[0][0]
expect(callArgs.reasoning).toBeUndefined()
})

it("should handle enableReasoningEffort: false overriding reasoningEffort setting", async () => {
handler = new RooHandler({
...mockOptions,
enableReasoningEffort: false,
reasoningEffort: "high",
})
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume stream
}

// When explicitly disabled, should send enabled: false regardless of effort setting
expect(mockCreate).toHaveBeenCalledWith(
expect.objectContaining({
reasoning: { enabled: false },
}),
undefined,
)
})
})
})
Loading
Loading