@omnicross/core 0.2.1 → 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 (39) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +57 -57
  3. package/README.md +22 -22
  4. package/dist/{chunk-MPXOKQJP.cjs → chunk-2RCCLQYV.cjs} +1 -1
  5. package/dist/{chunk-Y4CRNHJO.js → chunk-4PFWFODB.js} +1 -1
  6. package/dist/{chunk-HL2YSPL7.cjs → chunk-BTBEJRGL.cjs} +140 -32
  7. package/dist/{chunk-NLUOTJWB.js → chunk-DXWFBBSK.js} +125 -17
  8. package/dist/{chunk-LFPQ2OVH.js → chunk-L7O2YQ5O.js} +1 -1
  9. package/dist/{chunk-D4WNI6BR.cjs → chunk-PTU7SXM3.cjs} +2 -2
  10. package/dist/completion/BuiltinToolExecutor.cjs +2 -2
  11. package/dist/completion/BuiltinToolExecutor.js +1 -1
  12. package/dist/completion/CompletionService.cjs +1 -1
  13. package/dist/completion/CompletionService.js +1 -1
  14. package/dist/completion.cjs +2 -2
  15. package/dist/completion.js +1 -1
  16. package/dist/index.cjs +2 -2
  17. package/dist/index.js +1 -1
  18. package/dist/outbound-api.cjs +1 -1
  19. package/dist/outbound-api.js +1 -1
  20. package/dist/provider-proxy/ProviderProxy.cjs +1 -1
  21. package/dist/provider-proxy/ProviderProxy.js +1 -1
  22. package/dist/provider-proxy/ingress/providerProxyShared.cjs +1 -1
  23. package/dist/provider-proxy/ingress/providerProxyShared.js +1 -1
  24. package/dist/provider-proxy.cjs +1 -1
  25. package/dist/provider-proxy.js +1 -1
  26. package/dist/runtime-5NCT3J3T.cjs +8 -0
  27. package/dist/{runtime-M5WXLD2R.js → runtime-JTHUWCBM.js} +2 -2
  28. package/dist/search/api.cjs +13 -8
  29. package/dist/search/api.d.cts +16 -1
  30. package/dist/search/api.d.ts +16 -1
  31. package/dist/search/api.js +10 -5
  32. package/dist/search/http.cjs +2 -2
  33. package/dist/search/http.d.cts +63 -9
  34. package/dist/search/http.d.ts +63 -9
  35. package/dist/search/http.js +1 -1
  36. package/dist/search.cjs +3 -3
  37. package/dist/search.js +2 -2
  38. package/package.json +3 -2
  39. package/dist/runtime-6QXNU526.cjs +0 -8
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Sayo
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sayo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE CHANGED
@@ -1,57 +1,57 @@
1
- @omnicross/core — THIRD-PARTY NOTICES
2
- ======================================
3
-
4
- This package contains code adapted from, and depends on, the following
5
- third-party works. Their respective licenses apply to those portions.
6
-
7
- --------------------------------------------------------------------------------
8
- 1. musistudio/llms (MIT License)
9
- --------------------------------------------------------------------------------
10
-
11
- The transformer subsystem (`src/transformer/`) — the unified-IR request/response
12
- transformer chain (`TransformerService`, `TransformerChainExecutor`, and the
13
- built-in transformers) — is adapted from the `musistudio/llms` project, the
14
- upstream of the transformer intermediate representation.
15
-
16
- Copyright (c) 2025 musistudio
17
- https://github.com/musistudio/llms
18
-
19
- Permission is hereby granted, free of charge, to any person obtaining a copy
20
- of this software and associated documentation files (the "Software"), to deal
21
- in the Software without restriction, including without limitation the rights
22
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
- copies of the Software, and to permit persons to whom the Software is
24
- furnished to do so, subject to the following conditions:
25
-
26
- The above copyright notice and this permission notice shall be included in
27
- all copies or substantial portions of the Software.
28
-
29
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
- SOFTWARE.
36
-
37
- --------------------------------------------------------------------------------
38
- 2. @mozilla/readability (Apache License 2.0)
39
- --------------------------------------------------------------------------------
40
-
41
- The built-in web-fetch tool (`src/completion/builtin-web-fetch.ts`) uses
42
- `@mozilla/readability` to extract readable article content from fetched HTML.
43
-
44
- Copyright Mozilla Foundation and contributors
45
- https://github.com/mozilla/readability
46
-
47
- Licensed under the Apache License, Version 2.0 (the "License"); you may not
48
- use this file except in compliance with the License. You may obtain a copy of
49
- the License at
50
-
51
- http://www.apache.org/licenses/LICENSE-2.0
52
-
53
- Unless required by applicable law or agreed to in writing, software
54
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
55
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
56
- License for the specific language governing permissions and limitations under
57
- the License.
1
+ @omnicross/core — THIRD-PARTY NOTICES
2
+ ======================================
3
+
4
+ This package contains code adapted from, and depends on, the following
5
+ third-party works. Their respective licenses apply to those portions.
6
+
7
+ --------------------------------------------------------------------------------
8
+ 1. musistudio/llms (MIT License)
9
+ --------------------------------------------------------------------------------
10
+
11
+ The transformer subsystem (`src/transformer/`) — the unified-IR request/response
12
+ transformer chain (`TransformerService`, `TransformerChainExecutor`, and the
13
+ built-in transformers) — is adapted from the `musistudio/llms` project, the
14
+ upstream of the transformer intermediate representation.
15
+
16
+ Copyright (c) 2025 musistudio
17
+ https://github.com/musistudio/llms
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to deal
21
+ in the Software without restriction, including without limitation the rights
22
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in
27
+ all copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ SOFTWARE.
36
+
37
+ --------------------------------------------------------------------------------
38
+ 2. @mozilla/readability (Apache License 2.0)
39
+ --------------------------------------------------------------------------------
40
+
41
+ The built-in web-fetch tool (`src/completion/builtin-web-fetch.ts`) uses
42
+ `@mozilla/readability` to extract readable article content from fetched HTML.
43
+
44
+ Copyright Mozilla Foundation and contributors
45
+ https://github.com/mozilla/readability
46
+
47
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
48
+ use this file except in compliance with the License. You may obtain a copy of
49
+ the License at
50
+
51
+ http://www.apache.org/licenses/LICENSE-2.0
52
+
53
+ Unless required by applicable law or agreed to in writing, software
54
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
55
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
56
+ License for the specific language governing permissions and limitations under
57
+ the License.
package/README.md CHANGED
@@ -1,22 +1,22 @@
1
- # @omnicross/core
2
-
3
- The omnicross LLM serving core — provider dispatch, the completion pipeline, the transformer chain, the outbound API server, and the resident provider proxy. Embed it in any Node project, or run it via [`@omnicross/daemon`](https://www.npmjs.com/package/@omnicross/daemon).
4
-
5
- Part of the [omnicross](https://github.com/Dumoedss/omnicross) monorepo — see the root README for the full overview.
6
-
7
- ```bash
8
- npm install @omnicross/core @omnicross/contracts
9
- ```
10
-
11
- The published core runtime remains supported on Node.js `>=20.9`. The monorepo's
12
- official OpenAI JavaScript SDK contract suite is contributor tooling, uses
13
- `openai@7.8.x`, and requires Node.js 22 or newer. Run it from the repository root
14
- with `npm run test:images-sdk-contract`; the command checks the Node major before
15
- loading the SDK. The SDK is intentionally not a runtime or package-local
16
- development dependency of `@omnicross/core`.
17
-
18
- ## License
19
-
20
- [MIT](LICENSE)
21
-
22
- This package adapts third-party work under its own license — see the `NOTICE` file.
1
+ # @omnicross/core
2
+
3
+ The omnicross LLM serving core — provider dispatch, the completion pipeline, the transformer chain, the outbound API server, and the resident provider proxy. Embed it in any Node project, or run it via [`@omnicross/daemon`](https://www.npmjs.com/package/@omnicross/daemon).
4
+
5
+ Part of the [omnicross](https://github.com/Dumoedss/omnicross) monorepo — see the root README for the full overview.
6
+
7
+ ```bash
8
+ npm install @omnicross/core @omnicross/contracts
9
+ ```
10
+
11
+ The published core runtime remains supported on Node.js `>=20.9`. The monorepo's
12
+ official OpenAI JavaScript SDK contract suite is contributor tooling, uses
13
+ `openai@7.8.x`, and requires Node.js 22 or newer. Run it from the repository root
14
+ with `npm run test:images-sdk-contract`; the command checks the Node major before
15
+ loading the SDK. The SDK is intentionally not a runtime or package-local
16
+ development dependency of `@omnicross/core`.
17
+
18
+ ## License
19
+
20
+ [MIT](LICENSE)
21
+
22
+ This package adapts third-party work under its own license — see the `NOTICE` file.
@@ -109,7 +109,7 @@ var BuiltinToolExecutor = class {
109
109
  */
110
110
  getRuntime() {
111
111
  if (this.runtime !== void 0) return Promise.resolve(this.runtime);
112
- this.runtimeInit ??= Promise.resolve().then(() => _interopRequireWildcard(require("./runtime-6QXNU526.cjs"))).then(({ createSearchRuntime }) => {
112
+ this.runtimeInit ??= Promise.resolve().then(() => _interopRequireWildcard(require("./runtime-5NCT3J3T.cjs"))).then(({ createSearchRuntime }) => {
113
113
  this.runtime = createSearchRuntime();
114
114
  return this.runtime;
115
115
  });
@@ -109,7 +109,7 @@ var BuiltinToolExecutor = class {
109
109
  */
110
110
  getRuntime() {
111
111
  if (this.runtime !== void 0) return Promise.resolve(this.runtime);
112
- this.runtimeInit ??= import("./runtime-M5WXLD2R.js").then(({ createSearchRuntime }) => {
112
+ this.runtimeInit ??= import("./runtime-JTHUWCBM.js").then(({ createSearchRuntime }) => {
113
113
  this.runtime = createSearchRuntime();
114
114
  return this.runtime;
115
115
  });
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
2
2
 
3
3
 
4
4
 
@@ -20,7 +20,11 @@ function searchHttpError(code, message, init) {
20
20
  retryable: init.retryable,
21
21
  cause: init.cause,
22
22
  // transport/stage last so a caller-supplied `details` can never shadow them.
23
- details: { ...init.details, transport: SEARCH_HTTP_TRANSPORT_ID, stage: init.stage }
23
+ details: {
24
+ ...init.details,
25
+ transport: _nullishCoalesce(init.transport, () => ( SEARCH_HTTP_TRANSPORT_ID)),
26
+ stage: init.stage
27
+ }
24
28
  });
25
29
  }
26
30
  function asSearchProviderError(value, providerId, fallbackStage) {
@@ -223,18 +227,25 @@ function bingTrustError(query, html) {
223
227
  if (links.length === 0) return null;
224
228
  const terms = meaningfulQueryTerms(query);
225
229
  if (terms.length === 0) return null;
226
- const titleSearchable = links.map((link) => _nullishCoalesce(link.textContent, () => ( ""))).join(" ").normalize("NFKC").toLocaleLowerCase();
230
+ const titleSearchable = separatorFree(
231
+ links.map((link) => _nullishCoalesce(link.textContent, () => ( ""))).join(" ").normalize("NFKC").toLocaleLowerCase()
232
+ );
227
233
  if (!terms.some((term) => titleSearchable.includes(term))) {
228
234
  return "Bing returned an untrusted search result page with zero query-term hits in result titles; refusing to return possible bot-decoy content.";
229
235
  }
230
- const searchable = links.map((link) => {
231
- const container = link.closest("li.b_algo, .b_algo");
232
- return `${_nullishCoalesce(link.textContent, () => ( ""))} ${_nullishCoalesce(link.getAttribute("href"), () => ( ""))} ${_nullishCoalesce(_optionalChain([container, 'optionalAccess', _16 => _16.querySelector, 'call', _17 => _17(".b_caption p, .b_algoSlug, p"), 'optionalAccess', _18 => _18.textContent]), () => ( ""))}`;
233
- }).join(" ").normalize("NFKC").toLocaleLowerCase();
236
+ const searchable = separatorFree(
237
+ links.map((link) => {
238
+ const container = link.closest("li.b_algo, .b_algo");
239
+ return `${_nullishCoalesce(link.textContent, () => ( ""))} ${_nullishCoalesce(link.getAttribute("href"), () => ( ""))} ${_nullishCoalesce(_optionalChain([container, 'optionalAccess', _16 => _16.querySelector, 'call', _17 => _17(".b_caption p, .b_algoSlug, p"), 'optionalAccess', _18 => _18.textContent]), () => ( ""))}`;
240
+ }).join(" ").normalize("NFKC").toLocaleLowerCase()
241
+ );
234
242
  const coveredTerms = terms.filter((term) => searchable.includes(term));
235
243
  const requiredCoverage = terms.length === 1 ? 1 : 2;
236
244
  return new Set(coveredTerms).size >= requiredCoverage ? null : "Bing returned an untrusted search result page; refusing to return possible bot-decoy content.";
237
245
  }
246
+ function separatorFree(text) {
247
+ return text.replace(/[^\p{L}\p{N}\s]/gu, "");
248
+ }
238
249
  function meaningfulQueryTerms(query) {
239
250
  const terms = _nullishCoalesce(query.normalize("NFKC").toLocaleLowerCase().match(/[\p{L}\p{N}]{2,}/gu), () => ( []));
240
251
  const expanded = terms.flatMap((term) => {
@@ -285,8 +296,8 @@ function decoderFor(label) {
285
296
  }
286
297
 
287
298
  // src/search/http/headers.ts
288
- var CHROME_VERSION = "144.0.0.0";
289
- var CHROME_MAJOR = CHROME_VERSION.split(".")[0];
299
+ var CHROME_VERSION = _nullishCoalesce(process.versions.chrome, () => ( "152.0.7977.65"));
300
+ var CHROME_MAJOR = CHROME_VERSION.split(".")[0] || "152";
290
301
  var SEARCH_BROWSER_HEADERS = Object.freeze({
291
302
  "User-Agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${CHROME_VERSION} Safari/537.36`,
292
303
  Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
@@ -306,13 +317,82 @@ function searchBrowserHeaders() {
306
317
  return { ...SEARCH_BROWSER_HEADERS };
307
318
  }
308
319
 
320
+ // src/search/http/impit.ts
321
+ var IMPIT_BROWSER = "chrome151";
322
+ var IMPERSONATED_HEADERS = [
323
+ "sec-ch-ua",
324
+ "sec-ch-ua-mobile",
325
+ "sec-ch-ua-platform",
326
+ "user-agent"
327
+ ];
328
+ var TRANSPORT_KIND = /* @__PURE__ */ Symbol("searchFetchKind");
329
+ function tagFetchKind(error, kind) {
330
+ if (error instanceof Error) {
331
+ error[TRANSPORT_KIND] = kind;
332
+ }
333
+ }
334
+ function fetchKindOf(error) {
335
+ return _optionalChain([error, 'optionalAccess', _19 => _19[TRANSPORT_KIND]]);
336
+ }
337
+ var impitConstructorPromise;
338
+ var impitClients = /* @__PURE__ */ new Map();
339
+ function loadImpitConstructor() {
340
+ impitConstructorPromise ??= Promise.resolve().then(() => _interopRequireWildcard(require("impit"))).then((module) => module.Impit).catch(() => void 0);
341
+ return impitConstructorPromise;
342
+ }
343
+ async function getImpitClient(proxyUrl, load = loadImpitConstructor) {
344
+ const ImpitClient = await load();
345
+ if (!ImpitClient) return void 0;
346
+ const key = _nullishCoalesce(proxyUrl, () => ( "<direct>"));
347
+ const cached = impitClients.get(key);
348
+ if (cached) return cached;
349
+ const client = new ImpitClient({
350
+ browser: IMPIT_BROWSER,
351
+ followRedirects: false,
352
+ vanillaFallback: false,
353
+ ...proxyUrl ? { proxyUrl } : {}
354
+ });
355
+ impitClients.set(key, client);
356
+ return client;
357
+ }
358
+ function withImpersonatedHeaders(init) {
359
+ const headers = new Headers(init.headers);
360
+ for (const name of IMPERSONATED_HEADERS) headers.delete(name);
361
+ return { ...init, headers };
362
+ }
363
+ function proxyConfigToUrl(config) {
364
+ if ("url" in config) {
365
+ try {
366
+ const protocol = new URL(config.url).protocol;
367
+ if (protocol === "http:" || protocol === "https:") return config.url;
368
+ if (protocol === "socks5:" || protocol === "socks5h:") {
369
+ return `socks5h://${config.url.slice(protocol.length + 2)}`;
370
+ }
371
+ return void 0;
372
+ } catch (e6) {
373
+ return void 0;
374
+ }
375
+ }
376
+ if (!config.host || !Number.isFinite(config.port)) return void 0;
377
+ const auth = config.username ? `${encodeURIComponent(config.username)}:${encodeURIComponent(_nullishCoalesce(config.password, () => ( "")))}@` : "";
378
+ if (config.type !== "http" && config.type !== "https" && config.type !== "socks5") {
379
+ return void 0;
380
+ }
381
+ const scheme = config.type === "socks5" ? "socks5h" : config.type;
382
+ return `${scheme}://${auth}${config.host}:${config.port}`;
383
+ }
384
+ function impitProxyUrlFrom(resolve, url) {
385
+ const config = _optionalChain([resolve, 'optionalCall', _20 => _20(url)]);
386
+ return config ? proxyConfigToUrl(config) : void 0;
387
+ }
388
+
309
389
  // src/search/http/transport.ts
310
390
  var DEFAULT_TIMEOUT_MS = 3e4;
311
391
  var DEFAULT_MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
312
392
  var MAX_REDIRECTS = 5;
313
393
  var REFUSED_STATUSES = /* @__PURE__ */ new Set([401, 403, 407, 429]);
314
394
  function createSearchHttpTransport(options = {}) {
315
- const fetchImpl = _nullishCoalesce(options.fetch, () => ( createUndiciFetch(options.env)));
395
+ const fetchImpl = _nullishCoalesce(options.fetch, () => ( createProductionSearchFetch(options)));
316
396
  const maxRedirects = _nullishCoalesce(options.maxRedirects, () => ( MAX_REDIRECTS));
317
397
  const egressPolicy = options.egressPolicy;
318
398
  return async (url, request) => {
@@ -321,9 +401,9 @@ function createSearchHttpTransport(options = {}) {
321
401
  host: hostOf(url)
322
402
  };
323
403
  const controller = new AbortController();
324
- const onAbort = () => controller.abort(_optionalChain([request, 'access', _19 => _19.signal, 'optionalAccess', _20 => _20.reason]));
325
- _optionalChain([request, 'access', _21 => _21.signal, 'optionalAccess', _22 => _22.addEventListener, 'call', _23 => _23("abort", onAbort, { once: true })]);
326
- if (_optionalChain([request, 'access', _24 => _24.signal, 'optionalAccess', _25 => _25.aborted])) onAbort();
404
+ const onAbort = () => controller.abort(_optionalChain([request, 'access', _21 => _21.signal, 'optionalAccess', _22 => _22.reason]));
405
+ _optionalChain([request, 'access', _23 => _23.signal, 'optionalAccess', _24 => _24.addEventListener, 'call', _25 => _25("abort", onAbort, { once: true })]);
406
+ if (_optionalChain([request, 'access', _26 => _26.signal, 'optionalAccess', _27 => _27.aborted])) onAbort();
327
407
  const timeoutMs = _nullishCoalesce(request.timeoutMs, () => ( DEFAULT_TIMEOUT_MS));
328
408
  let deadlineExpired = false;
329
409
  const timer = setTimeout(() => {
@@ -350,7 +430,7 @@ function createSearchHttpTransport(options = {}) {
350
430
  assertNoBotChallenge(rawText, context);
351
431
  return { finalUrl, status: response.status, contentType, rawText };
352
432
  } catch (error) {
353
- if (_optionalChain([request, 'access', _26 => _26.signal, 'optionalAccess', _27 => _27.aborted])) {
433
+ if (_optionalChain([request, 'access', _28 => _28.signal, 'optionalAccess', _29 => _29.aborted])) {
354
434
  throw searchHttpError("cancelled", "search request was cancelled by the caller", {
355
435
  stage: "fetch",
356
436
  providerId: context.providerId,
@@ -365,28 +445,55 @@ function createSearchHttpTransport(options = {}) {
365
445
  providerId: context.providerId,
366
446
  retryable: true,
367
447
  cause: error,
448
+ transport: fetchKindOf(error),
368
449
  details: { host: context.host }
369
450
  });
370
451
  }
371
452
  throw asSearchProviderError(error, context.providerId, "fetch");
372
453
  } finally {
373
454
  clearTimeout(timer);
374
- _optionalChain([request, 'access', _28 => _28.signal, 'optionalAccess', _29 => _29.removeEventListener, 'call', _30 => _30("abort", onAbort)]);
455
+ _optionalChain([request, 'access', _30 => _30.signal, 'optionalAccess', _31 => _31.removeEventListener, 'call', _32 => _32("abort", onAbort)]);
375
456
  }
376
457
  };
377
458
  }
378
459
  var defaultSearchHttpTransport = createSearchHttpTransport();
379
- function createUndiciFetch(env) {
460
+ function createProductionSearchFetch(options) {
380
461
  return async (url, init) => {
381
- const proxy = _chunk7RJI3NDIcjs.resolveSearchProxySettings.call(void 0, env);
382
- const dispatcher = proxy ? _chunk7RJI3NDIcjs.getSearchProxyDispatcher.call(void 0, proxy) : void 0;
383
- const requestInit = dispatcher ? { ...init, dispatcher } : init;
384
- return await _undici.fetch.call(void 0,
385
- url,
386
- requestInit
387
- );
462
+ const client = await getImpitClient(
463
+ impitProxyUrlFrom(options.resolveProxyConfig, url),
464
+ options.loadImpit
465
+ ).catch(() => void 0);
466
+ if (client) {
467
+ try {
468
+ return await client.fetch(
469
+ url,
470
+ withImpersonatedHeaders(init)
471
+ );
472
+ } catch (error) {
473
+ tagFetchKind(error, "impit");
474
+ throw error;
475
+ }
476
+ }
477
+ try {
478
+ const dispatcher = selectHttpDispatcher(options.env, url, options.resolveProxyDispatcher);
479
+ const requestInit = dispatcher ? { ...init, dispatcher } : init;
480
+ return await _undici.fetch.call(void 0,
481
+ url,
482
+ requestInit
483
+ );
484
+ } catch (error) {
485
+ tagFetchKind(error, "undici");
486
+ throw error;
487
+ }
388
488
  };
389
489
  }
490
+ function selectHttpDispatcher(env, url, resolveProxyDispatcher) {
491
+ return _nullishCoalesce(_optionalChain([resolveProxyDispatcher, 'optionalCall', _33 => _33(url)]), () => ( envProxyDispatcher(env)));
492
+ }
493
+ function envProxyDispatcher(env) {
494
+ const proxy = _chunk7RJI3NDIcjs.resolveSearchProxySettings.call(void 0, env);
495
+ return proxy ? _chunk7RJI3NDIcjs.getSearchProxyDispatcher.call(void 0, proxy) : void 0;
496
+ }
390
497
  async function fetchWithRedirectLimit(fetchImpl, url, signal, maxRedirects, context, egressPolicy) {
391
498
  let currentUrl = url;
392
499
  assertEgressAllowed(currentUrl, egressPolicy, "connect", context);
@@ -406,6 +513,7 @@ async function fetchWithRedirectLimit(fetchImpl, url, signal, maxRedirects, cont
406
513
  providerId: context.providerId,
407
514
  retryable: true,
408
515
  cause: error,
516
+ transport: fetchKindOf(error),
409
517
  details: { host: context.host }
410
518
  });
411
519
  }
@@ -414,7 +522,7 @@ async function fetchWithRedirectLimit(fetchImpl, url, signal, maxRedirects, cont
414
522
  }
415
523
  const location = response.headers.get("location");
416
524
  if (!location) return { response, finalUrl: currentUrl };
417
- void _optionalChain([response, 'access', _31 => _31.body, 'optionalAccess', _32 => _32.cancel, 'call', _33 => _33(), 'access', _34 => _34.catch, 'call', _35 => _35(() => void 0)]);
525
+ void _optionalChain([response, 'access', _34 => _34.body, 'optionalAccess', _35 => _35.cancel, 'call', _36 => _36(), 'access', _37 => _37.catch, 'call', _38 => _38(() => void 0)]);
418
526
  if (redirects === maxRedirects) throw tooManyRedirects(maxRedirects, context);
419
527
  const nextUrl = new URL(location, currentUrl).href;
420
528
  assertEgressAllowed(nextUrl, egressPolicy, "redirect", context);
@@ -445,7 +553,7 @@ function tooManyRedirects(maxRedirects, context) {
445
553
  });
446
554
  }
447
555
  async function readBodyWithLimit(response, maxResponseBytes, context) {
448
- const reader = _optionalChain([response, 'access', _36 => _36.body, 'optionalAccess', _37 => _37.getReader, 'call', _38 => _38()]);
556
+ const reader = _optionalChain([response, 'access', _39 => _39.body, 'optionalAccess', _40 => _40.getReader, 'call', _41 => _41()]);
449
557
  if (!reader) return "";
450
558
  const chunks = [];
451
559
  let totalBytes = 0;
@@ -491,7 +599,7 @@ function assertStatusUsable(status, context) {
491
599
  }
492
600
  function assertNoBotChallenge(html, context) {
493
601
  if (!/<(?:html|body|title|script)\b/i.test(html)) return;
494
- const title = _optionalChain([html, 'access', _39 => _39.match, 'call', _40 => _40(/<title[^>]*>(.*?)<\/title>/is), 'optionalAccess', _41 => _41[1], 'access', _42 => _42.replace, 'call', _43 => _43(/<[^>]+>/g, " "), 'access', _44 => _44.replace, 'call', _45 => _45(/\s+/g, " "), 'access', _46 => _46.trim, 'call', _47 => _47()]);
602
+ const title = _optionalChain([html, 'access', _42 => _42.match, 'call', _43 => _43(/<title[^>]*>(.*?)<\/title>/is), 'optionalAccess', _44 => _44[1], 'access', _45 => _45.replace, 'call', _46 => _46(/<[^>]+>/g, " "), 'access', _47 => _47.replace, 'call', _48 => _48(/\s+/g, " "), 'access', _49 => _49.trim, 'call', _50 => _50()]);
495
603
  const challengeTitle = /^(?:just a moment|attention required|access denied|robot check|security check)/i.test(
496
604
  _nullishCoalesce(title, () => ( ""))
497
605
  );
@@ -569,9 +677,9 @@ function parseDuckDuckGoSerp(html, maxResults) {
569
677
  ].map((container) => {
570
678
  const link = container.querySelector("a.result__a, .result__a");
571
679
  return {
572
- title: cleanText(_optionalChain([link, 'optionalAccess', _48 => _48.textContent])),
573
- url: cleanDuckDuckGoUrl(_nullishCoalesce(_optionalChain([link, 'optionalAccess', _49 => _49.href]), () => ( ""))),
574
- content: cleanText(_optionalChain([container, 'access', _50 => _50.querySelector, 'call', _51 => _51(".result__snippet, .result__body"), 'optionalAccess', _52 => _52.textContent]))
680
+ title: cleanText(_optionalChain([link, 'optionalAccess', _51 => _51.textContent])),
681
+ url: cleanDuckDuckGoUrl(_nullishCoalesce(_optionalChain([link, 'optionalAccess', _52 => _52.href]), () => ( ""))),
682
+ content: cleanText(_optionalChain([container, 'access', _53 => _53.querySelector, 'call', _54 => _54(".result__snippet, .result__body"), 'optionalAccess', _55 => _55.textContent]))
575
683
  };
576
684
  }).filter(isUsableResult);
577
685
  if (htmlResults.length > 0) {
@@ -581,11 +689,11 @@ function parseDuckDuckGoSerp(html, maxResults) {
581
689
  ...document.querySelectorAll("a.result-link")
582
690
  ].map((link) => {
583
691
  const row = link.closest("tr");
584
- const snippet = _optionalChain([row, 'optionalAccess', _53 => _53.nextElementSibling, 'optionalAccess', _54 => _54.querySelector, 'call', _55 => _55(".result-snippet")]);
692
+ const snippet = _optionalChain([row, 'optionalAccess', _56 => _56.nextElementSibling, 'optionalAccess', _57 => _57.querySelector, 'call', _58 => _58(".result-snippet")]);
585
693
  return {
586
694
  title: cleanText(link.textContent),
587
695
  url: cleanDuckDuckGoUrl(link.href),
588
- content: cleanText(_optionalChain([snippet, 'optionalAccess', _56 => _56.textContent]))
696
+ content: cleanText(_optionalChain([snippet, 'optionalAccess', _59 => _59.textContent]))
589
697
  };
590
698
  }).filter(isUsableResult).slice(0, maxResults);
591
699
  return { recognized: isDuckDuckGoSerp(document), results: liteResults };
@@ -595,7 +703,7 @@ function cleanDuckDuckGoUrl(rawUrl) {
595
703
  const absoluteUrl = rawUrl.startsWith("//") ? `https:${rawUrl}` : rawUrl;
596
704
  const url = new URL(absoluteUrl, "https://html.duckduckgo.com");
597
705
  return _nullishCoalesce(url.searchParams.get("uddg"), () => ( url.href));
598
- } catch (e6) {
706
+ } catch (e7) {
599
707
  return rawUrl;
600
708
  }
601
709
  }