@omnicross/core 0.2.0 → 0.3.0

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 (119) hide show
  1. package/dist/{BuiltinToolExecutor-CS2WpXhM.d.cts → BuiltinToolExecutor-BHgH-EaZ.d.cts} +25 -2
  2. package/dist/{BuiltinToolExecutor-BluWyeob.d.ts → BuiltinToolExecutor-Bi1LmiTP.d.ts} +25 -2
  3. package/dist/{CompletionService-BiJqftc-.d.cts → CompletionService-BniP7j88.d.cts} +2 -2
  4. package/dist/{CompletionService-NXN_Av5W.d.ts → CompletionService-BqrKPwfA.d.ts} +2 -2
  5. package/dist/{ProviderProxy-CgIcCVwk.d.cts → ProviderProxy-Bz_nkOwq.d.cts} +1 -1
  6. package/dist/{ProviderProxy-DYoY5XoT.d.ts → ProviderProxy-Ckr6oTrE.d.ts} +1 -1
  7. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +2 -2
  8. package/dist/auth/GeminiCodeAssistProjectResolver.js +1 -1
  9. package/dist/{chunk-FJNKXOWE.js → chunk-2C3TTBS7.js} +4 -4
  10. package/dist/{chunk-NZYN7C3P.cjs → chunk-2RCCLQYV.cjs} +53 -53
  11. package/dist/{chunk-CDHS2QDC.js → chunk-4PFWFODB.js} +53 -53
  12. package/dist/{chunk-OST5RJOJ.cjs → chunk-4Z3ZLLC2.cjs} +13 -7
  13. package/dist/chunk-7RJI3NDI.cjs +236 -0
  14. package/dist/chunk-BTBEJRGL.cjs +781 -0
  15. package/dist/chunk-DBBR6RHF.js +236 -0
  16. package/dist/chunk-DXWFBBSK.js +781 -0
  17. package/dist/chunk-E4QHVXV5.cjs +118 -0
  18. package/dist/chunk-L7O2YQ5O.js +386 -0
  19. package/dist/{chunk-WSJE42SG.js → chunk-LKDAN4D7.js} +3684 -2462
  20. package/dist/{chunk-DEIUR2TH.js → chunk-LQYS2N47.js} +12 -8
  21. package/dist/chunk-MZEGQSKQ.js +118 -0
  22. package/dist/chunk-PTU7SXM3.cjs +386 -0
  23. package/dist/{chunk-CTKM773J.cjs → chunk-UPQIWJIE.cjs} +12 -8
  24. package/dist/{chunk-CFSGYFOZ.js → chunk-VL5TUDTM.js} +7 -1
  25. package/dist/{chunk-7B56AJBB.cjs → chunk-VSYQ6XYN.cjs} +2233 -1011
  26. package/dist/{chunk-TVYA5JSQ.cjs → chunk-ZAPN7XA6.cjs} +5 -5
  27. package/dist/completion/BuiltinToolExecutor.cjs +2 -2
  28. package/dist/completion/BuiltinToolExecutor.d.cts +3 -1
  29. package/dist/completion/BuiltinToolExecutor.d.ts +3 -1
  30. package/dist/completion/BuiltinToolExecutor.js +1 -1
  31. package/dist/completion/CompletionService.cjs +11 -10
  32. package/dist/completion/CompletionService.d.cts +6 -3
  33. package/dist/completion/CompletionService.d.ts +6 -3
  34. package/dist/completion/CompletionService.js +10 -9
  35. package/dist/completion.cjs +11 -10
  36. package/dist/completion.d.cts +6 -3
  37. package/dist/completion.d.ts +6 -3
  38. package/dist/completion.js +10 -9
  39. package/dist/egress-I46O_p5L.d.cts +126 -0
  40. package/dist/egress-I46O_p5L.d.ts +126 -0
  41. package/dist/frontends-Doz0RaWu.d.cts +97 -0
  42. package/dist/frontends-Doz0RaWu.d.ts +97 -0
  43. package/dist/image-generation.cjs +2 -2
  44. package/dist/image-generation.d.cts +7 -4
  45. package/dist/image-generation.d.ts +7 -4
  46. package/dist/image-generation.js +1 -1
  47. package/dist/index.cjs +25 -10
  48. package/dist/index.d.cts +12 -8
  49. package/dist/index.d.ts +12 -8
  50. package/dist/index.js +24 -9
  51. package/dist/openai-operation.d.cts +4 -1
  52. package/dist/openai-operation.d.ts +4 -1
  53. package/dist/outbound-api/routeResolver.d.cts +9 -5
  54. package/dist/outbound-api/routeResolver.d.ts +9 -5
  55. package/dist/outbound-api/subscriptionRegistryPort.d.cts +4 -1
  56. package/dist/outbound-api/subscriptionRegistryPort.d.ts +4 -1
  57. package/dist/outbound-api/types.d.cts +8 -4
  58. package/dist/outbound-api/types.d.ts +8 -4
  59. package/dist/outbound-api.cjs +25 -10
  60. package/dist/outbound-api.d.cts +117 -8
  61. package/dist/outbound-api.d.ts +117 -8
  62. package/dist/outbound-api.js +24 -9
  63. package/dist/pipeline/AccountAllowanceScheduling.d.cts +8 -4
  64. package/dist/pipeline/AccountAllowanceScheduling.d.ts +8 -4
  65. package/dist/pipeline/upstreamFetch.cjs +2 -2
  66. package/dist/pipeline/upstreamFetch.js +1 -1
  67. package/dist/ports.d.cts +8 -4
  68. package/dist/ports.d.ts +8 -4
  69. package/dist/provider-proxy/ProviderProxy.cjs +11 -10
  70. package/dist/provider-proxy/ProviderProxy.d.cts +5 -2
  71. package/dist/provider-proxy/ProviderProxy.d.ts +5 -2
  72. package/dist/provider-proxy/ProviderProxy.js +10 -9
  73. package/dist/provider-proxy/ingress/providerProxyShared.cjs +13 -10
  74. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +22 -3
  75. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +22 -3
  76. package/dist/provider-proxy/ingress/providerProxyShared.js +12 -9
  77. package/dist/provider-proxy/types.d.cts +4 -1
  78. package/dist/provider-proxy/types.d.ts +4 -1
  79. package/dist/provider-proxy.cjs +11 -10
  80. package/dist/provider-proxy.d.cts +10 -6
  81. package/dist/provider-proxy.d.ts +10 -6
  82. package/dist/provider-proxy.js +10 -9
  83. package/dist/proxy-UZTtjPZx.d.cts +18 -0
  84. package/dist/proxy-UZTtjPZx.d.ts +18 -0
  85. package/dist/{routeResolver-rpKQLyDO.d.cts → routeResolver-Da0yvkL1.d.cts} +2 -2
  86. package/dist/{routeResolver-CTCcSHWu.d.ts → routeResolver-STwMz_G4.d.ts} +2 -2
  87. package/dist/runtime-5NCT3J3T.cjs +8 -0
  88. package/dist/runtime-JTHUWCBM.js +8 -0
  89. package/dist/runtime-t8AZacFF.d.cts +233 -0
  90. package/dist/runtime-t8AZacFF.d.ts +233 -0
  91. package/dist/search/api.cjs +766 -0
  92. package/dist/search/api.d.cts +385 -0
  93. package/dist/search/api.d.ts +385 -0
  94. package/dist/search/api.js +766 -0
  95. package/dist/search/http.cjs +37 -0
  96. package/dist/search/http.d.cts +323 -0
  97. package/dist/search/http.d.ts +323 -0
  98. package/dist/search/http.js +37 -0
  99. package/dist/search.cjs +57 -0
  100. package/dist/search.d.cts +113 -0
  101. package/dist/search.d.ts +113 -0
  102. package/dist/search.js +57 -0
  103. package/dist/transformer/transformers/AnthropicTransformer.cjs +3 -3
  104. package/dist/transformer/transformers/AnthropicTransformer.js +2 -2
  105. package/dist/transformer/transformers.cjs +7 -7
  106. package/dist/transformer/transformers.js +6 -6
  107. package/dist/transformer.cjs +6 -6
  108. package/dist/transformer.js +5 -5
  109. package/dist/{types-DsHBBk3h.d.cts → types-BSIJdsyl.d.cts} +15 -0
  110. package/dist/{types-CbglB73l.d.cts → types-Be-yt_6T.d.cts} +1 -1
  111. package/dist/{types-CVRge76p.d.ts → types-By9Tg6-I.d.ts} +15 -0
  112. package/dist/types-CbCZqLGg.d.cts +127 -0
  113. package/dist/types-CbCZqLGg.d.ts +127 -0
  114. package/dist/{types-jjU24eYG.d.cts → types-D-oHYusb.d.cts} +73 -4
  115. package/dist/{types-Bd72H4SB.d.ts → types-Dm4_36V4.d.ts} +1 -1
  116. package/dist/{types-5T223WYQ.d.ts → types-Dvlpjn0d.d.ts} +73 -4
  117. package/package.json +6 -3
  118. package/dist/{chunk-6OC3ORW6.js → chunk-EUZRH544.js} +3 -3
  119. package/dist/{chunk-SQMAEDNE.cjs → chunk-POUTD5AM.cjs} +2 -2
