Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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: 0 additions & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export interface ApiHandlerCreateMessageMetadata {
* Can be "none", "auto", "required", or a specific tool choice.
*/
tool_choice?: OpenAI.Chat.ChatCompletionCreateParams["tool_choice"]
// Tool calling is native-only.
/**
* Controls whether the model can return multiple tool calls in a single response.
* When true, parallel tool calls are enabled (OpenAI's parallel_tool_calls=true).
Expand Down
2 changes: 0 additions & 2 deletions src/api/providers/__tests__/lite-llm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,6 @@ describe("LiteLLMHandler", () => {
function: { name: "read_file", description: "Read a file", parameters: {} },
},
],
// Tool calling is native-only; legacy protocol fields are not supported.
}

const generator = handler.createMessage(systemPrompt, messages, metadata as any)
Expand Down Expand Up @@ -700,7 +699,6 @@ describe("LiteLLMHandler", () => {
function: { name: "read_file", description: "Read a file", parameters: {} },
},
],
// Tool calling is native-only; legacy protocol fields are not supported.
}

const generator = handler.createMessage(systemPrompt, messages, metadata as any)
Expand Down
3 changes: 1 addition & 2 deletions src/api/providers/fetchers/ollama.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ export const parseOllamaModel = (rawModel: OllamaModelInfoResponse): ModelInfo |
const contextWindow =
contextKey && typeof rawModel.model_info[contextKey] === "number" ? rawModel.model_info[contextKey] : undefined

// Filter out models that don't support tools.
// Roo Code tool calling is native-only; models without tool capability won't work.
// Filter out models that don't support tools. Models without tool capability won't work.
const supportsTools = rawModel.capabilities?.includes("tools") ?? false
if (!supportsTools) {
return null
Expand Down
1 change: 0 additions & 1 deletion src/api/providers/openrouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
consolidateReasoningDetails,
} from "../transform/openai-format"
import { normalizeMistralToolCallId } from "../transform/mistral-format"
// Tool calling is native-only.
import { ApiStreamChunk } from "../transform/stream"
import { convertToR1Format } from "../transform/r1-format"
import { addCacheBreakpoints as addAnthropicCacheBreakpoints } from "../transform/caching/anthropic"
Expand Down
3 changes: 1 addition & 2 deletions src/api/transform/model-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ export function getModelParams({
format,
...params,
reasoning: getOpenAiReasoning({ model, reasoningBudget, reasoningEffort, settings }),
// Tool calling is native-only; whether tools are included is determined
// by whether the caller provided tool definitions.
// Whether tools are included is determined by whether the caller provided tool definitions.
}
} else if (format === "gemini") {
return {
Expand Down
5 changes: 2 additions & 3 deletions src/core/condense/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import { supportPrompt } from "../../shared/support-prompt"

/**
* Checks if a message contains tool_result blocks.
* For native tools protocol, user messages with tool_result blocks require
* corresponding tool_use blocks from the previous assistant turn.
* User messages with tool_result blocks require corresponding tool_use blocks from the previous assistant turn.
*/
function hasToolResultBlocks(message: ApiMessage): boolean {
if (message.role !== "user" || typeof message.content === "string") {
Expand Down Expand Up @@ -187,7 +186,7 @@ export type SummarizeResponse = {
* @param {boolean} isAutomaticTrigger - Whether the summarization is triggered automatically
* @param {string} customCondensingPrompt - Optional custom prompt to use for condensing
* @param {ApiHandler} condensingApiHandler - Optional specific API handler to use for condensing
* @param {boolean} useNativeTools - Whether native tools protocol is being used (requires tool_use/tool_result pairing)
* @param {boolean} useNativeTools - Whether to preserve tool_use/tool_result pairing in summarization
* @returns {SummarizeResponse} - The result of the summarization operation (see above)
*/
export async function summarizeConversation(
Expand Down
1 change: 0 additions & 1 deletion src/core/environment/getEnvironmentDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ export async function getEnvironmentDetails(cline: Task, includeFileDetails: boo
language: language ?? formatLanguage(vscode.env.language),
})

// Tool calling is native-only.
const toolFormat = "native"

details += `\n\n# Current Mode\n`
Expand Down
2 changes: 1 addition & 1 deletion src/core/prompts/__tests__/system-prompt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ describe("SYSTEM_PROMPT", () => {
expect(prompt).not.toContain("## update_todo_list")
})

it("should include native tool instructions (native-only)", async () => {
it("should include native tool instructions", async () => {
const settings = {
maxConcurrentFileReads: 5,
todoListEnabled: true,
Expand Down
80 changes: 39 additions & 41 deletions src/core/prompts/sections/__tests__/tool-use-guidelines.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,56 @@ import { getToolUseGuidelinesSection } from "../tool-use-guidelines"
import { EXPERIMENT_IDS } from "../../../../shared/experiments"

describe("getToolUseGuidelinesSection", () => {
describe("native-only", () => {
describe("with MULTIPLE_NATIVE_TOOL_CALLS disabled (default)", () => {
it("should include proper numbered guidelines", () => {
const guidelines = getToolUseGuidelinesSection()
describe("with MULTIPLE_NATIVE_TOOL_CALLS disabled (default)", () => {
it("should include proper numbered guidelines", () => {
const guidelines = getToolUseGuidelinesSection()

// Check that all numbered items are present with correct numbering
expect(guidelines).toContain("1. Assess what information")
expect(guidelines).toContain("2. Choose the most appropriate tool")
expect(guidelines).toContain("3. If multiple actions are needed")
expect(guidelines).toContain("4. After each tool use")
})
// Check that all numbered items are present with correct numbering
expect(guidelines).toContain("1. Assess what information")
expect(guidelines).toContain("2. Choose the most appropriate tool")
expect(guidelines).toContain("3. If multiple actions are needed")
expect(guidelines).toContain("4. After each tool use")
})

it("should include single-tool-per-message guidance when experiment disabled", () => {
const guidelines = getToolUseGuidelinesSection({})
it("should include single-tool-per-message guidance when experiment disabled", () => {
const guidelines = getToolUseGuidelinesSection({})

expect(guidelines).toContain("use one tool at a time per message")
expect(guidelines).not.toContain("you may use multiple tools in a single message")
expect(guidelines).not.toContain("Formulate your tool use using")
expect(guidelines).toContain("ALWAYS wait for user confirmation")
})
expect(guidelines).toContain("use one tool at a time per message")
expect(guidelines).not.toContain("you may use multiple tools in a single message")
expect(guidelines).not.toContain("Formulate your tool use using")
expect(guidelines).toContain("ALWAYS wait for user confirmation")
})

it("should include simplified iterative process guidelines", () => {
const guidelines = getToolUseGuidelinesSection()
it("should include simplified iterative process guidelines", () => {
const guidelines = getToolUseGuidelinesSection()

expect(guidelines).toContain("carefully considering the user's response after each tool use")
expect(guidelines).toContain("It is crucial to proceed step-by-step")
})
expect(guidelines).toContain("carefully considering the user's response after each tool use")
expect(guidelines).toContain("It is crucial to proceed step-by-step")
})
})

describe("with MULTIPLE_NATIVE_TOOL_CALLS enabled", () => {
it("should include multiple-tools-per-message guidance when experiment enabled", () => {
const guidelines = getToolUseGuidelinesSection({
[EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS]: true,
})

expect(guidelines).toContain("you may use multiple tools in a single message")
expect(guidelines).not.toContain("use one tool at a time per message")
expect(guidelines).not.toContain("After each tool use, the user will respond")
describe("with MULTIPLE_NATIVE_TOOL_CALLS enabled", () => {
it("should include multiple-tools-per-message guidance when experiment enabled", () => {
const guidelines = getToolUseGuidelinesSection({
[EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS]: true,
})

it("should use simplified footer without step-by-step language", () => {
const guidelines = getToolUseGuidelinesSection({
[EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS]: true,
})
expect(guidelines).toContain("you may use multiple tools in a single message")
expect(guidelines).not.toContain("use one tool at a time per message")
expect(guidelines).not.toContain("After each tool use, the user will respond")
})

// When multiple tools per message is enabled, we don't want the
// "step-by-step" or "after each tool use" language that would
// contradict the ability to batch tool calls.
expect(guidelines).toContain("carefully considering the user's response after tool executions")
expect(guidelines).not.toContain("It is crucial to proceed step-by-step")
expect(guidelines).not.toContain("ALWAYS wait for user confirmation after each tool use")
it("should use simplified footer without step-by-step language", () => {
const guidelines = getToolUseGuidelinesSection({
[EXPERIMENT_IDS.MULTIPLE_NATIVE_TOOL_CALLS]: true,
})

// When multiple tools per message is enabled, we don't want the
// "step-by-step" or "after each tool use" language that would
// contradict the ability to batch tool calls.
expect(guidelines).toContain("carefully considering the user's response after tool executions")
expect(guidelines).not.toContain("It is crucial to proceed step-by-step")
expect(guidelines).not.toContain("ALWAYS wait for user confirmation after each tool use")
})
})

Expand Down
12 changes: 6 additions & 6 deletions src/core/prompts/sections/__tests__/tool-use.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ describe("getSharedToolUseSection", () => {
describe("native tool calling", () => {
it("should include one tool per message requirement when experiment is disabled", () => {
// No experiment flags passed (default: disabled)
const section = getSharedToolUseSection("native")
const section = getSharedToolUseSection()

expect(section).toContain("You must use exactly one tool call per assistant response")
expect(section).toContain("Do not call zero tools or more than one tool")
})

it("should include one tool per message requirement when experiment is explicitly disabled", () => {
const section = getSharedToolUseSection("native", { multipleNativeToolCalls: false })
const section = getSharedToolUseSection({ multipleNativeToolCalls: false })

expect(section).toContain("You must use exactly one tool call per assistant response")
expect(section).toContain("Do not call zero tools or more than one tool")
})

it("should NOT include one tool per message requirement when experiment is enabled", () => {
const section = getSharedToolUseSection("native", { multipleNativeToolCalls: true })
const section = getSharedToolUseSection({ multipleNativeToolCalls: true })

expect(section).not.toContain("You must use exactly one tool per message")
expect(section).not.toContain("every assistant message must include a tool call")
Expand All @@ -27,22 +27,22 @@ describe("getSharedToolUseSection", () => {
})

it("should include native tool-calling instructions", () => {
const section = getSharedToolUseSection("native")
const section = getSharedToolUseSection()

expect(section).toContain("provider-native tool-calling mechanism")
expect(section).toContain("Do not include XML markup or examples")
})

it("should NOT include XML formatting instructions", () => {
const section = getSharedToolUseSection("native")
const section = getSharedToolUseSection()

expect(section).not.toContain("<actual_tool_name>")
expect(section).not.toContain("</actual_tool_name>")
})
})

describe("default (native-only)", () => {
it("should default to native tool calling when no mode is specified", () => {
it("should default to native tool calling when no arguments are provided", () => {
const section = getSharedToolUseSection()
expect(section).toContain("provider-native tool-calling mechanism")
// No legacy XML-tag tool-calling remnants
Expand Down
3 changes: 1 addition & 2 deletions src/core/prompts/sections/tool-use.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { experiments, EXPERIMENT_IDS } from "../../../shared/experiments"

export function getSharedToolUseSection(_protocol = "native", experimentFlags?: Record<string, boolean>): string {
// Tool calling is native-only.
export function getSharedToolUseSection(experimentFlags?: Record<string, boolean>): string {
// Check if multiple native tool calls is enabled via experiment
const isMultipleNativeToolCallsEnabled = experiments.isEnabled(
experimentFlags ?? {},
Expand Down
7 changes: 2 additions & 5 deletions src/core/prompts/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ async function generatePrompt(

const codeIndexManager = CodeIndexManager.getInstance(context, cwd)

// Tool calling is native-only.
const effectiveProtocol = "native"

const [modesSection, mcpServersSection, skillsSection] = await Promise.all([
getModesSection(context),
shouldIncludeMcp
Expand All @@ -93,14 +90,14 @@ async function generatePrompt(
getSkillsSection(skillsManager, mode as string),
])

// Tools catalog is not included in the system prompt in native-only mode.
// Tools catalog is not included in the system prompt.
const toolsCatalog = ""

const basePrompt = `${roleDefinition}

${markdownFormattingSection()}

${getSharedToolUseSection(effectiveProtocol, experiments)}${toolsCatalog}
${getSharedToolUseSection(experiments)}${toolsCatalog}

${getToolUseGuidelinesSection(experiments)}

Expand Down
1 change: 0 additions & 1 deletion src/core/task-persistence/taskMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ export async function taskMetadata({
// initialStatus is included when provided (e.g., "active" for child tasks)
// to ensure the status is set from the very first save, avoiding race conditions
// where attempt_completion might run before a separate status update.
// Tool calling is native-only.
const historyItem: HistoryItem = {
id,
rootTaskId,
Expand Down
16 changes: 3 additions & 13 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
*/
private _taskMode: string | undefined

// Tool calling is native-only.

/**
* Promise that resolves when the task mode has been initialized.
* This ensures async mode initialization completes before the task is used.
Expand Down Expand Up @@ -385,7 +383,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
didAlreadyUseTool = false
didToolFailInCurrentTurn = false
didCompleteReadingStream = false
// Tool calling is native-only; no streaming parser is required.
// No streaming parser is required.
assistantMessageParser?: undefined
private providerProfileChangeListener?: (config: { name: string; provider?: string }) => void

Expand Down Expand Up @@ -1501,8 +1499,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

/**
* Updates the API configuration and rebuilds the API handler.
* Tool calling is native-only, so there is no tool-protocol switching or
* tool parser swapping here.
* There is no tool-protocol switching or tool parser swapping.
*
* @param newApiConfiguration - The new API configuration to use
*/
Expand Down Expand Up @@ -1595,7 +1592,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

const { contextTokens: prevContextTokens } = this.getTokenUsage()

// Tool calling is native-only; pass through so summarization preserves tool_use/tool_result integrity.
// Pass through so summarization preserves tool_use/tool_result integrity.
const useNativeTools = true

const {
Expand Down Expand Up @@ -1951,8 +1948,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// the task first.
this.apiConversationHistory = await this.getSavedApiConversationHistory()

// Tool calling is native-only.

const lastClineMessage = this.clineMessages
.slice()
.reverse()
Expand Down Expand Up @@ -3709,7 +3704,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
`Forcing truncation to ${FORCED_CONTEXT_REDUCTION_PERCENT}% of current context.`,
)

// Tool calling is native-only.
const useNativeTools = true

// Send condenseTaskContextStarted to show in-progress indicator
Expand Down Expand Up @@ -3877,7 +3871,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// Get the current profile ID using the helper method
const currentProfileId = this.getCurrentProfileId(state)

// Tool calling is native-only.
const useNativeTools = true

// Check if context management will likely run (threshold check)
Expand Down Expand Up @@ -4002,7 +3995,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
throw new Error("Auto-approval limit reached and user did not approve continuation")
}

// Tool calling is native-only.
// Whether we include tools is determined by whether we have any tools to send.
const modelInfo = this.api.getModel().info

Expand Down Expand Up @@ -4468,8 +4460,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
return this.workspacePath
}

// Tool protocol removed (native-only).

/**
* Provides convenient access to high-level message operations.
* Uses lazy initialization - the MessageManager is only created when first accessed.
Expand Down
2 changes: 0 additions & 2 deletions src/core/task/__tests__/task-tool-history.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ describe("Task Tool History Handling", () => {
},
]

// Tool calling is native-only; tool blocks must be preserved.

// Verify tool blocks are preserved
const assistantMessage = apiHistory[1]
const userMessage = apiHistory[2]
Expand Down
2 changes: 1 addition & 1 deletion src/core/tools/ReadFileTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ export class ReadFileTool extends BaseTool<"read_file"> {
task.didToolFailInCurrentTurn = true
}

// Build final result (native-only)
// Build final result
const finalResult = fileResults
.filter((result) => result.nativeContent)
.map((result) => result.nativeContent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ describe("Command Execution Timeout Integration", () => {
;(fs.access as any).mockResolvedValue(undefined)
;(TerminalRegistry.getOrCreateTerminal as any).mockResolvedValue(mockTerminal)

// Mock the executeCommandTool parameters (native-only)
// Mock the executeCommandTool parameters
mockBlock = {
type: "tool_use",
name: "execute_command",
Expand Down
1 change: 0 additions & 1 deletion src/core/tools/__tests__/readFileTool.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ function createMockCline(): any {
presentAssistantMessage: vi.fn(),
handleError: vi.fn().mockResolvedValue(undefined),
pushToolResult: vi.fn(),
// Tool calling is native-only; tests should not depend on legacy tag-stripping helpers.
fileContextTracker: {
trackFileContext: vi.fn().mockResolvedValue(undefined),
},
Expand Down
Loading