From 844579903479ce0e9cc5cb0b02f92386b3ac38c9 Mon Sep 17 00:00:00 2001 From: Hannes Rudolph Date: Wed, 26 Nov 2025 21:14:23 -0700 Subject: [PATCH] fix(claude-code): disable native tools and temperature support Claude Code manages its own tools and temperature via the CLI, so these capabilities should be disabled in the model definitions. Also refactors ClaudeCodeHandler to not extend BaseProvider and adds proper TypeScript return types. --- packages/types/src/providers/claude-code.ts | 30 +++++++++++++++++++++ src/api/providers/claude-code.ts | 25 ++++++++++++----- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/packages/types/src/providers/claude-code.ts b/packages/types/src/providers/claude-code.ts index 599b22b908..988617e515 100644 --- a/packages/types/src/providers/claude-code.ts +++ b/packages/types/src/providers/claude-code.ts @@ -47,6 +47,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-sonnet-4-5-20250929[1m]": { ...anthropicModels["claude-sonnet-4-5"], @@ -56,6 +59,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-sonnet-4-20250514": { ...anthropicModels["claude-sonnet-4-20250514"], @@ -64,6 +70,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-opus-4-5-20251101": { ...anthropicModels["claude-opus-4-5-20251101"], @@ -72,6 +81,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-opus-4-1-20250805": { ...anthropicModels["claude-opus-4-1-20250805"], @@ -80,6 +92,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-opus-4-20250514": { ...anthropicModels["claude-opus-4-20250514"], @@ -88,6 +103,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-3-7-sonnet-20250219": { ...anthropicModels["claude-3-7-sonnet-20250219"], @@ -96,6 +114,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-3-5-sonnet-20241022": { ...anthropicModels["claude-3-5-sonnet-20241022"], @@ -104,6 +125,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-3-5-haiku-20241022": { ...anthropicModels["claude-3-5-haiku-20241022"], @@ -112,6 +136,9 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, "claude-haiku-4-5-20251001": { ...anthropicModels["claude-haiku-4-5-20251001"], @@ -120,5 +147,8 @@ export const claudeCodeModels = { supportsReasoningEffort: false, supportsReasoningBudget: false, requiredReasoningBudget: false, + // Claude Code manages its own tools and temperature via the CLI + supportsNativeTools: false, + supportsTemperature: false, }, } as const satisfies Record diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts index dfafb78aab..a15512d65f 100644 --- a/src/api/providers/claude-code.ts +++ b/src/api/providers/claude-code.ts @@ -6,23 +6,26 @@ import { type ModelInfo, getClaudeCodeModelId, } from "@roo-code/types" -import { type ApiHandler } from ".." +import { type ApiHandler, ApiHandlerCreateMessageMetadata } from ".." import { ApiStreamUsageChunk, type ApiStream } from "../transform/stream" import { runClaudeCode } from "../../integrations/claude-code/run" import { filterMessagesForClaudeCode } from "../../integrations/claude-code/message-filter" -import { BaseProvider } from "./base-provider" import { t } from "../../i18n" import { ApiHandlerOptions } from "../../shared/api" +import { countTokens } from "../../utils/countTokens" -export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { +export class ClaudeCodeHandler implements ApiHandler { private options: ApiHandlerOptions constructor(options: ApiHandlerOptions) { - super() this.options = options } - override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream { + async *createMessage( + systemPrompt: string, + messages: Anthropic.Messages.MessageParam[], + _metadata?: ApiHandlerCreateMessageMetadata, + ): ApiStream { // Filter out image blocks since Claude Code doesn't support them const filteredMessages = filterMessagesForClaudeCode(messages) @@ -42,7 +45,7 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { // Usage is included with assistant messages, // but cost is included in the result chunk - let usage: ApiStreamUsageChunk = { + const usage: ApiStreamUsageChunk = { type: "usage", inputTokens: 0, outputTokens: 0, @@ -121,6 +124,7 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { } } + // Accumulate usage across streaming chunks usage.inputTokens += message.usage.input_tokens usage.outputTokens += message.usage.output_tokens usage.cacheReadTokens = (usage.cacheReadTokens || 0) + (message.usage.cache_read_input_tokens || 0) @@ -138,7 +142,7 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { } } - getModel() { + getModel(): { id: string; info: ModelInfo } { const modelId = this.options.apiModelId if (modelId && modelId in claudeCodeModels) { const id = modelId as ClaudeCodeModelId @@ -165,6 +169,13 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { } } + async countTokens(content: Anthropic.Messages.ContentBlockParam[]): Promise { + if (content.length === 0) { + return 0 + } + return countTokens(content, { useWorker: true }) + } + private attemptParse(str: string) { try { return JSON.parse(str)