@workflow/web-shared 5.0.0-beta.1 → 5.0.0-beta.3
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 +1 -1
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/event-list-view.d.ts +3 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +53 -53
- package/dist/components/event-list-view.js.map +1 -1
- package/dist/components/hook-actions.js.map +1 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +3 -1
- 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 +35 -0
- package/dist/components/new-trace-viewer/components/event-list.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 +100 -0
- package/dist/components/new-trace-viewer/components/split-pane.js.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +32 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +134 -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 +49 -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 +11 -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 +329 -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 +47 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +358 -0
- package/dist/components/new-trace-viewer/utils.js.map +1 -0
- package/dist/components/run-trace-view.d.ts +2 -1
- package/dist/components/run-trace-view.d.ts.map +1 -1
- package/dist/components/run-trace-view.js +2 -2
- package/dist/components/run-trace-view.js.map +1 -1
- package/dist/components/sidebar/attribute-panel.d.ts +7 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +76 -47
- package/dist/components/sidebar/attribute-panel.js.map +1 -1
- package/dist/components/sidebar/conversation-view.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 +3 -1
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +16 -36
- 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/resolve-hook-modal.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/components/map.js.map +1 -1
- package/dist/components/trace-viewer/components/markers.js.map +1 -1
- package/dist/components/trace-viewer/components/node.js.map +1 -1
- package/dist/components/trace-viewer/components/search-input.js.map +1 -1
- package/dist/components/trace-viewer/components/search.js.map +1 -1
- package/dist/components/trace-viewer/components/span-content.js.map +1 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +1 -1
- package/dist/components/trace-viewer/components/span-segments.js.map +1 -1
- package/dist/components/trace-viewer/components/span-strategies.js.map +1 -1
- package/dist/components/trace-viewer/components/ui.js.map +1 -1
- package/dist/components/trace-viewer/components/zoom-button.js.map +1 -1
- package/dist/components/trace-viewer/components/zoom-icons.js.map +1 -1
- package/dist/components/trace-viewer/context.js.map +1 -1
- package/dist/components/trace-viewer/index.js.map +1 -1
- package/dist/components/trace-viewer/trace-viewer.js.map +1 -1
- package/dist/components/trace-viewer/types.js.map +1 -1
- package/dist/components/trace-viewer/util/constants.js.map +1 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +1 -1
- package/dist/components/trace-viewer/util/timing.js.map +1 -1
- package/dist/components/trace-viewer/util/tree.js.map +1 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +1 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +1 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +1 -1
- package/dist/components/trace-viewer/worker.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/alert.js.map +1 -1
- package/dist/components/ui/card.js.map +1 -1
- package/dist/components/ui/data-inspector.d.ts +38 -1
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +211 -21
- package/dist/components/ui/data-inspector.js.map +1 -1
- package/dist/components/ui/decrypt-button.js.map +1 -1
- package/dist/components/ui/error-card.js.map +1 -1
- package/dist/components/ui/error-stack-block.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/ui/load-more-button.js.map +1 -1
- package/dist/components/ui/menu-dropdown.js.map +1 -1
- package/dist/components/ui/skeleton.js.map +1 -1
- package/dist/components/ui/spinner.js.map +1 -1
- package/dist/components/ui/timestamp-tooltip.js.map +1 -1
- package/dist/components/workflow-trace-view.d.ts +3 -1
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +9 -4
- package/dist/components/workflow-trace-view.js.map +1 -1
- package/dist/components/workflow-traces/event-colors.js.map +1 -1
- package/dist/components/workflow-traces/trace-colors.js.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
- package/dist/components/workflow-traces/trace-time-utils.js.map +1 -1
- package/dist/hooks/use-dark-mode.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/event-analysis.js.map +1 -1
- package/dist/lib/event-materialization.js.map +1 -1
- package/dist/lib/hydration.d.ts +8 -1
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +32 -2
- package/dist/lib/hydration.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/toast.js.map +1 -1
- package/dist/lib/trace-builder.js.map +1 -1
- package/dist/lib/utils.d.ts +7 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +17 -22
- package/dist/lib/utils.js.map +1 -1
- package/dist/styles.css +470 -1
- package/package.json +4 -3
- package/src/components/event-list-view.tsx +181 -173
- package/src/components/index.ts +11 -1
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +109 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +186 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +378 -0
- package/src/components/new-trace-viewer/context.tsx +94 -0
- package/src/components/new-trace-viewer/detail-panel.tsx +57 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +585 -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 +524 -0
- package/src/components/run-trace-view.tsx +3 -0
- package/src/components/sidebar/attribute-panel.tsx +200 -138
- 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 +91 -147
- 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-new.tsx +49 -0
- package/src/components/ui/data-inspector.tsx +436 -31
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/workflow-trace-view.tsx +12 -2
- package/src/components/workflow-traces/trace-span-construction.ts +1 -1
- package/src/index.ts +2 -0
- package/src/lib/hydration.ts +37 -0
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/utils.ts +18 -23
- 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
|
|
@@ -767,6 +767,7 @@ export const WorkflowTraceViewer = ({
|
|
|
767
767
|
onResolveHook,
|
|
768
768
|
onCancelRun,
|
|
769
769
|
onStreamClick,
|
|
770
|
+
onRunClick,
|
|
770
771
|
onSpanSelect,
|
|
771
772
|
onLoadEventData,
|
|
772
773
|
onLoadMoreSpans,
|
|
@@ -796,6 +797,8 @@ export const WorkflowTraceViewer = ({
|
|
|
796
797
|
onCancelRun?: (runId: string) => Promise<void>;
|
|
797
798
|
/** Callback when a stream reference is clicked in the detail panel */
|
|
798
799
|
onStreamClick?: (streamId: string) => void;
|
|
800
|
+
/** Callback when a run reference is clicked in the detail panel */
|
|
801
|
+
onRunClick?: (runId: string) => void;
|
|
799
802
|
/** Callback when a span is selected. */
|
|
800
803
|
onSpanSelect?: (info: SpanSelectionInfo) => void;
|
|
801
804
|
/** Callback to load event data for a specific event (lazy loading in sidebar) */
|
|
@@ -903,6 +906,12 @@ export const WorkflowTraceViewer = ({
|
|
|
903
906
|
});
|
|
904
907
|
}, [events, selectedSpan?.spanId]);
|
|
905
908
|
|
|
909
|
+
// Reset selected span when navigating to a different run
|
|
910
|
+
useEffect(() => {
|
|
911
|
+
setSelectedSpan(null);
|
|
912
|
+
setDeselectTrigger((n) => n + 1);
|
|
913
|
+
}, [run?.runId]);
|
|
914
|
+
|
|
906
915
|
const handleClose = useCallback(() => {
|
|
907
916
|
setSelectedSpan(null);
|
|
908
917
|
setDeselectTrigger((n) => n + 1);
|
|
@@ -965,7 +974,7 @@ export const WorkflowTraceViewer = ({
|
|
|
965
974
|
}
|
|
966
975
|
|
|
967
976
|
return (
|
|
968
|
-
<div className="relative w-full h-full flex">
|
|
977
|
+
<div className="relative w-full h-full flex flex-col">
|
|
969
978
|
{/* Timeline (takes remaining space) */}
|
|
970
979
|
<div className="flex-1 min-w-0 relative">
|
|
971
980
|
<TraceViewerContextProvider
|
|
@@ -1140,6 +1149,7 @@ export const WorkflowTraceViewer = ({
|
|
|
1140
1149
|
<EntityDetailPanel
|
|
1141
1150
|
run={run}
|
|
1142
1151
|
onStreamClick={onStreamClick}
|
|
1152
|
+
onRunClick={onRunClick}
|
|
1143
1153
|
spanDetailData={spanDetailData ?? null}
|
|
1144
1154
|
spanDetailError={spanDetailError}
|
|
1145
1155
|
spanDetailLoading={spanDetailLoading}
|
|
@@ -225,7 +225,7 @@ export function stepToSpan(stepEvents: Event[], maxEndTime: Date): Span | null {
|
|
|
225
225
|
|
|
226
226
|
return {
|
|
227
227
|
spanId: String(step.stepId),
|
|
228
|
-
name: parsedName?.shortName ??
|
|
228
|
+
name: parsedName?.shortName ?? String(step.stepName),
|
|
229
229
|
kind: 1, // INTERNAL span kind
|
|
230
230
|
resource,
|
|
231
231
|
library: WORKFLOW_LIBRARY,
|
package/src/index.ts
CHANGED
|
@@ -40,6 +40,7 @@ export {
|
|
|
40
40
|
ENCRYPTED_PLACEHOLDER,
|
|
41
41
|
extractStreamIds,
|
|
42
42
|
getWebRevivers,
|
|
43
|
+
hasEncryptedFields,
|
|
43
44
|
hydrateResourceIO,
|
|
44
45
|
hydrateResourceIOWithKey,
|
|
45
46
|
isClassInstanceRef,
|
|
@@ -49,6 +50,7 @@ export {
|
|
|
49
50
|
STREAM_REF_TYPE,
|
|
50
51
|
truncateId,
|
|
51
52
|
} from './lib/hydration';
|
|
53
|
+
export type { DecodedStreamChunkSource } from './lib/stream-display';
|
|
52
54
|
export type { ToastAdapter } from './lib/toast';
|
|
53
55
|
export { ToastProvider, useToast } from './lib/toast';
|
|
54
56
|
export type { StreamStep } from './lib/utils';
|
package/src/lib/hydration.ts
CHANGED
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
hydrateResourceIO as hydrateResourceIOGeneric,
|
|
12
12
|
isEncryptedData,
|
|
13
13
|
isExpiredStub,
|
|
14
|
+
isRunRef,
|
|
14
15
|
observabilityRevivers,
|
|
15
16
|
type Revivers,
|
|
17
|
+
serializedInstanceToRef,
|
|
16
18
|
} from '@workflow/core/serialization-format';
|
|
17
19
|
import { EVENT_DATA_REF_FIELDS } from '@workflow/world';
|
|
18
20
|
|
|
@@ -24,11 +26,15 @@ export {
|
|
|
24
26
|
extractStreamIds,
|
|
25
27
|
isClassInstanceRef,
|
|
26
28
|
isEncryptedData,
|
|
29
|
+
isRunRef,
|
|
27
30
|
isStreamId,
|
|
28
31
|
isStreamRef,
|
|
29
32
|
type Revivers,
|
|
33
|
+
RUN_REF_TYPE,
|
|
34
|
+
type RunRef,
|
|
30
35
|
STREAM_REF_TYPE,
|
|
31
36
|
type StreamRef,
|
|
37
|
+
serializedInstanceToRef,
|
|
32
38
|
truncateId,
|
|
33
39
|
} from '@workflow/core/serialization-format';
|
|
34
40
|
|
|
@@ -137,6 +143,11 @@ export function getWebRevivers(): Revivers {
|
|
|
137
143
|
// react-inspector shows the class name (it reads constructor.name).
|
|
138
144
|
Class: (value) => `<class:${extractClassName(value.classId)}>`,
|
|
139
145
|
Instance: (value) => {
|
|
146
|
+
// Run instances are rendered as clickable RunRef badges
|
|
147
|
+
const runRef = serializedInstanceToRef(value);
|
|
148
|
+
if (isRunRef(runRef)) {
|
|
149
|
+
return runRef;
|
|
150
|
+
}
|
|
140
151
|
const className = extractClassName(value.classId);
|
|
141
152
|
const data = value.data;
|
|
142
153
|
const props =
|
|
@@ -359,3 +370,29 @@ export async function hydrateResourceIOWithKey<T>(
|
|
|
359
370
|
|
|
360
371
|
return result as T;
|
|
361
372
|
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Check whether a hydrated resource (event, step, run, etc.) contains any
|
|
376
|
+
* encrypted display markers. Inspects the standard top-level fields
|
|
377
|
+
* (`input`, `output`, `error`, `metadata`) as well as the event-type-specific
|
|
378
|
+
* `eventData` ref fields.
|
|
379
|
+
*/
|
|
380
|
+
export function hasEncryptedFields(resource: unknown): boolean {
|
|
381
|
+
if (!resource || typeof resource !== 'object') return false;
|
|
382
|
+
const r = resource as Record<string, unknown>;
|
|
383
|
+
|
|
384
|
+
for (const key of ['input', 'output', 'metadata', 'error']) {
|
|
385
|
+
if (isEncryptedMarker(r[key])) return true;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (r.eventData && typeof r.eventData === 'object') {
|
|
389
|
+
const eventType = typeof r.eventType === 'string' ? r.eventType : '';
|
|
390
|
+
const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];
|
|
391
|
+
const ed = r.eventData as Record<string, unknown>;
|
|
392
|
+
for (const key of refKeys) {
|
|
393
|
+
if (key in ed && isEncryptedMarker(ed[key])) return true;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
@@ -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/utils.ts
CHANGED
|
@@ -7,7 +7,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
7
7
|
return twMerge(clsx(inputs));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
// const compactFormatter = new Intl.NumberFormat(undefined, {
|
|
11
|
+
// maximumFractionDigits: 2,
|
|
12
|
+
// });
|
|
13
|
+
|
|
14
|
+
const secondsFormatter = new Intl.NumberFormat(undefined, {
|
|
15
|
+
minimumFractionDigits: 2,
|
|
11
16
|
maximumFractionDigits: 2,
|
|
12
17
|
});
|
|
13
18
|
|
|
@@ -20,33 +25,25 @@ const MS_IN_DAY = 24 * MS_IN_HOUR;
|
|
|
20
25
|
* Formats a duration in milliseconds to a human-readable string.
|
|
21
26
|
*
|
|
22
27
|
* @param ms - Duration in milliseconds
|
|
23
|
-
* @param compact - If true, returns a single-unit format (e.g., "
|
|
24
|
-
* If false (default), returns multi-part format (e.g., "
|
|
28
|
+
* @param compact - If true, returns a single-unit format (e.g., "0.38s", "2.5m").
|
|
29
|
+
* If false (default), returns multi-part format (e.g., "1m 13.21s", "2d 5h 3m 12.00s").
|
|
25
30
|
*
|
|
26
|
-
* Compact format:
|
|
27
|
-
* - <
|
|
28
|
-
* - <
|
|
29
|
-
* - < 1h: shows minutes (e.g., "45m")
|
|
31
|
+
* Compact format (timeline markers):
|
|
32
|
+
* - < 1m: shows seconds (e.g., "0.38s", "45s")
|
|
33
|
+
* - < 1h: shows minutes (e.g., "2.5m")
|
|
30
34
|
* - >= 1h: shows hours (e.g., "2.5h")
|
|
31
35
|
*
|
|
32
36
|
* Full format:
|
|
33
|
-
* - <
|
|
34
|
-
* -
|
|
35
|
-
* - >= 1m: shows human-readable format (e.g., "1h 30m", "2d 5h")
|
|
37
|
+
* - < 1m: shows seconds (e.g., "0.38s", "2.71s")
|
|
38
|
+
* - >= 1m: shows decomposed format with fractional seconds (e.g., "1m 13.21s", "2m 13.04s")
|
|
36
39
|
*/
|
|
37
40
|
export function formatDuration(ms: number, compact = false): string {
|
|
38
41
|
if (ms === 0) {
|
|
39
|
-
return '
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// For durations less than 1 second, show milliseconds
|
|
43
|
-
if (ms < MS_IN_SECOND) {
|
|
44
|
-
return `${durationFormatter.format(ms)}ms`;
|
|
42
|
+
return '0s';
|
|
45
43
|
}
|
|
46
44
|
|
|
47
|
-
// For durations less than 1 minute, show seconds
|
|
48
45
|
if (ms < MS_IN_MINUTE) {
|
|
49
|
-
return `${
|
|
46
|
+
return `${secondsFormatter.format(ms / MS_IN_SECOND)}s`;
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
// Compact format: multi-unit without decimals (e.g. "8m 20s", "2h 30m")
|
|
@@ -61,11 +58,11 @@ export function formatDuration(ms: number, compact = false): string {
|
|
|
61
58
|
return m > 0 ? `${h}h ${m}m` : `${h}h`;
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
// Full format:
|
|
61
|
+
// Full format: decompose into larger units + fractional seconds
|
|
65
62
|
const days = Math.floor(ms / MS_IN_DAY);
|
|
66
63
|
const hours = Math.floor((ms % MS_IN_DAY) / MS_IN_HOUR);
|
|
67
64
|
const minutes = Math.floor((ms % MS_IN_HOUR) / MS_IN_MINUTE);
|
|
68
|
-
const seconds =
|
|
65
|
+
const seconds = (ms % 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(`${secondsFormatter.format(seconds)}s`);
|
|
84
79
|
|
|
85
80
|
return parts.join(' ');
|
|
86
81
|
}
|