@klarkxy/dsh-web-search-manager 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/docs/README.zh-CN.md +3 -0
- package/lib/client.inner.cjs +147 -26
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +147 -26
- package/lib/contracts.d.ts +3 -25
- package/lib/contracts.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +19 -59
- package/lib/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @klarkxy/dsh-web-search-manager
|
|
2
2
|
|
|
3
|
+
<!-- release-state-note -->
|
|
4
|
+
The [repository registry](../../README.md#plugin-lifecycle) tracks Draft → Testing → Published, moving forward only. Fixes, testing and version updates keep published packages Published; each update still passes release checks. First publication explicitly selects Testing packages and records Published only after npm archive verification. See the [release guide](../../RELEASING.md).
|
|
5
|
+
|
|
3
6
|
Choose which service answers the agent's web searches, set the limits every request runs under, and let the agent read public pages — all from one settings page.
|
|
4
7
|
|
|
5
8
|
[简体中文](docs/README.zh-CN.md)
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @klarkxy/dsh-web-search-manager
|
|
2
2
|
|
|
3
|
+
<!-- release-state-note -->
|
|
4
|
+
插件生命周期见[仓库状态清单](../../../README.zh-CN.md#插件生命周期):草稿 → 测试中 → 已发布,只向前推进。已发布插件的修复、测试和升版保持已发布;每次更新仍须通过发布检查。首次发布须明确选择测试中的包,并在 npm 归档验证成功后登记。详见[发布规则](../../../RELEASING.zh-CN.md)。
|
|
5
|
+
|
|
3
6
|
在一个设置页里挑选用哪个服务回答模型的网络搜索、设定每次请求的上限,并让模型读取公开网页。
|
|
4
7
|
|
|
5
8
|
[English](../README.md)
|
package/lib/client.inner.cjs
CHANGED
|
@@ -2,6 +2,47 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
3
3
|
let react = require("react");
|
|
4
4
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
//#region src/client-error.ts
|
|
6
|
+
/** Local adapter diagnostics only; third-party descriptions remain verbatim. */
|
|
7
|
+
const localErrors = {
|
|
8
|
+
"网络搜索设置格式无效。": "Invalid web search settings format.",
|
|
9
|
+
"未知操作。": "Unknown operation.",
|
|
10
|
+
"网络设置操作失败,请刷新后重试。": "The network settings operation failed. Refresh and try again.",
|
|
11
|
+
"查询须为 1 至 4000 字符。": "The query must contain 1 to 4,000 characters.",
|
|
12
|
+
"网络搜索插件已停止。": "The web search plugin has stopped.",
|
|
13
|
+
"请在设置 → 网络搜索中配置凭据并启用。": "Configure credentials and enable web search in Settings → Web search.",
|
|
14
|
+
"网络访问设置已改变,请重新发起请求。": "Network access settings changed. Start the request again.",
|
|
15
|
+
"网络请求已取消。": "The network request was cancelled.",
|
|
16
|
+
"网络请求已取消或超时。": "The network request was cancelled or timed out.",
|
|
17
|
+
"设置已被其他页面修改,请刷新后重试。": "Settings changed in another page. Refresh and try again.",
|
|
18
|
+
"供应商不支持自定义地址。": "The provider does not support a custom address.",
|
|
19
|
+
"供应商地址须为无凭据、无查询参数的 HTTPS 地址。": "The provider address must use HTTPS without credentials or query parameters.",
|
|
20
|
+
"需选择已安装的供应商并填写有效凭据。": "Choose an installed provider and enter valid credentials.",
|
|
21
|
+
"保存失败,本次运行已暂停网络访问以防意外联网。": "Saving failed. Network access is paused for this run to prevent unintended requests.",
|
|
22
|
+
"供应商未提供错误描述。": "The provider did not supply an error description.",
|
|
23
|
+
"供应商请求失败。": "Provider request failed.",
|
|
24
|
+
"搜索凭据已删除或不可用,请重新配置。": "Search credentials were deleted or are unavailable. Configure them again.",
|
|
25
|
+
"供应商配置不可用。": "Provider configuration is unavailable.",
|
|
26
|
+
"查询无效。": "Invalid query.",
|
|
27
|
+
"结果数须为 1 至 20。": "The result count must be from 1 to 20.",
|
|
28
|
+
"搜索已取消。": "Search cancelled.",
|
|
29
|
+
"Tavily 搜索已取消。": "Tavily search cancelled.",
|
|
30
|
+
"响应格式无效。": "Invalid response shape",
|
|
31
|
+
"响应缺失。": "Missing response",
|
|
32
|
+
"响应过大。": "Response too large",
|
|
33
|
+
"地址无效。": "Invalid endpoint"
|
|
34
|
+
};
|
|
35
|
+
function localErrorText(message, locale) {
|
|
36
|
+
const prefix = message.match(/^(\[(?:search|fetch):[^\]]+\] )(.*)$/s);
|
|
37
|
+
if (prefix) return prefix[1] + localErrorText(prefix[2], locale);
|
|
38
|
+
if (locale === "zh") return Object.entries(localErrors).find(([, english]) => english === message)?.[0] ?? message;
|
|
39
|
+
if (localErrors[message]) return localErrors[message];
|
|
40
|
+
const http = message.match(/^供应商请求失败(HTTP (\d{3}))。$/);
|
|
41
|
+
if (http) return `Provider request failed (HTTP ${http[1]}).`;
|
|
42
|
+
const config = message.match(/^(brave|bocha|firecrawl|serper|Tavily) 配置不可用。$/);
|
|
43
|
+
if (config) return `${config[1]} configuration is unavailable.`;
|
|
44
|
+
return message;
|
|
45
|
+
}
|
|
5
46
|
Object.values({
|
|
6
47
|
/** Surfaces, from the page up to the topmost nested card. */
|
|
7
48
|
surface: [
|
|
@@ -299,7 +340,7 @@ ${scope} {
|
|
|
299
340
|
border: 0.5px solid var(--dsw-alias-border-l3);
|
|
300
341
|
border-radius: var(--dsw-radius-md);
|
|
301
342
|
background: var(--dsw-alias-bg-layer-1);
|
|
302
|
-
font-family: var(--ds-font-family-code
|
|
343
|
+
font-family: var(--ds-font-family-code);
|
|
303
344
|
font-size: 12px;
|
|
304
345
|
line-height: 20px;
|
|
305
346
|
color: var(--dsw-alias-label-secondary);
|
|
@@ -462,6 +503,58 @@ const providerInfo = {
|
|
|
462
503
|
pricingUrl: "https://docs.tavily.com/documentation/api-credits"
|
|
463
504
|
}
|
|
464
505
|
};
|
|
506
|
+
const englishInfo = {
|
|
507
|
+
ddg: {
|
|
508
|
+
description: "Search public DuckDuckGo pages without registration or an API key.",
|
|
509
|
+
pricing: "Free to use; no search API fees."
|
|
510
|
+
},
|
|
511
|
+
bocha: {
|
|
512
|
+
description: "Search Chinese web content, returning titles, links and summaries.",
|
|
513
|
+
pricing: "Charged per request: listed price ¥0.036/request; trial credits depend on official offers."
|
|
514
|
+
},
|
|
515
|
+
brave: {
|
|
516
|
+
description: "Search web pages, news and more with Brave’s independent index.",
|
|
517
|
+
pricing: "$5 in monthly credits (about 1,000 requests); then $5/1,000 requests. A payment card is required to activate."
|
|
518
|
+
},
|
|
519
|
+
"deepseek-official": {
|
|
520
|
+
description: "Call built-in search through a DeepSeek model using the model API key.",
|
|
521
|
+
pricing: "Default Flash token pricing per million: input ¥1–2 (cache hits ¥0.02–0.04), output ¥4–8, varying by peak/off-peak hours. Platform terms govern promotional balance and tool fees."
|
|
522
|
+
},
|
|
523
|
+
exa: {
|
|
524
|
+
description: "Web search for AI with relevant pages and content snippets.",
|
|
525
|
+
pricing: "$20 on signup, then $10 monthly credits; $7/1,000 requests (up to 10 results each), plus $1/1,000 additional results beyond 10."
|
|
526
|
+
},
|
|
527
|
+
firecrawl: {
|
|
528
|
+
description: "Search the web and extract page content.",
|
|
529
|
+
pricing: "1,000 free credits/month; 2 credits per 10 search results. Hobby includes 5,000 credits/month at $16/month billed annually; extra credits cost $5/1,000."
|
|
530
|
+
},
|
|
531
|
+
serper: {
|
|
532
|
+
description: "Get Google web search results.",
|
|
533
|
+
pricing: "2,500 one-time signup requests; $50/50,000 requests ($1/1,000). Paid credits expire after 6 months."
|
|
534
|
+
},
|
|
535
|
+
tavily: {
|
|
536
|
+
description: "Web search for AI, currently using basic search.",
|
|
537
|
+
pricing: "1,000 free credits/month; basic search uses 1 credit/request. Pay as you go: $0.008/credit ($8/1,000 requests)."
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
const bundledDescriptions = {
|
|
541
|
+
ddg: ["无需注册。默认后端。", "No registration required. Default backend."],
|
|
542
|
+
"deepseek-official": ["使用已配置的 DeepSeek API Key,可能产生额外搜索费用。", "Uses the configured DeepSeek API key; additional search fees may apply."],
|
|
543
|
+
exa: ["独立 Search API。", "Independent Search API."],
|
|
544
|
+
brave: ["Brave Search API。", "Brave Search API."],
|
|
545
|
+
bocha: ["中文网页搜索 API。", "Chinese web search API."],
|
|
546
|
+
serper: ["Google 结果的 Search API。", "Search API for Google results."],
|
|
547
|
+
firecrawl: ["网页搜索与提取 API。", "Web search and extraction API."],
|
|
548
|
+
tavily: ["Search API;固定 basic 检索,不自动升级搜索深度。", "Search API using basic search; search depth is never upgraded automatically."]
|
|
549
|
+
};
|
|
550
|
+
/** Translate only manager-owned labels; externally supplied metadata stays verbatim. */
|
|
551
|
+
function providerDisplayLabel(provider, locale) {
|
|
552
|
+
if (!bundledCatalogId(provider)) return provider.label;
|
|
553
|
+
if (provider.label === "DeepSeek 搜索") return locale === "zh" ? provider.label : "DeepSeek search";
|
|
554
|
+
if (provider.label === "博查") return locale === "zh" ? provider.label : "Bocha";
|
|
555
|
+
if (provider.label === "网页读取") return locale === "zh" ? provider.label : "Read web pages";
|
|
556
|
+
return provider.label;
|
|
557
|
+
}
|
|
465
558
|
function bundledCatalogId(provider) {
|
|
466
559
|
if (!(typeof provider.configurationOwned === "boolean" ? provider.configurationOwned : !provider.configurationOwner || provider.configurationOwner === "@klarkxy/dsh-web-search-manager")) return;
|
|
467
560
|
return provider.id === "deepseek-managed" ? "deepseek-official" : provider.id;
|
|
@@ -476,8 +569,13 @@ function usesBundledPricing(provider) {
|
|
|
476
569
|
}
|
|
477
570
|
function searchProviderInfo(provider, locale = "zh") {
|
|
478
571
|
const catalogId = bundledCatalogId(provider);
|
|
479
|
-
const
|
|
480
|
-
const
|
|
572
|
+
const base = catalogId && Object.hasOwn(providerInfo, catalogId) ? providerInfo[catalogId] : void 0;
|
|
573
|
+
const known = base && locale === "en" ? {
|
|
574
|
+
...base,
|
|
575
|
+
...englishInfo[catalogId]
|
|
576
|
+
} : base;
|
|
577
|
+
const ownedCopy = catalogId ? bundledDescriptions[catalogId] : void 0;
|
|
578
|
+
const description = ownedCopy && provider.description === ownedCopy[0] ? ownedCopy[locale === "zh" ? 0 : 1] : base && provider.description === base.description ? known.description : provider.description.trim() ? provider.description : known?.description ?? provider.description;
|
|
481
579
|
if (provider.pricing?.trim()) return {
|
|
482
580
|
description,
|
|
483
581
|
pricing: provider.pricing,
|
|
@@ -783,6 +881,26 @@ const copy = {
|
|
|
783
881
|
unknownOwner: "Configure this service in its plugin"
|
|
784
882
|
}
|
|
785
883
|
};
|
|
884
|
+
var UiError = class extends Error {
|
|
885
|
+
key;
|
|
886
|
+
constructor(key) {
|
|
887
|
+
super(key);
|
|
888
|
+
this.key = key;
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
function uiMessage(message, locale, providers = []) {
|
|
892
|
+
if (typeof message === "string") return localErrorText(message, locale);
|
|
893
|
+
if ("key" in message) return copy[locale][message.key];
|
|
894
|
+
if ("sources" in message) return testOkText(locale, message.sources);
|
|
895
|
+
if ("moved" in message) {
|
|
896
|
+
const provider = providers.find((item) => item.id === message.moved);
|
|
897
|
+
return movedText(locale, provider ? providerDisplayLabel(provider, locale) : message.moved, message.position);
|
|
898
|
+
}
|
|
899
|
+
return message.invalid.map((key) => {
|
|
900
|
+
const [, min, max] = LIMITS.find((item) => item[0] === key);
|
|
901
|
+
return limitInvalidText(locale, copy[locale][key], min, max);
|
|
902
|
+
}).join(" ");
|
|
903
|
+
}
|
|
786
904
|
function movedText(locale, label, position) {
|
|
787
905
|
return locale === "zh" ? `${label} 已移至第 ${position} 位` : `${label} moved to position ${position}`;
|
|
788
906
|
}
|
|
@@ -968,7 +1086,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
968
1086
|
return next;
|
|
969
1087
|
} catch (cause) {
|
|
970
1088
|
if (!mountedRef.current || mine !== requestSeq.current) return;
|
|
971
|
-
setLoadError(cause instanceof Error && cause.message ? cause.message :
|
|
1089
|
+
setLoadError(cause instanceof Error && cause.message ? cause.message : { key: "failed" });
|
|
972
1090
|
if (source === "poll") return;
|
|
973
1091
|
throw cause;
|
|
974
1092
|
} finally {
|
|
@@ -979,7 +1097,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
979
1097
|
(0, react.useEffect)(() => {
|
|
980
1098
|
mountedRef.current = true;
|
|
981
1099
|
readGate.reset();
|
|
982
|
-
load().catch((cause) => setLoadError(cause instanceof Error && cause.message ? cause.message :
|
|
1100
|
+
load().catch((cause) => setLoadError(cause instanceof Error && cause.message ? cause.message : { key: "failed" }));
|
|
983
1101
|
const bind = () => bindStatusRefresh({
|
|
984
1102
|
isHidden: () => isPageHidden(hiddenRef.current),
|
|
985
1103
|
tick: async () => {
|
|
@@ -1034,7 +1152,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1034
1152
|
try {
|
|
1035
1153
|
await run();
|
|
1036
1154
|
} catch (cause) {
|
|
1037
|
-
setError(cause instanceof Error && cause.message ? cause.message :
|
|
1155
|
+
setError(cause instanceof UiError ? { key: cause.key } : cause instanceof Error && cause.message ? cause.message : { key: "failed" });
|
|
1038
1156
|
await load().catch(() => {});
|
|
1039
1157
|
} finally {
|
|
1040
1158
|
busyRef.current = false;
|
|
@@ -1067,7 +1185,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1067
1185
|
const snapshot = keys[provider.id] ?? "";
|
|
1068
1186
|
const typed = snapshot.trim();
|
|
1069
1187
|
if (!ownsProviderConfiguration(provider) || !provider.credentialRef || !typed) continue;
|
|
1070
|
-
if (writable[provider.credentialRef] === false) throw new
|
|
1188
|
+
if (writable[provider.credentialRef] === false) throw new UiError("readOnly");
|
|
1071
1189
|
unwrap(await client.remote.credentials.set(provider.credentialRef, typed));
|
|
1072
1190
|
setKeys((current) => current[provider.id] === snapshot ? {
|
|
1073
1191
|
...current,
|
|
@@ -1083,14 +1201,14 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1083
1201
|
[provider.id]: ""
|
|
1084
1202
|
}));
|
|
1085
1203
|
await load();
|
|
1086
|
-
setNote(
|
|
1204
|
+
setNote({ key: "keyDeleted" });
|
|
1087
1205
|
}
|
|
1088
1206
|
if (!status || !limitDraft) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1089
1207
|
className: "web-search-settings ws-root dsh-ui-panel",
|
|
1090
1208
|
children: [loadError ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1091
1209
|
role: "alert",
|
|
1092
1210
|
className: "dsh-ui-error",
|
|
1093
|
-
children: [text.loadFailed, loadError]
|
|
1211
|
+
children: [text.loadFailed, uiMessage(loadError, locale, status?.providers)]
|
|
1094
1212
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1095
1213
|
role: "status",
|
|
1096
1214
|
className: "dsh-ui-hint",
|
|
@@ -1129,7 +1247,10 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1129
1247
|
pendingRef.current = next;
|
|
1130
1248
|
setPendingOrder(next);
|
|
1131
1249
|
if (keyboard) refocusRef.current = id;
|
|
1132
|
-
setSortAnnouncement(
|
|
1250
|
+
setSortAnnouncement({
|
|
1251
|
+
moved: id,
|
|
1252
|
+
position: nextIndex + 1
|
|
1253
|
+
});
|
|
1133
1254
|
clearTimeout(timerRef.current);
|
|
1134
1255
|
timerRef.current = setTimeout(() => {
|
|
1135
1256
|
timerRef.current = void 0;
|
|
@@ -1150,13 +1271,13 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1150
1271
|
const value = parseLimit(limitDraft[key], min, max);
|
|
1151
1272
|
if (value === void 0) {
|
|
1152
1273
|
nextInvalid[key] = true;
|
|
1153
|
-
messages.push(
|
|
1274
|
+
messages.push(key);
|
|
1154
1275
|
} else parsed[key] = value;
|
|
1155
1276
|
}
|
|
1156
1277
|
setInvalid(nextInvalid);
|
|
1157
1278
|
if (messages.length) {
|
|
1158
1279
|
setNote("");
|
|
1159
|
-
setError(messages
|
|
1280
|
+
setError({ invalid: messages });
|
|
1160
1281
|
return;
|
|
1161
1282
|
}
|
|
1162
1283
|
action(async () => {
|
|
@@ -1170,7 +1291,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1170
1291
|
expectedRevision: current.settings.revision
|
|
1171
1292
|
}), true);
|
|
1172
1293
|
await load();
|
|
1173
|
-
setNote(
|
|
1294
|
+
setNote({ key: "saved" });
|
|
1174
1295
|
});
|
|
1175
1296
|
}
|
|
1176
1297
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -1197,19 +1318,19 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1197
1318
|
className: "ws-sr-only",
|
|
1198
1319
|
role: "status",
|
|
1199
1320
|
"aria-live": "polite",
|
|
1200
|
-
children: sortAnnouncement
|
|
1321
|
+
children: uiMessage(sortAnnouncement, locale, saved.providers)
|
|
1201
1322
|
}),
|
|
1202
1323
|
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1203
1324
|
role: "alert",
|
|
1204
1325
|
className: "dsh-ui-error",
|
|
1205
|
-
children: error
|
|
1326
|
+
children: uiMessage(error, locale, saved.providers)
|
|
1206
1327
|
}),
|
|
1207
1328
|
loadError ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1208
1329
|
className: "dsh-ui-stack",
|
|
1209
1330
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1210
1331
|
role: "alert",
|
|
1211
1332
|
className: "dsh-ui-error",
|
|
1212
|
-
children: [text.loadFailed, loadError]
|
|
1333
|
+
children: [text.loadFailed, uiMessage(loadError, locale, status?.providers)]
|
|
1213
1334
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1214
1335
|
variant: "outline",
|
|
1215
1336
|
size: "sm",
|
|
@@ -1223,7 +1344,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1223
1344
|
note && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1224
1345
|
role: "status",
|
|
1225
1346
|
className: "dsh-ui-notice",
|
|
1226
|
-
children: note
|
|
1347
|
+
children: uiMessage(note, locale, saved.providers)
|
|
1227
1348
|
}),
|
|
1228
1349
|
saved.storageFailed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1229
1350
|
role: "alert",
|
|
@@ -1349,7 +1470,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1349
1470
|
}),
|
|
1350
1471
|
draggable: !busy,
|
|
1351
1472
|
"aria-disabled": busy,
|
|
1352
|
-
"aria-label": text.dragPrefix + provider
|
|
1473
|
+
"aria-label": text.dragPrefix + providerDisplayLabel(provider, locale),
|
|
1353
1474
|
title: text.dragHint,
|
|
1354
1475
|
onDragStart: (event) => {
|
|
1355
1476
|
if (busy) {
|
|
@@ -1381,7 +1502,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1381
1502
|
children: [
|
|
1382
1503
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
1383
1504
|
className: "dsh-ui-heading",
|
|
1384
|
-
children: provider
|
|
1505
|
+
children: providerDisplayLabel(provider, locale)
|
|
1385
1506
|
}),
|
|
1386
1507
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1387
1508
|
className: "ws-provider-note",
|
|
@@ -1393,7 +1514,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1393
1514
|
}),
|
|
1394
1515
|
provider.signupUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AppLink, {
|
|
1395
1516
|
url: provider.signupUrl,
|
|
1396
|
-
label: provider
|
|
1517
|
+
label: providerDisplayLabel(provider, locale) + " " + text.signup,
|
|
1397
1518
|
children: text.signup
|
|
1398
1519
|
})
|
|
1399
1520
|
]
|
|
@@ -1402,7 +1523,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1402
1523
|
className: "web-search-provider-info",
|
|
1403
1524
|
children: [info.description ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: info.description }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [info.pricing, info.pricingUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [" ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AppLink, {
|
|
1404
1525
|
url: info.pricingUrl,
|
|
1405
|
-
label: provider
|
|
1526
|
+
label: providerDisplayLabel(provider, locale) + " " + text.pricing,
|
|
1406
1527
|
children: provider.id === "ddg" ? text.website : text.pricing
|
|
1407
1528
|
})] })] })]
|
|
1408
1529
|
}),
|
|
@@ -1422,7 +1543,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1422
1543
|
}) : null,
|
|
1423
1544
|
shared && participating && owned ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
|
|
1424
1545
|
className: "dsh-ui-meta",
|
|
1425
|
-
children: provider.credentialHint ?? text.sharedKey
|
|
1546
|
+
children: provider.credentialHint === "与模型设置共用 Key" ? locale === "zh" ? provider.credentialHint : "Shares a key with model settings" : provider.credentialHint ?? text.sharedKey
|
|
1426
1547
|
}) : null,
|
|
1427
1548
|
showKey ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1428
1549
|
className: "dsh-ui-field",
|
|
@@ -1452,7 +1573,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1452
1573
|
onClick: () => void action(async () => {
|
|
1453
1574
|
await saveKeys(provider);
|
|
1454
1575
|
await load();
|
|
1455
|
-
setNote(
|
|
1576
|
+
setNote({ key: "keySaved" });
|
|
1456
1577
|
}),
|
|
1457
1578
|
children: text.saveKey
|
|
1458
1579
|
}) : null, needsKey && !shared && provider.configured ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfirmButton, {
|
|
@@ -1468,7 +1589,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1468
1589
|
className: "web-search-rank-move",
|
|
1469
1590
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
1470
1591
|
checked: participating,
|
|
1471
|
-
label: provider
|
|
1592
|
+
label: providerDisplayLabel(provider, locale),
|
|
1472
1593
|
disabled: busy,
|
|
1473
1594
|
onChange: (next) => {
|
|
1474
1595
|
const following = next ? [...order, provider.id] : order.filter((id) => id !== provider.id);
|
|
@@ -1494,7 +1615,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1494
1615
|
await saveKeys();
|
|
1495
1616
|
const result = await call("test");
|
|
1496
1617
|
await load();
|
|
1497
|
-
setNote(
|
|
1618
|
+
setNote({ sources: result.sources });
|
|
1498
1619
|
}),
|
|
1499
1620
|
children: text.test
|
|
1500
1621
|
})
|
|
@@ -1577,7 +1698,7 @@ function NetworkSearchSettings({ client, hidden }) {
|
|
|
1577
1698
|
]
|
|
1578
1699
|
}), saved.providers.filter((provider) => provider.kind === "fetch").map((provider) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
1579
1700
|
value: provider.id,
|
|
1580
|
-
children: [provider
|
|
1701
|
+
children: [providerDisplayLabel(provider, locale), provider.configured ? "" : " · " + text.unavailable]
|
|
1581
1702
|
}, provider.id))]
|
|
1582
1703
|
})]
|
|
1583
1704
|
}),
|