@omnicross/core 0.2.1 → 0.3.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 (65) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +57 -57
  3. package/README.md +22 -22
  4. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +3 -3
  5. package/dist/auth/GeminiCodeAssistProjectResolver.js +2 -2
  6. package/dist/{chunk-MPXOKQJP.cjs → chunk-2RCCLQYV.cjs} +1 -1
  7. package/dist/{chunk-Y4CRNHJO.js → chunk-4PFWFODB.js} +1 -1
  8. package/dist/{chunk-T6NWPIYZ.cjs → chunk-AKIOOFY3.cjs} +2 -1
  9. package/dist/{chunk-HL2YSPL7.cjs → chunk-BTBEJRGL.cjs} +140 -32
  10. package/dist/{chunk-NLUOTJWB.js → chunk-DXWFBBSK.js} +125 -17
  11. package/dist/{chunk-VSYQ6XYN.cjs → chunk-EY3S7NJ3.cjs} +498 -424
  12. package/dist/{chunk-HVBBDBS3.cjs → chunk-FHXDUHVE.cjs} +96 -9
  13. package/dist/{chunk-LFPQ2OVH.js → chunk-L7O2YQ5O.js} +1 -1
  14. package/dist/{chunk-VL5TUDTM.js → chunk-N5Q5PBV5.js} +6 -1
  15. package/dist/{chunk-MKF46GNZ.js → chunk-NJS2DZE6.js} +91 -4
  16. package/dist/{chunk-U47LQXPB.js → chunk-NRYLPGQB.js} +2 -1
  17. package/dist/{chunk-D4WNI6BR.cjs → chunk-PTU7SXM3.cjs} +2 -2
  18. package/dist/{chunk-4Z3ZLLC2.cjs → chunk-RS773ZL3.cjs} +13 -8
  19. package/dist/{chunk-LKDAN4D7.js → chunk-STENJNJU.js} +111 -37
  20. package/dist/{chunk-23S5OPIO.js → chunk-T2VIZQT4.js} +1 -1
  21. package/dist/{chunk-6QQG7YG3.cjs → chunk-T55Z77BR.cjs} +3 -3
  22. package/dist/{chunk-YNJNTCSQ.cjs → chunk-XGVPGH7V.cjs} +2 -2
  23. package/dist/{chunk-OPRS4IQZ.js → chunk-YVBHFVTF.js} +2 -2
  24. package/dist/completion/BuiltinToolExecutor.cjs +2 -2
  25. package/dist/completion/BuiltinToolExecutor.js +1 -1
  26. package/dist/completion/CompletionService.cjs +8 -8
  27. package/dist/completion/CompletionService.js +7 -7
  28. package/dist/completion.cjs +8 -8
  29. package/dist/completion.js +7 -7
  30. package/dist/index.cjs +8 -8
  31. package/dist/index.js +7 -7
  32. package/dist/outbound-api/routeResolver.cjs +2 -2
  33. package/dist/outbound-api/routeResolver.js +1 -1
  34. package/dist/outbound-api.cjs +8 -8
  35. package/dist/outbound-api.js +7 -7
  36. package/dist/pipeline/AccountAllowanceScheduling.cjs +3 -3
  37. package/dist/pipeline/AccountAllowanceScheduling.js +2 -2
  38. package/dist/pipeline/AccountAllowanceStore.cjs +6 -2
  39. package/dist/pipeline/AccountAllowanceStore.d.cts +41 -1
  40. package/dist/pipeline/AccountAllowanceStore.d.ts +41 -1
  41. package/dist/pipeline/AccountAllowanceStore.js +5 -1
  42. package/dist/pipeline/SubscriptionAuthSource.cjs +4 -4
  43. package/dist/pipeline/SubscriptionAuthSource.js +3 -3
  44. package/dist/pipeline/upstreamFetch.cjs +3 -3
  45. package/dist/pipeline/upstreamFetch.js +2 -2
  46. package/dist/provider-proxy/ProviderProxy.cjs +8 -8
  47. package/dist/provider-proxy/ProviderProxy.js +7 -7
  48. package/dist/provider-proxy/ingress/providerProxyShared.cjs +8 -8
  49. package/dist/provider-proxy/ingress/providerProxyShared.js +7 -7
  50. package/dist/provider-proxy.cjs +8 -8
  51. package/dist/provider-proxy.js +7 -7
  52. package/dist/runtime-5NCT3J3T.cjs +8 -0
  53. package/dist/{runtime-M5WXLD2R.js → runtime-JTHUWCBM.js} +2 -2
  54. package/dist/search/api.cjs +13 -8
  55. package/dist/search/api.d.cts +16 -1
  56. package/dist/search/api.d.ts +16 -1
  57. package/dist/search/api.js +10 -5
  58. package/dist/search/http.cjs +2 -2
  59. package/dist/search/http.d.cts +63 -9
  60. package/dist/search/http.d.ts +63 -9
  61. package/dist/search/http.js +1 -1
  62. package/dist/search.cjs +3 -3
  63. package/dist/search.js +2 -2
  64. package/package.json +3 -2
  65. package/dist/runtime-6QXNU526.cjs +0 -8
@@ -62,7 +62,7 @@ var API_RESPONSE_BYTES = 2 * 1024 * 1024;
62
62
  var MAX_UPSTREAM_TEXT = 300;
