dsh-free-search 0.4.17 → 0.4.18

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 CHANGED
@@ -488,4 +488,10 @@ Windows users: The desktop shortcut already includes this configuration (`set NO
488
488
 
489
489
  ### License
490
490
 
491
- MIT
491
+ MIT
492
+
493
+ ## safeSearch 安全搜索过滤
494
+
495
+ - 全新配置项 `safeSearch`:`off`(引擎默认,不加参数)/ `moderate` / `strict`
496
+ - 作用于 Bing(adlt)、DuckDuckGo HTML(adlt)、DuckDuckGo Lite(adlt)
497
+ - 默认 `off`:不额外过滤,保持引擎自身默认行为;需要时在「设置 > 插件 > Free Search」切换
package/lib/client.js CHANGED
@@ -273,6 +273,7 @@ window.__ModuleLoader__.load({
273
273
  const [open, setOpen] = react.useState(false);
274
274
  const [state, setState] = react.useState({ status: "loading" });
275
275
  const [provider, setProvider] = react.useState("bing");
276
+ const [safeSearch, setSafeSearch] = react.useState("off");
276
277
  const [exaKey, setExaKey] = react.useState("");
277
278
  const [tavilyKey, setTavilyKey] = react.useState("");
278
279
  const [keenableKey, setKeenableKey] = react.useState("");
@@ -303,6 +304,7 @@ window.__ModuleLoader__.load({
303
304
  if (view) {
304
305
  const v = view.value ?? {};
305
306
  setProvider(v.provider ?? "ddg");
307
+ setSafeSearch(v.safeSearch === "strict" || v.safeSearch === "moderate" ? v.safeSearch : "off");
306
308
  setLang(v.lang === "en" ? "en" : "zh");
307
309
  setExaKey(v.exaApiKey ?? "");
308
310
  setTavilyKey(v.tavilyApiKey ?? "");
@@ -383,6 +385,7 @@ window.__ModuleLoader__.load({
383
385
  const ops = [{ op: "set", path: ["provider"], value: provider }];
384
386
  ops.push({ op: "set", path: ["lang"], value: lang });
385
387
  ops.push({ op: "set", path: ["keyStorage"], value: keyStorage });
388
+ ops.push({ op: "set", path: ["safeSearch"], value: safeSearch });
386
389
  if (keyStorage !== "credentials") {
387
390
  // settings 模式:key 仍写 settings.yaml(旧行为)
388
391
  for (const [field, value] of keyFields) {
@@ -570,6 +573,31 @@ react_jsx_runtime.jsx("div", {
570
573
  }),
571
574
  ],
572
575
  }),
576
+ react_jsx_runtime.jsx("div", {
577
+ className: "dshfs-field",
578
+ children: [
579
+ react_jsx_runtime.jsx("div", {
580
+ className: "dshfs-label",
581
+ children: "Safe search filter (adlt)",
582
+ }),
583
+ react_jsx_runtime.jsx("select", {
584
+ className: "dshfs-select",
585
+ value: safeSearch,
586
+ style: { colorScheme: selectColorScheme },
587
+ disabled: !ready || saving,
588
+ onChange: (e) => setSafeSearch(e.target.value),
589
+ children: [
590
+ react_jsx_runtime.jsx("option", { value: "off", children: "Off - engine default (no filtering)" }, "off"),
591
+ react_jsx_runtime.jsx("option", { value: "moderate", children: "Moderate - Bing default" }, "moderate"),
592
+ react_jsx_runtime.jsx("option", { value: "strict", children: "Strict" }, "strict"),
593
+ ],
594
+ }),
595
+ react_jsx_runtime.jsx("p", {
596
+ className: "dshfs-hint",
597
+ children: "Applies to bing (adlt), ddg, ddg-lite (adlt degree). If you see the engine's own filtering, adjust here.",
598
+ }),
599
+ ],
600
+ }),
573
601
  react_jsx_runtime.jsx("div", {
574
602
  className: "dshfs-field",
575
603
  children: [
package/lib/index.js CHANGED
@@ -241,6 +241,9 @@ async function fetchHtmlWithRetry(url, signal) {
241
241
  async function searchDdgHtml(query, maxResults, options, signal) {
242
242
  const params = new URLSearchParams({ q: query });
243
243
  if (options?.region) params.set("kl", options.region);
244
+ // DDG 安全搜索:off(adlt=-1) / moderate(adlt=0) / strict(adlt=1)
245
+ const adlt = options?.safeSearch ?? "off";
246
+ params.set("adlt", adlt === "strict" ? "1" : adlt === "moderate" ? "0" : "-1");
244
247
  // DDG 时间过滤:df=d/w/m/y(只支持固定档,自定义取近似档)
245
248
  if (options?.timeRange) {
246
249
  const df = { day: "d", week: "w", month: "m", year: "y" }[approximateTimeRange(options.timeRange.days ?? 7)];
@@ -268,6 +271,8 @@ async function searchDdgHtml(query, maxResults, options, signal) {
268
271
 
269
272
  async function searchDdgLite(query, maxResults, options, signal) {
270
273
  const params = new URLSearchParams({ q: query });
274
+ const adlt = options?.safeSearch ?? "off";
275
+ params.set("adlt", adlt === "strict" ? "1" : adlt === "moderate" ? "0" : "-1");
271
276
  // DDG Lite 同样支持 df 时间过滤
272
277
  if (options?.timeRange) {
273
278
  const df = { day: "d", week: "w", month: "m", year: "y" }[approximateTimeRange(options.timeRange.days ?? 7)];
@@ -296,6 +301,10 @@ async function searchDdgLite(query, maxResults, options, signal) {
296
301
 
297
302
  async function searchBing(query, maxResults, options, signal) {
298
303
  const params = new URLSearchParams({ q: query, mkt: options?.bingMarket ?? "zh-CN" });
304
+ const adlt = options?.safeSearch ?? "off";
305
+ if (adlt === "off") params.set("adlt", "off");
306
+ else if (adlt === "moderate") params.set("adlt", "moderate");
307
+ else if (adlt === "strict") params.set("adlt", "strict");
299
308
  const html = await fetchHtmlWithRetry(`${BING_URL}?${params}`, signal);
300
309
  const blocks = html.match(/<li class="b_algo"[\s\S]*?<\/li>/g) ?? [];
301
310
  const sources = [];
@@ -1417,6 +1426,7 @@ const Config = z.object({
1417
1426
  lang: z.string().default("zh"),
1418
1427
  region: z.string(),
1419
1428
  bingMarket: z.string().default("zh-CN"),
1429
+ safeSearch: z.string().default("off"),
1420
1430
  searxngInstances: z.array(z.string()),
1421
1431
  platforms: z.array(z.string()).default(["github", "v2ex", "bilibili", "reddit", "hn", "stackoverflow", "wikipedia", "npm"]),
1422
1432
  exaApiKey: z.string().role("secret"),
@@ -2011,6 +2021,7 @@ function apply(ctx, config) {
2011
2021
  "",
2012
2022
  "You have the web_search tool. Its backend engine is chosen in Settings > Plugins > Free Search.",
2013
2023
  "Current engine: " + (current().provider ?? "bing"),
2024
+ "Safe search filter (Settings > Plugins > Free Search): " + (current().safeSearch ?? "off") + " (off|moderate|strict). Engine default off; applies to bing/ddg/ddg-lite.",
2014
2025
  "",
2015
2026
  "Available engines and their requirements:",
2016
2027
  "- ddg (DuckDuckGo HTML) - FREE, no key (may be rate-limited)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-free-search",
3
- "version": "0.4.17",
3
+ "version": "0.4.18",
4
4
  "description": "Free web search for DeepSeek Harness: 10 engines (Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable keyless) + time filtering + platform search + web_fetch, with web settings UI.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",