dsh-web-search-pro 0.1.4 → 0.1.6

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.
Files changed (52) hide show
  1. package/LOGIN.md +161 -108
  2. package/README.md +180 -156
  3. package/cordis.patch.yml +12 -12
  4. package/lib/client/SettingsCard.js +17 -0
  5. package/lib/client/SettingsCard.js.map +1 -0
  6. package/lib/client/context-types.js +2 -0
  7. package/lib/client/context-types.js.map +1 -0
  8. package/lib/client/fields.js +25 -0
  9. package/lib/client/fields.js.map +1 -0
  10. package/lib/client/form.js +375 -0
  11. package/lib/client/form.js.map +1 -0
  12. package/lib/client/index.js +22 -0
  13. package/lib/client/index.js.map +1 -0
  14. package/lib/client/locales.js +76 -0
  15. package/lib/client/locales.js.map +1 -0
  16. package/lib/client/styles.js +41 -0
  17. package/lib/client/styles.js.map +1 -0
  18. package/lib/client.js +1077 -0
  19. package/lib/client.js.map +1 -0
  20. package/lib/engines.js +1 -1
  21. package/lib/engines.js.map +1 -1
  22. package/lib/index.js +1 -1
  23. package/lib/index.js.map +1 -1
  24. package/lib/store.js +51 -51
  25. package/lib/types/client/SettingsCard.d.ts +2 -0
  26. package/lib/types/client/context-types.d.ts +8 -0
  27. package/lib/types/client/fields.d.ts +48 -0
  28. package/lib/types/client/form.d.ts +83 -0
  29. package/lib/types/client/index.d.ts +16 -0
  30. package/lib/types/client/locales.d.ts +81 -0
  31. package/lib/types/client/styles.d.ts +41 -0
  32. package/package.json +148 -93
  33. package/scripts/check-client-bundle.mjs +16 -0
  34. package/scripts/clean-lib.mjs +3 -0
  35. package/scripts/save-login.mjs +84 -77
  36. /package/lib/{backend-registry.d.ts → types/backend-registry.d.ts} +0 -0
  37. /package/lib/{browser-service.d.ts → types/browser-service.d.ts} +0 -0
  38. /package/lib/{cache-key.d.ts → types/cache-key.d.ts} +0 -0
  39. /package/lib/{config.d.ts → types/config.d.ts} +0 -0
  40. /package/lib/{deps.d.ts → types/deps.d.ts} +0 -0
  41. /package/lib/{engines.d.ts → types/engines.d.ts} +0 -0
  42. /package/lib/{exa-client.d.ts → types/exa-client.d.ts} +0 -0
  43. /package/lib/{extract.d.ts → types/extract.d.ts} +0 -0
  44. /package/lib/{fetch.d.ts → types/fetch.d.ts} +0 -0
  45. /package/lib/{index.d.ts → types/index.d.ts} +0 -0
  46. /package/lib/{memory-cache.d.ts → types/memory-cache.d.ts} +0 -0
  47. /package/lib/{platform-search.d.ts → types/platform-search.d.ts} +0 -0
  48. /package/lib/{router.d.ts → types/router.d.ts} +0 -0
  49. /package/lib/{safe-http.d.ts → types/safe-http.d.ts} +0 -0
  50. /package/lib/{store.d.ts → types/store.d.ts} +0 -0
  51. /package/lib/{tools.d.ts → types/tools.d.ts} +0 -0
  52. /package/lib/{util.d.ts → types/util.d.ts} +0 -0
