refactor(search): fold zai-search into the glm provider
The separate zai-search entry showed "No connections" on the web search page because credentials live on the `glm` connection, not on it. Every other provider that does both chat and search (antigravity, kimi, xai, gemini) declares webSearch on the provider itself, so do the same here. - glm gains serviceKinds ["llm", "webSearch"] and the MCP searchConfig - the request builder / normalizer move from "zai-search" to "glm" - drop the zai-search registry entry and its svg logo, which also removes the only need for svg logo support in getProviderIconSrc ollama-search keeps its own entry and credentialFallback: its search endpoint is unrelated to the ollama chat transport.
This commit is contained in:
@@ -394,12 +394,12 @@ function buildOllamaSearchRequest(config, params) {
|
||||
};
|
||||
}
|
||||
|
||||
// ── Z.AI Coding plan MCP web_search_prime ─────────────────────────────────
|
||||
// ── GLM Coding plan MCP web_search_prime ──────────────────────────────────
|
||||
// POST https://api.z.ai/api/mcp/web_search_prime/mcp
|
||||
// JSON-RPC envelope: { jsonrpc, id, method: "tools/call",
|
||||
// params: { name: "web_search_prime", arguments: { search_query, count } } }
|
||||
// Response: { result: { content: [{ type: "text", text: "<json>" }] } }
|
||||
function buildZaiSearchRequest(config, params) {
|
||||
function buildGlmSearchRequest(config, params) {
|
||||
const body = {
|
||||
jsonrpc: "2.0",
|
||||
id: `9r-${Date.now()}`,
|
||||
@@ -437,7 +437,7 @@ const BUILDERS = {
|
||||
"searxng": buildSearxngRequest,
|
||||
"xquik": buildXquikRequest,
|
||||
"ollama-search": buildOllamaSearchRequest,
|
||||
"zai-search": buildZaiSearchRequest,
|
||||
"glm": buildGlmSearchRequest,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -257,7 +257,7 @@ function normalizeOllamaSearch(data, _query, _searchType) {
|
||||
return { results, totalResults: results.length };
|
||||
}
|
||||
|
||||
function normalizeZaiSearch(data, _query, _searchType) {
|
||||
function normalizeGlmSearch(data, _query, _searchType) {
|
||||
const now = new Date().toISOString();
|
||||
// MCP envelope: { result: { content: [{ type: "text", text: "<json>" }] } }
|
||||
let payload = data;
|
||||
@@ -270,7 +270,7 @@ function normalizeZaiSearch(data, _query, _searchType) {
|
||||
: Array.isArray(payload) ? payload
|
||||
: [];
|
||||
const results = items.map((item, idx) =>
|
||||
makeResult("zai-search", {
|
||||
makeResult("glm", {
|
||||
title: item.title,
|
||||
url: item.link || item.url,
|
||||
snippet: item.content || "",
|
||||
@@ -295,7 +295,7 @@ const NORMALIZERS = {
|
||||
"searxng": normalizeSearxng,
|
||||
"xquik": normalizeXquik,
|
||||
"ollama-search": normalizeOllamaSearch,
|
||||
"zai-search": normalizeZaiSearch,
|
||||
"glm": normalizeGlmSearch,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,6 +53,20 @@ export default {
|
||||
{ id: "glm-4.7", name: "GLM 4.7" },
|
||||
{ id: "glm-4.6v", name: "GLM 4.6V (Vision)" },
|
||||
],
|
||||
serviceKinds: ["llm", "webSearch"],
|
||||
// Coding plan bundles web search on the same API key as chat.
|
||||
searchConfig: {
|
||||
baseUrl: "https://api.z.ai/api/mcp/web_search_prime/mcp",
|
||||
method: "POST",
|
||||
authType: "apikey",
|
||||
authHeader: "bearer",
|
||||
costPerQuery: 0,
|
||||
searchTypes: ["web"],
|
||||
defaultMaxResults: 5,
|
||||
maxMaxResults: 50,
|
||||
timeoutMs: 10000,
|
||||
cacheTTLMs: 300000,
|
||||
},
|
||||
features: {
|
||||
usage: true,
|
||||
usageApikey: true,
|
||||
|
||||
@@ -98,7 +98,6 @@ import p95 from "./xai.js";
|
||||
import p96 from "./xiaomi-mimo.js";
|
||||
import p97 from "./xiaomi-tokenplan.js";
|
||||
import p98 from "./youcom.js";
|
||||
import p124 from "./zai-search.js";
|
||||
import p99 from "./alims-intl.js";
|
||||
import p100 from "./codebuddy-intl.js";
|
||||
// Temporarily hidden — no tool calling support (trae SOLO agent / windsurf gRPC skip ToolCallChunk).
|
||||
@@ -225,7 +224,6 @@ export default [
|
||||
p96,
|
||||
p97,
|
||||
p98,
|
||||
p124,
|
||||
p99,
|
||||
p100,
|
||||
// p102, // trae — hidden, no tool calling
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
export default {
|
||||
id: "zai-search",
|
||||
alias: "zai-search",
|
||||
display: {
|
||||
name: "GLM Coding Search",
|
||||
icon: "travel_explore",
|
||||
color: "#2563EB",
|
||||
textIcon: "GS",
|
||||
website: "https://z.ai",
|
||||
notice: {
|
||||
text: "Web search via the Z.AI Coding plan MCP endpoint. Reuses the API key from the GLM Coding provider.",
|
||||
apiKeyUrl: "https://open.bigmodel.cn/usercenter/apikeys",
|
||||
},
|
||||
},
|
||||
category: "apikey",
|
||||
authType: "apikey",
|
||||
authModes: ["apikey"],
|
||||
serviceKinds: ["webSearch"],
|
||||
// Credential fallback: reuses the GLM Coding plan API key — one key, chat + search.
|
||||
credentialFallback: "glm",
|
||||
searchConfig: {
|
||||
baseUrl: "https://api.z.ai/api/mcp/web_search_prime/mcp",
|
||||
method: "POST",
|
||||
authType: "apikey",
|
||||
authHeader: "bearer",
|
||||
costPerQuery: 0,
|
||||
freeMonthlyQuota: 0,
|
||||
searchTypes: ["web"],
|
||||
defaultMaxResults: 5,
|
||||
maxMaxResults: 50,
|
||||
timeoutMs: 10000,
|
||||
cacheTTLMs: 300000,
|
||||
},
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="128" height="128" rx="28" fill="#6366f1"/>
|
||||
<text x="64" y="64" text-anchor="middle" dominant-baseline="central" font-family="system-ui,-apple-system,sans-serif" font-size="48" font-weight="700" fill="#ffffff">Z</text>
|
||||
<text x="64" y="98" text-anchor="middle" dominant-baseline="central" font-family="system-ui,-apple-system,sans-serif" font-size="16" font-weight="600" fill="#c7d2fe">.AI</text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 521 B |
@@ -8,9 +8,6 @@ const ICON_ALIASES = {
|
||||
"ollama-search": "ollama",
|
||||
};
|
||||
|
||||
// Providers that ship an .svg logo instead of .png.
|
||||
const SVG_PROVIDER_IDS = new Set(["zai-search"]);
|
||||
|
||||
// Runtime only — first 404 remembers id for the whole session
|
||||
const failedIds = new Set();
|
||||
|
||||
@@ -29,13 +26,10 @@ export function resolveProviderIconId(providerId) {
|
||||
return aliased;
|
||||
}
|
||||
|
||||
/** `/providers/{id}.{png|svg}` or null when previously failed. */
|
||||
/** `/providers/{id}.png` or null when previously failed. */
|
||||
export function getProviderIconSrc(providerId) {
|
||||
const id = resolveProviderIconId(providerId);
|
||||
if (!id) return null;
|
||||
// svg for vector logos, png for everything else
|
||||
const ext = SVG_PROVIDER_IDS.has(id) ? "svg" : "png";
|
||||
return `/providers/${id}.${ext}`;
|
||||
return id ? `/providers/${id}.png` : null;
|
||||
}
|
||||
|
||||
/** Call from img onError so later mounts skip the request. */
|
||||
|
||||
Reference in New Issue
Block a user