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