63
63
  function createSearchApiTransport(options = {}) {
64
64
  const policy = options.egressPolicy;
65
- const fetchImpl = _nullishCoalesce(options.fetch, () => ( createUndiciApiFetch(options.env, policy)));
65
+ const fetchImpl = _nullishCoalesce(options.fetch, () => ( createUndiciApiFetch(options.env, policy, options.resolveProxyDispatcher)));
66
66
  const maxRedirects = _nullishCoalesce(options.maxRedirects, () => ( API_MAX_REDIRECTS));
67
67
  return async (request) => {
68
68
  const context = {
@@ -122,14 +122,18 @@ function createSearchApiTransport(options = {}) {
122
122
  };
123
123
  }
124
124
  var defaultSearchApiTransport = createSearchApiTransport();
125
- function selectApiDispatcher(env, policy) {
125
+ function selectApiDispatcher(env, policy, override) {
126
+ if (_optionalChain([override, 'optionalAccess', _13 => _13.resolveProxyDispatcher])) {
127
+ const dispatcher = override.resolveProxyDispatcher(override.url);
128
+ if (dispatcher) return { dispatcher, proxied: true };
129
+ }
126
130
  const proxy = _chunk7RJI3NDIcjs.resolveSearchProxySettings.call(void 0, env);
127
131
  if (proxy) return { dispatcher: _chunk7RJI3NDIcjs.getSearchProxyDispatcher.call(void 0, proxy), proxied: true };
128
132
  return { dispatcher: _chunk7RJI3NDIcjs.createEgressGuardedDispatcher.call(void 0, policy), proxied: false };
129
133
  }
130
- function createUndiciApiFetch(env, policy) {
134
+ function createUndiciApiFetch(env, policy, resolveProxyDispatcher) {
131
135
  return async (url, init) => {
132
- const { dispatcher } = selectApiDispatcher(env, policy);
136
+ const { dispatcher } = selectApiDispatcher(env, policy, { url, resolveProxyDispatcher });
133
137
  return await _undici.fetch.call(void 0,
134
138
  url,
135
139
  { ...init, dispatcher }
@@ -168,7 +172,7 @@ async function fetchWithValidatedRedirects(fetchImpl, initialUrl, request, signa
168
172
  if (response.status < 300 || response.status >= 400) return response;
169
173
  const location = response.headers.get("location");
170
174
  if (!location) return response;
171
- void _optionalChain([response, 'access', _13 => _13.body, 'optionalAccess', _14 => _14.cancel, 'call', _15 => _15(), 'access', _16 => _16.catch, 'call', _17 => _17(() => void 0)]);
175
+ void _optionalChain([response, 'access', _14 => _14.body, 'optionalAccess', _15 => _15.cancel, 'call', _16 => _16(), 'access', _17 => _17.catch, 'call', _18 => _18(() => void 0)]);
172
176
  if (redirects === maxRedirects) throw tooManyRedirects(maxRedirects, context);
173
177
  let nextUrl;
174
178
  try {
@@ -208,7 +212,7 @@ function assertEgressAllowed(url, policy, context) {
208
212
  const denial = error;
209
213
  throw apiError(denial.code, denial.message, {
210
214
  stage: "egress",
211
- context: { ...context, host: _nullishCoalesce(_optionalChain([denial, 'access', _18 => _18.details, 'optionalAccess', _19 => _19.host]), () => ( context.host)) },
215
+ context: { ...context, host: _nullishCoalesce(_optionalChain([denial, 'access', _19 => _19.details, 'optionalAccess', _20 => _20.host]), () => ( context.host)) },
212
216
  retryable: false,
213
217
  cause: denial,
214
218
  details: denial.details
@@ -224,7 +228,7 @@ function tooManyRedirects(maxRedirects, context) {
224
228
  });
225
229
  }
226
230
  async function readJsonBodyWithLimit(response, context) {
227
- const reader = _optionalChain([response, 'access', _20 => _20.body, 'optionalAccess', _21 => _21.getReader, 'call', _22 => _22()]);
231
+ const reader = _optionalChain([response, 'access', _21 => _21.body, 'optionalAccess', _22 => _22.getReader, 'call', _23 => _23()]);
228
232
  if (!reader) return "";
229
233
  const chunks = [];
230
234
  let totalBytes = 0;
@@ -673,7 +677,8 @@ var ZHIPU_CAPABILITIES = Object.freeze({
673
677
  function apiSearchContributions(configs, options = {}) {
674
678
  const transport = createSearchApiTransport({
675
679
  fetch: options.fetchImpl,
676
- egressPolicy: options.egressPolicy
680
+ egressPolicy: options.egressPolicy,
681
+ resolveProxyDispatcher: options.resolveProxyDispatcher
677
682
  });
678
683
  const contributions = [];
679
684
  if (configs.tavily) {
@@ -1,10 +1,10 @@
1
1
  import { SearchProviderCapabilities, SearchProviderContribution, SearchProviderId, SearchOptions, SearchUrlReadResult, SearchProvider, SearchResult, SearchProviderError } from '@omnicross/contracts/search-types';
2
+ import { Dispatcher } from 'undici';
2
3
  import { S as SearchEgressPolicy } from '../egress-I46O_p5L.cjs';
3
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';
4
5
  export { d as SEARCH_API_TRANSPORT_ID, e as SearchApiRequest, f as SearchApiStage } from '../types-CbCZqLGg.cjs';
5
6
  import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.cjs';
6
7
  import 'node:dns';
7
- import 'undici';
8
8
 
9
9
  /**
10
10
  * The API search contributions.
@@ -44,6 +44,11 @@ interface ApiSearchContributionOptions {
44
44
  egressPolicy?: SearchEgressPolicy;
45
45
  /** Fetch primitive seam. Omit for the production undici transport. */
46
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;
47
52
  }
48
53
  /**
49
54
  * Build contributions for exactly the providers `configs` names.
@@ -286,6 +291,16 @@ interface SearchApiTransportOptions {
286
291
  fetch?: SearchApiFetch;
287
292
  /** Environment to read proxy variables from. Defaults to `process.env`. */
288
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;
289
304
  /** Egress policy. Defaults to public-only. */
290
305
  egressPolicy?: SearchEgressPolicy;
291
306
  /** Redirect hop cap. Defaults to {@link API_MAX_REDIRECTS}. */
@@ -1,10 +1,10 @@
1
1
  import { SearchProviderCapabilities, SearchProviderContribution, SearchProviderId, SearchOptions, SearchUrlReadResult, SearchProvider, SearchResult, SearchProviderError } from '@omnicross/contracts/search-types';
2
+ import { Dispatcher } from 'undici';
2
3
  import { S as SearchEgressPolicy } from '../egress-I46O_p5L.js';
3
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.js';
4
5
  export { d as SEARCH_API_TRANSPORT_ID, e as SearchApiRequest, f as SearchApiStage } from '../types-CbCZqLGg.js';
5
6
  import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.js';
6
7
  import 'node:dns';
7
- import 'undici';
8
8
 
9
9
  /**
10
10
  * The API search contributions.
@@ -44,6 +44,11 @@ interface ApiSearchContributionOptions {
44
44
  egressPolicy?: SearchEgressPolicy;
45
45
  /** Fetch primitive seam. Omit for the production undici transport. */
46
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;
47
52
  }
48
53
  /**
49
54
  * Build contributions for exactly the providers `configs` names.
@@ -286,6 +291,16 @@ interface SearchApiTransportOptions {
286
291
  fetch?: SearchApiFetch;
287
292
  /** Environment to read proxy variables from. Defaults to `process.env`. */
288
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;
289
304
  /** Egress policy. Defaults to public-only. */
290
305
  egressPolicy?: SearchEgressPolicy;
291
306
  /** Redirect hop cap. Defaults to {@link API_MAX_REDIRECTS}. */
@@ -62,7 +62,7 @@ var API_RESPONSE_BYTES = 2 * 1024 * 1024;
62
62
  var MAX_UPSTREAM_TEXT = 300;
63
63
  function createSearchApiTransport(options = {}) {
64
64
  const policy = options.egressPolicy;
65
- const fetchImpl = options.fetch ?? createUndiciApiFetch(options.env, policy);
65
+ const fetchImpl = options.fetch ?? createUndiciApiFetch(options.env, policy, options.resolveProxyDispatcher);
66
66
  const maxRedirects = options.maxRedirects ?? API_MAX_REDIRECTS;
67
67
  return async (request) => {
68
68
  const context = {
@@ -122,14 +122,18 @@ function createSearchApiTransport(options = {}) {
122
122
  };
123
123
  }
124
124
  var defaultSearchApiTransport = createSearchApiTransport();
125
- function selectApiDispatcher(env, policy) {
125
+ function selectApiDispatcher(env, policy, override) {
126
+ if (override?.resolveProxyDispatcher) {
127
+ const dispatcher = override.resolveProxyDispatcher(override.url);
128
+ if (dispatcher) return { dispatcher, proxied: true };
129
+ }
126
130
  const proxy = resolveSearchProxySettings(env);
127
131
  if (proxy) return { dispatcher: getSearchProxyDispatcher(proxy), proxied: true };
128
132
  return { dispatcher: createEgressGuardedDispatcher(policy), proxied: false };
129
133
  }
130
- function createUndiciApiFetch(env, policy) {
134
+ function createUndiciApiFetch(env, policy, resolveProxyDispatcher) {
131
135
  return async (url, init) => {
132
- const { dispatcher } = selectApiDispatcher(env, policy);
136
+ const { dispatcher } = selectApiDispatcher(env, policy, { url, resolveProxyDispatcher });
133
137
  return await undiciFetch(
134
138
  url,
135
139
  { ...init, dispatcher }
@@ -673,7 +677,8 @@ var ZHIPU_CAPABILITIES = Object.freeze({
673
677
  function apiSearchContributions(configs, options = {}) {
674
678
  const transport = createSearchApiTransport({
675
679
  fetch: options.fetchImpl,
676
- egressPolicy: options.egressPolicy
680
+ egressPolicy: options.egressPolicy,
681
+ resolveProxyDispatcher: options.resolveProxyDispatcher
677
682
  });
678
683
  const contributions = [];
679
684
  if (configs.tavily) {
@@ -15,7 +15,7 @@
15
15
 
16
16
 
17
17
 
18
- var _chunkHL2YSPL7cjs = require('../chunk-HL2YSPL7.cjs');
18
+ var _chunkBTBEJRGLcjs = require('../chunk-BTBEJRGL.cjs');
19
19
  require('../chunk-7RJI3NDI.cjs');
20
20
 
21
21
 
@@ -34,4 +34,4 @@ require('../chunk-7RJI3NDI.cjs');
34
34
 
35
35
 
36
36
 
37
- exports.DEFAULT_MAX_RESULTS = _chunkHL2YSPL7cjs.DEFAULT_MAX_RESULTS; exports.DEFAULT_SEARCH_TIMEOUT_MS = _chunkHL2YSPL7cjs.DEFAULT_SEARCH_TIMEOUT_MS; exports.HTTP_BING_PROVIDER_ID = _chunkHL2YSPL7cjs.HTTP_BING_PROVIDER_ID; exports.HTTP_DUCKDUCKGO_PROVIDER_ID = _chunkHL2YSPL7cjs.HTTP_DUCKDUCKGO_PROVIDER_ID; exports.HTTP_SEARCH_CAPABILITIES = _chunkHL2YSPL7cjs.HTTP_SEARCH_CAPABILITIES; exports.HttpBingProvider = _chunkHL2YSPL7cjs.HttpBingProvider; exports.HttpDuckDuckGoProvider = _chunkHL2YSPL7cjs.HttpDuckDuckGoProvider; exports.MAX_REDIRECTS = _chunkHL2YSPL7cjs.MAX_REDIRECTS; exports.MAX_RESULTS = _chunkHL2YSPL7cjs.MAX_RESULTS; exports.SEARCH_BROWSER_HEADERS = _chunkHL2YSPL7cjs.SEARCH_BROWSER_HEADERS; exports.SEARCH_HTTP_TRANSPORT_ID = _chunkHL2YSPL7cjs.SEARCH_HTTP_TRANSPORT_ID; exports.SEARCH_RESPONSE_BYTES = _chunkHL2YSPL7cjs.SEARCH_RESPONSE_BYTES; exports.builtinHttpSearchContributions = _chunkHL2YSPL7cjs.builtinHttpSearchContributions; exports.clampMaxResults = _chunkHL2YSPL7cjs.clampMaxResults; exports.createSearchHttpTransport = _chunkHL2YSPL7cjs.createSearchHttpTransport; exports.defaultSearchHttpTransport = _chunkHL2YSPL7cjs.defaultSearchHttpTransport;
37
+ exports.DEFAULT_MAX_RESULTS = _chunkBTBEJRGLcjs.DEFAULT_MAX_RESULTS; exports.DEFAULT_SEARCH_TIMEOUT_MS = _chunkBTBEJRGLcjs.DEFAULT_SEARCH_TIMEOUT_MS; exports.HTTP_BING_PROVIDER_ID = _chunkBTBEJRGLcjs.HTTP_BING_PROVIDER_ID; exports.HTTP_DUCKDUCKGO_PROVIDER_ID = _chunkBTBEJRGLcjs.HTTP_DUCKDUCKGO_PROVIDER_ID; exports.HTTP_SEARCH_CAPABILITIES = _chunkBTBEJRGLcjs.HTTP_SEARCH_CAPABILITIES; exports.HttpBingProvider = _chunkBTBEJRGLcjs.HttpBingProvider; exports.HttpDuckDuckGoProvider = _chunkBTBEJRGLcjs.HttpDuckDuckGoProvider; exports.MAX_REDIRECTS = _chunkBTBEJRGLcjs.MAX_REDIRECTS; exports.MAX_RESULTS = _chunkBTBEJRGLcjs.MAX_RESULTS; exports.SEARCH_BROWSER_HEADERS = _chunkBTBEJRGLcjs.SEARCH_BROWSER_HEADERS; exports.SEARCH_HTTP_TRANSPORT_ID = _chunkBTBEJRGLcjs.SEARCH_HTTP_TRANSPORT_ID; exports.SEARCH_RESPONSE_BYTES = _chunkBTBEJRGLcjs.SEARCH_RESPONSE_BYTES; exports.builtinHttpSearchContributions = _chunkBTBEJRGLcjs.builtinHttpSearchContributions; exports.clampMaxResults = _chunkBTBEJRGLcjs.clampMaxResults; exports.createSearchHttpTransport = _chunkBTBEJRGLcjs.createSearchHttpTransport; exports.defaultSearchHttpTransport = _chunkBTBEJRGLcjs.defaultSearchHttpTransport;
@@ -1,8 +1,10 @@
1
1
  import { SearchProviderId, SearchResult, SearchProviderCapabilities, SearchProviderContribution, SearchProvider, SearchOptions } from '@omnicross/contracts/search-types';
2
+ import { ProxyConfig } from '@omnicross/contracts/account-tokens-types';
3
+ import { Dispatcher } from 'undici';
2
4
  import { S as SearchEgressPolicy } from '../egress-I46O_p5L.cjs';
5
+ import { ImpitOptions, Impit } from 'impit';
3
6
  import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.cjs';
4
7
  import 'node:dns';
5
- import 'undici';
6
8
 
7
9
  /**
8
10
  * Shared vocabulary for the keyless HTTP search slice (plan 阶段2).
@@ -160,12 +162,13 @@ declare function clampMaxResults(maxResults: number | undefined): number;
160
162
  * This is the profile `packages/core/test-fixtures/http-search/` was captured
161
163
  * with, so changing it invalidates the fixtures as live-behavior evidence.
162
164
  *
163
- * Ported from Elftia's `webFetchHttp.browserHeaders()` with ONE deliberate
164
- * difference: the Chrome version is PINNED here instead of read from
165
- * `process.versions.chrome`. Elftia runs inside Electron and inherits a real
166
- * Chromium version; `@omnicross/core` runs in plain Node, where that field is
167
- * absent pinning keeps the sent profile identical across every host and
168
- * matches the spec's "pinned Chrome desktop User-Agent".
165
+ * Ported verbatim from Elftia's `webFetchHttp.browserHeaders()` a verified
166
+ * config; do not deviate from it. The Chromium version is read from the
167
+ * RUNTIME, exactly as Elftia does: `process.versions.chrome` inside an
168
+ * Electron host (a real, complete build number), and Elftia's own fixed
169
+ * fallback when no Chromium runtime reports one (plain Node). Never pin or
170
+ * invent a version string here a fabricated build number is a bot
171
+ * fingerprint no real browser ever sends.
169
172
  *
170
173
  * @module search/http/headers
171
174
  */
@@ -211,6 +214,34 @@ declare class HttpDuckDuckGoProvider implements SearchProvider {
211
214
  search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
212
215
  }
213
216
 
217
+ /**
218
+ * The browser-impersonating fetch primitive for the keyless HTTP slice.
219
+ *
220
+ * Ported from Elftia's `nodeWebFetchTransport` (the impit half): impit supplies
221
+ * a current-Chrome TLS/HTTP2 fingerprint, which is the difference between a
222
+ * real SERP and a bot-decoy page on engines that fingerprint the client
223
+ * handshake. This is a verified config — `browser`, `followRedirects` and
224
+ * `vanillaFallback` mirror Elftia exactly; do not deviate.
225
+ *
226
+ * Fixed semantics:
227
+ * - `followRedirects: false`, so the transport's manual, egress-validated
228
+ * redirect walk keeps sole ownership of hop decisions.
229
+ * - `vanillaFallback: false`: if the platform binary is unavailable we degrade
230
+ * to the bounded undici path IN THIS MODULE'S CALLER — never silently to a
231
+ * vanilla (non-impersonating) impit mode that would look like a browser and
232
+ * handshake like Node.
233
+ * - Request-specific `user-agent`/`sec-ch-ua*` headers are REMOVED, so the
234
+ * headers stay consistent with the impersonated fingerprint (impit sends its
235
+ * own matching set).
236
+ * - One client per proxy URL, cached; if `impit` cannot be imported at all the
237
+ * answer is `undefined` and the caller uses the undici fallback.
238
+ *
239
+ * @module search/http/impit
240
+ */
241
+
242
+ /** Structural constructor type — resilient to impit being absent at runtime. */
243
+ type ImpitConstructor = new (options?: ImpitOptions) => Impit;
244
+
214
245
  /**
215
246
  * The shared HTTP transport both keyless search providers run on.
216
247
  *
@@ -221,8 +252,14 @@ declare class HttpDuckDuckGoProvider implements SearchProvider {
221
252
  * `details.stage`.
222
253
  *
223
254
  * Fixed semantics:
224
- * - undici `fetch`, with an `EnvHttpProxyAgent` dispatcher when the environment
225
- * configures a proxy (cached per proxy signature).
255
+ * - impit first (Elftia's verified browser-impersonating client a real
256
+ * Chrome TLS/HTTP2 fingerprint; `followRedirects: false` keeps this
257
+ * transport's manual, egress-validated walk in charge), with the layered
258
+ * `resolveProxyConfig` as its proxy source. When the impit platform binary
259
+ * is unavailable, the bounded undici path serves instead, with a per-request
260
+ * proxy dispatcher: the layered `resolveProxyDispatcher` override first (the
261
+ * daemon's `fetchUpstream` resolver), else the `EnvHttpProxyAgent` the
262
+ * environment configures (cached per proxy signature).
226
263
  * - The pinned browser navigation header profile (see `./headers`).
227
264
  * - `redirect: 'manual'`, at most {@link MAX_REDIRECTS} hops, with the initial
228
265
  * URL and every hop target checked against the search egress policy
@@ -253,6 +290,23 @@ interface SearchHttpTransportOptions {
253
290
  fetch?: SearchHttpFetch;
254
291
  /** Environment to read proxy variables from. Defaults to `process.env`. */
255
292
  env?: ProxyEnvironment;
293
+ /**
294
+ * Layered proxy-dispatcher override for one request URL, AHEAD of the env
295
+ * layer. The daemon passes `fetchUpstream`'s resolver here so search egress
296
+ * follows the same `server.proxy` stack (global config, socks5 included) as
297
+ * LLM upstream traffic; a `NO_PROXY`/loopback target yields `undefined`
298
+ * inside that resolver and falls through to the env layer unchanged.
299
+ */
300
+ resolveProxyDispatcher?: (url: string) => Dispatcher | undefined;
301
+ /**
302
+ * Layered proxy CONFIG for one request URL — the impit path's proxy source,
303
+ * because impit takes a proxy URL, not an undici dispatcher. The daemon
304
+ * passes its `fetchUpstream`-layered resolver, so `server.proxy` (socks5
305
+ * included) governs impersonated requests exactly like LLM egress.
306
+ */
307
+ resolveProxyConfig?: (url: string) => ProxyConfig | undefined;
308
+ /** Test seam for the impit constructor loader. Omit for the real import. */
309
+ loadImpit?: () => Promise<ImpitConstructor | undefined>;
256
310
  /** Redirect hop cap. Defaults to {@link MAX_REDIRECTS}. */
257
311
  maxRedirects?: number;
258
312
  /**
@@ -1,8 +1,10 @@
1
1
  import { SearchProviderId, SearchResult, SearchProviderCapabilities, SearchProviderContribution, SearchProvider, SearchOptions } from '@omnicross/contracts/search-types';
2
+ import { ProxyConfig } from '@omnicross/contracts/account-tokens-types';
3
+ import { Dispatcher } from 'undici';
2
4
  import { S as SearchEgressPolicy } from '../egress-I46O_p5L.js';
5
+ import { ImpitOptions, Impit } from 'impit';
3
6
  import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.js';
4
7
  import 'node:dns';
5
- import 'undici';
6
8
 
7
9
  /**
8
10
  * Shared vocabulary for the keyless HTTP search slice (plan 阶段2).
@@ -160,12 +162,13 @@ declare function clampMaxResults(maxResults: number | undefined): number;
160
162
  * This is the profile `packages/core/test-fixtures/http-search/` was captured
161
163
  * with, so changing it invalidates the fixtures as live-behavior evidence.
162
164
  *
163
- * Ported from Elftia's `webFetchHttp.browserHeaders()` with ONE deliberate
164
- * difference: the Chrome version is PINNED here instead of read from
165
- * `process.versions.chrome`. Elftia runs inside Electron and inherits a real
166
- * Chromium version; `@omnicross/core` runs in plain Node, where that field is
167
- * absent pinning keeps the sent profile identical across every host and
168
- * matches the spec's "pinned Chrome desktop User-Agent".
165
+ * Ported verbatim from Elftia's `webFetchHttp.browserHeaders()` a verified
166
+ * config; do not deviate from it. The Chromium version is read from the
167
+ * RUNTIME, exactly as Elftia does: `process.versions.chrome` inside an
168
+ * Electron host (a real, complete build number), and Elftia's own fixed
169
+ * fallback when no Chromium runtime reports one (plain Node). Never pin or
170
+ * invent a version string here a fabricated build number is a bot
171
+ * fingerprint no real browser ever sends.
169
172
  *
170
173
  * @module search/http/headers
171
174
  */
@@ -211,6 +214,34 @@ declare class HttpDuckDuckGoProvider implements SearchProvider {
211
214
  search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
212
215
  }
213
216
 
217
+ /**
218
+ * The browser-impersonating fetch primitive for the keyless HTTP slice.
219
+ *
220
+ * Ported from Elftia's `nodeWebFetchTransport` (the impit half): impit supplies
221
+ * a current-Chrome TLS/HTTP2 fingerprint, which is the difference between a
222
+ * real SERP and a bot-decoy page on engines that fingerprint the client
223
+ * handshake. This is a verified config — `browser`, `followRedirects` and
224
+ * `vanillaFallback` mirror Elftia exactly; do not deviate.
225
+ *
226
+ * Fixed semantics:
227
+ * - `followRedirects: false`, so the transport's manual, egress-validated
228
+ * redirect walk keeps sole ownership of hop decisions.
229
+ * - `vanillaFallback: false`: if the platform binary is unavailable we degrade
230
+ * to the bounded undici path IN THIS MODULE'S CALLER — never silently to a
231
+ * vanilla (non-impersonating) impit mode that would look like a browser and
232
+ * handshake like Node.
233
+ * - Request-specific `user-agent`/`sec-ch-ua*` headers are REMOVED, so the
234
+ * headers stay consistent with the impersonated fingerprint (impit sends its
235
+ * own matching set).
236
+ * - One client per proxy URL, cached; if `impit` cannot be imported at all the
237
+ * answer is `undefined` and the caller uses the undici fallback.
238
+ *
239
+ * @module search/http/impit
240
+ */
241
+
242
+ /** Structural constructor type — resilient to impit being absent at runtime. */
243
+ type ImpitConstructor = new (options?: ImpitOptions) => Impit;
244
+
214
245
  /**
215
246
  * The shared HTTP transport both keyless search providers run on.
216
247
  *
@@ -221,8 +252,14 @@ declare class HttpDuckDuckGoProvider implements SearchProvider {
221
252
  * `details.stage`.
222
253
  *
223
254
  * Fixed semantics:
224
- * - undici `fetch`, with an `EnvHttpProxyAgent` dispatcher when the environment
225
- * configures a proxy (cached per proxy signature).
255
+ * - impit first (Elftia's verified browser-impersonating client a real
256
+ * Chrome TLS/HTTP2 fingerprint; `followRedirects: false` keeps this
257
+ * transport's manual, egress-validated walk in charge), with the layered
258
+ * `resolveProxyConfig` as its proxy source. When the impit platform binary
259
+ * is unavailable, the bounded undici path serves instead, with a per-request
260
+ * proxy dispatcher: the layered `resolveProxyDispatcher` override first (the
261
+ * daemon's `fetchUpstream` resolver), else the `EnvHttpProxyAgent` the
262
+ * environment configures (cached per proxy signature).
226
263
  * - The pinned browser navigation header profile (see `./headers`).
227
264
  * - `redirect: 'manual'`, at most {@link MAX_REDIRECTS} hops, with the initial
228
265
  * URL and every hop target checked against the search egress policy
@@ -253,6 +290,23 @@ interface SearchHttpTransportOptions {
253
290
  fetch?: SearchHttpFetch;
254
291
  /** Environment to read proxy variables from. Defaults to `process.env`. */
255
292
  env?: ProxyEnvironment;
293
+ /**
294
+ * Layered proxy-dispatcher override for one request URL, AHEAD of the env
295
+ * layer. The daemon passes `fetchUpstream`'s resolver here so search egress
296
+ * follows the same `server.proxy` stack (global config, socks5 included) as
297
+ * LLM upstream traffic; a `NO_PROXY`/loopback target yields `undefined`
298
+ * inside that resolver and falls through to the env layer unchanged.
299
+ */
300
+ resolveProxyDispatcher?: (url: string) => Dispatcher | undefined;
301
+ /**
302
+ * Layered proxy CONFIG for one request URL — the impit path's proxy source,
303
+ * because impit takes a proxy URL, not an undici dispatcher. The daemon
304
+ * passes its `fetchUpstream`-layered resolver, so `server.proxy` (socks5
305
+ * included) governs impersonated requests exactly like LLM egress.
306
+ */
307
+ resolveProxyConfig?: (url: string) => ProxyConfig | undefined;
308
+ /** Test seam for the impit constructor loader. Omit for the real import. */
309
+ loadImpit?: () => Promise<ImpitConstructor | undefined>;
256
310
  /** Redirect hop cap. Defaults to {@link MAX_REDIRECTS}. */
257
311
  maxRedirects?: number;
258
312
  /**
@@ -15,7 +15,7 @@ import {
15
15
  clampMaxResults,
16
16
  createSearchHttpTransport,
17
17
  defaultSearchHttpTransport
18
- } from "../chunk-NLUOTJWB.js";
18
+ } from "../chunk-DXWFBBSK.js";
19
19
  import "../chunk-DBBR6RHF.js";
20
20
  export {
21
21
  DEFAULT_MAX_RESULTS,
package/dist/search.cjs CHANGED
@@ -8,8 +8,8 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkD4WNI6BRcjs = require('./chunk-D4WNI6BR.cjs');
12
- require('./chunk-HL2YSPL7.cjs');
11
+ var _chunkPTU7SXM3cjs = require('./chunk-PTU7SXM3.cjs');
12
+ require('./chunk-BTBEJRGL.cjs');
13
13
 
14
14
 
15
15
 
@@ -54,4 +54,4 @@ var _chunkE4QHVXV5cjs = require('./chunk-E4QHVXV5.cjs');
54
54
 
55
55
 
56
56
 
57
- exports.DEFAULT_NORMALIZED_MAX_RESULTS = _chunkD4WNI6BRcjs.DEFAULT_NORMALIZED_MAX_RESULTS; exports.DEFAULT_SEARCH_EGRESS_POLICY = _chunk7RJI3NDIcjs.DEFAULT_SEARCH_EGRESS_POLICY; exports.DEFAULT_SEARCH_FRONTEND_MODES = _chunkE4QHVXV5cjs.DEFAULT_SEARCH_FRONTEND_MODES; exports.SEARCH_FRONTEND_MODES = _chunkE4QHVXV5cjs.SEARCH_FRONTEND_MODES; exports.SEARCH_FRONTEND_NAMES = _chunkE4QHVXV5cjs.SEARCH_FRONTEND_NAMES; exports.SEARCH_UNSUPPORTED_CAPABILITY_CODE = _chunkE4QHVXV5cjs.SEARCH_UNSUPPORTED_CAPABILITY_CODE; exports.SearchOrchestrator = _chunkD4WNI6BRcjs.SearchOrchestrator; exports.SearchProviderRegistry = _chunkD4WNI6BRcjs.SearchProviderRegistry; exports.SearchRegistryError = _chunkD4WNI6BRcjs.SearchRegistryError; exports.assertEgressAddressAllowed = _chunk7RJI3NDIcjs.assertEgressAddressAllowed; exports.createEgressGuardedDispatcher = _chunk7RJI3NDIcjs.createEgressGuardedDispatcher; exports.createEgressGuardedLookup = _chunk7RJI3NDIcjs.createEgressGuardedLookup; exports.createSearchRuntime = _chunkD4WNI6BRcjs.createSearchRuntime; exports.findEgressDenial = _chunk7RJI3NDIcjs.findEgressDenial; exports.hashSearchQuery = _chunkD4WNI6BRcjs.hashSearchQuery; exports.isDirectResultUrl = _chunkD4WNI6BRcjs.isDirectResultUrl; exports.isSearchFrontendMode = _chunkE4QHVXV5cjs.isSearchFrontendMode; exports.normalizeSearchFrontendModes = _chunkE4QHVXV5cjs.normalizeSearchFrontendModes; exports.normalizeSearchResults = _chunkD4WNI6BRcjs.normalizeSearchResults; exports.normalizedResultLimit = _chunkD4WNI6BRcjs.normalizedResultLimit; exports.searchErrorHttpStatus = _chunkE4QHVXV5cjs.searchErrorHttpStatus; exports.searchRuntimeAsWebSearchBackend = _chunkE4QHVXV5cjs.searchRuntimeAsWebSearchBackend; exports.validateEgressUrl = _chunk7RJI3NDIcjs.validateEgressUrl; exports.validateSearchFrontendModes = _chunkE4QHVXV5cjs.validateSearchFrontendModes;
57
+ exports.DEFAULT_NORMALIZED_MAX_RESULTS = _chunkPTU7SXM3cjs.DEFAULT_NORMALIZED_MAX_RESULTS; exports.DEFAULT_SEARCH_EGRESS_POLICY = _chunk7RJI3NDIcjs.DEFAULT_SEARCH_EGRESS_POLICY; exports.DEFAULT_SEARCH_FRONTEND_MODES = _chunkE4QHVXV5cjs.DEFAULT_SEARCH_FRONTEND_MODES; exports.SEARCH_FRONTEND_MODES = _chunkE4QHVXV5cjs.SEARCH_FRONTEND_MODES; exports.SEARCH_FRONTEND_NAMES = _chunkE4QHVXV5cjs.SEARCH_FRONTEND_NAMES; exports.SEARCH_UNSUPPORTED_CAPABILITY_CODE = _chunkE4QHVXV5cjs.SEARCH_UNSUPPORTED_CAPABILITY_CODE; exports.SearchOrchestrator = _chunkPTU7SXM3cjs.SearchOrchestrator; exports.SearchProviderRegistry = _chunkPTU7SXM3cjs.SearchProviderRegistry; exports.SearchRegistryError = _chunkPTU7SXM3cjs.SearchRegistryError; exports.assertEgressAddressAllowed = _chunk7RJI3NDIcjs.assertEgressAddressAllowed; exports.createEgressGuardedDispatcher = _chunk7RJI3NDIcjs.createEgressGuardedDispatcher; exports.createEgressGuardedLookup = _chunk7RJI3NDIcjs.createEgressGuardedLookup; exports.createSearchRuntime = _chunkPTU7SXM3cjs.createSearchRuntime; exports.findEgressDenial = _chunk7RJI3NDIcjs.findEgressDenial; exports.hashSearchQuery = _chunkPTU7SXM3cjs.hashSearchQuery; exports.isDirectResultUrl = _chunkPTU7SXM3cjs.isDirectResultUrl; exports.isSearchFrontendMode = _chunkE4QHVXV5cjs.isSearchFrontendMode; exports.normalizeSearchFrontendModes = _chunkE4QHVXV5cjs.normalizeSearchFrontendModes; exports.normalizeSearchResults = _chunkPTU7SXM3cjs.normalizeSearchResults; exports.normalizedResultLimit = _chunkPTU7SXM3cjs.normalizedResultLimit; exports.searchErrorHttpStatus = _chunkE4QHVXV5cjs.searchErrorHttpStatus; exports.searchRuntimeAsWebSearchBackend = _chunkE4QHVXV5cjs.searchRuntimeAsWebSearchBackend; exports.validateEgressUrl = _chunk7RJI3NDIcjs.validateEgressUrl; exports.validateSearchFrontendModes = _chunkE4QHVXV5cjs.validateSearchFrontendModes;
package/dist/search.js CHANGED
@@ -8,8 +8,8 @@ import {
8
8
  isDirectResultUrl,
9
9
  normalizeSearchResults,
10
10
  normalizedResultLimit
11
- } from "./chunk-LFPQ2OVH.js";
12
- import "./chunk-NLUOTJWB.js";
11
+ } from "./chunk-L7O2YQ5O.js";
12
+ import "./chunk-DXWFBBSK.js";
13
13
  import {
14
14
  DEFAULT_SEARCH_EGRESS_POLICY,
15
15
  assertEgressAddressAllowed,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnicross/core",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Omnicross LLM serving core — provider dispatch, completion pipeline, transformers, and the provider proxy.",
5
5
  "license": "MIT",
6
6
  "author": "Sayo (https://github.com/Dumoedss)",
@@ -56,9 +56,10 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "@mozilla/readability": "^0.6.0",
59
- "@omnicross/contracts": "^0.2.1",
59
+ "@omnicross/contracts": "^0.3.1",
60
60
  "busboy": "^1.6.0",
61
61
  "entities": "^6.0.1",
62
+ "impit": "^0.14.4",
62
63
  "jsdom": "^24.1.3",
63
64
  "sharp": "^0.35.4",
64
65
  "socks": "^2.8.3",
@@ -1,8 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
- var _chunkD4WNI6BRcjs = require('./chunk-D4WNI6BR.cjs');
4
- require('./chunk-HL2YSPL7.cjs');
5
- require('./chunk-7RJI3NDI.cjs');
6
-
7
-
8
- exports.createSearchRuntime = _chunkD4WNI6BRcjs.createSearchRuntime;