@omnicross/core 0.1.10 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/{BuiltinToolExecutor-CS2WpXhM.d.cts → BuiltinToolExecutor-BHgH-EaZ.d.cts} +25 -2
- package/dist/{BuiltinToolExecutor-BluWyeob.d.ts → BuiltinToolExecutor-Bi1LmiTP.d.ts} +25 -2
- package/dist/{CompletionService-kNA17cfI.d.cts → CompletionService-BniP7j88.d.cts} +2 -2
- package/dist/{CompletionService-C3BX0Ovy.d.ts → CompletionService-BqrKPwfA.d.ts} +2 -2
- package/dist/{ProviderProxy-QdwNV6l1.d.cts → ProviderProxy-Bz_nkOwq.d.cts} +1 -1
- package/dist/{ProviderProxy--ROec6VI.d.ts → ProviderProxy-Ckr6oTrE.d.ts} +1 -1
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -6
- package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -4
- package/dist/{chunk-NGYOO5TO.js → chunk-2C3TTBS7.js} +7 -7
- package/dist/{chunk-QUSEZNYS.cjs → chunk-32SRZFFP.cjs} +4 -1
- package/dist/chunk-4JOU54M5.js +200 -0
- package/dist/{chunk-2UTGX6FM.js → chunk-4VVCXVB7.js} +1 -1
- package/dist/{chunk-RJUONLUQ.cjs → chunk-4Z3ZLLC2.cjs} +14 -8
- package/dist/chunk-6DDYNS2B.cjs +384 -0
- package/dist/{chunk-GXEZ2R3E.js → chunk-6OKXH2TW.js} +18 -7
- package/dist/{chunk-YWL7YZWS.cjs → chunk-7LRTPNFL.cjs} +5 -0
- package/dist/{chunk-CCVRRJOX.js → chunk-7PIUVCKK.js} +9 -2
- package/dist/chunk-7RJI3NDI.cjs +236 -0
- package/dist/{chunk-IIRPUVPH.cjs → chunk-7ZHBN75N.cjs} +3 -1
- package/dist/chunk-D4WNI6BR.cjs +386 -0
- package/dist/chunk-DBBR6RHF.js +236 -0
- package/dist/chunk-E4QHVXV5.cjs +118 -0
- package/dist/{chunk-HKB656B4.js → chunk-EUZRH544.js} +55 -287
- package/dist/{chunk-WNKWAEUR.js → chunk-EYGBM2VC.js} +3 -1
- package/dist/{chunk-UWDW6PN3.cjs → chunk-FX325I5Q.cjs} +20 -9
- package/dist/chunk-G4CZIUIB.cjs +200 -0
- package/dist/chunk-HCOQQAZE.cjs +123 -0
- package/dist/chunk-HL2YSPL7.cjs +673 -0
- package/dist/{chunk-55FMGZ3L.js → chunk-HN74IGEO.js} +1 -1
- package/dist/{chunk-ZY6KU6P3.js → chunk-HOMUGKHR.js} +8 -5
- package/dist/{chunk-AOFWNWLT.cjs → chunk-IUL4VWNU.cjs} +22 -1
- package/dist/{chunk-5LNYGCIW.cjs → chunk-KIQ2HA2A.cjs} +5 -5
- package/dist/{chunk-MUHWHQVM.cjs → chunk-KQBLZMP6.cjs} +4 -3
- package/dist/chunk-LFEH7CEO.js +384 -0
- package/dist/chunk-LFPQ2OVH.js +386 -0
- package/dist/{chunk-FEBAQI5A.js → chunk-LKDAN4D7.js} +6363 -1350
- package/dist/chunk-LQYS2N47.js +3923 -0
- package/dist/{chunk-NZYN7C3P.cjs → chunk-MPXOKQJP.cjs} +53 -53
- package/dist/chunk-MZEGQSKQ.js +118 -0
- package/dist/chunk-N76KU6F5.js +123 -0
- package/dist/chunk-NLUOTJWB.js +673 -0
- package/dist/{chunk-CMVXX7ON.cjs → chunk-NOITAVHA.cjs} +114 -58
- package/dist/{chunk-Q27JY5RG.cjs → chunk-OIKREZVQ.cjs} +7 -4
- package/dist/{chunk-ZQQUD66M.cjs → chunk-POUTD5AM.cjs} +63 -295
- package/dist/{chunk-6D4W22P4.js → chunk-QIIAMBTM.js} +4 -1
- package/dist/{chunk-56QD3YW6.cjs → chunk-QWNUOR7F.cjs} +11 -4
- package/dist/{chunk-S3DYFEBE.js → chunk-R4VCO2CB.js} +10 -1
- package/dist/{chunk-4VZX5F4T.cjs → chunk-T6NWPIYZ.cjs} +5 -2
- package/dist/{chunk-EBLFCNPY.js → chunk-U47LQXPB.js} +5 -2
- package/dist/chunk-UPQIWJIE.cjs +3923 -0
- package/dist/{chunk-N7OOJI5V.js → chunk-V2UKUTJ3.js} +5 -0
- package/dist/{chunk-45FHEOKW.js → chunk-V53ZEFXC.js} +92 -36
- package/dist/{chunk-RJ5ZGNI3.js → chunk-VL5TUDTM.js} +8 -2
- package/dist/{chunk-TIT74RIL.cjs → chunk-VSYQ6XYN.cjs} +6837 -1824
- package/dist/{chunk-OC6DOOFX.cjs → chunk-VXRTQZF2.cjs} +5 -5
- package/dist/{chunk-RICPANBY.cjs → chunk-WX2E2G7H.cjs} +13 -4
- package/dist/{chunk-DE2SRBFZ.js → chunk-X335TJNS.js} +4 -3
- package/dist/{chunk-CDHS2QDC.js → chunk-Y4CRNHJO.js} +53 -53
- package/dist/{chunk-P7EM6BND.cjs → chunk-ZAPN7XA6.cjs} +10 -10
- package/dist/{chunk-N2EIM2XJ.js → chunk-ZLNHPUFA.js} +22 -1
- package/dist/completion/BuiltinToolExecutor.cjs +2 -2
- package/dist/completion/BuiltinToolExecutor.d.cts +3 -1
- package/dist/completion/BuiltinToolExecutor.d.ts +3 -1
- package/dist/completion/BuiltinToolExecutor.js +1 -1
- package/dist/completion/CompletionService.cjs +32 -28
- package/dist/completion/CompletionService.d.cts +7 -3
- package/dist/completion/CompletionService.d.ts +7 -3
- package/dist/completion/CompletionService.js +31 -27
- package/dist/completion.cjs +40 -36
- package/dist/completion.d.cts +7 -3
- package/dist/completion.d.ts +7 -3
- package/dist/completion.js +39 -35
- package/dist/egress-I46O_p5L.d.cts +126 -0
- package/dist/egress-I46O_p5L.d.ts +126 -0
- package/dist/frontends-Doz0RaWu.d.cts +97 -0
- package/dist/frontends-Doz0RaWu.d.ts +97 -0
- package/dist/image-generation.cjs +52 -0
- package/dist/image-generation.d.cts +96 -0
- package/dist/image-generation.d.ts +96 -0
- package/dist/image-generation.js +52 -0
- package/dist/index.cjs +142 -32
- package/dist/index.d.cts +16 -8
- package/dist/index.d.ts +16 -8
- package/dist/index.js +159 -49
- package/dist/openai-operation.cjs +18 -0
- package/dist/openai-operation.d.cts +22 -0
- package/dist/openai-operation.d.ts +22 -0
- package/dist/openai-operation.js +18 -0
- package/dist/outbound-api/auditCapture.cjs +3 -3
- package/dist/outbound-api/auditCapture.d.cts +13 -2
- package/dist/outbound-api/auditCapture.d.ts +13 -2
- package/dist/outbound-api/auditCapture.js +2 -2
- package/dist/outbound-api/auditRedact.cjs +2 -2
- package/dist/outbound-api/auditRedact.js +1 -1
- package/dist/outbound-api/routeResolver.cjs +2 -2
- package/dist/outbound-api/routeResolver.d.cts +11 -4
- package/dist/outbound-api/routeResolver.d.ts +11 -4
- package/dist/outbound-api/routeResolver.js +1 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.cts +5 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.ts +5 -1
- package/dist/outbound-api/types.d.cts +10 -3
- package/dist/outbound-api/types.d.ts +10 -3
- package/dist/outbound-api.cjs +65 -33
- package/dist/outbound-api.d.cts +205 -10
- package/dist/outbound-api.d.ts +205 -10
- package/dist/outbound-api.js +64 -32
- package/dist/pipeline/AccountAllowanceScheduling.d.cts +22 -15
- package/dist/pipeline/AccountAllowanceScheduling.d.ts +22 -15
- package/dist/pipeline/LlmConfigProviderAuth.cjs +3 -3
- package/dist/pipeline/LlmConfigProviderAuth.js +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.cjs +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.d.cts +7 -0
- package/dist/pipeline/SubscriptionAccountHealth.d.ts +7 -0
- package/dist/pipeline/SubscriptionAccountHealth.js +1 -1
- package/dist/pipeline/executeProviderCall.cjs +2 -2
- package/dist/pipeline/executeProviderCall.d.cts +11 -6
- package/dist/pipeline/executeProviderCall.d.ts +11 -6
- package/dist/pipeline/executeProviderCall.js +1 -1
- package/dist/pipeline/upstreamFetch.cjs +2 -2
- package/dist/pipeline/upstreamFetch.d.cts +5 -0
- package/dist/pipeline/upstreamFetch.d.ts +5 -0
- package/dist/pipeline/upstreamFetch.js +1 -1
- package/dist/ports.d.cts +10 -3
- package/dist/ports.d.ts +10 -3
- package/dist/provider-proxy/ProviderProxy.cjs +32 -28
- package/dist/provider-proxy/ProviderProxy.d.cts +6 -2
- package/dist/provider-proxy/ProviderProxy.d.ts +6 -2
- package/dist/provider-proxy/ProviderProxy.js +31 -27
- package/dist/provider-proxy/identity/codexCliHeaders.cjs +4 -2
- package/dist/provider-proxy/identity/codexCliHeaders.d.cts +26 -6
- package/dist/provider-proxy/identity/codexCliHeaders.d.ts +26 -6
- package/dist/provider-proxy/identity/codexCliHeaders.js +5 -3
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +36 -28
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +41 -9
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +41 -9
- package/dist/provider-proxy/ingress/providerProxyShared.js +35 -27
- package/dist/provider-proxy/types.d.cts +17 -483
- package/dist/provider-proxy/types.d.ts +17 -483
- package/dist/provider-proxy.cjs +46 -28
- package/dist/provider-proxy.d.cts +34 -8
- package/dist/provider-proxy.d.ts +34 -8
- package/dist/provider-proxy.js +45 -27
- package/dist/proxy-UZTtjPZx.d.cts +18 -0
- package/dist/proxy-UZTtjPZx.d.ts +18 -0
- package/dist/{routeResolver-CVFE8KKe.d.cts → routeResolver-Da0yvkL1.d.cts} +4 -2
- package/dist/{routeResolver-C0mkkZaM.d.ts → routeResolver-STwMz_G4.d.ts} +4 -2
- package/dist/runtime-6QXNU526.cjs +8 -0
- package/dist/runtime-M5WXLD2R.js +8 -0
- package/dist/runtime-t8AZacFF.d.cts +233 -0
- package/dist/runtime-t8AZacFF.d.ts +233 -0
- package/dist/search/api.cjs +761 -0
- package/dist/search/api.d.cts +370 -0
- package/dist/search/api.d.ts +370 -0
- package/dist/search/api.js +761 -0
- package/dist/search/http.cjs +37 -0
- package/dist/search/http.d.cts +269 -0
- package/dist/search/http.d.ts +269 -0
- package/dist/search/http.js +37 -0
- package/dist/search.cjs +57 -0
- package/dist/search.d.cts +113 -0
- package/dist/search.d.ts +113 -0
- package/dist/search.js +57 -0
- package/dist/transformer/TransformerChainExecutor.cjs +2 -2
- package/dist/transformer/TransformerChainExecutor.d.cts +2 -2
- package/dist/transformer/TransformerChainExecutor.d.ts +2 -2
- package/dist/transformer/TransformerChainExecutor.js +1 -1
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.cjs +16 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.cts +53 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.ts +53 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.js +16 -0
- package/dist/transformer/transformers/AnthropicTransformer.cjs +4 -3
- package/dist/transformer/transformers/AnthropicTransformer.js +3 -2
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +4 -4
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +3 -3
- package/dist/transformer/transformers/GeminiTransformer.cjs +4 -4
- package/dist/transformer/transformers/GeminiTransformer.js +3 -3
- package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -3
- package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -2
- package/dist/transformer/transformers/OpenAITransformer.cjs +3 -3
- package/dist/transformer/transformers/OpenAITransformer.js +2 -2
- package/dist/transformer/transformers.cjs +11 -10
- package/dist/transformer/transformers.js +12 -11
- package/dist/transformer/types.d.cts +39 -4
- package/dist/transformer/types.d.ts +39 -4
- package/dist/transformer.cjs +14 -13
- package/dist/transformer.js +13 -12
- package/dist/types-BSIJdsyl.d.cts +1130 -0
- package/dist/types-Be-yt_6T.d.cts +196 -0
- package/dist/types-By9Tg6-I.d.ts +1130 -0
- package/dist/types-CbCZqLGg.d.cts +127 -0
- package/dist/types-CbCZqLGg.d.ts +127 -0
- package/dist/{types-C2MwkLah.d.cts → types-D-oHYusb.d.cts} +250 -21
- package/dist/types-Dm4_36V4.d.ts +196 -0
- package/dist/{types-BB8pxk_3.d.ts → types-Dvlpjn0d.d.ts} +250 -21
- package/dist/usage.cjs +2 -2
- package/dist/usage.d.cts +6 -1
- package/dist/usage.d.ts +6 -1
- package/dist/usage.js +1 -1
- package/package.json +71 -64
- package/dist/chunk-FCR77GYM.cjs +0 -33
- package/dist/chunk-K5NM7VAH.js +0 -33
- /package/dist/{chunk-XXFYLL7R.js → chunk-ECZ3ZE2C.js} +0 -0
- /package/dist/{chunk-3SCOLIPT.cjs → chunk-MXI2PWIC.cjs} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
var _chunkHL2YSPL7cjs = require('../chunk-HL2YSPL7.cjs');
|
|
19
|
+
require('../chunk-7RJI3NDI.cjs');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
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;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { SearchProviderId, SearchResult, SearchProviderCapabilities, SearchProviderContribution, SearchProvider, SearchOptions } from '@omnicross/contracts/search-types';
|
|
2
|
+
import { S as SearchEgressPolicy } from '../egress-I46O_p5L.cjs';
|
|
3
|
+
import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.cjs';
|
|
4
|
+
import 'node:dns';
|
|
5
|
+
import 'undici';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Shared vocabulary for the keyless HTTP search slice (plan 阶段2).
|
|
9
|
+
*
|
|
10
|
+
* Everything here is transport- and parser-neutral so the providers, the
|
|
11
|
+
* shared transport, and the doctor can agree on one set of names without
|
|
12
|
+
* importing each other.
|
|
13
|
+
*
|
|
14
|
+
* @module search/http/types
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The transport identity stamped on every failure this slice throws.
|
|
19
|
+
*
|
|
20
|
+
* Phase 1 ships exactly one transport. `impit` (Elftia's browser-fingerprint
|
|
21
|
+
* client) is deliberately NOT introduced here — the injection seam below is the
|
|
22
|
+
* whole extent of future-proofing, so an alternative transport can never become
|
|
23
|
+
* an implicit behavior change.
|
|
24
|
+
*/
|
|
25
|
+
declare const SEARCH_HTTP_TRANSPORT_ID = "undici";
|
|
26
|
+
/**
|
|
27
|
+
* Which phase of a search failed (plan §11.4 — transport identity and failure
|
|
28
|
+
* stage must be observable).
|
|
29
|
+
*
|
|
30
|
+
* - `connect` — the request never produced a response (DNS, TCP, TLS).
|
|
31
|
+
* - `fetch` — a response arrived but is unusable (refused status, deadline).
|
|
32
|
+
* - `redirect` — the redirect chain exceeded its cap.
|
|
33
|
+
* - `body-cap` — the response body outgrew its byte cap mid-stream.
|
|
34
|
+
* - `challenge` — the engine served a bot challenge instead of a SERP.
|
|
35
|
+
* - `trust` — the page parsed, but the anti-decoy check refused it.
|
|
36
|
+
* - `parse` — the page is not recognizable as this engine's SERP.
|
|
37
|
+
*/
|
|
38
|
+
type SearchHttpStage = 'connect' | 'fetch' | 'redirect' | 'body-cap' | 'challenge' | 'trust' | 'parse';
|
|
39
|
+
/** One fetched search page. */
|
|
40
|
+
interface SearchHttpResource {
|
|
41
|
+
/** The URL the response was finally served from (after redirects). */
|
|
42
|
+
finalUrl: string;
|
|
43
|
+
/** HTTP status of the final response. */
|
|
44
|
+
status: number;
|
|
45
|
+
/** `content-type` header value, or `''`. */
|
|
46
|
+
contentType: string;
|
|
47
|
+
/** Decoded response body. */
|
|
48
|
+
rawText: string;
|
|
49
|
+
}
|
|
50
|
+
/** What the transport needs to execute one attempt. */
|
|
51
|
+
interface SearchHttpRequest {
|
|
52
|
+
/** Hard budget for this single attempt, in milliseconds. */
|
|
53
|
+
timeoutMs: number;
|
|
54
|
+
/** Byte cap enforced while the body streams in. */
|
|
55
|
+
maxResponseBytes: number;
|
|
56
|
+
/** Caller cancellation. Aborting surfaces as code `cancelled`, never `timeout`. */
|
|
57
|
+
signal?: AbortSignal;
|
|
58
|
+
/** Stamped onto thrown errors so a failure names its provider. */
|
|
59
|
+
providerId?: SearchProviderId;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The seam both providers accept in their constructor.
|
|
63
|
+
*
|
|
64
|
+
* This is the test seam (fixtures are served through it) and the seam a future
|
|
65
|
+
* alternative transport would occupy.
|
|
66
|
+
*/
|
|
67
|
+
type SearchHttpTransport = (url: string, request: SearchHttpRequest) => Promise<SearchHttpResource>;
|
|
68
|
+
/**
|
|
69
|
+
* The low-level fetch primitive the shared transport drives — undici's `fetch`
|
|
70
|
+
* by default. Separate from {@link SearchHttpTransport} so redirect, body-cap
|
|
71
|
+
* and header behavior can be unit-tested without a network.
|
|
72
|
+
*/
|
|
73
|
+
type SearchHttpFetch = (url: string, init: RequestInit) => Promise<Response>;
|
|
74
|
+
/** The outcome of running one engine's parser over one page. */
|
|
75
|
+
interface ParsedSerp {
|
|
76
|
+
/**
|
|
77
|
+
* Whether the page is structurally recognizable as this engine's SERP.
|
|
78
|
+
*
|
|
79
|
+
* This is what separates "the engine found nothing" (recognized, zero
|
|
80
|
+
* results → `[]`) from "the engine's markup changed under us" (unrecognized
|
|
81
|
+
* → `parse_failed`).
|
|
82
|
+
*/
|
|
83
|
+
recognized: boolean;
|
|
84
|
+
/** Usable organic results, already clamped to the caller's `maxResults`. */
|
|
85
|
+
results: SearchResult[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The builtin HTTP search contributions.
|
|
90
|
+
*
|
|
91
|
+
* Everything the registry must not infer is declared here: `source` and `kind`
|
|
92
|
+
* are stated, never derived from the id's spelling, and the capability set is
|
|
93
|
+
* explicit down to the options these engines do NOT honor.
|
|
94
|
+
*
|
|
95
|
+
* `priorityHint` is deliberately absent. Provider ordering is the orchestrator's
|
|
96
|
+
* decision (阶段3); encoding a preference here would recreate exactly the
|
|
97
|
+
* scattered-fallback-order problem the extraction exists to remove.
|
|
98
|
+
*
|
|
99
|
+
* @module search/http/contributions
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* What both keyless HTTP engines can do.
|
|
104
|
+
*
|
|
105
|
+
* `supportsRegion` / `supportsLanguage` / `supportsTimeRange` are false because
|
|
106
|
+
* the scraped endpoints never honored those options; per the contract, a
|
|
107
|
+
* provider ignores an option it does not declare rather than failing.
|
|
108
|
+
*/
|
|
109
|
+
declare const HTTP_SEARCH_CAPABILITIES: Readonly<SearchProviderCapabilities>;
|
|
110
|
+
/**
|
|
111
|
+
* Both builtin HTTP providers, ready to hand to a registry.
|
|
112
|
+
*
|
|
113
|
+
* @param transport - optional shared transport for both providers (tests, or a
|
|
114
|
+
* future alternative client). Omit for the production undici transport.
|
|
115
|
+
*/
|
|
116
|
+
declare function builtinHttpSearchContributions(transport?: SearchHttpTransport): SearchProviderContribution[];
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The candidate-URL walk both HTTP providers share.
|
|
120
|
+
*
|
|
121
|
+
* Mirrors the baselined `searchWebViaFetch` loop (one shared deadline, split
|
|
122
|
+
* evenly across the remaining candidates, last error retained) with one
|
|
123
|
+
* plan-mandated behavior change: the three-way outcome distinction.
|
|
124
|
+
*
|
|
125
|
+
* Elftia collapses "the engine found nothing" and "the engine's markup changed"
|
|
126
|
+
* into a single `response contained no result entries` error. Here they are
|
|
127
|
+
* different answers:
|
|
128
|
+
*
|
|
129
|
+
* - a recognized SERP with zero organic results → `[]` (a legitimate answer);
|
|
130
|
+
* - an unrecognizable page → `parse_failed` (the parser-drift alarm);
|
|
131
|
+
* - a challenge or decoy page → a `challenge`/`trust` staged failure, checked
|
|
132
|
+
* before either of the above.
|
|
133
|
+
*
|
|
134
|
+
* The divergence is deliberate (plan §11.4) and is recorded for 阶段5's
|
|
135
|
+
* behavior-comparison report as an allowed difference.
|
|
136
|
+
*
|
|
137
|
+
* @module search/http/engine
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
/** Response byte cap at the search call sites (the fetch layer allows 5 MiB). */
|
|
141
|
+
declare const SEARCH_RESPONSE_BYTES: number;
|
|
142
|
+
/** Default budget for one whole search, across all its candidate URLs. */
|
|
143
|
+
declare const DEFAULT_SEARCH_TIMEOUT_MS = 15000;
|
|
144
|
+
/** `maxResults` clamp: [1, 10], defaulting to 5. */
|
|
145
|
+
declare const DEFAULT_MAX_RESULTS = 5;
|
|
146
|
+
declare const MAX_RESULTS = 10;
|
|
147
|
+
/**
|
|
148
|
+
* Clamp a caller's `maxResults` into the engine-supported range.
|
|
149
|
+
*
|
|
150
|
+
* `NaN` passes through to `slice(0, NaN)` and yields `[]`, exactly as the
|
|
151
|
+
* baseline does. Left at parity deliberately: normalizing pathological option
|
|
152
|
+
* values belongs to the runtime that owns option handling (阶段3), not to two
|
|
153
|
+
* providers that would then disagree with every other one.
|
|
154
|
+
*/
|
|
155
|
+
declare function clampMaxResults(maxResults: number | undefined): number;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The browser navigation header profile the search transport sends.
|
|
159
|
+
*
|
|
160
|
+
* This is the profile `packages/core/test-fixtures/http-search/` was captured
|
|
161
|
+
* with, so changing it invalidates the fixtures as live-behavior evidence.
|
|
162
|
+
*
|
|
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".
|
|
169
|
+
*
|
|
170
|
+
* @module search/http/headers
|
|
171
|
+
*/
|
|
172
|
+
/** The exact header set sent with every search request. */
|
|
173
|
+
declare const SEARCH_BROWSER_HEADERS: Readonly<Record<string, string>>;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* `http-bing` — keyless Bing search over the shared HTTP transport.
|
|
177
|
+
*
|
|
178
|
+
* Standalone by construction: `new HttpBingProvider()` works with no config, no
|
|
179
|
+
* registry and no host. Nothing in Phase 1 阶段2 registers or calls it — that is
|
|
180
|
+
* 阶段3's job.
|
|
181
|
+
*
|
|
182
|
+
* @module search/http/HttpBingProvider
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/** The id this provider registers under. */
|
|
186
|
+
declare const HTTP_BING_PROVIDER_ID = "http-bing";
|
|
187
|
+
declare class HttpBingProvider implements SearchProvider {
|
|
188
|
+
readonly id: SearchProviderId;
|
|
189
|
+
private readonly transport;
|
|
190
|
+
constructor(transport?: SearchHttpTransport);
|
|
191
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* `http-duckduckgo` — keyless DuckDuckGo search over the shared HTTP transport.
|
|
196
|
+
*
|
|
197
|
+
* Two candidate endpoints, tried in order under one shared deadline: the html
|
|
198
|
+
* endpoint first, then the lite endpoint. The lite endpoint is reached only when
|
|
199
|
+
* the html one produced no usable results (or failed outright) — the baselined
|
|
200
|
+
* behavior.
|
|
201
|
+
*
|
|
202
|
+
* @module search/http/HttpDuckDuckGoProvider
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
/** The id this provider registers under. */
|
|
206
|
+
declare const HTTP_DUCKDUCKGO_PROVIDER_ID = "http-duckduckgo";
|
|
207
|
+
declare class HttpDuckDuckGoProvider implements SearchProvider {
|
|
208
|
+
readonly id: SearchProviderId;
|
|
209
|
+
private readonly transport;
|
|
210
|
+
constructor(transport?: SearchHttpTransport);
|
|
211
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* The shared HTTP transport both keyless search providers run on.
|
|
216
|
+
*
|
|
217
|
+
* Ported from Elftia's `webFetchHttp.fetchWebResource` + `nodeWebFetchTransport`
|
|
218
|
+
* (baselined in `docs/design/search-baseline/elftia-search-baseline.md` §3.3),
|
|
219
|
+
* with the failure channel replaced: instead of bare `Error` strings, every
|
|
220
|
+
* failure is a `SearchProviderError` carrying `details.transport` and
|
|
221
|
+
* `details.stage`.
|
|
222
|
+
*
|
|
223
|
+
* Fixed semantics:
|
|
224
|
+
* - undici `fetch`, with an `EnvHttpProxyAgent` dispatcher when the environment
|
|
225
|
+
* configures a proxy (cached per proxy signature).
|
|
226
|
+
* - The pinned browser navigation header profile (see `./headers`).
|
|
227
|
+
* - `redirect: 'manual'`, at most {@link MAX_REDIRECTS} hops, with the initial
|
|
228
|
+
* URL and every hop target checked against the search egress policy
|
|
229
|
+
* (`../egress`). These two engines are fixed-host and keyless, so nothing an
|
|
230
|
+
* attacker controls picks the URL — but a redirect target is upstream input,
|
|
231
|
+
* and this is the seam 阶段2 identified and 阶段4 fills. The default policy
|
|
232
|
+
* permits every public host, so the fixed engines and the live `cn.bing.com`
|
|
233
|
+
* geo-redirect are unaffected.
|
|
234
|
+
* - A byte cap enforced WHILE the body streams — an oversized page fails, it is
|
|
235
|
+
* never silently truncated (this diverges from Elftia, which truncates and
|
|
236
|
+
* parses the fragment; the spec requires a `body-cap` failure).
|
|
237
|
+
* - One deadline per attempt; caller aborts surface as `cancelled`, the deadline
|
|
238
|
+
* as `timeout`, never conflated.
|
|
239
|
+
* - Compression is undici's business: it negotiates `Accept-Encoding` and
|
|
240
|
+
* decodes the response.
|
|
241
|
+
*
|
|
242
|
+
* `impit` is NOT used. undici is the sole Phase-1 transport; the injection seam
|
|
243
|
+
* below is the only future-proofing.
|
|
244
|
+
*
|
|
245
|
+
* @module search/http/transport
|
|
246
|
+
*/
|
|
247
|
+
|
|
248
|
+
/** Redirect hop cap. */
|
|
249
|
+
declare const MAX_REDIRECTS = 5;
|
|
250
|
+
/** Knobs for {@link createSearchHttpTransport}. */
|
|
251
|
+
interface SearchHttpTransportOptions {
|
|
252
|
+
/** The fetch primitive to drive. Defaults to undici's `fetch`. */
|
|
253
|
+
fetch?: SearchHttpFetch;
|
|
254
|
+
/** Environment to read proxy variables from. Defaults to `process.env`. */
|
|
255
|
+
env?: ProxyEnvironment;
|
|
256
|
+
/** Redirect hop cap. Defaults to {@link MAX_REDIRECTS}. */
|
|
257
|
+
maxRedirects?: number;
|
|
258
|
+
/**
|
|
259
|
+
* Egress policy for the initial URL and every redirect hop. Defaults to
|
|
260
|
+
* public-only, which is all these fixed-host engines ever need.
|
|
261
|
+
*/
|
|
262
|
+
egressPolicy?: SearchEgressPolicy;
|
|
263
|
+
}
|
|
264
|
+
/** Build a transport. Tests inject `fetch`; production takes the default. */
|
|
265
|
+
declare function createSearchHttpTransport(options?: SearchHttpTransportOptions): SearchHttpTransport;
|
|
266
|
+
/** The production transport: undici, reading proxy settings from `process.env`. */
|
|
267
|
+
declare const defaultSearchHttpTransport: SearchHttpTransport;
|
|
268
|
+
|
|
269
|
+
export { DEFAULT_MAX_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, HTTP_BING_PROVIDER_ID, HTTP_DUCKDUCKGO_PROVIDER_ID, HTTP_SEARCH_CAPABILITIES, HttpBingProvider, HttpDuckDuckGoProvider, MAX_REDIRECTS, MAX_RESULTS, type ParsedSerp, SEARCH_BROWSER_HEADERS, SEARCH_HTTP_TRANSPORT_ID, SEARCH_RESPONSE_BYTES, type SearchHttpFetch, type SearchHttpRequest, type SearchHttpResource, type SearchHttpStage, type SearchHttpTransport, type SearchHttpTransportOptions, builtinHttpSearchContributions, clampMaxResults, createSearchHttpTransport, defaultSearchHttpTransport };
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { SearchProviderId, SearchResult, SearchProviderCapabilities, SearchProviderContribution, SearchProvider, SearchOptions } from '@omnicross/contracts/search-types';
|
|
2
|
+
import { S as SearchEgressPolicy } from '../egress-I46O_p5L.js';
|
|
3
|
+
import { P as ProxyEnvironment } from '../proxy-UZTtjPZx.js';
|
|
4
|
+
import 'node:dns';
|
|
5
|
+
import 'undici';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Shared vocabulary for the keyless HTTP search slice (plan 阶段2).
|
|
9
|
+
*
|
|
10
|
+
* Everything here is transport- and parser-neutral so the providers, the
|
|
11
|
+
* shared transport, and the doctor can agree on one set of names without
|
|
12
|
+
* importing each other.
|
|
13
|
+
*
|
|
14
|
+
* @module search/http/types
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The transport identity stamped on every failure this slice throws.
|
|
19
|
+
*
|
|
20
|
+
* Phase 1 ships exactly one transport. `impit` (Elftia's browser-fingerprint
|
|
21
|
+
* client) is deliberately NOT introduced here — the injection seam below is the
|
|
22
|
+
* whole extent of future-proofing, so an alternative transport can never become
|
|
23
|
+
* an implicit behavior change.
|
|
24
|
+
*/
|
|
25
|
+
declare const SEARCH_HTTP_TRANSPORT_ID = "undici";
|
|
26
|
+
/**
|
|
27
|
+
* Which phase of a search failed (plan §11.4 — transport identity and failure
|
|
28
|
+
* stage must be observable).
|
|
29
|
+
*
|
|
30
|
+
* - `connect` — the request never produced a response (DNS, TCP, TLS).
|
|
31
|
+
* - `fetch` — a response arrived but is unusable (refused status, deadline).
|
|
32
|
+
* - `redirect` — the redirect chain exceeded its cap.
|
|
33
|
+
* - `body-cap` — the response body outgrew its byte cap mid-stream.
|
|
34
|
+
* - `challenge` — the engine served a bot challenge instead of a SERP.
|
|
35
|
+
* - `trust` — the page parsed, but the anti-decoy check refused it.
|
|
36
|
+
* - `parse` — the page is not recognizable as this engine's SERP.
|
|
37
|
+
*/
|
|
38
|
+
type SearchHttpStage = 'connect' | 'fetch' | 'redirect' | 'body-cap' | 'challenge' | 'trust' | 'parse';
|
|
39
|
+
/** One fetched search page. */
|
|
40
|
+
interface SearchHttpResource {
|
|
41
|
+
/** The URL the response was finally served from (after redirects). */
|
|
42
|
+
finalUrl: string;
|
|
43
|
+
/** HTTP status of the final response. */
|
|
44
|
+
status: number;
|
|
45
|
+
/** `content-type` header value, or `''`. */
|
|
46
|
+
contentType: string;
|
|
47
|
+
/** Decoded response body. */
|
|
48
|
+
rawText: string;
|
|
49
|
+
}
|
|
50
|
+
/** What the transport needs to execute one attempt. */
|
|
51
|
+
interface SearchHttpRequest {
|
|
52
|
+
/** Hard budget for this single attempt, in milliseconds. */
|
|
53
|
+
timeoutMs: number;
|
|
54
|
+
/** Byte cap enforced while the body streams in. */
|
|
55
|
+
maxResponseBytes: number;
|
|
56
|
+
/** Caller cancellation. Aborting surfaces as code `cancelled`, never `timeout`. */
|
|
57
|
+
signal?: AbortSignal;
|
|
58
|
+
/** Stamped onto thrown errors so a failure names its provider. */
|
|
59
|
+
providerId?: SearchProviderId;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The seam both providers accept in their constructor.
|
|
63
|
+
*
|
|
64
|
+
* This is the test seam (fixtures are served through it) and the seam a future
|
|
65
|
+
* alternative transport would occupy.
|
|
66
|
+
*/
|
|
67
|
+
type SearchHttpTransport = (url: string, request: SearchHttpRequest) => Promise<SearchHttpResource>;
|
|
68
|
+
/**
|
|
69
|
+
* The low-level fetch primitive the shared transport drives — undici's `fetch`
|
|
70
|
+
* by default. Separate from {@link SearchHttpTransport} so redirect, body-cap
|
|
71
|
+
* and header behavior can be unit-tested without a network.
|
|
72
|
+
*/
|
|
73
|
+
type SearchHttpFetch = (url: string, init: RequestInit) => Promise<Response>;
|
|
74
|
+
/** The outcome of running one engine's parser over one page. */
|
|
75
|
+
interface ParsedSerp {
|
|
76
|
+
/**
|
|
77
|
+
* Whether the page is structurally recognizable as this engine's SERP.
|
|
78
|
+
*
|
|
79
|
+
* This is what separates "the engine found nothing" (recognized, zero
|
|
80
|
+
* results → `[]`) from "the engine's markup changed under us" (unrecognized
|
|
81
|
+
* → `parse_failed`).
|
|
82
|
+
*/
|
|
83
|
+
recognized: boolean;
|
|
84
|
+
/** Usable organic results, already clamped to the caller's `maxResults`. */
|
|
85
|
+
results: SearchResult[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The builtin HTTP search contributions.
|
|
90
|
+
*
|
|
91
|
+
* Everything the registry must not infer is declared here: `source` and `kind`
|
|
92
|
+
* are stated, never derived from the id's spelling, and the capability set is
|
|
93
|
+
* explicit down to the options these engines do NOT honor.
|
|
94
|
+
*
|
|
95
|
+
* `priorityHint` is deliberately absent. Provider ordering is the orchestrator's
|
|
96
|
+
* decision (阶段3); encoding a preference here would recreate exactly the
|
|
97
|
+
* scattered-fallback-order problem the extraction exists to remove.
|
|
98
|
+
*
|
|
99
|
+
* @module search/http/contributions
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* What both keyless HTTP engines can do.
|
|
104
|
+
*
|
|
105
|
+
* `supportsRegion` / `supportsLanguage` / `supportsTimeRange` are false because
|
|
106
|
+
* the scraped endpoints never honored those options; per the contract, a
|
|
107
|
+
* provider ignores an option it does not declare rather than failing.
|
|
108
|
+
*/
|
|
109
|
+
declare const HTTP_SEARCH_CAPABILITIES: Readonly<SearchProviderCapabilities>;
|
|
110
|
+
/**
|
|
111
|
+
* Both builtin HTTP providers, ready to hand to a registry.
|
|
112
|
+
*
|
|
113
|
+
* @param transport - optional shared transport for both providers (tests, or a
|
|
114
|
+
* future alternative client). Omit for the production undici transport.
|
|
115
|
+
*/
|
|
116
|
+
declare function builtinHttpSearchContributions(transport?: SearchHttpTransport): SearchProviderContribution[];
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The candidate-URL walk both HTTP providers share.
|
|
120
|
+
*
|
|
121
|
+
* Mirrors the baselined `searchWebViaFetch` loop (one shared deadline, split
|
|
122
|
+
* evenly across the remaining candidates, last error retained) with one
|
|
123
|
+
* plan-mandated behavior change: the three-way outcome distinction.
|
|
124
|
+
*
|
|
125
|
+
* Elftia collapses "the engine found nothing" and "the engine's markup changed"
|
|
126
|
+
* into a single `response contained no result entries` error. Here they are
|
|
127
|
+
* different answers:
|
|
128
|
+
*
|
|
129
|
+
* - a recognized SERP with zero organic results → `[]` (a legitimate answer);
|
|
130
|
+
* - an unrecognizable page → `parse_failed` (the parser-drift alarm);
|
|
131
|
+
* - a challenge or decoy page → a `challenge`/`trust` staged failure, checked
|
|
132
|
+
* before either of the above.
|
|
133
|
+
*
|
|
134
|
+
* The divergence is deliberate (plan §11.4) and is recorded for 阶段5's
|
|
135
|
+
* behavior-comparison report as an allowed difference.
|
|
136
|
+
*
|
|
137
|
+
* @module search/http/engine
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
/** Response byte cap at the search call sites (the fetch layer allows 5 MiB). */
|
|
141
|
+
declare const SEARCH_RESPONSE_BYTES: number;
|
|
142
|
+
/** Default budget for one whole search, across all its candidate URLs. */
|
|
143
|
+
declare const DEFAULT_SEARCH_TIMEOUT_MS = 15000;
|
|
144
|
+
/** `maxResults` clamp: [1, 10], defaulting to 5. */
|
|
145
|
+
declare const DEFAULT_MAX_RESULTS = 5;
|
|
146
|
+
declare const MAX_RESULTS = 10;
|
|
147
|
+
/**
|
|
148
|
+
* Clamp a caller's `maxResults` into the engine-supported range.
|
|
149
|
+
*
|
|
150
|
+
* `NaN` passes through to `slice(0, NaN)` and yields `[]`, exactly as the
|
|
151
|
+
* baseline does. Left at parity deliberately: normalizing pathological option
|
|
152
|
+
* values belongs to the runtime that owns option handling (阶段3), not to two
|
|
153
|
+
* providers that would then disagree with every other one.
|
|
154
|
+
*/
|
|
155
|
+
declare function clampMaxResults(maxResults: number | undefined): number;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The browser navigation header profile the search transport sends.
|
|
159
|
+
*
|
|
160
|
+
* This is the profile `packages/core/test-fixtures/http-search/` was captured
|
|
161
|
+
* with, so changing it invalidates the fixtures as live-behavior evidence.
|
|
162
|
+
*
|
|
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".
|
|
169
|
+
*
|
|
170
|
+
* @module search/http/headers
|
|
171
|
+
*/
|
|
172
|
+
/** The exact header set sent with every search request. */
|
|
173
|
+
declare const SEARCH_BROWSER_HEADERS: Readonly<Record<string, string>>;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* `http-bing` — keyless Bing search over the shared HTTP transport.
|
|
177
|
+
*
|
|
178
|
+
* Standalone by construction: `new HttpBingProvider()` works with no config, no
|
|
179
|
+
* registry and no host. Nothing in Phase 1 阶段2 registers or calls it — that is
|
|
180
|
+
* 阶段3's job.
|
|
181
|
+
*
|
|
182
|
+
* @module search/http/HttpBingProvider
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/** The id this provider registers under. */
|
|
186
|
+
declare const HTTP_BING_PROVIDER_ID = "http-bing";
|
|
187
|
+
declare class HttpBingProvider implements SearchProvider {
|
|
188
|
+
readonly id: SearchProviderId;
|
|
189
|
+
private readonly transport;
|
|
190
|
+
constructor(transport?: SearchHttpTransport);
|
|
191
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* `http-duckduckgo` — keyless DuckDuckGo search over the shared HTTP transport.
|
|
196
|
+
*
|
|
197
|
+
* Two candidate endpoints, tried in order under one shared deadline: the html
|
|
198
|
+
* endpoint first, then the lite endpoint. The lite endpoint is reached only when
|
|
199
|
+
* the html one produced no usable results (or failed outright) — the baselined
|
|
200
|
+
* behavior.
|
|
201
|
+
*
|
|
202
|
+
* @module search/http/HttpDuckDuckGoProvider
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
/** The id this provider registers under. */
|
|
206
|
+
declare const HTTP_DUCKDUCKGO_PROVIDER_ID = "http-duckduckgo";
|
|
207
|
+
declare class HttpDuckDuckGoProvider implements SearchProvider {
|
|
208
|
+
readonly id: SearchProviderId;
|
|
209
|
+
private readonly transport;
|
|
210
|
+
constructor(transport?: SearchHttpTransport);
|
|
211
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* The shared HTTP transport both keyless search providers run on.
|
|
216
|
+
*
|
|
217
|
+
* Ported from Elftia's `webFetchHttp.fetchWebResource` + `nodeWebFetchTransport`
|
|
218
|
+
* (baselined in `docs/design/search-baseline/elftia-search-baseline.md` §3.3),
|
|
219
|
+
* with the failure channel replaced: instead of bare `Error` strings, every
|
|
220
|
+
* failure is a `SearchProviderError` carrying `details.transport` and
|
|
221
|
+
* `details.stage`.
|
|
222
|
+
*
|
|
223
|
+
* Fixed semantics:
|
|
224
|
+
* - undici `fetch`, with an `EnvHttpProxyAgent` dispatcher when the environment
|
|
225
|
+
* configures a proxy (cached per proxy signature).
|
|
226
|
+
* - The pinned browser navigation header profile (see `./headers`).
|
|
227
|
+
* - `redirect: 'manual'`, at most {@link MAX_REDIRECTS} hops, with the initial
|
|
228
|
+
* URL and every hop target checked against the search egress policy
|
|
229
|
+
* (`../egress`). These two engines are fixed-host and keyless, so nothing an
|
|
230
|
+
* attacker controls picks the URL — but a redirect target is upstream input,
|
|
231
|
+
* and this is the seam 阶段2 identified and 阶段4 fills. The default policy
|
|
232
|
+
* permits every public host, so the fixed engines and the live `cn.bing.com`
|
|
233
|
+
* geo-redirect are unaffected.
|
|
234
|
+
* - A byte cap enforced WHILE the body streams — an oversized page fails, it is
|
|
235
|
+
* never silently truncated (this diverges from Elftia, which truncates and
|
|
236
|
+
* parses the fragment; the spec requires a `body-cap` failure).
|
|
237
|
+
* - One deadline per attempt; caller aborts surface as `cancelled`, the deadline
|
|
238
|
+
* as `timeout`, never conflated.
|
|
239
|
+
* - Compression is undici's business: it negotiates `Accept-Encoding` and
|
|
240
|
+
* decodes the response.
|
|
241
|
+
*
|
|
242
|
+
* `impit` is NOT used. undici is the sole Phase-1 transport; the injection seam
|
|
243
|
+
* below is the only future-proofing.
|
|
244
|
+
*
|
|
245
|
+
* @module search/http/transport
|
|
246
|
+
*/
|
|
247
|
+
|
|
248
|
+
/** Redirect hop cap. */
|
|
249
|
+
declare const MAX_REDIRECTS = 5;
|
|
250
|
+
/** Knobs for {@link createSearchHttpTransport}. */
|
|
251
|
+
interface SearchHttpTransportOptions {
|
|
252
|
+
/** The fetch primitive to drive. Defaults to undici's `fetch`. */
|
|
253
|
+
fetch?: SearchHttpFetch;
|
|
254
|
+
/** Environment to read proxy variables from. Defaults to `process.env`. */
|
|
255
|
+
env?: ProxyEnvironment;
|
|
256
|
+
/** Redirect hop cap. Defaults to {@link MAX_REDIRECTS}. */
|
|
257
|
+
maxRedirects?: number;
|
|
258
|
+
/**
|
|
259
|
+
* Egress policy for the initial URL and every redirect hop. Defaults to
|
|
260
|
+
* public-only, which is all these fixed-host engines ever need.
|
|
261
|
+
*/
|
|
262
|
+
egressPolicy?: SearchEgressPolicy;
|
|
263
|
+
}
|
|
264
|
+
/** Build a transport. Tests inject `fetch`; production takes the default. */
|
|
265
|
+
declare function createSearchHttpTransport(options?: SearchHttpTransportOptions): SearchHttpTransport;
|
|
266
|
+
/** The production transport: undici, reading proxy settings from `process.env`. */
|
|
267
|
+
declare const defaultSearchHttpTransport: SearchHttpTransport;
|
|
268
|
+
|
|
269
|
+
export { DEFAULT_MAX_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, HTTP_BING_PROVIDER_ID, HTTP_DUCKDUCKGO_PROVIDER_ID, HTTP_SEARCH_CAPABILITIES, HttpBingProvider, HttpDuckDuckGoProvider, MAX_REDIRECTS, MAX_RESULTS, type ParsedSerp, SEARCH_BROWSER_HEADERS, SEARCH_HTTP_TRANSPORT_ID, SEARCH_RESPONSE_BYTES, type SearchHttpFetch, type SearchHttpRequest, type SearchHttpResource, type SearchHttpStage, type SearchHttpTransport, type SearchHttpTransportOptions, builtinHttpSearchContributions, clampMaxResults, createSearchHttpTransport, defaultSearchHttpTransport };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_MAX_RESULTS,
|
|
3
|
+
DEFAULT_SEARCH_TIMEOUT_MS,
|
|
4
|
+
HTTP_BING_PROVIDER_ID,
|
|
5
|
+
HTTP_DUCKDUCKGO_PROVIDER_ID,
|
|
6
|
+
HTTP_SEARCH_CAPABILITIES,
|
|
7
|
+
HttpBingProvider,
|
|
8
|
+
HttpDuckDuckGoProvider,
|
|
9
|
+
MAX_REDIRECTS,
|
|
10
|
+
MAX_RESULTS,
|
|
11
|
+
SEARCH_BROWSER_HEADERS,
|
|
12
|
+
SEARCH_HTTP_TRANSPORT_ID,
|
|
13
|
+
SEARCH_RESPONSE_BYTES,
|
|
14
|
+
builtinHttpSearchContributions,
|
|
15
|
+
clampMaxResults,
|
|
16
|
+
createSearchHttpTransport,
|
|
17
|
+
defaultSearchHttpTransport
|
|
18
|
+
} from "../chunk-NLUOTJWB.js";
|
|
19
|
+
import "../chunk-DBBR6RHF.js";
|
|
20
|
+
export {
|
|
21
|
+
DEFAULT_MAX_RESULTS,
|
|
22
|
+
DEFAULT_SEARCH_TIMEOUT_MS,
|
|
23
|
+
HTTP_BING_PROVIDER_ID,
|
|
24
|
+
HTTP_DUCKDUCKGO_PROVIDER_ID,
|
|
25
|
+
HTTP_SEARCH_CAPABILITIES,
|
|
26
|
+
HttpBingProvider,
|
|
27
|
+
HttpDuckDuckGoProvider,
|
|
28
|
+
MAX_REDIRECTS,
|
|
29
|
+
MAX_RESULTS,
|
|
30
|
+
SEARCH_BROWSER_HEADERS,
|
|
31
|
+
SEARCH_HTTP_TRANSPORT_ID,
|
|
32
|
+
SEARCH_RESPONSE_BYTES,
|
|
33
|
+
builtinHttpSearchContributions,
|
|
34
|
+
clampMaxResults,
|
|
35
|
+
createSearchHttpTransport,
|
|
36
|
+
defaultSearchHttpTransport
|
|
37
|
+
};
|
package/dist/search.cjs
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
var _chunkD4WNI6BRcjs = require('./chunk-D4WNI6BR.cjs');
|
|
12
|
+
require('./chunk-HL2YSPL7.cjs');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
var _chunk7RJI3NDIcjs = require('./chunk-7RJI3NDI.cjs');
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
var _chunkE4QHVXV5cjs = require('./chunk-E4QHVXV5.cjs');
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
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;
|