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
@@ -16,7 +16,9 @@ import type { Store } from '../store.ts';
16
16
  import type { EvidenceService } from '../pipeline/service.ts';
17
17
  import type { BrowserGetter } from '../browser-access.ts';
18
18
  import type { ProviderState } from '../provider.ts';
19
- export declare const ACTION_GROUPS: readonly ["search", "read", "history", "sources", "rules", "cache"];
19
+ import type { OverlayStore } from '../overlay.ts';
20
+ import type { PendingRestart } from '../restart.ts';
21
+ export declare const ACTION_GROUPS: readonly ["search", "read", "history", "sources", "rules", "cache", "config"];
20
22
  export type ActionGroup = typeof ACTION_GROUPS[number];
21
23
  /**
22
24
  * One parameter node. A subset of the Host's tool parameter DSL, so the same
@@ -51,8 +53,10 @@ export interface OutputSchema {
51
53
  * - `none`: runs directly.
52
54
  * - `install`: runs an external installer (`sources.install`).
53
55
  * - `local-write`: changes or deletes locally stored data (cache, history rows, extraction rules).
56
+ * - `config`: changes the agent overlay (search order, confidence, platform chains); runs without asking, denied in read-only mode.
57
+ * - `run-program`: lets the plugin run a local program (a custom CLI spec); always asks the user, denied in read-only mode.
54
58
  */
