@workflow/web-shared 4.1.0-beta.52 → 4.1.0-beta.53

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 (145) hide show
  1. package/dist/components/error-boundary.d.ts +15 -20
  2. package/dist/components/error-boundary.d.ts.map +1 -1
  3. package/dist/components/error-boundary.js +17 -31
  4. package/dist/components/error-boundary.js.map +1 -1
  5. package/dist/components/event-list-view.d.ts +7 -6
  6. package/dist/components/event-list-view.d.ts.map +1 -1
  7. package/dist/components/event-list-view.js +492 -109
  8. package/dist/components/event-list-view.js.map +1 -1
  9. package/dist/components/index.d.ts +1 -0
  10. package/dist/components/index.d.ts.map +1 -1
  11. package/dist/components/index.js +1 -0
  12. package/dist/components/index.js.map +1 -1
  13. package/dist/components/run-trace-view.d.ts +2 -1
  14. package/dist/components/run-trace-view.d.ts.map +1 -1
  15. package/dist/components/run-trace-view.js +2 -2
  16. package/dist/components/run-trace-view.js.map +1 -1
  17. package/dist/components/sidebar/attribute-panel.d.ts +2 -1
  18. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  19. package/dist/components/sidebar/attribute-panel.js +53 -142
  20. package/dist/components/sidebar/attribute-panel.js.map +1 -1
  21. package/dist/components/sidebar/conversation-view.d.ts.map +1 -1
  22. package/dist/components/sidebar/conversation-view.js +3 -17
  23. package/dist/components/sidebar/conversation-view.js.map +1 -1
  24. package/dist/components/sidebar/entity-detail-panel.d.ts +3 -1
  25. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  26. package/dist/components/sidebar/entity-detail-panel.js +63 -10
  27. package/dist/components/sidebar/entity-detail-panel.js.map +1 -1
  28. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  29. package/dist/components/sidebar/events-list.js +4 -8
  30. package/dist/components/sidebar/events-list.js.map +1 -1
  31. package/dist/components/sidebar/resolve-hook-modal.d.ts +3 -0
  32. package/dist/components/sidebar/resolve-hook-modal.d.ts.map +1 -1
  33. package/dist/components/sidebar/resolve-hook-modal.js +152 -3
  34. package/dist/components/sidebar/resolve-hook-modal.js.map +1 -1
  35. package/dist/components/stream-viewer.d.ts +7 -5
  36. package/dist/components/stream-viewer.d.ts.map +1 -1
  37. package/dist/components/stream-viewer.js +54 -22
  38. package/dist/components/stream-viewer.js.map +1 -1
  39. package/dist/components/trace-viewer/components/markers.d.ts +2 -1
  40. package/dist/components/trace-viewer/components/markers.d.ts.map +1 -1
  41. package/dist/components/trace-viewer/components/markers.js +59 -20
  42. package/dist/components/trace-viewer/components/markers.js.map +1 -1
  43. package/dist/components/trace-viewer/components/node.d.ts +5 -1
  44. package/dist/components/trace-viewer/components/node.d.ts.map +1 -1
  45. package/dist/components/trace-viewer/components/node.js +250 -68
  46. package/dist/components/trace-viewer/components/node.js.map +1 -1
  47. package/dist/components/trace-viewer/components/span-content.d.ts +19 -0
  48. package/dist/components/trace-viewer/components/span-content.d.ts.map +1 -0
  49. package/dist/components/trace-viewer/components/span-content.js +137 -0
  50. package/dist/components/trace-viewer/components/span-content.js.map +1 -0
  51. package/dist/components/trace-viewer/components/span-detail-panel.d.ts.map +1 -1
  52. package/dist/components/trace-viewer/components/span-detail-panel.js +3 -2
  53. package/dist/components/trace-viewer/components/span-detail-panel.js.map +1 -1
  54. package/dist/components/trace-viewer/components/span-segments.d.ts +50 -0
  55. package/dist/components/trace-viewer/components/span-segments.d.ts.map +1 -0
  56. package/dist/components/trace-viewer/components/span-segments.js +392 -0
  57. package/dist/components/trace-viewer/components/span-segments.js.map +1 -0
  58. package/dist/components/trace-viewer/components/span-strategies.d.ts +46 -0
  59. package/dist/components/trace-viewer/components/span-strategies.d.ts.map +1 -0
  60. package/dist/components/trace-viewer/components/span-strategies.js +108 -0
  61. package/dist/components/trace-viewer/components/span-strategies.js.map +1 -0
  62. package/dist/components/trace-viewer/context.d.ts +7 -6
  63. package/dist/components/trace-viewer/context.d.ts.map +1 -1
  64. package/dist/components/trace-viewer/context.js +47 -18
  65. package/dist/components/trace-viewer/context.js.map +1 -1
  66. package/dist/components/trace-viewer/trace-viewer.d.ts +5 -1
  67. package/dist/components/trace-viewer/trace-viewer.d.ts.map +1 -1
  68. package/dist/components/trace-viewer/trace-viewer.js +87 -11
  69. package/dist/components/trace-viewer/trace-viewer.js.map +1 -1
  70. package/dist/components/trace-viewer/trace-viewer.module.css +179 -6
  71. package/dist/components/trace-viewer/util/timing.d.ts +5 -0
  72. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
  73. package/dist/components/trace-viewer/util/timing.js +12 -0
  74. package/dist/components/trace-viewer/util/timing.js.map +1 -1
  75. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts +1 -1
  76. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts.map +1 -1
  77. package/dist/components/trace-viewer/util/use-streaming-spans.js +29 -17
  78. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +1 -1
  79. package/dist/components/trace-viewer/worker.js +3 -1
  80. package/dist/components/trace-viewer/worker.js.map +1 -1
  81. package/dist/components/ui/alert.js +3 -3
  82. package/dist/components/ui/alert.js.map +1 -1
  83. package/dist/components/ui/card.d.ts.map +1 -1
  84. package/dist/components/ui/card.js +2 -2
  85. package/dist/components/ui/card.js.map +1 -1
  86. package/dist/components/ui/data-inspector.d.ts +17 -0
  87. package/dist/components/ui/data-inspector.d.ts.map +1 -0
  88. package/dist/components/ui/data-inspector.js +184 -0
  89. package/dist/components/ui/data-inspector.js.map +1 -0
  90. package/dist/components/ui/error-card.d.ts.map +1 -1
  91. package/dist/components/ui/error-card.js +4 -1
  92. package/dist/components/ui/error-card.js.map +1 -1
  93. package/dist/components/ui/inspector-theme.d.ts +39 -24
  94. package/dist/components/ui/inspector-theme.d.ts.map +1 -1
  95. package/dist/components/ui/inspector-theme.js +90 -38
  96. package/dist/components/ui/inspector-theme.js.map +1 -1
  97. package/dist/components/ui/skeleton.d.ts +1 -1
  98. package/dist/components/ui/skeleton.d.ts.map +1 -1
  99. package/dist/components/ui/skeleton.js +2 -2
  100. package/dist/components/ui/skeleton.js.map +1 -1
  101. package/dist/components/workflow-trace-view.d.ts +3 -1
  102. package/dist/components/workflow-trace-view.d.ts.map +1 -1
  103. package/dist/components/workflow-trace-view.js +435 -21
  104. package/dist/components/workflow-trace-view.js.map +1 -1
  105. package/dist/components/workflow-traces/trace-span-construction.d.ts +1 -1
  106. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
  107. package/dist/components/workflow-traces/trace-span-construction.js +2 -2
  108. package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
  109. package/dist/lib/hydration.d.ts.map +1 -1
  110. package/dist/lib/hydration.js +17 -3
  111. package/dist/lib/hydration.js.map +1 -1
  112. package/dist/styles.css +186 -0
  113. package/package.json +8 -7
  114. package/src/components/error-boundary.tsx +29 -40
  115. package/src/components/event-list-view.tsx +1000 -287
  116. package/src/components/index.ts +1 -0
  117. package/src/components/run-trace-view.tsx +3 -0
  118. package/src/components/sidebar/attribute-panel.tsx +58 -258
  119. package/src/components/sidebar/conversation-view.tsx +30 -27
  120. package/src/components/sidebar/entity-detail-panel.tsx +86 -20
  121. package/src/components/sidebar/events-list.tsx +4 -11
  122. package/src/components/sidebar/resolve-hook-modal.tsx +206 -47
  123. package/src/components/stream-viewer.tsx +138 -61
  124. package/src/components/trace-viewer/components/markers.tsx +69 -21
  125. package/src/components/trace-viewer/components/node.tsx +346 -100
  126. package/src/components/trace-viewer/components/span-content.tsx +247 -0
  127. package/src/components/trace-viewer/components/span-detail-panel.tsx +7 -2
  128. package/src/components/trace-viewer/components/span-segments.ts +516 -0
  129. package/src/components/trace-viewer/components/span-strategies.ts +205 -0
  130. package/src/components/trace-viewer/context.tsx +92 -40
  131. package/src/components/trace-viewer/trace-viewer.module.css +179 -6
  132. package/src/components/trace-viewer/trace-viewer.tsx +115 -11
  133. package/src/components/trace-viewer/util/timing.ts +13 -0
  134. package/src/components/trace-viewer/util/use-streaming-spans.ts +28 -17
  135. package/src/components/trace-viewer/worker.ts +4 -1
  136. package/src/components/ui/alert.tsx +3 -3
  137. package/src/components/ui/card.tsx +3 -5
  138. package/src/components/ui/data-inspector.tsx +318 -0
  139. package/src/components/ui/error-card.tsx +17 -6
  140. package/src/components/ui/inspector-theme.ts +127 -39
  141. package/src/components/ui/skeleton.tsx +3 -1
  142. package/src/components/workflow-trace-view.tsx +625 -26
  143. package/src/components/workflow-traces/trace-span-construction.ts +3 -2
  144. package/src/lib/hydration.ts +17 -8
  145. package/src/styles.css +186 -0
