dsh-web-search-pro 0.2.0 → 0.2.3

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 (266) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/README.md +197 -32
  3. package/assets/skills/dsh-web-search-pro/SKILL.md +14 -13
  4. package/assets/skills/dsh-web-search-pro/references/config.md +36 -0
  5. package/assets/skills/dsh-web-search-pro/references/sources.md +19 -4
  6. package/assets/skills/dsh-web-search-pro/references/troubleshooting.md +3 -1
  7. package/catalog/sources.v1.json +22 -12
  8. package/lib/actions/approval.js +50 -1
  9. package/lib/actions/approval.js.map +1 -1
  10. package/lib/actions/config.js +274 -0
  11. package/lib/actions/config.js.map +1 -0
  12. package/lib/actions/errors.js +8 -1
  13. package/lib/actions/errors.js.map +1 -1
  14. package/lib/actions/format.js +10 -0
  15. package/lib/actions/format.js.map +1 -1
  16. package/lib/actions/index-view.js +2 -2
  17. package/lib/actions/index-view.js.map +1 -1
  18. package/lib/actions/read.js +7 -3
  19. package/lib/actions/read.js.map +1 -1
  20. package/lib/actions/registry.js +3 -1
  21. package/lib/actions/registry.js.map +1 -1
  22. package/lib/actions/run.js +2 -2
  23. package/lib/actions/run.js.map +1 -1
  24. package/lib/actions/schema.js +18 -0
  25. package/lib/actions/schema.js.map +1 -1
  26. package/lib/actions/search.js +12 -6
  27. package/lib/actions/search.js.map +1 -1
  28. package/lib/actions/sources.js +116 -41
  29. package/lib/actions/sources.js.map +1 -1
  30. package/lib/actions/types.js +19 -1
  31. package/lib/actions/types.js.map +1 -1
  32. package/lib/browser-access.js +25 -0
  33. package/lib/browser-access.js.map +1 -1
  34. package/lib/catalog/recommend.js +11 -3
  35. package/lib/catalog/recommend.js.map +1 -1
  36. package/lib/catalog/schema.js +3 -1
  37. package/lib/catalog/schema.js.map +1 -1
  38. package/lib/cli/builtin-specs.js +341 -0
  39. package/lib/cli/builtin-specs.js.map +1 -0
  40. package/lib/cli/chain.js +193 -0
  41. package/lib/cli/chain.js.map +1 -0
  42. package/lib/cli/chains-spec.js +118 -0
  43. package/lib/cli/chains-spec.js.map +1 -0
  44. package/lib/cli/engine.js +99 -0
  45. package/lib/cli/engine.js.map +1 -0
  46. package/lib/cli/opencli-sites.js +83 -0
  47. package/lib/cli/opencli-sites.js.map +1 -0
  48. package/lib/cli/opencli.js +153 -0
  49. package/lib/cli/opencli.js.map +1 -0
  50. package/lib/cli/probe.js +128 -0
  51. package/lib/cli/probe.js.map +1 -0
  52. package/lib/cli/runner.js +564 -0
  53. package/lib/cli/runner.js.map +1 -0
  54. package/lib/cli/spec.js +496 -0
  55. package/lib/cli/spec.js.map +1 -0
  56. package/lib/cli/time-text.js +79 -0
  57. package/lib/cli/time-text.js.map +1 -0
  58. package/lib/cli/trial.js +57 -0
  59. package/lib/cli/trial.js.map +1 -0
  60. package/lib/client/SettingsCard.js +14 -32
  61. package/lib/client/SettingsCard.js.map +1 -1
  62. package/lib/client/agent-mark.js +27 -0
  63. package/lib/client/agent-mark.js.map +1 -0
  64. package/lib/client/card-frame.js +118 -0
  65. package/lib/client/card-frame.js.map +1 -0
  66. package/lib/client/cli-form.js +257 -0
  67. package/lib/client/cli-form.js.map +1 -0
  68. package/lib/client/field-docs.js +130 -0
  69. package/lib/client/field-docs.js.map +1 -0
  70. package/lib/client/field-keys.js +81 -0
  71. package/lib/client/field-keys.js.map +1 -0
  72. package/lib/client/field-rows.js +71 -0
  73. package/lib/client/field-rows.js.map +1 -0
  74. package/lib/client/fill.js +3 -0
  75. package/lib/client/fill.js.map +1 -0
  76. package/lib/client/form-specs.js +15 -1
  77. package/lib/client/form-specs.js.map +1 -1
  78. package/lib/client/form.js +296 -27
  79. package/lib/client/form.js.map +1 -1
  80. package/lib/client/group-advanced.js +23 -0
  81. package/lib/client/group-advanced.js.map +1 -0
  82. package/lib/client/group-agent.js +28 -0
  83. package/lib/client/group-agent.js.map +1 -0
  84. package/lib/client/group-cli.js +136 -0
  85. package/lib/client/group-cli.js.map +1 -0
  86. package/lib/client/group-common.js +29 -0
  87. package/lib/client/group-common.js.map +1 -0
  88. package/lib/client/group-judge.js +67 -0
  89. package/lib/client/group-judge.js.map +1 -0
  90. package/lib/client/group-order.js +201 -0
  91. package/lib/client/group-order.js.map +1 -0
  92. package/lib/client/group-runtime.js +33 -0
  93. package/lib/client/group-runtime.js.map +1 -0
  94. package/lib/client/group-sources.js +83 -0
  95. package/lib/client/group-sources.js.map +1 -0
  96. package/lib/client/groups-basic.js +36 -0
  97. package/lib/client/groups-basic.js.map +1 -0
  98. package/lib/client/index.js.map +1 -1
  99. package/lib/client/json-list.js +50 -0
  100. package/lib/client/json-list.js.map +1 -0
  101. package/lib/client/locales.js +666 -215
  102. package/lib/client/locales.js.map +1 -1
  103. package/lib/client/order.js +192 -0
  104. package/lib/client/order.js.map +1 -0
  105. package/lib/client/overlay-ops.js +46 -0
  106. package/lib/client/overlay-ops.js.map +1 -0
  107. package/lib/client/sources-table.js +1 -0
  108. package/lib/client/sources-table.js.map +1 -1
  109. package/lib/client/styles.js +74 -47
  110. package/lib/client/styles.js.map +1 -1
  111. package/lib/client/text-view.js +98 -0
  112. package/lib/client/text-view.js.map +1 -0
  113. package/lib/client/ui-kit.js +120 -0
  114. package/lib/client/ui-kit.js.map +1 -0
  115. package/lib/client/validators.js +22 -0
  116. package/lib/client/validators.js.map +1 -1
  117. package/lib/client.js +9151 -1987
  118. package/lib/client.js.map +1 -1
  119. package/lib/config-fillers.js +53 -0
  120. package/lib/config-fillers.js.map +1 -0
  121. package/lib/config-groups.js +49 -0
  122. package/lib/config-groups.js.map +1 -0
  123. package/lib/config.js +87 -107
  124. package/lib/config.js.map +1 -1
  125. package/lib/default-chain.js +66 -0
  126. package/lib/default-chain.js.map +1 -0
  127. package/lib/deps.js +109 -102
  128. package/lib/deps.js.map +1 -1
  129. package/lib/engine-error.js +19 -0
  130. package/lib/engine-error.js.map +1 -0
  131. package/lib/engines.js +32 -115
  132. package/lib/engines.js.map +1 -1
  133. package/lib/fetch.js +23 -4
  134. package/lib/fetch.js.map +1 -1
  135. package/lib/index.js +30 -5
  136. package/lib/index.js.map +1 -1
  137. package/lib/overlay-types.js +88 -0
  138. package/lib/overlay-types.js.map +1 -0
  139. package/lib/overlay.js +683 -0
  140. package/lib/overlay.js.map +1 -0
  141. package/lib/pipeline/candidates.js +27 -1
  142. package/lib/pipeline/candidates.js.map +1 -1
  143. package/lib/pipeline/compile.js +63 -0
  144. package/lib/pipeline/compile.js.map +1 -1
  145. package/lib/pipeline/confidence.js +64 -0
  146. package/lib/pipeline/confidence.js.map +1 -0
  147. package/lib/pipeline/fusion.js +50 -3
  148. package/lib/pipeline/fusion.js.map +1 -1
  149. package/lib/pipeline/plan.js +2 -2
  150. package/lib/pipeline/plan.js.map +1 -1
  151. package/lib/pipeline/render.js +20 -2
  152. package/lib/pipeline/render.js.map +1 -1
  153. package/lib/pipeline/run.js +21 -7
  154. package/lib/pipeline/run.js.map +1 -1
  155. package/lib/pipeline/sources-spec.js +19 -3
  156. package/lib/pipeline/sources-spec.js.map +1 -1
  157. package/lib/providers/builtin.js +13 -14
  158. package/lib/providers/builtin.js.map +1 -1
  159. package/lib/providers/deepseek.js +348 -0
  160. package/lib/providers/deepseek.js.map +1 -0
  161. package/lib/providers/http.js.map +1 -1
  162. package/lib/providers/keyed-meta.js +7 -0
  163. package/lib/providers/keyed-meta.js.map +1 -1
  164. package/lib/providers/platforms.js +118 -58
  165. package/lib/providers/platforms.js.map +1 -1
  166. package/lib/providers/registry.js.map +1 -1
  167. package/lib/restart.js +47 -0
  168. package/lib/restart.js.map +1 -0
  169. package/lib/router.js +203 -27
  170. package/lib/router.js.map +1 -1
  171. package/lib/rpc-types.js +15 -0
  172. package/lib/rpc-types.js.map +1 -0
  173. package/lib/rpc.js +85 -0
  174. package/lib/rpc.js.map +1 -0
  175. package/lib/tools.js +10 -4
  176. package/lib/tools.js.map +1 -1
  177. package/lib/types/actions/approval.d.ts +11 -0
  178. package/lib/types/actions/config.d.ts +54 -0
  179. package/lib/types/actions/format.d.ts +9 -2
  180. package/lib/types/actions/run.d.ts +1 -0
  181. package/lib/types/actions/schema.d.ts +7 -1
  182. package/lib/types/actions/sources.d.ts +29 -3
  183. package/lib/types/actions/types.d.ts +28 -2
  184. package/lib/types/browser-access.d.ts +17 -0
  185. package/lib/types/catalog/recommend.d.ts +4 -0
  186. package/lib/types/catalog/schema.d.ts +2 -0
  187. package/lib/types/cli/builtin-specs.d.ts +38 -0
  188. package/lib/types/cli/chain.d.ts +83 -0
  189. package/lib/types/cli/chains-spec.d.ts +48 -0
  190. package/lib/types/cli/engine.d.ts +50 -0
  191. package/lib/types/cli/opencli-sites.d.ts +24 -0
  192. package/lib/types/cli/opencli.d.ts +77 -0
  193. package/lib/types/cli/probe.d.ts +53 -0
  194. package/lib/types/cli/runner.d.ts +126 -0
  195. package/lib/types/cli/spec.d.ts +269 -0
  196. package/lib/types/cli/time-text.d.ts +12 -0
  197. package/lib/types/cli/trial.d.ts +19 -0
  198. package/lib/types/client/SettingsCard.d.ts +17 -1
  199. package/lib/types/client/agent-mark.d.ts +22 -0
  200. package/lib/types/client/card-frame.d.ts +35 -0
  201. package/lib/types/client/cli-form.d.ts +97 -0
  202. package/lib/types/client/field-docs.d.ts +15 -0
  203. package/lib/types/client/field-keys.d.ts +41 -0
  204. package/lib/types/client/field-rows.d.ts +70 -0
  205. package/lib/types/client/fill.d.ts +2 -0
  206. package/lib/types/client/form-specs.d.ts +12 -3
  207. package/lib/types/client/form.d.ts +79 -1
  208. package/lib/types/client/group-advanced.d.ts +9 -0
  209. package/lib/types/client/group-agent.d.ts +20 -0
  210. package/lib/types/client/group-cli.d.ts +52 -0
  211. package/lib/types/client/group-common.d.ts +12 -0
  212. package/lib/types/client/group-judge.d.ts +17 -0
  213. package/lib/types/client/group-order.d.ts +26 -0
  214. package/lib/types/client/group-runtime.d.ts +15 -0
  215. package/lib/types/client/group-sources.d.ts +46 -0
  216. package/lib/types/client/groups-basic.d.ts +18 -0
  217. package/lib/types/client/index.d.ts +8 -0
  218. package/lib/types/client/json-list.d.ts +21 -0
  219. package/lib/types/client/locales.d.ts +1079 -196
  220. package/lib/types/client/order.d.ts +102 -0
  221. package/lib/types/client/overlay-ops.d.ts +37 -0
  222. package/lib/types/client/styles.d.ts +56 -41
  223. package/lib/types/client/text-view.d.ts +22 -0
  224. package/lib/types/client/ui-kit.d.ts +200 -0
  225. package/lib/types/client/validators.d.ts +6 -0
  226. package/lib/types/config-fillers.d.ts +9 -0
  227. package/lib/types/config-groups.d.ts +23 -0
  228. package/lib/types/config.d.ts +265 -216
  229. package/lib/types/default-chain.d.ts +63 -0
  230. package/lib/types/deps.d.ts +25 -23
  231. package/lib/types/engine-error.d.ts +12 -0
  232. package/lib/types/engines.d.ts +45 -10
  233. package/lib/types/fetch.d.ts +12 -3
  234. package/lib/types/index.d.ts +164 -146
  235. package/lib/types/overlay-types.d.ts +98 -0
  236. package/lib/types/overlay.d.ts +141 -0
  237. package/lib/types/pipeline/candidates.d.ts +19 -0
  238. package/lib/types/pipeline/compile.d.ts +11 -0
  239. package/lib/types/pipeline/confidence.d.ts +35 -0
  240. package/lib/types/pipeline/fusion.d.ts +23 -1
  241. package/lib/types/pipeline/render.d.ts +16 -0
  242. package/lib/types/pipeline/run.d.ts +3 -1
  243. package/lib/types/pipeline/sources-spec.d.ts +5 -2
  244. package/lib/types/pipeline/types.d.ts +37 -0
  245. package/lib/types/providers/deepseek.d.ts +130 -0
  246. package/lib/types/providers/http.d.ts +2 -1
  247. package/lib/types/providers/keyed-meta.d.ts +5 -0
  248. package/lib/types/providers/platforms.d.ts +15 -3
  249. package/lib/types/providers/registry.d.ts +10 -0
  250. package/lib/types/restart.d.ts +52 -0
  251. package/lib/types/router.d.ts +69 -9
  252. package/lib/types/rpc-types.d.ts +79 -0
  253. package/lib/types/rpc.d.ts +41 -0
  254. package/lib/types/tools.d.ts +6 -0
  255. package/lib/types/util.d.ts +16 -1
  256. package/lib/util.js +17 -4
  257. package/lib/util.js.map +1 -1
  258. package/package.json +51 -43
  259. package/scripts/check-client-bundle.mjs +1 -1
  260. package/scripts/cli-login-check.mjs +214 -0
  261. package/lib/client/RubricEditor.js +0 -47
  262. package/lib/client/RubricEditor.js.map +0 -1
  263. package/lib/client/fields.js +0 -31
  264. package/lib/client/fields.js.map +0 -1
  265. package/lib/types/client/RubricEditor.d.ts +0 -6
  266. package/lib/types/client/fields.d.ts +0 -65
