@mastra/client-js 0.10.22-alpha.3 → 0.10.22-alpha.4
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +24 -0
- package/dist/index.cjs +502 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +502 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/agent.d.ts +11 -1
- package/dist/resources/agent.d.ts.map +1 -1
- package/dist/types.d.ts +9 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/process-mastra-stream.d.ts +7 -0
- package/dist/utils/process-mastra-stream.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/resources/agent.ts +647 -2
- package/src/types.ts +16 -1
- package/src/utils/process-mastra-stream.test.ts +353 -0
- package/src/utils/process-mastra-stream.ts +49 -0
package/dist/index.js
CHANGED
|
@@ -309,6 +309,94 @@ function parseClientRuntimeContext(runtimeContext) {
|
|
|
309
309
|
}
|
|
310
310
|
return void 0;
|
|
311
311
|
}
|
|
312
|
+
|
|
313
|
+
// src/utils/process-mastra-stream.ts
|
|
314
|
+
async function processMastraStream({
|
|
315
|
+
stream,
|
|
316
|
+
onChunk
|
|
317
|
+
}) {
|
|
318
|
+
const reader = stream.getReader();
|
|
319
|
+
const decoder = new TextDecoder();
|
|
320
|
+
let buffer = "";
|
|
321
|
+
try {
|
|
322
|
+
while (true) {
|
|
323
|
+
const { done, value } = await reader.read();
|
|
324
|
+
if (done) break;
|
|
325
|
+
buffer += decoder.decode(value, { stream: true });
|
|
326
|
+
const lines = buffer.split("\n\n");
|
|
327
|
+
buffer = lines.pop() || "";
|
|
328
|
+
for (const line of lines) {
|
|
329
|
+
if (line.startsWith("data: ")) {
|
|
330
|
+
const data = line.slice(6);
|
|
331
|
+
if (data === "[DONE]") {
|
|
332
|
+
console.log("\u{1F3C1} Stream finished");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
const json = JSON.parse(data);
|
|
337
|
+
await onChunk(json);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
console.error("\u274C JSON parse error:", error, "Data:", data);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} finally {
|
|
345
|
+
reader.releaseLock();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/resources/agent.ts
|
|
350
|
+
async function executeToolCallAndRespond({
|
|
351
|
+
response,
|
|
352
|
+
params,
|
|
353
|
+
runId,
|
|
354
|
+
resourceId,
|
|
355
|
+
threadId,
|
|
356
|
+
runtimeContext,
|
|
357
|
+
respondFn
|
|
358
|
+
}) {
|
|
359
|
+
if (response.finishReason === "tool-calls") {
|
|
360
|
+
const toolCalls = response.toolCalls;
|
|
361
|
+
if (!toolCalls || !Array.isArray(toolCalls)) {
|
|
362
|
+
return response;
|
|
363
|
+
}
|
|
364
|
+
for (const toolCall of toolCalls) {
|
|
365
|
+
const clientTool = params.clientTools?.[toolCall.toolName];
|
|
366
|
+
if (clientTool && clientTool.execute) {
|
|
367
|
+
const result = await clientTool.execute(
|
|
368
|
+
{ context: toolCall?.args, runId, resourceId, threadId, runtimeContext },
|
|
369
|
+
{
|
|
370
|
+
messages: response.messages,
|
|
371
|
+
toolCallId: toolCall?.toolCallId
|
|
372
|
+
}
|
|
373
|
+
);
|
|
374
|
+
const updatedMessages = [
|
|
375
|
+
{
|
|
376
|
+
role: "user",
|
|
377
|
+
content: params.messages
|
|
378
|
+
},
|
|
379
|
+
...response.response.messages,
|
|
380
|
+
{
|
|
381
|
+
role: "tool",
|
|
382
|
+
content: [
|
|
383
|
+
{
|
|
384
|
+
type: "tool-result",
|
|
385
|
+
toolCallId: toolCall.toolCallId,
|
|
386
|
+
toolName: toolCall.toolName,
|
|
387
|
+
result
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
];
|
|
392
|
+
return respondFn({
|
|
393
|
+
...params,
|
|
394
|
+
messages: updatedMessages
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
312
400
|
var AgentVoice = class extends BaseResource {
|
|
313
401
|
constructor(options, agentId) {
|
|
314
402
|
super(options);
|
|
@@ -435,6 +523,34 @@ var Agent = class extends BaseResource {
|
|
|
435
523
|
}
|
|
436
524
|
return response;
|
|
437
525
|
}
|
|
526
|
+
async generateVNext(params) {
|
|
527
|
+
const processedParams = {
|
|
528
|
+
...params,
|
|
529
|
+
output: params.output ? zodToJsonSchema(params.output) : void 0,
|
|
530
|
+
runtimeContext: parseClientRuntimeContext(params.runtimeContext),
|
|
531
|
+
clientTools: processClientTools(params.clientTools)
|
|
532
|
+
};
|
|
533
|
+
const { runId, resourceId, threadId, runtimeContext } = processedParams;
|
|
534
|
+
const response = await this.request(
|
|
535
|
+
`/api/agents/${this.agentId}/generate/vnext`,
|
|
536
|
+
{
|
|
537
|
+
method: "POST",
|
|
538
|
+
body: processedParams
|
|
539
|
+
}
|
|
540
|
+
);
|
|
541
|
+
if (response.finishReason === "tool-calls") {
|
|
542
|
+
return executeToolCallAndRespond({
|
|
543
|
+
response,
|
|
544
|
+
params,
|
|
545
|
+
runId,
|
|
546
|
+
resourceId,
|
|
547
|
+
threadId,
|
|
548
|
+
runtimeContext,
|
|
549
|
+
respondFn: this.generateVNext.bind(this)
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
return response;
|
|
553
|
+
}
|
|
438
554
|
async processChatResponse({
|
|
439
555
|
stream,
|
|
440
556
|
update,
|
|
@@ -725,6 +841,392 @@ var Agent = class extends BaseResource {
|
|
|
725
841
|
};
|
|
726
842
|
return streamResponse;
|
|
727
843
|
}
|
|
844
|
+
async processChatResponse_vNext({
|
|
845
|
+
stream,
|
|
846
|
+
update,
|
|
847
|
+
onToolCall,
|
|
848
|
+
onFinish,
|
|
849
|
+
getCurrentDate = () => /* @__PURE__ */ new Date(),
|
|
850
|
+
lastMessage
|
|
851
|
+
}) {
|
|
852
|
+
const replaceLastMessage = lastMessage?.role === "assistant";
|
|
853
|
+
let step = replaceLastMessage ? 1 + // find max step in existing tool invocations:
|
|
854
|
+
(lastMessage.toolInvocations?.reduce((max, toolInvocation) => {
|
|
855
|
+
return Math.max(max, toolInvocation.step ?? 0);
|
|
856
|
+
}, 0) ?? 0) : 0;
|
|
857
|
+
const message = replaceLastMessage ? structuredClone(lastMessage) : {
|
|
858
|
+
id: v4(),
|
|
859
|
+
createdAt: getCurrentDate(),
|
|
860
|
+
role: "assistant",
|
|
861
|
+
content: "",
|
|
862
|
+
parts: []
|
|
863
|
+
};
|
|
864
|
+
let currentTextPart = void 0;
|
|
865
|
+
let currentReasoningPart = void 0;
|
|
866
|
+
let currentReasoningTextDetail = void 0;
|
|
867
|
+
function updateToolInvocationPart(toolCallId, invocation) {
|
|
868
|
+
const part = message.parts.find(
|
|
869
|
+
(part2) => part2.type === "tool-invocation" && part2.toolInvocation.toolCallId === toolCallId
|
|
870
|
+
);
|
|
871
|
+
if (part != null) {
|
|
872
|
+
part.toolInvocation = invocation;
|
|
873
|
+
} else {
|
|
874
|
+
message.parts.push({
|
|
875
|
+
type: "tool-invocation",
|
|
876
|
+
toolInvocation: invocation
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
const data = [];
|
|
881
|
+
let messageAnnotations = replaceLastMessage ? lastMessage?.annotations : void 0;
|
|
882
|
+
const partialToolCalls = {};
|
|
883
|
+
let usage = {
|
|
884
|
+
completionTokens: NaN,
|
|
885
|
+
promptTokens: NaN,
|
|
886
|
+
totalTokens: NaN
|
|
887
|
+
};
|
|
888
|
+
let finishReason = "unknown";
|
|
889
|
+
function execUpdate() {
|
|
890
|
+
const copiedData = [...data];
|
|
891
|
+
if (messageAnnotations?.length) {
|
|
892
|
+
message.annotations = messageAnnotations;
|
|
893
|
+
}
|
|
894
|
+
const copiedMessage = {
|
|
895
|
+
// deep copy the message to ensure that deep changes (msg attachments) are updated
|
|
896
|
+
// with SolidJS. SolidJS uses referential integration of sub-objects to detect changes.
|
|
897
|
+
...structuredClone(message),
|
|
898
|
+
// add a revision id to ensure that the message is updated with SWR. SWR uses a
|
|
899
|
+
// hashing approach by default to detect changes, but it only works for shallow
|
|
900
|
+
// changes. This is why we need to add a revision id to ensure that the message
|
|
901
|
+
// is updated with SWR (without it, the changes get stuck in SWR and are not
|
|
902
|
+
// forwarded to rendering):
|
|
903
|
+
revisionId: v4()
|
|
904
|
+
};
|
|
905
|
+
update({
|
|
906
|
+
message: copiedMessage,
|
|
907
|
+
data: copiedData,
|
|
908
|
+
replaceLastMessage
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
await processMastraStream({
|
|
912
|
+
stream,
|
|
913
|
+
// TODO: casting as any here because the stream types were all typed as any before in core.
|
|
914
|
+
// but this is completely wrong and this fn is probably broken. Remove ":any" and you'll see a bunch of type errors
|
|
915
|
+
onChunk: async (chunk) => {
|
|
916
|
+
switch (chunk.type) {
|
|
917
|
+
case "step-start": {
|
|
918
|
+
if (!replaceLastMessage) {
|
|
919
|
+
message.id = chunk.payload.messageId;
|
|
920
|
+
}
|
|
921
|
+
message.parts.push({ type: "step-start" });
|
|
922
|
+
execUpdate();
|
|
923
|
+
break;
|
|
924
|
+
}
|
|
925
|
+
case "text-delta": {
|
|
926
|
+
if (currentTextPart == null) {
|
|
927
|
+
currentTextPart = {
|
|
928
|
+
type: "text",
|
|
929
|
+
text: chunk.payload.text
|
|
930
|
+
};
|
|
931
|
+
message.parts.push(currentTextPart);
|
|
932
|
+
} else {
|
|
933
|
+
currentTextPart.text += chunk.payload.text;
|
|
934
|
+
}
|
|
935
|
+
message.content += chunk.payload.text;
|
|
936
|
+
execUpdate();
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
case "reasoning-delta": {
|
|
940
|
+
if (currentReasoningTextDetail == null) {
|
|
941
|
+
currentReasoningTextDetail = { type: "text", text: chunk.payload.text };
|
|
942
|
+
if (currentReasoningPart != null) {
|
|
943
|
+
currentReasoningPart.details.push(currentReasoningTextDetail);
|
|
944
|
+
}
|
|
945
|
+
} else {
|
|
946
|
+
currentReasoningTextDetail.text += chunk.payload.text;
|
|
947
|
+
}
|
|
948
|
+
if (currentReasoningPart == null) {
|
|
949
|
+
currentReasoningPart = {
|
|
950
|
+
type: "reasoning",
|
|
951
|
+
reasoning: chunk.payload.text,
|
|
952
|
+
details: [currentReasoningTextDetail]
|
|
953
|
+
};
|
|
954
|
+
message.parts.push(currentReasoningPart);
|
|
955
|
+
} else {
|
|
956
|
+
currentReasoningPart.reasoning += chunk.payload.text;
|
|
957
|
+
}
|
|
958
|
+
message.reasoning = (message.reasoning ?? "") + chunk.payload.text;
|
|
959
|
+
execUpdate();
|
|
960
|
+
break;
|
|
961
|
+
}
|
|
962
|
+
case "file": {
|
|
963
|
+
message.parts.push({
|
|
964
|
+
type: "file",
|
|
965
|
+
mimeType: chunk.payload.mimeType,
|
|
966
|
+
data: chunk.payload.data
|
|
967
|
+
});
|
|
968
|
+
execUpdate();
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
case "source": {
|
|
972
|
+
message.parts.push({
|
|
973
|
+
type: "source",
|
|
974
|
+
source: chunk.payload.source
|
|
975
|
+
});
|
|
976
|
+
execUpdate();
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
case "tool-call": {
|
|
980
|
+
const invocation = {
|
|
981
|
+
state: "call",
|
|
982
|
+
step,
|
|
983
|
+
...chunk.payload
|
|
984
|
+
};
|
|
985
|
+
if (partialToolCalls[chunk.payload.toolCallId] != null) {
|
|
986
|
+
message.toolInvocations[partialToolCalls[chunk.payload.toolCallId].index] = invocation;
|
|
987
|
+
} else {
|
|
988
|
+
if (message.toolInvocations == null) {
|
|
989
|
+
message.toolInvocations = [];
|
|
990
|
+
}
|
|
991
|
+
message.toolInvocations.push(invocation);
|
|
992
|
+
}
|
|
993
|
+
updateToolInvocationPart(chunk.payload.toolCallId, invocation);
|
|
994
|
+
execUpdate();
|
|
995
|
+
if (onToolCall) {
|
|
996
|
+
const result = await onToolCall({ toolCall: chunk.payload });
|
|
997
|
+
if (result != null) {
|
|
998
|
+
const invocation2 = {
|
|
999
|
+
state: "result",
|
|
1000
|
+
step,
|
|
1001
|
+
...chunk.payload,
|
|
1002
|
+
result
|
|
1003
|
+
};
|
|
1004
|
+
message.toolInvocations[message.toolInvocations.length - 1] = invocation2;
|
|
1005
|
+
updateToolInvocationPart(chunk.payload.toolCallId, invocation2);
|
|
1006
|
+
execUpdate();
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
case "tool-call-input-streaming-start": {
|
|
1011
|
+
if (message.toolInvocations == null) {
|
|
1012
|
+
message.toolInvocations = [];
|
|
1013
|
+
}
|
|
1014
|
+
partialToolCalls[chunk.payload.toolCallId] = {
|
|
1015
|
+
text: "",
|
|
1016
|
+
step,
|
|
1017
|
+
toolName: chunk.payload.toolName,
|
|
1018
|
+
index: message.toolInvocations.length
|
|
1019
|
+
};
|
|
1020
|
+
const invocation = {
|
|
1021
|
+
state: "partial-call",
|
|
1022
|
+
step,
|
|
1023
|
+
toolCallId: chunk.payload.toolCallId,
|
|
1024
|
+
toolName: chunk.payload.toolName,
|
|
1025
|
+
args: void 0
|
|
1026
|
+
};
|
|
1027
|
+
message.toolInvocations.push(invocation);
|
|
1028
|
+
updateToolInvocationPart(chunk.payload.toolCallId, invocation);
|
|
1029
|
+
execUpdate();
|
|
1030
|
+
break;
|
|
1031
|
+
}
|
|
1032
|
+
case "tool-call-delta": {
|
|
1033
|
+
const partialToolCall = partialToolCalls[chunk.payload.toolCallId];
|
|
1034
|
+
partialToolCall.text += chunk.payload.argsTextDelta;
|
|
1035
|
+
const { value: partialArgs } = parsePartialJson(partialToolCall.text);
|
|
1036
|
+
const invocation = {
|
|
1037
|
+
state: "partial-call",
|
|
1038
|
+
step: partialToolCall.step,
|
|
1039
|
+
toolCallId: chunk.payload.toolCallId,
|
|
1040
|
+
toolName: partialToolCall.toolName,
|
|
1041
|
+
args: partialArgs
|
|
1042
|
+
};
|
|
1043
|
+
message.toolInvocations[partialToolCall.index] = invocation;
|
|
1044
|
+
updateToolInvocationPart(chunk.payload.toolCallId, invocation);
|
|
1045
|
+
execUpdate();
|
|
1046
|
+
break;
|
|
1047
|
+
}
|
|
1048
|
+
case "tool-result": {
|
|
1049
|
+
const toolInvocations = message.toolInvocations;
|
|
1050
|
+
if (toolInvocations == null) {
|
|
1051
|
+
throw new Error("tool_result must be preceded by a tool_call");
|
|
1052
|
+
}
|
|
1053
|
+
const toolInvocationIndex = toolInvocations.findIndex(
|
|
1054
|
+
(invocation2) => invocation2.toolCallId === chunk.payload.toolCallId
|
|
1055
|
+
);
|
|
1056
|
+
if (toolInvocationIndex === -1) {
|
|
1057
|
+
throw new Error("tool_result must be preceded by a tool_call with the same toolCallId");
|
|
1058
|
+
}
|
|
1059
|
+
const invocation = {
|
|
1060
|
+
...toolInvocations[toolInvocationIndex],
|
|
1061
|
+
state: "result",
|
|
1062
|
+
...chunk.payload
|
|
1063
|
+
};
|
|
1064
|
+
toolInvocations[toolInvocationIndex] = invocation;
|
|
1065
|
+
updateToolInvocationPart(chunk.payload.toolCallId, invocation);
|
|
1066
|
+
execUpdate();
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
case "error": {
|
|
1070
|
+
throw new Error(chunk.payload.error);
|
|
1071
|
+
}
|
|
1072
|
+
case "data": {
|
|
1073
|
+
data.push(...chunk.payload.data);
|
|
1074
|
+
execUpdate();
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
case "step-finish": {
|
|
1078
|
+
step += 1;
|
|
1079
|
+
currentTextPart = chunk.payload.isContinued ? currentTextPart : void 0;
|
|
1080
|
+
currentReasoningPart = void 0;
|
|
1081
|
+
currentReasoningTextDetail = void 0;
|
|
1082
|
+
execUpdate();
|
|
1083
|
+
break;
|
|
1084
|
+
}
|
|
1085
|
+
case "finish": {
|
|
1086
|
+
finishReason = chunk.payload.finishReason;
|
|
1087
|
+
if (chunk.payload.usage != null) {
|
|
1088
|
+
usage = chunk.payload.usage;
|
|
1089
|
+
}
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
onFinish?.({ message, finishReason, usage });
|
|
1096
|
+
}
|
|
1097
|
+
async processStreamResponse_vNext(processedParams, writable) {
|
|
1098
|
+
const response = await this.request(`/api/agents/${this.agentId}/stream/vnext`, {
|
|
1099
|
+
method: "POST",
|
|
1100
|
+
body: processedParams,
|
|
1101
|
+
stream: true
|
|
1102
|
+
});
|
|
1103
|
+
if (!response.body) {
|
|
1104
|
+
throw new Error("No response body");
|
|
1105
|
+
}
|
|
1106
|
+
try {
|
|
1107
|
+
let toolCalls = [];
|
|
1108
|
+
let messages = [];
|
|
1109
|
+
const [streamForWritable, streamForProcessing] = response.body.tee();
|
|
1110
|
+
streamForWritable.pipeTo(writable, {
|
|
1111
|
+
preventClose: true
|
|
1112
|
+
}).catch((error) => {
|
|
1113
|
+
console.error("Error piping to writable stream:", error);
|
|
1114
|
+
});
|
|
1115
|
+
this.processChatResponse_vNext({
|
|
1116
|
+
stream: streamForProcessing,
|
|
1117
|
+
update: ({ message }) => {
|
|
1118
|
+
const existingIndex = messages.findIndex((m) => m.id === message.id);
|
|
1119
|
+
if (existingIndex !== -1) {
|
|
1120
|
+
messages[existingIndex] = message;
|
|
1121
|
+
} else {
|
|
1122
|
+
messages.push(message);
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
onFinish: async ({ finishReason, message }) => {
|
|
1126
|
+
if (finishReason === "tool-calls") {
|
|
1127
|
+
const toolCall = [...message?.parts ?? []].reverse().find((part) => part.type === "tool-invocation")?.toolInvocation;
|
|
1128
|
+
if (toolCall) {
|
|
1129
|
+
toolCalls.push(toolCall);
|
|
1130
|
+
}
|
|
1131
|
+
for (const toolCall2 of toolCalls) {
|
|
1132
|
+
const clientTool = processedParams.clientTools?.[toolCall2.toolName];
|
|
1133
|
+
if (clientTool && clientTool.execute) {
|
|
1134
|
+
const result = await clientTool.execute(
|
|
1135
|
+
{
|
|
1136
|
+
context: toolCall2?.args,
|
|
1137
|
+
runId: processedParams.runId,
|
|
1138
|
+
resourceId: processedParams.resourceId,
|
|
1139
|
+
threadId: processedParams.threadId,
|
|
1140
|
+
runtimeContext: processedParams.runtimeContext
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
messages: response.messages,
|
|
1144
|
+
toolCallId: toolCall2?.toolCallId
|
|
1145
|
+
}
|
|
1146
|
+
);
|
|
1147
|
+
const lastMessage = JSON.parse(JSON.stringify(messages[messages.length - 1]));
|
|
1148
|
+
const toolInvocationPart = lastMessage?.parts?.find(
|
|
1149
|
+
(part) => part.type === "tool-invocation" && part.toolInvocation?.toolCallId === toolCall2.toolCallId
|
|
1150
|
+
);
|
|
1151
|
+
if (toolInvocationPart) {
|
|
1152
|
+
toolInvocationPart.toolInvocation = {
|
|
1153
|
+
...toolInvocationPart.toolInvocation,
|
|
1154
|
+
state: "result",
|
|
1155
|
+
result
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
const toolInvocation = lastMessage?.toolInvocations?.find(
|
|
1159
|
+
(toolInvocation2) => toolInvocation2.toolCallId === toolCall2.toolCallId
|
|
1160
|
+
);
|
|
1161
|
+
if (toolInvocation) {
|
|
1162
|
+
toolInvocation.state = "result";
|
|
1163
|
+
toolInvocation.result = result;
|
|
1164
|
+
}
|
|
1165
|
+
const writer = writable.getWriter();
|
|
1166
|
+
try {
|
|
1167
|
+
await writer.write(
|
|
1168
|
+
new TextEncoder().encode(
|
|
1169
|
+
"a:" + JSON.stringify({
|
|
1170
|
+
toolCallId: toolCall2.toolCallId,
|
|
1171
|
+
result
|
|
1172
|
+
}) + "\n"
|
|
1173
|
+
)
|
|
1174
|
+
);
|
|
1175
|
+
} finally {
|
|
1176
|
+
writer.releaseLock();
|
|
1177
|
+
}
|
|
1178
|
+
const originalMessages = processedParams.messages;
|
|
1179
|
+
const messageArray = Array.isArray(originalMessages) ? originalMessages : [originalMessages];
|
|
1180
|
+
this.processStreamResponse_vNext(
|
|
1181
|
+
{
|
|
1182
|
+
...processedParams,
|
|
1183
|
+
messages: [...messageArray, ...messages.filter((m) => m.id !== lastMessage.id), lastMessage]
|
|
1184
|
+
},
|
|
1185
|
+
writable
|
|
1186
|
+
).catch((error) => {
|
|
1187
|
+
console.error("Error processing stream response:", error);
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
} else {
|
|
1192
|
+
setTimeout(() => {
|
|
1193
|
+
writable.close();
|
|
1194
|
+
}, 0);
|
|
1195
|
+
}
|
|
1196
|
+
},
|
|
1197
|
+
lastMessage: void 0
|
|
1198
|
+
}).catch((error) => {
|
|
1199
|
+
console.error("Error processing stream response:", error);
|
|
1200
|
+
});
|
|
1201
|
+
} catch (error) {
|
|
1202
|
+
console.error("Error processing stream response:", error);
|
|
1203
|
+
}
|
|
1204
|
+
return response;
|
|
1205
|
+
}
|
|
1206
|
+
async streamVNext(params) {
|
|
1207
|
+
const processedParams = {
|
|
1208
|
+
...params,
|
|
1209
|
+
output: params.output ? zodToJsonSchema(params.output) : void 0,
|
|
1210
|
+
runtimeContext: parseClientRuntimeContext(params.runtimeContext),
|
|
1211
|
+
clientTools: processClientTools(params.clientTools)
|
|
1212
|
+
};
|
|
1213
|
+
const { readable, writable } = new TransformStream();
|
|
1214
|
+
const response = await this.processStreamResponse_vNext(processedParams, writable);
|
|
1215
|
+
const streamResponse = new Response(readable, {
|
|
1216
|
+
status: response.status,
|
|
1217
|
+
statusText: response.statusText,
|
|
1218
|
+
headers: response.headers
|
|
1219
|
+
});
|
|
1220
|
+
streamResponse.processDataStream = async ({
|
|
1221
|
+
onChunk
|
|
1222
|
+
}) => {
|
|
1223
|
+
await processMastraStream({
|
|
1224
|
+
stream: streamResponse.body,
|
|
1225
|
+
onChunk
|
|
1226
|
+
});
|
|
1227
|
+
};
|
|
1228
|
+
return streamResponse;
|
|
1229
|
+
}
|
|
728
1230
|
/**
|
|
729
1231
|
* Processes the stream response and handles tool calls
|
|
730
1232
|
*/
|