@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.
Files changed (135) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +1 -1
  3. package/dist/account.d.cts +1 -1
  4. package/dist/account.d.ts +1 -1
  5. package/dist/agents.cjs +12 -12
  6. package/dist/agents.d.cts +1 -1
  7. package/dist/agents.d.ts +1 -1
  8. package/dist/agents.js +2 -2
  9. package/dist/ai.cjs +3 -3
  10. package/dist/ai.d.cts +1 -1
  11. package/dist/ai.d.ts +1 -1
  12. package/dist/ai.js +2 -2
  13. package/dist/apps.cjs +6 -6
  14. package/dist/apps.d.cts +1 -1
  15. package/dist/apps.d.ts +1 -1
  16. package/dist/apps.js +2 -2
  17. package/dist/architecture.cjs +11 -11
  18. package/dist/architecture.d.cts +1 -1
  19. package/dist/architecture.d.ts +1 -1
  20. package/dist/architecture.js +2 -2
  21. package/dist/audio.cjs +5 -5
  22. package/dist/audio.d.cts +1 -1
  23. package/dist/audio.d.ts +1 -1
  24. package/dist/audio.js +2 -2
  25. package/dist/chat.cjs +12 -12
  26. package/dist/chat.d.cts +1 -1
  27. package/dist/chat.d.ts +1 -1
  28. package/dist/chat.js +2 -2
  29. package/dist/{chunk-PMGKZ4FT.cjs → chunk-2ZHIYXHV.cjs} +279 -34
  30. package/dist/{chunk-PIVTHTVR.js → chunk-6KHHHBG5.js} +270 -36
  31. package/dist/{chunk-KIEAFMKB.js → chunk-PIPE5OML.js} +100 -46
  32. package/dist/{chunk-2SXAAKGV.cjs → chunk-PKYPPATQ.cjs} +100 -45
  33. package/dist/code.cjs +7 -7
  34. package/dist/code.d.cts +1 -1
  35. package/dist/code.d.ts +1 -1
  36. package/dist/code.js +2 -2
  37. package/dist/commerce.d.cts +1 -1
  38. package/dist/commerce.d.ts +1 -1
  39. package/dist/communications.cjs +5 -5
  40. package/dist/communications.d.cts +1 -1
  41. package/dist/communications.d.ts +1 -1
  42. package/dist/communications.js +2 -2
  43. package/dist/computer.cjs +4 -4
  44. package/dist/computer.d.cts +1 -1
  45. package/dist/computer.d.ts +1 -1
  46. package/dist/computer.js +2 -2
  47. package/dist/content.cjs +5 -5
  48. package/dist/content.d.cts +1 -1
  49. package/dist/content.d.ts +1 -1
  50. package/dist/content.js +2 -2
  51. package/dist/crm.cjs +3 -3
  52. package/dist/crm.d.cts +1 -1
  53. package/dist/crm.d.ts +1 -1
  54. package/dist/crm.js +2 -2
  55. package/dist/data.d.cts +1 -1
  56. package/dist/data.d.ts +1 -1
  57. package/dist/education.cjs +5 -5
  58. package/dist/education.d.cts +1 -1
  59. package/dist/education.d.ts +1 -1
  60. package/dist/education.js +2 -2
  61. package/dist/files.cjs +21 -21
  62. package/dist/files.d.cts +1 -1
  63. package/dist/files.d.ts +1 -1
  64. package/dist/files.js +2 -2
  65. package/dist/human-resources.d.cts +1 -1
  66. package/dist/human-resources.d.ts +1 -1
  67. package/dist/{index-C3ZlP3BI.d.cts → index-Gj30ybjE.d.cts} +42 -3
  68. package/dist/{index-C3ZlP3BI.d.ts → index-Gj30ybjE.d.ts} +42 -3
  69. package/dist/index.cjs +188 -288
  70. package/dist/index.d.cts +129 -180
  71. package/dist/index.d.ts +129 -180
  72. package/dist/index.js +81 -206
  73. package/dist/integrations.cjs +4 -4
  74. package/dist/integrations.d.cts +1 -1
  75. package/dist/integrations.d.ts +1 -1
  76. package/dist/integrations.js +2 -2
  77. package/dist/intelligence.cjs +10 -8
  78. package/dist/intelligence.d.cts +13 -13
  79. package/dist/intelligence.d.ts +13 -13
  80. package/dist/intelligence.js +5 -3
  81. package/dist/{keys.generated-CK_C5UXG.d.cts → keys.generated-DZUiM-uA.d.cts} +5 -3
  82. package/dist/{keys.generated-CK_C5UXG.d.ts → keys.generated-DZUiM-uA.d.ts} +5 -3
  83. package/dist/knowledge.cjs +43 -43
  84. package/dist/knowledge.d.cts +13 -13
  85. package/dist/knowledge.d.ts +13 -13
  86. package/dist/knowledge.js +2 -2
  87. package/dist/legal.cjs +7 -7
  88. package/dist/legal.d.cts +1 -1
  89. package/dist/legal.d.ts +1 -1
  90. package/dist/legal.js +2 -2
  91. package/dist/marketing.cjs +77 -77
  92. package/dist/marketing.d.cts +27 -27
  93. package/dist/marketing.d.ts +27 -27
  94. package/dist/marketing.js +2 -2
  95. package/dist/masterwork.cjs +33 -33
  96. package/dist/masterwork.d.cts +1 -1
  97. package/dist/masterwork.d.ts +1 -1
  98. package/dist/masterwork.js +2 -2
  99. package/dist/media.cjs +12 -12
  100. package/dist/media.d.cts +1 -1
  101. package/dist/media.d.ts +1 -1
  102. package/dist/media.js +2 -2
  103. package/dist/net.cjs +19 -20
  104. package/dist/net.d.cts +41 -41
  105. package/dist/net.d.ts +41 -41
  106. package/dist/net.js +1 -2
  107. package/dist/platform.cjs +4 -4
  108. package/dist/platform.d.cts +1 -1
  109. package/dist/platform.d.ts +1 -1
  110. package/dist/platform.js +2 -2
  111. package/dist/publish.cjs +8 -8
  112. package/dist/publish.d.cts +1 -1
  113. package/dist/publish.d.ts +1 -1
  114. package/dist/publish.js +2 -2
  115. package/dist/schemas.d.cts +78 -15
  116. package/dist/schemas.d.ts +78 -15
  117. package/dist/stream.cjs +11 -11
  118. package/dist/stream.d.cts +1 -1
  119. package/dist/stream.d.ts +1 -1
  120. package/dist/stream.js +2 -2
  121. package/dist/types.cjs +2 -0
  122. package/dist/types.d.cts +72245 -0
  123. package/dist/types.d.ts +72245 -0
  124. package/dist/types.js +1 -0
  125. package/dist/web.cjs +27 -27
  126. package/dist/web.d.cts +17 -17
  127. package/dist/web.d.ts +17 -17
  128. package/dist/web.js +2 -2
  129. package/dist/workflows.cjs +14 -14
  130. package/dist/workflows.d.cts +23 -26
  131. package/dist/workflows.d.ts +23 -26
  132. package/dist/workflows.js +2 -2
  133. package/package.json +14 -4
  134. package/dist/chunk-FNIYADWI.cjs +0 -59
  135. package/dist/chunk-YTEOFGFC.js +0 -57
