@omnicross/core 0.2.0 → 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/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-BiJqftc-.d.cts → CompletionService-BniP7j88.d.cts} +2 -2
- package/dist/{CompletionService-NXN_Av5W.d.ts → CompletionService-BqrKPwfA.d.ts} +2 -2
- package/dist/{ProviderProxy-CgIcCVwk.d.cts → ProviderProxy-Bz_nkOwq.d.cts} +1 -1
- package/dist/{ProviderProxy-DYoY5XoT.d.ts → ProviderProxy-Ckr6oTrE.d.ts} +1 -1
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +2 -2
- package/dist/auth/GeminiCodeAssistProjectResolver.js +1 -1
- package/dist/{chunk-FJNKXOWE.js → chunk-2C3TTBS7.js} +4 -4
- package/dist/{chunk-NZYN7C3P.cjs → chunk-2RCCLQYV.cjs} +53 -53
- package/dist/{chunk-CDHS2QDC.js → chunk-4PFWFODB.js} +53 -53
- package/dist/{chunk-OST5RJOJ.cjs → chunk-4Z3ZLLC2.cjs} +13 -7
- package/dist/chunk-7RJI3NDI.cjs +236 -0
- package/dist/chunk-BTBEJRGL.cjs +781 -0
- package/dist/chunk-DBBR6RHF.js +236 -0
- package/dist/chunk-DXWFBBSK.js +781 -0
- package/dist/chunk-E4QHVXV5.cjs +118 -0
- package/dist/chunk-L7O2YQ5O.js +386 -0
- package/dist/{chunk-WSJE42SG.js → chunk-LKDAN4D7.js} +3684 -2462
- package/dist/{chunk-DEIUR2TH.js → chunk-LQYS2N47.js} +12 -8
- package/dist/chunk-MZEGQSKQ.js +118 -0
- package/dist/chunk-PTU7SXM3.cjs +386 -0
- package/dist/{chunk-CTKM773J.cjs → chunk-UPQIWJIE.cjs} +12 -8
- package/dist/{chunk-CFSGYFOZ.js → chunk-VL5TUDTM.js} +7 -1
- package/dist/{chunk-7B56AJBB.cjs → chunk-VSYQ6XYN.cjs} +2233 -1011
- package/dist/{chunk-TVYA5JSQ.cjs → chunk-ZAPN7XA6.cjs} +5 -5
- 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 +11 -10
- package/dist/completion/CompletionService.d.cts +6 -3
- package/dist/completion/CompletionService.d.ts +6 -3
- package/dist/completion/CompletionService.js +10 -9
- package/dist/completion.cjs +11 -10
- package/dist/completion.d.cts +6 -3
- package/dist/completion.d.ts +6 -3
- package/dist/completion.js +10 -9
- 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 +2 -2
- package/dist/image-generation.d.cts +7 -4
- package/dist/image-generation.d.ts +7 -4
- package/dist/image-generation.js +1 -1
- package/dist/index.cjs +25 -10
- package/dist/index.d.cts +12 -8
- package/dist/index.d.ts +12 -8
- package/dist/index.js +24 -9
- package/dist/openai-operation.d.cts +4 -1
- package/dist/openai-operation.d.ts +4 -1
- package/dist/outbound-api/routeResolver.d.cts +9 -5
- package/dist/outbound-api/routeResolver.d.ts +9 -5
- package/dist/outbound-api/subscriptionRegistryPort.d.cts +4 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.ts +4 -1
- package/dist/outbound-api/types.d.cts +8 -4
- package/dist/outbound-api/types.d.ts +8 -4
- package/dist/outbound-api.cjs +25 -10
- package/dist/outbound-api.d.cts +117 -8
- package/dist/outbound-api.d.ts +117 -8
- package/dist/outbound-api.js +24 -9
- package/dist/pipeline/AccountAllowanceScheduling.d.cts +8 -4
- package/dist/pipeline/AccountAllowanceScheduling.d.ts +8 -4
- package/dist/pipeline/upstreamFetch.cjs +2 -2
- package/dist/pipeline/upstreamFetch.js +1 -1
- package/dist/ports.d.cts +8 -4
- package/dist/ports.d.ts +8 -4
- package/dist/provider-proxy/ProviderProxy.cjs +11 -10
- package/dist/provider-proxy/ProviderProxy.d.cts +5 -2
- package/dist/provider-proxy/ProviderProxy.d.ts +5 -2
- package/dist/provider-proxy/ProviderProxy.js +10 -9
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +13 -10
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +22 -3
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +22 -3
- package/dist/provider-proxy/ingress/providerProxyShared.js +12 -9
- package/dist/provider-proxy/types.d.cts +4 -1
- package/dist/provider-proxy/types.d.ts +4 -1
- package/dist/provider-proxy.cjs +11 -10
- package/dist/provider-proxy.d.cts +10 -6
- package/dist/provider-proxy.d.ts +10 -6
- package/dist/provider-proxy.js +10 -9
- package/dist/proxy-UZTtjPZx.d.cts +18 -0
- package/dist/proxy-UZTtjPZx.d.ts +18 -0
- package/dist/{routeResolver-rpKQLyDO.d.cts → routeResolver-Da0yvkL1.d.cts} +2 -2
- package/dist/{routeResolver-CTCcSHWu.d.ts → routeResolver-STwMz_G4.d.ts} +2 -2
- package/dist/runtime-5NCT3J3T.cjs +8 -0
- package/dist/runtime-JTHUWCBM.js +8 -0
- package/dist/runtime-t8AZacFF.d.cts +233 -0
- package/dist/runtime-t8AZacFF.d.ts +233 -0
- package/dist/search/api.cjs +766 -0
- package/dist/search/api.d.cts +385 -0
- package/dist/search/api.d.ts +385 -0
- package/dist/search/api.js +766 -0
- package/dist/search/http.cjs +37 -0
- package/dist/search/http.d.cts +323 -0
- package/dist/search/http.d.ts +323 -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/transformers/AnthropicTransformer.cjs +3 -3
- package/dist/transformer/transformers/AnthropicTransformer.js +2 -2
- package/dist/transformer/transformers.cjs +7 -7
- package/dist/transformer/transformers.js +6 -6
- package/dist/transformer.cjs +6 -6
- package/dist/transformer.js +5 -5
- package/dist/{types-DsHBBk3h.d.cts → types-BSIJdsyl.d.cts} +15 -0
- package/dist/{types-CbglB73l.d.cts → types-Be-yt_6T.d.cts} +1 -1
- package/dist/{types-CVRge76p.d.ts → types-By9Tg6-I.d.ts} +15 -0
- package/dist/types-CbCZqLGg.d.cts +127 -0
- package/dist/types-CbCZqLGg.d.ts +127 -0
- package/dist/{types-jjU24eYG.d.cts → types-D-oHYusb.d.cts} +73 -4
- package/dist/{types-Bd72H4SB.d.ts → types-Dm4_36V4.d.ts} +1 -1
- package/dist/{types-5T223WYQ.d.ts → types-Dvlpjn0d.d.ts} +73 -4
- package/package.json +6 -3
- package/dist/{chunk-6OC3ORW6.js → chunk-EUZRH544.js} +3 -3
- package/dist/{chunk-SQMAEDNE.cjs → chunk-POUTD5AM.cjs} +2 -2
|
@@ -1765,7 +1765,10 @@ async function readJsonBody(request2, options) {
|
|
|
1765
1765
|
|
|
1766
1766
|
// src/image-generation/openai-images/types.ts
|
|
1767
1767
|
var DEFAULT_IMAGE_API_LIMITS = Object.freeze({
|
|
1768
|
-
|
|
1768
|
+
// Codex's built-in image tool sends edits as JSON data URLs rather than
|
|
1769
|
+
// multipart files. Leave room for the Base64 expansion of the bounded
|
|
1770
|
+
// aggregate input budget plus the small JSON/options envelope.
|
|
1771
|
+
maxJsonBytes: 96 * 1024 * 1024,
|
|
1769
1772
|
maxMultipartBytes: 64 * 1024 * 1024,
|
|
1770
1773
|
maxFileBytes: 50 * 1024 * 1024,
|
|
1771
1774
|
maxTotalInputBytes: 64 * 1024 * 1024,
|
|
@@ -2326,7 +2329,7 @@ async function readMultipartEdit(request2, scope, limits, signal) {
|
|
|
2326
2329
|
function invalid4(param = "image") {
|
|
2327
2330
|
throw new ImageGenerationError("invalid_image_request", { param });
|
|
2328
2331
|
}
|
|
2329
|
-
function closedInput(value,
|
|
2332
|
+
function closedInput(value, limits) {
|
|
2330
2333
|
if (!value || typeof value !== "object" || Array.isArray(value)) invalid4();
|
|
2331
2334
|
const record2 = value;
|
|
2332
2335
|
const keys = Object.keys(record2);
|
|
@@ -2334,8 +2337,9 @@ function closedInput(value, maxRemoteUrlBytes) {
|
|
|
2334
2337
|
const key = keys[0];
|
|
2335
2338
|
if (key !== "file_id" && key !== "image_url") invalid4();
|
|
2336
2339
|
const item = record2[key];
|
|
2337
|
-
|
|
2338
|
-
|
|
2340
|
+
if (typeof item !== "string" || !item) invalid4();
|
|
2341
|
+
const maxBytes = key === "file_id" ? 256 : item.toLowerCase().startsWith("data:") ? Math.ceil(limits.maxFileBytes / 3) * 4 + 64 : limits.maxRemoteUrlBytes;
|
|
2342
|
+
if (Buffer.byteLength(item, "utf8") > maxBytes) invalid4();
|
|
2339
2343
|
return { [key]: item };
|
|
2340
2344
|
}
|
|
2341
2345
|
function decodedBase64Length(value) {
|
|
@@ -2407,7 +2411,7 @@ async function resolveReference(referenceId, runtime, scope) {
|
|
|
2407
2411
|
return asset;
|
|
2408
2412
|
}
|
|
2409
2413
|
async function resolveImageInput(value, runtime, scope, signal) {
|
|
2410
|
-
const input = closedInput(value, runtime.limits
|
|
2414
|
+
const input = closedInput(value, runtime.limits);
|
|
2411
2415
|
if ("file_id" in input) return resolveReference(input.file_id, runtime, scope);
|
|
2412
2416
|
if (input.image_url.toLowerCase().startsWith("data:")) {
|
|
2413
2417
|
return resolveDataUrl(input.image_url, runtime, scope, signal);
|
|
@@ -2432,10 +2436,10 @@ async function resolveImageInput(value, runtime, scope, signal) {
|
|
|
2432
2436
|
materializer
|
|
2433
2437
|
});
|
|
2434
2438
|
}
|
|
2435
|
-
function parseImageInputList(value,
|
|
2439
|
+
function parseImageInputList(value, limits) {
|
|
2436
2440
|
const list = Array.isArray(value) ? value : [value];
|
|
2437
2441
|
if (list.length < 1 || list.length > 16) invalid4();
|
|
2438
|
-
for (const item of list) closedInput(item,
|
|
2442
|
+
for (const item of list) closedInput(item, limits);
|
|
2439
2443
|
return list;
|
|
2440
2444
|
}
|
|
2441
2445
|
|
|
@@ -2481,7 +2485,7 @@ function createImageEditHandler(deps) {
|
|
|
2481
2485
|
});
|
|
2482
2486
|
const inputs = parseImageInputList(
|
|
2483
2487
|
record2.images ?? record2.image,
|
|
2484
|
-
runtime.limits
|
|
2488
|
+
runtime.limits
|
|
2485
2489
|
);
|
|
2486
2490
|
const resolveObservedInput = async (input) => {
|
|
2487
2491
|
const reference = isReferenceInput(input);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// 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 = 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
|
+
import {
|
|
74
|
+
searchErrorToLegacyWebSearchResponse,
|
|
75
|
+
toLegacyWebSearchResponse
|
|
76
|
+
} from "@omnicross/contracts/search-compat";
|
|
77
|
+
import { toSearchErrorShape } from "@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 toLegacyWebSearchResponse(response);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return searchErrorToLegacyWebSearchResponse(query, toSearchErrorShape(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
|
+
export {
|
|
109
|
+
SEARCH_FRONTEND_NAMES,
|
|
110
|
+
SEARCH_FRONTEND_MODES,
|
|
111
|
+
DEFAULT_SEARCH_FRONTEND_MODES,
|
|
112
|
+
SEARCH_UNSUPPORTED_CAPABILITY_CODE,
|
|
113
|
+
searchErrorHttpStatus,
|
|
114
|
+
isSearchFrontendMode,
|
|
115
|
+
normalizeSearchFrontendModes,
|
|
116
|
+
validateSearchFrontendModes,
|
|
117
|
+
searchRuntimeAsWebSearchBackend
|
|
118
|
+
};
|
|
@@ -0,0 +1,386 @@
|
|
|
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;
|
|
2
|
+
|
|
3
|
+
var _chunkBTBEJRGLcjs = require('./chunk-BTBEJRGL.cjs');
|
|
4
|
+
|
|
5
|
+
// src/search/orchestrator.ts
|
|
6
|
+
var _searchtypes = require('@omnicross/contracts/search-types');
|
|
7
|
+
var _crypto = require('crypto');
|
|
8
|
+
|
|
9
|
+
// src/search/normalize.ts
|
|
10
|
+
var DEFAULT_NORMALIZED_MAX_RESULTS = 5;
|
|
11
|
+
var SERP_REDIRECT_RULES = [
|
|
12
|
+
{ domain: "google.com", paths: ["/search", "/goto"] },
|
|
13
|
+
{ domain: "bing.com", paths: ["/search"] },
|
|
14
|
+
{ domain: "duckduckgo.com", paths: ["/html/", "/l/"] },
|
|
15
|
+
{ domain: "baidu.com", paths: ["/s"] }
|
|
16
|
+
];
|
|
17
|
+
function isDirectResultUrl(rawUrl) {
|
|
18
|
+
let url;
|
|
19
|
+
try {
|
|
20
|
+
url = new URL(rawUrl);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
25
|
+
const host = url.hostname.toLowerCase();
|
|
26
|
+
for (const rule of SERP_REDIRECT_RULES) {
|
|
27
|
+
if (host !== rule.domain && !host.endsWith(`.${rule.domain}`)) continue;
|
|
28
|
+
if (rule.paths.includes(url.pathname)) return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
function normalizedResultLimit(maxResults) {
|
|
33
|
+
const requested = maxResults === void 0 || !Number.isFinite(maxResults) ? DEFAULT_NORMALIZED_MAX_RESULTS : Math.floor(maxResults);
|
|
34
|
+
return Math.max(1, requested);
|
|
35
|
+
}
|
|
36
|
+
function normalizeSearchResults(results, maxResults) {
|
|
37
|
+
const limit = normalizedResultLimit(maxResults);
|
|
38
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
39
|
+
const normalized = [];
|
|
40
|
+
for (const result of results) {
|
|
41
|
+
if (result === null || typeof result !== "object") continue;
|
|
42
|
+
const title = typeof result.title === "string" ? result.title.trim() : "";
|
|
43
|
+
const url = typeof result.url === "string" ? result.url.trim() : "";
|
|
44
|
+
if (title.length === 0 || !isDirectResultUrl(url)) continue;
|
|
45
|
+
if (seenUrls.has(url)) continue;
|
|
46
|
+
seenUrls.add(url);
|
|
47
|
+
normalized.push({
|
|
48
|
+
title,
|
|
49
|
+
url,
|
|
50
|
+
content: typeof result.content === "string" ? result.content.trim() : ""
|
|
51
|
+
});
|
|
52
|
+
if (normalized.length >= limit) break;
|
|
53
|
+
}
|
|
54
|
+
return normalized;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/search/orchestrator.ts
|
|
58
|
+
var QUERY_HASH_LENGTH = 12;
|
|
59
|
+
function hashSearchQuery(query) {
|
|
60
|
+
return _crypto.createHash.call(void 0, "sha256").update(query).digest("hex").slice(0, QUERY_HASH_LENGTH);
|
|
61
|
+
}
|
|
62
|
+
var SearchOrchestrator = class {
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
constructor(registry, options = {}) {
|
|
67
|
+
this.registry = registry;
|
|
68
|
+
this.defaultPolicy = _nullishCoalesce(options.policy, () => ( {}));
|
|
69
|
+
this.onEvent = options.onEvent;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run one search.
|
|
73
|
+
*
|
|
74
|
+
* @param request - the query, an optional pinned provider, and per-request
|
|
75
|
+
* options. `options` is passed to the provider untouched: providers own
|
|
76
|
+
* their own timeouts and the orchestrator adds no second timeout layer.
|
|
77
|
+
* @param policyOverride - per-request policy, merged field-by-field over the
|
|
78
|
+
* orchestrator's default.
|
|
79
|
+
* @throws {SearchProviderError} when no provider produced a response.
|
|
80
|
+
*/
|
|
81
|
+
async search(request, policyOverride) {
|
|
82
|
+
const policy = { ...this.defaultPolicy, ...policyOverride };
|
|
83
|
+
const requestId = _crypto.randomUUID.call(void 0, );
|
|
84
|
+
const queryHash = hashSearchQuery(request.query);
|
|
85
|
+
const startedAt = Date.now();
|
|
86
|
+
const attempts = [];
|
|
87
|
+
const emitComplete = (providerId, resultCount) => {
|
|
88
|
+
this.emit({
|
|
89
|
+
type: "search_complete",
|
|
90
|
+
requestId,
|
|
91
|
+
queryHash,
|
|
92
|
+
...providerId === void 0 ? {} : { providerId },
|
|
93
|
+
resultCount,
|
|
94
|
+
fallbackCount: fallbackCountOf(attempts),
|
|
95
|
+
durationMs: Date.now() - startedAt
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
let plan;
|
|
99
|
+
try {
|
|
100
|
+
plan = this.planCandidates(request, policy);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
emitComplete(void 0, 0);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
if (plan.skippedPreferred !== void 0) {
|
|
106
|
+
this.emit({
|
|
107
|
+
type: "search_attempt",
|
|
108
|
+
requestId,
|
|
109
|
+
queryHash,
|
|
110
|
+
providerId: plan.skippedPreferred.providerId,
|
|
111
|
+
outcome: "failed",
|
|
112
|
+
errorCode: plan.skippedPreferred.errorCode,
|
|
113
|
+
durationMs: 0
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
let lastError;
|
|
117
|
+
for (const candidate of plan.candidates) {
|
|
118
|
+
const attemptStartedAt = Date.now();
|
|
119
|
+
try {
|
|
120
|
+
const produced = await candidate.provider.search(request.query, request.options);
|
|
121
|
+
const durationMs = Date.now() - attemptStartedAt;
|
|
122
|
+
const results = normalizeSearchResults(produced, _optionalChain([request, 'access', _ => _.options, 'optionalAccess', _2 => _2.maxResults]));
|
|
123
|
+
attempts.push({
|
|
124
|
+
providerId: candidate.id,
|
|
125
|
+
outcome: "success",
|
|
126
|
+
resultCount: results.length,
|
|
127
|
+
durationMs
|
|
128
|
+
});
|
|
129
|
+
this.emit({
|
|
130
|
+
type: "search_attempt",
|
|
131
|
+
requestId,
|
|
132
|
+
queryHash,
|
|
133
|
+
providerId: candidate.id,
|
|
134
|
+
outcome: "success",
|
|
135
|
+
resultCount: results.length,
|
|
136
|
+
durationMs
|
|
137
|
+
});
|
|
138
|
+
emitComplete(candidate.id, results.length);
|
|
139
|
+
return {
|
|
140
|
+
query: request.query,
|
|
141
|
+
providerId: candidate.id,
|
|
142
|
+
results,
|
|
143
|
+
attempts,
|
|
144
|
+
fallbackCount: fallbackCountOf(attempts)
|
|
145
|
+
};
|
|
146
|
+
} catch (error) {
|
|
147
|
+
const durationMs = Date.now() - attemptStartedAt;
|
|
148
|
+
const shape = _searchtypes.toSearchErrorShape.call(void 0, error);
|
|
149
|
+
const isCancelled = shape.code === "cancelled" || _optionalChain([request, 'access', _3 => _3.options, 'optionalAccess', _4 => _4.signal, 'optionalAccess', _5 => _5.aborted]) === true;
|
|
150
|
+
const errorCode = isCancelled ? "cancelled" : shape.code;
|
|
151
|
+
attempts.push({
|
|
152
|
+
providerId: candidate.id,
|
|
153
|
+
outcome: "failed",
|
|
154
|
+
errorCode,
|
|
155
|
+
durationMs
|
|
156
|
+
});
|
|
157
|
+
this.emit({
|
|
158
|
+
type: "search_attempt",
|
|
159
|
+
requestId,
|
|
160
|
+
queryHash,
|
|
161
|
+
providerId: candidate.id,
|
|
162
|
+
outcome: "failed",
|
|
163
|
+
errorCode,
|
|
164
|
+
durationMs
|
|
165
|
+
});
|
|
166
|
+
if (isCancelled) {
|
|
167
|
+
emitComplete(void 0, 0);
|
|
168
|
+
throw shape.code === "cancelled" ? error : new (0, _searchtypes.SearchProviderError)("cancelled", "search was cancelled by the caller", {
|
|
169
|
+
providerId: candidate.id,
|
|
170
|
+
retryable: false,
|
|
171
|
+
cause: error
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
lastError = asSearchProviderError(error, shape.code, shape.message, candidate.id);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
emitComplete(void 0, 0);
|
|
178
|
+
throw exhaustionError(attempts, lastError);
|
|
179
|
+
}
|
|
180
|
+
/** Resolve the candidate list for one request. */
|
|
181
|
+
planCandidates(request, policy) {
|
|
182
|
+
if (request.provider !== void 0) {
|
|
183
|
+
const pinned = this.registry.get(request.provider);
|
|
184
|
+
if (pinned === void 0) {
|
|
185
|
+
throw new (0, _searchtypes.SearchProviderError)(
|
|
186
|
+
"upstream_unavailable",
|
|
187
|
+
`search provider '${request.provider}' is not registered in this runtime`,
|
|
188
|
+
{ providerId: request.provider, retryable: false }
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (!isAllowed(pinned.id, policy)) {
|
|
192
|
+
throw new (0, _searchtypes.SearchProviderError)(
|
|
193
|
+
"policy_denied",
|
|
194
|
+
`search provider '${request.provider}' is not allowed by the active search policy`,
|
|
195
|
+
{ providerId: request.provider, retryable: false }
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
return { candidates: [pinned] };
|
|
199
|
+
}
|
|
200
|
+
const allowed = this.registry.list().filter((entry) => isAllowed(entry.id, policy));
|
|
201
|
+
let ordered = allowed;
|
|
202
|
+
let skippedPreferred;
|
|
203
|
+
if (policy.preferred !== void 0) {
|
|
204
|
+
const preferred = allowed.find((entry) => entry.id === policy.preferred);
|
|
205
|
+
if (preferred === void 0) {
|
|
206
|
+
skippedPreferred = {
|
|
207
|
+
providerId: policy.preferred,
|
|
208
|
+
errorCode: this.registry.has(policy.preferred) ? "policy_denied" : "upstream_unavailable"
|
|
209
|
+
};
|
|
210
|
+
} else {
|
|
211
|
+
ordered = [preferred, ...allowed.filter((entry) => entry.id !== preferred.id)];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (policy.fallbackEnabled === false) ordered = ordered.slice(0, 1);
|
|
215
|
+
if (policy.maxAttempts !== void 0) {
|
|
216
|
+
ordered = ordered.slice(0, Math.max(0, Math.floor(policy.maxAttempts)));
|
|
217
|
+
}
|
|
218
|
+
return { candidates: ordered, ...skippedPreferred === void 0 ? {} : { skippedPreferred } };
|
|
219
|
+
}
|
|
220
|
+
/** Deliver one event. A listener that throws must never fail a search. */
|
|
221
|
+
emit(event) {
|
|
222
|
+
if (this.onEvent === void 0) return;
|
|
223
|
+
try {
|
|
224
|
+
this.onEvent(event);
|
|
225
|
+
} catch (e2) {
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
function fallbackCountOf(attempts) {
|
|
230
|
+
return Math.max(0, attempts.length - 1);
|
|
231
|
+
}
|
|
232
|
+
function isAllowed(id, policy) {
|
|
233
|
+
return policy.allowed === void 0 || policy.allowed.includes(id);
|
|
234
|
+
}
|
|
235
|
+
function asSearchProviderError(error, code, message, providerId) {
|
|
236
|
+
if (error instanceof _searchtypes.SearchProviderError) return error;
|
|
237
|
+
return new (0, _searchtypes.SearchProviderError)(code, message, { providerId, cause: error });
|
|
238
|
+
}
|
|
239
|
+
function exhaustionError(attempts, lastError) {
|
|
240
|
+
if (attempts.length === 1 && lastError !== void 0) return lastError;
|
|
241
|
+
if (attempts.length === 0) {
|
|
242
|
+
return new (0, _searchtypes.SearchProviderError)(
|
|
243
|
+
"upstream_unavailable",
|
|
244
|
+
"no eligible search provider was available (0 attempts)",
|
|
245
|
+
{ retryable: false }
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
const trail = attempts.map((attempt) => `${attempt.providerId}:${_nullishCoalesce(attempt.errorCode, () => ( "unknown"))}`).join(",");
|
|
249
|
+
return new (0, _searchtypes.SearchProviderError)(
|
|
250
|
+
_nullishCoalesce(_optionalChain([lastError, 'optionalAccess', _6 => _6.code]), () => ( "upstream_unavailable")),
|
|
251
|
+
`search failed after ${attempts.length} attempt(s)`,
|
|
252
|
+
{ retryable: _optionalChain([lastError, 'optionalAccess', _7 => _7.retryable]), details: { attempts: trail }, cause: lastError }
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/search/registry.ts
|
|
257
|
+
var SearchRegistryError = class _SearchRegistryError extends Error {
|
|
258
|
+
constructor(message) {
|
|
259
|
+
super(message);
|
|
260
|
+
this.name = "SearchRegistryError";
|
|
261
|
+
Object.setPrototypeOf(this, _SearchRegistryError.prototype);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
var SearchProviderRegistry = (_class = class {
|
|
265
|
+
__init() {this.entries = /* @__PURE__ */ new Map()}
|
|
266
|
+
|
|
267
|
+
__init2() {this.nextSequence = 0}
|
|
268
|
+
constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
|
|
269
|
+
this.allowBuiltinOverride = options.allowBuiltinOverride === true;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Register one provider.
|
|
273
|
+
*
|
|
274
|
+
* @param contribution - the provider with its origin, transport, and
|
|
275
|
+
* capabilities declared.
|
|
276
|
+
* @param context - who is registering, for a Phase-2 host. Retained as-is;
|
|
277
|
+
* no rule reads it today, and the parameter exists so adding one later is
|
|
278
|
+
* not a signature change for every caller.
|
|
279
|
+
* @throws {SearchRegistryError} on a blank id, a duplicate id, or a host
|
|
280
|
+
* contribution colliding with a builtin without `allowBuiltinOverride`.
|
|
281
|
+
*/
|
|
282
|
+
register(contribution, context) {
|
|
283
|
+
const id = contribution.id;
|
|
284
|
+
if (typeof id !== "string" || id.trim().length === 0) {
|
|
285
|
+
throw new SearchRegistryError("a search provider contribution needs a non-blank id");
|
|
286
|
+
}
|
|
287
|
+
const existing = this.entries.get(id);
|
|
288
|
+
let sequence = this.nextSequence;
|
|
289
|
+
if (existing !== void 0) {
|
|
290
|
+
const isPermittedOverride = this.allowBuiltinOverride && contribution.source === "host" && existing.contribution.source === "builtin";
|
|
291
|
+
if (!isPermittedOverride) {
|
|
292
|
+
throw new SearchRegistryError(
|
|
293
|
+
existing.contribution.source === "builtin" && contribution.source === "host" ? `search provider '${id}' is a builtin; overriding it requires allowBuiltinOverride` : `search provider '${id}' is already registered`
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
sequence = existing.sequence;
|
|
297
|
+
} else {
|
|
298
|
+
this.nextSequence += 1;
|
|
299
|
+
}
|
|
300
|
+
this.entries.set(id, { contribution, context, sequence });
|
|
301
|
+
}
|
|
302
|
+
/** Whether an id is currently registered. */
|
|
303
|
+
has(id) {
|
|
304
|
+
return this.entries.has(id);
|
|
305
|
+
}
|
|
306
|
+
/** The contribution registered under `id`, if any. */
|
|
307
|
+
get(id) {
|
|
308
|
+
return _optionalChain([this, 'access', _8 => _8.entries, 'access', _9 => _9.get, 'call', _10 => _10(id), 'optionalAccess', _11 => _11.contribution]);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Remove a provider.
|
|
312
|
+
*
|
|
313
|
+
* The Phase-2 host-disconnect hook: when a host goes away its contributions
|
|
314
|
+
* go with it, and the id becomes free to register again.
|
|
315
|
+
*
|
|
316
|
+
* @returns whether something was removed.
|
|
317
|
+
*/
|
|
318
|
+
unregister(id) {
|
|
319
|
+
return this.entries.delete(id);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Every registered contribution, in candidate order.
|
|
323
|
+
*
|
|
324
|
+
* `priorityHint` ascending; contributions without a hint come AFTER every
|
|
325
|
+
* hinted one (an absent hint is "no opinion", not "highest priority"); ties
|
|
326
|
+
* keep registration order. The builtin HTTP contributions carry no hints, so
|
|
327
|
+
* today this is exactly registration order.
|
|
328
|
+
*/
|
|
329
|
+
list() {
|
|
330
|
+
return [...this.entries.values()].sort((a, b) => {
|
|
331
|
+
const aHint = a.contribution.priorityHint;
|
|
332
|
+
const bHint = b.contribution.priorityHint;
|
|
333
|
+
if (aHint !== bHint) {
|
|
334
|
+
if (aHint === void 0) return 1;
|
|
335
|
+
if (bHint === void 0) return -1;
|
|
336
|
+
return aHint - bHint;
|
|
337
|
+
}
|
|
338
|
+
return a.sequence - b.sequence;
|
|
339
|
+
}).map((entry) => entry.contribution);
|
|
340
|
+
}
|
|
341
|
+
}, _class);
|
|
342
|
+
|
|
343
|
+
// src/search/runtime.ts
|
|
344
|
+
function createSearchRuntime(options = {}) {
|
|
345
|
+
const registry = new SearchProviderRegistry({
|
|
346
|
+
allowBuiltinOverride: options.allowBuiltinOverride === true
|
|
347
|
+
});
|
|
348
|
+
for (const contribution of _nullishCoalesce(options.contributions, () => ( _chunkBTBEJRGLcjs.builtinHttpSearchContributions.call(void 0, )))) {
|
|
349
|
+
registry.register(contribution);
|
|
350
|
+
}
|
|
351
|
+
const orchestrator = new SearchOrchestrator(registry, {
|
|
352
|
+
...options.policy === void 0 ? {} : { policy: options.policy },
|
|
353
|
+
...options.onEvent === void 0 ? {} : { onEvent: options.onEvent }
|
|
354
|
+
});
|
|
355
|
+
return {
|
|
356
|
+
search(request) {
|
|
357
|
+
return orchestrator.search(request);
|
|
358
|
+
},
|
|
359
|
+
registerContribution(contribution, context) {
|
|
360
|
+
registry.register(contribution, context);
|
|
361
|
+
},
|
|
362
|
+
unregisterContribution(id) {
|
|
363
|
+
return registry.unregister(id);
|
|
364
|
+
},
|
|
365
|
+
listProviders() {
|
|
366
|
+
return registry.list().map((contribution) => ({
|
|
367
|
+
id: contribution.id,
|
|
368
|
+
source: contribution.source,
|
|
369
|
+
kind: contribution.kind,
|
|
370
|
+
capabilities: { ...contribution.capabilities }
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
exports.DEFAULT_NORMALIZED_MAX_RESULTS = DEFAULT_NORMALIZED_MAX_RESULTS; exports.isDirectResultUrl = isDirectResultUrl; exports.normalizedResultLimit = normalizedResultLimit; exports.normalizeSearchResults = normalizeSearchResults; exports.hashSearchQuery = hashSearchQuery; exports.SearchOrchestrator = SearchOrchestrator; exports.SearchRegistryError = SearchRegistryError; exports.SearchProviderRegistry = SearchProviderRegistry; exports.createSearchRuntime = createSearchRuntime;
|
|
@@ -1765,7 +1765,10 @@ async function readJsonBody(request2, options) {
|
|
|
1765
1765
|
|
|
1766
1766
|
// src/image-generation/openai-images/types.ts
|
|
1767
1767
|
var DEFAULT_IMAGE_API_LIMITS = Object.freeze({
|
|
1768
|
-
|
|
1768
|
+
// Codex's built-in image tool sends edits as JSON data URLs rather than
|
|
1769
|
+
// multipart files. Leave room for the Base64 expansion of the bounded
|
|
1770
|
+
// aggregate input budget plus the small JSON/options envelope.
|
|
1771
|
+
maxJsonBytes: 96 * 1024 * 1024,
|
|
1769
1772
|
maxMultipartBytes: 64 * 1024 * 1024,
|
|
1770
1773
|
maxFileBytes: 50 * 1024 * 1024,
|
|
1771
1774
|
maxTotalInputBytes: 64 * 1024 * 1024,
|
|
@@ -2326,7 +2329,7 @@ async function readMultipartEdit(request2, scope, limits, signal) {
|
|
|
2326
2329
|
function invalid4(param = "image") {
|
|
2327
2330
|
throw new ImageGenerationError("invalid_image_request", { param });
|
|
2328
2331
|
}
|
|
2329
|
-
function closedInput(value,
|
|
2332
|
+
function closedInput(value, limits) {
|
|
2330
2333
|
if (!value || typeof value !== "object" || Array.isArray(value)) invalid4();
|
|
2331
2334
|
const record2 = value;
|
|
2332
2335
|
const keys = Object.keys(record2);
|
|
@@ -2334,8 +2337,9 @@ function closedInput(value, maxRemoteUrlBytes) {
|
|
|
2334
2337
|
const key = keys[0];
|
|
2335
2338
|
if (key !== "file_id" && key !== "image_url") invalid4();
|
|
2336
2339
|
const item = record2[key];
|
|
2337
|
-
|
|
2338
|
-
|
|
2340
|
+
if (typeof item !== "string" || !item) invalid4();
|
|
2341
|
+
const maxBytes = key === "file_id" ? 256 : item.toLowerCase().startsWith("data:") ? Math.ceil(limits.maxFileBytes / 3) * 4 + 64 : limits.maxRemoteUrlBytes;
|
|
2342
|
+
if (Buffer.byteLength(item, "utf8") > maxBytes) invalid4();
|
|
2339
2343
|
return { [key]: item };
|
|
2340
2344
|
}
|
|
2341
2345
|
function decodedBase64Length(value) {
|
|
@@ -2407,7 +2411,7 @@ async function resolveReference(referenceId, runtime, scope) {
|
|
|
2407
2411
|
return asset;
|
|
2408
2412
|
}
|
|
2409
2413
|
async function resolveImageInput(value, runtime, scope, signal) {
|
|
2410
|
-
const input = closedInput(value, runtime.limits
|
|
2414
|
+
const input = closedInput(value, runtime.limits);
|
|
2411
2415
|
if ("file_id" in input) return resolveReference(input.file_id, runtime, scope);
|
|
2412
2416
|
if (input.image_url.toLowerCase().startsWith("data:")) {
|
|
2413
2417
|
return resolveDataUrl(input.image_url, runtime, scope, signal);
|
|
@@ -2432,10 +2436,10 @@ async function resolveImageInput(value, runtime, scope, signal) {
|
|
|
2432
2436
|
materializer
|
|
2433
2437
|
});
|
|
2434
2438
|
}
|
|
2435
|
-
function parseImageInputList(value,
|
|
2439
|
+
function parseImageInputList(value, limits) {
|
|
2436
2440
|
const list = Array.isArray(value) ? value : [value];
|
|
2437
2441
|
if (list.length < 1 || list.length > 16) invalid4();
|
|
2438
|
-
for (const item of list) closedInput(item,
|
|
2442
|
+
for (const item of list) closedInput(item, limits);
|
|
2439
2443
|
return list;
|
|
2440
2444
|
}
|
|
2441
2445
|
|
|
@@ -2481,7 +2485,7 @@ function createImageEditHandler(deps) {
|
|
|
2481
2485
|
});
|
|
2482
2486
|
const inputs = parseImageInputList(
|
|
2483
2487
|
_nullishCoalesce(record2.images, () => ( record2.image)),
|
|
2484
|
-
runtime.limits
|
|
2488
|
+
runtime.limits
|
|
2485
2489
|
);
|
|
2486
2490
|
const resolveObservedInput = async (input) => {
|
|
2487
2491
|
const reference = isReferenceInput(input);
|
|
@@ -32,6 +32,12 @@ function bumpUpstreamProxyGeneration() {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
function isClientDisconnectAbort(signal) {
|
|
36
|
+
if (!signal?.aborted) return false;
|
|
37
|
+
const reason = signal.reason;
|
|
38
|
+
if (!reason || typeof reason !== "object") return false;
|
|
39
|
+
return reason.code === "client_disconnect";
|
|
40
|
+
}
|
|
35
41
|
function normalizeProxy(cfg) {
|
|
36
42
|
if ("url" in cfg) {
|
|
37
43
|
let u;
|
|
@@ -144,7 +150,7 @@ function fetchUpstream(url, init, ctx) {
|
|
|
144
150
|
return response;
|
|
145
151
|
},
|
|
146
152
|
(error) => {
|
|
147
|
-
recordActivity(0);
|
|
153
|
+
if (!isClientDisconnectAbort(init.signal)) recordActivity(0);
|
|
148
154
|
throw error;
|
|
149
155
|
}
|
|
150
156
|
);
|