openclaw/src
holny 1e18169ed8
fix(web-search): prefer OAuth-ready Grok over Tavily during auto-detection (#156048)
Closes #155956

## What Problem This Solves

Fixes: automatic `web_search` chooses Tavily ahead of Grok when both a Tavily environment key and a usable xAI OAuth profile are present.

## User Impact

Automatic search follows the documented credential precedence: Grok (30) before Tavily (70), with Tavily still available if Grok fails. Explicit provider selections and environment-only setups retain their behavior. No configuration or migration changes are required.

## Why This Change Was Made

The secrets snapshot cannot see OAuth profiles. Its environment-selected provider must not override the runtime's OAuth-aware ordering. Configured selections and resolved non-environment snapshot preferences remain unchanged.

## Evidence

Exercised an isolated Gateway started with `pnpm openclaw gateway run --allow-unconfigured`, invoking the shipped `POST /tools/invoke` endpoint with `{"tool":"web_search","args":{"query":"..."}}`. The real bundled xAI and Tavily implementations used configured HTTP base URLs through a local synthetic provider proxy. Credentials were synthetic: a persisted, unexpired xAI OAuth profile and `TAVILY_API_KEY`. No provider-selection callbacks or runtime snapshots were mocked in this Gateway proof; no paid provider calls were made.

Observed provider HTTP requests and returned Gateway results:

| Scenario | HTTP request order | Returned provider |
| --- | --- | --- |
| Original selection code, OAuth + environment | Tavily 200 only | Tavily (bug reproduced) |
| Candidate, same persisted configuration | Grok 200 only | Grok |
| Candidate after merging current main | Grok 200 only | Grok |
| Grok temporarily returns 503 | Grok 503, Tavily 200 | Tavily |
| Grok recovers on next query | Grok 200 only | Grok |
| Existing config explicitly pins Tavily | Tavily 200 only | Tavily |
| Existing config pins Grok, Grok returns 503 | Grok 503 only; no Tavily request | Grok error retaining HTTP 503 |
| Pinned Grok recovers on next query | Grok 200 only | Grok |
| Fresh state with only the Tavily environment key | Tavily 200 only | Tavily |
| Fresh-state setup with OAuth + environment, pinned Tavily at startup | Tavily 200 only | Tavily |
| Removing that pin through normal config reload | Grok 200 only | Grok |

The negative control restored only the original production selection block, rebuilt through the supported CLI wrapper, and restarted the same Gateway/state; it selected Tavily. Restoring the fix selected Grok. Initial fixture setup exposed Doctor's OAuth-refresh invalidation of the synthetic token; reseeding an unexpired synthetic profile through the auth SDK before the comparison resolved that fixture issue.

Focused regression proof: `node scripts/run-vitest.mjs src/web-search/runtime-autodetect-order.test.ts src/web-search/runtime.test.ts --maxWorkers=1` passed **37/37** after the main merge (19.94 seconds wall; four ordering cases took 288 ms). With the production fix removed, the OAuth-first and fallback-order cases both failed for the intended wrong-order reason; environment-only and explicit-pin controls passed. The new cases live in a focused sibling suite, avoiding growth of the over-cap runtime suite. The line-cap ratchet passes. Hosted CI owns test-type validation; no local project-wide typecheck was run.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-09-23 10:02:36 +05:30
..
acp test: reduce ACP in-memory poll latency (#155504) 2026-09-22 18:52:53 -07:00
agents fix: final replies lost when updates interrupt delivery (#156102) 2026-09-22 22:10:20 -06:00
audit chore(qa): qualify execution identity across live boundaries (#156033) 2026-09-22 20:15:02 -05:00
auto-reply fix: identify local worker timeouts in channel replies (#155675) 2026-09-23 09:58:54 +05:30
boards perf(sessions): reuse worker membership snapshots across viewers (#155620) 2026-09-22 12:41:58 +00:00
bootstrap
canvas
channels fix(telegram): keep a visible outcome when final delivery fails (#155906) 2026-09-23 09:59:35 +05:30
chat
claws test(claws): preserve filesystem mode after the close-failure fixture (#156058) 2026-09-22 18:54:42 -07:00
cli fix(doctor): recover retained plugin sources after upgrades (#156052) 2026-09-22 21:14:21 -07:00
commands fix(doctor): recover retained plugin sources after upgrades (#156052) 2026-09-22 21:14:21 -07:00
compat
config fix(doctor): recover retained plugin sources after upgrades (#156052) 2026-09-22 21:14:21 -07:00
context-engine
cron feat(diagnostics): identify agents across message and model-call traces (#156018) 2026-09-22 17:11:38 -07:00
daemon fix: handle endpoint-protected plists during Gateway activation (#149307) 2026-09-22 20:37:25 -07:00
decisions feat(decisions): add explicit evaluation and Labs opt-in foundation (#155134) 2026-09-22 15:55:02 -07:00
docs
fleet fix(ci): reduce packed Node test tails (#155985) 2026-09-22 17:04:57 -07:00
flows fix(doctor): recover retained plugin sources after upgrades (#156052) 2026-09-22 21:14:21 -07:00
gateway perf(sessions): reuse prepared rows for chat history (#156055) 2026-09-23 04:13:16 +00:00
hooks
image-generation refactor(media): reduce SDK dependency fan-in (#154789) 2026-09-21 12:58:24 +00:00
infra fix(doctor): recover retained plugin sources after upgrades (#156052) 2026-09-22 21:14:21 -07:00
interactive
link-understanding
llm fix: stop cancelled completions before provider dispatch (#155819) 2026-09-22 18:48:54 +01:00
logging fix: keep cold child compilation outside CI test deadlines (#156011) 2026-09-22 17:41:19 -07:00
mcp fix: recognize verified team admins as channel owners (#153508) 2026-09-21 19:56:45 -07:00
media fix(worker): serialize workspace helpers from explicit source (#156068) 2026-09-22 21:59:03 -05:00
media-generation refactor(media): reduce SDK dependency fan-in (#154789) 2026-09-21 12:58:24 +00:00
media-understanding fix: stop cancelled completions before provider dispatch (#155819) 2026-09-22 18:48:54 +01:00
meeting-bot fix(meetings): wait for pending audio setup on leave (#155787) 2026-09-22 11:32:27 -07:00
memory feat: personalize USER bootstrap with authenticated profiles (#153966) 2026-09-21 08:17:29 -07:00
memory-host-sdk
model-catalog
model-picker fix: model switches fail with an incompatible runtime pin (#154918) 2026-09-21 18:33:53 -04:00
music-generation
node-host fix(runtime): preserve Node worker dependencies and cleanup diagnostics (#155292) 2026-09-22 16:14:05 -07:00
pairing fix: recognize verified team admins as channel owners (#153508) 2026-09-21 19:56:45 -07:00
plugin-sdk perf(sessions): move streaming transcript writes off the main thread (#156095) 2026-09-23 03:48:47 +00:00
plugin-state test(plugin-state): distinguish borrowed and foreign lifecycle owners 2026-09-22 16:36:56 -07:00
plugins perf(memory): narrow workspace and MIME imports (#155043) 2026-09-22 21:31:01 -07:00
process ci: defer native lifecycle matrices to release verification (#156077) 2026-09-23 04:06:04 +00:00
projects refactor(mcp): run OAuth writes and leases in the state worker (#148859) 2026-09-21 20:35:55 -07:00
provider-runtime
proxy-capture fix: keep cold child compilation outside CI test deadlines (#156011) 2026-09-22 17:41:19 -07:00
realtime-transcription
routing
scripts fix: keep cold child compilation outside CI test deadlines (#156011) 2026-09-22 17:41:19 -07:00
secrets fix(secrets): use bounded JSON reads for audit inputs (#155683) 2026-09-22 05:00:49 -07:00
security fix(skills): stop quarantining safety guides for prompt keywords (#154441) 2026-09-21 19:09:14 -07:00
session-cards
sessions perf(sessions): move streaming transcript writes off the main thread (#156095) 2026-09-23 03:48:47 +00:00
shared fix(worker): serialize workspace helpers from explicit source (#156068) 2026-09-22 21:59:03 -05:00
skills fix(skills): track coverage loss after watcher readiness (#155901) 2026-09-23 08:47:06 +08:00
snapshot perf(sqlite): trim snapshot worker startup imports 2026-09-22 01:41:08 -07:00
state perf(state): preserve lifecycle publication across concurrent writes (#155631) 2026-09-23 01:26:50 +00:00
status perf(state): move session RPC SQL off the Gateway main thread (#155740) 2026-09-22 15:27:37 -07:00
system-agent fix: keep ACP harness models out of native calls (#153756) 2026-09-22 22:58:40 +01:00
talk fix(test): await Talk storage cleanup before removing fixtures 2026-09-22 12:58:12 -07:00
tasks fix(tasks): release lineage for terminal creation receipts (#156111) 2026-09-23 04:03:33 +00:00
test-fixtures
test-helpers fix: keep cold child compilation outside CI test deadlines (#156011) 2026-09-22 17:41:19 -07:00
test-utils fix: avoid Gateway freezes when starting agent turns (#156064) 2026-09-22 19:16:15 -07:00
trajectory
transcripts fix(ci): reduce packed Node test tails (#155985) 2026-09-22 17:04:57 -07:00
tts
tui fix: keep cold child compilation outside CI test deadlines (#156011) 2026-09-22 17:41:19 -07:00
types
utils improve: reduce session delivery reader imports (#154740) 2026-09-21 04:26:04 -07:00
video-generation
web
web-fetch
web-search fix(web-search): prefer OAuth-ready Grok over Tavily during auto-detection (#156048) 2026-09-23 10:02:36 +05:30
wizard fix: keep cold child compilation outside CI test deadlines (#156011) 2026-09-22 17:41:19 -07:00
worker fix(worker): serialize workspace helpers from explicit source (#156068) 2026-09-22 21:59:03 -05:00
browser-lifecycle-cleanup.test.ts fix(browser): preserve successor tabs during stale cleanup (#155307) 2026-09-21 18:09:09 -07:00
browser-lifecycle-cleanup.ts fix(browser): preserve successor tabs during stale cleanup (#155307) 2026-09-21 18:09:09 -07:00
docker-build-cache.test.ts
docker-healthcheck.test.ts
docker-healthcheck.ts
docker-image-digests.test.ts
docker-setup.e2e.test-support.ts
docker-setup.e2e.test.ts
dockerfile.test.ts
entry.compile-cache.test.ts
entry.compile-cache.ts
entry.esm-resolve-fast-path.test.ts
entry.esm-resolve-fast-path.ts
entry.memory-json.test.ts refactor: compact agent storage and index full-text maintenance (#153683) 2026-09-21 16:23:13 -07:00
entry.respawn-diagnostics.test.ts
entry.respawn.test.ts
entry.respawn.ts
entry.run-main.test.ts
entry.test.ts
entry.ts
entry.version-fast-path.test.ts
entry.version-fast-path.ts
global-state.ts
globals.test.ts
globals.ts
index.entrypoint.test.ts
index.test.ts
index.ts
install-sh-version.test.ts
library.test.ts
library.ts
logger.test.ts
logger.ts
logging.ts
param-key.ts
plugin-activation-boundary.test.ts
poll-params.test.ts
poll-params.ts
polls.test.ts
polls.ts
runtime.test.ts
runtime.ts
tsconfig.json improve(ci): shorten complete lint and typecheck jobs (#154150) 2026-09-21 17:11:25 +00:00
utils.test.ts
utils.ts
version.test.ts
version.ts