@mastra/client-js 0.10.10 → 0.10.11-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AbstractAgent, EventType } from '@ag-ui/client';
2
2
  import { Observable } from 'rxjs';
3
- import { processDataStream, parsePartialJson } from '@ai-sdk/ui-utils';
3
+ import { processTextStream, processDataStream, parsePartialJson } from '@ai-sdk/ui-utils';
4
4
  import { ZodSchema } from 'zod';
5
5
  import originalZodToJsonSchema from 'zod-to-json-schema';
6
6
  import { isVercelTool } from '@mastra/core/tools';
@@ -376,7 +376,11 @@ var Agent = class extends BaseResource {
376
376
  body: processedParams
377
377
  });
378
378
  if (response.finishReason === "tool-calls") {
379
- for (const toolCall of response.toolCalls) {
379
+ const toolCalls = response.toolCalls;
380
+ if (!toolCalls || !Array.isArray(toolCalls)) {
381
+ return response;
382
+ }
383
+ for (const toolCall of toolCalls) {
380
384
  const clientTool = params.clientTools?.[toolCall.toolName];
381
385
  if (clientTool && clientTool.execute) {
382
386
  const result = await clientTool.execute(
@@ -419,7 +423,8 @@ var Agent = class extends BaseResource {
419
423
  onToolCall,
420
424
  onFinish,
421
425
  getCurrentDate = () => /* @__PURE__ */ new Date(),
422
- lastMessage
426
+ lastMessage,
427
+ streamProtocol
423
428
  }) {
424
429
  const replaceLastMessage = lastMessage?.role === "assistant";
425
430
  let step = replaceLastMessage ? 1 + // find max step in existing tool invocations:
@@ -480,228 +485,213 @@ var Agent = class extends BaseResource {
480
485
  replaceLastMessage
481
486
  });
482
487
  }
483
- await processDataStream({
484
- stream,
485
- onTextPart(value) {
486
- if (currentTextPart == null) {
487
- currentTextPart = {
488
- type: "text",
489
- text: value
490
- };
491
- message.parts.push(currentTextPart);
492
- } else {
493
- currentTextPart.text += value;
488
+ if (streamProtocol === "text") {
489
+ await processTextStream({
490
+ stream,
491
+ onTextPart(value) {
492
+ message.content += value;
493
+ execUpdate();
494
494
  }
495
- message.content += value;
496
- execUpdate();
497
- },
498
- onReasoningPart(value) {
499
- if (currentReasoningTextDetail == null) {
500
- currentReasoningTextDetail = { type: "text", text: value };
501
- if (currentReasoningPart != null) {
502
- currentReasoningPart.details.push(currentReasoningTextDetail);
495
+ });
496
+ onFinish?.({ message, finishReason, usage });
497
+ } else {
498
+ await processDataStream({
499
+ stream,
500
+ onTextPart(value) {
501
+ if (currentTextPart == null) {
502
+ currentTextPart = {
503
+ type: "text",
504
+ text: value
505
+ };
506
+ message.parts.push(currentTextPart);
507
+ } else {
508
+ currentTextPart.text += value;
503
509
  }
504
- } else {
505
- currentReasoningTextDetail.text += value;
506
- }
507
- if (currentReasoningPart == null) {
508
- currentReasoningPart = {
509
- type: "reasoning",
510
- reasoning: value,
511
- details: [currentReasoningTextDetail]
512
- };
513
- message.parts.push(currentReasoningPart);
514
- } else {
515
- currentReasoningPart.reasoning += value;
516
- }
517
- message.reasoning = (message.reasoning ?? "") + value;
518
- execUpdate();
519
- },
520
- onReasoningSignaturePart(value) {
521
- if (currentReasoningTextDetail != null) {
522
- currentReasoningTextDetail.signature = value.signature;
523
- }
524
- },
525
- onRedactedReasoningPart(value) {
526
- if (currentReasoningPart == null) {
527
- currentReasoningPart = {
528
- type: "reasoning",
529
- reasoning: "",
530
- details: []
531
- };
532
- message.parts.push(currentReasoningPart);
533
- }
534
- currentReasoningPart.details.push({
535
- type: "redacted",
536
- data: value.data
537
- });
538
- currentReasoningTextDetail = void 0;
539
- execUpdate();
540
- },
541
- onFilePart(value) {
542
- message.parts.push({
543
- type: "file",
544
- mimeType: value.mimeType,
545
- data: value.data
546
- });
547
- execUpdate();
548
- },
549
- onSourcePart(value) {
550
- message.parts.push({
551
- type: "source",
552
- source: value
553
- });
554
- execUpdate();
555
- },
556
- onToolCallStreamingStartPart(value) {
557
- if (message.toolInvocations == null) {
558
- message.toolInvocations = [];
559
- }
560
- partialToolCalls[value.toolCallId] = {
561
- text: "",
562
- step,
563
- toolName: value.toolName,
564
- index: message.toolInvocations.length
565
- };
566
- const invocation = {
567
- state: "partial-call",
568
- step,
569
- toolCallId: value.toolCallId,
570
- toolName: value.toolName,
571
- args: void 0
572
- };
573
- message.toolInvocations.push(invocation);
574
- updateToolInvocationPart(value.toolCallId, invocation);
575
- execUpdate();
576
- },
577
- onToolCallDeltaPart(value) {
578
- const partialToolCall = partialToolCalls[value.toolCallId];
579
- partialToolCall.text += value.argsTextDelta;
580
- const { value: partialArgs } = parsePartialJson(partialToolCall.text);
581
- const invocation = {
582
- state: "partial-call",
583
- step: partialToolCall.step,
584
- toolCallId: value.toolCallId,
585
- toolName: partialToolCall.toolName,
586
- args: partialArgs
587
- };
588
- message.toolInvocations[partialToolCall.index] = invocation;
589
- updateToolInvocationPart(value.toolCallId, invocation);
590
- execUpdate();
591
- },
592
- async onToolCallPart(value) {
593
- const invocation = {
594
- state: "call",
595
- step,
596
- ...value
597
- };
598
- if (partialToolCalls[value.toolCallId] != null) {
599
- message.toolInvocations[partialToolCalls[value.toolCallId].index] = invocation;
600
- } else {
510
+ message.content += value;
511
+ execUpdate();
512
+ },
513
+ onReasoningPart(value) {
514
+ if (currentReasoningTextDetail == null) {
515
+ currentReasoningTextDetail = { type: "text", text: value };
516
+ if (currentReasoningPart != null) {
517
+ currentReasoningPart.details.push(currentReasoningTextDetail);
518
+ }
519
+ } else {
520
+ currentReasoningTextDetail.text += value;
521
+ }
522
+ if (currentReasoningPart == null) {
523
+ currentReasoningPart = {
524
+ type: "reasoning",
525
+ reasoning: value,
526
+ details: [currentReasoningTextDetail]
527
+ };
528
+ message.parts.push(currentReasoningPart);
529
+ } else {
530
+ currentReasoningPart.reasoning += value;
531
+ }
532
+ message.reasoning = (message.reasoning ?? "") + value;
533
+ execUpdate();
534
+ },
535
+ onReasoningSignaturePart(value) {
536
+ if (currentReasoningTextDetail != null) {
537
+ currentReasoningTextDetail.signature = value.signature;
538
+ }
539
+ },
540
+ onRedactedReasoningPart(value) {
541
+ if (currentReasoningPart == null) {
542
+ currentReasoningPart = {
543
+ type: "reasoning",
544
+ reasoning: "",
545
+ details: []
546
+ };
547
+ message.parts.push(currentReasoningPart);
548
+ }
549
+ currentReasoningPart.details.push({
550
+ type: "redacted",
551
+ data: value.data
552
+ });
553
+ currentReasoningTextDetail = void 0;
554
+ execUpdate();
555
+ },
556
+ onFilePart(value) {
557
+ message.parts.push({
558
+ type: "file",
559
+ mimeType: value.mimeType,
560
+ data: value.data
561
+ });
562
+ execUpdate();
563
+ },
564
+ onSourcePart(value) {
565
+ message.parts.push({
566
+ type: "source",
567
+ source: value
568
+ });
569
+ execUpdate();
570
+ },
571
+ onToolCallStreamingStartPart(value) {
601
572
  if (message.toolInvocations == null) {
602
573
  message.toolInvocations = [];
603
574
  }
575
+ partialToolCalls[value.toolCallId] = {
576
+ text: "",
577
+ step,
578
+ toolName: value.toolName,
579
+ index: message.toolInvocations.length
580
+ };
581
+ const invocation = {
582
+ state: "partial-call",
583
+ step,
584
+ toolCallId: value.toolCallId,
585
+ toolName: value.toolName,
586
+ args: void 0
587
+ };
604
588
  message.toolInvocations.push(invocation);
605
- }
606
- updateToolInvocationPart(value.toolCallId, invocation);
607
- execUpdate();
608
- if (onToolCall) {
609
- const result = await onToolCall({ toolCall: value });
610
- if (result != null) {
611
- const invocation2 = {
612
- state: "result",
613
- step,
614
- ...value,
615
- result
616
- };
617
- message.toolInvocations[message.toolInvocations.length - 1] = invocation2;
618
- updateToolInvocationPart(value.toolCallId, invocation2);
619
- execUpdate();
589
+ updateToolInvocationPart(value.toolCallId, invocation);
590
+ execUpdate();
591
+ },
592
+ onToolCallDeltaPart(value) {
593
+ const partialToolCall = partialToolCalls[value.toolCallId];
594
+ partialToolCall.text += value.argsTextDelta;
595
+ const { value: partialArgs } = parsePartialJson(partialToolCall.text);
596
+ const invocation = {
597
+ state: "partial-call",
598
+ step: partialToolCall.step,
599
+ toolCallId: value.toolCallId,
600
+ toolName: partialToolCall.toolName,
601
+ args: partialArgs
602
+ };
603
+ message.toolInvocations[partialToolCall.index] = invocation;
604
+ updateToolInvocationPart(value.toolCallId, invocation);
605
+ execUpdate();
606
+ },
607
+ async onToolCallPart(value) {
608
+ const invocation = {
609
+ state: "call",
610
+ step,
611
+ ...value
612
+ };
613
+ if (partialToolCalls[value.toolCallId] != null) {
614
+ message.toolInvocations[partialToolCalls[value.toolCallId].index] = invocation;
615
+ } else {
616
+ if (message.toolInvocations == null) {
617
+ message.toolInvocations = [];
618
+ }
619
+ message.toolInvocations.push(invocation);
620
620
  }
621
+ updateToolInvocationPart(value.toolCallId, invocation);
622
+ execUpdate();
623
+ if (onToolCall) {
624
+ const result = await onToolCall({ toolCall: value });
625
+ if (result != null) {
626
+ const invocation2 = {
627
+ state: "result",
628
+ step,
629
+ ...value,
630
+ result
631
+ };
632
+ message.toolInvocations[message.toolInvocations.length - 1] = invocation2;
633
+ updateToolInvocationPart(value.toolCallId, invocation2);
634
+ execUpdate();
635
+ }
636
+ }
637
+ },
638
+ onToolResultPart(value) {
639
+ const toolInvocations = message.toolInvocations;
640
+ if (toolInvocations == null) {
641
+ throw new Error("tool_result must be preceded by a tool_call");
642
+ }
643
+ const toolInvocationIndex = toolInvocations.findIndex(
644
+ (invocation2) => invocation2.toolCallId === value.toolCallId
645
+ );
646
+ if (toolInvocationIndex === -1) {
647
+ throw new Error("tool_result must be preceded by a tool_call with the same toolCallId");
648
+ }
649
+ const invocation = {
650
+ ...toolInvocations[toolInvocationIndex],
651
+ state: "result",
652
+ ...value
653
+ };
654
+ toolInvocations[toolInvocationIndex] = invocation;
655
+ updateToolInvocationPart(value.toolCallId, invocation);
656
+ execUpdate();
657
+ },
658
+ onDataPart(value) {
659
+ data.push(...value);
660
+ execUpdate();
661
+ },
662
+ onMessageAnnotationsPart(value) {
663
+ if (messageAnnotations == null) {
664
+ messageAnnotations = [...value];
665
+ } else {
666
+ messageAnnotations.push(...value);
667
+ }
668
+ execUpdate();
669
+ },
670
+ onFinishStepPart(value) {
671
+ step += 1;
672
+ currentTextPart = value.isContinued ? currentTextPart : void 0;
673
+ currentReasoningPart = void 0;
674
+ currentReasoningTextDetail = void 0;
675
+ },
676
+ onStartStepPart(value) {
677
+ if (!replaceLastMessage) {
678
+ message.id = value.messageId;
679
+ }
680
+ message.parts.push({ type: "step-start" });
681
+ execUpdate();
682
+ },
683
+ onFinishMessagePart(value) {
684
+ finishReason = value.finishReason;
685
+ if (value.usage != null) {
686
+ usage = value.usage;
687
+ }
688
+ },
689
+ onErrorPart(error) {
690
+ throw new Error(error);
621
691
  }
622
- },
623
- onToolResultPart(value) {
624
- const toolInvocations = message.toolInvocations;
625
- if (toolInvocations == null) {
626
- throw new Error("tool_result must be preceded by a tool_call");
627
- }
628
- const toolInvocationIndex = toolInvocations.findIndex((invocation2) => invocation2.toolCallId === value.toolCallId);
629
- if (toolInvocationIndex === -1) {
630
- throw new Error("tool_result must be preceded by a tool_call with the same toolCallId");
631
- }
632
- const invocation = {
633
- ...toolInvocations[toolInvocationIndex],
634
- state: "result",
635
- ...value
636
- };
637
- toolInvocations[toolInvocationIndex] = invocation;
638
- updateToolInvocationPart(value.toolCallId, invocation);
639
- execUpdate();
640
- },
641
- onDataPart(value) {
642
- data.push(...value);
643
- execUpdate();
644
- },
645
- onMessageAnnotationsPart(value) {
646
- if (messageAnnotations == null) {
647
- messageAnnotations = [...value];
648
- } else {
649
- messageAnnotations.push(...value);
650
- }
651
- execUpdate();
652
- },
653
- onFinishStepPart(value) {
654
- step += 1;
655
- currentTextPart = value.isContinued ? currentTextPart : void 0;
656
- currentReasoningPart = void 0;
657
- currentReasoningTextDetail = void 0;
658
- },
659
- onStartStepPart(value) {
660
- if (!replaceLastMessage) {
661
- message.id = value.messageId;
662
- }
663
- message.parts.push({ type: "step-start" });
664
- execUpdate();
665
- },
666
- onFinishMessagePart(value) {
667
- finishReason = value.finishReason;
668
- if (value.usage != null) {
669
- usage = value.usage;
670
- }
671
- },
672
- onErrorPart(error) {
673
- throw new Error(error);
674
- }
675
- });
676
- onFinish?.({ message, finishReason, usage });
677
- }
678
- /**
679
- * Streams a response from the agent
680
- * @param params - Stream parameters including prompt
681
- * @returns Promise containing the enhanced Response object with processDataStream method
682
- */
683
- async stream(params) {
684
- const processedParams = {
685
- ...params,
686
- output: params.output ? zodToJsonSchema(params.output) : void 0,
687
- experimental_output: params.experimental_output ? zodToJsonSchema(params.experimental_output) : void 0,
688
- runtimeContext: parseClientRuntimeContext(params.runtimeContext),
689
- clientTools: processClientTools(params.clientTools)
690
- };
691
- const { readable, writable } = new TransformStream();
692
- const response = await this.processStreamResponse(processedParams, writable);
693
- const streamResponse = new Response(readable, {
694
- status: response.status,
695
- statusText: response.statusText,
696
- headers: response.headers
697
- });
698
- streamResponse.processDataStream = async (options = {}) => {
699
- await processDataStream({
700
- stream: streamResponse.body,
701
- ...options
702
692
  });
703
- };
704
- return streamResponse;
693
+ onFinish?.({ message, finishReason, usage });
694
+ }
705
695
  }
706
696
  /**
707
697
  * Processes the stream response and handles tool calls
@@ -716,6 +706,7 @@ var Agent = class extends BaseResource {
716
706
  throw new Error("No response body");
717
707
  }
718
708
  try {
709
+ const streamProtocol = processedParams.output ? "text" : "data";
719
710
  let toolCalls = [];
720
711
  let messages = [];
721
712
  const [streamForWritable, streamForProcessing] = response.body.tee();
@@ -795,17 +786,55 @@ var Agent = class extends BaseResource {
795
786
  }
796
787
  } else {
797
788
  setTimeout(() => {
798
- writable.close();
789
+ if (!writable.locked) {
790
+ writable.close();
791
+ }
799
792
  }, 0);
800
793
  }
801
794
  },
802
- lastMessage: void 0
795
+ lastMessage: void 0,
796
+ streamProtocol
803
797
  });
804
798
  } catch (error) {
805
799
  console.error("Error processing stream response:", error);
806
800
  }
807
801
  return response;
808
802
  }
803
+ /**
804
+ * Streams a response from the agent
805
+ * @param params - Stream parameters including prompt
806
+ * @returns Promise containing the enhanced Response object with processDataStream and processTextStream methods
807
+ */
808
+ async stream(params) {
809
+ const processedParams = {
810
+ ...params,
811
+ output: params.output ? zodToJsonSchema(params.output) : void 0,
812
+ experimental_output: params.experimental_output ? zodToJsonSchema(params.experimental_output) : void 0,
813
+ runtimeContext: parseClientRuntimeContext(params.runtimeContext),
814
+ clientTools: processClientTools(params.clientTools)
815
+ };
816
+ const { readable, writable } = new TransformStream();
817
+ const response = await this.processStreamResponse(processedParams, writable);
818
+ const streamResponse = new Response(readable, {
819
+ status: response.status,
820
+ statusText: response.statusText,
821
+ headers: response.headers
822
+ });
823
+ streamResponse.processDataStream = async (options = {}) => {
824
+ await processDataStream({
825
+ stream: streamResponse.body,
826
+ ...options
827
+ });
828
+ };
829
+ streamResponse.processTextStream = async (options) => {
830
+ await processTextStream({
831
+ stream: streamResponse.body,
832
+ onTextPart: options?.onTextPart ?? (() => {
833
+ })
834
+ });
835
+ };
836
+ return streamResponse;
837
+ }
809
838
  /**
810
839
  * Gets details about a specific tool available to the agent
811
840
  * @param toolId - ID of the tool to retrieve
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/client-js",
3
- "version": "0.10.10",
3
+ "version": "0.10.11-alpha.0",
4
4
  "description": "The official TypeScript library for the Mastra Client API",
5
5
  "author": "",
6
6
  "type": "module",
@@ -33,7 +33,7 @@
33
33
  "rxjs": "7.8.1",
34
34
  "zod": "^3.25.67",
35
35
  "zod-to-json-schema": "^3.24.5",
36
- "@mastra/core": "0.10.11"
36
+ "@mastra/core": "0.10.12-alpha.0"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "zod": "^3.0.0"
package/src/example.ts CHANGED
@@ -14,25 +14,53 @@ import z from 'zod';
14
14
  const agent = client.getAgent('weatherAgent');
15
15
  const response = await agent.stream({
16
16
  messages: 'what is the weather in new york?',
17
+ output: z.object({
18
+ weather: z.string(),
19
+ temperature: z.number(),
20
+ humidity: z.number(),
21
+ windSpeed: z.number(),
22
+ windDirection: z.string(),
23
+ windGust: z.number(),
24
+ windChill: z.number(),
25
+ }),
17
26
  });
18
27
 
19
- response.processDataStream({
20
- onTextPart: text => {
21
- process.stdout.write(text);
22
- },
23
- onFilePart: file => {
24
- console.log(file);
25
- },
26
- onDataPart: data => {
27
- console.log(data);
28
- },
29
- onErrorPart: error => {
30
- console.error(error);
31
- },
32
- onToolCallPart(streamPart) {
33
- console.log(streamPart);
34
- },
35
- });
28
+ // Process data stream - unstructured output
29
+
30
+ // response.processDataStream({
31
+ // onTextPart: text => {
32
+ // process.stdout.write(text);
33
+ // },
34
+ // onFilePart: file => {
35
+ // console.log(file);
36
+ // },
37
+ // onDataPart: data => {
38
+ // console.log(data);
39
+ // },
40
+ // onErrorPart: error => {
41
+ // console.error(error);
42
+ // },
43
+ // onToolCallPart(streamPart) {
44
+ // console.log(streamPart);
45
+ // },
46
+ // });
47
+
48
+ // Process text stream - structured output
49
+
50
+ // response.processTextStream({
51
+ // onTextPart: text => {
52
+ // process.stdout.write(text);
53
+ // },
54
+ // });
55
+
56
+ // read the response body directly
57
+
58
+ // const reader = response.body!.getReader();
59
+ // while (true) {
60
+ // const { done, value } = await reader.read();
61
+ // if (done) break;
62
+ // console.log(new TextDecoder().decode(value));
63
+ // }
36
64
  } catch (error) {
37
65
  console.error(error);
38
66
  }