@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,236 @@
|
|
|
1
|
+
// src/search/egress.ts
|
|
2
|
+
import { lookup as defaultDnsLookup } from "dns";
|
|
3
|
+
import { isIP } from "net";
|
|
4
|
+
import {
|
|
5
|
+
isSearchProviderError,
|
|
6
|
+
SearchProviderError
|
|
7
|
+
} from "@omnicross/contracts/search-types";
|
|
8
|
+
import { Agent } from "undici";
|
|
9
|
+
var DEFAULT_SEARCH_EGRESS_POLICY = Object.freeze({});
|
|
10
|
+
var ALLOWED_SCHEMES = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
11
|
+
var METADATA_HOSTNAMES = /* @__PURE__ */ new Set(["metadata.google.internal"]);
|
|
12
|
+
var DENIAL_TEXT = Object.freeze({
|
|
13
|
+
scheme: "only http and https are permitted",
|
|
14
|
+
malformed: "the request target is not a valid absolute URL",
|
|
15
|
+
loopback: "loopback addresses are not permitted",
|
|
16
|
+
unspecified: "unspecified addresses are not permitted",
|
|
17
|
+
"link-local": "link-local addresses are not permitted",
|
|
18
|
+
private: "private addresses are not permitted",
|
|
19
|
+
"unique-local": "unique-local addresses are not permitted",
|
|
20
|
+
metadata: "cloud metadata endpoints are not permitted"
|
|
21
|
+
});
|
|
22
|
+
function validateEgressUrl(url, policy = DEFAULT_SEARCH_EGRESS_POLICY, providerId) {
|
|
23
|
+
let parsed;
|
|
24
|
+
try {
|
|
25
|
+
parsed = url instanceof URL ? url : new URL(url);
|
|
26
|
+
} catch {
|
|
27
|
+
throw egressDenied("unknown-host", "malformed", providerId);
|
|
28
|
+
}
|
|
29
|
+
if (!ALLOWED_SCHEMES.has(parsed.protocol)) {
|
|
30
|
+
throw egressDenied(parsed.hostname || "unknown-host", "scheme", providerId, parsed.protocol);
|
|
31
|
+
}
|
|
32
|
+
const hostname = parsed.hostname;
|
|
33
|
+
if (isAllowlisted(hostname, policy)) return parsed;
|
|
34
|
+
const denial = classifyHostname(hostname);
|
|
35
|
+
if (denial) throw egressDenied(hostname, denial, providerId);
|
|
36
|
+
return parsed;
|
|
37
|
+
}
|
|
38
|
+
function assertEgressAddressAllowed(address, hostname, policy = DEFAULT_SEARCH_EGRESS_POLICY, providerId) {
|
|
39
|
+
if (isAllowlisted(hostname, policy)) return;
|
|
40
|
+
const denial = classifyAddress(address);
|
|
41
|
+
if (denial) throw egressDenied(hostname, denial, providerId, void 0, address);
|
|
42
|
+
}
|
|
43
|
+
function isAllowlisted(hostname, policy) {
|
|
44
|
+
const allowed = policy.allowedPrivateHosts;
|
|
45
|
+
if (!allowed || allowed.length === 0) return false;
|
|
46
|
+
const normalized = normalizeHostname(hostname);
|
|
47
|
+
return allowed.some((entry) => normalizeHostname(entry) === normalized);
|
|
48
|
+
}
|
|
49
|
+
function normalizeHostname(hostname) {
|
|
50
|
+
const trimmed = hostname.trim().toLowerCase().replace(/\.+$/, "");
|
|
51
|
+
return trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed;
|
|
52
|
+
}
|
|
53
|
+
function classifyHostname(hostname) {
|
|
54
|
+
const candidate = normalizeHostname(hostname);
|
|
55
|
+
if (candidate === "") return "malformed";
|
|
56
|
+
const version = isIP(candidate);
|
|
57
|
+
if (version !== 0) return classifyAddress(candidate);
|
|
58
|
+
if (candidate === "localhost" || candidate.endsWith(".localhost")) return "loopback";
|
|
59
|
+
if (METADATA_HOSTNAMES.has(candidate)) return "metadata";
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
function classifyAddress(address) {
|
|
63
|
+
const candidate = normalizeHostname(address);
|
|
64
|
+
const version = isIP(candidate);
|
|
65
|
+
if (version === 4) return classifyIPv4(candidate);
|
|
66
|
+
if (version === 6) return classifyIPv6(candidate);
|
|
67
|
+
return "malformed";
|
|
68
|
+
}
|
|
69
|
+
function classifyIPv4(address) {
|
|
70
|
+
const octets = address.split(".").map((part) => Number.parseInt(part, 10));
|
|
71
|
+
if (octets.length !== 4 || octets.some((octet) => !Number.isInteger(octet))) return "malformed";
|
|
72
|
+
const [a, b, c, d] = octets;
|
|
73
|
+
if (a === 127) return "loopback";
|
|
74
|
+
if (a === 0) return "unspecified";
|
|
75
|
+
if (a === 10) return "private";
|
|
76
|
+
if (a === 172 && b >= 16 && b <= 31) return "private";
|
|
77
|
+
if (a === 192 && b === 168) return "private";
|
|
78
|
+
if (a === 169 && b === 254 && c === 169 && d === 254) return "metadata";
|
|
79
|
+
if (a === 169 && b === 254) return "link-local";
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
function classifyIPv6(address) {
|
|
83
|
+
const pieces = parseIPv6Pieces(address);
|
|
84
|
+
if (!pieces) return "malformed";
|
|
85
|
+
const topIsZero = pieces.slice(0, 5).every((piece) => piece === 0);
|
|
86
|
+
if (topIsZero && (pieces[5] === 65535 || pieces[5] === 0)) {
|
|
87
|
+
const embedded = [pieces[6] >> 8, pieces[6] & 255, pieces[7] >> 8, pieces[7] & 255];
|
|
88
|
+
const isLoopbackOrUnspecified = pieces[5] === 0 && pieces[6] === 0 && pieces[7] <= 1;
|
|
89
|
+
if (isLoopbackOrUnspecified) return pieces[7] === 1 ? "loopback" : "unspecified";
|
|
90
|
+
return classifyIPv4(embedded.join("."));
|
|
91
|
+
}
|
|
92
|
+
if ((pieces[0] & 65472) === 65152) return "link-local";
|
|
93
|
+
if ((pieces[0] & 65024) === 64512) return "unique-local";
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
function parseIPv6Pieces(address) {
|
|
97
|
+
let text = address.split("%")[0];
|
|
98
|
+
const lastColon = text.lastIndexOf(":");
|
|
99
|
+
const tail = text.slice(lastColon + 1);
|
|
100
|
+
if (tail.includes(".")) {
|
|
101
|
+
if (isIP(tail) !== 4) return void 0;
|
|
102
|
+
const octets = tail.split(".").map((part) => Number.parseInt(part, 10));
|
|
103
|
+
const high = (octets[0] << 8 | octets[1]).toString(16);
|
|
104
|
+
const low = (octets[2] << 8 | octets[3]).toString(16);
|
|
105
|
+
text = `${text.slice(0, lastColon + 1)}${high}:${low}`;
|
|
106
|
+
}
|
|
107
|
+
const halves = text.split("::");
|
|
108
|
+
if (halves.length > 2) return void 0;
|
|
109
|
+
const head = halves[0] === "" ? [] : halves[0].split(":");
|
|
110
|
+
const rest = halves.length === 2 ? halves[1] === "" ? [] : halves[1].split(":") : [];
|
|
111
|
+
let groups;
|
|
112
|
+
if (halves.length === 1) {
|
|
113
|
+
if (head.length !== 8) return void 0;
|
|
114
|
+
groups = head;
|
|
115
|
+
} else {
|
|
116
|
+
const zeros = 8 - head.length - rest.length;
|
|
117
|
+
if (zeros < 1) return void 0;
|
|
118
|
+
groups = [...head, ...Array.from({ length: zeros }, () => "0"), ...rest];
|
|
119
|
+
}
|
|
120
|
+
const pieces = [];
|
|
121
|
+
for (const group of groups) {
|
|
122
|
+
if (!/^[0-9a-f]{1,4}$/i.test(group)) return void 0;
|
|
123
|
+
pieces.push(Number.parseInt(group, 16));
|
|
124
|
+
}
|
|
125
|
+
return pieces;
|
|
126
|
+
}
|
|
127
|
+
function egressDenied(hostname, reason, providerId, scheme, resolvedAddress) {
|
|
128
|
+
const subject = scheme ? `scheme "${scheme}"` : `host "${hostname}"`;
|
|
129
|
+
const via = resolvedAddress ? ` (resolved to a ${reason} address)` : "";
|
|
130
|
+
const details = { host: hostname, egressClass: reason };
|
|
131
|
+
if (resolvedAddress) details.egressStage = "dns";
|
|
132
|
+
return new SearchProviderError(
|
|
133
|
+
"policy_denied",
|
|
134
|
+
`egress policy denied ${subject}${via}: ${DENIAL_TEXT[reason]}`,
|
|
135
|
+
{
|
|
136
|
+
providerId,
|
|
137
|
+
retryable: false,
|
|
138
|
+
details
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function findEgressDenial(error) {
|
|
143
|
+
let current = error;
|
|
144
|
+
for (let depth = 0; depth < 6 && current !== void 0 && current !== null; depth += 1) {
|
|
145
|
+
if (isSearchProviderError(current) && current.code === "policy_denied") {
|
|
146
|
+
return current;
|
|
147
|
+
}
|
|
148
|
+
current = current instanceof Error ? current.cause : void 0;
|
|
149
|
+
}
|
|
150
|
+
return void 0;
|
|
151
|
+
}
|
|
152
|
+
function createEgressGuardedLookup(policy = DEFAULT_SEARCH_EGRESS_POLICY, lookupImpl = defaultDnsLookup) {
|
|
153
|
+
const guarded = (hostname, options, callback) => {
|
|
154
|
+
const requestedAll = Boolean(options?.all);
|
|
155
|
+
const lookupOptions = { ...options, all: true };
|
|
156
|
+
lookupImpl(hostname, lookupOptions, (error, addresses) => {
|
|
157
|
+
if (error) {
|
|
158
|
+
callback(error);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const entries = Array.isArray(addresses) ? addresses : [];
|
|
162
|
+
if (entries.length === 0) {
|
|
163
|
+
callback(new Error(`no addresses resolved for ${hostname}`));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
for (const entry of entries) assertEgressAddressAllowed(entry.address, hostname, policy);
|
|
168
|
+
} catch (denial) {
|
|
169
|
+
callback(denial);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (requestedAll) callback(null, entries);
|
|
173
|
+
else callback(null, entries[0].address, entries[0].family);
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
return guarded;
|
|
177
|
+
}
|
|
178
|
+
var guardedDispatchers = /* @__PURE__ */ new Map();
|
|
179
|
+
function createEgressGuardedDispatcher(policy = DEFAULT_SEARCH_EGRESS_POLICY, lookupImpl) {
|
|
180
|
+
if (lookupImpl) {
|
|
181
|
+
return new Agent({ connect: { lookup: createEgressGuardedLookup(policy, lookupImpl) } });
|
|
182
|
+
}
|
|
183
|
+
const signature = JSON.stringify(normalizePolicy(policy));
|
|
184
|
+
const cached = guardedDispatchers.get(signature);
|
|
185
|
+
if (cached) return cached;
|
|
186
|
+
const dispatcher = new Agent({ connect: { lookup: createEgressGuardedLookup(policy) } });
|
|
187
|
+
guardedDispatchers.set(signature, dispatcher);
|
|
188
|
+
return dispatcher;
|
|
189
|
+
}
|
|
190
|
+
function normalizePolicy(policy) {
|
|
191
|
+
return {
|
|
192
|
+
allowedPrivateHosts: [...policy.allowedPrivateHosts ?? []].map(normalizeHostname).sort((left, right) => left < right ? -1 : left > right ? 1 : 0)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/search/http/proxy.ts
|
|
197
|
+
import { EnvHttpProxyAgent } from "undici";
|
|
198
|
+
var cachedProxySignature = "";
|
|
199
|
+
var cachedProxyDispatcher;
|
|
200
|
+
function resolveSearchProxySettings(env = process.env) {
|
|
201
|
+
const allProxy = firstNonEmpty(env.all_proxy, env.ALL_PROXY);
|
|
202
|
+
const httpProxy = firstNonEmpty(env.http_proxy, env.HTTP_PROXY, allProxy);
|
|
203
|
+
const httpsProxy = firstNonEmpty(env.https_proxy, env.HTTPS_PROXY, allProxy);
|
|
204
|
+
if (!httpProxy && !httpsProxy) return void 0;
|
|
205
|
+
const noProxy = firstNonEmpty(env.no_proxy, env.NO_PROXY);
|
|
206
|
+
return {
|
|
207
|
+
...httpProxy ? { httpProxy } : {},
|
|
208
|
+
...httpsProxy ? { httpsProxy } : {},
|
|
209
|
+
...noProxy ? { noProxy } : {}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function getSearchProxyDispatcher(proxy) {
|
|
213
|
+
const signature = JSON.stringify(proxy);
|
|
214
|
+
if (cachedProxyDispatcher && cachedProxySignature === signature) return cachedProxyDispatcher;
|
|
215
|
+
cachedProxySignature = signature;
|
|
216
|
+
cachedProxyDispatcher = new EnvHttpProxyAgent(proxy);
|
|
217
|
+
return cachedProxyDispatcher;
|
|
218
|
+
}
|
|
219
|
+
function firstNonEmpty(...values) {
|
|
220
|
+
for (const value of values) {
|
|
221
|
+
const trimmed = value?.trim();
|
|
222
|
+
if (trimmed) return trimmed;
|
|
223
|
+
}
|
|
224
|
+
return void 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export {
|
|
228
|
+
DEFAULT_SEARCH_EGRESS_POLICY,
|
|
229
|
+
validateEgressUrl,
|
|
230
|
+
assertEgressAddressAllowed,
|
|
231
|
+
findEgressDenial,
|
|
232
|
+
createEgressGuardedLookup,
|
|
233
|
+
createEgressGuardedDispatcher,
|
|
234
|
+
resolveSearchProxySettings,
|
|
235
|
+
getSearchProxyDispatcher
|
|
236
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/search/frontends.ts
|
|
2
|
+
var SEARCH_FRONTEND_NAMES = Object.freeze([
|
|
3
|
+
"codex",
|
|
4
|
+
"responses",
|
|
5
|
+
"anthropic"
|
|
6
|
+
]);
|
|
7
|
+
var SEARCH_FRONTEND_MODES = Object.freeze([
|
|
8
|
+
"native",
|
|
9
|
+
"managed",
|
|
10
|
+
"off"
|
|
11
|
+
]);
|
|
12
|
+
var DEFAULT_SEARCH_FRONTEND_MODES = Object.freeze({
|
|
13
|
+
codex: "off",
|
|
14
|
+
responses: "native",
|
|
15
|
+
anthropic: "native"
|
|
16
|
+
});
|
|
17
|
+
var SEARCH_UNSUPPORTED_CAPABILITY_CODE = "unsupported_capability";
|
|
18
|
+
function searchErrorHttpStatus(code) {
|
|
19
|
+
switch (code) {
|
|
20
|
+
case "rate_limited":
|
|
21
|
+
return 429;
|
|
22
|
+
case "timeout":
|
|
23
|
+
return 504;
|
|
24
|
+
case "cancelled":
|
|
25
|
+
return 499;
|
|
26
|
+
case "config_missing":
|
|
27
|
+
return 503;
|
|
28
|
+
case "auth_failed":
|
|
29
|
+
case "upstream_unavailable":
|
|
30
|
+
case "parse_failed":
|
|
31
|
+
case "policy_denied":
|
|
32
|
+
return 502;
|
|
33
|
+
default:
|
|
34
|
+
return 502;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isSearchFrontendMode(value) {
|
|
38
|
+
return typeof value === "string" && SEARCH_FRONTEND_MODES.includes(value);
|
|
39
|
+
}
|
|
40
|
+
function record(value) {
|
|
41
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
42
|
+
}
|
|
43
|
+
function normalizeSearchFrontendModes(value) {
|
|
44
|
+
const raw = _nullishCoalesce(record(value), () => ( {}));
|
|
45
|
+
const modes = {
|
|
46
|
+
...DEFAULT_SEARCH_FRONTEND_MODES
|
|
47
|
+
};
|
|
48
|
+
for (const name of SEARCH_FRONTEND_NAMES) {
|
|
49
|
+
const candidate = raw[name];
|
|
50
|
+
if (isSearchFrontendMode(candidate)) modes[name] = candidate;
|
|
51
|
+
}
|
|
52
|
+
return Object.freeze(modes);
|
|
53
|
+
}
|
|
54
|
+
function validateSearchFrontendModes(value, path = "$.search.modes") {
|
|
55
|
+
if (value === void 0) return [];
|
|
56
|
+
const raw = record(value);
|
|
57
|
+
if (!raw) return [`${path}: expected an object`];
|
|
58
|
+
const errors = [];
|
|
59
|
+
for (const [key, candidate] of Object.entries(raw)) {
|
|
60
|
+
if (!SEARCH_FRONTEND_NAMES.includes(key)) {
|
|
61
|
+
errors.push(`${path}.${key}: unknown frontend (expected ${SEARCH_FRONTEND_NAMES.join(", ")})`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (isSearchFrontendMode(candidate)) continue;
|
|
65
|
+
errors.push(
|
|
66
|
+
`${path}.${key}: not a mode (got ${typeof candidate}; expected ${SEARCH_FRONTEND_MODES.join(", ")})`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return errors;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/search/webSearchBackendCompat.ts
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
var _searchcompat = require('@omnicross/contracts/search-compat');
|
|
77
|
+
var _searchtypes = require('@omnicross/contracts/search-types');
|
|
78
|
+
function searchRuntimeAsWebSearchBackend(runtime, options = {}) {
|
|
79
|
+
return {
|
|
80
|
+
async search(query, providerId, searchOptions) {
|
|
81
|
+
try {
|
|
82
|
+
const response = await runtime.search({
|
|
83
|
+
query,
|
|
84
|
+
provider: providerId,
|
|
85
|
+
// `WebSearchOptions` is a strict subset of `SearchOptions` with
|
|
86
|
+
// identical field names — asserted in the contracts tests.
|
|
87
|
+
...searchOptions === void 0 ? {} : { options: searchOptions }
|
|
88
|
+
});
|
|
89
|
+
return _searchcompat.toLegacyWebSearchResponse.call(void 0, response);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return _searchcompat.searchErrorToLegacyWebSearchResponse.call(void 0, query, _searchtypes.toSearchErrorShape.call(void 0, error));
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
isProviderEnabled(id) {
|
|
95
|
+
return runtime.listProviders().some((descriptor) => descriptor.id === id);
|
|
96
|
+
},
|
|
97
|
+
async readUrl(url, readOptions) {
|
|
98
|
+
if (options.readUrl !== void 0) return options.readUrl(url, readOptions);
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
url,
|
|
102
|
+
error: "URL reading is not available through the search runtime adapter"
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
exports.SEARCH_FRONTEND_NAMES = SEARCH_FRONTEND_NAMES; exports.SEARCH_FRONTEND_MODES = SEARCH_FRONTEND_MODES; exports.DEFAULT_SEARCH_FRONTEND_MODES = DEFAULT_SEARCH_FRONTEND_MODES; exports.SEARCH_UNSUPPORTED_CAPABILITY_CODE = SEARCH_UNSUPPORTED_CAPABILITY_CODE; exports.searchErrorHttpStatus = searchErrorHttpStatus; exports.isSearchFrontendMode = isSearchFrontendMode; exports.normalizeSearchFrontendModes = normalizeSearchFrontendModes; exports.validateSearchFrontendModes = validateSearchFrontendModes; exports.searchRuntimeAsWebSearchBackend = searchRuntimeAsWebSearchBackend;
|