@workflow/web-shared 4.0.1-beta.24 → 4.0.1-beta.26

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 (49) hide show
  1. package/dist/api/workflow-api-client.d.ts +40 -5
  2. package/dist/api/workflow-api-client.d.ts.map +1 -1
  3. package/dist/api/workflow-api-client.js +280 -196
  4. package/dist/api/workflow-api-client.js.map +1 -1
  5. package/dist/api/workflow-server-actions.d.ts +18 -1
  6. package/dist/api/workflow-server-actions.d.ts.map +1 -1
  7. package/dist/api/workflow-server-actions.js +173 -93
  8. package/dist/api/workflow-server-actions.js.map +1 -1
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/utils.d.ts +19 -0
  14. package/dist/lib/utils.d.ts.map +1 -1
  15. package/dist/lib/utils.js +64 -0
  16. package/dist/lib/utils.js.map +1 -1
  17. package/dist/sidebar/attribute-panel.d.ts +6 -2
  18. package/dist/sidebar/attribute-panel.d.ts.map +1 -1
  19. package/dist/sidebar/attribute-panel.js +136 -9
  20. package/dist/sidebar/attribute-panel.js.map +1 -1
  21. package/dist/sidebar/detail-card.d.ts.map +1 -1
  22. package/dist/sidebar/detail-card.js +2 -2
  23. package/dist/sidebar/detail-card.js.map +1 -1
  24. package/dist/sidebar/events-list.d.ts +2 -1
  25. package/dist/sidebar/events-list.d.ts.map +1 -1
  26. package/dist/sidebar/events-list.js +9 -7
  27. package/dist/sidebar/events-list.js.map +1 -1
  28. package/dist/sidebar/workflow-detail-panel.d.ts +5 -1
  29. package/dist/sidebar/workflow-detail-panel.d.ts.map +1 -1
  30. package/dist/sidebar/workflow-detail-panel.js +2 -2
  31. package/dist/sidebar/workflow-detail-panel.js.map +1 -1
  32. package/dist/stream-viewer.d.ts +13 -0
  33. package/dist/stream-viewer.d.ts.map +1 -0
  34. package/dist/stream-viewer.js +108 -0
  35. package/dist/stream-viewer.js.map +1 -0
  36. package/dist/trace-viewer/components/markers.js +2 -2
  37. package/dist/trace-viewer/components/markers.js.map +1 -1
  38. package/dist/trace-viewer/components/span-detail-panel.js +2 -2
  39. package/dist/trace-viewer/components/span-detail-panel.js.map +1 -1
  40. package/dist/trace-viewer/trace-viewer.module.css +25 -20
  41. package/dist/trace-viewer/util/timing.d.ts +7 -1
  42. package/dist/trace-viewer/util/timing.d.ts.map +1 -1
  43. package/dist/trace-viewer/util/timing.js +7 -12
  44. package/dist/trace-viewer/util/timing.js.map +1 -1
  45. package/dist/workflow-trace-view.d.ts +3 -1
  46. package/dist/workflow-trace-view.d.ts.map +1 -1
  47. package/dist/workflow-trace-view.js +2 -2
  48. package/dist/workflow-trace-view.js.map +1 -1
  49. package/package.json +4 -3
@@ -1,16 +1,16 @@
1
1
  'use client';
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
3
  import { getPaginationDisplay } from '../lib/utils';
4
- import { cancelRun as cancelRunServerAction, fetchEvents, fetchEventsByCorrelationId, fetchHook, fetchHooks, fetchRun, fetchRuns, fetchStep, fetchSteps, readStreamServerAction, recreateRun as recreateRunServerAction, } from './workflow-server-actions';
4
+ import { cancelRun as cancelRunServerAction, fetchEvents, fetchEventsByCorrelationId, fetchHook, fetchHooks, fetchRun, fetchRuns, fetchStep, fetchSteps, fetchStreams, readStreamServerAction, recreateRun as recreateRunServerAction, } from './workflow-server-actions';
5
5
  const MAX_ITEMS = 1000;
6
6
  const LIVE_POLL_LIMIT = 10;
7
7
  const LIVE_STEP_UPDATE_INTERVAL_MS = 2000;
8
8
  const LIVE_UPDATE_INTERVAL_MS = 5000;
9
9
  /**
10
- * Helper to convert ServerActionError to WorkflowAPIError
10
+ * Helper to convert ServerActionError to WorkflowWebAPIError
11
11
  */
