@darlingc/dsh-freesearch 0.5.3 → 0.5.4
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 +26 -2
- package/lib/client.js +2 -2
- package/lib/index.js +15 -10
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -57,8 +57,9 @@ dsh 默认的搜索 provider 依赖 DeepSeek 官方 API key(`DEEPSEEK_API_KEY`
|
|
|
57
57
|
| `keenable` | Keenable | 免费 | **无 key 也可用**(MCP 匿名),配 key 提升额度 |
|
|
58
58
|
| `perplexity` | Perplexity | 付费 | 需 `PERPLEXITY_API_KEY` |
|
|
59
59
|
| `deepseek-official` | DeepSeek 官方 | 付费 | 需 `DEEPSEEK_API_KEY` |
|
|
60
|
+
| `gemini` | Gemini (Google Search Grounding) | 免费层 | 需 `GEMINI_API_KEY`(AI Studio 免费层;走 Google 联网 grounding) |
|
|
60
61
|
|
|
61
|
-
- **默认引擎为 `bing
|
|
62
|
+
- **默认引擎为 `bing`**(免费且最稳定),安装后开箱即用;**`gemini` 建议作为回退/按需引擎**,不要默认首选(见下方配额警示)。
|
|
62
63
|
- **自动回退**:任何引擎失败(免费限流/反爬,付费缺 key/无效/网络错误)都会自动轮流尝试下一个引擎——先试其他已配 key 的付费引擎,再试免费引擎(Bing/AnySearch 等),并在结果中附带回退提示——搜索不会因引擎问题直接失败。
|
|
63
64
|
- **设置页有官网链接**:免费引擎显示"访问官网 →",付费引擎显示"获取 API Key →"(新标签页打开):
|
|
64
65
|
- Exa:<https://dashboard.exa.ai/api-keys>
|
|
@@ -74,6 +75,17 @@ dsh 默认的搜索 provider 依赖 DeepSeek 官方 API key(`DEEPSEEK_API_KEY`
|
|
|
74
75
|
- **Tavily**:通过 `x-tavily-access-mode: keyless` 头走 keyless 匿名额度,不配 key 即可用;配置 `TAVILY_API_KEY` 后走账号档,额度更高、结果质量更稳定。
|
|
75
76
|
- **Keenable**:无 key 时走其公开 MCP 端点(`api.keenable.ai/mcp`)匿名调用;配置 `KEENABLE_API_KEY` 后走 REST API(`api.keenable.ai/v1/search`),额度更高、按组织限流。
|
|
76
77
|
|
|
78
|
+
#### Gemini 联网搜索引擎(Google Search Grounding)
|
|
79
|
+
|
|
80
|
+
- **原理**:调用 Gemini API 的 `generateContent` + `tools:[{google_search:{}}]`(Google Search Grounding),模型在生成时联网并返回 `groundingChunks`(来源 `{uri,title}`)+ `groundingSupports`(回答段落与来源的映射,用于拼 snippet)。结果自动转成统一 `{url,title,snippet}` 形式接入本插件。
|
|
81
|
+
- **Key 配置**:在 AI Studio(aistudio.google.com/apikey)免费创建 `GEMINI_API_KEY`,放入 `~/.dsh/.credentials.yaml` 的 `refs.GEMINI_API_KEY`,或在 `~/.dsh/settings.yaml` 的 `free-search:` 下设置 `geminiApiKey`。
|
|
82
|
+
- **模型**:默认 `gemini-2.5-flash`(免费层唯一已实测可联网的模型)。当前 AI Studio 免费层**无需绑卡**即可用 Google Search grounding。
|
|
83
|
+
- **⚠️ 配额警示(务必注意)**:
|
|
84
|
+
- `gemini-2.5-flash` **文本输出 RPD 仅约 20/天** —— 千万别把它当常规文本问答模型用,会秒爆。本引擎只走 grounding(联网搜索),计的是**搜索 RPD**,不占那 20 次文本额度。
|
|
85
|
+
- **搜索 RPD 约 1,500/天**(与 Flash-Lite 共享),**RPM 约 5**。每次搜索引擎调用 = 1 次 grounded prompt = 1 搜索 RPD。超限会返回 HTTP 429,本插件会**自动回退到其它免费引擎**(Bing 等),搜索不会因此失败。
|
|
86
|
+
- 因此**不建议把 `gemini` 设为默认首选引擎**(`free-search.provider: gemini`),默认 `bing` + 失败自动回退即可;把 `gemini` 当按需/回退引擎最稳。
|
|
87
|
+
- **与其它引擎差异**:Gemini grounding 返回的是"模型 Ground 到的来源集合",不是像 Bing 那样的排序结果列表——数量不固定、通常偏少、无优先级;`maxResults` 只能做客户端截断。作为默认搜索体验与真实搜索引擎略有不同。
|
|
88
|
+
|
|
77
89
|
### 安装
|
|
78
90
|
|
|
79
91
|
推荐从 npm registry 或 git 安装(装成真实拷贝,避免本地 link 软链导致的依赖解析问题):
|
|
@@ -316,8 +328,9 @@ This plugin provides multiple free search engines with automatic fallback, compl
|
|
|
316
328
|
| `keenable` | Keenable | Free | **Usable without a key** (anonymous MCP); configure a key for higher quota |
|
|
317
329
|
| `perplexity` | Perplexity | Paid | Requires `PERPLEXITY_API_KEY` |
|
|
318
330
|
| `deepseek-official` | DeepSeek Official | Paid | Requires `DEEPSEEK_API_KEY` |
|
|
331
|
+
| `gemini` | Gemini (Google Search Grounding) | Free tier | Requires `GEMINI_API_KEY` (AI Studio free tier; uses Google Search Grounding) |
|
|
319
332
|
|
|
320
|
-
- **Default engine is `bing`** (free and most stable), ready to use out of the box
|
|
333
|
+
- **Default engine is `bing`** (free and most stable), ready to use out of the box. **Prefer keeping `gemini` as a fallback / on-demand engine** rather than the default (see quota warning below).
|
|
321
334
|
- **Auto-failover**: any engine failure (rate-limited free engine, or missing/invalid paid key, network error) automatically tries the next engine — the configured engine first, then other engines (exa/tavily/keenable are tried even without a key because they have built-in keyless quota), then the remaining free engines (Bing/AnySearch etc.) — with a note attached to the results naming the engine that actually served them (e.g. `Note: perplexity unavailable or failed, using exa.`). Search never fails outright because of engine issues.
|
|
322
335
|
- **Official Links in Settings**: Free engines display "Visit Website →", while paid engines display "Get API Key →" (opens in a new tab):
|
|
323
336
|
- Exa: <https://dashboard.exa.ai/api-keys>
|
|
@@ -333,6 +346,17 @@ This plugin provides multiple free search engines with automatic fallback, compl
|
|
|
333
346
|
- **Tavily**: offers keyless anonymous quota via the `x-tavily-access-mode: keyless` header — it works without a key; configuring `TAVILY_API_KEY` switches to the account tier for higher quota and more stable results.
|
|
334
347
|
- **Keenable**: without a key it is called via its public MCP endpoint (`api.keenable.ai/mcp`); configuring `KEENABLE_API_KEY` switches to the REST API (`api.keenable.ai/v1/search`) for higher quota and organization-scoped rate limits.
|
|
335
348
|
|
|
349
|
+
#### Gemini live web search (Google Search Grounding)
|
|
350
|
+
|
|
351
|
+
- **How it works**: calls `generateContent` with `tools:[{google_search:{}}]` (Google Search Grounding); the model searches live during generation and returns `groundingChunks` (sources `{uri,title}`) + `groundingSupports` (answer-segment → chunk mapping used to build the snippet). Results are normalized into the plugin's unified `{url,title,snippet}` shape.
|
|
352
|
+
- **Key**: create a free `GEMINI_API_KEY` at AI Studio (aistudio.google.com/apikey) and store it in `refs.GEMINI_API_KEY` under `~/.dsh/.credentials.yaml`, or set `geminiApiKey` under `free-search:` in `~/.dsh/settings.yaml`.
|
|
353
|
+
- **Model**: defaults to `gemini-2.5-flash` (the only free-tier model verified to work online here). Google Search Grounding is available on the AI Studio **free tier with no credit card**.
|
|
354
|
+
- **⚠️ Quota warning (important)**:
|
|
355
|
+
- `gemini-2.5-flash` has a **text-output RPD of only ~20/day** — do **not** use it as a general text model or you will exhaust it instantly. This engine only uses grounding (web search), which counts against the **search RPD**, not the text quota.
|
|
356
|
+
- **Search RPD ≈ 1,500/day** (shared with Flash-Lite), **RPM ≈ 5**. Each engine call = 1 grounded prompt = 1 search RPD. Exceeding it returns HTTP 429, and this plugin **auto-falls-back to other free engines** (Bing, etc.), so search never hard-fails.
|
|
357
|
+
- So keep `provider: bing` as default and let `gemini` act as a fallback / on-demand engine rather than the primary load.
|
|
358
|
+
- **Difference vs. other engines**: Gemini grounding returns the set of sources the model grounded on — not a ranked SERP list like Bing/DDG. Count is not fixed and is usually small, with no ordering; `maxResults` can only truncate client-side.
|
|
359
|
+
|
|
336
360
|
### Installation
|
|
337
361
|
|
|
338
362
|
Install from the npm registry or Git (installed as a real copy, which avoids the dependency-resolution problem caused by a local `link:` symlink):
|
package/lib/client.js
CHANGED
|
@@ -156,8 +156,8 @@ window.__ModuleLoader__.load({
|
|
|
156
156
|
},
|
|
157
157
|
};
|
|
158
158
|
const tt = (lang) => I18N[lang === "en" ? "en" : "zh"];
|
|
159
|
-
// 当前插件版本(与 lib/index.js 的 PLUGIN_VERSION 保持一致)
|
|
160
|
-
const PLUGIN_VERSION = "0.5.
|
|
159
|
+
// 当前插件版本(与 lib/index.js 的 PLUGIN_VERSION、package.json 保持一致)
|
|
160
|
+
const PLUGIN_VERSION = "0.5.4";
|
|
161
161
|
const ENGINES = [
|
|
162
162
|
{ id: "ddg", label: "DuckDuckGo · HTML", badge: "FREE", link: "https://duckduckgo.com" },
|
|
163
163
|
{ id: "ddg-lite", label: "DuckDuckGo · Lite", badge: "FREE", link: "https://duckduckgo.com" },
|
package/lib/index.js
CHANGED
|
@@ -28,7 +28,7 @@ const GEMINI_MODEL = "gemini-2.5-flash";
|
|
|
28
28
|
const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent`;
|
|
29
29
|
|
|
30
30
|
// 当前插件版本(发布时与 package.json 同步)
|
|
31
|
-
const PLUGIN_VERSION = "0.5.
|
|
31
|
+
const PLUGIN_VERSION = "0.5.4";
|
|
32
32
|
// 检查更新的 npm registry 元数据地址(@darlingc/dsh-freesearch 是 npmjs 上的公开包)
|
|
33
33
|
const NPM_REGISTRY_URL = "https://registry.npmjs.org/@darlingc%2Fdsh-freesearch/latest";
|
|
34
34
|
const PLUGIN_NPM_URL = "https://www.npmjs.com/package/@darlingc/dsh-freesearch";
|
|
@@ -67,21 +67,26 @@ function compareVersions(a, b) {
|
|
|
67
67
|
return 0;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// 检测插件的安装模式:遍历 profiles/*/node_modules
|
|
70
|
+
// 检测插件的安装模式:遍历 profiles/*/node_modules/<pkg>,
|
|
71
71
|
// symlink(link: 本地开发)→ isLink=true;npm 真安装 → isLink=false;找不到 → null
|
|
72
|
+
// 主包名已 scoped 为 @darlingc/dsh-freesearch(路径 node_modules/@darlingc/dsh-freesearch);
|
|
73
|
+
// 兼容历史遗留的非 scoped 旧名 dsh-free-search,避免旧安装检测不到。
|
|
74
|
+
const PACKAGE_BASENAMES = ["@darlingc/dsh-freesearch", "dsh-free-search"];
|
|
72
75
|
function detectInstallMode() {
|
|
73
76
|
const profilesDir = path.join(process.cwd(), "profiles");
|
|
74
77
|
let found = null;
|
|
75
78
|
try {
|
|
76
79
|
for (const name of fs.readdirSync(profilesDir)) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
for (const dirName of PACKAGE_BASENAMES) {
|
|
81
|
+
const pkgPath = path.join(profilesDir, name, "node_modules", ...dirName.split("/"));
|
|
82
|
+
if (!fs.existsSync(pkgPath)) continue;
|
|
83
|
+
let isLink = false;
|
|
84
|
+
try {
|
|
85
|
+
isLink = fs.lstatSync(pkgPath).isSymbolicLink();
|
|
86
|
+
} catch {}
|
|
87
|
+
found = { profileDir: path.join(profilesDir, name), isLink };
|
|
88
|
+
return found;
|
|
89
|
+
}
|
|
85
90
|
}
|
|
86
91
|
} catch {}
|
|
87
92
|
return found;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@darlingc/dsh-freesearch",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "Free web search for DeepSeek Harness: 11 engines (Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable keyless + Gemini grounding) + time filtering + platform search + web_fetch, with web settings UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"lib/client.js",
|
|
15
15
|
"cordis.patch.yml"
|
|
16
16
|
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "node scripts/check-version.mjs",
|
|
19
|
+
"check:version": "node scripts/check-version.mjs",
|
|
20
|
+
"postversion": "node scripts/check-version.mjs"
|
|
21
|
+
},
|
|
17
22
|
"keywords": [
|
|
18
23
|
"deepseek-harness",
|
|
19
24
|
"dsh",
|