@workflow/web-shared 5.0.0-beta.2 → 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/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 +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/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-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/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/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 +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 +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/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-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/index.ts +1 -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
|
|
@@ -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>
|
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/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
|
}
|