@@ -0,0 +1,385 @@
1
+ import { SearchProviderCapabilities, SearchProviderContribution, SearchProviderId, SearchOptions, SearchUrlReadResult, SearchProvider, SearchResult, SearchProviderError } from '@omnicross/contracts/search-types';
2
+ import { Dispatcher } from 'undici';
3
+ import { S as SearchEgressPolicy } from '../egress-I46O_p5L.cjs';
4
+ import { a as SearchApiFetch, S as SearchApiProviderConfigs, J as JinaProviderConfig, b as SearchApiTransport, c as SearxngProviderConfig, T as TavilyProviderConfig, Z as ZhipuProviderConfig } from '../types-CbCZqLGg.cjs';
5
+ export { d as SEARCH_API_TRANSPORT_ID, e as SearchApiRequest, f as SearchApiStage } from '../types-CbCZqLGg.cjs';
6
+ import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.cjs';
7
+ import 'node:dns';
8
+
9
+ /**
10
+ * The API search contributions.
11
+ *
12
+ * Everything the registry must not infer is declared here: `source` and `kind`
13
+ * are stated, never derived from an id's spelling, and each adapter's
14
+ * capabilities are explicit down to the options it does NOT honor.
15
+ *
16
+ * The gating rule is the important one: a provider absent from `configs`
17
+ * produces NO contribution. It is unconfigured, not broken. A runtime that
18
+ * registered a keyless Tavily would advertise a capability it cannot honor and
19
+ * then burn a fallback attempt discovering that — so the absence is the
20
+ * feature. (`doctor search` still shows those providers as `unconfigured`
21
+ * rows; that is what doctor is for.)
22
+ *
23
+ * `priorityHint` is deliberately absent, as in the HTTP slice: ordering is the
24
+ * orchestrator's decision, and encoding a preference here would recreate the
25
+ * scattered-fallback-order problem the extraction exists to remove.
26
+ *
27
+ * @module search/api/contributions
28
+ */
29
+
30
+ /** Tavily: key required, search only. */
31
+ declare const TAVILY_CAPABILITIES: Readonly<SearchProviderCapabilities>;
32
+ /** Jina: keyless-capable, and the only adapter that can read a URL. */
33
+ declare const JINA_CAPABILITIES: Readonly<SearchProviderCapabilities>;
34
+ /** SearXNG: configured by HOST, not by key. */
35
+ declare const SEARXNG_CAPABILITIES: Readonly<SearchProviderCapabilities>;
36
+ /** Zhipu and Z.AI: key required, search only. */
37
+ declare const ZHIPU_CAPABILITIES: Readonly<SearchProviderCapabilities>;
38
+ /** Knobs for {@link apiSearchContributions}. */
39
+ interface ApiSearchContributionOptions {
40
+ /**
41
+ * Egress policy for every request these providers make. Omit for public-only.
42
+ * An internal SearXNG deployment is enabled by naming its hostname here.
43
+ */
44
+ egressPolicy?: SearchEgressPolicy;
45
+ /** Fetch primitive seam. Omit for the production undici transport. */
46
+ fetchImpl?: SearchApiFetch;
47
+ /**
48
+ * Layered proxy-dispatcher override handed to the shared transport (the
49
+ * daemon's `fetchUpstream` resolver). Only meaningful without `fetchImpl`.
50
+ */
51
+ resolveProxyDispatcher?: (url: string) => Dispatcher | undefined;
52
+ }
53
+ /**
54
+ * Build contributions for exactly the providers `configs` names.
55
+ *
56
+ * All adapters share ONE transport instance, so the egress policy and the
57
+ * dispatcher cache are shared too.
58
+ *
59
+ * The returned order mirrors Elftia's registry registration order
60
+ * (`tavily, jina, searxng, zhipu, z.ai`), which is what the registry preserves
61
+ * — but note that the ORDER PROVIDERS ARE TRIED is the orchestrator's policy,
62
+ * not this list.
63
+ */
64
+ declare function apiSearchContributions(configs: SearchApiProviderConfigs, options?: ApiSearchContributionOptions): SearchProviderContribution[];
65
+
66
+ /**
67
+ * The Jina reader — full page content for one URL.
68
+ *
69
+ * Ported from Elftia's `JinaReader` (sha256 `85d8b2a6…`, re-verified
70
+ * byte-identical against the 阶段0 manifest before porting) as a STANDALONE
71
+ * class, kept deliberately separate from `JinaSearchProvider`: the two call
72
+ * different hosts (`r.jina.ai` vs `s.jina.ai`) and answer different questions,
73
+ * and Elftia only ever coupled them through a `setApiKey` call.
74
+ *
75
+ * One behavior change: Elftia returns an in-band `{ success: false, error }`
76
+ * shape on failure, which is exactly the code-less error string the new
77
+ * contract exists to remove — a fallback policy cannot decide on it. This
78
+ * client throws the taxonomy `SearchProviderError` the shared transport
79
+ * produces. The legacy shape is still reachable through the existing
80
+ * `search-compat` converters for any consumer that needs it.
81
+ *
82
+ * The host is fixed at `r.jina.ai`, as in Elftia. Configurability is not added
83
+ * speculatively — but the request still passes egress validation like every
84
+ * other, so the fixed host buys no bypass.
85
+ *
86
+ * NOTE (plan §16, unresolved and owned by a later stage): this reader and
87
+ * `BuiltinToolExecutor`'s `web_fetch` are two ways to turn a URL into text.
88
+ * Whether they should become one capability with different policies or stay two
89
+ * bounded interfaces is NOT decided here, and `web_fetch` is untouched.
90
+ *
91
+ * @module search/api/JinaReaderClient
92
+ */
93
+
94
+ /** Elftia's reader host. Not configurable there, and not made so here. */
95
+ declare const JINA_READER_HOST = "https://r.jina.ai";
96
+ declare class JinaReaderClient {
97
+ private readonly config;
98
+ private readonly transport;
99
+ private readonly providerId;
100
+ private readonly rotator;
101
+ constructor(config?: JinaProviderConfig, transport?: SearchApiTransport, providerId?: SearchProviderId);
102
+ /**
103
+ * Read one URL.
104
+ *
105
+ * The key is OPTIONAL, as in the baseline: the reader answers unauthenticated
106
+ * requests at a lower rate limit.
107
+ */
108
+ readUrl(url: string, options?: SearchOptions): Promise<SearchUrlReadResult>;
109
+ }
110
+
111
+ /**
112
+ * `jina` — the Jina search API on the new provider contract.
113
+ *
114
+ * Ported from Elftia's `JinaProvider` (sha256 `374d2252…`, re-verified
115
+ * byte-identical against the 阶段0 manifest before porting). GET
116
+ * `{apiHost}/<encoded query>`, key OPTIONAL (the endpoint answers
117
+ * unauthenticated at a lower rate limit), `X-Engine: direct` only when the
118
+ * caller asks for page content, and the `content || description` mapping.
119
+ *
120
+ * SEARCH and READER are split, unlike the baseline where one `configureProvider`
121
+ * call pushed the key into both. This class owns search; {@link JinaReaderClient}
122
+ * owns `readUrl` and is injected, so `capabilities.supportsUrlRead: true` names
123
+ * something that always works rather than something that works if a setter was
124
+ * called.
125
+ *
126
+ * @module search/api/JinaSearchProvider
127
+ */
128
+
129
+ /** The id this provider registers under. */
130
+ declare const JINA_PROVIDER_ID = "jina";
131
+ /** Elftia's default search host. */
132
+ declare const JINA_DEFAULT_HOST = "https://s.jina.ai";
133
+ /** Elftia's default result count. */
134
+ declare const JINA_DEFAULT_MAX_RESULTS = 5;
135
+ declare class JinaSearchProvider implements SearchProvider {
136
+ private readonly config;
137
+ private readonly transport;
138
+ readonly id: SearchProviderId;
139
+ private readonly rotator;
140
+ private readonly reader;
141
+ constructor(config?: JinaProviderConfig, transport?: SearchApiTransport, reader?: JinaReaderClient);
142
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
143
+ /** Read one URL through the split-out reader client. */
144
+ readUrl(url: string, options?: SearchOptions): Promise<SearchUrlReadResult>;
145
+ }
146
+
147
+ /**
148
+ * Round-robin selection across a provider's comma-separated API keys.
149
+ *
150
+ * Ported from Elftia's `ApiKeyRotator`
151
+ * (`capabilities/search/ApiKeyRotator.ts`, sha256 `9c649cba…`, re-verified
152
+ * byte-identical against the 阶段0 manifest before porting). Behavior is
153
+ * unchanged:
154
+ *
155
+ * - a single key is returned as-is, with no rotation;
156
+ * - empty or whitespace-only input returns `''`, and the ADAPTER raises the
157
+ * `config_missing` failure — the rotator never decides whether a provider is
158
+ * configured;
159
+ * - multiple keys advance one step per call, wrapping defensively in case the
160
+ * configured list shrank between calls.
161
+ *
162
+ * One instance per provider instance, as in Elftia. The index is in-memory and
163
+ * resets with the process, which matches how the keys themselves are re-read
164
+ * from configuration at startup.
165
+ *
166
+ * @module search/api/rotator
167
+ */
168
+ declare class ApiKeyRotator {
169
+ private index;
170
+ /**
171
+ * Pick the next key from a comma-separated list, advancing the counter.
172
+ *
173
+ * Returns `''` when nothing is configured — never `undefined`, so callers
174
+ * have one falsy case to test rather than two.
175
+ */
176
+ pick(rawKeyString: string | undefined): string;
177
+ /** Reset the rotation counter, e.g. after a configuration update. */
178
+ reset(): void;
179
+ /** How many usable keys the string holds. */
180
+ countKeys(rawKeyString: string | undefined): number;
181
+ /**
182
+ * Every configured key.
183
+ *
184
+ * Not in the Elftia original: redaction has to strip EVERY key a provider
185
+ * could have sent, not just the one this request rotated onto, or a key
186
+ * echoed by an upstream error survives whenever the counter has moved on.
187
+ */
188
+ allKeys(rawKeyString: string | undefined): string[];
189
+ }
190
+
191
+ /**
192
+ * `searxng` — a self-hosted SearXNG instance on the new provider contract.
193
+ *
194
+ * Ported from Elftia's `SearxngProvider` (sha256 `c1ec6694…`, re-verified
195
+ * byte-identical against the 阶段0 manifest before porting). GET
196
+ * `{apiHost}/search?q=&format=json&pageno=1`, with Basic auth sent only when
197
+ * BOTH credentials are present.
198
+ *
199
+ * The only provider whose required setting is a HOST rather than a key, and
200
+ * therefore the one the egress policy exists to accommodate: a SearXNG instance
201
+ * usually lives on a private address, which the default policy denies. An
202
+ * operator enables theirs by naming its hostname in
203
+ * `SearchEgressPolicy.allowedPrivateHosts` — an explicit, admin-level decision,
204
+ * never something this adapter infers from the fact that a host was configured.
205
+ *
206
+ * @module search/api/SearxngSearchProvider
207
+ */
208
+
209
+ /** The id this provider registers under. */
210
+ declare const SEARXNG_PROVIDER_ID = "searxng";
211
+ /** Elftia's default result count. */
212
+ declare const SEARXNG_DEFAULT_MAX_RESULTS = 5;
213
+ declare class SearxngSearchProvider implements SearchProvider {
214
+ private readonly config;
215
+ private readonly transport;
216
+ readonly id: SearchProviderId;
217
+ constructor(config: SearxngProviderConfig, transport?: SearchApiTransport);
218
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
219
+ }
220
+
221
+ /**
222
+ * `tavily` — the Tavily search API on the new provider contract.
223
+ *
224
+ * Ported from Elftia's `TavilyProvider` (sha256 `3134dcd7…`, re-verified
225
+ * byte-identical against the 阶段0 manifest before porting). The wire contract
226
+ * is unchanged: POST `{apiHost}/search` with the key IN THE JSON BODY,
227
+ * `search_depth: 'advanced'`, and no client-side slicing — Tavily honors
228
+ * `max_results` itself.
229
+ *
230
+ * That body-borne key is why the shared transport's redaction is mandatory
231
+ * rather than defensive: a 4xx that quotes the request back is a direct path
232
+ * from a credential to a log file. Every key this provider could have sent is
233
+ * handed to the transport as `secrets`, not just the one this call rotated
234
+ * onto.
235
+ *
236
+ * @module search/api/TavilySearchProvider
237
+ */
238
+
239
+ /** The id this provider registers under. */
240
+ declare const TAVILY_PROVIDER_ID = "tavily";
241
+ /** Elftia's default host, used when no `apiHost` override is configured. */
242
+ declare const TAVILY_DEFAULT_HOST = "https://api.tavily.com";
243
+ /** Elftia's default result count. */
244
+ declare const TAVILY_DEFAULT_MAX_RESULTS = 5;
245
+ declare class TavilySearchProvider implements SearchProvider {
246
+ private readonly config;
247
+ private readonly transport;
248
+ readonly id: SearchProviderId;
249
+ private readonly rotator;
250
+ constructor(config: TavilyProviderConfig, transport?: SearchApiTransport);
251
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
252
+ }
253
+
254
+ /**
255
+ * The shared transport every API search adapter runs on.
256
+ *
257
+ * Elftia's four adapters each call global `fetch` directly, each build their
258
+ * own `<label> search failed: <status> - <responseText>` string, and each
259
+ * follow redirects silently. Porting that shape four times would mean writing
260
+ * the SSRF check and the secret redaction four times — so the ported adapters
261
+ * share this one transport instead, and it owns everything that must not be
262
+ * re-implemented per provider:
263
+ *
264
+ * - **Egress validation** of the initial URL and of EVERY redirect hop.
265
+ * - **A manual redirect walk** (cap {@link API_MAX_REDIRECTS}). This is a
266
+ * deliberate divergence from Elftia's `redirect: 'follow'`, recorded for
267
+ * 阶段5's comparison report: per-hop validation is impossible without it, and
268
+ * a JSON API that redirects now gets checked instead of silently followed.
269
+ * - **The guarded dispatcher** on direct connections, so a hostname that
270
+ * resolves into a denied class cannot be connected to. Proxied connections
271
+ * take the proxy dispatcher and keep URL-level checks only — see
272
+ * {@link selectApiDispatcher}.
273
+ * - **Status mapping** onto the eight-code taxonomy.
274
+ * - **Redaction**, through one sanitizer every error message passes. Tavily
275
+ * sends its API key in the request BODY, so an upstream 4xx that quotes the
276
+ * request is a direct path from a credential to a log file. This is the only
277
+ * thing standing in that path.
278
+ *
279
+ * @module search/api/transport
280
+ */
281
+
282
+ /** Redirect hop cap, matching the HTTP slice. */
283
+ declare const API_MAX_REDIRECTS = 5;
284
+ /** Default per-request budget, matching the search layer's HTTP budget. */
285
+ declare const DEFAULT_API_TIMEOUT_MS = 15000;
286
+ /** Sanity cap on a JSON response body. Search payloads are kilobytes. */
287
+ declare const API_RESPONSE_BYTES: number;
288
+ /** Knobs for {@link createSearchApiTransport}. */
289
+ interface SearchApiTransportOptions {
290
+ /** The fetch primitive to drive. Defaults to undici's `fetch`. */
291
+ fetch?: SearchApiFetch;
292
+ /** Environment to read proxy variables from. Defaults to `process.env`. */
293
+ env?: ProxyEnvironment;
294
+ /**
295
+ * Layered proxy-dispatcher override for one request URL, AHEAD of the env
296
+ * layer (the daemon's `fetchUpstream` resolver, so search follows
297
+ * `server.proxy`). When it yields a dispatcher the connection is proxied —
298
+ * URL and per-hop egress validation still apply, address-level validation
299
+ * does not, the same documented limitation as the env proxy. When it yields
300
+ * `undefined` the env layer and then the egress-guarded dispatcher apply,
301
+ * exactly as before.
302
+ */
303
+ resolveProxyDispatcher?: (url: string) => Dispatcher | undefined;
304
+ /** Egress policy. Defaults to public-only. */
305
+ egressPolicy?: SearchEgressPolicy;
306
+ /** Redirect hop cap. Defaults to {@link API_MAX_REDIRECTS}. */
307
+ maxRedirects?: number;
308
+ }
309
+ /** Build an API transport. Tests inject `fetch`; production takes the default. */
310
+ declare function createSearchApiTransport(options?: SearchApiTransportOptions): SearchApiTransport;
311
+ /** The production transport: undici, proxy from `process.env`, default policy. */
312
+ declare const defaultSearchApiTransport: SearchApiTransport;
313
+ /**
314
+ * Require an array at `field` on a JSON payload.
315
+ *
316
+ * Elftia tolerates a missing array on three of the four adapters
317
+ * (`data.results || []`), which turns a changed response shape into an
318
+ * empty-but-successful search. That re-conflates exactly what 阶段2 separated:
319
+ * a missing array is drift, not "the engine found nothing". All four adapters
320
+ * now require the array and raise `parse_failed` — a recorded divergence for
321
+ * 阶段5's comparison report. An array that is PRESENT and empty stays a
322
+ * legitimate zero-result success.
323
+ */
324
+ declare function requireResultArray(payload: unknown, field: string, providerId: SearchProviderId, label: string): unknown[];
325
+ /** A pre-flight configuration failure. Thrown before any network IO. */
326
+ declare function apiConfigMissing(providerId: SearchProviderId, message: string): SearchProviderError;
327
+ /**
328
+ * Make upstream text safe to put in an error message.
329
+ *
330
+ * Four passes, in this order because each depends on the last not having run:
331
+ * credential-valued JSON fields go first (they survive even for a key this
332
+ * process never held), then the configured secret VALUES, then bare
333
+ * `Bearer`/`Basic` tokens, then whole URLs. Whitespace collapse and the length
334
+ * cap come last, so the cap can never bisect a secret into a surviving half.
335
+ *
336
+ * Exported for the leak gate, which greps the output of every produced error.
337
+ */
338
+ declare function sanitizeUpstreamText(text: string, secrets?: ReadonlyArray<string | undefined>): string;
339
+
340
+ /**
341
+ * `zhipu` and `z.ai` — one wire contract, two provider ids.
342
+ *
343
+ * Ported from Elftia's `ZhipuProvider` (sha256 `2a9a0f5b…`, re-verified
344
+ * byte-identical against the 阶段0 manifest before porting), including the
345
+ * one-class-two-instances shape: the two services speak the same API and differ
346
+ * only in their default host, so the id is a constructor argument and the
347
+ * contributions factory registers two instances.
348
+ *
349
+ * Two ported quirks that later stages must not "fix":
350
+ *
351
+ * - **`maxResults` defaults to 10**, where every other adapter defaults to 5.
352
+ * That is the baseline's behavior and it is preserved deliberately; the
353
+ * orchestrator's normalization caps results at what the caller asked for
354
+ * anyway.
355
+ * - **Results carry `link`, not `url`.** The mapping is part of the wire
356
+ * contract, not a typo.
357
+ *
358
+ * @module search/api/ZhipuSearchProvider
359
+ */
360
+
361
+ /** The two ids this one class is registered under. */
362
+ declare const ZHIPU_PROVIDER_ID = "zhipu";
363
+ declare const ZAI_PROVIDER_ID = "z.ai";
364
+ /** Per-id default hosts, as in the baseline. */
365
+ declare const ZHIPU_DEFAULT_HOSTS: Readonly<Record<string, string>>;
366
+ /** The divergent default: 10, where every other adapter uses 5. */
367
+ declare const ZHIPU_DEFAULT_MAX_RESULTS = 10;
368
+ /**
369
+ * Point a configured host at the `/web_search` endpoint.
370
+ *
371
+ * Ported verbatim from the baseline, including which forms it accepts:
372
+ * an explicit `/web_search` is left alone, a bare version segment (`/v4`) gets
373
+ * `/web_search` appended, and anything else gets `/v4/web_search`.
374
+ */
375
+ declare function normalizeZhipuApiUrl(apiHost: string): string;
376
+ declare class ZhipuSearchProvider implements SearchProvider {
377
+ private readonly config;
378
+ private readonly transport;
379
+ readonly id: SearchProviderId;
380
+ private readonly rotator;
381
+ constructor(id: SearchProviderId, config: ZhipuProviderConfig, transport?: SearchApiTransport);
382
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
383
+ }
384
+
385
+ export { API_MAX_REDIRECTS, API_RESPONSE_BYTES, ApiKeyRotator, type ApiSearchContributionOptions, DEFAULT_API_TIMEOUT_MS, JINA_CAPABILITIES, JINA_DEFAULT_HOST, JINA_DEFAULT_MAX_RESULTS, JINA_PROVIDER_ID, JINA_READER_HOST, JinaProviderConfig, JinaReaderClient, JinaSearchProvider, SEARXNG_CAPABILITIES, SEARXNG_DEFAULT_MAX_RESULTS, SEARXNG_PROVIDER_ID, SearchApiFetch, SearchApiProviderConfigs, SearchApiTransport, type SearchApiTransportOptions, SearxngProviderConfig, SearxngSearchProvider, TAVILY_CAPABILITIES, TAVILY_DEFAULT_HOST, TAVILY_DEFAULT_MAX_RESULTS, TAVILY_PROVIDER_ID, TavilyProviderConfig, TavilySearchProvider, ZAI_PROVIDER_ID, ZHIPU_CAPABILITIES, ZHIPU_DEFAULT_HOSTS, ZHIPU_DEFAULT_MAX_RESULTS, ZHIPU_PROVIDER_ID, ZhipuProviderConfig, ZhipuSearchProvider, apiConfigMissing, apiSearchContributions, createSearchApiTransport, defaultSearchApiTransport, normalizeZhipuApiUrl, requireResultArray, sanitizeUpstreamText };