@mastra/client-js 0.10.6-alpha.2 → 0.10.6-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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @mastra/client-js@0.10.6-alpha.2 build /home/runner/work/mastra/mastra/client-sdks/client-js
2
+ > @mastra/client-js@0.10.6-alpha.4 build /home/runner/work/mastra/mastra/client-sdks/client-js
3
3
  > tsup src/index.ts --format esm,cjs --dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -9,11 +9,11 @@
9
9
  CLI Cleaning output folder
10
10
  ESM Build start
11
11
  CJS Build start
12
- ESM dist/index.js 53.26 KB
13
- ESM ⚡️ Build success in 1252ms
14
- CJS dist/index.cjs 53.55 KB
15
- CJS ⚡️ Build success in 1256ms
12
+ ESM dist/index.js 66.22 KB
13
+ ESM ⚡️ Build success in 2601ms
14
+ CJS dist/index.cjs 66.51 KB
15
+ CJS ⚡️ Build success in 2613ms
16
16
  DTS Build start
17
- DTS ⚡️ Build success in 14921ms
18
- DTS dist/index.d.ts 39.03 KB
19
- DTS dist/index.d.cts 39.03 KB
17
+ DTS ⚡️ Build success in 19250ms
18
+ DTS dist/index.d.ts 39.17 KB
19
+ DTS dist/index.d.cts 39.17 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @mastra/client-js
2
2
 
3
+ ## 0.10.6-alpha.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [a8b194f]
8
+ - @mastra/core@0.10.7-alpha.4
9
+
10
+ ## 0.10.6-alpha.3
11
+
12
+ ### Patch Changes
13
+
14
+ - 18a5d59: clientTools client side execution
15
+ - Updated dependencies [792c4c0]
16
+ - Updated dependencies [502fe05]
17
+ - Updated dependencies [4efcfa0]
18
+ - @mastra/core@0.10.7-alpha.3
19
+
3
20
  ## 0.10.6-alpha.2
4
21
 
5
22
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -299,8 +299,6 @@ function parseClientRuntimeContext(runtimeContext$1) {
299
299
  }
300
300
  return void 0;
301
301
  }
