@mastra/client-js 0.0.0-bundle-dynamic-imports-20250424001248 → 0.0.0-cloud-transporter-20250513033346

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/client-js",
3
- "version": "0.0.0-bundle-dynamic-imports-20250424001248",
3
+ "version": "0.0.0-cloud-transporter-20250513033346",
4
4
  "description": "The official TypeScript library for the Mastra Client API",
5
5
  "author": "",
6
6
  "type": "module",
@@ -22,14 +22,16 @@
22
22
  "repository": "github:mastra-ai/client-js",
23
23
  "license": "Elastic-2.0",
24
24
  "dependencies": {
25
+ "@ag-ui/client": "^0.0.27",
25
26
  "@ai-sdk/ui-utils": "^1.1.19",
26
27
  "json-schema": "^0.4.0",
27
- "zod": "^3.24.2",
28
- "zod-to-json-schema": "^3.24.3",
29
- "@mastra/core": "0.0.0-bundle-dynamic-imports-20250424001248"
28
+ "rxjs": "7.8.1",
29
+ "zod": "^3.24.3",
30
+ "zod-to-json-schema": "^3.24.5",
31
+ "@mastra/core": "0.0.0-cloud-transporter-20250513033346"
30
32
  },
31
33
  "peerDependencies": {
32
- "zod": "^3.24.2"
34
+ "zod": "^3.0.0"
33
35
  },
34
36
  "devDependencies": {
35
37
  "@babel/preset-env": "^7.26.9",
@@ -39,8 +41,8 @@
39
41
  "@types/node": "^20.17.27",
40
42
  "tsup": "^8.4.0",
41
43
  "typescript": "^5.8.2",
42
- "vitest": "^3.0.9",
43
- "@internal/lint": "0.0.2"
44
+ "vitest": "^3.1.2",
45
+ "@internal/lint": "0.0.0-cloud-transporter-20250513033346"
44
46
  },