@@ -0,0 +1,247 @@
1
+ 'use client';
2
+
3
+ import type { CSSProperties, ReactNode } from 'react';
4
+ import styles from '../trace-viewer.module.css';
5
+ import type { SpanNode } from '../types';
6
+ import { formatDuration } from '../util/timing';
7
+ import {
8
+ type Segment,
9
+ type SegmentStatus,
10
+ SEGMENT_CLASS_MAP,
11
+ computeSegments,
12
+ } from './span-segments';
13
+ import type { ResourceType, SpanLayout } from './span-strategies';
14
+
15
+ // ──────────────────────────────────────────────────────────────────────────
16
+ // Shared helpers
17
+ // ──────────────────────────────────────────────────────────────────────────
18
+
19
+ function getDuration(node: SpanNode): string {
20
+ if (node.isInstrumentationHint) {
21
+ return 'Get Started';
22
+ }
23
+ return formatDuration(node.duration);
24
+ }
25
+
26
+ // ──────────────────────────────────────────────────────────────────────────
27
+ // Segment rendering (shared across all workflow span types)
28
+ // ──────────────────────────────────────────────────────────────────────────
29
+
30
+ const SEGMENT_LABELS: Record<SegmentStatus, string> = {
31
+ queued: 'Queued',
32
+ running: '',
33
+ failed: 'Failed',
34
+ retrying: 'Retry wait',
35
+ succeeded: 'Executed',
36
+ waiting: 'Waiting',
37
+ sleeping: 'Sleeping',
38
+ received: 'Received',
39
+ };
40
+
41
+ function SegmentLayer({
42
+ segments,
43
+ spanDuration,
44
+ }: {
45
+ segments: Segment[];
46
+ spanDuration: number;
47
+ }): ReactNode {
48
+ if (segments.length === 0) return null;
49
+
50
+ return (
51
+ <div className={styles.segmentLayer}>
52
+ {segments.map((seg, i) => {
53
+ const className =
54
+ styles[SEGMENT_CLASS_MAP[seg.status] as keyof typeof styles];
55
+ const segDuration =
56
+ (seg.endFraction - seg.startFraction) * spanDuration;
57
+ const label = SEGMENT_LABELS[seg.status];
58
+ const style: CSSProperties = {
59
+ left: `${seg.startFraction * 100}%`,
60
+ width: `${(seg.endFraction - seg.startFraction) * 100}%`,
61
+ };
62
+
63
+ return (
64
+ <div
65
+ key={`seg-${seg.status}-${String(i)}`}
66
+ className={`${styles.segment} ${String(className)}`}
67
+ style={style}
68
+ title={
69
+ label
70
+ ? `${label} ${formatDuration(segDuration)}`
71
+ : formatDuration(segDuration)
72
+ }
73
+ />
74
+ );
75
+ })}
76
+ </div>
77
+ );
78
+ }
79
+
80
+ /** Build inline segment tags to render next to the span name. */
81
+ function getSegmentTags(
82
+ segments: Segment[],
83
+ spanDuration: number
84
+ ): { label: string; duration: string }[] {
85
+ const tags: { label: string; duration: string }[] = [];
86
+ for (let i = 0; i < segments.length; i++) {
87
+ const seg = segments[i];
88
+ const label = SEGMENT_LABELS[seg.status];
89
+ if (!label) continue; // skip "running" which has no label
90
+ let segDuration = (seg.endFraction - seg.startFraction) * spanDuration;
91
+
92
+ // For terminal segments (succeeded/failed) with ~0 duration,
93
+ // use the preceding running segment's duration instead.
94
+ if (
95
+ segDuration < 1 &&
96
+ (seg.status === 'succeeded' || seg.status === 'failed') &&
97
+ i > 0
98
+ ) {
99
+ const prev = segments[i - 1];
100
+ if (prev.status === 'running') {
101
+ segDuration = (prev.endFraction - prev.startFraction) * spanDuration;
102
+ }
103
+ }
104
+
105
+ // Skip tags that still have no meaningful duration
106
+ if (segDuration < 1) continue;
107
+
108
+ tags.push({ label, duration: formatDuration(segDuration) });
109
+ }
110
+ return tags;
111
+ }
112
+
113
+ // ──────────────────────────────────────────────────────────────────────────
114
+ // Text content (shared label + duration rendering)
115
+ // ──────────────────────────────────────────────────────────────────────────
116
+
117
+ function TextContent({
118
+ node,
119
+ layout,
120
+ durationMs,
121
+ segmentTags,
122
+ }: SpanContentProps & {
123
+ segmentTags?: { label: string; duration: string }[];
124
+ }): ReactNode {
125
+ const duration = node.isInstrumentationHint
126
+ ? getDuration(node)
127
+ : formatDuration(durationMs ?? node.duration);
128
+
129
+ if (layout.isSmall && !layout.isHovered) {
130
+ return null;
131
+ }
132
+
133
+ const showTags =
134
+ segmentTags &&
135
+ segmentTags.length > 0 &&
136
+ (layout.isHovered || layout.width > 200);
137
+
138
+ return (
139
+ <>
140
+ <span className={styles.spanName}>
141
+ {node.label || node.span.name}
142
+ {showTags
143
+ ? segmentTags.map((tag, i) => (
144
+ <span key={i} className={styles.segmentTag}>
145
+ {' · '}
146
+ {tag.label} {tag.duration}
147
+ </span>
148
+ ))
149
+ : null}
150
+ </span>
151
+ {layout.isHuge ? <span className={styles.spanSpacer} /> : null}
152
+ {layout.isHovered || layout.width > 128 ? (
153
+ <span className={styles.spanDuration}>{duration}</span>
154
+ ) : null}
155
+ </>
156
+ );
157
+ }
158
+
159
+ // ──────────────────────────────────────────────────────────────────────────
160
+ // Content props
161
+ // ──────────────────────────────────────────────────────────────────────────
162
+
163
+ export interface SpanContentProps {
164
+ node: SpanNode;
165
+ layout: SpanLayout;
166
+ durationMs?: number;
167
+ }
168
+
169
+ // ──────────────────────────────────────────────────────────────────────────
170
+ // Default content (generic OTEL spans — no segments)
171
+ // ──────────────────────────────────────────────────────────────────────────
172
+
173
+ function DefaultContent({ node, layout }: SpanContentProps): ReactNode {
174
+ return <TextContent node={node} layout={layout} />;
175
+ }
176
+
177
+ // ──────────────────────────────────────────────────────────────────────────
178
+ // Workflow content (segments + text for workflow span types)
179
+ // ──────────────────────────────────────────────────────────────────────────
180
+
181
+ function WorkflowContent({
182
+ resourceType,
183
+ node,
184
+ layout,
185
+ durationMs,
186
+ }: SpanContentProps & { resourceType: ResourceType }): ReactNode {
187
+ const spanDuration = durationMs ?? node.duration;
188
+ const { segments } = computeSegments(resourceType, node);
189
+ const segmentTags = getSegmentTags(segments, spanDuration);
190
+
191
+ return (
192
+ <>
193
+ <SegmentLayer segments={segments} spanDuration={spanDuration} />
194
+ <TextContent
195
+ durationMs={spanDuration}
196
+ node={node}
197
+ layout={layout}
198
+ segmentTags={segmentTags}
199
+ />
200
+ </>
201
+ );
202
+ }
203
+
204
+ // ──────────────────────────────────────────────────────────────────────────
205
+ // Per-type content components
206
+ // ──────────────────────────────────────────────────────────────────────────
207
+
208
+ export function RunContent(props: SpanContentProps): ReactNode {
209
+ return <WorkflowContent resourceType="run" {...props} />;
210
+ }
211
+
212
+ export function StepContent(props: SpanContentProps): ReactNode {
213
+ return <WorkflowContent resourceType="step" {...props} />;
214
+ }
215
+
216
+ export function HookContent(props: SpanContentProps): ReactNode {
217
+ return <WorkflowContent resourceType="hook" {...props} />;
218
+ }
219
+
220
+ export function SleepContent(props: SpanContentProps): ReactNode {
221
+ return <WorkflowContent resourceType="sleep" {...props} />;
222
+ }
223
+
224
+ // ──────────────────────────────────────────────────────────────────────────
225
+ // Dispatcher
226
+ // ──────────────────────────────────────────────────────────────────────────
227
+
228
+ /**
229
+ * Returns the inner content for a span based on its resource type.
230
+ */
231
+ export function SpanContent({
232
+ resourceType,
233
+ ...props
234
+ }: SpanContentProps & { resourceType: ResourceType }): ReactNode {
235
+ switch (resourceType) {
236
+ case 'run':
237
+ return <RunContent {...props} />;
238
+ case 'step':
239
+ return <StepContent {...props} />;
240
+ case 'hook':
241
+ return <HookContent {...props} />;
242
+ case 'sleep':
243
+ return <SleepContent {...props} />;
244
+ default:
245
+ return <DefaultContent {...props} />;
246
+ }
247
+ }
@@ -11,7 +11,11 @@ import {
11
11
  useRef,
12
12
  useState,
13
13
  } from 'react';
14
- import { initialState, useTraceViewer } from '../context';
14
+ import {
15
+ initialState,
16
+ useCustomPanelComponent,
17
+ useTraceViewer,
18
+ } from '../context';
15
19
  import styles from '../trace-viewer.module.css';
16
20
  import type {
17
21
  GetQuickLinks,
@@ -249,9 +253,10 @@ export function SpanDetailPanel({
249
253
  attached?: boolean;
250
254
  }): ReactNode {
251
255
  const {
252
- state: { selected, isMobile, customPanelComponent },
256
+ state: { selected, isMobile },
253
257
  dispatch,
254
258
  } = useTraceViewer();
259
+ const customPanelComponent = useCustomPanelComponent();
255
260
 
256
261
  if (!selected) return null;
257
262