haixunMaster/lib/search/orchestrator-search.ts

86 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

2026-06-21 12:50:31 +00:00
import { dedupeResults } from "./dedupe";
import { getSearchConfig } from "./config";
import {
DEFAULT_SEARCH_SOURCE_MODE,
modeAllowsBrave,
modeAllowsCrawler,
modeAllowsThreads,
type SearchSourceMode,
} from "./source-mode";
import type { KeywordInput, SearchProvider, SearchResult } from "./types";
export interface OrchestratedSearchResult {
results: SearchResult[];
providersUsed: string[];
}
export async function runOrchestratedSearch(
providers: {
threads: SearchProvider;
brave: SearchProvider;
crawler: SearchProvider;
},
keyword: KeywordInput,
options?: { skipCrawler?: boolean; sourceMode?: SearchSourceMode }
): Promise<OrchestratedSearchResult> {
const sourceMode = options?.sourceMode ?? DEFAULT_SEARCH_SOURCE_MODE;
const providersUsed: string[] = [];
let results: SearchResult[] = [];
if (modeAllowsThreads(sourceMode) && providers.threads.enabled()) {
const res = await providers.threads.search({
keyword: keyword.value,
limit: keyword.limit,
source: "threads",
searchType: "threads_keyword",
priority: keyword.priority,
});
if (res.status === "success" && res.results.length > 0) {
providersUsed.push("threads");
results = res.results;
}
}
if (
results.length === 0 &&
modeAllowsBrave(sourceMode) &&
keyword.priority === "high" &&
providers.brave.enabled()
) {
const res = await providers.brave.search({
keyword: keyword.value,
limit: Math.min(keyword.limit, getSearchConfig().brave.resultLimit),
source: "brave",
searchType: "web_search",
priority: keyword.priority,
patrolMode: true,
threadsOnly: true,
});
if (res.status === "success" && res.results.length > 0) {
providersUsed.push("brave");
results = res.results;
}
}
if (
results.length === 0 &&
modeAllowsCrawler(sourceMode) &&
!options?.skipCrawler &&
providers.crawler.enabled()
) {
const res = await providers.crawler.search({
keyword: keyword.value,
limit: keyword.limit,
source: "crawler",
searchType: "crawler",
priority: keyword.priority,
});
if (res.status === "success" && res.results.length > 0) {
providersUsed.push("crawler");
results = res.results;
}
}
results = dedupeResults(results);
return { results, providersUsed };
}