@mastra/client-js 1.15.0-alpha.5 → 1.15.0-alpha.6

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # @mastra/client-js
2
2
 
3
+ ## 1.15.0-alpha.6
4
+
5
+ ### Minor Changes
6
+
7
+ - Improved the Mastra A2A client to feel closer to the official A2A SDK without introducing a breaking change. ([#15720](https://github.com/mastra-ai/mastra/pull/15720))
8
+ - Added official-style A2A methods such as `getAgentCard()`, `sendMessageStream()`, `getExtendedAgentCard()`, and `getTaskPushNotificationConfig()`.
9
+ - Added typed A2A stream consumption for `sendMessageStream()` and `resubscribeTask()`.
10
+ - Kept older methods available as deprecated compatibility methods, including `getCard()` and `sendStreamingMessage()`.
11
+
12
+ ### Patch Changes
13
+
14
+ - Fixed Studio observability tabs so runtime-injected observability unlocks them. ([#15821](https://github.com/mastra-ai/mastra/pull/15821))
15
+
16
+ - Updated dependencies [[`c1ae974`](https://github.com/mastra-ai/mastra/commit/c1ae97491f6e57378ce880c3a397778c42adcdf1), [`13b4d7c`](https://github.com/mastra-ai/mastra/commit/13b4d7c16de34dff9095d1cd80f22f544b6cfe75), [`5a4b1ee`](https://github.com/mastra-ai/mastra/commit/5a4b1ee80212969621228104995589c0fa59e575), [`5a4b1ee`](https://github.com/mastra-ai/mastra/commit/5a4b1ee80212969621228104995589c0fa59e575), [`5a4b1ee`](https://github.com/mastra-ai/mastra/commit/5a4b1ee80212969621228104995589c0fa59e575), [`6c8c6c7`](https://github.com/mastra-ai/mastra/commit/6c8c6c71518394321a4692614aa4b11f3bb0a343), [`5a4b1ee`](https://github.com/mastra-ai/mastra/commit/5a4b1ee80212969621228104995589c0fa59e575), [`ec4cb26`](https://github.com/mastra-ai/mastra/commit/ec4cb26919972eb2031fea510f8f013e1d5b7ee2)]:
17
+ - @mastra/core@1.29.0-alpha.6
18
+
3
19
  ## 1.15.0-alpha.5
4
20
 
5
21
  ### Patch Changes
@@ -1671,16 +1671,16 @@ declare interface EventSourceMessage {
1671
1671
  * implementation in that browsers will default this to `message`, whereas this parser will
1672
1672
  * leave this as `undefined` if not explicitly declared.
1673
1673
  */
1674
- event?: string | undefined;
1674
+ event?: string | undefined
1675
1675
  /**
1676
1676
  * ID of the message, if any was provided by the server. Can be used by clients to keep the
1677
1677
  * last received message ID in sync when reconnecting.
1678
1678
  */
1679
- id?: string | undefined;
1679
+ id?: string | undefined
1680
1680
  /**
1681
1681
  * The data received for this message
1682
1682
  */
1683
- data: string;
1683
+ data: string
1684
1684
  }
1685
1685
 
1686
1686
  /**
@@ -1704,11 +1704,8 @@ declare interface EventSourceMessage {
1704
1704
  *
1705
1705
  * @public
1706
1706
  */
1707
- declare class EventSourceParserStream extends TransformStream<
1708
- string,
1709
- EventSourceMessage
1710
- > {
1711
- constructor({ onError, onRetry, onComment }?: StreamOptions);
1707
+ declare class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {
1708
+ constructor({onError, onRetry, onComment}?: StreamOptions)
1712
1709
  }
1713
1710
 
1714
1711
  /**
@@ -8149,19 +8146,19 @@ declare interface StreamOptions {
8149
8146
  *
8150
8147
  * @defaultValue `undefined`
8151
8148
  */
8152
- onError?: ("terminate" | ((error: Error) => void)) | undefined;
8149
+ onError?: ('terminate' | ((error: Error) => void)) | undefined
8153
8150
  /**
8154
8151
  * Callback for when a reconnection interval is sent from the server.
8155
8152
  *
8156
8153
  * @param retry - The number of milliseconds to wait before reconnecting.
8157
8154
  */
8158
- onRetry?: ((retry: number) => void) | undefined;
8155
+ onRetry?: ((retry: number) => void) | undefined
8159
8156
  /**
8160
8157
  * Callback for when a comment is encountered in the stream.
8161
8158
  *
8162
8159
  * @param comment - The comment encountered in the stream.
8163
8160
  */
8164
- onComment?: ((comment: string) => void) | undefined;
8161
+ onComment?: ((comment: string) => void) | undefined
8165
8162
  }
8166
8163
 
8167
8164
  /**
@@ -3,7 +3,7 @@ name: mastra-client-js
3
3
  description: Documentation for @mastra/client-js. Use when working with @mastra/client-js APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/client-js"
6
- version: "1.15.0-alpha.5"
6
+ version: "1.15.0-alpha.6"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.15.0-alpha.5",
2
+ "version": "1.15.0-alpha.6",
3
3
  "package": "@mastra/client-js",
4
4
  "exports": {
5
5
  "RequestContext": {
package/dist/index.cjs CHANGED
@@ -6,6 +6,7 @@ var error = require('@mastra/core/error');
6
6
  var schema = require('@mastra/schema-compat/schema');
7
7
  var requestContext = require('@mastra/core/request-context');
8
8
  var zodToJson = require('@mastra/schema-compat/zod-to-json');
9
+ var a2a = require('@mastra/core/a2a');
9
10
 
10
11
  // src/resources/agent.ts
11
12
  function normalizeRoutePath(path) {
@@ -2628,7 +2629,120 @@ var Workflow = class extends BaseResource {
2628
2629
  }
2629
2630
  };
2630
2631
 
2632
+ // src/utils/process-a2a-stream.ts
2633
+ function splitNextEvent(buffer) {
2634
+ const normalizedBuffer = buffer.replace(/\x1E/g, "\n\n");
2635
+ const match = normalizedBuffer.match(/\r?\n\r?\n/);
2636
+ if (!match || match.index === void 0) {
2637
+ return { rest: normalizedBuffer };
2638
+ }
2639
+ const separatorLength = match[0].length;
2640
+ return {
2641
+ eventBlock: normalizedBuffer.slice(0, match.index),
2642
+ rest: normalizedBuffer.slice(match.index + separatorLength)
2643
+ };
2644
+ }
2645
+ function parseEventBlock(eventBlock) {
2646
+ const trimmedBlock = eventBlock.trim();
2647
+ if (!trimmedBlock) {
2648
+ return {};
2649
+ }
2650
+ const lines = trimmedBlock.split(/\r?\n/);
2651
+ const dataLines = lines.filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart());
2652
+ const payload = dataLines.length > 0 ? dataLines.join("\n") : trimmedBlock;
2653
+ if (!payload || payload === "[DONE]") {
2654
+ return { done: true };
2655
+ }
2656
+ let parsed;
2657
+ try {
2658
+ parsed = JSON.parse(payload);
2659
+ } catch (error) {
2660
+ throw new Error(
2661
+ `Failed to parse A2A stream event: ${error instanceof Error ? error.message : "unknown parse error"}`
2662
+ );
2663
+ }
2664
+ if (parsed && typeof parsed === "object" && "error" in parsed && parsed.error) {
2665
+ throw new MastraClientError(200, "OK", `A2A stream error - ${JSON.stringify(parsed.error)}`, parsed.error);
2666
+ }
2667
+ if (parsed && typeof parsed === "object" && "result" in parsed) {
2668
+ return { event: parsed.result };
2669
+ }
2670
+ return { event: parsed };
2671
+ }
2672
+ async function* processA2AStream(stream) {
2673
+ const reader = stream.getReader();
2674
+ const decoder = new TextDecoder();
2675
+ let buffer = "";
2676
+ try {
2677
+ while (true) {
2678
+ const { done, value } = await reader.read();
2679
+ if (done) {
2680
+ buffer += decoder.decode();
2681
+ } else {
2682
+ buffer += decoder.decode(value, { stream: true });
2683
+ }
2684
+ while (true) {
2685
+ const { eventBlock, rest } = splitNextEvent(buffer);
2686
+ buffer = rest;
2687
+ if (!eventBlock) {
2688
+ break;
2689
+ }
2690
+ const parsedEvent = parseEventBlock(eventBlock);
2691
+ if (parsedEvent.done) {
2692
+ return;
2693
+ }
2694
+ if (parsedEvent.event) {
2695
+ yield parsedEvent.event;
2696
+ }
2697
+ }
2698
+ if (done) {
2699
+ break;
2700
+ }
2701
+ }
2702
+ if (buffer.trim()) {
2703
+ const parsedEvent = parseEventBlock(buffer);
2704
+ if (!parsedEvent.done && parsedEvent.event) {
2705
+ yield parsedEvent.event;
2706
+ }
2707
+ }
2708
+ } finally {
2709
+ reader.releaseLock();
2710
+ }
2711
+ }
2712
+
2631
2713
  // src/resources/a2a.ts
2714
+ function createA2AJsonRpcError(response) {
2715
+ const error = response.error;
2716
+ const message = error?.message ?? "Unknown A2A JSON-RPC error";
2717
+ return typeof error?.code === "number" ? new a2a.MastraA2AError(error.code, message, error.data) : new MastraClientError(200, "OK", `A2A JSON-RPC error - ${message}`, error);
2718
+ }
2719
+ function unwrapA2AResult(response) {
2720
+ if ("error" in response && response.error) {
2721
+ throw createA2AJsonRpcError(response);
2722
+ }
2723
+ if ("result" in response) {
2724
+ return response.result;
2725
+ }
2726
+ throw new MastraClientError(200, "OK", "A2A JSON-RPC response did not include a result", response);
2727
+ }
2728
+ async function requireResponseBody(response, method) {
2729
+ if (response.body) {
2730
+ return response.body;
2731
+ }
2732
+ const headerSummary = Array.from(response.headers.entries()).map(([key, value]) => `${key}: ${value}`).join(", ");
2733
+ let responseText = "";
2734
+ try {
2735
+ responseText = await response.text();
2736
+ } catch {
2737
+ }
2738
+ const details = [
2739
+ `A2A ${method} stream response did not include a body`,
2740
+ `(status: ${response.status} ${response.statusText})`,
2741
+ headerSummary ? `headers: ${headerSummary}` : "",
2742
+ responseText ? `body: ${responseText}` : ""
2743
+ ].filter(Boolean).join(" ");
2744
+ throw new MastraClientError(response.status, response.statusText, details);
2745
+ }
2632
2746
  var A2A = class extends BaseResource {
2633
2747
  constructor(options, agentId) {
2634
2748
  super(options);
@@ -2636,19 +2750,41 @@ var A2A = class extends BaseResource {
2636
2750
  }
2637
2751
  agentId;
2638
2752
  /**
2639
- * Get the agent card with metadata about the agent
2753
+ * Get the agent card with metadata about the agent.
2640
2754
  * @returns Promise containing the agent card information
2641
2755
  */
2642
- async getCard() {
2756
+ async getAgentCard() {
2643
2757
  return this.request(`/.well-known/${this.agentId}/agent-card.json`);
2644
2758
  }
2645
2759
  /**
2646
- * Send a message to the agent and gets a message or task response
2760
+ * @deprecated Use getAgentCard() instead.
2761
+ */
2762
+ async getCard() {
2763
+ return this.getAgentCard();
2764
+ }
2765
+ /**
2766
+ * Get the authenticated extended agent card.
2767
+ * @returns Promise containing the authenticated extended agent card
2768
+ */
2769
+ async getExtendedAgentCard() {
2770
+ const response = await this.request(`/a2a/${this.agentId}`, {
2771
+ method: "POST",
2772
+ body: {
2773
+ jsonrpc: "2.0",
2774
+ id: crypto.randomUUID(),
2775
+ method: "agent/getAuthenticatedExtendedCard"
2776
+ }
2777
+ });
2778
+ return unwrapA2AResult(response);
2779
+ }
2780
+ /**
2781
+ * @deprecated Use sendMessageStream() for the streaming experience.
2782
+ * Send a message to the agent and gets a message or task response.
2647
2783
  * @param params - Parameters for the task
2648
- * @returns Promise containing the response
2784
+ * @returns Promise containing the JSON-RPC response envelope
2649
2785
  */
2650
2786
  async sendMessage(params) {
2651
- const response = await this.request(`/a2a/${this.agentId}`, {
2787
+ return this.request(`/a2a/${this.agentId}`, {
2652
2788
  method: "POST",
2653
2789
  body: {
2654
2790
  jsonrpc: "2.0",
@@ -2657,15 +2793,14 @@ var A2A = class extends BaseResource {
2657
2793
  params
2658
2794
  }
2659
2795
  });
2660
- return response;
2661
2796
  }
2662
2797
  /**
2663
- * Sends a message to an agent to initiate/continue a task and subscribes
2798
+ * Sends a message to an agent to initiate or continue a task and subscribes
2664
2799
  * the client to real-time updates for that task via Server-Sent Events (SSE).
2665
2800
  * @param params - Parameters for the task
2666
- * @returns A stream of Server-Sent Events. Each SSE `data` field contains a `SendStreamingMessageResponse`
2801
+ * @returns An async generator of typed A2A stream events
2667
2802
  */
2668
- async sendStreamingMessage(params) {
2803
+ async *sendMessageStream(params) {
2669
2804
  const response = await this.request(`/a2a/${this.agentId}`, {
2670
2805
  method: "POST",
2671
2806
  body: {
@@ -2676,15 +2811,31 @@ var A2A = class extends BaseResource {
2676
2811
  },
2677
2812
  stream: true
2678
2813
  });
2679
- return response;
2814
+ yield* processA2AStream(await requireResponseBody(response, "message/stream"));
2680
2815
  }
2681
2816
  /**
2682
- * Get the status and result of a task
2817
+ * @deprecated Use sendMessageStream() instead.
2818
+ */
2819
+ async sendStreamingMessage(params) {
2820
+ return this.request(`/a2a/${this.agentId}`, {
2821
+ method: "POST",
2822
+ body: {
2823
+ jsonrpc: "2.0",
2824
+ id: crypto.randomUUID(),
2825
+ method: "message/stream",
2826
+ params
2827
+ },
2828
+ stream: true
2829
+ });
2830
+ }
2831
+ /**
2832
+ * @deprecated
2833
+ * Get the status and result of a task.
2683
2834
  * @param params - Parameters for querying the task
2684
- * @returns Promise containing the task response
2835
+ * @returns Promise containing the JSON-RPC response envelope
2685
2836
  */
2686
2837
  async getTask(params) {
2687
- const response = await this.request(`/a2a/${this.agentId}`, {
2838
+ return this.request(`/a2a/${this.agentId}`, {
2688
2839
  method: "POST",
2689
2840
  body: {
2690
2841
  jsonrpc: "2.0",
@@ -2693,10 +2844,10 @@ var A2A = class extends BaseResource {
2693
2844
  params
2694
2845
  }
2695
2846
  });
2696
- return response;
2697
2847
  }
2698
2848
  /**
2699
- * Cancel a running task
2849
+ * @deprecated
2850
+ * Cancel a running task.
2700
2851
  * @param params - Parameters identifying the task to cancel
2701
2852
  * @returns Promise containing the task response
2702
2853
  */
@@ -2711,6 +2862,92 @@ var A2A = class extends BaseResource {
2711
2862
  }
2712
2863
  });
2713
2864
  }
2865
+ /**
2866
+ * Resume a task stream for an existing task.
2867
+ * @param params - Parameters identifying the task to resubscribe to
2868
+ * @returns An async generator of typed A2A stream events
2869
+ */
2870
+ async *resubscribeTask(params) {
2871
+ const response = await this.request(`/a2a/${this.agentId}`, {
2872
+ method: "POST",
2873
+ body: {
2874
+ jsonrpc: "2.0",
2875
+ id: crypto.randomUUID(),
2876
+ method: "tasks/resubscribe",
2877
+ params
2878
+ },
2879
+ stream: true
2880
+ });
2881
+ yield* processA2AStream(await requireResponseBody(response, "tasks/resubscribe"));
2882
+ }
2883
+ /**
2884
+ * Set push notification config for a task.
2885
+ * @param params - Push notification configuration for the task
2886
+ * @returns Promise containing the push notification configuration
2887
+ */
2888
+ async setTaskPushNotificationConfig(params) {
2889
+ const response = await this.request(`/a2a/${this.agentId}`, {
2890
+ method: "POST",
2891
+ body: {
2892
+ jsonrpc: "2.0",
2893
+ id: crypto.randomUUID(),
2894
+ method: "tasks/pushNotificationConfig/set",
2895
+ params
2896
+ }
2897
+ });
2898
+ return unwrapA2AResult(response);
2899
+ }
2900
+ /**
2901
+ * Get push notification config for a task.
2902
+ * @param params - Parameters identifying the task
2903
+ * @returns Promise containing the push notification configuration
2904
+ */
2905
+ async getTaskPushNotificationConfig(params) {
2906
+ const response = await this.request(`/a2a/${this.agentId}`, {
2907
+ method: "POST",
2908
+ body: {
2909
+ jsonrpc: "2.0",
2910
+ id: crypto.randomUUID(),
2911
+ method: "tasks/pushNotificationConfig/get",
2912
+ params
2913
+ }
2914
+ });
2915
+ return unwrapA2AResult(response);
2916
+ }
2917
+ /**
2918
+ * List push notification configs for a task.
2919
+ * @param params - Parameters identifying the task
2920
+ * @returns Promise containing the push notification configurations
2921
+ */
2922
+ async listTaskPushNotificationConfig(params) {
2923
+ const response = await this.request(`/a2a/${this.agentId}`, {
2924
+ method: "POST",
2925
+ body: {
2926
+ jsonrpc: "2.0",
2927
+ id: crypto.randomUUID(),
2928
+ method: "tasks/pushNotificationConfig/list",
2929
+ params
2930
+ }
2931
+ });
2932
+ return unwrapA2AResult(response);
2933
+ }
2934
+ /**
2935
+ * Delete a push notification config for a task.
2936
+ * @param params - Parameters identifying the config to delete
2937
+ * @returns Promise that resolves when the config is deleted
2938
+ */
2939
+ async deleteTaskPushNotificationConfig(params) {
2940
+ const response = await this.request(`/a2a/${this.agentId}`, {
2941
+ method: "POST",
2942
+ body: {
2943
+ jsonrpc: "2.0",
2944
+ id: crypto.randomUUID(),
2945
+ method: "tasks/pushNotificationConfig/delete",
2946
+ params
2947
+ }
2948
+ });
2949
+ unwrapA2AResult(response);
2950
+ }
2714
2951
  };
2715
2952
 
2716
2953
  // src/resources/mcp-tool.ts