12
12
  function createWorkflowAPIError(serverError) {
13
- return new WorkflowAPIError(serverError.message, {
13
+ return new WorkflowWebAPIError(serverError.message, {
14
14
  cause: serverError.cause,
15
15
  request: serverError.request,
16
16
  layer: serverError.layer,
@@ -18,31 +18,50 @@ function createWorkflowAPIError(serverError) {
18
18
  }
19
19
  /**
20
20
  * Gets a user-facing error message from an error object.
21
- * Handles both WorkflowAPIError and regular Error instances.
21
+ * Handles both WorkflowWebAPIError and regular Error instances.
22
22
  */
23
23
  export const getErrorMessage = (error) => {
24
24
  if ('layer' in error && error.layer) {
25
- if (error instanceof WorkflowAPIError) {
25
+ if (error instanceof WorkflowWebAPIError) {
26
26
  if (error.request?.status === 403) {
27
27
  return 'Your current Vercel account does not have access to this data. Please use `vercel login` to log in, or use `vercel switch` to ensure you can access the correct team.';
28
28
  }
29
29
  }
30
- // WorkflowAPIError already has user-facing messages
30
+ // WorkflowWebAPIError already has user-facing messages
31
31
  return error.message;
32
32
  }
33
33
  return error instanceof Error ? error.message : 'An error occurred';
34
34
  };
35
35
  /**
36
- * Helper to handle server action results and throw WorkflowAPIError on failure
36
+ * Helper to handle server action results and throw WorkflowWebAPIError on failure
37
37
  */
38
- function unwrapServerActionResult(result) {
38
+ export async function unwrapServerActionResult(promise) {
39
+ let result;
40
+ try {
41
+ result = await promise;
42
+ }
43
+ catch (error) {
44
+ result = {
45
+ success: false,
46
+ error: error,
47
+ };
48
+ }
39
49
  if (!result.success) {
50
+ console.error('[web-api-client] error', result.error);
40
51
  if (!result.error) {
41
- throw new WorkflowAPIError('Unknown error occurred', { layer: 'client' });
42
- }
43
- throw createWorkflowAPIError(result.error);
52
+ return {
53
+ error: new WorkflowWebAPIError('Unknown error occurred', {
54
+ layer: 'client',
55
+ }),
56
+ result: null,
57
+ };
58
+ }
59
+ return {
60
+ error: createWorkflowAPIError(result.error),
61
+ result: null,
62
+ };
44
63
  }
45
- return result.data;
64
+ return { error: null, result: result.data };
46
65
  }
47
66
  /**
48
67
  * Error instance for API and server-side errors.
@@ -58,12 +77,12 @@ function unwrapServerActionResult(result) {
58
77
  * calling the server action, these fields will be populated:
59
78
  * - `error.layer` will be 'server'
60
79
  */
61
- export class WorkflowAPIError extends Error {
80
+ export class WorkflowWebAPIError extends Error {
62
81
  request;
63
82
  layer;
64
83
  constructor(message, options) {
65
84
  super(message, { cause: options?.cause });
66
- this.name = 'WorkflowAPIError';
85
+ this.name = 'WorkflowWebAPIError';
67
86
  this.request = options?.request;
68
87
  this.layer = options?.layer;
69
88
  if (options?.cause instanceof Error) {
@@ -117,42 +136,14 @@ export function useWorkflowRuns(env, params) {
117
136
  return;
118
137
  }
119
138
  }
120
- try {
121
- const serverResult = await fetchRuns(env, {
122
- cursor: pageCursor,
123
- sortOrder,
124
- limit: limit,
125
- workflowName,
126
- status,
127
- });
128
- const result = unwrapServerActionResult(serverResult);
129
- // Cache the result
130
- pageCache.current.set(cacheKey, {
131
- data: result.data,
132
- cursor: result.cursor,
133
- hasMore: result.hasMore,
134
- });
135
- setAllPageResults((prev) => {
136
- const newMap = new Map(prev);
137
- newMap.set(pageIndex, {
138
- data: result.data,
139
- isLoading: false,
140
- error: null,
141
- });
142
- return newMap;
143
- });
144
- setCursor(result.cursor);
145
- setHasMore(result.hasMore);
146
- }
147
- catch (err) {
148
- const error = err instanceof WorkflowAPIError
149
- ? err
150
- : err instanceof Error
151
- ? new WorkflowAPIError(err.message, {
152
- cause: err,
153
- layer: 'client',
154
- })
155
- : new WorkflowAPIError(String(err), { layer: 'client' });
139
+ const { error, result } = await unwrapServerActionResult(fetchRuns(env, {
140
+ cursor: pageCursor,
141
+ sortOrder,
142
+ limit: limit,
143
+ workflowName,
144
+ status,
145
+ }));
146
+ if (error) {
156
147
  setAllPageResults((prev) => {
157
148
  const newMap = new Map(prev);
158
149
  newMap.set(pageIndex, {
@@ -162,7 +153,25 @@ export function useWorkflowRuns(env, params) {
162
153
  });
163
154
  return newMap;
164
155
  });
156
+ return;
165
157
  }
158
+ // Cache the result
159
+ pageCache.current.set(cacheKey, {
160
+ data: result.data,
161
+ cursor: result.cursor,
162
+ hasMore: result.hasMore,
163
+ });
164
+ setAllPageResults((prev) => {
165
+ const newMap = new Map(prev);
166
+ newMap.set(pageIndex, {
167
+ data: result.data,
168
+ isLoading: false,
169
+ error: null,
170
+ });
171
+ return newMap;
172
+ });
173
+ setCursor(result.cursor);
174
+ setHasMore(result.hasMore);
166
175
  }, [env, workflowName, limit, sortOrder, status]);
167
176
  // Initial load
168
177
  // biome-ignore lint/correctness/useExhaustiveDependencies: Want to refetch first page on param change
@@ -281,41 +290,13 @@ export function useWorkflowHooks(env, params) {
281
290
  return;
282
291
  }
283
292
  }
284
- try {
285
- const serverResult = await fetchHooks(env, {
286
- runId,
287
- cursor: pageCursor,
288
- sortOrder,
289
- limit: limit,
290
- });
291
- const result = unwrapServerActionResult(serverResult);
292
- // Cache the result
293
- pageCache.current.set(cacheKey, {
294
- data: result.data,
295
- cursor: result.cursor,
296
- hasMore: result.hasMore,
297
- });
298
- setAllPageResults((prev) => {
299
- const newMap = new Map(prev);
300
- newMap.set(pageIndex, {
301
- data: result.data,
302
- isLoading: false,
303
- error: null,
304
- });
305
- return newMap;
306
- });
307
- setCursor(result.cursor);
308
- setHasMore(result.hasMore);
309
- }
310
- catch (err) {
311
- const error = err instanceof WorkflowAPIError
312
- ? err
313
- : err instanceof Error
314
- ? new WorkflowAPIError(err.message, {
315
- cause: err,
316
- layer: 'client',
317
- })
318
- : new WorkflowAPIError(String(err), { layer: 'client' });
293
+ const { error, result } = await unwrapServerActionResult(fetchHooks(env, {
294
+ runId,
295
+ cursor: pageCursor,
296
+ sortOrder,
297
+ limit: limit,
298
+ }));
299
+ if (error) {
319
300
  setAllPageResults((prev) => {
320
301
  const newMap = new Map(prev);
321
302
  newMap.set(pageIndex, {
@@ -325,7 +306,25 @@ export function useWorkflowHooks(env, params) {
325
306
  });
326
307
  return newMap;
327
308
  });
309
+ return;
328
310
  }
311
+ // Cache the result
312
+ pageCache.current.set(cacheKey, {
313
+ data: result.data,
314
+ cursor: result.cursor,
315
+ hasMore: result.hasMore,
316
+ });
317
+ setAllPageResults((prev) => {
318
+ const newMap = new Map(prev);
319
+ newMap.set(pageIndex, {
320
+ data: result.data,
321
+ isLoading: false,
322
+ error: null,
323
+ });
324
+ return newMap;
325
+ });
326
+ setCursor(result.cursor);
327
+ setHasMore(result.hasMore);
329
328
  }, [env, runId, limit, sortOrder]);
330
329
  // Initial load
331
330
  useEffect(() => {
@@ -402,12 +401,15 @@ async function fetchAllSteps(env, runId) {
402
401
  let stepsData = [];
403
402
  let stepsCursor;
404
403
  while (true) {
405
- const serverResult = await fetchSteps(env, runId, {
404
+ const { error, result } = await unwrapServerActionResult(fetchSteps(env, runId, {
406
405
  cursor: stepsCursor,
407
406
  sortOrder: 'asc',
408
407
  limit: 100,
409
- });
410
- const result = unwrapServerActionResult(serverResult);
408
+ }));
409
+ // TODO: We're not handling errors well for infinite fetches
410
+ if (error) {
411
+ break;
412
+ }
411
413
  stepsData = [...stepsData, ...result.data];
412
414
  if (!result.hasMore || !result.cursor || stepsData.length >= MAX_ITEMS) {
413
415
  break;
@@ -421,13 +423,15 @@ async function fetchAllHooks(env, runId) {
421
423
  let hooksData = [];
422
424
  let hooksCursor;
423
425
  while (true) {
424
- const serverResult = await fetchHooks(env, {
426
+ const { error, result } = await unwrapServerActionResult(fetchHooks(env, {
425
427
  runId,
426
428
  cursor: hooksCursor,
427
429
  sortOrder: 'asc',
428
430
  limit: 100,
429
- });
430
- const result = unwrapServerActionResult(serverResult);
431
+ }));
432
+ if (error) {
433
+ break;
434
+ }
431
435
  hooksData = [...hooksData, ...result.data];
432
436
  if (!result.hasMore || !result.cursor || hooksData.length >= MAX_ITEMS) {
433
437
  break;
@@ -441,12 +445,14 @@ async function fetchAllEvents(env, runId) {
441
445
  let eventsData = [];
442
446
  let eventsCursor;
443
447
  while (true) {
444
- const serverResult = await fetchEvents(env, runId, {
448
+ const { error, result } = await unwrapServerActionResult(fetchEvents(env, runId, {
445
449
  cursor: eventsCursor,
446
450
  sortOrder: 'asc',
447
451
  limit: 1000,
448
- });
449
- const result = unwrapServerActionResult(serverResult);
452
+ }));
453
+ if (error) {
454
+ break;
455
+ }
450
456
  eventsData = [...eventsData, ...result.data];
451
457
  if (!result.hasMore || !result.cursor || eventsData.length >= MAX_ITEMS) {
452
458
  break;
@@ -483,11 +489,13 @@ export function useWorkflowTraceViewerData(env, runId, options = {}) {
483
489
  setAuxiliaryDataLoading(true);
484
490
  setError(null);
485
491
  const promises = [
486
- fetchRun(env, runId).then((result) => {
487
- // The run is the most visible part - so we can start showing UI
488
- // as soon as we have the run
489
- setLoading(false);
490
- setRun(unwrapServerActionResult(result));
492
+ unwrapServerActionResult(fetchRun(env, runId)).then(({ error, result }) => {
493
+ if (error) {
494
+ setError(error);
495
+ return;
496
+ }
497
+ setRun(result);
498
+ return result;
491
499
  }),
492
500
  fetchAllSteps(env, runId).then((result) => {
493
501
  setSteps(result.data);
@@ -502,23 +510,17 @@ export function useWorkflowTraceViewerData(env, runId, options = {}) {
502
510
  setEventsCursor(result.cursor);
503
511
  }),
504
512
  ];
505
- try {
506
- // Fetch run
507
- await Promise.all(promises);
508
- }
509
- catch (err) {
510
- const error = err instanceof WorkflowAPIError
511
- ? err
512
- : err instanceof Error
513
- ? new WorkflowAPIError(err.message, { cause: err, layer: 'client' })
514
- : new WorkflowAPIError(String(err), { layer: 'client' });
513
+ const results = await Promise.allSettled(promises);
514
+ setLoading(false);
515
+ setAuxiliaryDataLoading(false);
516
+ setInitialLoadCompleted(true);
517
+ isFetchingRef.current = false;
518
+ // Just doing the first error, but would be nice to show multiple
519
+ const error = results.find((result) => result.status === 'rejected')
520
+ ?.reason;
521
+ if (error) {
515
522
  setError(error);
516
- }
517
- finally {
518
- setLoading(false);
519
- setAuxiliaryDataLoading(false);
520
- isFetchingRef.current = false;
521
- setInitialLoadCompleted(true);
523
+ return;
522
524
  }
523
525
  }, [env, runId]);
524
526
  // Helper to merge steps by ID
@@ -543,19 +545,25 @@ export function useWorkflowTraceViewerData(env, runId, options = {}) {
543
545
  if (run?.completedAt) {
544
546
  return false;
545
547
  }
546
- const serverResult = await fetchRun(env, runId);
547
- const result = unwrapServerActionResult(serverResult);
548
+ const { error, result } = await unwrapServerActionResult(fetchRun(env, runId));
549
+ if (error) {
550
+ setError(error);
551
+ return false;
552
+ }
548
553
  setRun(result);
549
554
  return true;
550
555
  }, [env, runId, run?.completedAt]);
551
556
  // Poll for new steps
552
557
  const pollSteps = useCallback(async () => {
553
- const serverResult = await fetchSteps(env, runId, {
558
+ const { error, result } = await unwrapServerActionResult(fetchSteps(env, runId, {
554
559
  cursor: stepsCursor,
555
560
  sortOrder: 'asc',
556
561
  limit: LIVE_POLL_LIMIT,
557
- });
558
- const result = unwrapServerActionResult(serverResult);
562
+ }));
563
+ if (error) {
564
+ setError(error);
565
+ return false;
566
+ }
559
567
  if (result.data.length > 0) {
560
568
  setSteps((prev) => mergeSteps(prev, result.data));
561
569
  if (result.cursor) {
@@ -567,13 +575,16 @@ export function useWorkflowTraceViewerData(env, runId, options = {}) {
567
575
  }, [env, runId, stepsCursor, mergeSteps]);
568
576
  // Poll for new hooks
569
577
  const pollHooks = useCallback(async () => {
570
- const serverResult = await fetchHooks(env, {
578
+ const { error, result } = await unwrapServerActionResult(fetchHooks(env, {
571
579
  runId,
572
580
  cursor: hooksCursor,
573
581
  sortOrder: 'asc',
574
582
  limit: LIVE_POLL_LIMIT,
575
- });
576
- const result = unwrapServerActionResult(serverResult);
583
+ }));
584
+ if (error) {
585
+ setError(error);
586
+ return false;
587
+ }
577
588
  if (result.data.length > 0) {
578
589
  setHooks((prev) => mergeHooks(prev, result.data));
579
590
  if (result.cursor) {
@@ -585,12 +596,15 @@ export function useWorkflowTraceViewerData(env, runId, options = {}) {
585
596
  }, [env, runId, hooksCursor, mergeHooks]);
586
597
  // Poll for new events
587
598
  const pollEvents = useCallback(async () => {
588
- const serverResult = await fetchEvents(env, runId, {
599
+ const { error, result } = await unwrapServerActionResult(fetchEvents(env, runId, {
589
600
  cursor: eventsCursor,
590
601
  sortOrder: 'asc',
591
602
  limit: LIVE_POLL_LIMIT,
592
- });
593
- const result = unwrapServerActionResult(serverResult);
603
+ }));
604
+ if (error) {
605
+ setError(error);
606
+ return false;
607
+ }
594
608
  if (result.data.length > 0) {
595
609
  setEvents((prev) => mergeEvents(prev, result.data));
596
610
  if (result.cursor) {
@@ -657,28 +671,37 @@ async function fetchResourceWithCorrelationId(env, resource, resourceId, options
657
671
  let correlationId;
658
672
  const resolveData = options.resolveData ?? 'all';
659
673
  if (resource === 'run') {
660
- const serverResult = await fetchRun(env, resourceId, resolveData);
661
- resourceData = unwrapServerActionResult(serverResult);
674
+ const { error, result } = await unwrapServerActionResult(fetchRun(env, resourceId, resolveData));
675
+ if (error) {
676
+ throw error;
677
+ }
678
+ resourceData = result;
662
679
  correlationId = resourceData.runId;
663
680
  }
664
681
  else if (resource === 'step') {
665
682
  const { runId } = options;
666
683
  if (!runId) {
667
- throw new WorkflowAPIError('runId is required for step resource', {
684
+ throw new WorkflowWebAPIError('runId is required for step resource', {
668
685
  layer: 'client',
669
686
  });
670
687
  }
671
- const serverResult = await fetchStep(env, runId, resourceId, resolveData);
672
- resourceData = unwrapServerActionResult(serverResult);
688
+ const { error, result } = await unwrapServerActionResult(fetchStep(env, runId, resourceId, resolveData));
689
+ if (error) {
690
+ throw error;
691
+ }
692
+ resourceData = result;
673
693
  correlationId = resourceData.stepId;
674
694
  }
675
695
  else if (resource === 'hook') {
676
- const serverResult = await fetchHook(env, resourceId, resolveData);
677
- resourceData = unwrapServerActionResult(serverResult);
696
+ const { error, result } = await unwrapServerActionResult(fetchHook(env, resourceId, resolveData));
697
+ if (error) {
698
+ throw error;
699
+ }
700
+ resourceData = result;
678
701
  correlationId = resourceData.hookId;
679
702
  }
680
703
  else {
681
- throw new WorkflowAPIError(`Unknown resource type: ${resource}`, {
704
+ throw new WorkflowWebAPIError(`Unknown resource type: ${resource}`, {
682
705
  layer: 'client',
683
706
  });
684
707
  }
@@ -698,52 +721,53 @@ export function useWorkflowResourceData(env, resource, resourceId, options = {})
698
721
  setLoading(true);
699
722
  setData(null);
700
723
  setError(null);
701
- try {
702
- if (resource === 'sleep') {
703
- const events = await fetchEventsByCorrelationId(env, resourceId, {
704
- sortOrder: 'asc',
705
- limit: 100,
706
- withData: true,
707
- });
708
- const eventsData = unwrapServerActionResult(events);
709
- const waitStartEvent = eventsData.data.find((event) => event.eventType === 'wait_created');
710
- if (waitStartEvent) {
711
- setData({
712
- waitId: waitStartEvent.correlationId,
713
- runId: waitStartEvent.runId,
714
- createdAt: waitStartEvent.createdAt,
715
- resumeAt: waitStartEvent.eventData.resumeAt,
716
- });
717
- }
724
+ if (resource === 'sleep') {
725
+ const { error, result } = await unwrapServerActionResult(fetchEventsByCorrelationId(env, resourceId, {
726
+ sortOrder: 'asc',
727
+ limit: 100,
728
+ withData: true,
729
+ }));
730
+ if (error) {
731
+ setError(error);
718
732
  return;
719
733
  }
720
- // Fetch resource with full data
734
+ const eventsData = result;
735
+ const waitStartEvent = eventsData.data.find((event) => event.eventType === 'wait_created');
736
+ if (waitStartEvent) {
737
+ setData({
738
+ waitId: waitStartEvent.correlationId,
739
+ runId: waitStartEvent.runId,
740
+ createdAt: waitStartEvent.createdAt,
741
+ resumeAt: waitStartEvent.eventData.resumeAt,
742
+ });
743
+ }
744
+ return;
745
+ }
746
+ // Fetch resource with full data
747
+ try {
721
748
  const { data: resourceData } = await fetchResourceWithCorrelationId(env, resource, resourceId, {
722
749
  runId,
723
750
  });
724
751
  setData(resourceData);
725
- if (resource === 'run') {
726
- setLoading(false);
727
- return;
728
- }
729
- // // Fetch events by correlation ID
730
- // const eventsData = await fetchAllEventsByCorrelationId(
731
- // env,
732
- // correlationId
733
- // );
734
- // setEvents(eventsData);
735
752
  }
736
- catch (err) {
737
- const error = err instanceof WorkflowAPIError
738
- ? err
739
- : err instanceof Error
740
- ? new WorkflowAPIError(err.message, { cause: err, layer: 'client' })
741
- : new WorkflowAPIError(String(err), { layer: 'client' });
742
- setError(error);
753
+ catch (error) {
754
+ if (error instanceof Error) {
755
+ setError(error);
756
+ }
757
+ else {
758
+ setError(new Error(String(error)));
759
+ }
760
+ return;
743
761
  }
744
762
  finally {
745
763
  setLoading(false);
746
764
  }
765
+ // // Fetch events by correlation ID
766
+ // const eventsData = await fetchAllEventsByCorrelationId(
767
+ // env,
768
+ // correlationId
769
+ // );
770
+ // setEvents(eventsData);
747
771
  }, [env, resource, resourceId, runId]);
748
772
  // Initial load
749
773
  useEffect(() => {
@@ -769,45 +793,105 @@ export function useWorkflowResourceData(env, resource, resourceId, options = {})
769
793
  * Cancel a workflow run
770
794
  */
771
795
  export async function cancelRun(env, runId) {
772
- try {
773
- const result = await cancelRunServerAction(env, runId);
774
- unwrapServerActionResult(result);
775
- }
776
- catch (err) {
777
- console.error('Error canceling run:', err);
778
- if (err instanceof WorkflowAPIError) {
779
- throw err;
780
- }
781
- throw new WorkflowAPIError(err instanceof Error ? err.message : 'Failed to cancel run', { cause: err, layer: 'client' });
796
+ const { error } = await unwrapServerActionResult(cancelRunServerAction(env, runId));
797
+ if (error) {
798
+ throw error;
782
799
  }
783
800
  }
784
801
  /**
785
802
  * Start a new workflow run
786
803
  */
787
804
  export async function recreateRun(env, runId) {
788
- try {
789
- const result = await recreateRunServerAction(env, runId);
790
- return unwrapServerActionResult(result);
791
- }
792
- catch (err) {
793
- console.error('Error starting run:', err);
794
- if (err instanceof WorkflowAPIError) {
795
- throw err;
796
- }
797
- throw new WorkflowAPIError(err instanceof Error ? err.message : 'Failed to start run', { cause: err, layer: 'client' });
805
+ const { error, result: resultData } = await unwrapServerActionResult(recreateRunServerAction(env, runId));
806
+ if (error) {
807
+ throw error;
798
808
  }
809
+ return resultData;
810
+ }
811
+ function isServerActionError(value) {
812
+ return (typeof value === 'object' &&
813
+ value !== null &&
814
+ 'message' in value &&
815
+ 'layer' in value &&
816
+ 'cause' in value &&
817
+ 'request' in value);
799
818
  }
800
819
  export async function readStream(env, streamId, startIndex) {
801
820
  try {
802
- const result = await readStreamServerAction(env, streamId, startIndex);
803
- return unwrapServerActionResult(result);
821
+ const stream = await readStreamServerAction(env, streamId, startIndex);
822
+ if (!stream) {
823
+ throw new WorkflowWebAPIError('Failed to read stream', {
824
+ layer: 'client',
825
+ });
826
+ }
827
+ if (isServerActionError(stream)) {
828
+ throw new WorkflowWebAPIError(stream.message, {
829
+ layer: 'client',
830
+ cause: stream.cause,
831
+ request: stream.request,
832
+ });
833
+ }
834
+ return stream;
804
835
  }
805
- catch (err) {
806
- console.error('Error reading stream:', err);
807
- if (err instanceof WorkflowAPIError) {
808
- throw err;
836
+ catch (error) {
837
+ if (error instanceof WorkflowWebAPIError) {
838
+ throw error;
809
839
  }
810
- throw new WorkflowAPIError(err instanceof Error ? err.message : 'Failed to read stream', { cause: err, layer: 'client' });
840
+ throw new WorkflowWebAPIError('Failed to read stream', {
841
+ layer: 'client',
842
+ cause: error,
843
+ });
844
+ }
845
+ }
846
+ /**
847
+ * List all stream IDs for a run
848
+ */
849
+ export async function listStreams(env, runId) {
850
+ const { error, result } = await unwrapServerActionResult(fetchStreams(env, runId));
851
+ if (error) {
852
+ throw error;
811
853
  }
854
+ return result;
855
+ }
856
+ const STREAMS_REFRESH_INTERVAL_MS = 10000;
857
+ /**
858
+ * Hook to fetch and manage stream list for a run
859
+ */
860
+ export function useWorkflowStreams(env, runId, refreshInterval = STREAMS_REFRESH_INTERVAL_MS) {
861
+ const [streams, setStreams] = useState([]);
862
+ const [loading, setLoading] = useState(true);
863
+ const [error, setError] = useState(null);
864
+ const fetchData = useCallback(async () => {
865
+ setLoading(true);
866
+ setError(null);
867
+ try {
868
+ const result = await listStreams(env, runId);
869
+ setStreams(result);
870
+ }
871
+ catch (err) {
872
+ setError(err instanceof Error ? err : new Error(String(err)));
873
+ }
874
+ finally {
875
+ setLoading(false);
876
+ }
877
+ }, [env, runId]);
878
+ // Initial load
879
+ useEffect(() => {
880
+ fetchData();
881
+ }, [fetchData]);
882
+ // Auto-refresh interval
883
+ useEffect(() => {
884
+ if (!refreshInterval || refreshInterval <= 0) {
885
+ return;
886
+ }
887
+ const interval = setInterval(fetchData, refreshInterval);
888
+ return () => clearInterval(interval);
889
+ }, [refreshInterval, fetchData]);
890
+ return {
891
+ streams,
892
+ loading,
893
+ error,
894
+ refresh: fetchData,
895
+ };
812
896
  }
813
897
  //# sourceMappingURL=workflow-api-client.js.map