55
- export type ApprovalClass = 'none' | 'install' | 'local-write';
59
+ export type ApprovalClass = 'none' | 'install' | 'local-write' | 'config' | 'run-program';
56
60
  export interface ActionExample {
57
61
  args: Record<string, unknown>;
58
62
  note?: string;
@@ -74,9 +78,15 @@ export interface ActionServices {
74
78
  providerState?: () => ProviderState;
75
79
  /** Default characters one text exit may return (config `fetchDefaultChars`). */
76
80
  outputCap: () => number;
81
+ /** The agent overlay (run-time settings an agent may change); absent where the host of the actions has none (`config.*` then reports it). */
82
+ overlay?: OverlayStore;
83
+ /** Settings changed in the configuration that the running plugin only reads at start-up. */
84
+ pendingRestart?: () => PendingRestart[];
77
85
  }
78
86
  export interface ActionContext extends ActionServices {
79
87
  signal: AbortSignal;
88
+ /** The session the call belongs to (recorded in the overlay audit trail); undefined outside a session. */
89
+ sessionId?: string;
80
90
  }
81
91
  export interface ActionDef {
82
92
  /** `group.action`. */
@@ -103,6 +113,12 @@ export interface ActionDef {
103
113
  unavailable?(env: {
104
114
  browserReady: boolean;
105
115
  }): string | undefined;
116
+ /**
117
+ * Checks beyond the parameter schema that need no state and run no side effect, one message per problem ([] when fine).
118
+ * Run on the schema-validated arguments by `runAction` before `execute`, and by the approval hook before the user is asked,
119
+ * so a call that would be refused as INVALID_ARGS never becomes an approval prompt. Keep it a pure function of `args`.
120
+ */
121
+ precheck?(args: Record<string, any>): string[];
106
122
  execute(args: Record<string, any>, ctx: ActionContext): Promise<unknown>;
107
123
  /** The result as the text the model reads. */
108
124
  render(result: any, args: Record<string, any>): string;
@@ -117,6 +133,16 @@ export declare class ActionNotFoundError extends Error {
117
133
  readonly hint?: string | undefined;
118
134
  constructor(message: string, hint?: string | undefined);
119
135
  }
136
+ /** Raised when something the call needs is not set up here (a broken overlay file, say); mapped to CAPABILITY_UNAVAILABLE. */
137
+ export declare class ActionUnavailableError extends Error {
138
+ readonly hint?: string | undefined;
139
+ constructor(message: string, hint?: string | undefined);
140
+ }
141
+ /** Raised when a write is refused because the stored state moved on since the caller read it (revision mismatch); mapped to ACTION_FAILED with the hint to read again. */
142
+ export declare class ActionConflictError extends Error {
143
+ readonly hint?: string | undefined;
144
+ constructor(message: string, hint?: string | undefined);
145
+ }
120
146
  export declare const ERROR_CODES: readonly ["INVALID_ARGS", "UNKNOWN_ACTION", "CAPABILITY_UNAVAILABLE", "POLICY_DENIED", "DEADLINE", "CANCELLED", "NOT_FOUND", "ACTION_FAILED"];
121
147
  export type ErrorCode = typeof ERROR_CODES[number];
122
148
  export interface ActionErrorBody {
@@ -42,3 +42,20 @@ export declare function browserState(browser: BrowserService | undefined): {
42
42
  state: 'ready' | 'incomplete' | 'legacy' | 'missing';
43
43
  reason?: string;
44
44
  };
45
+ /** What a launch of the browser would do on this machine, as dsh-browser reports it (0.2.2+ `status().browser`). */
46
+ export interface BrowserLaunchReadiness {
47
+ ready: boolean;
48
+ /** Which browser a launch will use (`playwright-chromium`, `system-browser`, ...). */
49
+ source?: string;
50
+ /** Where it is. */
51
+ path?: string;
52
+ /** The one command (or step) that fixes `ready: false`, in dsh-browser's own words. */
53
+ advice?: string;
54
+ }
55
+ /**
56
+ * Whether the browser service can actually launch a browser. The service being present only means the plugin is loaded: a new user
57
+ * has no Playwright Chromium, and whether a system Chrome stands in is dsh-browser's decision. It is asked, never guessed, and
58
+ * only a dsh-browser that reports it (`status().browser`) is believed; any other answer (older plugin, a failing status call)
59
+ * is `undefined`, which callers treat as unknown and say nothing about.
60
+ */
61
+ export declare function browserLaunchReadiness(browser: BrowserService | undefined): Promise<BrowserLaunchReadiness | undefined>;
@@ -60,6 +60,10 @@ export interface Suggestion {
60
60
  /** First counter-example of the entry. */
61
61
  notFor?: string;
62
62
  verified: boolean;
63
+ /** "常用": the plugin's recommended source (it leads once its key is configured). */
64
+ common?: boolean;
65
+ /** The CLI backend this source runs through, when its adapter was not verified with a real search (`twitter: contract-only — …`). */
66
+ backend?: string;
63
67
  sourceFamily?: string;
64
68
  }
65
69
  export interface Recommendation {
@@ -62,6 +62,8 @@ export interface CatalogEntry {
62
62
  invoke?: string;
63
63
  /** Curation order among equals (lower first, default 50). */
64
64
  rank?: number;
65
+ /** "常用": the plugin's recommended source. Once its key is configured it leads the recommendations, and `search.recommend` marks it. Mirrors the provider descriptor's `common`. */
66
+ common?: boolean;
65
67
  /** Short install or configuration text. */
66
68
  install: string;
67
69
  license: string;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The built-in CLI adapter specs (dev-plan M12). Every argv, flag and output field was derived from the tool's own
3
+ * `--help` (and, where the help does not show the output shape, from the installed package source or the upstream
4
+ * README), and `verification` records how far each was checked:
5
+ * - `live`: a real read-only search was run and its output parsed (bili, gh, omnireach, yt-dlp, wx-search-cli, xhs; the standalone
6
+ * opencli for the twitter and zhihu sites, see opencli-sites.ts; and Exa through mcporter, which is not a spec);
7
+ * - `contract-only`: help and version probed on a real install, output shape taken from the tool's own source,
8
+ * README or documented output option, because a search needs the user's login or reads browser cookies
9
+ * (zhihu, rdt, twitter, the other opencli sites);
10
+ * - `docs-only`: not installed here; derived from the upstream README (tanso).
11
+ * Fixtures for the contract-only and docs-only parsers are marked "constructed from help/docs" in test/fixtures/cli.
12
+ * @module web-search-pro/cli/builtin-specs
13
+ */
14
+ import { type CliAdapterSpec, type CliSearchSpec } from './spec.ts';
15
+ export declare const BILI_CLI_VERSION = "0.6.2";
16
+ export declare const BILI_CLI_REVISION = "489607468f967e0e11f3cdff6efc022d011e982a";
17
+ export declare const BILI_CLI_SOURCE = "git+https://github.com/public-clis/bilibili-cli@489607468f967e0e11f3cdff6efc022d011e982a";
18
+ export declare const BILI_CLI_INSTALLS: {
19
+ installer: string;
20
+ command: string;
21
+ }[];
22
+ export declare const TWITTER_CLI_INSTALLS: {
23
+ installer: string;
24
+ command: string;
25
+ }[];
26
+ /** The date of the checks recorded below. */
27
+ export declare const SPEC_CHECK_DATE = "2026-10-06";
28
+ /** The omnireach sources that need neither a key, a login nor a browser (the others are `heavy` / booster tiers or need a URL query). */
29
+ export declare const OMNIREACH_KEYLESS_SOURCES = "hackernews,youtube,github,wechat,bilibili";
30
+ /** The `wechat` platform's two tools and the multi-source `omnireach` platform come from the same specs; ids are the backend ids. */
31
+ export declare const BUILTIN_CLI_SPECS: readonly CliAdapterSpec[];
32
+ /**
33
+ * How far the adapter of a command (by its first bin name) was verified: a built-in spec's own record, and for the standalone
34
+ * OpenCLI that of the site of `platform` (`live` for twitter and zhihu), else `contract-only`.
35
+ */
36
+ export declare function cliVerificationOf(bin: string, platform?: string): string | undefined;
37
+ export declare const builtinSpecById: (id: string) => CliAdapterSpec | undefined;
38
+ export type { CliSearchSpec };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Platform backend chains (dev-plan M12): every platform provider resolves an ORDERED chain of backends - a standalone CLI
3
+ * spec (xhs, rdt, zhihu, twitter, bili, yt-dlp, omnireach, gh, ...), the standalone OpenCLI (`opencli`), the dsh-browser
4
+ * OpenCLI bridge (`browser-opencli`), dsh-browser's rendered search page (`browser-search`), or the plugin's REST client
5
+ * (`rest`). The order is configurable (`platformBackends`). A backend that is missing, incompatible or not logged in is
6
+ * skipped with its reason; the provider is unavailable only when the whole chain is, and its error names what to install
7
+ * or run. Readiness is local: no search, no login.
8
+ * @module web-search-pro/cli/chain
9
+ */
10
+ import { type Engine, type EngineDeps } from '../engines.ts';
11
+ import type { ResolvedConfig } from '../config.ts';
12
+ import { CHAIN_PLATFORMS, DEFAULT_CHAINS } from './chains-spec.ts';
13
+ import { type CliAdapterSpec } from './spec.ts';
14
+ export type BackendKind = 'cli' | 'opencli' | 'browser-opencli' | 'browser-search' | 'rest' | 'custom-cli';
15
+ export { DEFAULT_CHAINS, CHAIN_PLATFORMS };
16
+ export interface LegReadiness {
17
+ ready: boolean;
18
+ installation: 'missing' | 'detected' | 'incompatible' | 'not_required';
19
+ version?: string;
20
+ credential?: 'not_required' | 'missing' | 'configured';
21
+ reason?: string;
22
+ /** Why it is skipped (absent when ready). */
23
+ code?: 'disabled' | 'cli_missing' | 'cli_incompatible' | 'not_logged_in' | 'browser_missing' | 'unsupported';
24
+ }
25
+ export interface ChainLeg {
26
+ /** Backend id as written in `platformBackends`. */
27
+ id: string;
28
+ kind: BackendKind;
29
+ label: string;
30
+ engine: Engine;
31
+ readiness(): Promise<LegReadiness>;
32
+ /** How far this backend's contract was checked (`live`, `contract-only`, `docs-only`, `unverified`). */
33
+ verification: string;
34
+ }
35
+ export interface ChainResolution {
36
+ legs: ChainLeg[];
37
+ /** Problems of the configuration (an unknown or foreign backend id), for `sources.status`. */
38
+ diagnostics: string[];
39
+ }
40
+ export interface ChainContext {
41
+ deps: EngineDeps;
42
+ config: ResolvedConfig;
43
+ }
44
+ /** All specs a chain may use: the built-ins by id and the user's `cliAdapters` as `custom-cli:<id>`. */
45
+ export declare function allSpecs(config: Pick<ResolvedConfig, 'cliAdapters'>): {
46
+ specs: Map<string, CliAdapterSpec>;
47
+ diagnostics: string[];
48
+ };
49
+ /** The chain of one platform: the configured (`platformBackends`) or default order, each id turned into a leg or into a diagnostic. */
50
+ export declare function resolveChain(platform: string, ctx: ChainContext): ChainResolution;
51
+ export interface ChainEntryReport {
52
+ id: string;
53
+ kind: BackendKind;
54
+ label: string;
55
+ order: number;
56
+ state: 'ready' | 'skipped';
57
+ installation?: string;
58
+ version?: string;
59
+ credential?: string;
60
+ reason?: string;
61
+ verification: string;
62
+ }
63
+ /**
64
+ * What a chain can do right now, one word for the text and the structured fields alike:
65
+ * `ready` (a backend can run and its login is satisfied or not needed), `login_unverified` (a backend can run but its login
66
+ * cannot be checked locally: a browser session, a keyring), `needs_login` (nothing can run and at least one backend lacks its
67
+ * login or credential), `unavailable` (nothing can run: not installed, incompatible, disabled).
68
+ */
69
+ export type ChainState = 'ready' | 'login_unverified' | 'needs_login' | 'unavailable';
70
+ export interface ChainReport {
71
+ entries: ChainEntryReport[];
72
+ available: boolean;
73
+ state: ChainState;
74
+ /** The first ready leg, or the best state among the skipped ones. */
75
+ installation: 'missing' | 'detected' | 'incompatible' | 'not_required';
76
+ credential?: 'not_required' | 'missing' | 'configured';
77
+ /** Why nothing can run: every skip reason in chain order. */
78
+ reason?: string;
79
+ diagnosticCode?: string;
80
+ diagnostics: string[];
81
+ }
82
+ /** Local readiness of a whole chain (one probe per leg, cached). */
83
+ export declare function chainReport(platform: string, ctx: ChainContext): Promise<ChainReport>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The static facts of the platform backend chains (dev-plan M12), free of Node imports so the settings card validates
3
+ * `platformBackends` with the same code the server resolves it with: the default chain of each platform, which backend
4
+ * ids exist and which platforms each can serve.
5
+ * @module web-search-pro/cli/chains-spec
6
+ */
7
+ import { OPENCLI_SITE_OF } from './opencli-sites.ts';
8
+ /**
9
+ * The default chain of each platform: first usable backend answers, empty or failing ones fall through in order. The platforms
10
+ * that need a login (xiaohongshu, reddit, twitter, zhihu) try the standalone OpenCLI first: it reads the login of the user's
11
+ * own day-to-day Chrome through the OpenCLI Browser Bridge, so nothing is logged in by the plugin. The standalone CLIs
12
+ * (xhs, rdt, twitter, zhihu) stay as the optional fallback for users who logged them in themselves.
13
+ */
14
+ export declare const DEFAULT_CHAINS: Readonly<Record<string, readonly string[]>>;
15
+ /** Platforms whose provider is a chain (everything in the default table). */
16
+ export declare const CHAIN_PLATFORMS: readonly string[];
17
+ export { OPENCLI_SITE_OF };
18
+ /** Platforms the dsh-browser OpenCLI bridge has a site adapter for (pinned to engines.ts by a test). */
19
+ export declare const BROWSER_OPENCLI_PLATFORMS: readonly string[];
20
+ /** Platforms with a built-in rendered-search-page spec in dsh-browser's searchResults (pinned to platform-search.ts by a test). */
21
+ export declare const BROWSER_SEARCH_PLATFORMS: readonly string[];
22
+ /** Platforms the plugin's own REST client serves. */
23
+ export declare const REST_PLATFORMS: readonly string[];
24
+ /** Backend ids that are not CLI specs. */
25
+ export declare const FIXED_BACKENDS: readonly ["opencli", "browser-opencli", "browser-search", "rest"];
26
+ /** Whether `id` names a platform backend: a built-in CLI spec, a fixed backend, or a custom CLI (`custom-cli:<id>`). */
27
+ export declare function isBackendId(id: string): boolean;
28
+ export interface BackendServing {
29
+ ok: boolean;
30
+ why?: string;
31
+ }
32
+ /**
33
+ * Whether backend `id` can serve `platform`. `specPlatforms` maps a CLI spec id (built-in, or `custom-cli:<id>` of the user)
34
+ * to the platforms it lists; a user spec serves any platform its chain names.
35
+ */
36
+ export declare function backendServes(id: string, platform: string, specPlatforms: ReadonlyMap<string, readonly string[]>): BackendServing;
37
+ /** The CLI specs a chain may name: the built-ins by id and the user's valid `cliAdapters` as `custom-cli:<id>`. */
38
+ export declare function specPlatformsOf(cliAdapters: unknown): {
39
+ platforms: Map<string, readonly string[]>;
40
+ diagnostics: string[];
41
+ };
42
+ /** The declared platforms of the user's CLI adapters that no backend chain exists for (the spec would serve nothing there). */
43
+ export declare function customCliPlatformIssues(cliAdapters: unknown): string[];
44
+ /**
45
+ * Every problem of the `platformBackends` setting (shape, unknown platform, unknown or foreign backend id) given the
46
+ * `cliAdapters` setting. The settings card and `sources.status` both call this.
47
+ */
48
+ export declare function platformBackendIssues(platformBackends: unknown, cliAdapters: unknown): string[];
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The Engine of a CLI adapter spec (dev-plan M12): one search leg that probes the command's contract (cached), then runs
3
+ * the spec through the shared runner. `available()` is synchronous and local (settings gates plus the probe cache);
4
+ * every failure reaches the caller as a structured error naming what to install or run.
5
+ * @module web-search-pro/cli/engine
6
+ */
7
+ import type { Engine, EngineDeps } from '../engines.ts';
8
+ import { CliAdapterError } from './runner.ts';
9
+ import { type CliProbeResult } from './probe.ts';
10
+ import { type CliAdapterSpec } from './spec.ts';
11
+ import type { runCli } from '../util.ts';
12
+ /** Why a spec is switched off by settings, or undefined when it may run. */
13
+ export declare function disabledBySettings(spec: Pick<CliAdapterSpec, 'id'>, deps: Pick<EngineDeps, 'enableCli' | 'agentReachEnabled'>): string | undefined;
14
+ /**
15
+ * The environment a spec's credential variables are read from: the process environment overlaid with the values the router
16
+ * resolved (settings literal -> DSH credentials -> process environment). Undefined = the process environment as it is.
17
+ */
18
+ export declare function specEnv(deps: Pick<EngineDeps, 'cliEnv'>): NodeJS.ProcessEnv | undefined;
19
+ export interface CliLegOptions {
20
+ /** Engine id (default: the spec id). */
21
+ id?: string;
22
+ label?: string;
23
+ /** Test seam: replaces the process runner; the contract probe is then skipped (the caller controls the command). */
24
+ run?: typeof runCli;
25
+ env?: NodeJS.ProcessEnv;
26
+ home?: string;
27
+ /** The credentials are checked by the caller (the legacy twitter engine). */
28
+ skipCredentialGate?: boolean;
29
+ /** A user-defined spec: every row it returns says which CLI it came from and that nothing here verified it. */
30
+ userDefined?: boolean;
31
+ }
32
+ /** The probe verdict as the structured error a search would raise, or undefined when the command is usable. */
33
+ export declare function probeError(spec: Pick<CliAdapterSpec, 'bins' | 'packageNote'>, probe: CliProbeResult): CliAdapterError | undefined;
34
+ export declare function cliSpecEngine(spec: CliAdapterSpec, platform: string, deps: Pick<EngineDeps, 'enableCli' | 'agentReachEnabled' | 'cliEnv'>, options?: CliLegOptions): Engine;
35
+ export interface SpecReadiness {
36
+ ready: boolean;
37
+ installation: 'missing' | 'detected' | 'incompatible';
38
+ version?: string;
39
+ path?: string;
40
+ /** Absent when the tool needs a login that cannot be checked from here (a keyring, a browser session). */
41
+ credential?: 'not_required' | 'missing' | 'configured';
42
+ /** Why it cannot run, naming what to install or run. */
43
+ reason?: string;
44
+ code: 'ok' | 'disabled' | 'cli_missing' | 'cli_incompatible' | 'not_logged_in';
45
+ }
46
+ /** Local readiness of one spec: settings, contract probe, then the credentials it needs. Never runs a search. */
47
+ export declare function specReadiness(spec: CliAdapterSpec, deps: Pick<EngineDeps, 'enableCli' | 'agentReachEnabled' | 'cliEnv'>, options?: {
48
+ env?: NodeJS.ProcessEnv;
49
+ home?: string;
50
+ }): Promise<SpecReadiness>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The static facts of the standalone OpenCLI sites the plugin searches (free of Node imports, so the catalog and the chain
3
+ * specs can read them): which site serves which platform, how each site's `search` rows map to sources, and how far each
4
+ * mapping was verified. The spec generation itself (src/cli/opencli.ts) reads the live command table.
5
+ * @module web-search-pro/cli/opencli-sites
6
+ */
7
+ import type { CliAdapterSpec, CliOutputSpec } from './spec.ts';
8
+ /** Platform -> site of the standalone OpenCLI (`opencli <site> search`). */
9
+ export declare const OPENCLI_SITE_OF: Readonly<Record<string, string>>;
10
+ export declare const GENERIC_OUTPUT: CliOutputSpec;
11
+ /**
12
+ * The output mapping of the sites the plugin knows by their real columns. All four print a JSON array of flat rows under `-f json`.
13
+ * - twitter, zhihu: MEASURED (opencli 1.8.8, 2026-10-27, fixtures live-opencli-*). twitter rows are `id, author (handle), bio, text,
14
+ * created_at (X API format), likes (number), views (string), url (https://x.com/i/status/<id>), has_media, media_urls, ...`; the
15
+ * title and meta line follow the standalone twitter backend (text, then author · likes · views · time). zhihu rows are
16
+ * `rank, title, type, author, votes, url` and carry no excerpt and no time.
17
+ * - xiaohongshu, reddit: NOT MEASURED. The only runs failed (login wall; an HTML page instead of JSON), so the mapping is the
18
+ * documented columns of clis/xiaohongshu/search.js (`rank, title, author, likes, published_at (date from the note id), url`,
19
+ * the url is a signed search_result link) and clis/reddit/search.js (`id, title, subreddit (r/x), author, score, comments, url,
20
+ * created_utc (epoch seconds), selftext, ...`), read from the source of 1.8.8.
21
+ */
22
+ export declare const SITE_OUTPUT: Readonly<Record<string, CliOutputSpec>>;
23
+ /** How far the search of one OpenCLI site was checked (`live`, `contract-only`). */
24
+ export declare function opencliSiteVerification(site: string): NonNullable<CliAdapterSpec['verification']>;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Standalone OpenCLI (dev-plan M12): the `opencli` command the user installed themselves, which drives their own Chrome
3
+ * through its Browser Bridge, independent of the dsh-browser plugin. It has one command per site and the plugin only
4
+ * calls `<site> search`, and only for sites that `opencli list -f json` itself reports with a read-access `search`
5
+ * command taking a positional query (the catalog is the tool's own, so a site without search, such as douyin or v2ex,
6
+ * is never assumed to have one). The list is a local call: no browser, no login.
7
+ * @module web-search-pro/cli/opencli
8
+ */
9
+ import { runCli } from '../util.ts';
10
+ import { type ProbeSubject } from './probe.ts';
11
+ import { type CliAdapterSpec, type CliErrorCodesSpec } from './spec.ts';
12
+ import { opencliSiteVerification } from './opencli-sites.ts';
13
+ export { OPENCLI_SITE_OF } from './chains-spec.ts';
14
+ export { opencliSiteVerification };
15
+ /** The command that proves this is the OpenCLI whose `list` output the adapter understands. Verified on 1.8.8. */
16
+ export declare const OPENCLI_PROBE: ProbeSubject;
17
+ /**
18
+ * The browser options every browser-backed site command of OpenCLI accepts (read from `opencli <site> search --help` and
19
+ * dist/src/execution.js of 1.8.8): the command runs in a background window (no focus is taken from the user's Chrome), with an
20
+ * ephemeral site session whose tab is released when it finishes. These are also its defaults; the plugin passes them
21
+ * explicitly so a changed `OPENCLI_WINDOW` / `OPENCLI_SITE_SESSION` environment cannot bring a window to the front, and only
22
+ * when the command itself lists the three options (a command without a browser rejects unknown options).
23
+ */
24
+ export declare const OPENCLI_SILENT_ARGS: readonly string[];
25
+ /** The probe of one site's search command: it must list the three silent browser options (`opencli <site> search --help`). Local, cached, no browser. */
26
+ export declare function opencliSiteProbe(site: string): ProbeSubject;
27
+ export interface OpencliSite {
28
+ site: string;
29
+ /** `cookie` sites use the user's logged-in Chrome; `public` sites need no login. */
30
+ strategy: string;
31
+ /** Whether the command drives the browser at all. */
32
+ browser: boolean;
33
+ hasLimit: boolean;
34
+ /** The site's domain as the command table gives it (`www.zhihu.com`), for the "log in to ..." hint. */
35
+ domain?: string;
36
+ }
37
+ /** Sites with a read `search` command taking a positional query, from the JSON of `opencli list -f json`. Pure. */
38
+ export declare function parseOpencliList(json: string): Map<string, OpencliSite>;
39
+ export declare function clearOpencliCache(): void;
40
+ /** The searchable sites of the installed OpenCLI (cached 5 minutes); `undefined` when the command cannot be listed. */
41
+ export declare function listOpencliSites(options?: {
42
+ run?: typeof runCli;
43
+ ttlMs?: number;
44
+ now?: () => number;
45
+ force?: boolean;
46
+ }): Promise<{
47
+ sites?: Map<string, OpencliSite>;
48
+ problem?: string;
49
+ }>;
50
+ /**
51
+ * The failure format of OpenCLI 1.8.8 (dist/src/errors.js `toEnvelope`, printed as YAML on stderr whatever `-f` says):
52
+ * `ok: false` / `error: { code, message, help?, exitCode }`. Codes, from that file and the site adapters:
53
+ * - AUTH_REQUIRED (exit 77): the Chrome has no login for the site -> not logged in (measured on xiaohongshu);
54
+ * - LOGIN_WALL (77), SECURITY_BLOCK, RATE_LIMITED, FORBIDDEN: an HTML page where JSON was expected, a risk-control block -> blocked;
55
+ * UNKNOWN with a JSON parse error on an HTML body (`Unexpected token '<'`) is the same thing from an adapter that does not
56
+ * check (measured on reddit through a proxy);
57
+ * - EMPTY_RESULT (66), NO_DATA, EMPTY_RESPONSE: nothing found; BROWSER_CONNECT (69): no Chrome / bridge; TIMEOUT (75);
58
+ * - ARGUMENT, INVALID_ARGUMENT, ...: the arguments of this adapter are not accepted by that version.
59
+ * Anything else (COMMAND_EXEC, FETCH_ERROR, HTTP_ERROR, ...) keeps OpenCLI's own message.
60
+ */
61
+ export declare const OPENCLI_ERROR_CODES: CliErrorCodesSpec;
62
+ /** The spec that runs `opencli <site> search` for one platform, or undefined when the generated spec is invalid (a site named like a write command). */
63
+ export declare function opencliSearchSpec(platform: string, entry: OpencliSite, options?: {
64
+ silent?: boolean;
65
+ }): CliAdapterSpec | undefined;
66
+ export interface OpencliSearchPlan {
67
+ spec?: CliAdapterSpec;
68
+ entry?: OpencliSite;
69
+ problem?: string;
70
+ hint?: string;
71
+ silent: boolean;
72
+ }
73
+ /**
74
+ * Everything a search of one platform through the standalone OpenCLI needs, checked locally (the command table and the site's
75
+ * `--help`, never a search): the site's entry, whether its command takes the silent browser options, and the generated spec.
76
+ */
77
+ export declare function planOpencliSearch(platform: string, site: string): Promise<OpencliSearchPlan>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Contract probes of CLI adapter specs (dev-plan M12, design §4.3 / §4.4): local only, cached with a TTL. A probe finds
3
+ * the command on PATH and runs ONLY the spec's version and help commands, then checks the contract the spec needs: a
4
+ * minimum version and the subcommands / flags that must appear in the help text. A same-named program with another
5
+ * contract is `incompatible`, not `detected`. A probe never runs a search and never logs in.
6
+ * @module web-search-pro/cli/probe
7
+ */
8
+ import { runCli } from '../util.ts';
9
+ import { type CliAdapterSpec } from './spec.ts';
10
+ export type CliInstallation = 'missing' | 'detected' | 'incompatible';
11
+ export interface CliProbeResult {
12
+ state: CliInstallation;
13
+ /** The command name that matched. */
14
+ bin?: string;
15
+ /** Where it was found. */
16
+ path?: string;
17
+ version?: string;
18
+ /** Why it is incompatible or missing. */
19
+ reason?: string;
20
+ checkedAt: number;
21
+ }
22
+ /** What a probe needs of a spec: where the command is, how it is checked, and the environment it runs in. */
23
+ export type ProbeSubject = Pick<CliAdapterSpec, 'id' | 'bins' | 'probe' | 'packageNote' | 'env'>;
24
+ export interface CliProbeOptions {
25
+ run?: typeof runCli;
26
+ /** Cache lifetime; default 60 s. */
27
+ ttlMs?: number;
28
+ /** Skip the cache (an explicit "check again"). */
29
+ force?: boolean;
30
+ now?: () => number;
31
+ }
32
+ export declare function clearProbeCache(): void;
33
+ /** The executable `cmd` resolves to on PATH (no process is spawned; Windows tries PATHEXT). */
34
+ export declare function findOnPath(cmd: string, env?: NodeJS.ProcessEnv): string | undefined;
35
+ /** The cached probe of a spec, when one is fresh (no spawn: `Engine.available()` is synchronous). */
36
+ export declare function cachedProbe(spec: ProbeSubject, ttlMs?: number, now?: () => number): CliProbeResult | undefined;
37
+ export interface ContractInput {
38
+ code: number;
39
+ output: string;
40
+ }
41
+ /**
42
+ * Decide whether version and help output satisfy a spec's contract. Pure (the fixtures tests call it directly).
43
+ * The version command may fail or print nothing unless the spec asks for a minimum version.
44
+ */
45
+ export declare function evaluateCliContract(spec: Pick<CliAdapterSpec, 'probe'>, bin: string, version: ContractInput, help: ContractInput): {
46
+ state: 'detected' | 'incompatible';
47
+ version?: string;
48
+ reason?: string;
49
+ };
50
+ /** Probe one spec (cached; concurrent calls for the same spec share one run). */
51
+ export declare function probeCli(spec: ProbeSubject, options?: CliProbeOptions): Promise<CliProbeResult>;
52
+ /** Probe many specs with a small concurrency bound (a settings refresh must not spawn dozens of processes at once). */
53
+ export declare function probeAll(specs: readonly ProbeSubject[], options?: CliProbeOptions, concurrency?: number): Promise<Map<string, CliProbeResult>>;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * The runner of CLI adapter specs (dev-plan M12): spawns the tool without a shell, decodes its output as UTF-8, caps
3
+ * time and size, maps the output to search sources and every failure to a structured error. It never logs or echoes
4
+ * environment values (error text is scrubbed of any value of a variable the spec names) and never runs a login.
5
+ * @module web-search-pro/cli/runner
6
+ */
7
+ import type { WebSearchSource } from '@deepseek-ai/dsh-web';
8
+ import { runCli, type CliResult } from '../util.ts';
9
+ import { EngineError } from '../engine-error.ts';
10
+ import { type CliAdapterSpec, type CliErrorCode, type CliErrorCodesSpec, type CliOutputSpec, type CliSearchSpec, type FieldSource } from './spec.ts';
11
+ /** A structured failure of a CLI adapter: `code` is one of {@link CliErrorCode}; `hint` says what the user can do. */
12
+ export declare class CliAdapterError extends EngineError {
13
+ readonly hint?: string | undefined;
14
+ constructor(message: string, code: CliErrorCode, hint?: string | undefined, retryable?: boolean);
15
+ }
16
+ /**
17
+ * A NO_PROXY list with its IPv6 entries written without brackets (`[::1]` / `[::1]:8080` -> `::1`). Python's httpx (omnireach, and
18
+ * any tool built on it) refuses a bracketed entry with "Invalid port: ':1]'" and the whole search fails; the DSH Host sets
19
+ * `NO_PROXY` with `[::1]`, which a plain terminal does not (found live 2026-10-26). Every tool that takes NO_PROXY accepts the bare form.
20
+ */
21
+ export declare function normalizeNoProxy(list: string): string;
22
+ /** The environment a spec's command runs with: the base set, what the spec lists, and the fixed UTF-8 / `env.set` values. */
23
+ export declare function buildCliEnv(spec: Pick<CliAdapterSpec, 'env'>, source?: NodeJS.ProcessEnv): Record<string, string>;
24
+ /** Names of the credential variables a spec relies on that are not set. */
25
+ export declare function missingEnv(spec: Pick<CliAdapterSpec, 'env'>, source?: NodeJS.ProcessEnv): string[];
26
+ /** The home-relative saved-login files of a spec that exist (existence only; the content is never read). */
27
+ export declare function savedLoginPresent(spec: Pick<CliAdapterSpec, 'login'>, opts?: {
28
+ home?: string;
29
+ exists?: (file: string) => boolean;
30
+ }): boolean | undefined;
31
+ /** Credential variables the plugin also resolves from its own settings / DSH credentials (config literal -> credentials ref -> environment). */
32
+ export declare const SETTINGS_BACKED_ENV: Readonly<Record<string, string>>;
33
+ /** What the user must do to log in: the tool's own command run by them, or the environment variables they set. Never run by the plugin. */
34
+ export declare function loginHint(spec: Pick<CliAdapterSpec, 'bins' | 'login' | 'env'>): string;
35
+ export declare function getPath(root: unknown, dotted: string): unknown;
36
+ export declare function resolveField(source: FieldSource | undefined, item: unknown, empty?: ReadonlySet<string>, now?: number): string | undefined;
37
+ /**
38
+ * Whether the whole stdout of a text-mode command is a JSON object / array or a YAML mapping / sequence document: the tool then
39
+ * printed a structured format the text parsers must not guess at (twitter-cli prints YAML when piped, issue #38).
40
+ */
41
+ export declare function structuredKind(text: string): 'JSON' | 'YAML' | undefined;
42
+ /**
43
+ * Parse a tool's stdout into the items its output spec describes. A broken payload is CLI_CONTRACT_MISMATCH (the tool is not
44
+ * what the spec says); a payload that says it failed (`expect` not met) is CLI_FAILED with the tool's own message.
45
+ */
46
+ export declare function parseCliItems(spec: Pick<CliAdapterSpec, 'bins'>, output: CliOutputSpec, stdout: string): unknown[];
47
+ /** The failure payload (`ok: false`, `error: { code, message }`) a tool prints on stderr or stdout: JSON, or a YAML document after any notices. */
48
+ export declare function parseFailurePayload(text: string): unknown;
49
+ /**
50
+ * A failed command run (non-zero exit) as the structured error its own code and message call for, or undefined when the
51
+ * spec lists no codes or the output carries nothing readable (the generic handling then applies).
52
+ */
53
+ export declare function mapToolFailure(codes: CliErrorCodesSpec | undefined, result: Pick<CliResult, 'code' | 'stdout' | 'stderr'>, spec: Pick<CliAdapterSpec, 'bins' | 'login' | 'env'>, redact?: (text: string) => string): CliAdapterError | EngineError | undefined;
54
+ /** The tool's own error text from a parsed json / yaml payload (`errorPaths`), when it carries one. */
55
+ export declare function payloadError(output: CliOutputSpec, stdout: string): string | undefined;
56
+ /**
57
+ * Strip markup from a field. Highlight tags (`<em>备案</em>`) vanish without leaving a space (Chinese words must not be split),
58
+ * block-level tags become a space, entities are decoded.
59
+ */
60
+ export declare function stripMarkup(input: string): string;
61
+ /**
62
+ * Map parsed items to sources by the output spec: http(s) URLs only, snippets and titles capped, tags stripped when asked.
63
+ * `skipped` counts the items (objects) that had no usable link, so the caller can say so instead of silently returning fewer.
64
+ */
65
+ export declare function mapCliItemsDetailed(output: CliOutputSpec, items: readonly unknown[], count: number, now?: number): {
66
+ sources: WebSearchSource[];
67
+ skipped: number;
68
+ };
69
+ export declare function mapCliItems(output: CliOutputSpec, items: readonly unknown[], count: number, now?: number): WebSearchSource[];
70
+ /**
71
+ * The result of a `lines: { mode: 'whole' }` command: the whole stdout as ONE source. The text is cut at `maxChars` with a note that
72
+ * says how much was shown; the title is "<id>: <query>"; the link is the stand-in `cli://<id>?q=<query>` (it is no web page, so the
73
+ * evidence pipeline lists it but never fetches it). Undefined when the tool printed nothing.
74
+ */
75
+ export declare function wholeOutputSource(spec: Pick<CliAdapterSpec, 'id'>, output: CliOutputSpec, query: string, stdout: string): WebSearchSource | undefined;
76
+ /** Parse and map in one go (what the fixtures tests call). */
77
+ export declare function parseCliOutput(spec: Pick<CliAdapterSpec, 'bins'>, search: CliSearchSpec, stdout: string, count?: number, now?: number): WebSearchSource[];
78
+ /** Split a query into words; double quotes keep a phrase in one word (`a "b c" d` -> `a`, `b c`, `d`) and are dropped. */
79
+ export declare function splitTerms(query: string): string[];
80
+ /**
81
+ * Fill the placeholders of an argv template. A value that would read as a flag gets a leading space (the tool then takes it as the query)
82
+ * unless a `--` precedes it. A `{terms}` token becomes one token per word of the query.
83
+ */
84
+ export declare function buildArgv(search: Pick<CliSearchSpec, 'argv' | 'maxCount' | 'overfetch'>, input: {
85
+ query: string;
86
+ count: number;
87
+ }): string[];
88
+ export interface CliRunInput {
89
+ query: string;
90
+ count: number;
91
+ signal?: AbortSignal | undefined;
92
+ }
93
+ export interface CliRunOptions {
94
+ /** Platform being searched (selects `spec.searches[platform]`). */
95
+ platform?: string;
96
+ /** `search` (default) or `read`. */
97
+ operation?: 'search' | 'read';
98
+ /** Resolved command (a path or the bin name); default `spec.bins[0]`. */
99
+ bin?: string;
100
+ /** Test seams. */
101
+ run?: typeof runCli;
102
+ env?: NodeJS.ProcessEnv;
103
+ home?: string;
104
+ exists?: (file: string) => boolean;
105
+ /** The caller checks the credentials itself (the legacy twitter engine): skip the pre-run credential gate. */
106
+ skipCredentialGate?: boolean;
107
+ /** Test seam: the clock `{ time }` fields read relative texts (`3小时前`) against. */
108
+ now?: number;
109
+ /** Sees what the command printed (secrets redacted) before it is interpreted: the settings card's trial shows the tool's own words. */
110
+ observe?: (result: {
111
+ code: number;
112
+ stdout: string;
113
+ stderr: string;
114
+ }) => void;
115
+ }
116
+ /**
117
+ * Run one spec command for a query and return its sources. Throws {@link CliAdapterError} (CLI_NOT_FOUND,
118
+ * CLI_CONTRACT_MISMATCH, CLI_NOT_LOGGED_IN, CLI_FAILED), ENGINE_EMPTY for a valid empty answer, ENGINE_TIMEOUT, or the
119
+ * abort reason when the caller's signal fires. Nothing is run when the spec's credentials are missing.
120
+ */
121
+ export declare function runCliSearch(spec: CliAdapterSpec, input: CliRunInput, options?: CliRunOptions): Promise<WebSearchSource[]>;
122
+ /** {@link runCliSearch} that also reports how many results had no usable link and were skipped. */
123
+ export declare function runCliSearchDetailed(spec: CliAdapterSpec, input: CliRunInput, options?: CliRunOptions): Promise<{
124
+ sources: WebSearchSource[];
125
+ skipped: number;
126
+ }>;