@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.
package/dist/index.cjs CHANGED
@@ -26,6 +26,9 @@ __export(index_exports, {
26
26
  IMAGE_REFERENCE_ROLES: () => IMAGE_REFERENCE_ROLES,
27
27
  IMAGE_ROLE_META: () => IMAGE_ROLE_META,
28
28
  MATRX_AI_API_VERSION_DEFAULT: () => MATRX_AI_API_VERSION_DEFAULT,
29
+ MATRX_LIVE_STREAM_UNAVAILABLE: () => MATRX_LIVE_STREAM_UNAVAILABLE,
30
+ MATRX_RESUME_CONFLICT: () => MATRX_RESUME_CONFLICT,
31
+ MATRX_RUN_IN_PROGRESS: () => MATRX_RUN_IN_PROGRESS,
29
32
  MatrxApiError: () => MatrxApiError,
30
33
  MatrxRunError: () => MatrxRunError,
31
34
  OrganizationContextError: () => OrganizationContextError,
@@ -59,7 +62,9 @@ __export(index_exports, {
59
62
  isControlVariable: () => isControlVariable,
60
63
  isCoveredAiPath: () => isCoveredAiPath,
61
64
  isImageReferenceRole: () => isImageReferenceRole,
65
+ isLiveStreamUnavailable: () => isLiveStreamUnavailable,
62
66
  isReferenceRole: () => isReferenceRole,
67
+ isResumeConflict: () => isResumeConflict,
63
68
  isV2Path: () => isV2Path,
64
69
  listConversationPendingToolCalls: () => listConversationPendingToolCalls,
65
70
  listRuntimeOperationEvents: () => listRuntimeOperationEvents,
@@ -71,6 +76,7 @@ __export(index_exports, {
71
76
  normalizeMatrxError: () => normalizeMatrxError,
72
77
  normalizeMatrxStreamEnvelope: () => normalizeMatrxStreamEnvelope,
73
78
  normalizeReferenceName: () => normalizeReferenceName,
79
+ openMatrxStream: () => openMatrxStream,
74
80
  orderVariablesForForm: () => orderVariablesForForm,
75
81
  parseMatrxSseFrame: () => parseMatrxSseFrame,
76
82
  partitionControlVariables: () => partitionControlVariables,
@@ -78,25 +84,33 @@ __export(index_exports, {
78
84
  projectAgentEvents: () => projectAgentEvents,
79
85
  projectAgentResultForDisplay: () => projectAgentResultForDisplay,
80
86
  projectWorkflowNodeEvent: () => projectWorkflowNodeEvent,
87
+ providerSessionFailureBody: () => providerSessionFailureBody,
81
88
  readImageRoleLimits: () => readImageRoleLimits,
89
+ readLiveRunRequestId: () => readLiveRunRequestId,
90
+ readMatrxErrorCode: () => readMatrxErrorCode,
82
91
  readMatrxNdjsonStream: () => readMatrxNdjsonStream,
83
92
  readMatrxSseStream: () => readMatrxSseStream,
84
93
  referenceRoleCaption: () => referenceRoleCaption,
85
94
  rejoinRuntimeOperation: () => rejoinRuntimeOperation,
95
+ reportProviderSessionFailure: () => reportProviderSessionFailure,
86
96
  requireOrganizationContext: () => requireOrganizationContext,
87
97
  resumeAgentConversation: () => resumeAgentConversation,
98
+ resumeOrRejoin: () => resumeOrRejoin,
88
99
  roleTakesName: () => roleTakesName,
89
100
  rolesFor: () => rolesFor,
90
101
  runAgentToCompletion: () => runAgentToCompletion,
102
+ runtimeOperationRejoinPath: () => runtimeOperationRejoinPath,
91
103
  startAgentRun: () => startAgentRun,
92
104
  startMandateRun: () => startMandateRun,
105
+ streamErrorText: () => streamErrorText,
93
106
  submitAgentToolResults: () => submitAgentToolResults,
94
107
  toV1FallbackUrl: () => toV1FallbackUrl,
95
108
  toV2Path: () => toV2Path,
96
109
  variableNameOfImageUrl: () => variableNameOfImageUrl,
97
110
  variableNameOfMediaUrl: () => variableNameOfMediaUrl,
98
111
  variableRunHint: () => variableRunHint,
99
- variableRunLabel: () => variableRunLabel
112
+ variableRunLabel: () => variableRunLabel,
113
+ withRunOrganization: () => withRunOrganization
100
114
  });
101
115
  module.exports = __toCommonJS(index_exports);
102
116
 
@@ -1369,136 +1383,6 @@ async function requestStream(transport, path, options) {
1369
1383
  return response;
1370
1384
  }
1371
1385
 
1372
- // matrx/run.ts
1373
- async function streamCall(transport, path, body, options) {
1374
- const response = await requestStream(transport, path, {
1375
- method: "POST",
1376
- // This client IS the streaming path — `stream: true` always, last so a
1377
- // caller-supplied value can never flip the response off NDJSON.
1378
- body: { ...body, stream: true },
1379
- ...options.signal ? { signal: options.signal } : {}
1380
- });
1381
- return toRunHandle(response, options);
1382
- }
1383
- function startAgentRun(transport, agentId, request, options = {}) {
1384
- return streamCall(
1385
- transport,
1386
- `/ai/agents/${encodePathSegment(agentId)}`,
1387
- request,
1388
- options
1389
- );
1390
- }
1391
- function startMandateRun(transport, mandateKey, request, options = {}) {
1392
- return streamCall(
1393
- transport,
1394
- `/ai/mandates/${encodePathSegment(mandateKey)}`,
1395
- request,
1396
- options
1397
- );
1398
- }
1399
- function continueAgentConversation(transport, conversationId, request, options = {}) {
1400
- return streamCall(
1401
- transport,
1402
- `/ai/conversations/${encodePathSegment(conversationId)}`,
1403
- request,
1404
- options
1405
- );
1406
- }
1407
- function resumeAgentConversation(transport, conversationId, request = {}, options = {}) {
1408
- return streamCall(
1409
- transport,
1410
- `/ai/conversations/${encodePathSegment(conversationId)}/resume`,
1411
- request,
1412
- options
1413
- );
1414
- }
1415
- function cancelAgentRun(transport, requestId, options = {}) {
1416
- const query = buildQuery(
1417
- options.mode === "interrupt" ? { mode: "interrupt" } : {}
1418
- );
1419
- return requestJson(
1420
- transport,
1421
- `/ai/cancel/${encodePathSegment(requestId)}${query}`,
1422
- {
1423
- method: "POST",
1424
- ...options.signal ? { signal: options.signal } : {}
1425
- }
1426
- );
1427
- }
1428
- var MatrxRunError = class extends Error {
1429
- name = "MatrxRunError";
1430
- /** The verbatim `error` event payload, when one fired. */
1431
- errorPayload;
1432
- /** The `user_request` completion status (`"failed"` | `"cancelled"`), when that was the trigger. */
1433
- completionStatus;
1434
- /** Text streamed before the failure — partial content never vanishes. */
1435
- partialText;
1436
- constructor(args) {
1437
- super(args.message);
1438
- this.errorPayload = args.errorPayload ?? null;
1439
- this.completionStatus = args.completionStatus ?? null;
1440
- this.partialText = args.partialText ?? "";
1441
- }
1442
- };
1443
- function isRecord4(value) {
1444
- return typeof value === "object" && value !== null && !Array.isArray(value);
1445
- }
1446
- function stringField(value, key) {
1447
- if (!isRecord4(value)) return null;
1448
- const field = value[key];
1449
- return typeof field === "string" && field ? field : null;
1450
- }
1451
- async function runAgentToCompletion(transport, agentId, request, options = {}) {
1452
- const handle = await startAgentRun(transport, agentId, request, options);
1453
- let text = "";
1454
- let completion = null;
1455
- let failure = null;
1456
- for await (const envelope of handle.events) {
1457
- options.onEvent?.(envelope);
1458
- if (envelope.event === "chunk") {
1459
- const chunk = stringField(envelope.data, "text");
1460
- if (chunk !== null) {
1461
- text += chunk;
1462
- options.onChunk?.(text);
1463
- }
1464
- continue;
1465
- }
1466
- if (envelope.event === "error" && failure === null) {
1467
- const payload = isRecord4(envelope.data) ? envelope.data : null;
1468
- failure = new MatrxRunError({
1469
- message: stringField(payload, "user_message") ?? stringField(payload, "message") ?? "The agent run failed",
1470
- errorPayload: payload,
1471
- partialText: text
1472
- });
1473
- continue;
1474
- }
1475
- if (envelope.event !== "completion" || !isRecord4(envelope.data)) continue;
1476
- if (envelope.data.operation !== "user_request") continue;
1477
- completion = envelope.data;
1478
- const status = envelope.data.status;
1479
- if ((status === "failed" || status === "cancelled") && failure === null) {
1480
- const result = isRecord4(envelope.data.result) ? envelope.data.result : null;
1481
- failure = new MatrxRunError({
1482
- message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
1483
- completionStatus: status,
1484
- partialText: text
1485
- });
1486
- }
1487
- }
1488
- if (failure) throw failure;
1489
- if (!text && completion) {
1490
- const result = completion.result;
1491
- const output = stringField(result, "output");
1492
- if (output !== null) text = output;
1493
- }
1494
- return {
1495
- text,
1496
- requestId: handle.requestId,
1497
- conversationId: handle.conversationId,
1498
- completion
1499
- };
1500
- }
1501
-
1502
1386
  // matrx/operations.ts
1503
1387
  var TERMINAL_MATRX_RUNTIME_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
1504
1388
  var RUNTIME_STATUSES = /* @__PURE__ */ new Set([
@@ -1663,6 +1547,317 @@ async function rejoinRuntimeOperation(transport, requestId, options = {}) {
1663
1547
  return toRunHandle(response, options);
1664
1548
  }
1665
1549
 
1550
+ // matrx/rejoin.ts
1551
+ var MATRX_RUN_IN_PROGRESS = "run_in_progress";
1552
+ var MATRX_RESUME_CONFLICT = "resume_conflict";
1553
+ var MATRX_LIVE_STREAM_UNAVAILABLE = "live_stream_unavailable";
1554
+ function isRecord4(value) {
1555
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1556
+ }
1557
+ function nonBlank(value) {
1558
+ return typeof value === "string" && value.trim() ? value : null;
1559
+ }
1560
+ function detailCandidates(body) {
1561
+ if (!isRecord4(body)) return [];
1562
+ const out = [];
1563
+ if (isRecord4(body.detail)) out.push(body.detail);
1564
+ if (isRecord4(body.details)) out.push(body.details);
1565
+ out.push(body);
1566
+ return out;
1567
+ }
1568
+ function statusOf(error) {
1569
+ if (!isRecord4(error) && !(error instanceof Error)) return null;
1570
+ const status = error.status;
1571
+ return typeof status === "number" ? status : null;
1572
+ }
1573
+ function bodyOf(error) {
1574
+ if (!isRecord4(error) && !(error instanceof Error)) return void 0;
1575
+ return error.serverDetail;
1576
+ }
1577
+ function readMatrxErrorCode(error) {
1578
+ for (const candidate of detailCandidates(bodyOf(error))) {
1579
+ const code = nonBlank(candidate.code);
1580
+ if (code) return code;
1581
+ }
1582
+ for (const candidate of detailCandidates(bodyOf(error))) {
1583
+ const code = nonBlank(candidate.error);
1584
+ if (code) return code;
1585
+ }
1586
+ return null;
1587
+ }
1588
+ function readLiveRunRequestId(error) {
1589
+ if (statusOf(error) !== 409) return null;
1590
+ for (const candidate of detailCandidates(bodyOf(error))) {
1591
+ if (candidate.code !== MATRX_RUN_IN_PROGRESS) continue;
1592
+ const live = nonBlank(candidate.live_request_id);
1593
+ if (live) return live.trim();
1594
+ }
1595
+ return null;
1596
+ }
1597
+ function isResumeConflict(error) {
1598
+ return statusOf(error) === 409 && readMatrxErrorCode(error) === MATRX_RESUME_CONFLICT;
1599
+ }
1600
+ function isLiveStreamUnavailable(error) {
1601
+ return statusOf(error) === 409 && readMatrxErrorCode(error) === MATRX_LIVE_STREAM_UNAVAILABLE;
1602
+ }
1603
+ function runtimeOperationRejoinPath(requestId) {
1604
+ return `/runtime/operations/${encodePathSegment(requestId)}/rejoin`;
1605
+ }
1606
+ function streamErrorText(eventOrPayload) {
1607
+ if (!isRecord4(eventOrPayload)) return null;
1608
+ const payload = typeof eventOrPayload.event === "string" && isRecord4(eventOrPayload.data) ? eventOrPayload.data : eventOrPayload;
1609
+ return nonBlank(payload.user_message) ?? nonBlank(payload.message);
1610
+ }
1611
+ async function openMatrxStream(transport, path, options = {}) {
1612
+ const response = await requestStream(transport, path, {
1613
+ method: "POST",
1614
+ ...options.body !== void 0 ? { body: options.body } : {},
1615
+ ...options.signal ? { signal: options.signal } : {}
1616
+ });
1617
+ return toRunHandle(response, options);
1618
+ }
1619
+ function withRunOrganization(transport, organizationId) {
1620
+ const orgId = requireOrganizationContext(organizationId);
1621
+ return {
1622
+ fetch: (path, init) => transport.fetch(path, {
1623
+ ...init,
1624
+ headers: { ...init.headers, "X-Organization-Id": orgId }
1625
+ })
1626
+ };
1627
+ }
1628
+ async function drain(handle, onEnvelope) {
1629
+ for await (const envelope of handle.events) onEnvelope(envelope);
1630
+ }
1631
+ async function resumeOrRejoin(transport, resumeCall, options) {
1632
+ const { onEnvelope, organizationId, onRejoin, onOperationEvent, follow, ...rest } = options;
1633
+ const bound = organizationId ? withRunOrganization(transport, organizationId) : transport;
1634
+ const streamOptions = {
1635
+ ...rest,
1636
+ ...options.signal ? { signal: options.signal } : {}
1637
+ };
1638
+ let liveRequestId;
1639
+ try {
1640
+ const handle = await resumeCall(bound, streamOptions);
1641
+ await drain(handle, onEnvelope);
1642
+ return { kind: "resumed", requestId: handle.requestId };
1643
+ } catch (error) {
1644
+ if (error instanceof MatrxApiError && isResumeConflict(error)) {
1645
+ return { kind: "resume_conflict", error };
1646
+ }
1647
+ const live = readLiveRunRequestId(error);
1648
+ if (!live) throw error;
1649
+ liveRequestId = live;
1650
+ }
1651
+ onRejoin?.(liveRequestId);
1652
+ try {
1653
+ const handle = await rejoinRuntimeOperation(bound, liveRequestId, streamOptions);
1654
+ await drain(handle, onEnvelope);
1655
+ return { kind: "rejoined", liveRequestId };
1656
+ } catch (error) {
1657
+ if (!isLiveStreamUnavailable(error)) throw error;
1658
+ }
1659
+ const statusView = await getRuntimeOperationStatus(bound, liveRequestId, {
1660
+ ...options.signal ? { signal: options.signal } : {}
1661
+ });
1662
+ const operation = statusView?.operations.find((op) => !op.is_terminal) ?? statusView?.operations[0] ?? null;
1663
+ if (!operation) {
1664
+ return {
1665
+ kind: "followed",
1666
+ liveRequestId,
1667
+ executionId: null,
1668
+ ended: false,
1669
+ status: null
1670
+ };
1671
+ }
1672
+ if (operation.is_terminal) {
1673
+ return {
1674
+ kind: "followed",
1675
+ liveRequestId,
1676
+ executionId: operation.execution_id,
1677
+ ended: true,
1678
+ status: operation.status
1679
+ };
1680
+ }
1681
+ const result = await followRuntimeOperationToEnd(bound, operation.execution_id, {
1682
+ ...follow,
1683
+ lastEventSeq: operation.last_event_seq,
1684
+ ...options.signal ? { signal: options.signal } : {},
1685
+ onEvent: (event) => onOperationEvent?.(event)
1686
+ });
1687
+ return {
1688
+ kind: "followed",
1689
+ liveRequestId,
1690
+ executionId: operation.execution_id,
1691
+ ended: result.ended,
1692
+ status: result.status
1693
+ };
1694
+ }
1695
+
1696
+ // matrx/run.ts
1697
+ async function streamCall(transport, path, body, options) {
1698
+ const response = await requestStream(transport, path, {
1699
+ method: "POST",
1700
+ // This client IS the streaming path — `stream: true` always, last so a
1701
+ // caller-supplied value can never flip the response off NDJSON.
1702
+ body: { ...body, stream: true },
1703
+ ...options.signal ? { signal: options.signal } : {}
1704
+ });
1705
+ return toRunHandle(response, options);
1706
+ }
1707
+ function startAgentRun(transport, agentId, request, options = {}) {
1708
+ return streamCall(
1709
+ transport,
1710
+ `/ai/agents/${encodePathSegment(agentId)}`,
1711
+ request,
1712
+ options
1713
+ );
1714
+ }
1715
+ function startMandateRun(transport, mandateKey, request, options = {}) {
1716
+ return streamCall(
1717
+ transport,
1718
+ `/ai/mandates/${encodePathSegment(mandateKey)}`,
1719
+ request,
1720
+ options
1721
+ );
1722
+ }
1723
+ function continueAgentConversation(transport, conversationId, request, options = {}) {
1724
+ return streamCall(
1725
+ transport,
1726
+ `/ai/conversations/${encodePathSegment(conversationId)}`,
1727
+ request,
1728
+ options
1729
+ );
1730
+ }
1731
+ function resumeAgentConversation(transport, conversationId, request = {}, options = {}) {
1732
+ return streamCall(
1733
+ transport,
1734
+ `/ai/conversations/${encodePathSegment(conversationId)}/resume`,
1735
+ request,
1736
+ options
1737
+ );
1738
+ }
1739
+ function cancelAgentRun(transport, requestId, options = {}) {
1740
+ const query = buildQuery(
1741
+ options.mode === "interrupt" ? { mode: "interrupt" } : {}
1742
+ );
1743
+ return requestJson(
1744
+ transport,
1745
+ `/ai/cancel/${encodePathSegment(requestId)}${query}`,
1746
+ {
1747
+ method: "POST",
1748
+ ...options.signal ? { signal: options.signal } : {}
1749
+ }
1750
+ );
1751
+ }
1752
+ var MatrxRunError = class extends Error {
1753
+ name = "MatrxRunError";
1754
+ /** The verbatim `error` event payload, when one fired. */
1755
+ errorPayload;
1756
+ /** The `user_request` completion status (`"failed"` | `"cancelled"`), when that was the trigger. */
1757
+ completionStatus;
1758
+ /** Text streamed before the failure — partial content never vanishes. */
1759
+ partialText;
1760
+ constructor(args) {
1761
+ super(args.message);
1762
+ this.errorPayload = args.errorPayload ?? null;
1763
+ this.completionStatus = args.completionStatus ?? null;
1764
+ this.partialText = args.partialText ?? "";
1765
+ }
1766
+ };
1767
+ function isRecord5(value) {
1768
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1769
+ }
1770
+ function stringField(value, key) {
1771
+ if (!isRecord5(value)) return null;
1772
+ const field = value[key];
1773
+ return typeof field === "string" && field ? field : null;
1774
+ }
1775
+ async function runAgentToCompletion(transport, agentId, request, options = {}) {
1776
+ const handle = await startAgentRun(transport, agentId, request, options);
1777
+ let text = "";
1778
+ let completion = null;
1779
+ let failure = null;
1780
+ for await (const envelope of handle.events) {
1781
+ options.onEvent?.(envelope);
1782
+ if (envelope.event === "chunk") {
1783
+ const chunk = stringField(envelope.data, "text");
1784
+ if (chunk !== null) {
1785
+ text += chunk;
1786
+ options.onChunk?.(text);
1787
+ }
1788
+ continue;
1789
+ }
1790
+ if (envelope.event === "error" && failure === null) {
1791
+ const payload = isRecord5(envelope.data) ? envelope.data : null;
1792
+ failure = new MatrxRunError({
1793
+ message: streamErrorText(payload) ?? "The agent run failed",
1794
+ errorPayload: payload,
1795
+ partialText: text
1796
+ });
1797
+ continue;
1798
+ }
1799
+ if (envelope.event !== "completion" || !isRecord5(envelope.data)) continue;
1800
+ if (envelope.data.operation !== "user_request") continue;
1801
+ completion = envelope.data;
1802
+ const status = envelope.data.status;
1803
+ if ((status === "failed" || status === "cancelled") && failure === null) {
1804
+ const result = isRecord5(envelope.data.result) ? envelope.data.result : null;
1805
+ failure = new MatrxRunError({
1806
+ message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
1807
+ completionStatus: status,
1808
+ partialText: text
1809
+ });
1810
+ }
1811
+ }
1812
+ if (failure) throw failure;
1813
+ if (!text && completion) {
1814
+ const result = completion.result;
1815
+ const output = stringField(result, "output");
1816
+ if (output !== null) text = output;
1817
+ }
1818
+ return {
1819
+ text,
1820
+ requestId: handle.requestId,
1821
+ conversationId: handle.conversationId,
1822
+ completion
1823
+ };
1824
+ }
1825
+
1826
+ // matrx/provider-failures.ts
1827
+ var clip = (value, max) => value.length > max ? value.slice(0, max) : value;
1828
+ function providerSessionFailureBody(failure) {
1829
+ const message = failure.message?.trim() || failure.error_type?.trim() || (failure.status_code ? `HTTP ${failure.status_code}` : "provider session failed");
1830
+ const body = {
1831
+ provider: failure.provider,
1832
+ message: clip(message, 4e3)
1833
+ };
1834
+ if (failure.model?.trim()) body.model = clip(failure.model.trim(), 200);
1835
+ if (failure.error_type?.trim()) body.error_type = clip(failure.error_type.trim(), 200);
1836
+ if (typeof failure.status_code === "number" && Number.isInteger(failure.status_code) && failure.status_code >= 100 && failure.status_code <= 599) {
1837
+ body.status_code = failure.status_code;
1838
+ }
1839
+ return body;
1840
+ }
1841
+ async function reportProviderSessionFailure(transport, failure, options = {}) {
1842
+ try {
1843
+ return await requestJson(
1844
+ transport,
1845
+ "/broker/provider-failures",
1846
+ {
1847
+ method: "POST",
1848
+ body: providerSessionFailureBody(failure),
1849
+ ...options.signal ? { signal: options.signal } : {}
1850
+ }
1851
+ );
1852
+ } catch (error) {
1853
+ console.warn(
1854
+ `[provider-failures] could not report a ${failure.provider} session failure`,
1855
+ error
1856
+ );
1857
+ return null;
1858
+ }
1859
+ }
1860
+
1666
1861
  // matrx/tools.ts
1667
1862
  function submitAgentToolResults(transport, conversationId, results, options = {}) {
1668
1863
  return requestJson(