@ai-matrx/agents 0.36.0 → 0.37.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/CHANGELOG.md +10 -0
- package/dist/content-transfer/index.cjs +12 -12
- package/dist/content-transfer/index.cjs.map +1 -1
- package/dist/content-transfer/index.d.cts +1 -1
- package/dist/content-transfer/index.d.ts +1 -1
- package/dist/content-transfer/index.js +12 -12
- package/dist/content-transfer/index.js.map +1 -1
- package/dist/content-transfer/react/index.cjs +12 -12
- package/dist/content-transfer/react/index.cjs.map +1 -1
- package/dist/content-transfer/react/index.d.cts +1 -1
- package/dist/content-transfer/react/index.d.ts +1 -1
- package/dist/content-transfer/react/index.js +12 -12
- package/dist/content-transfer/react/index.js.map +1 -1
- package/dist/index.cjs +1458 -1220
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1461 -1223
- package/dist/index.js.map +1 -1
- package/dist/{keys.generated-DCtN66RS.d.cts → keys.generated-klzs6I1T.d.cts} +4 -4
- package/dist/{keys.generated-DCtN66RS.d.ts → keys.generated-klzs6I1T.d.ts} +4 -4
- package/dist/mandates/index.cjs +2 -2
- package/dist/mandates/index.cjs.map +1 -1
- package/dist/mandates/index.d.cts +2 -2
- package/dist/mandates/index.d.ts +2 -2
- package/dist/mandates/index.js +2 -2
- package/dist/mandates/index.js.map +1 -1
- package/dist/matrx/index.cjs +1721 -1483
- package/dist/matrx/index.cjs.map +1 -1
- package/dist/matrx/index.d.cts +376 -211
- package/dist/matrx/index.d.ts +376 -211
- package/dist/matrx/index.js +1724 -1486
- package/dist/matrx/index.js.map +1 -1
- package/dist/message-parts/index.d.cts +1 -100929
- package/dist/message-parts/index.d.ts +1 -100929
- package/dist/portable/mcp.cjs +99 -11
- package/dist/portable/mcp.cjs.map +1 -1
- package/dist/portable/mcp.js +99 -11
- package/dist/portable/mcp.js.map +1 -1
- package/dist/react/index.cjs +145 -57
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +3 -1
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.js +145 -57
- package/dist/react/index.js.map +1 -1
- package/mandates/snapshots/keys.0.37.0.json +653 -0
- package/package.json +2 -2
- package/dist/{operations-BT5kKMHl.d.cts → operations-DqOe2zob.d.cts} +34 -34
- package/dist/{operations-BT5kKMHl.d.ts → operations-DqOe2zob.d.ts} +34 -34
package/dist/index.js
CHANGED
|
@@ -859,1387 +859,1614 @@ function extractMatrxErrorCode(serverDetail) {
|
|
|
859
859
|
// matrx/client.ts
|
|
860
860
|
import { isNetError as isNetError2 } from "@ai-matrx/data";
|
|
861
861
|
import { credentialToHeaders } from "@ai-matrx/data";
|
|
862
|
+
import { extractErrorMessage } from "@ai-matrx/data/net";
|
|
862
863
|
|
|
863
|
-
// matrx/
|
|
864
|
-
|
|
865
|
-
|
|
864
|
+
// matrx/backend-errors.ts
|
|
865
|
+
var BackendApiError = class extends Error {
|
|
866
|
+
/** Machine-readable error code */
|
|
866
867
|
code;
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
const candidate = overrideOrganizationId ?? selectedOrganizationId;
|
|
887
|
-
if (typeof candidate !== "string" || candidate.trim().length === 0) {
|
|
888
|
-
throw new OrganizationContextError(
|
|
889
|
-
"organization_context_required",
|
|
890
|
-
"Select an organization before sending this request."
|
|
891
|
-
);
|
|
868
|
+
/** Developer-facing detail */
|
|
869
|
+
detail;
|
|
870
|
+
/** Safe to display directly in the UI */
|
|
871
|
+
userMessage;
|
|
872
|
+
/** Extra info (validation errors, etc.) */
|
|
873
|
+
details;
|
|
874
|
+
/** Unique request ID for support/debugging */
|
|
875
|
+
requestId;
|
|
876
|
+
/** HTTP status code (if from an HTTP response) */
|
|
877
|
+
status;
|
|
878
|
+
constructor(data) {
|
|
879
|
+
super(data.userMessage);
|
|
880
|
+
this.name = "BackendApiError";
|
|
881
|
+
this.code = data.code;
|
|
882
|
+
this.detail = data.detail;
|
|
883
|
+
this.userMessage = data.userMessage;
|
|
884
|
+
this.details = data.details ?? null;
|
|
885
|
+
this.requestId = data.requestId ?? "";
|
|
886
|
+
this.status = data.status ?? null;
|
|
892
887
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
888
|
+
/** Convert to the wire format for logging */
|
|
889
|
+
toJSON() {
|
|
890
|
+
return {
|
|
891
|
+
error: this.code,
|
|
892
|
+
message: this.detail,
|
|
893
|
+
user_message: this.userMessage,
|
|
894
|
+
details: this.details,
|
|
895
|
+
request_id: this.requestId
|
|
896
|
+
};
|
|
899
897
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
898
|
+
};
|
|
899
|
+
var StreamTransportError = class extends BackendApiError {
|
|
900
|
+
/** Always true — reattach and let the server settle the outcome. */
|
|
901
|
+
resumable = true;
|
|
902
|
+
constructor(data) {
|
|
903
|
+
super({
|
|
904
|
+
code: "stream_transport_lost",
|
|
905
|
+
detail: data.detail,
|
|
906
|
+
userMessage: "The connection dropped. Your run is still going on the server \u2014 reconnecting to it now.",
|
|
907
|
+
details: data.details ?? null,
|
|
908
|
+
...data.requestId !== void 0 ? { requestId: data.requestId } : {}
|
|
909
|
+
});
|
|
910
|
+
this.name = "StreamTransportError";
|
|
911
911
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
return {
|
|
918
|
-
...withoutOrganizationHeader,
|
|
919
|
-
"X-Organization-Id": normalizedOrganizationId
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
function assertQueryOrganizationMatchesContext(queryParams, organizationId) {
|
|
923
|
-
if (!queryParams || queryParams.organization_id === void 0) return;
|
|
924
|
-
const queryOrganizationId = requireOrganizationContext(
|
|
925
|
-
String(queryParams.organization_id)
|
|
926
|
-
);
|
|
927
|
-
if (queryOrganizationId !== requireOrganizationContext(organizationId)) {
|
|
928
|
-
throw new OrganizationContextError(
|
|
929
|
-
"organization_context_mismatch",
|
|
930
|
-
"Query organization_id must match the request context organization."
|
|
931
|
-
);
|
|
912
|
+
};
|
|
913
|
+
function isStreamTransportLost(error) {
|
|
914
|
+
if (error instanceof StreamTransportError) return true;
|
|
915
|
+
if (error instanceof BackendApiError) {
|
|
916
|
+
return error.code === "stream_transport_lost";
|
|
932
917
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
resilientFetch
|
|
939
|
-
} from "@ai-matrx/data/net";
|
|
940
|
-
var MATRX_AI_API_VERSION_DEFAULT = "v2";
|
|
941
|
-
var V2_COVERED_AI_PATH_TEMPLATES = [
|
|
942
|
-
"/ai/manual",
|
|
943
|
-
"/ai/chat",
|
|
944
|
-
"/ai/agents/{agent_id}",
|
|
945
|
-
"/ai/agent/{agent_id}",
|
|
946
|
-
// singular alias — behaves identically
|
|
947
|
-
"/ai/conversations/{conversation_id}",
|
|
948
|
-
"/ai/conversation/{conversation_id}",
|
|
949
|
-
// singular alias
|
|
950
|
-
"/ai/prompts/{prompt_id}",
|
|
951
|
-
// saved-prompt execution
|
|
952
|
-
"/ai/mandates/{mandate_key}"
|
|
953
|
-
// THE MANDATE DOOR — `/v2` sibling exists (routers/v2.py)
|
|
954
|
-
];
|
|
955
|
-
function toV2Path(path) {
|
|
956
|
-
const withLead = path.startsWith("/") ? path : `/${path}`;
|
|
957
|
-
if (withLead.startsWith("/api/")) {
|
|
958
|
-
const rest = withLead.slice("/api".length);
|
|
959
|
-
return rest.startsWith("/v2/") ? withLead : `/api/v2${rest}`;
|
|
918
|
+
if (error && typeof error === "object") {
|
|
919
|
+
const code = error.code;
|
|
920
|
+
if (code === "stream_transport_lost") return true;
|
|
921
|
+
const errorType = error.error_type;
|
|
922
|
+
if (errorType === "transport_lost") return true;
|
|
960
923
|
}
|
|
961
|
-
return
|
|
962
|
-
}
|
|
963
|
-
var COVERED_INTERPOLATED_PATH = [
|
|
964
|
-
/^(?:\/api)?\/ai\/manual$/,
|
|
965
|
-
/^(?:\/api)?\/ai\/chat$/,
|
|
966
|
-
/^(?:\/api)?\/ai\/agents\/[^/]+$/,
|
|
967
|
-
/^(?:\/api)?\/ai\/agent\/[^/]+$/,
|
|
968
|
-
/^(?:\/api)?\/ai\/conversations\/[^/]+$/,
|
|
969
|
-
/^(?:\/api)?\/ai\/conversation\/[^/]+$/,
|
|
970
|
-
/^(?:\/api)?\/ai\/prompts\/[^/]+$/,
|
|
971
|
-
// `/warm` etc. deliberately don't match
|
|
972
|
-
/^(?:\/api)?\/ai\/mandates\/[^/]+$/
|
|
973
|
-
// the mandate door
|
|
974
|
-
];
|
|
975
|
-
function isCoveredAiPath(path) {
|
|
976
|
-
return COVERED_INTERPOLATED_PATH.some((re) => re.test(path));
|
|
977
|
-
}
|
|
978
|
-
function isV2Path(pathOrUrl) {
|
|
979
|
-
return /\/v2\/ai\//.test(pathOrUrl);
|
|
980
|
-
}
|
|
981
|
-
function toV1FallbackUrl(url) {
|
|
982
|
-
return url.replace(/\/v2\/ai\//, "/ai/");
|
|
983
|
-
}
|
|
984
|
-
function applyAiApiVersion(path, version) {
|
|
985
|
-
if (version !== "v2") return path;
|
|
986
|
-
return isCoveredAiPath(path) ? toV2Path(path) : path;
|
|
924
|
+
return false;
|
|
987
925
|
}
|
|
988
|
-
async function
|
|
989
|
-
const
|
|
990
|
-
|
|
991
|
-
console.warn(
|
|
992
|
-
`[matrx] ai_v2_downgrade \u2192 retrying on v1. v2=${url} reason=${reason}`
|
|
993
|
-
);
|
|
994
|
-
onDowngrade?.({ url, reason, ...status2 !== void 0 ? { status: status2 } : {} });
|
|
995
|
-
};
|
|
996
|
-
if (!isV2Path(url)) return resilientFetch(url, init, fetchOpts);
|
|
997
|
-
let result;
|
|
926
|
+
async function parseHttpError(response) {
|
|
927
|
+
const status = response.status;
|
|
928
|
+
let body = null;
|
|
998
929
|
try {
|
|
999
|
-
|
|
1000
|
-
} catch
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
map[template] = toV2Path(template);
|
|
930
|
+
body = await response.json();
|
|
931
|
+
} catch {
|
|
932
|
+
try {
|
|
933
|
+
const text = await response.text();
|
|
934
|
+
return new BackendApiError({
|
|
935
|
+
code: statusToCode(status),
|
|
936
|
+
detail: text || `HTTP ${status}`,
|
|
937
|
+
userMessage: text || `Request failed (${status})`,
|
|
938
|
+
status
|
|
939
|
+
});
|
|
940
|
+
} catch {
|
|
941
|
+
return new BackendApiError({
|
|
942
|
+
code: statusToCode(status),
|
|
943
|
+
detail: `HTTP ${status}`,
|
|
944
|
+
userMessage: `Request failed (${status})`,
|
|
945
|
+
status
|
|
946
|
+
});
|
|
947
|
+
}
|
|
1018
948
|
}
|
|
1019
|
-
return
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
// matrx/client.ts
|
|
1023
|
-
function classifyStatus(status) {
|
|
1024
|
-
return status >= 400 && status < 500 ? "validation_error" : "http_error";
|
|
949
|
+
return parseHttpErrorBody(body, status);
|
|
1025
950
|
}
|
|
1026
|
-
function
|
|
1027
|
-
if (
|
|
1028
|
-
return {
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
name: err.name
|
|
1035
|
-
};
|
|
951
|
+
function parseHttpErrorBody(body, status) {
|
|
952
|
+
if (!body) {
|
|
953
|
+
return new BackendApiError({
|
|
954
|
+
code: statusToCode(status),
|
|
955
|
+
detail: `HTTP ${status}`,
|
|
956
|
+
userMessage: `Request failed (${status})`,
|
|
957
|
+
status
|
|
958
|
+
});
|
|
1036
959
|
}
|
|
1037
|
-
if (
|
|
1038
|
-
return {
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
960
|
+
if (typeof body.error === "string" && typeof body.user_message === "string") {
|
|
961
|
+
return new BackendApiError({
|
|
962
|
+
code: body.error,
|
|
963
|
+
detail: body.message || `HTTP ${status}`,
|
|
964
|
+
userMessage: body.user_message,
|
|
965
|
+
details: body.details ?? null,
|
|
966
|
+
requestId: typeof body.request_id === "string" ? body.request_id : void 0,
|
|
967
|
+
status
|
|
968
|
+
});
|
|
1045
969
|
}
|
|
1046
|
-
if (
|
|
1047
|
-
|
|
970
|
+
if (typeof body.error === "object" && body.error !== null) {
|
|
971
|
+
const errorObj = body.error;
|
|
972
|
+
return new BackendApiError({
|
|
973
|
+
code: errorObj.type || errorObj.error || statusToCode(status),
|
|
974
|
+
detail: errorObj.message || `HTTP ${status}`,
|
|
975
|
+
userMessage: errorObj.user_message || errorObj.user_visible_message || errorObj.message || `Request failed (${status})`,
|
|
976
|
+
details: errorObj.details ?? null,
|
|
977
|
+
requestId: typeof errorObj.request_id === "string" ? errorObj.request_id : void 0,
|
|
978
|
+
status
|
|
979
|
+
});
|
|
1048
980
|
}
|
|
1049
|
-
if (
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
981
|
+
if (Array.isArray(body.detail)) {
|
|
982
|
+
const first = body.detail[0];
|
|
983
|
+
const firstMsg = first && typeof first.msg === "string" ? first.msg : null;
|
|
984
|
+
return new BackendApiError({
|
|
985
|
+
code: statusToCode(status),
|
|
986
|
+
detail: firstMsg ? `Validation error: ${firstMsg}` : JSON.stringify(body.detail),
|
|
987
|
+
userMessage: firstMsg || `Request failed (${status})`,
|
|
988
|
+
details: body.detail,
|
|
989
|
+
status
|
|
990
|
+
});
|
|
1058
991
|
}
|
|
1059
|
-
if (
|
|
1060
|
-
const
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
992
|
+
if (typeof body.detail === "object" && body.detail !== null && !Array.isArray(body.detail)) {
|
|
993
|
+
const d = body.detail;
|
|
994
|
+
const code = typeof d.code === "string" && d.code || typeof d.error === "string" && d.error || statusToCode(status);
|
|
995
|
+
const message = typeof d.message === "string" && d.message || typeof d.detail === "string" && d.detail || `HTTP ${status}`;
|
|
996
|
+
return new BackendApiError({
|
|
997
|
+
code,
|
|
998
|
+
detail: message,
|
|
999
|
+
userMessage: typeof d.user_message === "string" && d.user_message || typeof d.user_visible_message === "string" && d.user_visible_message || message,
|
|
1000
|
+
details: d.details ?? d,
|
|
1001
|
+
requestId: typeof d.request_id === "string" ? d.request_id : void 0,
|
|
1002
|
+
status
|
|
1003
|
+
});
|
|
1070
1004
|
}
|
|
1071
|
-
return
|
|
1005
|
+
return new BackendApiError({
|
|
1006
|
+
code: typeof body.error === "string" ? body.error : statusToCode(status),
|
|
1007
|
+
detail: body.message || body.detail || body.error || `HTTP ${status}`,
|
|
1008
|
+
userMessage: body.user_message || body.user_visible_message || body.message || body.detail || `Request failed (${status})`,
|
|
1009
|
+
details: body.details ?? null,
|
|
1010
|
+
requestId: typeof body.request_id === "string" ? body.request_id : void 0,
|
|
1011
|
+
status
|
|
1012
|
+
});
|
|
1072
1013
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
([name]) => name.toLowerCase() !== "content-type"
|
|
1078
|
-
)
|
|
1079
|
-
);
|
|
1014
|
+
function parseCallApiError(error) {
|
|
1015
|
+
const status = error.status ?? 500;
|
|
1016
|
+
const body = error.serverDetail && typeof error.serverDetail === "object" && !Array.isArray(error.serverDetail) ? error.serverDetail : { message: error.message };
|
|
1017
|
+
return parseHttpErrorBody(body, status);
|
|
1080
1018
|
}
|
|
1081
|
-
function
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
connectTimeoutMs = PRODUCTION_CONNECT_TIMEOUT_MS,
|
|
1089
|
-
totalTimeoutMs = null,
|
|
1090
|
-
expectedErrorStatuses,
|
|
1091
|
-
diagnostics,
|
|
1092
|
-
source = "matrxTransport"
|
|
1093
|
-
} = options;
|
|
1094
|
-
if (baseUrl === void 0 === (resolveTarget === void 0)) {
|
|
1095
|
-
throw new Error(
|
|
1096
|
-
"createMatrxTransport: provide exactly one of `baseUrl` or `resolveTarget`."
|
|
1097
|
-
);
|
|
1019
|
+
function parseStreamError(data) {
|
|
1020
|
+
if (!data || typeof data !== "object") {
|
|
1021
|
+
return new BackendApiError({
|
|
1022
|
+
code: "internal_error",
|
|
1023
|
+
detail: typeof data === "string" ? data : "Unknown streaming error",
|
|
1024
|
+
userMessage: typeof data === "string" ? data : "Something went wrong"
|
|
1025
|
+
});
|
|
1098
1026
|
}
|
|
1099
|
-
const
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
};
|
|
1109
|
-
return {
|
|
1110
|
-
async fetch(path, init) {
|
|
1111
|
-
const target = resolve();
|
|
1112
|
-
const versionedPath = applyAiApiVersion(path, resolveVersion());
|
|
1113
|
-
const url = `${target.baseUrl}${versionedPath}`;
|
|
1114
|
-
const credentialHeaders = credentials ? credentialToHeaders(await credentials.get()) : {};
|
|
1115
|
-
let headers = {
|
|
1116
|
-
...init.headers,
|
|
1117
|
-
...stripContentType(credentialHeaders),
|
|
1118
|
-
...stripContentType(target.policyHeaders ?? {})
|
|
1119
|
-
};
|
|
1120
|
-
const orgId = resolveOrganizationId();
|
|
1121
|
-
if (orgId !== null) {
|
|
1122
|
-
headers = applyOrganizationContextHeader(headers, orgId);
|
|
1123
|
-
}
|
|
1124
|
-
const info = {
|
|
1125
|
-
url,
|
|
1126
|
-
method: init.method,
|
|
1127
|
-
path,
|
|
1128
|
-
channel: target.channel ?? "default",
|
|
1129
|
-
source
|
|
1130
|
-
};
|
|
1131
|
-
diagnostics?.onRequest?.(info);
|
|
1132
|
-
let response;
|
|
1133
|
-
try {
|
|
1134
|
-
({ response } = await fetchWithMatrxProtocolFallback(
|
|
1135
|
-
url,
|
|
1136
|
-
{
|
|
1137
|
-
method: init.method,
|
|
1138
|
-
headers,
|
|
1139
|
-
...init.body !== void 0 ? { body: init.body } : {}
|
|
1140
|
-
},
|
|
1141
|
-
{
|
|
1142
|
-
...init.signal ? { signal: init.signal } : {},
|
|
1143
|
-
connectTimeoutMs,
|
|
1144
|
-
totalTimeoutMs,
|
|
1145
|
-
throwOnHttpError: false,
|
|
1146
|
-
...diagnostics?.onProtocolDowngrade ? { onDowngrade: diagnostics.onProtocolDowngrade } : {}
|
|
1147
|
-
}
|
|
1148
|
-
));
|
|
1149
|
-
} catch (err) {
|
|
1150
|
-
diagnostics?.onError?.(normalizeMatrxError(err), info);
|
|
1151
|
-
throw err;
|
|
1152
|
-
}
|
|
1153
|
-
if (!response.ok && !expectedErrorStatuses?.includes(response.status)) {
|
|
1154
|
-
const serverDetail = await response.clone().json().catch(() => void 0);
|
|
1155
|
-
const code = extractMatrxErrorCode(serverDetail);
|
|
1156
|
-
diagnostics?.onError?.(
|
|
1157
|
-
{
|
|
1158
|
-
type: classifyStatus(response.status),
|
|
1159
|
-
message: extractMatrxErrorMessage(serverDetail) ?? `HTTP ${response.status}`,
|
|
1160
|
-
status: response.status,
|
|
1161
|
-
serverDetail,
|
|
1162
|
-
...code ? { code } : {}
|
|
1163
|
-
},
|
|
1164
|
-
info
|
|
1165
|
-
);
|
|
1166
|
-
}
|
|
1167
|
-
return response;
|
|
1168
|
-
}
|
|
1169
|
-
};
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
// matrx/conversation.ts
|
|
1173
|
-
function mintMatrxConversationId() {
|
|
1174
|
-
return crypto.randomUUID();
|
|
1175
|
-
}
|
|
1176
|
-
function newStoredConversationStart(conversationId) {
|
|
1177
|
-
return {
|
|
1178
|
-
conversation_id: conversationId ?? mintMatrxConversationId(),
|
|
1179
|
-
is_new: true,
|
|
1180
|
-
store: true
|
|
1181
|
-
};
|
|
1027
|
+
const obj = data;
|
|
1028
|
+
const details = typeof obj.details === "object" && obj.details !== null ? obj.details : null;
|
|
1029
|
+
return new BackendApiError({
|
|
1030
|
+
code: obj.code || obj.error_type || obj.error || "internal_error",
|
|
1031
|
+
detail: obj.message || "Streaming error",
|
|
1032
|
+
userMessage: obj.user_message || obj.message || "Something went wrong",
|
|
1033
|
+
details,
|
|
1034
|
+
requestId: typeof obj.request_id === "string" ? obj.request_id : typeof details?.request_id === "string" ? details.request_id : void 0
|
|
1035
|
+
});
|
|
1182
1036
|
}
|
|
1183
|
-
function
|
|
1184
|
-
|
|
1037
|
+
function parsePersistedBackendError(data, requestId = "") {
|
|
1038
|
+
if (!data || typeof data !== "object") return null;
|
|
1039
|
+
const error = data;
|
|
1040
|
+
const failures = Array.isArray(error.failures) ? error.failures : [];
|
|
1041
|
+
const firstSpecific = failures.find(
|
|
1042
|
+
(failure) => typeof failure === "object" && failure !== null && typeof failure.message === "string"
|
|
1043
|
+
);
|
|
1044
|
+
const summary = typeof error.message === "string" ? error.message : "Backend operation failed";
|
|
1045
|
+
const specific = typeof firstSpecific?.message === "string" ? firstSpecific.message : summary;
|
|
1046
|
+
const detail = specific === summary ? summary : `${summary}: ${specific}`;
|
|
1047
|
+
const code = typeof error.type === "string" ? error.type : "internal_error";
|
|
1048
|
+
const userMessage = typeof error.user_message === "string" && error.user_message ? error.user_message : detail;
|
|
1049
|
+
return new BackendApiError({
|
|
1050
|
+
code,
|
|
1051
|
+
detail,
|
|
1052
|
+
userMessage,
|
|
1053
|
+
details: error,
|
|
1054
|
+
requestId
|
|
1055
|
+
});
|
|
1185
1056
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1057
|
+
var GENERIC_MESSAGE_PATTERNS = [
|
|
1058
|
+
/failed unexpectedly/i,
|
|
1059
|
+
/^\s*something went wrong/i,
|
|
1060
|
+
/please try again(\s+later)?\.?\s*$/i,
|
|
1061
|
+
/^\s*request failed\b/i,
|
|
1062
|
+
/^\s*unknown (streaming )?error/i,
|
|
1063
|
+
/^\s*internal server error\.?\s*$/i
|
|
1064
|
+
];
|
|
1065
|
+
function isGenericUserMessage(message) {
|
|
1066
|
+
const value = (message ?? "").trim();
|
|
1067
|
+
if (!value) return true;
|
|
1068
|
+
return GENERIC_MESSAGE_PATTERNS.some((pattern) => pattern.test(value));
|
|
1192
1069
|
}
|
|
1193
|
-
function
|
|
1070
|
+
function unwrapUpstreamError(message) {
|
|
1071
|
+
const start = message.indexOf("{");
|
|
1072
|
+
const end = message.lastIndexOf("}");
|
|
1073
|
+
if (start < 0 || end <= start) return null;
|
|
1074
|
+
let parsed;
|
|
1075
|
+
try {
|
|
1076
|
+
parsed = JSON.parse(message.slice(start, end + 1));
|
|
1077
|
+
} catch {
|
|
1078
|
+
return null;
|
|
1079
|
+
}
|
|
1080
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1081
|
+
const body = parsed;
|
|
1082
|
+
const inner = typeof body.message === "string" && body.message || typeof body.detail === "string" && body.detail || "";
|
|
1083
|
+
if (!inner) return null;
|
|
1084
|
+
const statusMatch = /\bHTTP (\d{3})\b/.exec(message.slice(0, start));
|
|
1194
1085
|
return {
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1086
|
+
message: inner,
|
|
1087
|
+
code: typeof body.error_type === "string" && body.error_type || typeof body.error === "string" && body.error || null,
|
|
1088
|
+
userMessage: typeof body.user_message === "string" ? body.user_message : null,
|
|
1089
|
+
requestId: typeof body.request_id === "string" ? body.request_id : null,
|
|
1090
|
+
status: statusMatch ? Number(statusMatch[1]) : null
|
|
1199
1091
|
};
|
|
1200
1092
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1093
|
+
function describeBackendFailure(error) {
|
|
1094
|
+
const chain = [];
|
|
1095
|
+
let code = "internal_error";
|
|
1096
|
+
let requestId = "";
|
|
1097
|
+
let status = null;
|
|
1098
|
+
let userFacing = null;
|
|
1099
|
+
if (error instanceof BackendApiError) {
|
|
1100
|
+
code = error.code;
|
|
1101
|
+
requestId = error.requestId;
|
|
1102
|
+
status = error.status;
|
|
1103
|
+
userFacing = error.userMessage;
|
|
1104
|
+
if (error.detail) chain.push(error.detail);
|
|
1105
|
+
if (error.userMessage && error.userMessage !== error.detail) {
|
|
1106
|
+
chain.push(error.userMessage);
|
|
1214
1107
|
}
|
|
1108
|
+
} else if (error instanceof Error) {
|
|
1109
|
+
chain.push(error.message);
|
|
1110
|
+
userFacing = error.message;
|
|
1111
|
+
} else if (typeof error === "string") {
|
|
1112
|
+
chain.push(error);
|
|
1113
|
+
userFacing = error;
|
|
1114
|
+
} else {
|
|
1115
|
+
chain.push("Unknown error");
|
|
1215
1116
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
return void 0;
|
|
1117
|
+
for (let cursor = 0; cursor < chain.length && cursor < 12; cursor += 1) {
|
|
1118
|
+
const upstream = unwrapUpstreamError(chain[cursor] ?? "");
|
|
1119
|
+
if (!upstream || chain.includes(upstream.message)) continue;
|
|
1120
|
+
chain.push(upstream.message);
|
|
1121
|
+
if (upstream.code) code = upstream.code;
|
|
1122
|
+
if (upstream.requestId) requestId = upstream.requestId;
|
|
1123
|
+
if (upstream.status !== null) status = upstream.status;
|
|
1224
1124
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
status: response.status,
|
|
1229
|
-
path,
|
|
1230
|
-
serverDetail: await readServerDetail(response)
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
async function requestJson(transport, path, options) {
|
|
1234
|
-
const hasBody = options.method !== "GET" && options.body !== void 0;
|
|
1235
|
-
const response = await transport.fetch(path, {
|
|
1236
|
-
method: options.method,
|
|
1237
|
-
headers: hasBody ? { "Content-Type": "application/json" } : {},
|
|
1238
|
-
...hasBody ? { body: JSON.stringify(options.body) } : {},
|
|
1239
|
-
...options.signal ? { signal: options.signal } : {}
|
|
1240
|
-
});
|
|
1241
|
-
if (!response.ok) return throwApiError(path, response);
|
|
1242
|
-
return await response.json();
|
|
1243
|
-
}
|
|
1244
|
-
function toRunHandle(response, options) {
|
|
1125
|
+
const specific = [...chain].reverse().find((message) => !isGenericUserMessage(message));
|
|
1126
|
+
const cause = specific ?? chain[0] ?? "Unknown error";
|
|
1127
|
+
const headlineWasGeneric = isGenericUserMessage(userFacing);
|
|
1245
1128
|
return {
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
...options.onValidEnvelope ? { onValidEnvelope: options.onValidEnvelope } : {}
|
|
1254
|
-
}),
|
|
1255
|
-
response
|
|
1129
|
+
code,
|
|
1130
|
+
cause,
|
|
1131
|
+
headline: headlineWasGeneric ? cause : userFacing ?? cause,
|
|
1132
|
+
headlineWasGeneric,
|
|
1133
|
+
chain,
|
|
1134
|
+
requestId,
|
|
1135
|
+
status
|
|
1256
1136
|
};
|
|
1257
1137
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1138
|
+
function getUserMessage(error) {
|
|
1139
|
+
if (error instanceof BackendApiError) {
|
|
1140
|
+
return error.userMessage;
|
|
1141
|
+
}
|
|
1142
|
+
if (error instanceof Error) {
|
|
1143
|
+
return error.message;
|
|
1144
|
+
}
|
|
1145
|
+
if (typeof error === "string") {
|
|
1146
|
+
return error;
|
|
1147
|
+
}
|
|
1148
|
+
if (typeof error === "object" && error !== null && typeof error.message === "string" && error.message) {
|
|
1149
|
+
return error.message;
|
|
1150
|
+
}
|
|
1151
|
+
return "Something went wrong";
|
|
1152
|
+
}
|
|
1153
|
+
function statusToCode(status) {
|
|
1154
|
+
switch (status) {
|
|
1155
|
+
case 401:
|
|
1156
|
+
return "auth_required";
|
|
1157
|
+
case 403:
|
|
1158
|
+
return "admin_required";
|
|
1159
|
+
case 404:
|
|
1160
|
+
return "not_found";
|
|
1161
|
+
case 422:
|
|
1162
|
+
return "validation_error";
|
|
1163
|
+
default:
|
|
1164
|
+
return "internal_error";
|
|
1277
1165
|
}
|
|
1278
|
-
return response;
|
|
1279
1166
|
}
|
|
1280
1167
|
|
|
1281
|
-
// matrx/
|
|
1282
|
-
|
|
1283
|
-
var
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1168
|
+
// matrx/org-context.ts
|
|
1169
|
+
import { isUuidShape } from "@ai-matrx/kit/uuid";
|
|
1170
|
+
var OrganizationContextError = class extends Error {
|
|
1171
|
+
code;
|
|
1172
|
+
constructor(code, message) {
|
|
1173
|
+
super(message);
|
|
1174
|
+
this.name = "OrganizationContextError";
|
|
1175
|
+
this.code = code;
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
function createOrganizationOperation(organizationId) {
|
|
1179
|
+
const organization_id = requireOrganizationContext(organizationId);
|
|
1180
|
+
return Object.freeze({ organization_id });
|
|
1181
|
+
}
|
|
1182
|
+
function assertOrganizationMatchesOperation(operation, organizationId) {
|
|
1183
|
+
if (operation.organization_id !== requireOrganizationContext(organizationId)) {
|
|
1184
|
+
throw new OrganizationContextError(
|
|
1185
|
+
"organization_context_mismatch",
|
|
1186
|
+
"Organization ID must match the request operation."
|
|
1298
1187
|
);
|
|
1299
|
-
} catch (error) {
|
|
1300
|
-
if (error instanceof MatrxApiError && error.status === 404) return null;
|
|
1301
|
-
throw error;
|
|
1302
1188
|
}
|
|
1303
1189
|
}
|
|
1304
|
-
|
|
1305
|
-
const
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1190
|
+
function requireOrganizationContext(selectedOrganizationId, overrideOrganizationId) {
|
|
1191
|
+
const candidate = overrideOrganizationId ?? selectedOrganizationId;
|
|
1192
|
+
if (typeof candidate !== "string" || candidate.trim().length === 0) {
|
|
1193
|
+
throw new OrganizationContextError(
|
|
1194
|
+
"organization_context_required",
|
|
1195
|
+
"Select an organization before sending this request."
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
const normalized = candidate.trim();
|
|
1199
|
+
if (!isUuidShape(normalized)) {
|
|
1200
|
+
throw new OrganizationContextError(
|
|
1201
|
+
"organization_context_invalid",
|
|
1202
|
+
"The selected organization ID is invalid."
|
|
1313
1203
|
);
|
|
1314
|
-
} catch (error) {
|
|
1315
|
-
if (error instanceof MatrxApiError && error.status === 404) return null;
|
|
1316
|
-
throw error;
|
|
1317
1204
|
}
|
|
1205
|
+
return normalized.toLowerCase();
|
|
1318
1206
|
}
|
|
1319
|
-
function
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
`/runtime/executions/${encodePathSegment(executionId)}/events${query}`,
|
|
1328
|
-
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1329
|
-
);
|
|
1330
|
-
}
|
|
1331
|
-
function parseEndStatus(data) {
|
|
1332
|
-
if (data === null) return null;
|
|
1333
|
-
try {
|
|
1334
|
-
const parsed = JSON.parse(data);
|
|
1335
|
-
if (typeof parsed === "object" && parsed !== null && typeof parsed.status === "string") {
|
|
1336
|
-
const status = parsed.status;
|
|
1337
|
-
return RUNTIME_STATUSES.has(status) ? status : null;
|
|
1207
|
+
function applyOrganizationContextHeader(headers, organizationId) {
|
|
1208
|
+
const normalizedOrganizationId = requireOrganizationContext(organizationId);
|
|
1209
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
1210
|
+
if (name.toLowerCase() === "x-organization-id" && value.trim().toLowerCase() !== normalizedOrganizationId) {
|
|
1211
|
+
throw new OrganizationContextError(
|
|
1212
|
+
"organization_context_mismatch",
|
|
1213
|
+
"X-Organization-Id must match the request context organization."
|
|
1214
|
+
);
|
|
1338
1215
|
}
|
|
1339
|
-
} catch {
|
|
1340
1216
|
}
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
const headers = { Accept: "text/event-stream" };
|
|
1346
|
-
if (cursor > 0) headers["Last-Event-ID"] = String(cursor);
|
|
1347
|
-
const response = await requestStream(
|
|
1348
|
-
transport,
|
|
1349
|
-
`/runtime/executions/${encodePathSegment(executionId)}/events/stream`,
|
|
1350
|
-
{
|
|
1351
|
-
method: "GET",
|
|
1352
|
-
headers,
|
|
1353
|
-
...options.signal ? { signal: options.signal } : {}
|
|
1354
|
-
}
|
|
1217
|
+
const withoutOrganizationHeader = Object.fromEntries(
|
|
1218
|
+
Object.entries(headers).filter(
|
|
1219
|
+
([name]) => name.toLowerCase() !== "x-organization-id"
|
|
1220
|
+
)
|
|
1355
1221
|
);
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1222
|
+
return {
|
|
1223
|
+
...withoutOrganizationHeader,
|
|
1224
|
+
"X-Organization-Id": normalizedOrganizationId
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
function assertQueryOrganizationMatchesContext(queryParams, organizationId) {
|
|
1228
|
+
if (!queryParams || queryParams.organization_id === void 0) return;
|
|
1229
|
+
const queryOrganizationId = requireOrganizationContext(
|
|
1230
|
+
String(queryParams.organization_id)
|
|
1359
1231
|
);
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
if (frame.event === "execution_event" && frame.data !== null) {
|
|
1366
|
-
let event;
|
|
1367
|
-
try {
|
|
1368
|
-
event = JSON.parse(frame.data);
|
|
1369
|
-
} catch (error) {
|
|
1370
|
-
options.onMalformedFrame?.(frame, error);
|
|
1371
|
-
yield { type: "liveness", cursor };
|
|
1372
|
-
continue;
|
|
1373
|
-
}
|
|
1374
|
-
if (frame.seq !== null && frame.seq > cursor) cursor = frame.seq;
|
|
1375
|
-
yield { type: "event", event, seq: frame.seq, cursor };
|
|
1376
|
-
continue;
|
|
1377
|
-
}
|
|
1378
|
-
yield { type: "liveness", cursor };
|
|
1232
|
+
if (queryOrganizationId !== requireOrganizationContext(organizationId)) {
|
|
1233
|
+
throw new OrganizationContextError(
|
|
1234
|
+
"organization_context_mismatch",
|
|
1235
|
+
"Query organization_id must match the request context organization."
|
|
1236
|
+
);
|
|
1379
1237
|
}
|
|
1380
1238
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
cursor = item.cursor;
|
|
1408
|
-
if (item.type === "end") {
|
|
1409
|
-
return { ended: true, status: item.status };
|
|
1410
|
-
}
|
|
1411
|
-
if (item.type === "event") {
|
|
1412
|
-
options.onEvent(item.event, item.seq);
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
failures += 1;
|
|
1416
|
-
} catch (error) {
|
|
1417
|
-
if (outer?.aborted) break;
|
|
1418
|
-
failures += 1;
|
|
1419
|
-
options.onAttemptError?.(error);
|
|
1420
|
-
} finally {
|
|
1421
|
-
if (stallTimer !== null) clearTimeout(stallTimer);
|
|
1422
|
-
outer?.removeEventListener("abort", onOuterAbort);
|
|
1423
|
-
}
|
|
1424
|
-
if (!outer?.aborted && failures < reconnectLimit) {
|
|
1425
|
-
await new Promise((r) => setTimeout(r, reconnectDelayMs));
|
|
1426
|
-
}
|
|
1239
|
+
|
|
1240
|
+
// matrx/protocol.ts
|
|
1241
|
+
import {
|
|
1242
|
+
isNetError,
|
|
1243
|
+
resilientFetch
|
|
1244
|
+
} from "@ai-matrx/data/net";
|
|
1245
|
+
var MATRX_AI_API_VERSION_DEFAULT = "v2";
|
|
1246
|
+
var V2_COVERED_AI_PATH_TEMPLATES = [
|
|
1247
|
+
"/ai/manual",
|
|
1248
|
+
"/ai/chat",
|
|
1249
|
+
"/ai/agents/{agent_id}",
|
|
1250
|
+
"/ai/agent/{agent_id}",
|
|
1251
|
+
// singular alias — behaves identically
|
|
1252
|
+
"/ai/conversations/{conversation_id}",
|
|
1253
|
+
"/ai/conversation/{conversation_id}",
|
|
1254
|
+
// singular alias
|
|
1255
|
+
"/ai/prompts/{prompt_id}",
|
|
1256
|
+
// saved-prompt execution
|
|
1257
|
+
"/ai/mandates/{mandate_key}"
|
|
1258
|
+
// THE MANDATE DOOR — `/v2` sibling exists (routers/v2.py)
|
|
1259
|
+
];
|
|
1260
|
+
function toV2Path(path) {
|
|
1261
|
+
const withLead = path.startsWith("/") ? path : `/${path}`;
|
|
1262
|
+
if (withLead.startsWith("/api/")) {
|
|
1263
|
+
const rest = withLead.slice("/api".length);
|
|
1264
|
+
return rest.startsWith("/v2/") ? withLead : `/api/v2${rest}`;
|
|
1427
1265
|
}
|
|
1428
|
-
return
|
|
1266
|
+
return withLead.startsWith("/v2/") ? withLead : `/v2${withLead}`;
|
|
1429
1267
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1268
|
+
var COVERED_INTERPOLATED_PATH = [
|
|
1269
|
+
/^(?:\/api)?\/ai\/manual$/,
|
|
1270
|
+
/^(?:\/api)?\/ai\/chat$/,
|
|
1271
|
+
/^(?:\/api)?\/ai\/agents\/[^/]+$/,
|
|
1272
|
+
/^(?:\/api)?\/ai\/agent\/[^/]+$/,
|
|
1273
|
+
/^(?:\/api)?\/ai\/conversations\/[^/]+$/,
|
|
1274
|
+
/^(?:\/api)?\/ai\/conversation\/[^/]+$/,
|
|
1275
|
+
/^(?:\/api)?\/ai\/prompts\/[^/]+$/,
|
|
1276
|
+
// `/warm` etc. deliberately don't match
|
|
1277
|
+
/^(?:\/api)?\/ai\/mandates\/[^/]+$/
|
|
1278
|
+
// the mandate door
|
|
1279
|
+
];
|
|
1280
|
+
function isCoveredAiPath(path) {
|
|
1281
|
+
return COVERED_INTERPOLATED_PATH.some((re) => re.test(path));
|
|
1443
1282
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
var MATRX_RUN_IN_PROGRESS = "run_in_progress";
|
|
1447
|
-
var MATRX_RESUME_CONFLICT = "resume_conflict";
|
|
1448
|
-
var MATRX_LIVE_STREAM_UNAVAILABLE = "live_stream_unavailable";
|
|
1449
|
-
function isRecord4(value) {
|
|
1450
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1283
|
+
function isV2Path(pathOrUrl) {
|
|
1284
|
+
return /\/v2\/ai\//.test(pathOrUrl);
|
|
1451
1285
|
}
|
|
1452
|
-
function
|
|
1453
|
-
return
|
|
1286
|
+
function toV1FallbackUrl(url) {
|
|
1287
|
+
return url.replace(/\/v2\/ai\//, "/ai/");
|
|
1454
1288
|
}
|
|
1455
|
-
function
|
|
1456
|
-
if (
|
|
1457
|
-
|
|
1458
|
-
if (isRecord4(body.detail)) out.push(body.detail);
|
|
1459
|
-
if (isRecord4(body.details)) out.push(body.details);
|
|
1460
|
-
out.push(body);
|
|
1461
|
-
return out;
|
|
1289
|
+
function applyAiApiVersion(path, version) {
|
|
1290
|
+
if (version !== "v2") return path;
|
|
1291
|
+
return isCoveredAiPath(path) ? toV2Path(path) : path;
|
|
1462
1292
|
}
|
|
1463
|
-
function
|
|
1464
|
-
|
|
1465
|
-
const
|
|
1466
|
-
|
|
1293
|
+
async function fetchWithMatrxProtocolFallback(url, init, opts = {}) {
|
|
1294
|
+
const { onDowngrade, ...fetchOpts } = opts;
|
|
1295
|
+
const logDowngrade = (reason, status2) => {
|
|
1296
|
+
console.warn(
|
|
1297
|
+
`[matrx] ai_v2_downgrade \u2192 retrying on v1. v2=${url} reason=${reason}`
|
|
1298
|
+
);
|
|
1299
|
+
onDowngrade?.({ url, reason, ...status2 !== void 0 ? { status: status2 } : {} });
|
|
1300
|
+
};
|
|
1301
|
+
if (!isV2Path(url)) return resilientFetch(url, init, fetchOpts);
|
|
1302
|
+
let result;
|
|
1303
|
+
try {
|
|
1304
|
+
result = await resilientFetch(url, init, fetchOpts);
|
|
1305
|
+
} catch (err) {
|
|
1306
|
+
const isAbort = isNetError(err) && err.code === "aborted" || err instanceof Error && err.name === "AbortError";
|
|
1307
|
+
if (isAbort) throw err;
|
|
1308
|
+
logDowngrade(String(err));
|
|
1309
|
+
return resilientFetch(toV1FallbackUrl(url), init, fetchOpts);
|
|
1310
|
+
}
|
|
1311
|
+
const status = result.response.status;
|
|
1312
|
+
if (status === 404 || status === 405 || status >= 500) {
|
|
1313
|
+
logDowngrade(`HTTP ${status}`, status);
|
|
1314
|
+
return resilientFetch(toV1FallbackUrl(url), init, fetchOpts);
|
|
1315
|
+
}
|
|
1316
|
+
return result;
|
|
1317
|
+
}
|
|
1318
|
+
function aiVersionPathOverrides(version) {
|
|
1319
|
+
if (version !== "v2") return {};
|
|
1320
|
+
const map = {};
|
|
1321
|
+
for (const template of V2_COVERED_AI_PATH_TEMPLATES) {
|
|
1322
|
+
map[template] = toV2Path(template);
|
|
1323
|
+
}
|
|
1324
|
+
return map;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
// matrx/call.ts
|
|
1328
|
+
function buildMatrxRequestUrl(baseUrl, pathTemplate, pathParams, queryParams) {
|
|
1329
|
+
let resolvedPath = pathTemplate;
|
|
1330
|
+
if (pathParams) {
|
|
1331
|
+
for (const [key, value] of Object.entries(pathParams)) {
|
|
1332
|
+
resolvedPath = resolvedPath.replace(`{${key}}`, encodeURIComponent(value));
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
const fullPath = resolvedPath.startsWith("/api/") ? resolvedPath.slice(4) : resolvedPath;
|
|
1336
|
+
const url = `${baseUrl}${fullPath}`;
|
|
1337
|
+
if (queryParams && Object.keys(queryParams).length > 0) {
|
|
1338
|
+
const qs = new URLSearchParams(
|
|
1339
|
+
Object.fromEntries(
|
|
1340
|
+
Object.entries(queryParams).map(([k, v]) => [k, String(v)])
|
|
1341
|
+
)
|
|
1342
|
+
).toString();
|
|
1343
|
+
return `${url}?${qs}`;
|
|
1344
|
+
}
|
|
1345
|
+
return url;
|
|
1346
|
+
}
|
|
1347
|
+
var MATRX_UI_ONLY_BODY_FIELDS = /* @__PURE__ */ new Set([
|
|
1348
|
+
"youtube_videos",
|
|
1349
|
+
"file_urls",
|
|
1350
|
+
"image_urls"
|
|
1351
|
+
]);
|
|
1352
|
+
function buildMatrxRequestBody(body, scope) {
|
|
1353
|
+
const raw = body ?? {};
|
|
1354
|
+
const base = {};
|
|
1355
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
1356
|
+
if (!MATRX_UI_ONLY_BODY_FIELDS.has(key)) base[key] = value;
|
|
1357
|
+
}
|
|
1358
|
+
if (base.organization_id === null || typeof base.organization_id === "string" && base.organization_id.trim() === "") {
|
|
1359
|
+
delete base.organization_id;
|
|
1360
|
+
}
|
|
1361
|
+
const bodyOrganizationId = base.organization_id;
|
|
1362
|
+
if (scope.organization_id !== void 0 && bodyOrganizationId !== void 0 && (typeof bodyOrganizationId !== "string" || bodyOrganizationId.trim() !== scope.organization_id)) {
|
|
1363
|
+
throw new OrganizationContextError(
|
|
1364
|
+
"organization_context_mismatch",
|
|
1365
|
+
"Request body organization_id must match the request context organization."
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
if (bodyOrganizationId !== void 0 && scope.organization_id !== void 0) {
|
|
1369
|
+
base.organization_id = scope.organization_id;
|
|
1370
|
+
}
|
|
1371
|
+
const scopeFields = {
|
|
1372
|
+
...scope.organization_id !== void 0 ? { organization_id: scope.organization_id } : {}
|
|
1373
|
+
};
|
|
1374
|
+
if (scope.project_id !== void 0) scopeFields.project_id = scope.project_id;
|
|
1375
|
+
if (scope.task_id !== void 0) scopeFields.task_id = scope.task_id;
|
|
1376
|
+
return { ...scopeFields, ...base };
|
|
1467
1377
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
return
|
|
1378
|
+
var BARE_TRANSPORT_CODE = /^\s*(?:HTTP|HTTP\s*Error|Status(?:\s*Code)?)?\s*[:\-]?\s*\d{3}\s*[.:!]?\s*$/i;
|
|
1379
|
+
function isBareTransportCode(text) {
|
|
1380
|
+
if (!text) return false;
|
|
1381
|
+
return BARE_TRANSPORT_CODE.test(text);
|
|
1471
1382
|
}
|
|
1472
|
-
function
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
if (code) return code;
|
|
1383
|
+
function bareStatusSentence(status) {
|
|
1384
|
+
if (status === 401 || status === 403) {
|
|
1385
|
+
return "The server would not let this request through \u2014 your session may have expired, or this account may not have access here. Sign in again, and if it repeats, ask an administrator.";
|
|
1476
1386
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
if (code) return code;
|
|
1387
|
+
if (status === 404) {
|
|
1388
|
+
return "The server has nothing at that address. Reload the page; if it repeats, report it \u2014 a client asking for something that no longer exists is a defect, not your mistake.";
|
|
1480
1389
|
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
var PREFIXED_ERROR_CODES = [
|
|
1484
|
-
"resume_conflict",
|
|
1485
|
-
"not_resumable",
|
|
1486
|
-
"outstanding_delegated_calls",
|
|
1487
|
-
"user_request_not_found",
|
|
1488
|
-
"run_in_flight"
|
|
1489
|
-
];
|
|
1490
|
-
function readMatrxErrorCodeFromMessage(message) {
|
|
1491
|
-
if (typeof message !== "string") return null;
|
|
1492
|
-
for (const code of PREFIXED_ERROR_CODES) {
|
|
1493
|
-
if (message.startsWith(`${code}:`)) return code;
|
|
1390
|
+
if (status === 429) {
|
|
1391
|
+
return "The server is rate-limiting this request. Wait a few seconds and try again.";
|
|
1494
1392
|
}
|
|
1495
|
-
|
|
1393
|
+
if (status >= 500) {
|
|
1394
|
+
return "The server failed while answering this, and sent no explanation. Try again in a moment; if it repeats, report it with the request id above.";
|
|
1395
|
+
}
|
|
1396
|
+
return "The server refused this request and sent no reason with it \u2014 the missing reason is itself a defect worth reporting. Reload the page and try once more; if it repeats, report it with the request id above.";
|
|
1496
1397
|
}
|
|
1497
|
-
|
|
1398
|
+
function honestTransportMessage(raw, status) {
|
|
1399
|
+
if (raw && !isBareTransportCode(raw)) return raw;
|
|
1400
|
+
return bareStatusSentence(status ?? 0);
|
|
1401
|
+
}
|
|
1402
|
+
var SENSITIVE_HEADER_NAME = /authorization|cookie|token|api[-_]?key/i;
|
|
1403
|
+
function buildSafeRequestLog(headers, body) {
|
|
1404
|
+
const safeHeaders = Object.fromEntries(
|
|
1405
|
+
Object.entries(headers).map(([name, value]) => [
|
|
1406
|
+
name,
|
|
1407
|
+
SENSITIVE_HEADER_NAME.test(name) ? "[REDACTED]" : value
|
|
1408
|
+
])
|
|
1409
|
+
);
|
|
1410
|
+
const bodyMetadata = Array.isArray(body) ? { type: "array", itemCount: body.length } : body && typeof body === "object" ? { type: "object", keys: Object.keys(body) } : { type: body === null ? "null" : typeof body };
|
|
1411
|
+
return { headers: safeHeaders, body: bodyMetadata };
|
|
1412
|
+
}
|
|
1413
|
+
function redactUrlForRequestLog(url) {
|
|
1498
1414
|
try {
|
|
1499
|
-
const
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1415
|
+
const parsed = new URL(url);
|
|
1416
|
+
for (const key of parsed.searchParams.keys()) {
|
|
1417
|
+
parsed.searchParams.set(key, "[REDACTED]");
|
|
1418
|
+
}
|
|
1419
|
+
return parsed.toString();
|
|
1420
|
+
} catch {
|
|
1421
|
+
const queryIndex = url.indexOf("?");
|
|
1422
|
+
return queryIndex === -1 ? url : `${url.slice(0, queryIndex)}?[REDACTED]`;
|
|
1504
1423
|
}
|
|
1505
|
-
return null;
|
|
1506
1424
|
}
|
|
1507
|
-
function
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1425
|
+
function shouldReportMatrxCallError(status, expectedErrorStatuses) {
|
|
1426
|
+
return status == null || !expectedErrorStatuses?.includes(status);
|
|
1427
|
+
}
|
|
1428
|
+
function parseMatrxNdjsonResponse(response, signal, hooks = {}) {
|
|
1429
|
+
const ids = {
|
|
1430
|
+
requestId: response.headers.get("X-Request-ID"),
|
|
1431
|
+
conversationId: response.headers.get("X-Conversation-ID")
|
|
1432
|
+
};
|
|
1433
|
+
async function* events() {
|
|
1434
|
+
if (!response.body) {
|
|
1435
|
+
throw new BackendApiError({
|
|
1436
|
+
code: "internal_error",
|
|
1437
|
+
detail: "Response has no body",
|
|
1438
|
+
userMessage: "No response received from server"
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
try {
|
|
1442
|
+
for await (const envelope of readMatrxNdjsonStream(response.body, {
|
|
1443
|
+
...signal ? { signal } : {},
|
|
1444
|
+
...hooks.onMalformedLine ? { onMalformedLine: hooks.onMalformedLine } : {},
|
|
1445
|
+
...hooks.onUnknownEnvelope ? { onUnknownEnvelope: hooks.onUnknownEnvelope } : {}
|
|
1446
|
+
})) {
|
|
1447
|
+
hooks.onEvent?.(envelope, ids);
|
|
1448
|
+
yield envelope;
|
|
1449
|
+
}
|
|
1450
|
+
} catch (error) {
|
|
1451
|
+
if (signal?.aborted || error instanceof Error && error.name === "AbortError") {
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
const transportError = error instanceof BackendApiError ? error : new StreamTransportError({
|
|
1455
|
+
detail: error instanceof Error ? error.message : "The response stream ended unexpectedly.",
|
|
1456
|
+
details: error,
|
|
1457
|
+
...ids.requestId ? { requestId: ids.requestId } : {}
|
|
1458
|
+
});
|
|
1459
|
+
hooks.onTransportError?.(transportError, ids);
|
|
1460
|
+
throw transportError;
|
|
1461
|
+
}
|
|
1511
1462
|
}
|
|
1512
|
-
return
|
|
1463
|
+
return { events: events(), ...ids };
|
|
1513
1464
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
const code = readMatrxErrorCode(error);
|
|
1519
|
-
if (code !== MATRX_RUN_IN_PROGRESS) return null;
|
|
1520
|
-
const liveRequestId = firstString(candidates, "live_request_id");
|
|
1521
|
-
const pathFromBody = firstString(candidates, "rejoin_path");
|
|
1522
|
-
const rejoinPath = pathFromBody && pathFromBody.startsWith("/") ? pathFromBody : liveRequestId ? runtimeOperationRejoinPath(liveRequestId) : null;
|
|
1523
|
-
if (!rejoinPath) return null;
|
|
1524
|
-
const root = bodyOf(error);
|
|
1465
|
+
var DEFAULT_CONNECT_TIMEOUT_MS = 15e3;
|
|
1466
|
+
var DEFAULT_JSON_TOTAL_TIMEOUT_MS = 3e4;
|
|
1467
|
+
async function httpErrorFrom(response) {
|
|
1468
|
+
const serverDetail = await response.json().catch(() => void 0);
|
|
1525
1469
|
return {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
body: isRecord4(root) ? root : {}
|
|
1470
|
+
type: response.status >= 400 && response.status < 500 ? "validation_error" : "http_error",
|
|
1471
|
+
message: extractMatrxErrorMessage(serverDetail) ?? bareStatusSentence(response.status),
|
|
1472
|
+
status: response.status,
|
|
1473
|
+
serverDetail
|
|
1531
1474
|
};
|
|
1532
1475
|
}
|
|
1533
|
-
function
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1476
|
+
async function executeMatrxCall(request, hooks = {}) {
|
|
1477
|
+
const upper = request.method.toUpperCase();
|
|
1478
|
+
const sendsBody = request.stream || upper !== "GET" && upper !== "HEAD";
|
|
1479
|
+
const { response } = await fetchWithMatrxProtocolFallback(
|
|
1480
|
+
request.url,
|
|
1481
|
+
{
|
|
1482
|
+
method: request.method,
|
|
1483
|
+
headers: request.headers,
|
|
1484
|
+
...sendsBody ? { body: JSON.stringify(request.body) } : {}
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
...request.signal ? { signal: request.signal } : {},
|
|
1488
|
+
connectTimeoutMs: request.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,
|
|
1489
|
+
totalTimeoutMs: request.stream ? null : request.totalTimeoutMs === void 0 ? DEFAULT_JSON_TOTAL_TIMEOUT_MS : request.totalTimeoutMs,
|
|
1490
|
+
throwOnHttpError: false,
|
|
1491
|
+
...hooks.onProtocolDowngrade ? { onDowngrade: hooks.onProtocolDowngrade } : {}
|
|
1492
|
+
}
|
|
1493
|
+
);
|
|
1494
|
+
const requestId = response.headers.get("X-Request-ID");
|
|
1495
|
+
const conversationId = response.headers.get("X-Conversation-ID");
|
|
1496
|
+
const idFields = {
|
|
1497
|
+
...requestId !== null ? { requestId } : {},
|
|
1498
|
+
...conversationId !== null ? { conversationId } : {}
|
|
1499
|
+
};
|
|
1500
|
+
if (!response.ok) {
|
|
1501
|
+
const error = await httpErrorFrom(response);
|
|
1502
|
+
if (request.stream) request.onStreamError?.(error);
|
|
1503
|
+
return { ...idFields, error };
|
|
1504
|
+
}
|
|
1505
|
+
if (!request.stream) {
|
|
1506
|
+
const data = response.status === 204 ? void 0 : await response.json();
|
|
1507
|
+
return { data, ...idFields };
|
|
1508
|
+
}
|
|
1509
|
+
if (request.consumeStream) {
|
|
1510
|
+
request.onStreamStart?.(requestId, conversationId);
|
|
1511
|
+
await request.consumeStream(response, { requestId, conversationId });
|
|
1512
|
+
request.onStreamComplete?.(requestId, conversationId);
|
|
1513
|
+
return idFields;
|
|
1514
|
+
}
|
|
1515
|
+
const parse = hooks.parseStream ?? ((res, signal) => parseMatrxNdjsonResponse(res, signal));
|
|
1516
|
+
const parsed = parse(response, request.signal);
|
|
1517
|
+
request.onStreamStart?.(parsed.requestId, parsed.conversationId);
|
|
1518
|
+
for await (const event of parsed.events) {
|
|
1519
|
+
request.onStreamEvent?.(event);
|
|
1520
|
+
}
|
|
1521
|
+
request.onStreamComplete?.(parsed.requestId, parsed.conversationId);
|
|
1522
|
+
return {
|
|
1523
|
+
...parsed.requestId !== null ? { requestId: parsed.requestId } : {},
|
|
1524
|
+
...parsed.conversationId !== null ? { conversationId: parsed.conversationId } : {}
|
|
1525
|
+
};
|
|
1538
1526
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1527
|
+
|
|
1528
|
+
// matrx/client.ts
|
|
1529
|
+
function classifyStatus(status) {
|
|
1530
|
+
return status >= 400 && status < 500 ? "validation_error" : "http_error";
|
|
1541
1531
|
}
|
|
1542
|
-
function
|
|
1543
|
-
|
|
1532
|
+
function normalizeMatrxError(err) {
|
|
1533
|
+
if (err instanceof OrganizationContextError) {
|
|
1534
|
+
return {
|
|
1535
|
+
type: "validation_error",
|
|
1536
|
+
message: err.message,
|
|
1537
|
+
code: err.code,
|
|
1538
|
+
name: err.name,
|
|
1539
|
+
...err.stack !== void 0 ? { stack: err.stack } : {}
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
1543
|
+
return { type: "abort_error", message: "Request was cancelled." };
|
|
1544
|
+
}
|
|
1545
|
+
if (err instanceof MatrxApiError) {
|
|
1546
|
+
return {
|
|
1547
|
+
type: classifyStatus(err.status),
|
|
1548
|
+
message: honestTransportMessage(err.message, err.status),
|
|
1549
|
+
status: err.status,
|
|
1550
|
+
serverDetail: err.serverDetail,
|
|
1551
|
+
...err.code ? { code: err.code } : {},
|
|
1552
|
+
name: err.name
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
if (err instanceof BackendApiError) {
|
|
1556
|
+
return {
|
|
1557
|
+
type: "network_error",
|
|
1558
|
+
message: honestTransportMessage(
|
|
1559
|
+
err.detail || err.userMessage,
|
|
1560
|
+
err.status ?? void 0
|
|
1561
|
+
),
|
|
1562
|
+
code: err.code,
|
|
1563
|
+
name: err.name,
|
|
1564
|
+
...err.status !== null ? { status: err.status } : {},
|
|
1565
|
+
...err.details !== null ? { serverDetail: err.details } : {}
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
if (isNetError2(err)) {
|
|
1569
|
+
if (err.code === "aborted") {
|
|
1570
|
+
return { type: "abort_error", message: err.message };
|
|
1571
|
+
}
|
|
1572
|
+
if (err.code === "http") {
|
|
1573
|
+
const status = err.status ?? 0;
|
|
1574
|
+
return {
|
|
1575
|
+
type: classifyStatus(status),
|
|
1576
|
+
message: honestTransportMessage(err.message, status),
|
|
1577
|
+
status
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
return { type: "network_error", message: err.message };
|
|
1581
|
+
}
|
|
1582
|
+
if (err instanceof Error) {
|
|
1583
|
+
const httpMatch = err.message.match(/HTTP (\d+):\s*(.*)/);
|
|
1584
|
+
if (httpMatch) {
|
|
1585
|
+
const status = parseInt(httpMatch[1], 10);
|
|
1586
|
+
return {
|
|
1587
|
+
type: classifyStatus(status),
|
|
1588
|
+
message: honestTransportMessage(httpMatch[2] ?? err.message, status),
|
|
1589
|
+
status
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
if (isBareTransportCode(err.message)) {
|
|
1593
|
+
const status = Number.parseInt(err.message.replace(/\D+/g, ""), 10);
|
|
1594
|
+
return {
|
|
1595
|
+
type: classifyStatus(status),
|
|
1596
|
+
message: bareStatusSentence(status),
|
|
1597
|
+
status
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
return { type: "network_error", message: err.message };
|
|
1601
|
+
}
|
|
1602
|
+
return { type: "unknown", message: extractErrorMessage(err) };
|
|
1544
1603
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1604
|
+
var PRODUCTION_CONNECT_TIMEOUT_MS = 15e3;
|
|
1605
|
+
function stripContentType(headers) {
|
|
1606
|
+
return Object.fromEntries(
|
|
1607
|
+
Object.entries(headers).filter(
|
|
1608
|
+
([name]) => name.toLowerCase() !== "content-type"
|
|
1609
|
+
)
|
|
1610
|
+
);
|
|
1549
1611
|
}
|
|
1550
|
-
|
|
1551
|
-
const
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1612
|
+
function createMatrxTransport(options) {
|
|
1613
|
+
const {
|
|
1614
|
+
baseUrl,
|
|
1615
|
+
resolveTarget,
|
|
1616
|
+
credentials,
|
|
1617
|
+
organizationId,
|
|
1618
|
+
aiApiVersion,
|
|
1619
|
+
connectTimeoutMs = PRODUCTION_CONNECT_TIMEOUT_MS,
|
|
1620
|
+
totalTimeoutMs = null,
|
|
1621
|
+
expectedErrorStatuses,
|
|
1622
|
+
diagnostics,
|
|
1623
|
+
source = "matrxTransport"
|
|
1624
|
+
} = options;
|
|
1625
|
+
if (baseUrl === void 0 === (resolveTarget === void 0)) {
|
|
1626
|
+
throw new Error(
|
|
1627
|
+
"createMatrxTransport: provide exactly one of `baseUrl` or `resolveTarget`."
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
const resolve = resolveTarget ?? (() => ({ baseUrl }));
|
|
1631
|
+
const resolveVersion = () => {
|
|
1632
|
+
if (aiApiVersion === void 0) return MATRX_AI_API_VERSION_DEFAULT;
|
|
1633
|
+
return typeof aiApiVersion === "function" ? aiApiVersion() : aiApiVersion;
|
|
1634
|
+
};
|
|
1635
|
+
const resolveOrganizationId = () => {
|
|
1636
|
+
if (organizationId === void 0) return null;
|
|
1637
|
+
const candidate = typeof organizationId === "function" ? organizationId() : organizationId;
|
|
1638
|
+
return requireOrganizationContext(candidate);
|
|
1639
|
+
};
|
|
1640
|
+
return {
|
|
1641
|
+
async fetch(path, init) {
|
|
1642
|
+
const target = resolve();
|
|
1643
|
+
const versionedPath = applyAiApiVersion(path, resolveVersion());
|
|
1644
|
+
const url = `${target.baseUrl}${versionedPath}`;
|
|
1645
|
+
const credentialHeaders = credentials ? credentialToHeaders(await credentials.get()) : {};
|
|
1646
|
+
let headers = {
|
|
1647
|
+
...init.headers,
|
|
1648
|
+
...stripContentType(credentialHeaders),
|
|
1649
|
+
...stripContentType(target.policyHeaders ?? {})
|
|
1650
|
+
};
|
|
1651
|
+
const orgId = resolveOrganizationId();
|
|
1652
|
+
if (orgId !== null) {
|
|
1653
|
+
headers = applyOrganizationContextHeader(headers, orgId);
|
|
1654
|
+
}
|
|
1655
|
+
const info = {
|
|
1656
|
+
url,
|
|
1657
|
+
method: init.method,
|
|
1658
|
+
path,
|
|
1659
|
+
channel: target.channel ?? "default",
|
|
1660
|
+
source
|
|
1661
|
+
};
|
|
1662
|
+
diagnostics?.onRequest?.(info);
|
|
1663
|
+
let response;
|
|
1664
|
+
try {
|
|
1665
|
+
({ response } = await fetchWithMatrxProtocolFallback(
|
|
1666
|
+
url,
|
|
1667
|
+
{
|
|
1668
|
+
method: init.method,
|
|
1669
|
+
headers,
|
|
1670
|
+
...init.body !== void 0 ? { body: init.body } : {}
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
...init.signal ? { signal: init.signal } : {},
|
|
1674
|
+
connectTimeoutMs,
|
|
1675
|
+
totalTimeoutMs,
|
|
1676
|
+
throwOnHttpError: false,
|
|
1677
|
+
...diagnostics?.onProtocolDowngrade ? { onDowngrade: diagnostics.onProtocolDowngrade } : {}
|
|
1678
|
+
}
|
|
1679
|
+
));
|
|
1680
|
+
} catch (err) {
|
|
1681
|
+
diagnostics?.onError?.(normalizeMatrxError(err), info);
|
|
1682
|
+
throw err;
|
|
1683
|
+
}
|
|
1684
|
+
if (!response.ok && !expectedErrorStatuses?.includes(response.status)) {
|
|
1685
|
+
const serverDetail = await response.clone().json().catch(() => void 0);
|
|
1686
|
+
const code = extractMatrxErrorCode(serverDetail);
|
|
1687
|
+
diagnostics?.onError?.(
|
|
1688
|
+
{
|
|
1689
|
+
type: classifyStatus(response.status),
|
|
1690
|
+
message: extractMatrxErrorMessage(serverDetail) ?? `HTTP ${response.status}`,
|
|
1691
|
+
status: response.status,
|
|
1692
|
+
serverDetail,
|
|
1693
|
+
...code ? { code } : {}
|
|
1694
|
+
},
|
|
1695
|
+
info
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
return response;
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1557
1701
|
}
|
|
1558
|
-
|
|
1559
|
-
|
|
1702
|
+
|
|
1703
|
+
// matrx/conversation.ts
|
|
1704
|
+
function mintMatrxConversationId() {
|
|
1705
|
+
return crypto.randomUUID();
|
|
1706
|
+
}
|
|
1707
|
+
function newStoredConversationStart(conversationId) {
|
|
1560
1708
|
return {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
})
|
|
1709
|
+
conversation_id: conversationId ?? mintMatrxConversationId(),
|
|
1710
|
+
is_new: true,
|
|
1711
|
+
store: true
|
|
1565
1712
|
};
|
|
1566
1713
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
if (options.lastEventId) headers["Last-Event-ID"] = String(options.lastEventId);
|
|
1570
|
-
let response;
|
|
1571
|
-
try {
|
|
1572
|
-
response = await requestStream(
|
|
1573
|
-
transport,
|
|
1574
|
-
`/runs/${encodePathSegment(runId)}/events/stream`,
|
|
1575
|
-
{
|
|
1576
|
-
method: "GET",
|
|
1577
|
-
headers,
|
|
1578
|
-
...options.signal ? { signal: options.signal } : {}
|
|
1579
|
-
}
|
|
1580
|
-
);
|
|
1581
|
-
} catch (error) {
|
|
1582
|
-
if (options.signal?.aborted) return { ended: false };
|
|
1583
|
-
throw error;
|
|
1584
|
-
}
|
|
1585
|
-
try {
|
|
1586
|
-
for await (const frame of readMatrxSseStream(
|
|
1587
|
-
response.body
|
|
1588
|
-
)) {
|
|
1589
|
-
if (frame.event === "end") return { ended: true };
|
|
1590
|
-
if (frame.data === null) continue;
|
|
1591
|
-
let parsed;
|
|
1592
|
-
try {
|
|
1593
|
-
parsed = JSON.parse(frame.data);
|
|
1594
|
-
} catch {
|
|
1595
|
-
continue;
|
|
1596
|
-
}
|
|
1597
|
-
if (!isRecord4(parsed)) continue;
|
|
1598
|
-
options.onEvent(parsed, parsed.event === "node_stream" ? null : frame.seq);
|
|
1599
|
-
}
|
|
1600
|
-
} catch (error) {
|
|
1601
|
-
if (!options.signal?.aborted) throw error;
|
|
1602
|
-
}
|
|
1603
|
-
return { ended: false };
|
|
1714
|
+
function continueStoredConversationStart(conversationId) {
|
|
1715
|
+
return { conversation_id: conversationId, is_new: false, store: true };
|
|
1604
1716
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1717
|
+
function newEphemeralConversationStart(conversationId) {
|
|
1718
|
+
return {
|
|
1719
|
+
conversation_id: conversationId ?? mintMatrxConversationId(),
|
|
1720
|
+
is_new: true,
|
|
1721
|
+
store: false
|
|
1722
|
+
};
|
|
1607
1723
|
}
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
onWorkflowEvent,
|
|
1615
|
-
follow,
|
|
1616
|
-
...rest
|
|
1617
|
-
} = options;
|
|
1618
|
-
const bound = organizationId ? withRunOrganization(transport, organizationId) : transport;
|
|
1619
|
-
const streamOptions = {
|
|
1620
|
-
...rest,
|
|
1621
|
-
...options.signal ? { signal: options.signal } : {}
|
|
1724
|
+
function continueEphemeralConversationStart(conversationId, priorMessages) {
|
|
1725
|
+
return {
|
|
1726
|
+
conversation_id: conversationId,
|
|
1727
|
+
is_new: false,
|
|
1728
|
+
store: false,
|
|
1729
|
+
prior_messages: priorMessages
|
|
1622
1730
|
};
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
// matrx/internal.ts
|
|
1734
|
+
function encodePathSegment(value) {
|
|
1735
|
+
return encodeURIComponent(value);
|
|
1736
|
+
}
|
|
1737
|
+
function buildQuery(params) {
|
|
1738
|
+
const search = new URLSearchParams();
|
|
1739
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1740
|
+
if (value === void 0) continue;
|
|
1741
|
+
if (Array.isArray(value)) {
|
|
1742
|
+
for (const entry of value) search.append(key, entry);
|
|
1743
|
+
} else {
|
|
1744
|
+
search.append(key, String(value));
|
|
1636
1745
|
}
|
|
1637
|
-
rejoin = target;
|
|
1638
1746
|
}
|
|
1639
|
-
|
|
1640
|
-
|
|
1747
|
+
const encoded = search.toString();
|
|
1748
|
+
return encoded ? `?${encoded}` : "";
|
|
1749
|
+
}
|
|
1750
|
+
async function readServerDetail(response) {
|
|
1641
1751
|
try {
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
body: {}
|
|
1646
|
-
});
|
|
1647
|
-
await drain(handle, onEnvelope);
|
|
1648
|
-
return { kind: "rejoined", rejoin };
|
|
1649
|
-
} catch (error) {
|
|
1650
|
-
const read = readLiveStreamUnavailable(error);
|
|
1651
|
-
if (!read) throw error;
|
|
1652
|
-
unavailable = read;
|
|
1752
|
+
return await response.json();
|
|
1753
|
+
} catch {
|
|
1754
|
+
return void 0;
|
|
1653
1755
|
}
|
|
1654
|
-
return followUnavailableRejoin(bound, rejoin, unavailable, {
|
|
1655
|
-
...signalOnly,
|
|
1656
|
-
...onOperationEvent ? { onOperationEvent } : {},
|
|
1657
|
-
...onWorkflowEvent ? { onWorkflowEvent } : {},
|
|
1658
|
-
...follow ? { follow } : {}
|
|
1659
|
-
});
|
|
1660
1756
|
}
|
|
1661
|
-
function
|
|
1662
|
-
|
|
1663
|
-
|
|
1757
|
+
async function throwApiError(path, response) {
|
|
1758
|
+
throw new MatrxApiError({
|
|
1759
|
+
status: response.status,
|
|
1760
|
+
path,
|
|
1761
|
+
serverDetail: await readServerDetail(response)
|
|
1762
|
+
});
|
|
1664
1763
|
}
|
|
1665
|
-
async function
|
|
1666
|
-
const
|
|
1667
|
-
const
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
onEvent: (event, seq) => options.onWorkflowEvent?.(event, seq)
|
|
1673
|
-
});
|
|
1674
|
-
return { kind: "followed_workflow", rejoin, runId, ended: result2.ended };
|
|
1675
|
-
}
|
|
1676
|
-
const liveRequestId = rejoin.liveRequestId;
|
|
1677
|
-
const statusView = liveRequestId ? await getRuntimeOperationStatus(bound, liveRequestId, signalOnly) : null;
|
|
1678
|
-
const operation = statusView?.operations.find((op) => !op.is_terminal) ?? statusView?.operations[0] ?? null;
|
|
1679
|
-
if (!operation) {
|
|
1680
|
-
return { kind: "followed", rejoin, executionId: null, ended: false, status: null };
|
|
1681
|
-
}
|
|
1682
|
-
if (operation.is_terminal) {
|
|
1683
|
-
return {
|
|
1684
|
-
kind: "followed",
|
|
1685
|
-
rejoin,
|
|
1686
|
-
executionId: operation.execution_id,
|
|
1687
|
-
ended: true,
|
|
1688
|
-
status: operation.status
|
|
1689
|
-
};
|
|
1690
|
-
}
|
|
1691
|
-
const result = await followRuntimeOperationToEnd(bound, operation.execution_id, {
|
|
1692
|
-
...options.follow,
|
|
1693
|
-
lastEventSeq: operation.last_event_seq,
|
|
1694
|
-
...signalOnly,
|
|
1695
|
-
onEvent: (event) => options.onOperationEvent?.(event)
|
|
1764
|
+
async function requestJson(transport, path, options) {
|
|
1765
|
+
const hasBody = options.method !== "GET" && options.body !== void 0;
|
|
1766
|
+
const response = await transport.fetch(path, {
|
|
1767
|
+
method: options.method,
|
|
1768
|
+
headers: hasBody ? { "Content-Type": "application/json" } : {},
|
|
1769
|
+
...hasBody ? { body: JSON.stringify(options.body) } : {},
|
|
1770
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1696
1771
|
});
|
|
1772
|
+
if (!response.ok) return throwApiError(path, response);
|
|
1773
|
+
return await response.json();
|
|
1774
|
+
}
|
|
1775
|
+
function toRunHandle(response, options) {
|
|
1697
1776
|
return {
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1777
|
+
requestId: response.headers.get("X-Request-ID"),
|
|
1778
|
+
conversationId: response.headers.get("X-Conversation-ID"),
|
|
1779
|
+
events: readMatrxNdjsonStream(response.body, {
|
|
1780
|
+
...options.signal ? { signal: options.signal } : {},
|
|
1781
|
+
...options.maxReadAhead !== void 0 ? { maxReadAhead: options.maxReadAhead } : {},
|
|
1782
|
+
...options.onMalformedLine ? { onMalformedLine: options.onMalformedLine } : {},
|
|
1783
|
+
...options.onUnknownEnvelope ? { onUnknownEnvelope: options.onUnknownEnvelope } : {},
|
|
1784
|
+
...options.onValidEnvelope ? { onValidEnvelope: options.onValidEnvelope } : {}
|
|
1785
|
+
}),
|
|
1786
|
+
response
|
|
1703
1787
|
};
|
|
1704
1788
|
}
|
|
1705
|
-
async function
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
switch (pickup.kind) {
|
|
1715
|
-
case "resumed":
|
|
1716
|
-
case "rejoined":
|
|
1717
|
-
return { state: "streamed" };
|
|
1718
|
-
case "resume_conflict":
|
|
1719
|
-
return { state: "retry" };
|
|
1720
|
-
case "followed_workflow":
|
|
1721
|
-
case "followed": {
|
|
1722
|
-
const status = pickup.kind === "followed" ? pickup.status : null;
|
|
1723
|
-
const nothingLive = pickup.kind === "followed" && pickup.executionId === null;
|
|
1724
|
-
if (pickup.ended || nothingLive) {
|
|
1725
|
-
return { state: "settled", status, ...await attempt(options.reloadSavedTurn) };
|
|
1726
|
-
}
|
|
1727
|
-
return {
|
|
1728
|
-
state: "still_running",
|
|
1729
|
-
...await attempt(options.onStillRunning ?? options.reloadSavedTurn)
|
|
1730
|
-
};
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
// matrx/run.ts
|
|
1736
|
-
async function streamCall(transport, path, body, options) {
|
|
1737
|
-
const response = await requestStream(transport, path, {
|
|
1738
|
-
method: "POST",
|
|
1739
|
-
// This client IS the streaming path — `stream: true` always, last so a
|
|
1740
|
-
// caller-supplied value can never flip the response off NDJSON.
|
|
1741
|
-
body: { ...body, stream: true },
|
|
1789
|
+
async function requestStream(transport, path, options) {
|
|
1790
|
+
const hasBody = options.method !== "GET" && options.body !== void 0;
|
|
1791
|
+
const response = await transport.fetch(path, {
|
|
1792
|
+
method: options.method,
|
|
1793
|
+
headers: {
|
|
1794
|
+
...hasBody ? { "Content-Type": "application/json" } : {},
|
|
1795
|
+
...options.headers
|
|
1796
|
+
},
|
|
1797
|
+
...hasBody ? { body: JSON.stringify(options.body) } : {},
|
|
1742
1798
|
...options.signal ? { signal: options.signal } : {}
|
|
1743
1799
|
});
|
|
1744
|
-
return
|
|
1800
|
+
if (!response.ok) return throwApiError(path, response);
|
|
1801
|
+
if (!response.body) {
|
|
1802
|
+
throw new MatrxApiError({
|
|
1803
|
+
status: response.status,
|
|
1804
|
+
path,
|
|
1805
|
+
serverDetail: { code: "missing_response_body" },
|
|
1806
|
+
message: "The streaming response carried no body."
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
return response;
|
|
1745
1810
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1811
|
+
|
|
1812
|
+
// matrx/operations.ts
|
|
1813
|
+
var TERMINAL_MATRX_RUNTIME_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
1814
|
+
var RUNTIME_STATUSES = /* @__PURE__ */ new Set([
|
|
1815
|
+
"pending",
|
|
1816
|
+
"running",
|
|
1817
|
+
"paused",
|
|
1818
|
+
"waiting_input",
|
|
1819
|
+
"completed",
|
|
1820
|
+
"failed",
|
|
1821
|
+
"cancelled"
|
|
1822
|
+
]);
|
|
1823
|
+
async function getRuntimeOperationStatus(transport, requestId, options = {}) {
|
|
1824
|
+
try {
|
|
1825
|
+
return await requestJson(
|
|
1826
|
+
transport,
|
|
1827
|
+
`/runtime/operations/${encodePathSegment(requestId)}`,
|
|
1828
|
+
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1829
|
+
);
|
|
1830
|
+
} catch (error) {
|
|
1831
|
+
if (error instanceof MatrxApiError && error.status === 404) return null;
|
|
1832
|
+
throw error;
|
|
1833
|
+
}
|
|
1753
1834
|
}
|
|
1754
|
-
function
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
`/ai/mandates/${encodePathSegment(mandateKey)}`,
|
|
1758
|
-
request,
|
|
1759
|
-
options
|
|
1835
|
+
async function getRuntimeOperationsByLink(transport, linkKind, linkId, options = {}) {
|
|
1836
|
+
const query = buildQuery(
|
|
1837
|
+
options.limit !== void 0 ? { limit: options.limit } : {}
|
|
1760
1838
|
);
|
|
1839
|
+
try {
|
|
1840
|
+
return await requestJson(
|
|
1841
|
+
transport,
|
|
1842
|
+
`/runtime/operations/by-link/${encodePathSegment(linkKind)}/${encodePathSegment(linkId)}${query}`,
|
|
1843
|
+
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1844
|
+
);
|
|
1845
|
+
} catch (error) {
|
|
1846
|
+
if (error instanceof MatrxApiError && error.status === 404) return null;
|
|
1847
|
+
throw error;
|
|
1848
|
+
}
|
|
1761
1849
|
}
|
|
1762
|
-
function
|
|
1763
|
-
|
|
1850
|
+
function listRuntimeOperationEvents(transport, executionId, options = {}) {
|
|
1851
|
+
const query = buildQuery({
|
|
1852
|
+
...options.afterSeq !== void 0 ? { after_seq: options.afterSeq } : {},
|
|
1853
|
+
...options.limit !== void 0 ? { limit: options.limit } : {},
|
|
1854
|
+
...options.kinds !== void 0 ? { kind: options.kinds } : {}
|
|
1855
|
+
});
|
|
1856
|
+
return requestJson(
|
|
1764
1857
|
transport,
|
|
1765
|
-
`/
|
|
1766
|
-
|
|
1767
|
-
options
|
|
1858
|
+
`/runtime/executions/${encodePathSegment(executionId)}/events${query}`,
|
|
1859
|
+
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1768
1860
|
);
|
|
1769
1861
|
}
|
|
1770
|
-
function
|
|
1771
|
-
return
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1862
|
+
function parseEndStatus(data) {
|
|
1863
|
+
if (data === null) return null;
|
|
1864
|
+
try {
|
|
1865
|
+
const parsed = JSON.parse(data);
|
|
1866
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.status === "string") {
|
|
1867
|
+
const status = parsed.status;
|
|
1868
|
+
return RUNTIME_STATUSES.has(status) ? status : null;
|
|
1869
|
+
}
|
|
1870
|
+
} catch {
|
|
1871
|
+
}
|
|
1872
|
+
return null;
|
|
1777
1873
|
}
|
|
1778
|
-
function
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
);
|
|
1782
|
-
|
|
1874
|
+
async function* followRuntimeOperationEvents(transport, executionId, options = {}) {
|
|
1875
|
+
let cursor = options.lastEventSeq ?? 0;
|
|
1876
|
+
const headers = { Accept: "text/event-stream" };
|
|
1877
|
+
if (cursor > 0) headers["Last-Event-ID"] = String(cursor);
|
|
1878
|
+
const response = await requestStream(
|
|
1783
1879
|
transport,
|
|
1784
|
-
`/
|
|
1880
|
+
`/runtime/executions/${encodePathSegment(executionId)}/events/stream`,
|
|
1785
1881
|
{
|
|
1786
|
-
method: "
|
|
1882
|
+
method: "GET",
|
|
1883
|
+
headers,
|
|
1787
1884
|
...options.signal ? { signal: options.signal } : {}
|
|
1788
1885
|
}
|
|
1789
1886
|
);
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
partialText;
|
|
1799
|
-
constructor(args) {
|
|
1800
|
-
super(args.message);
|
|
1801
|
-
this.errorPayload = args.errorPayload ?? null;
|
|
1802
|
-
this.completionStatus = args.completionStatus ?? null;
|
|
1803
|
-
this.partialText = args.partialText ?? "";
|
|
1804
|
-
}
|
|
1805
|
-
};
|
|
1806
|
-
function isRecord5(value) {
|
|
1807
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1808
|
-
}
|
|
1809
|
-
function stringField(value, key) {
|
|
1810
|
-
if (!isRecord5(value)) return null;
|
|
1811
|
-
const field = value[key];
|
|
1812
|
-
return typeof field === "string" && field ? field : null;
|
|
1813
|
-
}
|
|
1814
|
-
async function runAgentToCompletion(transport, agentId, request, options = {}) {
|
|
1815
|
-
const handle = await startAgentRun(transport, agentId, request, options);
|
|
1816
|
-
let text = "";
|
|
1817
|
-
let completion = null;
|
|
1818
|
-
let failure = null;
|
|
1819
|
-
for await (const envelope of handle.events) {
|
|
1820
|
-
options.onEvent?.(envelope);
|
|
1821
|
-
if (envelope.event === "chunk") {
|
|
1822
|
-
const chunk = stringField(envelope.data, "text");
|
|
1823
|
-
if (chunk !== null) {
|
|
1824
|
-
text += chunk;
|
|
1825
|
-
options.onChunk?.(text);
|
|
1826
|
-
}
|
|
1827
|
-
continue;
|
|
1887
|
+
const frames = readMatrxSseStream(
|
|
1888
|
+
response.body,
|
|
1889
|
+
options.onIncomplete ? { onIncomplete: options.onIncomplete } : {}
|
|
1890
|
+
);
|
|
1891
|
+
for await (const frame of frames) {
|
|
1892
|
+
if (frame.event === "end") {
|
|
1893
|
+
yield { type: "end", status: parseEndStatus(frame.data), cursor };
|
|
1894
|
+
return;
|
|
1828
1895
|
}
|
|
1829
|
-
if (
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1896
|
+
if (frame.event === "execution_event" && frame.data !== null) {
|
|
1897
|
+
let event;
|
|
1898
|
+
try {
|
|
1899
|
+
event = JSON.parse(frame.data);
|
|
1900
|
+
} catch (error) {
|
|
1901
|
+
options.onMalformedFrame?.(frame, error);
|
|
1902
|
+
yield { type: "liveness", cursor };
|
|
1903
|
+
continue;
|
|
1904
|
+
}
|
|
1905
|
+
if (frame.seq !== null && frame.seq > cursor) cursor = frame.seq;
|
|
1906
|
+
yield { type: "event", event, seq: frame.seq, cursor };
|
|
1836
1907
|
continue;
|
|
1837
1908
|
}
|
|
1838
|
-
|
|
1839
|
-
if (envelope.data.operation !== "user_request") continue;
|
|
1840
|
-
completion = envelope.data;
|
|
1841
|
-
const status = envelope.data.status;
|
|
1842
|
-
if ((status === "failed" || status === "cancelled") && failure === null) {
|
|
1843
|
-
const result = isRecord5(envelope.data.result) ? envelope.data.result : null;
|
|
1844
|
-
failure = new MatrxRunError({
|
|
1845
|
-
message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
|
|
1846
|
-
completionStatus: status,
|
|
1847
|
-
partialText: text
|
|
1848
|
-
});
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
if (failure) throw failure;
|
|
1852
|
-
if (!text && completion) {
|
|
1853
|
-
const result = completion.result;
|
|
1854
|
-
const output = stringField(result, "output");
|
|
1855
|
-
if (output !== null) text = output;
|
|
1856
|
-
}
|
|
1857
|
-
return {
|
|
1858
|
-
text,
|
|
1859
|
-
requestId: handle.requestId,
|
|
1860
|
-
conversationId: handle.conversationId,
|
|
1861
|
-
completion
|
|
1862
|
-
};
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
|
-
// matrx/provider-failures.ts
|
|
1866
|
-
var clip = (value, max) => value.length > max ? value.slice(0, max) : value;
|
|
1867
|
-
function providerSessionFailureBody(failure) {
|
|
1868
|
-
const message = failure.message?.trim() || failure.error_type?.trim() || (failure.status_code ? `HTTP ${failure.status_code}` : "provider session failed");
|
|
1869
|
-
const body = {
|
|
1870
|
-
provider: failure.provider,
|
|
1871
|
-
message: clip(message, 4e3)
|
|
1872
|
-
};
|
|
1873
|
-
if (failure.model?.trim()) body.model = clip(failure.model.trim(), 200);
|
|
1874
|
-
if (failure.error_type?.trim()) body.error_type = clip(failure.error_type.trim(), 200);
|
|
1875
|
-
if (typeof failure.status_code === "number" && Number.isInteger(failure.status_code) && failure.status_code >= 100 && failure.status_code <= 599) {
|
|
1876
|
-
body.status_code = failure.status_code;
|
|
1909
|
+
yield { type: "liveness", cursor };
|
|
1877
1910
|
}
|
|
1878
|
-
return body;
|
|
1879
1911
|
}
|
|
1880
|
-
async function
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1912
|
+
async function followRuntimeOperationToEnd(transport, executionId, options) {
|
|
1913
|
+
const stallTimeoutMs = options.stallTimeoutMs ?? 45e3;
|
|
1914
|
+
const reconnectLimit = options.reconnectLimit ?? 60;
|
|
1915
|
+
const reconnectDelayMs = options.reconnectDelayMs ?? 2e3;
|
|
1916
|
+
const outer = options.signal;
|
|
1917
|
+
let cursor = options.lastEventSeq ?? 0;
|
|
1918
|
+
let failures = 0;
|
|
1919
|
+
while (!outer?.aborted && failures < reconnectLimit) {
|
|
1920
|
+
const attempt2 = new AbortController();
|
|
1921
|
+
const onOuterAbort = () => attempt2.abort();
|
|
1922
|
+
outer?.addEventListener("abort", onOuterAbort, { once: true });
|
|
1923
|
+
let stallTimer = null;
|
|
1924
|
+
const armStall = () => {
|
|
1925
|
+
if (stallTimer !== null) clearTimeout(stallTimer);
|
|
1926
|
+
stallTimer = setTimeout(() => attempt2.abort(), stallTimeoutMs);
|
|
1927
|
+
};
|
|
1928
|
+
try {
|
|
1929
|
+
const items = followRuntimeOperationEvents(transport, executionId, {
|
|
1930
|
+
lastEventSeq: cursor,
|
|
1931
|
+
signal: attempt2.signal,
|
|
1932
|
+
...options.onMalformedFrame ? { onMalformedFrame: options.onMalformedFrame } : {}
|
|
1933
|
+
});
|
|
1934
|
+
armStall();
|
|
1935
|
+
for await (const item of items) {
|
|
1936
|
+
armStall();
|
|
1937
|
+
failures = 0;
|
|
1938
|
+
cursor = item.cursor;
|
|
1939
|
+
if (item.type === "end") {
|
|
1940
|
+
return { ended: true, status: item.status };
|
|
1941
|
+
}
|
|
1942
|
+
if (item.type === "event") {
|
|
1943
|
+
options.onEvent(item.event, item.seq);
|
|
1944
|
+
}
|
|
1889
1945
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
error
|
|
1895
|
-
|
|
1896
|
-
|
|
1946
|
+
failures += 1;
|
|
1947
|
+
} catch (error) {
|
|
1948
|
+
if (outer?.aborted) break;
|
|
1949
|
+
failures += 1;
|
|
1950
|
+
options.onAttemptError?.(error);
|
|
1951
|
+
} finally {
|
|
1952
|
+
if (stallTimer !== null) clearTimeout(stallTimer);
|
|
1953
|
+
outer?.removeEventListener("abort", onOuterAbort);
|
|
1954
|
+
}
|
|
1955
|
+
if (!outer?.aborted && failures < reconnectLimit) {
|
|
1956
|
+
await new Promise((r) => setTimeout(r, reconnectDelayMs));
|
|
1957
|
+
}
|
|
1897
1958
|
}
|
|
1959
|
+
return { ended: false, status: null };
|
|
1898
1960
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
function submitAgentToolResults(transport, conversationId, results, options = {}) {
|
|
1902
|
-
return requestJson(
|
|
1961
|
+
async function rejoinRuntimeOperation(transport, requestId, options = {}) {
|
|
1962
|
+
const response = await requestStream(
|
|
1903
1963
|
transport,
|
|
1904
|
-
`/
|
|
1964
|
+
`/runtime/operations/${encodePathSegment(requestId)}/rejoin`,
|
|
1905
1965
|
{
|
|
1906
1966
|
method: "POST",
|
|
1907
|
-
body
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
},
|
|
1967
|
+
// The route takes no body model; the reference client posts an empty
|
|
1968
|
+
// JSON object. Match it so proxies see an ordinary JSON POST.
|
|
1969
|
+
body: {},
|
|
1911
1970
|
...options.signal ? { signal: options.signal } : {}
|
|
1912
1971
|
}
|
|
1913
1972
|
);
|
|
1973
|
+
return toRunHandle(response, options);
|
|
1914
1974
|
}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
}
|
|
1923
|
-
);
|
|
1975
|
+
|
|
1976
|
+
// matrx/rejoin.ts
|
|
1977
|
+
var MATRX_RUN_IN_PROGRESS = "run_in_progress";
|
|
1978
|
+
var MATRX_RESUME_CONFLICT = "resume_conflict";
|
|
1979
|
+
var MATRX_LIVE_STREAM_UNAVAILABLE = "live_stream_unavailable";
|
|
1980
|
+
function isRecord4(value) {
|
|
1981
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1924
1982
|
}
|
|
1925
|
-
function
|
|
1926
|
-
|
|
1927
|
-
options.instanceId !== void 0 ? { instance_id: options.instanceId } : {}
|
|
1928
|
-
);
|
|
1929
|
-
return requestJson(
|
|
1930
|
-
transport,
|
|
1931
|
-
`/ai/user/pending_calls${query}`,
|
|
1932
|
-
{
|
|
1933
|
-
method: "GET",
|
|
1934
|
-
...options.signal ? { signal: options.signal } : {}
|
|
1935
|
-
}
|
|
1936
|
-
);
|
|
1983
|
+
function nonBlank(value) {
|
|
1984
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
1937
1985
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
this.details = data.details ?? null;
|
|
1960
|
-
this.requestId = data.requestId ?? "";
|
|
1961
|
-
this.status = data.status ?? null;
|
|
1986
|
+
function detailCandidates(body) {
|
|
1987
|
+
if (!isRecord4(body)) return [];
|
|
1988
|
+
const out = [];
|
|
1989
|
+
if (isRecord4(body.detail)) out.push(body.detail);
|
|
1990
|
+
if (isRecord4(body.details)) out.push(body.details);
|
|
1991
|
+
out.push(body);
|
|
1992
|
+
return out;
|
|
1993
|
+
}
|
|
1994
|
+
function statusOf(error) {
|
|
1995
|
+
if (!isRecord4(error) && !(error instanceof Error)) return null;
|
|
1996
|
+
const status = error.status;
|
|
1997
|
+
return typeof status === "number" ? status : null;
|
|
1998
|
+
}
|
|
1999
|
+
function bodyOf(error) {
|
|
2000
|
+
if (!isRecord4(error) && !(error instanceof Error)) return void 0;
|
|
2001
|
+
return error.serverDetail;
|
|
2002
|
+
}
|
|
2003
|
+
function readMatrxErrorCode(error) {
|
|
2004
|
+
for (const candidate of detailCandidates(bodyOf(error))) {
|
|
2005
|
+
const code = nonBlank(candidate.code);
|
|
2006
|
+
if (code) return code;
|
|
1962
2007
|
}
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
return
|
|
1966
|
-
error: this.code,
|
|
1967
|
-
message: this.detail,
|
|
1968
|
-
user_message: this.userMessage,
|
|
1969
|
-
details: this.details,
|
|
1970
|
-
request_id: this.requestId
|
|
1971
|
-
};
|
|
2008
|
+
for (const candidate of detailCandidates(bodyOf(error))) {
|
|
2009
|
+
const code = nonBlank(candidate.error);
|
|
2010
|
+
if (code) return code;
|
|
1972
2011
|
}
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
2012
|
+
return null;
|
|
2013
|
+
}
|
|
2014
|
+
var PREFIXED_ERROR_CODES = [
|
|
2015
|
+
"resume_conflict",
|
|
2016
|
+
"not_resumable",
|
|
2017
|
+
"outstanding_delegated_calls",
|
|
2018
|
+
"user_request_not_found",
|
|
2019
|
+
"run_in_flight"
|
|
2020
|
+
];
|
|
2021
|
+
function readMatrxErrorCodeFromMessage(message) {
|
|
2022
|
+
if (typeof message !== "string") return null;
|
|
2023
|
+
for (const code of PREFIXED_ERROR_CODES) {
|
|
2024
|
+
if (message.startsWith(`${code}:`)) return code;
|
|
1986
2025
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2026
|
+
return null;
|
|
2027
|
+
}
|
|
2028
|
+
async function readConversationOrganizationId(conversationId, read, onUnreadable) {
|
|
2029
|
+
try {
|
|
2030
|
+
const value = await read(conversationId);
|
|
2031
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
2032
|
+
onUnreadable?.(null);
|
|
2033
|
+
} catch (error) {
|
|
2034
|
+
onUnreadable?.(error instanceof Error ? error.message : String(error));
|
|
1992
2035
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2036
|
+
return null;
|
|
2037
|
+
}
|
|
2038
|
+
function firstString(candidates, key) {
|
|
2039
|
+
for (const candidate of candidates) {
|
|
2040
|
+
const value = nonBlank(candidate[key]);
|
|
2041
|
+
if (value) return value.trim();
|
|
1998
2042
|
}
|
|
1999
|
-
return
|
|
2043
|
+
return null;
|
|
2000
2044
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2045
|
+
function readLiveRunRejoin(error) {
|
|
2046
|
+
if (statusOf(error) !== 409) return null;
|
|
2047
|
+
const candidates = detailCandidates(bodyOf(error));
|
|
2048
|
+
if (candidates.length === 0) return null;
|
|
2049
|
+
const code = readMatrxErrorCode(error);
|
|
2050
|
+
if (code !== MATRX_RUN_IN_PROGRESS) return null;
|
|
2051
|
+
const liveRequestId = firstString(candidates, "live_request_id");
|
|
2052
|
+
const pathFromBody = firstString(candidates, "rejoin_path");
|
|
2053
|
+
const rejoinPath = pathFromBody && pathFromBody.startsWith("/") ? pathFromBody : liveRequestId ? runtimeOperationRejoinPath(liveRequestId) : null;
|
|
2054
|
+
if (!rejoinPath) return null;
|
|
2055
|
+
const root = bodyOf(error);
|
|
2056
|
+
return {
|
|
2057
|
+
liveRequestId,
|
|
2058
|
+
rejoinPath,
|
|
2059
|
+
runId: firstString(candidates, "run_id"),
|
|
2060
|
+
code,
|
|
2061
|
+
body: isRecord4(root) ? root : {}
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
function readLiveRunRequestId(error) {
|
|
2065
|
+
return readLiveRunRejoin(error)?.liveRequestId ?? null;
|
|
2066
|
+
}
|
|
2067
|
+
function isResumeConflict(error) {
|
|
2068
|
+
return statusOf(error) === 409 && readMatrxErrorCode(error) === MATRX_RESUME_CONFLICT;
|
|
2069
|
+
}
|
|
2070
|
+
function isLiveStreamUnavailable(error) {
|
|
2071
|
+
return statusOf(error) === 409 && readMatrxErrorCode(error) === MATRX_LIVE_STREAM_UNAVAILABLE;
|
|
2072
|
+
}
|
|
2073
|
+
function runtimeOperationRejoinPath(requestId) {
|
|
2074
|
+
return `/runtime/operations/${encodePathSegment(requestId)}/rejoin`;
|
|
2075
|
+
}
|
|
2076
|
+
function streamErrorText(eventOrPayload) {
|
|
2077
|
+
if (!isRecord4(eventOrPayload)) return null;
|
|
2078
|
+
const payload = typeof eventOrPayload.event === "string" && isRecord4(eventOrPayload.data) ? eventOrPayload.data : eventOrPayload;
|
|
2079
|
+
return nonBlank(payload.user_message) ?? nonBlank(payload.message);
|
|
2080
|
+
}
|
|
2081
|
+
async function openMatrxStream(transport, path, options = {}) {
|
|
2082
|
+
const response = await requestStream(transport, path, {
|
|
2083
|
+
method: "POST",
|
|
2084
|
+
...options.body !== void 0 ? { body: options.body } : {},
|
|
2085
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2086
|
+
});
|
|
2087
|
+
return toRunHandle(response, options);
|
|
2088
|
+
}
|
|
2089
|
+
function withRunOrganization(transport, organizationId) {
|
|
2090
|
+
const orgId = requireOrganizationContext(organizationId);
|
|
2091
|
+
return {
|
|
2092
|
+
fetch: (path, init) => transport.fetch(path, {
|
|
2093
|
+
...init,
|
|
2094
|
+
headers: { ...init.headers, "X-Organization-Id": orgId }
|
|
2095
|
+
})
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
async function followWorkflowRunEvents(transport, runId, options) {
|
|
2099
|
+
const headers = { Accept: "text/event-stream" };
|
|
2100
|
+
if (options.lastEventId) headers["Last-Event-ID"] = String(options.lastEventId);
|
|
2101
|
+
let response;
|
|
2004
2102
|
try {
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2103
|
+
response = await requestStream(
|
|
2104
|
+
transport,
|
|
2105
|
+
`/runs/${encodePathSegment(runId)}/events/stream`,
|
|
2106
|
+
{
|
|
2107
|
+
method: "GET",
|
|
2108
|
+
headers,
|
|
2109
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2110
|
+
}
|
|
2111
|
+
);
|
|
2112
|
+
} catch (error) {
|
|
2113
|
+
if (options.signal?.aborted) return { ended: false };
|
|
2114
|
+
throw error;
|
|
2115
|
+
}
|
|
2116
|
+
try {
|
|
2117
|
+
for await (const frame of readMatrxSseStream(
|
|
2118
|
+
response.body
|
|
2119
|
+
)) {
|
|
2120
|
+
if (frame.event === "end") return { ended: true };
|
|
2121
|
+
if (frame.data === null) continue;
|
|
2122
|
+
let parsed;
|
|
2123
|
+
try {
|
|
2124
|
+
parsed = JSON.parse(frame.data);
|
|
2125
|
+
} catch {
|
|
2126
|
+
continue;
|
|
2127
|
+
}
|
|
2128
|
+
if (!isRecord4(parsed)) continue;
|
|
2129
|
+
options.onEvent(parsed, parsed.event === "node_stream" ? null : frame.seq);
|
|
2022
2130
|
}
|
|
2131
|
+
} catch (error) {
|
|
2132
|
+
if (!options.signal?.aborted) throw error;
|
|
2023
2133
|
}
|
|
2024
|
-
return
|
|
2134
|
+
return { ended: false };
|
|
2025
2135
|
}
|
|
2026
|
-
function
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2136
|
+
async function drain(handle, onEnvelope) {
|
|
2137
|
+
for await (const envelope of handle.events) onEnvelope(envelope);
|
|
2138
|
+
}
|
|
2139
|
+
async function resumeOrRejoin(transport, resumeCall, options) {
|
|
2140
|
+
const {
|
|
2141
|
+
onEnvelope,
|
|
2142
|
+
organizationId,
|
|
2143
|
+
onRejoin,
|
|
2144
|
+
onOperationEvent,
|
|
2145
|
+
onWorkflowEvent,
|
|
2146
|
+
follow,
|
|
2147
|
+
...rest
|
|
2148
|
+
} = options;
|
|
2149
|
+
const bound = organizationId ? withRunOrganization(transport, organizationId) : transport;
|
|
2150
|
+
const streamOptions = {
|
|
2151
|
+
...rest,
|
|
2152
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2153
|
+
};
|
|
2154
|
+
const signalOnly = options.signal ? { signal: options.signal } : {};
|
|
2155
|
+
let rejoin;
|
|
2156
|
+
try {
|
|
2157
|
+
const handle = await resumeCall(bound, streamOptions);
|
|
2158
|
+
await drain(handle, onEnvelope);
|
|
2159
|
+
return { kind: "resumed", requestId: handle.requestId };
|
|
2160
|
+
} catch (error) {
|
|
2161
|
+
const target = readLiveRunRejoin(error);
|
|
2162
|
+
if (!target) {
|
|
2163
|
+
if (error instanceof MatrxApiError && isResumeConflict(error)) {
|
|
2164
|
+
return { kind: "resume_conflict", error };
|
|
2165
|
+
}
|
|
2166
|
+
throw error;
|
|
2167
|
+
}
|
|
2168
|
+
rejoin = target;
|
|
2034
2169
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
status
|
|
2170
|
+
onRejoin?.(rejoin);
|
|
2171
|
+
let unavailable;
|
|
2172
|
+
try {
|
|
2173
|
+
const handle = await openMatrxStream(bound, rejoin.rejoinPath, {
|
|
2174
|
+
...streamOptions,
|
|
2175
|
+
// The rejoin routes take no body model; the reference client posts {}.
|
|
2176
|
+
body: {}
|
|
2043
2177
|
});
|
|
2178
|
+
await drain(handle, onEnvelope);
|
|
2179
|
+
return { kind: "rejoined", rejoin };
|
|
2180
|
+
} catch (error) {
|
|
2181
|
+
const read = readLiveStreamUnavailable(error);
|
|
2182
|
+
if (!read) throw error;
|
|
2183
|
+
unavailable = read;
|
|
2044
2184
|
}
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2185
|
+
return followUnavailableRejoin(bound, rejoin, unavailable, {
|
|
2186
|
+
...signalOnly,
|
|
2187
|
+
...onOperationEvent ? { onOperationEvent } : {},
|
|
2188
|
+
...onWorkflowEvent ? { onWorkflowEvent } : {},
|
|
2189
|
+
...follow ? { follow } : {}
|
|
2190
|
+
});
|
|
2191
|
+
}
|
|
2192
|
+
function readLiveStreamUnavailable(error) {
|
|
2193
|
+
if (!isLiveStreamUnavailable(error)) return null;
|
|
2194
|
+
return { runId: firstString(detailCandidates(bodyOf(error)), "run_id") };
|
|
2195
|
+
}
|
|
2196
|
+
async function followUnavailableRejoin(transport, rejoin, unavailable, options = {}) {
|
|
2197
|
+
const bound = options.organizationId ? withRunOrganization(transport, options.organizationId) : transport;
|
|
2198
|
+
const signalOnly = options.signal ? { signal: options.signal } : {};
|
|
2199
|
+
const runId = unavailable.runId ?? rejoin.runId;
|
|
2200
|
+
if (runId && rejoin.rejoinPath.startsWith("/runtime/operations/")) {
|
|
2201
|
+
const result2 = await followWorkflowRunEvents(bound, runId, {
|
|
2202
|
+
...signalOnly,
|
|
2203
|
+
onEvent: (event, seq) => options.onWorkflowEvent?.(event, seq)
|
|
2054
2204
|
});
|
|
2205
|
+
return { kind: "followed_workflow", rejoin, runId, ended: result2.ended };
|
|
2055
2206
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
detail: firstMsg ? `Validation error: ${firstMsg}` : JSON.stringify(body.detail),
|
|
2062
|
-
userMessage: firstMsg || `Request failed (${status})`,
|
|
2063
|
-
details: body.detail,
|
|
2064
|
-
status
|
|
2065
|
-
});
|
|
2207
|
+
const liveRequestId = rejoin.liveRequestId;
|
|
2208
|
+
const statusView = liveRequestId ? await getRuntimeOperationStatus(bound, liveRequestId, signalOnly) : null;
|
|
2209
|
+
const operation = statusView?.operations.find((op) => !op.is_terminal) ?? statusView?.operations[0] ?? null;
|
|
2210
|
+
if (!operation) {
|
|
2211
|
+
return { kind: "followed", rejoin, executionId: null, ended: false, status: null };
|
|
2066
2212
|
}
|
|
2067
|
-
if (
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
details: d.details ?? d,
|
|
2076
|
-
requestId: typeof d.request_id === "string" ? d.request_id : void 0,
|
|
2077
|
-
status
|
|
2078
|
-
});
|
|
2213
|
+
if (operation.is_terminal) {
|
|
2214
|
+
return {
|
|
2215
|
+
kind: "followed",
|
|
2216
|
+
rejoin,
|
|
2217
|
+
executionId: operation.execution_id,
|
|
2218
|
+
ended: true,
|
|
2219
|
+
status: operation.status
|
|
2220
|
+
};
|
|
2079
2221
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
requestId: typeof body.request_id === "string" ? body.request_id : void 0,
|
|
2086
|
-
status
|
|
2222
|
+
const result = await followRuntimeOperationToEnd(bound, operation.execution_id, {
|
|
2223
|
+
...options.follow,
|
|
2224
|
+
lastEventSeq: operation.last_event_seq,
|
|
2225
|
+
...signalOnly,
|
|
2226
|
+
onEvent: (event) => options.onOperationEvent?.(event)
|
|
2087
2227
|
});
|
|
2228
|
+
return {
|
|
2229
|
+
kind: "followed",
|
|
2230
|
+
rejoin,
|
|
2231
|
+
executionId: operation.execution_id,
|
|
2232
|
+
ended: result.ended,
|
|
2233
|
+
status: result.status
|
|
2234
|
+
};
|
|
2088
2235
|
}
|
|
2089
|
-
function
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2236
|
+
async function attempt(run) {
|
|
2237
|
+
try {
|
|
2238
|
+
await run();
|
|
2239
|
+
return { reloaded: true };
|
|
2240
|
+
} catch (error) {
|
|
2241
|
+
return { reloaded: false, error };
|
|
2242
|
+
}
|
|
2093
2243
|
}
|
|
2094
|
-
function
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2244
|
+
async function settleRunPickup(pickup, options) {
|
|
2245
|
+
switch (pickup.kind) {
|
|
2246
|
+
case "resumed":
|
|
2247
|
+
case "rejoined":
|
|
2248
|
+
return { state: "streamed" };
|
|
2249
|
+
case "resume_conflict":
|
|
2250
|
+
return { state: "retry" };
|
|
2251
|
+
case "followed_workflow":
|
|
2252
|
+
case "followed": {
|
|
2253
|
+
const status = pickup.kind === "followed" ? pickup.status : null;
|
|
2254
|
+
const nothingLive = pickup.kind === "followed" && pickup.executionId === null;
|
|
2255
|
+
if (pickup.ended || nothingLive) {
|
|
2256
|
+
return { state: "settled", status, ...await attempt(options.reloadSavedTurn) };
|
|
2257
|
+
}
|
|
2258
|
+
return {
|
|
2259
|
+
state: "still_running",
|
|
2260
|
+
...await attempt(options.onStillRunning ?? options.reloadSavedTurn)
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2101
2263
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
// matrx/run.ts
|
|
2267
|
+
async function streamCall(transport, path, body, options) {
|
|
2268
|
+
const response = await requestStream(transport, path, {
|
|
2269
|
+
method: "POST",
|
|
2270
|
+
// This client IS the streaming path — `stream: true` always, last so a
|
|
2271
|
+
// caller-supplied value can never flip the response off NDJSON.
|
|
2272
|
+
body: { ...body, stream: true },
|
|
2273
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2110
2274
|
});
|
|
2275
|
+
return toRunHandle(response, options);
|
|
2111
2276
|
}
|
|
2112
|
-
function
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2277
|
+
function startAgentRun(transport, agentId, request, options = {}) {
|
|
2278
|
+
return streamCall(
|
|
2279
|
+
transport,
|
|
2280
|
+
`/ai/agents/${encodePathSegment(agentId)}`,
|
|
2281
|
+
request,
|
|
2282
|
+
options
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
function startMandateRun(transport, mandateKey, request, options = {}) {
|
|
2286
|
+
return streamCall(
|
|
2287
|
+
transport,
|
|
2288
|
+
`/ai/mandates/${encodePathSegment(mandateKey)}`,
|
|
2289
|
+
request,
|
|
2290
|
+
options
|
|
2291
|
+
);
|
|
2292
|
+
}
|
|
2293
|
+
function continueAgentConversation(transport, conversationId, request, options = {}) {
|
|
2294
|
+
return streamCall(
|
|
2295
|
+
transport,
|
|
2296
|
+
`/ai/conversations/${encodePathSegment(conversationId)}`,
|
|
2297
|
+
request,
|
|
2298
|
+
options
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2301
|
+
function resumeAgentConversation(transport, conversationId, request = {}, options = {}) {
|
|
2302
|
+
return streamCall(
|
|
2303
|
+
transport,
|
|
2304
|
+
`/ai/conversations/${encodePathSegment(conversationId)}/resume`,
|
|
2305
|
+
request,
|
|
2306
|
+
options
|
|
2118
2307
|
);
|
|
2119
|
-
const summary = typeof error.message === "string" ? error.message : "Backend operation failed";
|
|
2120
|
-
const specific = typeof firstSpecific?.message === "string" ? firstSpecific.message : summary;
|
|
2121
|
-
const detail = specific === summary ? summary : `${summary}: ${specific}`;
|
|
2122
|
-
const code = typeof error.type === "string" ? error.type : "internal_error";
|
|
2123
|
-
const userMessage = typeof error.user_message === "string" && error.user_message ? error.user_message : detail;
|
|
2124
|
-
return new BackendApiError({
|
|
2125
|
-
code,
|
|
2126
|
-
detail,
|
|
2127
|
-
userMessage,
|
|
2128
|
-
details: error,
|
|
2129
|
-
requestId
|
|
2130
|
-
});
|
|
2131
2308
|
}
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2309
|
+
function cancelAgentRun(transport, requestId, options = {}) {
|
|
2310
|
+
const query = buildQuery(
|
|
2311
|
+
options.mode === "interrupt" ? { mode: "interrupt" } : {}
|
|
2312
|
+
);
|
|
2313
|
+
return requestJson(
|
|
2314
|
+
transport,
|
|
2315
|
+
`/ai/cancel/${encodePathSegment(requestId)}${query}`,
|
|
2316
|
+
{
|
|
2317
|
+
method: "POST",
|
|
2318
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2319
|
+
}
|
|
2320
|
+
);
|
|
2144
2321
|
}
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2322
|
+
var MatrxRunError = class extends Error {
|
|
2323
|
+
name = "MatrxRunError";
|
|
2324
|
+
/** The verbatim `error` event payload, when one fired. */
|
|
2325
|
+
errorPayload;
|
|
2326
|
+
/** The `user_request` completion status (`"failed"` | `"cancelled"`), when that was the trigger. */
|
|
2327
|
+
completionStatus;
|
|
2328
|
+
/** Text streamed before the failure — partial content never vanishes. */
|
|
2329
|
+
partialText;
|
|
2330
|
+
constructor(args) {
|
|
2331
|
+
super(args.message);
|
|
2332
|
+
this.errorPayload = args.errorPayload ?? null;
|
|
2333
|
+
this.completionStatus = args.completionStatus ?? null;
|
|
2334
|
+
this.partialText = args.partialText ?? "";
|
|
2154
2335
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
if (!inner) return null;
|
|
2159
|
-
const statusMatch = /\bHTTP (\d{3})\b/.exec(message.slice(0, start));
|
|
2160
|
-
return {
|
|
2161
|
-
message: inner,
|
|
2162
|
-
code: typeof body.error_type === "string" && body.error_type || typeof body.error === "string" && body.error || null,
|
|
2163
|
-
userMessage: typeof body.user_message === "string" ? body.user_message : null,
|
|
2164
|
-
requestId: typeof body.request_id === "string" ? body.request_id : null,
|
|
2165
|
-
status: statusMatch ? Number(statusMatch[1]) : null
|
|
2166
|
-
};
|
|
2336
|
+
};
|
|
2337
|
+
function isRecord5(value) {
|
|
2338
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2167
2339
|
}
|
|
2168
|
-
function
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
if (
|
|
2181
|
-
|
|
2340
|
+
function stringField(value, key) {
|
|
2341
|
+
if (!isRecord5(value)) return null;
|
|
2342
|
+
const field = value[key];
|
|
2343
|
+
return typeof field === "string" && field ? field : null;
|
|
2344
|
+
}
|
|
2345
|
+
async function runAgentToCompletion(transport, agentId, request, options = {}) {
|
|
2346
|
+
const handle = await startAgentRun(transport, agentId, request, options);
|
|
2347
|
+
let text = "";
|
|
2348
|
+
let completion = null;
|
|
2349
|
+
let failure = null;
|
|
2350
|
+
for await (const envelope of handle.events) {
|
|
2351
|
+
options.onEvent?.(envelope);
|
|
2352
|
+
if (envelope.event === "chunk") {
|
|
2353
|
+
const chunk = stringField(envelope.data, "text");
|
|
2354
|
+
if (chunk !== null) {
|
|
2355
|
+
text += chunk;
|
|
2356
|
+
options.onChunk?.(text);
|
|
2357
|
+
}
|
|
2358
|
+
continue;
|
|
2359
|
+
}
|
|
2360
|
+
if (envelope.event === "error" && failure === null) {
|
|
2361
|
+
const payload = isRecord5(envelope.data) ? envelope.data : null;
|
|
2362
|
+
failure = new MatrxRunError({
|
|
2363
|
+
message: streamErrorText(payload) ?? "The agent run failed",
|
|
2364
|
+
errorPayload: payload,
|
|
2365
|
+
partialText: text
|
|
2366
|
+
});
|
|
2367
|
+
continue;
|
|
2368
|
+
}
|
|
2369
|
+
if (envelope.event !== "completion" || !isRecord5(envelope.data)) continue;
|
|
2370
|
+
if (envelope.data.operation !== "user_request") continue;
|
|
2371
|
+
completion = envelope.data;
|
|
2372
|
+
const status = envelope.data.status;
|
|
2373
|
+
if ((status === "failed" || status === "cancelled") && failure === null) {
|
|
2374
|
+
const result = isRecord5(envelope.data.result) ? envelope.data.result : null;
|
|
2375
|
+
failure = new MatrxRunError({
|
|
2376
|
+
message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
|
|
2377
|
+
completionStatus: status,
|
|
2378
|
+
partialText: text
|
|
2379
|
+
});
|
|
2182
2380
|
}
|
|
2183
|
-
} else if (error instanceof Error) {
|
|
2184
|
-
chain.push(error.message);
|
|
2185
|
-
userFacing = error.message;
|
|
2186
|
-
} else if (typeof error === "string") {
|
|
2187
|
-
chain.push(error);
|
|
2188
|
-
userFacing = error;
|
|
2189
|
-
} else {
|
|
2190
|
-
chain.push("Unknown error");
|
|
2191
2381
|
}
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
if (
|
|
2197
|
-
if (upstream.requestId) requestId = upstream.requestId;
|
|
2198
|
-
if (upstream.status !== null) status = upstream.status;
|
|
2382
|
+
if (failure) throw failure;
|
|
2383
|
+
if (!text && completion) {
|
|
2384
|
+
const result = completion.result;
|
|
2385
|
+
const output = stringField(result, "output");
|
|
2386
|
+
if (output !== null) text = output;
|
|
2199
2387
|
}
|
|
2200
|
-
const specific = [...chain].reverse().find((message) => !isGenericUserMessage(message));
|
|
2201
|
-
const cause = specific ?? chain[0] ?? "Unknown error";
|
|
2202
|
-
const headlineWasGeneric = isGenericUserMessage(userFacing);
|
|
2203
2388
|
return {
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
chain,
|
|
2209
|
-
requestId,
|
|
2210
|
-
status
|
|
2389
|
+
text,
|
|
2390
|
+
requestId: handle.requestId,
|
|
2391
|
+
conversationId: handle.conversationId,
|
|
2392
|
+
completion
|
|
2211
2393
|
};
|
|
2212
2394
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
if (
|
|
2224
|
-
|
|
2395
|
+
|
|
2396
|
+
// matrx/provider-failures.ts
|
|
2397
|
+
var clip = (value, max) => value.length > max ? value.slice(0, max) : value;
|
|
2398
|
+
function providerSessionFailureBody(failure) {
|
|
2399
|
+
const message = failure.message?.trim() || failure.error_type?.trim() || (failure.status_code ? `HTTP ${failure.status_code}` : "provider session failed");
|
|
2400
|
+
const body = {
|
|
2401
|
+
provider: failure.provider,
|
|
2402
|
+
message: clip(message, 4e3)
|
|
2403
|
+
};
|
|
2404
|
+
if (failure.model?.trim()) body.model = clip(failure.model.trim(), 200);
|
|
2405
|
+
if (failure.error_type?.trim()) body.error_type = clip(failure.error_type.trim(), 200);
|
|
2406
|
+
if (typeof failure.status_code === "number" && Number.isInteger(failure.status_code) && failure.status_code >= 100 && failure.status_code <= 599) {
|
|
2407
|
+
body.status_code = failure.status_code;
|
|
2225
2408
|
}
|
|
2226
|
-
return
|
|
2409
|
+
return body;
|
|
2227
2410
|
}
|
|
2228
|
-
function
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2411
|
+
async function reportProviderSessionFailure(transport, failure, options = {}) {
|
|
2412
|
+
try {
|
|
2413
|
+
return await requestJson(
|
|
2414
|
+
transport,
|
|
2415
|
+
"/broker/provider-failures",
|
|
2416
|
+
{
|
|
2417
|
+
method: "POST",
|
|
2418
|
+
body: providerSessionFailureBody(failure),
|
|
2419
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2420
|
+
}
|
|
2421
|
+
);
|
|
2422
|
+
} catch (error) {
|
|
2423
|
+
console.warn(
|
|
2424
|
+
`[provider-failures] could not report a ${failure.provider} session failure`,
|
|
2425
|
+
error
|
|
2426
|
+
);
|
|
2427
|
+
return null;
|
|
2240
2428
|
}
|
|
2241
2429
|
}
|
|
2242
2430
|
|
|
2431
|
+
// matrx/tools.ts
|
|
2432
|
+
function submitAgentToolResults(transport, conversationId, results, options = {}) {
|
|
2433
|
+
return requestJson(
|
|
2434
|
+
transport,
|
|
2435
|
+
`/ai/conversations/${encodePathSegment(conversationId)}/tool_results`,
|
|
2436
|
+
{
|
|
2437
|
+
method: "POST",
|
|
2438
|
+
body: {
|
|
2439
|
+
results,
|
|
2440
|
+
...options.instanceId !== void 0 ? { instance_id: options.instanceId } : {}
|
|
2441
|
+
},
|
|
2442
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2443
|
+
}
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
function listConversationPendingToolCalls(transport, conversationId, options = {}) {
|
|
2447
|
+
return requestJson(
|
|
2448
|
+
transport,
|
|
2449
|
+
`/ai/conversations/${encodePathSegment(conversationId)}/pending_calls`,
|
|
2450
|
+
{
|
|
2451
|
+
method: "GET",
|
|
2452
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2453
|
+
}
|
|
2454
|
+
);
|
|
2455
|
+
}
|
|
2456
|
+
function listUserPendingToolCalls(transport, options = {}) {
|
|
2457
|
+
const query = buildQuery(
|
|
2458
|
+
options.instanceId !== void 0 ? { instance_id: options.instanceId } : {}
|
|
2459
|
+
);
|
|
2460
|
+
return requestJson(
|
|
2461
|
+
transport,
|
|
2462
|
+
`/ai/user/pending_calls${query}`,
|
|
2463
|
+
{
|
|
2464
|
+
method: "GET",
|
|
2465
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2466
|
+
}
|
|
2467
|
+
);
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2243
2470
|
// matrx/endpoints.ts
|
|
2244
2471
|
var ENDPOINTS = {
|
|
2245
2472
|
/** AI endpoints — chat, agents, conversations */
|
|
@@ -3093,6 +3320,7 @@ export {
|
|
|
3093
3320
|
MATRX_LIVE_STREAM_UNAVAILABLE,
|
|
3094
3321
|
MATRX_RESUME_CONFLICT,
|
|
3095
3322
|
MATRX_RUN_IN_PROGRESS,
|
|
3323
|
+
MATRX_UI_ONLY_BODY_FIELDS,
|
|
3096
3324
|
MatrxApiError,
|
|
3097
3325
|
MatrxRunError,
|
|
3098
3326
|
OrganizationContextError,
|
|
@@ -3110,6 +3338,10 @@ export {
|
|
|
3110
3338
|
applyOrganizationContextHeader,
|
|
3111
3339
|
assertOrganizationMatchesOperation,
|
|
3112
3340
|
assertQueryOrganizationMatchesContext,
|
|
3341
|
+
bareStatusSentence,
|
|
3342
|
+
buildMatrxRequestBody,
|
|
3343
|
+
buildMatrxRequestUrl,
|
|
3344
|
+
buildSafeRequestLog,
|
|
3113
3345
|
cancelAgentRun,
|
|
3114
3346
|
continueAgentConversation,
|
|
3115
3347
|
continueEphemeralConversationStart,
|
|
@@ -3122,6 +3354,7 @@ export {
|
|
|
3122
3354
|
createWorkflowNodeProjection,
|
|
3123
3355
|
deriveRunInputs,
|
|
3124
3356
|
describeBackendFailure,
|
|
3357
|
+
executeMatrxCall,
|
|
3125
3358
|
extractMatrxErrorCode,
|
|
3126
3359
|
extractMatrxErrorMessage,
|
|
3127
3360
|
fetchWithMatrxProtocolFallback,
|
|
@@ -3132,7 +3365,9 @@ export {
|
|
|
3132
3365
|
getRuntimeOperationStatus,
|
|
3133
3366
|
getRuntimeOperationsByLink,
|
|
3134
3367
|
getUserMessage,
|
|
3368
|
+
honestTransportMessage,
|
|
3135
3369
|
imageRoleVerdict,
|
|
3370
|
+
isBareTransportCode,
|
|
3136
3371
|
isControlVariable,
|
|
3137
3372
|
isCoveredAiPath,
|
|
3138
3373
|
isGenericUserMessage,
|
|
@@ -3159,6 +3394,7 @@ export {
|
|
|
3159
3394
|
parseCallApiError,
|
|
3160
3395
|
parseHttpError,
|
|
3161
3396
|
parseHttpErrorBody,
|
|
3397
|
+
parseMatrxNdjsonResponse,
|
|
3162
3398
|
parseMatrxSseFrame,
|
|
3163
3399
|
parsePersistedBackendError,
|
|
3164
3400
|
parseStreamError,
|
|
@@ -3177,6 +3413,7 @@ export {
|
|
|
3177
3413
|
readMatrxErrorCodeFromMessage,
|
|
3178
3414
|
readMatrxNdjsonStream,
|
|
3179
3415
|
readMatrxSseStream,
|
|
3416
|
+
redactUrlForRequestLog,
|
|
3180
3417
|
referenceRoleCaption,
|
|
3181
3418
|
rejoinRuntimeOperation,
|
|
3182
3419
|
reportProviderSessionFailure,
|
|
@@ -3194,6 +3431,7 @@ export {
|
|
|
3194
3431
|
runWaitTimeoutMessage,
|
|
3195
3432
|
runtimeOperationRejoinPath,
|
|
3196
3433
|
settleRunPickup,
|
|
3434
|
+
shouldReportMatrxCallError,
|
|
3197
3435
|
startAgentRun,
|
|
3198
3436
|
startMandateRun,
|
|
3199
3437
|
streamErrorText,
|