mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 13:23:50 +03:00
fix(search): prefer the configured search connection over duckduckgo-free
When no explicit provider is requested and the auto-selected cheapest provider has no credentials, executeWebSearch ran the fallbackOnly loop first. duckduckgo-free (costPerQuery 0, authType none) always won there with an empty credentials object, so a configured paid connection such as serper-search was silently ignored and the caller got success:true with zero results. Move the sweep for other credentialed regular providers ahead of the fallbackOnly loop (and exclude fallbackOnly ids from it, so a free last-resort provider never outranks a configured one on cost). The fallbackOnly loop stays as the true last resort. The chat path only appeared correct because duckduckgo-free happened to fail there and handleSearch retried the alternate provider; on /v1/responses it "succeeded" with no results. Closes #11524
This commit is contained in:
@@ -182,6 +182,30 @@ export async function executeWebSearch(
|
||||
} else {
|
||||
credentials = await resolveSearchCredentials(providerConfig.id);
|
||||
|
||||
if (!credentials) {
|
||||
// A CONFIGURED provider always wins over a free `fallbackOnly` one (issue #11524):
|
||||
// sweep every regular provider for real credentials BEFORE considering the
|
||||
// last-resort ones. Running the fallbackOnly loop first made `duckduckgo-free`
|
||||
// (costPerQuery 0, no credentials required) win unconditionally, so an operator's
|
||||
// paid search connection was silently ignored whenever the cheapest auto-selected
|
||||
// provider happened to have no credentials.
|
||||
const sortedIds = Object.values(SEARCH_PROVIDERS)
|
||||
.filter((provider) => !provider.fallbackOnly && supportsSearchType(provider, searchType))
|
||||
.sort((a, b) => a.costPerQuery - b.costPerQuery)
|
||||
.map((provider) => provider.id);
|
||||
|
||||
for (const providerId of sortedIds) {
|
||||
if (providerId === providerConfig.id) continue;
|
||||
const altConfig = getSearchProvider(providerId);
|
||||
const altCreds = await resolveSearchCredentials(providerId);
|
||||
if (altConfig && altCreds) {
|
||||
providerConfig = altConfig;
|
||||
credentials = altCreds;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!credentials) {
|
||||
const fallbackProviders = Object.values(SEARCH_PROVIDERS)
|
||||
.filter((provider) => provider.fallbackOnly && supportsSearchType(provider, searchType))
|
||||
@@ -201,24 +225,6 @@ export async function executeWebSearch(
|
||||
}
|
||||
}
|
||||
|
||||
if (!credentials) {
|
||||
const sortedIds = Object.values(SEARCH_PROVIDERS)
|
||||
.filter((provider) => supportsSearchType(provider, searchType))
|
||||
.sort((a, b) => a.costPerQuery - b.costPerQuery)
|
||||
.map((provider) => provider.id);
|
||||
|
||||
for (const providerId of sortedIds) {
|
||||
if (providerId === providerConfig.id) continue;
|
||||
const altConfig = getSearchProvider(providerId);
|
||||
const altCreds = await resolveSearchCredentials(providerId);
|
||||
if (altConfig && altCreds) {
|
||||
providerConfig = altConfig;
|
||||
credentials = altCreds;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!credentials) {
|
||||
throw new WebSearchExecutionError(
|
||||
`No credentials configured for any search provider. Add an API key for a search provider (${Object.keys(
|
||||
|
||||
Reference in New Issue
Block a user