@ai-matrx/agents 0.2.1 → 0.5.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 +62 -3
- package/README.md +68 -6
- package/dist/index.cjs +831 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +803 -50
- package/dist/index.js.map +1 -1
- package/dist/matrx/index.cjs +747 -0
- package/dist/matrx/index.cjs.map +1 -0
- package/dist/matrx/index.d.cts +691 -0
- package/dist/matrx/index.d.ts +691 -0
- package/dist/matrx/index.js +723 -0
- package/dist/matrx/index.js.map +1 -0
- package/dist/projection/request.cjs +1 -1
- package/dist/projection/request.cjs.map +1 -1
- package/dist/projection/request.js +1 -1
- package/dist/projection/request.js.map +1 -1
- package/dist/projection/workflow.cjs +145 -18
- package/dist/projection/workflow.cjs.map +1 -1
- package/dist/projection/workflow.d.cts +18 -1
- package/dist/projection/workflow.d.ts +18 -1
- package/dist/projection/workflow.js +145 -19
- package/dist/projection/workflow.js.map +1 -1
- package/dist/stream/ndjson.cjs +143 -30
- package/dist/stream/ndjson.cjs.map +1 -1
- package/dist/stream/ndjson.d.cts +42 -7
- package/dist/stream/ndjson.d.ts +42 -7
- package/dist/stream/ndjson.js +142 -31
- package/dist/stream/ndjson.js.map +1 -1
- package/dist/stream/sse.cjs +69 -0
- package/dist/stream/sse.cjs.map +1 -0
- package/dist/stream/sse.d.cts +76 -0
- package/dist/stream/sse.d.ts +76 -0
- package/dist/stream/sse.js +65 -0
- package/dist/stream/sse.js.map +1 -0
- package/package.json +22 -2
package/dist/index.cjs
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// stream/ndjson.ts
|
|
4
|
+
var DEFAULT_MATRX_NDJSON_READ_AHEAD = 64;
|
|
4
5
|
function isRecord(value) {
|
|
5
6
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
7
|
}
|
|
7
8
|
function normalizeMatrxStreamEnvelope(value) {
|
|
8
9
|
if (!isRecord(value)) return null;
|
|
9
10
|
if (typeof value.event === "string") {
|
|
10
|
-
|
|
11
|
+
const streamSeq = typeof value.stream_seq === "number" && Number.isFinite(value.stream_seq) ? value.stream_seq : void 0;
|
|
12
|
+
return {
|
|
13
|
+
event: value.event,
|
|
14
|
+
data: value.data,
|
|
15
|
+
...streamSeq === void 0 ? {} : { stream_seq: streamSeq }
|
|
16
|
+
};
|
|
11
17
|
}
|
|
12
18
|
if (value.e === "c" && typeof value.t === "string") {
|
|
13
19
|
return { event: "chunk", data: { text: value.t } };
|
|
@@ -17,74 +23,179 @@ function normalizeMatrxStreamEnvelope(value) {
|
|
|
17
23
|
}
|
|
18
24
|
return null;
|
|
19
25
|
}
|
|
20
|
-
|
|
21
|
-
const queue = [];
|
|
22
|
-
let wakeConsumer = null;
|
|
23
|
-
let readerFinished = false;
|
|
24
|
-
const enqueue = (item) => {
|
|
25
|
-
queue.push(item);
|
|
26
|
-
const wake = wakeConsumer;
|
|
27
|
-
wakeConsumer = null;
|
|
28
|
-
wake?.();
|
|
29
|
-
};
|
|
30
|
-
const reader = body.getReader();
|
|
26
|
+
function createMatrxNdjsonFramer(options = {}) {
|
|
31
27
|
const decoder = new TextDecoder();
|
|
32
|
-
|
|
28
|
+
let buffer = "";
|
|
29
|
+
let lineNumber = 0;
|
|
30
|
+
let finished = false;
|
|
31
|
+
const assertOpen = () => {
|
|
32
|
+
if (finished) throw new Error("Matrx NDJSON framer is already finished");
|
|
33
|
+
};
|
|
34
|
+
const parseLine = (line, atCompletion) => {
|
|
35
|
+
const currentLineNumber = ++lineNumber;
|
|
33
36
|
const trimmed = line.trim();
|
|
34
|
-
if (!trimmed) return;
|
|
37
|
+
if (!trimmed) return null;
|
|
35
38
|
let parsed;
|
|
36
39
|
try {
|
|
37
40
|
parsed = JSON.parse(trimmed);
|
|
38
41
|
} catch (error) {
|
|
39
|
-
options.onMalformedLine?.({
|
|
40
|
-
|
|
42
|
+
options.onMalformedLine?.({
|
|
43
|
+
line: trimmed,
|
|
44
|
+
error,
|
|
45
|
+
lineNumber: currentLineNumber,
|
|
46
|
+
atCompletion
|
|
47
|
+
});
|
|
48
|
+
return null;
|
|
41
49
|
}
|
|
42
50
|
const envelope = normalizeMatrxStreamEnvelope(parsed);
|
|
43
|
-
if (envelope) {
|
|
44
|
-
enqueue({ kind: "event", value: envelope });
|
|
45
|
-
} else {
|
|
51
|
+
if (!envelope) {
|
|
46
52
|
options.onUnknownEnvelope?.(parsed);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
options.onValidEnvelope?.({
|
|
56
|
+
raw: parsed,
|
|
57
|
+
envelope,
|
|
58
|
+
line: trimmed,
|
|
59
|
+
lineNumber: currentLineNumber,
|
|
60
|
+
atCompletion
|
|
61
|
+
});
|
|
62
|
+
return envelope;
|
|
63
|
+
};
|
|
64
|
+
const pushDecodedText = (fragment) => {
|
|
65
|
+
buffer += fragment;
|
|
66
|
+
const lines = buffer.split("\n");
|
|
67
|
+
buffer = lines.pop() ?? "";
|
|
68
|
+
const envelopes = [];
|
|
69
|
+
for (const line of lines) {
|
|
70
|
+
const envelope = parseLine(line, false);
|
|
71
|
+
if (envelope) envelopes.push(envelope);
|
|
72
|
+
}
|
|
73
|
+
return envelopes;
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
pushText(fragment) {
|
|
77
|
+
assertOpen();
|
|
78
|
+
return pushDecodedText(decoder.decode() + fragment);
|
|
79
|
+
},
|
|
80
|
+
pushBytes(fragment) {
|
|
81
|
+
assertOpen();
|
|
82
|
+
return pushDecodedText(decoder.decode(fragment, { stream: true }));
|
|
83
|
+
},
|
|
84
|
+
finish() {
|
|
85
|
+
assertOpen();
|
|
86
|
+
finished = true;
|
|
87
|
+
const envelopes = pushDecodedText(decoder.decode());
|
|
88
|
+
if (buffer.length > 0) {
|
|
89
|
+
const envelope = parseLine(buffer, true);
|
|
90
|
+
buffer = "";
|
|
91
|
+
if (envelope) envelopes.push(envelope);
|
|
92
|
+
}
|
|
93
|
+
return envelopes;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function readAheadLimit(value) {
|
|
98
|
+
const limit = value ?? DEFAULT_MATRX_NDJSON_READ_AHEAD;
|
|
99
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
100
|
+
throw new RangeError("maxReadAhead must be a positive safe integer");
|
|
101
|
+
}
|
|
102
|
+
return limit;
|
|
103
|
+
}
|
|
104
|
+
async function* readMatrxNdjsonStream(body, options = {}) {
|
|
105
|
+
const maxReadAhead = readAheadLimit(options.maxReadAhead);
|
|
106
|
+
const queue = [];
|
|
107
|
+
let queuedEventCount = 0;
|
|
108
|
+
let wakeConsumer = null;
|
|
109
|
+
let wakeProducer = null;
|
|
110
|
+
let readerFinished = false;
|
|
111
|
+
let consumerClosed = false;
|
|
112
|
+
const wakeWaitingConsumer = () => {
|
|
113
|
+
const wake = wakeConsumer;
|
|
114
|
+
wakeConsumer = null;
|
|
115
|
+
wake?.();
|
|
116
|
+
};
|
|
117
|
+
const wakeWaitingProducer = () => {
|
|
118
|
+
const wake = wakeProducer;
|
|
119
|
+
wakeProducer = null;
|
|
120
|
+
wake?.();
|
|
121
|
+
};
|
|
122
|
+
const enqueueTerminal = (item) => {
|
|
123
|
+
if (consumerClosed) return;
|
|
124
|
+
queue.push(item);
|
|
125
|
+
wakeWaitingConsumer();
|
|
126
|
+
};
|
|
127
|
+
const enqueueEvent = async (value) => {
|
|
128
|
+
while (queuedEventCount >= maxReadAhead && !consumerClosed && !options.signal?.aborted) {
|
|
129
|
+
await new Promise((resolve) => {
|
|
130
|
+
wakeProducer = resolve;
|
|
131
|
+
});
|
|
47
132
|
}
|
|
133
|
+
if (consumerClosed || options.signal?.aborted) return false;
|
|
134
|
+
queue.push({ kind: "event", value });
|
|
135
|
+
queuedEventCount += 1;
|
|
136
|
+
wakeWaitingConsumer();
|
|
137
|
+
return true;
|
|
48
138
|
};
|
|
139
|
+
const waitForReadCapacity = async () => {
|
|
140
|
+
while (queuedEventCount >= maxReadAhead && !consumerClosed && !options.signal?.aborted) {
|
|
141
|
+
await new Promise((resolve) => {
|
|
142
|
+
wakeProducer = resolve;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return !consumerClosed && !options.signal?.aborted;
|
|
146
|
+
};
|
|
147
|
+
const reader = body.getReader();
|
|
148
|
+
const framer = createMatrxNdjsonFramer(options);
|
|
49
149
|
const onAbort = () => {
|
|
150
|
+
wakeWaitingProducer();
|
|
151
|
+
wakeWaitingConsumer();
|
|
50
152
|
void reader.cancel(options.signal?.reason).catch(() => void 0);
|
|
51
153
|
};
|
|
52
154
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
155
|
+
if (options.signal?.aborted) onAbort();
|
|
53
156
|
const readerPromise = (async () => {
|
|
54
|
-
let buffer = "";
|
|
55
157
|
try {
|
|
56
|
-
while (!options.signal?.aborted) {
|
|
158
|
+
while (!options.signal?.aborted && !consumerClosed) {
|
|
159
|
+
if (!await waitForReadCapacity()) return;
|
|
57
160
|
const { value, done } = await reader.read();
|
|
58
161
|
if (done) break;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
162
|
+
for (const envelope of framer.pushBytes(value)) {
|
|
163
|
+
if (!await enqueueEvent(envelope)) return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (!options.signal?.aborted && !consumerClosed) {
|
|
167
|
+
for (const envelope of framer.finish()) {
|
|
168
|
+
if (!await enqueueEvent(envelope)) return;
|
|
169
|
+
}
|
|
63
170
|
}
|
|
64
|
-
buffer += decoder.decode();
|
|
65
|
-
if (!options.signal?.aborted && buffer.trim()) parseLine(buffer);
|
|
66
171
|
} catch (error) {
|
|
67
|
-
const aborted = options.signal?.aborted || error instanceof Error && error.name === "AbortError";
|
|
68
|
-
if (!aborted)
|
|
172
|
+
const aborted = options.signal?.aborted || consumerClosed || error instanceof Error && error.name === "AbortError";
|
|
173
|
+
if (!aborted) enqueueTerminal({ kind: "error", error });
|
|
69
174
|
} finally {
|
|
70
175
|
readerFinished = true;
|
|
71
176
|
reader.releaseLock();
|
|
72
|
-
|
|
177
|
+
enqueueTerminal({ kind: "done" });
|
|
73
178
|
}
|
|
74
179
|
})();
|
|
75
180
|
try {
|
|
76
181
|
while (true) {
|
|
77
182
|
if (queue.length === 0) {
|
|
183
|
+
if (options.signal?.aborted || readerFinished) return;
|
|
78
184
|
await new Promise((resolve) => {
|
|
79
185
|
wakeConsumer = resolve;
|
|
80
186
|
});
|
|
81
187
|
}
|
|
82
188
|
const item = queue.shift();
|
|
189
|
+
if (item?.kind === "event") queuedEventCount -= 1;
|
|
190
|
+
wakeWaitingProducer();
|
|
83
191
|
if (!item || item.kind === "done") return;
|
|
84
192
|
if (item.kind === "error") throw item.error;
|
|
85
193
|
yield item.value;
|
|
86
194
|
}
|
|
87
195
|
} finally {
|
|
196
|
+
consumerClosed = true;
|
|
197
|
+
wakeWaitingProducer();
|
|
198
|
+
wakeWaitingConsumer();
|
|
88
199
|
options.signal?.removeEventListener("abort", onAbort);
|
|
89
200
|
if (!readerFinished) {
|
|
90
201
|
await reader.cancel().catch(() => void 0);
|
|
@@ -93,6 +204,68 @@ async function* readMatrxNdjsonStream(body, options = {}) {
|
|
|
93
204
|
}
|
|
94
205
|
}
|
|
95
206
|
|
|
207
|
+
// stream/sse.ts
|
|
208
|
+
var FRAME_SEPARATOR = /\r\n\r\n|\n\n|\r\r/;
|
|
209
|
+
var LINE_SEPARATOR = /\r\n|\n|\r/;
|
|
210
|
+
function parseMatrxSseFrame(frame) {
|
|
211
|
+
let event = "message";
|
|
212
|
+
let id = null;
|
|
213
|
+
const dataLines = [];
|
|
214
|
+
let sawData = false;
|
|
215
|
+
for (const line of frame.split(LINE_SEPARATOR)) {
|
|
216
|
+
if (line.startsWith(":")) continue;
|
|
217
|
+
if (line.startsWith("event:")) event = line.slice(6).trim();
|
|
218
|
+
else if (line.startsWith("data:")) {
|
|
219
|
+
sawData = true;
|
|
220
|
+
dataLines.push(line.slice(5).replace(/^ /, ""));
|
|
221
|
+
} else if (line.startsWith("id:")) id = line.slice(3).trim();
|
|
222
|
+
}
|
|
223
|
+
const seqCandidate = id !== null && id !== "" ? Number(id) : NaN;
|
|
224
|
+
const seq = Number.isSafeInteger(seqCandidate) && seqCandidate >= 0 ? seqCandidate : null;
|
|
225
|
+
return { event, id, seq, data: sawData ? dataLines.join("\n") : null };
|
|
226
|
+
}
|
|
227
|
+
function createMatrxSseFramer() {
|
|
228
|
+
let buffer = "";
|
|
229
|
+
return {
|
|
230
|
+
push(chunk) {
|
|
231
|
+
buffer += chunk;
|
|
232
|
+
const frames = [];
|
|
233
|
+
for (; ; ) {
|
|
234
|
+
const sep = FRAME_SEPARATOR.exec(buffer);
|
|
235
|
+
if (sep === null) break;
|
|
236
|
+
const frame = buffer.slice(0, sep.index);
|
|
237
|
+
buffer = buffer.slice(sep.index + sep[0].length);
|
|
238
|
+
frames.push(parseMatrxSseFrame(frame));
|
|
239
|
+
}
|
|
240
|
+
return frames;
|
|
241
|
+
},
|
|
242
|
+
flush() {
|
|
243
|
+
const rest = buffer;
|
|
244
|
+
buffer = "";
|
|
245
|
+
return { incomplete: rest.length > 0 ? rest : null };
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
async function* readMatrxSseStream(stream, options = {}) {
|
|
250
|
+
const reader = stream.getReader();
|
|
251
|
+
const decoder = new TextDecoder();
|
|
252
|
+
const framer = createMatrxSseFramer();
|
|
253
|
+
try {
|
|
254
|
+
for (; ; ) {
|
|
255
|
+
const { value, done } = await reader.read();
|
|
256
|
+
if (done) break;
|
|
257
|
+
const frames = framer.push(decoder.decode(value, { stream: true }));
|
|
258
|
+
for (const frame of frames) yield frame;
|
|
259
|
+
}
|
|
260
|
+
const tail = framer.push(decoder.decode());
|
|
261
|
+
for (const frame of tail) yield frame;
|
|
262
|
+
const { incomplete } = framer.flush();
|
|
263
|
+
if (incomplete !== null) options.onIncomplete?.(incomplete);
|
|
264
|
+
} finally {
|
|
265
|
+
reader.releaseLock();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
96
269
|
// presentation/result.ts
|
|
97
270
|
var PRIVATE_REASONING_TYPES = /* @__PURE__ */ new Set([
|
|
98
271
|
"thinking",
|
|
@@ -300,7 +473,7 @@ function projectAgentEvent(current, event) {
|
|
|
300
473
|
const status = toolStatus(lifecycle);
|
|
301
474
|
return {
|
|
302
475
|
...next,
|
|
303
|
-
status: status === "
|
|
476
|
+
status: status === "delegated" ? "awaiting-tools" : status === "completed" || status === "error" ? "streaming" : next.status,
|
|
304
477
|
tools: {
|
|
305
478
|
...current.tools,
|
|
306
479
|
[callId]: {
|
|
@@ -357,7 +530,33 @@ function projectAgentEvents(initial, events) {
|
|
|
357
530
|
}
|
|
358
531
|
|
|
359
532
|
// projection/workflow.ts
|
|
360
|
-
var
|
|
533
|
+
var DEFAULT_WORKFLOW_PROJECTION_LIMITS = {
|
|
534
|
+
maxOpenFrameSets: 32,
|
|
535
|
+
maxFramesPerBlock: 256,
|
|
536
|
+
maxBytesPerBlock: 1048576
|
|
537
|
+
};
|
|
538
|
+
function positiveSafeInteger(name, value) {
|
|
539
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
540
|
+
throw new RangeError(`${name} must be a positive safe integer`);
|
|
541
|
+
}
|
|
542
|
+
return value;
|
|
543
|
+
}
|
|
544
|
+
function resolveLimits(limits) {
|
|
545
|
+
return {
|
|
546
|
+
maxOpenFrameSets: positiveSafeInteger(
|
|
547
|
+
"maxOpenFrameSets",
|
|
548
|
+
limits?.maxOpenFrameSets ?? DEFAULT_WORKFLOW_PROJECTION_LIMITS.maxOpenFrameSets
|
|
549
|
+
),
|
|
550
|
+
maxFramesPerBlock: positiveSafeInteger(
|
|
551
|
+
"maxFramesPerBlock",
|
|
552
|
+
limits?.maxFramesPerBlock ?? DEFAULT_WORKFLOW_PROJECTION_LIMITS.maxFramesPerBlock
|
|
553
|
+
),
|
|
554
|
+
maxBytesPerBlock: positiveSafeInteger(
|
|
555
|
+
"maxBytesPerBlock",
|
|
556
|
+
limits?.maxBytesPerBlock ?? DEFAULT_WORKFLOW_PROJECTION_LIMITS.maxBytesPerBlock
|
|
557
|
+
)
|
|
558
|
+
};
|
|
559
|
+
}
|
|
361
560
|
function createWorkflowNodeProjection(input) {
|
|
362
561
|
return {
|
|
363
562
|
runId: input.runId,
|
|
@@ -368,6 +567,8 @@ function createWorkflowNodeProjection(input) {
|
|
|
368
567
|
renderBlocks: {},
|
|
369
568
|
renderBlockOrder: [],
|
|
370
569
|
openFrames: {},
|
|
570
|
+
limits: resolveLimits(input.limits),
|
|
571
|
+
lastRenderBlockIssue: null,
|
|
371
572
|
chunksReceived: 0,
|
|
372
573
|
charsStreamed: 0,
|
|
373
574
|
lastStreamingTs: null,
|
|
@@ -386,6 +587,9 @@ function asString2(value) {
|
|
|
386
587
|
function asNumber2(value) {
|
|
387
588
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
388
589
|
}
|
|
590
|
+
function utf8ByteLength(value) {
|
|
591
|
+
return new TextEncoder().encode(value).byteLength;
|
|
592
|
+
}
|
|
389
593
|
function toRenderBlock(value) {
|
|
390
594
|
const data = asRecord2(value);
|
|
391
595
|
if (!data) return null;
|
|
@@ -403,44 +607,139 @@ function toRenderBlock(value) {
|
|
|
403
607
|
metadata: asRecord2(data.metadata)
|
|
404
608
|
};
|
|
405
609
|
}
|
|
610
|
+
function withIssue(next, event, code, frameId, message, openFrames = next.openFrames) {
|
|
611
|
+
return {
|
|
612
|
+
...next,
|
|
613
|
+
openFrames,
|
|
614
|
+
lastRenderBlockIssue: {
|
|
615
|
+
code,
|
|
616
|
+
frameId,
|
|
617
|
+
streamSeq: event.stream_seq,
|
|
618
|
+
message
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
function withoutFrame(frames, frameId) {
|
|
623
|
+
if (!Object.hasOwn(frames, frameId)) return frames;
|
|
624
|
+
const next = { ...frames };
|
|
625
|
+
delete next[frameId];
|
|
626
|
+
return next;
|
|
627
|
+
}
|
|
406
628
|
function projectRenderFrame(current, event, next) {
|
|
407
629
|
const frameId = event.frame_id;
|
|
408
630
|
const frameCount = event.frame_count ?? 1;
|
|
409
631
|
const frameIndex = event.frame_index ?? 0;
|
|
410
|
-
if (!frameId || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {
|
|
411
|
-
return
|
|
632
|
+
if (!frameId || !Number.isSafeInteger(frameCount) || !Number.isSafeInteger(frameIndex) || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {
|
|
633
|
+
return withIssue(
|
|
634
|
+
next,
|
|
635
|
+
event,
|
|
636
|
+
"invalid_frame_metadata",
|
|
637
|
+
frameId ?? null,
|
|
638
|
+
"Render block frame metadata is invalid"
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
if (frameCount > current.limits.maxFramesPerBlock) {
|
|
642
|
+
return withIssue(
|
|
643
|
+
next,
|
|
644
|
+
event,
|
|
645
|
+
"frame_limit_exceeded",
|
|
646
|
+
frameId,
|
|
647
|
+
`Render block declares ${frameCount} frames; limit is ${current.limits.maxFramesPerBlock}`,
|
|
648
|
+
withoutFrame(current.openFrames, frameId)
|
|
649
|
+
);
|
|
412
650
|
}
|
|
413
651
|
const prior = current.openFrames[frameId];
|
|
652
|
+
if (prior && prior.frameCount !== frameCount) {
|
|
653
|
+
return withIssue(
|
|
654
|
+
next,
|
|
655
|
+
event,
|
|
656
|
+
"frame_count_mismatch",
|
|
657
|
+
frameId,
|
|
658
|
+
`Render block frame count changed from ${prior.frameCount} to ${frameCount}`,
|
|
659
|
+
withoutFrame(current.openFrames, frameId)
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
const priorSlice = prior?.slices[frameIndex];
|
|
663
|
+
const byteLength = (prior?.byteLength ?? 0) - (priorSlice === void 0 ? 0 : utf8ByteLength(priorSlice)) + utf8ByteLength(event.delta);
|
|
664
|
+
if (byteLength > current.limits.maxBytesPerBlock) {
|
|
665
|
+
return withIssue(
|
|
666
|
+
next,
|
|
667
|
+
event,
|
|
668
|
+
"byte_limit_exceeded",
|
|
669
|
+
frameId,
|
|
670
|
+
`Render block exceeds ${current.limits.maxBytesPerBlock} UTF-8 bytes`,
|
|
671
|
+
withoutFrame(current.openFrames, frameId)
|
|
672
|
+
);
|
|
673
|
+
}
|
|
414
674
|
const set = {
|
|
415
675
|
frameCount,
|
|
416
|
-
slices: { ...prior?.
|
|
676
|
+
slices: { ...prior?.slices ?? {}, [frameIndex]: event.delta },
|
|
677
|
+
byteLength
|
|
417
678
|
};
|
|
418
|
-
const openFrames = { ...current.openFrames
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
679
|
+
const openFrames = { ...current.openFrames };
|
|
680
|
+
let limitIssue = null;
|
|
681
|
+
if (!prior && Object.keys(openFrames).length >= current.limits.maxOpenFrameSets) {
|
|
682
|
+
const oldestFrameId = Object.keys(openFrames)[0];
|
|
683
|
+
if (oldestFrameId !== void 0) {
|
|
684
|
+
delete openFrames[oldestFrameId];
|
|
685
|
+
limitIssue = {
|
|
686
|
+
code: "open_frame_limit_exceeded",
|
|
687
|
+
frameId: oldestFrameId,
|
|
688
|
+
streamSeq: event.stream_seq,
|
|
689
|
+
message: `Evicted incomplete render block after reaching ${current.limits.maxOpenFrameSets} open frame sets`
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
openFrames[frameId] = set;
|
|
694
|
+
if (Object.keys(set.slices).length !== frameCount) {
|
|
695
|
+
return {
|
|
696
|
+
...next,
|
|
697
|
+
openFrames,
|
|
698
|
+
lastRenderBlockIssue: limitIssue ?? current.lastRenderBlockIssue
|
|
699
|
+
};
|
|
423
700
|
}
|
|
424
|
-
if (Object.keys(set.slices).length !== frameCount) return { ...next, openFrames };
|
|
425
701
|
delete openFrames[frameId];
|
|
426
|
-
|
|
702
|
+
const serialized = Array.from(
|
|
703
|
+
{ length: frameCount },
|
|
704
|
+
(_, index) => set.slices[index] ?? ""
|
|
705
|
+
).join("");
|
|
706
|
+
let parsed;
|
|
427
707
|
try {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
708
|
+
parsed = JSON.parse(serialized);
|
|
709
|
+
} catch (error) {
|
|
710
|
+
const detail = error instanceof Error ? `: ${error.message}` : "";
|
|
711
|
+
return withIssue(
|
|
712
|
+
next,
|
|
713
|
+
event,
|
|
714
|
+
"malformed_json",
|
|
715
|
+
frameId,
|
|
716
|
+
`Completed render block is not valid JSON${detail}`,
|
|
717
|
+
openFrames
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
const block = toRenderBlock(parsed);
|
|
721
|
+
if (!block) {
|
|
722
|
+
return withIssue(
|
|
723
|
+
next,
|
|
724
|
+
event,
|
|
725
|
+
"invalid_render_block",
|
|
726
|
+
frameId,
|
|
727
|
+
"Completed render block is missing blockId, blockIndex, or type",
|
|
728
|
+
openFrames
|
|
729
|
+
);
|
|
433
730
|
}
|
|
434
|
-
if (!block) return { ...next, openFrames };
|
|
435
731
|
return {
|
|
436
732
|
...next,
|
|
437
733
|
openFrames,
|
|
734
|
+
lastRenderBlockIssue: limitIssue ?? current.lastRenderBlockIssue,
|
|
438
735
|
renderBlocks: { ...current.renderBlocks, [block.blockId]: block },
|
|
439
736
|
renderBlockOrder: Object.hasOwn(current.renderBlocks, block.blockId) ? current.renderBlockOrder : [...current.renderBlockOrder, block.blockId]
|
|
440
737
|
};
|
|
441
738
|
}
|
|
442
739
|
function projectWorkflowNodeEvent(current, event) {
|
|
443
|
-
if (event.run_id !== current.runId || (event.node_id ?? "") !== current.nodeId)
|
|
740
|
+
if (event.run_id !== current.runId || (event.node_id ?? "") !== current.nodeId) {
|
|
741
|
+
return current;
|
|
742
|
+
}
|
|
444
743
|
if (event.stream_seq <= current.lastTransportSeq) return current;
|
|
445
744
|
const next = {
|
|
446
745
|
...current,
|
|
@@ -468,13 +767,496 @@ function projectWorkflowNodeEvent(current, event) {
|
|
|
468
767
|
}
|
|
469
768
|
}
|
|
470
769
|
|
|
770
|
+
// matrx/transport.ts
|
|
771
|
+
var MatrxApiError = class extends Error {
|
|
772
|
+
name = "MatrxApiError";
|
|
773
|
+
/** HTTP status of the failed response. */
|
|
774
|
+
status;
|
|
775
|
+
/** Machine code from the server body (`code`, or `detail.code`), when present. */
|
|
776
|
+
code;
|
|
777
|
+
/** The parsed server error body, verbatim (undefined when unparsable). */
|
|
778
|
+
serverDetail;
|
|
779
|
+
/** The request path the failure came from (server-relative). */
|
|
780
|
+
path;
|
|
781
|
+
constructor(args) {
|
|
782
|
+
super(
|
|
783
|
+
args.message ?? extractMatrxErrorMessage(args.serverDetail) ?? `HTTP ${args.status}`
|
|
784
|
+
);
|
|
785
|
+
this.status = args.status;
|
|
786
|
+
this.path = args.path;
|
|
787
|
+
this.serverDetail = args.serverDetail;
|
|
788
|
+
this.code = extractMatrxErrorCode(args.serverDetail);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
function isRecord3(value) {
|
|
792
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
793
|
+
}
|
|
794
|
+
function nonBlankString(value) {
|
|
795
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
796
|
+
}
|
|
797
|
+
function extractMatrxErrorMessage(serverDetail) {
|
|
798
|
+
if (!isRecord3(serverDetail)) return void 0;
|
|
799
|
+
const userMessage = nonBlankString(serverDetail.user_message);
|
|
800
|
+
if (userMessage) return userMessage;
|
|
801
|
+
const message = nonBlankString(serverDetail.message);
|
|
802
|
+
if (message) return message;
|
|
803
|
+
if (Array.isArray(serverDetail.details)) {
|
|
804
|
+
const messages = serverDetail.details.map((entry) => {
|
|
805
|
+
if (!isRecord3(entry)) return void 0;
|
|
806
|
+
const detailMessage = nonBlankString(entry.message);
|
|
807
|
+
if (!detailMessage) return void 0;
|
|
808
|
+
const field = nonBlankString(entry.field);
|
|
809
|
+
return field ? `${field}: ${detailMessage}` : detailMessage;
|
|
810
|
+
}).filter((m) => typeof m === "string");
|
|
811
|
+
if (messages.length > 0) return messages.join("; ");
|
|
812
|
+
}
|
|
813
|
+
const detail = serverDetail.detail;
|
|
814
|
+
if (isRecord3(detail)) {
|
|
815
|
+
const detailMessage = nonBlankString(detail.message) ?? nonBlankString(detail.user_message);
|
|
816
|
+
if (detailMessage) return detailMessage;
|
|
817
|
+
}
|
|
818
|
+
if (typeof detail === "string" && detail.trim()) return detail;
|
|
819
|
+
if (Array.isArray(detail)) {
|
|
820
|
+
const messages = detail.map(
|
|
821
|
+
(entry) => isRecord3(entry) ? nonBlankString(entry.msg) : void 0
|
|
822
|
+
).filter((m) => typeof m === "string");
|
|
823
|
+
if (messages.length > 0) return messages.join("; ");
|
|
824
|
+
}
|
|
825
|
+
return void 0;
|
|
826
|
+
}
|
|
827
|
+
function extractMatrxErrorCode(serverDetail) {
|
|
828
|
+
if (!isRecord3(serverDetail)) return null;
|
|
829
|
+
const topLevel = nonBlankString(serverDetail.code);
|
|
830
|
+
if (topLevel) return topLevel;
|
|
831
|
+
const detail = serverDetail.detail;
|
|
832
|
+
if (isRecord3(detail)) {
|
|
833
|
+
const nested = nonBlankString(detail.code);
|
|
834
|
+
if (nested) return nested;
|
|
835
|
+
}
|
|
836
|
+
return null;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// matrx/conversation.ts
|
|
840
|
+
function mintMatrxConversationId() {
|
|
841
|
+
return crypto.randomUUID();
|
|
842
|
+
}
|
|
843
|
+
function newStoredConversationStart(conversationId) {
|
|
844
|
+
return {
|
|
845
|
+
conversation_id: conversationId ?? mintMatrxConversationId(),
|
|
846
|
+
is_new: true,
|
|
847
|
+
store: true
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
function continueStoredConversationStart(conversationId) {
|
|
851
|
+
return { conversation_id: conversationId, is_new: false, store: true };
|
|
852
|
+
}
|
|
853
|
+
function newEphemeralConversationStart(conversationId) {
|
|
854
|
+
return {
|
|
855
|
+
conversation_id: conversationId ?? mintMatrxConversationId(),
|
|
856
|
+
is_new: true,
|
|
857
|
+
store: false
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
function continueEphemeralConversationStart(conversationId, priorMessages) {
|
|
861
|
+
return {
|
|
862
|
+
conversation_id: conversationId,
|
|
863
|
+
is_new: false,
|
|
864
|
+
store: false,
|
|
865
|
+
prior_messages: priorMessages
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// matrx/internal.ts
|
|
870
|
+
function encodePathSegment(value) {
|
|
871
|
+
return encodeURIComponent(value);
|
|
872
|
+
}
|
|
873
|
+
function buildQuery(params) {
|
|
874
|
+
const search = new URLSearchParams();
|
|
875
|
+
for (const [key, value] of Object.entries(params)) {
|
|
876
|
+
if (value === void 0) continue;
|
|
877
|
+
if (Array.isArray(value)) {
|
|
878
|
+
for (const entry of value) search.append(key, entry);
|
|
879
|
+
} else {
|
|
880
|
+
search.append(key, String(value));
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
const encoded = search.toString();
|
|
884
|
+
return encoded ? `?${encoded}` : "";
|
|
885
|
+
}
|
|
886
|
+
async function readServerDetail(response) {
|
|
887
|
+
try {
|
|
888
|
+
return await response.json();
|
|
889
|
+
} catch {
|
|
890
|
+
return void 0;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
async function throwApiError(path, response) {
|
|
894
|
+
throw new MatrxApiError({
|
|
895
|
+
status: response.status,
|
|
896
|
+
path,
|
|
897
|
+
serverDetail: await readServerDetail(response)
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
async function requestJson(transport, path, options) {
|
|
901
|
+
const hasBody = options.method !== "GET" && options.body !== void 0;
|
|
902
|
+
const response = await transport.fetch(path, {
|
|
903
|
+
method: options.method,
|
|
904
|
+
headers: hasBody ? { "Content-Type": "application/json" } : {},
|
|
905
|
+
...hasBody ? { body: JSON.stringify(options.body) } : {},
|
|
906
|
+
...options.signal ? { signal: options.signal } : {}
|
|
907
|
+
});
|
|
908
|
+
if (!response.ok) return throwApiError(path, response);
|
|
909
|
+
return await response.json();
|
|
910
|
+
}
|
|
911
|
+
function toRunHandle(response, options) {
|
|
912
|
+
return {
|
|
913
|
+
requestId: response.headers.get("X-Request-ID"),
|
|
914
|
+
conversationId: response.headers.get("X-Conversation-ID"),
|
|
915
|
+
events: readMatrxNdjsonStream(response.body, {
|
|
916
|
+
...options.signal ? { signal: options.signal } : {},
|
|
917
|
+
...options.maxReadAhead !== void 0 ? { maxReadAhead: options.maxReadAhead } : {},
|
|
918
|
+
...options.onMalformedLine ? { onMalformedLine: options.onMalformedLine } : {},
|
|
919
|
+
...options.onUnknownEnvelope ? { onUnknownEnvelope: options.onUnknownEnvelope } : {},
|
|
920
|
+
...options.onValidEnvelope ? { onValidEnvelope: options.onValidEnvelope } : {}
|
|
921
|
+
}),
|
|
922
|
+
response
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
async function requestStream(transport, path, options) {
|
|
926
|
+
const hasBody = options.method !== "GET" && options.body !== void 0;
|
|
927
|
+
const response = await transport.fetch(path, {
|
|
928
|
+
method: options.method,
|
|
929
|
+
headers: {
|
|
930
|
+
...hasBody ? { "Content-Type": "application/json" } : {},
|
|
931
|
+
...options.headers
|
|
932
|
+
},
|
|
933
|
+
...hasBody ? { body: JSON.stringify(options.body) } : {},
|
|
934
|
+
...options.signal ? { signal: options.signal } : {}
|
|
935
|
+
});
|
|
936
|
+
if (!response.ok) return throwApiError(path, response);
|
|
937
|
+
if (!response.body) {
|
|
938
|
+
throw new MatrxApiError({
|
|
939
|
+
status: response.status,
|
|
940
|
+
path,
|
|
941
|
+
serverDetail: { code: "missing_response_body" },
|
|
942
|
+
message: "The streaming response carried no body."
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
return response;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// matrx/run.ts
|
|
949
|
+
async function streamCall(transport, path, body, options) {
|
|
950
|
+
const response = await requestStream(transport, path, {
|
|
951
|
+
method: "POST",
|
|
952
|
+
// This client IS the streaming path — `stream: true` always, last so a
|
|
953
|
+
// caller-supplied value can never flip the response off NDJSON.
|
|
954
|
+
body: { ...body, stream: true },
|
|
955
|
+
...options.signal ? { signal: options.signal } : {}
|
|
956
|
+
});
|
|
957
|
+
return toRunHandle(response, options);
|
|
958
|
+
}
|
|
959
|
+
function startAgentRun(transport, agentId, request, options = {}) {
|
|
960
|
+
return streamCall(
|
|
961
|
+
transport,
|
|
962
|
+
`/ai/agents/${encodePathSegment(agentId)}`,
|
|
963
|
+
request,
|
|
964
|
+
options
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
function continueAgentConversation(transport, conversationId, request, options = {}) {
|
|
968
|
+
return streamCall(
|
|
969
|
+
transport,
|
|
970
|
+
`/ai/conversations/${encodePathSegment(conversationId)}`,
|
|
971
|
+
request,
|
|
972
|
+
options
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
function resumeAgentConversation(transport, conversationId, request = {}, options = {}) {
|
|
976
|
+
return streamCall(
|
|
977
|
+
transport,
|
|
978
|
+
`/ai/conversations/${encodePathSegment(conversationId)}/resume`,
|
|
979
|
+
request,
|
|
980
|
+
options
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
function cancelAgentRun(transport, requestId, options = {}) {
|
|
984
|
+
const query = buildQuery(
|
|
985
|
+
options.mode === "interrupt" ? { mode: "interrupt" } : {}
|
|
986
|
+
);
|
|
987
|
+
return requestJson(
|
|
988
|
+
transport,
|
|
989
|
+
`/ai/cancel/${encodePathSegment(requestId)}${query}`,
|
|
990
|
+
{
|
|
991
|
+
method: "POST",
|
|
992
|
+
...options.signal ? { signal: options.signal } : {}
|
|
993
|
+
}
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
var MatrxRunError = class extends Error {
|
|
997
|
+
name = "MatrxRunError";
|
|
998
|
+
/** The verbatim `error` event payload, when one fired. */
|
|
999
|
+
errorPayload;
|
|
1000
|
+
/** The `user_request` completion status (`"failed"` | `"cancelled"`), when that was the trigger. */
|
|
1001
|
+
completionStatus;
|
|
1002
|
+
/** Text streamed before the failure — partial content never vanishes. */
|
|
1003
|
+
partialText;
|
|
1004
|
+
constructor(args) {
|
|
1005
|
+
super(args.message);
|
|
1006
|
+
this.errorPayload = args.errorPayload ?? null;
|
|
1007
|
+
this.completionStatus = args.completionStatus ?? null;
|
|
1008
|
+
this.partialText = args.partialText ?? "";
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
function isRecord4(value) {
|
|
1012
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1013
|
+
}
|
|
1014
|
+
function stringField(value, key) {
|
|
1015
|
+
if (!isRecord4(value)) return null;
|
|
1016
|
+
const field = value[key];
|
|
1017
|
+
return typeof field === "string" && field ? field : null;
|
|
1018
|
+
}
|
|
1019
|
+
async function runAgentToCompletion(transport, agentId, request, options = {}) {
|
|
1020
|
+
const handle = await startAgentRun(transport, agentId, request, options);
|
|
1021
|
+
let text = "";
|
|
1022
|
+
let completion = null;
|
|
1023
|
+
let failure = null;
|
|
1024
|
+
for await (const envelope of handle.events) {
|
|
1025
|
+
options.onEvent?.(envelope);
|
|
1026
|
+
if (envelope.event === "chunk") {
|
|
1027
|
+
const chunk = stringField(envelope.data, "text");
|
|
1028
|
+
if (chunk !== null) {
|
|
1029
|
+
text += chunk;
|
|
1030
|
+
options.onChunk?.(text);
|
|
1031
|
+
}
|
|
1032
|
+
continue;
|
|
1033
|
+
}
|
|
1034
|
+
if (envelope.event === "error" && failure === null) {
|
|
1035
|
+
const payload = isRecord4(envelope.data) ? envelope.data : null;
|
|
1036
|
+
failure = new MatrxRunError({
|
|
1037
|
+
message: stringField(payload, "user_message") ?? stringField(payload, "message") ?? "The agent run failed",
|
|
1038
|
+
errorPayload: payload,
|
|
1039
|
+
partialText: text
|
|
1040
|
+
});
|
|
1041
|
+
continue;
|
|
1042
|
+
}
|
|
1043
|
+
if (envelope.event !== "completion" || !isRecord4(envelope.data)) continue;
|
|
1044
|
+
if (envelope.data.operation !== "user_request") continue;
|
|
1045
|
+
completion = envelope.data;
|
|
1046
|
+
const status = envelope.data.status;
|
|
1047
|
+
if ((status === "failed" || status === "cancelled") && failure === null) {
|
|
1048
|
+
const result = isRecord4(envelope.data.result) ? envelope.data.result : null;
|
|
1049
|
+
failure = new MatrxRunError({
|
|
1050
|
+
message: stringField(result, "error") ?? stringField(result, "user_message") ?? `The agent run ${status}`,
|
|
1051
|
+
completionStatus: status,
|
|
1052
|
+
partialText: text
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
if (failure) throw failure;
|
|
1057
|
+
if (!text && completion) {
|
|
1058
|
+
const result = completion.result;
|
|
1059
|
+
const output = stringField(result, "output");
|
|
1060
|
+
if (output !== null) text = output;
|
|
1061
|
+
}
|
|
1062
|
+
return {
|
|
1063
|
+
text,
|
|
1064
|
+
requestId: handle.requestId,
|
|
1065
|
+
conversationId: handle.conversationId,
|
|
1066
|
+
completion
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
// matrx/operations.ts
|
|
1071
|
+
var TERMINAL_MATRX_RUNTIME_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
1072
|
+
var RUNTIME_STATUSES = /* @__PURE__ */ new Set([
|
|
1073
|
+
"pending",
|
|
1074
|
+
"running",
|
|
1075
|
+
"paused",
|
|
1076
|
+
"waiting_input",
|
|
1077
|
+
"completed",
|
|
1078
|
+
"failed",
|
|
1079
|
+
"cancelled"
|
|
1080
|
+
]);
|
|
1081
|
+
async function getRuntimeOperationStatus(transport, requestId, options = {}) {
|
|
1082
|
+
try {
|
|
1083
|
+
return await requestJson(
|
|
1084
|
+
transport,
|
|
1085
|
+
`/runtime/operations/${encodePathSegment(requestId)}`,
|
|
1086
|
+
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1087
|
+
);
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
if (error instanceof MatrxApiError && error.status === 404) return null;
|
|
1090
|
+
throw error;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
async function getRuntimeOperationsByLink(transport, linkKind, linkId, options = {}) {
|
|
1094
|
+
const query = buildQuery(
|
|
1095
|
+
options.limit !== void 0 ? { limit: options.limit } : {}
|
|
1096
|
+
);
|
|
1097
|
+
try {
|
|
1098
|
+
return await requestJson(
|
|
1099
|
+
transport,
|
|
1100
|
+
`/runtime/operations/by-link/${encodePathSegment(linkKind)}/${encodePathSegment(linkId)}${query}`,
|
|
1101
|
+
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1102
|
+
);
|
|
1103
|
+
} catch (error) {
|
|
1104
|
+
if (error instanceof MatrxApiError && error.status === 404) return null;
|
|
1105
|
+
throw error;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
function listRuntimeOperationEvents(transport, executionId, options = {}) {
|
|
1109
|
+
const query = buildQuery({
|
|
1110
|
+
...options.afterSeq !== void 0 ? { after_seq: options.afterSeq } : {},
|
|
1111
|
+
...options.limit !== void 0 ? { limit: options.limit } : {},
|
|
1112
|
+
...options.kinds !== void 0 ? { kind: options.kinds } : {}
|
|
1113
|
+
});
|
|
1114
|
+
return requestJson(
|
|
1115
|
+
transport,
|
|
1116
|
+
`/runtime/executions/${encodePathSegment(executionId)}/events${query}`,
|
|
1117
|
+
{ method: "GET", ...options.signal ? { signal: options.signal } : {} }
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
function parseEndStatus(data) {
|
|
1121
|
+
if (data === null) return null;
|
|
1122
|
+
try {
|
|
1123
|
+
const parsed = JSON.parse(data);
|
|
1124
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.status === "string") {
|
|
1125
|
+
const status = parsed.status;
|
|
1126
|
+
return RUNTIME_STATUSES.has(status) ? status : null;
|
|
1127
|
+
}
|
|
1128
|
+
} catch {
|
|
1129
|
+
}
|
|
1130
|
+
return null;
|
|
1131
|
+
}
|
|
1132
|
+
async function* followRuntimeOperationEvents(transport, executionId, options = {}) {
|
|
1133
|
+
let cursor = options.lastEventSeq ?? 0;
|
|
1134
|
+
const headers = { Accept: "text/event-stream" };
|
|
1135
|
+
if (cursor > 0) headers["Last-Event-ID"] = String(cursor);
|
|
1136
|
+
const response = await requestStream(
|
|
1137
|
+
transport,
|
|
1138
|
+
`/runtime/executions/${encodePathSegment(executionId)}/events/stream`,
|
|
1139
|
+
{
|
|
1140
|
+
method: "GET",
|
|
1141
|
+
headers,
|
|
1142
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1143
|
+
}
|
|
1144
|
+
);
|
|
1145
|
+
const frames = readMatrxSseStream(
|
|
1146
|
+
response.body,
|
|
1147
|
+
options.onIncomplete ? { onIncomplete: options.onIncomplete } : {}
|
|
1148
|
+
);
|
|
1149
|
+
for await (const frame of frames) {
|
|
1150
|
+
if (frame.event === "end") {
|
|
1151
|
+
yield { type: "end", status: parseEndStatus(frame.data), cursor };
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
if (frame.event === "execution_event" && frame.data !== null) {
|
|
1155
|
+
let event;
|
|
1156
|
+
try {
|
|
1157
|
+
event = JSON.parse(frame.data);
|
|
1158
|
+
} catch (error) {
|
|
1159
|
+
options.onMalformedFrame?.(frame, error);
|
|
1160
|
+
yield { type: "liveness", cursor };
|
|
1161
|
+
continue;
|
|
1162
|
+
}
|
|
1163
|
+
if (frame.seq !== null && frame.seq > cursor) cursor = frame.seq;
|
|
1164
|
+
yield { type: "event", event, seq: frame.seq, cursor };
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
yield { type: "liveness", cursor };
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
async function rejoinRuntimeOperation(transport, requestId, options = {}) {
|
|
1171
|
+
const response = await requestStream(
|
|
1172
|
+
transport,
|
|
1173
|
+
`/runtime/operations/${encodePathSegment(requestId)}/rejoin`,
|
|
1174
|
+
{
|
|
1175
|
+
method: "POST",
|
|
1176
|
+
// The route takes no body model; the reference client posts an empty
|
|
1177
|
+
// JSON object. Match it so proxies see an ordinary JSON POST.
|
|
1178
|
+
body: {},
|
|
1179
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1180
|
+
}
|
|
1181
|
+
);
|
|
1182
|
+
return toRunHandle(response, options);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
// matrx/tools.ts
|
|
1186
|
+
function submitAgentToolResults(transport, conversationId, results, options = {}) {
|
|
1187
|
+
return requestJson(
|
|
1188
|
+
transport,
|
|
1189
|
+
`/ai/conversations/${encodePathSegment(conversationId)}/tool_results`,
|
|
1190
|
+
{
|
|
1191
|
+
method: "POST",
|
|
1192
|
+
body: {
|
|
1193
|
+
results,
|
|
1194
|
+
...options.instanceId !== void 0 ? { instance_id: options.instanceId } : {}
|
|
1195
|
+
},
|
|
1196
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1197
|
+
}
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
function listConversationPendingToolCalls(transport, conversationId, options = {}) {
|
|
1201
|
+
return requestJson(
|
|
1202
|
+
transport,
|
|
1203
|
+
`/ai/conversations/${encodePathSegment(conversationId)}/pending_calls`,
|
|
1204
|
+
{
|
|
1205
|
+
method: "GET",
|
|
1206
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1207
|
+
}
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
function listUserPendingToolCalls(transport, options = {}) {
|
|
1211
|
+
const query = buildQuery(
|
|
1212
|
+
options.instanceId !== void 0 ? { instance_id: options.instanceId } : {}
|
|
1213
|
+
);
|
|
1214
|
+
return requestJson(
|
|
1215
|
+
transport,
|
|
1216
|
+
`/ai/user/pending_calls${query}`,
|
|
1217
|
+
{
|
|
1218
|
+
method: "GET",
|
|
1219
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1220
|
+
}
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
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;
|
|
471
1233
|
exports.createAgentRequestProjection = createAgentRequestProjection;
|
|
1234
|
+
exports.createMatrxNdjsonFramer = createMatrxNdjsonFramer;
|
|
1235
|
+
exports.createMatrxSseFramer = createMatrxSseFramer;
|
|
472
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;
|
|
473
1248
|
exports.normalizeMatrxStreamEnvelope = normalizeMatrxStreamEnvelope;
|
|
1249
|
+
exports.parseMatrxSseFrame = parseMatrxSseFrame;
|
|
474
1250
|
exports.projectAgentEvent = projectAgentEvent;
|
|
475
1251
|
exports.projectAgentEvents = projectAgentEvents;
|
|
476
1252
|
exports.projectAgentResultForDisplay = projectAgentResultForDisplay;
|
|
477
1253
|
exports.projectWorkflowNodeEvent = projectWorkflowNodeEvent;
|
|
478
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;
|
|
479
1261
|
//# sourceMappingURL=index.cjs.map
|
|
480
1262
|
//# sourceMappingURL=index.cjs.map
|