Skip to content

Commit 573cfc3

Browse files
mrubensroomote
andauthored
Default to native tools for all models in the Roo provider (#9811)
Co-authored-by: Roo Code <[email protected]>
1 parent d065b88 commit 573cfc3

File tree

3 files changed

+35
-49
lines changed

3 files changed

+35
-49
lines changed

src/api/providers/__tests__/roo.spec.ts

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ vitest.mock("../../providers/fetchers/modelCache", () => ({
101101
supportsPromptCache: true,
102102
inputPrice: 0,
103103
outputPrice: 0,
104+
defaultToolProtocol: "native",
104105
},
105106
"minimax/minimax-m2:free": {
106107
maxTokens: 32_768,
@@ -110,6 +111,7 @@ vitest.mock("../../providers/fetchers/modelCache", () => ({
110111
supportsNativeTools: true,
111112
inputPrice: 0.15,
112113
outputPrice: 0.6,
114+
defaultToolProtocol: "native",
113115
},
114116
"anthropic/claude-haiku-4.5": {
115117
maxTokens: 8_192,
@@ -119,6 +121,7 @@ vitest.mock("../../providers/fetchers/modelCache", () => ({
119121
supportsNativeTools: true,
120122
inputPrice: 0.8,
121123
outputPrice: 4,
124+
defaultToolProtocol: "native",
122125
},
123126
}
124127
}
@@ -425,28 +428,15 @@ describe("RooHandler", () => {
425428
}
426429
})
427430

428-
it("should apply defaultToolProtocol: native for minimax/minimax-m2:free", () => {
429-
const handlerWithMinimax = new RooHandler({
430-
apiModelId: "minimax/minimax-m2:free",
431-
})
432-
const modelInfo = handlerWithMinimax.getModel()
433-
expect(modelInfo.id).toBe("minimax/minimax-m2:free")
434-
expect((modelInfo.info as any).defaultToolProtocol).toBe("native")
435-
// Verify cached model info is preserved
436-
expect(modelInfo.info.maxTokens).toBe(32_768)
437-
expect(modelInfo.info.contextWindow).toBe(1_000_000)
438-
})
439-
440-
it("should apply defaultToolProtocol: native for anthropic/claude-haiku-4.5", () => {
441-
const handlerWithHaiku = new RooHandler({
442-
apiModelId: "anthropic/claude-haiku-4.5",
443-
})
444-
const modelInfo = handlerWithHaiku.getModel()
445-
expect(modelInfo.id).toBe("anthropic/claude-haiku-4.5")
446-
expect((modelInfo.info as any).defaultToolProtocol).toBe("native")
447-
// Verify cached model info is preserved
448-
expect(modelInfo.info.maxTokens).toBe(8_192)
449-
expect(modelInfo.info.contextWindow).toBe(200_000)
431+
it("should have defaultToolProtocol: native for all roo provider models", () => {
432+
// Test that all models have defaultToolProtocol: native
433+
const testModels = ["minimax/minimax-m2:free", "anthropic/claude-haiku-4.5", "xai/grok-code-fast-1"]
434+
for (const modelId of testModels) {
435+
const handlerWithModel = new RooHandler({ apiModelId: modelId })
436+
const modelInfo = handlerWithModel.getModel()
437+
expect(modelInfo.id).toBe(modelId)
438+
expect((modelInfo.info as any).defaultToolProtocol).toBe("native")
439+
}
450440
})
451441

452442
it("should not override existing properties when applying MODEL_DEFAULTS", () => {

src/api/providers/fetchers/__tests__/roo.spec.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ describe("getRooModels", () => {
127127
description: "Model that requires reasoning",
128128
deprecated: false,
129129
isFree: false,
130+
defaultTemperature: undefined,
131+
defaultToolProtocol: "native",
132+
isStealthModel: undefined,
130133
})
131134
})
132135

@@ -174,6 +177,9 @@ describe("getRooModels", () => {
174177
description: "Normal model without reasoning",
175178
deprecated: false,
176179
isFree: false,
180+
defaultTemperature: undefined,
181+
defaultToolProtocol: "native",
182+
isStealthModel: undefined,
177183
})
178184
})
179185

@@ -578,21 +584,21 @@ describe("getRooModels", () => {
578584
expect(models["test/native-tools-model"].defaultToolProtocol).toBe("native")
579585
})
580586

581-
it("should imply supportsNativeTools when default-native-tools tag is present without tool-use tag", async () => {
587+
it("should set defaultToolProtocol to native for all models regardless of tags", async () => {
582588
const mockResponse = {
583589
object: "list",
584590
data: [
585591
{
586-
id: "test/implicit-native-tools",
592+
id: "test/model-without-tool-tags",
587593
object: "model",
588594
created: 1234567890,
589595
owned_by: "test",
590-
name: "Implicit Native Tools Model",
591-
description: "Model with default-native-tools but no tool-use tag",
596+
name: "Model Without Tool Tags",
597+
description: "Model without any tool-related tags",
592598
context_window: 128000,
593599
max_tokens: 8192,
594600
type: "language",
595-
tags: ["default-native-tools"], // Only default-native-tools, no tool-use
601+
tags: [], // No tool-related tags
596602
pricing: {
597603
input: "0.0001",
598604
output: "0.0002",
@@ -608,21 +614,22 @@ describe("getRooModels", () => {
608614

609615
const models = await getRooModels(baseUrl, apiKey)
610616

611-
expect(models["test/implicit-native-tools"].supportsNativeTools).toBe(true)
612-
expect(models["test/implicit-native-tools"].defaultToolProtocol).toBe("native")
617+
// All Roo provider models now default to native tool protocol
618+
expect(models["test/model-without-tool-tags"].supportsNativeTools).toBe(false)
619+
expect(models["test/model-without-tool-tags"].defaultToolProtocol).toBe("native")
613620
})
614621

615-
it("should not set defaultToolProtocol when default-native-tools tag is not present", async () => {
622+
it("should set supportsNativeTools from tool-use tag and always set defaultToolProtocol to native", async () => {
616623
const mockResponse = {
617624
object: "list",
618625
data: [
619626
{
620-
id: "test/non-native-model",
627+
id: "test/tool-use-model",
621628
object: "model",
622629
created: 1234567890,
623630
owned_by: "test",
624-
name: "Non-Native Tools Model",
625-
description: "Model without native tool calling default",
631+
name: "Tool Use Model",
632+
description: "Model with tool-use tag",
626633
context_window: 128000,
627634
max_tokens: 8192,
628635
type: "language",
@@ -642,8 +649,9 @@ describe("getRooModels", () => {
642649

643650
const models = await getRooModels(baseUrl, apiKey)
644651

645-
expect(models["test/non-native-model"].supportsNativeTools).toBe(true)
646-
expect(models["test/non-native-model"].defaultToolProtocol).toBeUndefined()
652+
// tool-use tag sets supportsNativeTools, and all models get defaultToolProtocol: native
653+
expect(models["test/tool-use-model"].supportsNativeTools).toBe(true)
654+
expect(models["test/tool-use-model"].defaultToolProtocol).toBe("native")
647655
})
648656

649657
it("should detect stealth mode from tags", async () => {

src/api/providers/fetchers/roo.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,9 @@ import { DEFAULT_HEADERS } from "../constants"
1010
// Exported so RooHandler.getModel() can also apply these for fallback cases
1111
export const MODEL_DEFAULTS: Record<string, Partial<ModelInfo>> = {
1212
"minimax/minimax-m2:free": {
13-
defaultToolProtocol: "native",
1413
includedTools: ["search_and_replace"],
1514
excludedTools: ["apply_diff"],
1615
},
17-
"anthropic/claude-haiku-4.5": {
18-
defaultToolProtocol: "native",
19-
},
20-
"xai/grok-code-fast-1": {
21-
defaultToolProtocol: "native",
22-
},
2316
}
2417

2518
/**
@@ -109,13 +102,8 @@ export async function getRooModels(baseUrl: string, apiKey?: string): Promise<Mo
109102
// Determine if the model requires reasoning effort based on tags
110103
const requiredReasoningEffort = tags.includes("reasoning-required")
111104

112-
// Determine if native tool calling should be the default protocol for this model
113-
const hasDefaultNativeTools = tags.includes("default-native-tools")
114-
const defaultToolProtocol = hasDefaultNativeTools ? ("native" as const) : undefined
115-
116105
// Determine if the model supports native tool calling based on tags
117-
// default-native-tools implies tool-use support
118-
const supportsNativeTools = tags.includes("tool-use") || hasDefaultNativeTools
106+
const supportsNativeTools = tags.includes("tool-use")
119107

120108
// Determine if the model should hide vendor/company identity (stealth mode)
121109
const isStealthModel = tags.includes("stealth")
@@ -143,7 +131,7 @@ export async function getRooModels(baseUrl: string, apiKey?: string): Promise<Mo
143131
deprecated: model.deprecated || false,
144132
isFree: tags.includes("free"),
145133
defaultTemperature: model.default_temperature,
146-
defaultToolProtocol,
134+
defaultToolProtocol: "native" as const,
147135
isStealthModel: isStealthModel || undefined,
148136
}
149137

0 commit comments

Comments
 (0)