@ai-matrx/agents 0.22.0 → 0.23.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.
@@ -701,136 +701,6 @@ async function requestStream(transport, path, options) {
701
701
  return response;
702
702
  }
703
703
 
704
- // matrx/run.ts
705
- async function streamCall(transport, path, body, options) {
706
- const response = await requestStream(transport, path, {
707
- method: "POST",
708
- // This client IS the streaming path — `stream: true` always, last so a
709
- // caller-supplied value can never flip the response off NDJSON.
710
- body: { ...body, stream: true },
711
- ...options.signal ? { signal: options.signal } : {}
712
- });
713
- return toRunHandle(response, options);
714
- }
715
- function startAgentRun(transport, agentId, request, options = {}) {
716
- return streamCall(
717
- transport,
718
- `/ai/agents/${encodePathSegment(agentId)}`,
719
- request,
720
- options
721
- );
722
- }
723
- function startMandateRun(transport, mandateKey, request, options = {}) {
724
- return streamCall(
725
- transport,
726
- `/ai/mandates/${encodePathSegment(mandateKey)}`,
727
- request,
728
- options
729
- );
730
- }
731
- function continueAgentConversation(transport, conversationId, request, options = {}) {
732
- return streamCall(
733
- transport,
734
- `/ai/conversations/${encodePathSegment(conversationId)}`,
735
- request,
736
- options
737
- );
738
- }
739
- function resumeAgentConversation(transport, conversationId, request = {}, options = {}) {
740
- return streamCall(
741
- transport,
742
- `/ai/conversations/${encodePathSegment(conversationId)}/resume`,
743
- request,
744
- options
745
- );
746
- }
747
- function cancelAgentRun(transport, requestId, options = {}) {
748
- const query = buildQuery(
749
- options.mode === "interrupt" ? { mode: "interrupt" } : {}
750
- );
751
- return requestJson(
752
- transport,
753
- `/ai/cancel/${encodePathSegment(requestId)}${query}`,
754
- {
755
- method: "POST",
756
- ...options.signal ? { signal: options.signal } : {}
757
- }
758
- );
759
- }
760
- var MatrxRunError = class extends Error {
761
- name = "MatrxRunError";
762
- /** The verbatim `error` event payload, when one fired. */
763
- errorPayload;
764
- /** The `user_request` completion status (`"failed"` | `"cancelled"`), when that was the trigger. */
765
- completionStatus;
766
- /** Text streamed before the failure — partial content never vanishes. */
767
- partialText;
768
- constructor(args) {
769
- super(args.message);
770
- this.errorPayload = args.errorPayload ?? null;
771
- this.completionStatus = args.completionStatus ?? null;
772
- this.partialText = args.partialText ?? "";
773
- }
774
- };
775
- function isRecord3(value) {
776
- return typeof value === "object" && value !== null && !Array.isArray(value);
777
- }
778
- function stringField(value, key) {
779
- if (!isRecord3(value)) return null;
780
- const field = value[key];
781
- return typeof field === "string" && field ? field : null;
782
- }
783
- async function runAgentToCompletion(transport, agentId, request, options = {}) {
784
- const handle = await startAgentRun(transport, agentId, request, options);
785
- let text = "";
786
- let completion = null;
787
- let failure = null;
788
- for await (const envelope of handle.events) {
789
- options.onEvent?.(envelope);
790
- if (envelope.event === "chunk") {
791
- const chunk = stringField(envelope.data, "text");
792
- if (chunk !== null) {
793
- text += chunk;
794
- options.onChunk?.(text);
795
- }
796
- continue;
797
- }
798
- if (envelope.event === "error" && failure === null) {
799
- const payload = isRecord3(envelope.data) ? envelope.data : null;
800
- failure = new MatrxRunError({
801
- message: stringField(payload, "user_message") ?? stringField(payload, "message") ?? "The agent run failed",
802
- errorPayload: payload,
803
- partialText: text
804
- });
805
- continue;
806
- }
807
- if (envelope.event !== "completion" || !isRecord3(envelope.data)) continue;
808
- if (envelope.data.operation !== "user_request") continue;
809
- completion = envelope.data;
810
- const status = envelope.data.status;
811
- if ((status === "failed" || status === "cancelled") && failure === null) {
812
- const result = isRecord3(envelope.data.result) ? envelope.data.result : null;
813
- failure = new MatrxRunError({
814
- message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
815
- completionStatus: status,
816
- partialText: text
817
- });
818
- }
819
- }
820
- if (failure) throw failure;
821
- if (!text && completion) {
822
- const result = completion.result;
823
- const output = stringField(result, "output");
824
- if (output !== null) text = output;
825
- }
826
- return {
827
- text,
828
- requestId: handle.requestId,
829
- conversationId: handle.conversationId,
830
- completion
831
- };
832
- }
833
-
834
704
  // stream/sse.ts
