Browse Source

feat: add tool protocol selector to advanced settings (#9324)

Co-authored-by: Roo Code <[email protected]>
Co-authored-by: Matt Rubens <[email protected]>
Daniel 1 month ago
parent
commit
c5b18c1581

+ 88 - 1
webview-ui/src/components/settings/ApiOptions.tsx

@@ -38,6 +38,8 @@ import {
 	vercelAiGatewayDefaultModelId,
 	deepInfraDefaultModelId,
 	minimaxDefaultModelId,
+	type ToolProtocol,
+	TOOL_PROTOCOL,
 } from "@roo-code/types"
 
 import { vscode } from "@src/utils/vscode"
@@ -46,6 +48,7 @@ import { useAppTranslation } from "@src/i18n/TranslationContext"
 import { useRouterModels } from "@src/components/ui/hooks/useRouterModels"
 import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel"
 import { useExtensionState } from "@src/context/ExtensionStateContext"
+import { EXPERIMENT_IDS, experimentDefault } from "@roo/experiments"
 import {
 	useOpenRouterModelProviders,
 	OPENROUTER_DEFAULT_PROVIDER_NAME,
@@ -137,7 +140,7 @@ const ApiOptions = ({
 	setErrorMessage,
 }: ApiOptionsProps) => {
 	const { t } = useAppTranslation()
-	const { organizationAllowList, cloudIsAuthenticated } = useExtensionState()
+	const { organizationAllowList, cloudIsAuthenticated, experiments: experimentsConfig } = useExtensionState()
 
 	const [customHeaders, setCustomHeaders] = useState<[string, string][]>(() => {
 		const headers = apiConfiguration?.openAiHeaders || {}
@@ -409,6 +412,57 @@ const ApiOptions = ({
 		}
 	}, [selectedProvider])
 
+	// Calculate the default protocol that would be used if toolProtocol is not set
+	// This mirrors the logic in resolveToolProtocol.ts (steps 2-5, skipping step 1 which is the user preference)
+	const defaultProtocol = useMemo((): ToolProtocol => {
+		// 2. Experimental Setting (nativeToolCalling experiment)
+		const nativeToolCallingEnabled =
+			experimentsConfig?.[EXPERIMENT_IDS.NATIVE_TOOL_CALLING] ??
+			experimentDefault[EXPERIMENT_IDS.NATIVE_TOOL_CALLING]
+
+		if (nativeToolCallingEnabled) {
+			// Check if model supports native tools
+			if (selectedModelInfo?.supportsNativeTools === true) {
+				return TOOL_PROTOCOL.NATIVE
+			}
+			// If experiment is enabled but model doesn't support it, return XML immediately
+			// This matches resolveToolProtocol.ts behavior (lines 53-57)
+			return TOOL_PROTOCOL.XML
+		}
+
+		// 3. Model Default
+		if (selectedModelInfo?.defaultToolProtocol) {
+			// Still need to check support even for model defaults
+			if (
+				selectedModelInfo.defaultToolProtocol === TOOL_PROTOCOL.NATIVE &&
+				selectedModelInfo.supportsNativeTools !== true
+			) {
+				return TOOL_PROTOCOL.XML
+			}
+			return selectedModelInfo.defaultToolProtocol
+		}
+
+		// 4. Provider Default (currently all providers default to XML)
+		// The nativePreferredProviders list in resolveToolProtocol.ts is currently empty
+		// If you update it there, update this logic as well
+
+		// 5. XML Fallback
+		return TOOL_PROTOCOL.XML
+	}, [experimentsConfig, selectedModelInfo])
+
+	// Determine whether to show the tool protocol selector
+	// Separate from defaultProtocol calculation to keep concerns separate
+	const showToolProtocolSelector = useMemo(() => {
+		const nativeToolCallingEnabled =
+			experimentsConfig?.[EXPERIMENT_IDS.NATIVE_TOOL_CALLING] ??
+			experimentDefault[EXPERIMENT_IDS.NATIVE_TOOL_CALLING]
+
+		// Only show if experiment is enabled AND model supports native tools
+		// If model doesn't support native tools, showing the selector is confusing
+		// since native protocol won't actually be available
+		return nativeToolCallingEnabled && selectedModelInfo?.supportsNativeTools === true
+	}, [experimentsConfig, selectedModelInfo])
+
 	// Convert providers to SearchableSelect options
 	const providerOptions = useMemo(() => {
 		// First filter by organization allow list
@@ -868,6 +922,39 @@ const ApiOptions = ({
 									</div>
 								</div>
 							)}
+						{showToolProtocolSelector && (
+							<div>
+								<label className="block font-medium mb-1">{t("settings:toolProtocol.label")}</label>
+								<Select
+									value={apiConfiguration.toolProtocol || "default"}
+									onValueChange={(value) => {
+										const newValue = value === "default" ? undefined : (value as ToolProtocol)
+										setApiConfigurationField("toolProtocol", newValue)
+									}}>
+									<SelectTrigger className="w-full">
+										<SelectValue placeholder={t("settings:common.select")} />
+									</SelectTrigger>
+									<SelectContent>
+										<SelectItem value="default">
+											{t("settings:toolProtocol.default")} (
+											{defaultProtocol === TOOL_PROTOCOL.NATIVE
+												? t("settings:toolProtocol.native")
+												: t("settings:toolProtocol.xml")}
+											)
+										</SelectItem>
+										<SelectItem value={TOOL_PROTOCOL.XML}>
+											{t("settings:toolProtocol.xml")}
+										</SelectItem>
+										<SelectItem value={TOOL_PROTOCOL.NATIVE}>
+											{t("settings:toolProtocol.native")}
+										</SelectItem>
+									</SelectContent>
+								</Select>
+								<div className="text-sm text-vscode-descriptionForeground mt-1">
+									{t("settings:toolProtocol.description")}
+								</div>
+							</div>
+						)}
 					</CollapsibleContent>
 				</Collapsible>
 			)}

+ 8 - 0
webview-ui/src/i18n/locales/ca/settings.json

@@ -693,6 +693,14 @@
 	"advancedSettings": {
 		"title": "Configuració avançada"
 	},
+	"toolProtocol": {
+		"label": "Protocol de crida d'eines",
+		"description": "Trieu com es comunica en Roo amb l'API. Natiu utilitza l'API de crida de funcions del proveïdor, mentre que XML utilitza definicions d'eines amb format XML.",
+		"default": "Per defecte",
+		"xml": "XML",
+		"native": "Natiu",
+		"currentDefault": "Per defecte: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Habilitar edició mitjançant diffs",

+ 8 - 0
webview-ui/src/i18n/locales/de/settings.json

@@ -693,6 +693,14 @@
 	"advancedSettings": {
 		"title": "Erweiterte Einstellungen"
 	},
+	"toolProtocol": {
+		"label": "Tool-Aufruf-Protokoll",
+		"description": "Wähle, wie Roo mit der API kommuniziert. Nativ verwendet die Funktionsaufruf-API des Anbieters, während XML XML-formatierte Werkzeugdefinitionen verwendet.",
+		"default": "Standard",
+		"xml": "XML",
+		"native": "Nativ",
+		"currentDefault": "Standard: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Bearbeitung durch Diffs aktivieren",

+ 8 - 0
webview-ui/src/i18n/locales/en/settings.json

@@ -698,6 +698,14 @@
 	"advancedSettings": {
 		"title": "Advanced settings"
 	},
+	"toolProtocol": {
+		"label": "Tool Call Protocol",
+		"description": "Choose how Roo communicates with the API. Native uses the provider's function calling API, while XML uses XML-formatted tool definitions.",
+		"default": "Default",
+		"xml": "XML",
+		"native": "Native",
+		"currentDefault": "Default: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Enable editing through diffs",

+ 8 - 0
webview-ui/src/i18n/locales/es/settings.json

@@ -693,6 +693,14 @@
 	"advancedSettings": {
 		"title": "Configuración avanzada"
 	},
+	"toolProtocol": {
+		"label": "Protocolo de llamada a herramientas",
+		"description": "Elija cómo Roo se comunica con la API. Nativo utiliza la API de llamada a funciones del proveedor, mientras que XML utiliza definiciones de herramientas con formato XML.",
+		"default": "Predeterminado",
+		"xml": "XML",
+		"native": "Nativo",
+		"currentDefault": "Predeterminado: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Habilitar edición a través de diffs",

+ 8 - 0
webview-ui/src/i18n/locales/fr/settings.json

@@ -693,6 +693,14 @@
 	"advancedSettings": {
 		"title": "Paramètres avancés"
 	},
+	"toolProtocol": {
+		"label": "Protocole d'appel d'outil",
+		"description": "Choisissez comment Roo communique avec l'API. Natif utilise l'API d'appel de fonction du fournisseur, tandis que XML utilise des définitions d'outils au format XML.",
+		"default": "Défaut",
+		"xml": "XML",
+		"native": "Natif",
+		"currentDefault": "Défaut: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Activer l'édition via des diffs",

+ 8 - 0
webview-ui/src/i18n/locales/hi/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "उन्नत सेटिंग्स"
 	},
+	"toolProtocol": {
+		"label": "टूल कॉल प्रोटोकॉल",
+		"description": "चुनें कि रू एपीआई के साथ कैसे संचार करता है। नेटिव प्रदाता के फ़ंक्शन कॉलिंग एपीआई का उपयोग करता है, जबकि एक्सएमएल एक्सएमएल-स्वरूपित टूल परिभाषाओं का उपयोग करता है।",
+		"default": "डिफ़ॉल्ट",
+		"xml": "एक्सएमएल",
+		"native": "नेटिव",
+		"currentDefault": "डिफ़ॉल्ट: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "diffs के माध्यम से संपादन सक्षम करें",

+ 8 - 0
webview-ui/src/i18n/locales/id/settings.json

@@ -698,6 +698,14 @@
 	"advancedSettings": {
 		"title": "Pengaturan lanjutan"
 	},
+	"toolProtocol": {
+		"label": "Protokol Panggilan Alat",
+		"description": "Pilih bagaimana Roo berkomunikasi dengan API. Asli menggunakan API panggilan fungsi penyedia, sedangkan XML menggunakan definisi alat berformat XML.",
+		"default": "Default",
+		"xml": "XML",
+		"native": "Asli",
+		"currentDefault": "Default: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Aktifkan editing melalui diff",

+ 8 - 0
webview-ui/src/i18n/locales/it/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Impostazioni avanzate"
 	},
+	"toolProtocol": {
+		"label": "Protocollo di chiamata dello strumento",
+		"description": "Scegli come Roo comunica con l'API. Nativo utilizza l'API di chiamata di funzione del provider, mentre XML utilizza definizioni di strumenti in formato XML.",
+		"default": "Predefinito",
+		"xml": "XML",
+		"native": "Nativo",
+		"currentDefault": "Predefinito: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Abilita modifica tramite diff",

+ 8 - 0
webview-ui/src/i18n/locales/ja/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "詳細設定"
 	},
+	"toolProtocol": {
+		"label": "ツールコールプロトコル",
+		"description": "Roo が API と通信する方法を選択します。ネイティブはプロバイダーの関数呼び出し API を使用し、XML は XML 形式のツール定義を使用します。",
+		"default": "デフォルト",
+		"xml": "XML",
+		"native": "ネイティブ",
+		"currentDefault": "デフォルト: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "diff経由の編集を有効化",

+ 8 - 0
webview-ui/src/i18n/locales/ko/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "고급 설정"
 	},
+	"toolProtocol": {
+		"label": "도구 호출 프로토콜",
+		"description": "Roo가 API와 통신하는 방법을 선택합니다. 네이티브는 공급자의 함수 호출 API를 사용하고 XML은 XML 형식의 도구 정의를 사용합니다.",
+		"default": "기본값",
+		"xml": "XML",
+		"native": "네이티브",
+		"currentDefault": "기본값: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "diff를 통한 편집 활성화",

+ 8 - 0
webview-ui/src/i18n/locales/nl/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Geavanceerde instellingen"
 	},
+	"toolProtocol": {
+		"label": "Tool Call Protocol",
+		"description": "Kies hoe Roo communiceert met de API. Native gebruikt de functie-aanroep API van de provider, terwijl XML gebruikmaakt van XML-geformatteerde tooldefinities.",
+		"default": "Standaard",
+		"xml": "XML",
+		"native": "Native",
+		"currentDefault": "Standaard: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Bewerken via diffs inschakelen",

+ 8 - 0
webview-ui/src/i18n/locales/pl/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Ustawienia zaawansowane"
 	},
+	"toolProtocol": {
+		"label": "Protokół wywołania narzędzia",
+		"description": "Wybierz, jak Roo komunikuje się z API. Natywny używa API wywołania funkcji dostawcy, podczas gdy XML używa definicji narzędzi w formacie XML.",
+		"default": "Domyślny",
+		"xml": "XML",
+		"native": "Natywny",
+		"currentDefault": "Domyślny: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Włącz edycję przez różnice",

+ 8 - 0
webview-ui/src/i18n/locales/pt-BR/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Configurações avançadas"
 	},
+	"toolProtocol": {
+		"label": "Protocolo de Chamada de Ferramenta",
+		"description": "Escolha como o Roo se comunica com a API. Nativo usa a API de chamada de função do provedor, enquanto XML usa definições de ferramentas formatadas em XML.",
+		"default": "Padrão",
+		"xml": "XML",
+		"native": "Nativo",
+		"currentDefault": "Padrão: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Ativar edição através de diffs",

+ 8 - 0
webview-ui/src/i18n/locales/ru/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Дополнительные настройки"
 	},
+	"toolProtocol": {
+		"label": "Протокол вызова инструментов",
+		"description": "Выберите, как Roo будет взаимодействовать с API. Нативный использует API вызова функций провайдера, а XML — определения инструментов в формате XML.",
+		"default": "По умолчанию",
+		"xml": "XML",
+		"native": "Нативный",
+		"currentDefault": "По умолчанию: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Включить редактирование через диффы",

+ 8 - 0
webview-ui/src/i18n/locales/tr/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Gelişmiş ayarlar"
 	},
+	"toolProtocol": {
+		"label": "Araç Çağrı Protokolü",
+		"description": "Roo'nun API ile nasıl iletişim kuracağını seçin. Yerel, sağlayıcının işlev çağırma API'sini kullanırken, XML, XML biçimli araç tanımlarını kullanır.",
+		"default": "Varsayılan",
+		"xml": "XML",
+		"native": "Yerel",
+		"currentDefault": "Varsayılan: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Diff'ler aracılığıyla düzenlemeyi etkinleştir",

+ 8 - 0
webview-ui/src/i18n/locales/vi/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "Cài đặt nâng cao"
 	},
+	"toolProtocol": {
+		"label": "Giao thức gọi công cụ",
+		"description": "Chọn cách Roo giao tiếp với API. Native sử dụng API gọi hàm của nhà cung cấp, trong khi XML sử dụng định nghĩa công cụ định dạng XML.",
+		"default": "Mặc định",
+		"xml": "XML",
+		"native": "Native",
+		"currentDefault": "Mặc định: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "Bật chỉnh sửa qua diff",

+ 8 - 0
webview-ui/src/i18n/locales/zh-CN/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "高级设置"
 	},
+	"toolProtocol": {
+		"label": "工具调用协议",
+		"description": "选择 Roo 如何与 API 通信。原生使用提供商的函数调用 API,而 XML 使用 XML 格式的工具定义。",
+		"default": "默认",
+		"xml": "XML",
+		"native": "原生",
+		"currentDefault": "默认: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "启用diff更新",

+ 8 - 0
webview-ui/src/i18n/locales/zh-TW/settings.json

@@ -694,6 +694,14 @@
 	"advancedSettings": {
 		"title": "進階設定"
 	},
+	"toolProtocol": {
+		"label": "工具呼叫協議",
+		"description": "選擇 Roo 如何與 API 通信。原生使用提供者的函數呼叫 API,而 XML 使用 XML 格式的工具定義。",
+		"default": "預設",
+		"xml": "XML",
+		"native": "原生",
+		"currentDefault": "預設: {{protocol}}"
+	},
 	"advanced": {
 		"diff": {
 			"label": "透過差異比對編輯",