45
47
  "scripts": {
46
48
  "build": "tsup src/index.ts --format esm,cjs --dts --clean --treeshake=smallest --splitting",
@@ -0,0 +1,180 @@
1
+ import type { Message } from '@ag-ui/client';
2
+ import { describe, it, expect } from 'vitest';
3
+ import { generateUUID, convertMessagesToMastraMessages } from './agui';
4
+
5
+ describe('generateUUID', () => {
6
+ it('should generate a valid UUID v4 string', () => {
7
+ const uuid = generateUUID();
8
+ // Check UUID format (8-4-4-4-12 hex digits)
9
+ expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
10
+ });
11
+
12
+ it('should generate unique UUIDs', () => {
13
+ const uuids = new Set();
14
+ for (let i = 0; i < 100; i++) {
15
+ uuids.add(generateUUID());
16
+ }
17
+ // All UUIDs should be unique
18
+ expect(uuids.size).toBe(100);
19
+ });
20
+ });
21
+
22
+ describe('convertMessagesToMastraMessages', () => {
23
+ it('should convert user messages correctly', () => {
24
+ const messages: Message[] = [
25
+ {
26
+ id: '1',
27
+ role: 'user',
28
+ content: 'Hello, world!',
29
+ },
30
+ ];
31
+
32
+ const result = convertMessagesToMastraMessages(messages);
33
+
34
+ expect(result).toEqual([
35
+ {
36
+ role: 'user',
37
+ content: 'Hello, world!',
38
+ },
39
+ ]);
40
+ });
41
+
42
+ it('should convert assistant messages correctly', () => {
43
+ const messages: Message[] = [
44
+ {
45
+ id: '1',
46
+ role: 'assistant',
47
+ content: 'Hello, I am an assistant',
48
+ },
49
+ ];
50
+
51
+ const result = convertMessagesToMastraMessages(messages);
52
+
53
+ expect(result).toEqual([
54
+ {
55
+ role: 'assistant',
56
+ content: [{ type: 'text', text: 'Hello, I am an assistant' }],
57
+ },
58
+ ]);
59
+ });
60
+
61
+ it('should convert assistant messages with tool calls correctly', () => {
62
+ const messages: Message[] = [
63
+ {
64
+ id: '1',
65
+ role: 'assistant',
66
+ content: undefined,
67
+ toolCalls: [
68
+ {
69
+ id: 'tool-call-1',
70
+ type: 'function',
71
+ function: {
72
+ name: 'getWeather',
73
+ arguments: '{"location":"San Francisco"}',
74
+ },
75
+ },
76
+ ],
77
+ },
78
+ ];
79
+
80
+ const result = convertMessagesToMastraMessages(messages);
81
+
82
+ expect(result).toEqual([
83
+ {
84
+ role: 'assistant',
85
+ content: [
86
+ {
87
+ type: 'tool-call',
88
+ toolCallId: 'tool-call-1',
89
+ toolName: 'getWeather',
90
+ args: { location: 'San Francisco' },
91
+ },
92
+ ],
93
+ },
94
+ {
95
+ role: 'tool',
96
+ content: [
97
+ {
98
+ type: 'tool-result',
99
+ toolCallId: 'tool-call-1',
100
+ toolName: 'getWeather',
101
+ result: { location: 'San Francisco' },
102
+ },
103
+ ],
104
+ },
105
+ ]);
106
+ });
107
+
108
+ it('should convert tool messages correctly', () => {
109
+ const messages: Message[] = [
110
+ {
111
+ id: '1',
112
+ role: 'tool',
113
+ toolCallId: 'tool-call-1',
114
+ content: '{"temperature":72,"unit":"F"}',
115
+ },
116
+ ];
117
+
118
+ const result = convertMessagesToMastraMessages(messages);
119
+
120
+ expect(result).toEqual([
121
+ {
122
+ role: 'tool',
123
+ content: [
124
+ {
125
+ type: 'tool-result',
126
+ toolCallId: 'tool-call-1',
127
+ toolName: 'unknown',
128
+ result: '{"temperature":72,"unit":"F"}',
129
+ },
130
+ ],
131
+ },
132
+ ]);
133
+ });
134
+
135
+ it('should convert a complex conversation correctly', () => {
136
+ const messages: Message[] = [
137
+ {
138
+ id: '1',
139
+ role: 'user',
140
+ content: "What's the weather in San Francisco?",
141
+ },
142
+ {
143
+ id: '2',
144
+ role: 'assistant',
145
+ content: undefined,
146
+ toolCalls: [
147
+ {
148
+ id: 'tool-call-1',
149
+ type: 'function',
150
+ function: {
151
+ name: 'getWeather',
152
+ arguments: '{"location":"San Francisco"}',
153
+ },
154
+ },
155
+ ],
156
+ },
157
+ {
158
+ id: '4',
159
+ role: 'assistant',
160
+ content: 'The weather in San Francisco is 72°F.',
161
+ },
162
+ ];
163
+
164
+ const result = convertMessagesToMastraMessages(messages);
165
+
166
+ expect(result).toHaveLength(4);
167
+ expect(result[0].role).toBe('user');
168
+ expect(result[1].role).toBe('assistant');
169
+ expect(result[2].role).toBe('tool');
170
+ expect(result[2].content).toEqual([
171
+ {
172
+ type: 'tool-result',
173
+ toolCallId: 'tool-call-1',
174
+ toolName: 'getWeather',
175
+ result: { location: 'San Francisco' },
176
+ },
177
+ ]);
178
+ expect(result[3].role).toBe('assistant');
179
+ });
180
+ });
@@ -0,0 +1,239 @@
1
+ // Cross-platform UUID generation function
2
+ import type {
3
+ AgentConfig,
4
+ BaseEvent,
5
+ Message,
6
+ RunAgentInput,
7
+ RunFinishedEvent,
8
+ RunStartedEvent,
9
+ TextMessageContentEvent,
10
+ TextMessageEndEvent,
11
+ TextMessageStartEvent,
12
+ ToolCallArgsEvent,
13
+ ToolCallEndEvent,
14
+ ToolCallStartEvent,
15
+ } from '@ag-ui/client';
16
+ import { AbstractAgent, EventType } from '@ag-ui/client';
17
+ import type { CoreMessage } from '@mastra/core';
18
+ import { Observable } from 'rxjs';
19
+ import type { Agent } from '../resources/agent';
20
+
21
+ interface MastraAgentConfig extends AgentConfig {
22
+ agent: Agent;
23
+ agentId: string;
24
+ resourceId?: string;
25
+ }
26
+
27
+ export class AGUIAdapter extends AbstractAgent {
28
+ agent: Agent;
29
+ resourceId?: string;
30
+ constructor({ agent, agentId, resourceId, ...rest }: MastraAgentConfig) {
31
+ super({
32
+ agentId,
33
+ ...rest,
34
+ });
35
+ this.agent = agent;
36
+ this.resourceId = resourceId;
37
+ }
38
+
39
+ protected run(input: RunAgentInput): Observable<BaseEvent> {
40
+ return new Observable<BaseEvent>(subscriber => {
41
+ const convertedMessages = convertMessagesToMastraMessages(input.messages);
42
+ subscriber.next({
43
+ type: EventType.RUN_STARTED,
44
+ threadId: input.threadId,
45
+ runId: input.runId,
46
+ } as RunStartedEvent);
47
+
48
+ this.agent
49
+ .stream({
50
+ threadId: input.threadId,
51
+ resourceId: this.resourceId ?? '',
52
+ runId: input.runId,
53
+ messages: convertedMessages,
54
+ clientTools: input.tools.reduce(
55
+ (acc, tool) => {
56
+ acc[tool.name as string] = {
57
+ id: tool.name,
58
+ description: tool.description,
59
+ inputSchema: tool.parameters,
60
+ };
61
+ return acc;
62
+ },
63
+ {} as Record<string, any>,
64
+ ),
65
+ })
66
+ .then(response => {
67
+ let currentMessageId: string | undefined = undefined;
68
+ let isInTextMessage = false;
69
+ return response.processDataStream({
70
+ onTextPart: text => {
71
+ if (currentMessageId === undefined) {
72
+ currentMessageId = generateUUID();
73
+ const message: TextMessageStartEvent = {
74
+ type: EventType.TEXT_MESSAGE_START,
75
+ messageId: currentMessageId,
76
+ role: 'assistant',
77
+ };
78
+ subscriber.next(message);
79
+ isInTextMessage = true;
80
+ }
81
+
82
+ const message: TextMessageContentEvent = {
83
+ type: EventType.TEXT_MESSAGE_CONTENT,
84
+ messageId: currentMessageId,
85
+ delta: text,
86
+ };
87
+ subscriber.next(message);
88
+ },
89
+ onFinishMessagePart: () => {
90
+ if (currentMessageId !== undefined) {
91
+ const message: TextMessageEndEvent = {
92
+ type: EventType.TEXT_MESSAGE_END,
93
+ messageId: currentMessageId,
94
+ };
95
+ subscriber.next(message);
96
+ isInTextMessage = false;
97
+ }
98
+ // Emit run finished event
99
+ subscriber.next({
100
+ type: EventType.RUN_FINISHED,
101
+ threadId: input.threadId,
102
+ runId: input.runId,
103
+ } as RunFinishedEvent);
104
+
105
+ // Complete the observable
106
+ subscriber.complete();
107
+ },
108
+ onToolCallPart(streamPart) {
109
+ const parentMessageId = currentMessageId || generateUUID();
110
+ if (isInTextMessage) {
111
+ const message: TextMessageEndEvent = {
112
+ type: EventType.TEXT_MESSAGE_END,
113
+ messageId: parentMessageId,
114
+ };
115
+ subscriber.next(message);
116
+ isInTextMessage = false;
117
+ }
118
+
119
+ subscriber.next({
120
+ type: EventType.TOOL_CALL_START,
121
+ toolCallId: streamPart.toolCallId,
122
+ toolCallName: streamPart.toolName,
123
+ parentMessageId,
124
+ } as ToolCallStartEvent);
125
+
126
+ subscriber.next({
127
+ type: EventType.TOOL_CALL_ARGS,
128
+ toolCallId: streamPart.toolCallId,
129
+ delta: JSON.stringify(streamPart.args),
130
+ parentMessageId,
131
+ } as ToolCallArgsEvent);
132
+
133
+ subscriber.next({
134
+ type: EventType.TOOL_CALL_END,
135
+ toolCallId: streamPart.toolCallId,
136
+ parentMessageId,
137
+ } as ToolCallEndEvent);
138
+ },
139
+ });
140
+ })
141
+ .catch(error => {
142
+ console.error('error', error);
143
+ // Handle error
144
+ subscriber.error(error);
145
+ });
146
+
147
+ return () => {};
148
+ });
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Generates a UUID v4 that works in both browser and Node.js environments
154
+ */
155
+ export function generateUUID(): string {
156
+ // Use crypto.randomUUID() if available (Node.js environment or modern browsers)
157
+ if (typeof crypto !== 'undefined') {
158
+ // Browser crypto API or Node.js crypto global
159
+ if (typeof crypto.randomUUID === 'function') {
160
+ return crypto.randomUUID();
161
+ }
162
+ // Fallback for older browsers
163
+ if (typeof crypto.getRandomValues === 'function') {
164
+ const buffer = new Uint8Array(16);
165
+ crypto.getRandomValues(buffer);
166
+ // Set version (4) and variant (8, 9, A, or B)
167
+ buffer[6] = (buffer[6]! & 0x0f) | 0x40; // version 4
168
+ buffer[8] = (buffer[8]! & 0x3f) | 0x80; // variant
169
+
170
+ // Convert to hex string in UUID format
171
+ let hex = '';
172
+ for (let i = 0; i < 16; i++) {
173
+ hex += buffer[i]!.toString(16).padStart(2, '0');
174
+ // Add hyphens at standard positions
175
+ if (i === 3 || i === 5 || i === 7 || i === 9) hex += '-';
176
+ }
177
+ return hex;
178
+ }
179
+ }
180
+
181
+ // Last resort fallback (less secure but works everywhere)
182
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
183
+ const r = (Math.random() * 16) | 0;
184
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
185
+ return v.toString(16);
186
+ });
187
+ }
188
+
189
+ export function convertMessagesToMastraMessages(messages: Message[]): CoreMessage[] {
190
+ const result: CoreMessage[] = [];
191
+
192
+ for (const message of messages) {
193
+ if (message.role === 'assistant') {
194
+ const parts: any[] = message.content ? [{ type: 'text', text: message.content }] : [];
195
+ for (const toolCall of message.toolCalls ?? []) {
196
+ parts.push({
197
+ type: 'tool-call',
198
+ toolCallId: toolCall.id,
199
+ toolName: toolCall.function.name,
200
+ args: JSON.parse(toolCall.function.arguments),
201
+ });
202
+ }
203
+ result.push({
204
+ role: 'assistant',
205
+ content: parts,
206
+ });
207
+ if (message.toolCalls?.length) {
208
+ result.push({
209
+ role: 'tool',
210
+ content: message.toolCalls.map(toolCall => ({
211
+ type: 'tool-result',
212
+ toolCallId: toolCall.id,
213
+ toolName: toolCall.function.name,
214
+ result: JSON.parse(toolCall.function.arguments),
215
+ })),
216
+ });
217
+ }
218
+ } else if (message.role === 'user') {
219
+ result.push({
220
+ role: 'user',
221
+ content: message.content || '',
222
+ });
223
+ } else if (message.role === 'tool') {
224
+ result.push({
225
+ role: 'tool',
226
+ content: [
227
+ {
228
+ type: 'tool-result',
229
+ toolCallId: message.toolCallId,
230
+ toolName: 'unknown',
231
+ result: message.content,
232
+ },
233
+ ],
234
+ });
235
+ }
236
+ }
237
+
238
+ return result;
239
+ }
package/src/client.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { Agent, MemoryThread, Tool, Workflow, Vector, BaseResource, Network } from './resources';
1
+ import type { AbstractAgent } from '@ag-ui/client';
2
+ import { AGUIAdapter } from './adapters/agui';
3
+ import { Agent, MemoryThread, Tool, Workflow, Vector, BaseResource, Network, VNextWorkflow, A2A } from './resources';
2
4
  import type {
3
5
  ClientOptions,
4
6
  CreateMemoryThreadParams,
@@ -13,6 +15,7 @@ import type {
13
15
  GetTelemetryParams,
14
16
  GetTelemetryResponse,
15
17
  GetToolResponse,
18
+ GetVNextWorkflowResponse,
16
19
  GetWorkflowResponse,
17
20
  SaveMessageToMemoryParams,
18
21
  SaveMessageToMemoryResponse,
@@ -31,6 +34,25 @@ export class MastraClient extends BaseResource {
31
34
  return this.request('/api/agents');
32
35
  }
33
36
 
37
+ public async getAGUI({ resourceId }: { resourceId: string }): Promise<Record<string, AbstractAgent>> {
38
+ const agents = await this.getAgents();
39
+
40
+ return Object.entries(agents).reduce(
41
+ (acc, [agentId]) => {
42
+ const agent = this.getAgent(agentId);
43
+
44
+ acc[agentId] = new AGUIAdapter({
45
+ agentId,
46
+ agent,
47
+ resourceId,
48
+ });
49
+
50
+ return acc;
51
+ },
52
+ {} as Record<string, AbstractAgent>,
53
+ );
54
+ }
55
+
34
56
  /**
35
57
  * Gets an agent instance by ID
36
58
  * @param agentId - ID of the agent to retrieve
@@ -121,6 +143,23 @@ export class MastraClient extends BaseResource {
121
143
  return new Workflow(this.options, workflowId);
122
144
  }
123
145
 
146
+ /**
147
+ * Retrieves all available vNext workflows
148
+ * @returns Promise containing map of vNext workflow IDs to vNext workflow details
149
+ */
150
+ public getVNextWorkflows(): Promise<Record<string, GetVNextWorkflowResponse>> {
151
+ return this.request('/api/workflows/v-next');
152
+ }
153
+
154
+ /**
155
+ * Gets a vNext workflow instance by ID
156
+ * @param workflowId - ID of the vNext workflow to retrieve
157
+ * @returns vNext Workflow instance
158
+ */
159
+ public getVNextWorkflow(workflowId: string) {
160
+ return new VNextWorkflow(this.options, workflowId);
161
+ }
162
+
124
163
  /**
125
164
  * Gets a vector instance by name
126
165
  * @param vectorName - Name of the vector to retrieve
@@ -162,7 +201,7 @@ export class MastraClient extends BaseResource {
162
201
  * @returns Promise containing telemetry data
163
202
  */
164
203
  public getTelemetry(params?: GetTelemetryParams): Promise<GetTelemetryResponse> {
165
- const { name, scope, page, perPage, attribute } = params || {};
204
+ const { name, scope, page, perPage, attribute, fromDate, toDate } = params || {};
166
205
  const _attribute = attribute ? Object.entries(attribute).map(([key, value]) => `${key}:${value}`) : [];
167
206
 
168
207
  const searchParams = new URLSearchParams();
@@ -187,6 +226,12 @@ export class MastraClient extends BaseResource {
187
226
  searchParams.set('attribute', _attribute);
188
227
  }
189
228
  }
229
+ if (fromDate) {
230
+ searchParams.set('fromDate', fromDate.toISOString());
231
+ }
232
+ if (toDate) {
233
+ searchParams.set('toDate', toDate.toISOString());
234
+ }
190
235
 
191
236
  if (searchParams.size) {
192
237
  return this.request(`/api/telemetry?${searchParams}`);
@@ -211,4 +256,13 @@ export class MastraClient extends BaseResource {
211
256
  public getNetwork(networkId: string) {
212
257
  return new Network(this.options, networkId);
213
258
  }
259
+
260
+ /**
261
+ * Gets an A2A client for interacting with an agent via the A2A protocol
262
+ * @param agentId - ID of the agent to interact with
263
+ * @returns A2A client instance
264
+ */
265
+ public getA2A(agentId: string) {
266
+ return new A2A(this.options, agentId);
267
+ }
214
268
  }
package/src/index.test.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { MessageType } from '@mastra/core';
2
1
  import { describe, expect, beforeEach, it, vi } from 'vitest';
3
2
 
4
3
  import { MastraClient } from './client';
@@ -237,6 +236,7 @@ describe('MastraClient Resources', () => {
237
236
  model: 'gpt-4',
238
237
  instructions: 'Test instructions',
239
238
  tools: {},
239
+ workflows: {},
240
240
  };
241
241
  mockFetchResponse(mockResponse);
242
242
 
@@ -489,7 +489,7 @@ describe('MastraClient Resources', () => {
489
489
  const result = await memoryThread.update({
490
490
  title: 'Updated Thread',
491
491
  metadata: { updated: true },
492
- resourceid: 'test-resource',
492
+ resourceId: 'test-resource',
493
493
  });
494
494
  expect(result).toEqual(mockResponse);
495
495
  expect(global.fetch).toHaveBeenCalledWith(
@@ -536,6 +536,7 @@ describe('MastraClient Resources', () => {
536
536
  content: 'test',
537
537
  role: 'user' as const,
538
538
  threadId: 'test-thread',
539
+ resourceId: 'test-resource',
539
540
  createdAt: new Date('2025-03-26T10:40:55.116Z'),
540
541
  },
541
542
  ];
@@ -552,6 +553,35 @@ describe('MastraClient Resources', () => {
552
553
  }),
553
554
  );
554
555
  });
556
+
557
+ it('should get thread messages with limit', async () => {
558
+ const mockResponse = {
559
+ messages: [
560
+ {
561
+ id: '1',
562
+ content: 'test',
563
+ threadId,
564
+ role: 'user',
565
+ type: 'text',
566
+ resourceId: 'test-resource',
567
+ createdAt: new Date(),
568
+ },
569
+ ],
570
+ uiMessages: [],
571
+ };
572
+ mockFetchResponse(mockResponse);
573
+
574
+ const limit = 5;
575
+ const result = await memoryThread.getMessages({ limit });
576
+
577
+ expect(result).toEqual(mockResponse);
578
+ expect(global.fetch).toHaveBeenCalledWith(
579
+ `${clientOptions.baseUrl}/api/memory/threads/${threadId}/messages?agentId=${agentId}&limit=${limit}`,
580
+ expect.objectContaining({
581
+ headers: expect.objectContaining(clientOptions.headers),
582
+ }),
583
+ );
584
+ });
555
585
  });
556
586
 
557
587
  describe('Tool Resource', () => {
@@ -584,10 +614,10 @@ describe('MastraClient Resources', () => {
584
614
  it('should execute tool', async () => {
585
615
  const mockResponse = { data: 'test' };
586
616
  mockFetchResponse(mockResponse);
587
- const result = await tool.execute({ data: '' });
617
+ const result = await tool.execute({ data: '', runId: 'test-run-id' });
588
618
  expect(result).toEqual(mockResponse);
589
619
  expect(global.fetch).toHaveBeenCalledWith(
590
- `${clientOptions.baseUrl}/api/tools/test-tool/execute`,
620
+ `${clientOptions.baseUrl}/api/tools/test-tool/execute?runId=test-run-id`,
591
621
  expect.objectContaining({
592
622
  method: 'POST',
593
623
  headers: expect.objectContaining({