mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-10 03:28:03 +00:00
feat: allow user-selectable tool format for OpenAI Compatible and Ollama providers
- Show tool protocol selector for OpenAI Compatible and Ollama providers regardless of model support - Allow users to manually choose between XML and native tool formats for custom models - Add special handling in resolveToolProtocol to respect user choice for these providers - Add comprehensive tests for the new behavior Fixes #9538
This commit is contained in:
parent
a20d047417
commit
85d3ae4fb6
3 changed files with 123 additions and 7 deletions
|
|
@ -317,4 +317,100 @@ describe("resolveToolProtocol", () => {
|
|||
expect(result).toBe(TOOL_PROTOCOL.XML) // Model default wins
|
||||
})
|
||||
})
|
||||
|
||||
describe("OpenAI Compatible and Ollama Provider Special Handling", () => {
|
||||
it("should allow native protocol for OpenAI Compatible provider even without model support", () => {
|
||||
const settings: ProviderSettings = {
|
||||
toolProtocol: "native",
|
||||
apiProvider: "openai",
|
||||
}
|
||||
// No model info provided (unknown model)
|
||||
const result = resolveToolProtocol(settings, undefined)
|
||||
expect(result).toBe(TOOL_PROTOCOL.NATIVE) // User preference is respected
|
||||
})
|
||||
|
||||
it("should allow native protocol for Ollama provider even without model support", () => {
|
||||
const settings: ProviderSettings = {
|
||||
toolProtocol: "native",
|
||||
apiProvider: "ollama",
|
||||
}
|
||||
const modelInfo: ModelInfo = {
|
||||
maxTokens: 4096,
|
||||
contextWindow: 128000,
|
||||
supportsPromptCache: false,
|
||||
supportsNativeTools: false, // Model doesn't support native
|
||||
}
|
||||
const result = resolveToolProtocol(settings, modelInfo)
|
||||
expect(result).toBe(TOOL_PROTOCOL.NATIVE) // User preference is respected for Ollama
|
||||
})
|
||||
|
||||
it("should allow XML protocol for OpenAI Compatible provider when user chooses it", () => {
|
||||
const settings: ProviderSettings = {
|
||||
toolProtocol: "xml",
|
||||
apiProvider: "openai",
|
||||
}
|
||||
const modelInfo: ModelInfo = {
|
||||
maxTokens: 4096,
|
||||
contextWindow: 128000,
|
||||
supportsPromptCache: false,
|
||||
supportsNativeTools: true, // Model supports native
|
||||
defaultToolProtocol: "native",
|
||||
}
|
||||
const result = resolveToolProtocol(settings, modelInfo)
|
||||
expect(result).toBe(TOOL_PROTOCOL.XML) // User preference is respected
|
||||
})
|
||||
|
||||
it("should use model default for OpenAI Compatible when no user preference", () => {
|
||||
const settings: ProviderSettings = {
|
||||
apiProvider: "openai",
|
||||
}
|
||||
const modelInfo: ModelInfo = {
|
||||
maxTokens: 4096,
|
||||
contextWindow: 128000,
|
||||
supportsPromptCache: false,
|
||||
supportsNativeTools: true,
|
||||
defaultToolProtocol: "native",
|
||||
}
|
||||
const result = resolveToolProtocol(settings, modelInfo)
|
||||
expect(result).toBe(TOOL_PROTOCOL.NATIVE) // Model default is used
|
||||
})
|
||||
|
||||
it("should fall back to XML for OpenAI Compatible when no preference and no model info", () => {
|
||||
const settings: ProviderSettings = {
|
||||
apiProvider: "openai",
|
||||
}
|
||||
const result = resolveToolProtocol(settings, undefined)
|
||||
expect(result).toBe(TOOL_PROTOCOL.XML) // XML fallback
|
||||
})
|
||||
|
||||
it("should still enforce support check for non-OpenAI/Ollama providers", () => {
|
||||
const settings: ProviderSettings = {
|
||||
toolProtocol: "native",
|
||||
apiProvider: "anthropic", // Not OpenAI or Ollama
|
||||
}
|
||||
const modelInfo: ModelInfo = {
|
||||
maxTokens: 4096,
|
||||
contextWindow: 128000,
|
||||
supportsPromptCache: false,
|
||||
supportsNativeTools: false, // Model doesn't support native
|
||||
}
|
||||
const result = resolveToolProtocol(settings, modelInfo)
|
||||
expect(result).toBe(TOOL_PROTOCOL.XML) // Falls back to XML for non-OpenAI/Ollama
|
||||
})
|
||||
|
||||
it("should allow native for Ollama with undefined model support", () => {
|
||||
const settings: ProviderSettings = {
|
||||
toolProtocol: "native",
|
||||
apiProvider: "ollama",
|
||||
}
|
||||
const modelInfo: ModelInfo = {
|
||||
maxTokens: 4096,
|
||||
contextWindow: 128000,
|
||||
supportsPromptCache: false,
|
||||
// supportsNativeTools is undefined
|
||||
}
|
||||
const result = resolveToolProtocol(settings, modelInfo)
|
||||
expect(result).toBe(TOOL_PROTOCOL.NATIVE) // User preference is respected for Ollama
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -15,17 +15,32 @@ import type { ProviderSettings, ModelInfo } from "@roo-code/types"
|
|||
* @returns The resolved tool protocol (either "xml" or "native")
|
||||
*/
|
||||
export function resolveToolProtocol(providerSettings: ProviderSettings, modelInfo?: ModelInfo): ToolProtocol {
|
||||
// If model doesn't support native tools, return XML immediately
|
||||
// Treat undefined as unsupported (only allow native when explicitly true)
|
||||
if (modelInfo?.supportsNativeTools !== true) {
|
||||
return TOOL_PROTOCOL.XML
|
||||
}
|
||||
// Special handling for OpenAI Compatible and Ollama providers:
|
||||
// Allow user to override tool protocol even for unknown models
|
||||
const isUserConfigurableProvider =
|
||||
providerSettings.apiProvider === "openai" || providerSettings.apiProvider === "ollama"
|
||||
|
||||
// 1. User Preference - Per-Profile (explicit profile setting, highest priority)
|
||||
if (providerSettings.toolProtocol) {
|
||||
// For user-configurable providers, always respect the user's choice
|
||||
if (isUserConfigurableProvider) {
|
||||
return providerSettings.toolProtocol
|
||||
}
|
||||
|
||||
// For other providers, only use native if model supports it
|
||||
if (providerSettings.toolProtocol === TOOL_PROTOCOL.NATIVE && modelInfo?.supportsNativeTools !== true) {
|
||||
return TOOL_PROTOCOL.XML
|
||||
}
|
||||
|
||||
return providerSettings.toolProtocol
|
||||
}
|
||||
|
||||
// If model doesn't support native tools and it's not a user-configurable provider, return XML
|
||||
// Treat undefined as unsupported (only allow native when explicitly true)
|
||||
if (modelInfo?.supportsNativeTools !== true && !isUserConfigurableProvider) {
|
||||
return TOOL_PROTOCOL.XML
|
||||
}
|
||||
|
||||
// 2. Model Default - model's preferred protocol
|
||||
if (modelInfo?.defaultToolProtocol) {
|
||||
return modelInfo.defaultToolProtocol
|
||||
|
|
|
|||
|
|
@ -423,8 +423,13 @@ const ApiOptions = ({
|
|||
// 3. XML fallback
|
||||
const defaultProtocol = selectedModelInfo?.defaultToolProtocol || TOOL_PROTOCOL.XML
|
||||
|
||||
// Show the tool protocol selector when model supports native tools
|
||||
const showToolProtocolSelector = selectedModelInfo?.supportsNativeTools === true
|
||||
// Show the tool protocol selector when:
|
||||
// 1. Model explicitly supports native tools, OR
|
||||
// 2. Provider is OpenAI Compatible or Ollama (to allow user control for custom models)
|
||||
const showToolProtocolSelector =
|
||||
selectedModelInfo?.supportsNativeTools === true ||
|
||||
selectedProvider === "openai" ||
|
||||
selectedProvider === "ollama"
|
||||
|
||||
// Convert providers to SearchableSelect options
|
||||
const providerOptions = useMemo(() => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue