@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.
- package/LICENSE +21 -21
- package/NOTICE +57 -57
- package/README.md +22 -22
- package/dist/{chunk-MPXOKQJP.cjs → chunk-2RCCLQYV.cjs} +1 -1
- package/dist/{chunk-Y4CRNHJO.js → chunk-4PFWFODB.js} +1 -1
- package/dist/{chunk-HL2YSPL7.cjs → chunk-BTBEJRGL.cjs} +140 -32
- package/dist/{chunk-NLUOTJWB.js → chunk-DXWFBBSK.js} +125 -17
- package/dist/{chunk-LFPQ2OVH.js → chunk-L7O2YQ5O.js} +1 -1
- package/dist/{chunk-D4WNI6BR.cjs → chunk-PTU7SXM3.cjs} +2 -2
- package/dist/completion/BuiltinToolExecutor.cjs +2 -2
- package/dist/completion/BuiltinToolExecutor.js +1 -1
- package/dist/completion/CompletionService.cjs +1 -1
- package/dist/completion/CompletionService.js +1 -1
- package/dist/completion.cjs +2 -2
- package/dist/completion.js +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/dist/outbound-api.cjs +1 -1
- package/dist/outbound-api.js +1 -1
- package/dist/provider-proxy/ProviderProxy.cjs +1 -1
- package/dist/provider-proxy/ProviderProxy.js +1 -1
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +1 -1
- package/dist/provider-proxy/ingress/providerProxyShared.js +1 -1
- package/dist/provider-proxy.cjs +1 -1
- package/dist/provider-proxy.js +1 -1
- package/dist/runtime-5NCT3J3T.cjs +8 -0
- package/dist/{runtime-M5WXLD2R.js → runtime-JTHUWCBM.js} +2 -2
- package/dist/search/api.cjs +13 -8
- package/dist/search/api.d.cts +16 -1
- package/dist/search/api.d.ts +16 -1
- package/dist/search/api.js +10 -5
- package/dist/search/http.cjs +2 -2
- package/dist/search/http.d.cts +63 -9
- package/dist/search/http.d.ts +63 -9
- package/dist/search/http.js +1 -1
- package/dist/search.cjs +3 -3
- package/dist/search.js +2 -2
- package/package.json +3 -2
- 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-
|
|
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-
|
|
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: {
|
|
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 =
|
|
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 =
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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 = "
|
|
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, () => (
|
|
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',
|
|
325
|
-
_optionalChain([request, 'access',
|
|
326
|
-
if (_optionalChain([request, 'access',
|
|
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',
|
|
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',
|
|
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
|
|
460
|
+
function createProductionSearchFetch(options) {
|
|
380
461
|
return async (url, init) => {
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
573
|
-
url: cleanDuckDuckGoUrl(_nullishCoalesce(_optionalChain([link, 'optionalAccess',
|
|
574
|
-
content: cleanText(_optionalChain([container, 'access',
|
|
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',
|
|
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',
|
|
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 (
|
|
706
|
+
} catch (e7) {
|
|
599
707
|
return rawUrl;
|
|
600
708
|
}
|
|
601
709
|
}
|