feat(search): add ollama-search and zai-search with credential fallback
Register two web search providers that reuse an existing chat provider's API key instead of requiring their own connection: - ollama-search (POST ollama.com/api/web_search) reuses the `ollama` key - zai-search (POST api.z.ai MCP web_search_prime) reuses the `glm` key A new `credentialFallback` registry field drives this: when a search provider has no connection of its own, the search handler falls back to the linked chat provider's credentials. Also teach getProviderIconSrc to serve .svg logos for providers that ship vector art.
This commit is contained in:
@@ -240,6 +240,48 @@ function normalizeXquik(data, _query, _searchType) {
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeOllamaSearch(data, _query, _searchType) {
|
||||
const now = new Date().toISOString();
|
||||
const items = Array.isArray(data?.results) ? data.results : (Array.isArray(data) ? data : []);
|
||||
const results = items.map((item, idx) =>
|
||||
makeResult("ollama-search", {
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
snippet: item.content || item.snippet || "",
|
||||
full_text: item.content,
|
||||
text_format: "text",
|
||||
published_at: item.published_at || null,
|
||||
source_type: item.source || null,
|
||||
}, idx, now)
|
||||
);
|
||||
return { results, totalResults: results.length };
|
||||
}
|
||||
|
||||
function normalizeZaiSearch(data, _query, _searchType) {
|
||||
const now = new Date().toISOString();
|
||||
// MCP envelope: { result: { content: [{ type: "text", text: "<json>" }] } }
|
||||
let payload = data;
|
||||
const textContent = data?.result?.content?.[0]?.text;
|
||||
if (typeof textContent === "string") {
|
||||
try { payload = JSON.parse(textContent); } catch { payload = {}; }
|
||||
}
|
||||
const items = Array.isArray(payload?.results) ? payload.results
|
||||
: Array.isArray(payload?.news) ? payload.news
|
||||
: Array.isArray(payload) ? payload
|
||||
: [];
|
||||
const results = items.map((item, idx) =>
|
||||
makeResult("zai-search", {
|
||||
title: item.title,
|
||||
url: item.link || item.url,
|
||||
snippet: item.content || "",
|
||||
published_at: item.publish_date || item.published_at || null,
|
||||
favicon_url: item.icon || null,
|
||||
source_type: item.media || null,
|
||||
}, idx, now)
|
||||
);
|
||||
return { results, totalResults: results.length };
|
||||
}
|
||||
|
||||
const NORMALIZERS = {
|
||||
"serper": normalizeSerper,
|
||||
"brave-search": normalizeBrave,
|
||||
@@ -252,6 +294,8 @@ const NORMALIZERS = {
|
||||
"youcom": normalizeYouCom,
|
||||
"searxng": normalizeSearxng,
|
||||
"xquik": normalizeXquik,
|
||||
"ollama-search": normalizeOllamaSearch,
|
||||
"zai-search": normalizeZaiSearch,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user