fix(ui): show web search providers for all models (#13472)

### What this PR does

Before this PR:
Web search provider options (Tavily, SearXNG, etc.) were only shown for
models matching `isFunctionCallingModel()` or when the user explicitly
set prompt tool-use mode. Local LLM models (e.g. Ollama) showed an empty
web search panel.

After this PR:
Web search provider options are always available for all models.

Fixes #13466

### Why we need it and why it was done in this way

At runtime, models that lack native function-calling support
automatically fall back to prompt-based tool use
(`ApiService.ts:254-256`), so web search providers work regardless of
model capability. The UI gate was unnecessarily restrictive and out of
sync with runtime behavior.

The following tradeoffs were made:
- This removes the UI-level capability check entirely. A discussion
point is whether users should be informed that prompt-based tool use is
being used as a fallback (no visual indicator currently exists).

The following alternatives were considered:
- Matching the gate to the runtime fallback condition
(`isFunctionCallingModel || isToolUseModeFunction`) — rejected because
prompt mode has almost no model restrictions, making any gate
unnecessary.

### Breaking changes

None.

### Special notes for your reviewer

**Behavior change**: selecting a web search provider on a
non-function-calling model now silently triggers prompt-based tool use
at runtime (this fallback already existed but was previously unreachable
from the UI). Please consider whether this implicit fallback is
acceptable or if it needs a user-visible indicator.

### Checklist

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [ ] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: N/A
- [x] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
Fixed web search provider options not showing for local LLM models (e.g. Ollama) in the chat input toolbar.
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Phantom
2026-03-15 09:49:20 +08:00
committed by GitHub
parent e860dd448f
commit c6ce1deecd

View File

@@ -12,7 +12,6 @@ import {
import type { QuickPanelListItem } from '@renderer/components/QuickPanel'
import { QuickPanelReservedSymbol } from '@renderer/components/QuickPanel'
import {
isFunctionCallingModel,
isGeminiModel,
isGPT5SeriesReasoningModel,
isOpenAIWebSearchModel,
@@ -27,7 +26,6 @@ import WebSearchService from '@renderer/services/WebSearchService'
import { getEffectiveMcpMode, type WebSearchProvider, type WebSearchProviderId } from '@renderer/types'
import { hasObjectKey } from '@renderer/utils'
import { isToolUseModeFunction } from '@renderer/utils/assistant'
import { isPromptToolUse } from '@renderer/utils/mcp-tools'
import { isGeminiWebSearchProvider } from '@renderer/utils/provider'
import { Globe } from 'lucide-react'
import { useCallback, useEffect, useMemo } from 'react'
@@ -138,24 +136,22 @@ export const useWebSearchPanelController = (assistantId: string, quickPanelContr
const providerItems = useMemo<QuickPanelListItem[]>(() => {
const isWebSearchModelEnabled = assistant.model && isWebSearchModel(assistant.model)
const items: QuickPanelListItem[] = []
if (isFunctionCallingModel(assistant.model) || isPromptToolUse(assistant)) {
items.push(
...providers
.map((p) => ({
label: p.name,
description: WebSearchService.isWebSearchEnabled(p.id)
? hasObjectKey(p, 'apiKey')
? t('settings.tool.websearch.apikey')
: t('settings.tool.websearch.free')
: t('chat.input.web_search.enable_content'),
icon: <WebSearchProviderIcon size={13} pid={p.id} />,
isSelected: p.id === assistant?.webSearchProviderId,
disabled: !WebSearchService.isWebSearchEnabled(p.id),
action: () => updateQuickPanelItem(p.id)
}))
.filter((item) => !item.disabled)
)
}
items.push(
...providers
.map((p) => ({
label: p.name,
description: WebSearchService.isWebSearchEnabled(p.id)
? hasObjectKey(p, 'apiKey')
? t('settings.tool.websearch.apikey')
: t('settings.tool.websearch.free')
: t('chat.input.web_search.enable_content'),
icon: <WebSearchProviderIcon size={13} pid={p.id} />,
isSelected: p.id === assistant?.webSearchProviderId,
disabled: !WebSearchService.isWebSearchEnabled(p.id),
action: () => updateQuickPanelItem(p.id)
}))
.filter((item) => !item.disabled)
)
if (isWebSearchModelEnabled) {
items.unshift({