@ai-matrx/api 0.1.9 → 0.1.11
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/CHANGELOG.md +11 -0
- package/README.md +1 -1
- package/dist/account.d.cts +1 -1
- package/dist/account.d.ts +1 -1
- package/dist/agents.cjs +12 -12
- package/dist/agents.d.cts +1 -1
- package/dist/agents.d.ts +1 -1
- package/dist/agents.js +2 -2
- package/dist/ai.cjs +3 -3
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/ai.js +2 -2
- package/dist/apps.cjs +6 -6
- package/dist/apps.d.cts +1 -1
- package/dist/apps.d.ts +1 -1
- package/dist/apps.js +2 -2
- package/dist/architecture.cjs +11 -11
- package/dist/architecture.d.cts +1 -1
- package/dist/architecture.d.ts +1 -1
- package/dist/architecture.js +2 -2
- package/dist/audio.cjs +5 -5
- package/dist/audio.d.cts +1 -1
- package/dist/audio.d.ts +1 -1
- package/dist/audio.js +2 -2
- package/dist/chat.cjs +12 -12
- package/dist/chat.d.cts +1 -1
- package/dist/chat.d.ts +1 -1
- package/dist/chat.js +2 -2
- package/dist/{chunk-PMGKZ4FT.cjs → chunk-2ZHIYXHV.cjs} +279 -34
- package/dist/{chunk-PIVTHTVR.js → chunk-6KHHHBG5.js} +270 -36
- package/dist/{chunk-KIEAFMKB.js → chunk-PIPE5OML.js} +100 -46
- package/dist/{chunk-2SXAAKGV.cjs → chunk-PKYPPATQ.cjs} +100 -45
- package/dist/code.cjs +7 -7
- package/dist/code.d.cts +1 -1
- package/dist/code.d.ts +1 -1
- package/dist/code.js +2 -2
- package/dist/commerce.d.cts +1 -1
- package/dist/commerce.d.ts +1 -1
- package/dist/communications.cjs +5 -5
- package/dist/communications.d.cts +1 -1
- package/dist/communications.d.ts +1 -1
- package/dist/communications.js +2 -2
- package/dist/computer.cjs +4 -4
- package/dist/computer.d.cts +1 -1
- package/dist/computer.d.ts +1 -1
- package/dist/computer.js +2 -2
- package/dist/content.cjs +5 -5
- package/dist/content.d.cts +1 -1
- package/dist/content.d.ts +1 -1
- package/dist/content.js +2 -2
- package/dist/crm.cjs +3 -3
- package/dist/crm.d.cts +1 -1
- package/dist/crm.d.ts +1 -1
- package/dist/crm.js +2 -2
- package/dist/data.d.cts +1 -1
- package/dist/data.d.ts +1 -1
- package/dist/education.cjs +5 -5
- package/dist/education.d.cts +1 -1
- package/dist/education.d.ts +1 -1
- package/dist/education.js +2 -2
- package/dist/files.cjs +21 -21
- package/dist/files.d.cts +1 -1
- package/dist/files.d.ts +1 -1
- package/dist/files.js +2 -2
- package/dist/human-resources.d.cts +1 -1
- package/dist/human-resources.d.ts +1 -1
- package/dist/{index-C3ZlP3BI.d.cts → index-Gj30ybjE.d.cts} +42 -3
- package/dist/{index-C3ZlP3BI.d.ts → index-Gj30ybjE.d.ts} +42 -3
- package/dist/index.cjs +188 -288
- package/dist/index.d.cts +129 -180
- package/dist/index.d.ts +129 -180
- package/dist/index.js +81 -206
- package/dist/integrations.cjs +4 -4
- package/dist/integrations.d.cts +1 -1
- package/dist/integrations.d.ts +1 -1
- package/dist/integrations.js +2 -2
- package/dist/intelligence.cjs +10 -8
- package/dist/intelligence.d.cts +13 -13
- package/dist/intelligence.d.ts +13 -13
- package/dist/intelligence.js +5 -3
- package/dist/{keys.generated-CK_C5UXG.d.cts → keys.generated-DZUiM-uA.d.cts} +5 -3
- package/dist/{keys.generated-CK_C5UXG.d.ts → keys.generated-DZUiM-uA.d.ts} +5 -3
- package/dist/knowledge.cjs +43 -43
- package/dist/knowledge.d.cts +13 -13
- package/dist/knowledge.d.ts +13 -13
- package/dist/knowledge.js +2 -2
- package/dist/legal.cjs +7 -7
- package/dist/legal.d.cts +1 -1
- package/dist/legal.d.ts +1 -1
- package/dist/legal.js +2 -2
- package/dist/marketing.cjs +77 -77
- package/dist/marketing.d.cts +27 -27
- package/dist/marketing.d.ts +27 -27
- package/dist/marketing.js +2 -2
- package/dist/masterwork.cjs +33 -33
- package/dist/masterwork.d.cts +1 -1
- package/dist/masterwork.d.ts +1 -1
- package/dist/masterwork.js +2 -2
- package/dist/media.cjs +12 -12
- package/dist/media.d.cts +1 -1
- package/dist/media.d.ts +1 -1
- package/dist/media.js +2 -2
- package/dist/net.cjs +19 -20
- package/dist/net.d.cts +41 -41
- package/dist/net.d.ts +41 -41
- package/dist/net.js +1 -2
- package/dist/platform.cjs +4 -4
- package/dist/platform.d.cts +1 -1
- package/dist/platform.d.ts +1 -1
- package/dist/platform.js +2 -2
- package/dist/publish.cjs +8 -8
- package/dist/publish.d.cts +1 -1
- package/dist/publish.d.ts +1 -1
- package/dist/publish.js +2 -2
- package/dist/schemas.d.cts +78 -15
- package/dist/schemas.d.ts +78 -15
- package/dist/stream.cjs +11 -11
- package/dist/stream.d.cts +1 -1
- package/dist/stream.d.ts +1 -1
- package/dist/stream.js +2 -2
- package/dist/types.cjs +2 -0
- package/dist/types.d.cts +72245 -0
- package/dist/types.d.ts +72245 -0
- package/dist/types.js +1 -0
- package/dist/web.cjs +27 -27
- package/dist/web.d.cts +17 -17
- package/dist/web.d.ts +17 -17
- package/dist/web.js +2 -2
- package/dist/workflows.cjs +14 -14
- package/dist/workflows.d.cts +23 -26
- package/dist/workflows.d.ts +23 -26
- package/dist/workflows.js +2 -2
- package/package.json +14 -4
- package/dist/chunk-FNIYADWI.cjs +0 -59
- package/dist/chunk-YTEOFGFC.js +0 -57
|
@@ -1,6 +1,89 @@
|
|
|
1
|
-
import { withRetry, isTransportFailure,
|
|
1
|
+
import { resilientFetch, isNetError, withRetry, isTransportFailure, AbortedError } from './chunk-PIPE5OML.js';
|
|
2
2
|
import { isUuidShape } from '@ai-matrx/kit/uuid';
|
|
3
|
-
import { toCredentialsPort, MATRX_HEADERS
|
|
3
|
+
import { credentialToHeaders, toCredentialsPort, MATRX_HEADERS } from '@ai-matrx/auth/credentials';
|
|
4
|
+
|
|
5
|
+
// src/core/protocol.ts
|
|
6
|
+
var MATRX_AI_API_VERSION_DEFAULT = "v2";
|
|
7
|
+
var V2_COVERED_AI_PATH_TEMPLATES = [
|
|
8
|
+
"/ai/manual",
|
|
9
|
+
"/ai/chat",
|
|
10
|
+
"/ai/agents/{agent_id}",
|
|
11
|
+
"/ai/agent/{agent_id}",
|
|
12
|
+
// singular alias — behaves identically
|
|
13
|
+
"/ai/conversations/{conversation_id}",
|
|
14
|
+
"/ai/conversation/{conversation_id}",
|
|
15
|
+
// singular alias
|
|
16
|
+
"/ai/prompts/{prompt_id}",
|
|
17
|
+
// saved-prompt execution
|
|
18
|
+
"/ai/mandates/{mandate_key}"
|
|
19
|
+
// THE MANDATE DOOR — `/v2` sibling exists (routers/v2.py)
|
|
20
|
+
];
|
|
21
|
+
function toV2Path(path) {
|
|
22
|
+
const withLead = path.startsWith("/") ? path : `/${path}`;
|
|
23
|
+
if (withLead.startsWith("/api/")) {
|
|
24
|
+
const rest = withLead.slice("/api".length);
|
|
25
|
+
return rest.startsWith("/v2/") ? withLead : `/api/v2${rest}`;
|
|
26
|
+
}
|
|
27
|
+
return withLead.startsWith("/v2/") ? withLead : `/v2${withLead}`;
|
|
28
|
+
}
|
|
29
|
+
var COVERED_INTERPOLATED_PATH = [
|
|
30
|
+
/^(?:\/api)?\/ai\/manual$/,
|
|
31
|
+
/^(?:\/api)?\/ai\/chat$/,
|
|
32
|
+
/^(?:\/api)?\/ai\/agents\/[^/]+$/,
|
|
33
|
+
/^(?:\/api)?\/ai\/agent\/[^/]+$/,
|
|
34
|
+
/^(?:\/api)?\/ai\/conversations\/[^/]+$/,
|
|
35
|
+
/^(?:\/api)?\/ai\/conversation\/[^/]+$/,
|
|
36
|
+
/^(?:\/api)?\/ai\/prompts\/[^/]+$/,
|
|
37
|
+
// `/warm` etc. deliberately don't match
|
|
38
|
+
/^(?:\/api)?\/ai\/mandates\/[^/]+$/
|
|
39
|
+
// the mandate door
|
|
40
|
+
];
|
|
41
|
+
function isCoveredAiPath(path) {
|
|
42
|
+
return COVERED_INTERPOLATED_PATH.some((re) => re.test(path));
|
|
43
|
+
}
|
|
44
|
+
function isV2Path(pathOrUrl) {
|
|
45
|
+
return /\/v2\/ai\//.test(pathOrUrl);
|
|
46
|
+
}
|
|
47
|
+
function toV1FallbackUrl(url) {
|
|
48
|
+
return url.replace(/\/v2\/ai\//, "/ai/");
|
|
49
|
+
}
|
|
50
|
+
function applyAiApiVersion(path, version) {
|
|
51
|
+
if (version !== "v2") return path;
|
|
52
|
+
return isCoveredAiPath(path) ? toV2Path(path) : path;
|
|
53
|
+
}
|
|
54
|
+
async function fetchWithMatrxProtocolFallback(url, init, opts = {}) {
|
|
55
|
+
const { onDowngrade, ...fetchOpts } = opts;
|
|
56
|
+
const logDowngrade = (reason, status2) => {
|
|
57
|
+
console.warn(
|
|
58
|
+
`[matrx] ai_v2_downgrade \u2192 retrying on v1. v2=${url} reason=${reason}`
|
|
59
|
+
);
|
|
60
|
+
onDowngrade?.({ url, reason, ...status2 !== void 0 ? { status: status2 } : {} });
|
|
61
|
+
};
|
|
62
|
+
if (!isV2Path(url)) return resilientFetch(url, init, fetchOpts);
|
|
63
|
+
let result;
|
|
64
|
+
try {
|
|
65
|
+
result = await resilientFetch(url, init, fetchOpts);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
const isAbort = isNetError(err) && err.code === "aborted" || err instanceof Error && err.name === "AbortError";
|
|
68
|
+
if (isAbort) throw err;
|
|
69
|
+
logDowngrade(String(err));
|
|
70
|
+
return resilientFetch(toV1FallbackUrl(url), init, fetchOpts);
|
|
71
|
+
}
|
|
72
|
+
const status = result.response.status;
|
|
73
|
+
if (status === 404 || status === 405 || status >= 500) {
|
|
74
|
+
logDowngrade(`HTTP ${status}`, status);
|
|
75
|
+
return resilientFetch(toV1FallbackUrl(url), init, fetchOpts);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
function aiVersionPathOverrides(version) {
|
|
80
|
+
if (version !== "v2") return {};
|
|
81
|
+
const map = {};
|
|
82
|
+
for (const template of V2_COVERED_AI_PATH_TEMPLATES) {
|
|
83
|
+
map[template] = toV2Path(template);
|
|
84
|
+
}
|
|
85
|
+
return map;
|
|
86
|
+
}
|
|
4
87
|
|
|
5
88
|
// src/core/backend-errors.ts
|
|
6
89
|
var BackendApiError = class extends Error {
|
|
@@ -822,7 +905,177 @@ var DEPLOYMENTS = {
|
|
|
822
905
|
}
|
|
823
906
|
};
|
|
824
907
|
var DOMAINS = ["account", "agents", "ai", "apps", "architecture", "audio", "chat", "code", "commerce", "communications", "computer", "content", "crm", "data", "education", "files", "human-resources", "integrations", "intelligence", "knowledge", "legal", "marketing", "masterwork", "media", "platform", "publish", "web", "workflows"];
|
|
908
|
+
var WIRE_FETCH_OPTION_KEYS = [
|
|
909
|
+
"redirect",
|
|
910
|
+
"cache",
|
|
911
|
+
"credentials",
|
|
912
|
+
"mode",
|
|
913
|
+
"keepalive",
|
|
914
|
+
"referrerPolicy",
|
|
915
|
+
"integrity",
|
|
916
|
+
"priority"
|
|
917
|
+
];
|
|
918
|
+
var SESSION_READY_TIMEOUT_MS = 3e3;
|
|
825
919
|
var DEFAULT_CONNECT_TIMEOUT_MS = 15e3;
|
|
920
|
+
function isBodyInit(body) {
|
|
921
|
+
return typeof body === "string" || typeof Blob !== "undefined" && body instanceof Blob || typeof FormData !== "undefined" && body instanceof FormData || typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || typeof ReadableStream !== "undefined" && body instanceof ReadableStream;
|
|
922
|
+
}
|
|
923
|
+
async function waitForSessionReady(credentials, timeoutMs = SESSION_READY_TIMEOUT_MS) {
|
|
924
|
+
const ready = credentials?.ready;
|
|
925
|
+
if (!ready) return;
|
|
926
|
+
let timer;
|
|
927
|
+
try {
|
|
928
|
+
await Promise.race([
|
|
929
|
+
ready.call(credentials).catch(() => void 0),
|
|
930
|
+
new Promise((resolve) => {
|
|
931
|
+
timer = setTimeout(resolve, Math.max(0, timeoutMs));
|
|
932
|
+
})
|
|
933
|
+
]);
|
|
934
|
+
} finally {
|
|
935
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function headerBag(headers) {
|
|
939
|
+
return { ...headers ?? {} };
|
|
940
|
+
}
|
|
941
|
+
function hasHeader(headers, name) {
|
|
942
|
+
const lower = name.toLowerCase();
|
|
943
|
+
return Object.keys(headers).some((key) => key.toLowerCase() === lower);
|
|
944
|
+
}
|
|
945
|
+
function encodeBody(method, body, headers) {
|
|
946
|
+
const upper = method.toUpperCase();
|
|
947
|
+
if (body === void 0 || upper === "GET" || upper === "HEAD") return void 0;
|
|
948
|
+
if (isBodyInit(body)) return body;
|
|
949
|
+
if (!hasHeader(headers, "content-type")) headers["Content-Type"] = "application/json";
|
|
950
|
+
return JSON.stringify(body);
|
|
951
|
+
}
|
|
952
|
+
function bodySize(body) {
|
|
953
|
+
if (body === void 0) return 0;
|
|
954
|
+
if (typeof body === "string") return new TextEncoder().encode(body).byteLength;
|
|
955
|
+
if (typeof Blob !== "undefined" && body instanceof Blob) return body.size;
|
|
956
|
+
if (body instanceof ArrayBuffer) return body.byteLength;
|
|
957
|
+
if (ArrayBuffer.isView(body)) return body.byteLength;
|
|
958
|
+
return 0;
|
|
959
|
+
}
|
|
960
|
+
function parseXhrHeaders(raw) {
|
|
961
|
+
const headers = new Headers();
|
|
962
|
+
for (const line of raw.trim().split(/[\r\n]+/)) {
|
|
963
|
+
const index = line.indexOf(":");
|
|
964
|
+
if (index <= 0) continue;
|
|
965
|
+
try {
|
|
966
|
+
headers.append(line.slice(0, index).trim(), line.slice(index + 1).trim());
|
|
967
|
+
} catch {
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
return headers;
|
|
971
|
+
}
|
|
972
|
+
function sendWithXhr(url, init, signal, totalTimeoutMs, onUploadProgress) {
|
|
973
|
+
const controller = new AbortController();
|
|
974
|
+
return new Promise((resolve, reject) => {
|
|
975
|
+
const xhr = new XMLHttpRequest();
|
|
976
|
+
xhr.open(init.method, url, true);
|
|
977
|
+
xhr.responseType = "arraybuffer";
|
|
978
|
+
for (const [name, value] of Object.entries(init.headers)) xhr.setRequestHeader(name, value);
|
|
979
|
+
if (totalTimeoutMs !== null && totalTimeoutMs > 0) xhr.timeout = totalTimeoutMs;
|
|
980
|
+
let lastLoaded = 0;
|
|
981
|
+
xhr.upload.onprogress = (event) => {
|
|
982
|
+
const loaded = Math.max(lastLoaded, event.loaded);
|
|
983
|
+
lastLoaded = loaded;
|
|
984
|
+
onUploadProgress({ loaded, total: event.lengthComputable ? event.total : 0 });
|
|
985
|
+
};
|
|
986
|
+
const onAbort = () => xhr.abort();
|
|
987
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
988
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
989
|
+
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
990
|
+
xhr.onload = () => {
|
|
991
|
+
cleanup();
|
|
992
|
+
const status = xhr.status === 0 ? 200 : xhr.status;
|
|
993
|
+
const nullBody = status === 204 || status === 205 || status === 304;
|
|
994
|
+
const response = new Response(nullBody ? null : xhr.response, {
|
|
995
|
+
status,
|
|
996
|
+
statusText: xhr.statusText,
|
|
997
|
+
headers: parseXhrHeaders(xhr.getAllResponseHeaders())
|
|
998
|
+
});
|
|
999
|
+
resolve({ response, controller });
|
|
1000
|
+
};
|
|
1001
|
+
xhr.onerror = () => {
|
|
1002
|
+
cleanup();
|
|
1003
|
+
reject(new TypeError(`Network failure uploading to ${url}`));
|
|
1004
|
+
};
|
|
1005
|
+
xhr.ontimeout = () => {
|
|
1006
|
+
cleanup();
|
|
1007
|
+
reject(new DOMException(`Upload to ${url} exceeded ${totalTimeoutMs}ms`, "TimeoutError"));
|
|
1008
|
+
};
|
|
1009
|
+
xhr.onabort = () => {
|
|
1010
|
+
cleanup();
|
|
1011
|
+
reject(new DOMException("The upload was cancelled.", "AbortError"));
|
|
1012
|
+
};
|
|
1013
|
+
if (signal?.aborted) {
|
|
1014
|
+
xhr.abort();
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
xhr.send(init.body ?? null);
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
async function sendOnWire(request, auth = {}) {
|
|
1021
|
+
const method = request.method.toUpperCase();
|
|
1022
|
+
const headers = headerBag(request.headers);
|
|
1023
|
+
const body = encodeBody(method, request.body, headers);
|
|
1024
|
+
await waitForSessionReady(auth.credentials, auth.readyTimeoutMs);
|
|
1025
|
+
const credentialHeaders = auth.credentials ? credentialToHeaders(await auth.credentials.get()) : {};
|
|
1026
|
+
const attempt = (sendHeaders) => {
|
|
1027
|
+
if (request.signal?.aborted) return Promise.reject(new AbortedError(request.signal.reason));
|
|
1028
|
+
const merged = { ...sendHeaders };
|
|
1029
|
+
if (request.onUploadProgress && body !== void 0) {
|
|
1030
|
+
if (typeof XMLHttpRequest !== "undefined" && !(typeof ReadableStream !== "undefined" && body instanceof ReadableStream)) {
|
|
1031
|
+
return sendWithXhr(
|
|
1032
|
+
request.url,
|
|
1033
|
+
{ method, headers: merged, body },
|
|
1034
|
+
request.signal,
|
|
1035
|
+
request.totalTimeoutMs ?? null,
|
|
1036
|
+
request.onUploadProgress
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
return fetchWithMatrxProtocolFallback(
|
|
1041
|
+
request.url,
|
|
1042
|
+
{ ...request.fetchOptions, method, headers: merged, ...body !== void 0 ? { body } : {} },
|
|
1043
|
+
{
|
|
1044
|
+
...request.signal ? { signal: request.signal } : {},
|
|
1045
|
+
connectTimeoutMs: request.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,
|
|
1046
|
+
totalTimeoutMs: request.totalTimeoutMs !== void 0 ? request.totalTimeoutMs : null,
|
|
1047
|
+
throwOnHttpError: false,
|
|
1048
|
+
...request.onProtocolDowngrade ? { onDowngrade: request.onProtocolDowngrade } : {}
|
|
1049
|
+
}
|
|
1050
|
+
).then((result) => {
|
|
1051
|
+
if (request.onUploadProgress && body !== void 0) {
|
|
1052
|
+
const total = bodySize(body);
|
|
1053
|
+
request.onUploadProgress({ loaded: total, total });
|
|
1054
|
+
}
|
|
1055
|
+
return result;
|
|
1056
|
+
});
|
|
1057
|
+
};
|
|
1058
|
+
const over = Object.fromEntries(
|
|
1059
|
+
Object.entries(request.overHeaders ?? {}).filter(([name]) => name.toLowerCase() !== "content-type")
|
|
1060
|
+
);
|
|
1061
|
+
const firstHeaders = { ...headers, ...credentialHeaders, ...over };
|
|
1062
|
+
const idempotent = method === "GET" || method === "HEAD";
|
|
1063
|
+
const attempts = Math.max(1, request.retryAttempts ?? 1);
|
|
1064
|
+
const first = idempotent && attempts > 1 && !request.stream ? await withRetry(() => attempt(firstHeaders), {
|
|
1065
|
+
attempts,
|
|
1066
|
+
retryOn: isTransportFailure,
|
|
1067
|
+
...request.signal ? { signal: request.signal } : {}
|
|
1068
|
+
}) : await attempt(firstHeaders);
|
|
1069
|
+
if (first.response.status !== 401 || !auth.refreshCredentials) return first;
|
|
1070
|
+
if (!await auth.refreshCredentials()) return first;
|
|
1071
|
+
await first.response.body?.cancel().catch(() => void 0);
|
|
1072
|
+
const retryHeaders = { ...headers };
|
|
1073
|
+
Object.assign(retryHeaders, auth.credentials ? credentialToHeaders(await auth.credentials.get()) : {}, over);
|
|
1074
|
+
return attempt(retryHeaders);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// src/api.ts
|
|
1078
|
+
var DEFAULT_CONNECT_TIMEOUT_MS2 = 15e3;
|
|
826
1079
|
function defaultRequestId() {
|
|
827
1080
|
const c = globalThis.crypto;
|
|
828
1081
|
if (c?.randomUUID) return c.randomUUID();
|
|
@@ -851,9 +1104,6 @@ function queryString(query) {
|
|
|
851
1104
|
}
|
|
852
1105
|
return parts.length ? `?${parts.join("&")}` : "";
|
|
853
1106
|
}
|
|
854
|
-
function isBodyInit(body) {
|
|
855
|
-
return typeof body === "string" || typeof Blob !== "undefined" && body instanceof Blob || typeof FormData !== "undefined" && body instanceof FormData || typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || typeof ReadableStream !== "undefined" && body instanceof ReadableStream;
|
|
856
|
-
}
|
|
857
1107
|
function acceptFor(stream) {
|
|
858
1108
|
switch (stream) {
|
|
859
1109
|
case "ndjson":
|
|
@@ -919,43 +1169,27 @@ function createApi(options = {}) {
|
|
|
919
1169
|
Accept: acceptFor(op.s),
|
|
920
1170
|
[MATRX_HEADERS.requestId]: requestId
|
|
921
1171
|
};
|
|
922
|
-
let body;
|
|
923
|
-
if (args?.body !== void 0 && op.m !== "GET" && op.m !== "HEAD") {
|
|
924
|
-
if (isBodyInit(args.body)) {
|
|
925
|
-
body = args.body;
|
|
926
|
-
} else {
|
|
927
|
-
body = JSON.stringify(args.body);
|
|
928
|
-
headers["Content-Type"] = "application/json";
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
const credentialHeaders = credentialToHeaders(await credentials.get());
|
|
932
|
-
Object.assign(headers, credentialHeaders);
|
|
933
1172
|
if (orgId !== null) headers[MATRX_HEADERS.organization] = orgId;
|
|
934
1173
|
options.onRequest?.({ operation: op.n, method: op.m, url, requestId, deployment: op.d });
|
|
935
|
-
const
|
|
936
|
-
url,
|
|
937
|
-
{ method: op.m, headers: sendHeaders, ...body !== void 0 ? { body } : {} },
|
|
1174
|
+
const { response, controller } = await sendOnWire(
|
|
938
1175
|
{
|
|
1176
|
+
url,
|
|
1177
|
+
method: op.m,
|
|
1178
|
+
headers,
|
|
1179
|
+
body: args?.body,
|
|
939
1180
|
...call?.signal ? { signal: call.signal } : {},
|
|
940
|
-
connectTimeoutMs: call?.connectTimeoutMs ?? options.connectTimeoutMs ??
|
|
1181
|
+
connectTimeoutMs: call?.connectTimeoutMs ?? options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS2,
|
|
941
1182
|
totalTimeoutMs: call?.totalTimeoutMs !== void 0 ? call.totalTimeoutMs : options.totalTimeoutMs ?? null,
|
|
942
|
-
|
|
1183
|
+
stream: Boolean(op.s),
|
|
1184
|
+
retryAttempts,
|
|
1185
|
+
...call?.onUploadProgress ? { onUploadProgress: call.onUploadProgress } : {}
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
credentials,
|
|
1189
|
+
...options.readyTimeoutMs !== void 0 ? { readyTimeoutMs: options.readyTimeoutMs } : {},
|
|
1190
|
+
...options.refreshCredentials ? { refreshCredentials: options.refreshCredentials } : {}
|
|
943
1191
|
}
|
|
944
1192
|
);
|
|
945
|
-
const idempotent = op.m === "GET" || op.m === "HEAD";
|
|
946
|
-
const { response, controller } = idempotent && retryAttempts > 1 && !op.s ? await withRetry(() => attempt(), {
|
|
947
|
-
attempts: retryAttempts,
|
|
948
|
-
retryOn: isTransportFailure,
|
|
949
|
-
...call?.signal ? { signal: call.signal } : {}
|
|
950
|
-
}) : await attempt();
|
|
951
|
-
if (response.status === 401 && options.refreshCredentials && await options.refreshCredentials()) {
|
|
952
|
-
const retryHeaders = { ...headers };
|
|
953
|
-
for (const name of Object.keys(credentialHeaders)) delete retryHeaders[name];
|
|
954
|
-
Object.assign(retryHeaders, credentialToHeaders(await credentials.get()));
|
|
955
|
-
const retried = await attempt(retryHeaders);
|
|
956
|
-
if (!retried.response.ok) throw await errorFrom(retried.response, interpolate(op.p, args?.path));
|
|
957
|
-
return { response: retried.response, requestId, controller: retried.controller };
|
|
958
|
-
}
|
|
959
1193
|
if (!response.ok) throw await errorFrom(response, interpolate(op.p, args?.path));
|
|
960
1194
|
return { response, requestId, controller };
|
|
961
1195
|
};
|
|
@@ -1022,4 +1256,4 @@ async function openJsonOrStream(api, op, args, options) {
|
|
|
1022
1256
|
return { kind: "stream", stream: toStream(op, response, requestId, controller) };
|
|
1023
1257
|
}
|
|
1024
1258
|
|
|
1025
|
-
export { BackendApiError, CONTRACT_SHA256, DEFAULT_MATRX_NDJSON_READ_AHEAD, DEPLOYMENTS, DOMAINS, MatrxApiError, OrganizationContextError, StreamTransportError, applyOrganizationContextHeader, assertOrganizationMatchesOperation, assertQueryOrganizationMatchesContext, createApi, createMatrxNdjsonFramer, createMatrxSseFramer, createOrganizationOperation, describeBackendFailure, extractMatrxErrorCode, extractMatrxErrorMessage, getUserMessage, isGenericUserMessage, isStreamTransportLost, normalizeMatrxStreamEnvelope, openJsonOrStream, openStream, parseCallApiError, parseHttpError, parseHttpErrorBody, parseMatrxSseFrame, parsePersistedBackendError, parseStreamError, readMatrxNdjsonStream, readMatrxSseStream, requireOrganizationContext, unwrapUpstreamError };
|
|
1259
|
+
export { BackendApiError, CONTRACT_SHA256, DEFAULT_MATRX_NDJSON_READ_AHEAD, DEPLOYMENTS, DOMAINS, MATRX_AI_API_VERSION_DEFAULT, MatrxApiError, OrganizationContextError, StreamTransportError, V2_COVERED_AI_PATH_TEMPLATES, WIRE_FETCH_OPTION_KEYS, aiVersionPathOverrides, applyAiApiVersion, applyOrganizationContextHeader, assertOrganizationMatchesOperation, assertQueryOrganizationMatchesContext, createApi, createMatrxNdjsonFramer, createMatrxSseFramer, createOrganizationOperation, describeBackendFailure, extractMatrxErrorCode, extractMatrxErrorMessage, fetchWithMatrxProtocolFallback, getUserMessage, isCoveredAiPath, isGenericUserMessage, isStreamTransportLost, isV2Path, normalizeMatrxStreamEnvelope, openJsonOrStream, openStream, parseCallApiError, parseHttpError, parseHttpErrorBody, parseMatrxSseFrame, parsePersistedBackendError, parseStreamError, readMatrxNdjsonStream, readMatrxSseStream, requireOrganizationContext, sendOnWire, toV1FallbackUrl, toV2Path, unwrapUpstreamError };
|
|
@@ -141,6 +141,58 @@ function toNetError(err) {
|
|
|
141
141
|
);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
// src/net/retry.ts
|
|
145
|
+
function defaultRetryOn(err) {
|
|
146
|
+
return isNetError(err) && err.retryable;
|
|
147
|
+
}
|
|
148
|
+
function sleep(ms, signal) {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
const timer = setTimeout(() => {
|
|
151
|
+
resolve();
|
|
152
|
+
if (signal) signal.removeEventListener("abort", onAbort);
|
|
153
|
+
}, ms);
|
|
154
|
+
const onAbort = () => {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
reject(signal?.reason ?? new Error("Aborted"));
|
|
157
|
+
};
|
|
158
|
+
if (signal) {
|
|
159
|
+
if (signal.aborted) {
|
|
160
|
+
clearTimeout(timer);
|
|
161
|
+
reject(signal.reason);
|
|
162
|
+
} else {
|
|
163
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
async function withRetry(fn, opts = {}) {
|
|
169
|
+
const attempts = Math.max(1, opts.attempts ?? 3);
|
|
170
|
+
const initialDelayMs = opts.initialDelayMs ?? 250;
|
|
171
|
+
const maxDelayMs = opts.maxDelayMs ?? 4e3;
|
|
172
|
+
const factor = opts.backoffFactor ?? 2;
|
|
173
|
+
const jitter = Math.max(0, Math.min(1, opts.jitter ?? 0.25));
|
|
174
|
+
const retryOn = opts.retryOn ?? defaultRetryOn;
|
|
175
|
+
let lastErr;
|
|
176
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
177
|
+
if (opts.signal?.aborted) throw opts.signal.reason;
|
|
178
|
+
try {
|
|
179
|
+
return await fn(attempt);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
lastErr = err;
|
|
182
|
+
if (attempt === attempts || !retryOn(err)) throw err;
|
|
183
|
+
const base = Math.min(
|
|
184
|
+
maxDelayMs,
|
|
185
|
+
initialDelayMs * Math.pow(factor, attempt - 1)
|
|
186
|
+
);
|
|
187
|
+
const jitterAmount = base * jitter * (Math.random() * 2 - 1);
|
|
188
|
+
const delayMs = Math.max(0, Math.round(base + jitterAmount));
|
|
189
|
+
opts.onRetry?.(attempt, err, delayMs);
|
|
190
|
+
await sleep(delayMs, opts.signal);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
throw lastErr;
|
|
194
|
+
}
|
|
195
|
+
|
|
144
196
|
// src/net/resilient-fetch.ts
|
|
145
197
|
var DEFAULTS = {
|
|
146
198
|
connectTimeoutMs: 15e3,
|
|
@@ -209,56 +261,58 @@ async function resilientFetch(url, init = {}, opts = {}) {
|
|
|
209
261
|
}
|
|
210
262
|
}
|
|
211
263
|
|
|
212
|
-
// src/net/
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
reject(signal.reason);
|
|
230
|
-
} else {
|
|
231
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
232
|
-
}
|
|
264
|
+
// src/net/stream-monitor.ts
|
|
265
|
+
var DEFAULTS2 = {
|
|
266
|
+
heartbeatTimeoutMs: 3e4,
|
|
267
|
+
maxLifetimeMs: 6e5
|
|
268
|
+
};
|
|
269
|
+
async function* monitorStream(source, opts = {}) {
|
|
270
|
+
const heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? DEFAULTS2.heartbeatTimeoutMs;
|
|
271
|
+
const maxLifetimeMs = opts.maxLifetimeMs ?? DEFAULTS2.maxLifetimeMs;
|
|
272
|
+
const abort = opts.abortController;
|
|
273
|
+
const startedAt = Date.now();
|
|
274
|
+
const iter = source[Symbol.asyncIterator]();
|
|
275
|
+
while (true) {
|
|
276
|
+
const elapsed = Date.now() - startedAt;
|
|
277
|
+
const remainingLifetime = maxLifetimeMs - elapsed;
|
|
278
|
+
if (remainingLifetime <= 0) {
|
|
279
|
+
abort?.abort("total-timeout");
|
|
280
|
+
throw new TotalTimeoutError(maxLifetimeMs);
|
|
233
281
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
282
|
+
const deadline = Math.min(heartbeatTimeoutMs, remainingLifetime);
|
|
283
|
+
let timer = null;
|
|
284
|
+
let timedOutKind = null;
|
|
285
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
286
|
+
timer = setTimeout(() => {
|
|
287
|
+
timedOutKind = deadline === remainingLifetime ? "total" : "heartbeat";
|
|
288
|
+
abort?.abort(
|
|
289
|
+
timedOutKind === "total" ? "total-timeout" : "heartbeat-timeout"
|
|
290
|
+
);
|
|
291
|
+
reject(
|
|
292
|
+
timedOutKind === "total" ? new TotalTimeoutError(maxLifetimeMs) : new HeartbeatTimeoutError(heartbeatTimeoutMs)
|
|
293
|
+
);
|
|
294
|
+
}, deadline);
|
|
295
|
+
});
|
|
296
|
+
let result;
|
|
246
297
|
try {
|
|
247
|
-
|
|
298
|
+
result = await Promise.race([iter.next(), timeoutPromise]);
|
|
248
299
|
} catch (err) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
300
|
+
if (timer !== null) clearTimeout(timer);
|
|
301
|
+
try {
|
|
302
|
+
const cleanup = iter.return?.(void 0);
|
|
303
|
+
if (cleanup) {
|
|
304
|
+
void Promise.resolve(cleanup).catch(() => {
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
} catch {
|
|
308
|
+
}
|
|
309
|
+
throw err;
|
|
259
310
|
}
|
|
311
|
+
if (timer !== null) clearTimeout(timer);
|
|
312
|
+
if (result.done) return;
|
|
313
|
+
opts.onHeartbeat?.(Date.now());
|
|
314
|
+
yield result.value;
|
|
260
315
|
}
|
|
261
|
-
throw lastErr;
|
|
262
316
|
}
|
|
263
317
|
|
|
264
|
-
export { AbortedError, ConnectTimeoutError, HeartbeatTimeoutError, HttpError, NetError, NetworkError, OfflineError, TotalTimeoutError, extractErrorMessage, isNetError, isTransportFailure, resilientFetch, toNetError, withRetry };
|
|
318
|
+
export { AbortedError, ConnectTimeoutError, HeartbeatTimeoutError, HttpError, NetError, NetworkError, OfflineError, TotalTimeoutError, extractErrorMessage, isNetError, isTransportFailure, monitorStream, resilientFetch, toNetError, withRetry };
|