835
705
  var FRAME_SEPARATOR = /\r\n\r\n|\n\n|\r\r/;
836
706
  var LINE_SEPARATOR = /\r\n|\n|\r/;
@@ -1057,6 +927,317 @@ async function rejoinRuntimeOperation(transport, requestId, options = {}) {
1057
927
  return toRunHandle(response, options);
1058
928
  }
1059
929
 
930
+ // matrx/rejoin.ts
931
+ var MATRX_RUN_IN_PROGRESS = "run_in_progress";
932
+ var MATRX_RESUME_CONFLICT = "resume_conflict";
933
+ var MATRX_LIVE_STREAM_UNAVAILABLE = "live_stream_unavailable";
934
+ function isRecord3(value) {
935
+ return typeof value === "object" && value !== null && !Array.isArray(value);
936
+ }
937
+ function nonBlank(value) {
938
+ return typeof value === "string" && value.trim() ? value : null;
939
+ }
940
+ function detailCandidates(body) {
941
+ if (!isRecord3(body)) return [];
942
+ const out = [];
943
+ if (isRecord3(body.detail)) out.push(body.detail);
944
+ if (isRecord3(body.details)) out.push(body.details);
945
+ out.push(body);
946
+ return out;
947
+ }
948
+ function statusOf(error) {
949
+ if (!isRecord3(error) && !(error instanceof Error)) return null;
950
+ const status = error.status;
951
+ return typeof status === "number" ? status : null;
952
+ }
953
+ function bodyOf(error) {
954
+ if (!isRecord3(error) && !(error instanceof Error)) return void 0;
955
+ return error.serverDetail;
956
+ }
957
+ function readMatrxErrorCode(error) {
958
+ for (const candidate of detailCandidates(bodyOf(error))) {
959
+ const code = nonBlank(candidate.code);
960
+ if (code) return code;
961
+ }
962
+ for (const candidate of detailCandidates(bodyOf(error))) {
963
+ const code = nonBlank(candidate.error);
964
+ if (code) return code;
965
+ }
966
+ return null;
967
+ }
968
+ function readLiveRunRequestId(error) {
969
+ if (statusOf(error) !== 409) return null;
970
+ for (const candidate of detailCandidates(bodyOf(error))) {
971
+ if (candidate.code !== MATRX_RUN_IN_PROGRESS) continue;
972
+ const live = nonBlank(candidate.live_request_id);
973
+ if (live) return live.trim();
974
+ }
975
+ return null;
976
+ }
977
+ function isResumeConflict(error) {
978
+ return statusOf(error) === 409 && readMatrxErrorCode(error) === MATRX_RESUME_CONFLICT;
979
+ }
980
+ function isLiveStreamUnavailable(error) {
981
+ return statusOf(error) === 409 && readMatrxErrorCode(error) === MATRX_LIVE_STREAM_UNAVAILABLE;
982
+ }
983
+ function runtimeOperationRejoinPath(requestId) {
984
+ return `/runtime/operations/${encodePathSegment(requestId)}/rejoin`;
985
+ }
986
+ function streamErrorText(eventOrPayload) {
987
+ if (!isRecord3(eventOrPayload)) return null;
988
+ const payload = typeof eventOrPayload.event === "string" && isRecord3(eventOrPayload.data) ? eventOrPayload.data : eventOrPayload;
989
+ return nonBlank(payload.user_message) ?? nonBlank(payload.message);
990
+ }
991
+ async function openMatrxStream(transport, path, options = {}) {
992
+ const response = await requestStream(transport, path, {
993
+ method: "POST",
994
+ ...options.body !== void 0 ? { body: options.body } : {},
995
+ ...options.signal ? { signal: options.signal } : {}
996
+ });
997
+ return toRunHandle(response, options);
998
+ }
999
+ function withRunOrganization(transport, organizationId) {
1000
+ const orgId = requireOrganizationContext(organizationId);
1001
+ return {
1002
+ fetch: (path, init) => transport.fetch(path, {
1003
+ ...init,
1004
+ headers: { ...init.headers, "X-Organization-Id": orgId }
1005
+ })
1006
+ };
1007
+ }
1008
+ async function drain(handle, onEnvelope) {
1009
+ for await (const envelope of handle.events) onEnvelope(envelope);
1010
+ }
1011
+ async function resumeOrRejoin(transport, resumeCall, options) {
1012
+ const { onEnvelope, organizationId, onRejoin, onOperationEvent, follow, ...rest } = options;
1013
+ const bound = organizationId ? withRunOrganization(transport, organizationId) : transport;
1014
+ const streamOptions = {
1015
+ ...rest,
1016
+ ...options.signal ? { signal: options.signal } : {}
1017
+ };
1018
+ let liveRequestId;
1019
+ try {
1020
+ const handle = await resumeCall(bound, streamOptions);
1021
+ await drain(handle, onEnvelope);
1022
+ return { kind: "resumed", requestId: handle.requestId };
1023
+ } catch (error) {
1024
+ if (error instanceof MatrxApiError && isResumeConflict(error)) {
1025
+ return { kind: "resume_conflict", error };
1026
+ }
1027
+ const live = readLiveRunRequestId(error);
1028
+ if (!live) throw error;
1029
+ liveRequestId = live;
1030
+ }
1031
+ onRejoin?.(liveRequestId);
1032
+ try {
1033
+ const handle = await rejoinRuntimeOperation(bound, liveRequestId, streamOptions);
1034
+ await drain(handle, onEnvelope);
1035
+ return { kind: "rejoined", liveRequestId };
1036
+ } catch (error) {
1037
+ if (!isLiveStreamUnavailable(error)) throw error;
1038
+ }
1039
+ const statusView = await getRuntimeOperationStatus(bound, liveRequestId, {
1040
+ ...options.signal ? { signal: options.signal } : {}
1041
+ });
1042
+ const operation = statusView?.operations.find((op) => !op.is_terminal) ?? statusView?.operations[0] ?? null;
1043
+ if (!operation) {
1044
+ return {
1045
+ kind: "followed",
1046
+ liveRequestId,
1047
+ executionId: null,
1048
+ ended: false,
1049
+ status: null
1050
+ };
1051
+ }
1052
+ if (operation.is_terminal) {
1053
+ return {
1054
+ kind: "followed",
1055
+ liveRequestId,
1056
+ executionId: operation.execution_id,
1057
+ ended: true,
1058
+ status: operation.status
1059
+ };
1060
+ }
1061
+ const result = await followRuntimeOperationToEnd(bound, operation.execution_id, {
1062
+ ...follow,
1063
+ lastEventSeq: operation.last_event_seq,
1064
+ ...options.signal ? { signal: options.signal } : {},
1065
+ onEvent: (event) => onOperationEvent?.(event)
1066
+ });
1067
+ return {
1068
+ kind: "followed",
1069
+ liveRequestId,
1070
+ executionId: operation.execution_id,
1071
+ ended: result.ended,
1072
+ status: result.status
1073
+ };
1074
+ }
1075
+
1076
+ // matrx/run.ts
1077
+ async function streamCall(transport, path, body, options) {
1078
+ const response = await requestStream(transport, path, {
1079
+ method: "POST",
1080
+ // This client IS the streaming path — `stream: true` always, last so a
1081
+ // caller-supplied value can never flip the response off NDJSON.
1082
+ body: { ...body, stream: true },
1083
+ ...options.signal ? { signal: options.signal } : {}
1084
+ });
1085
+ return toRunHandle(response, options);
1086
+ }
1087
+ function startAgentRun(transport, agentId, request, options = {}) {
1088
+ return streamCall(
1089
+ transport,
1090
+ `/ai/agents/${encodePathSegment(agentId)}`,
1091
+ request,
1092
+ options
1093
+ );
1094
+ }
1095
+ function startMandateRun(transport, mandateKey, request, options = {}) {
1096
+ return streamCall(
1097
+ transport,
1098
+ `/ai/mandates/${encodePathSegment(mandateKey)}`,
1099
+ request,
1100
+ options
1101
+ );
1102
+ }
1103
+ function continueAgentConversation(transport, conversationId, request, options = {}) {
1104
+ return streamCall(
1105
+ transport,
1106
+ `/ai/conversations/${encodePathSegment(conversationId)}`,
1107
+ request,
1108
+ options
1109
+ );
1110
+ }
1111
+ function resumeAgentConversation(transport, conversationId, request = {}, options = {}) {
1112
+ return streamCall(
1113
+ transport,
1114
+ `/ai/conversations/${encodePathSegment(conversationId)}/resume`,
1115
+ request,
1116
+ options
1117
+ );
1118
+ }
1119
+ function cancelAgentRun(transport, requestId, options = {}) {
1120
+ const query = buildQuery(
1121
+ options.mode === "interrupt" ? { mode: "interrupt" } : {}
1122
+ );
1123
+ return requestJson(
1124
+ transport,
1125
+ `/ai/cancel/${encodePathSegment(requestId)}${query}`,
1126
+ {
1127
+ method: "POST",
1128
+ ...options.signal ? { signal: options.signal } : {}
1129
+ }
1130
+ );
1131
+ }
1132
+ var MatrxRunError = class extends Error {
1133
+ name = "MatrxRunError";
1134
+ /** The verbatim `error` event payload, when one fired. */
1135
+ errorPayload;
1136
+ /** The `user_request` completion status (`"failed"` | `"cancelled"`), when that was the trigger. */
1137
+ completionStatus;
1138
+ /** Text streamed before the failure — partial content never vanishes. */
1139
+ partialText;
1140
+ constructor(args) {
1141
+ super(args.message);
1142
+ this.errorPayload = args.errorPayload ?? null;
1143
+ this.completionStatus = args.completionStatus ?? null;
1144
+ this.partialText = args.partialText ?? "";
1145
+ }
1146
+ };
1147
+ function isRecord4(value) {
1148
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1149
+ }
1150
+ function stringField(value, key) {
1151
+ if (!isRecord4(value)) return null;
1152
+ const field = value[key];
1153
+ return typeof field === "string" && field ? field : null;
1154
+ }
1155
+ async function runAgentToCompletion(transport, agentId, request, options = {}) {
1156
+ const handle = await startAgentRun(transport, agentId, request, options);
1157
+ let text = "";
1158
+ let completion = null;
1159
+ let failure = null;
1160
+ for await (const envelope of handle.events) {
1161
+ options.onEvent?.(envelope);
1162
+ if (envelope.event === "chunk") {
1163
+ const chunk = stringField(envelope.data, "text");
1164
+ if (chunk !== null) {
1165
+ text += chunk;
1166
+ options.onChunk?.(text);
1167
+ }
1168
+ continue;
1169
+ }
1170
+ if (envelope.event === "error" && failure === null) {
1171
+ const payload = isRecord4(envelope.data) ? envelope.data : null;
1172
+ failure = new MatrxRunError({
1173
+ message: streamErrorText(payload) ?? "The agent run failed",
1174
+ errorPayload: payload,
1175
+ partialText: text
1176
+ });
1177
+ continue;
1178
+ }
1179
+ if (envelope.event !== "completion" || !isRecord4(envelope.data)) continue;
1180
+ if (envelope.data.operation !== "user_request") continue;
1181
+ completion = envelope.data;
1182
+ const status = envelope.data.status;
1183
+ if ((status === "failed" || status === "cancelled") && failure === null) {
1184
+ const result = isRecord4(envelope.data.result) ? envelope.data.result : null;
1185
+ failure = new MatrxRunError({
1186
+ message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
1187
+ completionStatus: status,
1188
+ partialText: text
1189
+ });
1190
+ }
1191
+ }
1192
+ if (failure) throw failure;
1193
+ if (!text && completion) {
1194
+ const result = completion.result;
1195
+ const output = stringField(result, "output");
1196
+ if (output !== null) text = output;
1197
+ }
1198
+ return {
1199
+ text,
1200
+ requestId: handle.requestId,
1201
+ conversationId: handle.conversationId,
1202
+ completion
1203
+ };
1204
+ }
1205
+
1206
+ // matrx/provider-failures.ts
1207
+ var clip = (value, max) => value.length > max ? value.slice(0, max) : value;
1208
+ function providerSessionFailureBody(failure) {
1209
+ const message = failure.message?.trim() || failure.error_type?.trim() || (failure.status_code ? `HTTP ${failure.status_code}` : "provider session failed");
1210
+ const body = {
1211
+ provider: failure.provider,
1212
+ message: clip(message, 4e3)
1213
+ };
1214
+ if (failure.model?.trim()) body.model = clip(failure.model.trim(), 200);
1215
+ if (failure.error_type?.trim()) body.error_type = clip(failure.error_type.trim(), 200);
1216
+ if (typeof failure.status_code === "number" && Number.isInteger(failure.status_code) && failure.status_code >= 100 && failure.status_code <= 599) {
1217
+ body.status_code = failure.status_code;
1218
+ }
1219
+ return body;
1220
+ }
1221
+ async function reportProviderSessionFailure(transport, failure, options = {}) {
1222
+ try {
1223
+ return await requestJson(
1224
+ transport,
1225
+ "/broker/provider-failures",
1226
+ {
1227
+ method: "POST",
1228
+ body: providerSessionFailureBody(failure),
1229
+ ...options.signal ? { signal: options.signal } : {}
1230
+ }
1231
+ );
1232
+ } catch (error) {
1233
+ console.warn(
1234
+ `[provider-failures] could not report a ${failure.provider} session failure`,
1235
+ error
1236
+ );
1237
+ return null;
1238
+ }
1239
+ }
1240
+
1060
1241
  // matrx/tools.ts
