feat: web_search·ollama_web_search 폴백 체인 통일 + ollama_web_search 설명 정정

searchForSynthesis가 executeWebSearch에 위임하도록 재작성 — 두 툴이 동일한
6-provider 체인(searxng→ollama_cloud→tavily→google→brave→ddg→ddg_html) +
빈결과가드(21367ea) + 이벤트 보강을 공유. 이전엔 ollama_web_search가
searxng→ollama_cloud→ddg→ddg_html만 거치고 tavily/google/brave를 스킵하는
분리된 체인이었음(API 키가 없어 잠복 상태로 남아 있던 구멍).

ollamaWebSearchTool 설명이 "Ollama 모델이 DuckDuckGo 웹 검색을 수행"이라
적혀 있던 것을 실제 동작에 맞게 정정 — 코드가 먼저 폴백 체인으로 검색하고
Ollama chat API(config의 ollama.endpoint+model)는 요약만 담당. 모델은 검색을
직접 수행하거나 검색 여부를 결정하지 않음(환각 방지). 모델명처럼 변하는 값은
하드코딩하지 않고 config 참조로만 기술.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kim
2026-07-12 15:19:38 +09:00
co-authored by Claude
parent 20f0db935a
commit a11e554e88
+10 -20
View File
@@ -741,26 +741,16 @@ async function searchDDGHtml(query: string, limit: number): Promise<ToolResult>
};
}
// ── Shared fallback chain for search-then-synthesize callers (searxng → ollama_cloud → ddg → ddg_html) ──
// ── Shared fallback chain for search-then-synthesize callers ─────────────────
// Delegates to executeWebSearch so ollama_web_search uses the SAME provider chain
// as web_search (searxng → ollama_cloud → tavily → google → brave → ddg → ddg_html),
// including the empty-result guard (21367ea) and event-outcome enrichment. The two
// paths previously diverged here — ollama_web_search skipped tavily/google/brave and
// had no diagnostics — which stayed dormant only while those API keys were unset.
// searchOllama only consumes res.stdout, so the diagnostics/price-answer metadata
// executeWebSearch attaches to res.data is harmless here.
async function searchForSynthesis(query: string, limit: number): Promise<ToolResult> {
const cfg = getSearchConfig();
if (cfg.searxngUrl) {
try {
const res = await searchSearXNG(query, limit, cfg.searxngUrl);
if (res.success && res.stdout) return res;
} catch {}
}
if (cfg.ollamaApiKey) {
try {
const res = await searchOllamaCloud(query, limit, cfg.ollamaApiKey);
if (res.success && res.stdout) return res;
} catch {}
}
try {
const res = await searchDDG(query, limit);
if (res.success) return res;
} catch {}
return searchDDGHtml(query, limit);
return executeWebSearch({ query, max_results: limit });
}
// ── Ollama web-search (model-assisted) ────────────────────────────────────────
@@ -1015,7 +1005,7 @@ function getOllamaConfig(): { endpoint: string; model: string } {
export const ollamaWebSearchTool = {
name: 'ollama_web_search',
description: 'Ollama 모델이 DuckDuckGo 웹 검색을 수행하고 결과를 종합해서 자연어로 반환합니다. 일반 web_search와 달리 모델이 검색 결과를 해석·요약해서 답변합니다.',
description: '코드가 먼저 웹 검색을 수행하고(searxng→ollama_cloud→tavily→google→brave→ddg 폴백 체인, web_search와 동일) — 그 결과만 근거로 Ollama chat API(config의 ollama.endpoint+model, 변경 가능)가 자연어 답변을 요약·종합합니다. 모델은 검색을 직접 수행하거나 검색 여부를 결정하지 않음 — 코드가 무조건 검색한 결과 위에서만 답합니다(환각 방지). 참고: ollama_cloud provider(Ollama.com 웹서치 API)는 위 체인의 검색 후보 중 하나일 뿐, 이 툴과 별개.',
schema: {
query: 'string (required) - 검색 질문 또는 키워드',
max_results: 'number (optional, default 5) - 최대 검색 결과 수',