@omnicross/core 0.1.10 → 0.2.1

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