@@ -1,6 +1,89 @@
1
- import { withRetry, isTransportFailure, resilientFetch } from './chunk-KIEAFMKB.js';
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, credentialToHeaders } from '@ai-matrx/auth/credentials';
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 attempt = (sendHeaders = headers) => resilientFetch(
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 ?? DEFAULT_CONNECT_TIMEOUT_MS,
1181
+ connectTimeoutMs: call?.connectTimeoutMs ?? options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS2,
941
1182
  totalTimeoutMs: call?.totalTimeoutMs !== void 0 ? call.totalTimeoutMs : options.totalTimeoutMs ?? null,
942
- throwOnHttpError: false
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/retry.ts
213
- function defaultRetryOn(err) {
214
- return isNetError(err) && err.retryable;
215
- }
216
- function sleep(ms, signal) {
217
- return new Promise((resolve, reject) => {
218
- const timer = setTimeout(() => {
219
- resolve();
220
- if (signal) signal.removeEventListener("abort", onAbort);
221
- }, ms);
222
- const onAbort = () => {
223
- clearTimeout(timer);
224
- reject(signal?.reason ?? new Error("Aborted"));
225
- };
226
- if (signal) {
227
- if (signal.aborted) {
228
- clearTimeout(timer);
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
- async function withRetry(fn, opts = {}) {
237
- const attempts = Math.max(1, opts.attempts ?? 3);
238
- const initialDelayMs = opts.initialDelayMs ?? 250;
239
- const maxDelayMs = opts.maxDelayMs ?? 4e3;
240
- const factor = opts.backoffFactor ?? 2;
241
- const jitter = Math.max(0, Math.min(1, opts.jitter ?? 0.25));
242
- const retryOn = opts.retryOn ?? defaultRetryOn;
243
- let lastErr;
244
- for (let attempt = 1; attempt <= attempts; attempt++) {
245
- if (opts.signal?.aborted) throw opts.signal.reason;
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
- return await fn(attempt);
298
+ result = await Promise.race([iter.next(), timeoutPromise]);
248
299
  } catch (err) {
249
- lastErr = err;
250
- if (attempt === attempts || !retryOn(err)) throw err;
251
- const base = Math.min(
252
- maxDelayMs,
253
- initialDelayMs * Math.pow(factor, attempt - 1)
254
- );
255
- const jitterAmount = base * jitter * (Math.random() * 2 - 1);
256
- const delayMs = Math.max(0, Math.round(base + jitterAmount));
257
- opts.onRetry?.(attempt, err, delayMs);
258
- await sleep(delayMs, opts.signal);
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 };