1061
1242
  function submitAgentToolResults(transport, conversationId, results, options = {}) {
1062
1243
  return requestJson(
@@ -1097,6 +1278,9 @@ function listUserPendingToolCalls(transport, options = {}) {
1097
1278
  }
1098
1279
  export {
1099
1280
  MATRX_AI_API_VERSION_DEFAULT,
1281
+ MATRX_LIVE_STREAM_UNAVAILABLE,
1282
+ MATRX_RESUME_CONFLICT,
1283
+ MATRX_RUN_IN_PROGRESS,
1100
1284
  MatrxApiError,
1101
1285
  MatrxRunError,
1102
1286
  OrganizationContextError,
@@ -1120,6 +1304,8 @@ export {
1120
1304
  getRuntimeOperationStatus,
1121
1305
  getRuntimeOperationsByLink,
1122
1306
  isCoveredAiPath,
1307
+ isLiveStreamUnavailable,
1308
+ isResumeConflict,
1123
1309
  isV2Path,
1124
1310
  listConversationPendingToolCalls,
1125
1311
  listRuntimeOperationEvents,
@@ -1128,14 +1314,23 @@ export {
1128
1314
  newEphemeralConversationStart,
1129
1315
  newStoredConversationStart,
1130
1316
  normalizeMatrxError,
1317
+ openMatrxStream,
1318
+ providerSessionFailureBody,
1319
+ readLiveRunRequestId,
1320
+ readMatrxErrorCode,
1131
1321
  rejoinRuntimeOperation,
1322
+ reportProviderSessionFailure,
1132
1323
  requireOrganizationContext,
1133
1324
  resumeAgentConversation,
1325
+ resumeOrRejoin,
1134
1326
  runAgentToCompletion,
1327
+ runtimeOperationRejoinPath,
1135
1328
  startAgentRun,
1136
1329
  startMandateRun,
1330
+ streamErrorText,
1137
1331
  submitAgentToolResults,
1138
1332
  toV1FallbackUrl,
1139
- toV2Path
1333
+ toV2Path,
1334
+ withRunOrganization
1140
1335
  };
1141
1336
  //# sourceMappingURL=index.js.map