From e744da88706edaff8d98e0347a9f222a4ee0c3ee Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Fri, 11 Sep 2026 13:47:44 -0600 Subject: [PATCH] feat: update the web_search_coyote tool to attempt to use the current model first then fallback to the configured model for web searches --- assets/functions/tools/web_search_coyote.sh | 78 +++++++++++++++++---- 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/assets/functions/tools/web_search_coyote.sh b/assets/functions/tools/web_search_coyote.sh index 09d57bf..1ee3ace 100755 --- a/assets/functions/tools/web_search_coyote.sh +++ b/assets/functions/tools/web_search_coyote.sh @@ -8,10 +8,17 @@ set -e # @meta require-tools coyote -# @env WEB_SEARCH_MODEL=gemini:gemini-2.5-flash The model for web-searching. +# @env WEB_SEARCH_MODEL=gemini:gemini-2.5-flash The fallback model for web-searching. # -# supported coyote models: -# - gemini:gemini-2.0-* +# Model selection: when WEB_SEARCH_USE_CURRENT_MODEL is true (the default) and +# the running session's model (COYOTE_CURRENT_MODEL, injected by coyote for +# every tool call) natively supports web search, the search runs on the current +# model first. If the current model is unsupported, or if the search fails at +# runtime, the tool falls back to WEB_SEARCH_MODEL. If that also fails, the +# tool fails. +# +# supported coyote models (native web search): +# - gemini:* # - vertexai:gemini-* # - perplexity:* # - ernie:* @@ -20,29 +27,74 @@ set -e # client — the codex OAuth path uses the # Responses API where this parameter # does not exist) +# @env WEB_SEARCH_USE_CURRENT_MODEL=true Prefer the running session's model when it natively supports web search. # @env LLM_OUTPUT=/dev/stdout The output path -# shellcheck disable=SC2154 -main() { - client="${WEB_SEARCH_MODEL%%:*}" +# Returns 0 when the model natively supports web search via a known mechanism. +supports_native_search() { + case "$1" in + gemini:* | vertexai:gemini-* | perplexity:* | ernie:* | claude:*) return 0 ;; + openai:gpt-4o*search-preview*) return 0 ;; + *) return 1 ;; + esac +} - if [[ "$client" == "gemini" ]]; then +# Exports the request-body patch that enables native web search for the +# given model's client (clearing any patch left over from a prior attempt). +export_search_patch() { + unset COYOTE_PATCH_GEMINI_CHAT_COMPLETIONS \ + COYOTE_PATCH_VERTEXAI_CHAT_COMPLETIONS \ + COYOTE_PATCH_ERNIE_CHAT_COMPLETIONS \ + COYOTE_PATCH_CLAUDE_CHAT_COMPLETIONS \ + COYOTE_PATCH_OPENAI_CHAT_COMPLETIONS + + case "${1%%:*}" in + gemini) export COYOTE_PATCH_GEMINI_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"google_search":{}}]}}}' - elif [[ "$client" == "vertexai" ]]; then + ;; + vertexai) export COYOTE_PATCH_VERTEXAI_CHAT_COMPLETIONS='{ "gemini-1.5-.*":{"body":{"tools":[{"googleSearchRetrieval":{}}]}}, "gemini-2.0-.*":{"body":{"tools":[{"google_search":{}}]}} }' - elif [[ "$client" == "ernie" ]]; then + ;; + ernie) export COYOTE_PATCH_ERNIE_CHAT_COMPLETIONS='{".*":{"body":{"web_search":{"enable":true}}}}' - elif [[ "$client" == "claude" ]]; then + ;; + claude) export COYOTE_PATCH_CLAUDE_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"type":"web_search_20250305","name":"web_search","max_uses":5}]}}}' - elif [[ "$client" == "openai" ]]; then + ;; + openai) # Chat Completions native search exists only on the search-preview # models; the regex scopes the patch so other OpenAI models run # unpatched instead of erroring on an unsupported parameter. export COYOTE_PATCH_OPENAI_CHAT_COMPLETIONS='{"gpt-4o.*search-preview.*":{"body":{"web_search_options":{}}}}' + ;; + esac +} + +# shellcheck disable=SC2154 +run_search() { + export_search_patch "$1" + coyote -m "$1" "$argc_query" >>"$LLM_OUTPUT" +} + +main() { + local fallback="${WEB_SEARCH_MODEL:-gemini:gemini-2.5-flash}" + local current="${COYOTE_CURRENT_MODEL:-}" + local primary="" + + if [[ "${WEB_SEARCH_USE_CURRENT_MODEL:-true}" == "true" && -n "$current" && "$current" != "$fallback" ]] && + supports_native_search "$current"; then + primary="$current" fi - coyote -m "$WEB_SEARCH_MODEL" "$argc_query" >> "$LLM_OUTPUT" -} \ No newline at end of file + if [[ -n "$primary" ]]; then + if run_search "$primary"; then + return 0 + fi + echo "web_search: search with current model '$primary' failed; falling back to '$fallback'" >&2 + fi + + run_search "$fallback" +}