@mastra/client-js 0.0.0-trigger-playground-ui-package-20250506151043 → 0.0.0-tsconfig-compile-20250703214351

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.
@@ -0,0 +1,177 @@
1
+ import type { WatchEvent } from '@mastra/core/workflows';
2
+
3
+ import type {
4
+ ClientOptions,
5
+ GetVNextNetworkResponse,
6
+ GenerateVNextNetworkResponse,
7
+ LoopVNextNetworkResponse,
8
+ GenerateOrStreamVNextNetworkParams,
9
+ LoopStreamVNextNetworkParams,
10
+ } from '../types';
11
+
12
+ import { BaseResource } from './base';
13
+
14
+ const RECORD_SEPARATOR = '\x1E';
15
+
16
+ export class VNextNetwork extends BaseResource {
17
+ constructor(
18
+ options: ClientOptions,
19
+ private networkId: string,
20
+ ) {
21
+ super(options);
22
+ }
23
+
24
+ /**
25
+ * Retrieves details about the network
26
+ * @returns Promise containing vNext network details
27
+ */
28
+ details(): Promise<GetVNextNetworkResponse> {
29
+ return this.request(`/api/networks/v-next/${this.networkId}`);
30
+ }
31
+
32
+ /**
33
+ * Generates a response from the v-next network
34
+ * @param params - Generation parameters including message
35
+ * @returns Promise containing the generated response
36
+ */
37
+ generate(params: GenerateOrStreamVNextNetworkParams): Promise<GenerateVNextNetworkResponse> {
38
+ return this.request(`/api/networks/v-next/${this.networkId}/generate`, {
39
+ method: 'POST',
40
+ body: params,
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Generates a response from the v-next network using multiple primitives
46
+ * @param params - Generation parameters including message
47
+ * @returns Promise containing the generated response
48
+ */
49
+ loop(params: { message: string }): Promise<LoopVNextNetworkResponse> {
50
+ return this.request(`/api/networks/v-next/${this.networkId}/loop`, {
51
+ method: 'POST',
52
+ body: params,
53
+ });
54
+ }
55
+
56
+ private async *streamProcessor(stream: ReadableStream): AsyncGenerator<WatchEvent, void, unknown> {
57
+ const reader = stream.getReader();
58
+
59
+ // Track if we've finished reading from the stream
60
+ let doneReading = false;
61
+ // Buffer to accumulate partial chunks
62
+ let buffer = '';
63
+
64
+ try {
65
+ while (!doneReading) {
66
+ // Read the next chunk from the stream
67
+ const { done, value } = await reader.read();
68
+ doneReading = done;
69
+
70
+ // Skip processing if we're done and there's no value
71
+ if (done && !value) continue;
72
+
73
+ try {
74
+ // Decode binary data to text
75
+ const decoded = value ? new TextDecoder().decode(value) : '';
76
+
77
+ // Split the combined buffer and new data by record separator
78
+ const chunks = (buffer + decoded).split(RECORD_SEPARATOR);
79
+
80
+ // The last chunk might be incomplete, so save it for the next iteration
81
+ buffer = chunks.pop() || '';
82
+
83
+ // Process complete chunks
84
+ for (const chunk of chunks) {
85
+ if (chunk) {
86
+ // Only process non-empty chunks
87
+ if (typeof chunk === 'string') {
88
+ try {
89
+ const parsedChunk = JSON.parse(chunk);
90
+ yield parsedChunk;
91
+ } catch {
92
+ // Silently ignore parsing errors to maintain stream processing
93
+ // This allows the stream to continue even if one record is malformed
94
+ }
95
+ }
96
+ }
97
+ }
98
+ } catch {
99
+ // Silently ignore parsing errors to maintain stream processing
100
+ // This allows the stream to continue even if one record is malformed
101
+ }
102
+ }
103
+
104
+ // Process any remaining data in the buffer after stream is done
105
+ if (buffer) {
106
+ try {
107
+ yield JSON.parse(buffer);
108
+ } catch {
109
+ // Ignore parsing error for final chunk
110
+ }
111
+ }
112
+ } finally {
113
+ // Always ensure we clean up the reader
114
+ reader.cancel().catch(() => {
115
+ // Ignore cancel errors
116
+ });
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Streams a response from the v-next network
122
+ * @param params - Stream parameters including message
123
+ * @returns Promise containing the results
124
+ */
125
+ async stream(params: GenerateOrStreamVNextNetworkParams, onRecord: (record: WatchEvent) => void) {
126
+ const response: Response = await this.request(`/api/networks/v-next/${this.networkId}/stream`, {
127
+ method: 'POST',
128
+ body: params,
129
+ stream: true,
130
+ });
131
+
132
+ if (!response.ok) {
133
+ throw new Error(`Failed to stream vNext network: ${response.statusText}`);
134
+ }
135
+
136
+ if (!response.body) {
137
+ throw new Error('Response body is null');
138
+ }
139
+
140
+ for await (const record of this.streamProcessor(response.body)) {
141
+ if (typeof record === 'string') {
142
+ onRecord(JSON.parse(record));
143
+ } else {
144
+ onRecord(record);
145
+ }
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Streams a response from the v-next network loop
151
+ * @param params - Stream parameters including message
152
+ * @returns Promise containing the results
153
+ */
154
+ async loopStream(params: LoopStreamVNextNetworkParams, onRecord: (record: WatchEvent) => void) {
155
+ const response: Response = await this.request(`/api/networks/v-next/${this.networkId}/loop-stream`, {
156
+ method: 'POST',
157
+ body: params,
158
+ stream: true,
159
+ });
160
+
161
+ if (!response.ok) {
162
+ throw new Error(`Failed to stream vNext network loop: ${response.statusText}`);
163
+ }
164
+
165
+ if (!response.body) {
166
+ throw new Error('Response body is null');
167
+ }
168
+
169
+ for await (const record of this.streamProcessor(response.body)) {
170
+ if (typeof record === 'string') {
171
+ onRecord(JSON.parse(record));
172
+ } else {
173
+ onRecord(record);
174
+ }
175
+ }
176
+ }
177
+ }
@@ -1,11 +1,16 @@
1
+ import type { RuntimeContext } from '@mastra/core/runtime-context';
1
2
  import type {
2
- GetWorkflowResponse,
3
3
  ClientOptions,
4
- WorkflowRunResult,
4
+ GetWorkflowResponse,
5
5
  GetWorkflowRunsResponse,
6
6
  GetWorkflowRunsParams,
7
+ WorkflowRunResult,
8
+ WorkflowWatchResult,
9
+ GetWorkflowRunByIdResponse,
10
+ GetWorkflowRunExecutionResultResponse,
7
11
  } from '../types';
8
12
 
13
+ import { parseClientRuntimeContext } from '../utils';
9
14
  import { BaseResource } from './base';
10
15
 
11
16
  const RECORD_SEPARATOR = '\x1E';
@@ -18,6 +23,77 @@ export class Workflow extends BaseResource {
18
23
  super(options);
19
24
  }
20
25
 
26
+ /**
27
+ * Creates an async generator that processes a readable stream and yields workflow records
28
+ * separated by the Record Separator character (\x1E)
29
+ *
30
+ * @param stream - The readable stream to process
31
+ * @returns An async generator that yields parsed records
32
+ */
33
+ private async *streamProcessor(stream: ReadableStream): AsyncGenerator<WorkflowWatchResult, void, unknown> {
34
+ const reader = stream.getReader();
35
+
36
+ // Track if we've finished reading from the stream
37
+ let doneReading = false;
38
+ // Buffer to accumulate partial chunks
39
+ let buffer = '';
40
+
41
+ try {
42
+ while (!doneReading) {
43
+ // Read the next chunk from the stream
44
+ const { done, value } = await reader.read();
45
+ doneReading = done;
46
+
47
+ // Skip processing if we're done and there's no value
48
+ if (done && !value) continue;
49
+
50
+ try {
51
+ // Decode binary data to text
52
+ const decoded = value ? new TextDecoder().decode(value) : '';
53
+
54
+ // Split the combined buffer and new data by record separator
55
+ const chunks = (buffer + decoded).split(RECORD_SEPARATOR);
56
+
57
+ // The last chunk might be incomplete, so save it for the next iteration
58
+ buffer = chunks.pop() || '';
59
+
60
+ // Process complete chunks
61
+ for (const chunk of chunks) {
62
+ if (chunk) {
63
+ // Only process non-empty chunks
64
+ if (typeof chunk === 'string') {
65
+ try {
66
+ const parsedChunk = JSON.parse(chunk);
67
+ yield parsedChunk;
68
+ } catch {
69
+ // Silently ignore parsing errors to maintain stream processing
70
+ // This allows the stream to continue even if one record is malformed
71
+ }
72
+ }
73
+ }
74
+ }
75
+ } catch {
76
+ // Silently ignore parsing errors to maintain stream processing
77
+ // This allows the stream to continue even if one record is malformed
78
+ }
79
+ }
80
+
81
+ // Process any remaining data in the buffer after stream is done
82
+ if (buffer) {
83
+ try {
84
+ yield JSON.parse(buffer);
85
+ } catch {
86
+ // Ignore parsing error for final chunk
87
+ }
88
+ }
89
+ } finally {
90
+ // Always ensure we clean up the reader
91
+ reader.cancel().catch(() => {
92
+ // Ignore cancel errors
93
+ });
94
+ }
95
+ }
96
+
21
97
  /**
22
98
  * Retrieves details about the workflow
23
99
  * @returns Promise containing workflow details including steps and graphs
@@ -39,10 +115,10 @@ export class Workflow extends BaseResource {
39
115
  if (params?.toDate) {
40
116
  searchParams.set('toDate', params.toDate.toISOString());
41
117
  }
42
- if (params?.limit) {
118
+ if (params?.limit !== null && params?.limit !== undefined && !isNaN(Number(params?.limit))) {
43
119
  searchParams.set('limit', String(params.limit));
44
120
  }
45
- if (params?.offset) {
121
+ if (params?.offset !== null && params?.offset !== undefined && !isNaN(Number(params?.offset))) {
46
122
  searchParams.set('offset', String(params.offset));
47
123
  }
48
124
  if (params?.resourceId) {
@@ -57,21 +133,50 @@ export class Workflow extends BaseResource {
57
133
  }
58
134
 
59
135
  /**
60
- * @deprecated Use `startAsync` instead
61
- * Executes the workflow with the provided parameters
62
- * @param params - Parameters required for workflow execution
63
- * @returns Promise containing the workflow execution results
136
+ * Retrieves a specific workflow run by its ID
137
+ * @param runId - The ID of the workflow run to retrieve
138
+ * @returns Promise containing the workflow run details
139
+ */
140
+ runById(runId: string): Promise<GetWorkflowRunByIdResponse> {
141
+ return this.request(`/api/workflows/${this.workflowId}/runs/${runId}`);
142
+ }
143
+
144
+ /**
145
+ * Retrieves the execution result for a specific workflow run by its ID
146
+ * @param runId - The ID of the workflow run to retrieve the execution result for
147
+ * @returns Promise containing the workflow run execution result
64
148
  */
65
- execute(params: Record<string, any>): Promise<WorkflowRunResult> {
66
- return this.request(`/api/workflows/${this.workflowId}/execute`, {
149
+ runExecutionResult(runId: string): Promise<GetWorkflowRunExecutionResultResponse> {
150
+ return this.request(`/api/workflows/${this.workflowId}/runs/${runId}/execution-result`);
151
+ }
152
+
153
+ /**
154
+ * Cancels a specific workflow run by its ID
155
+ * @param runId - The ID of the workflow run to cancel
156
+ * @returns Promise containing a success message
157
+ */
158
+ cancelRun(runId: string): Promise<{ message: string }> {
159
+ return this.request(`/api/workflows/${this.workflowId}/runs/${runId}/cancel`, {
67
160
  method: 'POST',
68
- body: params,
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Sends an event to a specific workflow run by its ID
166
+ * @param params - Object containing the runId, event and data
167
+ * @returns Promise containing a success message
168
+ */
169
+ sendRunEvent(params: { runId: string; event: string; data: unknown }): Promise<{ message: string }> {
170
+ return this.request(`/api/workflows/${this.workflowId}/runs/${params.runId}/send-event`, {
171
+ method: 'POST',
172
+ body: { event: params.event, data: params.data },
69
173
  });
70
174
  }
71
175
 
72
176
  /**
73
177
  * Creates a new workflow run
74
- * @returns Promise containing the generated run ID
178
+ * @param params - Optional object containing the optional runId
179
+ * @returns Promise containing the runId of the created run
75
180
  */
76
181
  createRun(params?: { runId?: string }): Promise<{ runId: string }> {
77
182
  const searchParams = new URLSearchParams();
@@ -80,150 +185,162 @@ export class Workflow extends BaseResource {
80
185
  searchParams.set('runId', params.runId);
81
186
  }
82
187
 
83
- return this.request(`/api/workflows/${this.workflowId}/createRun?${searchParams.toString()}`, {
188
+ return this.request(`/api/workflows/${this.workflowId}/create-run?${searchParams.toString()}`, {
84
189
  method: 'POST',
85
190
  });
86
191
  }
87
192
 
88
193
  /**
89
194
  * Starts a workflow run synchronously without waiting for the workflow to complete
90
- * @param params - Object containing the runId and triggerData
195
+ * @param params - Object containing the runId, inputData and runtimeContext
91
196
  * @returns Promise containing success message
92
197
  */
93
- start(params: { runId: string; triggerData: Record<string, any> }): Promise<{ message: string }> {
198
+ start(params: {
199
+ runId: string;
200
+ inputData: Record<string, any>;
201
+ runtimeContext?: RuntimeContext | Record<string, any>;
202
+ }): Promise<{ message: string }> {
203
+ const runtimeContext = parseClientRuntimeContext(params.runtimeContext);
94
204
  return this.request(`/api/workflows/${this.workflowId}/start?runId=${params.runId}`, {
95
205
  method: 'POST',
96
- body: params?.triggerData,
206
+ body: { inputData: params?.inputData, runtimeContext },
97
207
  });
98
208
  }
99
209
 
100
210
  /**
101
211
  * Resumes a suspended workflow step synchronously without waiting for the workflow to complete
102
- * @param stepId - ID of the step to resume
103
- * @param runId - ID of the workflow run
104
- * @param context - Context to resume the workflow with
105
- * @returns Promise containing the workflow resume results
212
+ * @param params - Object containing the runId, step, resumeData and runtimeContext
213
+ * @returns Promise containing success message
106
214
  */
107
215
  resume({
108
- stepId,
216
+ step,
109
217
  runId,
110
- context,
218
+ resumeData,
219
+ ...rest
111
220
  }: {
112
- stepId: string;
221
+ step: string | string[];
113
222
  runId: string;
114
- context: Record<string, any>;
223
+ resumeData?: Record<string, any>;
224
+ runtimeContext?: RuntimeContext | Record<string, any>;
115
225
  }): Promise<{ message: string }> {
226
+ const runtimeContext = parseClientRuntimeContext(rest.runtimeContext);
116
227
  return this.request(`/api/workflows/${this.workflowId}/resume?runId=${runId}`, {
117
228
  method: 'POST',
229
+ stream: true,
118
230
  body: {
119
- stepId,
120
- context,
231
+ step,
232
+ resumeData,
233
+ runtimeContext,
121
234
  },
122
235
  });
123
236
  }
124
237
 
125
238
  /**
126
239
  * Starts a workflow run asynchronously and returns a promise that resolves when the workflow is complete
127
- * @param params - Object containing the optional runId and triggerData
240
+ * @param params - Object containing the optional runId, inputData and runtimeContext
128
241
  * @returns Promise containing the workflow execution results
129
242
  */
130
- startAsync(params: { runId?: string; triggerData: Record<string, any> }): Promise<WorkflowRunResult> {
243
+ startAsync(params: {
244
+ runId?: string;
245
+ inputData: Record<string, any>;
246
+ runtimeContext?: RuntimeContext | Record<string, any>;
247
+ }): Promise<WorkflowRunResult> {
131
248
  const searchParams = new URLSearchParams();
132
249
 
133
250
  if (!!params?.runId) {
134
251
  searchParams.set('runId', params.runId);
135
252
  }
136
253
 
254
+ const runtimeContext = parseClientRuntimeContext(params.runtimeContext);
255
+
137
256
  return this.request(`/api/workflows/${this.workflowId}/start-async?${searchParams.toString()}`, {
138
257
  method: 'POST',
139
- body: params?.triggerData,
258
+ body: { inputData: params.inputData, runtimeContext },
140
259
  });
141
260
  }
142
261
 
143
262
  /**
144
- * Resumes a suspended workflow step asynchronously and returns a promise that resolves when the workflow is complete
145
- * @param params - Object containing the runId, stepId, and context
146
- * @returns Promise containing the workflow resume results
263
+ * Starts a workflow run and returns a stream
264
+ * @param params - Object containing the optional runId, inputData and runtimeContext
265
+ * @returns Promise containing the workflow execution results
147
266
  */
148
- resumeAsync(params: { runId: string; stepId: string; context: Record<string, any> }): Promise<WorkflowRunResult> {
149
- return this.request(`/api/workflows/${this.workflowId}/resume-async?runId=${params.runId}`, {
150
- method: 'POST',
151
- body: {
152
- stepId: params.stepId,
153
- context: params.context,
154
- },
155
- });
156
- }
267
+ async stream(params: { runId?: string; inputData: Record<string, any>; runtimeContext?: RuntimeContext }) {
268
+ const searchParams = new URLSearchParams();
157
269
 
158
- /**
159
- * Creates an async generator that processes a readable stream and yields records
160
- * separated by the Record Separator character (\x1E)
161
- *
162
- * @param stream - The readable stream to process
163
- * @returns An async generator that yields parsed records
164
- */
165
- private async *streamProcessor(stream: ReadableStream): AsyncGenerator<WorkflowRunResult, void, unknown> {
166
- const reader = stream.getReader();
270
+ if (!!params?.runId) {
271
+ searchParams.set('runId', params.runId);
272
+ }
167
273
 
168
- // Track if we've finished reading from the stream
169
- let doneReading = false;
170
- // Buffer to accumulate partial chunks
171
- let buffer = '';
274
+ const runtimeContext = parseClientRuntimeContext(params.runtimeContext);
275
+ const response: Response = await this.request(
276
+ `/api/workflows/${this.workflowId}/stream?${searchParams.toString()}`,
277
+ {
278
+ method: 'POST',
279
+ body: { inputData: params.inputData, runtimeContext },
280
+ stream: true,
281
+ },
282
+ );
172
283
 
173
- try {
174
- while (!doneReading) {
175
- // Read the next chunk from the stream
176
- const { done, value } = await reader.read();
177
- doneReading = done;
284
+ if (!response.ok) {
285
+ throw new Error(`Failed to stream vNext workflow: ${response.statusText}`);
286
+ }
178
287
 
179
- // Skip processing if we're done and there's no value
180
- if (done && !value) continue;
288
+ if (!response.body) {
289
+ throw new Error('Response body is null');
290
+ }
181
291
 
292
+ // Create a transform stream that processes the response body
293
+ const transformStream = new TransformStream<ArrayBuffer, { type: string; payload: any }>({
294
+ start() {},
295
+ async transform(chunk, controller) {
182
296
  try {
183
297
  // Decode binary data to text
184
- const decoded = value ? new TextDecoder().decode(value) : '';
185
-
186
- // Split the combined buffer and new data by record separator
187
- const chunks = (buffer + decoded).split(RECORD_SEPARATOR);
298
+ const decoded = new TextDecoder().decode(chunk);
188
299
 
189
- // The last chunk might be incomplete, so save it for the next iteration
190
- buffer = chunks.pop() || '';
300
+ // Split by record separator
301
+ const chunks = decoded.split(RECORD_SEPARATOR);
191
302
 
192
- // Process complete chunks
303
+ // Process each chunk
193
304
  for (const chunk of chunks) {
194
305
  if (chunk) {
195
- // Only process non-empty chunks
196
- if (typeof chunk === 'string') {
197
- try {
198
- const parsedChunk = JSON.parse(chunk);
199
- yield parsedChunk;
200
- } catch {
201
- // Silently ignore parsing errors to maintain stream processing
202
- // This allows the stream to continue even if one record is malformed
203
- }
306
+ try {
307
+ const parsedChunk = JSON.parse(chunk);
308
+ controller.enqueue(parsedChunk);
309
+ } catch {
310
+ // Silently ignore parsing errors
204
311
  }
205
312
  }
206
313
  }
207
314
  } catch {
208
- // Silently ignore parsing errors to maintain stream processing
209
- // This allows the stream to continue even if one record is malformed
315
+ // Silently ignore processing errors
210
316
  }
211
- }
317
+ },
318
+ });
212
319
 
213
- // Process any remaining data in the buffer after stream is done
214
- if (buffer) {
215
- try {
216
- yield JSON.parse(buffer);
217
- } catch {
218
- // Ignore parsing error for final chunk
219
- }
220
- }
221
- } finally {
222
- // Always ensure we clean up the reader
223
- reader.cancel().catch(() => {
224
- // Ignore cancel errors
225
- });
226
- }
320
+ // Pipe the response body through the transform stream
321
+ return response.body.pipeThrough(transformStream);
322
+ }
323
+
324
+ /**
325
+ * Resumes a suspended workflow step asynchronously and returns a promise that resolves when the workflow is complete
326
+ * @param params - Object containing the runId, step, resumeData and runtimeContext
327
+ * @returns Promise containing the workflow resume results
328
+ */
329
+ resumeAsync(params: {
330
+ runId: string;
331
+ step: string | string[];
332
+ resumeData?: Record<string, any>;
333
+ runtimeContext?: RuntimeContext | Record<string, any>;
334
+ }): Promise<WorkflowRunResult> {
335
+ const runtimeContext = parseClientRuntimeContext(params.runtimeContext);
336
+ return this.request(`/api/workflows/${this.workflowId}/resume-async?runId=${params.runId}`, {
337
+ method: 'POST',
338
+ body: {
339
+ step: params.step,
340
+ resumeData: params.resumeData,
341
+ runtimeContext,
342
+ },
343
+ });
227
344
  }
228
345
 
229
346
  /**
@@ -231,7 +348,7 @@ export class Workflow extends BaseResource {
231
348
  * @param runId - Optional run ID to filter the watch stream
232
349
  * @returns AsyncGenerator that yields parsed records from the workflow watch stream
233
350
  */
234
- async watch({ runId }: { runId?: string }, onRecord: (record: WorkflowRunResult) => void) {
351
+ async watch({ runId }: { runId?: string }, onRecord: (record: WorkflowWatchResult) => void) {
235
352
  const response: Response = await this.request(`/api/workflows/${this.workflowId}/watch?runId=${runId}`, {
236
353
  stream: true,
237
354
  });
@@ -245,7 +362,35 @@ export class Workflow extends BaseResource {
245
362
  }
246
363
 
247
364
  for await (const record of this.streamProcessor(response.body)) {
248
- onRecord(record);
365
+ if (typeof record === 'string') {
366
+ onRecord(JSON.parse(record));
367
+ } else {
368
+ onRecord(record);
369
+ }
249
370
  }
250
371
  }
372
+
373
+ /**
374
+ * Creates a new ReadableStream from an iterable or async iterable of objects,
375
+ * serializing each as JSON and separating them with the record separator (\x1E).
376
+ *
377
+ * @param records - An iterable or async iterable of objects to stream
378
+ * @returns A ReadableStream emitting the records as JSON strings separated by the record separator
379
+ */
380
+ static createRecordStream(records: Iterable<any> | AsyncIterable<any>): ReadableStream {
381
+ const encoder = new TextEncoder();
382
+ return new ReadableStream({
383
+ async start(controller) {
384
+ try {
385
+ for await (const record of records as AsyncIterable<any>) {
386
+ const json = JSON.stringify(record) + RECORD_SEPARATOR;
387
+ controller.enqueue(encoder.encode(json));
388
+ }
389
+ controller.close();
390
+ } catch (err) {
391
+ controller.error(err);
392
+ }
393
+ },
394
+ });
395
+ }
251
396
  }