dsh-web-search-plugin 0.1.1 → 0.1.2
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/CHANGELOG.md +47 -52
- package/README.md +77 -62
- package/cordis.patch.yml +20 -0
- package/lib/brave.js +157 -0
- package/lib/client.js +146 -59
- package/lib/index.js +79 -223
- package/lib/shared.js +100 -0
- package/lib/tavily.js +132 -0
- package/package.json +16 -4
package/lib/client.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Browser half of `dsh-web-search-plugin`: a plugin card under the
|
|
3
3
|
* "settings → Plugins → Plugin configuration" surface that edits the
|
|
4
|
-
* `dsh-web-search-plugin` settings namespace
|
|
4
|
+
* `dsh-web-search-plugin` settings namespace. The card switches the
|
|
5
|
+
* Tavily / Brave backend and writes each engine's credential through the
|
|
6
|
+
* credentials domain (`TAVILY_API_KEY` / `BRAVE_API_KEY` by default).
|
|
5
7
|
*
|
|
6
8
|
* This bundle is a self-contained hand-written module in the exact wire format
|
|
7
9
|
* the client module system expects: one `window.__ModuleLoader__.load` call
|
|
@@ -21,28 +23,40 @@ window.__ModuleLoader__.load({
|
|
|
21
23
|
let react = require("react");
|
|
22
24
|
let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
23
25
|
|
|
24
|
-
/** Settings namespace of
|
|
26
|
+
/** Settings namespace of this plugin. */
|
|
25
27
|
const NS = "dsh-web-search-plugin";
|
|
26
|
-
/** Credential reference
|
|
27
|
-
const
|
|
28
|
-
/**
|
|
29
|
-
const
|
|
28
|
+
/** Credential reference Tavily keyed mode resolves when the section names none. */
|
|
29
|
+
const DEFAULT_TAVILY_KEY_REF = "TAVILY_API_KEY";
|
|
30
|
+
/** Credential reference Brave resolves when the section names none. */
|
|
31
|
+
const DEFAULT_BRAVE_KEY_REF = "BRAVE_API_KEY";
|
|
32
|
+
/** Form field the Tavily write-only credential control stages under. */
|
|
33
|
+
const TAVILY_API_KEY_FIELD = "apiKey";
|
|
34
|
+
/** Form field the Brave write-only credential control stages under. */
|
|
35
|
+
const BRAVE_API_KEY_FIELD = "braveApiKey";
|
|
36
|
+
const SECRET_FIELDS = new Set([TAVILY_API_KEY_FIELD, BRAVE_API_KEY_FIELD]);
|
|
30
37
|
|
|
31
38
|
/** Locale bundles for the card. */
|
|
32
39
|
const en = {
|
|
33
|
-
nav: "Web search
|
|
34
|
-
description: "
|
|
40
|
+
nav: "Web search",
|
|
41
|
+
description: "Tavily (keyless by default) or Brave Search. Switching engines here is enough — web.searchProvider stays dsh-web-search.",
|
|
42
|
+
provider: "Search engine",
|
|
43
|
+
providerTavily: "Tavily",
|
|
44
|
+
providerBrave: "Brave Search",
|
|
35
45
|
mode: "Auth mode",
|
|
36
46
|
modeKeyless: "Keyless (free, rate-limited)",
|
|
37
47
|
modeKeyed: "API key",
|
|
38
48
|
apiKey: "API key",
|
|
39
49
|
apiKeyHint: "Stored outside the settings file. Leave blank to keep the current key.",
|
|
40
50
|
apiKeySet: "A key is configured.",
|
|
41
|
-
apiKeyUnset: "No key is configured; keyed search is unavailable until one is.",
|
|
51
|
+
apiKeyUnset: "No key is configured; keyed / Brave search is unavailable until one is.",
|
|
42
52
|
apiKeyEnv: "Credential reference",
|
|
43
|
-
apiKeyEnvHint: "Name of the credential/env var resolved for keyed search.",
|
|
53
|
+
apiKeyEnvHint: "Name of the credential/env var resolved for keyed Tavily search.",
|
|
54
|
+
braveApiKeyEnv: "Credential reference",
|
|
55
|
+
braveApiKeyEnvHint: "Name of the credential/env var resolved for Brave search.",
|
|
44
56
|
baseURL: "Endpoint",
|
|
45
57
|
baseURLHint: "Leave blank to use the provider default.",
|
|
58
|
+
braveBaseURL: "Endpoint",
|
|
59
|
+
braveBaseURLHint: "Leave blank to use the Brave Search API default.",
|
|
46
60
|
maxResults: "Max results",
|
|
47
61
|
maxResultsHint: "Sources returned per search (1-20).",
|
|
48
62
|
searchDepth: "Search depth",
|
|
@@ -53,6 +67,18 @@ window.__ModuleLoader__.load({
|
|
|
53
67
|
topic: "Topic",
|
|
54
68
|
topicGeneral: "General",
|
|
55
69
|
topicNews: "News",
|
|
70
|
+
country: "Country",
|
|
71
|
+
countryHint: "ISO 2-letter code (e.g. cn). Leave blank for Brave's default.",
|
|
72
|
+
searchLang: "Search language",
|
|
73
|
+
searchLangHint: "e.g. zh-hans or en. Leave blank for Brave's default.",
|
|
74
|
+
freshness: "Freshness",
|
|
75
|
+
freshnessAny: "Any time",
|
|
76
|
+
freshnessDay: "Past day",
|
|
77
|
+
freshnessWeek: "Past week",
|
|
78
|
+
freshnessMonth: "Past month",
|
|
79
|
+
freshnessYear: "Past year",
|
|
80
|
+
proxy: "Proxy",
|
|
81
|
+
proxyHint: "HTTP(S) proxy URL. Leave blank to use HTTPS_PROXY / HTTP_PROXY.",
|
|
56
82
|
expand: "Show settings",
|
|
57
83
|
collapse: "Hide settings",
|
|
58
84
|
save: "Save",
|
|
@@ -65,19 +91,26 @@ window.__ModuleLoader__.load({
|
|
|
65
91
|
};
|
|
66
92
|
/** Simplified Chinese copy. */
|
|
67
93
|
const zh = {
|
|
68
|
-
nav: "
|
|
69
|
-
description: "Tavily
|
|
94
|
+
nav: "网页搜索",
|
|
95
|
+
description: "Tavily(默认 keyless)或 Brave Search。在此切换引擎即可,不必改 web.searchProvider。",
|
|
96
|
+
provider: "搜索引擎",
|
|
97
|
+
providerTavily: "Tavily",
|
|
98
|
+
providerBrave: "Brave Search",
|
|
70
99
|
mode: "认证模式",
|
|
71
100
|
modeKeyless: "Keyless(免费、限流)",
|
|
72
101
|
modeKeyed: "API key",
|
|
73
102
|
apiKey: "API Key",
|
|
74
103
|
apiKeyHint: "不写入设置文件。留空表示保持当前密钥。",
|
|
75
104
|
apiKeySet: "已配置密钥。",
|
|
76
|
-
apiKeyUnset: "未配置密钥;keyed 模式下搜索不可用。",
|
|
105
|
+
apiKeyUnset: "未配置密钥;keyed / Brave 模式下搜索不可用。",
|
|
77
106
|
apiKeyEnv: "凭据引用名",
|
|
78
107
|
apiKeyEnvHint: "keyed 模式解析的凭据/环境变量名。",
|
|
108
|
+
braveApiKeyEnv: "凭据引用名",
|
|
109
|
+
braveApiKeyEnvHint: "Brave 搜索解析的凭据/环境变量名。",
|
|
79
110
|
baseURL: "接口地址",
|
|
80
111
|
baseURLHint: "留空则使用提供方默认地址。",
|
|
112
|
+
braveBaseURL: "接口地址",
|
|
113
|
+
braveBaseURLHint: "留空则使用 Brave Search API 默认地址。",
|
|
81
114
|
maxResults: "结果数量",
|
|
82
115
|
maxResultsHint: "每次搜索返回的源数量(1-20)。",
|
|
83
116
|
searchDepth: "搜索深度",
|
|
@@ -88,6 +121,18 @@ window.__ModuleLoader__.load({
|
|
|
88
121
|
topic: "主题",
|
|
89
122
|
topicGeneral: "通用",
|
|
90
123
|
topicNews: "新闻",
|
|
124
|
+
country: "国家/地区",
|
|
125
|
+
countryHint: "ISO 两位码(如 cn)。留空使用 Brave 默认。",
|
|
126
|
+
searchLang: "搜索语言",
|
|
127
|
+
searchLangHint: "如 zh-hans、en。留空使用 Brave 默认。",
|
|
128
|
+
freshness: "时效",
|
|
129
|
+
freshnessAny: "不限",
|
|
130
|
+
freshnessDay: "过去一天",
|
|
131
|
+
freshnessWeek: "过去一周",
|
|
132
|
+
freshnessMonth: "过去一月",
|
|
133
|
+
freshnessYear: "过去一年",
|
|
134
|
+
proxy: "代理",
|
|
135
|
+
proxyHint: "HTTP(S) 代理 URL。留空则使用 HTTPS_PROXY / HTTP_PROXY。",
|
|
91
136
|
expand: "展开设置",
|
|
92
137
|
collapse: "收起设置",
|
|
93
138
|
save: "保存",
|
|
@@ -123,7 +168,7 @@ window.__ModuleLoader__.load({
|
|
|
123
168
|
}
|
|
124
169
|
};
|
|
125
170
|
}
|
|
126
|
-
/** A choice field spec
|
|
171
|
+
/** A choice field spec: staged as its raw string. */
|
|
127
172
|
function choiceField(field) {
|
|
128
173
|
return {
|
|
129
174
|
field,
|
|
@@ -141,16 +186,30 @@ window.__ModuleLoader__.load({
|
|
|
141
186
|
}
|
|
142
187
|
|
|
143
188
|
/**
|
|
144
|
-
* Staged form over the `dsh-web-search-plugin` settings namespace.
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* domain addressed by the reference the section names.
|
|
189
|
+
* Staged form over the `dsh-web-search-plugin` settings namespace.
|
|
190
|
+
* Write-only credential fields (`apiKey`, `braveApiKey`) have no section
|
|
191
|
+
* spec and are written through the credentials domain.
|
|
148
192
|
*/
|
|
149
|
-
var
|
|
193
|
+
var SearchCardForm = class {
|
|
150
194
|
constructor(scope, api) {
|
|
151
195
|
this.scope = scope;
|
|
152
196
|
this.api = api;
|
|
153
|
-
this.specs = new Map([
|
|
197
|
+
this.specs = new Map([
|
|
198
|
+
choiceField("provider"),
|
|
199
|
+
choiceField("mode"),
|
|
200
|
+
numberField("maxResults"),
|
|
201
|
+
textField("apiKeyEnv"),
|
|
202
|
+
textField("baseURL"),
|
|
203
|
+
choiceField("searchDepth"),
|
|
204
|
+
choiceField("topic"),
|
|
205
|
+
booleanField("includeAnswer"),
|
|
206
|
+
textField("braveApiKeyEnv"),
|
|
207
|
+
textField("braveBaseURL"),
|
|
208
|
+
textField("country"),
|
|
209
|
+
textField("searchLang"),
|
|
210
|
+
choiceField("freshness"),
|
|
211
|
+
textField("proxy")
|
|
212
|
+
].map((spec) => [spec.field, spec]));
|
|
154
213
|
this.staged = new Map();
|
|
155
214
|
this.saving = false;
|
|
156
215
|
this.failed = false;
|
|
@@ -182,10 +241,7 @@ window.__ModuleLoader__.load({
|
|
|
182
241
|
}
|
|
183
242
|
field(field) {
|
|
184
243
|
const staged = this.staged.get(field);
|
|
185
|
-
|
|
186
|
-
// report only their staged draft (mirroring the official
|
|
187
|
-
// cards' secret-field branch in CardForm.field).
|
|
188
|
-
if (field === API_KEY_FIELD) return {
|
|
244
|
+
if (SECRET_FIELDS.has(field)) return {
|
|
189
245
|
text: staged?.text ?? "",
|
|
190
246
|
overridden: false,
|
|
191
247
|
invalid: false
|
|
@@ -206,9 +262,9 @@ window.__ModuleLoader__.load({
|
|
|
206
262
|
plan() {
|
|
207
263
|
const plan = [];
|
|
208
264
|
for (const [field, staged] of this.staged) {
|
|
209
|
-
if (field
|
|
265
|
+
if (SECRET_FIELDS.has(field)) {
|
|
210
266
|
const value = staged.text.trim();
|
|
211
|
-
if (value !== "") plan.push({ field, run: () => this.writeKey(value) });
|
|
267
|
+
if (value !== "") plan.push({ field, run: () => this.writeKey(field, value) });
|
|
212
268
|
continue;
|
|
213
269
|
}
|
|
214
270
|
const spec = this.specs.get(field);
|
|
@@ -269,6 +325,7 @@ window.__ModuleLoader__.load({
|
|
|
269
325
|
this.staged.set(field, edit);
|
|
270
326
|
this.failed = false;
|
|
271
327
|
this.publish();
|
|
328
|
+
if (field === "provider" || field === "apiKeyEnv" || field === "braveApiKeyEnv") this.readCredential();
|
|
272
329
|
}
|
|
273
330
|
snapshotOf() {
|
|
274
331
|
return this.scope.getSnapshot();
|
|
@@ -289,12 +346,25 @@ window.__ModuleLoader__.load({
|
|
|
289
346
|
publish() {
|
|
290
347
|
for (const listener of this.listeners) listener();
|
|
291
348
|
}
|
|
292
|
-
/**
|
|
293
|
-
|
|
349
|
+
/** Draft-aware engine: staged `provider` wins over the saved section. */
|
|
350
|
+
providerOf() {
|
|
351
|
+
const staged = this.staged.get("provider");
|
|
352
|
+
if (staged !== void 0 && !staged.clear && staged.text.trim() !== "") return staged.text.trim();
|
|
353
|
+
const declared = this.sectionValue("provider");
|
|
354
|
+
return declared === "brave" ? "brave" : "tavily";
|
|
355
|
+
}
|
|
356
|
+
tavilyRef() {
|
|
294
357
|
const declared = this.sectionValue("apiKeyEnv");
|
|
295
|
-
return declared !== void 0 && declared.length > 0 ? declared :
|
|
358
|
+
return declared !== void 0 && declared.length > 0 ? declared : DEFAULT_TAVILY_KEY_REF;
|
|
359
|
+
}
|
|
360
|
+
braveRef() {
|
|
361
|
+
const declared = this.sectionValue("braveApiKeyEnv");
|
|
362
|
+
return declared !== void 0 && declared.length > 0 ? declared : DEFAULT_BRAVE_KEY_REF;
|
|
363
|
+
}
|
|
364
|
+
/** The credential reference the currently visible engine uses. */
|
|
365
|
+
refOf() {
|
|
366
|
+
return this.providerOf() === "brave" ? this.braveRef() : this.tavilyRef();
|
|
296
367
|
}
|
|
297
|
-
/** Ask the credentials domain about the reference the section currently names. */
|
|
298
368
|
async readCredential() {
|
|
299
369
|
const ref = this.refOf();
|
|
300
370
|
if (ref !== this.credential.ref) {
|
|
@@ -318,27 +388,26 @@ window.__ModuleLoader__.load({
|
|
|
318
388
|
this.credential = next;
|
|
319
389
|
this.publish();
|
|
320
390
|
}
|
|
321
|
-
/** Re-read after the Host reports a change to the reference this card watches. */
|
|
322
391
|
refreshCredential(ref) {
|
|
323
392
|
if (ref !== this.credential.ref) return;
|
|
324
393
|
this.readCredential();
|
|
325
394
|
}
|
|
326
|
-
|
|
327
|
-
|
|
395
|
+
async writeKey(field, value) {
|
|
396
|
+
const ref = field === BRAVE_API_KEY_FIELD ? this.braveRef() : this.tavilyRef();
|
|
328
397
|
try {
|
|
329
|
-
await this.api.credentials.set({ ref
|
|
398
|
+
await this.api.credentials.set({ ref, value });
|
|
330
399
|
} catch (_credentialWriteFailure) {}
|
|
331
400
|
await this.readCredential();
|
|
332
|
-
return this.credential.configured;
|
|
401
|
+
return this.credential.ref === ref ? this.credential.configured : true;
|
|
333
402
|
}
|
|
334
403
|
};
|
|
335
404
|
|
|
336
|
-
/** Bridges the
|
|
337
|
-
var
|
|
405
|
+
/** Bridges the plugin scope and the credentials domain onto the card. */
|
|
406
|
+
var SearchCardController = class {
|
|
338
407
|
constructor(scope, api) {
|
|
339
408
|
this.scope = scope;
|
|
340
409
|
this.api = api;
|
|
341
|
-
this.form = new
|
|
410
|
+
this.form = new SearchCardForm(scope, api);
|
|
342
411
|
this.store = this.form.bind(() => this.projection());
|
|
343
412
|
scope.subscribe(() => {
|
|
344
413
|
this.form.readCredential();
|
|
@@ -347,21 +416,29 @@ window.__ModuleLoader__.load({
|
|
|
347
416
|
projection() {
|
|
348
417
|
return {
|
|
349
418
|
...this.form.shell(),
|
|
419
|
+
provider: this.form.field("provider"),
|
|
350
420
|
mode: this.form.field("mode"),
|
|
351
|
-
apiKey: this.form.field(
|
|
421
|
+
apiKey: this.form.field(TAVILY_API_KEY_FIELD),
|
|
352
422
|
apiKeyEnv: this.form.field("apiKeyEnv"),
|
|
353
423
|
baseURL: this.form.field("baseURL"),
|
|
354
424
|
maxResults: this.form.field("maxResults"),
|
|
355
425
|
searchDepth: this.form.field("searchDepth"),
|
|
356
426
|
includeAnswer: this.form.field("includeAnswer"),
|
|
357
427
|
topic: this.form.field("topic"),
|
|
428
|
+
braveApiKey: this.form.field(BRAVE_API_KEY_FIELD),
|
|
429
|
+
braveApiKeyEnv: this.form.field("braveApiKeyEnv"),
|
|
430
|
+
braveBaseURL: this.form.field("braveBaseURL"),
|
|
431
|
+
country: this.form.field("country"),
|
|
432
|
+
searchLang: this.form.field("searchLang"),
|
|
433
|
+
freshness: this.form.field("freshness"),
|
|
434
|
+
proxy: this.form.field("proxy"),
|
|
358
435
|
apiKeyConfigured: this.form.credential.configured,
|
|
359
436
|
apiKeyWritable: this.form.credential.writable
|
|
360
437
|
};
|
|
361
438
|
}
|
|
362
439
|
inject() {
|
|
363
440
|
return {
|
|
364
|
-
hooks: {
|
|
441
|
+
hooks: { pluginSearchCard: this.store },
|
|
365
442
|
...this.form.actions()
|
|
366
443
|
};
|
|
367
444
|
}
|
|
@@ -372,23 +449,21 @@ window.__ModuleLoader__.load({
|
|
|
372
449
|
react.createElement("label", { style: { color: "var(--dsw-alias-label-primary)", fontSize: "13px", fontWeight: 500, lineHeight: "1.5" } }, label),
|
|
373
450
|
children,
|
|
374
451
|
hint ? react.createElement("p", { style: { color: "var(--dsw-alias-label-tertiary)", margin: 0, fontSize: "12px", lineHeight: "1.5" } }, hint) : null);
|
|
375
|
-
/** Text/number input. */
|
|
376
452
|
const textInput = (props) => react.createElement("input", { style: { border: "1px solid var(--dsw-alias-border-l2)", background: "var(--dsw-alias-bg-layer-3)", height: "34px", font: "inherit", color: "var(--dsw-alias-label-primary)", borderRadius: "8px", padding: "0 12px", fontSize: "13px", lineHeight: "1.5" }, type: "text", ...props.numeric ? { inputMode: "numeric" } : {}, ...props });
|
|
377
|
-
/** Password input for the write-only credential. */
|
|
378
453
|
const secretInput = (props) => react.createElement("input", { style: { border: "1px solid var(--dsw-alias-border-l2)", background: "var(--dsw-alias-bg-layer-3)", height: "34px", font: "inherit", color: "var(--dsw-alias-label-primary)", borderRadius: "8px", padding: "0 12px", fontSize: "13px", lineHeight: "1.5" }, type: "password", autoComplete: "off", ...props });
|
|
379
|
-
/** Choice select. */
|
|
380
454
|
const selectInput = (props) => react.createElement("select", { style: { border: "1px solid var(--dsw-alias-border-l2)", background: "var(--dsw-alias-bg-layer-3)", height: "34px", font: "inherit", color: "var(--dsw-alias-label-primary)", borderRadius: "8px", padding: "0 12px", fontSize: "13px", lineHeight: "1.5" }, ...props });
|
|
381
|
-
/** Checkbox for booleans. */
|
|
382
455
|
const checkboxInput = (props) => react.createElement("input", { type: "checkbox", style: { width: "16px", height: "16px", accentColor: "var(--dsw-alias-brand-primary)" }, ...props });
|
|
383
456
|
|
|
384
|
-
/** Render one plugin card:
|
|
385
|
-
function
|
|
457
|
+
/** Render one plugin card: engine switch plus the engine-specific form. */
|
|
458
|
+
function SearchCard(props) {
|
|
386
459
|
const { t } = props;
|
|
387
|
-
const state = props.
|
|
460
|
+
const state = props.usePluginSearchCard((snapshot) => snapshot);
|
|
388
461
|
const [open, setOpen] = react.useState(false);
|
|
389
462
|
if (!state.available) return null;
|
|
390
463
|
const disabled = !state.writable;
|
|
391
464
|
const blocked = !state.dirty || state.invalid || state.saving;
|
|
465
|
+
const brave = state.provider.text === "brave";
|
|
466
|
+
const keyed = state.mode.text === "keyed";
|
|
392
467
|
return react.createElement("li", { style: { border: "1px solid var(--dsw-alias-border-l2)", background: "var(--dsw-alias-bg-layer-3)", borderRadius: "12px", listStyle: "none" } },
|
|
393
468
|
react.createElement("button", { type: "button", "aria-expanded": open, onClick: () => setOpen(!open), style: { appearance: "none", width: "100%", font: "inherit", color: "inherit", textAlign: "left", cursor: "pointer", background: "0 0", border: "0", borderRadius: "12px", alignItems: "center", gap: "12px", padding: "14px 16px", display: "flex" } },
|
|
394
469
|
react.createElement("span", { style: { flexDirection: "column", flex: 1, gap: "4px", minWidth: 0, display: "flex" } },
|
|
@@ -398,22 +473,36 @@ window.__ModuleLoader__.load({
|
|
|
398
473
|
react.createElement("span", { style: { color: "var(--dsw-alias-label-tertiary)", flex: "none" } }, open ? "▾" : "▸")),
|
|
399
474
|
open ? react.createElement("div", { style: { borderTop: "1px solid var(--dsw-alias-border-l2)", margin: "0 16px", paddingBottom: "8px" } },
|
|
400
475
|
!state.writable ? react.createElement("p", { style: { color: "var(--dsw-alias-label-tertiary)", margin: "12px 0 0", fontSize: "12px", lineHeight: "1.5" } }, t("readOnly")) : null,
|
|
401
|
-
fieldRow(t("
|
|
476
|
+
fieldRow(t("provider"), null, selectInput({ id: "plugin-config-web-search-provider", value: brave ? "brave" : "tavily", disabled, onChange: (e) => props.edit("provider", e.target.value), children: [
|
|
477
|
+
react.createElement("option", { value: "tavily", key: "tavily" }, t("providerTavily")),
|
|
478
|
+
react.createElement("option", { value: "brave", key: "brave" }, t("providerBrave"))
|
|
479
|
+
] })),
|
|
480
|
+
brave ? null : fieldRow(t("mode"), null, selectInput({ id: "plugin-config-web-search-mode", value: state.mode.text, disabled, onChange: (e) => props.edit("mode", e.target.value), children: [
|
|
402
481
|
react.createElement("option", { value: "keyless", key: "keyless" }, t("modeKeyless")),
|
|
403
482
|
react.createElement("option", { value: "keyed", key: "keyed" }, t("modeKeyed"))
|
|
404
483
|
] })),
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
fieldRow(t("baseURL"), t("baseURLHint"), textInput({ id: "plugin-config-web-search-base", value: state.baseURL.text, disabled, onChange: (e) => props.edit("baseURL", e.target.value), onReset: () => props.resetField("baseURL") })),
|
|
408
|
-
fieldRow(t("searchDepth"), null, selectInput({ id: "plugin-config-web-search-depth", value: state.searchDepth.text, disabled, onChange: (e) => props.edit("searchDepth", e.target.value), children: [
|
|
484
|
+
(!brave && keyed) || brave ? fieldRow(t("apiKey"), t("apiKeyHint"), secretInput({ id: "plugin-config-web-search-key", value: brave ? state.braveApiKey.text : state.apiKey.text, disabled: !state.apiKeyWritable, placeholder: state.apiKeyConfigured ? t("apiKeySet") : t("apiKeyUnset"), onChange: (e) => props.edit(brave ? BRAVE_API_KEY_FIELD : TAVILY_API_KEY_FIELD, e.target.value) })) : null,
|
|
485
|
+
(!brave && keyed) || brave ? fieldRow(brave ? t("braveApiKeyEnv") : t("apiKeyEnv"), brave ? t("braveApiKeyEnvHint") : t("apiKeyEnvHint"), textInput({ id: "plugin-config-web-search-keyref", value: brave ? state.braveApiKeyEnv.text : state.apiKeyEnv.text, disabled, onChange: (e) => props.edit(brave ? "braveApiKeyEnv" : "apiKeyEnv", e.target.value), onReset: () => props.resetField(brave ? "braveApiKeyEnv" : "apiKeyEnv") })) : null,
|
|
486
|
+
brave ? fieldRow(t("braveBaseURL"), t("braveBaseURLHint"), textInput({ id: "plugin-config-web-search-brave-base", value: state.braveBaseURL.text, disabled, onChange: (e) => props.edit("braveBaseURL", e.target.value), onReset: () => props.resetField("braveBaseURL") })) : fieldRow(t("baseURL"), t("baseURLHint"), textInput({ id: "plugin-config-web-search-base", value: state.baseURL.text, disabled, onChange: (e) => props.edit("baseURL", e.target.value), onReset: () => props.resetField("baseURL") })),
|
|
487
|
+
brave ? null : fieldRow(t("searchDepth"), null, selectInput({ id: "plugin-config-web-search-depth", value: state.searchDepth.text, disabled, onChange: (e) => props.edit("searchDepth", e.target.value), children: [
|
|
409
488
|
react.createElement("option", { value: "basic", key: "basic" }, t("searchDepthBasic")),
|
|
410
489
|
react.createElement("option", { value: "advanced", key: "advanced" }, t("searchDepthAdvanced"))
|
|
411
490
|
] })),
|
|
412
|
-
fieldRow(t("topic"), null, selectInput({ id: "plugin-config-web-search-topic", value: state.topic.text, disabled, onChange: (e) => props.edit("topic", e.target.value), children: [
|
|
491
|
+
brave ? null : fieldRow(t("topic"), null, selectInput({ id: "plugin-config-web-search-topic", value: state.topic.text, disabled, onChange: (e) => props.edit("topic", e.target.value), children: [
|
|
413
492
|
react.createElement("option", { value: "general", key: "general" }, t("topicGeneral")),
|
|
414
493
|
react.createElement("option", { value: "news", key: "news" }, t("topicNews"))
|
|
415
494
|
] })),
|
|
416
|
-
fieldRow(t("includeAnswer"), t("includeAnswerHint"), checkboxInput({ id: "plugin-config-web-search-answer", checked: state.includeAnswer.text === "true", disabled, onChange: (e) => props.edit("includeAnswer", e.target.checked ? "true" : "") })),
|
|
495
|
+
brave ? null : fieldRow(t("includeAnswer"), t("includeAnswerHint"), checkboxInput({ id: "plugin-config-web-search-answer", checked: state.includeAnswer.text === "true", disabled, onChange: (e) => props.edit("includeAnswer", e.target.checked ? "true" : "") })),
|
|
496
|
+
brave ? fieldRow(t("country"), t("countryHint"), textInput({ id: "plugin-config-web-search-country", value: state.country.text, disabled, onChange: (e) => props.edit("country", e.target.value), onReset: () => props.resetField("country") })) : null,
|
|
497
|
+
brave ? fieldRow(t("searchLang"), t("searchLangHint"), textInput({ id: "plugin-config-web-search-lang", value: state.searchLang.text, disabled, onChange: (e) => props.edit("searchLang", e.target.value), onReset: () => props.resetField("searchLang") })) : null,
|
|
498
|
+
brave ? fieldRow(t("freshness"), null, selectInput({ id: "plugin-config-web-search-freshness", value: state.freshness.text, disabled, onChange: (e) => props.edit("freshness", e.target.value), children: [
|
|
499
|
+
react.createElement("option", { value: "", key: "any" }, t("freshnessAny")),
|
|
500
|
+
react.createElement("option", { value: "pd", key: "pd" }, t("freshnessDay")),
|
|
501
|
+
react.createElement("option", { value: "pw", key: "pw" }, t("freshnessWeek")),
|
|
502
|
+
react.createElement("option", { value: "pm", key: "pm" }, t("freshnessMonth")),
|
|
503
|
+
react.createElement("option", { value: "py", key: "py" }, t("freshnessYear"))
|
|
504
|
+
] })) : null,
|
|
505
|
+
brave ? fieldRow(t("proxy"), t("proxyHint"), textInput({ id: "plugin-config-web-search-proxy", value: state.proxy.text, disabled, onChange: (e) => props.edit("proxy", e.target.value), onReset: () => props.resetField("proxy") })) : null,
|
|
417
506
|
fieldRow(t("maxResults"), t("maxResultsHint"), textInput({ id: "plugin-config-web-search-max", numeric: true, value: state.maxResults.text, disabled, onChange: (e) => props.edit("maxResults", e.target.value), onReset: () => props.resetField("maxResults") })),
|
|
418
507
|
react.createElement("div", { style: { borderTop: "1px solid var(--dsw-alias-border-l2)", justifyContent: "flex-end", alignItems: "center", gap: "8px", padding: "12px 0 4px", display: "flex" } },
|
|
419
508
|
state.failed ? react.createElement("p", { role: "status", style: { minWidth: 0, color: "var(--dsw-alias-label-error)", flex: 1, margin: 0, fontSize: "12px", lineHeight: "1.5" } }, t("saveFailed")) : null,
|
|
@@ -421,12 +510,12 @@ window.__ModuleLoader__.load({
|
|
|
421
510
|
react.createElement("button", { type: "button", disabled: blocked, onClick: props.save, style: { appearance: "none", font: "inherit", cursor: "pointer", border: "1px solid transparent", borderRadius: "8px", padding: "5px 14px", fontSize: "13px", lineHeight: "1.5", color: "var(--dsw-alias-label-on-brand)", background: "var(--dsw-alias-bg-brand-solid)" } }, t(state.saving ? "saving" : "save")))) : null);
|
|
422
511
|
}
|
|
423
512
|
|
|
424
|
-
/** Mount the
|
|
513
|
+
/** Mount the card into the plugin configuration surface. */
|
|
425
514
|
function apply(ctx) {
|
|
426
515
|
const { api } = ctx.get("connection");
|
|
427
516
|
const t = ctx.locale.bind(NS);
|
|
428
517
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-web-search-plugin: card dictionaries");
|
|
429
|
-
const controller = new
|
|
518
|
+
const controller = new SearchCardController(ctx.settingsScope.bind({ namespace: NS }), api);
|
|
430
519
|
ctx.effect(() => ctx.remote.$on("credentials/updated", (ref) => {
|
|
431
520
|
controller.form.refreshCredential(ref);
|
|
432
521
|
}), "dsh-web-search-plugin: credential invalidations");
|
|
@@ -436,11 +525,10 @@ window.__ModuleLoader__.load({
|
|
|
436
525
|
key: "dsh-web-search-plugin",
|
|
437
526
|
locale: NS,
|
|
438
527
|
inject: () => controller.inject()
|
|
439
|
-
},
|
|
528
|
+
}, SearchCard);
|
|
440
529
|
});
|
|
441
530
|
}
|
|
442
531
|
|
|
443
|
-
/** Cordis service names this browser plugin's apply reads (fiber inject). */
|
|
444
532
|
const inject = ["slots", "locale", "connection", "remote", "settingsScope"];
|
|
445
533
|
|
|
446
534
|
exports.apply = apply;
|
|
@@ -448,4 +536,3 @@ window.__ModuleLoader__.load({
|
|
|
448
536
|
return module.exports;
|
|
449
537
|
}
|
|
450
538
|
});
|
|
451
|
-
//# sourceMappingURL=client.js.map
|