@workflow/web-shared 5.0.0-beta.2 → 5.0.0-beta.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.
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/new-trace-viewer/components/copy-button.d.ts +9 -0
- package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/copy-button.js +27 -0
- package/dist/components/new-trace-viewer/components/copy-button.js.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +8 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.js +38 -0
- package/dist/components/new-trace-viewer/components/event-list.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.js +99 -0
- package/dist/components/new-trace-viewer/components/split-pane.js.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +31 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +138 -0
- package/dist/components/new-trace-viewer/components/timeline.js.map +1 -0
- package/dist/components/new-trace-viewer/context.d.ts +15 -0
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/context.js +47 -0
- package/dist/components/new-trace-viewer/context.js.map +1 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts +10 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/detail-panel.js +12 -0
- package/dist/components/new-trace-viewer/detail-panel.js.map +1 -0
- package/dist/components/new-trace-viewer/icons.d.ts +6 -0
- package/dist/components/new-trace-viewer/icons.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/icons.js +15 -0
- package/dist/components/new-trace-viewer/icons.js.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +8 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.js +349 -0
- package/dist/components/new-trace-viewer/trace-viewer.js.map +1 -0
- package/dist/components/new-trace-viewer/types.d.ts +1 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/types.js +2 -0
- package/dist/components/new-trace-viewer/types.js.map +1 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts +1 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/util/constants.js +2 -0
- package/dist/components/new-trace-viewer/util/constants.js.map +1 -0
- package/dist/components/new-trace-viewer/utils.d.ts +42 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +305 -0
- package/dist/components/new-trace-viewer/utils.js.map +1 -0
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +42 -23
- package/dist/components/sidebar/attribute-panel.js.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +1 -1
- package/dist/components/sidebar/copyable-data-block.js.map +1 -1
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +1 -1
- package/dist/components/sidebar/detail-card.js.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.d.ts +1 -3
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +3 -25
- package/dist/components/sidebar/entity-detail-panel.js.map +1 -1
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +2 -2
- package/dist/components/sidebar/events-list.js.map +1 -1
- package/dist/components/sidebar/sidebar-data-context.d.ts +29 -0
- package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar-data-context.js +19 -0
- package/dist/components/sidebar/sidebar-data-context.js.map +1 -0
- package/dist/components/stream-viewer.d.ts +1 -1
- package/dist/components/stream-viewer.d.ts.map +1 -1
- package/dist/components/stream-viewer.js +2 -26
- package/dist/components/stream-viewer.js.map +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +5 -8
- package/dist/components/trace-viewer/util/timing.js.map +1 -1
- package/dist/components/trace-viewer-new.d.ts +10 -0
- package/dist/components/trace-viewer-new.d.ts.map +1 -0
- package/dist/components/trace-viewer-new.js +23 -0
- package/dist/components/trace-viewer-new.js.map +1 -0
- package/dist/components/ui/data-inspector.d.ts +21 -0
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +99 -4
- package/dist/components/ui/data-inspector.js.map +1 -1
- package/dist/components/ui/inspector-theme.d.ts +9 -10
- package/dist/components/ui/inspector-theme.d.ts.map +1 -1
- package/dist/components/ui/inspector-theme.js +38 -71
- package/dist/components/ui/inspector-theme.js.map +1 -1
- package/dist/components/workflow-trace-view.d.ts +1 -3
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +4 -4
- package/dist/components/workflow-trace-view.js.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.d.ts +2 -2
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +16 -3
- package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/stream-display.d.ts +18 -0
- package/dist/lib/stream-display.d.ts.map +1 -0
- package/dist/lib/stream-display.js +30 -0
- package/dist/lib/stream-display.js.map +1 -0
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +2 -1
- package/dist/lib/trace-builder.js.map +1 -1
- package/dist/lib/utils.d.ts +9 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +26 -31
- package/dist/lib/utils.js.map +1 -1
- package/dist/styles.css +470 -1
- package/package.json +3 -2
- package/src/components/index.ts +5 -0
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +116 -0
- package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
- package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
- package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +185 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +382 -0
- package/src/components/new-trace-viewer/context.tsx +92 -0
- package/src/components/new-trace-viewer/detail-panel.tsx +58 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +645 -0
- package/src/components/new-trace-viewer/types.ts +0 -0
- package/src/components/new-trace-viewer/util/constants.ts +0 -0
- package/src/components/new-trace-viewer/utils.ts +450 -0
- package/src/components/sidebar/attribute-panel.tsx +43 -32
- package/src/components/sidebar/copyable-data-block.tsx +1 -1
- package/src/components/sidebar/detail-card.tsx +1 -19
- package/src/components/sidebar/entity-detail-panel.tsx +0 -71
- package/src/components/sidebar/events-list.tsx +9 -6
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/stream-viewer.tsx +18 -40
- package/src/components/trace-viewer/util/timing.ts +5 -9
- package/src/components/trace-viewer-new.tsx +49 -0
- package/src/components/ui/data-inspector.tsx +235 -4
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/workflow-trace-view.tsx +2 -6
- package/src/components/workflow-traces/trace-span-construction.ts +22 -4
- package/src/index.ts +1 -0
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/trace-builder.ts +2 -1
- package/src/lib/utils.ts +27 -32
- package/src/styles.css +470 -1
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared theme configuration for react-inspector's ObjectInspector.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* - null:
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - functions (special): cyan
|
|
12
|
-
* - date: magenta
|
|
4
|
+
* Colors follow Geist's Shiki JSON palette so the inspector reads the same
|
|
5
|
+
* as highlighted code blocks across the product:
|
|
6
|
+
* - property names / punctuation: --ds-gray-1000 (default foreground)
|
|
7
|
+
* - strings / numbers / booleans: --ds-green-900
|
|
8
|
+
* - null / undefined: --ds-gray-900 (muted)
|
|
9
|
+
* - regexp / function: --ds-purple-900
|
|
10
|
+
* - date: --ds-pink-900
|
|
13
11
|
*
|
|
14
|
-
*
|
|
12
|
+
* Because the `--ds-*` tokens adapt to theme automatically, the light and
|
|
13
|
+
* dark objects are intentionally identical.
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
// ---------------------------------------------------------------------------
|
|
@@ -25,11 +24,11 @@ export interface InspectorThemeExtended {
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
export const inspectorThemeExtendedLight: InspectorThemeExtended = {
|
|
28
|
-
OBJECT_VALUE_DATE_COLOR: '
|
|
27
|
+
OBJECT_VALUE_DATE_COLOR: 'var(--ds-pink-900)',
|
|
29
28
|
};
|
|
30
29
|
|
|
31
30
|
export const inspectorThemeExtendedDark: InspectorThemeExtended = {
|
|
32
|
-
OBJECT_VALUE_DATE_COLOR: '
|
|
31
|
+
OBJECT_VALUE_DATE_COLOR: 'var(--ds-pink-900)',
|
|
33
32
|
};
|
|
34
33
|
|
|
35
34
|
// ---------------------------------------------------------------------------
|
|
@@ -57,96 +56,55 @@ const shared = {
|
|
|
57
56
|
// Light theme
|
|
58
57
|
// ---------------------------------------------------------------------------
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
const geistTheme = {
|
|
61
60
|
...shared,
|
|
62
61
|
|
|
63
62
|
// Base text
|
|
64
63
|
BASE_COLOR: 'var(--ds-gray-1000)',
|
|
65
64
|
|
|
66
|
-
// Property names —
|
|
67
|
-
OBJECT_NAME_COLOR: 'var(--ds-gray-
|
|
65
|
+
// Property names — default foreground (matches JSON key color in Geist Shiki)
|
|
66
|
+
OBJECT_NAME_COLOR: 'var(--ds-gray-1000)',
|
|
68
67
|
|
|
69
|
-
// Strings & symbols — green
|
|
70
|
-
OBJECT_VALUE_STRING_COLOR: '
|
|
71
|
-
OBJECT_VALUE_SYMBOL_COLOR: '
|
|
68
|
+
// Strings & symbols — green
|
|
69
|
+
OBJECT_VALUE_STRING_COLOR: 'var(--ds-green-900)',
|
|
70
|
+
OBJECT_VALUE_SYMBOL_COLOR: 'var(--ds-green-900)',
|
|
72
71
|
|
|
73
|
-
// Numbers & booleans —
|
|
74
|
-
OBJECT_VALUE_NUMBER_COLOR: '
|
|
75
|
-
OBJECT_VALUE_BOOLEAN_COLOR: '
|
|
72
|
+
// Numbers & booleans — green (Geist JSON tokens)
|
|
73
|
+
OBJECT_VALUE_NUMBER_COLOR: 'var(--ds-green-900)',
|
|
74
|
+
OBJECT_VALUE_BOOLEAN_COLOR: 'var(--ds-green-900)',
|
|
76
75
|
|
|
77
|
-
// null —
|
|
76
|
+
// null — muted foreground
|
|
78
77
|
OBJECT_VALUE_NULL_COLOR: 'var(--ds-gray-900)',
|
|
79
78
|
|
|
80
|
-
// undefined —
|
|
81
|
-
OBJECT_VALUE_UNDEFINED_COLOR: 'var(--ds-gray-
|
|
79
|
+
// undefined — muted foreground
|
|
80
|
+
OBJECT_VALUE_UNDEFINED_COLOR: 'var(--ds-gray-900)',
|
|
82
81
|
|
|
83
|
-
// RegExp —
|
|
84
|
-
OBJECT_VALUE_REGEXP_COLOR: '
|
|
82
|
+
// RegExp — purple
|
|
83
|
+
OBJECT_VALUE_REGEXP_COLOR: 'var(--ds-purple-900)',
|
|
85
84
|
|
|
86
|
-
// Functions —
|
|
87
|
-
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: '
|
|
85
|
+
// Functions — purple
|
|
86
|
+
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: 'var(--ds-purple-900)',
|
|
88
87
|
|
|
89
|
-
// HTML (
|
|
90
|
-
HTML_TAG_COLOR: 'var(--ds-gray-
|
|
91
|
-
HTML_TAGNAME_COLOR: '
|
|
92
|
-
HTML_ATTRIBUTE_NAME_COLOR: '
|
|
93
|
-
HTML_ATTRIBUTE_VALUE_COLOR: '
|
|
94
|
-
HTML_COMMENT_COLOR: 'var(--ds-gray-
|
|
95
|
-
HTML_DOCTYPE_COLOR: 'var(--ds-gray-
|
|
88
|
+
// HTML (rarely used here, kept consistent with the palette)
|
|
89
|
+
HTML_TAG_COLOR: 'var(--ds-gray-900)',
|
|
90
|
+
HTML_TAGNAME_COLOR: 'var(--ds-blue-900)',
|
|
91
|
+
HTML_ATTRIBUTE_NAME_COLOR: 'var(--ds-amber-900)',
|
|
92
|
+
HTML_ATTRIBUTE_VALUE_COLOR: 'var(--ds-green-900)',
|
|
93
|
+
HTML_COMMENT_COLOR: 'var(--ds-gray-700)',
|
|
94
|
+
HTML_DOCTYPE_COLOR: 'var(--ds-gray-700)',
|
|
96
95
|
|
|
97
96
|
// Structural
|
|
98
|
-
ARROW_COLOR: 'var(--ds-gray-
|
|
97
|
+
ARROW_COLOR: 'var(--ds-gray-700)',
|
|
99
98
|
TABLE_BORDER_COLOR: 'var(--ds-gray-300)',
|
|
100
99
|
TABLE_TH_BACKGROUND_COLOR: 'var(--ds-gray-100)',
|
|
101
100
|
TABLE_TH_HOVER_COLOR: 'var(--ds-gray-200)',
|
|
102
|
-
TABLE_SORT_ICON_COLOR: 'var(--ds-gray-
|
|
101
|
+
TABLE_SORT_ICON_COLOR: 'var(--ds-gray-700)',
|
|
103
102
|
};
|
|
104
103
|
|
|
104
|
+
export const inspectorThemeLight = geistTheme;
|
|
105
|
+
|
|
105
106
|
// ---------------------------------------------------------------------------
|
|
106
107
|
// Dark theme
|
|
107
108
|
// ---------------------------------------------------------------------------
|
|
108
109
|
|
|
109
|
-
export const inspectorThemeDark =
|
|
110
|
-
...shared,
|
|
111
|
-
|
|
112
|
-
// Base text
|
|
113
|
-
BASE_COLOR: 'var(--ds-gray-1000)',
|
|
114
|
-
|
|
115
|
-
// Property names — white/light foreground (Node: unstyled = white in dark terminal)
|
|
116
|
-
OBJECT_NAME_COLOR: 'var(--ds-gray-900)',
|
|
117
|
-
|
|
118
|
-
// Strings & symbols — green (Node: 'green')
|
|
119
|
-
OBJECT_VALUE_STRING_COLOR: '#4ade80', // green-400
|
|
120
|
-
OBJECT_VALUE_SYMBOL_COLOR: '#4ade80',
|
|
121
|
-
|
|
122
|
-
// Numbers & booleans — yellow (Node: 'yellow')
|
|
123
|
-
OBJECT_VALUE_NUMBER_COLOR: '#facc15', // yellow-400
|
|
124
|
-
OBJECT_VALUE_BOOLEAN_COLOR: '#facc15',
|
|
125
|
-
|
|
126
|
-
// null — bold foreground / white (Node: 'bold')
|
|
127
|
-
OBJECT_VALUE_NULL_COLOR: 'var(--ds-gray-1000)',
|
|
128
|
-
|
|
129
|
-
// undefined — grey (Node: 'grey')
|
|
130
|
-
OBJECT_VALUE_UNDEFINED_COLOR: 'var(--ds-gray-500)',
|
|
131
|
-
|
|
132
|
-
// RegExp — red (Node regexp palette)
|
|
133
|
-
OBJECT_VALUE_REGEXP_COLOR: '#f87171', // red-400
|
|
134
|
-
|
|
135
|
-
// Functions — cyan (Node: 'special' → 'cyan')
|
|
136
|
-
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: '#22d3ee', // cyan-400
|
|
137
|
-
|
|
138
|
-
// HTML
|
|
139
|
-
HTML_TAG_COLOR: 'var(--ds-gray-500)',
|
|
140
|
-
HTML_TAGNAME_COLOR: '#22d3ee',
|
|
141
|
-
HTML_ATTRIBUTE_NAME_COLOR: '#facc15',
|
|
142
|
-
HTML_ATTRIBUTE_VALUE_COLOR: '#4ade80',
|
|
143
|
-
HTML_COMMENT_COLOR: 'var(--ds-gray-500)',
|
|
144
|
-
HTML_DOCTYPE_COLOR: 'var(--ds-gray-500)',
|
|
145
|
-
|
|
146
|
-
// Structural
|
|
147
|
-
ARROW_COLOR: 'var(--ds-gray-500)',
|
|
148
|
-
TABLE_BORDER_COLOR: 'var(--ds-gray-300)',
|
|
149
|
-
TABLE_TH_BACKGROUND_COLOR: 'var(--ds-gray-100)',
|
|
150
|
-
TABLE_TH_HOVER_COLOR: 'var(--ds-gray-200)',
|
|
151
|
-
TABLE_SORT_ICON_COLOR: 'var(--ds-gray-500)',
|
|
152
|
-
};
|
|
110
|
+
export const inspectorThemeDark = geistTheme;
|
|
@@ -17,6 +17,7 @@ import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
|
|
17
17
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
18
18
|
import { createPortal } from 'react-dom';
|
|
19
19
|
import { useToast } from '../lib/toast';
|
|
20
|
+
import { buildTrace, type TraceWithMeta } from '../lib/trace-builder';
|
|
20
21
|
import { ErrorBoundary } from './error-boundary';
|
|
21
22
|
import {
|
|
22
23
|
EntityDetailPanel,
|
|
@@ -36,7 +37,6 @@ import {
|
|
|
36
37
|
getCustomSpanClassName,
|
|
37
38
|
getCustomSpanEventClassName,
|
|
38
39
|
} from './workflow-traces/trace-colors';
|
|
39
|
-
import { buildTrace, type TraceWithMeta } from '../lib/trace-builder';
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* While a run is live, continuously grow root.duration and rescale so the
|
|
@@ -776,7 +776,6 @@ export const WorkflowTraceViewer = ({
|
|
|
776
776
|
encryptionKey,
|
|
777
777
|
onDecrypt,
|
|
778
778
|
isDecrypting = false,
|
|
779
|
-
hasEncryptedData = false,
|
|
780
779
|
}: {
|
|
781
780
|
run: WorkflowRun;
|
|
782
781
|
events: Event[];
|
|
@@ -819,8 +818,6 @@ export const WorkflowTraceViewer = ({
|
|
|
819
818
|
onDecrypt?: () => void;
|
|
820
819
|
/** Whether the encryption key is currently being fetched */
|
|
821
820
|
isDecrypting?: boolean;
|
|
822
|
-
/** Run-level hint: the run contains encrypted data (from probe). */
|
|
823
|
-
hasEncryptedData?: boolean;
|
|
824
821
|
}) => {
|
|
825
822
|
const toast = useToast();
|
|
826
823
|
const [selectedSpan, setSelectedSpan] = useState<SelectedSpanInfo | null>(
|
|
@@ -977,7 +974,7 @@ export const WorkflowTraceViewer = ({
|
|
|
977
974
|
}
|
|
978
975
|
|
|
979
976
|
return (
|
|
980
|
-
<div className="relative w-full h-full flex">
|
|
977
|
+
<div className="relative w-full h-full flex flex-col">
|
|
981
978
|
{/* Timeline (takes remaining space) */}
|
|
982
979
|
<div className="flex-1 min-w-0 relative">
|
|
983
980
|
<TraceViewerContextProvider
|
|
@@ -1164,7 +1161,6 @@ export const WorkflowTraceViewer = ({
|
|
|
1164
1161
|
onDecrypt={onDecrypt}
|
|
1165
1162
|
isDecrypting={isDecrypting}
|
|
1166
1163
|
selectedSpan={selectedSpan}
|
|
1167
|
-
hasEncryptedData={hasEncryptedData}
|
|
1168
1164
|
/>
|
|
1169
1165
|
</ErrorBoundary>
|
|
1170
1166
|
</div>
|
|
@@ -59,7 +59,7 @@ export const waitEventsToWaitEntity = (
|
|
|
59
59
|
waitId: string;
|
|
60
60
|
runId: string;
|
|
61
61
|
createdAt: Date;
|
|
62
|
-
resumeAt
|
|
62
|
+
resumeAt?: Date;
|
|
63
63
|
completedAt?: Date;
|
|
64
64
|
} | null => {
|
|
65
65
|
const startEvent = events.find((event) => event.eventType === 'wait_created');
|
|
@@ -73,7 +73,9 @@ export const waitEventsToWaitEntity = (
|
|
|
73
73
|
waitId: startEvent.correlationId,
|
|
74
74
|
runId: startEvent.runId,
|
|
75
75
|
createdAt: startEvent.createdAt,
|
|
76
|
-
resumeAt: startEvent.eventData?.resumeAt
|
|
76
|
+
resumeAt: startEvent.eventData?.resumeAt
|
|
77
|
+
? new Date(startEvent.eventData.resumeAt)
|
|
78
|
+
: undefined,
|
|
77
79
|
completedAt: completedEvent?.createdAt,
|
|
78
80
|
};
|
|
79
81
|
};
|
|
@@ -81,13 +83,29 @@ export const waitEventsToWaitEntity = (
|
|
|
81
83
|
/**
|
|
82
84
|
* Converts a workflow Wait to an OpenTelemetry Span
|
|
83
85
|
*/
|
|
84
|
-
export function waitToSpan(
|
|
86
|
+
export function waitToSpan(
|
|
87
|
+
events: Event[],
|
|
88
|
+
maxEndTime: Date,
|
|
89
|
+
fallbackEndTime = maxEndTime
|
|
90
|
+
): Span | null {
|
|
85
91
|
const wait = waitEventsToWaitEntity(events);
|
|
86
92
|
if (!wait) {
|
|
87
93
|
return null;
|
|
88
94
|
}
|
|
89
95
|
const startTime = wait.createdAt;
|
|
90
|
-
const
|
|
96
|
+
const startMs = startTime.getTime();
|
|
97
|
+
let endTime = wait.completedAt;
|
|
98
|
+
if (!endTime) {
|
|
99
|
+
const fallbackCap =
|
|
100
|
+
wait.resumeAt && wait.resumeAt.getTime() < fallbackEndTime.getTime()
|
|
101
|
+
? wait.resumeAt
|
|
102
|
+
: fallbackEndTime;
|
|
103
|
+
endTime =
|
|
104
|
+
maxEndTime.getTime() > startMs &&
|
|
105
|
+
maxEndTime.getTime() < fallbackCap.getTime()
|
|
106
|
+
? maxEndTime
|
|
107
|
+
: fallbackCap;
|
|
108
|
+
}
|
|
91
109
|
const start = dateToOtelTime(startTime);
|
|
92
110
|
const end = dateToOtelTime(endTime);
|
|
93
111
|
const duration = calculateDuration(startTime, endTime);
|
package/src/index.ts
CHANGED
|
@@ -50,6 +50,7 @@ export {
|
|
|
50
50
|
STREAM_REF_TYPE,
|
|
51
51
|
truncateId,
|
|
52
52
|
} from './lib/hydration';
|
|
53
|
+
export type { DecodedStreamChunkSource } from './lib/stream-display';
|
|
53
54
|
export type { ToastAdapter } from './lib/toast';
|
|
54
55
|
export { ToastProvider, useToast } from './lib/toast';
|
|
55
56
|
export type { StreamStep } from './lib/utils';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface DecodedStreamChunkSource {
|
|
2
|
+
type: string;
|
|
3
|
+
encoding: 'utf-8';
|
|
4
|
+
rawSummary: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface FormattedStreamChunkDisplay {
|
|
8
|
+
text: string;
|
|
9
|
+
decodedFrom?: DecodedStreamChunkSource;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function summarizeArrayBufferView(value: ArrayBufferView): string {
|
|
13
|
+
const ta = value as unknown as {
|
|
14
|
+
length: number;
|
|
15
|
+
constructor: { name: string };
|
|
16
|
+
} & ArrayLike<number>;
|
|
17
|
+
const name = ta.constructor.name;
|
|
18
|
+
const preview = Array.from(
|
|
19
|
+
{ length: Math.min(ta.length, 8) },
|
|
20
|
+
(_, i) => ta[i]
|
|
21
|
+
);
|
|
22
|
+
const suffix = ta.length > 8 ? ', …' : '';
|
|
23
|
+
return `${name}(${ta.length}) [${preview.join(', ')}${suffix}]`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Decode a typed array as UTF-8 text when valid, otherwise return a compact
|
|
28
|
+
* raw-byte summary. Used by `DataInspector`'s `collapseRefs` pipeline so
|
|
29
|
+
* hydrated `Uint8Array` chunks (e.g. AI SDK text deltas) render as readable
|
|
30
|
+
* text while still exposing the underlying byte layout.
|
|
31
|
+
*/
|
|
32
|
+
export function formatArrayBufferViewForDisplay(
|
|
33
|
+
value: ArrayBufferView
|
|
34
|
+
): FormattedStreamChunkDisplay {
|
|
35
|
+
try {
|
|
36
|
+
const text = new TextDecoder('utf-8', { fatal: true }).decode(value);
|
|
37
|
+
return {
|
|
38
|
+
text,
|
|
39
|
+
decodedFrom: {
|
|
40
|
+
type: value.constructor.name,
|
|
41
|
+
encoding: 'utf-8',
|
|
42
|
+
rawSummary: summarizeArrayBufferView(value),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
} catch {
|
|
46
|
+
return { text: summarizeArrayBufferView(value) };
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/lib/trace-builder.ts
CHANGED
|
@@ -117,6 +117,7 @@ function buildSpans(
|
|
|
117
117
|
// unknown territory. Even when the run is completed, we may not have loaded
|
|
118
118
|
// all events yet, so always use the latest event we've actually seen.
|
|
119
119
|
const childMaxEnd = latestKnownTime;
|
|
120
|
+
const runMaxEnd = run.completedAt ?? now;
|
|
120
121
|
|
|
121
122
|
const stepSpans = Array.from(groupedEvents.eventsByStepId.values())
|
|
122
123
|
.map((events) => stepToSpan(events, childMaxEnd))
|
|
@@ -127,7 +128,7 @@ function buildSpans(
|
|
|
127
128
|
.filter((span): span is Span => span !== null);
|
|
128
129
|
|
|
129
130
|
const waitSpans = Array.from(groupedEvents.timerEvents.values())
|
|
130
|
-
.map((events) => waitToSpan(events, childMaxEnd))
|
|
131
|
+
.map((events) => waitToSpan(events, childMaxEnd, runMaxEnd))
|
|
131
132
|
.filter((span): span is Span => span !== null);
|
|
132
133
|
|
|
133
134
|
return {
|
package/src/lib/utils.ts
CHANGED
|
@@ -7,10 +7,6 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
7
7
|
return twMerge(clsx(inputs));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const durationFormatter = new Intl.NumberFormat(undefined, {
|
|
11
|
-
maximumFractionDigits: 2,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
10
|
const MS_IN_SECOND = 1000;
|
|
15
11
|
const MS_IN_MINUTE = 60 * MS_IN_SECOND;
|
|
16
12
|
const MS_IN_HOUR = 60 * MS_IN_MINUTE;
|
|
@@ -20,52 +16,53 @@ const MS_IN_DAY = 24 * MS_IN_HOUR;
|
|
|
20
16
|
* Formats a duration in milliseconds to a human-readable string.
|
|
21
17
|
*
|
|
22
18
|
* @param ms - Duration in milliseconds
|
|
23
|
-
* @param compact - If true, returns a
|
|
24
|
-
* If false (default), returns multi-part format (e.g., "
|
|
19
|
+
* @param compact - If true, returns a compact format (e.g., "380ms", "2m 30s").
|
|
20
|
+
* If false (default), returns multi-part format (e.g., "1m 13s", "2d 5h 3m 12s").
|
|
25
21
|
*
|
|
26
|
-
* Compact format:
|
|
27
|
-
* - < 1s: shows milliseconds (e.g., "
|
|
22
|
+
* Compact format (timeline markers):
|
|
23
|
+
* - < 1s: shows milliseconds (e.g., "380ms")
|
|
28
24
|
* - < 1m: shows seconds (e.g., "45s")
|
|
29
|
-
* - < 1h: shows minutes (e.g., "
|
|
30
|
-
* - >= 1h: shows hours (e.g., "
|
|
25
|
+
* - < 1h: shows minutes and seconds (e.g., "2m 30s")
|
|
26
|
+
* - >= 1h: shows hours and minutes (e.g., "2h 30m")
|
|
31
27
|
*
|
|
32
28
|
* Full format:
|
|
33
|
-
* - < 1s: shows milliseconds (e.g., "
|
|
34
|
-
* - < 1m: shows seconds (e.g., "
|
|
35
|
-
* - >= 1m: shows
|
|
29
|
+
* - < 1s: shows milliseconds (e.g., "380ms")
|
|
30
|
+
* - < 1m: shows seconds (e.g., "45s")
|
|
31
|
+
* - >= 1m: shows decomposed format with whole seconds (e.g., "1m 13s", "2m 13s")
|
|
36
32
|
*/
|
|
37
33
|
export function formatDuration(ms: number, compact = false): string {
|
|
38
34
|
if (ms === 0) {
|
|
39
|
-
return '
|
|
35
|
+
return '0s';
|
|
40
36
|
}
|
|
41
37
|
|
|
42
|
-
// For durations less than 1 second, show milliseconds
|
|
43
38
|
if (ms < MS_IN_SECOND) {
|
|
44
|
-
|
|
39
|
+
const roundedMs = Math.round(ms);
|
|
40
|
+
return roundedMs < MS_IN_SECOND ? `${roundedMs}ms` : '1s';
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
const roundedMs = Math.round(ms / MS_IN_SECOND) * MS_IN_SECOND;
|
|
44
|
+
|
|
45
|
+
if (roundedMs < MS_IN_MINUTE) {
|
|
46
|
+
return `${Math.floor(roundedMs / MS_IN_SECOND)}s`;
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
// Compact format: multi-unit without decimals (e.g. "8m 20s", "2h 30m")
|
|
53
50
|
if (compact) {
|
|
54
|
-
if (
|
|
55
|
-
const m = Math.floor(
|
|
56
|
-
const s = Math.floor((
|
|
51
|
+
if (roundedMs < MS_IN_HOUR) {
|
|
52
|
+
const m = Math.floor(roundedMs / MS_IN_MINUTE);
|
|
53
|
+
const s = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);
|
|
57
54
|
return s > 0 ? `${m}m ${s}s` : `${m}m`;
|
|
58
55
|
}
|
|
59
|
-
const h = Math.floor(
|
|
60
|
-
const m = Math.floor((
|
|
56
|
+
const h = Math.floor(roundedMs / MS_IN_HOUR);
|
|
57
|
+
const m = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);
|
|
61
58
|
return m > 0 ? `${h}h ${m}m` : `${h}h`;
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
// Full format:
|
|
65
|
-
const days = Math.floor(
|
|
66
|
-
const hours = Math.floor((
|
|
67
|
-
const minutes = Math.floor((
|
|
68
|
-
const seconds = Math.floor((
|
|
61
|
+
// Full format: decompose into larger units + whole seconds.
|
|
62
|
+
const days = Math.floor(roundedMs / MS_IN_DAY);
|
|
63
|
+
const hours = Math.floor((roundedMs % MS_IN_DAY) / MS_IN_HOUR);
|
|
64
|
+
const minutes = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);
|
|
65
|
+
const seconds = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);
|
|
69
66
|
|
|
70
67
|
const parts: string[] = [];
|
|
71
68
|
|
|
@@ -78,9 +75,7 @@ export function formatDuration(ms: number, compact = false): string {
|
|
|
78
75
|
if (minutes > 0) {
|
|
79
76
|
parts.push(`${minutes}m`);
|
|
80
77
|
}
|
|
81
|
-
|
|
82
|
-
parts.push(`${seconds}s`);
|
|
83
|
-
}
|
|
78
|
+
parts.push(`${seconds}s`);
|
|
84
79
|
|
|
85
80
|
return parts.join(' ');
|
|
86
81
|
}
|