Skip to content
Open
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
3 changes: 3 additions & 0 deletions packages/types/src/provider-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ const openAiSchema = baseProviderSettingsSchema.extend({
openAiStreamingEnabled: z.boolean().optional(),
openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration.
openAiHeaders: z.record(z.string(), z.string()).optional(),
// When enabled, adds strict: true to tool definitions and modifies schemas for OpenAI strict mode.
// Disable this for providers like kie.ai that don't support OpenAI's strict mode.
openAiStrictToolMode: z.boolean().optional(),
})

const ollamaSchema = baseProviderSettingsSchema.extend({
Expand Down
12 changes: 11 additions & 1 deletion src/api/providers/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ export abstract class BaseProvider implements ApiHandler {
* Converts an array of tools to be compatible with OpenAI's strict mode.
* Filters for function tools, applies schema conversion to their parameters,
* and ensures all tools have consistent strict: true values.
*
* @param tools - Array of tools to convert
* @param useStrictMode - When true (default), adds strict: true and modifies schemas for OpenAI strict mode.
* When false, skips strict mode modifications for providers that don't support it (e.g. kie.ai).
*/
protected convertToolsForOpenAI(tools: any[] | undefined): any[] | undefined {
protected convertToolsForOpenAI(tools: any[] | undefined, useStrictMode: boolean = true): any[] | undefined {
if (!tools) {
return undefined
}
Expand All @@ -38,6 +42,12 @@ export abstract class BaseProvider implements ApiHandler {
// to preserve optional parameters from the MCP server schema
const isMcp = isMcpTool(tool.function.name)

// When strict mode is disabled (for providers like kie.ai), don't add strict: true
// and don't modify the schema
if (!useStrictMode) {
return tool
}

return {
...tool,
function: {
Expand Down
20 changes: 16 additions & 4 deletions src/api/providers/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,18 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl

const isGrokXAI = this._isGrokXAI(this.options.openAiBaseUrl)

// Strict tool mode is enabled by default for backward compatibility
// Disable for providers like kie.ai that don't support OpenAI's strict mode
const useStrictToolMode = this.options.openAiStrictToolMode !== false

const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = {
model: modelId,
temperature: this.options.modelTemperature ?? (deepseekReasoner ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
messages: convertedMessages,
stream: true as const,
...(isGrokXAI ? {} : { stream_options: { include_usage: true } }),
...(reasoning && reasoning),
tools: this.convertToolsForOpenAI(metadata?.tools),
tools: this.convertToolsForOpenAI(metadata?.tools, useStrictToolMode),
tool_choice: metadata?.tool_choice,
parallel_tool_calls: metadata?.parallelToolCalls ?? false,
}
Expand Down Expand Up @@ -221,13 +225,17 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
yield this.processUsageMetrics(lastUsage, modelInfo)
}
} else {
// Strict tool mode is enabled by default for backward compatibility
// Disable for providers like kie.ai that don't support OpenAI's strict mode
const useStrictToolMode = this.options.openAiStrictToolMode !== false

const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = {
model: modelId,
messages: deepseekReasoner
? convertToR1Format([{ role: "user", content: systemPrompt }, ...messages])
: [systemMessage, ...convertToOpenAiMessages(messages)],
// Tools are always present (minimum ALWAYS_AVAILABLE_TOOLS)
tools: this.convertToolsForOpenAI(metadata?.tools),
tools: this.convertToolsForOpenAI(metadata?.tools, useStrictToolMode),
tool_choice: metadata?.tool_choice,
parallel_tool_calls: metadata?.parallelToolCalls ?? false,
}
Expand Down Expand Up @@ -329,6 +337,10 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
const modelInfo = this.getModel().info
const methodIsAzureAiInference = this._isAzureAiInference(this.options.openAiBaseUrl)

// Strict tool mode is enabled by default for backward compatibility
// Disable for providers like kie.ai that don't support OpenAI's strict mode
const useStrictToolMode = this.options.openAiStrictToolMode !== false

if (this.options.openAiStreamingEnabled ?? true) {
const isGrokXAI = this._isGrokXAI(this.options.openAiBaseUrl)

Expand All @@ -346,7 +358,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
reasoning_effort: modelInfo.reasoningEffort as "low" | "medium" | "high" | undefined,
temperature: undefined,
// Tools are always present (minimum ALWAYS_AVAILABLE_TOOLS)
tools: this.convertToolsForOpenAI(metadata?.tools),
tools: this.convertToolsForOpenAI(metadata?.tools, useStrictToolMode),
tool_choice: metadata?.tool_choice,
parallel_tool_calls: metadata?.parallelToolCalls ?? false,
}
Expand Down Expand Up @@ -380,7 +392,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
reasoning_effort: modelInfo.reasoningEffort as "low" | "medium" | "high" | undefined,
temperature: undefined,
// Tools are always present (minimum ALWAYS_AVAILABLE_TOOLS)
tools: this.convertToolsForOpenAI(metadata?.tools),
tools: this.convertToolsForOpenAI(metadata?.tools, useStrictToolMode),
tool_choice: metadata?.tool_choice,
parallel_tool_calls: metadata?.parallelToolCalls ?? false,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ export const OpenAICompatible = ({
onChange={handleInputChange("openAiStreamingEnabled", noTransform)}>
{t("settings:modelInfo.enableStreaming")}
</Checkbox>
<div>
<Checkbox
checked={apiConfiguration?.openAiStrictToolMode ?? true}
onChange={handleInputChange("openAiStrictToolMode", noTransform)}>
{t("settings:providers.openAi.strictToolMode")}
</Checkbox>
<div className="text-sm text-vscode-descriptionForeground ml-6">
{t("settings:providers.openAi.strictToolModeDescription")}
</div>
</div>
<div>
<Checkbox
checked={apiConfiguration?.includeMaxTokens ?? true}
Expand Down
4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/ca/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/de/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,10 @@
"learnMore": "Learn more about provider routing"
}
},
"openAi": {
"strictToolMode": "Enable strict tool mode",
"strictToolModeDescription": "Adds OpenAI-specific strict mode to tool definitions. Disable this for providers like kie.ai that don't support strict mode."
},
"customModel": {
"capabilities": "Configure the capabilities and pricing for your custom OpenAI-compatible model. Be careful when specifying the model capabilities, as they can affect how Roo Code performs.",
"maxTokens": {
Expand Down
4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/es/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/fr/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/hi/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/id/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/it/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/ja/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/ko/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/nl/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/pl/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/pt-BR/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/ru/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/tr/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/vi/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/zh-CN/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions webview-ui/src/i18n/locales/zh-TW/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading