@ai-matrx/agents 0.2.0 → 0.3.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 +27 -0
- package/README.md +46 -5
- package/dist/index.cjs +385 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +381 -32
- package/dist/index.js.map +1 -1
- 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 +245 -0
- package/dist/projection/workflow.cjs.map +1 -0
- package/dist/projection/workflow.d.cts +61 -0
- package/dist/projection/workflow.d.ts +61 -0
- package/dist/projection/workflow.js +241 -0
- package/dist/projection/workflow.js.map +1 -0
- 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/package.json +11 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
// stream/ndjson.ts
|
|
2
|
+
var DEFAULT_MATRX_NDJSON_READ_AHEAD = 64;
|
|
2
3
|
function isRecord(value) {
|
|
3
4
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
5
|
}
|
|
5
6
|
function normalizeMatrxStreamEnvelope(value) {
|
|
6
7
|
if (!isRecord(value)) return null;
|
|
7
8
|
if (typeof value.event === "string") {
|
|
8
|
-
|
|
9
|
+
const streamSeq = typeof value.stream_seq === "number" && Number.isFinite(value.stream_seq) ? value.stream_seq : void 0;
|
|
10
|
+
return {
|
|
11
|
+
event: value.event,
|
|
12
|
+
data: value.data,
|
|
13
|
+
...streamSeq === void 0 ? {} : { stream_seq: streamSeq }
|
|
14
|
+
};
|
|
9
15
|
}
|
|
10
16
|
if (value.e === "c" && typeof value.t === "string") {
|
|
11
17
|
return { event: "chunk", data: { text: value.t } };
|
|
@@ -15,74 +21,179 @@ function normalizeMatrxStreamEnvelope(value) {
|
|
|
15
21
|
}
|
|
16
22
|
return null;
|
|
17
23
|
}
|
|
18
|
-
|
|
19
|
-
const queue = [];
|
|
20
|
-
let wakeConsumer = null;
|
|
21
|
-
let readerFinished = false;
|
|
22
|
-
const enqueue = (item) => {
|
|
23
|
-
queue.push(item);
|
|
24
|
-
const wake = wakeConsumer;
|
|
25
|
-
wakeConsumer = null;
|
|
26
|
-
wake?.();
|
|
27
|
-
};
|
|
28
|
-
const reader = body.getReader();
|
|
24
|
+
function createMatrxNdjsonFramer(options = {}) {
|
|
29
25
|
const decoder = new TextDecoder();
|
|
30
|
-
|
|
26
|
+
let buffer = "";
|
|
27
|
+
let lineNumber = 0;
|
|
28
|
+
let finished = false;
|
|
29
|
+
const assertOpen = () => {
|
|
30
|
+
if (finished) throw new Error("Matrx NDJSON framer is already finished");
|
|
31
|
+
};
|
|
32
|
+
const parseLine = (line, atCompletion) => {
|
|
33
|
+
const currentLineNumber = ++lineNumber;
|
|
31
34
|
const trimmed = line.trim();
|
|
32
|
-
if (!trimmed) return;
|
|
35
|
+
if (!trimmed) return null;
|
|
33
36
|
let parsed;
|
|
34
37
|
try {
|
|
35
38
|
parsed = JSON.parse(trimmed);
|
|
36
39
|
} catch (error) {
|
|
37
|
-
options.onMalformedLine?.({
|
|
38
|
-
|
|
40
|
+
options.onMalformedLine?.({
|
|
41
|
+
line: trimmed,
|
|
42
|
+
error,
|
|
43
|
+
lineNumber: currentLineNumber,
|
|
44
|
+
atCompletion
|
|
45
|
+
});
|
|
46
|
+
return null;
|
|
39
47
|
}
|
|
40
48
|
const envelope = normalizeMatrxStreamEnvelope(parsed);
|
|
41
|
-
if (envelope) {
|
|
42
|
-
enqueue({ kind: "event", value: envelope });
|
|
43
|
-
} else {
|
|
49
|
+
if (!envelope) {
|
|
44
50
|
options.onUnknownEnvelope?.(parsed);
|
|
51
|
+
return null;
|
|
45
52
|
}
|
|
53
|
+
options.onValidEnvelope?.({
|
|
54
|
+
raw: parsed,
|
|
55
|
+
envelope,
|
|
56
|
+
line: trimmed,
|
|
57
|
+
lineNumber: currentLineNumber,
|
|
58
|
+
atCompletion
|
|
59
|
+
});
|
|
60
|
+
return envelope;
|
|
46
61
|
};
|
|
62
|
+
const pushDecodedText = (fragment) => {
|
|
63
|
+
buffer += fragment;
|
|
64
|
+
const lines = buffer.split("\n");
|
|
65
|
+
buffer = lines.pop() ?? "";
|
|
66
|
+
const envelopes = [];
|
|
67
|
+
for (const line of lines) {
|
|
68
|
+
const envelope = parseLine(line, false);
|
|
69
|
+
if (envelope) envelopes.push(envelope);
|
|
70
|
+
}
|
|
71
|
+
return envelopes;
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
pushText(fragment) {
|
|
75
|
+
assertOpen();
|
|
76
|
+
return pushDecodedText(decoder.decode() + fragment);
|
|
77
|
+
},
|
|
78
|
+
pushBytes(fragment) {
|
|
79
|
+
assertOpen();
|
|
80
|
+
return pushDecodedText(decoder.decode(fragment, { stream: true }));
|
|
81
|
+
},
|
|
82
|
+
finish() {
|
|
83
|
+
assertOpen();
|
|
84
|
+
finished = true;
|
|
85
|
+
const envelopes = pushDecodedText(decoder.decode());
|
|
86
|
+
if (buffer.length > 0) {
|
|
87
|
+
const envelope = parseLine(buffer, true);
|
|
88
|
+
buffer = "";
|
|
89
|
+
if (envelope) envelopes.push(envelope);
|
|
90
|
+
}
|
|
91
|
+
return envelopes;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function readAheadLimit(value) {
|
|
96
|
+
const limit = value ?? DEFAULT_MATRX_NDJSON_READ_AHEAD;
|
|
97
|
+
if (!Number.isSafeInteger(limit) || limit < 1) {
|
|
98
|
+
throw new RangeError("maxReadAhead must be a positive safe integer");
|
|
99
|
+
}
|
|
100
|
+
return limit;
|
|
101
|
+
}
|
|
102
|
+
async function* readMatrxNdjsonStream(body, options = {}) {
|
|
103
|
+
const maxReadAhead = readAheadLimit(options.maxReadAhead);
|
|
104
|
+
const queue = [];
|
|
105
|
+
let queuedEventCount = 0;
|
|
106
|
+
let wakeConsumer = null;
|
|
107
|
+
let wakeProducer = null;
|
|
108
|
+
let readerFinished = false;
|
|
109
|
+
let consumerClosed = false;
|
|
110
|
+
const wakeWaitingConsumer = () => {
|
|
111
|
+
const wake = wakeConsumer;
|
|
112
|
+
wakeConsumer = null;
|
|
113
|
+
wake?.();
|
|
114
|
+
};
|
|
115
|
+
const wakeWaitingProducer = () => {
|
|
116
|
+
const wake = wakeProducer;
|
|
117
|
+
wakeProducer = null;
|
|
118
|
+
wake?.();
|
|
119
|
+
};
|
|
120
|
+
const enqueueTerminal = (item) => {
|
|
121
|
+
if (consumerClosed) return;
|
|
122
|
+
queue.push(item);
|
|
123
|
+
wakeWaitingConsumer();
|
|
124
|
+
};
|
|
125
|
+
const enqueueEvent = async (value) => {
|
|
126
|
+
while (queuedEventCount >= maxReadAhead && !consumerClosed && !options.signal?.aborted) {
|
|
127
|
+
await new Promise((resolve) => {
|
|
128
|
+
wakeProducer = resolve;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (consumerClosed || options.signal?.aborted) return false;
|
|
132
|
+
queue.push({ kind: "event", value });
|
|
133
|
+
queuedEventCount += 1;
|
|
134
|
+
wakeWaitingConsumer();
|
|
135
|
+
return true;
|
|
136
|
+
};
|
|
137
|
+
const waitForReadCapacity = async () => {
|
|
138
|
+
while (queuedEventCount >= maxReadAhead && !consumerClosed && !options.signal?.aborted) {
|
|
139
|
+
await new Promise((resolve) => {
|
|
140
|
+
wakeProducer = resolve;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return !consumerClosed && !options.signal?.aborted;
|
|
144
|
+
};
|
|
145
|
+
const reader = body.getReader();
|
|
146
|
+
const framer = createMatrxNdjsonFramer(options);
|
|
47
147
|
const onAbort = () => {
|
|
148
|
+
wakeWaitingProducer();
|
|
149
|
+
wakeWaitingConsumer();
|
|
48
150
|
void reader.cancel(options.signal?.reason).catch(() => void 0);
|
|
49
151
|
};
|
|
50
152
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
153
|
+
if (options.signal?.aborted) onAbort();
|
|
51
154
|
const readerPromise = (async () => {
|
|
52
|
-
let buffer = "";
|
|
53
155
|
try {
|
|
54
|
-
while (!options.signal?.aborted) {
|
|
156
|
+
while (!options.signal?.aborted && !consumerClosed) {
|
|
157
|
+
if (!await waitForReadCapacity()) return;
|
|
55
158
|
const { value, done } = await reader.read();
|
|
56
159
|
if (done) break;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
160
|
+
for (const envelope of framer.pushBytes(value)) {
|
|
161
|
+
if (!await enqueueEvent(envelope)) return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!options.signal?.aborted && !consumerClosed) {
|
|
165
|
+
for (const envelope of framer.finish()) {
|
|
166
|
+
if (!await enqueueEvent(envelope)) return;
|
|
167
|
+
}
|
|
61
168
|
}
|
|
62
|
-
buffer += decoder.decode();
|
|
63
|
-
if (!options.signal?.aborted && buffer.trim()) parseLine(buffer);
|
|
64
169
|
} catch (error) {
|
|
65
|
-
const aborted = options.signal?.aborted || error instanceof Error && error.name === "AbortError";
|
|
66
|
-
if (!aborted)
|
|
170
|
+
const aborted = options.signal?.aborted || consumerClosed || error instanceof Error && error.name === "AbortError";
|
|
171
|
+
if (!aborted) enqueueTerminal({ kind: "error", error });
|
|
67
172
|
} finally {
|
|
68
173
|
readerFinished = true;
|
|
69
174
|
reader.releaseLock();
|
|
70
|
-
|
|
175
|
+
enqueueTerminal({ kind: "done" });
|
|
71
176
|
}
|
|
72
177
|
})();
|
|
73
178
|
try {
|
|
74
179
|
while (true) {
|
|
75
180
|
if (queue.length === 0) {
|
|
181
|
+
if (options.signal?.aborted || readerFinished) return;
|
|
76
182
|
await new Promise((resolve) => {
|
|
77
183
|
wakeConsumer = resolve;
|
|
78
184
|
});
|
|
79
185
|
}
|
|
80
186
|
const item = queue.shift();
|
|
187
|
+
if (item?.kind === "event") queuedEventCount -= 1;
|
|
188
|
+
wakeWaitingProducer();
|
|
81
189
|
if (!item || item.kind === "done") return;
|
|
82
190
|
if (item.kind === "error") throw item.error;
|
|
83
191
|
yield item.value;
|
|
84
192
|
}
|
|
85
193
|
} finally {
|
|
194
|
+
consumerClosed = true;
|
|
195
|
+
wakeWaitingProducer();
|
|
196
|
+
wakeWaitingConsumer();
|
|
86
197
|
options.signal?.removeEventListener("abort", onAbort);
|
|
87
198
|
if (!readerFinished) {
|
|
88
199
|
await reader.cancel().catch(() => void 0);
|
|
@@ -298,7 +409,7 @@ function projectAgentEvent(current, event) {
|
|
|
298
409
|
const status = toolStatus(lifecycle);
|
|
299
410
|
return {
|
|
300
411
|
...next,
|
|
301
|
-
status: status === "
|
|
412
|
+
status: status === "delegated" ? "awaiting-tools" : status === "completed" || status === "error" ? "streaming" : next.status,
|
|
302
413
|
tools: {
|
|
303
414
|
...current.tools,
|
|
304
415
|
[callId]: {
|
|
@@ -354,6 +465,244 @@ function projectAgentEvents(initial, events) {
|
|
|
354
465
|
return events.reduce(projectAgentEvent, initial);
|
|
355
466
|
}
|
|
356
467
|
|
|
357
|
-
|
|
468
|
+
// projection/workflow.ts
|
|
469
|
+
var DEFAULT_WORKFLOW_PROJECTION_LIMITS = {
|
|
470
|
+
maxOpenFrameSets: 32,
|
|
471
|
+
maxFramesPerBlock: 256,
|
|
472
|
+
maxBytesPerBlock: 1048576
|
|
473
|
+
};
|
|
474
|
+
function positiveSafeInteger(name, value) {
|
|
475
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
476
|
+
throw new RangeError(`${name} must be a positive safe integer`);
|
|
477
|
+
}
|
|
478
|
+
return value;
|
|
479
|
+
}
|
|
480
|
+
function resolveLimits(limits) {
|
|
481
|
+
return {
|
|
482
|
+
maxOpenFrameSets: positiveSafeInteger(
|
|
483
|
+
"maxOpenFrameSets",
|
|
484
|
+
limits?.maxOpenFrameSets ?? DEFAULT_WORKFLOW_PROJECTION_LIMITS.maxOpenFrameSets
|
|
485
|
+
),
|
|
486
|
+
maxFramesPerBlock: positiveSafeInteger(
|
|
487
|
+
"maxFramesPerBlock",
|
|
488
|
+
limits?.maxFramesPerBlock ?? DEFAULT_WORKFLOW_PROJECTION_LIMITS.maxFramesPerBlock
|
|
489
|
+
),
|
|
490
|
+
maxBytesPerBlock: positiveSafeInteger(
|
|
491
|
+
"maxBytesPerBlock",
|
|
492
|
+
limits?.maxBytesPerBlock ?? DEFAULT_WORKFLOW_PROJECTION_LIMITS.maxBytesPerBlock
|
|
493
|
+
)
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
function createWorkflowNodeProjection(input) {
|
|
497
|
+
return {
|
|
498
|
+
runId: input.runId,
|
|
499
|
+
nodeId: input.nodeId,
|
|
500
|
+
answer: "",
|
|
501
|
+
reasoning: "",
|
|
502
|
+
blockShadowed: false,
|
|
503
|
+
renderBlocks: {},
|
|
504
|
+
renderBlockOrder: [],
|
|
505
|
+
openFrames: {},
|
|
506
|
+
limits: resolveLimits(input.limits),
|
|
507
|
+
lastRenderBlockIssue: null,
|
|
508
|
+
chunksReceived: 0,
|
|
509
|
+
charsStreamed: 0,
|
|
510
|
+
lastStreamingTs: null,
|
|
511
|
+
lastPhase: null,
|
|
512
|
+
lastTool: null,
|
|
513
|
+
lastWarning: null,
|
|
514
|
+
lastTransportSeq: 0
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
function asRecord2(value) {
|
|
518
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
519
|
+
}
|
|
520
|
+
function asString2(value) {
|
|
521
|
+
return typeof value === "string" ? value : null;
|
|
522
|
+
}
|
|
523
|
+
function asNumber2(value) {
|
|
524
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
525
|
+
}
|
|
526
|
+
function utf8ByteLength(value) {
|
|
527
|
+
return new TextEncoder().encode(value).byteLength;
|
|
528
|
+
}
|
|
529
|
+
function toRenderBlock(value) {
|
|
530
|
+
const data = asRecord2(value);
|
|
531
|
+
if (!data) return null;
|
|
532
|
+
const blockId = asString2(data.blockId);
|
|
533
|
+
const blockIndex = asNumber2(data.blockIndex);
|
|
534
|
+
const type = asString2(data.type);
|
|
535
|
+
if (blockId === null || blockIndex === null || type === null) return null;
|
|
536
|
+
return {
|
|
537
|
+
blockId,
|
|
538
|
+
blockIndex,
|
|
539
|
+
type,
|
|
540
|
+
status: data.status === "complete" || data.status === "error" ? data.status : "streaming",
|
|
541
|
+
content: asString2(data.content),
|
|
542
|
+
data: asRecord2(data.data),
|
|
543
|
+
metadata: asRecord2(data.metadata)
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function withIssue(next, event, code, frameId, message, openFrames = next.openFrames) {
|
|
547
|
+
return {
|
|
548
|
+
...next,
|
|
549
|
+
openFrames,
|
|
550
|
+
lastRenderBlockIssue: {
|
|
551
|
+
code,
|
|
552
|
+
frameId,
|
|
553
|
+
streamSeq: event.stream_seq,
|
|
554
|
+
message
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
function withoutFrame(frames, frameId) {
|
|
559
|
+
if (!Object.hasOwn(frames, frameId)) return frames;
|
|
560
|
+
const next = { ...frames };
|
|
561
|
+
delete next[frameId];
|
|
562
|
+
return next;
|
|
563
|
+
}
|
|
564
|
+
function projectRenderFrame(current, event, next) {
|
|
565
|
+
const frameId = event.frame_id;
|
|
566
|
+
const frameCount = event.frame_count ?? 1;
|
|
567
|
+
const frameIndex = event.frame_index ?? 0;
|
|
568
|
+
if (!frameId || !Number.isSafeInteger(frameCount) || !Number.isSafeInteger(frameIndex) || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {
|
|
569
|
+
return withIssue(
|
|
570
|
+
next,
|
|
571
|
+
event,
|
|
572
|
+
"invalid_frame_metadata",
|
|
573
|
+
frameId ?? null,
|
|
574
|
+
"Render block frame metadata is invalid"
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
if (frameCount > current.limits.maxFramesPerBlock) {
|
|
578
|
+
return withIssue(
|
|
579
|
+
next,
|
|
580
|
+
event,
|
|
581
|
+
"frame_limit_exceeded",
|
|
582
|
+
frameId,
|
|
583
|
+
`Render block declares ${frameCount} frames; limit is ${current.limits.maxFramesPerBlock}`,
|
|
584
|
+
withoutFrame(current.openFrames, frameId)
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
const prior = current.openFrames[frameId];
|
|
588
|
+
if (prior && prior.frameCount !== frameCount) {
|
|
589
|
+
return withIssue(
|
|
590
|
+
next,
|
|
591
|
+
event,
|
|
592
|
+
"frame_count_mismatch",
|
|
593
|
+
frameId,
|
|
594
|
+
`Render block frame count changed from ${prior.frameCount} to ${frameCount}`,
|
|
595
|
+
withoutFrame(current.openFrames, frameId)
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
const priorSlice = prior?.slices[frameIndex];
|
|
599
|
+
const byteLength = (prior?.byteLength ?? 0) - (priorSlice === void 0 ? 0 : utf8ByteLength(priorSlice)) + utf8ByteLength(event.delta);
|
|
600
|
+
if (byteLength > current.limits.maxBytesPerBlock) {
|
|
601
|
+
return withIssue(
|
|
602
|
+
next,
|
|
603
|
+
event,
|
|
604
|
+
"byte_limit_exceeded",
|
|
605
|
+
frameId,
|
|
606
|
+
`Render block exceeds ${current.limits.maxBytesPerBlock} UTF-8 bytes`,
|
|
607
|
+
withoutFrame(current.openFrames, frameId)
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
const set = {
|
|
611
|
+
frameCount,
|
|
612
|
+
slices: { ...prior?.slices ?? {}, [frameIndex]: event.delta },
|
|
613
|
+
byteLength
|
|
614
|
+
};
|
|
615
|
+
const openFrames = { ...current.openFrames };
|
|
616
|
+
let limitIssue = null;
|
|
617
|
+
if (!prior && Object.keys(openFrames).length >= current.limits.maxOpenFrameSets) {
|
|
618
|
+
const oldestFrameId = Object.keys(openFrames)[0];
|
|
619
|
+
if (oldestFrameId !== void 0) {
|
|
620
|
+
delete openFrames[oldestFrameId];
|
|
621
|
+
limitIssue = {
|
|
622
|
+
code: "open_frame_limit_exceeded",
|
|
623
|
+
frameId: oldestFrameId,
|
|
624
|
+
streamSeq: event.stream_seq,
|
|
625
|
+
message: `Evicted incomplete render block after reaching ${current.limits.maxOpenFrameSets} open frame sets`
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
openFrames[frameId] = set;
|
|
630
|
+
if (Object.keys(set.slices).length !== frameCount) {
|
|
631
|
+
return {
|
|
632
|
+
...next,
|
|
633
|
+
openFrames,
|
|
634
|
+
lastRenderBlockIssue: limitIssue ?? current.lastRenderBlockIssue
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
delete openFrames[frameId];
|
|
638
|
+
const serialized = Array.from(
|
|
639
|
+
{ length: frameCount },
|
|
640
|
+
(_, index) => set.slices[index] ?? ""
|
|
641
|
+
).join("");
|
|
642
|
+
let parsed;
|
|
643
|
+
try {
|
|
644
|
+
parsed = JSON.parse(serialized);
|
|
645
|
+
} catch (error) {
|
|
646
|
+
const detail = error instanceof Error ? `: ${error.message}` : "";
|
|
647
|
+
return withIssue(
|
|
648
|
+
next,
|
|
649
|
+
event,
|
|
650
|
+
"malformed_json",
|
|
651
|
+
frameId,
|
|
652
|
+
`Completed render block is not valid JSON${detail}`,
|
|
653
|
+
openFrames
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
const block = toRenderBlock(parsed);
|
|
657
|
+
if (!block) {
|
|
658
|
+
return withIssue(
|
|
659
|
+
next,
|
|
660
|
+
event,
|
|
661
|
+
"invalid_render_block",
|
|
662
|
+
frameId,
|
|
663
|
+
"Completed render block is missing blockId, blockIndex, or type",
|
|
664
|
+
openFrames
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
...next,
|
|
669
|
+
openFrames,
|
|
670
|
+
lastRenderBlockIssue: limitIssue ?? current.lastRenderBlockIssue,
|
|
671
|
+
renderBlocks: { ...current.renderBlocks, [block.blockId]: block },
|
|
672
|
+
renderBlockOrder: Object.hasOwn(current.renderBlocks, block.blockId) ? current.renderBlockOrder : [...current.renderBlockOrder, block.blockId]
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
function projectWorkflowNodeEvent(current, event) {
|
|
676
|
+
if (event.run_id !== current.runId || (event.node_id ?? "") !== current.nodeId) {
|
|
677
|
+
return current;
|
|
678
|
+
}
|
|
679
|
+
if (event.stream_seq <= current.lastTransportSeq) return current;
|
|
680
|
+
const next = {
|
|
681
|
+
...current,
|
|
682
|
+
chunksReceived: event.chunks_received,
|
|
683
|
+
charsStreamed: event.chars_streamed,
|
|
684
|
+
lastStreamingTs: event.ts,
|
|
685
|
+
lastTransportSeq: event.stream_seq,
|
|
686
|
+
blockShadowed: current.blockShadowed || Boolean(event.block_shadowed)
|
|
687
|
+
};
|
|
688
|
+
switch (event.kind) {
|
|
689
|
+
case "chunk":
|
|
690
|
+
return { ...next, answer: current.answer + event.delta };
|
|
691
|
+
case "reasoning":
|
|
692
|
+
return { ...next, reasoning: current.reasoning + event.delta };
|
|
693
|
+
case "phase":
|
|
694
|
+
return { ...next, lastPhase: event.delta };
|
|
695
|
+
case "tool":
|
|
696
|
+
return { ...next, lastTool: event.delta };
|
|
697
|
+
case "warning":
|
|
698
|
+
return { ...next, lastWarning: event.delta };
|
|
699
|
+
case "render_block":
|
|
700
|
+
return projectRenderFrame(current, event, next);
|
|
701
|
+
default:
|
|
702
|
+
return next;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export { DEFAULT_MATRX_NDJSON_READ_AHEAD, DEFAULT_WORKFLOW_PROJECTION_LIMITS, createAgentRequestProjection, createMatrxNdjsonFramer, createWorkflowNodeProjection, normalizeMatrxStreamEnvelope, projectAgentEvent, projectAgentEvents, projectAgentResultForDisplay, projectWorkflowNodeEvent, readMatrxNdjsonStream };
|
|
358
707
|
//# sourceMappingURL=index.js.map
|
|
359
708
|
//# sourceMappingURL=index.js.map
|