mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
feat: add openAiStrictToolMode setting for OpenAI-compatible providers
This adds a new setting `openAiStrictToolMode` that allows users to disable OpenAI strict mode for tool definitions. When strict mode is disabled: - No `strict: true` is added to tool definitions - No schema modifications (additionalProperties: false, all required) are made This is useful for providers like kie.ai that use the Gemini 3 Pro model and do not support OpenAI's strict mode for function calling. The setting defaults to true for backward compatibility. Closes #11011
This commit is contained in:
parent
17d3456e96
commit
4cdd126a47
5 changed files with 44 additions and 5 deletions
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -152,6 +152,10 @@ 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),
|
||||
|
|
@ -159,7 +163,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|||
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,
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue