@workflow/web-shared 5.0.0-beta.2 → 5.0.0-beta.21
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/error-boundary.js +1 -1
- package/dist/components/event-list-view.d.ts +16 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +196 -85
- package/dist/components/hook-actions.js +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -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/event-list.d.ts +10 -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 +46 -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/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/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/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/span-markers.d.ts +46 -0
- package/dist/components/new-trace-viewer/components/span-markers.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/span-markers.js +85 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +15 -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 +105 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +36 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +254 -0
- package/dist/components/new-trace-viewer/components/timeline.module.css +46 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.js +19 -0
- package/dist/components/new-trace-viewer/components/use-row-window.d.ts +34 -0
- package/dist/components/new-trace-viewer/components/use-row-window.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/use-row-window.js +107 -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/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/search.d.ts +19 -0
- package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/search.js +134 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +11 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.js +462 -0
- package/dist/components/new-trace-viewer/types.d.ts +3 -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/utils.d.ts +61 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +345 -0
- package/dist/components/run-trace-view.js +1 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +129 -102
- package/dist/components/sidebar/attributes-block.d.ts +28 -0
- package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
- package/dist/components/sidebar/attributes-block.js +81 -0
- package/dist/components/sidebar/conversation-view.js +1 -1
- package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
- package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +16 -15
- package/dist/components/sidebar/detail-card.d.ts +5 -6
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +32 -16
- 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 +17 -35
- package/dist/components/sidebar/events-list.d.ts +3 -1
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +36 -22
- package/dist/components/sidebar/resolve-hook-modal.js +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/span-detail-merge.d.ts +16 -0
- package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
- package/dist/components/sidebar/span-detail-merge.js +53 -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 +3 -27
- package/dist/components/trace-viewer/components/map.js +1 -1
- package/dist/components/trace-viewer/components/markers.js +1 -1
- package/dist/components/trace-viewer/components/node.d.ts.map +1 -1
- package/dist/components/trace-viewer/components/node.js +2 -1
- package/dist/components/trace-viewer/components/search-input.js +1 -1
- package/dist/components/trace-viewer/components/search.js +1 -1
- package/dist/components/trace-viewer/components/span-content.js +1 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
- package/dist/components/trace-viewer/components/span-segments.js +1 -1
- package/dist/components/trace-viewer/components/span-strategies.js +1 -1
- package/dist/components/trace-viewer/components/ui.js +1 -1
- package/dist/components/trace-viewer/components/zoom-button.js +1 -1
- package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
- package/dist/components/trace-viewer/context.js +1 -1
- package/dist/components/trace-viewer/index.js +1 -1
- package/dist/components/trace-viewer/trace-viewer.js +1 -1
- package/dist/components/trace-viewer/trace-viewer.module.css +4 -4
- package/dist/components/trace-viewer/types.js +1 -1
- package/dist/components/trace-viewer/util/constants.js +1 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts +3 -3
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +8 -11
- package/dist/components/trace-viewer/util/tree.js +1 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
- package/dist/components/trace-viewer/worker.js +1 -1
- package/dist/components/trace-viewer-new.d.ts +14 -0
- package/dist/components/trace-viewer-new.d.ts.map +1 -0
- package/dist/components/trace-viewer-new.js +21 -0
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/button.d.ts +10 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +46 -0
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/context-card.d.ts +47 -0
- package/dist/components/ui/context-card.d.ts.map +1 -0
- package/dist/components/ui/context-card.js +471 -0
- package/dist/components/ui/data-inspector.d.ts +22 -0
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +103 -13
- package/dist/components/ui/decrypt-button.js +1 -1
- package/dist/components/ui/error-card.js +1 -1
- package/dist/components/ui/error-stack-block.d.ts +17 -10
- package/dist/components/ui/error-stack-block.d.ts.map +1 -1
- package/dist/components/ui/error-stack-block.js +49 -30
- package/dist/components/ui/icon-button.d.ts +19 -0
- package/dist/components/ui/icon-button.d.ts.map +1 -0
- package/dist/components/ui/icon-button.js +29 -0
- 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 +39 -72
- package/dist/components/ui/kbd.d.ts +6 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +6 -0
- package/dist/components/ui/load-more-button.js +1 -1
- package/dist/components/ui/menu-dropdown.js +1 -1
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/spinner.js +1 -1
- package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
- package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
- package/dist/components/ui/timestamp-tooltip.js +80 -132
- package/dist/components/ui/tooltip.d.ts +10 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +12 -0
- 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 +11 -13
- package/dist/components/workflow-traces/event-colors.d.ts +1 -0
- package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
- package/dist/components/workflow-traces/event-colors.js +12 -1
- package/dist/components/workflow-traces/trace-colors.js +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 +19 -5
- package/dist/components/workflow-traces/trace-time-utils.js +1 -1
- package/dist/hooks/use-dark-mode.js +1 -1
- package/dist/hooks/use-intersection-observer.d.ts +17 -0
- package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
- package/dist/hooks/use-intersection-observer.js +29 -0
- package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
- package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
- package/dist/hooks/use-load-more-on-scroll.js +28 -0
- package/dist/hooks/use-reduced-motion.d.ts +10 -0
- package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
- package/dist/hooks/use-reduced-motion.js +29 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/lib/event-analysis.js +1 -1
- package/dist/lib/event-materialization.js +1 -1
- package/dist/lib/exact-event-search-id.d.ts +25 -0
- package/dist/lib/exact-event-search-id.d.ts.map +1 -0
- package/dist/lib/exact-event-search-id.js +39 -0
- package/dist/lib/hydration.d.ts +6 -0
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +154 -2
- 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/toast.js +1 -1
- package/dist/lib/trace-builder.d.ts +15 -0
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +29 -3
- package/dist/lib/utils.d.ts +20 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +74 -31
- package/dist/lib/zstd-browser-decoder.d.ts +7 -0
- package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
- package/dist/lib/zstd-browser-decoder.js +41 -0
- package/dist/styles.css +484 -1
- package/package.json +10 -5
- package/src/components/event-list-view.tsx +279 -104
- package/src/components/index.ts +7 -0
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +136 -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/span-markers.tsx +173 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +198 -0
- package/src/components/new-trace-viewer/components/timeline.module.css +46 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +744 -0
- package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +94 -0
- package/src/components/new-trace-viewer/components/use-row-window.ts +140 -0
- package/src/components/new-trace-viewer/context.tsx +90 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/search.ts +178 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +843 -0
- package/src/components/new-trace-viewer/types.ts +2 -0
- package/src/components/new-trace-viewer/utils.test.ts +182 -0
- package/src/components/new-trace-viewer/utils.ts +519 -0
- package/src/components/sidebar/attribute-panel.tsx +194 -240
- package/src/components/sidebar/attributes-block.tsx +173 -0
- package/src/components/sidebar/copyable-data-block.tsx +49 -27
- package/src/components/sidebar/detail-card.tsx +119 -59
- package/src/components/sidebar/entity-detail-panel.tsx +55 -111
- package/src/components/sidebar/events-list.tsx +85 -96
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/sidebar/span-detail-merge.ts +65 -0
- package/src/components/stream-viewer.tsx +18 -40
- package/src/components/trace-viewer/components/node.tsx +3 -2
- package/src/components/trace-viewer/trace-viewer.module.css +4 -4
- package/src/components/trace-viewer/util/timing.ts +7 -11
- package/src/components/trace-viewer-new.tsx +55 -0
- package/src/components/ui/button.tsx +68 -0
- package/src/components/ui/context-card.tsx +784 -0
- package/src/components/ui/data-inspector.tsx +244 -22
- package/src/components/ui/error-stack-block.tsx +84 -55
- package/src/components/ui/icon-button.tsx +53 -0
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/ui/kbd.tsx +21 -0
- package/src/components/ui/timestamp-tooltip.tsx +132 -194
- package/src/components/ui/tooltip.tsx +47 -0
- package/src/components/workflow-trace-view.tsx +19 -15
- package/src/components/workflow-traces/event-colors.ts +12 -0
- package/src/components/workflow-traces/trace-span-construction.ts +24 -5
- package/src/hooks/use-intersection-observer.ts +57 -0
- package/src/hooks/use-load-more-on-scroll.ts +49 -0
- package/src/hooks/use-reduced-motion.ts +34 -0
- package/src/index.ts +9 -0
- package/src/lib/exact-event-search-id.ts +67 -0
- package/src/lib/hydration.ts +166 -1
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/trace-builder.ts +34 -2
- package/src/lib/utils.ts +83 -31
- package/src/lib/zstd-browser-decoder.ts +42 -0
- package/src/styles.css +484 -1
- package/dist/components/error-boundary.js.map +0 -1
- package/dist/components/event-list-view.js.map +0 -1
- package/dist/components/hook-actions.js.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/components/run-trace-view.js.map +0 -1
- package/dist/components/sidebar/attribute-panel.js.map +0 -1
- package/dist/components/sidebar/conversation-view.js.map +0 -1
- package/dist/components/sidebar/copyable-data-block.js.map +0 -1
- package/dist/components/sidebar/detail-card.js.map +0 -1
- package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
- package/dist/components/sidebar/events-list.js.map +0 -1
- package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
- package/dist/components/stream-viewer.js.map +0 -1
- package/dist/components/trace-viewer/components/map.js.map +0 -1
- package/dist/components/trace-viewer/components/markers.js.map +0 -1
- package/dist/components/trace-viewer/components/node.js.map +0 -1
- package/dist/components/trace-viewer/components/search-input.js.map +0 -1
- package/dist/components/trace-viewer/components/search.js.map +0 -1
- package/dist/components/trace-viewer/components/span-content.js.map +0 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
- package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
- package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
- package/dist/components/trace-viewer/components/ui.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
- package/dist/components/trace-viewer/context.js.map +0 -1
- package/dist/components/trace-viewer/index.js.map +0 -1
- package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
- package/dist/components/trace-viewer/types.js.map +0 -1
- package/dist/components/trace-viewer/util/constants.js.map +0 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
- package/dist/components/trace-viewer/util/timing.js.map +0 -1
- package/dist/components/trace-viewer/util/tree.js.map +0 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
- package/dist/components/trace-viewer/worker.js.map +0 -1
- package/dist/components/ui/alert.js.map +0 -1
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/data-inspector.js.map +0 -1
- package/dist/components/ui/decrypt-button.js.map +0 -1
- package/dist/components/ui/error-card.js.map +0 -1
- package/dist/components/ui/error-stack-block.js.map +0 -1
- package/dist/components/ui/inspector-theme.js.map +0 -1
- package/dist/components/ui/load-more-button.js.map +0 -1
- package/dist/components/ui/menu-dropdown.js.map +0 -1
- package/dist/components/ui/skeleton.js.map +0 -1
- package/dist/components/ui/spinner.js.map +0 -1
- package/dist/components/ui/timestamp-tooltip.js.map +0 -1
- package/dist/components/workflow-trace-view.js.map +0 -1
- package/dist/components/workflow-traces/event-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
- package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
- package/dist/hooks/use-dark-mode.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/event-analysis.js.map +0 -1
- package/dist/lib/event-materialization.js.map +0 -1
- package/dist/lib/hydration.js.map +0 -1
- package/dist/lib/toast.js.map +0 -1
- package/dist/lib/trace-builder.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
|
@@ -3,16 +3,30 @@
|
|
|
3
3
|
import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
|
|
4
4
|
import type { Event, WorkflowRun } from '@workflow/world';
|
|
5
5
|
import { Check, ChevronRight, Copy } from 'lucide-react';
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
KeyboardEvent as ReactKeyboardEvent,
|
|
8
|
+
MouseEvent as ReactMouseEvent,
|
|
9
|
+
ReactNode,
|
|
10
|
+
} from 'react';
|
|
7
11
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
12
|
import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso';
|
|
13
|
+
import {
|
|
14
|
+
type ExactIdSearchResult,
|
|
15
|
+
type ExactWorkflowSearchIdKind,
|
|
16
|
+
looksLikeWorkflowIdSearchInput,
|
|
17
|
+
parseExactWorkflowSearchId,
|
|
18
|
+
} from '../lib/exact-event-search-id';
|
|
9
19
|
import { isEncryptedMarker } from '../lib/hydration';
|
|
10
|
-
import {
|
|
20
|
+
import { useToast } from '../lib/toast';
|
|
11
21
|
import { formatDuration } from '../lib/utils';
|
|
22
|
+
import { AttrSetEventBlock } from './sidebar/attributes-block';
|
|
23
|
+
import { ContextCardProvider } from './ui/context-card';
|
|
12
24
|
import { DataInspector, DecryptClickContext } from './ui/data-inspector';
|
|
25
|
+
import { DecryptButton } from './ui/decrypt-button';
|
|
13
26
|
import {
|
|
14
27
|
ErrorStackBlock,
|
|
15
|
-
|
|
28
|
+
isStructuredError,
|
|
29
|
+
type StructuredErrorRecord,
|
|
16
30
|
} from './ui/error-stack-block';
|
|
17
31
|
import { LoadMoreButton } from './ui/load-more-button';
|
|
18
32
|
import { MenuDropdown } from './ui/menu-dropdown';
|
|
@@ -84,6 +98,10 @@ function getStatusDotColor(eventType: string): string {
|
|
|
84
98
|
if (eventType === 'step_retrying') {
|
|
85
99
|
return 'var(--ds-amber-700)';
|
|
86
100
|
}
|
|
101
|
+
// Attribute changes → teal
|
|
102
|
+
if (eventType === 'attr_set') {
|
|
103
|
+
return 'var(--ds-teal-900)';
|
|
104
|
+
}
|
|
87
105
|
// Completed/succeeded → green
|
|
88
106
|
if (
|
|
89
107
|
eventType === 'step_completed' ||
|
|
@@ -142,7 +160,7 @@ function buildNameMaps(
|
|
|
142
160
|
return { correlationNameMap, workflowName };
|
|
143
161
|
}
|
|
144
162
|
|
|
145
|
-
interface DurationInfo {
|
|
163
|
+
export interface DurationInfo {
|
|
146
164
|
/** Time from created → started (ms) */
|
|
147
165
|
queued?: number;
|
|
148
166
|
/** Time from started → completed/failed/cancelled (ms) */
|
|
@@ -154,19 +172,30 @@ interface DurationInfo {
|
|
|
154
172
|
* created ↔ started (queued) and started ↔ completed/failed/cancelled (ran).
|
|
155
173
|
* Also computes run-level durations under the key '__run__'.
|
|
156
174
|
*/
|
|
157
|
-
function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
|
|
175
|
+
export function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
|
|
176
|
+
// Process events in chronological order so the result doesn't depend on
|
|
177
|
+
// the caller's sort direction. Retried steps emit multiple `step_started`
|
|
178
|
+
// events for the same correlationId; the queued duration must be measured
|
|
179
|
+
// against the first one, not the last.
|
|
180
|
+
const chronological = [...events].sort(
|
|
181
|
+
(a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
|
|
182
|
+
);
|
|
183
|
+
|
|
158
184
|
const createdTimes = new Map<string, number>();
|
|
185
|
+
const firstStartedTimes = new Map<string, number>();
|
|
159
186
|
const startedTimes = new Map<string, number>();
|
|
160
187
|
const durations = new Map<string, DurationInfo>();
|
|
161
188
|
|
|
162
|
-
for (const event of
|
|
189
|
+
for (const event of chronological) {
|
|
163
190
|
const ts = new Date(event.createdAt).getTime();
|
|
164
191
|
const key = event.correlationId ?? '__run__';
|
|
165
192
|
const type: string = event.eventType;
|
|
166
193
|
|
|
167
194
|
// Track created times (first event for each correlation)
|
|
168
195
|
if (type === 'step_created' || type === 'run_created') {
|
|
169
|
-
createdTimes.
|
|
196
|
+
if (!createdTimes.has(key)) {
|
|
197
|
+
createdTimes.set(key, ts);
|
|
198
|
+
}
|
|
170
199
|
}
|
|
171
200
|
|
|
172
201
|
// Track started times & compute queued duration
|
|
@@ -176,16 +205,21 @@ function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
|
|
|
176
205
|
type === 'workflow_started'
|
|
177
206
|
) {
|
|
178
207
|
startedTimes.set(key, ts);
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
208
|
+
// The queued duration is anchored on the first start event only —
|
|
209
|
+
// subsequent step_started events come from retries.
|
|
210
|
+
if (!firstStartedTimes.has(key)) {
|
|
211
|
+
firstStartedTimes.set(key, ts);
|
|
212
|
+
// If no explicit created event was seen, use the started time as created
|
|
213
|
+
if (!createdTimes.has(key)) {
|
|
214
|
+
createdTimes.set(key, ts);
|
|
215
|
+
}
|
|
216
|
+
const createdAt = createdTimes.get(key);
|
|
217
|
+
const info = durations.get(key) ?? {};
|
|
218
|
+
if (createdAt !== undefined) {
|
|
219
|
+
info.queued = ts - createdAt;
|
|
220
|
+
}
|
|
221
|
+
durations.set(key, info);
|
|
187
222
|
}
|
|
188
|
-
durations.set(key, info);
|
|
189
223
|
}
|
|
190
224
|
|
|
191
225
|
// Compute ran duration on terminal events
|
|
@@ -230,7 +264,10 @@ function isRunLevel(eventType: string): boolean {
|
|
|
230
264
|
eventType === 'run_cancelled' ||
|
|
231
265
|
eventType === 'workflow_started' ||
|
|
232
266
|
eventType === 'workflow_completed' ||
|
|
233
|
-
eventType === 'workflow_failed'
|
|
267
|
+
eventType === 'workflow_failed' ||
|
|
268
|
+
// attr_set carries a dedup correlationId rather than a child entity ID,
|
|
269
|
+
// so it groups and labels with the run itself.
|
|
270
|
+
eventType === 'attr_set'
|
|
234
271
|
);
|
|
235
272
|
}
|
|
236
273
|
|
|
@@ -492,20 +529,20 @@ function deepParseJson(value: unknown): unknown {
|
|
|
492
529
|
}
|
|
493
530
|
|
|
494
531
|
/**
|
|
495
|
-
* Extracts a structured error
|
|
532
|
+
* Extracts a structured error from event data, if present.
|
|
496
533
|
* Returns the error object to render with ErrorStackBlock, or null if not applicable.
|
|
497
534
|
*/
|
|
498
535
|
function extractStructuredError(
|
|
499
536
|
data: unknown,
|
|
500
537
|
eventType?: string
|
|
501
|
-
):
|
|
538
|
+
): StructuredErrorRecord | null {
|
|
502
539
|
if (!eventType || !ERROR_EVENT_TYPES.has(eventType)) return null;
|
|
503
540
|
if (data == null || typeof data !== 'object') return null;
|
|
504
541
|
const record = data as Record<string, unknown>;
|
|
505
542
|
// Check the nested `error` field first (the StructuredError)
|
|
506
|
-
if (
|
|
507
|
-
// Some error formats put the stack at the top level of eventData
|
|
508
|
-
if (
|
|
543
|
+
if (isStructuredError(record.error)) return record.error;
|
|
544
|
+
// Some error formats put the message/stack at the top level of eventData.
|
|
545
|
+
if (isStructuredError(record)) return record;
|
|
509
546
|
return null;
|
|
510
547
|
}
|
|
511
548
|
|
|
@@ -566,6 +603,12 @@ function PayloadBlock({
|
|
|
566
603
|
);
|
|
567
604
|
}
|
|
568
605
|
|
|
606
|
+
// Attribute changes — render the changed keys and the writer instead of
|
|
607
|
+
// the raw JSON payload.
|
|
608
|
+
if (eventType === 'attr_set') {
|
|
609
|
+
return <AttrSetEventBlock data={cleaned} />;
|
|
610
|
+
}
|
|
611
|
+
|
|
569
612
|
return (
|
|
570
613
|
<div className="relative group/payload">
|
|
571
614
|
<div
|
|
@@ -705,6 +748,12 @@ interface EventsListProps {
|
|
|
705
748
|
isDecrypting?: boolean;
|
|
706
749
|
/** Run-level hint: the run contains encrypted data (from probe). */
|
|
707
750
|
hasEncryptedData?: boolean;
|
|
751
|
+
/** Fetch events for an exact correlation or event ID. */
|
|
752
|
+
onExactIdSearch?: (
|
|
753
|
+
id: string,
|
|
754
|
+
kind: ExactWorkflowSearchIdKind,
|
|
755
|
+
signal?: AbortSignal
|
|
756
|
+
) => Promise<ExactIdSearchResult>;
|
|
708
757
|
}
|
|
709
758
|
|
|
710
759
|
function EventRow({
|
|
@@ -727,6 +776,7 @@ function EventRow({
|
|
|
727
776
|
onCacheEventData,
|
|
728
777
|
encryptionKey,
|
|
729
778
|
onEncryptedDataDetected,
|
|
779
|
+
suppressGroupDimming = false,
|
|
730
780
|
}: {
|
|
731
781
|
event: Event;
|
|
732
782
|
index: number;
|
|
@@ -747,6 +797,8 @@ function EventRow({
|
|
|
747
797
|
onCacheEventData: (eventId: string, data: unknown) => void;
|
|
748
798
|
encryptionKey?: Uint8Array;
|
|
749
799
|
onEncryptedDataDetected?: () => void;
|
|
800
|
+
/** Exact-ID search results should not dim unrelated rows. */
|
|
801
|
+
suppressGroupDimming?: boolean;
|
|
750
802
|
}) {
|
|
751
803
|
const [isLoading, setIsLoading] = useState(false);
|
|
752
804
|
const [loadedEventData, setLoadedEventData] = useState<unknown | null>(
|
|
@@ -788,7 +840,7 @@ function EventRow({
|
|
|
788
840
|
|
|
789
841
|
const hasActive = activeGroupKey !== undefined;
|
|
790
842
|
const isRelated = rowGroupKey !== undefined && rowGroupKey === activeGroupKey;
|
|
791
|
-
const isDimmed = hasActive && !isRelated;
|
|
843
|
+
const isDimmed = hasActive && !isRelated && !suppressGroupDimming;
|
|
792
844
|
const isPulsing = hasActive && isRelated;
|
|
793
845
|
|
|
794
846
|
// Gutter state derived from selectedGroupRange
|
|
@@ -1125,7 +1177,7 @@ function EventRow({
|
|
|
1125
1177
|
// Main component
|
|
1126
1178
|
// ──────────────────────────────────────────────────────────────────────────
|
|
1127
1179
|
|
|
1128
|
-
|
|
1180
|
+
function EventListViewInner({
|
|
1129
1181
|
events,
|
|
1130
1182
|
run,
|
|
1131
1183
|
onLoadEventData,
|
|
@@ -1139,7 +1191,9 @@ export function EventListView({
|
|
|
1139
1191
|
onDecrypt,
|
|
1140
1192
|
isDecrypting = false,
|
|
1141
1193
|
hasEncryptedData: hasEncryptedDataProp = false,
|
|
1194
|
+
onExactIdSearch,
|
|
1142
1195
|
}: EventsListProps) {
|
|
1196
|
+
const toast = useToast();
|
|
1143
1197
|
const [internalSortOrder, setInternalSortOrder] = useState<'asc' | 'desc'>(
|
|
1144
1198
|
'asc'
|
|
1145
1199
|
);
|
|
@@ -1155,25 +1209,42 @@ export function EventListView({
|
|
|
1155
1209
|
[onSortOrderChange]
|
|
1156
1210
|
);
|
|
1157
1211
|
|
|
1212
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
1213
|
+
const [searchResults, setSearchResults] = useState<Event[] | null>(null);
|
|
1214
|
+
const [searchResultsTruncated, setSearchResultsTruncated] = useState(false);
|
|
1215
|
+
const [searchError, setSearchError] = useState<string | null>(null);
|
|
1216
|
+
const [searchLoading, setSearchLoading] = useState(false);
|
|
1217
|
+
const [searchNotFound, setSearchNotFound] = useState(false);
|
|
1218
|
+
const searchRequestRef = useRef(0);
|
|
1219
|
+
const virtuosoRef = useRef<VirtuosoHandle>(null);
|
|
1220
|
+
|
|
1221
|
+
const parsedSearchId = useMemo(
|
|
1222
|
+
() => parseExactWorkflowSearchId(searchQuery),
|
|
1223
|
+
[searchQuery]
|
|
1224
|
+
);
|
|
1225
|
+
const isExactSearchActive = searchResults !== null;
|
|
1226
|
+
|
|
1158
1227
|
const sortedEvents = useMemo(() => {
|
|
1159
|
-
|
|
1228
|
+
const sourceEvents = isExactSearchActive ? searchResults : (events ?? []);
|
|
1229
|
+
if (sourceEvents.length === 0) return [];
|
|
1160
1230
|
const dir = effectiveSortOrder === 'desc' ? -1 : 1;
|
|
1161
|
-
return [...
|
|
1231
|
+
return [...sourceEvents].sort(
|
|
1162
1232
|
(a, b) =>
|
|
1163
1233
|
dir *
|
|
1164
1234
|
(new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())
|
|
1165
1235
|
);
|
|
1166
|
-
}, [events, effectiveSortOrder]);
|
|
1236
|
+
}, [events, effectiveSortOrder, isExactSearchActive, searchResults]);
|
|
1167
1237
|
|
|
1168
1238
|
// Detect encrypted fields across all loaded events (inline eventData).
|
|
1169
1239
|
const hasEncryptedInlineData = useMemo(() => {
|
|
1170
|
-
|
|
1171
|
-
|
|
1240
|
+
const sourceEvents = isExactSearchActive ? searchResults : events;
|
|
1241
|
+
if (!sourceEvents) return false;
|
|
1242
|
+
for (const event of sourceEvents) {
|
|
1172
1243
|
const ed = (event as Record<string, unknown>).eventData;
|
|
1173
1244
|
if (hasEncryptedValues(ed)) return true;
|
|
1174
1245
|
}
|
|
1175
1246
|
return false;
|
|
1176
|
-
}, [events]);
|
|
1247
|
+
}, [events, isExactSearchActive, searchResults]);
|
|
1177
1248
|
|
|
1178
1249
|
// Tracks whether any expanded row's lazy-loaded data contained encrypted markers.
|
|
1179
1250
|
// Set to true by EventRow via onEncryptedDataDetected; never reset (sticky).
|
|
@@ -1187,8 +1258,12 @@ export function EventListView({
|
|
|
1187
1258
|
hasEncryptedDataProp || hasEncryptedInlineData || foundEncryptedInLazyData;
|
|
1188
1259
|
|
|
1189
1260
|
const { correlationNameMap, workflowName } = useMemo(
|
|
1190
|
-
() =>
|
|
1191
|
-
|
|
1261
|
+
() =>
|
|
1262
|
+
buildNameMaps(
|
|
1263
|
+
isExactSearchActive ? searchResults : (events ?? null),
|
|
1264
|
+
run ?? null
|
|
1265
|
+
),
|
|
1266
|
+
[events, isExactSearchActive, run, searchResults]
|
|
1192
1267
|
);
|
|
1193
1268
|
|
|
1194
1269
|
const durationMap = useMemo(
|
|
@@ -1278,68 +1353,139 @@ export function EventListView({
|
|
|
1278
1353
|
return first >= 0 ? { first, last } : null;
|
|
1279
1354
|
}, [activeGroupKey, sortedEvents]);
|
|
1280
1355
|
|
|
1281
|
-
const [searchQuery, setSearchQuery] = useState('');
|
|
1282
|
-
const virtuosoRef = useRef<VirtuosoHandle>(null);
|
|
1283
|
-
|
|
1284
|
-
const searchIndex = useMemo(() => {
|
|
1285
|
-
const entries: {
|
|
1286
|
-
fields: string[];
|
|
1287
|
-
groupKey?: string;
|
|
1288
|
-
eventId: string;
|
|
1289
|
-
index: number;
|
|
1290
|
-
}[] = [];
|
|
1291
|
-
for (let i = 0; i < sortedEvents.length; i++) {
|
|
1292
|
-
const ev = sortedEvents[i];
|
|
1293
|
-
const isRun = isRunLevel(ev.eventType);
|
|
1294
|
-
const name = isRun
|
|
1295
|
-
? (workflowName ?? '')
|
|
1296
|
-
: ev.correlationId
|
|
1297
|
-
? (correlationNameMap.get(ev.correlationId) ?? '')
|
|
1298
|
-
: '';
|
|
1299
|
-
entries.push({
|
|
1300
|
-
fields: [
|
|
1301
|
-
ev.eventId,
|
|
1302
|
-
ev.correlationId ?? '',
|
|
1303
|
-
ev.eventType,
|
|
1304
|
-
formatEventType(ev.eventType),
|
|
1305
|
-
name,
|
|
1306
|
-
].map((f) => f.toLowerCase()),
|
|
1307
|
-
groupKey: ev.correlationId ?? (isRun ? '__run__' : undefined),
|
|
1308
|
-
eventId: ev.eventId,
|
|
1309
|
-
index: i,
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
|
-
return entries;
|
|
1313
|
-
}, [sortedEvents, correlationNameMap, workflowName]);
|
|
1314
|
-
|
|
1315
1356
|
useEffect(() => {
|
|
1316
|
-
const
|
|
1317
|
-
if (!
|
|
1357
|
+
const trimmed = searchQuery.trim();
|
|
1358
|
+
if (!trimmed) {
|
|
1359
|
+
searchRequestRef.current += 1;
|
|
1360
|
+
setSearchResults(null);
|
|
1361
|
+
setSearchResultsTruncated(false);
|
|
1362
|
+
setSearchError(null);
|
|
1363
|
+
setSearchLoading(false);
|
|
1364
|
+
setSearchNotFound(false);
|
|
1318
1365
|
setSelectedGroupKey(undefined);
|
|
1319
1366
|
return;
|
|
1320
1367
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1368
|
+
|
|
1369
|
+
const parsed = parseExactWorkflowSearchId(trimmed);
|
|
1370
|
+
if (!parsed || !onExactIdSearch) {
|
|
1371
|
+
setSearchResults(null);
|
|
1372
|
+
setSearchLoading(false);
|
|
1373
|
+
setSearchNotFound(false);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
const requestId = ++searchRequestRef.current;
|
|
1378
|
+
setSearchLoading(true);
|
|
1379
|
+
setSearchNotFound(false);
|
|
1380
|
+
setSearchError(null);
|
|
1381
|
+
|
|
1382
|
+
const abortController = new AbortController();
|
|
1383
|
+
|
|
1384
|
+
const timer = setTimeout(() => {
|
|
1385
|
+
void (async () => {
|
|
1386
|
+
try {
|
|
1387
|
+
const results = await onExactIdSearch(
|
|
1388
|
+
parsed.id,
|
|
1389
|
+
parsed.kind,
|
|
1390
|
+
abortController.signal
|
|
1391
|
+
);
|
|
1392
|
+
if (
|
|
1393
|
+
abortController.signal.aborted ||
|
|
1394
|
+
searchRequestRef.current !== requestId
|
|
1395
|
+
) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
if (results.status === 'error') {
|
|
1400
|
+
setSearchResults([]);
|
|
1401
|
+
setSearchResultsTruncated(false);
|
|
1402
|
+
setSearchNotFound(false);
|
|
1403
|
+
setSearchError(results.message);
|
|
1404
|
+
setSelectedGroupKey(undefined);
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
if (
|
|
1409
|
+
results.status === 'not_found' ||
|
|
1410
|
+
(results.status === 'ok' && results.events.length === 0)
|
|
1411
|
+
) {
|
|
1412
|
+
setSearchResults([]);
|
|
1413
|
+
setSearchResultsTruncated(false);
|
|
1414
|
+
setSearchNotFound(true);
|
|
1415
|
+
setSearchError(null);
|
|
1416
|
+
setSelectedGroupKey(undefined);
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
setSearchResults(results.events);
|
|
1421
|
+
setSearchResultsTruncated(Boolean(results.truncated));
|
|
1422
|
+
setSearchNotFound(false);
|
|
1423
|
+
setSearchError(null);
|
|
1424
|
+
setSelectedGroupKey(
|
|
1425
|
+
parsed.kind === 'event'
|
|
1426
|
+
? (() => {
|
|
1427
|
+
const first = results.events[0];
|
|
1428
|
+
if (!first) return undefined;
|
|
1429
|
+
return isRunLevel(first.eventType)
|
|
1430
|
+
? '__run__'
|
|
1431
|
+
: (first.correlationId ?? undefined);
|
|
1432
|
+
})()
|
|
1433
|
+
: parsed.id
|
|
1434
|
+
);
|
|
1435
|
+
virtuosoRef.current?.scrollToIndex({
|
|
1436
|
+
index: 0,
|
|
1437
|
+
align: 'start',
|
|
1438
|
+
behavior: 'smooth',
|
|
1439
|
+
});
|
|
1440
|
+
} catch {
|
|
1441
|
+
if (
|
|
1442
|
+
abortController.signal.aborted ||
|
|
1443
|
+
searchRequestRef.current !== requestId
|
|
1444
|
+
) {
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
setSearchResults([]);
|
|
1448
|
+
setSearchResultsTruncated(false);
|
|
1449
|
+
setSearchNotFound(false);
|
|
1450
|
+
setSearchError('Failed to search events. Try again.');
|
|
1451
|
+
setSelectedGroupKey(undefined);
|
|
1452
|
+
} finally {
|
|
1453
|
+
if (
|
|
1454
|
+
searchRequestRef.current === requestId &&
|
|
1455
|
+
!abortController.signal.aborted
|
|
1456
|
+
) {
|
|
1457
|
+
setSearchLoading(false);
|
|
1330
1458
|
}
|
|
1331
1459
|
}
|
|
1460
|
+
})();
|
|
1461
|
+
}, 300);
|
|
1462
|
+
|
|
1463
|
+
return () => {
|
|
1464
|
+
clearTimeout(timer);
|
|
1465
|
+
abortController.abort();
|
|
1466
|
+
};
|
|
1467
|
+
}, [searchQuery, onExactIdSearch]);
|
|
1468
|
+
|
|
1469
|
+
const handleSearchKeyDown = useCallback(
|
|
1470
|
+
(event: ReactKeyboardEvent<HTMLInputElement>) => {
|
|
1471
|
+
if (event.key !== 'Enter') {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
const trimmed = searchQuery.trim();
|
|
1476
|
+
if (
|
|
1477
|
+
!trimmed ||
|
|
1478
|
+
parseExactWorkflowSearchId(trimmed) ||
|
|
1479
|
+
!onExactIdSearch ||
|
|
1480
|
+
!looksLikeWorkflowIdSearchInput(trimmed)
|
|
1481
|
+
) {
|
|
1482
|
+
return;
|
|
1332
1483
|
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
align: 'center',
|
|
1339
|
-
behavior: 'smooth',
|
|
1340
|
-
});
|
|
1341
|
-
}
|
|
1342
|
-
}, [searchQuery, searchIndex]);
|
|
1484
|
+
|
|
1485
|
+
toast.info('Enter a full step ID, wait ID, hook ID, or event ID');
|
|
1486
|
+
},
|
|
1487
|
+
[searchQuery, onExactIdSearch, toast]
|
|
1488
|
+
);
|
|
1343
1489
|
|
|
1344
1490
|
// Track whether we've ever had events to distinguish initial load from refetch
|
|
1345
1491
|
const hasHadEventsRef = useRef(false);
|
|
@@ -1385,17 +1531,6 @@ export function EventListView({
|
|
|
1385
1531
|
);
|
|
1386
1532
|
}
|
|
1387
1533
|
|
|
1388
|
-
if (!isLoading && (!events || events.length === 0)) {
|
|
1389
|
-
return (
|
|
1390
|
-
<div
|
|
1391
|
-
className="flex items-center justify-center h-full text-sm"
|
|
1392
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
1393
|
-
>
|
|
1394
|
-
No events found
|
|
1395
|
-
</div>
|
|
1396
|
-
);
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
1534
|
return (
|
|
1400
1535
|
<DecryptClickContext.Provider
|
|
1401
1536
|
value={onDecrypt ? { onDecrypt, isDecrypting } : undefined}
|
|
@@ -1460,9 +1595,16 @@ export function EventListView({
|
|
|
1460
1595
|
</div>
|
|
1461
1596
|
<input
|
|
1462
1597
|
type="search"
|
|
1463
|
-
placeholder="Search by
|
|
1598
|
+
placeholder="Search by step ID, wait ID, hook ID, or event ID…"
|
|
1464
1599
|
value={searchQuery}
|
|
1465
1600
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
1601
|
+
onKeyDown={handleSearchKeyDown}
|
|
1602
|
+
disabled={!onExactIdSearch}
|
|
1603
|
+
title={
|
|
1604
|
+
onExactIdSearch
|
|
1605
|
+
? undefined
|
|
1606
|
+
: 'Exact ID search is unavailable in this view.'
|
|
1607
|
+
}
|
|
1466
1608
|
style={{
|
|
1467
1609
|
marginLeft: -16,
|
|
1468
1610
|
paddingInline: 12,
|
|
@@ -1473,6 +1615,8 @@ export function EventListView({
|
|
|
1473
1615
|
outline: 'none',
|
|
1474
1616
|
height: 40,
|
|
1475
1617
|
width: '100%',
|
|
1618
|
+
opacity: onExactIdSearch ? 1 : 0.5,
|
|
1619
|
+
cursor: onExactIdSearch ? 'text' : 'not-allowed',
|
|
1476
1620
|
}}
|
|
1477
1621
|
/>
|
|
1478
1622
|
</label>
|
|
@@ -1519,8 +1663,21 @@ export function EventListView({
|
|
|
1519
1663
|
</div>
|
|
1520
1664
|
|
|
1521
1665
|
{/* Virtualized event rows or refetching skeleton */}
|
|
1522
|
-
{isRefetching ? (
|
|
1666
|
+
{isRefetching || searchLoading ? (
|
|
1523
1667
|
<RowsSkeleton />
|
|
1668
|
+
) : sortedEvents.length === 0 ? (
|
|
1669
|
+
<div
|
|
1670
|
+
className="flex flex-1 items-center justify-center px-6 text-center text-sm"
|
|
1671
|
+
style={{ color: 'var(--ds-gray-700)' }}
|
|
1672
|
+
>
|
|
1673
|
+
{searchNotFound && searchQuery.trim()
|
|
1674
|
+
? `No events found for ${searchQuery.trim()}`
|
|
1675
|
+
: searchError
|
|
1676
|
+
? searchError
|
|
1677
|
+
: parsedSearchId && searchQuery.trim() && !onExactIdSearch
|
|
1678
|
+
? 'Exact ID search is unavailable in this view.'
|
|
1679
|
+
: 'No events found'}
|
|
1680
|
+
</div>
|
|
1524
1681
|
) : (
|
|
1525
1682
|
<Virtuoso
|
|
1526
1683
|
ref={virtuosoRef}
|
|
@@ -1528,7 +1685,11 @@ export function EventListView({
|
|
|
1528
1685
|
overscan={20}
|
|
1529
1686
|
defaultItemHeight={40}
|
|
1530
1687
|
endReached={() => {
|
|
1531
|
-
if (
|
|
1688
|
+
if (
|
|
1689
|
+
isExactSearchActive ||
|
|
1690
|
+
!hasMoreEvents ||
|
|
1691
|
+
isLoadingMoreEvents
|
|
1692
|
+
) {
|
|
1532
1693
|
return;
|
|
1533
1694
|
}
|
|
1534
1695
|
void onLoadMoreEvents?.();
|
|
@@ -1558,6 +1719,7 @@ export function EventListView({
|
|
|
1558
1719
|
onCacheEventData={cacheEventData}
|
|
1559
1720
|
encryptionKey={encryptionKey}
|
|
1560
1721
|
onEncryptedDataDetected={handleEncryptedDataDetected}
|
|
1722
|
+
suppressGroupDimming={isExactSearchActive}
|
|
1561
1723
|
/>
|
|
1562
1724
|
);
|
|
1563
1725
|
}}
|
|
@@ -1575,10 +1737,15 @@ export function EventListView({
|
|
|
1575
1737
|
}}
|
|
1576
1738
|
>
|
|
1577
1739
|
<span>
|
|
1578
|
-
{
|
|
1579
|
-
|
|
1740
|
+
{isExactSearchActive
|
|
1741
|
+
? searchError
|
|
1742
|
+
? searchError
|
|
1743
|
+
: searchNotFound
|
|
1744
|
+
? `No events found for ${searchQuery.trim()}`
|
|
1745
|
+
: `${sortedEvents.length} event${sortedEvents.length !== 1 ? 's' : ''} for ${searchQuery.trim()}${searchResultsTruncated ? ' (results may be truncated)' : ''}`
|
|
1746
|
+
: `${sortedEvents.length} event${sortedEvents.length !== 1 ? 's' : ''} loaded`}
|
|
1580
1747
|
</span>
|
|
1581
|
-
{hasMoreEvents && (
|
|
1748
|
+
{!isExactSearchActive && hasMoreEvents && (
|
|
1582
1749
|
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
1583
1750
|
<div className="pointer-events-auto">
|
|
1584
1751
|
<LoadMoreButton
|
|
@@ -1593,3 +1760,11 @@ export function EventListView({
|
|
|
1593
1760
|
</DecryptClickContext.Provider>
|
|
1594
1761
|
);
|
|
1595
1762
|
}
|
|
1763
|
+
|
|
1764
|
+
export function EventListView(props: EventsListProps) {
|
|
1765
|
+
return (
|
|
1766
|
+
<ContextCardProvider>
|
|
1767
|
+
<EventListViewInner {...props} />
|
|
1768
|
+
</ContextCardProvider>
|
|
1769
|
+
);
|
|
1770
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -15,6 +15,10 @@ export {
|
|
|
15
15
|
} from './hook-actions';
|
|
16
16
|
export { RunTraceView } from './run-trace-view';
|
|
17
17
|
export { ConversationView } from './sidebar/conversation-view';
|
|
18
|
+
export {
|
|
19
|
+
SidebarDataProvider,
|
|
20
|
+
type SidebarDataContextValue,
|
|
21
|
+
} from './sidebar/sidebar-data-context';
|
|
18
22
|
export type {
|
|
19
23
|
SelectedSpanInfo,
|
|
20
24
|
SpanSelectionInfo,
|
|
@@ -28,7 +32,10 @@ export {
|
|
|
28
32
|
type DecryptClickContextValue,
|
|
29
33
|
} from './ui/data-inspector';
|
|
30
34
|
export { DecryptButton } from './ui/decrypt-button';
|
|
35
|
+
export { IconButton } from './ui/icon-button';
|
|
31
36
|
export { LoadMoreButton } from './ui/load-more-button';
|
|
32
37
|
export { MenuDropdown, type MenuDropdownOption } from './ui/menu-dropdown';
|
|
33
38
|
export { Spinner } from './ui/spinner';
|
|
34
39
|
export { WorkflowTraceViewer } from './workflow-trace-view';
|
|
40
|
+
export { NewTraceViewer } from './trace-viewer-new';
|
|
41
|
+
export { TraceViewerSkeleton } from './new-trace-viewer/components/trace-viewer-skeleton';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Check, Copy } from 'lucide-react';
|
|
4
|
+
import { type JSX, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { cn } from '../../../lib/utils';
|
|
6
|
+
|
|
7
|
+
interface CopyButtonProps {
|
|
8
|
+
copyText: string;
|
|
9
|
+
ariaLabel: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function CopyButton({
|
|
14
|
+
copyText,
|
|
15
|
+
ariaLabel,
|
|
16
|
+
className,
|
|
17
|
+
}: CopyButtonProps): JSX.Element {
|
|
18
|
+
const [copied, setCopied] = useState(false);
|
|
19
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
return () => {
|
|
23
|
+
if (timeoutRef.current) {
|
|
24
|
+
clearTimeout(timeoutRef.current);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<button
|
|
31
|
+
type="button"
|
|
32
|
+
aria-label={ariaLabel}
|
|
33
|
+
className={cn(
|
|
34
|
+
'cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-0 p-1 m-0',
|
|
35
|
+
className
|
|
36
|
+
)}
|
|
37
|
+
onClick={(e) => {
|
|
38
|
+
e.stopPropagation();
|
|
39
|
+
if (timeoutRef.current) {
|
|
40
|
+
clearTimeout(timeoutRef.current);
|
|
41
|
+
}
|
|
42
|
+
void navigator.clipboard.writeText(copyText).then(() => {
|
|
43
|
+
setCopied(true);
|
|
44
|
+
timeoutRef.current = setTimeout(() => setCopied(false), 1000);
|
|
45
|
+
});
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<div className="relative w-3 h-3">
|
|
49
|
+
<div
|
|
50
|
+
className={cn(
|
|
51
|
+
'absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out',
|
|
52
|
+
copied ? 'scale-100 opacity-100' : 'scale-0 opacity-0'
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
<Check className="w-3 h-3" />
|
|
56
|
+
</div>
|
|
57
|
+
<div
|
|
58
|
+
className={cn(
|
|
59
|
+
'absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out',
|
|
60
|
+
copied ? 'scale-0 opacity-0' : 'scale-100 opacity-100'
|
|
61
|
+
)}
|
|
62
|
+
>
|
|
63
|
+
<Copy className="w-3 h-3" />
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</button>
|
|
67
|
+
);
|
|
68
|
+
}
|