package/lib/deps.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * External dependency detection and install for the CLI/platform backends.
3
- * Most backends shell out to tools installed outside DSH (bili, yt-dlp,
4
- * twitter, and mcporter). This module reports which are present and how to
5
- * install them; the sources.deps / sources.install actions expose it to the model. Each entry probes
6
- * the command the backend actually executes (the twitter backend runs
7
- * `twitter`, so finding `agent-reach` on PATH says nothing about it).
3
+ * Backends shell out to tools installed outside DSH: the built-in CLI adapter specs (bili, yt-dlp, twitter, xhs, zhihu,
4
+ * rdt, omnireach, gh, wx-search-cli, tanso, the standalone opencli) plus the user's own `cliAdapters`, and mcporter. This
5
+ * module reports which are present, whether the command on PATH really has the contract the adapter needs (a same-named
6
+ * program with another contract is `incompatible`, never `detected`), and how to install them; the sources.deps /
7
+ * sources.install actions expose it to the model. Probes are local, cached with a TTL, and never run a search or a login.
8
8
  *
9
9
  * Install is intentionally a MODEL-FACING TOOL, not a browser settings button:
10
10
  * a browser button running winget/pip/npm would be arbitrary command execution
@@ -13,50 +13,53 @@
13
13
  * @module web-search-pro/deps
