@workflow/web 5.0.0-beta.4 → 5.0.0-beta.41
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 -0
- package/build/client/assets/app-BkGXg64e.css +1 -0
- package/build/client/assets/arrow-up-right-jWH-UQH9.js +15 -0
- package/build/client/assets/{entry.client-BWsSsWQm.js → entry.client-LwI3HNYl.js} +25 -25
- package/build/client/assets/{highlighted-body-B3W2YXNL-B7T9pqeb.js → highlighted-body-B3W2YXNL-DmmWu7VM.js} +2 -2
- package/build/client/assets/{home-BIQJMe_Q.js → home-BwYHJJJr.js} +1762 -290
- package/build/client/assets/index-HqNj_XIX.js +200 -0
- package/build/client/assets/{index-DQa-BExo.js → index-PFjW8YjQ.js} +24 -24
- package/build/client/assets/loader-circle-fFQM94Ej.js +12 -0
- package/build/client/assets/manifest-f6a9dca2.js +1 -0
- package/build/client/assets/mermaid-3ZIDBTTL-D8CjRQta.css +1 -0
- package/build/client/assets/{mermaid-3ZIDBTTL-w46Kr90n.js → mermaid-3ZIDBTTL-DchhEfRL.js} +6169 -4615
- package/build/client/assets/{root-sXuXrryl.js → root-D6p4Hb4F.js} +17 -42
- package/build/client/assets/root-ZRjqDhEN.css +1 -0
- package/build/client/assets/run-detail-CWoGxu_0.css +1 -0
- package/build/client/assets/{run-detail-7Pj2mQLs.js → run-detail-vPCbZIXx.js} +1970 -1587
- package/build/client/assets/{workflow-graph-viewer-De9JQkZc.js → workflow-graph-viewer-t_fSwuwz.js} +5109 -5110
- package/build/client/assets/zstd-B5R2yJjB.wasm +0 -0
- package/build/client/assets/zstd-browser-decoder-BTw1glGN.js +27 -0
- package/build/server/assets/{server-build-DT0Hg0Yf.js → app-D8GiFFR6.js} +71220 -49560
- package/build/server/assets/{highlighted-body-B3W2YXNL-uaucauLI.js → highlighted-body-B3W2YXNL-BZVc2guG.js} +13 -8
- package/build/server/assets/index-BByEr1g6.js +154 -0
- package/build/server/assets/index-BfLBLRRi.js +204 -0
- package/build/server/assets/index-CETb4fkq.js +1164 -0
- package/build/server/assets/index-DTci39F3.js +1262 -0
- package/build/server/assets/{mermaid-3ZIDBTTL-DrZ5V6uv.js → mermaid-3ZIDBTTL-DOefrphg.js} +14 -9
- package/build/server/assets/{token-D7_Lld85.js → token-c3byIJRC.js} +5 -2
- package/build/server/assets/{token-util-CfY4anoc.js → token-util-C2yENsqE.js} +5 -2
- package/build/server/assets/websocket-server-DagS_hnJ.js +3669 -0
- package/build/server/assets/wrapper-Cnumc4u1.js +67 -0
- package/build/server/assets/ws-transport-2gJL6hC2.js +493 -0
- package/build/server/assets/zstd-browser-decoder-BCVvr1WT.js +70 -0
- package/build/server/index.js +48 -2
- package/handler.d.ts +22 -0
- package/handler.js +186 -0
- package/package.json +27 -12
- package/registry.d.ts +29 -0
- package/registry.js +89 -0
- package/build/client/assets/encryption-80GMP4r0.js +0 -26
- package/build/client/assets/manifest-77894282.js +0 -1
- package/build/client/assets/mermaid-3ZIDBTTL-DKxHcEOp.css +0 -1
- package/build/client/assets/root-C0Tu5TVN.css +0 -1
- package/build/client/assets/server-build-DqaxIrF0.css +0 -1
- package/build/client/assets/worker-CqHKTA7D.js +0 -115
- package/build/server/assets/app-CtOg8_v5.js +0 -9213
- package/build/server/assets/index-D02biwxV.js +0 -82
- package/build/server/assets/index-meg9qk8y.js +0 -1282
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { c as createLucideIcon,
|
|
4
|
-
import {
|
|
1
|
+
import { r as reactExports, j as jsxRuntimeExports, o as reactDomExports, D as ReactDOM, d as useNavigate, e as useSearchParams, c as Link, w as withComponentProps, G as useParams } from "./index-PFjW8YjQ.js";
|
|
2
|
+
import { C as CircleAlert, O as parseStepName, B as parseWorkflowName, Q as ErrorCard, U as format, Z as Zap, S as Send, R as ResolveHookModal, q as ChevronUp, X, N as ErrorBoundary, V as Circle, u as unwrapOrThrow, W as WorkflowWebAPIError, I as unwrapServerActionResult, Y as useEscapeKeydown, t as composeEventHandlers, _ as useCallbackRef, $ as useLayoutEffect2, s as useControllableState, a0 as useId, a1 as createContext2, v as Presence, x as createContextScope, n as hideOthers, o as ReactRemoveScroll, a2 as useFocusGuards, a3 as LAYOUT, a4 as wakeUpRun, l as resumeHook, A as Alert, c as AlertTitle, g as getErrorTitle, d as AlertDescription, e as getErrorMessage, a as Skeleton$1, a5 as RunActionsButtons, F as StatusBadge, h as CopyableText, b as RelativeTime, T as Tabs, K as TabsList, L as TabsTrigger, M as TabsContent, a6 as cancelRun, a7 as recreateRun } from "./workflow-graph-viewer-t_fSwuwz.js";
|
|
3
|
+
import { c as createLucideIcon, Y as cn, Z as CopyableDataBlock, $ as CollapsibleRoot, a0 as CollapsibleTrigger, a1 as CollapsibleContent, a2 as CopyButton, O as cva, a3 as RESERVED_ATTRIBUTE_KEY_PREFIX, a4 as Spinner, a5 as ContextCardProvider, h as useToast, a6 as Skeleton, a7 as DecryptClickContext, a8 as Yr, a9 as isEncryptedMarker, m as ChevronRight, aa as TimestampTooltip, ab as formatDuration, C as Check, l as Copy, ac as DataInspector, ad as _r, ae as isHookLifecycleEventType, af as isTerminalStepEventType, ag as isWaitEventType, ah as isStepEventType, ai as RunClickContext, aj as StreamClickContext, ak as Collapsible, al as isExpiredMarker, am as isDoStreamStep, an as extractConversation, ao as EncryptedDataBlock, ap as getEventDataRefFields, aq as hasEncryptedFields, ar as useSidebarDataOptional, as as isTerminalWorkflowRunStatus, at as clsx, au as useActiveSpan, av as useSidebarData, aw as Tooltip, ax as TooltipTrigger, ay as IconButton, az as TooltipContent, J as ChevronDown, aA as useRowWindow, aB as isSpanDimmedBySearch, aC as ROW_HEIGHT_PX, aD as getSpanDurationMs, aE as isSpanErrored, aF as formatDurationPrecise, aG as TooltipProvider, aH as ActiveSpanProvider, aI as useReducedMotion, aJ as searchSpans, aK as computeRootBounds, aL as computeTimeMarkers, aM as clampViewportToRoot, aN as getHighResInMs, aO as scrollRowIntoView, aP as TIMELINE_PADDING_PX, aQ as Minimap, aR as Timeline, aS as TimelineHeader, aT as wheelZoomScaleFactor, aU as wheelDeltaToPixels, aV as SidebarDataProvider, aW as fetchHook, n as fetchEvents, aX as hydrateResourceIOAsync, N as fetchRun, aY as fetchStep, aZ as hydrateResourceIO, a_ as fetchStreams, a$ as apiBase, b0 as Slot, L as useComposedRefs, b1 as Slottable, e as cn$1, b2 as buttonVariants, b3 as fetchEvent, b4 as fetchEventsByCorrelationId, b5 as isEncryptedData, b6 as hydrateData, b7 as decrypt, b8 as deriveRunPayloadKeys, b9 as getWebRevivers, T as Tooltip$1, a as TooltipTrigger$1, b as TooltipContent$1, ba as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, bb as getEncryptionKeyForRun, t as toast, bc as StreamViewerSkeleton, bd as Lock, be as StreamViewer } from "./mermaid-3ZIDBTTL-DchhEfRL.js";
|
|
4
|
+
import { A as ArrowUpRight } from "./arrow-up-right-jWH-UQH9.js";
|
|
5
5
|
/**
|
|
6
6
|
* @license lucide-react v0.575.0 - ISC
|
|
7
7
|
*
|
|
@@ -76,40 +76,457 @@ const __iconNode = [
|
|
|
76
76
|
["line", { x1: "8", x2: "14", y1: "11", y2: "11", key: "durymu" }]
|
|
77
77
|
];
|
|
78
78
|
const ZoomOut = createLucideIcon("zoom-out", __iconNode);
|
|
79
|
+
const WORKFLOW_ULID_BODY = "[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}";
|
|
80
|
+
const STEP_ID_PATTERN = new RegExp(`^step_(${WORKFLOW_ULID_BODY})$`, "i");
|
|
81
|
+
const WAIT_ID_PATTERN = new RegExp(`^wait_(${WORKFLOW_ULID_BODY})$`, "i");
|
|
82
|
+
const HOOK_ID_PATTERN = new RegExp(`^hook_(${WORKFLOW_ULID_BODY})$`, "i");
|
|
83
|
+
const EVENT_ID_PATTERN = new RegExp(`^evnt_(${WORKFLOW_ULID_BODY})$`, "i");
|
|
84
|
+
const WORKFLOW_ID_PREFIX_PATTERN = /^(step_|wait_|hook_|evnt_|wrun_)/i;
|
|
85
|
+
function matchPrefixedId(pattern, prefix, kind, query) {
|
|
86
|
+
const match = query.match(pattern);
|
|
87
|
+
if (!match) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return { kind, id: `${prefix}_${match[1].toUpperCase()}` };
|
|
91
|
+
}
|
|
92
|
+
function parseExactWorkflowSearchId(query) {
|
|
93
|
+
const trimmed = query.trim();
|
|
94
|
+
if (!trimmed) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return matchPrefixedId(STEP_ID_PATTERN, "step", "step", trimmed) ?? matchPrefixedId(WAIT_ID_PATTERN, "wait", "wait", trimmed) ?? matchPrefixedId(HOOK_ID_PATTERN, "hook", "hook", trimmed) ?? matchPrefixedId(EVENT_ID_PATTERN, "evnt", "event", trimmed);
|
|
98
|
+
}
|
|
99
|
+
function looksLikeWorkflowIdSearchInput(query) {
|
|
100
|
+
const trimmed = query.trim();
|
|
101
|
+
if (!WORKFLOW_ID_PREFIX_PATTERN.test(trimmed)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return /\d/.test(trimmed);
|
|
105
|
+
}
|
|
106
|
+
const ELLIPSIS = "…";
|
|
107
|
+
const MIN_START = 3;
|
|
108
|
+
const MIN_END = 3;
|
|
109
|
+
const MIN_KEPT = MIN_START + MIN_END;
|
|
110
|
+
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
111
|
+
function toGraphemes(text) {
|
|
112
|
+
if (graphemeSegmenter) {
|
|
113
|
+
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
114
|
+
}
|
|
115
|
+
return Array.from(text);
|
|
116
|
+
}
|
|
117
|
+
function buildCandidate(graphemes, kept) {
|
|
118
|
+
if (kept <= 0) {
|
|
119
|
+
return {
|
|
120
|
+
prefixText: "",
|
|
121
|
+
prefixGraphemeCount: 0,
|
|
122
|
+
suffixText: "",
|
|
123
|
+
suffixGraphemeCount: 0,
|
|
124
|
+
text: ELLIPSIS,
|
|
125
|
+
truncated: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const suffixGraphemeCount = kept >= MIN_KEPT ? Math.max(MIN_END, Math.floor(kept / 2)) : Math.floor(kept / 2);
|
|
129
|
+
const prefixGraphemeCount = kept - suffixGraphemeCount;
|
|
130
|
+
const prefixText = graphemes.slice(0, prefixGraphemeCount).join("");
|
|
131
|
+
const suffixText = suffixGraphemeCount > 0 ? graphemes.slice(-suffixGraphemeCount).join("") : "";
|
|
132
|
+
return {
|
|
133
|
+
prefixText,
|
|
134
|
+
prefixGraphemeCount,
|
|
135
|
+
suffixText,
|
|
136
|
+
suffixGraphemeCount,
|
|
137
|
+
text: prefixText + ELLIPSIS + suffixText,
|
|
138
|
+
truncated: true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function middleTruncate(graphemes, availableWidth, measure, fullWidth) {
|
|
142
|
+
const fullText = graphemes.join("");
|
|
143
|
+
const resolvedFullWidth = fullWidth ?? measure(fullText);
|
|
144
|
+
if (availableWidth <= 0 || graphemes.length === 0) {
|
|
145
|
+
return {
|
|
146
|
+
prefixText: fullText,
|
|
147
|
+
prefixGraphemeCount: graphemes.length,
|
|
148
|
+
suffixText: "",
|
|
149
|
+
suffixGraphemeCount: 0,
|
|
150
|
+
text: fullText,
|
|
151
|
+
truncated: false
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (resolvedFullWidth <= availableWidth) {
|
|
155
|
+
return {
|
|
156
|
+
prefixText: fullText,
|
|
157
|
+
prefixGraphemeCount: graphemes.length,
|
|
158
|
+
suffixText: "",
|
|
159
|
+
suffixGraphemeCount: 0,
|
|
160
|
+
text: fullText,
|
|
161
|
+
truncated: false
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
let lo = 0;
|
|
165
|
+
let hi = graphemes.length - 1;
|
|
166
|
+
let best = -1;
|
|
167
|
+
while (lo <= hi) {
|
|
168
|
+
const mid = lo + hi >>> 1;
|
|
169
|
+
const candidate = buildCandidate(graphemes, mid);
|
|
170
|
+
if (measure(candidate.text) <= availableWidth) {
|
|
171
|
+
best = mid;
|
|
172
|
+
lo = mid + 1;
|
|
173
|
+
} else {
|
|
174
|
+
hi = mid - 1;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (best === -1) {
|
|
178
|
+
return {
|
|
179
|
+
prefixText: "",
|
|
180
|
+
prefixGraphemeCount: 0,
|
|
181
|
+
suffixText: "",
|
|
182
|
+
suffixGraphemeCount: 0,
|
|
183
|
+
text: "",
|
|
184
|
+
truncated: true
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return buildCandidate(graphemes, best);
|
|
188
|
+
}
|
|
189
|
+
function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value }) {
|
|
190
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
191
|
+
if (selectionStart < 0 || selectionEnd > visibleText.length || selectionStart >= selectionEnd) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
195
|
+
return value;
|
|
196
|
+
}
|
|
197
|
+
const ellipsisStart = prefixText.length;
|
|
198
|
+
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
199
|
+
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const originalGraphemes = toGraphemes(value);
|
|
203
|
+
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
204
|
+
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
205
|
+
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
206
|
+
return originalGraphemes.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount).join("");
|
|
207
|
+
}
|
|
208
|
+
function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value }) {
|
|
209
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
210
|
+
const trimmedSelectionText = selectionText.trim();
|
|
211
|
+
if (!trimmedSelectionText) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
215
|
+
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
216
|
+
if (trimmedSelectionText === visibleText) {
|
|
217
|
+
return leading + value + trailing;
|
|
218
|
+
}
|
|
219
|
+
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
223
|
+
if (selectionStart === -1) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
227
|
+
const mappedText = getMiddleTruncateCopyText({
|
|
228
|
+
prefixText,
|
|
229
|
+
selectionEnd,
|
|
230
|
+
selectionStart,
|
|
231
|
+
suffixText,
|
|
232
|
+
value
|
|
233
|
+
});
|
|
234
|
+
return mappedText === null ? null : leading + mappedText + trailing;
|
|
235
|
+
}
|
|
236
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? reactExports.useEffect : reactExports.useLayoutEffect;
|
|
237
|
+
function createFullState(value, graphemes) {
|
|
238
|
+
return {
|
|
239
|
+
displayText: value,
|
|
240
|
+
isTruncated: false,
|
|
241
|
+
prefixGraphemeCount: graphemes.length,
|
|
242
|
+
prefixText: value,
|
|
243
|
+
suffixGraphemeCount: 0,
|
|
244
|
+
suffixText: ""
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function useMiddleTruncate(value) {
|
|
248
|
+
const graphemes = reactExports.useMemo(() => toGraphemes(value), [value]);
|
|
249
|
+
const fullState = reactExports.useMemo(() => createFullState(value, graphemes), [graphemes, value]);
|
|
250
|
+
const ref = reactExports.useRef(null);
|
|
251
|
+
const measureRef = reactExports.useRef(null);
|
|
252
|
+
const [state, setState] = reactExports.useState(() => fullState);
|
|
253
|
+
const rafRef = reactExports.useRef(0);
|
|
254
|
+
const updateState = reactExports.useCallback((nextState) => {
|
|
255
|
+
setState((currentState) => {
|
|
256
|
+
if (currentState.displayText === nextState.displayText && currentState.isTruncated === nextState.isTruncated && currentState.prefixText === nextState.prefixText && currentState.prefixGraphemeCount === nextState.prefixGraphemeCount && currentState.suffixText === nextState.suffixText && currentState.suffixGraphemeCount === nextState.suffixGraphemeCount) {
|
|
257
|
+
return currentState;
|
|
258
|
+
}
|
|
259
|
+
return nextState;
|
|
260
|
+
});
|
|
261
|
+
}, []);
|
|
262
|
+
const recalculate = reactExports.useCallback(() => {
|
|
263
|
+
const el = ref.current;
|
|
264
|
+
const measureEl = measureRef.current;
|
|
265
|
+
if (!el || !measureEl)
|
|
266
|
+
return;
|
|
267
|
+
const available = el.clientWidth;
|
|
268
|
+
if (available <= 0) {
|
|
269
|
+
updateState(fullState);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const measure = (text) => {
|
|
273
|
+
measureEl.textContent = text;
|
|
274
|
+
return measureEl.scrollWidth;
|
|
275
|
+
};
|
|
276
|
+
const fullWidth = measure(value);
|
|
277
|
+
if (fullWidth <= available) {
|
|
278
|
+
updateState(fullState);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const result = middleTruncate(graphemes, available, measure, fullWidth);
|
|
282
|
+
updateState({
|
|
283
|
+
displayText: result.text,
|
|
284
|
+
isTruncated: result.truncated,
|
|
285
|
+
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
286
|
+
prefixText: result.prefixText,
|
|
287
|
+
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
288
|
+
suffixText: result.suffixText
|
|
289
|
+
});
|
|
290
|
+
}, [fullState, graphemes, updateState, value]);
|
|
291
|
+
useIsomorphicLayoutEffect(() => {
|
|
292
|
+
recalculate();
|
|
293
|
+
}, [recalculate]);
|
|
294
|
+
reactExports.useEffect(() => {
|
|
295
|
+
var _a;
|
|
296
|
+
const el = ref.current;
|
|
297
|
+
if (!el)
|
|
298
|
+
return;
|
|
299
|
+
const debouncedRecalc = () => {
|
|
300
|
+
cancelAnimationFrame(rafRef.current);
|
|
301
|
+
rafRef.current = requestAnimationFrame(recalculate);
|
|
302
|
+
};
|
|
303
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(debouncedRecalc) : null;
|
|
304
|
+
ro == null ? void 0 : ro.observe(el);
|
|
305
|
+
window.addEventListener("resize", debouncedRecalc);
|
|
306
|
+
const onFontsLoaded = () => {
|
|
307
|
+
debouncedRecalc();
|
|
308
|
+
};
|
|
309
|
+
const fontSet = "fonts" in document ? document.fonts : null;
|
|
310
|
+
(_a = fontSet == null ? void 0 : fontSet.addEventListener) == null ? void 0 : _a.call(fontSet, "loadingdone", onFontsLoaded);
|
|
311
|
+
return () => {
|
|
312
|
+
var _a2;
|
|
313
|
+
ro == null ? void 0 : ro.disconnect();
|
|
314
|
+
window.removeEventListener("resize", debouncedRecalc);
|
|
315
|
+
cancelAnimationFrame(rafRef.current);
|
|
316
|
+
(_a2 = fontSet == null ? void 0 : fontSet.removeEventListener) == null ? void 0 : _a2.call(fontSet, "loadingdone", onFontsLoaded);
|
|
317
|
+
};
|
|
318
|
+
}, [recalculate]);
|
|
319
|
+
return {
|
|
320
|
+
ref,
|
|
321
|
+
measureRef,
|
|
322
|
+
displayText: state.displayText,
|
|
323
|
+
isTruncated: state.isTruncated,
|
|
324
|
+
prefixGraphemeCount: state.prefixGraphemeCount,
|
|
325
|
+
prefixText: state.prefixText,
|
|
326
|
+
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
327
|
+
suffixText: state.suffixText
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function getRangeOffsets(container, range) {
|
|
331
|
+
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
const startRange = document.createRange();
|
|
335
|
+
startRange.selectNodeContents(container);
|
|
336
|
+
startRange.setEnd(range.startContainer, range.startOffset);
|
|
337
|
+
const endRange = document.createRange();
|
|
338
|
+
endRange.selectNodeContents(container);
|
|
339
|
+
endRange.setEnd(range.endContainer, range.endOffset);
|
|
340
|
+
return {
|
|
341
|
+
end: endRange.toString().length,
|
|
342
|
+
start: startRange.toString().length
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function MiddleTruncate({ value, className, onCopy: onCopyProp, ...props }) {
|
|
346
|
+
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
347
|
+
const visibleRef = reactExports.useRef(null);
|
|
348
|
+
const handleCopy = reactExports.useCallback((e) => {
|
|
349
|
+
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
350
|
+
if (e.defaultPrevented || !isTruncated)
|
|
351
|
+
return;
|
|
352
|
+
const selection = window.getSelection();
|
|
353
|
+
if (!selection || selection.rangeCount === 0)
|
|
354
|
+
return;
|
|
355
|
+
const selectionText = selection.toString();
|
|
356
|
+
if (!selectionText)
|
|
357
|
+
return;
|
|
358
|
+
const range = selection.getRangeAt(0);
|
|
359
|
+
const visibleEl = visibleRef.current;
|
|
360
|
+
let copyText = null;
|
|
361
|
+
if (e.currentTarget.contains(range.startContainer) && e.currentTarget.contains(range.endContainer) && visibleEl) {
|
|
362
|
+
const offsets = getRangeOffsets(visibleEl, range);
|
|
363
|
+
if (offsets) {
|
|
364
|
+
copyText = getMiddleTruncateCopyText({
|
|
365
|
+
prefixText,
|
|
366
|
+
selectionEnd: offsets.end,
|
|
367
|
+
selectionStart: offsets.start,
|
|
368
|
+
suffixText,
|
|
369
|
+
value
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
copyText ?? (copyText = getMiddleTruncateCopyTextFromSelectionText({
|
|
374
|
+
prefixText,
|
|
375
|
+
selectionText,
|
|
376
|
+
suffixText,
|
|
377
|
+
value
|
|
378
|
+
}));
|
|
379
|
+
if (copyText === null)
|
|
380
|
+
return;
|
|
381
|
+
e.preventDefault();
|
|
382
|
+
e.clipboardData.setData("text/plain", copyText);
|
|
383
|
+
}, [onCopyProp, isTruncated, prefixText, suffixText, value]);
|
|
384
|
+
return jsxRuntimeExports.jsxs("span", { title: isTruncated ? value : void 0, ...props, ref, className: cn("relative inline-grid min-w-0 max-w-full overflow-hidden whitespace-nowrap", className), onCopy: handleCopy, children: [isTruncated && jsxRuntimeExports.jsx("span", { className: "sr-only select-none", children: value }), jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: "pointer-events-none col-start-1 row-start-1 invisible select-none whitespace-nowrap", children: value }), jsxRuntimeExports.jsx("span", { "aria-hidden": isTruncated || void 0, className: "col-start-1 row-start-1 min-w-0 overflow-hidden", ref: visibleRef, children: isTruncated ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("span", { children: prefixText }), jsxRuntimeExports.jsx("span", { children: ELLIPSIS }), jsxRuntimeExports.jsx("span", { children: suffixText })] }) : displayText }), jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute left-0 top-0 inline-block invisible select-none whitespace-nowrap", ref: measureRef })] });
|
|
385
|
+
}
|
|
386
|
+
function isReservedAttributeKey(key) {
|
|
387
|
+
return key.startsWith(RESERVED_ATTRIBUTE_KEY_PREFIX);
|
|
388
|
+
}
|
|
389
|
+
const rowValueVariants = cva("min-w-0 flex-1 truncate text-right text-copy-13 text-gray-1000", {
|
|
390
|
+
variants: {
|
|
391
|
+
variant: {
|
|
392
|
+
default: "",
|
|
393
|
+
mono: "font-mono"
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
defaultVariants: {
|
|
397
|
+
variant: "default"
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
const rowCopyValueVariants = cva("flex min-w-0 flex-1 items-center justify-end gap-1 overflow-hidden text-copy-13 text-gray-1000", {
|
|
401
|
+
variants: {
|
|
402
|
+
variant: {
|
|
403
|
+
default: "",
|
|
404
|
+
mono: "font-mono"
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
defaultVariants: {
|
|
408
|
+
variant: "default"
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
function DetailKeyValueRowBase({ label, value, copyText, href, removed = false, variant }) {
|
|
412
|
+
const stringValue = typeof value === "string" ? value : void 0;
|
|
413
|
+
return jsxRuntimeExports.jsxs("div", { className: "px-1.5 hover:bg-gray-100 flex justify-between gap-3 -mx-1.5 py-0.5 rounded items-center", children: [jsxRuntimeExports.jsx("span", { className: "flex min-w-0 items-center gap-1.5 truncate text-label-13 text-gray-900", children: label }), removed ? jsxRuntimeExports.jsx("span", { className: "shrink-0 text-copy-13 italic text-gray-700", children: "removed" }) : copyText ? jsxRuntimeExports.jsxs("div", { className: cn(rowCopyValueVariants({ variant })), title: copyText, children: [href ? jsxRuntimeExports.jsxs("a", { href, target: "_blank", rel: "noreferrer", className: cn(rowValueVariants({ variant }), "flex min-w-0 items-center gap-0.5 hover:underline"), children: [jsxRuntimeExports.jsx(MiddleTruncate, { value: copyText, className: "min-w-0 text-right", style: { gridTemplateColumns: "minmax(0, 1fr)" } }), jsxRuntimeExports.jsx(ArrowUpRight, { "aria-hidden": true, className: "h-3 w-3 shrink-0" })] }) : jsxRuntimeExports.jsx(MiddleTruncate, { value: copyText, className: cn(rowValueVariants({ variant, className: "text-right" })), style: { gridTemplateColumns: "minmax(0, 1fr)" } }), jsxRuntimeExports.jsx(CopyButton, { copyText, ariaLabel: `Copy ${label}`, className: "shrink-0 -mr-1" })] }) : jsxRuntimeExports.jsx("span", { className: cn(rowValueVariants({ variant })), title: stringValue, children: href ? jsxRuntimeExports.jsx("a", { href, target: "_blank", rel: "noreferrer", className: "hover:underline", children: value }) : value })] });
|
|
414
|
+
}
|
|
415
|
+
function DetailKeyValueRow(props) {
|
|
416
|
+
return jsxRuntimeExports.jsx(DetailKeyValueRowBase, { ...props });
|
|
417
|
+
}
|
|
418
|
+
function DetailMonoKeyValueRow(props) {
|
|
419
|
+
return jsxRuntimeExports.jsx(DetailKeyValueRowBase, { ...props, variant: "mono" });
|
|
420
|
+
}
|
|
421
|
+
function AttributeRow({ attributeKey, value, removed = false }) {
|
|
422
|
+
return jsxRuntimeExports.jsx(DetailKeyValueRow, { label: attributeKey, value, removed });
|
|
423
|
+
}
|
|
424
|
+
function sortAttributeKeys(keys) {
|
|
425
|
+
return [...keys].sort((a, b) => {
|
|
426
|
+
const aReserved = isReservedAttributeKey(a);
|
|
427
|
+
const bReserved = isReservedAttributeKey(b);
|
|
428
|
+
if (aReserved !== bReserved)
|
|
429
|
+
return aReserved ? 1 : -1;
|
|
430
|
+
return a.localeCompare(b);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function RunAttributesCard({ attributes }) {
|
|
434
|
+
const keys = sortAttributeKeys(Object.keys(attributes));
|
|
435
|
+
if (keys.length === 0)
|
|
436
|
+
return null;
|
|
437
|
+
return jsxRuntimeExports.jsxs(CollapsibleRoot, { defaultOpen: true, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { children: "Attributes" }), jsxRuntimeExports.jsx(CollapsibleContent, { className: "mb-4", children: jsxRuntimeExports.jsx("div", { className: "flex flex-col", children: keys.map((key) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: key, value: attributes[key] }, key)) }) })] });
|
|
438
|
+
}
|
|
439
|
+
function formatMetadataValue(value) {
|
|
440
|
+
if (value == null) {
|
|
441
|
+
return String(value);
|
|
442
|
+
}
|
|
443
|
+
if (typeof value === "string") {
|
|
444
|
+
return value;
|
|
445
|
+
}
|
|
446
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
447
|
+
return String(value);
|
|
448
|
+
}
|
|
449
|
+
try {
|
|
450
|
+
return JSON.stringify(value);
|
|
451
|
+
} catch {
|
|
452
|
+
return String(value);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function isMetadataRecord(value) {
|
|
456
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
457
|
+
}
|
|
458
|
+
function RunMetadataCard({ metadata }) {
|
|
459
|
+
if (!isMetadataRecord(metadata)) {
|
|
460
|
+
return jsxRuntimeExports.jsxs(CollapsibleRoot, { defaultOpen: true, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { children: "Metadata" }), jsxRuntimeExports.jsx(CollapsibleContent, { className: "mb-4", children: jsxRuntimeExports.jsx(CopyableDataBlock, { data: metadata }) })] });
|
|
461
|
+
}
|
|
462
|
+
const keys = Object.keys(metadata).sort((a, b) => a.localeCompare(b));
|
|
463
|
+
if (keys.length === 0)
|
|
464
|
+
return null;
|
|
465
|
+
return jsxRuntimeExports.jsxs(CollapsibleRoot, { defaultOpen: true, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { children: "Metadata" }), jsxRuntimeExports.jsx(CollapsibleContent, { className: "mb-4", children: jsxRuntimeExports.jsx("div", { className: "flex flex-col", children: keys.map((key) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: key, value: formatMetadataValue(metadata[key]) }, key)) }) })] });
|
|
466
|
+
}
|
|
467
|
+
function isAttrSetEventData(data) {
|
|
468
|
+
if (data === null || typeof data !== "object")
|
|
469
|
+
return false;
|
|
470
|
+
const record = data;
|
|
471
|
+
return Array.isArray(record.changes) && record.changes.every((c) => c !== null && typeof c === "object" && typeof c.key === "string");
|
|
472
|
+
}
|
|
473
|
+
function describeWriter(writer) {
|
|
474
|
+
if (!writer)
|
|
475
|
+
return null;
|
|
476
|
+
if (writer.type === "workflow")
|
|
477
|
+
return "Set by workflow";
|
|
478
|
+
if (writer.type === "step") {
|
|
479
|
+
return `Set by step ${writer.stepId} (attempt ${writer.attempt})`;
|
|
480
|
+
}
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
function AttrSetEventBlock({ data }) {
|
|
484
|
+
if (!isAttrSetEventData(data)) {
|
|
485
|
+
return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
|
|
486
|
+
}
|
|
487
|
+
const writerLabel = describeWriter(data.writer);
|
|
488
|
+
return jsxRuntimeExports.jsxs("div", { className: "flex flex-col px-3 py-1", children: [jsxRuntimeExports.jsx("div", { className: "flex flex-col", children: data.changes.map((change, index) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: change.key, removed: change.value === null, value: change.value ?? void 0 }, `${change.key}:${index}`)) }), writerLabel && jsxRuntimeExports.jsx("div", { className: "border-t py-1.5 text-label-12", style: {
|
|
489
|
+
borderColor: "var(--ds-gray-alpha-400)",
|
|
490
|
+
color: "var(--ds-gray-700)"
|
|
491
|
+
}, children: writerLabel })] });
|
|
492
|
+
}
|
|
79
493
|
const STYLES$2 = `.wf-decrypt-btn{appearance:none;-webkit-appearance:none;border:none;display:inline-flex;align-items:center;justify-content:center;height:40px;padding:0 12px;border-radius:6px;font-size:14px;font-weight:500;line-height:20px;cursor:pointer;white-space:nowrap;gap:6px;transition:background 150ms}.wf-decrypt-idle{color:var(--ds-gray-1000);background:var(--ds-background-100);box-shadow:0 0 0 1px var(--ds-gray-400)}.wf-decrypt-idle:hover{background:var(--ds-gray-alpha-200)}.wf-decrypt-done{color:var(--ds-green-900);background:var(--ds-green-100);box-shadow:0 0 0 1px var(--ds-green-400);cursor:default}`;
|
|
80
494
|
function DecryptButton({ decrypted = false, loading = false, onClick }) {
|
|
81
495
|
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { dangerouslySetInnerHTML: { __html: STYLES$2 } }), jsxRuntimeExports.jsxs("button", { type: "button", onClick: decrypted ? void 0 : onClick, disabled: decrypted || loading, className: `wf-decrypt-btn ${decrypted ? "wf-decrypt-done" : "wf-decrypt-idle"}`, children: [loading ? jsxRuntimeExports.jsx(Spinner, { size: 14 }) : decrypted ? jsxRuntimeExports.jsxs("svg", { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), jsxRuntimeExports.jsx("path", { d: "M7 11V7a5 5 0 0 1 9.9-1" })] }) : jsxRuntimeExports.jsxs("svg", { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), jsxRuntimeExports.jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] }), loading ? "Decrypting…" : decrypted ? "Decrypted" : "Decrypt"] })] });
|
|
82
496
|
}
|
|
83
|
-
function
|
|
84
|
-
return value != null && typeof value === "object" && "
|
|
497
|
+
function isStructuredError(value) {
|
|
498
|
+
return value != null && typeof value === "object" && (typeof value.message === "string" || typeof value.stack === "string");
|
|
499
|
+
}
|
|
500
|
+
function deriveTitle(message) {
|
|
501
|
+
const firstLine = message.split("\n").find((line) => line.trim().length > 0) ?? message;
|
|
502
|
+
return firstLine.trim();
|
|
85
503
|
}
|
|
86
504
|
function ErrorStackBlock({ value }) {
|
|
87
|
-
const
|
|
88
|
-
const stack = value.stack;
|
|
505
|
+
const stack = typeof value.stack === "string" ? value.stack : void 0;
|
|
89
506
|
const message = typeof value.message === "string" ? value.message : void 0;
|
|
90
|
-
const
|
|
507
|
+
const body = stack ?? message ?? "";
|
|
508
|
+
const title = message ? deriveTitle(message) : deriveTitle(body);
|
|
509
|
+
const copyText = message && stack && !stack.includes(message) ? `${message}
|
|
91
510
|
|
|
92
|
-
${stack}` :
|
|
511
|
+
${stack}` : body;
|
|
93
512
|
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-hidden rounded-md border", style: {
|
|
94
513
|
borderColor: "var(--ds-red-400)",
|
|
95
514
|
background: "var(--ds-red-100)"
|
|
96
|
-
}, children: [jsxRuntimeExports.jsx(
|
|
97
|
-
borderColor: "var(--ds-red-400)",
|
|
98
|
-
background: "var(--ds-red-100)",
|
|
99
|
-
color: "var(--ds-red-900)"
|
|
100
|
-
}, onClick: () => {
|
|
101
|
-
navigator.clipboard.writeText(copyText).then(() => {
|
|
102
|
-
toast2.success("Copied to clipboard");
|
|
103
|
-
}).catch(() => {
|
|
104
|
-
toast2.error("Failed to copy");
|
|
105
|
-
});
|
|
106
|
-
}, children: jsxRuntimeExports.jsx(Copy, { size: 12 }) }), message && jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 px-3 py-2.5 pr-10", style: {
|
|
515
|
+
}, children: [jsxRuntimeExports.jsx(CopyButton, { copyText, ariaLabel: "Copy error", className: "absolute right-2 top-2 flex h-6 w-6 items-center justify-center rounded-md border border-red-400 bg-red-100 p-0 text-red-900 transition-transform transition-colors duration-100 hover:bg-red-200 active:scale-95" }), title && jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 pr-10", style: {
|
|
107
516
|
color: "var(--ds-red-900)",
|
|
108
517
|
borderBottom: "1px solid var(--ds-red-400)"
|
|
109
|
-
}, children: [jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 shrink-0"
|
|
518
|
+
}, children: [jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 shrink-0" }), jsxRuntimeExports.jsx("p", {
|
|
519
|
+
className: "text-label-12 font-semibold m-0 truncate",
|
|
520
|
+
// The full message or stack is in the body below; the header just
|
|
521
|
+
// shows the first line, single-line, with overflow
|
|
522
|
+
// ellipsised so a long title doesn't push the copy button or
|
|
523
|
+
// wrap into the framed hint/docs lines.
|
|
524
|
+
title: message,
|
|
525
|
+
children: title
|
|
526
|
+
})] }), body && jsxRuntimeExports.jsx("pre", { className: "px-3 py-2.5 text-label-12-mono whitespace-pre-wrap break-words overflow-auto m-0", style: {
|
|
110
527
|
color: "var(--ds-red-900)",
|
|
111
528
|
background: "var(--ds-red-200)"
|
|
112
|
-
}, children:
|
|
529
|
+
}, children: body })] });
|
|
113
530
|
}
|
|
114
531
|
const STYLES$1 = `.wf-load-more{appearance:none;-webkit-appearance:none;border:none;display:inline-flex;align-items:center;justify-content:center;height:32px;padding:0 12px;border-radius:6px;font-size:13px;font-weight:500;line-height:20px;color:var(--ds-gray-1000);background:var(--ds-background-100);box-shadow:0 0 0 1px var(--ds-gray-400);cursor:pointer;white-space:nowrap;gap:6px;transition:background 150ms}.wf-load-more:hover{background:var(--ds-gray-alpha-200)}.wf-load-more:disabled{opacity:.6;cursor:default}.wf-load-more:disabled:hover{background:var(--ds-background-100)}`;
|
|
115
532
|
function LoadMoreButton({ loading = false, onClick, label = "Load more", loadingLabel = "Loading..." }) {
|
|
@@ -154,190 +571,7 @@ function MenuDropdown({ options, value, onChange }) {
|
|
|
154
571
|
setOpen(false);
|
|
155
572
|
}, children: option.label }, option.value)) })] });
|
|
156
573
|
}
|
|
157
|
-
const
|
|
158
|
-
{ unit: "year", ms: 31536e6 },
|
|
159
|
-
{ unit: "month", ms: 2628e6 },
|
|
160
|
-
{ unit: "day", ms: 864e5 },
|
|
161
|
-
{ unit: "hour", ms: 36e5 },
|
|
162
|
-
{ unit: "minute", ms: 6e4 },
|
|
163
|
-
{ unit: "second", ms: 1e3 }
|
|
164
|
-
];
|
|
165
|
-
function formatTimeDifference(diff) {
|
|
166
|
-
let remaining = Math.abs(diff);
|
|
167
|
-
const result = [];
|
|
168
|
-
for (const { unit, ms } of TIME_UNITS) {
|
|
169
|
-
const value = Math.floor(remaining / ms);
|
|
170
|
-
if (value > 0 || result.length > 0) {
|
|
171
|
-
result.push(`${value} ${unit}${value !== 1 ? "s" : ""}`);
|
|
172
|
-
remaining %= ms;
|
|
173
|
-
}
|
|
174
|
-
if (result.length === 3)
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
return result.join(", ");
|
|
178
|
-
}
|
|
179
|
-
function useTimeAgo(date) {
|
|
180
|
-
const [timeAgo, setTimeAgo] = reactExports.useState("");
|
|
181
|
-
reactExports.useEffect(() => {
|
|
182
|
-
const update = () => {
|
|
183
|
-
const diff = Date.now() - date;
|
|
184
|
-
const formatted = formatTimeDifference(diff);
|
|
185
|
-
setTimeAgo(formatted ? `${formatted} ago` : "Just now");
|
|
186
|
-
};
|
|
187
|
-
update();
|
|
188
|
-
const timer = setInterval(update, 1e3);
|
|
189
|
-
return () => clearInterval(timer);
|
|
190
|
-
}, [date]);
|
|
191
|
-
return timeAgo;
|
|
192
|
-
}
|
|
193
|
-
function ZoneDateTimeRow({ date, zone }) {
|
|
194
|
-
var _a;
|
|
195
|
-
const dateObj = new Date(date);
|
|
196
|
-
const formattedZone = ((_a = new Intl.DateTimeFormat("en-US", {
|
|
197
|
-
timeZone: zone,
|
|
198
|
-
timeZoneName: "short"
|
|
199
|
-
}).formatToParts(dateObj).find((part) => part.type === "timeZoneName")) == null ? void 0 : _a.value) || zone;
|
|
200
|
-
const formattedDate = dateObj.toLocaleString("en-US", {
|
|
201
|
-
timeZone: zone,
|
|
202
|
-
year: "numeric",
|
|
203
|
-
month: "long",
|
|
204
|
-
day: "numeric"
|
|
205
|
-
});
|
|
206
|
-
const formattedTime = dateObj.toLocaleTimeString("en-US", {
|
|
207
|
-
timeZone: zone,
|
|
208
|
-
hour: "2-digit",
|
|
209
|
-
minute: "2-digit",
|
|
210
|
-
second: "2-digit"
|
|
211
|
-
});
|
|
212
|
-
return jsxRuntimeExports.jsxs("div", { style: {
|
|
213
|
-
display: "flex",
|
|
214
|
-
alignItems: "center",
|
|
215
|
-
justifyContent: "space-between",
|
|
216
|
-
gap: 12
|
|
217
|
-
}, children: [jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [jsxRuntimeExports.jsx("div", { style: {
|
|
218
|
-
display: "inline-flex",
|
|
219
|
-
alignItems: "center",
|
|
220
|
-
justifyContent: "center",
|
|
221
|
-
height: 16,
|
|
222
|
-
padding: "0 6px",
|
|
223
|
-
backgroundColor: "var(--ds-gray-200)",
|
|
224
|
-
borderRadius: 3,
|
|
225
|
-
fontSize: 11,
|
|
226
|
-
fontFamily: "var(--font-mono, monospace)",
|
|
227
|
-
fontWeight: 500,
|
|
228
|
-
color: "var(--ds-gray-900)",
|
|
229
|
-
whiteSpace: "nowrap"
|
|
230
|
-
}, children: formattedZone }), jsxRuntimeExports.jsx("span", { style: {
|
|
231
|
-
fontSize: 13,
|
|
232
|
-
color: "var(--ds-gray-1000)",
|
|
233
|
-
whiteSpace: "nowrap"
|
|
234
|
-
}, children: formattedDate })] }), jsxRuntimeExports.jsx("span", { style: {
|
|
235
|
-
fontSize: 11,
|
|
236
|
-
fontFamily: "var(--font-mono, monospace)",
|
|
237
|
-
fontVariantNumeric: "tabular-nums",
|
|
238
|
-
color: "var(--ds-gray-900)",
|
|
239
|
-
whiteSpace: "nowrap"
|
|
240
|
-
}, children: formattedTime })] });
|
|
241
|
-
}
|
|
242
|
-
function TimestampTooltipContent({ date }) {
|
|
243
|
-
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
244
|
-
const timeAgo = useTimeAgo(date);
|
|
245
|
-
return jsxRuntimeExports.jsxs("div", { style: {
|
|
246
|
-
display: "flex",
|
|
247
|
-
flexDirection: "column",
|
|
248
|
-
gap: 12,
|
|
249
|
-
minWidth: 300,
|
|
250
|
-
padding: "12px 14px"
|
|
251
|
-
}, children: [jsxRuntimeExports.jsx("span", { style: {
|
|
252
|
-
fontSize: 13,
|
|
253
|
-
fontVariantNumeric: "tabular-nums",
|
|
254
|
-
color: "var(--ds-gray-900)"
|
|
255
|
-
}, children: timeAgo }), jsxRuntimeExports.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [jsxRuntimeExports.jsx(ZoneDateTimeRow, { date, zone: "UTC" }), jsxRuntimeExports.jsx(ZoneDateTimeRow, { date, zone: localTimezone })] })] });
|
|
256
|
-
}
|
|
257
|
-
const TOOLTIP_WIDTH = 330;
|
|
258
|
-
const VIEWPORT_PAD = 8;
|
|
259
|
-
function TooltipPortal({ triggerRect, onMouseEnter, onMouseLeave, date }) {
|
|
260
|
-
const tooltipRef = reactExports.useRef(null);
|
|
261
|
-
const [style, setStyle] = reactExports.useState({
|
|
262
|
-
position: "fixed",
|
|
263
|
-
zIndex: 9999,
|
|
264
|
-
visibility: "hidden"
|
|
265
|
-
});
|
|
266
|
-
reactExports.useEffect(() => {
|
|
267
|
-
const placement = triggerRect.top > 240 ? "above" : "below";
|
|
268
|
-
const centerX = triggerRect.left + triggerRect.width / 2;
|
|
269
|
-
const el = tooltipRef.current;
|
|
270
|
-
const w = el ? el.offsetWidth : TOOLTIP_WIDTH;
|
|
271
|
-
const h = el ? el.offsetHeight : 100;
|
|
272
|
-
let left = centerX - w / 2;
|
|
273
|
-
left = Math.max(VIEWPORT_PAD, Math.min(left, window.innerWidth - w - VIEWPORT_PAD));
|
|
274
|
-
let top;
|
|
275
|
-
if (placement === "above") {
|
|
276
|
-
top = triggerRect.top - h - 6;
|
|
277
|
-
if (top < VIEWPORT_PAD) {
|
|
278
|
-
top = triggerRect.bottom + 6;
|
|
279
|
-
}
|
|
280
|
-
} else {
|
|
281
|
-
top = triggerRect.bottom + 6;
|
|
282
|
-
if (top + h > window.innerHeight - VIEWPORT_PAD) {
|
|
283
|
-
top = triggerRect.top - h - 6;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
setStyle({
|
|
287
|
-
position: "fixed",
|
|
288
|
-
left,
|
|
289
|
-
top,
|
|
290
|
-
zIndex: 9999,
|
|
291
|
-
borderRadius: 10,
|
|
292
|
-
border: "1px solid var(--ds-gray-alpha-200)",
|
|
293
|
-
backgroundColor: "var(--ds-background-100)",
|
|
294
|
-
boxShadow: "0 4px 12px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.06)",
|
|
295
|
-
visibility: "visible"
|
|
296
|
-
});
|
|
297
|
-
}, [triggerRect]);
|
|
298
|
-
return reactDomExports.createPortal(
|
|
299
|
-
// biome-ignore lint/a11y/noStaticElementInteractions: tooltip hover zone
|
|
300
|
-
jsxRuntimeExports.jsx("div", { ref: tooltipRef, onMouseEnter, onMouseLeave, style, children: jsxRuntimeExports.jsx(TimestampTooltipContent, { date }) }),
|
|
301
|
-
document.body
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
function TimestampTooltip({ date, children }) {
|
|
305
|
-
const [open, setOpen] = reactExports.useState(false);
|
|
306
|
-
const [triggerRect, setTriggerRect] = reactExports.useState(null);
|
|
307
|
-
const triggerRef = reactExports.useRef(null);
|
|
308
|
-
const closeTimer = reactExports.useRef(null);
|
|
309
|
-
reactExports.useEffect(() => {
|
|
310
|
-
return () => {
|
|
311
|
-
if (closeTimer.current)
|
|
312
|
-
clearTimeout(closeTimer.current);
|
|
313
|
-
};
|
|
314
|
-
}, []);
|
|
315
|
-
const ts = date == null ? null : typeof date === "number" ? date : new Date(date).getTime();
|
|
316
|
-
if (ts == null || Number.isNaN(ts))
|
|
317
|
-
return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children });
|
|
318
|
-
const cancelClose = () => {
|
|
319
|
-
if (closeTimer.current) {
|
|
320
|
-
clearTimeout(closeTimer.current);
|
|
321
|
-
closeTimer.current = null;
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
const scheduleClose = () => {
|
|
325
|
-
cancelClose();
|
|
326
|
-
closeTimer.current = setTimeout(() => setOpen(false), 120);
|
|
327
|
-
};
|
|
328
|
-
const handleOpen = () => {
|
|
329
|
-
cancelClose();
|
|
330
|
-
if (triggerRef.current) {
|
|
331
|
-
setTriggerRect(triggerRef.current.getBoundingClientRect());
|
|
332
|
-
}
|
|
333
|
-
setOpen(true);
|
|
334
|
-
};
|
|
335
|
-
return (
|
|
336
|
-
// biome-ignore lint/a11y/noStaticElementInteractions: tooltip trigger
|
|
337
|
-
jsxRuntimeExports.jsxs("span", { ref: triggerRef, onMouseEnter: handleOpen, onMouseLeave: scheduleClose, style: { display: "inline-flex" }, children: [children, open && triggerRect && jsxRuntimeExports.jsx(TooltipPortal, { triggerRect, onMouseEnter: cancelClose, onMouseLeave: scheduleClose, date: ts })] })
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
const ERROR_EVENT_TYPES$1 = /* @__PURE__ */ new Set([
|
|
574
|
+
const ERROR_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
341
575
|
"step_failed",
|
|
342
576
|
"step_retrying",
|
|
343
577
|
"run_failed",
|
|
@@ -358,6 +592,18 @@ function formatEventTime(date) {
|
|
|
358
592
|
hour12: false
|
|
359
593
|
}) + "." + date.getMilliseconds().toString().padStart(3, "0");
|
|
360
594
|
}
|
|
595
|
+
function parseEventDate(value) {
|
|
596
|
+
if (value == null)
|
|
597
|
+
return null;
|
|
598
|
+
const date = value instanceof Date ? value : new Date(String(value));
|
|
599
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
600
|
+
}
|
|
601
|
+
function getEffectiveEventDate$1(event) {
|
|
602
|
+
return parseEventDate(event.occurredAt) ?? new Date(event.createdAt);
|
|
603
|
+
}
|
|
604
|
+
function getEffectiveEventTime(event) {
|
|
605
|
+
return getEffectiveEventDate$1(event).getTime();
|
|
606
|
+
}
|
|
361
607
|
function formatEventType(eventType) {
|
|
362
608
|
return eventType.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
363
609
|
}
|
|
@@ -371,6 +617,9 @@ function getStatusDotColor(eventType) {
|
|
|
371
617
|
if (eventType === "step_retrying") {
|
|
372
618
|
return "var(--ds-amber-700)";
|
|
373
619
|
}
|
|
620
|
+
if (eventType === "attr_set") {
|
|
621
|
+
return "var(--ds-teal-900)";
|
|
622
|
+
}
|
|
374
623
|
if (eventType === "step_completed" || eventType === "run_completed" || eventType === "workflow_completed" || eventType === "hook_disposed" || eventType === "wait_completed") {
|
|
375
624
|
return "var(--ds-green-700)";
|
|
376
625
|
}
|
|
@@ -395,27 +644,34 @@ function buildNameMaps(events, run) {
|
|
|
395
644
|
return { correlationNameMap, workflowName };
|
|
396
645
|
}
|
|
397
646
|
function buildDurationMap(events) {
|
|
647
|
+
const chronological = [...events].sort((a, b) => getEffectiveEventTime(a) - getEffectiveEventTime(b));
|
|
398
648
|
const createdTimes = /* @__PURE__ */ new Map();
|
|
649
|
+
const firstStartedTimes = /* @__PURE__ */ new Map();
|
|
399
650
|
const startedTimes = /* @__PURE__ */ new Map();
|
|
400
651
|
const durations = /* @__PURE__ */ new Map();
|
|
401
|
-
for (const event of
|
|
402
|
-
const ts =
|
|
652
|
+
for (const event of chronological) {
|
|
653
|
+
const ts = getEffectiveEventTime(event);
|
|
403
654
|
const key = event.correlationId ?? "__run__";
|
|
404
655
|
const type = event.eventType;
|
|
405
656
|
if (type === "step_created" || type === "run_created") {
|
|
406
|
-
createdTimes.set(key, ts);
|
|
407
|
-
}
|
|
408
|
-
if (type === "step_started" || type === "run_started" || type === "workflow_started") {
|
|
409
|
-
startedTimes.set(key, ts);
|
|
410
657
|
if (!createdTimes.has(key)) {
|
|
411
658
|
createdTimes.set(key, ts);
|
|
412
659
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
660
|
+
}
|
|
661
|
+
if (type === "step_started" || type === "run_started" || type === "workflow_started") {
|
|
662
|
+
startedTimes.set(key, ts);
|
|
663
|
+
if (!firstStartedTimes.has(key)) {
|
|
664
|
+
firstStartedTimes.set(key, ts);
|
|
665
|
+
if (!createdTimes.has(key)) {
|
|
666
|
+
createdTimes.set(key, ts);
|
|
667
|
+
}
|
|
668
|
+
const createdAt = createdTimes.get(key);
|
|
669
|
+
const info = durations.get(key) ?? {};
|
|
670
|
+
if (createdAt !== void 0) {
|
|
671
|
+
info.queued = ts - createdAt;
|
|
672
|
+
}
|
|
673
|
+
durations.set(key, info);
|
|
417
674
|
}
|
|
418
|
-
durations.set(key, info);
|
|
419
675
|
}
|
|
420
676
|
if (type === "step_completed" || type === "step_failed" || type === "run_completed" || type === "run_failed" || type === "run_cancelled" || type === "workflow_completed" || type === "workflow_failed" || type === "wait_completed" || type === "hook_disposed") {
|
|
421
677
|
const startedAt = startedTimes.get(key);
|
|
@@ -438,7 +694,9 @@ function hasEncryptedValues(data) {
|
|
|
438
694
|
return false;
|
|
439
695
|
}
|
|
440
696
|
function isRunLevel(eventType) {
|
|
441
|
-
return eventType === "run_created" || eventType === "run_started" || eventType === "run_completed" || eventType === "run_failed" || eventType === "run_cancelled" || eventType === "workflow_started" || eventType === "workflow_completed" || eventType === "workflow_failed"
|
|
697
|
+
return eventType === "run_created" || eventType === "run_started" || eventType === "run_completed" || eventType === "run_failed" || eventType === "run_cancelled" || eventType === "workflow_started" || eventType === "workflow_completed" || eventType === "workflow_failed" || // attr_set carries a dedup correlationId rather than a child entity ID,
|
|
698
|
+
// so it groups and labels with the run itself.
|
|
699
|
+
eventType === "attr_set";
|
|
442
700
|
}
|
|
443
701
|
const GUTTER_WIDTH = 36;
|
|
444
702
|
const LANE_X = 20;
|
|
@@ -560,14 +818,14 @@ function deepParseJson(value) {
|
|
|
560
818
|
return value;
|
|
561
819
|
}
|
|
562
820
|
function extractStructuredError(data, eventType) {
|
|
563
|
-
if (!eventType || !ERROR_EVENT_TYPES
|
|
821
|
+
if (!eventType || !ERROR_EVENT_TYPES.has(eventType))
|
|
564
822
|
return null;
|
|
565
823
|
if (data == null || typeof data !== "object")
|
|
566
824
|
return null;
|
|
567
825
|
const record = data;
|
|
568
|
-
if (
|
|
826
|
+
if (isStructuredError(record.error))
|
|
569
827
|
return record.error;
|
|
570
|
-
if (
|
|
828
|
+
if (isStructuredError(record))
|
|
571
829
|
return record;
|
|
572
830
|
return null;
|
|
573
831
|
}
|
|
@@ -606,13 +864,22 @@ function PayloadBlock({ data, eventType }) {
|
|
|
606
864
|
if (structuredError) {
|
|
607
865
|
return jsxRuntimeExports.jsx("div", { className: "p-2", children: jsxRuntimeExports.jsx(ErrorStackBlock, { value: structuredError }) });
|
|
608
866
|
}
|
|
609
|
-
|
|
867
|
+
if (eventType === "attr_set") {
|
|
868
|
+
return jsxRuntimeExports.jsx(AttrSetEventBlock, { data: cleaned });
|
|
869
|
+
}
|
|
870
|
+
if (eventType === "run_cancelled") {
|
|
871
|
+
const cancelReason = cleaned != null && typeof cleaned === "object" && typeof cleaned.cancelReason === "string" ? cleaned.cancelReason : null;
|
|
872
|
+
if (cancelReason) {
|
|
873
|
+
return jsxRuntimeExports.jsxs("div", { className: "p-2 text-label-12", style: { color: "var(--ds-gray-1000)" }, children: [jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-gray-900)" }, children: "Reason: " }), jsxRuntimeExports.jsx("span", { className: "whitespace-pre-wrap break-words", children: cancelReason })] });
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return jsxRuntimeExports.jsxs("div", { className: "relative group/payload", children: [jsxRuntimeExports.jsx("div", { className: "overflow-x-auto p-2 text-[11px]", style: { color: "var(--ds-gray-1000)" }, children: jsxRuntimeExports.jsx(DataInspector, { data: cleaned, expandLevel: 2 }) }), jsxRuntimeExports.jsx("button", { type: "button", onClick: handleCopy, className: "absolute bottom-2 right-2 opacity-0 group-hover/payload:opacity-100 transition-opacity flex items-center gap-1 px-2 py-1 rounded-md text-button-12 hover:bg-[var(--ds-gray-alpha-200)]", style: { ...BUTTON_RESET_STYLE, color: "var(--ds-gray-700)" }, "aria-label": "Copy payload", children: copied ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Check, { className: "h-3 w-3", style: { color: "var(--ds-green-700)" } }), jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-green-700)" }, children: "Copied" })] }) : jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Copy, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { children: "Copy" })] }) })] });
|
|
610
877
|
}
|
|
611
878
|
const SORT_OPTIONS = [
|
|
612
879
|
{ value: "desc", label: "Newest" },
|
|
613
880
|
{ value: "asc", label: "Oldest" }
|
|
614
881
|
];
|
|
615
|
-
function RowsSkeleton() {
|
|
882
|
+
function RowsSkeleton({ showSeparateEventOccurrenceTimestamps = false }) {
|
|
616
883
|
return jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: Array.from({ length: 16 }, (_, i) => jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0", style: { height: 40 }, children: [jsxRuntimeExports.jsxs("div", { className: "relative flex-shrink-0 self-stretch flex items-center", style: { width: GUTTER_WIDTH }, children: [jsxRuntimeExports.jsx("div", { style: {
|
|
617
884
|
position: "absolute",
|
|
618
885
|
left: 8,
|
|
@@ -624,9 +891,9 @@ function RowsSkeleton() {
|
|
|
624
891
|
height: i % 4 === 0 ? 8 : 6,
|
|
625
892
|
borderRadius: "50%",
|
|
626
893
|
marginLeft: i % 4 === 0 ? 5 : 6
|
|
627
|
-
} })] }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0 flex items-center justify-center", children: jsxRuntimeExports.jsx(Skeleton, { className: "w-5 h-5", style: { borderRadius: 4 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "70%" } }) }), jsxRuntimeExports.jsxs("div", { className: "min-w-0 px-4 flex items-center gap-1.5", style: { flex: "2 1 0%" }, children: [jsxRuntimeExports.jsx(Skeleton, { className: "flex-shrink-0", style: { width: 6, height: 6, borderRadius: "50%" } }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "60%" } })] }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "50%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "75%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "75%" } }) })] }, i)) });
|
|
894
|
+
} })] }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0 flex items-center justify-center", children: jsxRuntimeExports.jsx(Skeleton, { className: "w-5 h-5", style: { borderRadius: 4 } }) }), showSeparateEventOccurrenceTimestamps && jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "70%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "70%" } }) }), jsxRuntimeExports.jsxs("div", { className: "min-w-0 px-4 flex items-center gap-1.5", style: { flex: "2 1 0%" }, children: [jsxRuntimeExports.jsx(Skeleton, { className: "flex-shrink-0", style: { width: 6, height: 6, borderRadius: "50%" } }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "60%" } })] }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "50%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "75%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "75%" } }) })] }, i)) });
|
|
628
895
|
}
|
|
629
|
-
function EventRow$1({ event, index, isFirst, isLast, isExpanded, onToggleExpand, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData, onCacheEventData, encryptionKey, onEncryptedDataDetected }) {
|
|
896
|
+
function EventRow$1({ event, index, isFirst, isLast, isExpanded, onToggleExpand, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData, onCacheEventData, encryptionKey, onEncryptedDataDetected, suppressGroupDimming = false, showSeparateEventOccurrenceTimestamps = false }) {
|
|
630
897
|
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
631
898
|
const [loadedEventData, setLoadedEventData] = reactExports.useState(cachedEventData);
|
|
632
899
|
const [loadError, setLoadError] = reactExports.useState(null);
|
|
@@ -639,6 +906,8 @@ function EventRow$1({ event, index, isFirst, isLast, isExpanded, onToggleExpand,
|
|
|
639
906
|
const rowGroupKey = isRunLevel(event.eventType) ? "__run__" : event.correlationId ?? void 0;
|
|
640
907
|
const statusDotColor = getStatusDotColor(event.eventType);
|
|
641
908
|
const createdAt = new Date(event.createdAt);
|
|
909
|
+
const occurredAt = parseEventDate(event.occurredAt);
|
|
910
|
+
const displayedCreatedAt = showSeparateEventOccurrenceTimestamps ? createdAt : getEffectiveEventDate$1(event);
|
|
642
911
|
const hasExistingEventData = "eventData" in event && event.eventData != null;
|
|
643
912
|
const isRun = isRunLevel(event.eventType);
|
|
644
913
|
const eventName = isRun ? workflowName ?? "-" : event.correlationId ? correlationNameMap.get(event.correlationId) ?? "-" : "-";
|
|
@@ -646,7 +915,7 @@ function EventRow$1({ event, index, isFirst, isLast, isExpanded, onToggleExpand,
|
|
|
646
915
|
const durationInfo = durationKey ? durationMap.get(durationKey) : void 0;
|
|
647
916
|
const hasActive = activeGroupKey !== void 0;
|
|
648
917
|
const isRelated = rowGroupKey !== void 0 && rowGroupKey === activeGroupKey;
|
|
649
|
-
const isDimmed = hasActive && !isRelated;
|
|
918
|
+
const isDimmed = hasActive && !isRelated && !suppressGroupDimming;
|
|
650
919
|
const isPulsing = hasActive && isRelated;
|
|
651
920
|
const showBranch = hasActive && isRelated && !isRun;
|
|
652
921
|
const showLaneLine = selectedGroupRange !== null && index >= selectedGroupRange.first && index <= selectedGroupRange.last;
|
|
@@ -737,12 +1006,12 @@ function EventRow$1({ event, index, isFirst, isLast, isExpanded, onToggleExpand,
|
|
|
737
1006
|
return jsxRuntimeExports.jsxs("div", { "data-event-id": event.eventId, onMouseEnter: () => onHoverGroup(rowGroupKey), onMouseLeave: () => onHoverGroup(void 0), children: [jsxRuntimeExports.jsxs("div", { role: "button", tabIndex: 0, onClick: handleRowClick, onKeyDown: (e) => {
|
|
738
1007
|
if (e.key === "Enter" || e.key === " ")
|
|
739
1008
|
handleRowClick();
|
|
740
|
-
}, className: "w-full text-left flex items-center gap-0 text-
|
|
1009
|
+
}, className: "w-full text-left flex items-center gap-0 text-label-13 hover:bg-[var(--ds-gray-alpha-100)] transition-colors cursor-pointer", style: { minHeight: 40 }, children: [jsxRuntimeExports.jsx(TreeGutter, { isFirst, isLast: isLast && !isExpanded, isRunLevel: isRun, statusDotColor, pulse: isPulsing, hasSelection: hasActive, showBranch, showLaneLine, isLaneStart, isLaneEnd }), jsxRuntimeExports.jsxs("div", { className: "flex items-center flex-1 min-w-0", style: { opacity: contentOpacity, transition: "opacity 150ms" }, children: [jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center w-5 h-5 flex-shrink-0 rounded", style: {
|
|
741
1010
|
border: "1px solid var(--ds-gray-400)"
|
|
742
1011
|
}, children: jsxRuntimeExports.jsx(ChevronRight, { className: "h-3 w-3 transition-transform", style: {
|
|
743
1012
|
color: "var(--ds-gray-900)",
|
|
744
1013
|
transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
|
|
745
|
-
} }) }), jsxRuntimeExports.jsx("div", { className: "tabular-nums min-w-0 px-4", style: { color: "var(--ds-gray-900)", flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(TimestampTooltip, { date:
|
|
1014
|
+
} }) }), showSeparateEventOccurrenceTimestamps && jsxRuntimeExports.jsx("div", { className: "tabular-nums min-w-0 px-4", style: { color: "var(--ds-gray-900)", flex: "2 1 0%" }, children: occurredAt ? jsxRuntimeExports.jsx(TimestampTooltip, { date: occurredAt, children: jsxRuntimeExports.jsx("span", { children: formatEventTime(occurredAt) }) }) : "-" }), jsxRuntimeExports.jsx("div", { className: "tabular-nums min-w-0 px-4", style: { color: "var(--ds-gray-900)", flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(TimestampTooltip, { date: displayedCreatedAt, children: jsxRuntimeExports.jsx("span", { children: formatEventTime(displayedCreatedAt) }) }) }), jsxRuntimeExports.jsx("div", { className: "font-medium min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5", style: { color: "var(--ds-gray-900)" }, children: [jsxRuntimeExports.jsxs("span", { style: {
|
|
746
1015
|
position: "relative",
|
|
747
1016
|
display: "inline-flex",
|
|
748
1017
|
width: 6,
|
|
@@ -765,13 +1034,14 @@ function EventRow$1({ event, index, isFirst, isLast, isExpanded, onToggleExpand,
|
|
|
765
1034
|
borderColor: "var(--ds-gray-alpha-200)",
|
|
766
1035
|
opacity: contentOpacity,
|
|
767
1036
|
transition: "opacity 150ms"
|
|
768
|
-
}, children: [((durationInfo == null ? void 0 : durationInfo.queued) !== void 0 || (durationInfo == null ? void 0 : durationInfo.ran) !== void 0) && jsxRuntimeExports.jsxs("div", { className: "px-2 pb-1.5 text-
|
|
1037
|
+
}, children: [((durationInfo == null ? void 0 : durationInfo.queued) !== void 0 || (durationInfo == null ? void 0 : durationInfo.ran) !== void 0) && jsxRuntimeExports.jsxs("div", { className: "px-2 pb-1.5 text-label-12 flex gap-3", style: { color: "var(--ds-gray-900)" }, children: [durationInfo.queued !== void 0 && durationInfo.queued > 0 && jsxRuntimeExports.jsxs("span", { children: ["Queued for", " ", jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatDuration(durationInfo.queued) })] }), durationInfo.ran !== void 0 && jsxRuntimeExports.jsxs("span", { children: ["Ran for", " ", jsxRuntimeExports.jsx("span", { className: "font-mono tabular-nums", children: formatDuration(durationInfo.ran) })] })] }), displayPayload != null ? jsxRuntimeExports.jsx(PayloadBlock, { data: displayPayload, eventType: event.eventType }) : loadError ? jsxRuntimeExports.jsx("div", { className: "rounded-md border p-3 text-label-12", style: {
|
|
769
1038
|
borderColor: "var(--ds-red-400)",
|
|
770
1039
|
backgroundColor: "var(--ds-red-100)",
|
|
771
1040
|
color: "var(--ds-red-900)"
|
|
772
|
-
}, children: loadError }) : isLoading || loadedEventData === null && !hasAttemptedLoad && event.correlationId ? jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 p-3", children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "75%" } }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "50%" } }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "60%" } })] }) : jsxRuntimeExports.jsx("div", { className: "p-2 text-
|
|
1041
|
+
}, children: loadError }) : isLoading || loadedEventData === null && !hasAttemptedLoad && event.correlationId ? jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 p-3", children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "75%" } }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "50%" } }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: "60%" } })] }) : jsxRuntimeExports.jsx("div", { className: "p-2 text-label-12", style: { color: "var(--ds-gray-900)" }, children: "No data" })] })] })] });
|
|
773
1042
|
}
|
|
774
|
-
function
|
|
1043
|
+
function EventListViewInner({ events, run, onLoadEventData, hasMoreEvents = false, isLoadingMoreEvents = false, onLoadMoreEvents, encryptionKey, isLoading = false, sortOrder: sortOrderProp, onSortOrderChange, onDecrypt, isDecrypting = false, hasEncryptedData: hasEncryptedDataProp = false, onExactIdSearch, showSeparateEventOccurrenceTimestamps = false }) {
|
|
1044
|
+
const toast2 = useToast();
|
|
775
1045
|
const [internalSortOrder, setInternalSortOrder] = reactExports.useState("asc");
|
|
776
1046
|
const effectiveSortOrder = sortOrderProp ?? internalSortOrder;
|
|
777
1047
|
const handleSortOrderChange = reactExports.useCallback((order) => {
|
|
@@ -781,28 +1051,40 @@ function EventListView({ events, run, onLoadEventData, hasMoreEvents = false, is
|
|
|
781
1051
|
setInternalSortOrder(order);
|
|
782
1052
|
}
|
|
783
1053
|
}, [onSortOrderChange]);
|
|
1054
|
+
const [searchQuery, setSearchQuery] = reactExports.useState("");
|
|
1055
|
+
const [searchResults, setSearchResults] = reactExports.useState(null);
|
|
1056
|
+
const [searchResultsTruncated, setSearchResultsTruncated] = reactExports.useState(false);
|
|
1057
|
+
const [searchError, setSearchError] = reactExports.useState(null);
|
|
1058
|
+
const [searchLoading, setSearchLoading] = reactExports.useState(false);
|
|
1059
|
+
const [searchNotFound, setSearchNotFound] = reactExports.useState(false);
|
|
1060
|
+
const searchRequestRef = reactExports.useRef(0);
|
|
1061
|
+
const virtuosoRef = reactExports.useRef(null);
|
|
1062
|
+
const parsedSearchId = reactExports.useMemo(() => parseExactWorkflowSearchId(searchQuery), [searchQuery]);
|
|
1063
|
+
const isExactSearchActive = searchResults !== null;
|
|
784
1064
|
const sortedEvents = reactExports.useMemo(() => {
|
|
785
|
-
|
|
1065
|
+
const sourceEvents = isExactSearchActive ? searchResults : events ?? [];
|
|
1066
|
+
if (sourceEvents.length === 0)
|
|
786
1067
|
return [];
|
|
787
1068
|
const dir = effectiveSortOrder === "desc" ? -1 : 1;
|
|
788
|
-
return [...
|
|
789
|
-
}, [events, effectiveSortOrder]);
|
|
1069
|
+
return [...sourceEvents].sort((a, b) => dir * (getEffectiveEventTime(a) - getEffectiveEventTime(b)));
|
|
1070
|
+
}, [events, effectiveSortOrder, isExactSearchActive, searchResults]);
|
|
790
1071
|
const hasEncryptedInlineData = reactExports.useMemo(() => {
|
|
791
|
-
|
|
1072
|
+
const sourceEvents = isExactSearchActive ? searchResults : events;
|
|
1073
|
+
if (!sourceEvents)
|
|
792
1074
|
return false;
|
|
793
|
-
for (const event of
|
|
1075
|
+
for (const event of sourceEvents) {
|
|
794
1076
|
const ed = event.eventData;
|
|
795
1077
|
if (hasEncryptedValues(ed))
|
|
796
1078
|
return true;
|
|
797
1079
|
}
|
|
798
1080
|
return false;
|
|
799
|
-
}, [events]);
|
|
1081
|
+
}, [events, isExactSearchActive, searchResults]);
|
|
800
1082
|
const [foundEncryptedInLazyData, setFoundEncryptedInLazyData] = reactExports.useState(false);
|
|
801
1083
|
const handleEncryptedDataDetected = reactExports.useCallback(() => {
|
|
802
1084
|
setFoundEncryptedInLazyData(true);
|
|
803
1085
|
}, []);
|
|
804
1086
|
const hasEncryptedData = hasEncryptedDataProp || hasEncryptedInlineData || foundEncryptedInLazyData;
|
|
805
|
-
const { correlationNameMap, workflowName } = reactExports.useMemo(() => buildNameMaps(events ?? null, run ?? null), [events, run]);
|
|
1087
|
+
const { correlationNameMap, workflowName } = reactExports.useMemo(() => buildNameMaps(isExactSearchActive ? searchResults : events ?? null, run ?? null), [events, isExactSearchActive, run, searchResults]);
|
|
806
1088
|
const durationMap = reactExports.useMemo(() => buildDurationMap(sortedEvents), [sortedEvents]);
|
|
807
1089
|
const [selectedGroupKey, setSelectedGroupKey] = reactExports.useState(void 0);
|
|
808
1090
|
const [hoveredGroupKey, setHoveredGroupKey] = reactExports.useState(void 0);
|
|
@@ -870,123 +1152,273 @@ function EventListView({ events, run, onLoadEventData, hasMoreEvents = false, is
|
|
|
870
1152
|
}
|
|
871
1153
|
return first >= 0 ? { first, last } : null;
|
|
872
1154
|
}, [activeGroupKey, sortedEvents]);
|
|
873
|
-
const [searchQuery, setSearchQuery] = reactExports.useState("");
|
|
874
|
-
const virtuosoRef = reactExports.useRef(null);
|
|
875
|
-
const searchIndex = reactExports.useMemo(() => {
|
|
876
|
-
const entries = [];
|
|
877
|
-
for (let i = 0; i < sortedEvents.length; i++) {
|
|
878
|
-
const ev = sortedEvents[i];
|
|
879
|
-
const isRun = isRunLevel(ev.eventType);
|
|
880
|
-
const name = isRun ? workflowName ?? "" : ev.correlationId ? correlationNameMap.get(ev.correlationId) ?? "" : "";
|
|
881
|
-
entries.push({
|
|
882
|
-
fields: [
|
|
883
|
-
ev.eventId,
|
|
884
|
-
ev.correlationId ?? "",
|
|
885
|
-
ev.eventType,
|
|
886
|
-
formatEventType(ev.eventType),
|
|
887
|
-
name
|
|
888
|
-
].map((f) => f.toLowerCase()),
|
|
889
|
-
groupKey: ev.correlationId ?? (isRun ? "__run__" : void 0),
|
|
890
|
-
eventId: ev.eventId,
|
|
891
|
-
index: i
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
return entries;
|
|
895
|
-
}, [sortedEvents, correlationNameMap, workflowName]);
|
|
896
1155
|
reactExports.useEffect(() => {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1156
|
+
const trimmed = searchQuery.trim();
|
|
1157
|
+
if (!trimmed) {
|
|
1158
|
+
searchRequestRef.current += 1;
|
|
1159
|
+
setSearchResults(null);
|
|
1160
|
+
setSearchResultsTruncated(false);
|
|
1161
|
+
setSearchError(null);
|
|
1162
|
+
setSearchLoading(false);
|
|
1163
|
+
setSearchNotFound(false);
|
|
900
1164
|
setSelectedGroupKey(void 0);
|
|
901
1165
|
return;
|
|
902
1166
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1167
|
+
const parsed = parseExactWorkflowSearchId(trimmed);
|
|
1168
|
+
if (!parsed || !onExactIdSearch) {
|
|
1169
|
+
setSearchResults(null);
|
|
1170
|
+
setSearchLoading(false);
|
|
1171
|
+
setSearchNotFound(false);
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
const requestId = ++searchRequestRef.current;
|
|
1175
|
+
setSearchLoading(true);
|
|
1176
|
+
setSearchNotFound(false);
|
|
1177
|
+
setSearchError(null);
|
|
1178
|
+
const abortController = new AbortController();
|
|
1179
|
+
const timer = setTimeout(() => {
|
|
1180
|
+
void (async () => {
|
|
1181
|
+
var _a;
|
|
1182
|
+
try {
|
|
1183
|
+
const results = await onExactIdSearch(parsed.id, parsed.kind, abortController.signal);
|
|
1184
|
+
if (abortController.signal.aborted || searchRequestRef.current !== requestId) {
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
if (results.status === "error") {
|
|
1188
|
+
setSearchResults([]);
|
|
1189
|
+
setSearchResultsTruncated(false);
|
|
1190
|
+
setSearchNotFound(false);
|
|
1191
|
+
setSearchError(results.message);
|
|
1192
|
+
setSelectedGroupKey(void 0);
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
if (results.status === "not_found" || results.status === "ok" && results.events.length === 0) {
|
|
1196
|
+
setSearchResults([]);
|
|
1197
|
+
setSearchResultsTruncated(false);
|
|
1198
|
+
setSearchNotFound(true);
|
|
1199
|
+
setSearchError(null);
|
|
1200
|
+
setSelectedGroupKey(void 0);
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
setSearchResults(results.events);
|
|
1204
|
+
setSearchResultsTruncated(Boolean(results.truncated));
|
|
1205
|
+
setSearchNotFound(false);
|
|
1206
|
+
setSearchError(null);
|
|
1207
|
+
setSelectedGroupKey(parsed.kind === "event" ? (() => {
|
|
1208
|
+
const first = results.events[0];
|
|
1209
|
+
if (!first)
|
|
1210
|
+
return void 0;
|
|
1211
|
+
return isRunLevel(first.eventType) ? "__run__" : first.correlationId ?? void 0;
|
|
1212
|
+
})() : parsed.id);
|
|
1213
|
+
(_a = virtuosoRef.current) == null ? void 0 : _a.scrollToIndex({
|
|
1214
|
+
index: 0,
|
|
1215
|
+
align: "start",
|
|
1216
|
+
behavior: "smooth"
|
|
1217
|
+
});
|
|
1218
|
+
} catch {
|
|
1219
|
+
if (abortController.signal.aborted || searchRequestRef.current !== requestId) {
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
setSearchResults([]);
|
|
1223
|
+
setSearchResultsTruncated(false);
|
|
1224
|
+
setSearchNotFound(false);
|
|
1225
|
+
setSearchError("Failed to search events. Try again.");
|
|
1226
|
+
setSelectedGroupKey(void 0);
|
|
1227
|
+
} finally {
|
|
1228
|
+
if (searchRequestRef.current === requestId && !abortController.signal.aborted) {
|
|
1229
|
+
setSearchLoading(false);
|
|
912
1230
|
}
|
|
913
1231
|
}
|
|
914
|
-
}
|
|
1232
|
+
})();
|
|
1233
|
+
}, 300);
|
|
1234
|
+
return () => {
|
|
1235
|
+
clearTimeout(timer);
|
|
1236
|
+
abortController.abort();
|
|
1237
|
+
};
|
|
1238
|
+
}, [searchQuery, onExactIdSearch]);
|
|
1239
|
+
const handleSearchKeyDown = reactExports.useCallback((event) => {
|
|
1240
|
+
if (event.key !== "Enter") {
|
|
1241
|
+
return;
|
|
915
1242
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
index: bestMatch.index,
|
|
920
|
-
align: "center",
|
|
921
|
-
behavior: "smooth"
|
|
922
|
-
});
|
|
1243
|
+
const trimmed = searchQuery.trim();
|
|
1244
|
+
if (!trimmed || parseExactWorkflowSearchId(trimmed) || !onExactIdSearch || !looksLikeWorkflowIdSearchInput(trimmed)) {
|
|
1245
|
+
return;
|
|
923
1246
|
}
|
|
924
|
-
|
|
1247
|
+
toast2.info("Enter a full step ID, wait ID, hook ID, or event ID");
|
|
1248
|
+
}, [searchQuery, onExactIdSearch, toast2]);
|
|
925
1249
|
const hasHadEventsRef = reactExports.useRef(false);
|
|
926
1250
|
if (sortedEvents.length > 0) {
|
|
927
1251
|
hasHadEventsRef.current = true;
|
|
928
1252
|
}
|
|
929
|
-
const isInitialLoad = isLoading && !hasHadEventsRef.current;
|
|
930
|
-
const isRefetching = isLoading && hasHadEventsRef.current && sortedEvents.length === 0;
|
|
931
|
-
if (isInitialLoad) {
|
|
932
|
-
return jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col overflow-hidden", children: [jsxRuntimeExports.jsx("div", { style: { padding: 6 }, children: jsxRuntimeExports.jsx(Skeleton, { style: { height: 40, borderRadius: 6 } }) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0 h-10 border-b flex-shrink-0", style: { borderColor: "var(--ds-gray-alpha-200)" }, children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", style: { width: GUTTER_WIDTH } }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 40 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 72 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 44 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 92 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 60 } }) })] }), jsxRuntimeExports.jsx(RowsSkeleton, {})] });
|
|
1253
|
+
const isInitialLoad = isLoading && !hasHadEventsRef.current;
|
|
1254
|
+
const isRefetching = isLoading && hasHadEventsRef.current && sortedEvents.length === 0;
|
|
1255
|
+
if (isInitialLoad) {
|
|
1256
|
+
return jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col overflow-hidden", children: [jsxRuntimeExports.jsx("div", { style: { padding: 6 }, children: jsxRuntimeExports.jsx(Skeleton, { style: { height: 40, borderRadius: 6 } }) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0 h-10 border-b flex-shrink-0", style: { borderColor: "var(--ds-gray-alpha-200)" }, children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", style: { width: GUTTER_WIDTH } }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 40 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 72 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 44 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 92 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton, { className: "h-3", style: { width: 60 } }) })] }), jsxRuntimeExports.jsx(RowsSkeleton, {})] });
|
|
1257
|
+
}
|
|
1258
|
+
return jsxRuntimeExports.jsx(DecryptClickContext.Provider, { value: onDecrypt ? { onDecrypt, isDecrypting } : void 0, children: jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col overflow-hidden", children: [jsxRuntimeExports.jsx("style", { children: `@keyframes workflow-dot-pulse{0%{transform:scale(1);opacity:.7}70%,100%{transform:scale(2.2);opacity:0}}` }), jsxRuntimeExports.jsxs("div", { style: {
|
|
1259
|
+
padding: 6,
|
|
1260
|
+
backgroundColor: "var(--ds-background-100)",
|
|
1261
|
+
display: "flex",
|
|
1262
|
+
gap: 6
|
|
1263
|
+
}, children: [jsxRuntimeExports.jsxs("label", { style: {
|
|
1264
|
+
display: "flex",
|
|
1265
|
+
alignItems: "center",
|
|
1266
|
+
justifyContent: "center",
|
|
1267
|
+
borderRadius: 6,
|
|
1268
|
+
boxShadow: "0 0 0 1px var(--ds-gray-alpha-400)",
|
|
1269
|
+
background: "var(--ds-background-100)",
|
|
1270
|
+
height: 40,
|
|
1271
|
+
flex: 1,
|
|
1272
|
+
minWidth: 0
|
|
1273
|
+
}, children: [jsxRuntimeExports.jsx("div", { style: {
|
|
1274
|
+
width: 40,
|
|
1275
|
+
height: 40,
|
|
1276
|
+
display: "flex",
|
|
1277
|
+
alignItems: "center",
|
|
1278
|
+
justifyContent: "center",
|
|
1279
|
+
color: "var(--ds-gray-800)",
|
|
1280
|
+
flexShrink: 0
|
|
1281
|
+
}, children: jsxRuntimeExports.jsxs("svg", { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", focusable: "false", children: [jsxRuntimeExports.jsx("circle", { cx: "7", cy: "7", r: "4.5", stroke: "currentColor", strokeWidth: "1.5" }), jsxRuntimeExports.jsx("path", { d: "M11.5 11.5L14 14", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] }) }), jsxRuntimeExports.jsx("input", { type: "search", placeholder: "Search by step ID, wait ID, hook ID, or event ID…", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: handleSearchKeyDown, disabled: !onExactIdSearch, title: onExactIdSearch ? void 0 : "Exact ID search is unavailable in this view.", style: {
|
|
1282
|
+
marginLeft: -16,
|
|
1283
|
+
paddingInline: 12,
|
|
1284
|
+
fontFamily: "inherit",
|
|
1285
|
+
fontSize: 14,
|
|
1286
|
+
background: "transparent",
|
|
1287
|
+
border: "none",
|
|
1288
|
+
outline: "none",
|
|
1289
|
+
height: 40,
|
|
1290
|
+
width: "100%",
|
|
1291
|
+
opacity: onExactIdSearch ? 1 : 0.5,
|
|
1292
|
+
cursor: onExactIdSearch ? "text" : "not-allowed"
|
|
1293
|
+
} })] }), jsxRuntimeExports.jsx(MenuDropdown, { options: SORT_OPTIONS, value: effectiveSortOrder, onChange: handleSortOrderChange }), (hasEncryptedData || encryptionKey) && onDecrypt && jsxRuntimeExports.jsx(DecryptButton, { decrypted: !!encryptionKey, loading: isDecrypting, onClick: onDecrypt })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0 text-label-13 font-medium h-10 border-b flex-shrink-0", style: {
|
|
1294
|
+
borderColor: "var(--ds-gray-alpha-200)",
|
|
1295
|
+
color: "var(--ds-gray-900)",
|
|
1296
|
+
backgroundColor: "var(--ds-background-100)"
|
|
1297
|
+
}, children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", style: { width: GUTTER_WIDTH } }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0" }), showSeparateEventOccurrenceTimestamps && jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Occurred" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Created" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Event Type" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Name" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Correlation ID" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Event ID" })] }), isRefetching || searchLoading ? jsxRuntimeExports.jsx(RowsSkeleton, { showSeparateEventOccurrenceTimestamps }) : sortedEvents.length === 0 ? jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-copy-14", style: { color: "var(--ds-gray-700)" }, children: searchNotFound && searchQuery.trim() ? `No events found for ${searchQuery.trim()}` : searchError ? searchError : parsedSearchId && searchQuery.trim() && !onExactIdSearch ? "Exact ID search is unavailable in this view." : "No events found" }) : jsxRuntimeExports.jsx(Yr, { ref: virtuosoRef, totalCount: sortedEvents.length, overscan: 20, defaultItemHeight: 40, endReached: () => {
|
|
1298
|
+
if (isExactSearchActive || !hasMoreEvents || isLoadingMoreEvents) {
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
void (onLoadMoreEvents == null ? void 0 : onLoadMoreEvents());
|
|
1302
|
+
}, itemContent: (index) => {
|
|
1303
|
+
const ev = sortedEvents[index];
|
|
1304
|
+
return jsxRuntimeExports.jsx(EventRow$1, { event: ev, index, isFirst: index === 0, isLast: index === sortedEvents.length - 1, isExpanded: expandedEventIds.has(ev.eventId), onToggleExpand: toggleEventExpanded, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData: eventDataCacheRef.current.get(ev.eventId) ?? null, onCacheEventData: cacheEventData, encryptionKey, onEncryptedDataDetected: handleEncryptedDataDetected, suppressGroupDimming: isExactSearchActive, showSeparateEventOccurrenceTimestamps });
|
|
1305
|
+
}, style: { flex: 1, minHeight: 0 } }), jsxRuntimeExports.jsxs("div", { className: "relative flex-shrink-0 flex items-center h-10 border-t px-4 text-label-12", style: {
|
|
1306
|
+
borderColor: "var(--ds-gray-alpha-200)",
|
|
1307
|
+
color: "var(--ds-gray-900)",
|
|
1308
|
+
backgroundColor: "var(--ds-background-100)"
|
|
1309
|
+
}, children: [jsxRuntimeExports.jsx("span", { children: isExactSearchActive ? searchError ? searchError : searchNotFound ? `No events found for ${searchQuery.trim()}` : `${sortedEvents.length} event${sortedEvents.length !== 1 ? "s" : ""} for ${searchQuery.trim()}${searchResultsTruncated ? " (results may be truncated)" : ""}` : `${sortedEvents.length} event${sortedEvents.length !== 1 ? "s" : ""} loaded` }), !isExactSearchActive && hasMoreEvents && jsxRuntimeExports.jsx("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: jsxRuntimeExports.jsx("div", { className: "pointer-events-auto", children: jsxRuntimeExports.jsx(LoadMoreButton, { loading: isLoadingMoreEvents, onClick: () => void (onLoadMoreEvents == null ? void 0 : onLoadMoreEvents()) }) }) })] })] }) });
|
|
1310
|
+
}
|
|
1311
|
+
function EventListView(props) {
|
|
1312
|
+
return jsxRuntimeExports.jsx(ContextCardProvider, { children: jsxRuntimeExports.jsx(EventListViewInner, { ...props }) });
|
|
1313
|
+
}
|
|
1314
|
+
function ConversationView({ messages }) {
|
|
1315
|
+
if (messages.length === 0) {
|
|
1316
|
+
return jsxRuntimeExports.jsx("div", { className: "text-center py-8 text-[11px]", style: { color: "var(--ds-gray-600)" }, children: "No messages" });
|
|
1317
|
+
}
|
|
1318
|
+
return jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-3 p-3", children: messages.map((message, index) => jsxRuntimeExports.jsx(MessageBubble, { message }, index)) });
|
|
1319
|
+
}
|
|
1320
|
+
function MessageBubble({ message }) {
|
|
1321
|
+
const role = message.role;
|
|
1322
|
+
const parts = parseContent(message.content);
|
|
1323
|
+
const style = getRoleStyle(role);
|
|
1324
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded-md border text-[11px]", style: {
|
|
1325
|
+
backgroundColor: style.bg,
|
|
1326
|
+
borderColor: style.border
|
|
1327
|
+
}, children: [jsxRuntimeExports.jsx("div", { className: "px-2.5 py-1 border-b text-[10px] font-medium uppercase tracking-wide", style: {
|
|
1328
|
+
borderColor: style.border,
|
|
1329
|
+
color: style.label
|
|
1330
|
+
}, children: role }), jsxRuntimeExports.jsx("div", { className: "px-2.5 py-2 space-y-2", children: parts.map((part, i) => jsxRuntimeExports.jsx(ContentPart, { part, role }, i)) })] });
|
|
1331
|
+
}
|
|
1332
|
+
function ContentPart({ part, role }) {
|
|
1333
|
+
if (part.type === "text") {
|
|
1334
|
+
if (!part.text)
|
|
1335
|
+
return null;
|
|
1336
|
+
if (role === "assistant") {
|
|
1337
|
+
return jsxRuntimeExports.jsx("div", { className: "prose prose-sm max-w-none text-[11px] [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", style: { color: "var(--ds-gray-1000)" }, children: jsxRuntimeExports.jsx(_r, { children: part.text }) });
|
|
1338
|
+
}
|
|
1339
|
+
return jsxRuntimeExports.jsx("div", { className: "whitespace-pre-wrap break-words", style: { color: "var(--ds-gray-1000)" }, children: part.text });
|
|
1340
|
+
}
|
|
1341
|
+
if (part.type === "tool-call") {
|
|
1342
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded border px-2 py-1.5", style: {
|
|
1343
|
+
backgroundColor: "var(--ds-purple-100)",
|
|
1344
|
+
borderColor: "var(--ds-purple-300)"
|
|
1345
|
+
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-medium", children: [jsxRuntimeExports.jsx("span", { children: "🔧" }), jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-purple-900)" }, children: part.toolName })] }), part.input != null && jsxRuntimeExports.jsx("div", { className: "mt-1.5 overflow-x-auto p-1.5 rounded", style: { backgroundColor: "var(--ds-gray-100)" }, children: typeof part.input === "string" ? jsxRuntimeExports.jsx("pre", { className: "text-[10px]", style: { color: "var(--ds-gray-800)" }, children: part.input }) : jsxRuntimeExports.jsx(DataInspector, { data: part.input }) })] });
|
|
1346
|
+
}
|
|
1347
|
+
if (part.type === "tool-result") {
|
|
1348
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded border px-2 py-1.5", style: {
|
|
1349
|
+
backgroundColor: "var(--ds-green-100)",
|
|
1350
|
+
borderColor: "var(--ds-green-300)"
|
|
1351
|
+
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-medium", children: [jsxRuntimeExports.jsx("span", { children: "✓" }), jsxRuntimeExports.jsxs("span", { style: { color: "var(--ds-green-900)" }, children: [part.toolName, " result"] })] }), part.output != null && jsxRuntimeExports.jsx("div", { className: "mt-1.5 overflow-x-auto max-h-[200px] overflow-y-auto p-1.5 rounded", style: { backgroundColor: "var(--ds-gray-100)" }, children: typeof part.output === "string" ? jsxRuntimeExports.jsx("pre", { className: "text-[10px]", style: { color: "var(--ds-gray-800)" }, children: part.output }) : jsxRuntimeExports.jsx(DataInspector, { data: part.output, expandLevel: 1 }) })] });
|
|
1352
|
+
}
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1355
|
+
function getRoleStyle(role) {
|
|
1356
|
+
switch (role) {
|
|
1357
|
+
case "user":
|
|
1358
|
+
return {
|
|
1359
|
+
bg: "var(--ds-blue-100)",
|
|
1360
|
+
border: "var(--ds-blue-300)",
|
|
1361
|
+
label: "var(--ds-blue-700)"
|
|
1362
|
+
};
|
|
1363
|
+
case "assistant":
|
|
1364
|
+
return {
|
|
1365
|
+
bg: "var(--ds-gray-100)",
|
|
1366
|
+
border: "var(--ds-gray-300)",
|
|
1367
|
+
label: "var(--ds-gray-700)"
|
|
1368
|
+
};
|
|
1369
|
+
case "system":
|
|
1370
|
+
return {
|
|
1371
|
+
bg: "var(--ds-amber-100)",
|
|
1372
|
+
border: "var(--ds-amber-300)",
|
|
1373
|
+
label: "var(--ds-amber-700)"
|
|
1374
|
+
};
|
|
1375
|
+
case "tool":
|
|
1376
|
+
return {
|
|
1377
|
+
bg: "var(--ds-green-50)",
|
|
1378
|
+
border: "var(--ds-green-300)",
|
|
1379
|
+
label: "var(--ds-green-700)"
|
|
1380
|
+
};
|
|
1381
|
+
default:
|
|
1382
|
+
return {
|
|
1383
|
+
bg: "var(--ds-gray-100)",
|
|
1384
|
+
border: "var(--ds-gray-300)",
|
|
1385
|
+
label: "var(--ds-gray-700)"
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function parseContent(content) {
|
|
1390
|
+
if (typeof content === "string") {
|
|
1391
|
+
return [{ type: "text", text: content }];
|
|
933
1392
|
}
|
|
934
|
-
if (
|
|
935
|
-
return
|
|
1393
|
+
if (Array.isArray(content)) {
|
|
1394
|
+
return content.map((part) => {
|
|
1395
|
+
if (typeof part === "string") {
|
|
1396
|
+
return { type: "text", text: part };
|
|
1397
|
+
}
|
|
1398
|
+
if ((part == null ? void 0 : part.type) === "text") {
|
|
1399
|
+
return { type: "text", text: String(part.text ?? "") };
|
|
1400
|
+
}
|
|
1401
|
+
if ((part == null ? void 0 : part.type) === "tool-call") {
|
|
1402
|
+
return {
|
|
1403
|
+
type: "tool-call",
|
|
1404
|
+
toolName: part.toolName,
|
|
1405
|
+
input: part.input
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
if ((part == null ? void 0 : part.type) === "tool-result") {
|
|
1409
|
+
return {
|
|
1410
|
+
type: "tool-result",
|
|
1411
|
+
toolName: part.toolName,
|
|
1412
|
+
output: part.output
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
return { type: "text", text: "" };
|
|
1416
|
+
});
|
|
936
1417
|
}
|
|
937
|
-
return
|
|
938
|
-
padding: 6,
|
|
939
|
-
backgroundColor: "var(--ds-background-100)",
|
|
940
|
-
display: "flex",
|
|
941
|
-
gap: 6
|
|
942
|
-
}, children: [jsxRuntimeExports.jsxs("label", { style: {
|
|
943
|
-
display: "flex",
|
|
944
|
-
alignItems: "center",
|
|
945
|
-
justifyContent: "center",
|
|
946
|
-
borderRadius: 6,
|
|
947
|
-
boxShadow: "0 0 0 1px var(--ds-gray-alpha-400)",
|
|
948
|
-
background: "var(--ds-background-100)",
|
|
949
|
-
height: 40,
|
|
950
|
-
flex: 1,
|
|
951
|
-
minWidth: 0
|
|
952
|
-
}, children: [jsxRuntimeExports.jsx("div", { style: {
|
|
953
|
-
width: 40,
|
|
954
|
-
height: 40,
|
|
955
|
-
display: "flex",
|
|
956
|
-
alignItems: "center",
|
|
957
|
-
justifyContent: "center",
|
|
958
|
-
color: "var(--ds-gray-800)",
|
|
959
|
-
flexShrink: 0
|
|
960
|
-
}, children: jsxRuntimeExports.jsxs("svg", { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", focusable: "false", children: [jsxRuntimeExports.jsx("circle", { cx: "7", cy: "7", r: "4.5", stroke: "currentColor", strokeWidth: "1.5" }), jsxRuntimeExports.jsx("path", { d: "M11.5 11.5L14 14", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] }) }), jsxRuntimeExports.jsx("input", { type: "search", placeholder: "Search by name, event type, or ID…", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), style: {
|
|
961
|
-
marginLeft: -16,
|
|
962
|
-
paddingInline: 12,
|
|
963
|
-
fontFamily: "inherit",
|
|
964
|
-
fontSize: 14,
|
|
965
|
-
background: "transparent",
|
|
966
|
-
border: "none",
|
|
967
|
-
outline: "none",
|
|
968
|
-
height: 40,
|
|
969
|
-
width: "100%"
|
|
970
|
-
} })] }), jsxRuntimeExports.jsx(MenuDropdown, { options: SORT_OPTIONS, value: effectiveSortOrder, onChange: handleSortOrderChange }), (hasEncryptedData || encryptionKey) && onDecrypt && jsxRuntimeExports.jsx(DecryptButton, { decrypted: !!encryptionKey, loading: isDecrypting, onClick: onDecrypt })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0 text-[13px] font-medium h-10 border-b flex-shrink-0", style: {
|
|
971
|
-
borderColor: "var(--ds-gray-alpha-200)",
|
|
972
|
-
color: "var(--ds-gray-900)",
|
|
973
|
-
backgroundColor: "var(--ds-background-100)"
|
|
974
|
-
}, children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", style: { width: GUTTER_WIDTH } }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Time" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Event Type" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Name" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Correlation ID" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Event ID" })] }), isRefetching ? jsxRuntimeExports.jsx(RowsSkeleton, {}) : jsxRuntimeExports.jsx(Yr, { ref: virtuosoRef, totalCount: sortedEvents.length, overscan: 20, defaultItemHeight: 40, endReached: () => {
|
|
975
|
-
if (!hasMoreEvents || isLoadingMoreEvents) {
|
|
976
|
-
return;
|
|
977
|
-
}
|
|
978
|
-
void (onLoadMoreEvents == null ? void 0 : onLoadMoreEvents());
|
|
979
|
-
}, itemContent: (index) => {
|
|
980
|
-
const ev = sortedEvents[index];
|
|
981
|
-
return jsxRuntimeExports.jsx(EventRow$1, { event: ev, index, isFirst: index === 0, isLast: index === sortedEvents.length - 1, isExpanded: expandedEventIds.has(ev.eventId), onToggleExpand: toggleEventExpanded, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData: eventDataCacheRef.current.get(ev.eventId) ?? null, onCacheEventData: cacheEventData, encryptionKey, onEncryptedDataDetected: handleEncryptedDataDetected });
|
|
982
|
-
}, style: { flex: 1, minHeight: 0 } }), jsxRuntimeExports.jsxs("div", { className: "relative flex-shrink-0 flex items-center h-10 border-t px-4 text-xs", style: {
|
|
983
|
-
borderColor: "var(--ds-gray-alpha-200)",
|
|
984
|
-
color: "var(--ds-gray-900)",
|
|
985
|
-
backgroundColor: "var(--ds-background-100)"
|
|
986
|
-
}, children: [jsxRuntimeExports.jsxs("span", { children: [sortedEvents.length, " event", sortedEvents.length !== 1 ? "s" : "", " loaded"] }), hasMoreEvents && jsxRuntimeExports.jsx("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: jsxRuntimeExports.jsx("div", { className: "pointer-events-auto", children: jsxRuntimeExports.jsx(LoadMoreButton, { loading: isLoadingMoreEvents, onClick: () => void (onLoadMoreEvents == null ? void 0 : onLoadMoreEvents()) }) }) })] })] }) });
|
|
1418
|
+
return [];
|
|
987
1419
|
}
|
|
988
1420
|
function shouldShowVerticalLine(eventType) {
|
|
989
|
-
if (eventType
|
|
1421
|
+
if (isHookLifecycleEventType(eventType)) {
|
|
990
1422
|
return true;
|
|
991
1423
|
}
|
|
992
1424
|
return false;
|
|
@@ -1037,12 +1469,20 @@ const MARKER_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
1037
1469
|
"step_failed",
|
|
1038
1470
|
"run_failed",
|
|
1039
1471
|
"wait_created",
|
|
1040
|
-
"wait_completed"
|
|
1472
|
+
"wait_completed",
|
|
1473
|
+
"attr_set"
|
|
1041
1474
|
]);
|
|
1042
|
-
|
|
1475
|
+
const getEventTimestamp = (event) => {
|
|
1476
|
+
const value = (event == null ? void 0 : event.occurredAt) ?? (event == null ? void 0 : event.createdAt);
|
|
1477
|
+
if (!value)
|
|
1478
|
+
return void 0;
|
|
1479
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1480
|
+
return Number.isNaN(date.getTime()) ? void 0 : date;
|
|
1481
|
+
};
|
|
1482
|
+
function convertEventsToSpanEvents(events, filterTypes = true, options = {}) {
|
|
1043
1483
|
return events.filter((event) => filterTypes ? MARKER_EVENT_TYPES.has(event.eventType) : true).map((event) => ({
|
|
1044
1484
|
name: event.eventType,
|
|
1045
|
-
timestamp: dateToOtelTime(event.createdAt),
|
|
1485
|
+
timestamp: dateToOtelTime(options.preferOccurredAt ? getEventTimestamp(event) ?? event.createdAt : event.createdAt),
|
|
1046
1486
|
attributes: {
|
|
1047
1487
|
eventId: event.eventId,
|
|
1048
1488
|
correlationId: event.correlationId,
|
|
@@ -1062,9 +1502,9 @@ const waitEventsToWaitEntity = (events) => {
|
|
|
1062
1502
|
return {
|
|
1063
1503
|
waitId: startEvent.correlationId,
|
|
1064
1504
|
runId: startEvent.runId,
|
|
1065
|
-
createdAt: startEvent.createdAt,
|
|
1505
|
+
createdAt: getEventTimestamp(startEvent) ?? startEvent.createdAt,
|
|
1066
1506
|
resumeAt: ((_a = startEvent.eventData) == null ? void 0 : _a.resumeAt) ? new Date(startEvent.eventData.resumeAt) : void 0,
|
|
1067
|
-
completedAt: completedEvent
|
|
1507
|
+
completedAt: getEventTimestamp(completedEvent)
|
|
1068
1508
|
};
|
|
1069
1509
|
};
|
|
1070
1510
|
function waitToSpan(events, maxEndTime, fallbackEndTime = maxEndTime) {
|
|
@@ -1121,16 +1561,16 @@ const stepEventsToStepEntity = (events) => {
|
|
|
1121
1561
|
status = "running";
|
|
1122
1562
|
attempt += 1;
|
|
1123
1563
|
if (!startedAt)
|
|
1124
|
-
startedAt = e.createdAt;
|
|
1564
|
+
startedAt = getEventTimestamp(e) ?? e.createdAt;
|
|
1125
1565
|
completedAt = void 0;
|
|
1126
1566
|
break;
|
|
1127
1567
|
case "step_completed":
|
|
1128
1568
|
status = "completed";
|
|
1129
|
-
completedAt = e.createdAt;
|
|
1569
|
+
completedAt = getEventTimestamp(e) ?? e.createdAt;
|
|
1130
1570
|
break;
|
|
1131
1571
|
case "step_failed":
|
|
1132
1572
|
status = "failed";
|
|
1133
|
-
completedAt = e.createdAt;
|
|
1573
|
+
completedAt = getEventTimestamp(e) ?? e.createdAt;
|
|
1134
1574
|
break;
|
|
1135
1575
|
case "step_retrying":
|
|
1136
1576
|
status = "pending";
|
|
@@ -1147,8 +1587,8 @@ const stepEventsToStepEntity = (events) => {
|
|
|
1147
1587
|
stepName: ((_a = createdEvent == null ? void 0 : createdEvent.eventData) == null ? void 0 : _a.stepName) ?? "",
|
|
1148
1588
|
status,
|
|
1149
1589
|
attempt,
|
|
1150
|
-
createdAt: anchorEvent.createdAt,
|
|
1151
|
-
updatedAt: (lastEvent == null ? void 0 : lastEvent.createdAt) ?? anchorEvent.createdAt,
|
|
1590
|
+
createdAt: getEventTimestamp(anchorEvent) ?? anchorEvent.createdAt,
|
|
1591
|
+
updatedAt: getEventTimestamp(lastEvent) ?? (lastEvent == null ? void 0 : lastEvent.createdAt) ?? anchorEvent.createdAt,
|
|
1152
1592
|
startedAt,
|
|
1153
1593
|
completedAt,
|
|
1154
1594
|
specVersion: anchorEvent.specVersion
|
|
@@ -1165,13 +1605,20 @@ function stepToSpan(stepEvents, maxEndTime) {
|
|
|
1165
1605
|
data: step
|
|
1166
1606
|
};
|
|
1167
1607
|
const resource = "step";
|
|
1168
|
-
const
|
|
1169
|
-
|
|
1170
|
-
|
|
1608
|
+
const events = convertEventsToSpanEvents(stepEvents, false, {
|
|
1609
|
+
preferOccurredAt: true
|
|
1610
|
+
});
|
|
1611
|
+
const spanStartEvent = stepEvents.find((event) => event.eventType === "step_created") ?? stepEvents[0];
|
|
1612
|
+
const spanStartTime = getEventTimestamp(spanStartEvent) ?? new Date(step.createdAt);
|
|
1171
1613
|
let activeStartTime = step.startedAt ? new Date(step.startedAt) : void 0;
|
|
1172
1614
|
const firstStartEvent = stepEvents.find((event) => event.eventType === "step_started");
|
|
1173
1615
|
if (firstStartEvent) {
|
|
1174
|
-
activeStartTime = new Date(firstStartEvent.createdAt);
|
|
1616
|
+
activeStartTime = getEventTimestamp(firstStartEvent) ?? new Date(firstStartEvent.createdAt);
|
|
1617
|
+
}
|
|
1618
|
+
let endTime = new Date(maxEndTime);
|
|
1619
|
+
if (step.completedAt) {
|
|
1620
|
+
const completedEvent = stepEvents.slice().reverse().find((event) => isTerminalStepEventType(event.eventType));
|
|
1621
|
+
endTime = getEventTimestamp(completedEvent) ?? new Date(step.completedAt);
|
|
1175
1622
|
}
|
|
1176
1623
|
return {
|
|
1177
1624
|
spanId: String(step.stepId),
|
|
@@ -1193,7 +1640,7 @@ function stepToSpan(stepEvents, maxEndTime) {
|
|
|
1193
1640
|
};
|
|
1194
1641
|
}
|
|
1195
1642
|
const hookEventsToHookEntity = (events) => {
|
|
1196
|
-
var _a
|
|
1643
|
+
var _a;
|
|
1197
1644
|
const createdEvent = events.find((event) => event.eventType === "hook_created");
|
|
1198
1645
|
if (!createdEvent) {
|
|
1199
1646
|
return null;
|
|
@@ -1205,10 +1652,10 @@ const hookEventsToHookEntity = (events) => {
|
|
|
1205
1652
|
hookId: createdEvent.correlationId,
|
|
1206
1653
|
runId: createdEvent.runId,
|
|
1207
1654
|
token: (_a = createdEvent.eventData) == null ? void 0 : _a.token,
|
|
1208
|
-
createdAt: createdEvent.createdAt,
|
|
1655
|
+
createdAt: getEventTimestamp(createdEvent) ?? createdEvent.createdAt,
|
|
1209
1656
|
receivedCount: receivedEvents.length,
|
|
1210
|
-
lastReceivedAt: (lastReceivedEvent
|
|
1211
|
-
disposedAt: (
|
|
1657
|
+
lastReceivedAt: getEventTimestamp(lastReceivedEvent),
|
|
1658
|
+
disposedAt: getEventTimestamp(disposedEvents.at(-1))
|
|
1212
1659
|
};
|
|
1213
1660
|
};
|
|
1214
1661
|
function hookToSpan(hookEvents, maxEndTime) {
|
|
@@ -1220,7 +1667,7 @@ function hookToSpan(hookEvents, maxEndTime) {
|
|
|
1220
1667
|
const endTime = hook.disposedAt || maxEndTime;
|
|
1221
1668
|
return {
|
|
1222
1669
|
spanId: String(hook.hookId),
|
|
1223
|
-
name: String(hook.hookId),
|
|
1670
|
+
name: hook.token ?? String(hook.hookId),
|
|
1224
1671
|
kind: 1,
|
|
1225
1672
|
// INTERNAL span kind
|
|
1226
1673
|
resource: "hook",
|
|
@@ -1241,15 +1688,26 @@ function hookToSpan(hookEvents, maxEndTime) {
|
|
|
1241
1688
|
function runToSpan(run, runEvents, nowTime) {
|
|
1242
1689
|
var _a;
|
|
1243
1690
|
const now = nowTime ?? /* @__PURE__ */ new Date();
|
|
1691
|
+
const runCreatedEvent = runEvents.find((event) => event.eventType === "run_created");
|
|
1692
|
+
const runStartedEvent = runEvents.find((event) => event.eventType === "run_started");
|
|
1693
|
+
const terminalEvent = runEvents.slice().reverse().find((event) => event.eventType === "run_completed" || event.eventType === "run_failed" || event.eventType === "run_cancelled");
|
|
1694
|
+
const spanStartTime = getEventTimestamp(runCreatedEvent) ?? new Date(run.createdAt);
|
|
1695
|
+
const activeStartTime = getEventTimestamp(runStartedEvent) ?? (run.startedAt ? new Date(run.startedAt) : void 0);
|
|
1696
|
+
const completedAt = getEventTimestamp(terminalEvent) ?? run.completedAt ?? void 0;
|
|
1697
|
+
const endTime = completedAt ?? now;
|
|
1244
1698
|
const { input: _i, output: _o, error: _e, ...runIdentity } = run;
|
|
1245
1699
|
const attributes = {
|
|
1246
1700
|
resource: "run",
|
|
1247
|
-
data:
|
|
1701
|
+
data: {
|
|
1702
|
+
...runIdentity,
|
|
1703
|
+
createdAt: spanStartTime,
|
|
1704
|
+
startedAt: activeStartTime,
|
|
1705
|
+
completedAt
|
|
1706
|
+
}
|
|
1248
1707
|
};
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
const events = convertEventsToSpanEvents(runEvents, false);
|
|
1708
|
+
const events = convertEventsToSpanEvents(runEvents, false, {
|
|
1709
|
+
preferOccurredAt: true
|
|
1710
|
+
});
|
|
1253
1711
|
return {
|
|
1254
1712
|
spanId: String(run.runId),
|
|
1255
1713
|
name: String(((_a = parseWorkflowName(run.workflowName)) == null ? void 0 : _a.shortName) ?? "?"),
|
|
@@ -1269,9 +1727,15 @@ function runToSpan(run, runEvents, nowTime) {
|
|
|
1269
1727
|
activeStartTime: activeStartTime && activeStartTime.getTime() > spanStartTime.getTime() ? dateToOtelTime(activeStartTime) : void 0
|
|
1270
1728
|
};
|
|
1271
1729
|
}
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1274
|
-
|
|
1730
|
+
const isRunLevelEvent = (event) => !event.correlationId || !isWaitEventType(event.eventType) && !isHookLifecycleEventType(event.eventType) && !isStepEventType(event.eventType);
|
|
1731
|
+
function filterSpanRawEvents(events, resource, spanId) {
|
|
1732
|
+
if (resource === "run") {
|
|
1733
|
+
return events.filter(isRunLevelEvent);
|
|
1734
|
+
}
|
|
1735
|
+
if (!spanId)
|
|
1736
|
+
return [];
|
|
1737
|
+
return events.filter((e) => e.correlationId === spanId);
|
|
1738
|
+
}
|
|
1275
1739
|
function pushEvent(map, correlationId, event) {
|
|
1276
1740
|
const existing = map.get(correlationId);
|
|
1277
1741
|
if (existing) {
|
|
@@ -1291,15 +1755,15 @@ function groupEventsByCorrelation(events) {
|
|
|
1291
1755
|
runLevelEvents.push(event);
|
|
1292
1756
|
continue;
|
|
1293
1757
|
}
|
|
1294
|
-
if (
|
|
1758
|
+
if (isWaitEventType(event.eventType)) {
|
|
1295
1759
|
pushEvent(timerEvents, correlationId, event);
|
|
1296
1760
|
continue;
|
|
1297
1761
|
}
|
|
1298
|
-
if (
|
|
1762
|
+
if (isHookLifecycleEventType(event.eventType)) {
|
|
1299
1763
|
pushEvent(hookEvents, correlationId, event);
|
|
1300
1764
|
continue;
|
|
1301
1765
|
}
|
|
1302
|
-
if (
|
|
1766
|
+
if (isStepEventType(event.eventType)) {
|
|
1303
1767
|
pushEvent(eventsByStepId, correlationId, event);
|
|
1304
1768
|
continue;
|
|
1305
1769
|
}
|
|
@@ -1310,7 +1774,7 @@ function groupEventsByCorrelation(events) {
|
|
|
1310
1774
|
function computeLatestKnownTime(events, run) {
|
|
1311
1775
|
let latest = new Date(run.createdAt).getTime();
|
|
1312
1776
|
for (const event of events) {
|
|
1313
|
-
const t = new Date(event.createdAt).getTime();
|
|
1777
|
+
const t = (getEventTimestamp(event) ?? new Date(event.createdAt)).getTime();
|
|
1314
1778
|
if (t > latest)
|
|
1315
1779
|
latest = t;
|
|
1316
1780
|
}
|
|
@@ -1366,150 +1830,86 @@ function buildTrace(run, events, now) {
|
|
|
1366
1830
|
knownDurationMs: Math.max(0, knownDurationMs)
|
|
1367
1831
|
};
|
|
1368
1832
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
return
|
|
1374
|
-
}
|
|
1375
|
-
function MessageBubble({ message }) {
|
|
1376
|
-
const role = message.role;
|
|
1377
|
-
const parts = parseContent(message.content);
|
|
1378
|
-
const style = getRoleStyle(role);
|
|
1379
|
-
return jsxRuntimeExports.jsxs("div", { className: "rounded-md border text-[11px]", style: {
|
|
1380
|
-
backgroundColor: style.bg,
|
|
1381
|
-
borderColor: style.border
|
|
1382
|
-
}, children: [jsxRuntimeExports.jsx("div", { className: "px-2.5 py-1 border-b text-[10px] font-medium uppercase tracking-wide", style: {
|
|
1383
|
-
borderColor: style.border,
|
|
1384
|
-
color: style.label
|
|
1385
|
-
}, children: role }), jsxRuntimeExports.jsx("div", { className: "px-2.5 py-2 space-y-2", children: parts.map((part, i) => jsxRuntimeExports.jsx(ContentPart, { part, role }, i)) })] });
|
|
1386
|
-
}
|
|
1387
|
-
function ContentPart({ part, role }) {
|
|
1388
|
-
if (part.type === "text") {
|
|
1389
|
-
if (!part.text)
|
|
1390
|
-
return null;
|
|
1391
|
-
if (role === "assistant") {
|
|
1392
|
-
return jsxRuntimeExports.jsx("div", { className: "prose prose-sm max-w-none text-[11px] [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", style: { color: "var(--ds-gray-1000)" }, children: jsxRuntimeExports.jsx(_r, { children: part.text }) });
|
|
1393
|
-
}
|
|
1394
|
-
return jsxRuntimeExports.jsx("div", { className: "whitespace-pre-wrap break-words", style: { color: "var(--ds-gray-1000)" }, children: part.text });
|
|
1395
|
-
}
|
|
1396
|
-
if (part.type === "tool-call") {
|
|
1397
|
-
return jsxRuntimeExports.jsxs("div", { className: "rounded border px-2 py-1.5", style: {
|
|
1398
|
-
backgroundColor: "var(--ds-purple-100)",
|
|
1399
|
-
borderColor: "var(--ds-purple-300)"
|
|
1400
|
-
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-medium", children: [jsxRuntimeExports.jsx("span", { children: "🔧" }), jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-purple-900)" }, children: part.toolName })] }), part.input != null && jsxRuntimeExports.jsx("div", { className: "mt-1.5 overflow-x-auto p-1.5 rounded", style: { backgroundColor: "var(--ds-gray-100)" }, children: typeof part.input === "string" ? jsxRuntimeExports.jsx("pre", { className: "text-[10px]", style: { color: "var(--ds-gray-800)" }, children: part.input }) : jsxRuntimeExports.jsx(DataInspector, { data: part.input }) })] });
|
|
1401
|
-
}
|
|
1402
|
-
if (part.type === "tool-result") {
|
|
1403
|
-
return jsxRuntimeExports.jsxs("div", { className: "rounded border px-2 py-1.5", style: {
|
|
1404
|
-
backgroundColor: "var(--ds-green-100)",
|
|
1405
|
-
borderColor: "var(--ds-green-300)"
|
|
1406
|
-
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-medium", children: [jsxRuntimeExports.jsx("span", { children: "✓" }), jsxRuntimeExports.jsxs("span", { style: { color: "var(--ds-green-900)" }, children: [part.toolName, " result"] })] }), part.output != null && jsxRuntimeExports.jsx("div", { className: "mt-1.5 overflow-x-auto max-h-[200px] overflow-y-auto p-1.5 rounded", style: { backgroundColor: "var(--ds-gray-100)" }, children: typeof part.output === "string" ? jsxRuntimeExports.jsx("pre", { className: "text-[10px]", style: { color: "var(--ds-gray-800)" }, children: part.output }) : jsxRuntimeExports.jsx(DataInspector, { data: part.output, expandLevel: 1 }) })] });
|
|
1407
|
-
}
|
|
1408
|
-
return null;
|
|
1833
|
+
const GUTTER_PX = 1;
|
|
1834
|
+
const MIN_PX = 50;
|
|
1835
|
+
const DEFAULT_START_PX = 340;
|
|
1836
|
+
function paneColTemplate(startPx) {
|
|
1837
|
+
return `${startPx}px ${GUTTER_PX}px minmax(${MIN_PX}px, 1fr)`;
|
|
1409
1838
|
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
};
|
|
1430
|
-
case "tool":
|
|
1431
|
-
return {
|
|
1432
|
-
bg: "var(--ds-green-50)",
|
|
1433
|
-
border: "var(--ds-green-300)",
|
|
1434
|
-
label: "var(--ds-green-700)"
|
|
1435
|
-
};
|
|
1436
|
-
default:
|
|
1437
|
-
return {
|
|
1438
|
-
bg: "var(--ds-gray-100)",
|
|
1439
|
-
border: "var(--ds-gray-300)",
|
|
1440
|
-
label: "var(--ds-gray-700)"
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1839
|
+
const COL_TEMPLATE = paneColTemplate(DEFAULT_START_PX);
|
|
1840
|
+
const ROWS = [
|
|
1841
|
+
{ id: "r0", name: 62, off: 0, bar: 72 },
|
|
1842
|
+
{ id: "r1", name: 78, off: 6, bar: 48 },
|
|
1843
|
+
{ id: "r2", name: 50, off: 10, bar: 55 },
|
|
1844
|
+
{ id: "r3", name: 84, off: 18, bar: 30 },
|
|
1845
|
+
{ id: "r4", name: 45, off: 18, bar: 42 },
|
|
1846
|
+
{ id: "r5", name: 66, off: 34, bar: 38 },
|
|
1847
|
+
{ id: "r6", name: 55, off: 41, bar: 25 },
|
|
1848
|
+
{ id: "r7", name: 40, off: 50, bar: 30 }
|
|
1849
|
+
];
|
|
1850
|
+
const HEADER_MARKERS = ["m0", "m1", "m2", "m3"];
|
|
1851
|
+
const HeaderDivider = () => jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-full w-px bg-gray-alpha-400" }) });
|
|
1852
|
+
function TraceViewerSkeleton() {
|
|
1853
|
+
return jsxRuntimeExports.jsxs("output", { "aria-busy": "true", "aria-label": "Loading trace", className: "flex flex-col w-full h-full min-h-0 bg-background-100", children: [jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Loading trace…" }), jsxRuntimeExports.jsx("div", { className: "relative h-10 min-h-10 shrink-0 border-b border-gray-alpha-400", children: jsxRuntimeExports.jsx("div", { className: "absolute inset-x-4 top-[6px]", children: ROWS.map((row, index) => jsxRuntimeExports.jsx(Skeleton, { className: "absolute h-[3px] rounded-full", style: {
|
|
1854
|
+
left: `${row.off}%`,
|
|
1855
|
+
width: `${row.bar}%`,
|
|
1856
|
+
top: index * 3.5
|
|
1857
|
+
} }, row.id)) }) }), jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: COL_TEMPLATE }, children: [jsxRuntimeExports.jsxs("div", { className: "h-10 min-h-10 flex items-center border-b border-gray-alpha-400 pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Skeleton, { className: "w-3.5 h-3.5 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5 w-40" })] }), jsxRuntimeExports.jsx(HeaderDivider, {}), jsxRuntimeExports.jsx("div", { className: "h-10 min-h-10 flex items-end border-b border-gray-alpha-400 px-4 pb-1 gap-2", children: jsxRuntimeExports.jsx("div", { className: "relative flex-1 flex items-end justify-between", children: HEADER_MARKERS.map((id) => jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5 w-9" }, id)) }) })] }), jsxRuntimeExports.jsxs("div", { className: "grid flex-1 min-h-0 overflow-hidden", style: { gridTemplateColumns: COL_TEMPLATE }, children: [jsxRuntimeExports.jsx("div", { className: "block overflow-visible", children: jsxRuntimeExports.jsx("ul", { className: "block divide-y divide-gray-alpha-400 border-b border-gray-alpha-400", children: ROWS.map((row) => jsxRuntimeExports.jsxs("li", { className: "h-10 flex items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsx(Skeleton, { className: "w-4 h-4 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5", style: { width: `${row.name}%` } })] }), jsxRuntimeExports.jsx(Skeleton, { className: "ml-2 h-3.5 w-10 shrink-0" })] }, row.id)) }) }), jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-full w-px bg-gray-alpha-400" }), jsxRuntimeExports.jsx("div", { className: "relative min-h-0", children: ROWS.map((row) => jsxRuntimeExports.jsx("div", { className: "relative h-10", children: jsxRuntimeExports.jsx("div", { className: "absolute inset-x-4 inset-y-0", children: jsxRuntimeExports.jsx(Skeleton, { className: "absolute top-1/2 -translate-y-1/2 h-6 rounded-[0.25rem]", style: { left: `${row.off}%`, width: `${row.bar}%` } }) }) }, row.id)) })] })] });
|
|
1443
1858
|
}
|
|
1444
|
-
function
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
toolName: part.toolName,
|
|
1460
|
-
input: part.input
|
|
1461
|
-
};
|
|
1462
|
-
}
|
|
1463
|
-
if ((part == null ? void 0 : part.type) === "tool-result") {
|
|
1464
|
-
return {
|
|
1465
|
-
type: "tool-result",
|
|
1466
|
-
toolName: part.toolName,
|
|
1467
|
-
output: part.output
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
|
-
return { type: "text", text: "" };
|
|
1859
|
+
function useIntersectionObserver(elementRef, { threshold = 0, rootRef, rootMargin = "0%", freezeOnceVisible = false } = {}) {
|
|
1860
|
+
const [entry, setEntry] = reactExports.useState();
|
|
1861
|
+
const frozen = (entry == null ? void 0 : entry.isIntersecting) && freezeOnceVisible;
|
|
1862
|
+
reactExports.useEffect(() => {
|
|
1863
|
+
const node = elementRef == null ? void 0 : elementRef.current;
|
|
1864
|
+
const hasIOSupport = !!window.IntersectionObserver;
|
|
1865
|
+
if (!hasIOSupport || frozen || !node)
|
|
1866
|
+
return;
|
|
1867
|
+
const updateEntry = ([entry2]) => {
|
|
1868
|
+
setEntry(entry2);
|
|
1869
|
+
};
|
|
1870
|
+
const observer = new IntersectionObserver(updateEntry, {
|
|
1871
|
+
threshold,
|
|
1872
|
+
root: (rootRef == null ? void 0 : rootRef.current) ?? null,
|
|
1873
|
+
rootMargin
|
|
1471
1874
|
});
|
|
1472
|
-
|
|
1473
|
-
|
|
1875
|
+
observer.observe(node);
|
|
1876
|
+
return () => observer.disconnect();
|
|
1877
|
+
}, [elementRef, threshold, rootRef, rootMargin, frozen]);
|
|
1878
|
+
return entry;
|
|
1474
1879
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
};
|
|
1487
|
-
|
|
1488
|
-
const toast2 = useToast();
|
|
1489
|
-
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-x-auto rounded-md border p-3", style: { borderColor: "var(--ds-gray-300)" }, children: [jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Copy data", title: "Copy", className: "!absolute !right-2 !top-2 !flex !h-6 !w-6 !items-center !justify-center !rounded-md !border !bg-[var(--ds-background-100)] !text-[var(--ds-gray-800)] transition-transform transition-colors duration-100 hover:!bg-[var(--ds-gray-alpha-200)] active:!scale-95 active:!bg-[var(--ds-gray-alpha-300)]", style: { borderColor: "var(--ds-gray-300)" }, onClick: () => {
|
|
1490
|
-
navigator.clipboard.writeText(serializeForClipboard(data)).then(() => {
|
|
1491
|
-
toast2.success("Copied to clipboard");
|
|
1492
|
-
}).catch(() => {
|
|
1493
|
-
toast2.error("Failed to copy");
|
|
1494
|
-
});
|
|
1495
|
-
}, children: jsxRuntimeExports.jsx(Copy, { size: 12 }) }), jsxRuntimeExports.jsx(DataInspector, { data })] });
|
|
1880
|
+
function useLoadMoreOnScroll(loadMore, { hasMore, isLoadingMore, rootRef, rootMargin = "400px" }) {
|
|
1881
|
+
const sentinelRef = reactExports.useRef(null);
|
|
1882
|
+
const entry = useIntersectionObserver(sentinelRef, { rootRef, rootMargin });
|
|
1883
|
+
const loadMoreRef = reactExports.useRef(loadMore);
|
|
1884
|
+
reactExports.useEffect(() => {
|
|
1885
|
+
loadMoreRef.current = loadMore;
|
|
1886
|
+
}, [loadMore]);
|
|
1887
|
+
reactExports.useEffect(() => {
|
|
1888
|
+
if ((entry == null ? void 0 : entry.isIntersecting) && hasMore && !isLoadingMore) {
|
|
1889
|
+
loadMoreRef.current();
|
|
1890
|
+
}
|
|
1891
|
+
}, [entry == null ? void 0 : entry.isIntersecting, hasMore, isLoadingMore]);
|
|
1892
|
+
return sentinelRef;
|
|
1496
1893
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1894
|
+
const kbdVariants = cva("inline-flex items-center justify-center rounded px-1 text-center font-sans", {
|
|
1895
|
+
variants: {
|
|
1896
|
+
variant: {
|
|
1897
|
+
subtle: "bg-background-100/20",
|
|
1898
|
+
outline: "border border-gray-alpha-400 bg-background-100 font-medium text-gray-900"
|
|
1899
|
+
},
|
|
1900
|
+
size: {
|
|
1901
|
+
default: "h-5 min-w-5 text-label-12 leading-none",
|
|
1902
|
+
compact: "h-4 min-h-4 min-w-4 text-[11px] leading-none",
|
|
1903
|
+
search: "h-5 min-h-5 min-w-5 text-label-13 leading-[1.7em]"
|
|
1904
|
+
}
|
|
1905
|
+
},
|
|
1906
|
+
defaultVariants: {
|
|
1907
|
+
variant: "subtle",
|
|
1908
|
+
size: "default"
|
|
1506
1909
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
color: "var(--ds-gray-900)",
|
|
1511
|
-
listStyle: "none"
|
|
1512
|
-
}, children: jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1.5", children: [jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: "shrink-0 transition-transform group-open:rotate-90" }), summary] }) }), jsxRuntimeExports.jsx("div", { className: `mt-2 ${contentClassName ?? ""}`, children })] });
|
|
1910
|
+
});
|
|
1911
|
+
function Kbd({ children, className, variant, size, ...props }) {
|
|
1912
|
+
return jsxRuntimeExports.jsx("kbd", { className: cn(kbdVariants({ variant, size, className })), ...props, children });
|
|
1513
1913
|
}
|
|
1514
1914
|
function TabButton({ active, onClick, children }) {
|
|
1515
1915
|
return jsxRuntimeExports.jsx("button", { type: "button", role: "tab", "aria-selected": active, tabIndex: active ? 0 : -1, onClick, className: "px-3 py-1.5 text-[11px] font-medium transition-colors -mb-px", style: {
|
|
@@ -1548,28 +1948,15 @@ const conversationTabs = [
|
|
|
1548
1948
|
{ id: "conversation", label: "Conversation" },
|
|
1549
1949
|
{ id: "json", label: "Raw JSON" }
|
|
1550
1950
|
];
|
|
1551
|
-
function ConversationWithTabs({ conversation, args }) {
|
|
1951
|
+
function ConversationWithTabs({ conversation, args, defaultOpen, onOpenChange }) {
|
|
1552
1952
|
const [activeTab, setActiveTab] = reactExports.useState("conversation");
|
|
1553
|
-
return jsxRuntimeExports.jsx(
|
|
1953
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen, onOpenChange, children: jsxRuntimeExports.jsx(TabbedContainer, { tabs: conversationTabs, activeTab, onTabChange: setActiveTab, ariaLabel: "Conversation view", children: activeTab === "conversation" ? jsxRuntimeExports.jsx(ConversationView, { messages: conversation }) : jsxRuntimeExports.jsx("div", { className: "p-3", children: Array.isArray(args) ? args.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(args) }) }) });
|
|
1554
1954
|
}
|
|
1555
1955
|
function EncryptedFieldBlock() {
|
|
1556
|
-
|
|
1557
|
-
if (ctx) {
|
|
1558
|
-
return jsxRuntimeExports.jsxs("button", { type: "button", onClick: ctx.onDecrypt, disabled: ctx.isDecrypting, className: "flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-xs cursor-pointer transition-colors", style: {
|
|
1559
|
-
borderColor: "var(--ds-gray-400)",
|
|
1560
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
1561
|
-
color: "var(--ds-gray-700)",
|
|
1562
|
-
opacity: ctx.isDecrypting ? 0.6 : 1
|
|
1563
|
-
}, title: "Click to decrypt", children: [ctx.isDecrypting ? jsxRuntimeExports.jsx(Spinner, { size: 12 }) : jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { className: "font-medium", children: ctx.isDecrypting ? "Decrypting…" : "Decrypt" })] });
|
|
1564
|
-
}
|
|
1565
|
-
return jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
1566
|
-
borderColor: "var(--ds-gray-300)",
|
|
1567
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
1568
|
-
color: "var(--ds-gray-700)"
|
|
1569
|
-
}, children: [jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Encrypted" })] });
|
|
1956
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
1570
1957
|
}
|
|
1571
1958
|
function ExpiredFieldBlock() {
|
|
1572
|
-
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-
|
|
1959
|
+
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-label-12", style: {
|
|
1573
1960
|
borderColor: "var(--ds-gray-300)",
|
|
1574
1961
|
backgroundColor: "var(--ds-gray-100)",
|
|
1575
1962
|
color: "var(--ds-gray-700)"
|
|
@@ -1600,36 +1987,44 @@ const attributeOrder = [
|
|
|
1600
1987
|
"runId",
|
|
1601
1988
|
"attempt",
|
|
1602
1989
|
"token",
|
|
1990
|
+
"tokenRetentionUntil",
|
|
1991
|
+
"isWebhook",
|
|
1992
|
+
"isSystem",
|
|
1603
1993
|
"receivedCount",
|
|
1604
1994
|
"lastReceivedAt",
|
|
1605
1995
|
"disposedAt",
|
|
1606
1996
|
"correlationId",
|
|
1607
1997
|
"eventType",
|
|
1608
1998
|
"deploymentId",
|
|
1999
|
+
"vercelId",
|
|
2000
|
+
"computeInstanceId",
|
|
1609
2001
|
"specVersion",
|
|
1610
2002
|
"workflowCoreVersion",
|
|
1611
2003
|
"ownerId",
|
|
1612
2004
|
"projectId",
|
|
1613
2005
|
"environment",
|
|
1614
2006
|
"executionContext",
|
|
2007
|
+
"occurredAt",
|
|
1615
2008
|
"createdAt",
|
|
1616
2009
|
"startedAt",
|
|
1617
2010
|
"updatedAt",
|
|
1618
2011
|
"completedAt",
|
|
1619
2012
|
"expiredAt",
|
|
1620
2013
|
"retryAfter",
|
|
2014
|
+
"errorCode",
|
|
1621
2015
|
"error",
|
|
1622
2016
|
"metadata",
|
|
1623
2017
|
"eventData",
|
|
1624
2018
|
"input",
|
|
1625
2019
|
"output",
|
|
2020
|
+
"attributes",
|
|
1626
2021
|
"resumeAt"
|
|
1627
2022
|
];
|
|
1628
|
-
const
|
|
1629
|
-
const
|
|
1630
|
-
|
|
1631
|
-
return aIndex - bIndex;
|
|
2023
|
+
const attributeOrderIndex = (attribute) => {
|
|
2024
|
+
const index = attributeOrder.indexOf(attribute);
|
|
2025
|
+
return index === -1 ? attributeOrder.length : index;
|
|
1632
2026
|
};
|
|
2027
|
+
const sortByAttributeOrder = (a, b) => attributeOrderIndex(a) - attributeOrderIndex(b);
|
|
1633
2028
|
const attributeDisplayNames = {
|
|
1634
2029
|
moduleSpecifier: "Module",
|
|
1635
2030
|
workflowName: "Workflow Name",
|
|
@@ -1639,11 +2034,17 @@ const attributeDisplayNames = {
|
|
|
1639
2034
|
attempt: "Attempts",
|
|
1640
2035
|
eventId: "Event ID",
|
|
1641
2036
|
runId: "Run ID",
|
|
2037
|
+
token: "Token",
|
|
2038
|
+
tokenRetentionUntil: "Minimum Retention Until",
|
|
1642
2039
|
eventType: "Event Type",
|
|
2040
|
+
errorCode: "Error Code",
|
|
1643
2041
|
correlationId: "Correlation ID",
|
|
1644
2042
|
deploymentId: "Deployment ID",
|
|
2043
|
+
vercelId: "Request ID",
|
|
2044
|
+
computeInstanceId: "Compute Instance ID",
|
|
1645
2045
|
specVersion: "Spec Version",
|
|
1646
2046
|
workflowCoreVersion: "@workflow/core version",
|
|
2047
|
+
occurredAt: "Occurred",
|
|
1647
2048
|
createdAt: "Created",
|
|
1648
2049
|
startedAt: "Started",
|
|
1649
2050
|
updatedAt: "Updated",
|
|
@@ -1670,7 +2071,7 @@ const getModuleSpecifierFromName = (value) => {
|
|
|
1670
2071
|
}
|
|
1671
2072
|
return raw;
|
|
1672
2073
|
};
|
|
1673
|
-
const parseDateValue = (value) => {
|
|
2074
|
+
const parseDateValue$1 = (value) => {
|
|
1674
2075
|
if (value == null) {
|
|
1675
2076
|
return null;
|
|
1676
2077
|
}
|
|
@@ -1683,35 +2084,21 @@ const parseDateValue = (value) => {
|
|
|
1683
2084
|
const date = typeof value === "number" ? new Date(value) : new Date(String(value));
|
|
1684
2085
|
return Number.isNaN(date.getTime()) ? null : date;
|
|
1685
2086
|
};
|
|
1686
|
-
const formatLocalMillisecondTime = (date) => date.
|
|
1687
|
-
year: "numeric",
|
|
1688
|
-
month: "numeric",
|
|
1689
|
-
day: "numeric",
|
|
1690
|
-
hour: "numeric",
|
|
1691
|
-
minute: "numeric",
|
|
1692
|
-
second: "numeric",
|
|
1693
|
-
fractionalSecondDigits: 3
|
|
1694
|
-
});
|
|
1695
|
-
const localMillisecondTime = (value) => {
|
|
1696
|
-
const date = parseDateValue(value);
|
|
1697
|
-
if (!date) {
|
|
1698
|
-
return "-";
|
|
1699
|
-
}
|
|
1700
|
-
return formatLocalMillisecondTime(date);
|
|
1701
|
-
};
|
|
2087
|
+
const formatLocalMillisecondTime = (date) => format(date, "MMM dd HH:mm:ss.SS OO").toUpperCase();
|
|
1702
2088
|
const localMillisecondTimeOrNull = (value) => {
|
|
1703
|
-
const date = parseDateValue(value);
|
|
2089
|
+
const date = parseDateValue$1(value);
|
|
1704
2090
|
if (!date) {
|
|
1705
2091
|
return null;
|
|
1706
2092
|
}
|
|
1707
2093
|
return formatLocalMillisecondTime(date);
|
|
1708
2094
|
};
|
|
1709
2095
|
const timestampWithTooltipOrNull = (value) => {
|
|
1710
|
-
const date = parseDateValue(value);
|
|
2096
|
+
const date = parseDateValue$1(value);
|
|
1711
2097
|
if (!date)
|
|
1712
2098
|
return null;
|
|
1713
2099
|
return jsxRuntimeExports.jsx(TimestampTooltip, { date, children: jsxRuntimeExports.jsx("span", { children: formatLocalMillisecondTime(date) }) });
|
|
1714
2100
|
};
|
|
2101
|
+
const opaqueIdOrNull = (value) => hasDisplayContent(value) ? String(value) : null;
|
|
1715
2102
|
const attributeToDisplayFn = {
|
|
1716
2103
|
// Names that need pretty-printing
|
|
1717
2104
|
workflowName: (_value) => null,
|
|
@@ -1719,7 +2106,7 @@ const attributeToDisplayFn = {
|
|
|
1719
2106
|
stepName: (_value) => null,
|
|
1720
2107
|
// IDs
|
|
1721
2108
|
runId: (_value) => null,
|
|
1722
|
-
stepId: (
|
|
2109
|
+
stepId: (value) => String(value),
|
|
1723
2110
|
hookId: (value) => String(value),
|
|
1724
2111
|
eventId: (value) => String(value),
|
|
1725
2112
|
// Run/step details
|
|
@@ -1727,15 +2114,23 @@ const attributeToDisplayFn = {
|
|
|
1727
2114
|
attempt: (value) => String(value),
|
|
1728
2115
|
// Hook details
|
|
1729
2116
|
token: (value) => String(value),
|
|
2117
|
+
tokenRetentionUntil: timestampWithTooltipOrNull,
|
|
1730
2118
|
isWebhook: (value) => String(value),
|
|
2119
|
+
isSystem: (value) => String(value),
|
|
1731
2120
|
receivedCount: (value) => String(value),
|
|
1732
2121
|
lastReceivedAt: localMillisecondTimeOrNull,
|
|
1733
2122
|
disposedAt: localMillisecondTimeOrNull,
|
|
2123
|
+
// Internal resume plumbing — not surfaced in the UI
|
|
2124
|
+
resumeContext: (_value) => null,
|
|
2125
|
+
resumeId: (_value) => null,
|
|
2126
|
+
resumeCapabilities: (_value) => null,
|
|
1734
2127
|
// Event details
|
|
1735
2128
|
eventType: (value) => String(value),
|
|
1736
2129
|
correlationId: (value) => String(value),
|
|
1737
2130
|
// Project details
|
|
1738
2131
|
deploymentId: (value) => String(value),
|
|
2132
|
+
vercelId: opaqueIdOrNull,
|
|
2133
|
+
computeInstanceId: opaqueIdOrNull,
|
|
1739
2134
|
specVersion: (value) => String(value),
|
|
1740
2135
|
workflowCoreVersion: (value) => String(value),
|
|
1741
2136
|
// Tenancy (we don't show these)
|
|
@@ -1743,7 +2138,16 @@ const attributeToDisplayFn = {
|
|
|
1743
2138
|
projectId: (_value) => null,
|
|
1744
2139
|
environment: (_value) => null,
|
|
1745
2140
|
executionContext: (_value) => null,
|
|
2141
|
+
// Attributes — string-string metadata attached to the run.
|
|
2142
|
+
// Rendered as key-value rows in its own collapsible section;
|
|
2143
|
+
// if empty/missing, hidden by the hasDisplayContent gate.
|
|
2144
|
+
attributes: (value) => {
|
|
2145
|
+
if (!hasDisplayContent(value))
|
|
2146
|
+
return null;
|
|
2147
|
+
return jsxRuntimeExports.jsx(RunAttributesCard, { attributes: value });
|
|
2148
|
+
},
|
|
1746
2149
|
// Dates — wrapped with TimestampTooltip showing UTC/local + relative time
|
|
2150
|
+
occurredAt: timestampWithTooltipOrNull,
|
|
1747
2151
|
createdAt: timestampWithTooltipOrNull,
|
|
1748
2152
|
startedAt: timestampWithTooltipOrNull,
|
|
1749
2153
|
updatedAt: (_value) => null,
|
|
@@ -1755,105 +2159,154 @@ const attributeToDisplayFn = {
|
|
|
1755
2159
|
metadata: (value) => {
|
|
1756
2160
|
if (!hasDisplayContent(value))
|
|
1757
2161
|
return null;
|
|
1758
|
-
if (isEncryptedMarker(value))
|
|
1759
|
-
return jsxRuntimeExports.jsx(
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
2162
|
+
if (isEncryptedMarker(value)) {
|
|
2163
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Metadata", children: jsxRuntimeExports.jsx(EncryptedDataBlock, {}) });
|
|
2164
|
+
}
|
|
2165
|
+
if (isExpiredMarker(value)) {
|
|
2166
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Metadata", children: jsxRuntimeExports.jsx(ExpiredFieldBlock, {}) });
|
|
2167
|
+
}
|
|
2168
|
+
return jsxRuntimeExports.jsx(RunMetadataCard, { metadata: value });
|
|
1763
2169
|
},
|
|
1764
2170
|
input: (value, context) => {
|
|
1765
|
-
if (isEncryptedMarker(value))
|
|
1766
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
2171
|
+
if (isEncryptedMarker(value)) {
|
|
2172
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2173
|
+
}
|
|
1767
2174
|
if (isExpiredMarker(value))
|
|
1768
2175
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1769
2176
|
if (value && typeof value === "object" && "args" in value) {
|
|
1770
2177
|
const { args, closureVars, thisVal } = value;
|
|
1771
|
-
const argCount2 = Array.isArray(args) ? args.length : 0;
|
|
1772
|
-
const argLabel2 = argCount2 === 1 ? "argument" : "arguments";
|
|
1773
2178
|
const hasClosureVars = hasDisplayContent(closureVars);
|
|
1774
2179
|
const hasThisVal = hasDisplayContent(thisVal);
|
|
1775
2180
|
const hasArgs = hasDisplayContent(args);
|
|
1776
2181
|
if ((context == null ? void 0 : context.stepName) && isDoStreamStep(context.stepName)) {
|
|
1777
2182
|
const conversation = extractConversation(args);
|
|
1778
2183
|
if (conversation && conversation.length > 0) {
|
|
1779
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args }), hasClosureVars && jsxRuntimeExports.jsx(
|
|
2184
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args, defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "This Value", children: JsonBlock(thisVal) })] });
|
|
1780
2185
|
}
|
|
1781
2186
|
}
|
|
1782
2187
|
if (!hasArgs && !hasClosureVars && !hasThisVal) {
|
|
1783
|
-
return jsxRuntimeExports.jsx(
|
|
2188
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input (no data)", disabled: true });
|
|
1784
2189
|
}
|
|
1785
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(
|
|
2190
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: Array.isArray(args) ? args.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(args) }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "Context", children: JsonBlock(thisVal) })] });
|
|
1786
2191
|
}
|
|
1787
|
-
const argCount = Array.isArray(value) ? value.length : 0;
|
|
1788
|
-
const argLabel = argCount === 1 ? "argument" : "arguments";
|
|
1789
2192
|
if (!hasDisplayContent(value)) {
|
|
1790
|
-
return jsxRuntimeExports.jsx(
|
|
2193
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input (no data)", disabled: true });
|
|
1791
2194
|
}
|
|
1792
|
-
return jsxRuntimeExports.jsx(
|
|
2195
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: Array.isArray(value) ? value.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(value) });
|
|
1793
2196
|
},
|
|
1794
|
-
output: (value) => {
|
|
2197
|
+
output: (value, context) => {
|
|
2198
|
+
if (isEncryptedMarker(value)) {
|
|
2199
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Output", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2200
|
+
}
|
|
1795
2201
|
if (!hasDisplayContent(value))
|
|
1796
2202
|
return null;
|
|
1797
|
-
if (isEncryptedMarker(value))
|
|
1798
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
1799
2203
|
if (isExpiredMarker(value))
|
|
1800
2204
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1801
|
-
return jsxRuntimeExports.jsx(
|
|
2205
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Output", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: JsonBlock(value) });
|
|
1802
2206
|
},
|
|
1803
2207
|
error: (value) => {
|
|
1804
|
-
if (isEncryptedMarker(value))
|
|
1805
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
2208
|
+
if (isEncryptedMarker(value)) {
|
|
2209
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2210
|
+
}
|
|
1806
2211
|
if (isExpiredMarker(value))
|
|
1807
2212
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1808
2213
|
if (!hasDisplayContent(value))
|
|
1809
2214
|
return null;
|
|
1810
|
-
if (
|
|
1811
|
-
return jsxRuntimeExports.jsx(
|
|
2215
|
+
if (isStructuredError(value)) {
|
|
2216
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(ErrorStackBlock, { value }) });
|
|
1812
2217
|
}
|
|
1813
|
-
return jsxRuntimeExports.jsx(
|
|
2218
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Error", defaultOpen: true, children: JsonBlock(value) });
|
|
1814
2219
|
},
|
|
1815
2220
|
eventData: (value) => {
|
|
1816
|
-
if (isEncryptedMarker(value))
|
|
1817
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
2221
|
+
if (isEncryptedMarker(value)) {
|
|
2222
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Event Data", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2223
|
+
}
|
|
1818
2224
|
if (isExpiredMarker(value))
|
|
1819
2225
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1820
2226
|
if (!hasDisplayContent(value))
|
|
1821
2227
|
return null;
|
|
1822
|
-
return jsxRuntimeExports.jsx(
|
|
1823
|
-
}
|
|
2228
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Event Data", defaultOpen: true, children: JsonBlock(value) });
|
|
2229
|
+
},
|
|
2230
|
+
errorCode: (value) => {
|
|
2231
|
+
if (typeof value !== "string" || value.length === 0)
|
|
2232
|
+
return null;
|
|
2233
|
+
return String(value);
|
|
2234
|
+
},
|
|
2235
|
+
// Internal encryption plumbing: the run's X25519 public key, used by
|
|
2236
|
+
// cross-run writers to seal payloads to this run. Not actionable for users
|
|
2237
|
+
// and not secret — hidden rather than rendered as 44 opaque base64 chars.
|
|
2238
|
+
encryptionPublicKey: (_value) => null
|
|
1824
2239
|
};
|
|
1825
2240
|
const resolvableAttributes = [
|
|
1826
2241
|
"input",
|
|
1827
2242
|
"output",
|
|
1828
2243
|
"error",
|
|
1829
2244
|
"metadata",
|
|
2245
|
+
"attributes",
|
|
2246
|
+
"eventData"
|
|
2247
|
+
];
|
|
2248
|
+
const selfHeaderedAttributes = /* @__PURE__ */ new Set([
|
|
2249
|
+
"input",
|
|
2250
|
+
"output",
|
|
2251
|
+
"error",
|
|
2252
|
+
"metadata",
|
|
2253
|
+
"attributes",
|
|
1830
2254
|
"eventData"
|
|
1831
|
-
];
|
|
1832
|
-
const ExpiredDataMessage = () => jsxRuntimeExports.jsx("div", { className: "text-
|
|
2255
|
+
]);
|
|
2256
|
+
const ExpiredDataMessage = () => jsxRuntimeExports.jsx("div", { className: "text-label-12 rounded-md border p-4 my-2", style: {
|
|
1833
2257
|
borderColor: "var(--ds-gray-300)",
|
|
1834
2258
|
backgroundColor: "var(--ds-gray-100)",
|
|
1835
2259
|
color: "var(--ds-gray-700)"
|
|
1836
2260
|
}, children: jsxRuntimeExports.jsx("span", { children: "The data for this run has expired and is no longer available." }) });
|
|
2261
|
+
const copyableBasicAttributes = /* @__PURE__ */ new Set([
|
|
2262
|
+
"stepId",
|
|
2263
|
+
"hookId",
|
|
2264
|
+
"eventId",
|
|
2265
|
+
"deploymentId",
|
|
2266
|
+
"vercelId",
|
|
2267
|
+
"computeInstanceId",
|
|
2268
|
+
"moduleSpecifier",
|
|
2269
|
+
"token"
|
|
2270
|
+
]);
|
|
2271
|
+
const loadingSectionLabels = {
|
|
2272
|
+
input: "Input",
|
|
2273
|
+
output: "Output",
|
|
2274
|
+
eventData: "Event Data"
|
|
2275
|
+
};
|
|
1837
2276
|
const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
|
|
1838
|
-
const
|
|
1839
|
-
|
|
1840
|
-
|
|
2277
|
+
const decryptCtx = reactExports.useContext(DecryptClickContext);
|
|
2278
|
+
const sectionOpenRef = reactExports.useRef(false);
|
|
2279
|
+
const handleSectionOpenChange = reactExports.useCallback((open) => {
|
|
2280
|
+
sectionOpenRef.current = open;
|
|
2281
|
+
}, []);
|
|
2282
|
+
const label = loadingSectionLabels[attribute];
|
|
2283
|
+
if (isLoading && label && !hasDisplayContent(value)) {
|
|
2284
|
+
if (decryptCtx == null ? void 0 : decryptCtx.hasEncryptedData) {
|
|
2285
|
+
return jsxRuntimeExports.jsx(Collapsible, { label, defaultOpen: attribute === "eventData" || sectionOpenRef.current, onOpenChange: handleSectionOpenChange, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2286
|
+
}
|
|
2287
|
+
return jsxRuntimeExports.jsx(Collapsible, { label });
|
|
1841
2288
|
}
|
|
1842
2289
|
const displayFn = attributeToDisplayFn[attribute];
|
|
1843
2290
|
if (!displayFn) {
|
|
1844
2291
|
return null;
|
|
1845
2292
|
}
|
|
1846
|
-
const displayValue = displayFn(value,
|
|
2293
|
+
const displayValue = displayFn(value, {
|
|
2294
|
+
...context,
|
|
2295
|
+
sectionOpen: sectionOpenRef.current,
|
|
2296
|
+
onSectionOpenChange: handleSectionOpenChange
|
|
2297
|
+
});
|
|
1847
2298
|
if (!displayValue) {
|
|
1848
2299
|
return null;
|
|
1849
2300
|
}
|
|
1850
2301
|
if (inline) {
|
|
1851
2302
|
return jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium", style: { color: "var(--ds-gray-700)" }, children: attribute }), jsxRuntimeExports.jsx("span", { className: "text-[11px]", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] });
|
|
1852
2303
|
}
|
|
1853
|
-
|
|
2304
|
+
if (selfHeaderedAttributes.has(attribute)) {
|
|
2305
|
+
return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: displayValue });
|
|
2306
|
+
}
|
|
2307
|
+
return jsxRuntimeExports.jsxs("div", { className: "relative", children: [typeof isLoading === "boolean" && isLoading && jsxRuntimeExports.jsx("div", { className: "absolute top-9 right-4", children: jsxRuntimeExports.jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2", style: { borderColor: "var(--ds-gray-900)" } }) }), jsxRuntimeExports.jsxs("div", { className: "my-2 flex flex-col gap-0", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-1000 font-medium first-letter:uppercase", children: attribute }), jsxRuntimeExports.jsx("span", { className: "text-label-12", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] }, attribute)] });
|
|
1854
2308
|
};
|
|
1855
|
-
const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
|
|
1856
|
-
const toast2 = useToast();
|
|
2309
|
+
const AttributePanel = ({ data, moduleSpecifier, moduleSourceUrl, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
|
|
1857
2310
|
const displayData = reactExports.useMemo(() => {
|
|
1858
2311
|
const result = { ...data };
|
|
1859
2312
|
const execCtx = data.executionContext;
|
|
@@ -1875,14 +2328,16 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
|
|
|
1875
2328
|
const present = Object.keys(displayData).filter((key) => resolvableAttributes.includes(key)).sort(sortByAttributeOrder);
|
|
1876
2329
|
if (!isLoading)
|
|
1877
2330
|
return present;
|
|
1878
|
-
|
|
1879
|
-
|
|
2331
|
+
if (resource === "sleep")
|
|
2332
|
+
return present;
|
|
2333
|
+
const loadingPlaceholders = ["input", "output"];
|
|
2334
|
+
for (const key of loadingPlaceholders) {
|
|
1880
2335
|
if (!present.includes(key)) {
|
|
1881
2336
|
present.push(key);
|
|
1882
2337
|
}
|
|
1883
2338
|
}
|
|
1884
2339
|
return present.sort(sortByAttributeOrder);
|
|
1885
|
-
}, [displayData, isLoading]);
|
|
2340
|
+
}, [displayData, isLoading, resource]);
|
|
1886
2341
|
const visibleBasicAttributes = basicAttributes.filter((attribute) => {
|
|
1887
2342
|
const displayFn = attributeToDisplayFn[attribute];
|
|
1888
2343
|
if (!displayFn)
|
|
@@ -1913,46 +2368,37 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
|
|
|
1913
2368
|
const displayContext = reactExports.useMemo(() => ({
|
|
1914
2369
|
stepName: displayData.stepName
|
|
1915
2370
|
}), [displayData.stepName]);
|
|
1916
|
-
const
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
}, [
|
|
1923
|
-
return jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsx(DecryptClickContext.Provider, { value: onDecrypt ? { onDecrypt, isDecrypting } : void 0, children: jsxRuntimeExports.jsxs("div", { children: [visibleBasicAttributes.length > 0 && jsxRuntimeExports.jsxs("div", { className: "mb-3 flex flex-col overflow-hidden rounded-md border", style: {
|
|
1924
|
-
borderColor: "var(--ds-gray-300)"
|
|
1925
|
-
}, children: [orderedBasicAttributes.map((attribute, index) => {
|
|
2371
|
+
const outerDecryptCtx = reactExports.useContext(DecryptClickContext);
|
|
2372
|
+
const decryptValue = onDecrypt ? {
|
|
2373
|
+
onDecrypt,
|
|
2374
|
+
isDecrypting,
|
|
2375
|
+
hasEncryptedData: outerDecryptCtx == null ? void 0 : outerDecryptCtx.hasEncryptedData
|
|
2376
|
+
} : outerDecryptCtx;
|
|
2377
|
+
return jsxRuntimeExports.jsx(ContextCardProvider, { children: jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsxs(DecryptClickContext.Provider, { value: decryptValue, children: [visibleBasicAttributes.length > 0 && jsxRuntimeExports.jsxs(CollapsibleRoot, { defaultOpen: true, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { children: "Metadata" }), jsxRuntimeExports.jsx(CollapsibleContent, { className: "mt-0 mb-2", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col", children: [orderedBasicAttributes.map((attribute) => {
|
|
1926
2378
|
var _a;
|
|
1927
2379
|
const displayValue = (_a = attributeToDisplayFn[attribute]) == null ? void 0 : _a.call(attributeToDisplayFn, displayData[attribute]);
|
|
1928
|
-
const
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
const showDivider = index < orderedBasicAttributes.length - 1 || showResumeAtSkeleton;
|
|
1933
|
-
return jsxRuntimeExports.jsxs("div", { className: "py-1", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1", children: [jsxRuntimeExports.jsx("span", { className: shouldCapitalizeLabel ? "text-[14px] first-letter:uppercase" : "text-[14px]", style: { color: "var(--ds-gray-700)" }, children: getAttributeDisplayName(attribute) }), isModuleSpecifier ? jsxRuntimeExports.jsx("button", { type: "button", className: "min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono", style: {
|
|
1934
|
-
color: "var(--ds-gray-1000)",
|
|
1935
|
-
background: "transparent",
|
|
1936
|
-
border: "none",
|
|
1937
|
-
padding: 0
|
|
1938
|
-
}, title: moduleSpecifierValue, onClick: () => handleCopyModuleSpecifier(moduleSpecifierValue), children: moduleSpecifierValue }) : jsxRuntimeExports.jsx("span", { className: "min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] }), showDivider ? jsxRuntimeExports.jsx("div", { className: "mx-2.5 border-b", style: { borderColor: "var(--ds-gray-300)" } }) : null] }, attribute);
|
|
1939
|
-
}), isLoading && resource === "sleep" && !displayData.resumeAt && jsxRuntimeExports.jsx("div", { className: "py-1", children: jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1", children: [jsxRuntimeExports.jsx("span", { className: "text-[14px] first-letter:uppercase", style: { color: "var(--ds-gray-700)" }, children: "resumeAt" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[55%]" })] }) })] }), error ? jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load resource details", details: error.message, className: "my-4" }) : hasExpired ? jsxRuntimeExports.jsx(ExpiredDataMessage, {}) : jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: resolvedAttributes.map((attribute) => jsxRuntimeExports.jsx(AttributeBlock, { isLoading, attribute, value: displayData[attribute], context: displayContext }, attribute)) })] }) }) }) });
|
|
2380
|
+
const isCopyableBasicAttribute = copyableBasicAttributes.has(attribute) && typeof displayValue === "string";
|
|
2381
|
+
const label = getAttributeDisplayName(attribute);
|
|
2382
|
+
return jsxRuntimeExports.jsx(DetailMonoKeyValueRow, { label, value: displayValue, copyText: isCopyableBasicAttribute ? displayValue : void 0, href: attribute === "moduleSpecifier" ? moduleSourceUrl : void 0 }, attribute);
|
|
2383
|
+
}), isLoading && resource === "sleep" && !displayData.resumeAt && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 py-0.5", children: [jsxRuntimeExports.jsx("span", { className: "text-label-13 text-gray-900", children: "Resume" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[55%]" })] })] }) })] }), error ? jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load resource details", details: error.message, className: "my-4" }) : hasExpired ? jsxRuntimeExports.jsx(ExpiredDataMessage, {}) : resolvedAttributes.length > 0 ? resolvedAttributes.map((attribute) => jsxRuntimeExports.jsx(AttributeBlock, { isLoading, attribute, value: displayData[attribute], context: displayContext }, attribute)) : null] }) }) }) });
|
|
1940
2384
|
};
|
|
1941
|
-
const
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
"
|
|
1950
|
-
"
|
|
1951
|
-
"
|
|
1952
|
-
"
|
|
1953
|
-
"
|
|
1954
|
-
|
|
1955
|
-
|
|
2385
|
+
const parseDateValue = (value) => {
|
|
2386
|
+
if (value == null)
|
|
2387
|
+
return null;
|
|
2388
|
+
const date = value instanceof Date ? value : new Date(String(value));
|
|
2389
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
2390
|
+
};
|
|
2391
|
+
const getEffectiveEventDate = (event) => parseDateValue(event.occurredAt) ?? new Date(event.createdAt);
|
|
2392
|
+
const formatEventTimestamp = (date) => date.toLocaleString(void 0, {
|
|
2393
|
+
month: "short",
|
|
2394
|
+
day: "numeric",
|
|
2395
|
+
hour: "numeric",
|
|
2396
|
+
minute: "numeric",
|
|
2397
|
+
second: "numeric",
|
|
2398
|
+
fractionalSecondDigits: 3,
|
|
2399
|
+
timeZoneName: "short"
|
|
2400
|
+
});
|
|
2401
|
+
function EventItem({ event, onLoadEventData, encryptionKey, showSeparateEventOccurrenceTimestamps = false }) {
|
|
1956
2402
|
const [loadedData, setLoadedData] = reactExports.useState(null);
|
|
1957
2403
|
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
1958
2404
|
const [loadError, setLoadError] = reactExports.useState(null);
|
|
@@ -1960,17 +2406,17 @@ function EventItem({ event, onLoadEventData, encryptionKey }) {
|
|
|
1960
2406
|
const loadedDataRef = reactExports.useRef(null);
|
|
1961
2407
|
const existingData = "eventData" in event && event.eventData != null ? event.eventData : null;
|
|
1962
2408
|
const mergedDisplay = loadedData ?? existingData;
|
|
1963
|
-
const canHaveData =
|
|
1964
|
-
const loadEventData = reactExports.useCallback(async (
|
|
1965
|
-
if (!onLoadEventData
|
|
2409
|
+
const canHaveData = existingData !== null || getEventDataRefFields(event.eventType).length > 0;
|
|
2410
|
+
const loadEventData = reactExports.useCallback(async (force) => {
|
|
2411
|
+
if (!onLoadEventData)
|
|
1966
2412
|
return;
|
|
1967
|
-
if (!
|
|
2413
|
+
if (!force && loadedDataRef.current !== null) {
|
|
1968
2414
|
return;
|
|
1969
2415
|
}
|
|
1970
2416
|
try {
|
|
1971
2417
|
setIsLoading(true);
|
|
1972
2418
|
setLoadError(null);
|
|
1973
|
-
const data = await onLoadEventData(event
|
|
2419
|
+
const data = await onLoadEventData(event);
|
|
1974
2420
|
loadedDataRef.current = data;
|
|
1975
2421
|
setLoadedData(data);
|
|
1976
2422
|
} catch (err) {
|
|
@@ -1978,122 +2424,244 @@ function EventItem({ event, onLoadEventData, encryptionKey }) {
|
|
|
1978
2424
|
} finally {
|
|
1979
2425
|
setIsLoading(false);
|
|
1980
2426
|
}
|
|
1981
|
-
}, [onLoadEventData, event
|
|
1982
|
-
const handleExpand = reactExports.useCallback(
|
|
2427
|
+
}, [onLoadEventData, event]);
|
|
2428
|
+
const handleExpand = reactExports.useCallback(() => {
|
|
1983
2429
|
if (isLoading)
|
|
1984
2430
|
return;
|
|
1985
2431
|
wasExpandedRef.current = true;
|
|
1986
|
-
|
|
2432
|
+
void loadEventData(false);
|
|
1987
2433
|
}, [isLoading, loadEventData]);
|
|
1988
|
-
reactExports.
|
|
2434
|
+
reactExports.useLayoutEffect(() => {
|
|
1989
2435
|
if (!encryptionKey || !wasExpandedRef.current)
|
|
1990
2436
|
return;
|
|
1991
2437
|
loadedDataRef.current = null;
|
|
1992
2438
|
setLoadedData(null);
|
|
1993
|
-
void loadEventData(
|
|
2439
|
+
void loadEventData(true);
|
|
1994
2440
|
}, [encryptionKey, loadEventData]);
|
|
1995
2441
|
const createdAt = new Date(event.createdAt);
|
|
2442
|
+
const occurredAt = parseDateValue(event.occurredAt);
|
|
2443
|
+
const displayedCreatedAt = showSeparateEventOccurrenceTimestamps ? createdAt : getEffectiveEventDate(event);
|
|
2444
|
+
const displayedCreatedAtTime = displayedCreatedAt.toLocaleTimeString(void 0, {
|
|
2445
|
+
hour: "numeric",
|
|
2446
|
+
minute: "numeric",
|
|
2447
|
+
second: "numeric"
|
|
2448
|
+
});
|
|
1996
2449
|
const displayPayload = isLoading ? loadedData : mergedDisplay;
|
|
1997
|
-
return jsxRuntimeExports.jsxs(
|
|
2450
|
+
return jsxRuntimeExports.jsxs(CollapsibleRoot, { variant: "card", onOpenChange: canHaveData ? (open) => {
|
|
1998
2451
|
if (open)
|
|
1999
2452
|
handleExpand();
|
|
2000
|
-
} : void 0, children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-col
|
|
2001
|
-
borderColor: "var(--ds-gray-300)",
|
|
2002
|
-
backgroundColor: "var(--ds-gray-100)"
|
|
2003
|
-
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 px-2.5 py-1.5", style: { borderColor: "var(--ds-gray-300)" }, children: [jsxRuntimeExports.jsx("span", { className: "text-[13px] font-medium", style: { color: "var(--ds-gray-700)" }, children: "Event ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-[13px] font-mono", style: { color: "var(--ds-gray-1000)" }, title: event.eventId, children: event.eventId })] }), event.correlationId && jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 px-2.5 py-1.5", style: { borderColor: "var(--ds-gray-300)" }, children: [jsxRuntimeExports.jsx("span", { className: "text-[13px] font-medium", style: { color: "var(--ds-gray-700)" }, children: "Correlation ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-[13px] font-mono", style: { color: "var(--ds-gray-1000)" }, title: event.correlationId, children: event.correlationId })] })] }), isLoading && jsxRuntimeExports.jsxs("div", { className: "mt-2 rounded-md border p-3", style: {
|
|
2004
|
-
borderColor: "var(--ds-gray-300)"
|
|
2005
|
-
}, children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[35%]" }), jsxRuntimeExports.jsx(Skeleton, { className: "mt-2 h-4 w-[90%]" }), jsxRuntimeExports.jsx(Skeleton, { className: "mt-2 h-4 w-[75%]" })] }), loadError && jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load event data", details: loadError, className: "mt-2" }), displayPayload != null && jsxRuntimeExports.jsx("div", { className: "mt-2", children: jsxRuntimeExports.jsx(EventDataBlock, { eventType: event.eventType, data: displayPayload }) })] });
|
|
2453
|
+
} : void 0, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { className: "px-3 py-2", children: jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center justify-between gap-3", children: [jsxRuntimeExports.jsx("span", { className: "text-gray-1000 text-label-12 font-mono", children: event.eventType }), jsxRuntimeExports.jsx("span", { className: "shrink-0 text-label-13 text-gray-900", children: displayedCreatedAtTime })] }) }), jsxRuntimeExports.jsxs(CollapsibleContent, { children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-col bg-background-200 [&:has(+_*)]:border-b [&:has(+_*)]:border-gray-alpha-400", children: [showSeparateEventOccurrenceTimestamps && occurredAt && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Occurred" }), jsxRuntimeExports.jsx(TimestampTooltip, { date: occurredAt, children: jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: formatEventTimestamp(occurredAt) }) })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Event ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: event.eventId })] }), event.correlationId && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Correlation ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: event.correlationId })] })] }), isLoading && jsxRuntimeExports.jsxs("div", { className: "p-3", children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[35%]" }), jsxRuntimeExports.jsx(Skeleton, { className: "mt-2 h-4 w-[90%]" }), jsxRuntimeExports.jsx(Skeleton, { className: "mt-2 h-4 w-[75%]" })] }), loadError && jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load event data", details: loadError, className: "mt-2" }), displayPayload != null && jsxRuntimeExports.jsx("div", { className: "[&>div]:border-none [&>div]:rounded-none", children: jsxRuntimeExports.jsx(EventDataBlock, { eventType: event.eventType, data: displayPayload }) })] })] });
|
|
2006
2454
|
}
|
|
2007
2455
|
function hasOnlyExpiredFields(data, eventType) {
|
|
2008
2456
|
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2009
2457
|
return false;
|
|
2010
2458
|
}
|
|
2011
2459
|
const record = data;
|
|
2012
|
-
const refKeys =
|
|
2460
|
+
const refKeys = getEventDataRefFields(eventType);
|
|
2013
2461
|
const presentKeys = refKeys.filter((k) => k in record);
|
|
2014
2462
|
return presentKeys.length > 0 && presentKeys.every((k) => isExpiredMarker(record[k]));
|
|
2015
2463
|
}
|
|
2016
2464
|
function EventDataBlock({ eventType, data }) {
|
|
2017
2465
|
if (isExpiredMarker(data) || hasOnlyExpiredFields(data, eventType)) {
|
|
2018
|
-
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-
|
|
2466
|
+
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-label-12", style: {
|
|
2019
2467
|
borderColor: "var(--ds-gray-300)",
|
|
2020
2468
|
backgroundColor: "var(--ds-gray-100)",
|
|
2021
2469
|
color: "var(--ds-gray-700)"
|
|
2022
2470
|
}, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
|
|
2023
2471
|
}
|
|
2024
|
-
if (
|
|
2472
|
+
if (hasEncryptedFields({ eventType, eventData: data })) {
|
|
2473
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
2474
|
+
}
|
|
2475
|
+
if (eventType === "attr_set") {
|
|
2476
|
+
return jsxRuntimeExports.jsx(AttrSetEventBlock, { data });
|
|
2477
|
+
}
|
|
2478
|
+
if (getEventDataRefFields(eventType).includes("error") && data != null && typeof data === "object") {
|
|
2025
2479
|
const record = data;
|
|
2026
|
-
if (
|
|
2480
|
+
if (isStructuredError(record.error)) {
|
|
2027
2481
|
return jsxRuntimeExports.jsx(ErrorStackBlock, { value: record.error });
|
|
2028
2482
|
}
|
|
2029
|
-
if (
|
|
2483
|
+
if (isStructuredError(record)) {
|
|
2030
2484
|
return jsxRuntimeExports.jsx(ErrorStackBlock, { value: record });
|
|
2031
2485
|
}
|
|
2032
2486
|
}
|
|
2033
2487
|
return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
|
|
2034
2488
|
}
|
|
2035
|
-
function EventsList({ events, isLoading = false, error, onLoadEventData, encryptionKey }) {
|
|
2036
|
-
const sortedEvents = reactExports.useMemo(() => [...events].sort((a, b) =>
|
|
2037
|
-
|
|
2489
|
+
function EventsList({ events, isLoading = false, error, onLoadEventData, onStreamClick, onRunClick, encryptionKey, showSeparateEventOccurrenceTimestamps = false }) {
|
|
2490
|
+
const sortedEvents = reactExports.useMemo(() => [...events].sort((a, b) => getEffectiveEventDate(a).getTime() - getEffectiveEventDate(b).getTime()), [events]);
|
|
2491
|
+
const hasEvents = sortedEvents.length > 0 && !error;
|
|
2492
|
+
if (!hasEvents && !isLoading) {
|
|
2493
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Events", disabled: true });
|
|
2494
|
+
}
|
|
2495
|
+
return jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsxs(CollapsibleRoot, { defaultOpen: true, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { children: "Events" }), jsxRuntimeExports.jsx(CollapsibleContent, { className: "mb-0", children: isLoading ? jsxRuntimeExports.jsx("div", { className: "flex flex-col -mx-4", children: [0, 1, 2].map((i) => jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 bg-background-200 px-4 py-2", children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-32 rounded" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3 w-16 rounded" })] }, i)) }) : jsxRuntimeExports.jsx("div", { className: "flex flex-col -mx-4", children: sortedEvents.map((event) => jsxRuntimeExports.jsx(EventItem, { event, onLoadEventData, encryptionKey, showSeparateEventOccurrenceTimestamps }, event.eventId)) }) })] }) }) });
|
|
2496
|
+
}
|
|
2497
|
+
const hasField = (value, key) => key in value;
|
|
2498
|
+
const RESOURCES_WITH_FETCHED_DETAIL = /* @__PURE__ */ new Set(["run", "step", "sleep"]);
|
|
2499
|
+
function resourceNeedsFetchedDetail(resource) {
|
|
2500
|
+
return resource !== void 0 && RESOURCES_WITH_FETCHED_DETAIL.has(resource);
|
|
2501
|
+
}
|
|
2502
|
+
function deriveSpanDetailView(args) {
|
|
2503
|
+
const { resource, resourceId, inlineData, fetchedDetail, fetchedError } = args;
|
|
2504
|
+
const matchedDetail = spanDetailMatchesSelection(fetchedDetail, resource, resourceId) ? fetchedDetail : null;
|
|
2505
|
+
const displayData = mergeSpanDetail(inlineData, matchedDetail);
|
|
2506
|
+
if (!resource || !resourceId) {
|
|
2507
|
+
return { status: "idle", displayData, detail: null, error: void 0 };
|
|
2508
|
+
}
|
|
2509
|
+
if (fetchedError) {
|
|
2510
|
+
return {
|
|
2511
|
+
status: "error",
|
|
2512
|
+
displayData,
|
|
2513
|
+
detail: matchedDetail,
|
|
2514
|
+
error: fetchedError
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
if (!resourceNeedsFetchedDetail(resource)) {
|
|
2518
|
+
return {
|
|
2519
|
+
status: "ready",
|
|
2520
|
+
displayData,
|
|
2521
|
+
detail: matchedDetail,
|
|
2522
|
+
error: void 0
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
if (matchedDetail !== null) {
|
|
2526
|
+
return {
|
|
2527
|
+
status: "ready",
|
|
2528
|
+
displayData,
|
|
2529
|
+
detail: matchedDetail,
|
|
2530
|
+
error: void 0
|
|
2531
|
+
};
|
|
2532
|
+
}
|
|
2533
|
+
return { status: "loading", displayData, detail: null, error: void 0 };
|
|
2534
|
+
}
|
|
2535
|
+
function spanDetailMatchesSelection(detail, resource, resourceId) {
|
|
2536
|
+
if (!detail || typeof detail !== "object" || !resource || !resourceId) {
|
|
2537
|
+
return false;
|
|
2538
|
+
}
|
|
2539
|
+
switch (resource) {
|
|
2540
|
+
case "step":
|
|
2541
|
+
return hasField(detail, "stepId") && detail.stepId === resourceId;
|
|
2542
|
+
case "hook":
|
|
2543
|
+
return hasField(detail, "hookId") && detail.hookId === resourceId;
|
|
2544
|
+
case "sleep":
|
|
2545
|
+
return hasField(detail, "waitId") && detail.waitId === resourceId;
|
|
2546
|
+
case "run":
|
|
2547
|
+
return hasField(detail, "runId") && !("stepId" in detail) && !("hookId" in detail) && !("waitId" in detail) && detail.runId === resourceId;
|
|
2548
|
+
default:
|
|
2549
|
+
return false;
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
function mergeSpanDetail(spanData, detail) {
|
|
2553
|
+
if (!detail || typeof detail !== "object") {
|
|
2554
|
+
return spanData;
|
|
2555
|
+
}
|
|
2556
|
+
if (!spanData || typeof spanData !== "object") {
|
|
2557
|
+
return detail;
|
|
2558
|
+
}
|
|
2559
|
+
const merged = { ...detail };
|
|
2560
|
+
for (const [key, value] of Object.entries(spanData)) {
|
|
2561
|
+
if (value !== void 0) {
|
|
2562
|
+
merged[key] = value;
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
return merged;
|
|
2038
2566
|
}
|
|
2039
|
-
function
|
|
2040
|
-
|
|
2567
|
+
function deriveSpanSelection(selectedSpan) {
|
|
2568
|
+
if (!selectedSpan)
|
|
2569
|
+
return null;
|
|
2570
|
+
const { resource, data } = selectedSpan;
|
|
2571
|
+
if (resource === "step" && data && typeof data === "object" && "stepId" in data) {
|
|
2572
|
+
const step = data;
|
|
2573
|
+
return { resource: "step", resourceId: step.stepId, runId: step.runId };
|
|
2574
|
+
}
|
|
2575
|
+
if (resource === "run" && data && typeof data === "object" && "runId" in data) {
|
|
2576
|
+
return { resource: "run", resourceId: data.runId };
|
|
2577
|
+
}
|
|
2578
|
+
if (resource === "hook" && data && typeof data === "object" && "hookId" in data) {
|
|
2579
|
+
return { resource: "hook", resourceId: data.hookId };
|
|
2580
|
+
}
|
|
2581
|
+
if (resource === "sleep") {
|
|
2582
|
+
if (!selectedSpan.spanId)
|
|
2583
|
+
return null;
|
|
2584
|
+
const waitData = data;
|
|
2585
|
+
return {
|
|
2586
|
+
resource: "sleep",
|
|
2587
|
+
resourceId: selectedSpan.spanId,
|
|
2588
|
+
runId: waitData == null ? void 0 : waitData.runId
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
return null;
|
|
2041
2592
|
}
|
|
2042
|
-
function
|
|
2043
|
-
|
|
2593
|
+
function useSelectedSpanDetail(selectedSpan, fetchSpanDetail) {
|
|
2594
|
+
const selection = reactExports.useMemo(() => deriveSpanSelection(selectedSpan), [selectedSpan]);
|
|
2595
|
+
const resource = selection == null ? void 0 : selection.resource;
|
|
2596
|
+
const resourceId = selection == null ? void 0 : selection.resourceId;
|
|
2597
|
+
const runId = selection == null ? void 0 : selection.runId;
|
|
2598
|
+
const selectionKey = resource && resourceId ? `${resource}:${resourceId}` : null;
|
|
2599
|
+
const needsFetch = resourceNeedsFetchedDetail(resource);
|
|
2600
|
+
const [fetched, setFetched] = reactExports.useState({ detail: null, error: null, errorKey: null });
|
|
2601
|
+
const tokenRef = reactExports.useRef(0);
|
|
2602
|
+
const selectionRef = reactExports.useRef(selection);
|
|
2603
|
+
selectionRef.current = selection;
|
|
2604
|
+
reactExports.useEffect(() => {
|
|
2605
|
+
if (!selectionKey || !needsFetch) {
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2608
|
+
const activeSelection = selectionRef.current;
|
|
2609
|
+
if (!activeSelection) {
|
|
2610
|
+
return;
|
|
2611
|
+
}
|
|
2612
|
+
const token = ++tokenRef.current;
|
|
2613
|
+
fetchSpanDetail(activeSelection).then((detail) => {
|
|
2614
|
+
if (tokenRef.current !== token)
|
|
2615
|
+
return;
|
|
2616
|
+
setFetched({ detail, error: null, errorKey: null });
|
|
2617
|
+
}).catch((err) => {
|
|
2618
|
+
if (tokenRef.current !== token)
|
|
2619
|
+
return;
|
|
2620
|
+
setFetched({
|
|
2621
|
+
detail: null,
|
|
2622
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
2623
|
+
errorKey: selectionKey
|
|
2624
|
+
});
|
|
2625
|
+
});
|
|
2626
|
+
}, [selectionKey, runId, needsFetch, fetchSpanDetail]);
|
|
2627
|
+
const scopedError = fetched.errorKey === selectionKey ? fetched.error : null;
|
|
2628
|
+
const view = reactExports.useMemo(() => deriveSpanDetailView({
|
|
2629
|
+
resource,
|
|
2630
|
+
resourceId,
|
|
2631
|
+
inlineData: selectedSpan == null ? void 0 : selectedSpan.data,
|
|
2632
|
+
fetchedDetail: fetched.detail,
|
|
2633
|
+
fetchedError: scopedError
|
|
2634
|
+
}), [resource, resourceId, selectedSpan == null ? void 0 : selectedSpan.data, fetched.detail, scopedError]);
|
|
2635
|
+
return {
|
|
2636
|
+
status: view.status,
|
|
2637
|
+
resource,
|
|
2638
|
+
resourceId,
|
|
2639
|
+
runId,
|
|
2640
|
+
displayData: view.displayData,
|
|
2641
|
+
detail: view.detail,
|
|
2642
|
+
error: view.error
|
|
2643
|
+
};
|
|
2044
2644
|
}
|
|
2045
2645
|
function isHook(data) {
|
|
2046
2646
|
return data !== null && typeof data === "object" && "hookId" in data;
|
|
2047
2647
|
}
|
|
2048
|
-
function EntityDetailPanel({ run, onStreamClick, onRunClick,
|
|
2648
|
+
function EntityDetailPanel({ run, onStreamClick, onRunClick, fetchSpanDetail, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan, showSeparateEventOccurrenceTimestamps = false, getModuleSourceUrl }) {
|
|
2049
2649
|
const toast2 = useToast();
|
|
2050
2650
|
const [stoppingSleep, setStoppingSleep] = reactExports.useState(false);
|
|
2051
2651
|
const [showResolveHookModal, setShowResolveHookModal] = reactExports.useState(false);
|
|
2052
2652
|
const [resolvingHook, setResolvingHook] = reactExports.useState(false);
|
|
2053
2653
|
const [resolvedHookIds, setResolvedHookIds] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
2654
|
+
const sidebar = useSidebarDataOptional();
|
|
2655
|
+
const hasEncryptedData = Boolean((sidebar == null ? void 0 : sidebar.hasEncryptedData) && !encryptionKey);
|
|
2054
2656
|
const data = selectedSpan == null ? void 0 : selectedSpan.data;
|
|
2055
2657
|
const rawEvents = selectedSpan == null ? void 0 : selectedSpan.rawEvents;
|
|
2056
2658
|
const rawEventsLength = (rawEvents == null ? void 0 : rawEvents.length) ?? 0;
|
|
2057
|
-
const { resource, resourceId,
|
|
2058
|
-
|
|
2059
|
-
return { resource: void 0, resourceId: void 0, runId: void 0 };
|
|
2060
|
-
}
|
|
2061
|
-
const res = selectedSpan.resource;
|
|
2062
|
-
if (res === "step" && isStep(data)) {
|
|
2063
|
-
return { resource: "step", resourceId: data.stepId, runId: data.runId };
|
|
2064
|
-
}
|
|
2065
|
-
if (res === "run" && isWorkflowRun(data)) {
|
|
2066
|
-
return { resource: "run", resourceId: data.runId, runId: void 0 };
|
|
2067
|
-
}
|
|
2068
|
-
if (res === "hook" && isHook(data)) {
|
|
2069
|
-
return { resource: "hook", resourceId: data.hookId, runId: void 0 };
|
|
2070
|
-
}
|
|
2071
|
-
if (res === "sleep") {
|
|
2072
|
-
const waitData = data;
|
|
2073
|
-
return {
|
|
2074
|
-
resource: "sleep",
|
|
2075
|
-
resourceId: selectedSpan.spanId,
|
|
2076
|
-
runId: waitData == null ? void 0 : waitData.runId
|
|
2077
|
-
};
|
|
2078
|
-
}
|
|
2079
|
-
return { resource: void 0, resourceId: void 0, runId: void 0 };
|
|
2080
|
-
}, [selectedSpan, data]);
|
|
2081
|
-
const onSpanSelectRef = reactExports.useRef(onSpanSelect);
|
|
2082
|
-
onSpanSelectRef.current = onSpanSelect;
|
|
2083
|
-
reactExports.useEffect(() => {
|
|
2084
|
-
if (resource && resourceId && ["run", "step", "hook", "sleep"].includes(resource)) {
|
|
2085
|
-
onSpanSelectRef.current({
|
|
2086
|
-
resource,
|
|
2087
|
-
resourceId,
|
|
2088
|
-
runId
|
|
2089
|
-
});
|
|
2090
|
-
}
|
|
2091
|
-
}, [resource, resourceId, runId]);
|
|
2659
|
+
const { status, resource, resourceId, displayData, detail: matchedSpanDetailData, error } = useSelectedSpanDetail(selectedSpan, fetchSpanDetail);
|
|
2660
|
+
const loading = status === "loading";
|
|
2092
2661
|
const canWakeUp = reactExports.useMemo(() => {
|
|
2093
2662
|
if (resource !== "sleep" || !rawEvents)
|
|
2094
2663
|
return false;
|
|
2095
|
-
|
|
2096
|
-
if (terminalStates.includes(run.status))
|
|
2664
|
+
if (isTerminalWorkflowRunStatus(run.status))
|
|
2097
2665
|
return false;
|
|
2098
2666
|
const hasWaitCreated = rawEvents.some((e) => e.eventType === "wait_created");
|
|
2099
2667
|
if (!hasWaitCreated)
|
|
@@ -2106,8 +2674,7 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spa
|
|
|
2106
2674
|
return false;
|
|
2107
2675
|
if (resolvedHookIds.has(resourceId))
|
|
2108
2676
|
return false;
|
|
2109
|
-
|
|
2110
|
-
if (terminalStates.includes(run.status))
|
|
2677
|
+
if (isTerminalWorkflowRunStatus(run.status))
|
|
2111
2678
|
return false;
|
|
2112
2679
|
const hasHookDisposed = rawEvents.some((e) => e.eventType === "hook_disposed");
|
|
2113
2680
|
if (hasHookDisposed)
|
|
@@ -2121,19 +2688,17 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spa
|
|
|
2121
2688
|
run.status,
|
|
2122
2689
|
resolvedHookIds
|
|
2123
2690
|
]);
|
|
2124
|
-
const error = spanDetailError ?? void 0;
|
|
2125
|
-
const loading = spanDetailLoading ?? false;
|
|
2126
2691
|
const hookToken = reactExports.useMemo(() => {
|
|
2127
2692
|
if (resource !== "hook" || !resourceId)
|
|
2128
2693
|
return void 0;
|
|
2129
|
-
if (isHook(
|
|
2130
|
-
return
|
|
2694
|
+
if (isHook(matchedSpanDetailData) && matchedSpanDetailData.token) {
|
|
2695
|
+
return matchedSpanDetailData.token;
|
|
2131
2696
|
}
|
|
2132
2697
|
if (isHook(data) && data.token) {
|
|
2133
2698
|
return data.token;
|
|
2134
2699
|
}
|
|
2135
2700
|
return void 0;
|
|
2136
|
-
}, [resource, resourceId,
|
|
2701
|
+
}, [resource, resourceId, matchedSpanDetailData, data]);
|
|
2137
2702
|
reactExports.useEffect(() => {
|
|
2138
2703
|
if (error && selectedSpan && resource) {
|
|
2139
2704
|
toast2.error(`Failed to load ${resource} details`, {
|
|
@@ -2188,7 +2753,7 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spa
|
|
|
2188
2753
|
}
|
|
2189
2754
|
try {
|
|
2190
2755
|
setResolvingHook(true);
|
|
2191
|
-
const candidate =
|
|
2756
|
+
const candidate = matchedSpanDetailData ?? data;
|
|
2192
2757
|
const hook = isHook(candidate) ? candidate : void 0;
|
|
2193
2758
|
await onResolveHook(hookToken, payload, hook);
|
|
2194
2759
|
toast2.success("Hook resolved", {
|
|
@@ -2206,8 +2771,7 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spa
|
|
|
2206
2771
|
} finally {
|
|
2207
2772
|
setResolvingHook(false);
|
|
2208
2773
|
}
|
|
2209
|
-
}, [onResolveHook, hookToken, resolvingHook,
|
|
2210
|
-
const displayData = spanDetailData ?? data;
|
|
2774
|
+
}, [onResolveHook, hookToken, resolvingHook, matchedSpanDetailData, data]);
|
|
2211
2775
|
const moduleSpecifier = reactExports.useMemo(() => {
|
|
2212
2776
|
const displayRecord = displayData;
|
|
2213
2777
|
const displayStepName = displayRecord.stepName;
|
|
@@ -2217,391 +2781,353 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spa
|
|
|
2217
2781
|
}
|
|
2218
2782
|
if (typeof displayWorkflowName === "string") {
|
|
2219
2783
|
return displayWorkflowName;
|
|
2220
|
-
}
|
|
2221
|
-
if (typeof run.workflowName === "string") {
|
|
2222
|
-
return run.workflowName;
|
|
2223
|
-
}
|
|
2224
|
-
return void 0;
|
|
2225
|
-
}, [displayData, run.workflowName]);
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
}, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsx("section", { children: jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, expiredAt: run.expiredAt, isLoading: loading, error: error ?? void 0, onStreamClick, onRunClick, onDecrypt, isDecrypting, resource }) }), resource !== "run" && rawEvents && jsxRuntimeExports.jsx("section", { children: jsxRuntimeExports.jsx(EventsList, { events: rawEvents, onLoadEventData, encryptionKey }) })] })] }) }), jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: showResolveHookModal, onClose: () => setShowResolveHookModal(false), onSubmit: handleResolveHook, isSubmitting: resolvingHook })] });
|
|
2240
|
-
}
|
|
2241
|
-
function CopyButton({ copyText, ariaLabel, className }) {
|
|
2242
|
-
const [copied, setCopied] = reactExports.useState(false);
|
|
2243
|
-
const timeoutRef = reactExports.useRef(null);
|
|
2244
|
-
reactExports.useEffect(() => {
|
|
2245
|
-
return () => {
|
|
2246
|
-
if (timeoutRef.current) {
|
|
2247
|
-
clearTimeout(timeoutRef.current);
|
|
2248
|
-
}
|
|
2249
|
-
};
|
|
2250
|
-
}, []);
|
|
2251
|
-
return jsxRuntimeExports.jsx("button", { type: "button", "aria-label": ariaLabel, className: cn("cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-none p-1 m-0", className), onClick: (e) => {
|
|
2252
|
-
e.stopPropagation();
|
|
2253
|
-
if (timeoutRef.current) {
|
|
2254
|
-
clearTimeout(timeoutRef.current);
|
|
2255
|
-
}
|
|
2256
|
-
void navigator.clipboard.writeText(copyText).then(() => {
|
|
2257
|
-
setCopied(true);
|
|
2258
|
-
timeoutRef.current = setTimeout(() => setCopied(false), 1e3);
|
|
2259
|
-
});
|
|
2260
|
-
}, children: jsxRuntimeExports.jsxs("div", { className: "relative w-3 h-3", children: [jsxRuntimeExports.jsx("div", { className: cn("absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out", copied ? "scale-100 opacity-100" : "scale-0 opacity-0"), children: jsxRuntimeExports.jsx(Check, { className: "w-3 h-3" }) }), jsxRuntimeExports.jsx("div", { className: cn("absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out", copied ? "scale-0 opacity-0" : "scale-100 opacity-100"), children: jsxRuntimeExports.jsx(Copy, { className: "w-3 h-3" }) })] }) });
|
|
2261
|
-
}
|
|
2262
|
-
const WorkflowIcon = () => {
|
|
2263
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", "stroke-linejoin": "round", style: { color: "currentColor" }, viewBox: "0 0 16 16", width: "16", children: jsxRuntimeExports.jsx("path", { d: "M5.75 7L6.4209 7.33594L4.85254 10.4717C5.38789 10.771 5.75 11.3431 5.75 12V14C5.75 14.9665 4.96648 15.75 4 15.75H2C1.03352 15.75 0.25 14.9665 0.25 14V12C0.25 11.0335 1.03352 10.25 2 10.25H3.28711L5.0791 6.66504L5.75 7ZM14 10.25C14.9665 10.25 15.75 11.0335 15.75 12V14C15.75 14.9665 14.9665 15.75 14 15.75H12C11.1185 15.75 10.3909 15.098 10.2695 14.25H7V12.75H10.25V12C10.25 11.0335 11.0335 10.25 12 10.25H14ZM2 11.75C1.86192 11.75 1.75 11.8619 1.75 12V14C1.75 14.1381 1.86192 14.25 2 14.25H4C4.13808 14.25 4.25 14.1381 4.25 14V12C4.25 11.8619 4.13808 11.75 4 11.75H2ZM12 11.75C11.8619 11.75 11.75 11.8619 11.75 12V14C11.75 14.1381 11.8619 14.25 12 14.25H14C14.1381 14.25 14.25 14.1381 14.25 14V12C14.25 11.8619 14.1381 11.75 14 11.75H12ZM9 0.25C9.96649 0.25 10.75 1.03351 10.75 2V4C10.75 4.44642 10.5808 4.85197 10.3057 5.16113L12.2041 8.6416L10.8877 9.36035L8.91895 5.75H7C6.03351 5.75 5.25 4.96649 5.25 4V2C5.25 1.03351 6.03351 0.25 7 0.25H9ZM7 1.75C6.86193 1.75 6.75 1.86193 6.75 2V4C6.75 4.13807 6.86193 4.25 7 4.25H9C9.13807 4.25 9.25 4.13807 9.25 4V2C9.25 1.86193 9.13807 1.75 9 1.75H7Z", fill: "currentColor" }) });
|
|
2264
|
-
};
|
|
2265
|
-
const WebhookIcon = () => {
|
|
2266
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", "stroke-linejoin": "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M5.8349 3.24994C5.14454 4.44567 5.55423 5.97464 6.74996 6.665L7.39465 7.03721L7.02726 7.68466L5.14599 11C5.21289 11.1531 5.25 11.3222 5.25 11.5C5.25 12.1904 4.69036 12.75 4 12.75C3.30964 12.75 2.75 12.1904 2.75 11.5C2.75 10.8634 3.22584 10.338 3.84123 10.26L5.38944 7.5316C3.95909 6.30274 3.55857 4.19264 4.53586 2.49994C5.64043 0.586765 8.08679 -0.0687357 9.99996 1.03583C11.836 2.09584 12.5137 4.39156 11.5892 6.26591L10.4949 4.33754C10.4418 3.53274 10.0009 2.76843 9.24996 2.33487C8.05423 1.64452 6.52525 2.0542 5.8349 3.24994ZM9.146 4.99996C9.21289 4.84686 9.25 4.67776 9.25 4.5C9.25 3.80964 8.69036 3.25 8 3.25C7.30964 3.25 6.75 3.80964 6.75 4.5C6.75 5.13659 7.22586 5.66203 7.84127 5.74002L9.72266 9.05556L10.0956 9.71274L10.75 9.33493C11.9457 8.64458 13.4747 9.05427 14.165 10.25C14.8554 11.4457 14.4457 12.9747 13.25 13.6651C12.5047 14.0953 11.63 14.0983 10.9096 13.75H8.69252C9.85895 15.4685 12.1727 16.0191 14 14.9641C15.9131 13.8595 16.5686 11.4132 15.4641 9.5C14.4886 7.81038 12.4665 7.10169 10.6895 7.71998L9.146 4.99996ZM13.25 11.5C13.25 12.1904 12.6904 12.75 12 12.75C11.591 12.75 11.228 12.5536 10.9999 12.25H7.9298C7.57875 14.1006 5.95279 15.5 4 15.5C1.79086 15.5 0 13.7091 0 11.5C0 9.40018 1.61801 7.67826 3.67529 7.51299L2.58098 9.44147C1.92792 9.89251 1.5 10.6463 1.5 11.5C1.5 12.8807 2.61929 14 4 14C5.38071 14 6.5 12.8807 6.5 11.5V10.75H7.25H10.9999C11.228 10.4464 11.591 10.25 12 10.25C12.6904 10.25 13.25 10.8096 13.25 11.5Z", fill: "currentColor" }) });
|
|
2267
|
-
};
|
|
2268
|
-
const SleepIcon = () => {
|
|
2269
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7.25 1.25V2.03971C5.87928 2.18571 4.62678 2.72736 3.6089 3.54824L3.03033 2.96967L2.5 2.43934L1.43934 3.5L1.96967 4.03033L2.54824 4.6089C1.57979 5.80976 1 7.33717 1 9C1 12.866 4.13401 16 8 16C11.866 16 15 12.866 15 9C15 7.33717 14.4202 5.80976 13.4518 4.6089L14.0303 4.03033L14.5607 3.5L13.5 2.43934L12.9697 2.96967L12.3911 3.54824C11.3732 2.72736 10.1207 2.18571 8.75 2.03971V1.25H9.25H10V-0.25H9.25H8.75H7.25H6.75H6V1.25H6.75H7.25ZM2.5 9C2.5 5.96243 4.96243 3.5 8 3.5C11.0376 3.5 13.5 5.96243 13.5 9C13.5 12.0376 11.0376 14.5 8 14.5C4.96243 14.5 2.5 12.0376 2.5 9ZM8.75 6.75V6H7.25V6.75V9V9.75H8.75V9V6.75Z", fill: "currentColor" }) });
|
|
2270
|
-
};
|
|
2271
|
-
const StepForwardIcon = () => {
|
|
2272
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.21969 12.5303L4.75002 13.0607L5.81068 12L5.28035 11.4697L1.81068 7.99999L5.28035 4.53032L5.81068 3.99999L4.75002 2.93933L4.21969 3.46966L0.39647 7.29289C0.00594562 7.68341 0.00594562 8.31658 0.39647 8.7071L4.21969 12.5303ZM11.7804 12.5303L11.25 13.0607L10.1894 12L10.7197 11.4697L14.1894 7.99999L10.7197 4.53032L10.1894 3.99999L11.25 2.93933L11.7804 3.46966L15.6036 7.29289C15.9941 7.68341 15.9941 8.31658 15.6036 8.7071L11.7804 12.5303Z", fill: "currentColor" }) });
|
|
2273
|
-
};
|
|
2274
|
-
const ELLIPSIS = "...";
|
|
2275
|
-
const MIN_START = 3;
|
|
2276
|
-
const MIN_END = 3;
|
|
2277
|
-
const MIN_KEPT = MIN_START + MIN_END;
|
|
2278
|
-
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
2279
|
-
function toGraphemes(text) {
|
|
2280
|
-
if (graphemeSegmenter) {
|
|
2281
|
-
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
2282
|
-
}
|
|
2283
|
-
return Array.from(text);
|
|
2284
|
-
}
|
|
2285
|
-
function buildCandidate(graphemes, kept) {
|
|
2286
|
-
if (kept <= 0) {
|
|
2287
|
-
return {
|
|
2288
|
-
prefixText: "",
|
|
2289
|
-
prefixGraphemeCount: 0,
|
|
2290
|
-
suffixText: "",
|
|
2291
|
-
suffixGraphemeCount: 0,
|
|
2292
|
-
text: ELLIPSIS,
|
|
2293
|
-
truncated: true
|
|
2294
|
-
};
|
|
2295
|
-
}
|
|
2296
|
-
const suffixGraphemeCount = kept >= MIN_KEPT ? Math.max(MIN_END, Math.floor(kept / 2)) : Math.floor(kept / 2);
|
|
2297
|
-
const prefixGraphemeCount = kept - suffixGraphemeCount;
|
|
2298
|
-
const prefixText = graphemes.slice(0, prefixGraphemeCount).join("");
|
|
2299
|
-
const suffixText = suffixGraphemeCount > 0 ? graphemes.slice(-suffixGraphemeCount).join("") : "";
|
|
2300
|
-
return {
|
|
2301
|
-
prefixText,
|
|
2302
|
-
prefixGraphemeCount,
|
|
2303
|
-
suffixText,
|
|
2304
|
-
suffixGraphemeCount,
|
|
2305
|
-
text: prefixText + ELLIPSIS + suffixText,
|
|
2306
|
-
truncated: true
|
|
2307
|
-
};
|
|
2308
|
-
}
|
|
2309
|
-
function middleTruncate(graphemes, availableWidth, measure, fullWidth) {
|
|
2310
|
-
const fullText = graphemes.join("");
|
|
2311
|
-
const resolvedFullWidth = fullWidth ?? measure(fullText);
|
|
2312
|
-
if (availableWidth <= 0 || graphemes.length === 0) {
|
|
2313
|
-
return {
|
|
2314
|
-
prefixText: fullText,
|
|
2315
|
-
prefixGraphemeCount: graphemes.length,
|
|
2316
|
-
suffixText: "",
|
|
2317
|
-
suffixGraphemeCount: 0,
|
|
2318
|
-
text: fullText,
|
|
2319
|
-
truncated: false
|
|
2320
|
-
};
|
|
2321
|
-
}
|
|
2322
|
-
if (resolvedFullWidth <= availableWidth) {
|
|
2323
|
-
return {
|
|
2324
|
-
prefixText: fullText,
|
|
2325
|
-
prefixGraphemeCount: graphemes.length,
|
|
2326
|
-
suffixText: "",
|
|
2327
|
-
suffixGraphemeCount: 0,
|
|
2328
|
-
text: fullText,
|
|
2329
|
-
truncated: false
|
|
2330
|
-
};
|
|
2331
|
-
}
|
|
2332
|
-
let lo = 0;
|
|
2333
|
-
let hi = graphemes.length - 1;
|
|
2334
|
-
let best = -1;
|
|
2335
|
-
while (lo <= hi) {
|
|
2336
|
-
const mid = lo + hi >>> 1;
|
|
2337
|
-
const candidate = buildCandidate(graphemes, mid);
|
|
2338
|
-
if (measure(candidate.text) <= availableWidth) {
|
|
2339
|
-
best = mid;
|
|
2340
|
-
lo = mid + 1;
|
|
2341
|
-
} else {
|
|
2342
|
-
hi = mid - 1;
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
if (best === -1) {
|
|
2346
|
-
return {
|
|
2347
|
-
prefixText: "",
|
|
2348
|
-
prefixGraphemeCount: 0,
|
|
2349
|
-
suffixText: "",
|
|
2350
|
-
suffixGraphemeCount: 0,
|
|
2351
|
-
text: "",
|
|
2352
|
-
truncated: true
|
|
2353
|
-
};
|
|
2354
|
-
}
|
|
2355
|
-
return buildCandidate(graphemes, best);
|
|
2356
|
-
}
|
|
2357
|
-
function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value }) {
|
|
2358
|
-
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
2359
|
-
if (selectionStart < 0 || selectionEnd > visibleText.length || selectionStart >= selectionEnd) {
|
|
2360
|
-
return null;
|
|
2361
|
-
}
|
|
2362
|
-
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
2363
|
-
return value;
|
|
2364
|
-
}
|
|
2365
|
-
const ellipsisStart = prefixText.length;
|
|
2366
|
-
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
2367
|
-
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
2368
|
-
return null;
|
|
2369
|
-
}
|
|
2370
|
-
const originalGraphemes = toGraphemes(value);
|
|
2371
|
-
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
2372
|
-
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
2373
|
-
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
2374
|
-
return originalGraphemes.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount).join("");
|
|
2375
|
-
}
|
|
2376
|
-
function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value }) {
|
|
2377
|
-
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
2378
|
-
const trimmedSelectionText = selectionText.trim();
|
|
2379
|
-
if (!trimmedSelectionText) {
|
|
2380
|
-
return null;
|
|
2381
|
-
}
|
|
2382
|
-
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
2383
|
-
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
2384
|
-
if (trimmedSelectionText === visibleText) {
|
|
2385
|
-
return leading + value + trailing;
|
|
2386
|
-
}
|
|
2387
|
-
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
2784
|
+
}
|
|
2785
|
+
if (typeof run.workflowName === "string") {
|
|
2786
|
+
return run.workflowName;
|
|
2787
|
+
}
|
|
2788
|
+
return void 0;
|
|
2789
|
+
}, [displayData, run.workflowName]);
|
|
2790
|
+
const moduleSourceUrl = reactExports.useMemo(() => {
|
|
2791
|
+
if (!getModuleSourceUrl || !moduleSpecifier)
|
|
2792
|
+
return void 0;
|
|
2793
|
+
const parsed = parseStepName(moduleSpecifier) ?? parseWorkflowName(moduleSpecifier);
|
|
2794
|
+
if (!parsed)
|
|
2795
|
+
return void 0;
|
|
2796
|
+
const dataDeploymentId = displayData.deploymentId;
|
|
2797
|
+
return getModuleSourceUrl({
|
|
2798
|
+
moduleSpecifier: parsed.moduleSpecifier,
|
|
2799
|
+
deploymentId: typeof dataDeploymentId === "string" ? dataDeploymentId : run.deploymentId
|
|
2800
|
+
});
|
|
2801
|
+
}, [getModuleSourceUrl, moduleSpecifier, displayData, run.deploymentId]);
|
|
2802
|
+
if (!selectedSpan || !resource || !resourceId) {
|
|
2388
2803
|
return null;
|
|
2389
2804
|
}
|
|
2390
|
-
const
|
|
2391
|
-
|
|
2392
|
-
|
|
2805
|
+
const hasPendingActions = resource === "sleep" && canWakeUp || resource === "hook" && canResolveHook;
|
|
2806
|
+
return jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col", children: [jsxRuntimeExports.jsx(DecryptClickContext.Provider, { value: onDecrypt ? { onDecrypt, isDecrypting, hasEncryptedData } : void 0, children: jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto px-4 pb-8", children: [hasPendingActions && jsxRuntimeExports.jsxs("div", { className: "mb-4 rounded-lg border p-2", style: {
|
|
2807
|
+
borderColor: "var(--ds-gray-300)",
|
|
2808
|
+
backgroundColor: "var(--ds-gray-100)"
|
|
2809
|
+
}, children: [jsxRuntimeExports.jsx("p", { className: "mb-2 px-1 text-label-13 font-medium uppercase tracking-wide", style: { color: "var(--ds-gray-700)" }, children: "Actions" }), jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [resource === "sleep" && canWakeUp && jsxRuntimeExports.jsxs("button", { type: "button", onClick: handleWakeUp, disabled: stoppingSleep, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-button-14", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", stoppingSleep ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
|
|
2810
|
+
background: "var(--ds-amber-200)",
|
|
2811
|
+
color: "var(--ds-amber-900)"
|
|
2812
|
+
}, children: [jsxRuntimeExports.jsx(Zap, { className: "h-4 w-4" }), stoppingSleep ? "Waking up..." : "Wake Up Sleep"] }), resource === "hook" && canResolveHook && jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setShowResolveHookModal(true), disabled: resolvingHook, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-button-14", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", resolvingHook ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
|
|
2813
|
+
background: "var(--ds-gray-1000)",
|
|
2814
|
+
color: "var(--ds-background-100)"
|
|
2815
|
+
}, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, moduleSourceUrl, expiredAt: run.expiredAt, isLoading: loading, error: error ?? void 0, onStreamClick, onRunClick, onDecrypt, isDecrypting, resource }), rawEvents && jsxRuntimeExports.jsx(EventsList, { events: rawEvents, onLoadEventData, onStreamClick, onRunClick, encryptionKey, showSeparateEventOccurrenceTimestamps })] }) }), jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: showResolveHookModal, onClose: () => setShowResolveHookModal(false), onSubmit: handleResolveHook, isSubmitting: resolvingHook })] });
|
|
2816
|
+
}
|
|
2817
|
+
const PANEL_MIN_WIDTH = 280;
|
|
2818
|
+
const PANEL_HARD_MAX_WIDTH = 1300;
|
|
2819
|
+
const PANEL_DEFAULT_WIDTH = 360;
|
|
2820
|
+
const MAIN_MIN_WIDTH = 400;
|
|
2821
|
+
const PANEL_WIDTH_STORAGE_KEY = "workflow-trace-detail-panel-width";
|
|
2822
|
+
function clamp(value, min, max) {
|
|
2823
|
+
return Math.min(Math.max(value, min), max);
|
|
2824
|
+
}
|
|
2825
|
+
function computeMaxPanelWidth(availableWidth) {
|
|
2826
|
+
if (availableWidth <= 0)
|
|
2827
|
+
return PANEL_HARD_MAX_WIDTH;
|
|
2828
|
+
return Math.min(Math.max(availableWidth - MAIN_MIN_WIDTH, 0), PANEL_HARD_MAX_WIDTH);
|
|
2829
|
+
}
|
|
2830
|
+
function clampPanelWidth(width, availableWidth) {
|
|
2831
|
+
return clamp(width, PANEL_MIN_WIDTH, computeMaxPanelWidth(availableWidth));
|
|
2832
|
+
}
|
|
2833
|
+
function readStoredPanelWidth() {
|
|
2834
|
+
if (typeof window === "undefined")
|
|
2835
|
+
return PANEL_DEFAULT_WIDTH;
|
|
2836
|
+
try {
|
|
2837
|
+
const raw = window.localStorage.getItem(PANEL_WIDTH_STORAGE_KEY);
|
|
2838
|
+
const value = raw ? Number(raw) : Number.NaN;
|
|
2839
|
+
if (!Number.isFinite(value))
|
|
2840
|
+
return PANEL_DEFAULT_WIDTH;
|
|
2841
|
+
return clamp(value, PANEL_MIN_WIDTH, PANEL_HARD_MAX_WIDTH);
|
|
2842
|
+
} catch {
|
|
2843
|
+
return PANEL_DEFAULT_WIDTH;
|
|
2393
2844
|
}
|
|
2394
|
-
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
2395
|
-
const mappedText = getMiddleTruncateCopyText({
|
|
2396
|
-
prefixText,
|
|
2397
|
-
selectionEnd,
|
|
2398
|
-
selectionStart,
|
|
2399
|
-
suffixText,
|
|
2400
|
-
value
|
|
2401
|
-
});
|
|
2402
|
-
return mappedText === null ? null : leading + mappedText + trailing;
|
|
2403
2845
|
}
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
suffixGraphemeCount: 0,
|
|
2412
|
-
suffixText: ""
|
|
2413
|
-
};
|
|
2846
|
+
function writeStoredPanelWidth(width) {
|
|
2847
|
+
if (typeof window === "undefined")
|
|
2848
|
+
return;
|
|
2849
|
+
try {
|
|
2850
|
+
window.localStorage.setItem(PANEL_WIDTH_STORAGE_KEY, String(Math.round(width)));
|
|
2851
|
+
} catch {
|
|
2852
|
+
}
|
|
2414
2853
|
}
|
|
2415
|
-
function
|
|
2416
|
-
const
|
|
2417
|
-
const
|
|
2418
|
-
const
|
|
2419
|
-
const
|
|
2420
|
-
const
|
|
2421
|
-
const rafRef = reactExports.useRef(
|
|
2422
|
-
const
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
}
|
|
2854
|
+
function DraggableBorder({ element, position, onWidthChange, onReset, "aria-label": ariaLabel, "aria-controls": ariaControls, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuenow": ariaValueNow }) {
|
|
2855
|
+
const [isDragging, setIsDragging] = reactExports.useState(false);
|
|
2856
|
+
const pointerIdRef = reactExports.useRef(null);
|
|
2857
|
+
const startXRef = reactExports.useRef(0);
|
|
2858
|
+
const startWidthRef = reactExports.useRef(0);
|
|
2859
|
+
const pendingWidthRef = reactExports.useRef(0);
|
|
2860
|
+
const rafRef = reactExports.useRef(null);
|
|
2861
|
+
const movedRef = reactExports.useRef(false);
|
|
2862
|
+
const lastDragEndAtRef = reactExports.useRef(0);
|
|
2863
|
+
reactExports.useEffect(() => {
|
|
2864
|
+
return () => {
|
|
2865
|
+
if (rafRef.current)
|
|
2866
|
+
cancelAnimationFrame(rafRef.current);
|
|
2867
|
+
};
|
|
2429
2868
|
}, []);
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
const measureEl = measureRef.current;
|
|
2433
|
-
if (!el || !measureEl)
|
|
2869
|
+
reactExports.useEffect(() => {
|
|
2870
|
+
if (!isDragging)
|
|
2434
2871
|
return;
|
|
2435
|
-
const
|
|
2436
|
-
|
|
2437
|
-
|
|
2872
|
+
const previous = document.body.style.userSelect;
|
|
2873
|
+
document.body.style.userSelect = "none";
|
|
2874
|
+
return () => {
|
|
2875
|
+
document.body.style.userSelect = previous;
|
|
2876
|
+
};
|
|
2877
|
+
}, [isDragging]);
|
|
2878
|
+
const stopDrag = () => {
|
|
2879
|
+
pointerIdRef.current = null;
|
|
2880
|
+
setIsDragging(false);
|
|
2881
|
+
if (rafRef.current) {
|
|
2882
|
+
cancelAnimationFrame(rafRef.current);
|
|
2883
|
+
rafRef.current = null;
|
|
2884
|
+
if (movedRef.current)
|
|
2885
|
+
onWidthChange(pendingWidthRef.current);
|
|
2886
|
+
}
|
|
2887
|
+
if (movedRef.current) {
|
|
2888
|
+
movedRef.current = false;
|
|
2889
|
+
lastDragEndAtRef.current = performance.now();
|
|
2890
|
+
}
|
|
2891
|
+
};
|
|
2892
|
+
const handlePointerDown = (e) => {
|
|
2893
|
+
if (pointerIdRef.current !== null)
|
|
2894
|
+
return;
|
|
2895
|
+
const el = element.current;
|
|
2896
|
+
if (!el)
|
|
2897
|
+
return;
|
|
2898
|
+
if (e.pointerType === "mouse" && e.button !== 0)
|
|
2899
|
+
return;
|
|
2900
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2901
|
+
pointerIdRef.current = e.pointerId;
|
|
2902
|
+
startXRef.current = e.clientX;
|
|
2903
|
+
startWidthRef.current = el.offsetWidth;
|
|
2904
|
+
movedRef.current = false;
|
|
2905
|
+
setIsDragging(true);
|
|
2906
|
+
};
|
|
2907
|
+
const handlePointerMove = (e) => {
|
|
2908
|
+
if (pointerIdRef.current !== e.pointerId)
|
|
2438
2909
|
return;
|
|
2910
|
+
if (Math.abs(e.clientX - startXRef.current) > 4) {
|
|
2911
|
+
movedRef.current = true;
|
|
2439
2912
|
}
|
|
2440
|
-
const
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2913
|
+
const delta = position === "left" ? startXRef.current - e.clientX : e.clientX - startXRef.current;
|
|
2914
|
+
pendingWidthRef.current = startWidthRef.current + delta;
|
|
2915
|
+
if (!rafRef.current) {
|
|
2916
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
2917
|
+
rafRef.current = null;
|
|
2918
|
+
onWidthChange(pendingWidthRef.current);
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
};
|
|
2922
|
+
const handlePointerEnd = (e) => {
|
|
2923
|
+
if (pointerIdRef.current !== e.pointerId)
|
|
2924
|
+
return;
|
|
2925
|
+
stopDrag();
|
|
2926
|
+
};
|
|
2927
|
+
const handleLostPointerCapture = (e) => {
|
|
2928
|
+
if (pointerIdRef.current !== null && e.pointerId !== pointerIdRef.current) {
|
|
2447
2929
|
return;
|
|
2448
2930
|
}
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
2454
|
-
prefixText: result.prefixText,
|
|
2455
|
-
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
2456
|
-
suffixText: result.suffixText
|
|
2457
|
-
});
|
|
2458
|
-
}, [fullState, graphemes, updateState, value]);
|
|
2459
|
-
useIsomorphicLayoutEffect(() => {
|
|
2460
|
-
recalculate();
|
|
2461
|
-
}, [recalculate]);
|
|
2462
|
-
reactExports.useEffect(() => {
|
|
2463
|
-
var _a;
|
|
2464
|
-
const el = ref.current;
|
|
2465
|
-
if (!el)
|
|
2931
|
+
stopDrag();
|
|
2932
|
+
};
|
|
2933
|
+
const handleDoubleClick = () => {
|
|
2934
|
+
if (movedRef.current || performance.now() - lastDragEndAtRef.current < 500) {
|
|
2466
2935
|
return;
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
rafRef.current = requestAnimationFrame(recalculate);
|
|
2470
|
-
};
|
|
2471
|
-
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(debouncedRecalc) : null;
|
|
2472
|
-
ro == null ? void 0 : ro.observe(el);
|
|
2473
|
-
window.addEventListener("resize", debouncedRecalc);
|
|
2474
|
-
const onFontsLoaded = () => {
|
|
2475
|
-
debouncedRecalc();
|
|
2476
|
-
};
|
|
2477
|
-
const fontSet = "fonts" in document ? document.fonts : null;
|
|
2478
|
-
(_a = fontSet == null ? void 0 : fontSet.addEventListener) == null ? void 0 : _a.call(fontSet, "loadingdone", onFontsLoaded);
|
|
2479
|
-
return () => {
|
|
2480
|
-
var _a2;
|
|
2481
|
-
ro == null ? void 0 : ro.disconnect();
|
|
2482
|
-
window.removeEventListener("resize", debouncedRecalc);
|
|
2483
|
-
cancelAnimationFrame(rafRef.current);
|
|
2484
|
-
(_a2 = fontSet == null ? void 0 : fontSet.removeEventListener) == null ? void 0 : _a2.call(fontSet, "loadingdone", onFontsLoaded);
|
|
2485
|
-
};
|
|
2486
|
-
}, [recalculate]);
|
|
2487
|
-
return {
|
|
2488
|
-
ref,
|
|
2489
|
-
measureRef,
|
|
2490
|
-
displayText: state.displayText,
|
|
2491
|
-
isTruncated: state.isTruncated,
|
|
2492
|
-
prefixGraphemeCount: state.prefixGraphemeCount,
|
|
2493
|
-
prefixText: state.prefixText,
|
|
2494
|
-
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
2495
|
-
suffixText: state.suffixText
|
|
2936
|
+
}
|
|
2937
|
+
onReset == null ? void 0 : onReset();
|
|
2496
2938
|
};
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2939
|
+
const handleKeyDown = (e) => {
|
|
2940
|
+
const el = element.current;
|
|
2941
|
+
if (!el)
|
|
2942
|
+
return;
|
|
2943
|
+
const step = e.shiftKey ? 64 : 16;
|
|
2944
|
+
const grow = position === "left" ? 1 : -1;
|
|
2945
|
+
let next = null;
|
|
2946
|
+
if (e.key === "ArrowLeft") {
|
|
2947
|
+
next = el.offsetWidth + grow * step;
|
|
2948
|
+
} else if (e.key === "ArrowRight") {
|
|
2949
|
+
next = el.offsetWidth - grow * step;
|
|
2950
|
+
} else if (e.key === "Home" && ariaValueMin !== void 0) {
|
|
2951
|
+
next = ariaValueMin;
|
|
2952
|
+
} else if (e.key === "End" && ariaValueMax !== void 0) {
|
|
2953
|
+
next = ariaValueMax;
|
|
2954
|
+
}
|
|
2955
|
+
if (next === null)
|
|
2956
|
+
return;
|
|
2957
|
+
e.preventDefault();
|
|
2958
|
+
onWidthChange(next);
|
|
2511
2959
|
};
|
|
2960
|
+
return jsxRuntimeExports.jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": ariaLabel, "aria-controls": ariaControls, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuenow": ariaValueNow, tabIndex: 0, className: cn("group absolute inset-y-0 z-10 w-[17px] cursor-col-resize touch-none outline-none", position === "left" ? "-left-2" : "-right-2"), onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerEnd, onPointerCancel: handlePointerEnd, onLostPointerCapture: handleLostPointerCapture, onDoubleClick: handleDoubleClick, onKeyDown: handleKeyDown, children: jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-transparent transition-colors delay-75 duration-100", "group-hover:bg-gray-500 group-focus-visible:bg-[var(--ds-focus-color)]", isDragging && "bg-gray-500") }) });
|
|
2512
2961
|
}
|
|
2513
|
-
function
|
|
2514
|
-
const
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
2518
|
-
if (e.defaultPrevented || !isTruncated)
|
|
2962
|
+
function useElementWidth(ref, enabled = true) {
|
|
2963
|
+
const [width, setWidth] = reactExports.useState(0);
|
|
2964
|
+
reactExports.useLayoutEffect(() => {
|
|
2965
|
+
if (!enabled)
|
|
2519
2966
|
return;
|
|
2520
|
-
const
|
|
2521
|
-
if (!
|
|
2967
|
+
const el = ref.current;
|
|
2968
|
+
if (!el)
|
|
2522
2969
|
return;
|
|
2523
|
-
|
|
2524
|
-
|
|
2970
|
+
setWidth(Math.round(el.getBoundingClientRect().width));
|
|
2971
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
2972
|
+
setWidth(Math.round((entry == null ? void 0 : entry.contentRect.width) ?? 0));
|
|
2973
|
+
});
|
|
2974
|
+
observer.observe(el);
|
|
2975
|
+
return () => observer.disconnect();
|
|
2976
|
+
}, [ref, enabled]);
|
|
2977
|
+
return width;
|
|
2978
|
+
}
|
|
2979
|
+
const DETAIL_PANEL_ID = "trace-detail-panel";
|
|
2980
|
+
function useSelectedSpanInfo() {
|
|
2981
|
+
const { activeSpan } = useActiveSpan();
|
|
2982
|
+
const sidebar = useSidebarData();
|
|
2983
|
+
return reactExports.useMemo(() => {
|
|
2984
|
+
var _a, _b;
|
|
2985
|
+
if (!activeSpan)
|
|
2986
|
+
return null;
|
|
2987
|
+
const resource = (_a = activeSpan.attributes) == null ? void 0 : _a.resource;
|
|
2988
|
+
const rawEvents = filterSpanRawEvents(sidebar.events, resource, activeSpan.spanId);
|
|
2989
|
+
return {
|
|
2990
|
+
data: (_b = activeSpan.attributes) == null ? void 0 : _b.data,
|
|
2991
|
+
resource,
|
|
2992
|
+
spanId: activeSpan.spanId,
|
|
2993
|
+
rawEvents
|
|
2994
|
+
};
|
|
2995
|
+
}, [activeSpan, sidebar]);
|
|
2996
|
+
}
|
|
2997
|
+
function TraceDetailPanel({ containerRef, onNavigateToSpan, onClose }) {
|
|
2998
|
+
const { activeSpan, activeSpanId, spans } = useActiveSpan();
|
|
2999
|
+
const sidebar = useSidebarData();
|
|
3000
|
+
const selectedSpan = useSelectedSpanInfo();
|
|
3001
|
+
const isOpen = Boolean(activeSpan);
|
|
3002
|
+
const [storedWidth, setStoredWidth] = reactExports.useState(() => readStoredPanelWidth());
|
|
3003
|
+
const containerWidth = useElementWidth(containerRef, isOpen);
|
|
3004
|
+
const asideRef = reactExports.useRef(null);
|
|
3005
|
+
const handleResize = reactExports.useCallback((next) => {
|
|
3006
|
+
const clamped = clampPanelWidth(next, containerWidth);
|
|
3007
|
+
setStoredWidth(clamped);
|
|
3008
|
+
writeStoredPanelWidth(clamped);
|
|
3009
|
+
}, [containerWidth]);
|
|
3010
|
+
const panelWidth = clampPanelWidth(storedWidth, containerWidth);
|
|
3011
|
+
const panelMaxWidth = Math.max(PANEL_MIN_WIDTH, computeMaxPanelWidth(containerWidth));
|
|
3012
|
+
const { prevSpanId, nextSpanId } = reactExports.useMemo(() => {
|
|
3013
|
+
var _a, _b;
|
|
3014
|
+
if (!activeSpanId)
|
|
3015
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3016
|
+
const i = spans.findIndex((s) => s.spanId === activeSpanId);
|
|
3017
|
+
if (i === -1)
|
|
3018
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3019
|
+
return {
|
|
3020
|
+
prevSpanId: ((_a = spans[i - 1]) == null ? void 0 : _a.spanId) ?? null,
|
|
3021
|
+
nextSpanId: ((_b = spans[i + 1]) == null ? void 0 : _b.spanId) ?? null
|
|
3022
|
+
};
|
|
3023
|
+
}, [activeSpanId, spans]);
|
|
3024
|
+
const handleSelectPrev = reactExports.useCallback(() => {
|
|
3025
|
+
if (prevSpanId)
|
|
3026
|
+
onNavigateToSpan(prevSpanId);
|
|
3027
|
+
}, [prevSpanId, onNavigateToSpan]);
|
|
3028
|
+
const handleSelectNext = reactExports.useCallback(() => {
|
|
3029
|
+
if (nextSpanId)
|
|
3030
|
+
onNavigateToSpan(nextSpanId);
|
|
3031
|
+
}, [nextSpanId, onNavigateToSpan]);
|
|
3032
|
+
reactExports.useEffect(() => {
|
|
3033
|
+
if (!isOpen)
|
|
2525
3034
|
return;
|
|
2526
|
-
const
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
const
|
|
2531
|
-
if (
|
|
2532
|
-
|
|
2533
|
-
prefixText,
|
|
2534
|
-
selectionEnd: offsets.end,
|
|
2535
|
-
selectionStart: offsets.start,
|
|
2536
|
-
suffixText,
|
|
2537
|
-
value
|
|
2538
|
-
});
|
|
3035
|
+
const onKeyDown = (e) => {
|
|
3036
|
+
if (e.key !== "j" && e.key !== "k" && e.key !== "ArrowDown" && e.key !== "ArrowUp") {
|
|
3037
|
+
return;
|
|
3038
|
+
}
|
|
3039
|
+
const target = e.target;
|
|
3040
|
+
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || (target == null ? void 0 : target.isContentEditable)) {
|
|
3041
|
+
return;
|
|
2539
3042
|
}
|
|
3043
|
+
const targetId = e.key === "k" || e.key === "ArrowUp" ? prevSpanId : nextSpanId;
|
|
3044
|
+
if (targetId) {
|
|
3045
|
+
e.preventDefault();
|
|
3046
|
+
onNavigateToSpan(targetId);
|
|
3047
|
+
}
|
|
3048
|
+
};
|
|
3049
|
+
window.addEventListener("keydown", onKeyDown);
|
|
3050
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
3051
|
+
}, [isOpen, prevSpanId, nextSpanId, onNavigateToSpan]);
|
|
3052
|
+
const selectedSpanName = reactExports.useMemo(() => {
|
|
3053
|
+
var _a, _b;
|
|
3054
|
+
if (!(selectedSpan == null ? void 0 : selectedSpan.data))
|
|
3055
|
+
return "Details";
|
|
3056
|
+
const data = selectedSpan.data;
|
|
3057
|
+
if (selectedSpan.resource === "hook") {
|
|
3058
|
+
return data.token ?? data.hookId;
|
|
2540
3059
|
}
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
return;
|
|
2549
|
-
e.preventDefault();
|
|
2550
|
-
e.clipboardData.setData("text/plain", copyText);
|
|
2551
|
-
}, [onCopyProp, isTruncated, prefixText, suffixText, value]);
|
|
2552
|
-
return jsxRuntimeExports.jsxs("span", { title: isTruncated ? value : void 0, ...props, ref, className: cn("relative inline-grid min-w-0 max-w-full overflow-hidden whitespace-nowrap", className), onCopy: handleCopy, children: [isTruncated && jsxRuntimeExports.jsx("span", { className: "sr-only select-none", children: value }), jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: "pointer-events-none col-start-1 row-start-1 invisible select-none whitespace-nowrap", children: value }), jsxRuntimeExports.jsx("span", { "aria-hidden": isTruncated || void 0, className: "col-start-1 row-start-1 min-w-0 overflow-hidden", ref: visibleRef, children: isTruncated ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("span", { children: prefixText }), jsxRuntimeExports.jsx("span", { children: ELLIPSIS }), jsxRuntimeExports.jsx("span", { children: suffixText })] }) : displayText }), jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute left-0 top-0 inline-block invisible select-none whitespace-nowrap", ref: measureRef })] });
|
|
3060
|
+
const stepName = data.stepName;
|
|
3061
|
+
const workflowName = data.workflowName;
|
|
3062
|
+
return (stepName ? (_a = parseStepName(stepName)) == null ? void 0 : _a.shortName : void 0) ?? (workflowName ? (_b = parseWorkflowName(workflowName)) == null ? void 0 : _b.shortName : void 0) ?? stepName ?? workflowName ?? data.hookId ?? "Details";
|
|
3063
|
+
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource]);
|
|
3064
|
+
if (!activeSpan)
|
|
3065
|
+
return null;
|
|
3066
|
+
return jsxRuntimeExports.jsxs("aside", { ref: asideRef, id: DETAIL_PANEL_ID, className: "relative flex flex-col h-full max-h-full shrink-0 bg-background-100 border-l border-gray-alpha-400", style: { width: panelWidth }, children: [jsxRuntimeExports.jsx(DraggableBorder, { element: asideRef, position: "left", onWidthChange: handleResize, onReset: () => handleResize(PANEL_DEFAULT_WIDTH), "aria-label": "Resize span details panel", "aria-controls": DETAIL_PANEL_ID, "aria-valuemin": PANEL_MIN_WIDTH, "aria-valuemax": panelMaxWidth, "aria-valuenow": Math.min(Math.max(Math.round(panelWidth), PANEL_MIN_WIDTH), panelMaxWidth) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 py-[7.5px]", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 font-medium text-gray-1000 truncate block", children: selectedSpanName }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrev, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNext, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate down", jsxRuntimeExports.jsx(Kbd, { children: "J" })] }) : null] }), jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "w-px h-4 bg-gray-alpha-400 mx-1" }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Close span details", "aria-keyshortcuts": "Escape", onClick: onClose, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, fetchSpanDetail: sidebar.fetchSpanDetail, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan, showSeparateEventOccurrenceTimestamps: sidebar.showSeparateEventOccurrenceTimestamps, getModuleSourceUrl: sidebar.getModuleSourceUrl }) }) })] });
|
|
2553
3067
|
}
|
|
3068
|
+
const WorkflowIcon = () => {
|
|
3069
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", style: { color: "currentColor" }, viewBox: "0 0 16 16", width: "16", children: jsxRuntimeExports.jsx("path", { d: "M5.75 7L6.4209 7.33594L4.85254 10.4717C5.38789 10.771 5.75 11.3431 5.75 12V14C5.75 14.9665 4.96648 15.75 4 15.75H2C1.03352 15.75 0.25 14.9665 0.25 14V12C0.25 11.0335 1.03352 10.25 2 10.25H3.28711L5.0791 6.66504L5.75 7ZM14 10.25C14.9665 10.25 15.75 11.0335 15.75 12V14C15.75 14.9665 14.9665 15.75 14 15.75H12C11.1185 15.75 10.3909 15.098 10.2695 14.25H7V12.75H10.25V12C10.25 11.0335 11.0335 10.25 12 10.25H14ZM2 11.75C1.86192 11.75 1.75 11.8619 1.75 12V14C1.75 14.1381 1.86192 14.25 2 14.25H4C4.13808 14.25 4.25 14.1381 4.25 14V12C4.25 11.8619 4.13808 11.75 4 11.75H2ZM12 11.75C11.8619 11.75 11.75 11.8619 11.75 12V14C11.75 14.1381 11.8619 14.25 12 14.25H14C14.1381 14.25 14.25 14.1381 14.25 14V12C14.25 11.8619 14.1381 11.75 14 11.75H12ZM9 0.25C9.96649 0.25 10.75 1.03351 10.75 2V4C10.75 4.44642 10.5808 4.85197 10.3057 5.16113L12.2041 8.6416L10.8877 9.36035L8.91895 5.75H7C6.03351 5.75 5.25 4.96649 5.25 4V2C5.25 1.03351 6.03351 0.25 7 0.25H9ZM7 1.75C6.86193 1.75 6.75 1.86193 6.75 2V4C6.75 4.13807 6.86193 4.25 7 4.25H9C9.13807 4.25 9.25 4.13807 9.25 4V2C9.25 1.86193 9.13807 1.75 9 1.75H7Z", fill: "currentColor" }) });
|
|
3070
|
+
};
|
|
3071
|
+
const WebhookIcon = () => {
|
|
3072
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M5.8349 3.24994C5.14454 4.44567 5.55423 5.97464 6.74996 6.665L7.39465 7.03721L7.02726 7.68466L5.14599 11C5.21289 11.1531 5.25 11.3222 5.25 11.5C5.25 12.1904 4.69036 12.75 4 12.75C3.30964 12.75 2.75 12.1904 2.75 11.5C2.75 10.8634 3.22584 10.338 3.84123 10.26L5.38944 7.5316C3.95909 6.30274 3.55857 4.19264 4.53586 2.49994C5.64043 0.586765 8.08679 -0.0687357 9.99996 1.03583C11.836 2.09584 12.5137 4.39156 11.5892 6.26591L10.4949 4.33754C10.4418 3.53274 10.0009 2.76843 9.24996 2.33487C8.05423 1.64452 6.52525 2.0542 5.8349 3.24994ZM9.146 4.99996C9.21289 4.84686 9.25 4.67776 9.25 4.5C9.25 3.80964 8.69036 3.25 8 3.25C7.30964 3.25 6.75 3.80964 6.75 4.5C6.75 5.13659 7.22586 5.66203 7.84127 5.74002L9.72266 9.05556L10.0956 9.71274L10.75 9.33493C11.9457 8.64458 13.4747 9.05427 14.165 10.25C14.8554 11.4457 14.4457 12.9747 13.25 13.6651C12.5047 14.0953 11.63 14.0983 10.9096 13.75H8.69252C9.85895 15.4685 12.1727 16.0191 14 14.9641C15.9131 13.8595 16.5686 11.4132 15.4641 9.5C14.4886 7.81038 12.4665 7.10169 10.6895 7.71998L9.146 4.99996ZM13.25 11.5C13.25 12.1904 12.6904 12.75 12 12.75C11.591 12.75 11.228 12.5536 10.9999 12.25H7.9298C7.57875 14.1006 5.95279 15.5 4 15.5C1.79086 15.5 0 13.7091 0 11.5C0 9.40018 1.61801 7.67826 3.67529 7.51299L2.58098 9.44147C1.92792 9.89251 1.5 10.6463 1.5 11.5C1.5 12.8807 2.61929 14 4 14C5.38071 14 6.5 12.8807 6.5 11.5V10.75H7.25H10.9999C11.228 10.4464 11.591 10.25 12 10.25C12.6904 10.25 13.25 10.8096 13.25 11.5Z", fill: "currentColor" }) });
|
|
3073
|
+
};
|
|
3074
|
+
const SleepIcon = () => {
|
|
3075
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7.25 1.25V2.03971C5.87928 2.18571 4.62678 2.72736 3.6089 3.54824L3.03033 2.96967L2.5 2.43934L1.43934 3.5L1.96967 4.03033L2.54824 4.6089C1.57979 5.80976 1 7.33717 1 9C1 12.866 4.13401 16 8 16C11.866 16 15 12.866 15 9C15 7.33717 14.4202 5.80976 13.4518 4.6089L14.0303 4.03033L14.5607 3.5L13.5 2.43934L12.9697 2.96967L12.3911 3.54824C11.3732 2.72736 10.1207 2.18571 8.75 2.03971V1.25H9.25H10V-0.25H9.25H8.75H7.25H6.75H6V1.25H6.75H7.25ZM2.5 9C2.5 5.96243 4.96243 3.5 8 3.5C11.0376 3.5 13.5 5.96243 13.5 9C13.5 12.0376 11.0376 14.5 8 14.5C4.96243 14.5 2.5 12.0376 2.5 9ZM8.75 6.75V6H7.25V6.75V9V9.75H8.75V9V6.75Z", fill: "currentColor" }) });
|
|
3076
|
+
};
|
|
3077
|
+
const StepForwardIcon = () => {
|
|
3078
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.21969 12.5303L4.75002 13.0607L5.81068 12L5.28035 11.4697L1.81068 7.99999L5.28035 4.53032L5.81068 3.99999L4.75002 2.93933L4.21969 3.46966L0.39647 7.29289C0.00594562 7.68341 0.00594562 8.31658 0.39647 8.7071L4.21969 12.5303ZM11.7804 12.5303L11.25 13.0607L10.1894 12L10.7197 11.4697L14.1894 7.99999L10.7197 4.53032L10.1894 3.99999L11.25 2.93933L11.7804 3.46966L15.6036 7.29289C15.9941 7.68341 15.9941 8.31658 15.6036 8.7071L11.7804 12.5303Z", fill: "currentColor" }) });
|
|
3079
|
+
};
|
|
2554
3080
|
const eventStyles = {
|
|
2555
|
-
run: { icon: WorkflowIcon, className: "text-blue-900" },
|
|
2556
|
-
step: { icon: StepForwardIcon, className: "text-green-900" },
|
|
2557
|
-
hook: { icon: WebhookIcon, className: "text-
|
|
2558
|
-
sleep: { icon: SleepIcon, className: "text-gray-900" }
|
|
3081
|
+
run: { icon: WorkflowIcon, className: "text-blue-900", label: "Workflow" },
|
|
3082
|
+
step: { icon: StepForwardIcon, className: "text-green-900", label: "Step" },
|
|
3083
|
+
hook: { icon: WebhookIcon, className: "text-gray-900", label: "Hook" },
|
|
3084
|
+
sleep: { icon: SleepIcon, className: "text-gray-900", label: "Sleep" }
|
|
2559
3085
|
};
|
|
2560
3086
|
const defaultStyle = {
|
|
2561
3087
|
icon: Circle,
|
|
2562
|
-
className: "text-gray-900"
|
|
3088
|
+
className: "text-gray-900",
|
|
3089
|
+
label: "Event"
|
|
2563
3090
|
};
|
|
2564
3091
|
const ROW_HEIGHT_CLASS = "h-10";
|
|
2565
3092
|
function getEventStyle(resource, isErrored) {
|
|
2566
3093
|
const style = eventStyles[resource] ?? defaultStyle;
|
|
2567
3094
|
return {
|
|
2568
3095
|
icon: style.icon,
|
|
2569
|
-
className: cn(isErrored ? "text-red-900" : style.className)
|
|
3096
|
+
className: cn(isErrored ? "text-red-900" : style.className),
|
|
3097
|
+
label: style.label
|
|
2570
3098
|
};
|
|
2571
3099
|
}
|
|
2572
|
-
const EventRow = ({ span, isSelected, onSelectSpan }) => {
|
|
3100
|
+
const EventRow = ({ span, isSelected, isDimmed, onSelectSpan }) => {
|
|
2573
3101
|
const durationMs = getSpanDurationMs(span);
|
|
2574
|
-
const isErrored = span
|
|
2575
|
-
const { icon: Icon, className: tagClassName } = getEventStyle(span.resource, isErrored);
|
|
2576
|
-
return jsxRuntimeExports.jsx("li", { className: cn("relative overflow-clip group
|
|
3102
|
+
const isErrored = isSpanErrored(span);
|
|
3103
|
+
const { icon: Icon, className: tagClassName, label: iconLabel } = getEventStyle(span.resource, isErrored);
|
|
3104
|
+
return jsxRuntimeExports.jsx("li", { className: cn("relative overflow-clip group transition-opacity", ROW_HEIGHT_CLASS, isDimmed && "opacity-35"), role: "treeitem", "aria-selected": isSelected, "aria-expanded": isSelected, "aria-level": 1, onClick: () => onSelectSpan(span.spanId), children: jsxRuntimeExports.jsx("div", { className: "h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200", children: jsxRuntimeExports.jsxs("div", { className: "flex h-full min-w-0 items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsxs(Tooltip, { delayDuration: 500, children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx("span", { className: cn("shrink-0", tagClassName), children: jsxRuntimeExports.jsx(Icon, { className: "w-4 h-4" }) }) }), jsxRuntimeExports.jsx(TooltipContent, { side: "top", children: iconLabel })] }), jsxRuntimeExports.jsx("span", { className: "min-w-0 text-label-14", children: jsxRuntimeExports.jsx(MiddleTruncate, { value: span.name }) })] }), jsxRuntimeExports.jsx("div", { className: "ml-2 shrink-0", children: jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900 tabular-nums", children: formatDurationPrecise(durationMs) }) })] }) }) });
|
|
2577
3105
|
};
|
|
2578
|
-
const EventList = ({ spans, activeSpanId, onSelectSpan }) => {
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
3106
|
+
const EventList = ({ spans, activeSpanId, searchResult, onSelectSpan }) => {
|
|
3107
|
+
const listRef = reactExports.useRef(null);
|
|
3108
|
+
const { start, end } = useRowWindow(listRef, spans.length, ROW_HEIGHT_PX);
|
|
3109
|
+
return jsxRuntimeExports.jsx("ul", { ref: listRef, id: "event-list", role: "tree", className: "block min-h-0 overflow-visible divide-y divide-gray-400 border-b border-gray-400", style: {
|
|
3110
|
+
paddingTop: start * ROW_HEIGHT_PX,
|
|
3111
|
+
paddingBottom: (spans.length - end) * ROW_HEIGHT_PX
|
|
3112
|
+
}, children: spans.slice(start, end).map((span) => jsxRuntimeExports.jsx(EventRow, { span, isSelected: span.spanId === activeSpanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelectSpan }, span.spanId)) });
|
|
2582
3113
|
};
|
|
2583
|
-
const
|
|
2584
|
-
|
|
2585
|
-
const DEFAULT_START_PX = 340;
|
|
2586
|
-
function SplitPane({ children, className, defaultStartWidth = DEFAULT_START_PX, startHeader, endHeader }) {
|
|
3114
|
+
const SPLIT_PANE_START_ID = "trace-split-start";
|
|
3115
|
+
function SplitPane({ children, className, startHeader, endHeader, scrollContainerRef }) {
|
|
2587
3116
|
const parts = reactExports.Children.toArray(children);
|
|
2588
|
-
if (parts.length !==
|
|
2589
|
-
throw new Error("SplitPane expects exactly
|
|
3117
|
+
if (parts.length !== 3) {
|
|
3118
|
+
throw new Error("SplitPane expects exactly three children");
|
|
2590
3119
|
}
|
|
2591
|
-
const [start, end] = parts;
|
|
2592
|
-
const [startPx, setStartPx] = reactExports.useState(
|
|
2593
|
-
const [isDragging, setIsDragging] = reactExports.useState(false);
|
|
3120
|
+
const [start, end, endOverlay] = parts;
|
|
3121
|
+
const [startPx, setStartPx] = reactExports.useState(DEFAULT_START_PX);
|
|
2594
3122
|
const containerRef = reactExports.useRef(null);
|
|
2595
|
-
const
|
|
2596
|
-
const
|
|
2597
|
-
const
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
};
|
|
2604
|
-
}, []);
|
|
3123
|
+
const startRef = reactExports.useRef(null);
|
|
3124
|
+
const containerWidth = useElementWidth(containerRef);
|
|
3125
|
+
const setContainerRef = reactExports.useCallback((node) => {
|
|
3126
|
+
containerRef.current = node;
|
|
3127
|
+
if (scrollContainerRef) {
|
|
3128
|
+
scrollContainerRef.current = node;
|
|
3129
|
+
}
|
|
3130
|
+
}, [scrollContainerRef]);
|
|
2605
3131
|
const clampPx = reactExports.useCallback((px) => {
|
|
2606
3132
|
const el = containerRef.current;
|
|
2607
3133
|
if (!el)
|
|
@@ -2609,80 +3135,72 @@ function SplitPane({ children, className, defaultStartWidth = DEFAULT_START_PX,
|
|
|
2609
3135
|
const maxPx = el.getBoundingClientRect().width - MIN_PX - GUTTER_PX;
|
|
2610
3136
|
return Math.min(maxPx, Math.max(MIN_PX, px));
|
|
2611
3137
|
}, []);
|
|
3138
|
+
const handleWidthChange = reactExports.useCallback((next) => setStartPx(clampPx(next)), [clampPx]);
|
|
3139
|
+
const handleReset = reactExports.useCallback(() => setStartPx(clampPx(DEFAULT_START_PX)), [clampPx]);
|
|
3140
|
+
const effectiveStartPx = containerWidth > 0 ? Math.max(MIN_PX, Math.min(containerWidth - MIN_PX - GUTTER_PX, startPx)) : startPx;
|
|
3141
|
+
const colTemplate = paneColTemplate(effectiveStartPx);
|
|
3142
|
+
const maxStartPx = Math.max(MIN_PX, containerWidth > 0 ? containerWidth - MIN_PX - GUTTER_PX : startPx);
|
|
3143
|
+
return jsxRuntimeExports.jsxs("div", { className: cn("relative flex flex-col h-full min-h-0", className), children: [jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { children: startHeader }), jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { className: "h-full w-px bg-gray-alpha-400", "aria-hidden": true }) }), jsxRuntimeExports.jsx("div", { children: endHeader })] }), jsxRuntimeExports.jsxs("div", { ref: setContainerRef, className: "grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { ref: startRef, id: SPLIT_PANE_START_ID, className: "min-w-0", children: start }), jsxRuntimeExports.jsxs("div", { className: "relative z-20 isolate flex shrink-0 justify-center", children: [jsxRuntimeExports.jsx("span", { className: "pointer-events-none relative z-10 h-full w-px shrink-0 bg-gray-alpha-400", "aria-hidden": true }), jsxRuntimeExports.jsx(DraggableBorder, { element: startRef, position: "right", onWidthChange: handleWidthChange, onReset: handleReset, "aria-label": "Resize event list", "aria-controls": SPLIT_PANE_START_ID, "aria-valuemin": MIN_PX, "aria-valuemax": maxStartPx, "aria-valuenow": Math.min(Math.max(Math.round(effectiveStartPx), MIN_PX), maxStartPx) })] }), end] }), jsxRuntimeExports.jsxs("div", { className: "pointer-events-none absolute inset-x-0 bottom-3 z-[5] grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", {}), jsxRuntimeExports.jsx("div", {}), jsxRuntimeExports.jsx("div", { className: "flex min-w-0 items-center justify-between gap-3 pl-4 pr-3", children: endOverlay })] })] });
|
|
3144
|
+
}
|
|
3145
|
+
const hint = "_hint_1dmsq_3";
|
|
3146
|
+
const styles = {
|
|
3147
|
+
hint
|
|
3148
|
+
};
|
|
3149
|
+
const DISMISSALS_KEY = "workflow-step-shortcut-helper-dismissals";
|
|
3150
|
+
const DISMISSAL_LIMIT = 3;
|
|
3151
|
+
const HINT_ROTATION_MS = 8e3;
|
|
3152
|
+
function getAltKeyLabel() {
|
|
3153
|
+
if (typeof navigator === "undefined")
|
|
3154
|
+
return "Alt";
|
|
3155
|
+
return navigator.platform.toLowerCase().includes("mac") ? "Option" : "Alt";
|
|
3156
|
+
}
|
|
3157
|
+
function readDismissals() {
|
|
3158
|
+
try {
|
|
3159
|
+
const dismissals = Number.parseInt(window.localStorage.getItem(DISMISSALS_KEY) ?? "0", 10);
|
|
3160
|
+
return Number.isNaN(dismissals) ? 0 : dismissals;
|
|
3161
|
+
} catch {
|
|
3162
|
+
return 0;
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
function AltHint() {
|
|
3166
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: ["Hold", jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "mx-1", children: getAltKeyLabel() }), "to see delta between spans"] });
|
|
3167
|
+
}
|
|
3168
|
+
function NavHint() {
|
|
3169
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: ["Use", jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "ml-1", children: "J" }), jsxRuntimeExports.jsx("span", { className: "mx-1", children: "/" }), jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "mr-1", children: "K" }), "to move between spans"] });
|
|
3170
|
+
}
|
|
3171
|
+
function TraceShortcutHelper({ hasMultipleSpans, reducedMotion }) {
|
|
3172
|
+
const [visible, setVisible] = reactExports.useState(false);
|
|
3173
|
+
const [index, setIndex] = reactExports.useState(0);
|
|
3174
|
+
reactExports.useEffect(() => {
|
|
3175
|
+
setVisible(readDismissals() < DISMISSAL_LIMIT);
|
|
3176
|
+
}, []);
|
|
2612
3177
|
reactExports.useEffect(() => {
|
|
2613
|
-
if (
|
|
3178
|
+
if (reducedMotion)
|
|
2614
3179
|
return;
|
|
2615
|
-
const
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
setStartPx(pendingPx.current);
|
|
2627
|
-
});
|
|
2628
|
-
}
|
|
2629
|
-
};
|
|
2630
|
-
const onPointerUp = (e) => {
|
|
2631
|
-
if (e.pointerId !== pointerIdRef.current)
|
|
2632
|
-
return;
|
|
2633
|
-
const gutter2 = gutterRef.current;
|
|
2634
|
-
if (gutter2 == null ? void 0 : gutter2.hasPointerCapture(e.pointerId)) {
|
|
2635
|
-
gutter2.releasePointerCapture(e.pointerId);
|
|
2636
|
-
}
|
|
2637
|
-
if (rafRef.current) {
|
|
2638
|
-
cancelAnimationFrame(rafRef.current);
|
|
2639
|
-
rafRef.current = null;
|
|
2640
|
-
}
|
|
2641
|
-
pointerIdRef.current = null;
|
|
2642
|
-
setIsDragging(false);
|
|
2643
|
-
};
|
|
2644
|
-
document.addEventListener("pointermove", onPointerMove);
|
|
2645
|
-
document.addEventListener("pointerup", onPointerUp);
|
|
2646
|
-
document.addEventListener("pointercancel", onPointerUp);
|
|
2647
|
-
return () => {
|
|
2648
|
-
document.removeEventListener("pointermove", onPointerMove);
|
|
2649
|
-
document.removeEventListener("pointerup", onPointerUp);
|
|
2650
|
-
document.removeEventListener("pointercancel", onPointerUp);
|
|
2651
|
-
};
|
|
2652
|
-
}, [isDragging, clampPx]);
|
|
2653
|
-
const handlePointerDown = (e) => {
|
|
2654
|
-
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2655
|
-
pointerIdRef.current = e.pointerId;
|
|
2656
|
-
setIsDragging(true);
|
|
2657
|
-
};
|
|
2658
|
-
const handleLostPointerCapture = () => {
|
|
2659
|
-
pointerIdRef.current = null;
|
|
2660
|
-
setIsDragging(false);
|
|
2661
|
-
if (rafRef.current) {
|
|
2662
|
-
cancelAnimationFrame(rafRef.current);
|
|
2663
|
-
rafRef.current = null;
|
|
3180
|
+
const id = setInterval(() => {
|
|
3181
|
+
setIndex((i) => i === 0 ? 1 : 0);
|
|
3182
|
+
}, HINT_ROTATION_MS);
|
|
3183
|
+
return () => clearInterval(id);
|
|
3184
|
+
}, [reducedMotion]);
|
|
3185
|
+
if (!visible || !hasMultipleSpans)
|
|
3186
|
+
return null;
|
|
3187
|
+
const dismiss = () => {
|
|
3188
|
+
try {
|
|
3189
|
+
window.localStorage.setItem(DISMISSALS_KEY, String(readDismissals() + 1));
|
|
3190
|
+
} catch {
|
|
2664
3191
|
}
|
|
3192
|
+
setVisible(false);
|
|
2665
3193
|
};
|
|
2666
|
-
|
|
2667
|
-
const hasHeaders = startHeader != null || endHeader != null;
|
|
2668
|
-
const gutter = jsxRuntimeExports.jsx("div", { ref: gutterRef, className: "relative z-20 isolate flex shrink-0 cursor-col-resize justify-center", onPointerDown: handlePointerDown, onLostPointerCapture: handleLostPointerCapture, children: jsxRuntimeExports.jsx("span", { className: "pointer-events-none relative z-10 h-full w-px shrink-0 bg-gray-alpha-400", "aria-hidden": true }) });
|
|
2669
|
-
if (hasHeaders) {
|
|
2670
|
-
return jsxRuntimeExports.jsxs("div", { className: cn("flex flex-col h-full min-h-0", className), children: [jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { children: startHeader }), jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { className: "h-full w-px bg-gray-alpha-400", "aria-hidden": true }) }), jsxRuntimeExports.jsx("div", { children: endHeader })] }), jsxRuntimeExports.jsxs("div", { ref: containerRef, className: cn("grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", isDragging && "select-none"), style: { gridTemplateColumns: colTemplate }, children: [start, gutter, end] })] });
|
|
2671
|
-
}
|
|
2672
|
-
return jsxRuntimeExports.jsxs("div", { ref: containerRef, className: cn("grid h-full min-h-0 content-start overflow-x-hidden overflow-y-auto", isDragging && "select-none", className), style: { gridTemplateColumns: colTemplate, height: "100%" }, children: [start, gutter, end] });
|
|
2673
|
-
}
|
|
2674
|
-
function DetailPanel({ span, rootStart, onClose }) {
|
|
2675
|
-
const startMs = getHighResInMs(span.startTime);
|
|
2676
|
-
const durationMs = getSpanDurationMs(span);
|
|
2677
|
-
const offsetMs = startMs - rootStart;
|
|
2678
|
-
return jsxRuntimeExports.jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), jsxRuntimeExports.jsx("button", { type: "button", className: "p-1 rounded-md text-gray-900 hover:text-gray-1000 hover:bg-gray-alpha-200 transition-colors", onClick: onClose, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] }), jsxRuntimeExports.jsx("div", { className: "overflow-y-auto p-3 space-y-3", children: jsxRuntimeExports.jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm", children: [jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Resource" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 font-mono", children: span.resource }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Duration" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 tabular-nums font-mono", children: formatDuration(durationMs) }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Offset" }), jsxRuntimeExports.jsxs("dd", { className: "text-gray-1000 tabular-nums font-mono", children: ["+", formatDuration(offsetMs)] }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Status" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 font-mono", children: span.status.code === 2 ? "Error" : "OK" })] }) })] });
|
|
3194
|
+
return jsxRuntimeExports.jsxs("div", { className: "group pointer-events-auto hidden h-8 w-fit items-center gap-1 text-label-12 leading-none text-gray-900 @min-[480px]:flex", children: [jsxRuntimeExports.jsx("span", { "aria-live": "polite", "aria-atomic": "true", className: "inline-flex items-center whitespace-nowrap", children: reducedMotion ? jsxRuntimeExports.jsx(AltHint, {}) : jsxRuntimeExports.jsx("span", { className: `inline-flex items-center ${styles.hint}`, children: index === 0 ? jsxRuntimeExports.jsx(AltHint, {}) : jsxRuntimeExports.jsx(NavHint, {}) }, index) }), jsxRuntimeExports.jsx("button", { type: "button", className: "inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100 motion-reduce:transition-none", onClick: dismiss, "aria-label": "Dismiss trace shortcuts helper", children: jsxRuntimeExports.jsx(X, { className: "h-3 w-3" }) })] });
|
|
2679
3195
|
}
|
|
2680
3196
|
const MIN_VIEWPORT_MS = 1e-3;
|
|
3197
|
+
const ZOOM_DEBOUNCE_MS = 150;
|
|
2681
3198
|
function useAnimatedViewport(initial) {
|
|
2682
3199
|
const [viewport, setViewportState] = reactExports.useState(initial);
|
|
2683
3200
|
const animRef = reactExports.useRef(null);
|
|
2684
3201
|
const currentRef = reactExports.useRef(initial);
|
|
2685
3202
|
currentRef.current = viewport;
|
|
3203
|
+
const reducedMotion = useReducedMotion();
|
|
2686
3204
|
const cancel = reactExports.useCallback(() => {
|
|
2687
3205
|
if (animRef.current) {
|
|
2688
3206
|
cancelAnimationFrame(animRef.current.raf);
|
|
@@ -2691,11 +3209,16 @@ function useAnimatedViewport(initial) {
|
|
|
2691
3209
|
}, []);
|
|
2692
3210
|
const animateTo = reactExports.useCallback((target) => {
|
|
2693
3211
|
cancel();
|
|
3212
|
+
if (reducedMotion) {
|
|
3213
|
+
currentRef.current = target;
|
|
3214
|
+
setViewportState(target);
|
|
3215
|
+
return;
|
|
3216
|
+
}
|
|
2694
3217
|
const from = currentRef.current;
|
|
2695
3218
|
const anim = { raf: 0, from, to: target, start: performance.now() };
|
|
2696
3219
|
const tick = () => {
|
|
2697
|
-
const t = Math.min((performance.now() - anim.start) /
|
|
2698
|
-
const e =
|
|
3220
|
+
const t = Math.min((performance.now() - anim.start) / 240, 1);
|
|
3221
|
+
const e = t < 0.5 ? 8 * t * t * t * t : 1 - (-2 * t + 2) ** 4 / 2;
|
|
2699
3222
|
setViewportState({
|
|
2700
3223
|
start: anim.from.start + (anim.to.start - anim.from.start) * e,
|
|
2701
3224
|
end: anim.from.end + (anim.to.end - anim.from.end) * e
|
|
@@ -2707,7 +3230,7 @@ function useAnimatedViewport(initial) {
|
|
|
2707
3230
|
};
|
|
2708
3231
|
animRef.current = anim;
|
|
2709
3232
|
anim.raf = requestAnimationFrame(tick);
|
|
2710
|
-
}, [cancel]);
|
|
3233
|
+
}, [cancel, reducedMotion]);
|
|
2711
3234
|
const setViewport = reactExports.useCallback((update) => {
|
|
2712
3235
|
cancel();
|
|
2713
3236
|
if (typeof update === "function") {
|
|
@@ -2724,38 +3247,26 @@ function useAnimatedViewport(initial) {
|
|
|
2724
3247
|
reactExports.useEffect(() => cancel, [cancel]);
|
|
2725
3248
|
return { viewport, setViewport, animateTo };
|
|
2726
3249
|
}
|
|
2727
|
-
function
|
|
2728
|
-
|
|
2729
|
-
const sidebar = useSidebarDataOptional();
|
|
2730
|
-
return reactExports.useMemo(() => {
|
|
2731
|
-
var _a, _b;
|
|
2732
|
-
if (!activeSpan || !sidebar)
|
|
2733
|
-
return null;
|
|
2734
|
-
const correlationId = activeSpan.spanId;
|
|
2735
|
-
const rawEvents = correlationId ? sidebar.events.filter((e) => e.correlationId === correlationId) : [];
|
|
2736
|
-
return {
|
|
2737
|
-
data: (_a = activeSpan.attributes) == null ? void 0 : _a.data,
|
|
2738
|
-
resource: (_b = activeSpan.attributes) == null ? void 0 : _b.resource,
|
|
2739
|
-
spanId: activeSpan.spanId,
|
|
2740
|
-
rawEvents
|
|
2741
|
-
};
|
|
2742
|
-
}, [activeSpan, sidebar == null ? void 0 : sidebar.events]);
|
|
2743
|
-
}
|
|
2744
|
-
function NewTraceViewer$1({ trace }) {
|
|
2745
|
-
return jsxRuntimeExports.jsx(ActiveSpanProvider, { spans: trace.spans, children: jsxRuntimeExports.jsx(NewTraceViewerContent, { trace }) });
|
|
3250
|
+
function TraceViewer$1({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
3251
|
+
return jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 300, children: jsxRuntimeExports.jsx(ActiveSpanProvider, { spans: trace.spans, children: jsxRuntimeExports.jsx(TraceViewerContent, { trace, onLoadMore, hasMore, isLoadingMore }) }) });
|
|
2746
3252
|
}
|
|
2747
|
-
function
|
|
2748
|
-
const {
|
|
2749
|
-
const
|
|
2750
|
-
const selectedSpan = useSelectedSpanInfo();
|
|
3253
|
+
function TraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
3254
|
+
const { activeSpanId, setActiveSpan, clearActiveSpan } = useActiveSpan();
|
|
3255
|
+
const reducedMotion = useReducedMotion();
|
|
2751
3256
|
const [searchQuery, setSearchQuery] = reactExports.useState("");
|
|
2752
|
-
const
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
return trace.spans;
|
|
2756
|
-
return trace.spans.filter((s) => s.name.toLowerCase().includes(q) || s.resource.toLowerCase().includes(q));
|
|
2757
|
-
}, [trace.spans, searchQuery]);
|
|
3257
|
+
const deferredSearchQuery = reactExports.useDeferredValue(searchQuery);
|
|
3258
|
+
const paneRootRef = reactExports.useRef(null);
|
|
3259
|
+
const searchResult = reactExports.useMemo(() => searchSpans(trace.spans, deferredSearchQuery), [trace.spans, deferredSearchQuery]);
|
|
2758
3260
|
const root = reactExports.useMemo(() => computeRootBounds(trace.spans), [trace.spans]);
|
|
3261
|
+
const scrollContainerRef = reactExports.useRef(null);
|
|
3262
|
+
const loadMore = reactExports.useCallback(() => {
|
|
3263
|
+
void (onLoadMore == null ? void 0 : onLoadMore());
|
|
3264
|
+
}, [onLoadMore]);
|
|
3265
|
+
const loadMoreSentinelRef = useLoadMoreOnScroll(loadMore, {
|
|
3266
|
+
hasMore: Boolean(onLoadMore && hasMore),
|
|
3267
|
+
isLoadingMore: Boolean(isLoadingMore),
|
|
3268
|
+
rootRef: scrollContainerRef
|
|
3269
|
+
});
|
|
2759
3270
|
const { viewport, setViewport, animateTo } = useAnimatedViewport({
|
|
2760
3271
|
start: root.startTime,
|
|
2761
3272
|
end: root.startTime + root.duration
|
|
@@ -2776,53 +3287,46 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2776
3287
|
return prev;
|
|
2777
3288
|
});
|
|
2778
3289
|
prevRootRef.current = { start: newStart, end: newEnd };
|
|
2779
|
-
}, [root.startTime, root.duration]);
|
|
3290
|
+
}, [root.startTime, root.duration, setViewport]);
|
|
2780
3291
|
const viewDuration = viewport.end - viewport.start;
|
|
3292
|
+
const viewportRef = reactExports.useRef(viewport);
|
|
3293
|
+
viewportRef.current = viewport;
|
|
2781
3294
|
const timeMarkers = reactExports.useMemo(() => computeTimeMarkers(viewDuration, viewport.start - root.startTime), [viewDuration, viewport.start, root.startTime]);
|
|
2782
3295
|
const resetZoom = reactExports.useCallback(() => {
|
|
2783
3296
|
animateTo({ start: root.startTime, end: root.startTime + root.duration });
|
|
2784
3297
|
}, [animateTo, root.startTime, root.duration]);
|
|
3298
|
+
const clampToRoot = reactExports.useCallback((next) => clampViewportToRoot(next, root.startTime, root.endTime, MIN_VIEWPORT_MS), [root.startTime, root.endTime]);
|
|
3299
|
+
const handleRevealTime = reactExports.useCallback((timeMs) => {
|
|
3300
|
+
const { start, end } = viewportRef.current;
|
|
3301
|
+
const duration = end - start;
|
|
3302
|
+
animateTo(clampToRoot({
|
|
3303
|
+
start: timeMs - duration / 2,
|
|
3304
|
+
end: timeMs + duration / 2
|
|
3305
|
+
}));
|
|
3306
|
+
}, [animateTo, clampToRoot]);
|
|
2785
3307
|
const ZOOM_FACTOR = 0.5;
|
|
2786
3308
|
const zoomBy = reactExports.useCallback((factor) => {
|
|
2787
|
-
const
|
|
2788
|
-
const
|
|
2789
|
-
const
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
let newEnd = center + newDuration / 2;
|
|
2796
|
-
if (newStart < rootS) {
|
|
2797
|
-
newStart = rootS;
|
|
2798
|
-
newEnd = rootS + newDuration;
|
|
2799
|
-
}
|
|
2800
|
-
if (newEnd > rootE) {
|
|
2801
|
-
newEnd = rootE;
|
|
2802
|
-
newStart = Math.max(rootS, rootE - newDuration);
|
|
2803
|
-
}
|
|
2804
|
-
return { start: newStart, end: newEnd };
|
|
2805
|
-
});
|
|
2806
|
-
}, [setViewport, root.startTime, root.duration]);
|
|
3309
|
+
const { start, end } = viewportRef.current;
|
|
3310
|
+
const center = (start + end) / 2;
|
|
3311
|
+
const newDuration = Math.max(MIN_VIEWPORT_MS, (end - start) * factor);
|
|
3312
|
+
animateTo(clampToRoot({
|
|
3313
|
+
start: center - newDuration / 2,
|
|
3314
|
+
end: center + newDuration / 2
|
|
3315
|
+
}));
|
|
3316
|
+
}, [animateTo, clampToRoot]);
|
|
2807
3317
|
const zoomIn = reactExports.useCallback(() => zoomBy(ZOOM_FACTOR), [zoomBy]);
|
|
2808
3318
|
const zoomOut = reactExports.useCallback(() => zoomBy(1 / ZOOM_FACTOR), [zoomBy]);
|
|
2809
|
-
const
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
return;
|
|
2813
|
-
}
|
|
2814
|
-
setActiveSpan(spanId);
|
|
3319
|
+
const isAtMinZoom = viewDuration >= root.duration;
|
|
3320
|
+
const isAtMaxZoom = viewDuration <= MIN_VIEWPORT_MS;
|
|
3321
|
+
const focusViewportOnSpan = reactExports.useCallback((spanId) => {
|
|
2815
3322
|
const span = trace.spans.find((s) => s.spanId === spanId);
|
|
2816
3323
|
if (!span)
|
|
2817
3324
|
return;
|
|
2818
3325
|
const spanStart = getHighResInMs(span.startTime);
|
|
2819
3326
|
const spanEnd = getHighResInMs(span.endTime);
|
|
2820
3327
|
const spanDuration = spanEnd - spanStart;
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
const rootD = root.duration;
|
|
2824
|
-
if (spanDuration > rootD * 0.8) {
|
|
2825
|
-
animateTo({ start: rootS, end: rootE });
|
|
3328
|
+
if (spanDuration > root.duration * 0.8) {
|
|
3329
|
+
animateTo({ start: root.startTime, end: root.endTime });
|
|
2826
3330
|
return;
|
|
2827
3331
|
}
|
|
2828
3332
|
const padding = Math.max(spanDuration * 0.2, MIN_VIEWPORT_MS / 2);
|
|
@@ -2833,34 +3337,67 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2833
3337
|
newStart = center - MIN_VIEWPORT_MS / 2;
|
|
2834
3338
|
newEnd = center + MIN_VIEWPORT_MS / 2;
|
|
2835
3339
|
}
|
|
2836
|
-
|
|
2837
|
-
const duration = newEnd - newStart;
|
|
2838
|
-
newStart = rootS;
|
|
2839
|
-
newEnd = Math.min(rootE, rootS + duration);
|
|
2840
|
-
}
|
|
2841
|
-
if (newEnd > rootE) {
|
|
2842
|
-
const duration = newEnd - newStart;
|
|
2843
|
-
newEnd = rootE;
|
|
2844
|
-
newStart = Math.max(rootS, rootE - duration);
|
|
2845
|
-
}
|
|
2846
|
-
animateTo({ start: newStart, end: newEnd });
|
|
3340
|
+
animateTo(clampToRoot({ start: newStart, end: newEnd }));
|
|
2847
3341
|
}, [
|
|
2848
3342
|
animateTo,
|
|
2849
|
-
setActiveSpan,
|
|
2850
|
-
clearActiveSpan,
|
|
2851
|
-
activeSpanId,
|
|
2852
3343
|
trace.spans,
|
|
2853
3344
|
root.startTime,
|
|
2854
|
-
root.
|
|
3345
|
+
root.endTime,
|
|
3346
|
+
root.duration,
|
|
3347
|
+
clampToRoot
|
|
3348
|
+
]);
|
|
3349
|
+
const scrollSpanIntoView = reactExports.useCallback((spanId) => {
|
|
3350
|
+
var _a;
|
|
3351
|
+
const index = trace.spans.findIndex((s) => s.spanId === spanId);
|
|
3352
|
+
if (index === -1)
|
|
3353
|
+
return;
|
|
3354
|
+
const list = ((_a = scrollContainerRef.current) == null ? void 0 : _a.querySelector("#event-list")) ?? null;
|
|
3355
|
+
scrollRowIntoView(list, index, ROW_HEIGHT_PX, {
|
|
3356
|
+
behavior: reducedMotion ? "auto" : "smooth"
|
|
3357
|
+
});
|
|
3358
|
+
}, [trace.spans, reducedMotion]);
|
|
3359
|
+
const zoomTimerRef = reactExports.useRef(null);
|
|
3360
|
+
const cancelPendingZoom = reactExports.useCallback(() => {
|
|
3361
|
+
if (zoomTimerRef.current !== null) {
|
|
3362
|
+
clearTimeout(zoomTimerRef.current);
|
|
3363
|
+
zoomTimerRef.current = null;
|
|
3364
|
+
}
|
|
3365
|
+
}, []);
|
|
3366
|
+
reactExports.useEffect(() => cancelPendingZoom, [cancelPendingZoom]);
|
|
3367
|
+
const handleClearActiveSpan = reactExports.useCallback(() => {
|
|
3368
|
+
cancelPendingZoom();
|
|
3369
|
+
clearActiveSpan();
|
|
3370
|
+
}, [cancelPendingZoom, clearActiveSpan]);
|
|
3371
|
+
const handleSelectSpan = reactExports.useCallback((spanId) => {
|
|
3372
|
+
cancelPendingZoom();
|
|
3373
|
+
if (spanId === activeSpanId) {
|
|
3374
|
+
clearActiveSpan();
|
|
3375
|
+
return;
|
|
3376
|
+
}
|
|
3377
|
+
setActiveSpan(spanId);
|
|
3378
|
+
focusViewportOnSpan(spanId);
|
|
3379
|
+
}, [
|
|
3380
|
+
cancelPendingZoom,
|
|
3381
|
+
activeSpanId,
|
|
3382
|
+
clearActiveSpan,
|
|
3383
|
+
setActiveSpan,
|
|
3384
|
+
focusViewportOnSpan
|
|
2855
3385
|
]);
|
|
3386
|
+
const navigateToSpan = reactExports.useCallback((spanId) => {
|
|
3387
|
+
setActiveSpan(spanId);
|
|
3388
|
+
scrollSpanIntoView(spanId);
|
|
3389
|
+
cancelPendingZoom();
|
|
3390
|
+
zoomTimerRef.current = setTimeout(() => {
|
|
3391
|
+
zoomTimerRef.current = null;
|
|
3392
|
+
focusViewportOnSpan(spanId);
|
|
3393
|
+
}, ZOOM_DEBOUNCE_MS);
|
|
3394
|
+
}, [setActiveSpan, scrollSpanIntoView, cancelPendingZoom, focusViewportOnSpan]);
|
|
2856
3395
|
const [altHeld, setAltHeld] = reactExports.useState(false);
|
|
2857
3396
|
reactExports.useEffect(() => {
|
|
2858
3397
|
const onKeyDown = (e) => {
|
|
2859
3398
|
if (e.key === "Escape") {
|
|
2860
|
-
|
|
2861
|
-
}
|
|
2862
|
-
if (e.key === "Alt") {
|
|
2863
|
-
e.preventDefault();
|
|
3399
|
+
handleClearActiveSpan();
|
|
3400
|
+
} else if (e.key === "Alt") {
|
|
2864
3401
|
setAltHeld(true);
|
|
2865
3402
|
}
|
|
2866
3403
|
};
|
|
@@ -2877,16 +3414,16 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2877
3414
|
window.removeEventListener("keyup", onKeyUp);
|
|
2878
3415
|
window.removeEventListener("blur", onBlur);
|
|
2879
3416
|
};
|
|
2880
|
-
}, [
|
|
3417
|
+
}, [handleClearActiveSpan]);
|
|
2881
3418
|
const timelineRef = reactExports.useRef(null);
|
|
2882
|
-
const [
|
|
3419
|
+
const [hover, setHover] = reactExports.useState(null);
|
|
2883
3420
|
const hoverInfo = reactExports.useMemo(() => {
|
|
2884
|
-
if (
|
|
3421
|
+
if (hover == null)
|
|
2885
3422
|
return null;
|
|
2886
|
-
const absTime = viewport.start +
|
|
3423
|
+
const absTime = viewport.start + hover.fraction * viewDuration;
|
|
2887
3424
|
const offset = absTime - root.startTime;
|
|
2888
|
-
return { fraction:
|
|
2889
|
-
}, [
|
|
3425
|
+
return { fraction: hover.fraction, label: formatDurationPrecise(offset) };
|
|
3426
|
+
}, [hover, viewport.start, viewDuration, root.startTime]);
|
|
2890
3427
|
const handleTimelineMouseMove = reactExports.useCallback((e) => {
|
|
2891
3428
|
const el = timelineRef.current;
|
|
2892
3429
|
if (!el)
|
|
@@ -2896,19 +3433,17 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2896
3433
|
if (contentWidth <= 0)
|
|
2897
3434
|
return;
|
|
2898
3435
|
const fraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
|
|
2899
|
-
|
|
3436
|
+
setHover({
|
|
3437
|
+
fraction,
|
|
3438
|
+
rowIndex: Math.floor((e.clientY - rect.top) / ROW_HEIGHT_PX)
|
|
3439
|
+
});
|
|
2900
3440
|
}, []);
|
|
2901
3441
|
const handleTimelineMouseLeave = reactExports.useCallback(() => {
|
|
2902
|
-
|
|
3442
|
+
setHover(null);
|
|
2903
3443
|
}, []);
|
|
2904
3444
|
reactExports.useEffect(() => {
|
|
2905
3445
|
const el = timelineRef.current;
|
|
2906
|
-
if (!el)
|
|
2907
|
-
return;
|
|
2908
|
-
const rootS = root.startTime;
|
|
2909
|
-
const rootE = root.startTime + root.duration;
|
|
2910
|
-
const rootD = root.duration;
|
|
2911
|
-
if (rootD <= 0)
|
|
3446
|
+
if (!el || root.duration <= 0)
|
|
2912
3447
|
return;
|
|
2913
3448
|
const onWheel = (e) => {
|
|
2914
3449
|
const isZoomGesture = e.ctrlKey || e.metaKey;
|
|
@@ -2921,81 +3456,50 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2921
3456
|
if (contentWidth <= 0)
|
|
2922
3457
|
return;
|
|
2923
3458
|
if (isZoomGesture) {
|
|
2924
|
-
let dy = e.deltaY;
|
|
2925
|
-
if (e.deltaMode === 1)
|
|
2926
|
-
dy *= 16;
|
|
2927
3459
|
const cursorFraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
|
|
2928
|
-
const scaleFactor =
|
|
3460
|
+
const scaleFactor = wheelZoomScaleFactor(e);
|
|
2929
3461
|
setViewport((prev) => {
|
|
2930
3462
|
const prevDuration = prev.end - prev.start;
|
|
2931
3463
|
const cursorTime = prev.start + cursorFraction * prevDuration;
|
|
2932
|
-
const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
newEnd = rootS + newDuration;
|
|
2938
|
-
}
|
|
2939
|
-
if (newEnd > rootE) {
|
|
2940
|
-
newEnd = rootE;
|
|
2941
|
-
newStart = Math.max(rootS, rootE - newDuration);
|
|
2942
|
-
}
|
|
2943
|
-
return { start: newStart, end: newEnd };
|
|
3464
|
+
const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(root.duration, prevDuration * scaleFactor));
|
|
3465
|
+
return clampToRoot({
|
|
3466
|
+
start: cursorTime - cursorFraction * newDuration,
|
|
3467
|
+
end: cursorTime + (1 - cursorFraction) * newDuration
|
|
3468
|
+
});
|
|
2944
3469
|
});
|
|
2945
3470
|
} else {
|
|
2946
|
-
|
|
2947
|
-
if (e.deltaMode === 1)
|
|
2948
|
-
dx *= 16;
|
|
3471
|
+
const dx = wheelDeltaToPixels(e.deltaX, e.deltaMode);
|
|
2949
3472
|
setViewport((prev) => {
|
|
2950
|
-
const
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
newStart = rootS;
|
|
2956
|
-
newEnd = rootS + prevDuration;
|
|
2957
|
-
}
|
|
2958
|
-
if (newEnd > rootE) {
|
|
2959
|
-
newEnd = rootE;
|
|
2960
|
-
newStart = Math.max(rootS, rootE - prevDuration);
|
|
2961
|
-
}
|
|
2962
|
-
return { start: newStart, end: newEnd };
|
|
3473
|
+
const panAmount = dx / contentWidth * (prev.end - prev.start);
|
|
3474
|
+
return clampToRoot({
|
|
3475
|
+
start: prev.start + panAmount,
|
|
3476
|
+
end: prev.end + panAmount
|
|
3477
|
+
});
|
|
2963
3478
|
});
|
|
2964
3479
|
}
|
|
2965
3480
|
};
|
|
2966
3481
|
el.addEventListener("wheel", onWheel, { passive: false });
|
|
2967
3482
|
return () => el.removeEventListener("wheel", onWheel);
|
|
2968
|
-
}, [root.
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
return (stepName ? (_a = parseStepName(stepName)) == null ? void 0 : _a.shortName : void 0) ?? (workflowName ? (_b = parseWorkflowName(workflowName)) == null ? void 0 : _b.shortName : void 0) ?? stepName ?? workflowName ?? data.hookId ?? "Details";
|
|
2977
|
-
}, [selectedSpan == null ? void 0 : selectedSpan.data]);
|
|
2978
|
-
const selectedResource = selectedSpan == null ? void 0 : selectedSpan.resource;
|
|
2979
|
-
const selectedResourceId = reactExports.useMemo(() => {
|
|
2980
|
-
if (!(selectedSpan == null ? void 0 : selectedSpan.data))
|
|
2981
|
-
return void 0;
|
|
2982
|
-
const data = selectedSpan.data;
|
|
2983
|
-
return data.stepId ?? data.runId ?? data.hookId ?? selectedSpan.spanId;
|
|
2984
|
-
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.spanId]);
|
|
2985
|
-
return jsxRuntimeExports.jsxs("div", { "data-pane": "pane-root", "data-has-detail": activeSpan ? "" : void 0, className: "grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsxs(SplitPane, { startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center px-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", onClick: () => setSearchQuery(""), className: "shrink-0 p-0.5 rounded-sm text-gray-800 hover:text-gray-1000 hover:bg-gray-200 transition-colors", children: jsxRuntimeExports.jsx(X, { className: "w-3 h-3" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo }), children: [jsxRuntimeExports.jsx("div", { className: "block overflow-visible", children: jsxRuntimeExports.jsx(EventList, { spans: filteredSpans, activeSpanId, onSelectSpan: handleSelectSpan }) }), jsxRuntimeExports.jsx("div", { ref: timelineRef, className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: filteredSpans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, onSelect: handleSelectSpan, hoverFraction, altHeld }) })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-lg bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100", onClick: zoomOut, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100", onClick: zoomIn, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan && sidebar ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 px-4 pt-4 pb-3", children: jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntimeExports.jsx("span", { className: "text-[15px] font-semibold text-gray-1000 truncate block", children: selectedSpanName }), selectedResourceId && jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center gap-2", children: [selectedResource && jsxRuntimeExports.jsx("span", { className: `inline-flex items-center rounded-md px-1.5 py-0.5 text-[11px] font-medium leading-none shrink-0 ${selectedResource === "step" ? "bg-green-200 text-green-900" : selectedResource === "run" ? "bg-blue-200 text-blue-900" : selectedResource === "hook" ? "bg-yellow-200 text-yellow-900" : "bg-gray-200 text-gray-900"}`, children: selectedResource.charAt(0).toUpperCase() + selectedResource.slice(1) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[13px] font-mono text-gray-700 min-w-0", title: selectedResourceId, children: [jsxRuntimeExports.jsx("span", { className: "truncate", children: selectedResourceId }), jsxRuntimeExports.jsx(CopyButton, { copyText: selectedResourceId, ariaLabel: "Copy ID", className: "shrink-0" })] })] })] }), jsxRuntimeExports.jsx("button", { type: "button", className: "p-1 rounded-md text-gray-900 hover:text-gray-1000 hover:bg-gray-alpha-200 transition-colors shrink-0", onClick: clearActiveSpan, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] }) }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan }) }) })] }) : activeSpan ? jsxRuntimeExports.jsx(DetailPanel, { span: activeSpan, rootStart: root.startTime, onClose: clearActiveSpan }) : null] });
|
|
3483
|
+
}, [root.duration, setViewport, clampToRoot]);
|
|
3484
|
+
return jsxRuntimeExports.jsxs("div", { ref: paneRootRef, "data-pane": "pane-root", className: "relative flex w-full h-full max-h-full", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "@container flex-1 min-w-0 grid grid-rows-[auto_1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsx(Minimap, { spans: trace.spans, root, viewport, minViewportMs: MIN_VIEWPORT_MS, onViewportChange: setViewport, onAnimateTo: animateTo }), jsxRuntimeExports.jsxs(SplitPane, { scrollContainerRef, startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
|
|
3485
|
+
if (e.key === "Escape" && searchQuery) {
|
|
3486
|
+
e.preventDefault();
|
|
3487
|
+
e.stopPropagation();
|
|
3488
|
+
setSearchQuery("");
|
|
3489
|
+
}
|
|
3490
|
+
}, placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-label-14 text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => setSearchQuery(""), className: "-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-label-16 text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex", children: jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "search", children: "Esc" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }), jsxRuntimeExports.jsx("div", { ref: loadMoreSentinelRef, className: "flex justify-center", children: isLoadingMore ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 py-3 text-label-14 text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsx("div", { ref: timelineRef, id: "trace-timeline", className: "@container block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: trace.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult, onSelect: handleSelectSpan, onRevealTime: handleRevealTime, hover, altHeld }) }), jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace.spans.length > 1, reducedMotion }), jsxRuntimeExports.jsxs("div", { className: "pointer-events-auto flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomOut, disabled: isAtMinZoom, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, disabled: isAtMaxZoom, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] })] })] }), jsxRuntimeExports.jsx(TraceDetailPanel, { containerRef: paneRootRef, onNavigateToSpan: navigateToSpan, onClose: handleClearActiveSpan })] });
|
|
2986
3491
|
}
|
|
2987
|
-
const
|
|
2988
|
-
const
|
|
3492
|
+
const TraceViewer = ({ run, events, sidebarData, onLoadMore, hasMore, isLoadingMore, loading = false }) => {
|
|
3493
|
+
const trace = reactExports.useMemo(() => {
|
|
2989
3494
|
if (!(run == null ? void 0 : run.runId)) {
|
|
2990
3495
|
return void 0;
|
|
2991
3496
|
}
|
|
2992
3497
|
return buildTrace(run, events, /* @__PURE__ */ new Date());
|
|
2993
3498
|
}, [run, events]);
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
return jsxRuntimeExports.jsx("div", { className: "relative w-full h-full flex items-center justify-center", children: jsxRuntimeExports.jsx("div", { className: "text-gray-500 text-sm", children: "Loading trace…" }) });
|
|
3499
|
+
if (!trace || loading && events.length === 0) {
|
|
3500
|
+
return jsxRuntimeExports.jsx(TraceViewerSkeleton, {});
|
|
2997
3501
|
}
|
|
2998
|
-
return jsxRuntimeExports.jsx(SidebarDataProvider, { value: sidebarData, children: jsxRuntimeExports.jsx("div", { className: "relative w-full h-full flex", children: jsxRuntimeExports.jsx(
|
|
3502
|
+
return jsxRuntimeExports.jsx(SidebarDataProvider, { value: sidebarData, children: jsxRuntimeExports.jsx("div", { className: "relative w-full h-full flex", children: jsxRuntimeExports.jsx(TraceViewer$1, { trace, onLoadMore, hasMore, isLoadingMore }) }) });
|
|
2999
3503
|
};
|
|
3000
3504
|
async function fetchResourceWithCorrelationId(env, resource, resourceId, options = {}) {
|
|
3001
3505
|
const resolveData = options.resolveData ?? "all";
|
|
@@ -3025,130 +3529,45 @@ async function fetchResourceWithCorrelationId(env, resource, resourceId, options
|
|
|
3025
3529
|
}
|
|
3026
3530
|
return { data: resourceData, correlationId };
|
|
3027
3531
|
}
|
|
3028
|
-
function
|
|
3029
|
-
const {
|
|
3030
|
-
const
|
|
3031
|
-
|
|
3032
|
-
)
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
setLoading(false);
|
|
3043
|
-
return;
|
|
3044
|
-
}
|
|
3045
|
-
const selectionKey = `${resource}:${resourceId}`;
|
|
3046
|
-
if (selectionKey !== prevSelectionRef.current) {
|
|
3047
|
-
setData(null);
|
|
3048
|
-
prevSelectionRef.current = selectionKey;
|
|
3049
|
-
}
|
|
3050
|
-
setError(null);
|
|
3051
|
-
setLoading(true);
|
|
3052
|
-
if (resource === "hook") {
|
|
3053
|
-
try {
|
|
3054
|
-
const { error: error2, result } = await unwrapServerActionResult(
|
|
3055
|
-
fetchHook(env, resourceId, "all")
|
|
3056
|
-
);
|
|
3057
|
-
if (error2) {
|
|
3058
|
-
setError(error2);
|
|
3059
|
-
return;
|
|
3060
|
-
}
|
|
3061
|
-
try {
|
|
3062
|
-
setData(await hydrate(result));
|
|
3063
|
-
} catch (hydrateError) {
|
|
3064
|
-
setError(
|
|
3065
|
-
hydrateError instanceof Error ? hydrateError : new Error(String(hydrateError))
|
|
3066
|
-
);
|
|
3067
|
-
}
|
|
3068
|
-
} finally {
|
|
3069
|
-
setLoading(false);
|
|
3070
|
-
}
|
|
3071
|
-
return;
|
|
3072
|
-
}
|
|
3073
|
-
if (resource === "sleep") {
|
|
3074
|
-
try {
|
|
3075
|
-
if (!runId) {
|
|
3076
|
-
setError(new Error("runId is required for loading sleep details"));
|
|
3077
|
-
return;
|
|
3078
|
-
}
|
|
3079
|
-
const { error: error2, result } = await unwrapServerActionResult(
|
|
3080
|
-
fetchEvents(env, runId, {
|
|
3081
|
-
sortOrder: "asc",
|
|
3082
|
-
limit: 1e3,
|
|
3083
|
-
withData: true
|
|
3084
|
-
})
|
|
3085
|
-
);
|
|
3086
|
-
if (error2) {
|
|
3087
|
-
setError(error2);
|
|
3088
|
-
return;
|
|
3089
|
-
}
|
|
3090
|
-
try {
|
|
3091
|
-
const allEvents = result.data.map(
|
|
3092
|
-
hydrateResourceIO
|
|
3093
|
-
);
|
|
3094
|
-
const waitEvents = await Promise.all(
|
|
3095
|
-
allEvents.filter((e) => e.correlationId === resourceId).map(hydrate)
|
|
3096
|
-
);
|
|
3097
|
-
const data2 = waitEventsToWaitEntity(waitEvents);
|
|
3098
|
-
if (data2 === null) {
|
|
3099
|
-
setError(
|
|
3100
|
-
new Error(
|
|
3101
|
-
`Failed to load ${resource} details: missing required event data`
|
|
3102
|
-
)
|
|
3103
|
-
);
|
|
3104
|
-
return;
|
|
3105
|
-
}
|
|
3106
|
-
setData(data2);
|
|
3107
|
-
} catch (hydrateError) {
|
|
3108
|
-
setError(
|
|
3109
|
-
hydrateError instanceof Error ? hydrateError : new Error(String(hydrateError))
|
|
3110
|
-
);
|
|
3111
|
-
}
|
|
3112
|
-
} finally {
|
|
3113
|
-
setLoading(false);
|
|
3114
|
-
}
|
|
3115
|
-
return;
|
|
3532
|
+
async function fetchSpanDetailResource(env, selection, options = {}) {
|
|
3533
|
+
const { resource, resourceId, runId } = selection;
|
|
3534
|
+
const { encryptionKey } = options;
|
|
3535
|
+
const hydrate = async (value) => hydrateResourceIOAsync(value, encryptionKey);
|
|
3536
|
+
if (resource === "hook") {
|
|
3537
|
+
const result = await unwrapOrThrow(fetchHook(env, resourceId, "all"));
|
|
3538
|
+
return hydrate(result);
|
|
3539
|
+
}
|
|
3540
|
+
if (resource === "sleep") {
|
|
3541
|
+
if (!runId) {
|
|
3542
|
+
throw new WorkflowWebAPIError(
|
|
3543
|
+
"runId is required for loading sleep details",
|
|
3544
|
+
{ layer: "client" }
|
|
3545
|
+
);
|
|
3116
3546
|
}
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3547
|
+
const result = await unwrapOrThrow(
|
|
3548
|
+
fetchEvents(env, runId, { sortOrder: "asc", limit: 1e3, withData: true })
|
|
3549
|
+
);
|
|
3550
|
+
const waitEvents = await Promise.all(
|
|
3551
|
+
result.data.filter((e) => e.correlationId === resourceId).map(hydrate)
|
|
3552
|
+
);
|
|
3553
|
+
const data2 = waitEventsToWaitEntity(waitEvents);
|
|
3554
|
+
if (data2 === null) {
|
|
3555
|
+
throw new WorkflowWebAPIError(
|
|
3556
|
+
`Failed to load ${resource} details: missing required event data`,
|
|
3557
|
+
{ layer: "client" }
|
|
3123
3558
|
);
|
|
3124
|
-
setData(await hydrate(resourceData));
|
|
3125
|
-
} catch (error2) {
|
|
3126
|
-
if (error2 instanceof Error) {
|
|
3127
|
-
setError(error2);
|
|
3128
|
-
} else {
|
|
3129
|
-
setError(new Error(String(error2)));
|
|
3130
|
-
}
|
|
3131
|
-
return;
|
|
3132
|
-
} finally {
|
|
3133
|
-
setLoading(false);
|
|
3134
3559
|
}
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3560
|
+
return data2;
|
|
3561
|
+
}
|
|
3562
|
+
const { data } = await fetchResourceWithCorrelationId(
|
|
3563
|
+
env,
|
|
3564
|
+
resource,
|
|
3565
|
+
resourceId,
|
|
3566
|
+
{
|
|
3567
|
+
runId
|
|
3142
3568
|
}
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
}, [refreshInterval, fetchData]);
|
|
3146
|
-
return {
|
|
3147
|
-
data,
|
|
3148
|
-
loading,
|
|
3149
|
-
error,
|
|
3150
|
-
refresh: fetchData
|
|
3151
|
-
};
|
|
3569
|
+
);
|
|
3570
|
+
return hydrate(data);
|
|
3152
3571
|
}
|
|
3153
3572
|
function mergeById(prev, next, idKey) {
|
|
3154
3573
|
const combined = [...prev, ...next];
|
|
@@ -3187,6 +3606,7 @@ const LIVE_POLL_LIMIT = 100;
|
|
|
3187
3606
|
const INITIAL_PAGE_SIZE$1 = 500;
|
|
3188
3607
|
const LOAD_MORE_PAGE_SIZE$1 = 100;
|
|
3189
3608
|
const LIVE_UPDATE_INTERVAL_MS = 5e3;
|
|
3609
|
+
const AUTO_LOAD_MAX_EVENTS = 500;
|
|
3190
3610
|
function useWorkflowTraceViewerData(env, runId, options = {}) {
|
|
3191
3611
|
const { live = false } = options;
|
|
3192
3612
|
const [run, setRun] = reactExports.useState(null);
|
|
@@ -3295,6 +3715,12 @@ function useWorkflowTraceViewerData(env, runId, options = {}) {
|
|
|
3295
3715
|
eventsHasMore,
|
|
3296
3716
|
eventsCursor
|
|
3297
3717
|
]);
|
|
3718
|
+
reactExports.useEffect(() => {
|
|
3719
|
+
if (events.length >= AUTO_LOAD_MAX_EVENTS) {
|
|
3720
|
+
return;
|
|
3721
|
+
}
|
|
3722
|
+
loadMoreTraceData();
|
|
3723
|
+
}, [events.length, loadMoreTraceData]);
|
|
3298
3724
|
const pollRun = reactExports.useCallback(async () => {
|
|
3299
3725
|
if (run == null ? void 0 : run.completedAt) {
|
|
3300
3726
|
return false;
|
|
@@ -3382,7 +3808,7 @@ async function readStream(_env, streamId, runId, signal, cursor) {
|
|
|
3382
3808
|
if (cursor) {
|
|
3383
3809
|
params.set("cursor", cursor);
|
|
3384
3810
|
}
|
|
3385
|
-
const url =
|
|
3811
|
+
const url = `${apiBase()}/api/stream/${encodeURIComponent(streamId)}?${params.toString()}`;
|
|
3386
3812
|
const response = await fetch(url, { signal });
|
|
3387
3813
|
if (!response.ok) {
|
|
3388
3814
|
const errorData = await response.json().catch(() => null);
|
|
@@ -4555,6 +4981,7 @@ function BreadcrumbSeparator({
|
|
|
4555
4981
|
}
|
|
4556
4982
|
const INITIAL_PAGE_SIZE = 100;
|
|
4557
4983
|
const LOAD_MORE_PAGE_SIZE = 100;
|
|
4984
|
+
const MAX_CORRELATION_SEARCH_PAGES = 30;
|
|
4558
4985
|
function useEventsListData(env, runId, options = {}) {
|
|
4559
4986
|
const { sortOrder = "asc", encryptionKey, enabled = true } = options;
|
|
4560
4987
|
const [events, setEvents] = reactExports.useState([]);
|
|
@@ -4566,6 +4993,10 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4566
4993
|
const isFetchingRef = reactExports.useRef(false);
|
|
4567
4994
|
const encryptionKeyRef = reactExports.useRef(encryptionKey);
|
|
4568
4995
|
encryptionKeyRef.current = encryptionKey;
|
|
4996
|
+
const hydrateEvents = reactExports.useCallback(async (rawEvents) => {
|
|
4997
|
+
const key = encryptionKeyRef.current;
|
|
4998
|
+
return Promise.all(rawEvents.map((ev) => hydrateResourceIOAsync(ev, key)));
|
|
4999
|
+
}, []);
|
|
4569
5000
|
const fetchInitial = reactExports.useCallback(async () => {
|
|
4570
5001
|
if (isFetchingRef.current) return;
|
|
4571
5002
|
isFetchingRef.current = true;
|
|
@@ -4585,16 +5016,7 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4585
5016
|
if (fetchError) {
|
|
4586
5017
|
setError(fetchError);
|
|
4587
5018
|
} else {
|
|
4588
|
-
|
|
4589
|
-
const key = encryptionKeyRef.current;
|
|
4590
|
-
if (key) {
|
|
4591
|
-
const decrypted = await Promise.all(
|
|
4592
|
-
hydrated.map((ev) => hydrateResourceIOWithKey(ev, key))
|
|
4593
|
-
);
|
|
4594
|
-
setEvents(decrypted);
|
|
4595
|
-
} else {
|
|
4596
|
-
setEvents(hydrated);
|
|
4597
|
-
}
|
|
5019
|
+
setEvents(await hydrateEvents(result.data));
|
|
4598
5020
|
setCursor(result.hasMore ? result.cursor : void 0);
|
|
4599
5021
|
setHasMore(Boolean(result.hasMore));
|
|
4600
5022
|
}
|
|
@@ -4604,14 +5026,14 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4604
5026
|
setLoading(false);
|
|
4605
5027
|
isFetchingRef.current = false;
|
|
4606
5028
|
}
|
|
4607
|
-
}, [env, runId, sortOrder]);
|
|
5029
|
+
}, [env, runId, sortOrder, hydrateEvents]);
|
|
4608
5030
|
reactExports.useEffect(() => {
|
|
4609
5031
|
if (enabled) fetchInitial();
|
|
4610
5032
|
}, [fetchInitial, enabled]);
|
|
4611
5033
|
reactExports.useEffect(() => {
|
|
4612
5034
|
if (!encryptionKey || events.length === 0) return;
|
|
4613
5035
|
let cancelled = false;
|
|
4614
|
-
Promise.all(events.map((ev) =>
|
|
5036
|
+
Promise.all(events.map((ev) => hydrateResourceIOAsync(ev, encryptionKey))).then((decrypted) => {
|
|
4615
5037
|
if (!cancelled) setEvents(decrypted);
|
|
4616
5038
|
}).catch(() => {
|
|
4617
5039
|
});
|
|
@@ -4635,16 +5057,8 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4635
5057
|
setError(fetchError);
|
|
4636
5058
|
} else {
|
|
4637
5059
|
if (result.data.length > 0) {
|
|
4638
|
-
const hydrated = result.data
|
|
4639
|
-
|
|
4640
|
-
if (key) {
|
|
4641
|
-
const decrypted = await Promise.all(
|
|
4642
|
-
hydrated.map((ev) => hydrateResourceIOWithKey(ev, key))
|
|
4643
|
-
);
|
|
4644
|
-
setEvents((prev) => [...prev, ...decrypted]);
|
|
4645
|
-
} else {
|
|
4646
|
-
setEvents((prev) => [...prev, ...hydrated]);
|
|
4647
|
-
}
|
|
5060
|
+
const hydrated = await hydrateEvents(result.data);
|
|
5061
|
+
setEvents((prev) => [...prev, ...hydrated]);
|
|
4648
5062
|
}
|
|
4649
5063
|
setCursor(result.hasMore ? result.cursor : void 0);
|
|
4650
5064
|
setHasMore(Boolean(result.hasMore));
|
|
@@ -4654,14 +5068,66 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4654
5068
|
} finally {
|
|
4655
5069
|
setLoadingMore(false);
|
|
4656
5070
|
}
|
|
4657
|
-
}, [env, runId, sortOrder, cursor, loadingMore]);
|
|
5071
|
+
}, [env, runId, sortOrder, cursor, loadingMore, hydrateEvents]);
|
|
5072
|
+
const searchByExactId = reactExports.useCallback(
|
|
5073
|
+
async (id, kind, signal) => {
|
|
5074
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
5075
|
+
throw new DOMException("Aborted", "AbortError");
|
|
5076
|
+
}
|
|
5077
|
+
if (kind === "event") {
|
|
5078
|
+
const { error: fetchError, result } = await unwrapServerActionResult(
|
|
5079
|
+
fetchEvent(env, runId, id, "none")
|
|
5080
|
+
);
|
|
5081
|
+
if (fetchError || (signal == null ? void 0 : signal.aborted)) {
|
|
5082
|
+
return fetchError ? { status: "error", message: fetchError.message } : (() => {
|
|
5083
|
+
throw new DOMException("Aborted", "AbortError");
|
|
5084
|
+
})();
|
|
5085
|
+
}
|
|
5086
|
+
const [event] = await hydrateEvents([result]);
|
|
5087
|
+
return (event == null ? void 0 : event.runId) === runId ? { status: "ok", events: [event] } : { status: "not_found" };
|
|
5088
|
+
}
|
|
5089
|
+
const matched = [];
|
|
5090
|
+
let nextCursor;
|
|
5091
|
+
let pagesFetched = 0;
|
|
5092
|
+
let truncated = false;
|
|
5093
|
+
do {
|
|
5094
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
5095
|
+
throw new DOMException("Aborted", "AbortError");
|
|
5096
|
+
}
|
|
5097
|
+
const { error: fetchError, result } = await unwrapServerActionResult(
|
|
5098
|
+
fetchEventsByCorrelationId(env, id, {
|
|
5099
|
+
cursor: nextCursor,
|
|
5100
|
+
sortOrder,
|
|
5101
|
+
limit: 100,
|
|
5102
|
+
withData: false,
|
|
5103
|
+
runId
|
|
5104
|
+
})
|
|
5105
|
+
);
|
|
5106
|
+
if (fetchError) {
|
|
5107
|
+
return { status: "error", message: fetchError.message };
|
|
5108
|
+
}
|
|
5109
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
5110
|
+
throw new DOMException("Aborted", "AbortError");
|
|
5111
|
+
}
|
|
5112
|
+
pagesFetched += 1;
|
|
5113
|
+
const hydrated = await hydrateEvents(result.data);
|
|
5114
|
+
matched.push(...hydrated.filter((event) => event.runId === runId));
|
|
5115
|
+
const hitPageCap = pagesFetched >= MAX_CORRELATION_SEARCH_PAGES;
|
|
5116
|
+
truncated = truncated || hitPageCap && Boolean(result.hasMore && result.cursor);
|
|
5117
|
+
nextCursor = !hitPageCap && result.hasMore && result.cursor ? result.cursor : void 0;
|
|
5118
|
+
} while (nextCursor);
|
|
5119
|
+
return matched.length > 0 ? { status: "ok", events: matched, truncated: truncated || void 0 } : { status: "not_found" };
|
|
5120
|
+
},
|
|
5121
|
+
[env, runId, sortOrder, hydrateEvents]
|
|
5122
|
+
);
|
|
4658
5123
|
return {
|
|
4659
5124
|
events,
|
|
4660
5125
|
loading,
|
|
4661
5126
|
error,
|
|
4662
5127
|
hasMore,
|
|
4663
5128
|
loadingMore,
|
|
4664
|
-
loadMore
|
|
5129
|
+
loadMore,
|
|
5130
|
+
searchByExactId
|
|
4665
5131
|
};
|
|
4666
5132
|
}
|
|
4667
5133
|
const FRAME_HEADER_SIZE = 4;
|
|
@@ -4682,6 +5148,9 @@ function detectEncoding(data) {
|
|
|
4682
5148
|
function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
4683
5149
|
const [chunks, setChunks] = reactExports.useState([]);
|
|
4684
5150
|
const [isLive, setIsLive] = reactExports.useState(false);
|
|
5151
|
+
const [isInitialLoading, setIsInitialLoading] = reactExports.useState(
|
|
5152
|
+
Boolean(streamId && runId)
|
|
5153
|
+
);
|
|
4685
5154
|
const [error, setError] = reactExports.useState(null);
|
|
4686
5155
|
const abortControllerRef = reactExports.useRef(null);
|
|
4687
5156
|
const chunkIdRef = reactExports.useRef(0);
|
|
@@ -4710,9 +5179,8 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4710
5179
|
if (!cryptoKey) {
|
|
4711
5180
|
return { encrypted: true };
|
|
4712
5181
|
}
|
|
4713
|
-
const payload = frameData.slice(4);
|
|
4714
5182
|
hydrated = hydrateData(
|
|
4715
|
-
await decrypt(
|
|
5183
|
+
await decrypt(frameData, cryptoKey),
|
|
4716
5184
|
revivers
|
|
4717
5185
|
);
|
|
4718
5186
|
} else {
|
|
@@ -4729,6 +5197,8 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4729
5197
|
reactExports.useEffect(() => {
|
|
4730
5198
|
setChunks([]);
|
|
4731
5199
|
setError(null);
|
|
5200
|
+
setIsLive(false);
|
|
5201
|
+
setIsInitialLoading(Boolean(streamId && runId));
|
|
4732
5202
|
chunkIdRef.current = 0;
|
|
4733
5203
|
frameCountRef.current = 0;
|
|
4734
5204
|
serverCursorRef.current = null;
|
|
@@ -4737,13 +5207,12 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4737
5207
|
pollTimerRef.current = null;
|
|
4738
5208
|
}
|
|
4739
5209
|
if (!streamId || !runId) {
|
|
4740
|
-
|
|
5210
|
+
setIsInitialLoading(false);
|
|
4741
5211
|
return;
|
|
4742
5212
|
}
|
|
4743
5213
|
let mounted = true;
|
|
4744
5214
|
const abortController = new AbortController();
|
|
4745
5215
|
abortControllerRef.current = abortController;
|
|
4746
|
-
setIsLive(true);
|
|
4747
5216
|
const revivers = getWebRevivers();
|
|
4748
5217
|
const parseLegacyLine = (line) => {
|
|
4749
5218
|
const chunkId = chunkIdRef.current++;
|
|
@@ -4865,13 +5334,14 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4865
5334
|
};
|
|
4866
5335
|
const readStreamData = async () => {
|
|
4867
5336
|
try {
|
|
4868
|
-
const cryptoKey = encryptionKey ? await
|
|
5337
|
+
const cryptoKey = encryptionKey ? await deriveRunPayloadKeys(encryptionKey) : void 0;
|
|
4869
5338
|
const initialChunks = [];
|
|
4870
5339
|
const result = await fetchAndParse(initialChunks, cryptoKey);
|
|
4871
5340
|
if (result.encrypted) {
|
|
4872
5341
|
if (mounted) {
|
|
4873
5342
|
setError("This stream is encrypted. Click Decrypt to view.");
|
|
4874
5343
|
setIsLive(false);
|
|
5344
|
+
setIsInitialLoading(false);
|
|
4875
5345
|
}
|
|
4876
5346
|
return;
|
|
4877
5347
|
}
|
|
@@ -4879,11 +5349,13 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4879
5349
|
serverCursorRef.current = result.cursor;
|
|
4880
5350
|
if (!mounted || abortController.signal.aborted) return;
|
|
4881
5351
|
setChunks(initialChunks);
|
|
5352
|
+
setIsInitialLoading(false);
|
|
4882
5353
|
if (result.done) {
|
|
4883
5354
|
setIsLive(false);
|
|
4884
5355
|
return;
|
|
4885
5356
|
}
|
|
4886
5357
|
if (isRunActive(runStatusRef.current)) {
|
|
5358
|
+
setIsLive(true);
|
|
4887
5359
|
const poll = async () => {
|
|
4888
5360
|
if (!mounted || abortController.signal.aborted) return;
|
|
4889
5361
|
try {
|
|
@@ -4921,6 +5393,7 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4921
5393
|
if (mounted) {
|
|
4922
5394
|
setError(err instanceof Error ? err.message : String(err));
|
|
4923
5395
|
setIsLive(false);
|
|
5396
|
+
setIsInitialLoading(false);
|
|
4924
5397
|
}
|
|
4925
5398
|
}
|
|
4926
5399
|
};
|
|
@@ -4941,11 +5414,11 @@ function useStreamReader(env, streamId, runId, encryptionKey, runStatus) {
|
|
|
4941
5414
|
setIsLive(false);
|
|
4942
5415
|
}
|
|
4943
5416
|
}, [runStatus]);
|
|
4944
|
-
return { chunks, isLive, error };
|
|
5417
|
+
return { chunks, isLive, isInitialLoading, error };
|
|
4945
5418
|
}
|
|
4946
5419
|
function LiveStatus({ hasError, errorMessage }) {
|
|
4947
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
4948
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
5420
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip$1, { children: [
|
|
5421
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
4949
5422
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
4950
5423
|
"div",
|
|
4951
5424
|
{
|
|
@@ -4963,7 +5436,7 @@ function LiveStatus({ hasError, errorMessage }) {
|
|
|
4963
5436
|
}
|
|
4964
5437
|
)
|
|
4965
5438
|
] }) }),
|
|
4966
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: hasError ? `Error updating data: ${errorMessage}` : `Content updates every ${LIVE_UPDATE_INTERVAL_MS$1 / 1e3} seconds` }) })
|
|
5439
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: hasError ? `Error updating data: ${errorMessage}` : `Content updates every ${LIVE_UPDATE_INTERVAL_MS$1 / 1e3} seconds` }) })
|
|
4967
5440
|
] }) });
|
|
4968
5441
|
}
|
|
4969
5442
|
({
|
|
@@ -4971,7 +5444,6 @@ function LiveStatus({ hasError, errorMessage }) {
|
|
|
4971
5444
|
});
|
|
4972
5445
|
function RunDetailView({
|
|
4973
5446
|
runId,
|
|
4974
|
-
// TODO: This should open the right sidebar within the trace viewer
|
|
4975
5447
|
selectedId: _selectedId
|
|
4976
5448
|
}) {
|
|
4977
5449
|
var _a;
|
|
@@ -5049,29 +5521,16 @@ function RunDetailView({
|
|
|
5049
5521
|
if (error2) {
|
|
5050
5522
|
throw error2;
|
|
5051
5523
|
}
|
|
5052
|
-
const fullEvent =
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
}
|
|
5056
|
-
return null;
|
|
5057
|
-
},
|
|
5058
|
-
[env]
|
|
5059
|
-
);
|
|
5060
|
-
const handleLoadSidebarEventData = reactExports.useCallback(
|
|
5061
|
-
async (_correlationId, eventId) => {
|
|
5062
|
-
const { error: error2, result } = await unwrapServerActionResult(
|
|
5063
|
-
fetchEvent(env, runId, eventId, "all")
|
|
5524
|
+
const fullEvent = await hydrateResourceIOAsync(
|
|
5525
|
+
result,
|
|
5526
|
+
encryptionKeyRef.current ?? void 0
|
|
5064
5527
|
);
|
|
5065
|
-
if (error2) {
|
|
5066
|
-
throw error2;
|
|
5067
|
-
}
|
|
5068
|
-
const fullEvent = encryptionKeyRef.current ? await hydrateResourceIOWithKey(result, encryptionKeyRef.current) : hydrateResourceIO(result);
|
|
5069
5528
|
if ("eventData" in fullEvent) {
|
|
5070
5529
|
return fullEvent.eventData;
|
|
5071
5530
|
}
|
|
5072
5531
|
return null;
|
|
5073
5532
|
},
|
|
5074
|
-
[env
|
|
5533
|
+
[env]
|
|
5075
5534
|
);
|
|
5076
5535
|
serverConfig.backendId === "local" || serverConfig.backendId === "@workflow/world-local";
|
|
5077
5536
|
const {
|
|
@@ -5080,7 +5539,10 @@ function RunDetailView({
|
|
|
5080
5539
|
loading,
|
|
5081
5540
|
error,
|
|
5082
5541
|
update,
|
|
5083
|
-
hasEncryptedData
|
|
5542
|
+
hasEncryptedData,
|
|
5543
|
+
loadMoreTraceData,
|
|
5544
|
+
hasMoreTraceData,
|
|
5545
|
+
isLoadingMoreTraceData
|
|
5084
5546
|
} = useWorkflowTraceViewerData(env, runId, { live: true });
|
|
5085
5547
|
const run = runData ?? {};
|
|
5086
5548
|
const [encryptionKey, setEncryptionKey] = reactExports.useState(null);
|
|
@@ -5091,36 +5553,22 @@ function RunDetailView({
|
|
|
5091
5553
|
loading: eventsListLoading,
|
|
5092
5554
|
hasMore: hasMoreEventsTab,
|
|
5093
5555
|
loadingMore: loadingMoreEventsTab,
|
|
5094
|
-
loadMore: loadMoreEventsTab
|
|
5556
|
+
loadMore: loadMoreEventsTab,
|
|
5557
|
+
searchByExactId
|
|
5095
5558
|
} = useEventsListData(env, runId, {
|
|
5096
5559
|
sortOrder: eventsSortOrder,
|
|
5097
5560
|
encryptionKey: encryptionKey ?? void 0,
|
|
5098
5561
|
enabled: activeTab === "events"
|
|
5099
5562
|
});
|
|
5100
|
-
const
|
|
5101
|
-
|
|
5102
|
-
);
|
|
5103
|
-
const {
|
|
5104
|
-
data: spanDetailData,
|
|
5105
|
-
loading: spanDetailLoading,
|
|
5106
|
-
error: spanDetailError,
|
|
5107
|
-
refresh: refreshSpanDetail
|
|
5108
|
-
} = useWorkflowResourceData(
|
|
5109
|
-
env,
|
|
5110
|
-
(spanSelection == null ? void 0 : spanSelection.resource) ?? "run",
|
|
5111
|
-
(spanSelection == null ? void 0 : spanSelection.resourceId) ?? "",
|
|
5112
|
-
{
|
|
5113
|
-
runId: spanSelection == null ? void 0 : spanSelection.runId,
|
|
5114
|
-
enabled: Boolean(
|
|
5115
|
-
(spanSelection == null ? void 0 : spanSelection.resource) && (spanSelection == null ? void 0 : spanSelection.resourceId) && spanSelection.resource !== "hook"
|
|
5116
|
-
),
|
|
5563
|
+
const fetchSpanDetail = reactExports.useCallback(
|
|
5564
|
+
(selection) => fetchSpanDetailResource(env, selection, {
|
|
5117
5565
|
encryptionKey: encryptionKey ?? void 0
|
|
5118
|
-
}
|
|
5566
|
+
}),
|
|
5567
|
+
[env, encryptionKey]
|
|
5119
5568
|
);
|
|
5120
5569
|
const [isDecrypting, setIsDecrypting] = reactExports.useState(false);
|
|
5121
5570
|
const handleDecrypt = reactExports.useCallback(async () => {
|
|
5122
5571
|
if (encryptionKey) {
|
|
5123
|
-
refreshSpanDetail();
|
|
5124
5572
|
return;
|
|
5125
5573
|
}
|
|
5126
5574
|
setIsDecrypting(true);
|
|
@@ -5135,26 +5583,19 @@ function RunDetailView({
|
|
|
5135
5583
|
return;
|
|
5136
5584
|
}
|
|
5137
5585
|
setEncryptionKey(keyResult);
|
|
5138
|
-
toast.success("Run data decrypted successfully");
|
|
5139
5586
|
} finally {
|
|
5140
5587
|
setIsDecrypting(false);
|
|
5141
5588
|
}
|
|
5142
|
-
}, [encryptionKey, env, runId
|
|
5143
|
-
const handleSpanSelect = reactExports.useCallback((info) => {
|
|
5144
|
-
setSpanSelection(info);
|
|
5145
|
-
}, []);
|
|
5589
|
+
}, [encryptionKey, env, runId]);
|
|
5146
5590
|
const sidebarData = reactExports.useMemo(
|
|
5147
5591
|
() => ({
|
|
5148
5592
|
run,
|
|
5149
5593
|
events: allEvents ?? [],
|
|
5150
|
-
|
|
5151
|
-
spanDetailError,
|
|
5152
|
-
spanDetailLoading,
|
|
5153
|
-
onSpanSelect: handleSpanSelect,
|
|
5594
|
+
fetchSpanDetail,
|
|
5154
5595
|
onStreamClick: handleStreamClick,
|
|
5155
5596
|
onRunClick: handleRunRefClick,
|
|
5156
5597
|
onWakeUpSleep: handleWakeUpSleep,
|
|
5157
|
-
onLoadEventData:
|
|
5598
|
+
onLoadEventData: handleLoadEventData,
|
|
5158
5599
|
onResolveHook: handleResolveHook,
|
|
5159
5600
|
encryptionKey: encryptionKey ?? void 0,
|
|
5160
5601
|
onDecrypt: handleDecrypt,
|
|
@@ -5164,14 +5605,11 @@ function RunDetailView({
|
|
|
5164
5605
|
[
|
|
5165
5606
|
run,
|
|
5166
5607
|
allEvents,
|
|
5167
|
-
|
|
5168
|
-
spanDetailError,
|
|
5169
|
-
spanDetailLoading,
|
|
5170
|
-
handleSpanSelect,
|
|
5608
|
+
fetchSpanDetail,
|
|
5171
5609
|
handleStreamClick,
|
|
5172
5610
|
handleRunRefClick,
|
|
5173
5611
|
handleWakeUpSleep,
|
|
5174
|
-
|
|
5612
|
+
handleLoadEventData,
|
|
5175
5613
|
handleResolveHook,
|
|
5176
5614
|
encryptionKey,
|
|
5177
5615
|
handleDecrypt,
|
|
@@ -5187,6 +5625,7 @@ function RunDetailView({
|
|
|
5187
5625
|
const {
|
|
5188
5626
|
chunks: streamChunks,
|
|
5189
5627
|
isLive: streamIsLive,
|
|
5628
|
+
isInitialLoading: streamIsInitialLoading,
|
|
5190
5629
|
error: streamError
|
|
5191
5630
|
} = useStreamReader(env, selectedStreamId, runId, encryptionKey, run.status);
|
|
5192
5631
|
const handleCancelClick = () => {
|
|
@@ -5199,7 +5638,7 @@ function RunDetailView({
|
|
|
5199
5638
|
setShowCancelDialog(false);
|
|
5200
5639
|
await cancelRun(env, runId);
|
|
5201
5640
|
await update();
|
|
5202
|
-
toast.success("Run cancelled
|
|
5641
|
+
toast.success("Run cancelled");
|
|
5203
5642
|
} catch (err) {
|
|
5204
5643
|
console.error("Failed to cancel run:", err);
|
|
5205
5644
|
toast.error("Failed to cancel run", {
|
|
@@ -5218,7 +5657,7 @@ function RunDetailView({
|
|
|
5218
5657
|
setRerunning(true);
|
|
5219
5658
|
setShowRerunDialog(false);
|
|
5220
5659
|
const newRunId = await recreateRun(env, run.runId);
|
|
5221
|
-
toast.success("New run started
|
|
5660
|
+
toast.success("New run started", {
|
|
5222
5661
|
description: `Run ID: ${newRunId}`
|
|
5223
5662
|
});
|
|
5224
5663
|
navigate(`/run/${newRunId}`);
|
|
@@ -5235,8 +5674,8 @@ function RunDetailView({
|
|
|
5235
5674
|
if (error && !runData) {
|
|
5236
5675
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { variant: "destructive", className: "m-4", children: [
|
|
5237
5676
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
|
|
5238
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Error loading workflow run" }),
|
|
5239
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: error
|
|
5677
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: getErrorTitle(error, "Error loading workflow run") }),
|
|
5678
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: getErrorMessage(error) })
|
|
5240
5679
|
] });
|
|
5241
5680
|
}
|
|
5242
5681
|
const workflowName = (_a = parseWorkflowName(run.workflowName)) == null ? void 0 : _a.shortName;
|
|
@@ -5336,12 +5775,12 @@ function RunDetailView({
|
|
|
5336
5775
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs", children: run.runId ? run.completedAt ? /* @__PURE__ */ jsxRuntimeExports.jsx(RelativeTime, { date: run.completedAt }) : "-" : /* @__PURE__ */ jsxRuntimeExports.jsx(Skeleton$1, { className: "w-[110px] h-[20px]" }) })
|
|
5337
5776
|
] }),
|
|
5338
5777
|
run.expiredAt != null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
5339
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
|
|
5340
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground cursor-help flex items-center gap-1", children: [
|
|
5778
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip$1, { children: [
|
|
5779
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground cursor-help flex items-center gap-1", children: [
|
|
5341
5780
|
"Expired",
|
|
5342
5781
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { className: "w-3 h-3" })
|
|
5343
5782
|
] }) }),
|
|
5344
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "The storage data for this run has expired and is no longer available." }) })
|
|
5783
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent$1, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "The storage data for this run has expired and is no longer available." }) })
|
|
5345
5784
|
] }),
|
|
5346
5785
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx(RelativeTime, { date: run.expiredAt }) })
|
|
5347
5786
|
] })
|
|
@@ -5370,12 +5809,16 @@ function RunDetailView({
|
|
|
5370
5809
|
"Streams"
|
|
5371
5810
|
] })
|
|
5372
5811
|
] }),
|
|
5373
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "trace", className: "mt-0 flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { title: "Failed to load trace viewer", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full -mx-6 bg-background-100 border-t border-gray-alpha-400 overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5374
|
-
|
|
5812
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "trace", className: "mt-0 flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { title: "Failed to load trace viewer", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative h-full -mx-6 bg-background-100 border-t border-gray-alpha-400 overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5813
|
+
TraceViewer,
|
|
5375
5814
|
{
|
|
5376
5815
|
run,
|
|
5377
5816
|
events: allEvents ?? [],
|
|
5378
|
-
|
|
5817
|
+
loading,
|
|
5818
|
+
sidebarData,
|
|
5819
|
+
onLoadMore: loadMoreTraceData,
|
|
5820
|
+
hasMore: hasMoreTraceData,
|
|
5821
|
+
isLoadingMore: isLoadingMoreTraceData
|
|
5379
5822
|
}
|
|
5380
5823
|
) }) }) }),
|
|
5381
5824
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "events", className: "mt-0 flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { title: "Failed to load events list", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -5393,118 +5836,58 @@ function RunDetailView({
|
|
|
5393
5836
|
onSortOrderChange: setEventsSortOrder,
|
|
5394
5837
|
onDecrypt: handleDecrypt,
|
|
5395
5838
|
isDecrypting,
|
|
5396
|
-
hasEncryptedData
|
|
5839
|
+
hasEncryptedData,
|
|
5840
|
+
onExactIdSearch: searchByExactId
|
|
5397
5841
|
}
|
|
5398
5842
|
) }) }) }),
|
|
5399
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "streams", className: "mt-0 flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { title: "Failed to load stream data", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full
|
|
5400
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5843
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "streams", className: "mt-0 flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { title: "Failed to load stream data", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative -mx-6 flex h-full min-h-0 overflow-hidden border-t border-gray-alpha-400 bg-background-100", children: [
|
|
5844
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-[340px] shrink-0 flex-col border-r border-gray-alpha-400 bg-background-100", children: [
|
|
5845
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5846
|
+
"div",
|
|
5847
|
+
{
|
|
5848
|
+
"aria-hidden": "true",
|
|
5849
|
+
className: "h-10 min-h-10 border-b border-gray-alpha-400"
|
|
5850
|
+
}
|
|
5851
|
+
),
|
|
5852
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 flex-1 divide-y divide-gray-400 overflow-y-auto", children: streamsLoading ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col divide-y divide-gray-400", children: [
|
|
5853
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-10 items-center pl-4 pr-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Skeleton$1, { className: "h-3.5 w-24" }) }),
|
|
5854
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-10 items-center pl-4 pr-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Skeleton$1, { className: "h-3.5 w-32" }) }),
|
|
5855
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-10 items-center pl-4 pr-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Skeleton$1, { className: "h-3.5 w-20" }) })
|
|
5856
|
+
] }) : streamsError ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-2 text-label-12 text-red-900", children: streamsError.message }) : streams.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-10 items-center px-4 text-label-12 text-gray-900", children: "No streams found for this run" }) : streams.map((streamId) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5857
|
+
"button",
|
|
5858
|
+
{
|
|
5859
|
+
type: "button",
|
|
5860
|
+
onClick: () => setSelectedStreamId(streamId),
|
|
5861
|
+
className: `flex h-10 w-full min-w-0 items-center truncate pl-4 pr-2 text-left text-label-14 transition-colors ${selectedStreamId === streamId ? "bg-gray-100 text-gray-1000 hover:bg-gray-200 active:bg-gray-200" : "bg-transparent text-gray-900 hover:bg-gray-100 hover:text-gray-1000 focus-visible:bg-gray-100 focus-visible:text-gray-1000"}`,
|
|
5862
|
+
title: streamId,
|
|
5863
|
+
children: streamId
|
|
5407
5864
|
},
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
"div",
|
|
5426
|
-
{
|
|
5427
|
-
className: "p-4 text-xs",
|
|
5428
|
-
style: { color: "var(--ds-gray-600)" },
|
|
5429
|
-
children: "No streams found for this run"
|
|
5430
|
-
}
|
|
5431
|
-
) : streams.map((streamId) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5432
|
-
"button",
|
|
5433
|
-
{
|
|
5434
|
-
type: "button",
|
|
5435
|
-
onClick: () => setSelectedStreamId(streamId),
|
|
5436
|
-
className: "w-full text-left px-3 py-2 text-xs font-mono truncate hover:bg-accent transition-colors",
|
|
5437
|
-
style: {
|
|
5438
|
-
backgroundColor: selectedStreamId === streamId ? "var(--ds-gray-200)" : "transparent",
|
|
5439
|
-
color: "var(--ds-gray-1000)"
|
|
5440
|
-
},
|
|
5441
|
-
title: streamId,
|
|
5442
|
-
children: streamId
|
|
5443
|
-
},
|
|
5444
|
-
streamId
|
|
5445
|
-
)) })
|
|
5446
|
-
]
|
|
5447
|
-
}
|
|
5448
|
-
),
|
|
5449
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-w-0", children: selectedStreamId ? (streamError == null ? void 0 : streamError.includes("encrypted")) && !encryptionKey ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
5450
|
-
"div",
|
|
5451
|
-
{
|
|
5452
|
-
className: "h-full flex flex-col items-center justify-center gap-3 rounded-lg border p-4",
|
|
5453
|
-
style: {
|
|
5454
|
-
borderColor: "var(--ds-gray-300)",
|
|
5455
|
-
backgroundColor: "var(--ds-gray-100)"
|
|
5456
|
-
},
|
|
5457
|
-
children: [
|
|
5458
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5459
|
-
Lock,
|
|
5460
|
-
{
|
|
5461
|
-
className: "h-6 w-6",
|
|
5462
|
-
style: { color: "var(--ds-gray-700)" }
|
|
5463
|
-
}
|
|
5464
|
-
),
|
|
5465
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5466
|
-
"div",
|
|
5467
|
-
{
|
|
5468
|
-
className: "text-sm",
|
|
5469
|
-
style: { color: "var(--ds-gray-900)" },
|
|
5470
|
-
children: "This stream is encrypted."
|
|
5471
|
-
}
|
|
5472
|
-
),
|
|
5473
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5474
|
-
DecryptButton,
|
|
5475
|
-
{
|
|
5476
|
-
onClick: handleDecrypt,
|
|
5477
|
-
loading: isDecrypting
|
|
5478
|
-
}
|
|
5479
|
-
)
|
|
5480
|
-
]
|
|
5481
|
-
}
|
|
5482
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5865
|
+
streamId
|
|
5866
|
+
)) })
|
|
5867
|
+
] }),
|
|
5868
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden bg-background-100", children: streamsLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StreamViewerSkeleton, {}) }) : selectedStreamId ? (streamError == null ? void 0 : streamError.includes("encrypted")) && !encryptionKey ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-full items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [
|
|
5869
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { className: "h-8 w-8 text-gray-700" }),
|
|
5870
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
|
|
5871
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-label-14 font-medium text-gray-1000", children: "Encrypted Stream" }),
|
|
5872
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-label-12 text-gray-900", children: "Decrypt this stream to view its chunks." })
|
|
5873
|
+
] }),
|
|
5874
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5875
|
+
DecryptButton,
|
|
5876
|
+
{
|
|
5877
|
+
onClick: handleDecrypt,
|
|
5878
|
+
loading: isDecrypting
|
|
5879
|
+
}
|
|
5880
|
+
)
|
|
5881
|
+
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5483
5882
|
StreamViewer,
|
|
5484
5883
|
{
|
|
5485
5884
|
streamId: selectedStreamId,
|
|
5486
5885
|
chunks: streamChunks,
|
|
5487
5886
|
isLive: streamIsLive,
|
|
5887
|
+
isLoading: streamIsInitialLoading,
|
|
5488
5888
|
error: (streamError == null ? void 0 : streamError.includes("encrypted")) ? null : streamError
|
|
5489
5889
|
}
|
|
5490
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5491
|
-
"div",
|
|
5492
|
-
{
|
|
5493
|
-
className: "h-full flex items-center justify-center rounded-lg border",
|
|
5494
|
-
style: {
|
|
5495
|
-
borderColor: "var(--ds-gray-300)",
|
|
5496
|
-
backgroundColor: "var(--ds-gray-100)"
|
|
5497
|
-
},
|
|
5498
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
5499
|
-
"div",
|
|
5500
|
-
{
|
|
5501
|
-
className: "text-sm",
|
|
5502
|
-
style: { color: "var(--ds-gray-600)" },
|
|
5503
|
-
children: streams.length > 0 ? "Select a stream to view its data" : "No streams available"
|
|
5504
|
-
}
|
|
5505
|
-
)
|
|
5506
|
-
}
|
|
5507
|
-
) })
|
|
5890
|
+
) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-label-14 text-gray-600", children: streams.length > 0 ? "Select a stream to view its data" : "No streams available" }) }) })
|
|
5508
5891
|
] }) }) }),
|
|
5509
5892
|
false
|
|
5510
5893
|
]
|