dsh-web-search-pro 0.2.1 → 0.2.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/CHANGELOG.md +227 -0
- package/README.en.md +117 -0
- package/README.md +72 -578
- package/assets/skills/dsh-web-search-pro/SKILL.md +13 -12
- package/assets/skills/dsh-web-search-pro/references/config.md +36 -0
- package/assets/skills/dsh-web-search-pro/references/sources.md +13 -7
- package/assets/skills/dsh-web-search-pro/references/troubleshooting.md +3 -1
- package/catalog/sources.v1.json +16 -14
- package/lib/actions/approval.js +50 -1
- package/lib/actions/approval.js.map +1 -1
- package/lib/actions/config.js +274 -0
- package/lib/actions/config.js.map +1 -0
- package/lib/actions/errors.js +8 -1
- package/lib/actions/errors.js.map +1 -1
- package/lib/actions/format.js +10 -0
- package/lib/actions/format.js.map +1 -1
- package/lib/actions/index-view.js +2 -2
- package/lib/actions/index-view.js.map +1 -1
- package/lib/actions/read.js +7 -3
- package/lib/actions/read.js.map +1 -1
- package/lib/actions/registry.js +3 -1
- package/lib/actions/registry.js.map +1 -1
- package/lib/actions/run.js +2 -2
- package/lib/actions/run.js.map +1 -1
- package/lib/actions/schema.js +18 -0
- package/lib/actions/schema.js.map +1 -1
- package/lib/actions/search.js +7 -2
- package/lib/actions/search.js.map +1 -1
- package/lib/actions/sources.js +76 -18
- package/lib/actions/sources.js.map +1 -1
- package/lib/actions/types.js +19 -1
- package/lib/actions/types.js.map +1 -1
- package/lib/browser-access.js +25 -0
- package/lib/browser-access.js.map +1 -1
- package/lib/catalog/recommend.js +11 -3
- package/lib/catalog/recommend.js.map +1 -1
- package/lib/catalog/schema.js +3 -1
- package/lib/catalog/schema.js.map +1 -1
- package/lib/cli/builtin-specs.js +57 -22
- package/lib/cli/builtin-specs.js.map +1 -1
- package/lib/cli/chain.js +13 -12
- package/lib/cli/chain.js.map +1 -1
- package/lib/cli/chains-spec.js +31 -11
- package/lib/cli/chains-spec.js.map +1 -1
- package/lib/cli/engine.js +19 -3
- package/lib/cli/engine.js.map +1 -1
- package/lib/cli/opencli-sites.js +83 -0
- package/lib/cli/opencli-sites.js.map +1 -0
- package/lib/cli/opencli.js +65 -17
- package/lib/cli/opencli.js.map +1 -1
- package/lib/cli/probe.js +1 -1
- package/lib/cli/probe.js.map +1 -1
- package/lib/cli/runner.js +217 -27
- package/lib/cli/runner.js.map +1 -1
- package/lib/cli/spec.js +100 -20
- package/lib/cli/spec.js.map +1 -1
- package/lib/cli/time-text.js +79 -0
- package/lib/cli/time-text.js.map +1 -0
- package/lib/cli/trial.js +57 -0
- package/lib/cli/trial.js.map +1 -0
- package/lib/client/SettingsCard.js +14 -32
- package/lib/client/SettingsCard.js.map +1 -1
- package/lib/client/agent-mark.js +27 -0
- package/lib/client/agent-mark.js.map +1 -0
- package/lib/client/card-frame.js +118 -0
- package/lib/client/card-frame.js.map +1 -0
- package/lib/client/cli-form.js +257 -0
- package/lib/client/cli-form.js.map +1 -0
- package/lib/client/field-docs.js +130 -0
- package/lib/client/field-docs.js.map +1 -0
- package/lib/client/field-keys.js +81 -0
- package/lib/client/field-keys.js.map +1 -0
- package/lib/client/field-rows.js +71 -0
- package/lib/client/field-rows.js.map +1 -0
- package/lib/client/fill.js +3 -0
- package/lib/client/fill.js.map +1 -0
- package/lib/client/form-specs.js +13 -1
- package/lib/client/form-specs.js.map +1 -1
- package/lib/client/form.js +282 -24
- package/lib/client/form.js.map +1 -1
- package/lib/client/group-advanced.js +23 -0
- package/lib/client/group-advanced.js.map +1 -0
- package/lib/client/group-agent.js +28 -0
- package/lib/client/group-agent.js.map +1 -0
- package/lib/client/group-cli.js +136 -0
- package/lib/client/group-cli.js.map +1 -0
- package/lib/client/group-common.js +29 -0
- package/lib/client/group-common.js.map +1 -0
- package/lib/client/group-judge.js +67 -0
- package/lib/client/group-judge.js.map +1 -0
- package/lib/client/group-order.js +201 -0
- package/lib/client/group-order.js.map +1 -0
- package/lib/client/group-runtime.js +33 -0
- package/lib/client/group-runtime.js.map +1 -0
- package/lib/client/group-sources.js +83 -0
- package/lib/client/group-sources.js.map +1 -0
- package/lib/client/groups-basic.js +36 -0
- package/lib/client/groups-basic.js.map +1 -0
- package/lib/client/index.js.map +1 -1
- package/lib/client/json-list.js +50 -0
- package/lib/client/json-list.js.map +1 -0
- package/lib/client/locales.js +666 -219
- package/lib/client/locales.js.map +1 -1
- package/lib/client/order.js +192 -0
- package/lib/client/order.js.map +1 -0
- package/lib/client/overlay-ops.js +46 -0
- package/lib/client/overlay-ops.js.map +1 -0
- package/lib/client/sources-table.js +1 -0
- package/lib/client/sources-table.js.map +1 -1
- package/lib/client/styles.js +74 -47
- package/lib/client/styles.js.map +1 -1
- package/lib/client/text-view.js +98 -0
- package/lib/client/text-view.js.map +1 -0
- package/lib/client/ui-kit.js +120 -0
- package/lib/client/ui-kit.js.map +1 -0
- package/lib/client/validators.js +8 -1
- package/lib/client/validators.js.map +1 -1
- package/lib/client.js +7313 -1571
- package/lib/client.js.map +1 -1
- package/lib/config-fillers.js +53 -0
- package/lib/config-fillers.js.map +1 -0
- package/lib/config-groups.js +49 -0
- package/lib/config-groups.js.map +1 -0
- package/lib/config.js +84 -108
- package/lib/config.js.map +1 -1
- package/lib/default-chain.js +66 -0
- package/lib/default-chain.js.map +1 -0
- package/lib/deps.js +1 -1
- package/lib/deps.js.map +1 -1
- package/lib/engines.js +3 -3
- package/lib/engines.js.map +1 -1
- package/lib/fetch.js +23 -4
- package/lib/fetch.js.map +1 -1
- package/lib/fiber-config.js +5 -0
- package/lib/fiber-config.js.map +1 -0
- package/lib/index.js +36 -7
- package/lib/index.js.map +1 -1
- package/lib/overlay-types.js +88 -0
- package/lib/overlay-types.js.map +1 -0
- package/lib/overlay.js +683 -0
- package/lib/overlay.js.map +1 -0
- package/lib/pipeline/candidates.js +27 -1
- package/lib/pipeline/candidates.js.map +1 -1
- package/lib/pipeline/compile.js +63 -0
- package/lib/pipeline/compile.js.map +1 -1
- package/lib/pipeline/confidence.js +64 -0
- package/lib/pipeline/confidence.js.map +1 -0
- package/lib/pipeline/fusion.js +50 -3
- package/lib/pipeline/fusion.js.map +1 -1
- package/lib/pipeline/plan.js +2 -2
- package/lib/pipeline/plan.js.map +1 -1
- package/lib/pipeline/render.js +20 -2
- package/lib/pipeline/render.js.map +1 -1
- package/lib/pipeline/run.js +17 -5
- package/lib/pipeline/run.js.map +1 -1
- package/lib/pipeline/sources-spec.js +19 -3
- package/lib/pipeline/sources-spec.js.map +1 -1
- package/lib/providers/builtin.js +3 -0
- package/lib/providers/builtin.js.map +1 -1
- package/lib/providers/deepseek.js +348 -0
- package/lib/providers/deepseek.js.map +1 -0
- package/lib/providers/http.js.map +1 -1
- package/lib/providers/keyed-meta.js +7 -0
- package/lib/providers/keyed-meta.js.map +1 -1
- package/lib/providers/platforms.js +18 -17
- package/lib/providers/platforms.js.map +1 -1
- package/lib/providers/registry.js.map +1 -1
- package/lib/restart.js +47 -0
- package/lib/restart.js.map +1 -0
- package/lib/router.js +145 -26
- package/lib/router.js.map +1 -1
- package/lib/rpc-types.js +15 -0
- package/lib/rpc-types.js.map +1 -0
- package/lib/rpc.js +118 -0
- package/lib/rpc.js.map +1 -0
- package/lib/tools.js +10 -4
- package/lib/tools.js.map +1 -1
- package/lib/types/actions/approval.d.ts +11 -0
- package/lib/types/actions/config.d.ts +54 -0
- package/lib/types/actions/format.d.ts +9 -2
- package/lib/types/actions/run.d.ts +1 -0
- package/lib/types/actions/schema.d.ts +7 -1
- package/lib/types/actions/sources.d.ts +29 -3
- package/lib/types/actions/types.d.ts +28 -2
- package/lib/types/browser-access.d.ts +17 -0
- package/lib/types/catalog/recommend.d.ts +4 -0
- package/lib/types/catalog/schema.d.ts +2 -0
- package/lib/types/cli/builtin-specs.d.ts +11 -3
- package/lib/types/cli/chains-spec.d.ts +12 -3
- package/lib/types/cli/engine.d.ts +10 -3
- package/lib/types/cli/opencli-sites.d.ts +24 -0
- package/lib/types/cli/opencli.d.ts +42 -3
- package/lib/types/cli/runner.d.ts +47 -8
- package/lib/types/cli/spec.d.ts +101 -8
- package/lib/types/cli/time-text.d.ts +12 -0
- package/lib/types/cli/trial.d.ts +19 -0
- package/lib/types/client/SettingsCard.d.ts +17 -1
- package/lib/types/client/agent-mark.d.ts +22 -0
- package/lib/types/client/card-frame.d.ts +35 -0
- package/lib/types/client/cli-form.d.ts +97 -0
- package/lib/types/client/field-docs.d.ts +15 -0
- package/lib/types/client/field-keys.d.ts +41 -0
- package/lib/types/client/field-rows.d.ts +70 -0
- package/lib/types/client/fill.d.ts +2 -0
- package/lib/types/client/form-specs.d.ts +12 -3
- package/lib/types/client/form.d.ts +79 -1
- package/lib/types/client/group-advanced.d.ts +9 -0
- package/lib/types/client/group-agent.d.ts +20 -0
- package/lib/types/client/group-cli.d.ts +52 -0
- package/lib/types/client/group-common.d.ts +12 -0
- package/lib/types/client/group-judge.d.ts +17 -0
- package/lib/types/client/group-order.d.ts +26 -0
- package/lib/types/client/group-runtime.d.ts +15 -0
- package/lib/types/client/group-sources.d.ts +46 -0
- package/lib/types/client/groups-basic.d.ts +18 -0
- package/lib/types/client/index.d.ts +8 -0
- package/lib/types/client/json-list.d.ts +21 -0
- package/lib/types/client/locales.d.ts +1079 -200
- package/lib/types/client/order.d.ts +102 -0
- package/lib/types/client/overlay-ops.d.ts +37 -0
- package/lib/types/client/styles.d.ts +56 -41
- package/lib/types/client/text-view.d.ts +22 -0
- package/lib/types/client/ui-kit.d.ts +200 -0
- package/lib/types/config-fillers.d.ts +9 -0
- package/lib/types/config-groups.d.ts +23 -0
- package/lib/types/config.d.ts +263 -225
- package/lib/types/default-chain.d.ts +63 -0
- package/lib/types/engines.d.ts +29 -1
- package/lib/types/fetch.d.ts +12 -3
- package/lib/types/fiber-config.d.ts +18 -0
- package/lib/types/index.d.ts +164 -150
- package/lib/types/overlay-types.d.ts +98 -0
- package/lib/types/overlay.d.ts +141 -0
- package/lib/types/pipeline/candidates.d.ts +17 -0
- package/lib/types/pipeline/compile.d.ts +11 -0
- package/lib/types/pipeline/confidence.d.ts +35 -0
- package/lib/types/pipeline/fusion.d.ts +23 -1
- package/lib/types/pipeline/render.d.ts +16 -0
- package/lib/types/pipeline/run.d.ts +2 -1
- package/lib/types/pipeline/sources-spec.d.ts +5 -2
- package/lib/types/pipeline/types.d.ts +37 -0
- package/lib/types/providers/deepseek.d.ts +130 -0
- package/lib/types/providers/http.d.ts +2 -1
- package/lib/types/providers/keyed-meta.d.ts +5 -0
- package/lib/types/providers/registry.d.ts +7 -0
- package/lib/types/restart.d.ts +52 -0
- package/lib/types/router.d.ts +57 -10
- package/lib/types/rpc-types.d.ts +79 -0
- package/lib/types/rpc.d.ts +74 -0
- package/lib/types/tools.d.ts +6 -0
- package/lib/types/util.d.ts +10 -0
- package/lib/util.js +10 -1
- package/lib/util.js.map +1 -1
- package/package.json +53 -44
- package/scripts/check-client-bundle.mjs +1 -1
- package/scripts/check-docs-links.mjs +107 -0
- package/scripts/cli-login-check.mjs +214 -0
- package/LOGIN.md +0 -161
- package/lib/client/RubricEditor.js +0 -47
- package/lib/client/RubricEditor.js.map +0 -1
- package/lib/client/fields.js +0 -31
- package/lib/client/fields.js.map +0 -1
- package/lib/types/client/RubricEditor.d.ts +0 -6
- package/lib/types/client/fields.d.ts +0 -65
|
@@ -5,9 +5,9 @@ description: "Web research with web_call search.run (an evidence pack: only the
|
|
|
5
5
|
|
|
6
6
|
# dsh-web-search-pro
|
|
7
7
|
|
|
8
|
-
Two tools. `web_index` shows what exists; `web_call` runs one action and returns `{ok, action, result | error{code,message,hint,schema?}}
|
|
8
|
+
Two tools. `web_index` shows what exists; `web_call` runs one action and returns `{ok, action, result | error{code,message,hint,schema?}}`. Actions are named `group.action`; do not guess other names.
|
|
9
9
|
|
|
10
|
-
For web research prefer `search.run` over `web_search` + `web_fetch`: it returns filtered evidence, not whole result lists and pages.
|
|
10
|
+
For web research prefer `search.run` over `web_search` + `web_fetch`: it returns filtered evidence, not whole result lists and pages. A Host `web_search` that answers with an `Evidence pack ...` (routed through this plugin) is a `search.run` pack: read gaps, then `history.expand` or `read.fetch`.
|
|
11
11
|
|
|
12
12
|
## 1. Search: evidence mode first
|
|
13
13
|
|
|
@@ -21,13 +21,13 @@ Pass `task` (one sentence: your goal, not the chat) or `profile` for an evidence
|
|
|
21
21
|
{"action":"search.run","args":{"query":"量子计算 最新进展 2026","task":"了解 2026 年量子计算的最新进展","profile":"news_fact","needs":"最新的纠错进展;主要厂商的路线图","constraints":"[{\"kind\":\"time_window\",\"value\":\"2026\",\"strength\":\"soft\"}]"}}
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
`needs` are `;`-separated sub-questions (default: the task). The query may be English
|
|
24
|
+
`needs` are `;`-separated sub-questions (default: the task). The query may be English with a Chinese task.
|
|
25
25
|
|
|
26
26
|
## 2. Read the pack before answering
|
|
27
27
|
|
|
28
28
|
- Cite the evidence URLs. Every excerpt has an `evidenceId`.
|
|
29
29
|
- **Coverage is heuristic.** A need listed in `gaps`, or an empty pack, does not mean the answer does not exist. Before saying "not found": expand or fetch, then try another source or phrasing (`gaps[].reason`: `no_candidates`, `no_page_content`, `weak_support`, `budget`).
|
|
30
|
-
- `low relevance` entries only avoid an empty pack; do not
|
|
30
|
+
- `low relevance` entries only avoid an empty pack; do not rely on them.
|
|
31
31
|
|
|
32
32
|
```json call
|
|
33
33
|
{"action":"history.expand","args":{"evidenceId":"e_1a2b3c"}}
|
|
@@ -53,7 +53,7 @@ A long page is capped; the reply gives `nextOffset`. Continue with `offset` (ser
|
|
|
53
53
|
{"action":"search.recommend","args":{"task":"find the official documentation for Rust async runtimes","profile":"docs_code"}}
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
returns at most 3 sources, ready ones first, with how to call each (`use`) and what is missing. Use one or two; add another only when the evidence is insufficient.
|
|
56
|
+
returns at most 3 sources, ready ones first, with how to call each (`use`) and what is missing. Use one or two; add another only when the evidence is insufficient. Needs setup: tell the user what is missing (`references/sources.md`), do not call it.
|
|
57
57
|
|
|
58
58
|
Name sources only when you have a reason:
|
|
59
59
|
|
|
@@ -63,7 +63,7 @@ Name sources only when you have a reason:
|
|
|
63
63
|
|
|
64
64
|
- `engines` takes ids from `search.recommend` / `sources.status` (aliases like `ddg` work; an unknown id lists the valid ones). Explicit engines are tried in order.
|
|
65
65
|
- `platform` searches one site (`github`, `v2ex`, `bilibili`, `rss` with `url`, `zhihu`, `xiaohongshu`, `twitter`, ...). With `task`/`profile` it is the evidence source (gate, page reads and scoring as usual). If it is unavailable the call fails with what is missing: tell the user, or pass `allowFallback:true` to search the web engines instead. Platforms run a backend chain; logins are the user's job (`references/sources.md`).
|
|
66
|
-
- **来源策略**: nothing configured = anonymous / free sources (English: Exa's keyless route, then ddg / bing; Chinese: ddg / bing). Sources the user configured a key for are promoted for their language
|
|
66
|
+
- **来源策略**: nothing configured = anonymous / free sources (English: Exa's keyless route, then ddg / bing; Chinese: ddg / bing). Sources the user configured a key for are promoted for their language, `deepseek` (常用, billed) first; settings `sources: {priority, disabled, budget}` rank and cap them (a used-up source is skipped, never an error). `engines` always wins. Tiers: `references/sources.md`.
|
|
67
67
|
|
|
68
68
|
## 4. Constraints
|
|
69
69
|
|
|
@@ -75,14 +75,15 @@ Name sources only when you have a reason:
|
|
|
75
75
|
|
|
76
76
|
## 5. Budgets
|
|
77
77
|
|
|
78
|
-
- `budget` (evidence mode): excerpt characters, default 6000, max 30000. Gaps caused by budget say so
|
|
79
|
-
- `count`: max results (1-20). A page read is capped at 20000 characters
|
|
80
|
-
- Model scoring (when enabled) has
|
|
81
|
-
- `cache.clear`, `history.delete`, `rules.upsert|remove|import
|
|
78
|
+
- `budget` (evidence mode): excerpt characters, default 6000, max 30000. Gaps caused by budget say so: raise it or expand.
|
|
79
|
+
- `count`: max results (1-20). A page read is capped at 20000 characters; `maxChars` raises it.
|
|
80
|
+
- Model scoring (when enabled) has token caps; `sources.status` shows usage (`references/judges.md`).
|
|
81
|
+
- `cache.clear`, `history.delete`, `rules.upsert|remove|import`, `sources.install` and `config.*` change local state or the machine: run them only when the user asks.
|
|
82
|
+
- The user asks you to reorder sources, switch one off or add a CLI as a source: `config.inspect` first, then `config.set_order` / `set_confidence` / `upsert_cli` (asks the user) with a real `reason`: `references/config.md`.
|
|
82
83
|
|
|
83
84
|
## 6. Browser hand-off
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
Pages that need interaction, login or a rendered DOM: the dsh-browser plugin (its skill `dsh-browser`, or `browser_index`). `read.snapshot` and browser platforms work only when it is installed and ready (`sources.status` shows `browser`).
|
|
86
87
|
|
|
87
88
|
## 7. When something fails
|
|
88
89
|
|
|
@@ -95,4 +96,4 @@ For pages that need interaction, login, or a rendered DOM, use the dsh-browser p
|
|
|
95
96
|
| `DEADLINE` | retry narrower, fewer engines |
|
|
96
97
|
| `ACTION_FAILED` | read the message; empty or failed engines are listed in the result (`enginesTried`, `fallbackNote`) |
|
|
97
98
|
|
|
98
|
-
Quota, fake-IP
|
|
99
|
+
Quota, fake-IP, cooldowns: `references/troubleshooting.md`. Judge providers, rubrics (settings): `references/judges.md`. Keyed sources, catalog: `references/sources.md`. Bad extraction: `rules.upsert`, then `read.fetch` `fresh:true`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Changing the search order at run time: `config.*`
|
|
2
|
+
|
|
3
|
+
Use these when the **user** asks you to change how searches are routed: put a source first or last, switch one off, trust one source less, change the backends a platform tries, or add a command-line tool as a source. Do not use them on your own initiative to "improve" results.
|
|
4
|
+
|
|
5
|
+
The user's configuration (the profile) is the baseline. `config.*` writes a separate **overlay** on top of it. It applies at once to the next call, the user sees every change in the settings card ("Agent changes", with your reason and the time) and can adopt it into their configuration or revoke it. You cannot touch keys, paths, budgets or switches this way, and nothing you write deletes a baseline entry.
|
|
6
|
+
|
|
7
|
+
## The order of work
|
|
8
|
+
|
|
9
|
+
1. `config.inspect`: what is in force, which entries come from the overlay, the `revision`, the recent audit trail, and settings waiting for a plugin restart (`待重启`).
|
|
10
|
+
2. Make one change with a real `reason` (3-300 characters, what the user asked and why). Pass `expectedRevision` from the inspect so a change made meanwhile (by the user in the card) is not overwritten.
|
|
11
|
+
3. Tell the user what changed and that they can revoke it in the settings card.
|
|
12
|
+
|
|
13
|
+
```json call
|
|
14
|
+
{"action":"config.inspect","args":{}}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```json call
|
|
18
|
+
{"action":"config.set_order","args":{"engines":["bing","ddg","exa"],"reason":"The user asked to try bing before ddg for Chinese queries","expectedRevision":0}}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## The actions
|
|
22
|
+
|
|
23
|
+
- `config.set_order {engines?, priority?, disabled?, platform?, backends?}`: each list **replaces** the list in force (give the whole list). `platform` and `backends` go together: the whole backend chain of that platform. A custom CLI is written `custom-cli:<id>`. To stop using a source put it in `disabled`.
|
|
24
|
+
- `config.set_confidence {id, value}`: 0..1, slightly lowers a source's weight when results are fused (1 = no change). Omit `value` to drop the overlay's entry.
|
|
25
|
+
- `config.upsert_cli {id, spec}`: add or replace a custom CLI source. **It always asks the user first** (it lets the plugin run a local program; the prompt shows the command and argument templates). With no one to ask (a headless run) it is refused: tell the user instead. The spec must pass the same read-only checks as in the card (no login or write commands, no cookie or credential flags, no secrets). Try the spec's command yourself first only if the user asked you to; `sources.deps` shows whether the tool is installed.
|
|
26
|
+
- `config.remove_cli {id}`: only a CLI the overlay added, and not while the overlay still names it in an order list. A CLI from the configuration is switched off with `config.set_order {disabled:[...,"custom-cli:<id>"]}`.
|
|
27
|
+
- `config.reset {scope, id?}`: `all`, `order` (engines, priority, disabled), `confidence`, `cli`, `platform`; `id` narrows the last three to one entry. `reset all` also repairs an overlay file that could not be read.
|
|
28
|
+
- `config.export`: the settings in force as YAML. Show it to the user if they want to keep the change in their configuration.
|
|
29
|
+
|
|
30
|
+
## Errors
|
|
31
|
+
|
|
32
|
+
- `INVALID_ARGS`: the message names the id or value the validators refused. Nothing was written.
|
|
33
|
+
- `ACTION_FAILED` with "revision N, not M": someone changed the overlay since you read it. `config.inspect` again and decide again.
|
|
34
|
+
- `CAPABILITY_UNAVAILABLE`: the overlay file is unreadable or no longer agrees with the configuration and is being ignored as a whole (the configuration applies as written). Ask the user, or `config.reset {scope:"all"}` if they agree.
|
|
35
|
+
- `POLICY_DENIED`: the browser plugin's `automationMode` is read-only, or the user refused. Do not retry; ask the user.
|
|
36
|
+
- Settings marked `待重启` in `config.inspect` / `sources.status` (`toolSurface`, `dbPath`, `registerProvider`, `providerId`, `timeoutMs`, `memoryCacheEntries`, `verbose`, `playwright.snapshotDir`) only take effect after the plugin restarts; tell the user, you cannot change them anyway.
|
|
@@ -8,9 +8,9 @@ Every source has a cost tier, shown by `search.recommend` and `sources.status`:
|
|
|
8
8
|
|
|
9
9
|
- `anonymous`: no key, account or money (rate limits aside): `ddg`, `bing`, `exa` over its keyless MCP route (needs `mcporter` and an `exa` MCP server), `wikipedia`, `hackernews`, `stackexchange`, `openalex`, `semanticscholar`, `anysearch`, `github`, `arxiv`, `pubmed`, `v2ex`, `rss`, `searxng`.
|
|
10
10
|
- `free-quota`: needs a key, account or login and is free to use: `tavily` (1000 credits a month), `brave` ($5 of credits a month, a card for identity), `linkup`, `serper` (2500 queries at sign-up, once), `jina` (10M tokens per new key, once), `baidu-qianfan` (100 calls a day), `exa` with an API key ($10 a month), `github-code` (a free token), login platforms.
|
|
11
|
-
- `paid`: `bocha`, `metaso`, `zhipu` (no free allowance on the official pages).
|
|
11
|
+
- `paid`: `deepseek` ($0.75 per 1,000 successful requests), `bocha`, `metaso`, `zhipu` (no free allowance on the official pages).
|
|
12
12
|
|
|
13
|
-
Order of precedence for the automatic plan: (1) `engines` / `platform` in the call; (2) the user's `priority` list (setting `sources:`); (3) sources the user configured with a key, promoted for their language and profile (at most two, one per family); (4) otherwise the anonymous / free defaults. A paid source is used only when the user configured its key; `evidence.sourcePolicy: anonymous-only` never uses a source that needs a key, account or login. `budget: { <id>: {total, daily} }` under `sources:` (optional, nothing is capped by default) caps a source; a used-up one is skipped with a note and the plan falls back to free sources. `sources.status` shows used and remaining requests. Example for a Bocha account with 1000 requests: `sources: { budget: { bocha: { total: 1000, daily: 50 } } }`. These are the user's settings: do not change them, tell the user.
|
|
13
|
+
Order of precedence for the automatic plan: (1) `engines` / `platform` in the call; (2) the user's `priority` list (setting `sources:`); (3) sources the user configured with a key, promoted for their language and profile (at most two, one per family; `deepseek`, the 常用 source, goes first of them in both languages, and leads a plain search's default chain while `engines` is the default list); (4) otherwise the anonymous / free defaults. A paid source is used only when the user configured its key; `evidence.sourcePolicy: anonymous-only` never uses a source that needs a key, account or login. `budget: { <id>: {total, daily} }` under `sources:` (optional, nothing is capped by default) caps a source; a used-up one is skipped with a note and the plan falls back to free sources. `sources.status` shows used and remaining requests. Example for a Bocha account with 1000 requests: `sources: { budget: { bocha: { total: 1000, daily: 50 } } }`. These are the user's settings: do not change them, tell the user.
|
|
14
14
|
|
|
15
15
|
## Kinds
|
|
16
16
|
|
|
@@ -19,6 +19,7 @@ Order of precedence for the automatic plan: (1) `engines` / `platform` in the ca
|
|
|
19
19
|
|
|
20
20
|
| id | language | key variable |
|
|
21
21
|
|---|---|---|
|
|
22
|
+
| `deepseek` | zh + en, 常用 | `DEEPSEEK_API_KEY` (DeepSeek Search API; verified live 2026-10-26; billed, see below) |
|
|
22
23
|
| `exa` | en | `EXA_API_KEY` |
|
|
23
24
|
| `bocha` | zh | `BOCHA_SEARCH_API_KEY` (falls back to `BOCHA_JEV_API_KEY`; verified live 2026-10-04) |
|
|
24
25
|
| `tavily` | en | `TAVILY_API_KEY` |
|
|
@@ -31,17 +32,18 @@ Order of precedence for the automatic plan: (1) `engines` / `platform` in the ca
|
|
|
31
32
|
| `jina` | any | `JINA_API_KEY` |
|
|
32
33
|
|
|
33
34
|
- **Self-hosted**: `searxng` needs `searxngUrl` in settings (no public instance is built in).
|
|
34
|
-
- **CLI** (`sources.deps` lists them with `installation`: missing / detected / incompatible; `sources.install` installs one when the user asks): `bili`, `yt-dlp`, `twitter` (also needs `TWITTER_AUTH_TOKEN` and `TWITTER_CT0`), `xhs`, `zhihu`, `rdt
|
|
35
|
+
- **CLI** (`sources.deps` lists them with `installation`: missing / detected / incompatible; `sources.install` installs one when the user asks): `bili`, `yt-dlp`, `twitter` (twitter-cli, an optional fallback; also needs `TWITTER_AUTH_TOKEN` and `TWITTER_CT0` in DSH credentials or the Host process environment, not just a shell profile), `xhs`, `zhihu`, `rdt` (optional fallbacks), `omnireach`, `gh`, `wx-search-cli`, `tanso`, standalone `opencli`, the user's own `cliAdapters`, `mcporter`, `agent-reach` (optional helper). See "Backend chains" below.
|
|
35
36
|
- **Browser-based** (need dsh-browser and a saved login): `weibo`, `douban`, `tieba`, `douyin`, `kuaishou`, and the dsh-browser OpenCLI legs of `instagram` / `facebook` (and the last legs of `xiaohongshu`, `reddit`, `twitter`, `zhihu`).
|
|
36
37
|
|
|
37
38
|
## Backend chains (CLI adapters)
|
|
38
39
|
|
|
39
|
-
Every platform is ONE source with an ordered chain of backends; the first usable one answers, empty or failing ones fall through. `sources.status` shows each platform's `chain` (order, state, why a backend is skipped). Defaults: `xiaohongshu`: opencli (standalone) > xhs > browser-opencli; `reddit`:
|
|
40
|
+
Every platform is ONE source with an ordered chain of backends; the first usable one answers, empty or failing ones fall through. `sources.status` shows each platform's `chain` (order, state, why a backend is skipped). Defaults: `xiaohongshu`: opencli (standalone) > xhs > browser-opencli; `reddit`: opencli > rdt > browser-opencli; `zhihu`: opencli > zhihu > browser-search; `twitter`: opencli > twitter > browser-opencli (the four login platforms try the standalone OpenCLI first: it uses the login of the user's own day-to-day Chrome); `bilibili`: bili; `youtube`: yt-dlp; `github`, `github-issues`, `github-code`: rest > gh; `wechat` (公众号): omnireach > wx-search-cli; `omnireach` (multi-source, never planned on its own). The user can reorder with `platformBackends: { <platform>: [ids] }` (an explicit order is used as written) and add read-only adapters in `cliAdapters` (platform `custom-cli:<id>`); an invalid entry is ignored and explained in `sources.status` `notes`.
|
|
40
41
|
|
|
41
|
-
- A backend that is not installed, has another contract (`incompatible`, with the reason)
|
|
42
|
-
- **Login is the user's job.** Never run `xhs login`, `rdt login`, `zhihu login`, `gh auth login` or anything like them, and never pass cookie options.
|
|
43
|
-
- Verification differs per adapter (`sources.deps` shows it): `live` (bili, gh repos, omnireach
|
|
42
|
+
- A backend that is not installed, has another contract (`incompatible`, with the reason), is not logged in, was blocked by the site or failed is passed over; the result's notes say `skipped backends: <id>: <reason>` and the history names the backend that answered. When the whole chain is down the error names every backend and what to install or run. Report it; do not retry.
|
|
43
|
+
- **Login is the user's job.** Never run `xhs login`, `rdt login`, `zhihu login`, `gh auth login` or anything like them, and never pass cookie options. For `xiaohongshu`, `zhihu`, `reddit` and `twitter` the recommended path is the standalone `opencli`, which uses the login of the user's own Chrome (the user logs in to the site there and has the OpenCLI Browser Bridge extension installed): when it reports "not logged in", tell the user to log in to that site in their Chrome and retry; do not look for a login command. The CLIs `xhs`, `rdt`, `zhihu`, `twitter` are optional fallbacks the user logs in with the tool's own login; they are not run until a saved login exists (without one they read browser cookies themselves). A failure that says the site "returned a web page instead of data" is a login wall, risk control or an IP block (Reddit blocks proxied addresses): report it, do not retry in a loop.
|
|
44
|
+
- Verification differs per adapter (`sources.deps` shows it): `live` (bili, gh repos / issues / code, omnireach, yt-dlp, wx-search-cli, xhs, and standalone opencli for the twitter and zhihu sites), `contract-only` (help probed, output shape from the tool's source or docs, no successful search run: zhihu, rdt, twitter CLIs and standalone opencli for xiaohongshu / reddit; `sources.status` tags these backends), `docs-only` (tanso, from upstream docs). Treat contract-only and docs-only results as experimental.
|
|
44
45
|
- The plugin only ever runs read commands (search); posting, liking, following and the like are refused by the adapter spec itself.
|
|
46
|
+
- **User-defined CLIs** (`cliAdapters`, shown in the settings card under "Custom CLI"): registered as `custom-cli:<id>`. With `engine: true` one is a general engine that can go into `engines` (`engines=custom-cli:<id>`); with `platforms: [...]` it can sit in those platforms' backend chains. Their results carry `via`, `confidence` (when below 1) and `tag` ("user-defined, not verified by the plugin"): treat them as unverified. A spec with `output.lines: { mode: whole }` returns the tool's whole stdout as ONE result with a stand-in link `cli://<id>?q=...`: it is not a web page, evidence mode lists it but never fetches it, and its text is cut at `maxChars` with a note. the setting `sources: { confidence: { <id>: 0-1 } }` lowers how much a source weighs when several are fused (a custom CLI defaults to 0.5, built-ins to 1) and never drops a result. To test one without the panel: `sources.status`, then `search.run engines=custom-cli:<id>`.
|
|
45
47
|
|
|
46
48
|
## Platforms (one site or community)
|
|
47
49
|
|
|
@@ -57,6 +59,10 @@ Platforms are sources like any other (`sources.status` lists them with `kind: pl
|
|
|
57
59
|
- `url` (rss only), `authProfile` and `rulePack` go with `platform`; `browserBindings` fill the last two per platform.
|
|
58
60
|
- The user's own `customPlatforms` appear here as platforms too, under their key.
|
|
59
61
|
|
|
62
|
+
## DeepSeek Search and Fetch (常用)
|
|
63
|
+
|
|
64
|
+
`deepseek` is the plugin's common source: `POST https://api.deepseek.com/v1/tools/search`, the same API key as the DeepSeek models (`DEEPSEEK_API_KEY`, a DSH credential, or `keyedSources.deepseek.apiKey`). $0.75 per 1,000 SUCCESSFUL requests (empty results and failures are free; `count` does not change the price); calls through the Harness's own tools are free until 2026-11-01 Beijing time, but this plugin's direct calls are treated as billed. Results carry a model-ready `summary` (used as the excerpt), `date`, and the provider's own grades `rerankScore` (0-3, 1.5+ is good) and `authority` (0-4, 3+ is high): hints, not proof. Queries are cut to 128 characters (operators kept) and the result says so. 402 means the account balance is empty: tell the user to top it up. Cap it with the `sources` setting's `budget.deepseek`; turn it off by listing `deepseek` under its `disabled`. The Fetch API is `read.fetch mode:"deepseek"` (auto mode uses it as a fallback when `deepseekFetch` is on); its 403 / 404 are DeepSeek's answer, not the page's HTTP status.
|
|
65
|
+
|
|
60
66
|
## Setting a key (the user does this; never ask for the key value)
|
|
61
67
|
|
|
62
68
|
A key is read from, in order: the literal in settings (`exaApiKey`, `keyedSources.<id>.apiKey`), a credentials reference (`...Env` / `apiKeyEnv` names a variable or credential), then the default variable above. Tell the user which variable to set, then call `sources.status` and check the source shows `credential: configured`. A key that is configured but rejected (401/403) is reported as an error, not a cooldown.
|
|
@@ -6,6 +6,7 @@ Start with `sources.status`: it makes no search request and shows engine state,
|
|
|
6
6
|
|---|---|
|
|
7
7
|
| `resolved to proxy fake-IP ...` | Clash/TUN fake-IP DNS (`198.18.0.0/15`, `fdfe:dcba:9876::/64`, `2001:2::/48`). Ask the user to enable `allowProxyFakeIp` in the plugin's advanced settings (default off). It trusts only those DNS answers; literal fake-IP URLs, localhost and other private addresses stay blocked. |
|
|
8
8
|
| `quota_exhausted (HTTP 402)`, `ENGINE_QUOTA`, "no credit/quota" | The account or the anonymous tier is used up. It is not retried or cooled down. Use another source from `search.recommend`; for a keyed source tell the user to top up. Never retry in a loop. |
|
|
9
|
+
| DeepSeek `HTTP 402 ... 余额不足` | The DeepSeek API balance is empty (Search and Fetch share it). Tell the user to top it up at platform.deepseek.com; the plugin falls back to the next source meanwhile. 408 / 429 / 5xx from DeepSeek are retried twice after a wait before they count as a failure. |
|
|
9
10
|
| `ENGINE_RATE_LIMIT`, 429, a source in `cooldown` | The service said wait; the plugin respects `Retry-After`. Use a different source now; `cooldownUntil` shows when it is free. |
|
|
10
11
|
| 401 / 403 on a keyed source | The key is rejected: the user must check it. It does not cool the source down. |
|
|
11
12
|
| every engine returned nothing | Not an error. Rephrase, add a `site:` word, or try a source from `search.recommend`; a `fallbackNote` lists who was tried and skipped. |
|
|
@@ -13,10 +14,11 @@ Start with `sources.status`: it makes no search request and shows engine state,
|
|
|
13
14
|
| `platform X unavailable ... dsh-browser` | A browser-based or OpenCLI platform without the dsh-browser plugin (or with an older one). `sources.status` -> `browser` says `missing` / `incomplete`. Use a non-browser source, or ask the user to install or update it. |
|
|
14
15
|
| `dsh-browser 0.1.x is not supported by web-search-pro 0.2+` | Legacy browser: `sources.status` shows `browser: legacy (unsupported)`. `read.snapshot`, `read.fetch mode=playwright`, browser and OpenCLI platforms refuse; `auto` fetch skips the browser; everything else works. Tell the user to upgrade to `@anweat/dsh-browser ^0.2.0`; do not retry. |
|
|
15
16
|
| `CAPABILITY_UNAVAILABLE`, `platform X unavailable: ...` | A platform you named cannot run: the message says what is missing (browser, login, CLI, token, settings switch, cooldown) and the hint has the setup text. Tell the user. In evidence mode `allowFallback:true` searches the web engines instead; the pack's notes say so. |
|
|
17
|
+
| `opencli is not logged in`, or `the site returned a web page instead of data, or blocked the request` in a platform error or in `skipped backends` | The standalone OpenCLI uses the login of the user's own Chrome: ask the user to log in to that site in their Chrome (and check `opencli doctor` for the Browser Bridge extension). The second wording is a login wall, risk control or an IP block (Reddit blocks proxied addresses); report it, do not retry in a loop. The plugin never logs in for the user. |
|
|
16
18
|
| platform result is empty with `no results: ...` in `fallbackNote` | The platform ran and returned nothing; the note is the platform's own hint (usually a missing login or changed page selectors). Not an error and not cooled down. |
|
|
17
19
|
| login pages (`login_wall`), captcha | The text is not the content. Chinese communities need a saved, domain-scoped login (`browserBindings`). Do not try to bypass a captcha. |
|
|
18
20
|
| `js_shell` / empty page text | The page needs JavaScript. With dsh-browser ready, `read.fetch` already tried a render in `auto` mode; otherwise `read.snapshot`, or add a site rule (`rules.upsert` with `contentSelectors`). |
|
|
19
|
-
| twitter source `unavailable` | The `twitter` command, `enableCliBackends`, `agentReachEnabled` and `TWITTER_AUTH_TOKEN` + `TWITTER_CT0` must all be in place; the `note` says which is missing. `
|
|
21
|
+
| twitter source `unavailable` | The `twitter` command (twitter-cli 0.8.5+, its `search --help` must list `--json`), `enableCliBackends`, `agentReachEnabled` and `TWITTER_AUTH_TOKEN` + `TWITTER_CT0` must all be in place; the `note` says which is missing and where it looked. The tokens belong in DSH credentials (settings `twitterAuthToken` / `twitterCt0`, or the refs `twitterAuthTokenEnv` / `twitterCt0Env`) or in the Host process environment; a shell profile alone is not enough. Twitter results that look like field names or avatar/video links mean an old plugin parsing twitter-cli's default YAML (issue #38, fixed in 0.2.2). |
|
|
20
22
|
| `model budget exceeded` in notes | The judge's token cap was reached; rule scores were used. Results remain valid. |
|
|
21
23
|
| `partial: true` | The overall time limit (`timeoutMs` + 30 s) was reached; the pack holds what was ready. Expand or search again narrower. |
|
|
22
24
|
| `NOT_FOUND` on an id | Ids (`history`, `evidenceId`) disappear when the query is deleted or cleared. List again with `history.list`. |
|
package/catalog/sources.v1.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "dsh-web-search-pro/source-catalog",
|
|
3
3
|
"version": 1,
|
|
4
|
-
"updated": "2026-10-
|
|
4
|
+
"updated": "2026-10-27",
|
|
5
5
|
"description": "Known search sources, pure data. It never executes anything: only adapters registered in the provider registry can run; this file explains what is missing and how to set it up.",
|
|
6
6
|
"entries": [
|
|
7
|
+
{"id":"deepseek","label":"DeepSeek Search API","kind":"api","operations":["search"],"languages":["zh","en"],"regions":["global","cn"],"profiles":["general","news_fact","experience","compare","docs_code"],"resultKinds":["web"],"auth":"key","costTier":"paid","keyEnv":["DEEPSEEK_API_KEY"],"provider":"deepseek","rank":5,"common":true,"install":"Create an API key at platform.deepseek.com and set DEEPSEEK_API_KEY (or a DSH credential / the settings key field). Optional cap: sources.budget.deepseek. Optional page reader: deepseekFetch.","license":"proprietary API service","cost":"paid: $0.75 per 1,000 successful requests, Search and Fetch each; empty results and failures are free (api-docs.deepseek.com/guides/search, 2026-10-26)","url":"https://api-docs.deepseek.com/guides/search/","verification":{"status":"verified","date":"2026-10-26","note":"8 Search + 4 Fetch live requests: result shape, summary / rerank_score / authority / date, operators, 128-char limit, 401 / 404 bodies; 403 and retry paths from the docs only"},"recommendedFor":["General web search in Chinese and English with a model-ready summary, a date, and the service's own rerank score and authority grade"],"notFor":["accounts without API balance (HTTP 402)","queries over 128 characters: they are cut, with a note"]},
|
|
7
8
|
{"id":"seam","label":"DeepSeek native search (ctx.web)","kind":"api","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["general"],"resultKinds":["web"],"auth":"anonymous","costTier":"anonymous","requires":{"service":"ctx.web"},"provider":"seam","rank":60,"install":"Provided by the DSH host web capability; configure a web provider in the host.","license":"depends on the host provider","cost":"decided by the host provider behind ctx.web","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["one general web query through whatever provider the host selected"],"notFor":["evidence of independence: the upstream index is unknown"]},
|
|
8
9
|
{"id":"exa","label":"Exa","kind":"api","operations":["search"],"languages":["en"],"regions":["global"],"profiles":["general","news_fact","experience","compare","docs_code"],"resultKinds":["web"],"auth":"key","costTier":"anonymous","keyEnv":["EXA_API_KEY"],"provider":"exa","sourceFamily":"exa","rank":10,"install":"Set EXA_API_KEY (or exaApiKey). Without a key the mcporter MCP fallback works for plain queries only.","license":"proprietary API service","cost":"keyless MCP route (mcporter): anonymous, rate limited, verified 2026-10-04. API key route: $10 free credits monthly (https://exa.ai/pricing)","url":"https://exa.ai/docs/reference/search","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["English semantic web search","docs and technical articles"],"notFor":["advanced filters through the mcporter fallback"]},
|
|
9
10
|
{"id":"ddg","label":"DuckDuckGo","kind":"api","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["general","news_fact","experience","compare","docs_code","academic"],"resultKinds":["web"],"auth":"anonymous","costTier":"anonymous","provider":"ddg","rank":40,"install":"None (HTML endpoint, no key).","license":"free endpoint, no SLA","cost":"free","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["default keyless general web search","site:/-term operators"],"notFor":["heavy or parallel use: rate limits and bot checks return empty pages"]},
|
|
@@ -14,17 +15,17 @@
|
|
|
14
15
|
{"id":"github-code","label":"GitHub code search","kind":"api","operations":["search"],"languages":["*"],"regions":["global"],"auth":"key","costTier":"free-quota","keyEnv":["GITHUB_TOKEN","GH_TOKEN"],"sourceFamily":"github","license":"proprietary API service","cost":"free-quota: a free GitHub token is required; free within the REST search rate limits (https://docs.github.com/en/rest/search/search, 2026-10-04)","verification":{"status":"unverified","note":"REST search API; code search needs an authenticated request"},"profiles":["docs_code"],"resultKinds":["code"],"provider":"github-code","platform":"github-code","install":"Set GITHUB_TOKEN (or settings githubToken), or install gh and run `gh auth login` yourself: code search needs an authenticated request.","recommendedFor":["finding real usages of an API or a config key in public code"],"notFor":["use without a token","natural-language questions"]},
|
|
15
16
|
{"id":"github-issues","label":"GitHub issues and pull requests","kind":"api","operations":["search"],"languages":["*"],"regions":["global"],"auth":"anonymous","costTier":"anonymous","keyEnv":["GITHUB_TOKEN","GH_TOKEN"],"sourceFamily":"github","license":"proprietary API service","cost":"free within GitHub API limits","verification":{"status":"unverified","note":"REST search API; no live check recorded"},"profiles":["docs_code","experience"],"resultKinds":["forum"],"provider":"github-issues","platform":"github-issues","install":"None; GITHUB_TOKEN (optional) raises the rate limit.","recommendedFor":["known bugs, workarounds and maintainer answers for an error message"],"notFor":["general web knowledge"]},
|
|
16
17
|
{"id":"bilibili","label":"Bilibili (bili CLI)","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["video"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"bili"},"provider":"bilibili","platform":"bilibili","install":"uv tool install --force git+https://github.com/public-clis/bilibili-cli (pinned revision; sources.deps shows the command).","license":"Apache-2.0 (public-clis/bilibili-cli)","cost":"free","verification":{"status":"verified","date":"2026-10-06","version":"0.6.2","note":"bili search --type video --max 2 --json parsed live; contract probed by sources.deps"},"recommendedFor":["Chinese video tutorials and reviews"],"notFor":["text-first factual questions","another PyPI package named bilibili-cli (different contract)"]},
|
|
17
|
-
{"id":"youtube","label":"YouTube (yt-dlp)","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["experience"],"resultKinds":["video"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"yt-dlp"},"provider":"youtube","platform":"youtube","install":"uv tool install yt-dlp (or pip install yt-dlp).","license":"Unlicense (yt-dlp)","cost":"free","verification":{"status":"
|
|
18
|
+
{"id":"youtube","label":"YouTube (yt-dlp)","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["experience"],"resultKinds":["video"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"yt-dlp"},"provider":"youtube","platform":"youtube","install":"uv tool install yt-dlp (or pip install yt-dlp).","license":"Unlicense (yt-dlp)","cost":"free","verification":{"status":"verified","date":"2026-10-11","version":"2026.08.19","note":"yt-dlp ytsearch2:... --flat-playlist --print <template> run and parsed live"},"recommendedFor":["video talks, demos and tutorials"],"notFor":["transcripts (not wired into this plugin)"]},
|
|
18
19
|
{"id":"v2ex","label":"V2EX","kind":"api","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["forum"],"auth":"anonymous","costTier":"anonymous","provider":"v2ex","platform":"v2ex","install":"None.","license":"free public site","cost":"free","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["Chinese developer community experience"],"notFor":["English questions","official documentation"]},
|
|
19
20
|
{"id":"arxiv","label":"arXiv","kind":"api","operations":["search"],"languages":["en"],"regions":["global"],"profiles":["academic"],"resultKinds":["paper"],"auth":"anonymous","costTier":"anonymous","provider":"arxiv","platform":"arxiv","sourceFamily":"arxiv","install":"None.","license":"free public API","cost":"free","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["preprints in CS, physics, maths"],"notFor":["biomedicine (use PubMed)","peer-review status"]},
|
|
20
21
|
{"id":"pubmed","label":"PubMed","kind":"api","operations":["search"],"languages":["en"],"regions":["global"],"profiles":["academic"],"resultKinds":["paper"],"auth":"anonymous","costTier":"anonymous","provider":"pubmed","platform":"pubmed","sourceFamily":"pubmed","install":"None.","license":"free public API (NCBI)","cost":"free","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["biomedical and life-science literature"],"notFor":["computer science papers"]},
|
|
21
|
-
{"id":"twitter","label":"Twitter / X: twitter-cli,
|
|
22
|
-
{"id":"xiaohongshu","label":"Xiaohongshu (小红书): OpenCLI, xhs, dsh-browser","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","platform":"xiaohongshu","install":"
|
|
23
|
-
{"id":"reddit","label":"Reddit:
|
|
22
|
+
{"id":"twitter","label":"Twitter / X: OpenCLI (your Chrome), twitter-cli, dsh-browser","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["experience","news_fact"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"cli":"opencli"},"platform":"twitter","install":"Chain: standalone OpenCLI (npm i -g @jackwener/opencli + its Browser Bridge extension; log in to x.com in your own Chrome (the plugin never logs in)), optional twitter-cli (uv tool install twitter-cli; TWITTER_AUTH_TOKEN / TWITTER_CT0), dsh-browser OpenCLI. Reorder with platformBackends.","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","verification":{"status":"unverified","date":"2026-10-27","version":"1.8.8","note":"opencli 1.8.8 search run on the user's own Chrome and parsed (live fixture); the twitter-cli fallback is contract-only"},"recommendedFor":["live reactions and announcements by accounts"],"notFor":["anonymous use (needs an x.com login in your Chrome)","a different program named twitter on PATH (the twitter-cli fallback)"],"provider":"twitter"},
|
|
23
|
+
{"id":"xiaohongshu","label":"Xiaohongshu (小红书): OpenCLI, xhs, dsh-browser","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","platform":"xiaohongshu","install":"Chain: standalone OpenCLI (npm i -g @jackwener/opencli + its Browser Bridge extension; log in to xiaohongshu.com in your own Chrome (the plugin never logs in)), optional xhs (uv tool install xiaohongshu-cli; run `xhs login` yourself), dsh-browser OpenCLI. Reorder with platformBackends.","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","verification":{"status":"unverified","date":"2026-10-27","note":"xhs 0.6.4 search run with a saved login and parsed (live fixture); opencli 1.8.8 answered AUTH_REQUIRED (no login in that Chrome), so its mapping is contract-only"},"recommendedFor":["Chinese lifestyle and product experience notes"],"notFor":["use with no backend installed or logged in","high-volume crawling"],"provider":"xiaohongshu"},
|
|
24
|
+
{"id":"reddit","label":"Reddit: OpenCLI (your Chrome), rdt, dsh-browser","kind":"cli","operations":["search"],"languages":["en"],"regions":["global"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","platform":"reddit","install":"Chain: standalone OpenCLI (npm i -g @jackwener/opencli + its Browser Bridge extension; log in to reddit.com in your own Chrome (the plugin never logs in)), optional rdt (uv tool install git+https://github.com/public-clis/rdt-cli; run `rdt login` yourself), dsh-browser OpenCLI. Reddit may block a proxied IP.","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","verification":{"status":"unverified","date":"2026-10-27","note":"contract-only: opencli 1.8.8 got an HTML page instead of JSON on a proxied network (mapped as a blocked failure); rdt 0.4.2 help probed; no successful search run"},"recommendedFor":["English community experience threads"],"notFor":["use with no backend installed or logged in"],"provider":"reddit"},
|
|
24
25
|
{"id":"instagram","label":"Instagram via OpenCLI","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"platform":"instagram","install":"Install the dsh-browser plugin (bundles OpenCLI) and log in to the site in its browser; check with browser_opencli_status.","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","verification":{"status":"unverified","note":"shipped backend runs `opencli instagram search`; not re-verified on a pinned OpenCLI version"},"recommendedFor":["visual social posts"],"notFor":["use without dsh-browser and a logged-in session"],"provider":"instagram"},
|
|
25
26
|
{"id":"facebook","label":"Facebook via OpenCLI","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"platform":"facebook","install":"Install the dsh-browser plugin (bundles OpenCLI) and log in to the site in its browser; check with browser_opencli_status.","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","verification":{"status":"unverified","note":"shipped backend runs `opencli facebook search`; not re-verified on a pinned OpenCLI version"},"recommendedFor":["public posts and pages"],"notFor":["use without dsh-browser and a logged-in session"],"provider":"facebook"},
|
|
26
27
|
{"id":"rss","label":"RSS / Atom feeds","kind":"api","operations":["read"],"languages":["*"],"regions":["global"],"profiles":["news_fact"],"resultKinds":["web"],"auth":"anonymous","costTier":"anonymous","platform":"rss","install":"None; pass the feed URL as the url of search.run platform=rss.","license":"free","cost":"free","verification":{"status":"verified","note":"shipped built-in"},"recommendedFor":["latest items of a known feed or blog"],"notFor":["keyword search across the web"],"provider":"rss"},
|
|
27
|
-
{"id":"zhihu","label":"Zhihu (知乎): zhihu-cli, dsh-browser search page","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","platform":"zhihu","install":"
|
|
28
|
+
{"id":"zhihu","label":"Zhihu (知乎): OpenCLI (your Chrome), zhihu-cli, dsh-browser search page","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","platform":"zhihu","install":"Chain: standalone OpenCLI (npm i -g @jackwener/opencli + its Browser Bridge extension; log in to zhihu.com in your own Chrome (the plugin never logs in)), optional zhihu-cli (PyPI pyzhihu-cli; run `zhihu login` yourself), dsh-browser search page with a saved login (browserBindings).","license":"n/a (reads the site you are logged in to)","cost":"free (your account)","verification":{"status":"unverified","date":"2026-10-27","version":"1.8.8","note":"opencli 1.8.8 search run on the user's own Chrome and parsed (live fixture: title, type, author, votes, link); zhihu-cli is contract-only"},"recommendedFor":["Chinese Q&A and long-form answers"],"notFor":["use without a login","high-volume or unattended crawling","the Access-Secret zhihu CLI (a different tool)"],"provider":"zhihu"},
|
|
28
29
|
{"id":"weibo","label":"Weibo (微博) search page","kind":"browser","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"platform":"weibo","install":"Install dsh-browser, run scripts/save-login.mjs for the site and bind it with browserBindings.","license":"n/a (reads the site you are logged in to)","cost":"free (your account)","verification":{"status":"unverified","note":"best-effort selectors on the rendered search page; they break when the markup changes"},"recommendedFor":["Chinese real-time public reaction"],"notFor":["use without a saved login","high-volume or unattended crawling"],"provider":"weibo"},
|
|
29
30
|
{"id":"douban","label":"Douban (豆瓣) search page","kind":"browser","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"platform":"douban","install":"Install dsh-browser, run scripts/save-login.mjs for the site and bind it with browserBindings.","license":"n/a (reads the site you are logged in to)","cost":"free (your account)","verification":{"status":"unverified","note":"best-effort selectors on the rendered search page; they break when the markup changes"},"recommendedFor":["Chinese reviews of books, films and music"],"notFor":["use without a saved login","high-volume or unattended crawling"],"provider":"douban"},
|
|
30
31
|
{"id":"tieba","label":"Baidu Tieba (贴吧) search page","kind":"browser","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"platform":"tieba","install":"Install dsh-browser, run scripts/save-login.mjs for the site and bind it with browserBindings.","license":"n/a (reads the site you are logged in to)","cost":"free (your account)","verification":{"status":"unverified","note":"best-effort selectors on the rendered search page; they break when the markup changes"},"recommendedFor":["Chinese forum discussion"],"notFor":["use without a saved login","high-volume or unattended crawling"],"provider":"tieba"},
|
|
@@ -46,8 +47,8 @@
|
|
|
46
47
|
{"kind":"api","operations":["search"],"regions":["cn"],"profiles":["general","news_fact","experience","compare","docs_code"],"resultKinds":["web"],"auth":"key","costTier":"paid","license":"proprietary API service","verification":{"status":"unverified","note":"contract from the official guide, API reference and error-code page; never called live (no key)"},"notFor":["GLM generated answers: only raw search_result is used; the query is cut to 70 characters"],"id":"zhipu","label":"Zhipu (智谱) web search","languages":["zh"],"keyEnv":["ZHIPU_API_KEY"],"install":"Set ZHIPU_API_KEY (or keyedSources.zhipu.apiKey / a credentials ref); key from open.bigmodel.cn. Standalone web_search endpoint, search_std. Inactive until a key is set.","cost":"paid: no free allowance stated; search_std 0.01 CNY, search_pro 0.03 CNY per request (docs.bigmodel.cn web-search guide, 2026-10-04)","url":"https://docs.bigmodel.cn/cn/guide/tools/web-search","recommendedFor":["second Chinese search source with one domain filter and a recency window"],"provider":"zhipu","rank":30},
|
|
47
48
|
{"kind":"api","operations":["search"],"regions":["cn"],"profiles":["general","news_fact","experience","compare","docs_code"],"resultKinds":["web"],"auth":"key","costTier":"free-quota","license":"proprietary API service","verification":{"status":"unverified","note":"official page contradicts itself on the auth header: both Authorization and X-Appbuilder-Authorization are sent; never called live (no key)"},"notFor":["chat-completions generated answers: only web references are used; query cut to 72 units"],"id":"baidu-qianfan","label":"Baidu Qianfan (千帆) AI search","languages":["zh"],"keyEnv":["QIANFAN_API_KEY"],"install":"Set QIANFAN_API_KEY (or BAIDU_API_KEY / keyedSources.baidu-qianfan.apiKey); AppBuilder key from the Baidu AI cloud console. Inactive until a key is set.","cost":"free-quota: 100 calls per day, then paid post-payment (https://ai.baidu.com/ai-doc/AppBuilder/pmaxd1hvy)","url":"https://ai.baidu.com/ai-doc/AppBuilder/pmaxd1hvy","recommendedFor":["Chinese general web search with site, exclude and date-range filters"],"provider":"baidu-qianfan","rank":40,"sourceFamily":"baidu"},
|
|
48
49
|
{"kind":"api","operations":["search"],"regions":["global"],"profiles":["general","news_fact","experience","compare","docs_code"],"resultKinds":["web"],"auth":"key","costTier":"paid","license":"proprietary API service","verification":{"status":"unverified","note":"no adapter yet; facts from vendor documentation"},"notFor":["use before an adapter exists in this plugin"],"id":"parallel","label":"Parallel Search API / CLI","languages":["en"],"keyEnv":["PARALLEL_API_KEY"],"sourceFamily":"parallel","install":"Planned adapter for /v1/search; or parallel-cli (OAuth or key).","cost":"paid: metered plan; no free allowance confirmed","url":"https://docs.parallel.ai/integrations/cli","recommendedFor":["higher limits than the anonymous MCP tier"]},
|
|
49
|
-
{"id":"wx-search-cli","label":"wx-search-cli (WeChat articles)","kind":"cli","operations":["search","read"],"languages":["zh"],"regions":["cn"],"profiles":["news_fact","experience","general"],"resultKinds":["social"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"wx-search-cli"},"install":"npm i -g wx-search-cli (Node). Second backend of the wechat platform; documented contract only.","license":"MIT","cost":"free","url":"https://github.com/tjx666/wx-search-cli","verification":{"status":"
|
|
50
|
-
{"id":"omnireach","label":"OmniReach CLI / MCP","kind":"cli","operations":["search","fetch","read"],"languages":["zh","en"],"regions":["global","cn"],"profiles":["experience","general"],"resultKinds":["social","web"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"omnireach"},"install":"Python package from github.com/Daily-AC/omnireach (uv tool install). search.run platform=omnireach runs
|
|
50
|
+
{"id":"wx-search-cli","label":"wx-search-cli (WeChat articles)","kind":"cli","operations":["search","read"],"languages":["zh"],"regions":["cn"],"profiles":["news_fact","experience","general"],"resultKinds":["social"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"wx-search-cli"},"install":"npm i -g wx-search-cli (Node). Second backend of the wechat platform; documented contract only.","license":"MIT","cost":"free","url":"https://github.com/tjx666/wx-search-cli","verification":{"status":"verified","date":"2026-10-26","version":"0.1.0","note":"search run live (zh / en / nonsense) and parsed: 10 rows per page, resolved mp.weixin.qq.com links; Sogou anti-spider prints [] with exit 0"},"recommendedFor":["WeChat official-account articles via Sogou search"],"notFor":["stable unattended use: Sogou redirects and captchas change"]},
|
|
51
|
+
{"id":"omnireach","label":"OmniReach CLI / MCP","kind":"cli","operations":["search","fetch","read"],"languages":["zh","en"],"regions":["global","cn"],"profiles":["experience","general"],"resultKinds":["social","web"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"omnireach"},"install":"Python package from github.com/Daily-AC/omnireach (uv tool install). search.run platform=omnireach runs five explicit keyless sources (hackernews, youtube, github, wechat, bilibili); the tool's automatic routing is never used because it adds Chrome-backed google / twitter when opencli is on PATH.","license":"MIT","cost":"free","url":"https://github.com/Daily-AC/omnireach","verification":{"status":"verified","date":"2026-10-26","version":"0.19.0-alpha","note":"multi-source search with an explicit --on hackernews,youtube,github,wechat,bilibili and the wechat source run live and parsed; the automatic routing was seen adding Chrome-backed google / twitter sources and is never used"},"recommendedFor":["WeChat discovery, author work lists and media text"],"notFor":["assuming zero-config for every platform","private or logged-in sources (use their own CLI)"],"provider":"omnireach","platform":"omnireach"},
|
|
51
52
|
{"id":"opencli-tieba","label":"OpenCLI Tieba (贴吧)","kind":"cli","operations":["search","read"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"rank":70,"invoke":"dsh-browser: browser_opencli_catalog, then browser_opencli_run tieba","install":"Bundled with the dsh-browser plugin; needs its browser bridge and, for most sites, a logged-in session (browser_opencli_catalog lists the real commands).","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI/blob/main/docs/adapters/index.md","verification":{"status":"unverified","note":"commands from the OpenCLI adapter index (2026-09-30 research); verify against the installed version"},"recommendedFor":["commands: search, read"],"notFor":[]},
|
|
52
53
|
{"id":"opencli-hupu","label":"OpenCLI Hupu (虎扑)","kind":"cli","operations":["search","read"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"rank":70,"invoke":"dsh-browser: browser_opencli_catalog, then browser_opencli_run hupu","install":"Bundled with the dsh-browser plugin; needs its browser bridge and, for most sites, a logged-in session (browser_opencli_catalog lists the real commands).","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI/blob/main/docs/adapters/index.md","verification":{"status":"unverified","note":"commands from the OpenCLI adapter index (2026-09-30 research); verify against the installed version"},"recommendedFor":["commands: search, detail"],"notFor":[]},
|
|
53
54
|
{"id":"opencli-zhihu","label":"OpenCLI Zhihu (知乎)","kind":"cli","operations":["search","read","comments"],"languages":["zh"],"regions":["cn"],"profiles":["experience","general"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"rank":70,"invoke":"dsh-browser: browser_opencli_catalog, then browser_opencli_run zhihu","install":"Bundled with the dsh-browser plugin; needs its browser bridge and, for most sites, a logged-in session (browser_opencli_catalog lists the real commands).","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI/blob/main/docs/adapters/index.md","verification":{"status":"unverified","note":"commands from the OpenCLI adapter index (2026-09-30 research); verify against the installed version"},"recommendedFor":["commands: search, question, answer-detail, answer-comments"],"notFor":[]},
|
|
@@ -70,12 +71,13 @@
|
|
|
70
71
|
{"id":"opencli-toutiao","label":"OpenCLI Toutiao (头条)","kind":"cli","operations":["read","trending"],"languages":["zh"],"regions":["cn"],"profiles":["news_fact"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"rank":70,"invoke":"dsh-browser: browser_opencli_catalog, then browser_opencli_run toutiao","install":"Bundled with the dsh-browser plugin; needs its browser bridge and, for most sites, a logged-in session (browser_opencli_catalog lists the real commands).","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI/blob/main/docs/adapters/index.md","verification":{"status":"unverified","note":"commands from the OpenCLI adapter index (2026-09-30 research); verify against the installed version"},"recommendedFor":["commands: articles, hot, recommend (no `search`)"],"notFor":["keyword search: no `search` command listed"]},
|
|
71
72
|
{"id":"opencli-v2ex","label":"OpenCLI V2EX (OpenCLI)","kind":"cli","operations":["read","trending"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["forum"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"rank":70,"invoke":"dsh-browser: browser_opencli_catalog, then browser_opencli_run v2ex","install":"Bundled with the dsh-browser plugin; needs its browser bridge and, for most sites, a logged-in session (browser_opencli_catalog lists the real commands).","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI/blob/main/docs/adapters/index.md","verification":{"status":"unverified","note":"commands from the OpenCLI adapter index (2026-09-30 research); verify against the installed version"},"recommendedFor":["commands: hot, latest, topic (no `search`)"],"notFor":["keyword search through OpenCLI: use the built-in v2ex engine"]},
|
|
72
73
|
{"id":"opencli-quark","label":"OpenCLI Quark (夸克)","kind":"cli","operations":["read"],"languages":["zh"],"regions":["cn"],"profiles":[],"resultKinds":["files"],"auth":"login","costTier":"free-quota","requires":{"browser":true},"rank":70,"invoke":"dsh-browser: browser_opencli_catalog, then browser_opencli_run quark","install":"Bundled with the dsh-browser plugin; needs its browser bridge and, for most sites, a logged-in session (browser_opencli_catalog lists the real commands).","license":"Apache-2.0 (OpenCLI)","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI/blob/main/docs/adapters/index.md","verification":{"status":"unverified","note":"commands from the OpenCLI adapter index (2026-09-30 research); verify against the installed version"},"recommendedFor":["commands: cloud-drive operations"],"notFor":["web or content search: a cloud-drive adapter"]},
|
|
73
|
-
{"id":"wechat","label":"WeChat official accounts (公众号): OmniReach, wx-search-cli","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"anonymous","costTier":"anonymous","provider":"wechat","platform":"wechat","rank":70,"install":"Default chain: omnireach (uv tool install from Daily-AC/omnireach; `--on wechat`, Sogou, no key), then wx-search-cli (npm i -g wx-search-cli).","license":"MIT (OmniReach, wx-search-cli)","cost":"free; Sogou rate limits and captchas apply","url":"https://github.com/Daily-AC/omnireach","verification":{"status":"verified","date":"2026-10-
|
|
74
|
-
{"id":"xhs","label":"xhs (xiaohongshu-cli)","kind":"cli","operations":["search","read","comments"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"cli":"xhs"},"rank":60,"install":"uv tool install xiaohongshu-cli; run `xhs login` yourself (it reads your browser cookies). The plugin only runs `xhs search` and only with a saved login.","license":"see the upstream repository","cost":"free (your account)","url":"https://github.com/jackwener/xiaohongshu-cli","verification":{"status":"unverified","date":"2026-10-06","version":"0.6.4","note":"contract-only: help probed; output shape from the installed source; no search run"},"recommendedFor":["Chinese lifestyle and product experience notes"],"notFor":["write commands (post, like, comment, follow) are never run","use without a saved login"],"invoke":"search.run platform=xiaohongshu (
|
|
75
|
-
{"id":"
|
|
76
|
-
{"id":"
|
|
77
|
-
{"id":"
|
|
78
|
-
{"id":"
|
|
74
|
+
{"id":"wechat","label":"WeChat official accounts (公众号): OmniReach, wx-search-cli","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"anonymous","costTier":"anonymous","provider":"wechat","platform":"wechat","rank":70,"install":"Default chain: omnireach (uv tool install from Daily-AC/omnireach; `--on wechat`, Sogou, no key), then wx-search-cli (npm i -g wx-search-cli).","license":"MIT (OmniReach, wx-search-cli)","cost":"free; Sogou rate limits and captchas apply","url":"https://github.com/Daily-AC/omnireach","verification":{"status":"verified","date":"2026-10-26","version":"0.19.0-alpha","note":"omnireach search --on wechat --json and wx-search-cli search both returned parsed WeChat articles (re-run 2026-10-26)"},"recommendedFor":["WeChat official-account articles on Chinese policy, industry and product topics"],"notFor":["stable unattended use: Sogou captchas make real_url empty","non-WeChat sources"]},
|
|
75
|
+
{"id":"xhs","label":"xhs (xiaohongshu-cli)","kind":"cli","operations":["search","read","comments"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"cli":"xhs"},"rank":60,"install":"uv tool install xiaohongshu-cli; run `xhs login` yourself (it reads your browser cookies). The plugin only runs `xhs search` and only with a saved login.","license":"see the upstream repository","cost":"free (your account)","url":"https://github.com/jackwener/xiaohongshu-cli","verification":{"status":"unverified","date":"2026-10-06","version":"0.6.4","note":"contract-only: help probed; output shape from the installed source; no search run"},"recommendedFor":["Chinese lifestyle and product experience notes"],"notFor":["write commands (post, like, comment, follow) are never run","use without a saved login"],"invoke":"search.run platform=xiaohongshu (the optional fallback of its chain, after the standalone OpenCLI; set it first in platformBackends to prefer it)"},
|
|
76
|
+
{"id":"twitter-cli","label":"twitter-cli (PyPI twitter-cli)","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["experience","news_fact"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"cli":"twitter"},"rank":60,"install":"uv tool install twitter-cli (the command is `twitter`); set TWITTER_AUTH_TOKEN and TWITTER_CT0 in DSH credentials or the Host process environment. The plugin only runs `twitter search --json`.","url":"https://github.com/jackwener/twitter-cli","verification":{"status":"unverified","date":"2026-10-11","version":"0.8.5","note":"contract-only: help probed, --json envelope read from its source and issue #38; no search run by us (needs your tokens)"},"recommendedFor":["live reactions and announcements by accounts"],"notFor":["write commands (post, like, retweet, follow) are never run","use without both tokens","a different program named twitter on PATH"],"invoke":"search.run platform=twitter (the optional fallback of its chain, after the standalone OpenCLI; set it first in platformBackends to prefer it)","keyEnv":["TWITTER_AUTH_TOKEN","TWITTER_CT0"],"license":"see the upstream repository","cost":"free (your account)"},
|
|
77
|
+
{"id":"zhihu-cli","label":"zhihu-cli (pyzhihu-cli)","kind":"cli","operations":["search","read"],"languages":["zh"],"regions":["cn"],"profiles":["experience","compare"],"resultKinds":["qa"],"auth":"login","costTier":"free-quota","requires":{"cli":"zhihu"},"rank":60,"install":"uv tool install pyzhihu-cli (the command is `zhihu`); run `zhihu login` yourself. Not the Access-Secret zhihu-cli of dawnswwwww.","license":"see the upstream repository","cost":"free (your account)","url":"https://github.com/BAIGUANGMEI/zhihu-cli","verification":{"status":"unverified","date":"2026-10-06","version":"0.2.4","note":"contract-only: help probed; output shape from the installed source; no search run"},"recommendedFor":["Chinese Q&A and long-form answers"],"notFor":["publishing commands (ask, article, pin, vote) are never run","use without a saved login"],"invoke":"search.run platform=zhihu (the optional fallback of its chain, after the standalone OpenCLI; set it first in platformBackends to prefer it)"},
|
|
78
|
+
{"id":"rdt","label":"rdt (rdt-cli)","kind":"cli","operations":["search","read"],"languages":["en"],"regions":["global"],"profiles":["experience"],"resultKinds":["social"],"auth":"login","costTier":"free-quota","requires":{"cli":"rdt"},"rank":60,"install":"uv tool install git+https://github.com/public-clis/rdt-cli; run `rdt login` yourself (it extracts browser cookies). The plugin only runs `rdt search` and only with a saved login.","license":"see the upstream repository","cost":"free (your account)","verification":{"status":"unverified","date":"2026-10-06","version":"0.4.2","note":"contract-only: help probed; --compact --json shape from the installed source; no search run"},"recommendedFor":["English community experience threads"],"notFor":["write commands (comment, upvote, save, subscribe) are never run","use without a saved login"],"invoke":"search.run platform=reddit (the optional fallback of its chain, after the standalone OpenCLI; set it first in platformBackends to prefer it)"},
|
|
79
|
+
{"id":"opencli","label":"OpenCLI (standalone)","kind":"cli","operations":["search"],"languages":["*"],"regions":["global","cn"],"profiles":["experience","general"],"resultKinds":["social","web"],"auth":"login","costTier":"free-quota","requires":{"cli":"opencli"},"rank":65,"install":"npm i -g @jackwener/opencli + its Browser Bridge extension in your own Chrome. It uses that Chrome's login: log in to the sites there yourself, the plugin never logs in. First backend of the xiaohongshu, reddit, twitter and zhihu chains.","license":"Apache-2.0","cost":"free (your account)","url":"https://github.com/jackwener/OpenCLI","verification":{"status":"unverified","date":"2026-10-27","version":"1.8.8","note":"twitter and zhihu searches run and parsed (live fixtures); xiaohongshu answered AUTH_REQUIRED, reddit an HTML page (both mapped): those two mappings are contract-only"},"recommendedFor":["sites the table lists with a read search command: xiaohongshu, reddit, twitter, zhihu, weixin, hackernews, ..."],"notFor":["sites without a search command (douyin, v2ex, xiaoyuzhou, toutiao)","write commands (login, post, like, ...) are never run"]},
|
|
80
|
+
{"id":"gh","label":"GitHub CLI (gh)","kind":"cli","operations":["search"],"languages":["*"],"regions":["global"],"profiles":["docs_code","compare"],"resultKinds":["code"],"auth":"login","costTier":"free-quota","requires":{"cli":"gh"},"rank":55,"install":"brew install gh (or winget install GitHub.cli); run `gh auth login` yourself. Fallback backend of github, github-issues and github-code.","license":"MIT","cost":"free within GitHub API limits","url":"https://cli.github.com","verification":{"status":"verified","date":"2026-10-26","version":"2.101.0","note":"gh search repos, issues and code run live (zh / en / qualifier / empty) and parsed; the query is passed as separate words because gh quotes a one-token query as an exact phrase"},"recommendedFor":["repositories, issues and code with your own GitHub login"],"notFor":["use without gh auth login"],"invoke":"search.run platform=github (a backend of its chain; set it first in platformBackends to prefer it)"},
|
|
79
81
|
{"id":"tanso","label":"Tanso (Bocha / Zhihu API CLI)","kind":"cli","operations":["search"],"languages":["zh"],"regions":["cn"],"profiles":["news_fact","general"],"resultKinds":["web"],"auth":"key","costTier":"paid","keyEnv":["BOCHA_API_KEY","ZHIHU_ACCESS_SECRET"],"requires":{"cli":"tanso"},"provider":"tanso","platform":"tanso","rank":80,"install":"npm i -g @geekjourneyx/tanso, then `tanso config init` and put your own keys in its config. search.run platform=tanso runs only the bocha_web and zhihu_search sources.","license":"MIT","cost":"paid: your own Bocha / Zhihu keys, billed by those providers (no free allowance confirmed for this route)","url":"https://github.com/geekjourneyx/tanso","verification":{"status":"unverified","date":"2026-10-06","version":"2.0.2","note":"docs-only: contract from the upstream README; not installed or run"},"recommendedFor":["an API-contract reference for Bocha and Zhihu from the command line"],"notFor":["use instead of the built-in Bocha provider when you only need Bocha","the Volcengine answer source (never selected)"]},
|
|
80
82
|
{"id":"douyin-cli","label":"douyin-cli (tamnd)","kind":"cli","operations":["search","trending"],"languages":["zh"],"regions":["cn"],"profiles":["experience"],"resultKinds":["video"],"auth":"anonymous","costTier":"anonymous","requires":{"cli":"douyin"},"rank":90,"install":"brew install tamnd/tap/douyin or go install github.com/tamnd/douyin-cli/cmd/douyin@latest. Catalog only: no adapter, because the README does not document the search record fields.","license":"Apache-2.0","cost":"free","url":"https://github.com/tamnd/douyin-cli","verification":{"status":"unverified","date":"2026-10-06","version":"0.1.1","note":"docs-only: README read; output record fields undocumented, so no adapter spec was written"},"recommendedFor":["the open hot-search board (douyin hot)"],"notFor":["search from a datacenter or non-China IP: the README says it exits with code 4 behind the anti-bot wall","assuming a stable login-free search"]}
|
|
81
83
|
]
|
package/lib/actions/approval.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* present. Without it the mode is unknown and the strictest ordinary rule (`standard`: ask) applies.
|
|
9
9
|
* @module web-search-pro/actions/approval
|
|
10
10
|
*/
|
|
11
|
+
import { preflightArgs } from "./schema.js";
|
|
11
12
|
import { CALL_TOOL, INDEX_TOOL, findAction, findActionByFlatTool } from "./registry.js";
|
|
12
13
|
export const AUTOMATION_MODES = ['read-only', 'standard', 'autonomous', 'unrestricted'];
|
|
13
14
|
/** Maps a model-visible tool call to the action it will run; undefined for tools that are not ours. */
|
|
@@ -26,7 +27,7 @@ const clip = (text, max = 80) => text.length > max ? text.slice(0, max) + '…'
|
|
|
26
27
|
function describe(action, args) {
|
|
27
28
|
const input = (args && typeof args === 'object' ? args : {});
|
|
28
29
|
const parts = [];
|
|
29
|
-
for (const key of ['backend', 'installer', 'hostname', 'id', 'engine', 'olderThanDays']) {
|
|
30
|
+
for (const key of ['backend', 'installer', 'hostname', 'id', 'engine', 'olderThanDays', 'platform', 'scope']) {
|
|
30
31
|
if (input[key] !== undefined)
|
|
31
32
|
parts.push(`${key}=${clip(String(input[key]))}`);
|
|
32
33
|
}
|
|
@@ -34,6 +35,23 @@ function describe(action, args) {
|
|
|
34
35
|
parts.push(`rulesJson (${input.rulesJson.length} chars)`);
|
|
35
36
|
return parts.length ? `${action} ${parts.join(' ')}` : action;
|
|
36
37
|
}
|
|
38
|
+
/** The command and argument templates of a custom CLI spec, for the prompt the user answers: what the plugin would be allowed to run. */
|
|
39
|
+
export function describeCliSpec(spec) {
|
|
40
|
+
const input = (spec && typeof spec === 'object' ? spec : {});
|
|
41
|
+
const tokens = (value) => (Array.isArray(value) ? value.filter((token) => typeof token === 'string') : []).join(' ');
|
|
42
|
+
const search = input.search && typeof input.search === 'object' ? input.search : {};
|
|
43
|
+
const bins = Array.isArray(input.bins) ? input.bins.filter((bin) => typeof bin === 'string') : [];
|
|
44
|
+
const probe = input.probe && typeof input.probe === 'object' ? input.probe : {};
|
|
45
|
+
const env = input.env && typeof input.env === 'object' ? input.env : {};
|
|
46
|
+
const names = [...Array.isArray(env.required) ? env.required : [], ...Array.isArray(env.passthrough) ? env.passthrough : []].filter((name) => typeof name === 'string');
|
|
47
|
+
const parts = [
|
|
48
|
+
`command ${bins.join(' or ') || '(none)'}`,
|
|
49
|
+
`search: ${clip(tokens(search.argv), 160)}`,
|
|
50
|
+
`probe: ${clip(tokens(probe.versionArgs), 60)} ; ${clip(tokens(probe.helpArgs), 60)}`,
|
|
51
|
+
...names.length ? [`reads environment variables ${clip(names.join(', '), 100)}`] : [],
|
|
52
|
+
];
|
|
53
|
+
return parts.join('; ');
|
|
54
|
+
}
|
|
37
55
|
export function webPolicyDecision(actionName, args, mode) {
|
|
38
56
|
const action = findAction(actionName);
|
|
39
57
|
if (!action || action.approval === 'none')
|
|
@@ -46,6 +64,18 @@ export function webPolicyDecision(actionName, args, mode) {
|
|
|
46
64
|
return { kind: 'allow' };
|
|
47
65
|
return { kind: 'ask', reason: `${label}: Install an external Web Search Pro backend dependency` };
|
|
48
66
|
}
|
|
67
|
+
if (action.approval === 'run-program') {
|
|
68
|
+
// Whoever the automation mode trusts, a new program is the user's decision: asked in every mode but read-only, which refuses.
|
|
69
|
+
if (mode === 'read-only')
|
|
70
|
+
return { kind: 'deny', reason: `Adding a custom CLI is disabled by automationMode=${mode}` };
|
|
71
|
+
const input = (args && typeof args === 'object' ? args : {});
|
|
72
|
+
return { kind: 'ask', reason: `${label}: Let Web Search Pro run a local program as a search source — ${describeCliSpec(input.spec)}` };
|
|
73
|
+
}
|
|
74
|
+
if (action.approval === 'config') {
|
|
75
|
+
if (mode === 'read-only')
|
|
76
|
+
return { kind: 'deny', reason: `Changing the Web Search Pro search order is disabled by automationMode=${mode}` };
|
|
77
|
+
return { kind: 'allow' };
|
|
78
|
+
}
|
|
49
79
|
// local-write
|
|
50
80
|
if (mode === 'read-only')
|
|
51
81
|
return { kind: 'deny', reason: `Web Search Pro mutations are disabled by automationMode=${mode}` };
|
|
@@ -53,6 +83,25 @@ export function webPolicyDecision(actionName, args, mode) {
|
|
|
53
83
|
return { kind: 'allow' };
|
|
54
84
|
return { kind: 'ask', reason: `${label}: Modify Web Search Pro local state (cache, history or extraction rules)` };
|
|
55
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* What the `tools/pre-execute` hook decides for a resolved call: {@link webPolicyDecision}, except that a call `runAction` will
|
|
88
|
+
* refuse as INVALID_ARGS is let through unasked. Asking the user to approve (or denying) a call that cannot run only withholds the
|
|
89
|
+
* schema from the model (headless: "requires approval, but no approval channel is available"). Letting it through executes
|
|
90
|
+
* nothing, since `runAction` repeats the check (`preflightArgs`) before `execute`. This also holds in read-only mode: nothing
|
|
91
|
+
* runs, so the model gets the INVALID_ARGS reply with the schema rather than a refusal it cannot act on. A valid call is decided
|
|
92
|
+
* exactly as before. A failure of the check itself is not allowed to block the call: the ordinary decision applies.
|
|
93
|
+
*/
|
|
94
|
+
export function webCallDecision(actionName, args, mode) {
|
|
95
|
+
const action = findAction(actionName);
|
|
96
|
+
if (action && action.approval !== 'none') {
|
|
97
|
+
try {
|
|
98
|
+
if (!preflightArgs(action, args).ok)
|
|
99
|
+
return { kind: 'allow' };
|
|
100
|
+
}
|
|
101
|
+
catch { /* decide as for a valid call */ }
|
|
102
|
+
}
|
|
103
|
+
return webPolicyDecision(actionName, args, mode);
|
|
104
|
+
}
|
|
56
105
|
/** The dsh-browser automationMode, when the optional service is present and reports one. */
|
|
57
106
|
export async function automationModeOf(browser) {
|
|
58
107
|
const status = browser?.status;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/actions/approval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEvF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,CAAU,CAAA;AAgBhG,uGAAuG;AACvG,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAgB;IAC/D,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IACrD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAyC,CAAA;QAC7G,OAAO,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAgB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;IACvI,CAAC;IACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAC3C,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACtF,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,GAAG,GAAG,EAAE,EAAU,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;AAEpG,sFAAsF;AACtF,SAAS,QAAQ,CAAC,MAAc,EAAE,IAAa;IAC7C,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAA;IACvF,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/actions/approval.ts"],"names":[],"mappings":"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"}
|