14
14
  */
15
15
  import { runCli } from "./util.js";
16
- const IS_WIN = process.platform === 'win32';
17
- export const BILI_CLI_VERSION = '0.6.2';
18
- export const BILI_CLI_REVISION = '489607468f967e0e11f3cdff6efc022d011e982a';
19
- export const BILI_CLI_SOURCE = `git+https://github.com/public-clis/bilibili-cli@${BILI_CLI_REVISION}`;
20
- export const BILI_CLI_INSTALLS = [
21
- { installer: 'uv', command: `uv tool install --force ${BILI_CLI_SOURCE}` },
22
- { installer: 'pipx', command: `pipx install --force ${BILI_CLI_SOURCE}` },
23
- { installer: 'pip', command: `pip install --force-reinstall ${BILI_CLI_SOURCE}` },
16
+ import { BILI_CLI_INSTALLS, BILI_CLI_REVISION, BILI_CLI_SOURCE, BILI_CLI_VERSION, BUILTIN_CLI_SPECS, TWITTER_CLI_INSTALLS, builtinSpecById } from "./cli/builtin-specs.js";
17
+ import { OPENCLI_PROBE } from "./cli/opencli.js";
18
+ import { evaluateCliContract, findOnPath, probeAll } from "./cli/probe.js";
19
+ import { resolveCliAdapters } from "./cli/spec.js";
20
+ export { BILI_CLI_INSTALLS, BILI_CLI_REVISION, BILI_CLI_SOURCE, BILI_CLI_VERSION, TWITTER_CLI_INSTALLS };
21
+ const py = (pkg) => [
22
+ { installer: 'uv', command: 'uv tool install ' + pkg },
23
+ { installer: 'pipx', command: 'pipx install ' + pkg },
24
+ { installer: 'pip', command: 'pip install ' + pkg },
24
25
  ];
25
- function compareVersions(left, right) {
26
- const a = left.split('.').map(Number);
27
- const b = right.split('.').map(Number);
28
- for (let index = 0; index < Math.max(a.length, b.length); index++) {
29
- const delta = (a[index] ?? 0) - (b[index] ?? 0);
30
- if (delta !== 0)
31
- return delta;
32
- }
33
- return 0;
34
- }
26
+ /** Install commands of the spec-backed CLIs (a user-defined adapter has none: it names its own package in packageNote). */
27
+ const SPEC_INSTALLS = {
28
+ bili: BILI_CLI_INSTALLS,
29
+ 'yt-dlp': [{ installer: 'uv', command: 'uv tool install yt-dlp' }, { installer: 'pip', command: 'pip install yt-dlp' }],
30
+ twitter: TWITTER_CLI_INSTALLS,
31
+ xhs: py('xiaohongshu-cli'),
32
+ zhihu: py('pyzhihu-cli'),
33
+ rdt: py('git+https://github.com/public-clis/rdt-cli'),
34
+ omnireach: py('omnireach'),
35
+ gh: [{ installer: 'brew', command: 'brew install gh' }, { installer: 'winget', command: 'winget install GitHub.cli' }],
36
+ 'wx-search-cli': [{ installer: 'npm', command: 'npm i -g wx-search-cli' }],
37
+ tanso: [{ installer: 'npm', command: 'npm i -g @geekjourneyx/tanso' }],
38
+ opencli: [{ installer: 'npm', command: 'npm i -g @jackwener/opencli' }],
39
+ };
40
+ const USED_BY = {
41
+ bili: 'bilibili 平台后端',
42
+ 'yt-dlp': 'youtube 平台后端',
43
+ twitter: 'twitter 平台后端(第一后端,执行 `twitter search --json`;另需 TWITTER_AUTH_TOKEN 与 TWITTER_CT0,放在 DSH 凭据或宿主进程环境里)',
44
+ xhs: 'xiaohongshu 平台后端(只读 `xhs search`;需用户自行 `xhs login`)',
45
+ zhihu: 'zhihu 平台后端(只读 `zhihu search`;需用户自行 `zhihu login`)',
46
+ rdt: 'reddit 平台后端(只读 `rdt search`;需用户自行 `rdt login`)',
47
+ omnireach: 'wechat 平台后端与 omnireach 多源平台(只读 `omnireach search`)',
48
+ gh: 'github / github-issues / github-code 的 gh 回退后端(只读 `gh search`;需用户自行 `gh auth login`)',
49
+ 'wx-search-cli': 'wechat 平台第二后端(只读 `wx-search-cli search`;按上游文档,未实测)',
50
+ tanso: 'tanso 平台后端(只读;按上游文档,未实测)',
51
+ opencli: '独立 OpenCLI:xiaohongshu / reddit / twitter 等站点的搜索后端(按 `opencli list` 的 search 命令,使用用户自己的 Chrome)',
52
+ };
53
+ const LABELS = {
54
+ bili: 'bili-cli', 'yt-dlp': 'yt-dlp', twitter: 'twitter-cli', xhs: 'xhs (xiaohongshu-cli)', zhihu: 'zhihu-cli', rdt: 'rdt-cli', omnireach: 'OmniReach', gh: 'GitHub CLI',
55
+ 'wx-search-cli': 'wx-search-cli', tanso: 'Tanso', opencli: 'OpenCLI (standalone)',
56
+ };
35
57
  /** Validate the public-clis bili command rather than trusting an ambiguous package name. */
36
58
  export function evaluateBiliCli(versionOutput, searchHelpOutput) {
37
- const version = /\b(\d+\.\d+\.\d+)\b/.exec(versionOutput)?.[1];
38
- if (!version)
39
- return { available: false, diagnostic: 'bili --version returned no semantic version' };
40
- if (compareVersions(version, BILI_CLI_VERSION) < 0) {
41
- return { available: false, version, diagnostic: `bili ${version} is older than required ${BILI_CLI_VERSION}` };
42
- }
43
- const missing = ['--type', '--max', '--json'].filter(option => !searchHelpOutput.includes(option));
44
- if (missing.length) {
45
- return { available: false, version, diagnostic: `bili search contract missing ${missing.join(', ')}` };
46
- }
47
- return { available: true, version };
48
- }
49
- async function probeBiliCli(bin) {
50
- const env = { PYTHONUTF8: '1', PYTHONIOENCODING: 'utf-8' };
51
- const version = await runCli(bin, ['--version'], { timeoutMs: 8_000, signal: undefined, env, maxOutput: 64 * 1024 });
52
- if (version.code !== 0) {
53
- return { available: false, diagnostic: `bili --version failed with exit ${version.code}` };
54
- }
55
- const help = await runCli(bin, ['search', '--help'], { timeoutMs: 8_000, signal: undefined, env, maxOutput: 128 * 1024 });
56
- if (help.code !== 0) {
57
- return { available: false, diagnostic: `bili search --help failed with exit ${help.code}` };
58
- }
59
- return evaluateBiliCli(version.stdout + version.stderr, help.stdout + help.stderr);
59
+ const verdict = evaluateCliContract(builtinSpecById('bili'), 'bili', { code: 0, output: versionOutput }, { code: 0, output: searchHelpOutput });
60
+ if (verdict.state === 'detected')
61
+ return { available: true, ...verdict.version ? { version: verdict.version } : {} };
62
+ return { available: false, ...verdict.version ? { version: verdict.version } : {}, diagnostic: (verdict.reason ?? '').replace(/ \(a different program with the same name\?\)$/, '') };
60
63
  }
61
64
  /**
62
65
  * The twitter backend runs `twitter search <query> -n N` (twitter-cli). Another program that happens to be
@@ -69,37 +72,8 @@ export function evaluateTwitterCli(searchHelpOutput, exitCode) {
69
72
  return { available: false, diagnostic: 'twitter search --help does not describe a search command (not twitter-cli?)' };
70
73
  return { available: true };
71
74
  }
72
- async function probeTwitterCli(bin) {
73
- const help = await runCli(bin, ['search', '--help'], { timeoutMs: 8_000, signal: undefined, env: { PYTHONUTF8: '1', PYTHONIOENCODING: 'utf-8' }, maxOutput: 128 * 1024 });
74
- return evaluateTwitterCli(help.stdout + help.stderr, help.code);
75
- }
76
- export const TWITTER_CLI_INSTALLS = [
77
- { installer: 'uv', command: 'uv tool install twitter-cli' },
78
- { installer: 'pipx', command: 'pipx install twitter-cli' },
79
- { installer: 'pip', command: 'pip install twitter-cli' },
80
- ];
81
- /** One external tool the plugin may shell out to. */
82
- const DEPS = [
83
- {
84
- id: 'bili', label: 'bili-cli', usedBy: 'bilibili 后端',
85
- source: `public-clis/bilibili-cli v${BILI_CLI_VERSION} (${BILI_CLI_REVISION.slice(0, 12)})`,
86
- requiredVersion: `>=${BILI_CLI_VERSION}`,
87
- installs: BILI_CLI_INSTALLS,
88
- probe: probeBiliCli,
89
- },
90
- {
91
- id: 'yt-dlp', label: 'yt-dlp', usedBy: 'youtube 后端',
92
- installs: [
93
- { installer: 'uv', command: 'uv tool install yt-dlp' },
94
- { installer: 'pip', command: 'pip install yt-dlp' },
95
- ],
96
- },
97
- {
98
- id: 'twitter', label: 'twitter-cli', usedBy: 'twitter 平台后端(agentreach-twitter,执行 `twitter search`;另需 TWITTER_AUTH_TOKEN 与 TWITTER_CT0)',
99
- source: 'twitter-cli (PyPI twitter-cli; command `twitter`)',
100
- installs: TWITTER_CLI_INSTALLS,
101
- probe: probeTwitterCli,
102
- },
75
+ /** Non-spec tools: Exa's MCP fallback and the optional Agent-Reach installer helper. */
76
+ const EXTRA_DEPS = [
103
77
  {
104
78
  id: 'agent-reach', label: 'Agent-Reach', usedBy: '安装助手(可顺带装 twitter-cli 等渠道;本插件不直接执行它,twitter 搜索看 twitter 项)',
105
79
  optional: true,
@@ -114,36 +88,60 @@ const DEPS = [
114
88
  { installer: 'npm', command: 'npm i -g mcporter' },
115
89
  ],
116
90
  },
117
- // opencli and playwright are NOT listed here: they are bundled (plugin-local
118
- // node_modules, with global reuse fallback) in the dsh-browser plugin, which
119
- // this plugin uses optionally via the `browser` service.
91
+ // playwright is NOT listed here: it is bundled in the dsh-browser plugin, which this plugin uses optionally via the
92
+ // `browser` service. The dsh-browser OpenCLI is a backend of the platform chains, not a CLI of this list; the
93
+ // standalone `opencli` below is the user's own install.
120
94
  ];
121
- /** Resolve a command on PATH (win32: where.exe; posix: sh -c command -v). */
122
- async function resolveCmd(cmd) {
123
- const res = await runCli(IS_WIN ? 'where' : 'sh', IS_WIN ? [cmd] : ['-c', 'command -v ' + cmd], { timeoutMs: 8_000, signal: undefined, maxOutput: 64 * 1024 });
124
- if (res.code !== 0)
125
- return { found: false };
126
- const first = res.stdout.split(/\r?\n/).find(line => line.trim().length > 0);
127
- return first ? { found: true, path: first.trim() } : { found: false };
95
+ const infoOf = (subject, spec, usedBy, label, installs) => ({
96
+ id: subject.id,
97
+ label,
98
+ usedBy,
99
+ source: subject.packageNote,
100
+ ...subject.probe.minVersion ? { requiredVersion: '>=' + subject.probe.minVersion } : {},
101
+ ...spec?.verification ? { verification: spec.verification.status } : {},
102
+ installs,
103
+ });
104
+ /** The built-in specs (one entry per CLI; a CLI serving several platforms is one entry) and the standalone opencli. */
105
+ function builtinDeps() {
106
+ const out = BUILTIN_CLI_SPECS.map(spec => ({ subject: spec, info: infoOf(spec, spec, USED_BY[spec.id] ?? spec.platforms.join(' / ') + ' 后端', LABELS[spec.id] ?? spec.bins[0], SPEC_INSTALLS[spec.id] ?? []) }));
107
+ out.push({ subject: OPENCLI_PROBE, info: { ...infoOf(OPENCLI_PROBE, undefined, USED_BY.opencli, LABELS.opencli, SPEC_INSTALLS.opencli), verification: 'contract-only' } });
108
+ return out;
128
109
  }
129
- /** Detect all backends. */
130
- export async function detectDeps() {
131
- const out = [];
132
- for (const dep of DEPS) {
133
- const { probe, ...info } = dep;
134
- const resolved = await resolveCmd(dep.id);
135
- if (!resolved.found) {
136
- out.push({ ...info, available: false });
137
- continue;
138
- }
139
- const probed = probe ? await probe(resolved.path ?? dep.id) : { available: true };
140
- out.push({ ...info, ...probed, ...resolved.path ? { path: resolved.path } : {} });
110
+ /** Order the plugin has always listed them in, then the new adapters, then the user's. */
111
+ const ORDER = ['bili', 'yt-dlp', 'twitter', 'agent-reach', 'mcporter'];
112
+ export const DEP_IDS = [...new Set([...ORDER, ...BUILTIN_CLI_SPECS.map(s => s.id), 'opencli', ...EXTRA_DEPS.map(d => d.id)])];
113
+ /** Detect every dependency: the spec-backed CLIs through their cached contract probes, the rest by presence on PATH. */
114
+ export async function detectDeps(options = {}) {
115
+ const specs = builtinDeps();
116
+ const user = resolveCliAdapters(options.config?.cliAdapters).specs;
117
+ const userDeps = [...user].map(([id, spec]) => ({
118
+ subject: { ...spec, id: 'custom-cli:' + id },
119
+ info: { id: 'custom-cli:' + id, label: spec.bins[0] + ' (自定义)', usedBy: 'custom-cli:' + id + ' 平台后端(用户定义,未验证)', source: spec.packageNote, ...spec.probe.minVersion ? { requiredVersion: '>=' + spec.probe.minVersion } : {}, installs: [] },
120
+ }));
121
+ const all = [...specs, ...userDeps];
122
+ const probes = await probeAll(all.map(a => a.subject), { ...options.force ? { force: true } : {} });
123
+ const found = new Map();
124
+ for (const { subject, info } of all) {
125
+ const probe = probes.get(subject.id);
126
+ found.set(subject.id, {
127
+ ...info,
128
+ available: probe.state === 'detected',
129
+ installation: probe.state,
130
+ ...probe.path ? { path: probe.path } : {},
131
+ ...probe.version ? { version: probe.version } : {},
132
+ ...probe.state === 'incompatible' && probe.reason ? { diagnostic: probe.reason } : {},
133
+ });
141
134
  }
142
- return out;
135
+ for (const extra of EXTRA_DEPS) {
136
+ const path = findOnPath(extra.id);
137
+ found.set(extra.id, { ...extra, available: !!path, installation: path ? 'detected' : 'missing', ...path ? { path } : {} });
138
+ }
139
+ const order = [...ORDER, ...BUILTIN_CLI_SPECS.map(s => s.id), 'opencli', ...EXTRA_DEPS.map(d => d.id), ...userDeps.map(d => d.info.id)];
140
+ return [...new Set(order)].map(id => found.get(id)).filter((d) => d !== undefined);
143
141
  }
144
142
  /** Run the install command for one backend + installer. */
145
143
  export async function installDep(id, installer) {
146
- const dep = DEPS.find(d => d.id === id);
144
+ const dep = [...builtinDeps().map(b => ({ id: b.info.id, installs: b.info.installs })), ...EXTRA_DEPS].find(d => d.id === id);
147
145
  if (!dep)
148
146
  throw new Error('unknown dependency: ' + id);
149
147
  const target = dep.installs.find(i => i.installer === installer);
@@ -157,5 +155,14 @@ async function runCompound(command, timeoutMs) {
157
155
  const bin = parts.shift();
158
156
  return runCli(bin, parts, { timeoutMs, signal: undefined, maxOutput: 256 * 1024 });
159
157
  }
160
- export const DEP_IDS = DEPS.map(d => d.id);
158
+ /** The installer `sources.install` uses when none is named: the first one listed for the dependency. */
159
+ export function defaultInstaller(id) {
160
+ const dep = [...builtinDeps().map(b => ({ id: b.info.id, installs: b.info.installs })), ...EXTRA_DEPS].find(d => d.id === id);
161
+ if (!dep)
162
+ throw new Error('unknown backend: ' + id + ' (sources.deps lists them: ' + DEP_IDS.join(', ') + ')');
163
+ const first = dep.installs[0];
164
+ if (!first)
165
+ throw new Error(id + ' has no install command here: see its source in sources.deps');
166
+ return first.installer;
167
+ }
161
168
  //# sourceMappingURL=deps.js.map
package/lib/deps.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"deps.js","sourceRoot":"","sources":["../src/deps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deps.js","sourceRoot":"","sources":["../src/deps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The error every search engine and CLI adapter throws. Leaf module (no imports), so both engines.ts and the CLI adapter
3
+ * layer can extend it without an import cycle.
4
+ * @module web-search-pro/engine-error
5
+ */
6
+ export class EngineError extends Error {
7
+ code;
8
+ retryable;
9
+ retryAfterMs;
10
+ /** `retryAfterMs`: the service's own wait hint (Retry-After); the router uses it as the cooldown. */
11
+ constructor(message, code, retryable = true, retryAfterMs) {
12
+ super(message);
13
+ this.code = code;
14
+ this.retryable = retryable;
15
+ this.retryAfterMs = retryAfterMs;
16
+ this.name = 'EngineError';
17
+ }
18
+ }
19
+ //# sourceMappingURL=engine-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-error.js","sourceRoot":"","sources":["../src/engine-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAEE;IAAuB;IAA2B;IADxF,qGAAqG;IACrG,YAAY,OAAe,EAAW,IAAY,EAAW,YAAY,IAAI,EAAW,YAAqB;QAC3G,KAAK,CAAC,OAAO,CAAC,CAAA;QADsB,SAAI,GAAJ,IAAI,CAAQ;QAAW,cAAS,GAAT,SAAS,CAAO;QAAW,iBAAY,GAAZ,YAAY,CAAS;QAE3G,IAAI,CAAC,IAAI,GAAG,aAAa,CAAA;IAC3B,CAAC;CACF"}
package/lib/engines.js CHANGED
@@ -8,19 +8,11 @@ import { httpGet, runCli, jsYaml, stripTags, capText, decodeRedirectUrl } from "
8
8
  import { browserGap, requireBrowser } from "./browser-access.js";
9
9
  import { PLATFORM_SEARCH_SPECS, parseCookieString } from "./platform-search.js";
10
10
  import { ExaClient } from "./exa-client.js";
11
- export class EngineError extends Error {
12
- code;
13
- retryable;
14
- retryAfterMs;
15
- /** `retryAfterMs`: the service's own wait hint (Retry-After); the router uses it as the cooldown. */
16
- constructor(message, code, retryable = true, retryAfterMs) {
17
- super(message);
18
- this.code = code;
19
- this.retryable = retryable;
20
- this.retryAfterMs = retryAfterMs;
21
- this.name = 'EngineError';
22
- }
23
- }
11
+ import { EngineError } from "./engine-error.js";
12
+ import { cliSpecEngine, specEnv } from "./cli/engine.js";
13
+ import { builtinSpecById } from "./cli/builtin-specs.js";
14
+ import { buildArgv, missingEnv, parseCliOutput } from "./cli/runner.js";
15
+ export { EngineError };
24
16
  function withTimeout(promise, ms, label) {
25
17
  return new Promise((resolve, reject) => {
26
18
  const timer = setTimeout(() => reject(new EngineError(label + ' timed out', 'ENGINE_TIMEOUT')), ms);
@@ -357,58 +349,20 @@ export function githubIssuesEngine(deps) {
357
349
  },
358
350
  };
359
351
  }
360
- // ── Bilibili (bili CLI) ─────────────────────────────────────────────────────
352
+ // ── Bilibili (bili CLI, through the CLI adapter spec) ──────────────────────
353
+ const biliSpec = builtinSpecById('bili');
354
+ const ytDlpSpec = builtinSpecById('yt-dlp');
355
+ const twitterSpec = builtinSpecById('twitter');
361
356
  export function bilibiliEngine(deps) {
362
- return {
363
- id: 'bilibili',
364
- label: 'B站 (bili-cli)',
365
- available: () => deps.enableCli,
366
- async search(query, count, signal) {
367
- const res = await runCli('bili', biliSearchArgs(query, count), {
368
- timeoutMs: 30_000,
369
- signal,
370
- outputEncoding: 'utf-8',
371
- env: { PYTHONUTF8: '1', PYTHONIOENCODING: 'utf-8' },
372
- });
373
- if (res.code !== 0)
374
- throw new EngineError('bili search failed: ' + (res.stderr.trim() || res.stdout.trim() || 'exit ' + res.code).slice(0, 200), 'ENGINE_ERROR');
375
- return { sources: parseBilibiliSearchOutput(res.stdout) };
376
- },
377
- };
357
+ return cliSpecEngine(biliSpec, 'bilibili', deps, { id: 'bilibili', label: 'B站 (bili-cli)' });
378
358
  }
379
- /** Exact argv contract supported by public-clis/bilibili-cli v0.6.2+. */
359
+ /** Exact argv contract supported by public-clis/bilibili-cli v0.6.2+ (the `bili` spec). */
380
360
  export function biliSearchArgs(query, count) {
381
- return ['search', query, '--type', 'video', '--max', String(Math.min(Math.max(count, 1), 10)), '--json'];
361
+ return buildArgv(biliSpec.search, { query, count });
382
362
  }
383
- /** Parse and validate bili-cli's versioned JSON envelope. */
363
+ /** Parse and validate bili-cli's versioned JSON envelope (the `bili` spec). */
384
364
  export function parseBilibiliSearchOutput(output) {
385
- let envelope;
386
- try {
387
- envelope = JSON.parse(output);
388
- }
389
- catch {
390
- throw new EngineError('bili output is not valid UTF-8 JSON', 'ENGINE_ERROR');
391
- }
392
- if (envelope.ok !== true || envelope.schema_version !== '1' || !Array.isArray(envelope.data)) {
393
- const detail = typeof envelope.message === 'string'
394
- ? envelope.message
395
- : typeof envelope.error === 'string' ? envelope.error : 'unexpected response envelope';
396
- throw new EngineError('bili search failed: ' + capText(detail, 200), 'ENGINE_ERROR');
397
- }
398
- return envelope.data
399
- .filter(item => typeof item.bvid === 'string' && item.bvid.length > 0)
400
- .map(item => {
401
- const title = typeof item.title === 'string' ? stripTags(item.title) : undefined;
402
- const author = typeof item.author === 'string' ? item.author : undefined;
403
- const duration = typeof item.duration === 'string' ? item.duration : undefined;
404
- const play = typeof item.play === 'number' || typeof item.play === 'string' ? item.play : undefined;
405
- const meta = [author ? 'UP: ' + author : undefined, play !== undefined ? '播放: ' + play : undefined, duration].filter(Boolean);
406
- return {
407
- url: 'https://www.bilibili.com/video/' + item.bvid,
408
- ...title ? { title } : {},
409
- ...meta.length ? { snippet: capText(meta.join(' | '), 300) } : {},
410
- };
411
- });
365
+ return parseCliOutput(biliSpec, biliSpec.search, output, 1_000);
412
366
  }
413
367
  // ── V2EX (sov2ex community search API) ──────────────────────────────────────
414
368
  export function v2exEngine(allowProxyFakeIp = false) {
@@ -446,45 +400,13 @@ export function v2exEngine(allowProxyFakeIp = false) {
446
400
  },
447
401
  };
448
402
  }
449
- // ── YouTube (yt-dlp search) ─────────────────────────────────────────────────
403
+ // ── YouTube (yt-dlp search, through the CLI adapter spec) ───────────────────
450
404
  export function youtubeEngine(deps, cli = runCli) {
451
- return {
452
- id: 'youtube',
453
- label: 'YouTube (yt-dlp)',
454
- available: () => deps.enableCli,
455
- async search(query, count, signal) {
456
- const n = Math.min(count, 10);
457
- const res = await cli('yt-dlp', ['ytsearch' + n + ':' + query, '--flat-playlist', '--skip-download', '--no-warnings', '--print', '%(id)s\t%(title)s\t%(channel)s\t%(view_count)s\t%(duration_string)s'], { timeoutMs: 60_000, signal, outputEncoding: 'utf-8' });
458
- if (res.code !== 0)
459
- throw new EngineError('yt-dlp failed: ' + (res.stderr.trim() || res.stdout.trim() || 'exit ' + res.code).slice(0, 200), 'ENGINE_ERROR');
460
- const sources = [];
461
- for (const line of res.stdout.split(/\r?\n/)) {
462
- const [id, title, channel, views, duration] = line.split('\t');
463
- if (!id || !title)
464
- continue;
465
- const meta = [];
466
- if (channel)
467
- meta.push(channel);
468
- if (views && views !== 'None')
469
- meta.push(views + ' views');
470
- if (duration)
471
- meta.push(duration);
472
- sources.push({
473
- url: 'https://www.youtube.com/watch?v=' + id,
474
- title,
475
- ...meta.length ? { snippet: meta.join(' | ') } : {},
476
- });
477
- if (sources.length >= n)
478
- break;
479
- }
480
- if (!sources.length)
481
- throw new EngineError('yt-dlp returned no results', 'ENGINE_EMPTY', true);
482
- return { sources };
483
- },
484
- };
405
+ return cliSpecEngine(ytDlpSpec, 'youtube', deps, { id: 'youtube', label: 'YouTube (yt-dlp)', ...cli !== runCli ? { run: cli } : {} });
485
406
  }
486
407
  // ── OpenCLI platform search (reuses the user's logged-in browser session) ───
487
- const OPENCLI_PLATFORMS = {
408
+ /** Platforms the dsh-browser OpenCLI bridge has a site adapter for (platform -> adapter name). */
409
+ export const OPENCLI_PLATFORMS = {
488
410
  xiaohongshu: 'xiaohongshu',
489
411
  twitter: 'twitter',
490
412
  reddit: 'reddit',
@@ -530,31 +452,26 @@ export function opencliEngine(platform, deps) {
530
452
  };
531
453
  }
532
454
  // ── agent-reach CLI backends (twitter etc.) ─────────────────────────────────
455
+ /**
456
+ * The legacy `agentreach-twitter` engine, now a thin view of the `twitter` CLI spec (the platform chain uses the spec
457
+ * directly; this keeps the old engine id and its install message). Credentials are checked by `available()`.
458
+ */
533
459
  export function agentReachEngine(platform, deps) {
534
460
  if (platform === 'twitter') {
461
+ const leg = cliSpecEngine(twitterSpec, 'twitter', deps, { id: 'agentreach-twitter', label: 'agent-reach twitter-cli', skipCredentialGate: true });
535
462
  return {
536
463
  id: 'agentreach-twitter',
537
464
  label: 'agent-reach twitter-cli',
538
- available: () => deps.enableCli && deps.agentReachEnabled && !!process.env.TWITTER_AUTH_TOKEN && !!process.env.TWITTER_CT0,
539
- async search(query, count, signal) {
540
- const res = await runCli('twitter', ['search', query, '-n', String(Math.min(count, 10))], { timeoutMs: 45_000, signal });
541
- // Spawn failure (no `twitter` on PATH) comes back as exit -1 with no output: say what is missing.
542
- if (res.code === -1 && !res.timedOut && !res.stderr.trim() && !res.stdout.trim())
543
- throw new EngineError('the twitter command could not be started: install twitter-cli (sources.install backend=twitter); Agent-Reach alone does not provide it', 'ENGINE_UNAVAILABLE', false);
544
- if (res.code !== 0)
545
- throw new EngineError('twitter search failed: ' + (res.stderr.trim() || res.stdout.trim() || 'exit ' + res.code).slice(0, 200), 'ENGINE_ERROR');
546
- const sources = [];
547
- for (const line of res.stdout.split(/\r?\n/)) {
548
- const m = /(https?:\/\/[^\s]+)/.exec(line);
549
- if (!m)
550
- continue;
551
- const title = stripTags(line).replace(m[1], '').trim();
552
- if (title)
553
- sources.push({ url: m[1], title: capText(title, 200) });
554
- if (sources.length >= count)
555
- break;
465
+ available: () => deps.enableCli && deps.agentReachEnabled && missingEnv(twitterSpec, specEnv(deps)).length === 0,
466
+ async search(query, count, signal, options) {
467
+ try {
468
+ return await leg.search(query, count, signal, options);
469
+ }
470
+ catch (error) {
471
+ if (error?.code === 'CLI_NOT_FOUND')
472
+ throw new EngineError('the twitter command could not be started: install twitter-cli (sources.install backend=twitter); Agent-Reach alone does not provide it', 'ENGINE_UNAVAILABLE', false);
473
+ throw error;
556
474
  }
557
- return { sources };
558
475
  },
559
476
  };
560
477
  }