package/LOGIN.md CHANGED
@@ -1,108 +1,161 @@
1
- # 中文社区平台登录态(复用你已登录的浏览器)
2
-
3
- 知乎 / 微博 / 豆瓣 / 贴吧 / 抖音 / 快手 / 小红书的搜索页都有反爬与登录墙,
4
- 免登录的公开接口基本都被风控。所以这些平台走 **Playwright 驱动登录态浏览器** 的路径:
5
- 在你已登录的浏览器里打开搜索页、读渲染结果——不需要逆向任何签名。
6
-
7
- ## 方式一:登录一次保存登录态(推荐)
8
-
9
- 运行插件包里的脚本,按提示逐个平台登录一次(扫码/账号密码),
10
- 脚本会把所有 cookies 合并保存成一个 storageState JSON:
11
-
12
- ```bash
13
- cd dsh-web-search-pro
14
- node scripts/save-login.mjs all login-state.json
15
- # 或只登录一个平台:
16
- node scripts/save-login.mjs zhihu login-state.json
17
- ```
18
-
19
- 然后在 dsh-browser 的部署配置中创建命名、按域名授权的 AuthProfile:
20
-
21
- ```yaml
22
- # cordis.yml 中的 dsh-browser 插件行
23
- - id: browser
24
- name: '@anweat/dsh-browser'
25
- config:
26
- authProfiles:
27
- china-community:
28
- storageStatePath: 'D:/secrets/login-state.json'
29
- allowedDomains: [zhihu.com, weibo.com, douban.com, baidu.com, douyin.com, kuaishou.com]
30
- persistState: false
31
-
32
- # $DSH_HOME/settings.yaml
33
- ---
34
- web-search-pro:
35
- browserBindings:
36
- zhihu: { authProfile: china-community }
37
- weibo: { authProfile: china-community }
38
- ```
39
-
40
- > storageState 是 Playwright 的标准登录态文件(cookies + origins),
41
- > 同一份文件可含多个站点登录态,但每个 AuthProfile 必须显式给出 `allowedDomains`;访问其他域名会被拒绝。`persistState` 默认 false,只有明确开启才会原子回写新 Cookie/localStorage。
42
-
43
- ## 方式二:用 Cookie 插件导出
44
-
45
- 如果你更习惯手动导出:
46
-
47
- 1. 在浏览器装 Cookie-Editor(或 EditThisCookie)。
48
- 2. 在目标站点导出 cookies(JSON)。
49
- 3. 组装成 storageState 格式:
50
-
51
- ```json
52
- { "cookies": [ ...导出的 cookies... ], "origins": [] }
53
- ```
54
-
55
- 每个 cookie 至少需要 `name` `value` `domain` `path`(可补 `expires` `httpOnly` `secure`)。
56
-
57
- 不要把 Cookie JSON 作为模型工具参数传入;导入到本地 storageState 文件后只在配置中引用路径。
58
-
59
- ## 受控脚本增强(RulePack V2)
60
-
61
- dsh-browser 可配置命名 RulePack。它支持有界的 `waitFor` / `click` / `scroll` / `wait` 步骤;可选 init script 只能引用本地文件,必须提供 SHA-256,且文件不超过 64KB。RulePack 同样按 `matches` 限域,不接受模型直接提交任意 JavaScript。
62
-
63
- ```yaml
64
- rulePacks:
65
- zhihu-enhanced:
66
- matches: [zhihu.com]
67
- initScriptPath: 'D:/dsh/rules/zhihu-init.js'
68
- initScriptSha256: '<64位sha256>'
69
- steps:
70
- - { type: waitFor, selector: '.SearchResult-Card', timeoutMs: 10000 }
71
- - { type: scroll, deltaY: 1600, repeat: 2, waitMs: 300 }
72
- ```
73
-
74
- ## OpenCLI 社区平台
75
-
76
- Reddit / 小红书 / Twitter / Instagram / Facebook 走 OpenCLI Browser Bridge,使用当前 Chrome 扩展会话,不读取或导出 Cookie。`dsh-browser` 已包含 OpenCLI CLI,但 Chrome 扩展必须已安装并连接:
77
-
78
- ```bash
79
- opencli doctor
80
- opencli reddit search "DeepSeek Harness" -f yaml
81
- ```
82
-
83
- `doctor` 显示 daemon 正常但 extension disconnected,请启动安装了 OpenCLI 扩展的 Chrome profile;不要把 Quark 或禁用扩展的 Playwright 临时 profile 当作替代。只有需要在终端独立诊断时,才需要额外全局安装 `@jackwener/opencli`。
84
-
85
- ## 结果选择器可配置
86
-
87
- 站点改版后如果提取不到结果,不用改代码——在 `settings.yaml` 按平台覆盖选择器:
88
-
89
- ```yaml
90
- web-search-pro:
91
- platformRules:
92
- zhihu:
93
- item: '.SearchResult-Card'
94
- title: '.ContentItem-title'
95
- link: '.ContentItem-title a'
96
- text: '.Highlight'
97
- weibo:
98
- item: '.card-wrap'
99
- title: '.txt'
100
- link: '.from a'
101
- ```
102
-
103
- ## 安全与合规提醒
104
-
105
- - 仅做**单次、低频**的搜索调用,不要批量爬取;遵守目标平台的服务条款与 robots.txt。
106
- - 登录态文件包含你的登录凭据,请勿提交到公开仓库或分享给他人。
107
- - 本能力借鉴 MediaCrawler 的思路(登录态浏览器驱动搜索页),
108
- 但为 MIT 许可的独立实现,未使用其 NON-COMMERCIAL 许可下的签名算法代码。
1
+ # 中文社区平台登录态(复用你已登录的浏览器)
2
+
3
+ 知乎 / 微博 / 豆瓣 / 贴吧 / 抖音 / 快手 / 小红书的搜索页都有反爬与登录墙,
4
+ 免登录的公开接口基本都被风控。所以这些平台走 **Playwright 驱动登录态浏览器** 的路径:
5
+ 在你已登录的浏览器里打开搜索页、读渲染结果——不需要逆向任何签名。
6
+
7
+ ## 方式一:登录一次保存登录态(推荐)
8
+
9
+ 运行插件包里的脚本,按提示逐个平台登录一次(扫码/账号密码),
10
+ 脚本会把所有 cookies 合并保存成一个 storageState JSON:
11
+
12
+ ```bash
13
+ cd dsh-web-search-pro
14
+ node scripts/save-login.mjs all login-state.json
15
+ # 或只登录一个平台:
16
+ node scripts/save-login.mjs zhihu login-state.json
17
+ ```
18
+
19
+ 然后在 dsh-browser 的部署配置中创建命名、按域名授权的 AuthProfile:
20
+
21
+ ```yaml
22
+ # cordis.yml 中的 dsh-browser 插件行
23
+ - id: browser
24
+ name: '@anweat/dsh-browser'
25
+ config:
26
+ automationMode: standard # read-only | standard | autonomous | unrestricted
27
+ authProfiles:
28
+ china-community:
29
+ storageStatePath: 'D:/secrets/login-state.json'
30
+ allowedDomains: [zhihu.com, weibo.com, douban.com, baidu.com, douyin.com, kuaishou.com]
31
+ persistState: false
32
+
33
+ # $DSH_HOME/settings.yaml
34
+ ---
35
+ web-search-pro:
36
+ browserBindings:
37
+ zhihu: { authProfile: china-community }
38
+ weibo: { authProfile: china-community }
39
+ ```
40
+
41
+ > storageState Playwright 的标准登录态文件(cookies + origins),
42
+ > 同一份文件可含多个站点登录态,但每个 AuthProfile 必须显式给出 `allowedDomains`;访问其他域名会被拒绝。`persistState` 默认 false,只有明确开启才会原子回写新 Cookie/localStorage。
43
+ > `scripts/save-login.mjs` 优先复用 `@anweat/dsh-browser` 自带的 Playwright;默认启动其 bundled Chromium。如需显式使用已安装的 Chrome,可临时设置 `DSH_BROWSER_CHANNEL=chrome`。
44
+
45
+ ## 方式二:用 Cookie 插件导出
46
+
47
+ 如果你更习惯手动导出:
48
+
49
+ 1. 在浏览器装 Cookie-Editor(或 EditThisCookie)。
50
+ 2. 在目标站点导出 cookies(JSON)。
51
+ 3. 组装成 storageState 格式:
52
+
53
+ ```json
54
+ { "cookies": [ ...导出的 cookies... ], "origins": [] }
55
+ ```
56
+
57
+ 每个 cookie 至少需要 `name` `value` `domain` `path`(可补 `expires` `httpOnly` `secure`)。
58
+
59
+ 不要把 Cookie JSON 作为模型工具参数传入;导入到本地 storageState 文件后只在配置中引用路径。
60
+
61
+ ## 受控脚本增强(RulePack
62
+
63
+ dsh-browser 可配置命名 RulePack。它适合由部署者长期维护的站点增强,支持有界的 `waitFor` / `click` / `scroll` / `wait` 步骤;可选 init script 只能引用本地文件,必须提供 SHA-256,且文件不超过 64KB。RulePack 同样按 `matches` 限域。
64
+
65
+ ```yaml
66
+ rulePacks:
67
+ zhihu-enhanced:
68
+ matches: [zhihu.com]
69
+ initScriptPath: 'D:/dsh/rules/zhihu-init.js'
70
+ initScriptSha256: '<64位sha256>'
71
+ steps:
72
+ - { type: waitFor, selector: '.SearchResult-Card', timeoutMs: 10000 }
73
+ - { type: scroll, deltaY: 1600, repeat: 2, waitMs: 300 }
74
+ ```
75
+
76
+ ## 模型生成 Recipe
77
+
78
+ 临时、多步骤操作不必先写持久 RulePack。模型可调用 `browser_recipe_run`,每次最多 25 步:
79
+
80
+ ```json
81
+ {
82
+ "url": "https://example.com",
83
+ "steps": [
84
+ { "type": "wait", "condition": "selector", "value": "h1" },
85
+ { "type": "extract", "selector": "h1", "mode": "text" }
86
+ ]
87
+ }
88
+ ```
89
+
90
+ `wait`、`extract`、`assert`、`screenshot` 是只读路径;一旦包含 `click`、`fill`、`type`、`press`、`select`、`check`、`hover` 或 `scroll`,`standard` 会发起一次性审批,`autonomous` / `unrestricted` 直接执行,`read-only` 拒绝。
91
+
92
+ ## 外部模型生成 UserScript
93
+
94
+ 外部模型可以输出油猴格式脚本,但需要走“先验证、后执行”两步:
95
+
96
+ ```text
97
+ browser_script_validate({ url, source })
98
+ browser_userscript_run({ url, source, authProfile? })
99
+ ```
100
+
101
+ ```javascript
102
+ // ==UserScript==
103
+ // @name Read page heading
104
+ // @match https://example.com/*
105
+ // @grant none
106
+ // ==/UserScript==
107
+ return { heading: document.querySelector('h1')?.textContent || '' }
108
+ ```
109
+
110
+ 限制与边界:
111
+
112
+ - 必须声明 HTTP(S) `@match`,`@exclude` 生效;目标 URL 不匹配时拒绝。
113
+ - 只允许 `@grant none`,拒绝 `@require`,源码上限 64KB,输出与运行时间有界。
114
+ - 验证结果包含 SHA-256 和静态能力提示,但能力提示不是安全证明。
115
+ - 脚本运行在目标页主世界,能读写页面并使用该页已有登录态;除 `unrestricted` 外,`browser_userscript_run` 会进入 DSH 原生一次性审批。无审批测试也不要让脚本回传 Cookie、令牌、表单值等秘密。
116
+
117
+ 常见只读任务优先用 `browser_script_catalog` 中的内置 `article-clean`、`links`、`jsonld`、`forms`,无需提交任意脚本。
118
+
119
+ ## OpenCLI 社区平台
120
+
121
+ Reddit / 小红书 / Twitter / Instagram / Facebook 走 OpenCLI Browser Bridge,使用当前 Chrome 扩展会话,不读取或导出 Cookie。`dsh-browser` 已包含 OpenCLI CLI,但 Chrome 扩展必须已安装并连接:
122
+
123
+ ```bash
124
+ opencli doctor
125
+ opencli reddit search "DeepSeek Harness" -f yaml
126
+ opencli browser research open https://example.com --window background
127
+ opencli browser research state
128
+ opencli browser research extract
129
+ opencli browser research close
130
+ ```
131
+
132
+ 每个 `opencli browser` 子命令都必须显式给出 session 名(上例为 `research`),同名会话复用标签页状态。优先使用已有站点 adapter;没有 adapter 时优先 `network` / `extract`,最后再使用 `state` / `find` / `click` / `fill` 等 DOM 操作。
133
+
134
+ 模型内先用 `browser_opencli_status` 检查 daemon、扩展和 profile;高级调用使用 `browser_opencli_run({ args: [...] })`。argv 示例:`["browser", "research", "state"]`。这个通用入口可能触发发帖、删除等站点 adapter,所以除隔离测试用的 `unrestricted` 外都要求一次性审批。
135
+
136
+ 若 `doctor` 显示 daemon 正常但 extension disconnected,请显式启动安装了 OpenCLI Browser Bridge 的 Chrome;不要把 Quark 或禁用扩展的 Playwright 临时 profile 当作替代。只有需要在终端独立诊断时,才需要额外全局安装 `@jackwener/opencli`。
137
+
138
+ ## 结果选择器可配置
139
+
140
+ 站点改版后如果提取不到结果,不用改代码——在 `settings.yaml` 按平台覆盖选择器:
141
+
142
+ ```yaml
143
+ web-search-pro:
144
+ platformRules:
145
+ zhihu:
146
+ item: '.SearchResult-Card'
147
+ title: '.ContentItem-title'
148
+ link: '.ContentItem-title a'
149
+ text: '.Highlight'
150
+ weibo:
151
+ item: '.card-wrap'
152
+ title: '.txt'
153
+ link: '.from a'
154
+ ```
155
+
156
+ ## 安全与合规提醒
157
+
158
+ - 仅做**单次、低频**的搜索调用,不要批量爬取;遵守目标平台的服务条款与 robots.txt。
159
+ - 登录态文件包含你的登录凭据,请勿提交到公开仓库或分享给他人。
160
+ - 本能力借鉴 MediaCrawler 的思路(登录态浏览器驱动搜索页),
161
+ 但为 MIT 许可的独立实现,未使用其 NON-COMMERCIAL 许可下的签名算法代码。
package/README.md CHANGED
@@ -1,156 +1,180 @@
1
- # dsh-web-search-pro
2
-
3
- 增强型、可持久化的扩展网页搜索插件 for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)。
4
-
5
- 一个 DSH **bundle 插件**,把多引擎网页搜索、平台搜索、持久化缓存、受控按站增强和 Playwright 渲染打包成模型可直接调用的 11 个工具。路由控制面借鉴 Agent-Reach 的后端探测、顺序选择和失败冷却思路,核心逻辑为本项目原生 TypeScript 实现。
6
-
7
- ## 安装
8
-
9
- ```bash
10
- dsh plugin --profile web add dsh-web-search-pro # 自动装 dsh-browser(dependency)+ 自动挂载 browser 行(本 patch)
11
- # 或本地目录 / tarball:
12
- dsh plugin --profile web add ./dsh-web-search-pro
13
- # 重启(web profile 关闭了 HMR):
14
- dsh --profile web
15
- ```
16
-
17
- > npm 安装会解析 `@anweat/dsh-browser`;本地联调可用 `dsh plugin --profile web add ../dsh-browser ../dsh-web-search-pro` 一条命令显式列两个。
18
- > 依赖 `@deepseek-ai/*` 已发布到 npm(`^0.1.0-rc.6`,与社区 dsh-cc-tui 一致)。
19
- > 若你的 harness 是本地源码 checkout(如 `0.1.0-rc.5`),版本号可能有出入——用
20
- > `dsh plugin --profile web add ./<path>` 并在 profile 的 `pnpm-workspace.yaml`
21
- > 里对齐版本后重装即可。
22
-
23
- ## 快速使用与适用情形
24
-
25
- 安装并重启后,直接在 DSH 会话里要求模型调用工具即可:
26
-
27
- ```text
28
- 请调用 web_backend_status 检查后端,然后用 web_search_pro 搜索
29
- "DeepSeek Harness community feedback",指定 exa、fresh=true、返回 8 条来源。
30
- ```
31
-
32
- | 情形 | 推荐入口 | 说明 |
33
- |---|---|---|
34
- | 日常网页搜索 | `web_search_pro` | 默认按配置顺序回退;需要强制刷新时传 `fresh=true` |
35
- | 语义研究、社区观点 | `web_search_pro` + `exa` | 有 API Key 时走原生 Exa API;只有 Exa MCP 连接时自动经 `mcporter` 回退 |
36
- | 已知 URL 的批量正文 | `web_exa_contents` | 直接调用 Exa `/contents`,必须配置 `EXA_API_KEY` |
37
- | GitHub/B站/Reddit 等平台 | `web_platform_search` | Reddit 等 OpenCLI 平台需要 Chrome 扩展在线;中文受限站点使用 AuthProfile |
38
- | 登录后页面或私有论坛 | `browserBindings` + AuthProfile | Cookie 保存在本地 storageState,按域名授权,默认只读 |
39
- | 页面改版、懒加载 | `platformRules` 或 RulePack | 优先改选择器;需要等待/点击/滚动时再使用有界 RulePack |
40
-
41
- 先运行 `web_backend_status` 判断后端是否 ready。指定单一引擎时失败会原样返回;不指定时才会按 `engines` 顺序自动回退。
42
-
43
- ## 工具(11 个)
44
-
45
- | 工具 | 作用 |
46
- |---|---|
47
- | `web_search_pro` | 多引擎搜索 + RRF 融合 + 内存/SQLite 双层缓存 + 历史 |
48
- | `web_exa_contents` | 原生 Exa `/contents` 批量正文抓取(1-100 URL) |
49
- | `web_fetch_pro` | 可读化抓取(Jina → HTTP+规则抽取 → Playwright 兜底)+ 快照缓存 |
50
- | `web_platform_search` | 20 平台:GitHub/B站/YouTube/V2EX/小红书/Twitter/Reddit/IG/FB/RSS + 知乎/微博/豆瓣/贴吧/抖音/快手(Playwright 登录态) |
51
- | `web_snapshot` | Playwright 全页截图 + HTML + 文本落盘 |
52
- | `web_history` / `web_cache_clear` / `web_search_stats` | 持久历史 / 清缓存 / 存储统计 |
53
- | `web_rule` | 持久化按站提取规则(脚本猫式,list/upsert/remove) |
54
- | `web_backend_status` | 无副作用后端探测、失败/冷却诊断与 CLI 状态 |
55
- | `web_deps` | 检测/安装外部依赖(gh/bili/yt-dlp/opencli/agent-reach/mcporter/playwright) |
56
-
57
- ## 配置
58
-
59
- 三层,越靠前越日常:
60
-
61
- 1. **`$DSH_HOME/settings.yaml` → `web-search-pro:` 段**(热重载,改完即生效):
62
-
63
- ```yaml
64
- web-search-pro:
65
- exaApiKeyEnv: EXA_API_KEY # 推荐:运行环境或凭据服务,不把密钥写入配置
66
- jinaApiKeyEnv: JINA_API_KEY
67
- engines: [ddg, bing, exa, seam, jina]
68
- parallelEngines: false
69
- ttlSeconds: 3600
70
- searchMaxResults: 8
71
- browserBindings:
72
- zhihu:
73
- authProfile: china-community
74
- rulePack: zhihu-enhanced
75
- ```
76
-
77
- 2. **cordis.yml `config:`**(部署级默认值,见 `cordis.patch.yml`)。
78
- 3. **环境变量 / 凭据**:`$EXA_API_KEY`、`$JINA_API_KEY`(`exaApiKeyEnv`/`jinaApiKeyEnv` 引用)。
79
-
80
- ## 外部依赖(按需)
81
-
82
- 多数后端需要系统额外安装的工具;插件提供 `web_deps` 工具检测与安装:
83
-
84
- | 依赖 | 用途 | 安装 |
85
- |---|---|---|
86
- | bili-cli | B站后端 | `uv tool install bili-cli` / `pipx install bili-cli` |
87
- | yt-dlp | YouTube 后端 | `uv tool install yt-dlp` / `pip install yt-dlp` |
88
- | opencli | 小红书/Twitter/Reddit/IG/FB | 由 dsh-browser 内置;扩展未连接时用 `opencli doctor` 诊断 |
89
- | agent-reach | agent-reach 后端 | `uv tool install agent-reach` / `pip install agent-reach` |
90
- | mcporter | 无裸 API Key 时的 Exa MCP 回退 | `npm i -g mcporter` |
91
- | playwright | 渲染/截图后端 | 由 dsh-browser 内置;缺 Chromium 时调用 `browser_install` |
92
-
93
- ## 平台与引擎
94
-
95
- `seam`(ctx.web/DeepSeek 原生)· `exa` · `ddg` · `bing` · `jina` · `github`(REST 搜索 API,免 CLI;可选 `$GITHUB_TOKEN`/`githubToken` 提升限额并解锁代码搜索)· `bilibili` · `v2ex` · `youtube`。默认顺序 `ddg, bing, exa, seam, jina`(免费优先),失败自动回退;失败后短时冷却,`web_backend_status` 可查看原因;`multi` 并行融合。
96
-
97
- Exa 优先使用原生 API 客户端:`web_search_pro` 可传 `exaType`、域名包含/排除、发布时间范围和 category。若没有裸 API Key、但启用了 CLI 后端且 Exa MCP 已连接,搜索会自动通过 `mcporter` 完成;该兼容路径只支持 query + 结果数,高级筛选和 `web_exa_contents` 仍要求 `EXA_API_KEY`。不同选项、结果数、引擎顺序和单/多引擎模式使用不同缓存指纹。
98
-
99
- ## 开发
100
-
101
- ```bash
102
- pnpm install
103
- pnpm test
104
- pnpm build # tsc src → lib
105
- ```
106
-
107
- 源码在 `src/`;`lib/` 为发布产物(已提交)。
108
-
109
- ## License
110
-
111
- MIT
112
-
113
-
114
- ## 中文社区平台登录态
115
-
116
- zhihu / weibo / douban / tieba / douyin / kuaishou 的免登录公开接口都被风控,
117
- 所以走 **Playwright 驱动登录态浏览器**(借鉴 MediaCrawler 思路、MIT 独立实现,未用其签名算法):
118
-
119
- 1. 登录一次保存登录态:`node scripts/save-login.mjs all login-state.json`
120
- 2. 在 dsh-browser 配置中声明按域名隔离的 `authProfiles`
121
- 3. `browserBindings` 把平台绑定到 profile;站点改版时用 `platformRules` dsh-browser `rulePacks`
122
-
123
- 详见 [LOGIN.md](./LOGIN.md)。
124
-
125
-
126
- ## 历史管理
127
-
128
- web_history 支持:kind/query/engine/platform 过滤、replay(用 queryId 回放已存结果)、
129
- export(把过滤后的历史+结果写成 JSON 文件)。
130
-
131
- ## 自定义平台
132
-
133
- settings.yaml 里定义任意站点(URL 模板 + 结果选择器),
134
- web_platform_search 就能直接搜它——不需要改代码:
135
-
136
- web-search-pro:
137
- customPlatforms:
138
- mybili:
139
- name: '我的B站'
140
- url: 'https://search.bilibili.com/all?keyword={query}'
141
- item: '.bili-video-card'
142
- title: '.bili-video-card__info--tit'
143
- link: 'a'
144
- # 需要登录时优先通过 browserBindings 绑定命名 authProfile。
145
- myforum:
146
- name: '某论坛'
147
- url: 'https://forum.example.com/search?q={query}'
148
- item: '.thread'
149
- title: '.thread-title a'
150
- link: '.thread-title a'
151
- browserBindings:
152
- myforum:
153
- authProfile: forum
154
-
155
- 旧版 `customPlatforms.*.cookie` 仍兼容,但会让 Cookie 明文进入配置;新配置应使用 dsh-browser 的命名 AuthProfile,状态文件不要提交到仓库。
156
-
1
+ # dsh-web-search-pro
2
+
3
+ 增强型、可持久化的扩展网页搜索插件 for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)。
4
+
5
+ 一个 DSH **bundle 插件**,把多引擎网页搜索、平台搜索、持久化缓存、受控按站增强和 Playwright 渲染打包成模型可直接调用的 11 个工具。路由控制面借鉴 Agent-Reach 的后端探测、顺序选择和失败冷却思路,核心逻辑为本项目原生 TypeScript 实现。
6
+
7
+ ## 安装
8
+
9
+ ```bash
10
+ dsh plugin --profile web add dsh-web-search-pro # 自动装 dsh-browser(dependency)+ 自动挂载 browser 行(本 patch)
11
+ # 或本地目录 / tarball:
12
+ dsh plugin --profile web add ./dsh-web-search-pro
13
+ # 重启(web profile 关闭了 HMR):
14
+ dsh --profile web
15
+ ```
16
+
17
+ > npm 安装会解析 `@anweat/dsh-browser`;本地联调可用 `dsh plugin --profile web add ../dsh-browser ../dsh-web-search-pro` 一条命令显式列两个。
18
+ > 依赖 `@deepseek-ai/*` 已发布到 npm(`^0.1.0-rc.6`,与社区 dsh-cc-tui 一致)。
19
+ > 若你的 harness 是本地源码 checkout(如 `0.1.0-rc.5`),版本号可能有出入——用
20
+ > `dsh plugin --profile web add ./<path>` 并在 profile 的 `pnpm-workspace.yaml`
21
+ > 里对齐版本后重装即可。
22
+
23
+ ## 快速使用与适用情形
24
+
25
+ 安装并重启后,直接在 DSH 会话里要求模型调用工具即可:
26
+
27
+ ```text
28
+ 请调用 web_backend_status 检查后端,然后用 web_search_pro 搜索
29
+ "DeepSeek Harness community feedback",指定 exa、fresh=true、返回 8 条来源。
30
+ ```
31
+
32
+ | 情形 | 推荐入口 | 说明 |
33
+ |---|---|---|
34
+ | 日常网页搜索 | `web_search_pro` | 默认按配置顺序回退;需要强制刷新时传 `fresh=true` |
35
+ | 语义研究、社区观点 | `web_search_pro` + `exa` | 有 API Key 时走原生 Exa API;只有 Exa MCP 连接时自动经 `mcporter` 回退 |
36
+ | 已知 URL 的批量正文 | `web_exa_contents` | 直接调用 Exa `/contents`,必须配置 `EXA_API_KEY` |
37
+ | GitHub/B站/Reddit 等平台 | `web_platform_search` | Reddit 等 OpenCLI 平台需要 Chrome 扩展在线;中文受限站点使用 AuthProfile |
38
+ | 登录后页面或私有论坛 | `browserBindings` + AuthProfile | Cookie 保存在本地 storageState,按域名授权,默认只读 |
39
+ | 页面改版、懒加载 | `platformRules` 或 RulePack | 优先改选择器;需要等待/点击/滚动时再使用有界 RulePack |
40
+ | 模型生成多步页面操作 | `browser_recipe_run` | 只读步骤直接运行;页面交互按 dsh-browser 的 `automationMode` 决定拒绝/审批/直通 |
41
+ | 外部模型生成油猴脚本 | `browser_script_validate` `browser_userscript_run` | 强制 `@match`、`@grant none`、禁用 `@require`;仅 `unrestricted` 跳过审批 |
42
+ | OpenCLI 站点适配器或浏览器桥 | `browser_opencli_status` / `browser_opencli_run` | 明确使用 Chrome;仅 `unrestricted` 跳过通用 argv 审批 |
43
+
44
+ 先运行 `web_backend_status` 判断后端是否 ready。指定单一引擎时失败会原样返回;不指定时才会按 `engines` 顺序自动回退。
45
+
46
+ ## 工具(11 个)
47
+
48
+ | 工具 | 作用 |
49
+ |---|---|
50
+ | `web_search_pro` | 多引擎搜索 + RRF 融合 + 内存/SQLite 双层缓存 + 历史 |
51
+ | `web_exa_contents` | 原生 Exa `/contents` 批量正文抓取(1-100 URL) |
52
+ | `web_fetch_pro` | 可读化抓取(Jina HTTP+规则抽取 Playwright 兜底)+ 快照缓存 |
53
+ | `web_platform_search` | 20 平台:GitHub/B站/YouTube/V2EX/小红书/Twitter/Reddit/IG/FB/RSS + 知乎/微博/豆瓣/贴吧/抖音/快手(Playwright 登录态) |
54
+ | `web_snapshot` | Playwright 全页截图 + HTML + 文本落盘 |
55
+ | `web_history` / `web_cache_clear` / `web_search_stats` | 持久历史 / 清缓存 / 存储统计 |
56
+ | `web_rule` | 持久化按站提取规则(脚本猫式,list/upsert/remove) |
57
+ | `web_backend_status` | 无副作用后端探测、失败/冷却诊断与 CLI 状态 |
58
+ | `web_deps` | 检测/安装搜索后端的外部依赖(gh/bili/yt-dlp/agent-reach/mcporter);浏览器依赖由 dsh-browser 管理 |
59
+
60
+ ## 浏览器脚本与自动化分层
61
+
62
+ `dsh-browser >= 0.1.7` 提供三类脚本入口:
63
+
64
+ 1. **内置只读脚本**:`article-clean`、`links`、`jsonld`、`forms`,适合稳定抽取;先用 `browser_script_catalog` 查看。
65
+ 2. **Recipe**:最多 25 步的结构化 Playwright 操作,支持 wait/click/fill/type/press/select/check/hover/scroll/extract/assert/screenshot;交互步骤由自动化模式决定审批。
66
+ 3. **外部 UserScript**:适合外部模型生成站点专项逻辑。先 `browser_script_validate` 查看 SHA-256、域名范围与能力提示,再 `browser_userscript_run`;它在页面主世界运行,并非安全沙箱。
67
+
68
+ 工具自由度由 dsh-browser 的 `automationMode` 控制:`read-only` 仅暴露 10 个读取/校验工具;`standard`(默认)对交互、写 Recipe、外部脚本、OpenCLI 和安装操作审批;`autonomous` 直通页面交互和写 Recipe;`unrestricted` 为隔离测试 profile 提供完全无审批运行,但仍保留域名、参数、大小和步骤上限校验。
69
+
70
+ OpenCLI 用于已有站点 adapter 或复用 Chrome 登录会话。推荐顺序是 **站点 adapter → network/extract → DOM 操作**;先运行 `browser_opencli_status`。`browser_opencli_run` 接受 argv 数组而非 shell 字符串,可覆盖 adapter、显式 session 的 `browser state/find/get/click/fill/type/select/keys/wait/extract/network` 等命令;仅 `unrestricted` 跳过审批。
71
+
72
+ 更完整的 AuthProfile、脚本元数据与 OpenCLI 示例见 [LOGIN.md](./LOGIN.md)。
73
+
74
+ ## 配置
75
+
76
+ 三层,越靠前越日常:
77
+
78
+ 1. **DSH 可视化面板**:打开 `设置 → 插件 → 插件配置 → Web Search Pro`。面板按搜索策略、服务凭据、运行时后端和高级规则分组;修改先保留为本地草稿,点击“保存”后写入 `settings.yaml` 并热更新,支持放弃修改和逐字段恢复部署值。
79
+
80
+ - Exa、Jina、GitHub 密钥通过 DSH Credentials 写入,面板只显示“已配置/未配置”,不会把明文密钥读回浏览器。
81
+ - `platformRules`、`customPlatforms`、`browserBindings` 与 Playwright 设置使用 JSON 对象编辑器;格式或数值范围无效时会阻止保存。
82
+ - 浏览器工具的审批自由度仍由 `dsh-browser.automationMode` 管辖;用 `browser_status` 查看当前模式。Web Search Pro 面板只管理搜索插件自己的后端开关,不会绕过 dsh-browser 的审批策略。
83
+ - 更新带客户端面板的插件版本后需要重启 Web profile,让 DSH 客户端模块扫描器重新装载 `client.js`。
84
+
85
+ 2. **`$DSH_HOME/settings.yaml` → `web-search-pro:` 段**(热重载,改完即生效):
86
+
87
+ ```yaml
88
+ web-search-pro:
89
+ exaApiKeyEnv: EXA_API_KEY # 推荐:运行环境或凭据服务,不把密钥写入配置
90
+ jinaApiKeyEnv: JINA_API_KEY
91
+ engines: [ddg, bing, exa, seam, jina]
92
+ parallelEngines: false
93
+ ttlSeconds: 3600
94
+ searchMaxResults: 8
95
+ browserBindings:
96
+ zhihu:
97
+ authProfile: china-community
98
+ rulePack: zhihu-enhanced
99
+ ```
100
+
101
+ 3. **cordis.yml `config:`**(部署级默认值,见 `cordis.patch.yml`)。
102
+ 4. **环境变量 / 凭据**:`$EXA_API_KEY`、`$JINA_API_KEY`(`exaApiKeyEnv`/`jinaApiKeyEnv` 引用)。
103
+
104
+ ## 外部依赖(按需)
105
+
106
+ 多数后端需要系统额外安装的工具;插件提供 `web_deps` 工具检测与安装:
107
+
108
+ | 依赖 | 用途 | 安装 |
109
+ |---|---|---|
110
+ | bili-cli | B站后端 | `uv tool install bili-cli` / `pipx install bili-cli` |
111
+ | yt-dlp | YouTube 后端 | `uv tool install yt-dlp` / `pip install yt-dlp` |
112
+ | opencli | 小红书/Twitter/Reddit/IG/FB | 由 dsh-browser 内置;扩展未连接时用 `opencli doctor` 诊断 |
113
+ | agent-reach | agent-reach 后端 | `uv tool install agent-reach` / `pip install agent-reach` |
114
+ | mcporter | 无裸 API Key 时的 Exa MCP 回退 | `npm i -g mcporter` |
115
+ | playwright | 渲染/截图后端 | 由 dsh-browser 内置;缺 Chromium 时调用 `browser_install` |
116
+
117
+ ## 平台与引擎
118
+
119
+ `seam`(ctx.web/DeepSeek 原生)· `exa` · `ddg` · `bing` · `jina` · `github`(REST 搜索 API,免 CLI;可选 `$GITHUB_TOKEN`/`githubToken` 提升限额并解锁代码搜索)· `bilibili` · `v2ex` · `youtube`。默认顺序 `ddg, bing, exa, seam, jina`(免费优先),失败自动回退;失败后短时冷却,`web_backend_status` 可查看原因;`multi` 并行融合。
120
+
121
+ Exa 优先使用原生 API 客户端:`web_search_pro` 可传 `exaType`、域名包含/排除、发布时间范围和 category。若没有裸 API Key、但启用了 CLI 后端且 Exa MCP 已连接,搜索会自动通过 `mcporter` 完成;该兼容路径只支持 query + 结果数,高级筛选和 `web_exa_contents` 仍要求 `EXA_API_KEY`。不同选项、结果数、引擎顺序和单/多引擎模式使用不同缓存指纹。
122
+
123
+ ## 开发
124
+
125
+ ```bash
126
+ pnpm install
127
+ pnpm test
128
+ pnpm build # tsc src → lib
129
+ ```
130
+
131
+ 源码在 `src/`;`lib/` 为发布产物(已提交)。
132
+
133
+ ## License
134
+
135
+ MIT
136
+
137
+
138
+ ## 中文社区平台登录态
139
+
140
+ zhihu / weibo / douban / tieba / douyin / kuaishou 的免登录公开接口都被风控,
141
+ 所以走 **Playwright 驱动登录态浏览器**(借鉴 MediaCrawler 思路、MIT 独立实现,未用其签名算法):
142
+
143
+ 1. 登录一次保存登录态:`node scripts/save-login.mjs all login-state.json`
144
+ 2. dsh-browser 配置中声明按域名隔离的 `authProfiles`
145
+ 3. 在 `browserBindings` 把平台绑定到 profile;站点改版时用 `platformRules` 或 dsh-browser `rulePacks`
146
+
147
+ 详见 [LOGIN.md](./LOGIN.md)。
148
+
149
+
150
+ ## 历史管理
151
+
152
+ web_history 支持:kind/query/engine/platform 过滤、replay(用 queryId 回放已存结果)、
153
+ export(把过滤后的历史+结果写成 JSON 文件)。
154
+
155
+ ## 自定义平台
156
+
157
+ 在 settings.yaml 里定义任意站点(URL 模板 + 结果选择器),
158
+ web_platform_search 就能直接搜它——不需要改代码:
159
+
160
+ web-search-pro:
161
+ customPlatforms:
162
+ mybili:
163
+ name: '我的B站'
164
+ url: 'https://search.bilibili.com/all?keyword={query}'
165
+ item: '.bili-video-card'
166
+ title: '.bili-video-card__info--tit'
167
+ link: 'a'
168
+ # 需要登录时优先通过 browserBindings 绑定命名 authProfile。
169
+ myforum:
170
+ name: '某论坛'
171
+ url: 'https://forum.example.com/search?q={query}'
172
+ item: '.thread'
173
+ title: '.thread-title a'
174
+ link: '.thread-title a'
175
+ browserBindings:
176
+ myforum:
177
+ authProfile: forum
178
+
179
+ 旧版 `customPlatforms.*.cookie` 仍兼容,但会让 Cookie 明文进入配置;新配置应使用 dsh-browser 的命名 AuthProfile,状态文件不要提交到仓库。
180
+
package/cordis.patch.yml CHANGED
@@ -1,12 +1,12 @@
1
- # dsh-web-search-pro bundle patch.
2
- #
3
- # Install BOTH bundles (DSH activates only DIRECT dependencies' bundle layers):
4
- # dsh plugin --profile <name> add @anweat/dsh-browser dsh-web-search-pro
5
- #
6
- # @anweat/dsh-browser is declared as a peerDependency: it provides the browser
7
- # service that this plugin injects (inject: ['browser']).
8
- - insert:
9
- - id: web-search-pro
10
- name: dsh-web-search-pro
11
- config:
12
- verbose: false
1
+ # dsh-web-search-pro bundle patch.
2
+ #
3
+ # Install BOTH bundles (DSH activates only DIRECT dependencies' bundle layers):
4
+ # dsh plugin --profile <name> add @anweat/dsh-browser dsh-web-search-pro
5
+ #
6
+ # @anweat/dsh-browser is declared as a peerDependency: it provides the browser
7
+ # service that this plugin injects (inject: ['browser']).
8
+ - insert:
9
+ - id: web-search-pro
10
+ name: dsh-web-search-pro
11
+ config:
12
+ verbose: false