@workflow/web-shared 4.1.0-beta.47 → 4.1.0-beta.49
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/README.md +26 -52
- package/dist/components/error-boundary.d.ts.map +1 -0
- package/dist/{error-boundary.js → components/error-boundary.js} +1 -1
- package/dist/components/error-boundary.js.map +1 -0
- package/dist/{event-list-view.d.ts → components/event-list-view.d.ts} +2 -3
- package/dist/components/event-list-view.d.ts.map +1 -0
- package/dist/{event-list-view.js → components/event-list-view.js} +9 -17
- package/dist/components/event-list-view.js.map +1 -0
- package/dist/{hook-actions.d.ts → components/hook-actions.d.ts} +2 -3
- package/dist/components/hook-actions.d.ts.map +1 -0
- package/dist/{hook-actions.js → components/hook-actions.js} +3 -4
- package/dist/components/hook-actions.js.map +1 -0
- package/dist/components/index.d.ts +10 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +8 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/run-trace-view.d.ts +22 -0
- package/dist/components/run-trace-view.d.ts.map +1 -0
- package/dist/components/run-trace-view.js +11 -0
- package/dist/components/run-trace-view.js.map +1 -0
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -0
- package/dist/{sidebar → components/sidebar}/attribute-panel.js +3 -3
- package/dist/components/sidebar/attribute-panel.js.map +1 -0
- package/dist/components/sidebar/conversation-view.d.ts.map +1 -0
- package/dist/components/sidebar/conversation-view.js.map +1 -0
- package/dist/components/sidebar/detail-card.d.ts.map +1 -0
- package/dist/components/sidebar/detail-card.js.map +1 -0
- package/dist/components/sidebar/entity-detail-panel.d.ts +32 -0
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -0
- package/dist/{sidebar → components/sidebar}/entity-detail-panel.js +61 -49
- package/dist/components/sidebar/entity-detail-panel.js.map +1 -0
- package/dist/components/sidebar/events-list.d.ts +8 -0
- package/dist/components/sidebar/events-list.d.ts.map +1 -0
- package/dist/components/sidebar/events-list.js +16 -0
- package/dist/components/sidebar/events-list.js.map +1 -0
- package/dist/components/sidebar/resolve-hook-modal.d.ts.map +1 -0
- package/dist/components/sidebar/resolve-hook-modal.js.map +1 -0
- package/dist/components/stream-viewer.d.ts +18 -0
- package/dist/components/stream-viewer.d.ts.map +1 -0
- package/dist/{stream-viewer.js → components/stream-viewer.js} +1 -59
- package/dist/components/stream-viewer.js.map +1 -0
- package/dist/components/trace-viewer/components/map.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/map.js.map +1 -0
- package/dist/components/trace-viewer/components/markers.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/markers.js.map +1 -0
- package/dist/components/trace-viewer/components/node.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/node.js.map +1 -0
- package/dist/components/trace-viewer/components/search-input.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/search-input.js.map +1 -0
- package/dist/components/trace-viewer/components/search.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/search.js.map +1 -0
- package/dist/components/trace-viewer/components/span-detail-panel.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +1 -0
- package/dist/components/trace-viewer/components/ui.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/ui.js.map +1 -0
- package/dist/components/trace-viewer/components/zoom-button.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/zoom-button.js.map +1 -0
- package/dist/components/trace-viewer/components/zoom-icons.d.ts.map +1 -0
- package/dist/components/trace-viewer/components/zoom-icons.js.map +1 -0
- package/dist/components/trace-viewer/context.d.ts.map +1 -0
- package/dist/components/trace-viewer/context.js.map +1 -0
- package/dist/components/trace-viewer/index.d.ts.map +1 -0
- package/dist/components/trace-viewer/index.js.map +1 -0
- package/dist/components/trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/trace-viewer/trace-viewer.js.map +1 -0
- package/dist/components/trace-viewer/types.d.ts.map +1 -0
- package/dist/components/trace-viewer/types.js.map +1 -0
- package/dist/components/trace-viewer/util/constants.d.ts.map +1 -0
- package/dist/components/trace-viewer/util/constants.js.map +1 -0
- package/dist/components/trace-viewer/util/scrollbar-width.d.ts.map +1 -0
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +1 -0
- package/dist/{trace-viewer → components/trace-viewer}/util/timing.d.ts +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -0
- package/dist/{trace-viewer → components/trace-viewer}/util/timing.js +1 -1
- package/dist/components/trace-viewer/util/timing.js.map +1 -0
- package/dist/components/trace-viewer/util/tree.d.ts.map +1 -0
- package/dist/components/trace-viewer/util/tree.js.map +1 -0
- package/dist/components/trace-viewer/util/use-immediate-style.d.ts.map +1 -0
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +1 -0
- package/dist/components/trace-viewer/util/use-streaming-spans.d.ts.map +1 -0
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +1 -0
- package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts.map +1 -0
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +1 -0
- package/dist/components/trace-viewer/worker.d.ts.map +1 -0
- package/dist/components/trace-viewer/worker.js.map +1 -0
- package/dist/components/workflow-trace-view.d.ts +24 -0
- package/dist/components/workflow-trace-view.d.ts.map +1 -0
- package/dist/components/workflow-trace-view.js +152 -0
- package/dist/components/workflow-trace-view.js.map +1 -0
- package/dist/components/workflow-traces/event-colors.d.ts.map +1 -0
- package/dist/components/workflow-traces/event-colors.js.map +1 -0
- package/dist/components/workflow-traces/trace-colors.d.ts.map +1 -0
- package/dist/components/workflow-traces/trace-colors.js.map +1 -0
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -0
- package/dist/components/workflow-traces/trace-span-construction.js.map +1 -0
- package/dist/components/workflow-traces/trace-time-utils.d.ts.map +1 -0
- package/dist/components/workflow-traces/trace-time-utils.js.map +1 -0
- package/dist/index.d.ts +3 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -9
- package/dist/index.js.map +1 -1
- package/package.json +15 -11
- package/src/components/error-boundary.tsx +79 -0
- package/src/components/event-list-view.tsx +429 -0
- package/src/components/hook-actions.tsx +167 -0
- package/src/components/index.d.ts +1 -0
- package/src/components/index.ts +23 -0
- package/src/components/run-trace-view.tsx +75 -0
- package/src/components/sidebar/attribute-panel.tsx +938 -0
- package/src/components/sidebar/conversation-view.tsx +235 -0
- package/src/components/sidebar/detail-card.tsx +43 -0
- package/src/components/sidebar/entity-detail-panel.tsx +338 -0
- package/src/components/sidebar/events-list.tsx +119 -0
- package/src/components/sidebar/resolve-hook-modal.tsx +219 -0
- package/src/components/stream-viewer.tsx +143 -0
- package/src/components/trace-viewer/components/map.tsx +226 -0
- package/src/components/trace-viewer/components/markers.tsx +564 -0
- package/src/components/trace-viewer/components/node.tsx +259 -0
- package/src/components/trace-viewer/components/search-input.tsx +52 -0
- package/src/components/trace-viewer/components/search.tsx +47 -0
- package/src/components/trace-viewer/components/span-detail-panel.tsx +650 -0
- package/src/components/trace-viewer/components/ui.tsx +156 -0
- package/src/components/trace-viewer/components/zoom-button.tsx +61 -0
- package/src/components/trace-viewer/components/zoom-icons.tsx +65 -0
- package/src/components/trace-viewer/context.tsx +633 -0
- package/src/components/trace-viewer/index.tsx +4 -0
- package/src/components/trace-viewer/modules.d.ts +16 -0
- package/src/components/trace-viewer/trace-viewer.module.css +1292 -0
- package/src/components/trace-viewer/trace-viewer.tsx +448 -0
- package/src/components/trace-viewer/types.ts +234 -0
- package/src/components/trace-viewer/util/constants.ts +8 -0
- package/src/components/trace-viewer/util/scrollbar-width.ts +13 -0
- package/src/components/trace-viewer/util/timing.ts +33 -0
- package/src/components/trace-viewer/util/tree.ts +277 -0
- package/src/components/trace-viewer/util/use-immediate-style.ts +38 -0
- package/src/components/trace-viewer/util/use-streaming-spans.ts +415 -0
- package/src/components/trace-viewer/util/use-trackpad-zoom.tsx +51 -0
- package/src/components/trace-viewer/worker.ts +128 -0
- package/src/components/ui/alert.tsx +59 -0
- package/src/components/ui/card.tsx +88 -0
- package/src/components/ui/error-card.tsx +65 -0
- package/src/components/ui/skeleton.tsx +15 -0
- package/src/components/workflow-trace-view.tsx +306 -0
- package/src/components/workflow-traces/event-colors.ts +94 -0
- package/src/components/workflow-traces/trace-colors.ts +112 -0
- package/src/components/workflow-traces/trace-span-construction.ts +299 -0
- package/src/components/workflow-traces/trace-time-utils.ts +50 -0
- package/src/hooks/use-dark-mode.ts +34 -0
- package/src/index.d.ts +1 -0
- package/src/index.ts +29 -0
- package/src/lib/event-analysis.ts +231 -0
- package/src/lib/utils.ts +166 -0
- package/dist/api/workflow-api-client.d.ts +0 -543
- package/dist/api/workflow-api-client.d.ts.map +0 -1
- package/dist/api/workflow-api-client.js +0 -953
- package/dist/api/workflow-api-client.js.map +0 -1
- package/dist/api/workflow-server-actions.d.ts +0 -230
- package/dist/api/workflow-server-actions.d.ts.map +0 -1
- package/dist/api/workflow-server-actions.js +0 -861
- package/dist/api/workflow-server-actions.js.map +0 -1
- package/dist/error-boundary.d.ts.map +0 -1
- package/dist/error-boundary.js.map +0 -1
- package/dist/event-list-view.d.ts.map +0 -1
- package/dist/event-list-view.js.map +0 -1
- package/dist/hook-actions.d.ts.map +0 -1
- package/dist/hook-actions.js.map +0 -1
- package/dist/run-trace-view.d.ts +0 -8
- package/dist/run-trace-view.d.ts.map +0 -1
- package/dist/run-trace-view.js +0 -15
- package/dist/run-trace-view.js.map +0 -1
- package/dist/sidebar/attribute-panel.d.ts.map +0 -1
- package/dist/sidebar/attribute-panel.js.map +0 -1
- package/dist/sidebar/conversation-view.d.ts.map +0 -1
- package/dist/sidebar/conversation-view.js.map +0 -1
- package/dist/sidebar/detail-card.d.ts.map +0 -1
- package/dist/sidebar/detail-card.js.map +0 -1
- package/dist/sidebar/entity-detail-panel.d.ts +0 -12
- package/dist/sidebar/entity-detail-panel.d.ts.map +0 -1
- package/dist/sidebar/entity-detail-panel.js.map +0 -1
- package/dist/sidebar/events-list.d.ts +0 -9
- package/dist/sidebar/events-list.d.ts.map +0 -1
- package/dist/sidebar/events-list.js +0 -36
- package/dist/sidebar/events-list.js.map +0 -1
- package/dist/sidebar/resolve-hook-modal.d.ts.map +0 -1
- package/dist/sidebar/resolve-hook-modal.js.map +0 -1
- package/dist/stream-viewer.d.ts +0 -13
- package/dist/stream-viewer.d.ts.map +0 -1
- package/dist/stream-viewer.js.map +0 -1
- package/dist/trace-viewer/components/map.d.ts.map +0 -1
- package/dist/trace-viewer/components/map.js.map +0 -1
- package/dist/trace-viewer/components/markers.d.ts.map +0 -1
- package/dist/trace-viewer/components/markers.js.map +0 -1
- package/dist/trace-viewer/components/node.d.ts.map +0 -1
- package/dist/trace-viewer/components/node.js.map +0 -1
- package/dist/trace-viewer/components/search-input.d.ts.map +0 -1
- package/dist/trace-viewer/components/search-input.js.map +0 -1
- package/dist/trace-viewer/components/search.d.ts.map +0 -1
- package/dist/trace-viewer/components/search.js.map +0 -1
- package/dist/trace-viewer/components/span-detail-panel.d.ts.map +0 -1
- package/dist/trace-viewer/components/span-detail-panel.js.map +0 -1
- package/dist/trace-viewer/components/ui.d.ts.map +0 -1
- package/dist/trace-viewer/components/ui.js.map +0 -1
- package/dist/trace-viewer/components/zoom-button.d.ts.map +0 -1
- package/dist/trace-viewer/components/zoom-button.js.map +0 -1
- package/dist/trace-viewer/components/zoom-icons.d.ts.map +0 -1
- package/dist/trace-viewer/components/zoom-icons.js.map +0 -1
- package/dist/trace-viewer/context.d.ts.map +0 -1
- package/dist/trace-viewer/context.js.map +0 -1
- package/dist/trace-viewer/index.d.ts.map +0 -1
- package/dist/trace-viewer/index.js.map +0 -1
- package/dist/trace-viewer/trace-viewer.d.ts.map +0 -1
- package/dist/trace-viewer/trace-viewer.js.map +0 -1
- package/dist/trace-viewer/types.d.ts.map +0 -1
- package/dist/trace-viewer/types.js.map +0 -1
- package/dist/trace-viewer/util/constants.d.ts.map +0 -1
- package/dist/trace-viewer/util/constants.js.map +0 -1
- package/dist/trace-viewer/util/scrollbar-width.d.ts.map +0 -1
- package/dist/trace-viewer/util/scrollbar-width.js.map +0 -1
- package/dist/trace-viewer/util/timing.d.ts.map +0 -1
- package/dist/trace-viewer/util/timing.js.map +0 -1
- package/dist/trace-viewer/util/tree.d.ts.map +0 -1
- package/dist/trace-viewer/util/tree.js.map +0 -1
- package/dist/trace-viewer/util/use-immediate-style.d.ts.map +0 -1
- package/dist/trace-viewer/util/use-immediate-style.js.map +0 -1
- package/dist/trace-viewer/util/use-streaming-spans.d.ts.map +0 -1
- package/dist/trace-viewer/util/use-streaming-spans.js.map +0 -1
- package/dist/trace-viewer/util/use-trackpad-zoom.d.ts.map +0 -1
- package/dist/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
- package/dist/trace-viewer/worker.d.ts.map +0 -1
- package/dist/trace-viewer/worker.js.map +0 -1
- package/dist/workflow-trace-view.d.ts +0 -14
- package/dist/workflow-trace-view.d.ts.map +0 -1
- package/dist/workflow-trace-view.js +0 -135
- package/dist/workflow-trace-view.js.map +0 -1
- package/dist/workflow-traces/event-colors.d.ts.map +0 -1
- package/dist/workflow-traces/event-colors.js.map +0 -1
- package/dist/workflow-traces/trace-colors.d.ts.map +0 -1
- package/dist/workflow-traces/trace-colors.js.map +0 -1
- package/dist/workflow-traces/trace-span-construction.d.ts.map +0 -1
- package/dist/workflow-traces/trace-span-construction.js.map +0 -1
- package/dist/workflow-traces/trace-time-utils.d.ts.map +0 -1
- package/dist/workflow-traces/trace-time-utils.js.map +0 -1
- package/server/README.md +0 -1
- package/server/package.json +0 -4
- /package/dist/{error-boundary.d.ts → components/error-boundary.d.ts} +0 -0
- /package/dist/{sidebar → components/sidebar}/attribute-panel.d.ts +0 -0
- /package/dist/{sidebar → components/sidebar}/conversation-view.d.ts +0 -0
- /package/dist/{sidebar → components/sidebar}/conversation-view.js +0 -0
- /package/dist/{sidebar → components/sidebar}/detail-card.d.ts +0 -0
- /package/dist/{sidebar → components/sidebar}/detail-card.js +0 -0
- /package/dist/{sidebar → components/sidebar}/resolve-hook-modal.d.ts +0 -0
- /package/dist/{sidebar → components/sidebar}/resolve-hook-modal.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/map.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/map.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/markers.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/markers.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/node.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/node.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/search-input.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/search-input.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/search.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/search.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/span-detail-panel.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/span-detail-panel.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/ui.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/ui.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-button.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-button.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-icons.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-icons.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/context.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/context.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/index.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/index.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.module.css +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/types.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/types.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/constants.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/constants.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/scrollbar-width.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/scrollbar-width.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/tree.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/tree.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/use-immediate-style.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/use-immediate-style.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/use-streaming-spans.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/use-streaming-spans.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/use-trackpad-zoom.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/util/use-trackpad-zoom.js +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/worker.d.ts +0 -0
- /package/dist/{trace-viewer → components/trace-viewer}/worker.js +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/event-colors.d.ts +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/event-colors.js +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/trace-colors.d.ts +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/trace-colors.js +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/trace-span-construction.d.ts +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/trace-span-construction.js +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/trace-time-utils.d.ts +0 -0
- /package/dist/{workflow-traces → components/workflow-traces}/trace-time-utils.js +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
|
|
7
|
+
const Card = React.forwardRef<
|
|
8
|
+
HTMLDivElement,
|
|
9
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
10
|
+
>(({ className, ...props }, ref) => (
|
|
11
|
+
<div
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn(
|
|
14
|
+
'rounded-lg border bg-card text-card-foreground shadow-sm',
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
));
|
|
20
|
+
Card.displayName = 'Card';
|
|
21
|
+
|
|
22
|
+
const CardHeader = React.forwardRef<
|
|
23
|
+
HTMLDivElement,
|
|
24
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
25
|
+
>(({ className, ...props }, ref) => (
|
|
26
|
+
<div
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={cn('flex flex-col space-y-1.5 p-6', className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
CardHeader.displayName = 'CardHeader';
|
|
33
|
+
|
|
34
|
+
const CardTitle = React.forwardRef<
|
|
35
|
+
HTMLDivElement,
|
|
36
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
37
|
+
>(({ className, ...props }, ref) => (
|
|
38
|
+
<div
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn(
|
|
41
|
+
'text-2xl font-semibold leading-none tracking-tight',
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
));
|
|
47
|
+
CardTitle.displayName = 'CardTitle';
|
|
48
|
+
|
|
49
|
+
const CardDescription = React.forwardRef<
|
|
50
|
+
HTMLDivElement,
|
|
51
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
52
|
+
>(({ className, ...props }, ref) => (
|
|
53
|
+
<div
|
|
54
|
+
ref={ref}
|
|
55
|
+
className={cn('text-sm text-muted-foreground', className)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
));
|
|
59
|
+
CardDescription.displayName = 'CardDescription';
|
|
60
|
+
|
|
61
|
+
const CardContent = React.forwardRef<
|
|
62
|
+
HTMLDivElement,
|
|
63
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
64
|
+
>(({ className, ...props }, ref) => (
|
|
65
|
+
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
|
|
66
|
+
));
|
|
67
|
+
CardContent.displayName = 'CardContent';
|
|
68
|
+
|
|
69
|
+
const CardFooter = React.forwardRef<
|
|
70
|
+
HTMLDivElement,
|
|
71
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
72
|
+
>(({ className, ...props }, ref) => (
|
|
73
|
+
<div
|
|
74
|
+
ref={ref}
|
|
75
|
+
className={cn('flex items-center p-6 pt-0', className)}
|
|
76
|
+
{...props}
|
|
77
|
+
/>
|
|
78
|
+
));
|
|
79
|
+
CardFooter.displayName = 'CardFooter';
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
Card,
|
|
83
|
+
CardHeader,
|
|
84
|
+
CardFooter,
|
|
85
|
+
CardTitle,
|
|
86
|
+
CardDescription,
|
|
87
|
+
CardContent,
|
|
88
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { AlertCircle, ChevronDown } from 'lucide-react';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
|
|
7
|
+
interface ErrorCardProps {
|
|
8
|
+
/** Title shown in the header */
|
|
9
|
+
title: string;
|
|
10
|
+
/** Error message or details to show when expanded */
|
|
11
|
+
details?: string;
|
|
12
|
+
/** Additional class names */
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A collapsible error card that shows a title with an error icon,
|
|
18
|
+
* and expands to reveal details when clicked.
|
|
19
|
+
*/
|
|
20
|
+
export function ErrorCard({
|
|
21
|
+
title,
|
|
22
|
+
className,
|
|
23
|
+
details = 'Unknown error',
|
|
24
|
+
}: ErrorCardProps) {
|
|
25
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="flex justify-center w-full">
|
|
29
|
+
<div
|
|
30
|
+
className={cn(
|
|
31
|
+
'rounded-lg border border-destructive/50 bg-destructive/5 w-full max-w-[800px]',
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
34
|
+
>
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
38
|
+
className="w-full px-4 py-3 flex items-center justify-between gap-2 text-left hover:bg-destructive/10 transition-colors"
|
|
39
|
+
>
|
|
40
|
+
<div className="flex items-center gap-2 text-destructive">
|
|
41
|
+
<AlertCircle className="h-4 w-4 shrink-0" />
|
|
42
|
+
<span className="font-medium text-sm">{title}</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div className="flex items-center gap-1.5 text-destructive/70">
|
|
45
|
+
<span className="text-xs">Click to show details</span>
|
|
46
|
+
<ChevronDown
|
|
47
|
+
className={cn(
|
|
48
|
+
'h-4 w-4 transition-transform duration-200',
|
|
49
|
+
isExpanded && 'rotate-180'
|
|
50
|
+
)}
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
53
|
+
</button>
|
|
54
|
+
|
|
55
|
+
{isExpanded && details && (
|
|
56
|
+
<div className="px-4 pb-3 border-t border-destructive/20">
|
|
57
|
+
<pre className="mt-3 p-3 rounded-md bg-destructive/10 text-destructive text-xs font-mono whitespace-pre-wrap break-words overflow-auto">
|
|
58
|
+
{details}
|
|
59
|
+
</pre>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cn } from '../../lib/utils';
|
|
2
|
+
|
|
3
|
+
function Skeleton({
|
|
4
|
+
className,
|
|
5
|
+
...props
|
|
6
|
+
}: React.HTMLAttributes<HTMLDivElement>) {
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
className={cn('animate-pulse rounded-md bg-muted', className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { Skeleton };
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { Event, Hook, Step, WorkflowRun } from '@workflow/world';
|
|
4
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
5
|
+
import { toast } from 'sonner';
|
|
6
|
+
import { ErrorBoundary } from './error-boundary';
|
|
7
|
+
import {
|
|
8
|
+
EntityDetailPanel,
|
|
9
|
+
type SpanSelectionInfo,
|
|
10
|
+
} from './sidebar/entity-detail-panel';
|
|
11
|
+
import {
|
|
12
|
+
TraceViewerContextProvider,
|
|
13
|
+
TraceViewerTimeline,
|
|
14
|
+
} from './trace-viewer';
|
|
15
|
+
import type { Span } from './trace-viewer/types';
|
|
16
|
+
import { Skeleton } from './ui/skeleton';
|
|
17
|
+
import {
|
|
18
|
+
getCustomSpanClassName,
|
|
19
|
+
getCustomSpanEventClassName,
|
|
20
|
+
} from './workflow-traces/trace-colors';
|
|
21
|
+
import {
|
|
22
|
+
hookToSpan,
|
|
23
|
+
runToSpan,
|
|
24
|
+
stepToSpan,
|
|
25
|
+
WORKFLOW_LIBRARY,
|
|
26
|
+
waitToSpan,
|
|
27
|
+
} from './workflow-traces/trace-span-construction';
|
|
28
|
+
import { otelTimeToMs } from './workflow-traces/trace-time-utils';
|
|
29
|
+
|
|
30
|
+
const RE_RENDER_INTERVAL_MS = 2000;
|
|
31
|
+
|
|
32
|
+
type GroupedEvents = {
|
|
33
|
+
eventsByStepId: Map<string, Event[]>;
|
|
34
|
+
eventsByHookId: Map<string, Event[]>;
|
|
35
|
+
runLevelEvents: Event[];
|
|
36
|
+
timerEvents: Map<string, Event[]>;
|
|
37
|
+
hookEvents: Map<string, Event[]>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const isTimerEvent = (eventType: string) =>
|
|
41
|
+
eventType === 'wait_created' || eventType === 'wait_completed';
|
|
42
|
+
|
|
43
|
+
const isHookLifecycleEvent = (eventType: string) =>
|
|
44
|
+
eventType === 'hook_received' ||
|
|
45
|
+
eventType === 'hook_created' ||
|
|
46
|
+
eventType === 'hook_disposed';
|
|
47
|
+
|
|
48
|
+
const pushEvent = (
|
|
49
|
+
map: Map<string, Event[]>,
|
|
50
|
+
correlationId: string,
|
|
51
|
+
event: Event
|
|
52
|
+
) => {
|
|
53
|
+
const existing = map.get(correlationId);
|
|
54
|
+
if (existing) {
|
|
55
|
+
existing.push(event);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
map.set(correlationId, [event]);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const groupEventsByCorrelation = (
|
|
62
|
+
events: Event[],
|
|
63
|
+
steps: Step[],
|
|
64
|
+
hooks: Hook[]
|
|
65
|
+
): GroupedEvents => {
|
|
66
|
+
const eventsByStepId = new Map<string, Event[]>();
|
|
67
|
+
const eventsByHookId = new Map<string, Event[]>();
|
|
68
|
+
const runLevelEvents: Event[] = [];
|
|
69
|
+
const timerEvents = new Map<string, Event[]>();
|
|
70
|
+
const hookEvents = new Map<string, Event[]>();
|
|
71
|
+
const stepIds = new Set(steps.map((step) => step.stepId));
|
|
72
|
+
const hookIds = new Set(hooks.map((hook) => hook.hookId));
|
|
73
|
+
|
|
74
|
+
for (const event of events) {
|
|
75
|
+
const correlationId = event.correlationId;
|
|
76
|
+
if (!correlationId) {
|
|
77
|
+
runLevelEvents.push(event);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (isTimerEvent(event.eventType)) {
|
|
82
|
+
pushEvent(timerEvents, correlationId, event);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isHookLifecycleEvent(event.eventType)) {
|
|
87
|
+
pushEvent(hookEvents, correlationId, event);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (stepIds.has(correlationId)) {
|
|
92
|
+
pushEvent(eventsByStepId, correlationId, event);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (hookIds.has(correlationId)) {
|
|
97
|
+
pushEvent(eventsByHookId, correlationId, event);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
runLevelEvents.push(event);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
eventsByStepId,
|
|
106
|
+
eventsByHookId,
|
|
107
|
+
runLevelEvents,
|
|
108
|
+
timerEvents,
|
|
109
|
+
hookEvents,
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const buildSpans = (
|
|
114
|
+
run: WorkflowRun,
|
|
115
|
+
steps: Step[],
|
|
116
|
+
groupedEvents: GroupedEvents,
|
|
117
|
+
now: Date
|
|
118
|
+
) => {
|
|
119
|
+
const stepSpans = steps.map((step) => {
|
|
120
|
+
const stepEvents = groupedEvents.eventsByStepId.get(step.stepId) || [];
|
|
121
|
+
return stepToSpan(step, stepEvents, now);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const hookSpans = Array.from(groupedEvents.hookEvents.values())
|
|
125
|
+
.map((events) => hookToSpan(events, run, now))
|
|
126
|
+
.filter((span): span is Span => span !== null);
|
|
127
|
+
|
|
128
|
+
const waitSpans = Array.from(groupedEvents.timerEvents.values())
|
|
129
|
+
.map((events) => waitToSpan(events, run, now))
|
|
130
|
+
.filter((span): span is Span => span !== null);
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
runSpan: runToSpan(run, groupedEvents.runLevelEvents, now),
|
|
134
|
+
spans: [...stepSpans, ...hookSpans, ...waitSpans],
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const cascadeSpans = (runSpan: Span, spans: Span[]) => {
|
|
139
|
+
const sortedSpans = [
|
|
140
|
+
runSpan,
|
|
141
|
+
...spans.slice().sort((a, b) => {
|
|
142
|
+
const aStart = otelTimeToMs(a.startTime);
|
|
143
|
+
const bStart = otelTimeToMs(b.startTime);
|
|
144
|
+
return aStart - bStart;
|
|
145
|
+
}),
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
return sortedSpans.map((span, index) => {
|
|
149
|
+
const parentSpanId =
|
|
150
|
+
index === 0 ? undefined : String(sortedSpans[index - 1].spanId);
|
|
151
|
+
return {
|
|
152
|
+
...span,
|
|
153
|
+
parentSpanId,
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const buildTrace = (
|
|
159
|
+
run: WorkflowRun,
|
|
160
|
+
steps: Step[],
|
|
161
|
+
hooks: Hook[],
|
|
162
|
+
events: Event[],
|
|
163
|
+
now: Date
|
|
164
|
+
) => {
|
|
165
|
+
const groupedEvents = groupEventsByCorrelation(events, steps, hooks);
|
|
166
|
+
const { runSpan, spans } = buildSpans(run, steps, groupedEvents, now);
|
|
167
|
+
const sortedCascadingSpans = cascadeSpans(runSpan, spans);
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
traceId: run.runId,
|
|
171
|
+
rootSpanId: run.runId,
|
|
172
|
+
spans: sortedCascadingSpans,
|
|
173
|
+
resources: [
|
|
174
|
+
{
|
|
175
|
+
name: 'workflow',
|
|
176
|
+
attributes: {
|
|
177
|
+
'service.name': WORKFLOW_LIBRARY.name,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/** Re-export SpanSelectionInfo for consumers */
|
|
185
|
+
export type { SpanSelectionInfo };
|
|
186
|
+
|
|
187
|
+
export const WorkflowTraceViewer = ({
|
|
188
|
+
run,
|
|
189
|
+
steps,
|
|
190
|
+
hooks,
|
|
191
|
+
events,
|
|
192
|
+
isLoading,
|
|
193
|
+
error,
|
|
194
|
+
spanDetailData,
|
|
195
|
+
spanDetailLoading,
|
|
196
|
+
spanDetailError,
|
|
197
|
+
onWakeUpSleep,
|
|
198
|
+
onResolveHook,
|
|
199
|
+
onStreamClick,
|
|
200
|
+
onSpanSelect,
|
|
201
|
+
}: {
|
|
202
|
+
run: WorkflowRun;
|
|
203
|
+
steps: Step[];
|
|
204
|
+
hooks: Hook[];
|
|
205
|
+
events: Event[];
|
|
206
|
+
isLoading?: boolean;
|
|
207
|
+
error?: Error | null;
|
|
208
|
+
spanDetailData?: WorkflowRun | Step | Hook | Event | null;
|
|
209
|
+
spanDetailLoading?: boolean;
|
|
210
|
+
spanDetailError?: Error | null;
|
|
211
|
+
onWakeUpSleep?: (
|
|
212
|
+
runId: string,
|
|
213
|
+
correlationId: string
|
|
214
|
+
) => Promise<{ stoppedCount: number }>;
|
|
215
|
+
onResolveHook?: (
|
|
216
|
+
hookToken: string,
|
|
217
|
+
payload: unknown,
|
|
218
|
+
hook?: Hook
|
|
219
|
+
) => Promise<void>;
|
|
220
|
+
/** Callback when a stream reference is clicked in the detail panel */
|
|
221
|
+
onStreamClick?: (streamId: string) => void;
|
|
222
|
+
/** Callback when a span is selected. */
|
|
223
|
+
onSpanSelect?: (info: SpanSelectionInfo) => void;
|
|
224
|
+
}) => {
|
|
225
|
+
const [now, setNow] = useState(() => new Date());
|
|
226
|
+
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (!run?.completedAt) {
|
|
229
|
+
const interval = setInterval(() => {
|
|
230
|
+
setNow(new Date());
|
|
231
|
+
}, RE_RENDER_INTERVAL_MS);
|
|
232
|
+
return () => clearInterval(interval);
|
|
233
|
+
}
|
|
234
|
+
return undefined;
|
|
235
|
+
}, [run?.completedAt]);
|
|
236
|
+
|
|
237
|
+
const trace = useMemo(() => {
|
|
238
|
+
if (!run) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
return buildTrace(run, steps, hooks, events, now);
|
|
242
|
+
}, [run, steps, hooks, events, now]);
|
|
243
|
+
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
if (error && !isLoading) {
|
|
246
|
+
console.error(error);
|
|
247
|
+
toast.error('Error loading workflow trace data', {
|
|
248
|
+
description: error.message,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}, [error, isLoading]);
|
|
252
|
+
|
|
253
|
+
const DetailPanel = () => {
|
|
254
|
+
const handleSpanSelect = useCallback(
|
|
255
|
+
(info: SpanSelectionInfo) => {
|
|
256
|
+
onSpanSelect?.(info);
|
|
257
|
+
},
|
|
258
|
+
[onSpanSelect]
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
<EntityDetailPanel
|
|
263
|
+
run={run}
|
|
264
|
+
onStreamClick={onStreamClick}
|
|
265
|
+
spanDetailData={spanDetailData ?? null}
|
|
266
|
+
spanDetailError={spanDetailError}
|
|
267
|
+
spanDetailLoading={spanDetailLoading}
|
|
268
|
+
onSpanSelect={handleSpanSelect}
|
|
269
|
+
onWakeUpSleep={onWakeUpSleep}
|
|
270
|
+
onResolveHook={onResolveHook}
|
|
271
|
+
/>
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
if (isLoading || !trace) {
|
|
276
|
+
return (
|
|
277
|
+
<div className="relative w-full h-full">
|
|
278
|
+
<div className="border-b border-gray-alpha-400 w-full" />
|
|
279
|
+
<Skeleton className="w-full ml-2 mt-1 mb-1 h-[56px]" />
|
|
280
|
+
<div className="p-2 relative w-full">
|
|
281
|
+
<Skeleton className="w-full mt-6 h-[20px]" />
|
|
282
|
+
<Skeleton className="w-[10%] mt-2 ml-6 h-[20px]" />
|
|
283
|
+
<Skeleton className="w-[10%] mt-2 ml-12 h-[20px]" />
|
|
284
|
+
<Skeleton className="w-[20%] mt-2 ml-16 h-[20px]" />
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return (
|
|
291
|
+
<div className="relative w-full h-full">
|
|
292
|
+
<TraceViewerContextProvider
|
|
293
|
+
withPanel
|
|
294
|
+
customSpanClassNameFunc={getCustomSpanClassName}
|
|
295
|
+
customSpanEventClassNameFunc={getCustomSpanEventClassName}
|
|
296
|
+
customPanelComponent={
|
|
297
|
+
<ErrorBoundary title="Failed to load entity details">
|
|
298
|
+
<DetailPanel />
|
|
299
|
+
</ErrorBoundary>
|
|
300
|
+
}
|
|
301
|
+
>
|
|
302
|
+
<TraceViewerTimeline height="100%" trace={trace} withPanel />
|
|
303
|
+
</TraceViewerContextProvider>
|
|
304
|
+
</div>
|
|
305
|
+
);
|
|
306
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color utilities for workflow event markers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Event } from '@workflow/world';
|
|
6
|
+
|
|
7
|
+
export interface EventColorPalette {
|
|
8
|
+
/** Color of the diamond/marker itself */
|
|
9
|
+
color: string;
|
|
10
|
+
/** Background color for hover info popup */
|
|
11
|
+
background: string;
|
|
12
|
+
/** Border color for hover info popup */
|
|
13
|
+
border: string;
|
|
14
|
+
/** Text color for event name in hover popup */
|
|
15
|
+
text: string;
|
|
16
|
+
/** Secondary text color for timestamp in hover popup */
|
|
17
|
+
secondary: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get the color palette for an event based on its type
|
|
22
|
+
* - Red for failures (step_failed, run_failed)
|
|
23
|
+
* - Orange/yellow for retries (step_retrying)
|
|
24
|
+
* - Purple for webhook-related events
|
|
25
|
+
* - Blue otherwise (default)
|
|
26
|
+
*/
|
|
27
|
+
export function getEventColor(
|
|
28
|
+
eventType: Event['eventType']
|
|
29
|
+
): EventColorPalette {
|
|
30
|
+
// Failures - Red
|
|
31
|
+
if (eventType === 'step_failed' || eventType === 'run_failed') {
|
|
32
|
+
return {
|
|
33
|
+
color: 'var(--ds-red-600)',
|
|
34
|
+
background: 'var(--ds-red-100)',
|
|
35
|
+
border: 'var(--ds-red-500)',
|
|
36
|
+
text: 'var(--ds-red-900)',
|
|
37
|
+
secondary: 'var(--ds-red-700)',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Retries - Orange/Yellow
|
|
42
|
+
if (eventType === 'step_retrying') {
|
|
43
|
+
return {
|
|
44
|
+
color: 'var(--ds-amber-600)',
|
|
45
|
+
background: 'var(--ds-amber-100)',
|
|
46
|
+
border: 'var(--ds-amber-500)',
|
|
47
|
+
text: 'var(--ds-amber-900)',
|
|
48
|
+
secondary: 'var(--ds-amber-700)',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Webhook-related - Purple
|
|
53
|
+
if (
|
|
54
|
+
eventType === 'hook_created' ||
|
|
55
|
+
eventType === 'hook_received' ||
|
|
56
|
+
eventType === 'hook_disposed'
|
|
57
|
+
) {
|
|
58
|
+
return {
|
|
59
|
+
color: 'var(--ds-purple-600)',
|
|
60
|
+
background: 'var(--ds-purple-100)',
|
|
61
|
+
border: 'var(--ds-purple-500)',
|
|
62
|
+
text: 'var(--ds-purple-900)',
|
|
63
|
+
secondary: 'var(--ds-purple-700)',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Default - Blue
|
|
68
|
+
return {
|
|
69
|
+
color: 'var(--ds-blue-600)',
|
|
70
|
+
background: 'var(--ds-blue-100)',
|
|
71
|
+
border: 'var(--ds-blue-500)',
|
|
72
|
+
text: 'var(--ds-blue-900)',
|
|
73
|
+
secondary: 'var(--ds-blue-700)',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Determine whether to show a vertical line for an event
|
|
79
|
+
* - Show vertical lines for hook-related events
|
|
80
|
+
* - Hide vertical lines for all other workflow events by default
|
|
81
|
+
*/
|
|
82
|
+
export function shouldShowVerticalLine(eventType: Event['eventType']): boolean {
|
|
83
|
+
// Show vertical lines for hook-related events
|
|
84
|
+
if (
|
|
85
|
+
eventType === 'hook_created' ||
|
|
86
|
+
eventType === 'hook_received' ||
|
|
87
|
+
eventType === 'hook_disposed'
|
|
88
|
+
) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Hide vertical lines for all other workflow events
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color utilities for workflow traces
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Step, WorkflowRun } from '@workflow/world';
|
|
6
|
+
import styles from '../trace-viewer/trace-viewer.module.css';
|
|
7
|
+
import type { SpanNode, SpanNodeEvent } from '../trace-viewer/types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get the CSS class name for a workflow entity based on its status
|
|
11
|
+
*/
|
|
12
|
+
function getStatusClassName(
|
|
13
|
+
status: Step['status'] | WorkflowRun['status'],
|
|
14
|
+
isStripped = false
|
|
15
|
+
): string {
|
|
16
|
+
if (isStripped && status === 'pending') {
|
|
17
|
+
return styles.spanPendingStriped;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
switch (status) {
|
|
21
|
+
case 'running':
|
|
22
|
+
return styles.spanRunning;
|
|
23
|
+
case 'pending':
|
|
24
|
+
return styles.spanPending;
|
|
25
|
+
case 'completed':
|
|
26
|
+
return styles.spanCompleted;
|
|
27
|
+
case 'cancelled':
|
|
28
|
+
return styles.spanCancelled;
|
|
29
|
+
case 'failed':
|
|
30
|
+
return styles.spanFailed;
|
|
31
|
+
default:
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Check if a step name indicates it's a sleep step
|
|
38
|
+
*/
|
|
39
|
+
function isSleepStep(stepName: string): boolean {
|
|
40
|
+
return String(stepName).toLowerCase().endsWith('sleep');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get custom CSS class name for a span based on its attributes
|
|
45
|
+
* This is called dynamically by the trace viewer to style spans
|
|
46
|
+
*/
|
|
47
|
+
export const getCustomSpanClassName = (span: SpanNode): string => {
|
|
48
|
+
const attributes = span.span.attributes;
|
|
49
|
+
const resource = attributes?.resource;
|
|
50
|
+
|
|
51
|
+
if (resource === 'step') {
|
|
52
|
+
const stepData = attributes.data as Step;
|
|
53
|
+
const stepName = stepData?.stepName;
|
|
54
|
+
|
|
55
|
+
// DEPRECATED: Check if it's a sleep step
|
|
56
|
+
if (stepName && isSleepStep(stepName)) {
|
|
57
|
+
return styles.spanSleep;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Regular step - use status colors
|
|
61
|
+
const isStripped = stepData?.status === 'pending';
|
|
62
|
+
return getStatusClassName(stepData?.status, isStripped);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (resource === 'run') {
|
|
66
|
+
const runData = attributes.data as WorkflowRun;
|
|
67
|
+
return getStatusClassName(runData?.status, false);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (resource === 'hook') {
|
|
71
|
+
return styles.spanHook;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (resource === 'sleep') {
|
|
75
|
+
return styles.spanSleep;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Default: no custom class
|
|
79
|
+
return '';
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get custom CSS class name for a span event based on its type
|
|
84
|
+
* This is called dynamically by the trace viewer to style event markers
|
|
85
|
+
*/
|
|
86
|
+
export const getCustomSpanEventClassName = (
|
|
87
|
+
spanEvent: SpanNodeEvent
|
|
88
|
+
): string => {
|
|
89
|
+
const eventName = spanEvent.event.name;
|
|
90
|
+
|
|
91
|
+
// Failure events - Red
|
|
92
|
+
if (eventName === 'step_failed' || eventName === 'run_failed') {
|
|
93
|
+
return styles.eventFailed;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Retry events - Orange/Yellow
|
|
97
|
+
if (eventName === 'step_retrying') {
|
|
98
|
+
return styles.eventRetrying;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Webhook-related events - Purple
|
|
102
|
+
if (
|
|
103
|
+
eventName === 'hook_created' ||
|
|
104
|
+
eventName === 'hook_received' ||
|
|
105
|
+
eventName === 'hook_disposed'
|
|
106
|
+
) {
|
|
107
|
+
return styles.eventHook;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Default - Blue
|
|
111
|
+
return styles.eventDefault;
|
|
112
|
+
};
|