@ai-matrx/agents 0.5.0 → 0.6.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 +46 -0
- package/README.md +45 -16
- package/dist/index.cjs +415 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +396 -3
- package/dist/index.js.map +1 -1
- package/dist/matrx/index.cjs +401 -26
- package/dist/matrx/index.cjs.map +1 -1
- package/dist/matrx/index.d.cts +345 -1
- package/dist/matrx/index.d.ts +345 -1
- package/dist/matrx/index.js +382 -3
- package/dist/matrx/index.js.map +1 -1
- package/dist/presentation/result.cjs +23 -4
- package/dist/presentation/result.cjs.map +1 -1
- package/dist/presentation/result.js +3 -3
- package/dist/presentation/result.js.map +1 -1
- package/dist/projection/request.cjs +25 -6
- package/dist/projection/request.cjs.map +1 -1
- package/dist/projection/request.js +5 -3
- package/dist/projection/request.js.map +1 -1
- package/dist/projection/workflow.cjs +25 -6
- package/dist/projection/workflow.cjs.map +1 -1
- package/dist/projection/workflow.js +5 -3
- package/dist/projection/workflow.js.map +1 -1
- package/dist/react/index.cjs +1038 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +540 -0
- package/dist/react/index.d.ts +540 -0
- package/dist/react/index.js +1016 -0
- package/dist/react/index.js.map +1 -0
- package/dist/stream/ndjson.cjs +26 -7
- package/dist/stream/ndjson.cjs.map +1 -1
- package/dist/stream/ndjson.js +6 -3
- package/dist/stream/ndjson.js.map +1 -1
- package/dist/stream/sse.cjs +25 -6
- package/dist/stream/sse.cjs.map +1 -1
- package/dist/stream/sse.js +5 -3
- package/dist/stream/sse.js.map +1 -1
- package/package.json +28 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 — 2026-08-30
|
|
4
|
+
|
|
5
|
+
- **The production transport moved IN** (C22 — the hard parts live in the
|
|
6
|
+
package; hosts inject only identity). `@ai-matrx/agents/matrx` now ships
|
|
7
|
+
`createMatrxTransport({ baseUrl | resolveTarget, credentials, organizationId? })`
|
|
8
|
+
with everything else defaulted to the proven production values:
|
|
9
|
+
- connect timeout 15s / total UNCAPPED (stream-safe) over
|
|
10
|
+
`@ai-matrx/data/net`'s `resilientFetch` — `@ai-matrx/data` is now an
|
|
11
|
+
ordinary dependency (sanctioned sibling dep, C23/X3);
|
|
12
|
+
- the AI API protocol-version policy (`applyAiApiVersion`, default v2, the
|
|
13
|
+
scoped covered-surface allowlist) + the loud v2 → v1 transport fallback
|
|
14
|
+
(`fetchWithMatrxProtocolFallback`) — a caller abort is never logged as a
|
|
15
|
+
downgrade;
|
|
16
|
+
- credentials read FRESH per call through `@ai-matrx/data`'s
|
|
17
|
+
`CredentialsPort` / `credentialToHeaders` (token refresh mid-run picked
|
|
18
|
+
up); resolver policy headers supported for dynamic channels;
|
|
19
|
+
- the fail-closed `X-Organization-Id` kernel
|
|
20
|
+
(`requireOrganizationContext` / `applyOrganizationContextHeader` /
|
|
21
|
+
`assertQueryOrganizationMatchesContext`, moved verbatim from
|
|
22
|
+
matrx-frontend `lib/api/organization-context.ts`) — configured lanes
|
|
23
|
+
refuse before the wire, conversation lanes send org in the body only;
|
|
24
|
+
- the ONE error classification: `normalizeMatrxError` → `MatrxCallError`
|
|
25
|
+
(structurally compatible with matrx-frontend's `ApiCallError`);
|
|
26
|
+
- a typed diagnostics seam (`onRequest` / `onError` /
|
|
27
|
+
`onProtocolDowngrade`) with `expectedErrorStatuses` suppression;
|
|
28
|
+
- policy/credential `Content-Type` is stripped defensively — the wire owns
|
|
29
|
+
it (a policy Content-Type merged over a GET SSE call corrupts the wire).
|
|
30
|
+
- **The reconnect policy moved IN**: `followRuntimeOperationToEnd` — the full
|
|
31
|
+
production replay-then-follow loop (45s stall watchdog, 60 × 2s reconnect
|
|
32
|
+
budget reset by ANY parsed frame, durable `Last-Event-ID` cursor across
|
|
33
|
+
attempts), previously hand-rolled in matrx-frontend
|
|
34
|
+
`features/agents/runtime-reconnect/api.ts`. Fix over the ported original
|
|
35
|
+
(recorded per C22): the stall watchdog now also covers the connect phase,
|
|
36
|
+
so a hanging connect can no longer wedge an attempt forever.
|
|
37
|
+
- **New `/react` entry** (client-stamped): `useAgentRun`
|
|
38
|
+
(start / continue / cancel + streamed state as the parity-proven
|
|
39
|
+
`AgentRequestProjection`) and `useFollowRuntimeOperation` (the reconnect
|
|
40
|
+
follower as a hook, production knobs typed). `react >= 18` is an optional
|
|
41
|
+
peer needed only by this entry.
|
|
42
|
+
|
|
43
|
+
## 0.5.1 — 2026-08-29
|
|
44
|
+
|
|
45
|
+
- Clarified the package boundary in the published README: `@ai-matrx/agents`
|
|
46
|
+
talks to the fully assembled AI Dream brain, while
|
|
47
|
+
`@ai-matrx/agent-engine` runs a brain the embedder assembles locally.
|
|
48
|
+
|
|
3
49
|
## 0.5.0 — 2026-08-29
|
|
4
50
|
|
|
5
51
|
- Added `@ai-matrx/agents/matrx` — the Matrx API client: run an agent
|
package/README.md
CHANGED
|
@@ -5,6 +5,10 @@ standardizes the stream wire, pure request/workflow projection, and safe
|
|
|
5
5
|
Creator-facing result boundaries without importing React, Redux, Next.js, or
|
|
6
6
|
application code.
|
|
7
7
|
|
|
8
|
+
**This package talks to the fully assembled AI Dream brain. It does not run the
|
|
9
|
+
provider/tool loop locally; use `@ai-matrx/agent-engine` when you need to run a
|
|
10
|
+
brain you assemble with your own providers, tools, persistence, and memory.**
|
|
11
|
+
|
|
8
12
|
## Install
|
|
9
13
|
|
|
10
14
|
```bash
|
|
@@ -83,25 +87,24 @@ rejected or malformed blocks are observable through `lastRenderBlockIssue`.
|
|
|
83
87
|
|
|
84
88
|
## Run an agent end-to-end (`./matrx`)
|
|
85
89
|
|
|
86
|
-
The `@ai-matrx/agents/matrx` subpath is the Matrx API client.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
The `@ai-matrx/agents/matrx` subpath is the Matrx API client. Build the
|
|
91
|
+
PRODUCTION transport from identity alone — everything else (connect/total
|
|
92
|
+
timeout policy, the v2 → v1 protocol fallback, fresh-per-call credential
|
|
93
|
+
headers, the fail-closed org header, error classification, diagnostics
|
|
94
|
+
hooks) ships in the package with the proven production defaults:
|
|
90
95
|
|
|
91
96
|
```ts
|
|
92
97
|
import {
|
|
98
|
+
createMatrxTransport,
|
|
93
99
|
newEphemeralConversationStart,
|
|
94
100
|
runAgentToCompletion,
|
|
95
|
-
type MatrxTransport,
|
|
96
101
|
} from "@ai-matrx/agents/matrx";
|
|
97
102
|
|
|
98
|
-
const transport
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}),
|
|
104
|
-
};
|
|
103
|
+
const transport = createMatrxTransport({
|
|
104
|
+
baseUrl: "https://server.app.matrxserver.com",
|
|
105
|
+
credentials: { get: async () => ({ kind: "api_key", apiKey }) }, // CredentialsPort (@ai-matrx/data)
|
|
106
|
+
organizationId: orgId, // omit for conversation-lane calls (org rides the body)
|
|
107
|
+
});
|
|
105
108
|
|
|
106
109
|
const run = await runAgentToCompletion(transport, agentId, {
|
|
107
110
|
...newEphemeralConversationStart(),
|
|
@@ -110,20 +113,46 @@ const run = await runAgentToCompletion(transport, agentId, {
|
|
|
110
113
|
}, { onChunk: (text) => render(text) });
|
|
111
114
|
```
|
|
112
115
|
|
|
116
|
+
Hosts with dynamic routing pass `resolveTarget` (fresh per call: base URL,
|
|
117
|
+
extra policy headers, channel label) instead of `baseUrl`, and can wire the
|
|
118
|
+
typed `diagnostics` seam (`onRequest` / `onError` / `onProtocolDowngrade`)
|
|
119
|
+
into their telemetry. `MatrxTransport` remains a plain fetch-shaped port, so
|
|
120
|
+
a fully custom transport still plugs in.
|
|
121
|
+
|
|
113
122
|
Lower-level pieces: `startAgentRun` / `continueAgentConversation` /
|
|
114
123
|
`resumeAgentConversation` return a `MatrxRunHandle` (`X-Request-ID` and
|
|
115
124
|
`X-Conversation-ID` before any event, plus the normalized envelope stream);
|
|
116
125
|
`cancelAgentRun` stops a run by its server request id;
|
|
117
126
|
`getRuntimeOperationStatus` / `listRuntimeOperationEvents` /
|
|
118
127
|
`followRuntimeOperationEvents` / `rejoinRuntimeOperation` are the reconnect
|
|
119
|
-
ladder
|
|
128
|
+
ladder — and `followRuntimeOperationToEnd` is the full production reconnect
|
|
129
|
+
policy over them (stall watchdog, bounded retry budget, durable
|
|
130
|
+
`Last-Event-ID` cursor, all knobs typed and defaulted);
|
|
131
|
+
`submitAgentToolResults` + pending-call discovery drive delegated
|
|
120
132
|
client tools (watch `continuation_needed` → `resumeAgentConversation`).
|
|
121
133
|
|
|
134
|
+
## React hooks (`./react`)
|
|
135
|
+
|
|
136
|
+
Client-only bindings over the same transport:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { useAgentRun } from "@ai-matrx/agents/react";
|
|
140
|
+
|
|
141
|
+
const { phase, projection, start, cancel } = useAgentRun({ transport });
|
|
142
|
+
// projection is the parity-proven AgentRequestProjection: answer, reasoning,
|
|
143
|
+
// phases, operations, tools, render blocks, completion, error.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`useFollowRuntimeOperation({ transport, executionId, onEvent })` is the
|
|
147
|
+
reconnect follower as a hook — production stall/retry/cursor policy built in.
|
|
148
|
+
|
|
122
149
|
## Runtime support
|
|
123
150
|
|
|
124
|
-
The package
|
|
125
|
-
|
|
126
|
-
|
|
151
|
+
The package targets modern browsers, browser-based desktop shells,
|
|
152
|
+
extensions, Next.js client or server modules, and Node 20+. Its one runtime
|
|
153
|
+
dependency is `@ai-matrx/data` (the shared net-resilience + credentials
|
|
154
|
+
layer); `react >= 18` is an optional peer needed only by `./react`. No entry
|
|
155
|
+
point performs work at import time.
|
|
127
156
|
|
|
128
157
|
## Development
|
|
129
158
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,79 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
DEFAULT_MATRX_NDJSON_READ_AHEAD: () => DEFAULT_MATRX_NDJSON_READ_AHEAD,
|
|
24
|
+
DEFAULT_WORKFLOW_PROJECTION_LIMITS: () => DEFAULT_WORKFLOW_PROJECTION_LIMITS,
|
|
25
|
+
MATRX_AI_API_VERSION_DEFAULT: () => MATRX_AI_API_VERSION_DEFAULT,
|
|
26
|
+
MatrxApiError: () => MatrxApiError,
|
|
27
|
+
MatrxRunError: () => MatrxRunError,
|
|
28
|
+
OrganizationContextError: () => OrganizationContextError,
|
|
29
|
+
TERMINAL_MATRX_RUNTIME_STATUSES: () => TERMINAL_MATRX_RUNTIME_STATUSES,
|
|
30
|
+
V2_COVERED_AI_PATH_TEMPLATES: () => V2_COVERED_AI_PATH_TEMPLATES,
|
|
31
|
+
applyAiApiVersion: () => applyAiApiVersion,
|
|
32
|
+
applyOrganizationContextHeader: () => applyOrganizationContextHeader,
|
|
33
|
+
assertQueryOrganizationMatchesContext: () => assertQueryOrganizationMatchesContext,
|
|
34
|
+
cancelAgentRun: () => cancelAgentRun,
|
|
35
|
+
continueAgentConversation: () => continueAgentConversation,
|
|
36
|
+
continueEphemeralConversationStart: () => continueEphemeralConversationStart,
|
|
37
|
+
continueStoredConversationStart: () => continueStoredConversationStart,
|
|
38
|
+
createAgentRequestProjection: () => createAgentRequestProjection,
|
|
39
|
+
createMatrxNdjsonFramer: () => createMatrxNdjsonFramer,
|
|
40
|
+
createMatrxSseFramer: () => createMatrxSseFramer,
|
|
41
|
+
createMatrxTransport: () => createMatrxTransport,
|
|
42
|
+
createWorkflowNodeProjection: () => createWorkflowNodeProjection,
|
|
43
|
+
extractMatrxErrorCode: () => extractMatrxErrorCode,
|
|
44
|
+
extractMatrxErrorMessage: () => extractMatrxErrorMessage,
|
|
45
|
+
fetchWithMatrxProtocolFallback: () => fetchWithMatrxProtocolFallback,
|
|
46
|
+
followRuntimeOperationEvents: () => followRuntimeOperationEvents,
|
|
47
|
+
followRuntimeOperationToEnd: () => followRuntimeOperationToEnd,
|
|
48
|
+
getRuntimeOperationStatus: () => getRuntimeOperationStatus,
|
|
49
|
+
getRuntimeOperationsByLink: () => getRuntimeOperationsByLink,
|
|
50
|
+
isCoveredAiPath: () => isCoveredAiPath,
|
|
51
|
+
isV2Path: () => isV2Path,
|
|
52
|
+
listConversationPendingToolCalls: () => listConversationPendingToolCalls,
|
|
53
|
+
listRuntimeOperationEvents: () => listRuntimeOperationEvents,
|
|
54
|
+
listUserPendingToolCalls: () => listUserPendingToolCalls,
|
|
55
|
+
mintMatrxConversationId: () => mintMatrxConversationId,
|
|
56
|
+
newEphemeralConversationStart: () => newEphemeralConversationStart,
|
|
57
|
+
newStoredConversationStart: () => newStoredConversationStart,
|
|
58
|
+
normalizeMatrxError: () => normalizeMatrxError,
|
|
59
|
+
normalizeMatrxStreamEnvelope: () => normalizeMatrxStreamEnvelope,
|
|
60
|
+
parseMatrxSseFrame: () => parseMatrxSseFrame,
|
|
61
|
+
projectAgentEvent: () => projectAgentEvent,
|
|
62
|
+
projectAgentEvents: () => projectAgentEvents,
|
|
63
|
+
projectAgentResultForDisplay: () => projectAgentResultForDisplay,
|
|
64
|
+
projectWorkflowNodeEvent: () => projectWorkflowNodeEvent,
|
|
65
|
+
readMatrxNdjsonStream: () => readMatrxNdjsonStream,
|
|
66
|
+
readMatrxSseStream: () => readMatrxSseStream,
|
|
67
|
+
rejoinRuntimeOperation: () => rejoinRuntimeOperation,
|
|
68
|
+
requireOrganizationContext: () => requireOrganizationContext,
|
|
69
|
+
resumeAgentConversation: () => resumeAgentConversation,
|
|
70
|
+
runAgentToCompletion: () => runAgentToCompletion,
|
|
71
|
+
startAgentRun: () => startAgentRun,
|
|
72
|
+
submitAgentToolResults: () => submitAgentToolResults,
|
|
73
|
+
toV1FallbackUrl: () => toV1FallbackUrl,
|
|
74
|
+
toV2Path: () => toV2Path
|
|
75
|
+
});
|
|
76
|
+
module.exports = __toCommonJS(index_exports);
|
|
2
77
|
|
|
3
78
|
// stream/ndjson.ts
|
|
4
79
|
var DEFAULT_MATRX_NDJSON_READ_AHEAD = 64;
|
|
@@ -836,6 +911,296 @@ function extractMatrxErrorCode(serverDetail) {
|
|
|
836
911
|
return null;
|
|
837
912
|
}
|
|
838
913
|
|
|
914
|
+
// matrx/client.ts
|
|
915
|
+
var import_data = require("@ai-matrx/data");
|
|
916
|
+
var import_data2 = require("@ai-matrx/data");
|
|
917
|
+
|
|
918
|
+
// matrx/org-context.ts
|
|
919
|
+
var OrganizationContextError = class extends Error {
|
|
920
|
+
code;
|
|
921
|
+
constructor(code, message) {
|
|
922
|
+
super(message);
|
|
923
|
+
this.name = "OrganizationContextError";
|
|
924
|
+
this.code = code;
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
928
|
+
function requireOrganizationContext(selectedOrganizationId, overrideOrganizationId) {
|
|
929
|
+
const candidate = overrideOrganizationId ?? selectedOrganizationId;
|
|
930
|
+
if (typeof candidate !== "string" || candidate.trim().length === 0) {
|
|
931
|
+
throw new OrganizationContextError(
|
|
932
|
+
"organization_context_required",
|
|
933
|
+
"Select an organization before sending this request."
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
const normalized = candidate.trim();
|
|
937
|
+
if (!UUID_PATTERN.test(normalized)) {
|
|
938
|
+
throw new OrganizationContextError(
|
|
939
|
+
"organization_context_invalid",
|
|
940
|
+
"The selected organization ID is invalid."
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
return normalized.toLowerCase();
|
|
944
|
+
}
|
|
945
|
+
function applyOrganizationContextHeader(headers, organizationId) {
|
|
946
|
+
const normalizedOrganizationId = requireOrganizationContext(organizationId);
|
|
947
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
948
|
+
if (name.toLowerCase() === "x-organization-id" && value.trim().toLowerCase() !== normalizedOrganizationId) {
|
|
949
|
+
throw new OrganizationContextError(
|
|
950
|
+
"organization_context_mismatch",
|
|
951
|
+
"X-Organization-Id must match the request context organization."
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
const withoutOrganizationHeader = Object.fromEntries(
|
|
956
|
+
Object.entries(headers).filter(
|
|
957
|
+
([name]) => name.toLowerCase() !== "x-organization-id"
|
|
958
|
+
)
|
|
959
|
+
);
|
|
960
|
+
return {
|
|
961
|
+
...withoutOrganizationHeader,
|
|
962
|
+
"X-Organization-Id": normalizedOrganizationId
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
function assertQueryOrganizationMatchesContext(queryParams, organizationId) {
|
|
966
|
+
if (!queryParams || queryParams.organization_id === void 0) return;
|
|
967
|
+
const queryOrganizationId = requireOrganizationContext(
|
|
968
|
+
String(queryParams.organization_id)
|
|
969
|
+
);
|
|
970
|
+
if (queryOrganizationId !== requireOrganizationContext(organizationId)) {
|
|
971
|
+
throw new OrganizationContextError(
|
|
972
|
+
"organization_context_mismatch",
|
|
973
|
+
"Query organization_id must match the request context organization."
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// matrx/protocol.ts
|
|
979
|
+
var import_net = require("@ai-matrx/data/net");
|
|
980
|
+
var MATRX_AI_API_VERSION_DEFAULT = "v2";
|
|
981
|
+
var V2_COVERED_AI_PATH_TEMPLATES = [
|
|
982
|
+
"/ai/manual",
|
|
983
|
+
"/ai/chat",
|
|
984
|
+
"/ai/agents/{agent_id}",
|
|
985
|
+
"/ai/agent/{agent_id}",
|
|
986
|
+
// singular alias — behaves identically
|
|
987
|
+
"/ai/conversations/{conversation_id}",
|
|
988
|
+
"/ai/conversation/{conversation_id}",
|
|
989
|
+
// singular alias
|
|
990
|
+
"/ai/prompts/{prompt_id}",
|
|
991
|
+
// saved-prompt execution
|
|
992
|
+
"/ai/mandates/{mandate_key}"
|
|
993
|
+
// THE MANDATE DOOR — `/v2` sibling exists (routers/v2.py)
|
|
994
|
+
];
|
|
995
|
+
function toV2Path(path) {
|
|
996
|
+
const withLead = path.startsWith("/") ? path : `/${path}`;
|
|
997
|
+
if (withLead.startsWith("/api/")) {
|
|
998
|
+
const rest = withLead.slice("/api".length);
|
|
999
|
+
return rest.startsWith("/v2/") ? withLead : `/api/v2${rest}`;
|
|
1000
|
+
}
|
|
1001
|
+
return withLead.startsWith("/v2/") ? withLead : `/v2${withLead}`;
|
|
1002
|
+
}
|
|
1003
|
+
var COVERED_INTERPOLATED_PATH = [
|
|
1004
|
+
/^(?:\/api)?\/ai\/manual$/,
|
|
1005
|
+
/^(?:\/api)?\/ai\/chat$/,
|
|
1006
|
+
/^(?:\/api)?\/ai\/agents\/[^/]+$/,
|
|
1007
|
+
/^(?:\/api)?\/ai\/agent\/[^/]+$/,
|
|
1008
|
+
/^(?:\/api)?\/ai\/conversations\/[^/]+$/,
|
|
1009
|
+
/^(?:\/api)?\/ai\/conversation\/[^/]+$/,
|
|
1010
|
+
/^(?:\/api)?\/ai\/prompts\/[^/]+$/,
|
|
1011
|
+
// `/warm` etc. deliberately don't match
|
|
1012
|
+
/^(?:\/api)?\/ai\/mandates\/[^/]+$/
|
|
1013
|
+
// the mandate door
|
|
1014
|
+
];
|
|
1015
|
+
function isCoveredAiPath(path) {
|
|
1016
|
+
return COVERED_INTERPOLATED_PATH.some((re) => re.test(path));
|
|
1017
|
+
}
|
|
1018
|
+
function isV2Path(pathOrUrl) {
|
|
1019
|
+
return /\/v2\/ai\//.test(pathOrUrl);
|
|
1020
|
+
}
|
|
1021
|
+
function toV1FallbackUrl(url) {
|
|
1022
|
+
return url.replace(/\/v2\/ai\//, "/ai/");
|
|
1023
|
+
}
|
|
1024
|
+
function applyAiApiVersion(path, version) {
|
|
1025
|
+
if (version !== "v2") return path;
|
|
1026
|
+
return isCoveredAiPath(path) ? toV2Path(path) : path;
|
|
1027
|
+
}
|
|
1028
|
+
async function fetchWithMatrxProtocolFallback(url, init, opts = {}) {
|
|
1029
|
+
const { onDowngrade, ...fetchOpts } = opts;
|
|
1030
|
+
const logDowngrade = (reason, status2) => {
|
|
1031
|
+
console.warn(
|
|
1032
|
+
`[matrx] ai_v2_downgrade \u2192 retrying on v1. v2=${url} reason=${reason}`
|
|
1033
|
+
);
|
|
1034
|
+
onDowngrade?.({ url, reason, ...status2 !== void 0 ? { status: status2 } : {} });
|
|
1035
|
+
};
|
|
1036
|
+
if (!isV2Path(url)) return (0, import_net.resilientFetch)(url, init, fetchOpts);
|
|
1037
|
+
let result;
|
|
1038
|
+
try {
|
|
1039
|
+
result = await (0, import_net.resilientFetch)(url, init, fetchOpts);
|
|
1040
|
+
} catch (err) {
|
|
1041
|
+
const isAbort = (0, import_net.isNetError)(err) && err.code === "aborted" || err instanceof Error && err.name === "AbortError";
|
|
1042
|
+
if (isAbort) throw err;
|
|
1043
|
+
logDowngrade(String(err));
|
|
1044
|
+
return (0, import_net.resilientFetch)(toV1FallbackUrl(url), init, fetchOpts);
|
|
1045
|
+
}
|
|
1046
|
+
const status = result.response.status;
|
|
1047
|
+
if (status === 404 || status === 405 || status >= 500) {
|
|
1048
|
+
logDowngrade(`HTTP ${status}`, status);
|
|
1049
|
+
return (0, import_net.resilientFetch)(toV1FallbackUrl(url), init, fetchOpts);
|
|
1050
|
+
}
|
|
1051
|
+
return result;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// matrx/client.ts
|
|
1055
|
+
function classifyStatus(status) {
|
|
1056
|
+
return status >= 400 && status < 500 ? "validation_error" : "http_error";
|
|
1057
|
+
}
|
|
1058
|
+
function normalizeMatrxError(err) {
|
|
1059
|
+
if (err instanceof MatrxApiError) {
|
|
1060
|
+
return {
|
|
1061
|
+
type: classifyStatus(err.status),
|
|
1062
|
+
message: err.message,
|
|
1063
|
+
status: err.status,
|
|
1064
|
+
serverDetail: err.serverDetail,
|
|
1065
|
+
...err.code ? { code: err.code } : {},
|
|
1066
|
+
name: err.name
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
if (err instanceof OrganizationContextError) {
|
|
1070
|
+
return {
|
|
1071
|
+
type: "validation_error",
|
|
1072
|
+
message: err.message,
|
|
1073
|
+
code: err.code,
|
|
1074
|
+
name: err.name,
|
|
1075
|
+
...err.stack !== void 0 ? { stack: err.stack } : {}
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
1079
|
+
return { type: "abort_error", message: "Request was cancelled." };
|
|
1080
|
+
}
|
|
1081
|
+
if ((0, import_data.isNetError)(err)) {
|
|
1082
|
+
if (err.code === "aborted") {
|
|
1083
|
+
return { type: "abort_error", message: err.message };
|
|
1084
|
+
}
|
|
1085
|
+
if (err.code === "http") {
|
|
1086
|
+
const status = err.status ?? 0;
|
|
1087
|
+
return { type: classifyStatus(status), message: err.message, status };
|
|
1088
|
+
}
|
|
1089
|
+
return { type: "network_error", message: err.message };
|
|
1090
|
+
}
|
|
1091
|
+
if (err instanceof Error) {
|
|
1092
|
+
const httpMatch = err.message.match(/HTTP (\d+):\s*(.*)/);
|
|
1093
|
+
if (httpMatch) {
|
|
1094
|
+
const status = parseInt(httpMatch[1], 10);
|
|
1095
|
+
return {
|
|
1096
|
+
type: classifyStatus(status),
|
|
1097
|
+
message: httpMatch[2] ?? err.message,
|
|
1098
|
+
status
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
return { type: "network_error", message: err.message };
|
|
1102
|
+
}
|
|
1103
|
+
return { type: "unknown", message: String(err ?? "Unknown error") };
|
|
1104
|
+
}
|
|
1105
|
+
var PRODUCTION_CONNECT_TIMEOUT_MS = 15e3;
|
|
1106
|
+
function stripContentType(headers) {
|
|
1107
|
+
return Object.fromEntries(
|
|
1108
|
+
Object.entries(headers).filter(
|
|
1109
|
+
([name]) => name.toLowerCase() !== "content-type"
|
|
1110
|
+
)
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
function createMatrxTransport(options) {
|
|
1114
|
+
const {
|
|
1115
|
+
baseUrl,
|
|
1116
|
+
resolveTarget,
|
|
1117
|
+
credentials,
|
|
1118
|
+
organizationId,
|
|
1119
|
+
aiApiVersion,
|
|
1120
|
+
connectTimeoutMs = PRODUCTION_CONNECT_TIMEOUT_MS,
|
|
1121
|
+
totalTimeoutMs = null,
|
|
1122
|
+
expectedErrorStatuses,
|
|
1123
|
+
diagnostics,
|
|
1124
|
+
source = "matrxTransport"
|
|
1125
|
+
} = options;
|
|
1126
|
+
if (baseUrl === void 0 === (resolveTarget === void 0)) {
|
|
1127
|
+
throw new Error(
|
|
1128
|
+
"createMatrxTransport: provide exactly one of `baseUrl` or `resolveTarget`."
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
const resolve = resolveTarget ?? (() => ({ baseUrl }));
|
|
1132
|
+
const resolveVersion = () => {
|
|
1133
|
+
if (aiApiVersion === void 0) return MATRX_AI_API_VERSION_DEFAULT;
|
|
1134
|
+
return typeof aiApiVersion === "function" ? aiApiVersion() : aiApiVersion;
|
|
1135
|
+
};
|
|
1136
|
+
const resolveOrganizationId = () => {
|
|
1137
|
+
if (organizationId === void 0) return null;
|
|
1138
|
+
const candidate = typeof organizationId === "function" ? organizationId() : organizationId;
|
|
1139
|
+
return requireOrganizationContext(candidate);
|
|
1140
|
+
};
|
|
1141
|
+
return {
|
|
1142
|
+
async fetch(path, init) {
|
|
1143
|
+
const target = resolve();
|
|
1144
|
+
const versionedPath = applyAiApiVersion(path, resolveVersion());
|
|
1145
|
+
const url = `${target.baseUrl}${versionedPath}`;
|
|
1146
|
+
const credentialHeaders = credentials ? (0, import_data2.credentialToHeaders)(await credentials.get()) : {};
|
|
1147
|
+
let headers = {
|
|
1148
|
+
...init.headers,
|
|
1149
|
+
...stripContentType(credentialHeaders),
|
|
1150
|
+
...stripContentType(target.policyHeaders ?? {})
|
|
1151
|
+
};
|
|
1152
|
+
const orgId = resolveOrganizationId();
|
|
1153
|
+
if (orgId !== null) {
|
|
1154
|
+
headers = applyOrganizationContextHeader(headers, orgId);
|
|
1155
|
+
}
|
|
1156
|
+
const info = {
|
|
1157
|
+
url,
|
|
1158
|
+
method: init.method,
|
|
1159
|
+
path,
|
|
1160
|
+
channel: target.channel ?? "default",
|
|
1161
|
+
source
|
|
1162
|
+
};
|
|
1163
|
+
diagnostics?.onRequest?.(info);
|
|
1164
|
+
let response;
|
|
1165
|
+
try {
|
|
1166
|
+
({ response } = await fetchWithMatrxProtocolFallback(
|
|
1167
|
+
url,
|
|
1168
|
+
{
|
|
1169
|
+
method: init.method,
|
|
1170
|
+
headers,
|
|
1171
|
+
...init.body !== void 0 ? { body: init.body } : {}
|
|
1172
|
+
},
|
|
1173
|
+
{
|
|
1174
|
+
...init.signal ? { signal: init.signal } : {},
|
|
1175
|
+
connectTimeoutMs,
|
|
1176
|
+
totalTimeoutMs,
|
|
1177
|
+
throwOnHttpError: false,
|
|
1178
|
+
...diagnostics?.onProtocolDowngrade ? { onDowngrade: diagnostics.onProtocolDowngrade } : {}
|
|
1179
|
+
}
|
|
1180
|
+
));
|
|
1181
|
+
} catch (err) {
|
|
1182
|
+
diagnostics?.onError?.(normalizeMatrxError(err), info);
|
|
1183
|
+
throw err;
|
|
1184
|
+
}
|
|
1185
|
+
if (!response.ok && !expectedErrorStatuses?.includes(response.status)) {
|
|
1186
|
+
const serverDetail = await response.clone().json().catch(() => void 0);
|
|
1187
|
+
const code = extractMatrxErrorCode(serverDetail);
|
|
1188
|
+
diagnostics?.onError?.(
|
|
1189
|
+
{
|
|
1190
|
+
type: classifyStatus(response.status),
|
|
1191
|
+
message: extractMatrxErrorMessage(serverDetail) ?? `HTTP ${response.status}`,
|
|
1192
|
+
status: response.status,
|
|
1193
|
+
serverDetail,
|
|
1194
|
+
...code ? { code } : {}
|
|
1195
|
+
},
|
|
1196
|
+
info
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
return response;
|
|
1200
|
+
}
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
|
|
839
1204
|
// matrx/conversation.ts
|
|
840
1205
|
function mintMatrxConversationId() {
|
|
841
1206
|
return crypto.randomUUID();
|
|
@@ -1167,6 +1532,55 @@ async function* followRuntimeOperationEvents(transport, executionId, options = {
|
|
|
1167
1532
|
yield { type: "liveness", cursor };
|
|
1168
1533
|
}
|
|
1169
1534
|
}
|
|
1535
|
+
async function followRuntimeOperationToEnd(transport, executionId, options) {
|
|
1536
|
+
const stallTimeoutMs = options.stallTimeoutMs ?? 45e3;
|
|
1537
|
+
const reconnectLimit = options.reconnectLimit ?? 60;
|
|
1538
|
+
const reconnectDelayMs = options.reconnectDelayMs ?? 2e3;
|
|
1539
|
+
const outer = options.signal;
|
|
1540
|
+
let cursor = options.lastEventSeq ?? 0;
|
|
1541
|
+
let failures = 0;
|
|
1542
|
+
while (!outer?.aborted && failures < reconnectLimit) {
|
|
1543
|
+
const attempt = new AbortController();
|
|
1544
|
+
const onOuterAbort = () => attempt.abort();
|
|
1545
|
+
outer?.addEventListener("abort", onOuterAbort, { once: true });
|
|
1546
|
+
let stallTimer = null;
|
|
1547
|
+
const armStall = () => {
|
|
1548
|
+
if (stallTimer !== null) clearTimeout(stallTimer);
|
|
1549
|
+
stallTimer = setTimeout(() => attempt.abort(), stallTimeoutMs);
|
|
1550
|
+
};
|
|
1551
|
+
try {
|
|
1552
|
+
const items = followRuntimeOperationEvents(transport, executionId, {
|
|
1553
|
+
lastEventSeq: cursor,
|
|
1554
|
+
signal: attempt.signal,
|
|
1555
|
+
...options.onMalformedFrame ? { onMalformedFrame: options.onMalformedFrame } : {}
|
|
1556
|
+
});
|
|
1557
|
+
armStall();
|
|
1558
|
+
for await (const item of items) {
|
|
1559
|
+
armStall();
|
|
1560
|
+
failures = 0;
|
|
1561
|
+
cursor = item.cursor;
|
|
1562
|
+
if (item.type === "end") {
|
|
1563
|
+
return { ended: true, status: item.status };
|
|
1564
|
+
}
|
|
1565
|
+
if (item.type === "event") {
|
|
1566
|
+
options.onEvent(item.event, item.seq);
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
failures += 1;
|
|
1570
|
+
} catch (error) {
|
|
1571
|
+
if (outer?.aborted) break;
|
|
1572
|
+
failures += 1;
|
|
1573
|
+
options.onAttemptError?.(error);
|
|
1574
|
+
} finally {
|
|
1575
|
+
if (stallTimer !== null) clearTimeout(stallTimer);
|
|
1576
|
+
outer?.removeEventListener("abort", onOuterAbort);
|
|
1577
|
+
}
|
|
1578
|
+
if (!outer?.aborted && failures < reconnectLimit) {
|
|
1579
|
+
await new Promise((r) => setTimeout(r, reconnectDelayMs));
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
return { ended: false, status: null };
|
|
1583
|
+
}
|
|
1170
1584
|
async function rejoinRuntimeOperation(transport, requestId, options = {}) {
|
|
1171
1585
|
const response = await requestStream(
|
|
1172
1586
|
transport,
|
|
@@ -1220,43 +1634,4 @@ function listUserPendingToolCalls(transport, options = {}) {
|
|
|
1220
1634
|
}
|
|
1221
1635
|
);
|
|
1222
1636
|
}
|
|
1223
|
-
|
|
1224
|
-
exports.DEFAULT_MATRX_NDJSON_READ_AHEAD = DEFAULT_MATRX_NDJSON_READ_AHEAD;
|
|
1225
|
-
exports.DEFAULT_WORKFLOW_PROJECTION_LIMITS = DEFAULT_WORKFLOW_PROJECTION_LIMITS;
|
|
1226
|
-
exports.MatrxApiError = MatrxApiError;
|
|
1227
|
-
exports.MatrxRunError = MatrxRunError;
|
|
1228
|
-
exports.TERMINAL_MATRX_RUNTIME_STATUSES = TERMINAL_MATRX_RUNTIME_STATUSES;
|
|
1229
|
-
exports.cancelAgentRun = cancelAgentRun;
|
|
1230
|
-
exports.continueAgentConversation = continueAgentConversation;
|
|
1231
|
-
exports.continueEphemeralConversationStart = continueEphemeralConversationStart;
|
|
1232
|
-
exports.continueStoredConversationStart = continueStoredConversationStart;
|
|
1233
|
-
exports.createAgentRequestProjection = createAgentRequestProjection;
|
|
1234
|
-
exports.createMatrxNdjsonFramer = createMatrxNdjsonFramer;
|
|
1235
|
-
exports.createMatrxSseFramer = createMatrxSseFramer;
|
|
1236
|
-
exports.createWorkflowNodeProjection = createWorkflowNodeProjection;
|
|
1237
|
-
exports.extractMatrxErrorCode = extractMatrxErrorCode;
|
|
1238
|
-
exports.extractMatrxErrorMessage = extractMatrxErrorMessage;
|
|
1239
|
-
exports.followRuntimeOperationEvents = followRuntimeOperationEvents;
|
|
1240
|
-
exports.getRuntimeOperationStatus = getRuntimeOperationStatus;
|
|
1241
|
-
exports.getRuntimeOperationsByLink = getRuntimeOperationsByLink;
|
|
1242
|
-
exports.listConversationPendingToolCalls = listConversationPendingToolCalls;
|
|
1243
|
-
exports.listRuntimeOperationEvents = listRuntimeOperationEvents;
|
|
1244
|
-
exports.listUserPendingToolCalls = listUserPendingToolCalls;
|
|
1245
|
-
exports.mintMatrxConversationId = mintMatrxConversationId;
|
|
1246
|
-
exports.newEphemeralConversationStart = newEphemeralConversationStart;
|
|
1247
|
-
exports.newStoredConversationStart = newStoredConversationStart;
|
|
1248
|
-
exports.normalizeMatrxStreamEnvelope = normalizeMatrxStreamEnvelope;
|
|
1249
|
-
exports.parseMatrxSseFrame = parseMatrxSseFrame;
|
|
1250
|
-
exports.projectAgentEvent = projectAgentEvent;
|
|
1251
|
-
exports.projectAgentEvents = projectAgentEvents;
|
|
1252
|
-
exports.projectAgentResultForDisplay = projectAgentResultForDisplay;
|
|
1253
|
-
exports.projectWorkflowNodeEvent = projectWorkflowNodeEvent;
|
|
1254
|
-
exports.readMatrxNdjsonStream = readMatrxNdjsonStream;
|
|
1255
|
-
exports.readMatrxSseStream = readMatrxSseStream;
|
|
1256
|
-
exports.rejoinRuntimeOperation = rejoinRuntimeOperation;
|
|
1257
|
-
exports.resumeAgentConversation = resumeAgentConversation;
|
|
1258
|
-
exports.runAgentToCompletion = runAgentToCompletion;
|
|
1259
|
-
exports.startAgentRun = startAgentRun;
|
|
1260
|
-
exports.submitAgentToolResults = submitAgentToolResults;
|
|
1261
|
-
//# sourceMappingURL=index.cjs.map
|
|
1262
1637
|
//# sourceMappingURL=index.cjs.map
|