302
-
303
- // src/resources/agent.ts
304
302
  var AgentVoice = class extends BaseResource {
305
303
  constructor(options, agentId) {
306
304
  super(options);
@@ -369,7 +367,7 @@ var Agent = class extends BaseResource {
369
367
  details() {
370
368
  return this.request(`/api/agents/${this.agentId}`);
371
369
  }
372
- generate(params) {
370
+ async generate(params) {
373
371
  const processedParams = {
374
372
  ...params,
375
373
  output: params.output ? zodToJsonSchema(params.output) : void 0,
@@ -377,10 +375,310 @@ var Agent = class extends BaseResource {
377
375
  runtimeContext: parseClientRuntimeContext(params.runtimeContext),
378
376
  clientTools: processClientTools(params.clientTools)
379
377
  };
380
- return this.request(`/api/agents/${this.agentId}/generate`, {
378
+ const { runId, resourceId, threadId, runtimeContext } = processedParams;
379
+ const response = await this.request(`/api/agents/${this.agentId}/generate`, {
381
380
  method: "POST",
382
381
  body: processedParams
383
382
  });
383
+ if (response.finishReason === "tool-calls") {
384
+ for (const toolCall of response.toolCalls) {
385
+ const clientTool = params.clientTools?.[toolCall.toolName];
386
+ if (clientTool && clientTool.execute) {
387
+ const result = await clientTool.execute(
388
+ { context: toolCall?.args, runId, resourceId, threadId, runtimeContext },
389
+ {
390
+ messages: response.messages,
391
+ toolCallId: toolCall?.toolCallId
392
+ }
393
+ );
394
+ const updatedMessages = [
395
+ {
396
+ role: "user",
397
+ content: params.messages
398
+ },
399
+ ...response.response.messages,
400
+ {
401
+ role: "tool",
402
+ content: [
403
+ {
404
+ type: "tool-result",
405
+ toolCallId: toolCall.toolCallId,
406
+ toolName: toolCall.toolName,
407
+ result
408
+ }
409
+ ]
410
+ }
411
+ ];
412
+ return this.generate({
413
+ ...params,
414
+ messages: updatedMessages
415
+ });
416
+ }
417
+ }
418
+ }
419
+ return response;
420
+ }
421
+ async processChatResponse({
422
+ stream,
423
+ update,
424
+ onToolCall,
425
+ onFinish,
426
+ getCurrentDate = () => /* @__PURE__ */ new Date(),
427
+ lastMessage
428
+ }) {
429
+ const replaceLastMessage = lastMessage?.role === "assistant";
430
+ let step = replaceLastMessage ? 1 + // find max step in existing tool invocations:
431
+ (lastMessage.toolInvocations?.reduce((max, toolInvocation) => {
432
+ return Math.max(max, toolInvocation.step ?? 0);
433
+ }, 0) ?? 0) : 0;
434
+ const message = replaceLastMessage ? structuredClone(lastMessage) : {
435
+ id: crypto.randomUUID(),
436
+ createdAt: getCurrentDate(),
437
+ role: "assistant",
438
+ content: "",
439
+ parts: []
440
+ };
441
+ let currentTextPart = void 0;
442
+ let currentReasoningPart = void 0;
443
+ let currentReasoningTextDetail = void 0;
444
+ function updateToolInvocationPart(toolCallId, invocation) {
445
+ const part = message.parts.find(
446
+ (part2) => part2.type === "tool-invocation" && part2.toolInvocation.toolCallId === toolCallId
447
+ );
448
+ if (part != null) {
449
+ part.toolInvocation = invocation;
450
+ } else {
451
+ message.parts.push({
452
+ type: "tool-invocation",
453
+ toolInvocation: invocation
454
+ });
455
+ }
456
+ }
457
+ const data = [];
458
+ let messageAnnotations = replaceLastMessage ? lastMessage?.annotations : void 0;
459
+ const partialToolCalls = {};
460
+ let usage = {
461
+ completionTokens: NaN,
462
+ promptTokens: NaN,
463
+ totalTokens: NaN
464
+ };
465
+ let finishReason = "unknown";
466
+ function execUpdate() {
467
+ const copiedData = [...data];
468
+ if (messageAnnotations?.length) {
469
+ message.annotations = messageAnnotations;
470
+ }
471
+ const copiedMessage = {
472
+ // deep copy the message to ensure that deep changes (msg attachments) are updated
473
+ // with SolidJS. SolidJS uses referential integration of sub-objects to detect changes.
474
+ ...structuredClone(message),
475
+ // add a revision id to ensure that the message is updated with SWR. SWR uses a
476
+ // hashing approach by default to detect changes, but it only works for shallow
477
+ // changes. This is why we need to add a revision id to ensure that the message
478
+ // is updated with SWR (without it, the changes get stuck in SWR and are not
479
+ // forwarded to rendering):
480
+ revisionId: crypto.randomUUID()
481
+ };
482
+ update({
483
+ message: copiedMessage,
484
+ data: copiedData,
485
+ replaceLastMessage
486
+ });
487
+ }
488
+ await uiUtils.processDataStream({
489
+ stream,
490
+ onTextPart(value) {
491
+ if (currentTextPart == null) {
492
+ currentTextPart = {
493
+ type: "text",
494
+ text: value
495
+ };
496
+ message.parts.push(currentTextPart);
497
+ } else {
498
+ currentTextPart.text += value;
499
+ }
500
+ message.content += value;
501
+ execUpdate();
502
+ },
503
+ onReasoningPart(value) {
504
+ if (currentReasoningTextDetail == null) {
505
+ currentReasoningTextDetail = { type: "text", text: value };
506
+ if (currentReasoningPart != null) {
507
+ currentReasoningPart.details.push(currentReasoningTextDetail);
508
+ }
509
+ } else {
510
+ currentReasoningTextDetail.text += value;
511
+ }
512
+ if (currentReasoningPart == null) {
513
+ currentReasoningPart = {
514
+ type: "reasoning",
515
+ reasoning: value,
516
+ details: [currentReasoningTextDetail]
517
+ };
518
+ message.parts.push(currentReasoningPart);
519
+ } else {
520
+ currentReasoningPart.reasoning += value;
521
+ }
522
+ message.reasoning = (message.reasoning ?? "") + value;
523
+ execUpdate();
524
+ },
525
+ onReasoningSignaturePart(value) {
526
+ if (currentReasoningTextDetail != null) {
527
+ currentReasoningTextDetail.signature = value.signature;
528
+ }
529
+ },
530
+ onRedactedReasoningPart(value) {
531
+ if (currentReasoningPart == null) {
532
+ currentReasoningPart = {
533
+ type: "reasoning",
534
+ reasoning: "",
535
+ details: []
536
+ };
537
+ message.parts.push(currentReasoningPart);
538
+ }
539
+ currentReasoningPart.details.push({
540
+ type: "redacted",
541
+ data: value.data
542
+ });
543
+ currentReasoningTextDetail = void 0;
544
+ execUpdate();
545
+ },
546
+ onFilePart(value) {
547
+ message.parts.push({
548
+ type: "file",
549
+ mimeType: value.mimeType,
550
+ data: value.data
551
+ });
552
+ execUpdate();
553
+ },
554
+ onSourcePart(value) {
555
+ message.parts.push({
556
+ type: "source",
557
+ source: value
558
+ });
559
+ execUpdate();
560
+ },
561
+ onToolCallStreamingStartPart(value) {
562
+ if (message.toolInvocations == null) {
563
+ message.toolInvocations = [];
564
+ }
565
+ partialToolCalls[value.toolCallId] = {
566
+ text: "",
567
+ step,
568
+ toolName: value.toolName,
569
+ index: message.toolInvocations.length
570
+ };
571
+ const invocation = {
572
+ state: "partial-call",
573
+ step,
574
+ toolCallId: value.toolCallId,
575
+ toolName: value.toolName,
576
+ args: void 0
577
+ };
578
+ message.toolInvocations.push(invocation);
579
+ updateToolInvocationPart(value.toolCallId, invocation);
580
+ execUpdate();
581
+ },
582
+ onToolCallDeltaPart(value) {
583
+ const partialToolCall = partialToolCalls[value.toolCallId];
584
+ partialToolCall.text += value.argsTextDelta;
585
+ const { value: partialArgs } = uiUtils.parsePartialJson(partialToolCall.text);
586
+ const invocation = {
587
+ state: "partial-call",
588
+ step: partialToolCall.step,
589
+ toolCallId: value.toolCallId,
590
+ toolName: partialToolCall.toolName,
591
+ args: partialArgs
592
+ };
593
+ message.toolInvocations[partialToolCall.index] = invocation;
594
+ updateToolInvocationPart(value.toolCallId, invocation);
595
+ execUpdate();
596
+ },
597
+ async onToolCallPart(value) {
598
+ const invocation = {
599
+ state: "call",
600
+ step,
601
+ ...value
602
+ };
603
+ if (partialToolCalls[value.toolCallId] != null) {
604
+ message.toolInvocations[partialToolCalls[value.toolCallId].index] = invocation;
605
+ } else {
606
+ if (message.toolInvocations == null) {
607
+ message.toolInvocations = [];
608
+ }
609
+ message.toolInvocations.push(invocation);
610
+ }
611
+ updateToolInvocationPart(value.toolCallId, invocation);
612
+ execUpdate();
613
+ if (onToolCall) {
614
+ const result = await onToolCall({ toolCall: value });
615
+ if (result != null) {
616
+ const invocation2 = {
617
+ state: "result",
618
+ step,
619
+ ...value,
620
+ result
621
+ };
622
+ message.toolInvocations[message.toolInvocations.length - 1] = invocation2;
623
+ updateToolInvocationPart(value.toolCallId, invocation2);
624
+ execUpdate();
625
+ }
626
+ }
627
+ },
628
+ onToolResultPart(value) {
629
+ const toolInvocations = message.toolInvocations;
630
+ if (toolInvocations == null) {
631
+ throw new Error("tool_result must be preceded by a tool_call");
632
+ }
633
+ const toolInvocationIndex = toolInvocations.findIndex((invocation2) => invocation2.toolCallId === value.toolCallId);
634
+ if (toolInvocationIndex === -1) {
635
+ throw new Error("tool_result must be preceded by a tool_call with the same toolCallId");
636
+ }
637
+ const invocation = {
638
+ ...toolInvocations[toolInvocationIndex],
639
+ state: "result",
640
+ ...value
641
+ };
642
+ toolInvocations[toolInvocationIndex] = invocation;
643
+ updateToolInvocationPart(value.toolCallId, invocation);
644
+ execUpdate();
645
+ },
646
+ onDataPart(value) {
647
+ data.push(...value);
648
+ execUpdate();
649
+ },
650
+ onMessageAnnotationsPart(value) {
651
+ if (messageAnnotations == null) {
652
+ messageAnnotations = [...value];
653
+ } else {
654
+ messageAnnotations.push(...value);
655
+ }
656
+ execUpdate();
657
+ },
658
+ onFinishStepPart(value) {
659
+ step += 1;
660
+ currentTextPart = value.isContinued ? currentTextPart : void 0;
661
+ currentReasoningPart = void 0;
662
+ currentReasoningTextDetail = void 0;
663
+ },
664
+ onStartStepPart(value) {
665
+ if (!replaceLastMessage) {
666
+ message.id = value.messageId;
667
+ }
668
+ message.parts.push({ type: "step-start" });
669
+ execUpdate();
670
+ },
671
+ onFinishMessagePart(value) {
672
+ finishReason = value.finishReason;
673
+ if (value.usage != null) {
674
+ usage = value.usage;
675
+ }
676
+ },
677
+ onErrorPart(error) {
678
+ throw new Error(error);
679
+ }
680
+ });
681
+ onFinish?.({ message, finishReason, usage });
384
682
  }
385
683
  /**
386
684
  * Streams a response from the agent
@@ -395,6 +693,25 @@ var Agent = class extends BaseResource {
395
693
  runtimeContext: parseClientRuntimeContext(params.runtimeContext),
396
694
  clientTools: processClientTools(params.clientTools)
397
695
  };
696
+ const { readable, writable } = new TransformStream();
697
+ const response = await this.processStreamResponse(processedParams, writable);
698
+ const streamResponse = new Response(readable, {
699
+ status: response.status,
700
+ statusText: response.statusText,
701
+ headers: response.headers
702
+ });
703
+ streamResponse.processDataStream = async (options = {}) => {
704
+ await uiUtils.processDataStream({
705
+ stream: readable,
706
+ ...options
707
+ });
708
+ };
709
+ return streamResponse;
710
+ }
711
+ /**
712
+ * Processes the stream response and handles tool calls
713
+ */
714
+ async processStreamResponse(processedParams, writable) {
398
715
  const response = await this.request(`/api/agents/${this.agentId}/stream`, {
399
716
  method: "POST",
400
717
  body: processedParams,
@@ -403,12 +720,81 @@ var Agent = class extends BaseResource {
403
720
  if (!response.body) {
404
721
  throw new Error("No response body");
405
722
  }
406
- response.processDataStream = async (options = {}) => {
407
- await uiUtils.processDataStream({
408
- stream: response.body,
409
- ...options
723
+ try {
724
+ let toolCalls = [];
725
+ let finishReasonToolCalls = false;
726
+ let messages = [];
727
+ let hasProcessedToolCalls = false;
728
+ response.clone().body.pipeTo(writable, {
729
+ preventClose: true
410
730
  });
411
- };
731
+ await this.processChatResponse({
732
+ stream: response.clone().body,
733
+ update: ({ message }) => {
734
+ messages.push(message);
735
+ },
736
+ onFinish: ({ finishReason, message }) => {
737
+ if (finishReason === "tool-calls") {
738
+ finishReasonToolCalls = true;
739
+ const toolCall = [...message?.parts ?? []].reverse().find((part) => part.type === "tool-invocation")?.toolInvocation;
740
+ if (toolCall) {
741
+ toolCalls.push(toolCall);
742
+ }
743
+ }
744
+ },
745
+ lastMessage: void 0
746
+ });
747
+ if (finishReasonToolCalls && !hasProcessedToolCalls) {
748
+ hasProcessedToolCalls = true;
749
+ for (const toolCall of toolCalls) {
750
+ const clientTool = processedParams.clientTools?.[toolCall.toolName];
751
+ if (clientTool && clientTool.execute) {
752
+ const result = await clientTool.execute(
753
+ {
754
+ context: toolCall?.args,
755
+ runId: processedParams.runId,
756
+ resourceId: processedParams.resourceId,
757
+ threadId: processedParams.threadId,
758
+ runtimeContext: processedParams.runtimeContext
759
+ },
760
+ {
761
+ messages: response.messages,
762
+ toolCallId: toolCall?.toolCallId
763
+ }
764
+ );
765
+ const lastMessage = JSON.parse(JSON.stringify(messages[messages.length - 1]));
766
+ const toolInvocationPart = lastMessage?.parts?.find(
767
+ (part) => part.type === "tool-invocation" && part.toolInvocation?.toolCallId === toolCall.toolCallId
768
+ );
769
+ if (toolInvocationPart) {
770
+ toolInvocationPart.toolInvocation = {
771
+ ...toolInvocationPart.toolInvocation,
772
+ state: "result",
773
+ result
774
+ };
775
+ }
776
+ const toolInvocation = lastMessage?.toolInvocations?.find(
777
+ (toolInvocation2) => toolInvocation2.toolCallId === toolCall.toolCallId
778
+ );
779
+ if (toolInvocation) {
780
+ toolInvocation.state = "result";
781
+ toolInvocation.result = result;
782
+ }
783
+ const originalMessages = processedParams.messages;
784
+ const messageArray = Array.isArray(originalMessages) ? originalMessages : [originalMessages];
785
+ this.processStreamResponse(
786
+ {
787
+ ...processedParams,
788
+ messages: [...messageArray, ...messages, lastMessage]
789
+ },
790
+ writable
791
+ );
792
+ }
793
+ }
794
+ }
795
+ } catch (error) {
796
+ console.error("Error processing stream response:", error);
797
+ }
412
798
  return response;
413
799
  }
414
800
  /**
@@ -803,7 +1189,7 @@ var LegacyWorkflow = class extends BaseResource {
803
1189
  };
804
1190
 
805
1191
  // src/resources/tool.ts
806
- var Tool = class extends BaseResource {
1192
+ var Tool2 = class extends BaseResource {
807
1193
  constructor(options, toolId) {
808
1194
  super(options);
809
1195
  this.toolId = toolId;
@@ -1503,7 +1889,7 @@ var MastraClient = class extends BaseResource {
1503
1889
  * @returns Tool instance
1504
1890
  */
1505
1891
  getTool(toolId) {
1506
- return new Tool(this.options, toolId);
1892
+ return new Tool2(this.options, toolId);
1507
1893
  }
1508
1894
  /**
1509
1895
  * Retrieves all available legacy workflows
package/dist/index.d.cts CHANGED
@@ -417,6 +417,7 @@ declare class Agent extends BaseResource {
417
417
  output?: never;
418
418
  experimental_output: T;
419
419
  }): Promise<GenerateReturn<T>>;
420
+ private processChatResponse;
420
421
  /**
421
422
  * Streams a response from the agent
422
423
  * @param params - Stream parameters including prompt
@@ -425,6 +426,10 @@ declare class Agent extends BaseResource {
425
426
  stream<T extends JSONSchema7 | ZodSchema | undefined = undefined>(params: StreamParams<T>): Promise<Response & {
426
427
  processDataStream: (options?: Omit<Parameters<typeof processDataStream>[0], 'stream'>) => Promise<void>;
427
428
  }>;
429
+ /**
430
+ * Processes the stream response and handles tool calls
431
+ */
432
+ private processStreamResponse;
428
433
  /**
429
434
  * Gets details about a specific tool available to the agent
430
435
  * @param toolId - ID of the tool to retrieve
package/dist/index.d.ts CHANGED
@@ -417,6 +417,7 @@ declare class Agent extends BaseResource {
417
417
  output?: never;
418
418
  experimental_output: T;
419
419
  }): Promise<GenerateReturn<T>>;
420
+ private processChatResponse;
420
421
  /**
421
422
  * Streams a response from the agent
422
423
  * @param params - Stream parameters including prompt
@@ -425,6 +426,10 @@ declare class Agent extends BaseResource {
425
426
  stream<T extends JSONSchema7 | ZodSchema | undefined = undefined>(params: StreamParams<T>): Promise<Response & {
426
427
  processDataStream: (options?: Omit<Parameters<typeof processDataStream>[0], 'stream'>) => Promise<void>;
427
428
  }>;
429
+ /**
430
+ * Processes the stream response and handles tool calls
431
+ */
432
+ private processStreamResponse;
428
433
  /**
429
434
  * Gets details about a specific tool available to the agent
430
435
  * @param toolId - ID of the tool to retrieve