@workflow/web 5.0.0-beta.26 → 5.0.0-beta.28
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/build/client/assets/{encryption-g14N5vQl.js → encryption-BQTnudEZ.js} +1 -1
- package/build/client/assets/{entry.client-DOJDY_4b.js → entry.client-DQZ2hM2V.js} +24 -24
- package/build/client/assets/{highlighted-body-B3W2YXNL-QrddlyZu.js → highlighted-body-B3W2YXNL-CQ-a-eYE.js} +1 -1
- package/build/client/assets/{home-BNApVOct.js → home-DuZRFOMe.js} +1698 -234
- package/build/client/assets/{index-B6-SzLmT.js → index-ConSkUmc.js} +0 -2
- package/build/client/assets/{index-C7C6cDW5.js → index-HqNj_XIX.js} +10 -10
- package/build/client/assets/{manifest-379f050f.js → manifest-bb838d97.js} +1 -1
- package/build/client/assets/{mermaid-3ZIDBTTL-Cg-Mp5Kj.js → mermaid-3ZIDBTTL-QcES6x1o.js} +767 -279
- package/build/client/assets/root-BT69a3LD.css +1 -0
- package/build/client/assets/{root-BsPxYsbK.js → root-BiHTsCtP.js} +1 -1
- package/build/client/assets/{run-detail-sr7StYc6.js → run-detail-DSpZ5dnN.js} +925 -759
- package/build/client/assets/server-build-BkKXPNcO.css +1 -0
- package/build/client/assets/{workflow-graph-viewer-CcCwLmnF.js → workflow-graph-viewer-CyKfZJOQ.js} +227 -220
- package/build/client/assets/{zstd-browser-decoder-OOeWOMJw.js → zstd-browser-decoder-BigjGoI1.js} +2 -2
- package/build/server/assets/{app-DQ35jFT1.js → app-Cl6-bhGd.js} +43 -43
- package/build/server/assets/{highlighted-body-B3W2YXNL-DUlvgLoF.js → highlighted-body-B3W2YXNL-Daljn6fi.js} +4 -4
- package/build/server/assets/index-B_N7SdQh.js +115 -0
- package/build/server/assets/{index-BafExO0s.js → index-BfLBLRRi.js} +10 -10
- package/build/server/assets/{mermaid-3ZIDBTTL-BdnRYE9a.js → mermaid-3ZIDBTTL-xnUhfFrD.js} +4 -4
- package/build/server/assets/{server-build-0CazaFkH.js → server-build-D5Nuwxaw.js} +40483 -37602
- package/build/server/assets/{token-DK_R23fr.js → token-DDgfwjzz.js} +2 -2
- package/build/server/assets/{token-util-CaJAmsYa.js → token-util-CthtfGuG.js} +2 -2
- package/build/server/assets/{zstd-browser-decoder-pCjqxVHM.js → zstd-browser-decoder-zp5ZpR7T.js} +5 -5
- package/build/server/index.js +1 -1
- package/package.json +11 -9
- package/build/client/assets/root-F_dqJDC7.css +0 -1
- package/build/client/assets/server-build-DVBDkRDS.css +0 -1
- package/build/server/assets/index-BgRt1-Z6.js +0 -100
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, f as reactDomExports, G as ReactDOM, B as useNavigate, C as useSearchParams, A as Link, w as withComponentProps, H as useParams } from "./index-BXZSIDEp.js";
|
|
2
|
-
import {
|
|
3
|
-
import { c as createLucideIcon,
|
|
4
|
-
import { decrypt, importKey } from "./encryption-
|
|
5
|
-
import "./index-
|
|
2
|
+
import { C as Check, a as Copy, d as CircleAlert, U as parseStepName, G as parseWorkflowName, V as ErrorCard, Y as format, Z as Zap, S as Send, R as ResolveHookModal, t as ChevronUp, X, Q as ErrorBoundary, _ as Circle, u as unwrapOrThrow, W as WorkflowWebAPIError, K as unwrapServerActionResult, $ as useEscapeKeydown, w as composeEventHandlers, a0 as useCallbackRef, a1 as useLayoutEffect2, v as useControllableState, a2 as useId, a3 as createContext2, x as Presence, z as createContextScope, p as hideOthers, q as ReactRemoveScroll, a4 as useFocusGuards, a5 as LAYOUT, a6 as wakeUpRun, n as resumeHook, A as Alert, e as AlertTitle, g as getErrorTitle, h as AlertDescription, i as getErrorMessage, b as Skeleton$1, a7 as RunActionsButtons, H as StatusBadge, j as CopyableText, c as RelativeTime, T as Tabs, M as TabsList, N as TabsTrigger, O as TabsContent, B as cancelRun, a8 as recreateRun } from "./workflow-graph-viewer-CyKfZJOQ.js";
|
|
3
|
+
import { c as createLucideIcon, W as cn, X as DataInspector, Y as DecryptClickContext, Z as Button, $ as Spinner, a0 as Lock, a1 as CollapsibleRoot, a2 as CollapsibleTrigger, a3 as CollapsibleContent, M as cva, a4 as RESERVED_ATTRIBUTE_KEY_PREFIX, a5 as ContextCardProvider, h as useToast, a6 as Skeleton, a7 as Yr, a8 as isEncryptedMarker, C as ChevronRight, a9 as TimestampTooltip, aa as formatDuration, ab as _r, ac as RunClickContext, ad as StreamClickContext, ae as Collapsible, af as isExpiredMarker, ag as isDoStreamStep, ah as extractConversation, ai as hasEncryptedFields, aj as getEventDataRefFields, ak as useSidebarDataOptional, al as clsx, am as useActiveSpan, an as useSidebarData, ao as Tooltip, ap as TooltipTrigger, aq as IconButton, ar as TooltipContent, H as ChevronDown, as as useRowWindow, at as isSpanDimmedBySearch, au as ROW_HEIGHT_PX, av as getSpanDurationMs, aw as isSpanErrored, ax as formatDurationPrecise, ay as TooltipProvider, az as ActiveSpanProvider, aA as useReducedMotion, aB as searchSpans, aC as computeRootBounds, aD as computeTimeMarkers, aE as clampViewportToRoot, aF as getHighResInMs, aG as scrollRowIntoView, aH as TIMELINE_PADDING_PX, aI as Minimap, aJ as Timeline, aK as TimelineHeader, aL as wheelZoomScaleFactor, aM as wheelDeltaToPixels, aN as SidebarDataProvider, aO as fetchHook, l as fetchEvents, aP as hydrateResourceIOAsync, J as fetchRun, aQ as fetchStep, aR as hydrateResourceIO, aS as fetchStreams, aT as Slot, I as useComposedRefs, aU as Slottable, e as cn$1, aV as buttonVariants, aW as fetchEvent, aX as fetchEventsByCorrelationId, aY as isEncryptedData, aZ as hydrateData, a_ as getWebRevivers, T as Tooltip$1, a as TooltipTrigger$1, b as TooltipContent$1, a$ as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, b0 as getEncryptionKeyForRun, t as toast, L as LoaderCircle, b1 as StreamViewer } from "./mermaid-3ZIDBTTL-QcES6x1o.js";
|
|
4
|
+
import { decrypt, importKey } from "./encryption-BQTnudEZ.js";
|
|
5
|
+
import "./index-ConSkUmc.js";
|
|
6
6
|
/**
|
|
7
7
|
* @license lucide-react v0.575.0 - ISC
|
|
8
8
|
*
|
|
@@ -125,251 +125,561 @@ function CopyButton({ copyText, ariaLabel, className }) {
|
|
|
125
125
|
});
|
|
126
126
|
}, 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" }) })] }) });
|
|
127
127
|
}
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const serializeForClipboard = (value) => {
|
|
137
|
-
if (typeof value === "string")
|
|
138
|
-
return value;
|
|
139
|
-
if (typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
140
|
-
return String(value);
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
return JSON.stringify(value, null, 2);
|
|
144
|
-
} catch {
|
|
145
|
-
return String(value);
|
|
128
|
+
const ELLIPSIS = "…";
|
|
129
|
+
const MIN_START = 3;
|
|
130
|
+
const MIN_END = 3;
|
|
131
|
+
const MIN_KEPT = MIN_START + MIN_END;
|
|
132
|
+
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
133
|
+
function toGraphemes(text) {
|
|
134
|
+
if (graphemeSegmenter) {
|
|
135
|
+
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
146
136
|
}
|
|
147
|
-
|
|
148
|
-
function CopyableDataBlock({ data }) {
|
|
149
|
-
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-x-auto rounded-md border border-gray-alpha-400 p-3", children: [jsxRuntimeExports.jsx(CopyButton, { copyText: serializeForClipboard(data), ariaLabel: "Copy data", className: "absolute right-2 top-2 z-10 flex h-6 w-6 items-center justify-center rounded-md border border-gray-alpha-400 !bg-background-100 p-0 text-gray-900 transition-transform transition-colors duration-100 hover:bg-gray-200 active:scale-95 active:bg-gray-300" }), jsxRuntimeExports.jsx(DataInspector, { data })] });
|
|
137
|
+
return Array.from(text);
|
|
150
138
|
}
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
139
|
+
function buildCandidate(graphemes, kept) {
|
|
140
|
+
if (kept <= 0) {
|
|
141
|
+
return {
|
|
142
|
+
prefixText: "",
|
|
143
|
+
prefixGraphemeCount: 0,
|
|
144
|
+
suffixText: "",
|
|
145
|
+
suffixGraphemeCount: 0,
|
|
146
|
+
text: ELLIPSIS,
|
|
147
|
+
truncated: true
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
const suffixGraphemeCount = kept >= MIN_KEPT ? Math.max(MIN_END, Math.floor(kept / 2)) : Math.floor(kept / 2);
|
|
151
|
+
const prefixGraphemeCount = kept - suffixGraphemeCount;
|
|
152
|
+
const prefixText = graphemes.slice(0, prefixGraphemeCount).join("");
|
|
153
|
+
const suffixText = suffixGraphemeCount > 0 ? graphemes.slice(-suffixGraphemeCount).join("") : "";
|
|
154
|
+
return {
|
|
155
|
+
prefixText,
|
|
156
|
+
prefixGraphemeCount,
|
|
157
|
+
suffixText,
|
|
158
|
+
suffixGraphemeCount,
|
|
159
|
+
text: prefixText + ELLIPSIS + suffixText,
|
|
160
|
+
truncated: true
|
|
159
161
|
};
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
}
|
|
163
|
+
function middleTruncate(graphemes, availableWidth, measure, fullWidth) {
|
|
164
|
+
const fullText = graphemes.join("");
|
|
165
|
+
const resolvedFullWidth = fullWidth ?? measure(fullText);
|
|
166
|
+
if (availableWidth <= 0 || graphemes.length === 0) {
|
|
167
|
+
return {
|
|
168
|
+
prefixText: fullText,
|
|
169
|
+
prefixGraphemeCount: graphemes.length,
|
|
170
|
+
suffixText: "",
|
|
171
|
+
suffixGraphemeCount: 0,
|
|
172
|
+
text: fullText,
|
|
173
|
+
truncated: false
|
|
174
|
+
};
|
|
165
175
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
176
|
+
if (resolvedFullWidth <= availableWidth) {
|
|
177
|
+
return {
|
|
178
|
+
prefixText: fullText,
|
|
179
|
+
prefixGraphemeCount: graphemes.length,
|
|
180
|
+
suffixText: "",
|
|
181
|
+
suffixGraphemeCount: 0,
|
|
182
|
+
text: fullText,
|
|
183
|
+
truncated: false
|
|
184
|
+
};
|
|
169
185
|
}
|
|
170
|
-
|
|
171
|
-
|
|
186
|
+
let lo = 0;
|
|
187
|
+
let hi = graphemes.length - 1;
|
|
188
|
+
let best = -1;
|
|
189
|
+
while (lo <= hi) {
|
|
190
|
+
const mid = lo + hi >>> 1;
|
|
191
|
+
const candidate = buildCandidate(graphemes, mid);
|
|
192
|
+
if (measure(candidate.text) <= availableWidth) {
|
|
193
|
+
best = mid;
|
|
194
|
+
lo = mid + 1;
|
|
195
|
+
} else {
|
|
196
|
+
hi = mid - 1;
|
|
197
|
+
}
|
|
172
198
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const reserved = isReservedAttributeKey(attributeKey);
|
|
185
|
-
return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 py-0.5", children: [jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-label-13 text-gray-900", style: reserved ? { color: "var(--ds-gray-700)" } : void 0, children: [jsxRuntimeExports.jsx("span", { className: "truncate", children: attributeKey }), reserved && jsxRuntimeExports.jsx(ReservedBadge, {})] }), removed ? jsxRuntimeExports.jsx("span", { className: "shrink-0 text-copy-13 italic text-gray-700", children: "removed" }) : jsxRuntimeExports.jsx("span", { className: "max-w-[60%] truncate text-copy-13 text-gray-1000", title: value, children: value })] });
|
|
186
|
-
}
|
|
187
|
-
function sortAttributeKeys(keys) {
|
|
188
|
-
return [...keys].sort((a, b) => {
|
|
189
|
-
const aReserved = isReservedAttributeKey(a);
|
|
190
|
-
const bReserved = isReservedAttributeKey(b);
|
|
191
|
-
if (aReserved !== bReserved)
|
|
192
|
-
return aReserved ? 1 : -1;
|
|
193
|
-
return a.localeCompare(b);
|
|
194
|
-
});
|
|
199
|
+
if (best === -1) {
|
|
200
|
+
return {
|
|
201
|
+
prefixText: "",
|
|
202
|
+
prefixGraphemeCount: 0,
|
|
203
|
+
suffixText: "",
|
|
204
|
+
suffixGraphemeCount: 0,
|
|
205
|
+
text: "",
|
|
206
|
+
truncated: true
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return buildCandidate(graphemes, best);
|
|
195
210
|
}
|
|
196
|
-
function
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
211
|
+
function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value }) {
|
|
212
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
213
|
+
if (selectionStart < 0 || selectionEnd > visibleText.length || selectionStart >= selectionEnd) {
|
|
199
214
|
return null;
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
function describeWriter(writer) {
|
|
209
|
-
if (!writer)
|
|
215
|
+
}
|
|
216
|
+
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
const ellipsisStart = prefixText.length;
|
|
220
|
+
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
221
|
+
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
210
222
|
return null;
|
|
211
|
-
if (writer.type === "workflow")
|
|
212
|
-
return "Set by workflow";
|
|
213
|
-
if (writer.type === "step") {
|
|
214
|
-
return `Set by step ${writer.stepId} (attempt ${writer.attempt})`;
|
|
215
223
|
}
|
|
216
|
-
|
|
224
|
+
const originalGraphemes = toGraphemes(value);
|
|
225
|
+
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
226
|
+
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
227
|
+
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
228
|
+
return originalGraphemes.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount).join("");
|
|
217
229
|
}
|
|
218
|
-
function
|
|
219
|
-
|
|
220
|
-
|
|
230
|
+
function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value }) {
|
|
231
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
232
|
+
const trimmedSelectionText = selectionText.trim();
|
|
233
|
+
if (!trimmedSelectionText) {
|
|
234
|
+
return null;
|
|
221
235
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const title = message ? deriveTitle(message) : deriveTitle(body);
|
|
244
|
-
const copyText = message && stack && !stack.includes(message) ? `${message}
|
|
245
|
-
|
|
246
|
-
${stack}` : body;
|
|
247
|
-
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-hidden rounded-md border", style: {
|
|
248
|
-
borderColor: "var(--ds-red-400)",
|
|
249
|
-
background: "var(--ds-red-100)"
|
|
250
|
-
}, 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: {
|
|
251
|
-
color: "var(--ds-red-900)",
|
|
252
|
-
borderBottom: "1px solid var(--ds-red-400)"
|
|
253
|
-
}, children: [jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 shrink-0" }), jsxRuntimeExports.jsx("p", {
|
|
254
|
-
className: "text-xs font-semibold m-0 truncate",
|
|
255
|
-
// The full message or stack is in the body below; the header just
|
|
256
|
-
// shows the first line, single-line, with overflow
|
|
257
|
-
// ellipsised so a long title doesn't push the copy button or
|
|
258
|
-
// wrap into the framed hint/docs lines.
|
|
259
|
-
title: message,
|
|
260
|
-
children: title
|
|
261
|
-
})] }), body && jsxRuntimeExports.jsx("pre", { className: "px-3 py-2.5 text-xs font-mono whitespace-pre-wrap break-words overflow-auto m-0", style: {
|
|
262
|
-
color: "var(--ds-red-900)",
|
|
263
|
-
background: "var(--ds-red-200)"
|
|
264
|
-
}, children: body })] });
|
|
236
|
+
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
237
|
+
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
238
|
+
if (trimmedSelectionText === visibleText) {
|
|
239
|
+
return leading + value + trailing;
|
|
240
|
+
}
|
|
241
|
+
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
245
|
+
if (selectionStart === -1) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
249
|
+
const mappedText = getMiddleTruncateCopyText({
|
|
250
|
+
prefixText,
|
|
251
|
+
selectionEnd,
|
|
252
|
+
selectionStart,
|
|
253
|
+
suffixText,
|
|
254
|
+
value
|
|
255
|
+
});
|
|
256
|
+
return mappedText === null ? null : leading + mappedText + trailing;
|
|
265
257
|
}
|
|
266
|
-
const
|
|
267
|
-
function
|
|
268
|
-
return
|
|
258
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? reactExports.useEffect : reactExports.useLayoutEffect;
|
|
259
|
+
function createFullState(value, graphemes) {
|
|
260
|
+
return {
|
|
261
|
+
displayText: value,
|
|
262
|
+
isTruncated: false,
|
|
263
|
+
prefixGraphemeCount: graphemes.length,
|
|
264
|
+
prefixText: value,
|
|
265
|
+
suffixGraphemeCount: 0,
|
|
266
|
+
suffixText: ""
|
|
267
|
+
};
|
|
269
268
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const [open, setOpen] = reactExports.useState(false);
|
|
269
|
+
function useMiddleTruncate(value) {
|
|
270
|
+
const graphemes = reactExports.useMemo(() => toGraphemes(value), [value]);
|
|
271
|
+
const fullState = reactExports.useMemo(() => createFullState(value, graphemes), [graphemes, value]);
|
|
274
272
|
const ref = reactExports.useRef(null);
|
|
275
|
-
const
|
|
276
|
-
reactExports.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (
|
|
281
|
-
|
|
273
|
+
const measureRef = reactExports.useRef(null);
|
|
274
|
+
const [state, setState] = reactExports.useState(() => fullState);
|
|
275
|
+
const rafRef = reactExports.useRef(0);
|
|
276
|
+
const updateState = reactExports.useCallback((nextState) => {
|
|
277
|
+
setState((currentState) => {
|
|
278
|
+
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) {
|
|
279
|
+
return currentState;
|
|
282
280
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
]);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
281
|
+
return nextState;
|
|
282
|
+
});
|
|
283
|
+
}, []);
|
|
284
|
+
const recalculate = reactExports.useCallback(() => {
|
|
285
|
+
const el = ref.current;
|
|
286
|
+
const measureEl = measureRef.current;
|
|
287
|
+
if (!el || !measureEl)
|
|
288
|
+
return;
|
|
289
|
+
const available = el.clientWidth;
|
|
290
|
+
if (available <= 0) {
|
|
291
|
+
updateState(fullState);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const measure = (text) => {
|
|
295
|
+
measureEl.textContent = text;
|
|
296
|
+
return measureEl.scrollWidth;
|
|
297
|
+
};
|
|
298
|
+
const fullWidth = measure(value);
|
|
299
|
+
if (fullWidth <= available) {
|
|
300
|
+
updateState(fullState);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const result = middleTruncate(graphemes, available, measure, fullWidth);
|
|
304
|
+
updateState({
|
|
305
|
+
displayText: result.text,
|
|
306
|
+
isTruncated: result.truncated,
|
|
307
|
+
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
308
|
+
prefixText: result.prefixText,
|
|
309
|
+
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
310
|
+
suffixText: result.suffixText
|
|
311
|
+
});
|
|
312
|
+
}, [fullState, graphemes, updateState, value]);
|
|
313
|
+
useIsomorphicLayoutEffect(() => {
|
|
314
|
+
recalculate();
|
|
315
|
+
}, [recalculate]);
|
|
316
|
+
reactExports.useEffect(() => {
|
|
317
|
+
var _a;
|
|
318
|
+
const el = ref.current;
|
|
319
|
+
if (!el)
|
|
320
|
+
return;
|
|
321
|
+
const debouncedRecalc = () => {
|
|
322
|
+
cancelAnimationFrame(rafRef.current);
|
|
323
|
+
rafRef.current = requestAnimationFrame(recalculate);
|
|
324
|
+
};
|
|
325
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(debouncedRecalc) : null;
|
|
326
|
+
ro == null ? void 0 : ro.observe(el);
|
|
327
|
+
window.addEventListener("resize", debouncedRecalc);
|
|
328
|
+
const onFontsLoaded = () => {
|
|
329
|
+
debouncedRecalc();
|
|
330
|
+
};
|
|
331
|
+
const fontSet = "fonts" in document ? document.fonts : null;
|
|
332
|
+
(_a = fontSet == null ? void 0 : fontSet.addEventListener) == null ? void 0 : _a.call(fontSet, "loadingdone", onFontsLoaded);
|
|
333
|
+
return () => {
|
|
334
|
+
var _a2;
|
|
335
|
+
ro == null ? void 0 : ro.disconnect();
|
|
336
|
+
window.removeEventListener("resize", debouncedRecalc);
|
|
337
|
+
cancelAnimationFrame(rafRef.current);
|
|
338
|
+
(_a2 = fontSet == null ? void 0 : fontSet.removeEventListener) == null ? void 0 : _a2.call(fontSet, "loadingdone", onFontsLoaded);
|
|
339
|
+
};
|
|
340
|
+
}, [recalculate]);
|
|
341
|
+
return {
|
|
342
|
+
ref,
|
|
343
|
+
measureRef,
|
|
344
|
+
displayText: state.displayText,
|
|
345
|
+
isTruncated: state.isTruncated,
|
|
346
|
+
prefixGraphemeCount: state.prefixGraphemeCount,
|
|
347
|
+
prefixText: state.prefixText,
|
|
348
|
+
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
349
|
+
suffixText: state.suffixText
|
|
350
|
+
};
|
|
329
351
|
}
|
|
330
|
-
function
|
|
331
|
-
if (
|
|
352
|
+
function getRangeOffsets(container, range) {
|
|
353
|
+
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) {
|
|
332
354
|
return null;
|
|
333
|
-
|
|
334
|
-
|
|
355
|
+
}
|
|
356
|
+
const startRange = document.createRange();
|
|
357
|
+
startRange.selectNodeContents(container);
|
|
358
|
+
startRange.setEnd(range.startContainer, range.startOffset);
|
|
359
|
+
const endRange = document.createRange();
|
|
360
|
+
endRange.selectNodeContents(container);
|
|
361
|
+
endRange.setEnd(range.endContainer, range.endOffset);
|
|
362
|
+
return {
|
|
363
|
+
end: endRange.toString().length,
|
|
364
|
+
start: startRange.toString().length
|
|
365
|
+
};
|
|
335
366
|
}
|
|
336
|
-
function
|
|
337
|
-
|
|
367
|
+
function MiddleTruncate({ value, className, onCopy: onCopyProp, ...props }) {
|
|
368
|
+
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
369
|
+
const visibleRef = reactExports.useRef(null);
|
|
370
|
+
const handleCopy = reactExports.useCallback((e) => {
|
|
371
|
+
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
372
|
+
if (e.defaultPrevented || !isTruncated)
|
|
373
|
+
return;
|
|
374
|
+
const selection = window.getSelection();
|
|
375
|
+
if (!selection || selection.rangeCount === 0)
|
|
376
|
+
return;
|
|
377
|
+
const selectionText = selection.toString();
|
|
378
|
+
if (!selectionText)
|
|
379
|
+
return;
|
|
380
|
+
const range = selection.getRangeAt(0);
|
|
381
|
+
const visibleEl = visibleRef.current;
|
|
382
|
+
let copyText = null;
|
|
383
|
+
if (e.currentTarget.contains(range.startContainer) && e.currentTarget.contains(range.endContainer) && visibleEl) {
|
|
384
|
+
const offsets = getRangeOffsets(visibleEl, range);
|
|
385
|
+
if (offsets) {
|
|
386
|
+
copyText = getMiddleTruncateCopyText({
|
|
387
|
+
prefixText,
|
|
388
|
+
selectionEnd: offsets.end,
|
|
389
|
+
selectionStart: offsets.start,
|
|
390
|
+
suffixText,
|
|
391
|
+
value
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
copyText ?? (copyText = getMiddleTruncateCopyTextFromSelectionText({
|
|
396
|
+
prefixText,
|
|
397
|
+
selectionText,
|
|
398
|
+
suffixText,
|
|
399
|
+
value
|
|
400
|
+
}));
|
|
401
|
+
if (copyText === null)
|
|
402
|
+
return;
|
|
403
|
+
e.preventDefault();
|
|
404
|
+
e.clipboardData.setData("text/plain", copyText);
|
|
405
|
+
}, [onCopyProp, isTruncated, prefixText, suffixText, value]);
|
|
406
|
+
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 })] });
|
|
338
407
|
}
|
|
339
|
-
|
|
340
|
-
|
|
408
|
+
const encryptedPlaceholderPreview = `{
|
|
409
|
+
"input": "[encrypted]",
|
|
410
|
+
"result": "[encrypted]"
|
|
411
|
+
}`;
|
|
412
|
+
function EncryptedDataBlock() {
|
|
413
|
+
const ctx = reactExports.useContext(DecryptClickContext);
|
|
414
|
+
return jsxRuntimeExports.jsxs("div", { className: "relative min-h-20 overflow-hidden rounded-md border border-gray-alpha-400 bg-background-100", children: [jsxRuntimeExports.jsx("pre", { "aria-hidden": "true", className: "pointer-events-none m-0 select-none p-3 font-mono text-label-12 text-gray-900 blur-[4px]", children: encryptedPlaceholderPreview }), jsxRuntimeExports.jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: ctx ? jsxRuntimeExports.jsxs(Button, { onClick: ctx.onDecrypt, disabled: ctx.isDecrypting, size: "xs", children: [ctx.isDecrypting ? jsxRuntimeExports.jsx(Spinner, { size: 10 }) : jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { children: "Decrypt" })] }) : jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded border border-gray-alpha-400 bg-gray-100 px-1.5 py-0.5 text-button-12 font-medium text-gray-700", children: [jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), "Encrypted"] }) })] });
|
|
341
415
|
}
|
|
342
|
-
|
|
343
|
-
|
|
416
|
+
const serializeForClipboard = (value) => {
|
|
417
|
+
if (typeof value === "string")
|
|
418
|
+
return value;
|
|
419
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
420
|
+
return String(value);
|
|
421
|
+
}
|
|
422
|
+
try {
|
|
423
|
+
return JSON.stringify(value, null, 2);
|
|
424
|
+
} catch {
|
|
425
|
+
return String(value);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
function CopyableDataBlock({ data }) {
|
|
429
|
+
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-x-auto rounded-md border border-gray-alpha-400 p-3", children: [jsxRuntimeExports.jsx(CopyButton, { copyText: serializeForClipboard(data), ariaLabel: "Copy data", className: "absolute right-2 top-2 z-10 flex h-6 w-6 items-center justify-center rounded-md border border-gray-alpha-400 !bg-background-100 p-0 text-gray-900 transition-transform transition-colors duration-100 hover:bg-gray-200 active:scale-95 active:bg-gray-300" }), jsxRuntimeExports.jsx(DataInspector, { data })] });
|
|
344
430
|
}
|
|
345
|
-
function
|
|
346
|
-
|
|
347
|
-
|
|
431
|
+
function isReservedAttributeKey(key) {
|
|
432
|
+
return key.startsWith(RESERVED_ATTRIBUTE_KEY_PREFIX);
|
|
433
|
+
}
|
|
434
|
+
const rowValueVariants = cva("max-w-[60%] truncate text-right text-copy-13 text-gray-1000", {
|
|
435
|
+
variants: {
|
|
436
|
+
variant: {
|
|
437
|
+
default: "",
|
|
438
|
+
mono: "font-mono"
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
defaultVariants: {
|
|
442
|
+
variant: "default"
|
|
348
443
|
}
|
|
349
|
-
|
|
350
|
-
|
|
444
|
+
});
|
|
445
|
+
const rowCopyValueVariants = cva("flex min-w-0 max-w-[60%] items-center justify-end gap-1 text-copy-13 text-gray-1000", {
|
|
446
|
+
variants: {
|
|
447
|
+
variant: {
|
|
448
|
+
default: "",
|
|
449
|
+
mono: "font-mono"
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
defaultVariants: {
|
|
453
|
+
variant: "default"
|
|
351
454
|
}
|
|
352
|
-
|
|
353
|
-
|
|
455
|
+
});
|
|
456
|
+
function DetailKeyValueRowBase({ label, value, copyText, removed = false, variant }) {
|
|
457
|
+
const stringValue = typeof value === "string" ? value : void 0;
|
|
458
|
+
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: [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: value })] });
|
|
459
|
+
}
|
|
460
|
+
function DetailKeyValueRow(props) {
|
|
461
|
+
return jsxRuntimeExports.jsx(DetailKeyValueRowBase, { ...props });
|
|
462
|
+
}
|
|
463
|
+
function DetailMonoKeyValueRow(props) {
|
|
464
|
+
return jsxRuntimeExports.jsx(DetailKeyValueRowBase, { ...props, variant: "mono" });
|
|
465
|
+
}
|
|
466
|
+
function AttributeRow({ attributeKey, value, removed = false }) {
|
|
467
|
+
return jsxRuntimeExports.jsx(DetailKeyValueRow, { label: attributeKey, value, removed });
|
|
468
|
+
}
|
|
469
|
+
function sortAttributeKeys(keys) {
|
|
470
|
+
return [...keys].sort((a, b) => {
|
|
471
|
+
const aReserved = isReservedAttributeKey(a);
|
|
472
|
+
const bReserved = isReservedAttributeKey(b);
|
|
473
|
+
if (aReserved !== bReserved)
|
|
474
|
+
return aReserved ? 1 : -1;
|
|
475
|
+
return a.localeCompare(b);
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
function RunAttributesCard({ attributes }) {
|
|
479
|
+
const keys = sortAttributeKeys(Object.keys(attributes));
|
|
480
|
+
if (keys.length === 0)
|
|
481
|
+
return null;
|
|
482
|
+
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)) }) })] });
|
|
483
|
+
}
|
|
484
|
+
function formatMetadataValue(value) {
|
|
485
|
+
if (value == null) {
|
|
486
|
+
return String(value);
|
|
354
487
|
}
|
|
355
|
-
if (
|
|
356
|
-
return
|
|
488
|
+
if (typeof value === "string") {
|
|
489
|
+
return value;
|
|
357
490
|
}
|
|
358
|
-
if (
|
|
359
|
-
return
|
|
491
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
492
|
+
return String(value);
|
|
360
493
|
}
|
|
361
|
-
|
|
362
|
-
return
|
|
494
|
+
try {
|
|
495
|
+
return JSON.stringify(value);
|
|
496
|
+
} catch {
|
|
497
|
+
return String(value);
|
|
363
498
|
}
|
|
364
|
-
return "var(--ds-gray-600)";
|
|
365
499
|
}
|
|
366
|
-
function
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
500
|
+
function isMetadataRecord(value) {
|
|
501
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
502
|
+
}
|
|
503
|
+
function RunMetadataCard({ metadata }) {
|
|
504
|
+
if (!isMetadataRecord(metadata)) {
|
|
505
|
+
return jsxRuntimeExports.jsxs(CollapsibleRoot, { defaultOpen: true, children: [jsxRuntimeExports.jsx(CollapsibleTrigger, { children: "Metadata" }), jsxRuntimeExports.jsx(CollapsibleContent, { className: "mb-4", children: jsxRuntimeExports.jsx(CopyableDataBlock, { data: metadata }) })] });
|
|
506
|
+
}
|
|
507
|
+
const keys = Object.keys(metadata).sort((a, b) => a.localeCompare(b));
|
|
508
|
+
if (keys.length === 0)
|
|
509
|
+
return null;
|
|
510
|
+
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)) }) })] });
|
|
511
|
+
}
|
|
512
|
+
function isAttrSetEventData(data) {
|
|
513
|
+
if (data === null || typeof data !== "object")
|
|
514
|
+
return false;
|
|
515
|
+
const record = data;
|
|
516
|
+
return Array.isArray(record.changes) && record.changes.every((c) => c !== null && typeof c === "object" && typeof c.key === "string");
|
|
517
|
+
}
|
|
518
|
+
function describeWriter(writer) {
|
|
519
|
+
if (!writer)
|
|
520
|
+
return null;
|
|
521
|
+
if (writer.type === "workflow")
|
|
522
|
+
return "Set by workflow";
|
|
523
|
+
if (writer.type === "step") {
|
|
524
|
+
return `Set by step ${writer.stepId} (attempt ${writer.attempt})`;
|
|
525
|
+
}
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
function AttrSetEventBlock({ data }) {
|
|
529
|
+
if (!isAttrSetEventData(data)) {
|
|
530
|
+
return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
|
|
531
|
+
}
|
|
532
|
+
const writerLabel = describeWriter(data.writer);
|
|
533
|
+
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: {
|
|
534
|
+
borderColor: "var(--ds-gray-alpha-400)",
|
|
535
|
+
color: "var(--ds-gray-700)"
|
|
536
|
+
}, children: writerLabel })] });
|
|
537
|
+
}
|
|
538
|
+
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}`;
|
|
539
|
+
function DecryptButton({ decrypted = false, loading = false, onClick }) {
|
|
540
|
+
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"] })] });
|
|
541
|
+
}
|
|
542
|
+
function isStructuredError(value) {
|
|
543
|
+
return value != null && typeof value === "object" && (typeof value.message === "string" || typeof value.stack === "string");
|
|
544
|
+
}
|
|
545
|
+
function deriveTitle(message) {
|
|
546
|
+
const firstLine = message.split("\n").find((line) => line.trim().length > 0) ?? message;
|
|
547
|
+
return firstLine.trim();
|
|
548
|
+
}
|
|
549
|
+
function ErrorStackBlock({ value }) {
|
|
550
|
+
const stack = typeof value.stack === "string" ? value.stack : void 0;
|
|
551
|
+
const message = typeof value.message === "string" ? value.message : void 0;
|
|
552
|
+
const body = stack ?? message ?? "";
|
|
553
|
+
const title = message ? deriveTitle(message) : deriveTitle(body);
|
|
554
|
+
const copyText = message && stack && !stack.includes(message) ? `${message}
|
|
555
|
+
|
|
556
|
+
${stack}` : body;
|
|
557
|
+
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-hidden rounded-md border", style: {
|
|
558
|
+
borderColor: "var(--ds-red-400)",
|
|
559
|
+
background: "var(--ds-red-100)"
|
|
560
|
+
}, 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: {
|
|
561
|
+
color: "var(--ds-red-900)",
|
|
562
|
+
borderBottom: "1px solid var(--ds-red-400)"
|
|
563
|
+
}, children: [jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 shrink-0" }), jsxRuntimeExports.jsx("p", {
|
|
564
|
+
className: "text-xs font-semibold m-0 truncate",
|
|
565
|
+
// The full message or stack is in the body below; the header just
|
|
566
|
+
// shows the first line, single-line, with overflow
|
|
567
|
+
// ellipsised so a long title doesn't push the copy button or
|
|
568
|
+
// wrap into the framed hint/docs lines.
|
|
569
|
+
title: message,
|
|
570
|
+
children: title
|
|
571
|
+
})] }), body && jsxRuntimeExports.jsx("pre", { className: "px-3 py-2.5 text-xs font-mono whitespace-pre-wrap break-words overflow-auto m-0", style: {
|
|
572
|
+
color: "var(--ds-red-900)",
|
|
573
|
+
background: "var(--ds-red-200)"
|
|
574
|
+
}, children: body })] });
|
|
575
|
+
}
|
|
576
|
+
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)}`;
|
|
577
|
+
function LoadMoreButton({ loading = false, onClick, label = "Load more", loadingLabel = "Loading..." }) {
|
|
578
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { dangerouslySetInnerHTML: { __html: STYLES$1 } }), jsxRuntimeExports.jsxs("button", { type: "button", onClick, disabled: loading, className: "wf-load-more", children: [loading && jsxRuntimeExports.jsx(Spinner, { size: 14 }), loading ? loadingLabel : label] })] });
|
|
579
|
+
}
|
|
580
|
+
const STYLES = `.wf-menu-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;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;transition:background 150ms}.wf-menu-btn:hover{background:var(--ds-gray-alpha-200)}.wf-menu-item{appearance:none;-webkit-appearance:none;border:none;display:flex;align-items:center;width:100%;height:40px;padding:0 8px;border-radius:6px;font-size:14px;color:var(--ds-gray-1000);background:transparent;cursor:pointer;transition:background 150ms}.wf-menu-item:hover{background:var(--ds-gray-alpha-100)}`;
|
|
581
|
+
function MenuDropdown({ options, value, onChange }) {
|
|
582
|
+
var _a, _b;
|
|
583
|
+
const [open, setOpen] = reactExports.useState(false);
|
|
584
|
+
const ref = reactExports.useRef(null);
|
|
585
|
+
const label = ((_a = options.find((o) => o.value === value)) == null ? void 0 : _a.label) ?? ((_b = options[0]) == null ? void 0 : _b.label) ?? "";
|
|
586
|
+
reactExports.useEffect(() => {
|
|
587
|
+
if (!open)
|
|
588
|
+
return;
|
|
589
|
+
function handleClickOutside(e) {
|
|
590
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
591
|
+
setOpen(false);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
595
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
596
|
+
}, [open]);
|
|
597
|
+
return jsxRuntimeExports.jsxs("div", { ref, style: { position: "relative", flexShrink: 0 }, children: [jsxRuntimeExports.jsx("style", { dangerouslySetInnerHTML: { __html: STYLES } }), jsxRuntimeExports.jsxs("button", { type: "button", className: "wf-menu-btn", onClick: () => setOpen(!open), children: [jsxRuntimeExports.jsx("span", { children: label }), jsxRuntimeExports.jsx("svg", { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", style: {
|
|
598
|
+
marginLeft: 16,
|
|
599
|
+
marginRight: -4,
|
|
600
|
+
color: "var(--ds-gray-900)"
|
|
601
|
+
}, children: jsxRuntimeExports.jsx("path", { d: "M4.5 6L8 9.5L11.5 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), open && jsxRuntimeExports.jsx("div", { style: {
|
|
602
|
+
position: "absolute",
|
|
603
|
+
right: 0,
|
|
604
|
+
top: "100%",
|
|
605
|
+
marginTop: 4,
|
|
606
|
+
minWidth: 140,
|
|
607
|
+
padding: 4,
|
|
608
|
+
borderRadius: 12,
|
|
609
|
+
background: "var(--ds-background-100)",
|
|
610
|
+
boxShadow: "var(--ds-shadow-menu, var(--ds-shadow-medium))",
|
|
611
|
+
zIndex: 2001
|
|
612
|
+
}, role: "menu", children: options.map((option) => jsxRuntimeExports.jsx("button", { type: "button", role: "menuitem", className: "wf-menu-item", style: {
|
|
613
|
+
fontWeight: option.value === value ? 500 : 400
|
|
614
|
+
}, onClick: () => {
|
|
615
|
+
onChange(option.value);
|
|
616
|
+
setOpen(false);
|
|
617
|
+
}, children: option.label }, option.value)) })] });
|
|
618
|
+
}
|
|
619
|
+
const ERROR_EVENT_TYPES$1 = /* @__PURE__ */ new Set([
|
|
620
|
+
"step_failed",
|
|
621
|
+
"step_retrying",
|
|
622
|
+
"run_failed",
|
|
623
|
+
"workflow_failed"
|
|
624
|
+
]);
|
|
625
|
+
const BUTTON_RESET_STYLE = {
|
|
626
|
+
appearance: "none",
|
|
627
|
+
WebkitAppearance: "none",
|
|
628
|
+
border: "none",
|
|
629
|
+
background: "transparent"
|
|
630
|
+
};
|
|
631
|
+
const DOT_PULSE_ANIMATION = "workflow-dot-pulse 1.25s cubic-bezier(0, 0, 0.2, 1) infinite";
|
|
632
|
+
function formatEventTime(date) {
|
|
633
|
+
return date.toLocaleTimeString("en-US", {
|
|
634
|
+
hour: "2-digit",
|
|
635
|
+
minute: "2-digit",
|
|
636
|
+
second: "2-digit",
|
|
637
|
+
hour12: false
|
|
638
|
+
}) + "." + date.getMilliseconds().toString().padStart(3, "0");
|
|
639
|
+
}
|
|
640
|
+
function parseEventDate(value) {
|
|
641
|
+
if (value == null)
|
|
642
|
+
return null;
|
|
643
|
+
const date = value instanceof Date ? value : new Date(String(value));
|
|
644
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
645
|
+
}
|
|
646
|
+
function getEffectiveEventDate$1(event) {
|
|
647
|
+
return parseEventDate(event.occurredAt) ?? new Date(event.createdAt);
|
|
648
|
+
}
|
|
649
|
+
function getEffectiveEventTime(event) {
|
|
650
|
+
return getEffectiveEventDate$1(event).getTime();
|
|
651
|
+
}
|
|
652
|
+
function formatEventType(eventType) {
|
|
653
|
+
return eventType.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
654
|
+
}
|
|
655
|
+
function getStatusDotColor(eventType) {
|
|
656
|
+
if (eventType === "step_failed" || eventType === "run_failed" || eventType === "workflow_failed") {
|
|
657
|
+
return "var(--ds-red-700)";
|
|
658
|
+
}
|
|
659
|
+
if (eventType === "run_cancelled") {
|
|
660
|
+
return "var(--ds-amber-700)";
|
|
661
|
+
}
|
|
662
|
+
if (eventType === "step_retrying") {
|
|
663
|
+
return "var(--ds-amber-700)";
|
|
664
|
+
}
|
|
665
|
+
if (eventType === "attr_set") {
|
|
666
|
+
return "var(--ds-teal-900)";
|
|
667
|
+
}
|
|
668
|
+
if (eventType === "step_completed" || eventType === "run_completed" || eventType === "workflow_completed" || eventType === "hook_disposed" || eventType === "wait_completed") {
|
|
669
|
+
return "var(--ds-green-700)";
|
|
670
|
+
}
|
|
671
|
+
if (eventType === "step_started" || eventType === "run_started" || eventType === "workflow_started" || eventType === "hook_received") {
|
|
672
|
+
return "var(--ds-blue-700)";
|
|
673
|
+
}
|
|
674
|
+
return "var(--ds-gray-600)";
|
|
675
|
+
}
|
|
676
|
+
function buildNameMaps(events, run) {
|
|
677
|
+
var _a, _b;
|
|
678
|
+
const correlationNameMap = /* @__PURE__ */ new Map();
|
|
679
|
+
if (events) {
|
|
680
|
+
for (const event of events) {
|
|
681
|
+
if (event.eventType === "step_created" && event.correlationId) {
|
|
682
|
+
const stepName = ((_a = event.eventData) == null ? void 0 : _a.stepName) ?? "";
|
|
373
683
|
const parsed = parseStepName(String(stepName));
|
|
374
684
|
correlationNameMap.set(event.correlationId, (parsed == null ? void 0 : parsed.shortName) ?? stepName);
|
|
375
685
|
}
|
|
@@ -1040,7 +1350,13 @@ function EventListViewInner({ events, run, onLoadEventData, hasMoreEvents = fals
|
|
|
1040
1350
|
function EventListView(props) {
|
|
1041
1351
|
return jsxRuntimeExports.jsx(ContextCardProvider, { children: jsxRuntimeExports.jsx(EventListViewInner, { ...props }) });
|
|
1042
1352
|
}
|
|
1043
|
-
const
|
|
1353
|
+
const GUTTER_PX = 1;
|
|
1354
|
+
const MIN_PX = 50;
|
|
1355
|
+
const DEFAULT_START_PX = 340;
|
|
1356
|
+
function paneColTemplate(startPx) {
|
|
1357
|
+
return `${startPx}px ${GUTTER_PX}px minmax(${MIN_PX}px, 1fr)`;
|
|
1358
|
+
}
|
|
1359
|
+
const COL_TEMPLATE = paneColTemplate(DEFAULT_START_PX);
|
|
1044
1360
|
const ROWS = [
|
|
1045
1361
|
{ id: "r0", name: 62, off: 0, bar: 72 },
|
|
1046
1362
|
{ id: "r1", name: 78, off: 6, bar: 48 },
|
|
@@ -1054,7 +1370,11 @@ const ROWS = [
|
|
|
1054
1370
|
const HEADER_MARKERS = ["m0", "m1", "m2", "m3"];
|
|
1055
1371
|
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" }) });
|
|
1056
1372
|
function TraceViewerSkeleton() {
|
|
1057
|
-
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.
|
|
1373
|
+
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: {
|
|
1374
|
+
left: `${row.off}%`,
|
|
1375
|
+
width: `${row.bar}%`,
|
|
1376
|
+
top: index * 3.5
|
|
1377
|
+
} }, 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)) })] })] });
|
|
1058
1378
|
}
|
|
1059
1379
|
function shouldShowVerticalLine(eventType) {
|
|
1060
1380
|
if (eventType === "hook_created" || eventType === "hook_received" || eventType === "hook_disposed") {
|
|
@@ -1438,319 +1758,39 @@ function cascadeSpans(runSpan, spans) {
|
|
|
1438
1758
|
runSpan,
|
|
1439
1759
|
...spans.slice().sort((a, b) => {
|
|
1440
1760
|
const aStart = otelTimeToMs(a.startTime);
|
|
1441
|
-
const bStart = otelTimeToMs(b.startTime);
|
|
1442
|
-
return aStart - bStart;
|
|
1443
|
-
})
|
|
1444
|
-
];
|
|
1445
|
-
return sortedSpans.map((span, index) => {
|
|
1446
|
-
const parentSpanId = index === 0 ? void 0 : String(sortedSpans[index - 1].spanId);
|
|
1447
|
-
return {
|
|
1448
|
-
...span,
|
|
1449
|
-
parentSpanId
|
|
1450
|
-
};
|
|
1451
|
-
});
|
|
1452
|
-
}
|
|
1453
|
-
function buildTrace(run, events, now) {
|
|
1454
|
-
const groupedEvents = groupEventsByCorrelation(events);
|
|
1455
|
-
const latestKnownTime = computeLatestKnownTime(events, run);
|
|
1456
|
-
const { runSpan, spans } = buildSpans(run, groupedEvents, now, latestKnownTime);
|
|
1457
|
-
const sortedCascadingSpans = cascadeSpans(runSpan, spans);
|
|
1458
|
-
const traceStartMs = otelTimeToMs(runSpan.startTime);
|
|
1459
|
-
const knownDurationMs = latestKnownTime.getTime() - traceStartMs;
|
|
1460
|
-
return {
|
|
1461
|
-
traceId: run.runId,
|
|
1462
|
-
rootSpanId: run.runId,
|
|
1463
|
-
spans: sortedCascadingSpans,
|
|
1464
|
-
resources: [
|
|
1465
|
-
{
|
|
1466
|
-
name: "workflow",
|
|
1467
|
-
attributes: {
|
|
1468
|
-
"service.name": WORKFLOW_LIBRARY.name
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
],
|
|
1472
|
-
knownDurationMs: Math.max(0, knownDurationMs)
|
|
1473
|
-
};
|
|
1474
|
-
}
|
|
1475
|
-
const ELLIPSIS = "...";
|
|
1476
|
-
const MIN_START = 3;
|
|
1477
|
-
const MIN_END = 3;
|
|
1478
|
-
const MIN_KEPT = MIN_START + MIN_END;
|
|
1479
|
-
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
1480
|
-
function toGraphemes(text) {
|
|
1481
|
-
if (graphemeSegmenter) {
|
|
1482
|
-
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
1483
|
-
}
|
|
1484
|
-
return Array.from(text);
|
|
1485
|
-
}
|
|
1486
|
-
function buildCandidate(graphemes, kept) {
|
|
1487
|
-
if (kept <= 0) {
|
|
1488
|
-
return {
|
|
1489
|
-
prefixText: "",
|
|
1490
|
-
prefixGraphemeCount: 0,
|
|
1491
|
-
suffixText: "",
|
|
1492
|
-
suffixGraphemeCount: 0,
|
|
1493
|
-
text: ELLIPSIS,
|
|
1494
|
-
truncated: true
|
|
1495
|
-
};
|
|
1496
|
-
}
|
|
1497
|
-
const suffixGraphemeCount = kept >= MIN_KEPT ? Math.max(MIN_END, Math.floor(kept / 2)) : Math.floor(kept / 2);
|
|
1498
|
-
const prefixGraphemeCount = kept - suffixGraphemeCount;
|
|
1499
|
-
const prefixText = graphemes.slice(0, prefixGraphemeCount).join("");
|
|
1500
|
-
const suffixText = suffixGraphemeCount > 0 ? graphemes.slice(-suffixGraphemeCount).join("") : "";
|
|
1501
|
-
return {
|
|
1502
|
-
prefixText,
|
|
1503
|
-
prefixGraphemeCount,
|
|
1504
|
-
suffixText,
|
|
1505
|
-
suffixGraphemeCount,
|
|
1506
|
-
text: prefixText + ELLIPSIS + suffixText,
|
|
1507
|
-
truncated: true
|
|
1508
|
-
};
|
|
1509
|
-
}
|
|
1510
|
-
function middleTruncate(graphemes, availableWidth, measure, fullWidth) {
|
|
1511
|
-
const fullText = graphemes.join("");
|
|
1512
|
-
const resolvedFullWidth = fullWidth ?? measure(fullText);
|
|
1513
|
-
if (availableWidth <= 0 || graphemes.length === 0) {
|
|
1514
|
-
return {
|
|
1515
|
-
prefixText: fullText,
|
|
1516
|
-
prefixGraphemeCount: graphemes.length,
|
|
1517
|
-
suffixText: "",
|
|
1518
|
-
suffixGraphemeCount: 0,
|
|
1519
|
-
text: fullText,
|
|
1520
|
-
truncated: false
|
|
1521
|
-
};
|
|
1522
|
-
}
|
|
1523
|
-
if (resolvedFullWidth <= availableWidth) {
|
|
1524
|
-
return {
|
|
1525
|
-
prefixText: fullText,
|
|
1526
|
-
prefixGraphemeCount: graphemes.length,
|
|
1527
|
-
suffixText: "",
|
|
1528
|
-
suffixGraphemeCount: 0,
|
|
1529
|
-
text: fullText,
|
|
1530
|
-
truncated: false
|
|
1531
|
-
};
|
|
1532
|
-
}
|
|
1533
|
-
let lo = 0;
|
|
1534
|
-
let hi = graphemes.length - 1;
|
|
1535
|
-
let best = -1;
|
|
1536
|
-
while (lo <= hi) {
|
|
1537
|
-
const mid = lo + hi >>> 1;
|
|
1538
|
-
const candidate = buildCandidate(graphemes, mid);
|
|
1539
|
-
if (measure(candidate.text) <= availableWidth) {
|
|
1540
|
-
best = mid;
|
|
1541
|
-
lo = mid + 1;
|
|
1542
|
-
} else {
|
|
1543
|
-
hi = mid - 1;
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
if (best === -1) {
|
|
1547
|
-
return {
|
|
1548
|
-
prefixText: "",
|
|
1549
|
-
prefixGraphemeCount: 0,
|
|
1550
|
-
suffixText: "",
|
|
1551
|
-
suffixGraphemeCount: 0,
|
|
1552
|
-
text: "",
|
|
1553
|
-
truncated: true
|
|
1554
|
-
};
|
|
1555
|
-
}
|
|
1556
|
-
return buildCandidate(graphemes, best);
|
|
1557
|
-
}
|
|
1558
|
-
function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value }) {
|
|
1559
|
-
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
1560
|
-
if (selectionStart < 0 || selectionEnd > visibleText.length || selectionStart >= selectionEnd) {
|
|
1561
|
-
return null;
|
|
1562
|
-
}
|
|
1563
|
-
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
1564
|
-
return value;
|
|
1565
|
-
}
|
|
1566
|
-
const ellipsisStart = prefixText.length;
|
|
1567
|
-
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
1568
|
-
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
1569
|
-
return null;
|
|
1570
|
-
}
|
|
1571
|
-
const originalGraphemes = toGraphemes(value);
|
|
1572
|
-
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
1573
|
-
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
1574
|
-
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
1575
|
-
return originalGraphemes.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount).join("");
|
|
1576
|
-
}
|
|
1577
|
-
function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value }) {
|
|
1578
|
-
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
1579
|
-
const trimmedSelectionText = selectionText.trim();
|
|
1580
|
-
if (!trimmedSelectionText) {
|
|
1581
|
-
return null;
|
|
1582
|
-
}
|
|
1583
|
-
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
1584
|
-
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
1585
|
-
if (trimmedSelectionText === visibleText) {
|
|
1586
|
-
return leading + value + trailing;
|
|
1587
|
-
}
|
|
1588
|
-
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
1589
|
-
return null;
|
|
1590
|
-
}
|
|
1591
|
-
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
1592
|
-
if (selectionStart === -1) {
|
|
1593
|
-
return null;
|
|
1594
|
-
}
|
|
1595
|
-
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
1596
|
-
const mappedText = getMiddleTruncateCopyText({
|
|
1597
|
-
prefixText,
|
|
1598
|
-
selectionEnd,
|
|
1599
|
-
selectionStart,
|
|
1600
|
-
suffixText,
|
|
1601
|
-
value
|
|
1602
|
-
});
|
|
1603
|
-
return mappedText === null ? null : leading + mappedText + trailing;
|
|
1604
|
-
}
|
|
1605
|
-
const useIsomorphicLayoutEffect = typeof window === "undefined" ? reactExports.useEffect : reactExports.useLayoutEffect;
|
|
1606
|
-
function createFullState(value, graphemes) {
|
|
1607
|
-
return {
|
|
1608
|
-
displayText: value,
|
|
1609
|
-
isTruncated: false,
|
|
1610
|
-
prefixGraphemeCount: graphemes.length,
|
|
1611
|
-
prefixText: value,
|
|
1612
|
-
suffixGraphemeCount: 0,
|
|
1613
|
-
suffixText: ""
|
|
1614
|
-
};
|
|
1615
|
-
}
|
|
1616
|
-
function useMiddleTruncate(value) {
|
|
1617
|
-
const graphemes = reactExports.useMemo(() => toGraphemes(value), [value]);
|
|
1618
|
-
const fullState = reactExports.useMemo(() => createFullState(value, graphemes), [graphemes, value]);
|
|
1619
|
-
const ref = reactExports.useRef(null);
|
|
1620
|
-
const measureRef = reactExports.useRef(null);
|
|
1621
|
-
const [state, setState] = reactExports.useState(() => fullState);
|
|
1622
|
-
const rafRef = reactExports.useRef(0);
|
|
1623
|
-
const updateState = reactExports.useCallback((nextState) => {
|
|
1624
|
-
setState((currentState) => {
|
|
1625
|
-
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) {
|
|
1626
|
-
return currentState;
|
|
1627
|
-
}
|
|
1628
|
-
return nextState;
|
|
1629
|
-
});
|
|
1630
|
-
}, []);
|
|
1631
|
-
const recalculate = reactExports.useCallback(() => {
|
|
1632
|
-
const el = ref.current;
|
|
1633
|
-
const measureEl = measureRef.current;
|
|
1634
|
-
if (!el || !measureEl)
|
|
1635
|
-
return;
|
|
1636
|
-
const available = el.clientWidth;
|
|
1637
|
-
if (available <= 0) {
|
|
1638
|
-
updateState(fullState);
|
|
1639
|
-
return;
|
|
1640
|
-
}
|
|
1641
|
-
const measure = (text) => {
|
|
1642
|
-
measureEl.textContent = text;
|
|
1643
|
-
return measureEl.scrollWidth;
|
|
1644
|
-
};
|
|
1645
|
-
const fullWidth = measure(value);
|
|
1646
|
-
if (fullWidth <= available) {
|
|
1647
|
-
updateState(fullState);
|
|
1648
|
-
return;
|
|
1649
|
-
}
|
|
1650
|
-
const result = middleTruncate(graphemes, available, measure, fullWidth);
|
|
1651
|
-
updateState({
|
|
1652
|
-
displayText: result.text,
|
|
1653
|
-
isTruncated: result.truncated,
|
|
1654
|
-
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
1655
|
-
prefixText: result.prefixText,
|
|
1656
|
-
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
1657
|
-
suffixText: result.suffixText
|
|
1658
|
-
});
|
|
1659
|
-
}, [fullState, graphemes, updateState, value]);
|
|
1660
|
-
useIsomorphicLayoutEffect(() => {
|
|
1661
|
-
recalculate();
|
|
1662
|
-
}, [recalculate]);
|
|
1663
|
-
reactExports.useEffect(() => {
|
|
1664
|
-
var _a;
|
|
1665
|
-
const el = ref.current;
|
|
1666
|
-
if (!el)
|
|
1667
|
-
return;
|
|
1668
|
-
const debouncedRecalc = () => {
|
|
1669
|
-
cancelAnimationFrame(rafRef.current);
|
|
1670
|
-
rafRef.current = requestAnimationFrame(recalculate);
|
|
1671
|
-
};
|
|
1672
|
-
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(debouncedRecalc) : null;
|
|
1673
|
-
ro == null ? void 0 : ro.observe(el);
|
|
1674
|
-
window.addEventListener("resize", debouncedRecalc);
|
|
1675
|
-
const onFontsLoaded = () => {
|
|
1676
|
-
debouncedRecalc();
|
|
1677
|
-
};
|
|
1678
|
-
const fontSet = "fonts" in document ? document.fonts : null;
|
|
1679
|
-
(_a = fontSet == null ? void 0 : fontSet.addEventListener) == null ? void 0 : _a.call(fontSet, "loadingdone", onFontsLoaded);
|
|
1680
|
-
return () => {
|
|
1681
|
-
var _a2;
|
|
1682
|
-
ro == null ? void 0 : ro.disconnect();
|
|
1683
|
-
window.removeEventListener("resize", debouncedRecalc);
|
|
1684
|
-
cancelAnimationFrame(rafRef.current);
|
|
1685
|
-
(_a2 = fontSet == null ? void 0 : fontSet.removeEventListener) == null ? void 0 : _a2.call(fontSet, "loadingdone", onFontsLoaded);
|
|
1686
|
-
};
|
|
1687
|
-
}, [recalculate]);
|
|
1688
|
-
return {
|
|
1689
|
-
ref,
|
|
1690
|
-
measureRef,
|
|
1691
|
-
displayText: state.displayText,
|
|
1692
|
-
isTruncated: state.isTruncated,
|
|
1693
|
-
prefixGraphemeCount: state.prefixGraphemeCount,
|
|
1694
|
-
prefixText: state.prefixText,
|
|
1695
|
-
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
1696
|
-
suffixText: state.suffixText
|
|
1697
|
-
};
|
|
1698
|
-
}
|
|
1699
|
-
function getRangeOffsets(container, range) {
|
|
1700
|
-
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) {
|
|
1701
|
-
return null;
|
|
1702
|
-
}
|
|
1703
|
-
const startRange = document.createRange();
|
|
1704
|
-
startRange.selectNodeContents(container);
|
|
1705
|
-
startRange.setEnd(range.startContainer, range.startOffset);
|
|
1706
|
-
const endRange = document.createRange();
|
|
1707
|
-
endRange.selectNodeContents(container);
|
|
1708
|
-
endRange.setEnd(range.endContainer, range.endOffset);
|
|
1709
|
-
return {
|
|
1710
|
-
end: endRange.toString().length,
|
|
1711
|
-
start: startRange.toString().length
|
|
1712
|
-
};
|
|
1713
|
-
}
|
|
1714
|
-
function MiddleTruncate({ value, className, onCopy: onCopyProp, ...props }) {
|
|
1715
|
-
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
1716
|
-
const visibleRef = reactExports.useRef(null);
|
|
1717
|
-
const handleCopy = reactExports.useCallback((e) => {
|
|
1718
|
-
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
1719
|
-
if (e.defaultPrevented || !isTruncated)
|
|
1720
|
-
return;
|
|
1721
|
-
const selection = window.getSelection();
|
|
1722
|
-
if (!selection || selection.rangeCount === 0)
|
|
1723
|
-
return;
|
|
1724
|
-
const selectionText = selection.toString();
|
|
1725
|
-
if (!selectionText)
|
|
1726
|
-
return;
|
|
1727
|
-
const range = selection.getRangeAt(0);
|
|
1728
|
-
const visibleEl = visibleRef.current;
|
|
1729
|
-
let copyText = null;
|
|
1730
|
-
if (e.currentTarget.contains(range.startContainer) && e.currentTarget.contains(range.endContainer) && visibleEl) {
|
|
1731
|
-
const offsets = getRangeOffsets(visibleEl, range);
|
|
1732
|
-
if (offsets) {
|
|
1733
|
-
copyText = getMiddleTruncateCopyText({
|
|
1734
|
-
prefixText,
|
|
1735
|
-
selectionEnd: offsets.end,
|
|
1736
|
-
selectionStart: offsets.start,
|
|
1737
|
-
suffixText,
|
|
1738
|
-
value
|
|
1739
|
-
});
|
|
1761
|
+
const bStart = otelTimeToMs(b.startTime);
|
|
1762
|
+
return aStart - bStart;
|
|
1763
|
+
})
|
|
1764
|
+
];
|
|
1765
|
+
return sortedSpans.map((span, index) => {
|
|
1766
|
+
const parentSpanId = index === 0 ? void 0 : String(sortedSpans[index - 1].spanId);
|
|
1767
|
+
return {
|
|
1768
|
+
...span,
|
|
1769
|
+
parentSpanId
|
|
1770
|
+
};
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
function buildTrace(run, events, now) {
|
|
1774
|
+
const groupedEvents = groupEventsByCorrelation(events);
|
|
1775
|
+
const latestKnownTime = computeLatestKnownTime(events, run);
|
|
1776
|
+
const { runSpan, spans } = buildSpans(run, groupedEvents, now, latestKnownTime);
|
|
1777
|
+
const sortedCascadingSpans = cascadeSpans(runSpan, spans);
|
|
1778
|
+
const traceStartMs = otelTimeToMs(runSpan.startTime);
|
|
1779
|
+
const knownDurationMs = latestKnownTime.getTime() - traceStartMs;
|
|
1780
|
+
return {
|
|
1781
|
+
traceId: run.runId,
|
|
1782
|
+
rootSpanId: run.runId,
|
|
1783
|
+
spans: sortedCascadingSpans,
|
|
1784
|
+
resources: [
|
|
1785
|
+
{
|
|
1786
|
+
name: "workflow",
|
|
1787
|
+
attributes: {
|
|
1788
|
+
"service.name": WORKFLOW_LIBRARY.name
|
|
1789
|
+
}
|
|
1740
1790
|
}
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
selectionText,
|
|
1745
|
-
suffixText,
|
|
1746
|
-
value
|
|
1747
|
-
}));
|
|
1748
|
-
if (copyText === null)
|
|
1749
|
-
return;
|
|
1750
|
-
e.preventDefault();
|
|
1751
|
-
e.clipboardData.setData("text/plain", copyText);
|
|
1752
|
-
}, [onCopyProp, isTruncated, prefixText, suffixText, value]);
|
|
1753
|
-
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 })] });
|
|
1791
|
+
],
|
|
1792
|
+
knownDurationMs: Math.max(0, knownDurationMs)
|
|
1793
|
+
};
|
|
1754
1794
|
}
|
|
1755
1795
|
function ConversationView({ messages }) {
|
|
1756
1796
|
if (messages.length === 0) {
|
|
@@ -1897,7 +1937,7 @@ const conversationTabs = [
|
|
|
1897
1937
|
];
|
|
1898
1938
|
function ConversationWithTabs({ conversation, args }) {
|
|
1899
1939
|
const [activeTab, setActiveTab] = reactExports.useState("conversation");
|
|
1900
|
-
return jsxRuntimeExports.jsx(
|
|
1940
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input", 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) }) }) });
|
|
1901
1941
|
}
|
|
1902
1942
|
function EncryptedFieldBlock() {
|
|
1903
1943
|
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
@@ -2069,7 +2109,7 @@ const attributeToDisplayFn = {
|
|
|
2069
2109
|
environment: (_value) => null,
|
|
2070
2110
|
executionContext: (_value) => null,
|
|
2071
2111
|
// Attributes — string-string metadata attached to the run.
|
|
2072
|
-
// Rendered as key-value rows in its own collapsible
|
|
2112
|
+
// Rendered as key-value rows in its own collapsible section;
|
|
2073
2113
|
// if empty/missing, hidden by the hasDisplayContent gate.
|
|
2074
2114
|
attributes: (value) => {
|
|
2075
2115
|
if (!hasDisplayContent(value))
|
|
@@ -2089,15 +2129,17 @@ const attributeToDisplayFn = {
|
|
|
2089
2129
|
metadata: (value) => {
|
|
2090
2130
|
if (!hasDisplayContent(value))
|
|
2091
2131
|
return null;
|
|
2092
|
-
if (isEncryptedMarker(value))
|
|
2093
|
-
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2132
|
+
if (isEncryptedMarker(value)) {
|
|
2133
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Metadata", children: jsxRuntimeExports.jsx(EncryptedDataBlock, {}) });
|
|
2134
|
+
}
|
|
2135
|
+
if (isExpiredMarker(value)) {
|
|
2136
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Metadata", children: jsxRuntimeExports.jsx(ExpiredFieldBlock, {}) });
|
|
2137
|
+
}
|
|
2138
|
+
return jsxRuntimeExports.jsx(RunMetadataCard, { metadata: value });
|
|
2097
2139
|
},
|
|
2098
2140
|
input: (value, context) => {
|
|
2099
2141
|
if (isEncryptedMarker(value)) {
|
|
2100
|
-
return jsxRuntimeExports.jsx(
|
|
2142
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2101
2143
|
}
|
|
2102
2144
|
if (isExpiredMarker(value))
|
|
2103
2145
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
@@ -2109,51 +2151,51 @@ const attributeToDisplayFn = {
|
|
|
2109
2151
|
if ((context == null ? void 0 : context.stepName) && isDoStreamStep(context.stepName)) {
|
|
2110
2152
|
const conversation = extractConversation(args);
|
|
2111
2153
|
if (conversation && conversation.length > 0) {
|
|
2112
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args }), hasClosureVars && jsxRuntimeExports.jsx(
|
|
2154
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "This Value", children: JsonBlock(thisVal) })] });
|
|
2113
2155
|
}
|
|
2114
2156
|
}
|
|
2115
2157
|
if (!hasArgs && !hasClosureVars && !hasThisVal) {
|
|
2116
|
-
return jsxRuntimeExports.jsx(
|
|
2158
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input (no data)", disabled: true });
|
|
2117
2159
|
}
|
|
2118
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(
|
|
2160
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Collapsible, { label: "Input", 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) })] });
|
|
2119
2161
|
}
|
|
2120
2162
|
if (!hasDisplayContent(value)) {
|
|
2121
|
-
return jsxRuntimeExports.jsx(
|
|
2163
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input (no data)", disabled: true });
|
|
2122
2164
|
}
|
|
2123
|
-
return jsxRuntimeExports.jsx(
|
|
2165
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Input", children: Array.isArray(value) ? value.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(value) });
|
|
2124
2166
|
},
|
|
2125
2167
|
output: (value) => {
|
|
2126
2168
|
if (isEncryptedMarker(value)) {
|
|
2127
|
-
return jsxRuntimeExports.jsx(
|
|
2169
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Output", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2128
2170
|
}
|
|
2129
2171
|
if (!hasDisplayContent(value))
|
|
2130
2172
|
return null;
|
|
2131
2173
|
if (isExpiredMarker(value))
|
|
2132
2174
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2133
|
-
return jsxRuntimeExports.jsx(
|
|
2175
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Output", children: JsonBlock(value) });
|
|
2134
2176
|
},
|
|
2135
2177
|
error: (value) => {
|
|
2136
2178
|
if (isEncryptedMarker(value)) {
|
|
2137
|
-
return jsxRuntimeExports.jsx(
|
|
2179
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2138
2180
|
}
|
|
2139
2181
|
if (isExpiredMarker(value))
|
|
2140
2182
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2141
2183
|
if (!hasDisplayContent(value))
|
|
2142
2184
|
return null;
|
|
2143
2185
|
if (isStructuredError(value)) {
|
|
2144
|
-
return jsxRuntimeExports.jsx(
|
|
2186
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(ErrorStackBlock, { value }) });
|
|
2145
2187
|
}
|
|
2146
|
-
return jsxRuntimeExports.jsx(
|
|
2188
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Error", defaultOpen: true, children: JsonBlock(value) });
|
|
2147
2189
|
},
|
|
2148
2190
|
eventData: (value) => {
|
|
2149
2191
|
if (isEncryptedMarker(value)) {
|
|
2150
|
-
return jsxRuntimeExports.jsx(
|
|
2192
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Event Data", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2151
2193
|
}
|
|
2152
2194
|
if (isExpiredMarker(value))
|
|
2153
2195
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2154
2196
|
if (!hasDisplayContent(value))
|
|
2155
2197
|
return null;
|
|
2156
|
-
return jsxRuntimeExports.jsx(
|
|
2198
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Event Data", defaultOpen: true, children: JsonBlock(value) });
|
|
2157
2199
|
},
|
|
2158
2200
|
errorCode: (value) => {
|
|
2159
2201
|
if (typeof value !== "string" || value.length === 0)
|
|
@@ -2173,6 +2215,7 @@ const selfHeaderedAttributes = /* @__PURE__ */ new Set([
|
|
|
2173
2215
|
"input",
|
|
2174
2216
|
"output",
|
|
2175
2217
|
"error",
|
|
2218
|
+
"metadata",
|
|
2176
2219
|
"attributes",
|
|
2177
2220
|
"eventData"
|
|
2178
2221
|
]);
|
|
@@ -2194,9 +2237,9 @@ const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }
|
|
|
2194
2237
|
if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
|
|
2195
2238
|
const label = attribute === "eventData" ? "Event Data" : attribute === "output" ? "Output" : "Input";
|
|
2196
2239
|
if (decryptCtx == null ? void 0 : decryptCtx.hasEncryptedData) {
|
|
2197
|
-
return jsxRuntimeExports.jsx(
|
|
2240
|
+
return jsxRuntimeExports.jsx(Collapsible, { label, defaultOpen: attribute === "eventData", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2198
2241
|
}
|
|
2199
|
-
return jsxRuntimeExports.jsx(
|
|
2242
|
+
return jsxRuntimeExports.jsx(Collapsible, { label });
|
|
2200
2243
|
}
|
|
2201
2244
|
const displayFn = attributeToDisplayFn[attribute];
|
|
2202
2245
|
if (!displayFn) {
|
|
@@ -2282,12 +2325,13 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
|
|
|
2282
2325
|
isDecrypting,
|
|
2283
2326
|
hasEncryptedData: outerDecryptCtx == null ? void 0 : outerDecryptCtx.hasEncryptedData
|
|
2284
2327
|
} : outerDecryptCtx;
|
|
2285
|
-
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("
|
|
2328
|
+
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) => {
|
|
2286
2329
|
var _a;
|
|
2287
2330
|
const displayValue = (_a = attributeToDisplayFn[attribute]) == null ? void 0 : _a.call(attributeToDisplayFn, displayData[attribute]);
|
|
2288
2331
|
const isCopyableBasicAttribute = copyableBasicAttributes.has(attribute) && typeof displayValue === "string";
|
|
2289
|
-
|
|
2290
|
-
|
|
2332
|
+
const label = getAttributeDisplayName(attribute);
|
|
2333
|
+
return jsxRuntimeExports.jsx(DetailMonoKeyValueRow, { label, value: displayValue, copyText: isCopyableBasicAttribute ? displayValue : void 0 }, attribute);
|
|
2334
|
+
}), 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] }) }) }) });
|
|
2291
2335
|
};
|
|
2292
2336
|
const ERROR_EVENT_TYPES = /* @__PURE__ */ new Set(["step_failed", "step_retrying"]);
|
|
2293
2337
|
const DATA_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -2369,17 +2413,17 @@ function EventItem({ event, onLoadEventData, encryptionKey, showSeparateEventOcc
|
|
|
2369
2413
|
second: "numeric"
|
|
2370
2414
|
});
|
|
2371
2415
|
const displayPayload = isLoading ? loadedData : mergedDisplay;
|
|
2372
|
-
return jsxRuntimeExports.jsxs(
|
|
2416
|
+
return jsxRuntimeExports.jsxs(CollapsibleRoot, { variant: "card", onOpenChange: canHaveData ? (open) => {
|
|
2373
2417
|
if (open)
|
|
2374
2418
|
handleExpand();
|
|
2375
|
-
} : void 0, 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 }) })] });
|
|
2419
|
+
} : 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 }) })] })] });
|
|
2376
2420
|
}
|
|
2377
2421
|
function hasOnlyExpiredFields(data, eventType) {
|
|
2378
2422
|
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2379
2423
|
return false;
|
|
2380
2424
|
}
|
|
2381
2425
|
const record = data;
|
|
2382
|
-
const refKeys =
|
|
2426
|
+
const refKeys = getEventDataRefFields(eventType);
|
|
2383
2427
|
const presentKeys = refKeys.filter((k) => k in record);
|
|
2384
2428
|
return presentKeys.length > 0 && presentKeys.every((k) => isExpiredMarker(record[k]));
|
|
2385
2429
|
}
|
|
@@ -2412,9 +2456,9 @@ function EventsList({ events, isLoading = false, error, onLoadEventData, onStrea
|
|
|
2412
2456
|
const sortedEvents = reactExports.useMemo(() => [...events].sort((a, b) => getEffectiveEventDate(a).getTime() - getEffectiveEventDate(b).getTime()), [events]);
|
|
2413
2457
|
const hasEvents = sortedEvents.length > 0 && !error;
|
|
2414
2458
|
if (!hasEvents && !isLoading) {
|
|
2415
|
-
return jsxRuntimeExports.jsx(
|
|
2459
|
+
return jsxRuntimeExports.jsx(Collapsible, { label: "Events", disabled: true });
|
|
2416
2460
|
}
|
|
2417
|
-
return jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsx(
|
|
2461
|
+
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)) }) })] }) }) });
|
|
2418
2462
|
}
|
|
2419
2463
|
const hasField = (value, key) => key in value;
|
|
2420
2464
|
const RESOURCES_WITH_FETCHED_DETAIL = /* @__PURE__ */ new Set(["run", "step", "sleep"]);
|
|
@@ -2781,6 +2825,257 @@ const kbdVariants = cva("inline-flex items-center justify-center rounded px-1 te
|
|
|
2781
2825
|
function Kbd({ children, className, variant, size, ...props }) {
|
|
2782
2826
|
return jsxRuntimeExports.jsx("kbd", { className: cn(kbdVariants({ variant, size, className })), ...props, children });
|
|
2783
2827
|
}
|
|
2828
|
+
const PANEL_MIN_WIDTH = 280;
|
|
2829
|
+
const PANEL_HARD_MAX_WIDTH = 1300;
|
|
2830
|
+
const PANEL_DEFAULT_WIDTH = 360;
|
|
2831
|
+
const MAIN_MIN_WIDTH = 400;
|
|
2832
|
+
const PANEL_WIDTH_STORAGE_KEY = "workflow-trace-detail-panel-width";
|
|
2833
|
+
function clamp(value, min, max) {
|
|
2834
|
+
return Math.min(Math.max(value, min), max);
|
|
2835
|
+
}
|
|
2836
|
+
function computeMaxPanelWidth(availableWidth) {
|
|
2837
|
+
if (availableWidth <= 0)
|
|
2838
|
+
return PANEL_HARD_MAX_WIDTH;
|
|
2839
|
+
return Math.min(Math.max(availableWidth - MAIN_MIN_WIDTH, 0), PANEL_HARD_MAX_WIDTH);
|
|
2840
|
+
}
|
|
2841
|
+
function clampPanelWidth(width, availableWidth) {
|
|
2842
|
+
return clamp(width, PANEL_MIN_WIDTH, computeMaxPanelWidth(availableWidth));
|
|
2843
|
+
}
|
|
2844
|
+
function readStoredPanelWidth() {
|
|
2845
|
+
if (typeof window === "undefined")
|
|
2846
|
+
return PANEL_DEFAULT_WIDTH;
|
|
2847
|
+
try {
|
|
2848
|
+
const raw = window.localStorage.getItem(PANEL_WIDTH_STORAGE_KEY);
|
|
2849
|
+
const value = raw ? Number(raw) : Number.NaN;
|
|
2850
|
+
if (!Number.isFinite(value))
|
|
2851
|
+
return PANEL_DEFAULT_WIDTH;
|
|
2852
|
+
return clamp(value, PANEL_MIN_WIDTH, PANEL_HARD_MAX_WIDTH);
|
|
2853
|
+
} catch {
|
|
2854
|
+
return PANEL_DEFAULT_WIDTH;
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
function writeStoredPanelWidth(width) {
|
|
2858
|
+
if (typeof window === "undefined")
|
|
2859
|
+
return;
|
|
2860
|
+
try {
|
|
2861
|
+
window.localStorage.setItem(PANEL_WIDTH_STORAGE_KEY, String(Math.round(width)));
|
|
2862
|
+
} catch {
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
function DraggableBorder({ element, position, onWidthChange, onReset, "aria-label": ariaLabel, "aria-controls": ariaControls, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuenow": ariaValueNow }) {
|
|
2866
|
+
const [isDragging, setIsDragging] = reactExports.useState(false);
|
|
2867
|
+
const pointerIdRef = reactExports.useRef(null);
|
|
2868
|
+
const startXRef = reactExports.useRef(0);
|
|
2869
|
+
const startWidthRef = reactExports.useRef(0);
|
|
2870
|
+
const pendingWidthRef = reactExports.useRef(0);
|
|
2871
|
+
const rafRef = reactExports.useRef(null);
|
|
2872
|
+
const movedRef = reactExports.useRef(false);
|
|
2873
|
+
const lastDragEndAtRef = reactExports.useRef(0);
|
|
2874
|
+
reactExports.useEffect(() => {
|
|
2875
|
+
return () => {
|
|
2876
|
+
if (rafRef.current)
|
|
2877
|
+
cancelAnimationFrame(rafRef.current);
|
|
2878
|
+
};
|
|
2879
|
+
}, []);
|
|
2880
|
+
reactExports.useEffect(() => {
|
|
2881
|
+
if (!isDragging)
|
|
2882
|
+
return;
|
|
2883
|
+
const previous = document.body.style.userSelect;
|
|
2884
|
+
document.body.style.userSelect = "none";
|
|
2885
|
+
return () => {
|
|
2886
|
+
document.body.style.userSelect = previous;
|
|
2887
|
+
};
|
|
2888
|
+
}, [isDragging]);
|
|
2889
|
+
const stopDrag = () => {
|
|
2890
|
+
pointerIdRef.current = null;
|
|
2891
|
+
setIsDragging(false);
|
|
2892
|
+
if (rafRef.current) {
|
|
2893
|
+
cancelAnimationFrame(rafRef.current);
|
|
2894
|
+
rafRef.current = null;
|
|
2895
|
+
if (movedRef.current)
|
|
2896
|
+
onWidthChange(pendingWidthRef.current);
|
|
2897
|
+
}
|
|
2898
|
+
if (movedRef.current) {
|
|
2899
|
+
movedRef.current = false;
|
|
2900
|
+
lastDragEndAtRef.current = performance.now();
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
const handlePointerDown = (e) => {
|
|
2904
|
+
if (pointerIdRef.current !== null)
|
|
2905
|
+
return;
|
|
2906
|
+
const el = element.current;
|
|
2907
|
+
if (!el)
|
|
2908
|
+
return;
|
|
2909
|
+
if (e.pointerType === "mouse" && e.button !== 0)
|
|
2910
|
+
return;
|
|
2911
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2912
|
+
pointerIdRef.current = e.pointerId;
|
|
2913
|
+
startXRef.current = e.clientX;
|
|
2914
|
+
startWidthRef.current = el.offsetWidth;
|
|
2915
|
+
movedRef.current = false;
|
|
2916
|
+
setIsDragging(true);
|
|
2917
|
+
};
|
|
2918
|
+
const handlePointerMove = (e) => {
|
|
2919
|
+
if (pointerIdRef.current !== e.pointerId)
|
|
2920
|
+
return;
|
|
2921
|
+
if (Math.abs(e.clientX - startXRef.current) > 4) {
|
|
2922
|
+
movedRef.current = true;
|
|
2923
|
+
}
|
|
2924
|
+
const delta = position === "left" ? startXRef.current - e.clientX : e.clientX - startXRef.current;
|
|
2925
|
+
pendingWidthRef.current = startWidthRef.current + delta;
|
|
2926
|
+
if (!rafRef.current) {
|
|
2927
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
2928
|
+
rafRef.current = null;
|
|
2929
|
+
onWidthChange(pendingWidthRef.current);
|
|
2930
|
+
});
|
|
2931
|
+
}
|
|
2932
|
+
};
|
|
2933
|
+
const handlePointerEnd = (e) => {
|
|
2934
|
+
if (pointerIdRef.current !== e.pointerId)
|
|
2935
|
+
return;
|
|
2936
|
+
stopDrag();
|
|
2937
|
+
};
|
|
2938
|
+
const handleLostPointerCapture = (e) => {
|
|
2939
|
+
if (pointerIdRef.current !== null && e.pointerId !== pointerIdRef.current) {
|
|
2940
|
+
return;
|
|
2941
|
+
}
|
|
2942
|
+
stopDrag();
|
|
2943
|
+
};
|
|
2944
|
+
const handleDoubleClick = () => {
|
|
2945
|
+
if (movedRef.current || performance.now() - lastDragEndAtRef.current < 500) {
|
|
2946
|
+
return;
|
|
2947
|
+
}
|
|
2948
|
+
onReset == null ? void 0 : onReset();
|
|
2949
|
+
};
|
|
2950
|
+
const handleKeyDown = (e) => {
|
|
2951
|
+
const el = element.current;
|
|
2952
|
+
if (!el)
|
|
2953
|
+
return;
|
|
2954
|
+
const step = e.shiftKey ? 64 : 16;
|
|
2955
|
+
const grow = position === "left" ? 1 : -1;
|
|
2956
|
+
let next = null;
|
|
2957
|
+
if (e.key === "ArrowLeft") {
|
|
2958
|
+
next = el.offsetWidth + grow * step;
|
|
2959
|
+
} else if (e.key === "ArrowRight") {
|
|
2960
|
+
next = el.offsetWidth - grow * step;
|
|
2961
|
+
} else if (e.key === "Home" && ariaValueMin !== void 0) {
|
|
2962
|
+
next = ariaValueMin;
|
|
2963
|
+
} else if (e.key === "End" && ariaValueMax !== void 0) {
|
|
2964
|
+
next = ariaValueMax;
|
|
2965
|
+
}
|
|
2966
|
+
if (next === null)
|
|
2967
|
+
return;
|
|
2968
|
+
e.preventDefault();
|
|
2969
|
+
onWidthChange(next);
|
|
2970
|
+
};
|
|
2971
|
+
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") }) });
|
|
2972
|
+
}
|
|
2973
|
+
function useElementWidth(ref, enabled = true) {
|
|
2974
|
+
const [width, setWidth] = reactExports.useState(0);
|
|
2975
|
+
reactExports.useLayoutEffect(() => {
|
|
2976
|
+
if (!enabled)
|
|
2977
|
+
return;
|
|
2978
|
+
const el = ref.current;
|
|
2979
|
+
if (!el)
|
|
2980
|
+
return;
|
|
2981
|
+
setWidth(Math.round(el.getBoundingClientRect().width));
|
|
2982
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
2983
|
+
setWidth(Math.round((entry == null ? void 0 : entry.contentRect.width) ?? 0));
|
|
2984
|
+
});
|
|
2985
|
+
observer.observe(el);
|
|
2986
|
+
return () => observer.disconnect();
|
|
2987
|
+
}, [ref, enabled]);
|
|
2988
|
+
return width;
|
|
2989
|
+
}
|
|
2990
|
+
const DETAIL_PANEL_ID = "trace-detail-panel";
|
|
2991
|
+
function useSelectedSpanInfo() {
|
|
2992
|
+
const { activeSpan } = useActiveSpan();
|
|
2993
|
+
const sidebar = useSidebarData();
|
|
2994
|
+
return reactExports.useMemo(() => {
|
|
2995
|
+
var _a, _b;
|
|
2996
|
+
if (!activeSpan)
|
|
2997
|
+
return null;
|
|
2998
|
+
const resource = (_a = activeSpan.attributes) == null ? void 0 : _a.resource;
|
|
2999
|
+
const rawEvents = filterSpanRawEvents(sidebar.events, resource, activeSpan.spanId);
|
|
3000
|
+
return {
|
|
3001
|
+
data: (_b = activeSpan.attributes) == null ? void 0 : _b.data,
|
|
3002
|
+
resource,
|
|
3003
|
+
spanId: activeSpan.spanId,
|
|
3004
|
+
rawEvents
|
|
3005
|
+
};
|
|
3006
|
+
}, [activeSpan, sidebar]);
|
|
3007
|
+
}
|
|
3008
|
+
function TraceDetailPanel({ containerRef, onNavigateToSpan, onClose }) {
|
|
3009
|
+
const { activeSpan, activeSpanId, spans } = useActiveSpan();
|
|
3010
|
+
const sidebar = useSidebarData();
|
|
3011
|
+
const selectedSpan = useSelectedSpanInfo();
|
|
3012
|
+
const isOpen = Boolean(activeSpan);
|
|
3013
|
+
const [storedWidth, setStoredWidth] = reactExports.useState(() => readStoredPanelWidth());
|
|
3014
|
+
const containerWidth = useElementWidth(containerRef, isOpen);
|
|
3015
|
+
const asideRef = reactExports.useRef(null);
|
|
3016
|
+
const handleResize = reactExports.useCallback((next) => {
|
|
3017
|
+
const clamped = clampPanelWidth(next, containerWidth);
|
|
3018
|
+
setStoredWidth(clamped);
|
|
3019
|
+
writeStoredPanelWidth(clamped);
|
|
3020
|
+
}, [containerWidth]);
|
|
3021
|
+
const panelWidth = clampPanelWidth(storedWidth, containerWidth);
|
|
3022
|
+
const panelMaxWidth = Math.max(PANEL_MIN_WIDTH, computeMaxPanelWidth(containerWidth));
|
|
3023
|
+
const { prevSpanId, nextSpanId } = reactExports.useMemo(() => {
|
|
3024
|
+
var _a, _b;
|
|
3025
|
+
if (!activeSpanId)
|
|
3026
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3027
|
+
const i = spans.findIndex((s) => s.spanId === activeSpanId);
|
|
3028
|
+
if (i === -1)
|
|
3029
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3030
|
+
return {
|
|
3031
|
+
prevSpanId: ((_a = spans[i - 1]) == null ? void 0 : _a.spanId) ?? null,
|
|
3032
|
+
nextSpanId: ((_b = spans[i + 1]) == null ? void 0 : _b.spanId) ?? null
|
|
3033
|
+
};
|
|
3034
|
+
}, [activeSpanId, spans]);
|
|
3035
|
+
const handleSelectPrev = reactExports.useCallback(() => {
|
|
3036
|
+
if (prevSpanId)
|
|
3037
|
+
onNavigateToSpan(prevSpanId);
|
|
3038
|
+
}, [prevSpanId, onNavigateToSpan]);
|
|
3039
|
+
const handleSelectNext = reactExports.useCallback(() => {
|
|
3040
|
+
if (nextSpanId)
|
|
3041
|
+
onNavigateToSpan(nextSpanId);
|
|
3042
|
+
}, [nextSpanId, onNavigateToSpan]);
|
|
3043
|
+
reactExports.useEffect(() => {
|
|
3044
|
+
if (!isOpen)
|
|
3045
|
+
return;
|
|
3046
|
+
const onKeyDown = (e) => {
|
|
3047
|
+
if (e.key !== "j" && e.key !== "k" && e.key !== "ArrowDown" && e.key !== "ArrowUp") {
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
3050
|
+
const target = e.target;
|
|
3051
|
+
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || (target == null ? void 0 : target.isContentEditable)) {
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
const targetId = e.key === "k" || e.key === "ArrowUp" ? prevSpanId : nextSpanId;
|
|
3055
|
+
if (targetId) {
|
|
3056
|
+
e.preventDefault();
|
|
3057
|
+
onNavigateToSpan(targetId);
|
|
3058
|
+
}
|
|
3059
|
+
};
|
|
3060
|
+
window.addEventListener("keydown", onKeyDown);
|
|
3061
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
3062
|
+
}, [isOpen, prevSpanId, nextSpanId, onNavigateToSpan]);
|
|
3063
|
+
const selectedSpanName = reactExports.useMemo(() => {
|
|
3064
|
+
var _a, _b;
|
|
3065
|
+
if (!(selectedSpan == null ? void 0 : selectedSpan.data))
|
|
3066
|
+
return "Details";
|
|
3067
|
+
const data = selectedSpan.data;
|
|
3068
|
+
if (selectedSpan.resource === "hook") {
|
|
3069
|
+
return data.token ?? data.hookId;
|
|
3070
|
+
}
|
|
3071
|
+
const stepName = data.stepName;
|
|
3072
|
+
const workflowName = data.workflowName;
|
|
3073
|
+
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";
|
|
3074
|
+
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource]);
|
|
3075
|
+
if (!activeSpan)
|
|
3076
|
+
return null;
|
|
3077
|
+
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 }) }) })] });
|
|
3078
|
+
}
|
|
2784
3079
|
const WorkflowIcon = () => {
|
|
2785
3080
|
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" }) });
|
|
2786
3081
|
};
|
|
@@ -2812,10 +3107,8 @@ function getEventStyle(resource, isErrored) {
|
|
|
2812
3107
|
};
|
|
2813
3108
|
}
|
|
2814
3109
|
const EventRow = ({ span, isSelected, isDimmed, onSelectSpan }) => {
|
|
2815
|
-
var _a;
|
|
2816
3110
|
const durationMs = getSpanDurationMs(span);
|
|
2817
|
-
const
|
|
2818
|
-
const isErrored = span.status.code === 2 || workflowStatus === "failed";
|
|
3111
|
+
const isErrored = isSpanErrored(span);
|
|
2819
3112
|
const { icon: Icon, className: tagClassName } = getEventStyle(span.resource, isErrored);
|
|
2820
3113
|
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.jsx("span", { className: cn("shrink-0", tagClassName), children: jsxRuntimeExports.jsx(Icon, { className: "w-4 h-4" }) }), 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) }) })] }) }) });
|
|
2821
3114
|
};
|
|
@@ -2827,22 +3120,20 @@ const EventList = ({ spans, activeSpanId, searchResult, onSelectSpan }) => {
|
|
|
2827
3120
|
paddingBottom: (spans.length - end) * ROW_HEIGHT_PX
|
|
2828
3121
|
}, children: spans.slice(start, end).map((span) => jsxRuntimeExports.jsx(EventRow, { span, isSelected: span.spanId === activeSpanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelectSpan }, span.spanId)) });
|
|
2829
3122
|
};
|
|
2830
|
-
|
|
2831
|
-
const MIN_PX = 50;
|
|
2832
|
-
const DEFAULT_START_PX = 340;
|
|
2833
|
-
function SplitPane({ children, className, defaultStartWidth = DEFAULT_START_PX, startHeader, endHeader, scrollContainerRef }) {
|
|
3123
|
+
function SplitPane({ children, className, startHeader, endHeader, scrollContainerRef }) {
|
|
2834
3124
|
const parts = reactExports.Children.toArray(children);
|
|
2835
3125
|
if (parts.length !== 2) {
|
|
2836
3126
|
throw new Error("SplitPane expects exactly two children");
|
|
2837
3127
|
}
|
|
2838
3128
|
const [start, end] = parts;
|
|
2839
|
-
const [startPx, setStartPx] = reactExports.useState(
|
|
3129
|
+
const [startPx, setStartPx] = reactExports.useState(DEFAULT_START_PX);
|
|
2840
3130
|
const [isDragging, setIsDragging] = reactExports.useState(false);
|
|
2841
3131
|
const containerRef = reactExports.useRef(null);
|
|
2842
3132
|
const gutterRef = reactExports.useRef(null);
|
|
2843
3133
|
const rafRef = reactExports.useRef(null);
|
|
2844
|
-
const pendingPx = reactExports.useRef(
|
|
3134
|
+
const pendingPx = reactExports.useRef(DEFAULT_START_PX);
|
|
2845
3135
|
const pointerIdRef = reactExports.useRef(null);
|
|
3136
|
+
const containerWidth = useElementWidth(containerRef);
|
|
2846
3137
|
reactExports.useEffect(() => {
|
|
2847
3138
|
return () => {
|
|
2848
3139
|
if (rafRef.current)
|
|
@@ -2916,13 +3207,10 @@ function SplitPane({ children, className, defaultStartWidth = DEFAULT_START_PX,
|
|
|
2916
3207
|
rafRef.current = null;
|
|
2917
3208
|
}
|
|
2918
3209
|
};
|
|
2919
|
-
const
|
|
2920
|
-
const
|
|
3210
|
+
const effectiveStartPx = containerWidth > 0 ? Math.max(MIN_PX, Math.min(containerWidth - MIN_PX - GUTTER_PX, startPx)) : startPx;
|
|
3211
|
+
const colTemplate = paneColTemplate(effectiveStartPx);
|
|
2921
3212
|
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 }) });
|
|
2922
|
-
|
|
2923
|
-
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: setContainerRef, className: cn("grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", isDragging && "select-none"), style: { gridTemplateColumns: colTemplate }, children: [start, gutter, end] })] });
|
|
2924
|
-
}
|
|
2925
|
-
return jsxRuntimeExports.jsxs("div", { ref: setContainerRef, 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] });
|
|
3213
|
+
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: setContainerRef, className: cn("grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", isDragging && "select-none"), style: { gridTemplateColumns: colTemplate }, children: [start, gutter, end] })] });
|
|
2926
3214
|
}
|
|
2927
3215
|
const hint = "_hint_1dmsq_3";
|
|
2928
3216
|
const styles = {
|
|
@@ -3029,33 +3317,15 @@ function useAnimatedViewport(initial) {
|
|
|
3029
3317
|
reactExports.useEffect(() => cancel, [cancel]);
|
|
3030
3318
|
return { viewport, setViewport, animateTo };
|
|
3031
3319
|
}
|
|
3032
|
-
function useSelectedSpanInfo() {
|
|
3033
|
-
const { activeSpan } = useActiveSpan();
|
|
3034
|
-
const sidebar = useSidebarData();
|
|
3035
|
-
return reactExports.useMemo(() => {
|
|
3036
|
-
var _a, _b;
|
|
3037
|
-
if (!activeSpan)
|
|
3038
|
-
return null;
|
|
3039
|
-
const resource = (_a = activeSpan.attributes) == null ? void 0 : _a.resource;
|
|
3040
|
-
const rawEvents = filterSpanRawEvents(sidebar.events, resource, activeSpan.spanId);
|
|
3041
|
-
return {
|
|
3042
|
-
data: (_b = activeSpan.attributes) == null ? void 0 : _b.data,
|
|
3043
|
-
resource,
|
|
3044
|
-
spanId: activeSpan.spanId,
|
|
3045
|
-
rawEvents
|
|
3046
|
-
};
|
|
3047
|
-
}, [activeSpan, sidebar]);
|
|
3048
|
-
}
|
|
3049
3320
|
function NewTraceViewer$1({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
3050
3321
|
return jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 300, children: jsxRuntimeExports.jsx(ActiveSpanProvider, { spans: trace.spans, children: jsxRuntimeExports.jsx(NewTraceViewerContent, { trace, onLoadMore, hasMore, isLoadingMore }) }) });
|
|
3051
3322
|
}
|
|
3052
3323
|
function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
3053
|
-
const {
|
|
3054
|
-
const sidebar = useSidebarData();
|
|
3055
|
-
const selectedSpan = useSelectedSpanInfo();
|
|
3324
|
+
const { activeSpanId, setActiveSpan, clearActiveSpan } = useActiveSpan();
|
|
3056
3325
|
const reducedMotion = useReducedMotion();
|
|
3057
3326
|
const [searchQuery, setSearchQuery] = reactExports.useState("");
|
|
3058
3327
|
const deferredSearchQuery = reactExports.useDeferredValue(searchQuery);
|
|
3328
|
+
const paneRootRef = reactExports.useRef(null);
|
|
3059
3329
|
const searchResult = reactExports.useMemo(() => searchSpans(trace.spans, deferredSearchQuery), [trace.spans, deferredSearchQuery]);
|
|
3060
3330
|
const root = reactExports.useMemo(() => computeRootBounds(trace.spans), [trace.spans]);
|
|
3061
3331
|
const scrollContainerRef = reactExports.useRef(null);
|
|
@@ -3095,47 +3365,30 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3095
3365
|
const resetZoom = reactExports.useCallback(() => {
|
|
3096
3366
|
animateTo({ start: root.startTime, end: root.startTime + root.duration });
|
|
3097
3367
|
}, [animateTo, root.startTime, root.duration]);
|
|
3368
|
+
const clampToRoot = reactExports.useCallback((next) => clampViewportToRoot(next, root.startTime, root.endTime, MIN_VIEWPORT_MS), [root.startTime, root.endTime]);
|
|
3098
3369
|
const handleRevealTime = reactExports.useCallback((timeMs) => {
|
|
3099
|
-
const rootS = root.startTime;
|
|
3100
|
-
const rootE = root.startTime + root.duration;
|
|
3101
3370
|
const { start, end } = viewportRef.current;
|
|
3102
3371
|
const duration = end - start;
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
}
|
|
3109
|
-
if (newEnd > rootE) {
|
|
3110
|
-
newEnd = rootE;
|
|
3111
|
-
newStart = Math.max(rootS, rootE - duration);
|
|
3112
|
-
}
|
|
3113
|
-
animateTo({ start: newStart, end: newEnd });
|
|
3114
|
-
}, [animateTo, root.startTime, root.duration]);
|
|
3372
|
+
animateTo(clampToRoot({
|
|
3373
|
+
start: timeMs - duration / 2,
|
|
3374
|
+
end: timeMs + duration / 2
|
|
3375
|
+
}));
|
|
3376
|
+
}, [animateTo, clampToRoot]);
|
|
3115
3377
|
const ZOOM_FACTOR = 0.5;
|
|
3116
3378
|
const zoomBy = reactExports.useCallback((factor) => {
|
|
3117
|
-
const rootS = root.startTime;
|
|
3118
|
-
const rootE = root.startTime + root.duration;
|
|
3119
|
-
const rootD = root.duration;
|
|
3120
3379
|
setViewport((prev) => {
|
|
3121
|
-
const prevDuration = prev.end - prev.start;
|
|
3122
3380
|
const center = (prev.start + prev.end) / 2;
|
|
3123
|
-
const newDuration = Math.max(MIN_VIEWPORT_MS,
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
newEnd = rootS + newDuration;
|
|
3129
|
-
}
|
|
3130
|
-
if (newEnd > rootE) {
|
|
3131
|
-
newEnd = rootE;
|
|
3132
|
-
newStart = Math.max(rootS, rootE - newDuration);
|
|
3133
|
-
}
|
|
3134
|
-
return { start: newStart, end: newEnd };
|
|
3381
|
+
const newDuration = Math.max(MIN_VIEWPORT_MS, (prev.end - prev.start) * factor);
|
|
3382
|
+
return clampToRoot({
|
|
3383
|
+
start: center - newDuration / 2,
|
|
3384
|
+
end: center + newDuration / 2
|
|
3385
|
+
});
|
|
3135
3386
|
});
|
|
3136
|
-
}, [setViewport,
|
|
3387
|
+
}, [setViewport, clampToRoot]);
|
|
3137
3388
|
const zoomIn = reactExports.useCallback(() => zoomBy(ZOOM_FACTOR), [zoomBy]);
|
|
3138
3389
|
const zoomOut = reactExports.useCallback(() => zoomBy(1 / ZOOM_FACTOR), [zoomBy]);
|
|
3390
|
+
const isAtMinZoom = viewDuration >= root.duration;
|
|
3391
|
+
const isAtMaxZoom = viewDuration <= MIN_VIEWPORT_MS;
|
|
3139
3392
|
const focusViewportOnSpan = reactExports.useCallback((spanId) => {
|
|
3140
3393
|
const span = trace.spans.find((s) => s.spanId === spanId);
|
|
3141
3394
|
if (!span)
|
|
@@ -3143,11 +3396,8 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3143
3396
|
const spanStart = getHighResInMs(span.startTime);
|
|
3144
3397
|
const spanEnd = getHighResInMs(span.endTime);
|
|
3145
3398
|
const spanDuration = spanEnd - spanStart;
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
const rootD = root.duration;
|
|
3149
|
-
if (spanDuration > rootD * 0.8) {
|
|
3150
|
-
animateTo({ start: rootS, end: rootE });
|
|
3399
|
+
if (spanDuration > root.duration * 0.8) {
|
|
3400
|
+
animateTo({ start: root.startTime, end: root.endTime });
|
|
3151
3401
|
return;
|
|
3152
3402
|
}
|
|
3153
3403
|
const padding = Math.max(spanDuration * 0.2, MIN_VIEWPORT_MS / 2);
|
|
@@ -3158,18 +3408,15 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3158
3408
|
newStart = center - MIN_VIEWPORT_MS / 2;
|
|
3159
3409
|
newEnd = center + MIN_VIEWPORT_MS / 2;
|
|
3160
3410
|
}
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
}
|
|
3171
|
-
animateTo({ start: newStart, end: newEnd });
|
|
3172
|
-
}, [animateTo, trace.spans, root.startTime, root.duration]);
|
|
3411
|
+
animateTo(clampToRoot({ start: newStart, end: newEnd }));
|
|
3412
|
+
}, [
|
|
3413
|
+
animateTo,
|
|
3414
|
+
trace.spans,
|
|
3415
|
+
root.startTime,
|
|
3416
|
+
root.endTime,
|
|
3417
|
+
root.duration,
|
|
3418
|
+
clampToRoot
|
|
3419
|
+
]);
|
|
3173
3420
|
const scrollSpanIntoView = reactExports.useCallback((spanId) => {
|
|
3174
3421
|
var _a;
|
|
3175
3422
|
const index = trace.spans.findIndex((s) => s.spanId === spanId);
|
|
@@ -3218,24 +3465,11 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3218
3465
|
}, [setActiveSpan, scrollSpanIntoView, cancelPendingZoom, focusViewportOnSpan]);
|
|
3219
3466
|
const [altHeld, setAltHeld] = reactExports.useState(false);
|
|
3220
3467
|
reactExports.useEffect(() => {
|
|
3221
|
-
const handleSidebarNavKey = (e) => {
|
|
3222
|
-
const target = e.target;
|
|
3223
|
-
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || (target == null ? void 0 : target.isContentEditable)) {
|
|
3224
|
-
return;
|
|
3225
|
-
}
|
|
3226
|
-
const targetId = e.key === "k" ? prevSpanIdRef.current : nextSpanIdRef.current;
|
|
3227
|
-
if (targetId) {
|
|
3228
|
-
e.preventDefault();
|
|
3229
|
-
navigateToSpanRef.current(targetId);
|
|
3230
|
-
}
|
|
3231
|
-
};
|
|
3232
3468
|
const onKeyDown = (e) => {
|
|
3233
3469
|
if (e.key === "Escape") {
|
|
3234
3470
|
handleClearActiveSpan();
|
|
3235
3471
|
} else if (e.key === "Alt") {
|
|
3236
3472
|
setAltHeld(true);
|
|
3237
|
-
} else if (e.key === "j" || e.key === "k") {
|
|
3238
|
-
handleSidebarNavKey(e);
|
|
3239
3473
|
}
|
|
3240
3474
|
};
|
|
3241
3475
|
const onKeyUp = (e) => {
|
|
@@ -3259,7 +3493,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3259
3493
|
return null;
|
|
3260
3494
|
const absTime = viewport.start + hoverFraction * viewDuration;
|
|
3261
3495
|
const offset = absTime - root.startTime;
|
|
3262
|
-
return { fraction: hoverFraction, label:
|
|
3496
|
+
return { fraction: hoverFraction, label: formatDurationPrecise(offset) };
|
|
3263
3497
|
}, [hoverFraction, viewport.start, viewDuration, root.startTime]);
|
|
3264
3498
|
const handleTimelineMouseMove = reactExports.useCallback((e) => {
|
|
3265
3499
|
const el = timelineRef.current;
|
|
@@ -3277,12 +3511,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3277
3511
|
}, []);
|
|
3278
3512
|
reactExports.useEffect(() => {
|
|
3279
3513
|
const el = timelineRef.current;
|
|
3280
|
-
if (!el)
|
|
3281
|
-
return;
|
|
3282
|
-
const rootS = root.startTime;
|
|
3283
|
-
const rootE = root.startTime + root.duration;
|
|
3284
|
-
const rootD = root.duration;
|
|
3285
|
-
if (rootD <= 0)
|
|
3514
|
+
if (!el || root.duration <= 0)
|
|
3286
3515
|
return;
|
|
3287
3516
|
const onWheel = (e) => {
|
|
3288
3517
|
const isZoomGesture = e.ctrlKey || e.metaKey;
|
|
@@ -3295,97 +3524,38 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
|
|
|
3295
3524
|
if (contentWidth <= 0)
|
|
3296
3525
|
return;
|
|
3297
3526
|
if (isZoomGesture) {
|
|
3298
|
-
let dy = e.deltaY;
|
|
3299
|
-
if (e.deltaMode === 1)
|
|
3300
|
-
dy *= 16;
|
|
3301
3527
|
const cursorFraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
|
|
3302
|
-
const
|
|
3303
|
-
const scaleFactor = 2 ** (dy / (isMouseWheel ? 200 : 60));
|
|
3528
|
+
const scaleFactor = wheelZoomScaleFactor(e);
|
|
3304
3529
|
setViewport((prev) => {
|
|
3305
3530
|
const prevDuration = prev.end - prev.start;
|
|
3306
3531
|
const cursorTime = prev.start + cursorFraction * prevDuration;
|
|
3307
|
-
const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
newEnd = rootS + newDuration;
|
|
3313
|
-
}
|
|
3314
|
-
if (newEnd > rootE) {
|
|
3315
|
-
newEnd = rootE;
|
|
3316
|
-
newStart = Math.max(rootS, rootE - newDuration);
|
|
3317
|
-
}
|
|
3318
|
-
return { start: newStart, end: newEnd };
|
|
3532
|
+
const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(root.duration, prevDuration * scaleFactor));
|
|
3533
|
+
return clampToRoot({
|
|
3534
|
+
start: cursorTime - cursorFraction * newDuration,
|
|
3535
|
+
end: cursorTime + (1 - cursorFraction) * newDuration
|
|
3536
|
+
});
|
|
3319
3537
|
});
|
|
3320
3538
|
} else {
|
|
3321
|
-
|
|
3322
|
-
if (e.deltaMode === 1)
|
|
3323
|
-
dx *= 16;
|
|
3539
|
+
const dx = wheelDeltaToPixels(e.deltaX, e.deltaMode);
|
|
3324
3540
|
setViewport((prev) => {
|
|
3325
|
-
const
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
newStart = rootS;
|
|
3331
|
-
newEnd = rootS + prevDuration;
|
|
3332
|
-
}
|
|
3333
|
-
if (newEnd > rootE) {
|
|
3334
|
-
newEnd = rootE;
|
|
3335
|
-
newStart = Math.max(rootS, rootE - prevDuration);
|
|
3336
|
-
}
|
|
3337
|
-
return { start: newStart, end: newEnd };
|
|
3541
|
+
const panAmount = dx / contentWidth * (prev.end - prev.start);
|
|
3542
|
+
return clampToRoot({
|
|
3543
|
+
start: prev.start + panAmount,
|
|
3544
|
+
end: prev.end + panAmount
|
|
3545
|
+
});
|
|
3338
3546
|
});
|
|
3339
3547
|
}
|
|
3340
3548
|
};
|
|
3341
3549
|
el.addEventListener("wheel", onWheel, { passive: false });
|
|
3342
3550
|
return () => el.removeEventListener("wheel", onWheel);
|
|
3343
|
-
}, [root.
|
|
3344
|
-
|
|
3345
|
-
var _a, _b;
|
|
3346
|
-
if (!(selectedSpan == null ? void 0 : selectedSpan.data))
|
|
3347
|
-
return "Details";
|
|
3348
|
-
const data = selectedSpan.data;
|
|
3349
|
-
if (selectedSpan.resource === "hook") {
|
|
3350
|
-
return data.token ?? data.hookId;
|
|
3351
|
-
}
|
|
3352
|
-
const stepName = data.stepName;
|
|
3353
|
-
const workflowName = data.workflowName;
|
|
3354
|
-
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";
|
|
3355
|
-
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource]);
|
|
3356
|
-
const { prevSpanId, nextSpanId } = reactExports.useMemo(() => {
|
|
3357
|
-
var _a, _b;
|
|
3358
|
-
if (!activeSpanId)
|
|
3359
|
-
return { prevSpanId: null, nextSpanId: null };
|
|
3360
|
-
const i = trace.spans.findIndex((s) => s.spanId === activeSpanId);
|
|
3361
|
-
if (i === -1)
|
|
3362
|
-
return { prevSpanId: null, nextSpanId: null };
|
|
3363
|
-
return {
|
|
3364
|
-
prevSpanId: ((_a = trace.spans[i - 1]) == null ? void 0 : _a.spanId) ?? null,
|
|
3365
|
-
nextSpanId: ((_b = trace.spans[i + 1]) == null ? void 0 : _b.spanId) ?? null
|
|
3366
|
-
};
|
|
3367
|
-
}, [activeSpanId, trace.spans]);
|
|
3368
|
-
const handleSelectPrevSpan = reactExports.useCallback(() => {
|
|
3369
|
-
if (prevSpanId)
|
|
3370
|
-
navigateToSpan(prevSpanId);
|
|
3371
|
-
}, [prevSpanId, navigateToSpan]);
|
|
3372
|
-
const handleSelectNextSpan = reactExports.useCallback(() => {
|
|
3373
|
-
if (nextSpanId)
|
|
3374
|
-
navigateToSpan(nextSpanId);
|
|
3375
|
-
}, [nextSpanId, navigateToSpan]);
|
|
3376
|
-
const prevSpanIdRef = reactExports.useRef(prevSpanId);
|
|
3377
|
-
const nextSpanIdRef = reactExports.useRef(nextSpanId);
|
|
3378
|
-
const navigateToSpanRef = reactExports.useRef(navigateToSpan);
|
|
3379
|
-
prevSpanIdRef.current = prevSpanId;
|
|
3380
|
-
nextSpanIdRef.current = nextSpanId;
|
|
3381
|
-
navigateToSpanRef.current = navigateToSpan;
|
|
3382
|
-
return jsxRuntimeExports.jsxs("div", { "data-pane": "pane-root", "data-has-detail": activeSpan ? "" : void 0, className: "relative grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,360px,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, { 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) => {
|
|
3551
|
+
}, [root.duration, setViewport, clampToRoot]);
|
|
3552
|
+
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: "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) => {
|
|
3383
3553
|
if (e.key === "Escape" && searchQuery) {
|
|
3384
3554
|
e.preventDefault();
|
|
3385
3555
|
e.stopPropagation();
|
|
3386
3556
|
setSearchQuery("");
|
|
3387
3557
|
}
|
|
3388
|
-
}, 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", "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-base 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-sm text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsx("div", { ref: timelineRef, className: "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, hoverFraction, altHeld }) })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] 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, "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,
|
|
3558
|
+
}, 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", "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-base 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-sm 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: "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, hoverFraction, altHeld }) })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] 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 }), jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace.spans.length > 1, reducedMotion })] });
|
|
3389
3559
|
}
|
|
3390
3560
|
const NewTraceViewer = ({ run, events, sidebarData, onLoadMore, hasMore, isLoadingMore, loading = false }) => {
|
|
3391
3561
|
const trace = reactExports.useMemo(() => {
|
|
@@ -3430,7 +3600,7 @@ async function fetchResourceWithCorrelationId(env, resource, resourceId, options
|
|
|
3430
3600
|
async function fetchSpanDetailResource(env, selection, options = {}) {
|
|
3431
3601
|
const { resource, resourceId, runId } = selection;
|
|
3432
3602
|
const { encryptionKey } = options;
|
|
3433
|
-
const hydrate = async (value) =>
|
|
3603
|
+
const hydrate = async (value) => hydrateResourceIOAsync(value, encryptionKey);
|
|
3434
3604
|
if (resource === "hook") {
|
|
3435
3605
|
const result = await unwrapOrThrow(fetchHook(env, resourceId, "all"));
|
|
3436
3606
|
return hydrate(result);
|
|
@@ -3445,11 +3615,8 @@ async function fetchSpanDetailResource(env, selection, options = {}) {
|
|
|
3445
3615
|
const result = await unwrapOrThrow(
|
|
3446
3616
|
fetchEvents(env, runId, { sortOrder: "asc", limit: 1e3, withData: true })
|
|
3447
3617
|
);
|
|
3448
|
-
const allEvents = result.data.map(
|
|
3449
|
-
hydrateResourceIO
|
|
3450
|
-
);
|
|
3451
3618
|
const waitEvents = await Promise.all(
|
|
3452
|
-
|
|
3619
|
+
result.data.filter((e) => e.correlationId === resourceId).map(hydrate)
|
|
3453
3620
|
);
|
|
3454
3621
|
const data2 = waitEventsToWaitEntity(waitEvents);
|
|
3455
3622
|
if (data2 === null) {
|
|
@@ -4895,14 +5062,8 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4895
5062
|
const encryptionKeyRef = reactExports.useRef(encryptionKey);
|
|
4896
5063
|
encryptionKeyRef.current = encryptionKey;
|
|
4897
5064
|
const hydrateEvents = reactExports.useCallback(async (rawEvents) => {
|
|
4898
|
-
const hydrated = rawEvents.map(hydrateResourceIO);
|
|
4899
5065
|
const key = encryptionKeyRef.current;
|
|
4900
|
-
|
|
4901
|
-
return Promise.all(
|
|
4902
|
-
hydrated.map((ev) => hydrateResourceIOWithKey(ev, key))
|
|
4903
|
-
);
|
|
4904
|
-
}
|
|
4905
|
-
return hydrated;
|
|
5066
|
+
return Promise.all(rawEvents.map((ev) => hydrateResourceIOAsync(ev, key)));
|
|
4906
5067
|
}, []);
|
|
4907
5068
|
const fetchInitial = reactExports.useCallback(async () => {
|
|
4908
5069
|
if (isFetchingRef.current) return;
|
|
@@ -4940,7 +5101,7 @@ function useEventsListData(env, runId, options = {}) {
|
|
|
4940
5101
|
reactExports.useEffect(() => {
|
|
4941
5102
|
if (!encryptionKey || events.length === 0) return;
|
|
4942
5103
|
let cancelled = false;
|
|
4943
|
-
Promise.all(events.map((ev) =>
|
|
5104
|
+
Promise.all(events.map((ev) => hydrateResourceIOAsync(ev, encryptionKey))).then((decrypted) => {
|
|
4944
5105
|
if (!cancelled) setEvents(decrypted);
|
|
4945
5106
|
}).catch(() => {
|
|
4946
5107
|
});
|
|
@@ -5343,7 +5504,6 @@ function LiveStatus({ hasError, errorMessage }) {
|
|
|
5343
5504
|
});
|
|
5344
5505
|
function RunDetailView({
|
|
5345
5506
|
runId,
|
|
5346
|
-
// TODO: This should open the right sidebar within the trace viewer
|
|
5347
5507
|
selectedId: _selectedId
|
|
5348
5508
|
}) {
|
|
5349
5509
|
var _a;
|
|
@@ -5421,7 +5581,10 @@ function RunDetailView({
|
|
|
5421
5581
|
if (error2) {
|
|
5422
5582
|
throw error2;
|
|
5423
5583
|
}
|
|
5424
|
-
const fullEvent =
|
|
5584
|
+
const fullEvent = await hydrateResourceIOAsync(
|
|
5585
|
+
result,
|
|
5586
|
+
encryptionKeyRef.current ?? void 0
|
|
5587
|
+
);
|
|
5425
5588
|
if ("eventData" in fullEvent) {
|
|
5426
5589
|
return fullEvent.eventData;
|
|
5427
5590
|
}
|
|
@@ -5437,7 +5600,10 @@ function RunDetailView({
|
|
|
5437
5600
|
if (error2) {
|
|
5438
5601
|
throw error2;
|
|
5439
5602
|
}
|
|
5440
|
-
const fullEvent =
|
|
5603
|
+
const fullEvent = await hydrateResourceIOAsync(
|
|
5604
|
+
result,
|
|
5605
|
+
encryptionKeyRef.current ?? void 0
|
|
5606
|
+
);
|
|
5441
5607
|
if ("eventData" in fullEvent) {
|
|
5442
5608
|
return fullEvent.eventData;
|
|
5443
5609
|
}
|
|
@@ -5586,8 +5752,8 @@ function RunDetailView({
|
|
|
5586
5752
|
if (error && !runData) {
|
|
5587
5753
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { variant: "destructive", className: "m-4", children: [
|
|
5588
5754
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
|
|
5589
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Error loading workflow run" }),
|
|
5590
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: error
|
|
5755
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: getErrorTitle(error, "Error loading workflow run") }),
|
|
5756
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: getErrorMessage(error) })
|
|
5591
5757
|
] });
|
|
5592
5758
|
}
|
|
5593
5759
|
const workflowName = (_a = parseWorkflowName(run.workflowName)) == null ? void 0 : _a.shortName;
|