From 6956461cbec886905ce3758348355f0c94ca726c Mon Sep 17 00:00:00 2001 From: Christiaan Arnoldus Date: Wed, 17 Dec 2025 15:31:00 +0100 Subject: [PATCH 1/5] Add common parameters section (reasoning, verbosity) to CLI documentation --- cli/docs/PROVIDER_CONFIGURATION.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cli/docs/PROVIDER_CONFIGURATION.md b/cli/docs/PROVIDER_CONFIGURATION.md index 6746d75b4d4..ff392b68163 100644 --- a/cli/docs/PROVIDER_CONFIGURATION.md +++ b/cli/docs/PROVIDER_CONFIGURATION.md @@ -6,6 +6,7 @@ This guide provides detailed information on how to configure each provider in Ki - [Introduction](#introduction) - [Configuration Methods](#configuration-methods) +- [Common Parameters](#common-parameters) - [Provider Details](#provider-details) - [Kilo Code](#kilocode) - [Anthropic](#anthropic) @@ -64,6 +65,17 @@ You can configure providers using: --- +## Common Parameters + +**Description**: Parameters that are shared by all providers. + +**Optional Fields**: + +- `enableReasoningEffort` (boolean): Enable or disable reasoning for supported models. Many models have no, dynamic or compulsive reasoning regardless of this setting. Must be set to `true` for `reasoningEffort` or `modelMaxThinkingTokens` to take effect. +- `reasoningEffort` (text): Specify reasoning effort for supported models. Can be `"low"`, `"medium"`, `"high"` or `"xhigh"`. Requires `enableReasoningEffort` to be `true`, mutually exclusive with `modelMaxThinkingTokens`. +- `modelMaxThinkingTokens` (number): Specify reasoning token limit for supported models (mainly Claude models). Requires `enableReasoningEffort` to be `true`, mutually exclusive with `reasoningEffort`. +- `verbosity` (text): Controls the verbosity and length of the model response for supported models (mainly GPT-5.x and Claude Opus 4.5). Also known as output effort. Supported values are `"low"`, `"medium"` and `"high"`. + ## Provider Details ### kilocode From 1b61d67cf3b7c9c7a6a356ebf4e2e77426cdf52b Mon Sep 17 00:00:00 2001 From: Christiaan Arnoldus Date: Wed, 17 Dec 2025 16:31:11 +0100 Subject: [PATCH 2/5] Remove duplicate tool processing from OpenAI-compatible providers by mostly reverting to Roo version should fix #4529 --- .../base-openai-compatible-provider.ts | 10 ++---- src/api/providers/openai.ts | 35 +++---------------- 2 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/api/providers/base-openai-compatible-provider.ts b/src/api/providers/base-openai-compatible-provider.ts index ef549a42f0b..605a6583da1 100644 --- a/src/api/providers/base-openai-compatible-provider.ts +++ b/src/api/providers/base-openai-compatible-provider.ts @@ -1,7 +1,7 @@ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" -import { type ModelInfo } from "@roo-code/types" +import type { ModelInfo } from "@roo-code/types" import { type ApiHandlerOptions, getModelMaxOutputTokens } from "../../shared/api" import { XmlMatcher } from "../../utils/xml-matcher" @@ -15,7 +15,6 @@ import { verifyFinishReason } from "./kilocode/verifyFinishReason" import { handleOpenAIError } from "./utils/openai-error-handler" import { fetchWithTimeout } from "./kilocode/fetchWithTimeout" // kilocode_change import { getApiRequestTimeout } from "./utils/timeout-config" // kilocode_change -import { ToolCallAccumulator } from "./kilocode/nativeToolCallHelpers" // kilocode_change import { calculateApiCostOpenAI } from "../../shared/cost" type BaseOpenAiCompatibleProviderOptions = ApiHandlerOptions & { @@ -135,16 +134,11 @@ export abstract class BaseOpenAiCompatibleProvider }) as const, ) - const toolCallAccumulator = new ToolCallAccumulator() // kilocode_change let lastUsage: OpenAI.CompletionUsage | undefined for await (const chunk of stream) { verifyFinishReason(chunk.choices?.[0]) // kilocode_change - const delta = chunk.choices?.[0]?.delta - - yield* toolCallAccumulator.processChunk(chunk) // kilocode_change - // Check for provider-specific error responses (e.g., MiniMax base_resp) const chunkAny = chunk as any if (chunkAny.base_resp?.status_code && chunkAny.base_resp.status_code !== 0) { @@ -153,6 +147,8 @@ export abstract class BaseOpenAiCompatibleProvider ) } + const delta = chunk.choices?.[0]?.delta + if (delta?.content) { for (const processedChunk of matcher.update(delta.content)) { yield processedChunk diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index 207a9fa26f6..2a2065edd6e 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -19,7 +19,7 @@ import { convertToR1Format } from "../transform/r1-format" import { convertToSimpleMessages } from "../transform/simple-format" import { ApiStream, ApiStreamUsageChunk } from "../transform/stream" import { getModelParams } from "../transform/model-params" -import { ToolCallAccumulator } from "./kilocode/nativeToolCallHelpers" + import { DEFAULT_HEADERS } from "./constants" import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index" @@ -194,33 +194,22 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl ) let lastUsage - const toolCallAccumulator = new ToolCallAccumulator() // kilocode_change for await (const chunk of stream) { const delta = chunk.choices?.[0]?.delta ?? {} - yield* toolCallAccumulator.processChunk(chunk) // kilocode_change - if (delta.content) { for (const chunk of matcher.update(delta.content)) { yield chunk } } - // kilocode_change start: reasoning - const reasoningText = - "reasoning_content" in delta && typeof delta.reasoning_content === "string" - ? delta.reasoning_content - : "reasoning" in delta && typeof delta.reasoning === "string" - ? delta.reasoning - : undefined - if (reasoningText) { + if ("reasoning_content" in delta && delta.reasoning_content) { yield { type: "reasoning", - text: reasoningText, + text: (delta.reasoning_content as string | undefined) || "", } } - // kilocode_change end if (delta.tool_calls) { for (const toolCall of delta.tool_calls) { @@ -274,23 +263,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl throw handleOpenAIError(error, this.providerName) } - // kilocode_change start: reasoning - const message = response.choices[0]?.message - if (message) { - if ("reasoning" in message && typeof message.reasoning === "string") { - yield { - type: "reasoning", - text: message.reasoning, - } - } - if (message.content) { - yield { - type: "text", - text: message.content || "", - } - } - } - // kilocode_change end + const message = response.choices?.[0]?.message if (message?.tool_calls) { for (const toolCall of message.tool_calls) { From b826dc6608119ae3c77d80b13cc6762a706f6167 Mon Sep 17 00:00:00 2001 From: Christiaan Arnoldus Date: Wed, 17 Dec 2025 17:12:45 +0100 Subject: [PATCH 3/5] Revert --- src/api/providers/openai.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index 2a2065edd6e..e1e6c66b24a 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -204,12 +204,20 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl } } - if ("reasoning_content" in delta && delta.reasoning_content) { + // kilocode_change start: reasoning + const reasoningText = + "reasoning_content" in delta && typeof delta.reasoning_content === "string" + ? delta.reasoning_content + : "reasoning" in delta && typeof delta.reasoning === "string" + ? delta.reasoning + : undefined + if (reasoningText) { yield { type: "reasoning", - text: (delta.reasoning_content as string | undefined) || "", + text: reasoningText, } } + // kilocode_change end if (delta.tool_calls) { for (const toolCall of delta.tool_calls) { @@ -263,7 +271,23 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl throw handleOpenAIError(error, this.providerName) } - const message = response.choices?.[0]?.message + // kilocode_change start: reasoning + const message = response.choices[0]?.message + if (message) { + if ("reasoning" in message && typeof message.reasoning === "string") { + yield { + type: "reasoning", + text: message.reasoning, + } + } + if (message.content) { + yield { + type: "text", + text: message.content || "", + } + } + } + // kilocode_change end if (message?.tool_calls) { for (const toolCall of message.tool_calls) { From 9413d730814d88ac67c88e6eec9a66c2c701613e Mon Sep 17 00:00:00 2001 From: Christiaan Arnoldus Date: Wed, 17 Dec 2025 17:13:26 +0100 Subject: [PATCH 4/5] Changeset --- .changeset/silly-lamps-create.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/silly-lamps-create.md diff --git a/.changeset/silly-lamps-create.md b/.changeset/silly-lamps-create.md new file mode 100644 index 00000000000..897d1154b5a --- /dev/null +++ b/.changeset/silly-lamps-create.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Fix duplicate tool processing in OpenAI-compatible provider From 51f4774adcb90778826e00e9a50c45bb7bf11bc8 Mon Sep 17 00:00:00 2001 From: Kevin van Dijk Date: Wed, 17 Dec 2025 20:49:33 +0100 Subject: [PATCH 5/5] Fix image generation handler not using Kilo Gateway properly --- .changeset/little-ravens-rest.md | 5 +++ src/core/tools/GenerateImageTool.ts | 47 +++++++++++++---------------- 2 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 .changeset/little-ravens-rest.md diff --git a/.changeset/little-ravens-rest.md b/.changeset/little-ravens-rest.md new file mode 100644 index 00000000000..d56f2dded97 --- /dev/null +++ b/.changeset/little-ravens-rest.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Fix image generation handler not using Kilo Gateway properly diff --git a/src/core/tools/GenerateImageTool.ts b/src/core/tools/GenerateImageTool.ts index 9aef22dc1ae..91ee15c3566 100644 --- a/src/core/tools/GenerateImageTool.ts +++ b/src/core/tools/GenerateImageTool.ts @@ -203,17 +203,12 @@ export class GenerateImageTool extends BaseTool<"generate_image"> { } let result - if (modelProvider === "kilocode") { - // kilocode_change: Updated from "roo" to "kilocode" provider - // Use Kilo Code Cloud provider (supports both chat completions and images API via OpenRouter) - const rooHandler = new RooHandler({} as any) - result = await rooHandler.generateImage(prompt, selectedModel, inputImageData, apiMethod) - } else { - // Use OpenRouter provider (only supports chat completions API) - // kilocode_change start - const openRouterHandler = openRouterApiKey - ? new OpenRouterHandler({}) - : new KilocodeOpenrouterHandler({ + // kilocode_change start: Updated from "roo" to "kilocode" provider + // Use Kilo Code Cloud provider (supports both chat completions and images API via OpenRouter) + // Use OpenRouter provider (only supports chat completions API) + const handler = + modelProvider === "kilocode" + ? new KilocodeOpenrouterHandler({ kilocodeToken: kiloCodeApiKey, kilocodeOrganizationId: task.apiConfiguration.apiProvider === "kilocode" && @@ -221,21 +216,21 @@ export class GenerateImageTool extends BaseTool<"generate_image"> { ? task.apiConfiguration.kilocodeOrganizationId : undefined, }) - // kilocode_change end - result = await openRouterHandler.generateImage( - prompt, - selectedModel, - // kilocode_change start - openRouterApiKey || - kiloCodeApiKey || - (() => { - throw new Error("Unreachable because of earlier check.") - })(), - // kilocode_change end - inputImageData, - task.taskId, // kilocode_change - ) - } + : new OpenRouterHandler({}) + result = await handler.generateImage( + prompt, + selectedModel, + openRouterApiKey || + kiloCodeApiKey || + (() => { + throw new Error("Unreachable because of earlier check.") + })(), + + inputImageData, + task.taskId, + ) + + // kilocode_change end if (!result.success) { await task.say("error", result.error || "Failed to generate image")