Add backend-provided websearch connectors for OpenRouter and Gemini
| @@ -1951,6 +1951,17 @@ | ||
| 1951 | 1951 | </span> |
| 1952 | 1952 | </div> |
| 1953 | 1953 | </div> |
| 1954 | + <div class="range-block" data-source="makersuite,openrouter"> | |
| 1955 | + <label for="openai_enable_web_search" class="checkbox_label flexWrap widthFreeExpand"> | |
| 1956 | + <input id="openai_enable_web_search" type="checkbox" /> | |
| 1957 | + <span data-i18n="Enable web search">Enable web search</span> | |
| 1958 | + </label> | |
| 1959 | + <div class="flexBasis100p toggle-description justifyLeft"> | |
| 1960 | + <span> | |
| 1961 | + Use search capabilities provided by the backend. | |
| 1962 | + </span> | |
| 1963 | + </div> | |
| 1964 | + </div> | |
| 1954 | 1965 | <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,openrouter,groq,deepseek"> |
| 1955 | 1966 | <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand"> |
| 1956 | 1967 | <input id="openai_function_calling" type="checkbox" /> |
| @@ -300,6 +300,7 @@ export const settingsToUpdate = { | ||
| 300 | 300 | function_calling: ['#openai_function_calling', 'function_calling', true], |
| 301 | 301 | show_thoughts: ['#openai_show_thoughts', 'show_thoughts', true], |
| 302 | 302 | reasoning_effort: ['#openai_reasoning_effort', 'reasoning_effort', false], |
| 303 | + enable_web_search: ['#openai_enable_web_search', 'enable_web_search', true], | |
| 303 | 304 | seed: ['#seed_openai', 'seed', false], |
| 304 | 305 | n: ['#n_openai', 'n', false], |
| 305 | 306 | bypass_status_check: ['#openai_bypass_status_check', 'bypass_status_check', true], |
| @@ -380,6 +381,7 @@ const default_settings = { | ||
| 380 | 381 | custom_prompt_post_processing: custom_prompt_post_processing_types.NONE, |
| 381 | 382 | show_thoughts: true, |
| 382 | 383 | reasoning_effort: 'medium', |
| 384 | + enable_web_search: false, | |
| 383 | 385 | seed: -1, |
| 384 | 386 | n: 1, |
| 385 | 387 | }; |
| @@ -459,6 +461,7 @@ const oai_settings = { | ||
| 459 | 461 | custom_prompt_post_processing: custom_prompt_post_processing_types.NONE, |
| 460 | 462 | show_thoughts: true, |
| 461 | 463 | reasoning_effort: 'medium', |
| 464 | + enable_web_search: false, | |
| 462 | 465 | seed: -1, |
| 463 | 466 | n: 1, |
| 464 | 467 | }; |
| @@ -2000,6 +2003,7 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 2000 | 2003 | 'group_names': getGroupNames(), |
| 2001 | 2004 | 'include_reasoning': Boolean(oai_settings.show_thoughts), |
| 2002 | 2005 | 'reasoning_effort': String(oai_settings.reasoning_effort), |
| 2006 | + 'enable_web_search': Boolean(oai_settings.enable_web_search), | |
| 2003 | 2007 | }; |
| 2004 | 2008 | |
| 2005 | 2009 | if (!canMultiSwipe && ToolManager.canPerformToolCalls(type)) { |
| @@ -3222,6 +3226,7 @@ function loadOpenAISettings(data, settings) { | ||
| 3222 | 3226 | oai_settings.bypass_status_check = settings.bypass_status_check ?? default_settings.bypass_status_check; |
| 3223 | 3227 | oai_settings.show_thoughts = settings.show_thoughts ?? default_settings.show_thoughts; |
| 3224 | 3228 | oai_settings.reasoning_effort = settings.reasoning_effort ?? default_settings.reasoning_effort; |
| 3229 | + oai_settings.enable_web_search = settings.enable_web_search ?? default_settings.enable_web_search; | |
| 3225 | 3230 | oai_settings.seed = settings.seed ?? default_settings.seed; |
| 3226 | 3231 | oai_settings.n = settings.n ?? default_settings.n; |
| 3227 | 3232 | |
| @@ -3349,6 +3354,7 @@ function loadOpenAISettings(data, settings) { | ||
| 3349 | 3354 | $('#seed_openai').val(oai_settings.seed); |
| 3350 | 3355 | $('#n_openai').val(oai_settings.n); |
| 3351 | 3356 | $('#openai_show_thoughts').prop('checked', oai_settings.show_thoughts); |
| 3357 | + $('#openai_enable_web_search').prop('checked', oai_settings.enable_web_search); | |
| 3352 | 3358 | |
| 3353 | 3359 | $('#openai_reasoning_effort').val(oai_settings.reasoning_effort); |
| 3354 | 3360 | $(`#openai_reasoning_effort option[value="${oai_settings.reasoning_effort}"]`).prop('selected', true); |
| @@ -3613,6 +3619,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 3613 | 3619 | function_calling: settings.function_calling, |
| 3614 | 3620 | show_thoughts: settings.show_thoughts, |
| 3615 | 3621 | reasoning_effort: settings.reasoning_effort, |
| 3622 | + enable_web_search: settings.enable_web_search, | |
| 3616 | 3623 | seed: settings.seed, |
| 3617 | 3624 | n: settings.n, |
| 3618 | 3625 | }; |
| @@ -5572,6 +5579,11 @@ export function initOpenAI() { | ||
| 5572 | 5579 | saveSettingsDebounced(); |
| 5573 | 5580 | }); |
| 5574 | 5581 | |
| 5582 | + $('#openai_enable_web_search').on('input', function () { | |
| 5583 | + oai_settings.enable_web_search = !!$(this).prop('checked'); | |
| 5584 | + saveSettingsDebounced(); | |
| 5585 | + }); | |
| 5586 | + | |
| 5575 | 5587 | if (!CSS.supports('field-sizing', 'content')) { |
| 5576 | 5588 | $(document).on('input', '#openai_settings .autoSetHeight', function () { |
| 5577 | 5589 | resetScrollHeight($(this)); |
| @@ -99,6 +99,21 @@ function getOpenRouterTransforms(request) { | ||
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | /** |
| 102 | + * Gets OpenRouter plugins based on the request. | |
| 103 | + * @param {import('express').Request} request | |
| 104 | + * @returns {any[]} OpenRouter plugins | |
| 105 | + */ | |
| 106 | +function getOpenRouterPlugins(request) { | |
| 107 | + const plugins = []; | |
| 108 | + | |
| 109 | + if (request.body.enable_web_search) { | |
| 110 | + plugins.push({ 'id': 'web' }); | |
| 111 | + } | |
| 112 | + | |
| 113 | + return plugins; | |
| 114 | +} | |
| 115 | + | |
| 116 | +/** | |
| 102 | 117 | * Sends a request to Claude API. |
| 103 | 118 | * @param {express.Request} request Express request |
| 104 | 119 | * @param {express.Response} response Express response |
| @@ -323,6 +338,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 323 | 338 | |
| 324 | 339 | const model = String(request.body.model); |
| 325 | 340 | const stream = Boolean(request.body.stream); |
| 341 | + const enableWebSearch = Boolean(request.body.enable_web_search); | |
| 326 | 342 | const isThinking = model.includes('thinking'); |
| 327 | 343 | |
| 328 | 344 | const generationConfig = { |
| @@ -348,6 +364,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 348 | 364 | model.startsWith('gemini-exp') |
| 349 | 365 | ) && request.body.use_makersuite_sysprompt; |
| 350 | 366 | |
| 367 | + const tools = []; | |
| 351 | 368 | const prompt = convertGooglePrompt(request.body.messages, model, should_use_system_prompt, getPromptNames(request)); |
| 352 | 369 | let safetySettings = GEMINI_SAFETY; |
| 353 | 370 | |
| @@ -361,6 +378,13 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 361 | 378 | } |
| 362 | 379 | // Most of the other models allow for setting the threshold of filters, except for HARM_CATEGORY_CIVIC_INTEGRITY, to OFF. |
| 363 | 380 | |
| 381 | + if (enableWebSearch) { | |
| 382 | + const searchTool = model.includes('1.5') || model.includes('1.0') | |
| 383 | + ? ({ google_search_retrieval: {} }) | |
| 384 | + : ({ google_search: {} }); | |
| 385 | + tools.push(searchTool); | |
| 386 | + } | |
| 387 | + | |
| 364 | 388 | let body = { |
| 365 | 389 | contents: prompt.contents, |
| 366 | 390 | safetySettings: safetySettings, |
| @@ -371,6 +395,10 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 371 | 395 | body.systemInstruction = prompt.system_instruction; |
| 372 | 396 | } |
| 373 | 397 | |
| 398 | + if (tools.length) { | |
| 399 | + body.tools = tools; | |
| 400 | + } | |
| 401 | + | |
| 374 | 402 | return body; |
| 375 | 403 | } |
| 376 | 404 | |
| @@ -1014,6 +1042,7 @@ router.post('/generate', jsonParser, function (request, response) { | ||
| 1014 | 1042 | headers = { ...OPENROUTER_HEADERS }; |
| 1015 | 1043 | bodyParams = { |
| 1016 | 1044 | 'transforms': getOpenRouterTransforms(request), |
| 1045 | + 'plugins': getOpenRouterPlugins(request), | |
| 1017 | 1046 | 'include_reasoning': Boolean(request.body.include_reasoning), |
| 1018 | 1047 | }; |
| 1019 | 1048 | |