@workflow/web 5.0.0-beta.7 → 5.0.0-beta.9
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/{highlighted-body-B3W2YXNL-Cq4feDhL.js → highlighted-body-B3W2YXNL-ijzNrESJ.js} +1 -1
- package/build/client/assets/{home-B-DWbULo.js → home-MRChHR_P.js} +8 -16
- package/build/client/assets/{manifest-21016363.js → manifest-b100514d.js} +1 -1
- package/build/client/assets/{mermaid-3ZIDBTTL-PK-k2mDG.js → mermaid-3ZIDBTTL-3cOa-aZ5.js} +305 -123
- package/build/client/assets/{root-DDT0W3fG.js → root-3uuTxUQN.js} +1 -1
- package/build/client/assets/root-BYtlAgHl.css +1 -0
- package/build/client/assets/{run-detail-COyTZwjr.js → run-detail-8qGjUNCj.js} +969 -886
- package/build/client/assets/server-build-ByHD2s6b.css +1 -0
- package/build/client/assets/{workflow-graph-viewer-CVUKAMV1.js → workflow-graph-viewer-DaYMiBT9.js} +50 -41
- package/build/server/assets/{app-CASBD2Jz.js → app-BEgkHdDF.js} +1 -1
- package/build/server/assets/{highlighted-body-B3W2YXNL-DtYGrm0G.js → highlighted-body-B3W2YXNL-B4fAdNsB.js} +2 -2
- package/build/server/assets/index-DltGJ3CV.js +89 -0
- package/build/server/assets/{mermaid-3ZIDBTTL-D37Y2lwn.js → mermaid-3ZIDBTTL-C6M7jb0V.js} +2 -2
- package/build/server/assets/{server-build-BZS28Q46.js → server-build-Ctg6FoI8.js} +2017 -1544
- package/build/server/assets/{token-98GkKm4t.js → token-BNjLoJXz.js} +2 -2
- package/build/server/assets/{token-util-CHxt50WW.js → token-util-DwTdh-aG.js} +2 -2
- package/build/server/index.js +1 -1
- package/package.json +7 -7
- package/build/client/assets/root-B527kgKt.css +0 -1
- package/build/client/assets/server-build-BUmla00D.css +0 -1
- package/build/server/assets/index-B_Gtun0B.js +0 -80
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as jsxRuntimeExports, r as reactExports, f as reactDomExports, D as ReactDOM, B as useNavigate, C as useSearchParams, A as Link, w as withComponentProps, H as useParams } from "./index-BsV8i_Jn.js";
|
|
2
|
-
import {
|
|
3
|
-
import { c as createLucideIcon, M as Spinner,
|
|
2
|
+
import { q as Check, O as Copy, C as CircleAlert, Q as parseStepName, B as parseWorkflowName, j as ChevronRight, o as ChevronDown, U as ErrorCard, Z as Zap, S as Send, R as ResolveHookModal, V as Circle, X, p as ChevronUp, N as ErrorBoundary, I as unwrapServerActionResult, u as unwrapOrThrow, W as WorkflowWebAPIError, Y as useEscapeKeydown, t as composeEventHandlers, _ as useCallbackRef, $ as useLayoutEffect2, s as useControllableState, a0 as useId, a1 as createContext2, v as Presence, x as createContextScope, l as hideOthers, m as ReactRemoveScroll, a2 as useFocusGuards, a3 as LAYOUT, a4 as wakeUpRun, r as resumeHook, A as Alert, c as AlertTitle, d as AlertDescription, a as Skeleton$1, a5 as RunActionsButtons, F as StatusBadge, e as CopyableText, b as RelativeTime, T as Tabs, K as TabsList, L as TabsTrigger, M as TabsContent, y as cancelRun, a6 as recreateRun } from "./workflow-graph-viewer-DaYMiBT9.js";
|
|
3
|
+
import { c as createLucideIcon, M as Spinner, N as cn, O as Skeleton, U as DecryptClickContext, Y as Yr, W as isEncryptedMarker, X as formatDuration, Z as DataInspector, _ as _r, $ as Button, a0 as Lock, h as useToast, a1 as RunClickContext, a2 as StreamClickContext, a3 as isExpiredMarker, a4 as isDoStreamStep, a5 as extractConversation, a6 as hasEncryptedFields, a7 as EVENT_DATA_REF_FIELDS, a8 as useSidebarDataOptional, a9 as clsx, G as cva, aa as isSpanDimmedBySearch, ab as getSpanDurationMs, ac as getHighResInMs, ad as ActiveSpanProvider, ae as useActiveSpan, af as searchSpans, ag as computeRootBounds, ah as computeTimeMarkers, ai as TIMELINE_PADDING_PX, aj as Timeline, ak as TimelineHeader, al as SidebarDataProvider, am as hydrateResourceIOWithKey, an as hydrateResourceIO, ao as fetchHook, l as fetchEvents, F as fetchRun, ap as fetchStep, aq as fetchStreams, ar as Slot, E as useComposedRefs, as as Slottable, d as cn$1, at as buttonVariants, au as isEncryptedData, av as hydrateData, aw as getWebRevivers, T as Tooltip, a as TooltipTrigger, b as TooltipContent, ax as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, ay as fetchEvent, az as getEncryptionKeyForRun, t as toast, L as LoaderCircle, aA as StreamViewer } from "./mermaid-3ZIDBTTL-3cOa-aZ5.js";
|
|
4
4
|
import { decrypt, importKey } from "./encryption-C69WMRfh.js";
|
|
5
5
|
import "./index-Byi8AWfe.js";
|
|
6
6
|
/**
|
|
@@ -81,6 +81,27 @@ const STYLES$2 = `.wf-decrypt-btn{appearance:none;-webkit-appearance:none;border
|
|
|
81
81
|
function DecryptButton({ decrypted = false, loading = false, onClick }) {
|
|
82
82
|
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"] })] });
|
|
83
83
|
}
|
|
84
|
+
function CopyButton({ copyText, ariaLabel, className }) {
|
|
85
|
+
const [copied, setCopied] = reactExports.useState(false);
|
|
86
|
+
const timeoutRef = reactExports.useRef(null);
|
|
87
|
+
reactExports.useEffect(() => {
|
|
88
|
+
return () => {
|
|
89
|
+
if (timeoutRef.current) {
|
|
90
|
+
clearTimeout(timeoutRef.current);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}, []);
|
|
94
|
+
return jsxRuntimeExports.jsx("button", { type: "button", "aria-label": ariaLabel, className: cn("cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-0 p-1 m-0", className), onClick: (e) => {
|
|
95
|
+
e.stopPropagation();
|
|
96
|
+
if (timeoutRef.current) {
|
|
97
|
+
clearTimeout(timeoutRef.current);
|
|
98
|
+
}
|
|
99
|
+
void navigator.clipboard.writeText(copyText).then(() => {
|
|
100
|
+
setCopied(true);
|
|
101
|
+
timeoutRef.current = setTimeout(() => setCopied(false), 1e3);
|
|
102
|
+
});
|
|
103
|
+
}, 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" }) })] }) });
|
|
104
|
+
}
|
|
84
105
|
function isStructuredErrorWithStack(value) {
|
|
85
106
|
return value != null && typeof value === "object" && "stack" in value && typeof value.stack === "string";
|
|
86
107
|
}
|
|
@@ -89,7 +110,6 @@ function deriveTitle(message) {
|
|
|
89
110
|
return firstLine.trim();
|
|
90
111
|
}
|
|
91
112
|
function ErrorStackBlock({ value }) {
|
|
92
|
-
const toast2 = useToast();
|
|
93
113
|
const stack = value.stack;
|
|
94
114
|
const message = typeof value.message === "string" ? value.message : void 0;
|
|
95
115
|
const title = message ? deriveTitle(message) : void 0;
|
|
@@ -99,17 +119,7 @@ ${stack}` : stack;
|
|
|
99
119
|
return jsxRuntimeExports.jsxs("div", { className: "relative overflow-hidden rounded-md border", style: {
|
|
100
120
|
borderColor: "var(--ds-red-400)",
|
|
101
121
|
background: "var(--ds-red-100)"
|
|
102
|
-
}, children: [jsxRuntimeExports.jsx(
|
|
103
|
-
borderColor: "var(--ds-red-400)",
|
|
104
|
-
background: "var(--ds-red-100)",
|
|
105
|
-
color: "var(--ds-red-900)"
|
|
106
|
-
}, onClick: () => {
|
|
107
|
-
navigator.clipboard.writeText(copyText).then(() => {
|
|
108
|
-
toast2.success("Copied to clipboard");
|
|
109
|
-
}).catch(() => {
|
|
110
|
-
toast2.error("Failed to copy");
|
|
111
|
-
});
|
|
112
|
-
}, children: jsxRuntimeExports.jsx(Copy, { size: 12 }) }), title && jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 pr-10", style: {
|
|
122
|
+
}, 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: {
|
|
113
123
|
color: "var(--ds-red-900)",
|
|
114
124
|
borderBottom: "1px solid var(--ds-red-400)"
|
|
115
125
|
}, children: [jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 shrink-0" }), jsxRuntimeExports.jsx("p", {
|
|
@@ -409,27 +419,34 @@ function buildNameMaps(events, run) {
|
|
|
409
419
|
return { correlationNameMap, workflowName };
|
|
410
420
|
}
|
|
411
421
|
function buildDurationMap(events) {
|
|
422
|
+
const chronological = [...events].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
412
423
|
const createdTimes = /* @__PURE__ */ new Map();
|
|
424
|
+
const firstStartedTimes = /* @__PURE__ */ new Map();
|
|
413
425
|
const startedTimes = /* @__PURE__ */ new Map();
|
|
414
426
|
const durations = /* @__PURE__ */ new Map();
|
|
415
|
-
for (const event of
|
|
427
|
+
for (const event of chronological) {
|
|
416
428
|
const ts = new Date(event.createdAt).getTime();
|
|
417
429
|
const key = event.correlationId ?? "__run__";
|
|
418
430
|
const type = event.eventType;
|
|
419
431
|
if (type === "step_created" || type === "run_created") {
|
|
420
|
-
createdTimes.set(key, ts);
|
|
421
|
-
}
|
|
422
|
-
if (type === "step_started" || type === "run_started" || type === "workflow_started") {
|
|
423
|
-
startedTimes.set(key, ts);
|
|
424
432
|
if (!createdTimes.has(key)) {
|
|
425
433
|
createdTimes.set(key, ts);
|
|
426
434
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
435
|
+
}
|
|
436
|
+
if (type === "step_started" || type === "run_started" || type === "workflow_started") {
|
|
437
|
+
startedTimes.set(key, ts);
|
|
438
|
+
if (!firstStartedTimes.has(key)) {
|
|
439
|
+
firstStartedTimes.set(key, ts);
|
|
440
|
+
if (!createdTimes.has(key)) {
|
|
441
|
+
createdTimes.set(key, ts);
|
|
442
|
+
}
|
|
443
|
+
const createdAt = createdTimes.get(key);
|
|
444
|
+
const info = durations.get(key) ?? {};
|
|
445
|
+
if (createdAt !== void 0) {
|
|
446
|
+
info.queued = ts - createdAt;
|
|
447
|
+
}
|
|
448
|
+
durations.set(key, info);
|
|
431
449
|
}
|
|
432
|
-
durations.set(key, info);
|
|
433
450
|
}
|
|
434
451
|
if (type === "step_completed" || type === "step_failed" || type === "run_completed" || type === "run_failed" || type === "run_cancelled" || type === "workflow_completed" || type === "workflow_failed" || type === "wait_completed" || type === "hook_disposed") {
|
|
435
452
|
const startedAt = startedTimes.get(key);
|
|
@@ -1380,159 +1397,447 @@ function buildTrace(run, events, now) {
|
|
|
1380
1397
|
knownDurationMs: Math.max(0, knownDurationMs)
|
|
1381
1398
|
};
|
|
1382
1399
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1400
|
+
const ELLIPSIS = "...";
|
|
1401
|
+
const MIN_START = 3;
|
|
1402
|
+
const MIN_END = 3;
|
|
1403
|
+
const MIN_KEPT = MIN_START + MIN_END;
|
|
1404
|
+
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
1405
|
+
function toGraphemes(text) {
|
|
1406
|
+
if (graphemeSegmenter) {
|
|
1407
|
+
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
1386
1408
|
}
|
|
1387
|
-
return
|
|
1409
|
+
return Array.from(text);
|
|
1388
1410
|
}
|
|
1389
|
-
function
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
}
|
|
1411
|
+
function buildCandidate(graphemes, kept) {
|
|
1412
|
+
if (kept <= 0) {
|
|
1413
|
+
return {
|
|
1414
|
+
prefixText: "",
|
|
1415
|
+
prefixGraphemeCount: 0,
|
|
1416
|
+
suffixText: "",
|
|
1417
|
+
suffixGraphemeCount: 0,
|
|
1418
|
+
text: ELLIPSIS,
|
|
1419
|
+
truncated: true
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
const suffixGraphemeCount = kept >= MIN_KEPT ? Math.max(MIN_END, Math.floor(kept / 2)) : Math.floor(kept / 2);
|
|
1423
|
+
const prefixGraphemeCount = kept - suffixGraphemeCount;
|
|
1424
|
+
const prefixText = graphemes.slice(0, prefixGraphemeCount).join("");
|
|
1425
|
+
const suffixText = suffixGraphemeCount > 0 ? graphemes.slice(-suffixGraphemeCount).join("") : "";
|
|
1426
|
+
return {
|
|
1427
|
+
prefixText,
|
|
1428
|
+
prefixGraphemeCount,
|
|
1429
|
+
suffixText,
|
|
1430
|
+
suffixGraphemeCount,
|
|
1431
|
+
text: prefixText + ELLIPSIS + suffixText,
|
|
1432
|
+
truncated: true
|
|
1433
|
+
};
|
|
1400
1434
|
}
|
|
1401
|
-
function
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1435
|
+
function middleTruncate(graphemes, availableWidth, measure, fullWidth) {
|
|
1436
|
+
const fullText = graphemes.join("");
|
|
1437
|
+
const resolvedFullWidth = fullWidth ?? measure(fullText);
|
|
1438
|
+
if (availableWidth <= 0 || graphemes.length === 0) {
|
|
1439
|
+
return {
|
|
1440
|
+
prefixText: fullText,
|
|
1441
|
+
prefixGraphemeCount: graphemes.length,
|
|
1442
|
+
suffixText: "",
|
|
1443
|
+
suffixGraphemeCount: 0,
|
|
1444
|
+
text: fullText,
|
|
1445
|
+
truncated: false
|
|
1446
|
+
};
|
|
1409
1447
|
}
|
|
1410
|
-
if (
|
|
1411
|
-
return
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1448
|
+
if (resolvedFullWidth <= availableWidth) {
|
|
1449
|
+
return {
|
|
1450
|
+
prefixText: fullText,
|
|
1451
|
+
prefixGraphemeCount: graphemes.length,
|
|
1452
|
+
suffixText: "",
|
|
1453
|
+
suffixGraphemeCount: 0,
|
|
1454
|
+
text: fullText,
|
|
1455
|
+
truncated: false
|
|
1456
|
+
};
|
|
1415
1457
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1458
|
+
let lo = 0;
|
|
1459
|
+
let hi = graphemes.length - 1;
|
|
1460
|
+
let best = -1;
|
|
1461
|
+
while (lo <= hi) {
|
|
1462
|
+
const mid = lo + hi >>> 1;
|
|
1463
|
+
const candidate = buildCandidate(graphemes, mid);
|
|
1464
|
+
if (measure(candidate.text) <= availableWidth) {
|
|
1465
|
+
best = mid;
|
|
1466
|
+
lo = mid + 1;
|
|
1467
|
+
} else {
|
|
1468
|
+
hi = mid - 1;
|
|
1469
|
+
}
|
|
1421
1470
|
}
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
};
|
|
1432
|
-
case "assistant":
|
|
1433
|
-
return {
|
|
1434
|
-
bg: "var(--ds-gray-100)",
|
|
1435
|
-
border: "var(--ds-gray-300)",
|
|
1436
|
-
label: "var(--ds-gray-700)"
|
|
1437
|
-
};
|
|
1438
|
-
case "system":
|
|
1439
|
-
return {
|
|
1440
|
-
bg: "var(--ds-amber-100)",
|
|
1441
|
-
border: "var(--ds-amber-300)",
|
|
1442
|
-
label: "var(--ds-amber-700)"
|
|
1443
|
-
};
|
|
1444
|
-
case "tool":
|
|
1445
|
-
return {
|
|
1446
|
-
bg: "var(--ds-green-50)",
|
|
1447
|
-
border: "var(--ds-green-300)",
|
|
1448
|
-
label: "var(--ds-green-700)"
|
|
1449
|
-
};
|
|
1450
|
-
default:
|
|
1451
|
-
return {
|
|
1452
|
-
bg: "var(--ds-gray-100)",
|
|
1453
|
-
border: "var(--ds-gray-300)",
|
|
1454
|
-
label: "var(--ds-gray-700)"
|
|
1455
|
-
};
|
|
1471
|
+
if (best === -1) {
|
|
1472
|
+
return {
|
|
1473
|
+
prefixText: "",
|
|
1474
|
+
prefixGraphemeCount: 0,
|
|
1475
|
+
suffixText: "",
|
|
1476
|
+
suffixGraphemeCount: 0,
|
|
1477
|
+
text: "",
|
|
1478
|
+
truncated: true
|
|
1479
|
+
};
|
|
1456
1480
|
}
|
|
1481
|
+
return buildCandidate(graphemes, best);
|
|
1457
1482
|
}
|
|
1458
|
-
function
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
if (Array.isArray(content)) {
|
|
1463
|
-
return content.map((part) => {
|
|
1464
|
-
if (typeof part === "string") {
|
|
1465
|
-
return { type: "text", text: part };
|
|
1466
|
-
}
|
|
1467
|
-
if ((part == null ? void 0 : part.type) === "text") {
|
|
1468
|
-
return { type: "text", text: String(part.text ?? "") };
|
|
1469
|
-
}
|
|
1470
|
-
if ((part == null ? void 0 : part.type) === "tool-call") {
|
|
1471
|
-
return {
|
|
1472
|
-
type: "tool-call",
|
|
1473
|
-
toolName: part.toolName,
|
|
1474
|
-
input: part.input
|
|
1475
|
-
};
|
|
1476
|
-
}
|
|
1477
|
-
if ((part == null ? void 0 : part.type) === "tool-result") {
|
|
1478
|
-
return {
|
|
1479
|
-
type: "tool-result",
|
|
1480
|
-
toolName: part.toolName,
|
|
1481
|
-
output: part.output
|
|
1482
|
-
};
|
|
1483
|
-
}
|
|
1484
|
-
return { type: "text", text: "" };
|
|
1485
|
-
});
|
|
1483
|
+
function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value }) {
|
|
1484
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
1485
|
+
if (selectionStart < 0 || selectionEnd > visibleText.length || selectionStart >= selectionEnd) {
|
|
1486
|
+
return null;
|
|
1486
1487
|
}
|
|
1487
|
-
|
|
1488
|
-
}
|
|
1489
|
-
const serializeForClipboard = (value) => {
|
|
1490
|
-
if (typeof value === "string")
|
|
1488
|
+
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
1491
1489
|
return value;
|
|
1492
|
-
if (typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
1493
|
-
return String(value);
|
|
1494
1490
|
}
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
return
|
|
1491
|
+
const ellipsisStart = prefixText.length;
|
|
1492
|
+
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
1493
|
+
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
1494
|
+
return null;
|
|
1499
1495
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
toast2.success("Copied to clipboard");
|
|
1506
|
-
}).catch(() => {
|
|
1507
|
-
toast2.error("Failed to copy");
|
|
1508
|
-
});
|
|
1509
|
-
}, children: jsxRuntimeExports.jsx(Copy, { size: 12 }) }), jsxRuntimeExports.jsx(DataInspector, { data })] });
|
|
1496
|
+
const originalGraphemes = toGraphemes(value);
|
|
1497
|
+
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
1498
|
+
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
1499
|
+
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
1500
|
+
return originalGraphemes.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount).join("");
|
|
1510
1501
|
}
|
|
1511
|
-
function
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
color: "var(--ds-gray-700)",
|
|
1517
|
-
cursor: "not-allowed",
|
|
1518
|
-
opacity: 0.8
|
|
1519
|
-
}, children: summary });
|
|
1502
|
+
function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value }) {
|
|
1503
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
1504
|
+
const trimmedSelectionText = selectionText.trim();
|
|
1505
|
+
if (!trimmedSelectionText) {
|
|
1506
|
+
return null;
|
|
1520
1507
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1508
|
+
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
1509
|
+
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
1510
|
+
if (trimmedSelectionText === visibleText) {
|
|
1511
|
+
return leading + value + trailing;
|
|
1512
|
+
}
|
|
1513
|
+
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
1514
|
+
return null;
|
|
1515
|
+
}
|
|
1516
|
+
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
1517
|
+
if (selectionStart === -1) {
|
|
1518
|
+
return null;
|
|
1519
|
+
}
|
|
1520
|
+
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
1521
|
+
const mappedText = getMiddleTruncateCopyText({
|
|
1522
|
+
prefixText,
|
|
1523
|
+
selectionEnd,
|
|
1524
|
+
selectionStart,
|
|
1525
|
+
suffixText,
|
|
1526
|
+
value
|
|
1527
|
+
});
|
|
1528
|
+
return mappedText === null ? null : leading + mappedText + trailing;
|
|
1529
|
+
}
|
|
1530
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? reactExports.useEffect : reactExports.useLayoutEffect;
|
|
1531
|
+
function createFullState(value, graphemes) {
|
|
1532
|
+
return {
|
|
1533
|
+
displayText: value,
|
|
1534
|
+
isTruncated: false,
|
|
1535
|
+
prefixGraphemeCount: graphemes.length,
|
|
1536
|
+
prefixText: value,
|
|
1537
|
+
suffixGraphemeCount: 0,
|
|
1538
|
+
suffixText: ""
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
function useMiddleTruncate(value) {
|
|
1542
|
+
const graphemes = reactExports.useMemo(() => toGraphemes(value), [value]);
|
|
1543
|
+
const fullState = reactExports.useMemo(() => createFullState(value, graphemes), [graphemes, value]);
|
|
1544
|
+
const ref = reactExports.useRef(null);
|
|
1545
|
+
const measureRef = reactExports.useRef(null);
|
|
1546
|
+
const [state, setState] = reactExports.useState(() => fullState);
|
|
1547
|
+
const rafRef = reactExports.useRef(0);
|
|
1548
|
+
const updateState = reactExports.useCallback((nextState) => {
|
|
1549
|
+
setState((currentState) => {
|
|
1550
|
+
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) {
|
|
1551
|
+
return currentState;
|
|
1552
|
+
}
|
|
1553
|
+
return nextState;
|
|
1554
|
+
});
|
|
1555
|
+
}, []);
|
|
1556
|
+
const recalculate = reactExports.useCallback(() => {
|
|
1557
|
+
const el = ref.current;
|
|
1558
|
+
const measureEl = measureRef.current;
|
|
1559
|
+
if (!el || !measureEl)
|
|
1560
|
+
return;
|
|
1561
|
+
const available = el.clientWidth;
|
|
1562
|
+
if (available <= 0) {
|
|
1563
|
+
updateState(fullState);
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
const measure = (text) => {
|
|
1567
|
+
measureEl.textContent = text;
|
|
1568
|
+
return measureEl.scrollWidth;
|
|
1569
|
+
};
|
|
1570
|
+
const fullWidth = measure(value);
|
|
1571
|
+
if (fullWidth <= available) {
|
|
1572
|
+
updateState(fullState);
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
const result = middleTruncate(graphemes, available, measure, fullWidth);
|
|
1576
|
+
updateState({
|
|
1577
|
+
displayText: result.text,
|
|
1578
|
+
isTruncated: result.truncated,
|
|
1579
|
+
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
1580
|
+
prefixText: result.prefixText,
|
|
1581
|
+
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
1582
|
+
suffixText: result.suffixText
|
|
1583
|
+
});
|
|
1584
|
+
}, [fullState, graphemes, updateState, value]);
|
|
1585
|
+
useIsomorphicLayoutEffect(() => {
|
|
1586
|
+
recalculate();
|
|
1587
|
+
}, [recalculate]);
|
|
1588
|
+
reactExports.useEffect(() => {
|
|
1589
|
+
var _a;
|
|
1590
|
+
const el = ref.current;
|
|
1591
|
+
if (!el)
|
|
1592
|
+
return;
|
|
1593
|
+
const debouncedRecalc = () => {
|
|
1594
|
+
cancelAnimationFrame(rafRef.current);
|
|
1595
|
+
rafRef.current = requestAnimationFrame(recalculate);
|
|
1596
|
+
};
|
|
1597
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(debouncedRecalc) : null;
|
|
1598
|
+
ro == null ? void 0 : ro.observe(el);
|
|
1599
|
+
window.addEventListener("resize", debouncedRecalc);
|
|
1600
|
+
const onFontsLoaded = () => {
|
|
1601
|
+
debouncedRecalc();
|
|
1602
|
+
};
|
|
1603
|
+
const fontSet = "fonts" in document ? document.fonts : null;
|
|
1604
|
+
(_a = fontSet == null ? void 0 : fontSet.addEventListener) == null ? void 0 : _a.call(fontSet, "loadingdone", onFontsLoaded);
|
|
1605
|
+
return () => {
|
|
1606
|
+
var _a2;
|
|
1607
|
+
ro == null ? void 0 : ro.disconnect();
|
|
1608
|
+
window.removeEventListener("resize", debouncedRecalc);
|
|
1609
|
+
cancelAnimationFrame(rafRef.current);
|
|
1610
|
+
(_a2 = fontSet == null ? void 0 : fontSet.removeEventListener) == null ? void 0 : _a2.call(fontSet, "loadingdone", onFontsLoaded);
|
|
1611
|
+
};
|
|
1612
|
+
}, [recalculate]);
|
|
1613
|
+
return {
|
|
1614
|
+
ref,
|
|
1615
|
+
measureRef,
|
|
1616
|
+
displayText: state.displayText,
|
|
1617
|
+
isTruncated: state.isTruncated,
|
|
1618
|
+
prefixGraphemeCount: state.prefixGraphemeCount,
|
|
1619
|
+
prefixText: state.prefixText,
|
|
1620
|
+
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
1621
|
+
suffixText: state.suffixText
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
function getRangeOffsets(container, range) {
|
|
1625
|
+
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) {
|
|
1626
|
+
return null;
|
|
1627
|
+
}
|
|
1628
|
+
const startRange = document.createRange();
|
|
1629
|
+
startRange.selectNodeContents(container);
|
|
1630
|
+
startRange.setEnd(range.startContainer, range.startOffset);
|
|
1631
|
+
const endRange = document.createRange();
|
|
1632
|
+
endRange.selectNodeContents(container);
|
|
1633
|
+
endRange.setEnd(range.endContainer, range.endOffset);
|
|
1634
|
+
return {
|
|
1635
|
+
end: endRange.toString().length,
|
|
1636
|
+
start: startRange.toString().length
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
function MiddleTruncate({ value, className, onCopy: onCopyProp, ...props }) {
|
|
1640
|
+
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
1641
|
+
const visibleRef = reactExports.useRef(null);
|
|
1642
|
+
const handleCopy = reactExports.useCallback((e) => {
|
|
1643
|
+
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
1644
|
+
if (e.defaultPrevented || !isTruncated)
|
|
1645
|
+
return;
|
|
1646
|
+
const selection = window.getSelection();
|
|
1647
|
+
if (!selection || selection.rangeCount === 0)
|
|
1648
|
+
return;
|
|
1649
|
+
const selectionText = selection.toString();
|
|
1650
|
+
if (!selectionText)
|
|
1651
|
+
return;
|
|
1652
|
+
const range = selection.getRangeAt(0);
|
|
1653
|
+
const visibleEl = visibleRef.current;
|
|
1654
|
+
let copyText = null;
|
|
1655
|
+
if (e.currentTarget.contains(range.startContainer) && e.currentTarget.contains(range.endContainer) && visibleEl) {
|
|
1656
|
+
const offsets = getRangeOffsets(visibleEl, range);
|
|
1657
|
+
if (offsets) {
|
|
1658
|
+
copyText = getMiddleTruncateCopyText({
|
|
1659
|
+
prefixText,
|
|
1660
|
+
selectionEnd: offsets.end,
|
|
1661
|
+
selectionStart: offsets.start,
|
|
1662
|
+
suffixText,
|
|
1663
|
+
value
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
copyText ?? (copyText = getMiddleTruncateCopyTextFromSelectionText({
|
|
1668
|
+
prefixText,
|
|
1669
|
+
selectionText,
|
|
1670
|
+
suffixText,
|
|
1671
|
+
value
|
|
1672
|
+
}));
|
|
1673
|
+
if (copyText === null)
|
|
1674
|
+
return;
|
|
1675
|
+
e.preventDefault();
|
|
1676
|
+
e.clipboardData.setData("text/plain", copyText);
|
|
1677
|
+
}, [onCopyProp, isTruncated, prefixText, suffixText, value]);
|
|
1678
|
+
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 })] });
|
|
1679
|
+
}
|
|
1680
|
+
function ConversationView({ messages }) {
|
|
1681
|
+
if (messages.length === 0) {
|
|
1682
|
+
return jsxRuntimeExports.jsx("div", { className: "text-center py-8 text-[11px]", style: { color: "var(--ds-gray-600)" }, children: "No messages" });
|
|
1683
|
+
}
|
|
1684
|
+
return jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-3 p-3", children: messages.map((message, index) => jsxRuntimeExports.jsx(MessageBubble, { message }, index)) });
|
|
1685
|
+
}
|
|
1686
|
+
function MessageBubble({ message }) {
|
|
1687
|
+
const role = message.role;
|
|
1688
|
+
const parts = parseContent(message.content);
|
|
1689
|
+
const style = getRoleStyle(role);
|
|
1690
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded-md border text-[11px]", style: {
|
|
1691
|
+
backgroundColor: style.bg,
|
|
1692
|
+
borderColor: style.border
|
|
1693
|
+
}, children: [jsxRuntimeExports.jsx("div", { className: "px-2.5 py-1 border-b text-[10px] font-medium uppercase tracking-wide", style: {
|
|
1694
|
+
borderColor: style.border,
|
|
1695
|
+
color: style.label
|
|
1696
|
+
}, children: role }), jsxRuntimeExports.jsx("div", { className: "px-2.5 py-2 space-y-2", children: parts.map((part, i) => jsxRuntimeExports.jsx(ContentPart, { part, role }, i)) })] });
|
|
1697
|
+
}
|
|
1698
|
+
function ContentPart({ part, role }) {
|
|
1699
|
+
if (part.type === "text") {
|
|
1700
|
+
if (!part.text)
|
|
1701
|
+
return null;
|
|
1702
|
+
if (role === "assistant") {
|
|
1703
|
+
return jsxRuntimeExports.jsx("div", { className: "prose prose-sm max-w-none text-[11px] [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", style: { color: "var(--ds-gray-1000)" }, children: jsxRuntimeExports.jsx(_r, { children: part.text }) });
|
|
1704
|
+
}
|
|
1705
|
+
return jsxRuntimeExports.jsx("div", { className: "whitespace-pre-wrap break-words", style: { color: "var(--ds-gray-1000)" }, children: part.text });
|
|
1706
|
+
}
|
|
1707
|
+
if (part.type === "tool-call") {
|
|
1708
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded border px-2 py-1.5", style: {
|
|
1709
|
+
backgroundColor: "var(--ds-purple-100)",
|
|
1710
|
+
borderColor: "var(--ds-purple-300)"
|
|
1711
|
+
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-medium", children: [jsxRuntimeExports.jsx("span", { children: "🔧" }), jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-purple-900)" }, children: part.toolName })] }), part.input != null && jsxRuntimeExports.jsx("div", { className: "mt-1.5 overflow-x-auto p-1.5 rounded", style: { backgroundColor: "var(--ds-gray-100)" }, children: typeof part.input === "string" ? jsxRuntimeExports.jsx("pre", { className: "text-[10px]", style: { color: "var(--ds-gray-800)" }, children: part.input }) : jsxRuntimeExports.jsx(DataInspector, { data: part.input }) })] });
|
|
1712
|
+
}
|
|
1713
|
+
if (part.type === "tool-result") {
|
|
1714
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded border px-2 py-1.5", style: {
|
|
1715
|
+
backgroundColor: "var(--ds-green-100)",
|
|
1716
|
+
borderColor: "var(--ds-green-300)"
|
|
1717
|
+
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-medium", children: [jsxRuntimeExports.jsx("span", { children: "✓" }), jsxRuntimeExports.jsxs("span", { style: { color: "var(--ds-green-900)" }, children: [part.toolName, " result"] })] }), part.output != null && jsxRuntimeExports.jsx("div", { className: "mt-1.5 overflow-x-auto max-h-[200px] overflow-y-auto p-1.5 rounded", style: { backgroundColor: "var(--ds-gray-100)" }, children: typeof part.output === "string" ? jsxRuntimeExports.jsx("pre", { className: "text-[10px]", style: { color: "var(--ds-gray-800)" }, children: part.output }) : jsxRuntimeExports.jsx(DataInspector, { data: part.output, expandLevel: 1 }) })] });
|
|
1718
|
+
}
|
|
1719
|
+
return null;
|
|
1720
|
+
}
|
|
1721
|
+
function getRoleStyle(role) {
|
|
1722
|
+
switch (role) {
|
|
1723
|
+
case "user":
|
|
1724
|
+
return {
|
|
1725
|
+
bg: "var(--ds-blue-100)",
|
|
1726
|
+
border: "var(--ds-blue-300)",
|
|
1727
|
+
label: "var(--ds-blue-700)"
|
|
1728
|
+
};
|
|
1729
|
+
case "assistant":
|
|
1730
|
+
return {
|
|
1731
|
+
bg: "var(--ds-gray-100)",
|
|
1732
|
+
border: "var(--ds-gray-300)",
|
|
1733
|
+
label: "var(--ds-gray-700)"
|
|
1734
|
+
};
|
|
1735
|
+
case "system":
|
|
1736
|
+
return {
|
|
1737
|
+
bg: "var(--ds-amber-100)",
|
|
1738
|
+
border: "var(--ds-amber-300)",
|
|
1739
|
+
label: "var(--ds-amber-700)"
|
|
1740
|
+
};
|
|
1741
|
+
case "tool":
|
|
1742
|
+
return {
|
|
1743
|
+
bg: "var(--ds-green-50)",
|
|
1744
|
+
border: "var(--ds-green-300)",
|
|
1745
|
+
label: "var(--ds-green-700)"
|
|
1746
|
+
};
|
|
1747
|
+
default:
|
|
1748
|
+
return {
|
|
1749
|
+
bg: "var(--ds-gray-100)",
|
|
1750
|
+
border: "var(--ds-gray-300)",
|
|
1751
|
+
label: "var(--ds-gray-700)"
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
function parseContent(content) {
|
|
1756
|
+
if (typeof content === "string") {
|
|
1757
|
+
return [{ type: "text", text: content }];
|
|
1758
|
+
}
|
|
1759
|
+
if (Array.isArray(content)) {
|
|
1760
|
+
return content.map((part) => {
|
|
1761
|
+
if (typeof part === "string") {
|
|
1762
|
+
return { type: "text", text: part };
|
|
1763
|
+
}
|
|
1764
|
+
if ((part == null ? void 0 : part.type) === "text") {
|
|
1765
|
+
return { type: "text", text: String(part.text ?? "") };
|
|
1766
|
+
}
|
|
1767
|
+
if ((part == null ? void 0 : part.type) === "tool-call") {
|
|
1768
|
+
return {
|
|
1769
|
+
type: "tool-call",
|
|
1770
|
+
toolName: part.toolName,
|
|
1771
|
+
input: part.input
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
if ((part == null ? void 0 : part.type) === "tool-result") {
|
|
1775
|
+
return {
|
|
1776
|
+
type: "tool-result",
|
|
1777
|
+
toolName: part.toolName,
|
|
1778
|
+
output: part.output
|
|
1779
|
+
};
|
|
1780
|
+
}
|
|
1781
|
+
return { type: "text", text: "" };
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
return [];
|
|
1785
|
+
}
|
|
1786
|
+
const encryptedPlaceholderPreview = `{
|
|
1787
|
+
"input": "[encrypted]",
|
|
1788
|
+
"result": "[encrypted]"
|
|
1789
|
+
}`;
|
|
1790
|
+
function EncryptedDataBlock() {
|
|
1791
|
+
const ctx = reactExports.useContext(DecryptClickContext);
|
|
1792
|
+
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"] }) })] });
|
|
1793
|
+
}
|
|
1794
|
+
const serializeForClipboard = (value) => {
|
|
1795
|
+
if (typeof value === "string")
|
|
1796
|
+
return value;
|
|
1797
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
1798
|
+
return String(value);
|
|
1799
|
+
}
|
|
1800
|
+
try {
|
|
1801
|
+
return JSON.stringify(value, null, 2);
|
|
1802
|
+
} catch {
|
|
1803
|
+
return String(value);
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
function CopyableDataBlock({ data }) {
|
|
1807
|
+
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 })] });
|
|
1808
|
+
}
|
|
1809
|
+
function DetailCard({ summary, children, onToggle, disabled = false, defaultOpen = false, variant = "section", trailing, summaryClassName, contentClassName }) {
|
|
1810
|
+
const [open, setOpen] = reactExports.useState(defaultOpen);
|
|
1811
|
+
const handleToggle = (e) => {
|
|
1812
|
+
if (e.target !== e.currentTarget)
|
|
1813
|
+
return;
|
|
1814
|
+
const next = e.currentTarget.open;
|
|
1815
|
+
setOpen(next);
|
|
1816
|
+
onToggle == null ? void 0 : onToggle(next);
|
|
1817
|
+
};
|
|
1818
|
+
if (variant === "card") {
|
|
1819
|
+
if (disabled) {
|
|
1820
|
+
return jsxRuntimeExports.jsx("div", { className: cn("list-none px-3 py-4 bg-background-200 [&::-webkit-details-marker]:hidden", summaryClassName), style: { cursor: "not-allowed", opacity: 0.8 }, children: summary });
|
|
1821
|
+
}
|
|
1822
|
+
return jsxRuntimeExports.jsxs("details", { className: "group/card last:border-b border-gray-alpha-400", open, onToggle: handleToggle, children: [jsxRuntimeExports.jsx("summary", { className: cn("list-none cursor-pointer px-3 py-4 border-t border-gray-alpha-400 bg-background-200 hover:bg-gray-100 [&::-webkit-details-marker]:hidden", summaryClassName), children: jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1.5", children: [jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: cn("shrink-0 text-gray-700 group-hover/card:text-gray-1000", open && "rotate-90") }), summary] }) }), jsxRuntimeExports.jsx("div", { className: contentClassName, children })] });
|
|
1823
|
+
}
|
|
1824
|
+
const rowClasses = "flex h-9 items-center gap-2 px-2 -mx-2 text-heading-14 font-medium my-2";
|
|
1825
|
+
if (trailing) {
|
|
1826
|
+
return jsxRuntimeExports.jsx("section", { className: "-mx-4 border-t px-4 border-gray-alpha-400", children: jsxRuntimeExports.jsxs("div", { className: cn(rowClasses, summaryClassName), children: [jsxRuntimeExports.jsx("div", { className: "isolate relative shrink-0 w-3.5 h-3.5 text-gray-700", children: jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" }) }), jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1", children: summary }), jsxRuntimeExports.jsx("div", { className: "shrink-0 pr-1", children: trailing })] }) });
|
|
1827
|
+
}
|
|
1828
|
+
if (disabled) {
|
|
1829
|
+
return jsxRuntimeExports.jsx("section", { className: "-mx-4 border-t px-4 border-gray-alpha-400", children: jsxRuntimeExports.jsx("div", { className: cn(rowClasses, summaryClassName), style: { color: "var(--ds-gray-700)", cursor: "not-allowed" }, children: jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1", children: summary }) }) });
|
|
1830
|
+
}
|
|
1831
|
+
return jsxRuntimeExports.jsx("section", { className: "-mx-4 border-t px-4 border-gray-alpha-400", children: jsxRuntimeExports.jsxs("details", { className: "group", open, onToggle: handleToggle, children: [jsxRuntimeExports.jsxs("summary", { className: cn("group/trigger list-none cursor-pointer rounded hover:bg-gray-alpha-100 [&::-webkit-details-marker]:hidden", rowClasses, summaryClassName), children: [jsxRuntimeExports.jsxs("div", { className: "isolate relative shrink-0 text-gray-700 group-hover/trigger:text-gray-1000 w-3.5 h-3.5", children: [jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 opacity-100 group-open:opacity-0" }), jsxRuntimeExports.jsx(ChevronDown, { size: 14, className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 opacity-0 group-open:opacity-100" })] }), jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1", children: summary })] }), jsxRuntimeExports.jsx("div", { className: cn("mb-3", contentClassName), children })] }) });
|
|
1832
|
+
}
|
|
1833
|
+
function TabButton({ active, onClick, children }) {
|
|
1834
|
+
return jsxRuntimeExports.jsx("button", { type: "button", role: "tab", "aria-selected": active, tabIndex: active ? 0 : -1, onClick, className: "px-3 py-1.5 text-[11px] font-medium transition-colors -mb-px", style: {
|
|
1835
|
+
// Explicit styles to prevent app-level button overrides when web-shared
|
|
1836
|
+
// is embedded in a self-hosted app.
|
|
1837
|
+
backgroundColor: "transparent",
|
|
1838
|
+
borderTop: "none",
|
|
1839
|
+
borderLeft: "none",
|
|
1840
|
+
borderRight: "none",
|
|
1536
1841
|
borderBottom: `2px solid ${active ? "var(--ds-blue-600)" : "transparent"}`,
|
|
1537
1842
|
borderRadius: 0,
|
|
1538
1843
|
outline: "none",
|
|
@@ -1564,23 +1869,10 @@ const conversationTabs = [
|
|
|
1564
1869
|
];
|
|
1565
1870
|
function ConversationWithTabs({ conversation, args }) {
|
|
1566
1871
|
const [activeTab, setActiveTab] = reactExports.useState("conversation");
|
|
1567
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary:
|
|
1872
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "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) }) }) });
|
|
1568
1873
|
}
|
|
1569
1874
|
function EncryptedFieldBlock() {
|
|
1570
|
-
|
|
1571
|
-
if (ctx) {
|
|
1572
|
-
return jsxRuntimeExports.jsxs("button", { type: "button", onClick: ctx.onDecrypt, disabled: ctx.isDecrypting, className: "flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-xs cursor-pointer transition-colors", style: {
|
|
1573
|
-
borderColor: "var(--ds-gray-400)",
|
|
1574
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
1575
|
-
color: "var(--ds-gray-700)",
|
|
1576
|
-
opacity: ctx.isDecrypting ? 0.6 : 1
|
|
1577
|
-
}, title: "Click to decrypt", children: [ctx.isDecrypting ? jsxRuntimeExports.jsx(Spinner, { size: 12 }) : jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { className: "font-medium", children: ctx.isDecrypting ? "Decrypting…" : "Decrypt" })] });
|
|
1578
|
-
}
|
|
1579
|
-
return jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
1580
|
-
borderColor: "var(--ds-gray-300)",
|
|
1581
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
1582
|
-
color: "var(--ds-gray-700)"
|
|
1583
|
-
}, children: [jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Encrypted" })] });
|
|
1875
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
1584
1876
|
}
|
|
1585
1877
|
function ExpiredFieldBlock() {
|
|
1586
1878
|
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
@@ -1653,6 +1945,7 @@ const attributeDisplayNames = {
|
|
|
1653
1945
|
attempt: "Attempts",
|
|
1654
1946
|
eventId: "Event ID",
|
|
1655
1947
|
runId: "Run ID",
|
|
1948
|
+
token: "Token",
|
|
1656
1949
|
eventType: "Event Type",
|
|
1657
1950
|
correlationId: "Correlation ID",
|
|
1658
1951
|
deploymentId: "Deployment ID",
|
|
@@ -1706,13 +1999,6 @@ const formatLocalMillisecondTime = (date) => date.toLocaleString(void 0, {
|
|
|
1706
1999
|
second: "numeric",
|
|
1707
2000
|
fractionalSecondDigits: 3
|
|
1708
2001
|
});
|
|
1709
|
-
const localMillisecondTime = (value) => {
|
|
1710
|
-
const date = parseDateValue(value);
|
|
1711
|
-
if (!date) {
|
|
1712
|
-
return "-";
|
|
1713
|
-
}
|
|
1714
|
-
return formatLocalMillisecondTime(date);
|
|
1715
|
-
};
|
|
1716
2002
|
const localMillisecondTimeOrNull = (value) => {
|
|
1717
2003
|
const date = parseDateValue(value);
|
|
1718
2004
|
if (!date) {
|
|
@@ -1733,7 +2019,7 @@ const attributeToDisplayFn = {
|
|
|
1733
2019
|
stepName: (_value) => null,
|
|
1734
2020
|
// IDs
|
|
1735
2021
|
runId: (_value) => null,
|
|
1736
|
-
stepId: (
|
|
2022
|
+
stepId: (value) => String(value),
|
|
1737
2023
|
hookId: (value) => String(value),
|
|
1738
2024
|
eventId: (value) => String(value),
|
|
1739
2025
|
// Run/step details
|
|
@@ -1758,6 +2044,14 @@ const attributeToDisplayFn = {
|
|
|
1758
2044
|
projectId: (_value) => null,
|
|
1759
2045
|
environment: (_value) => null,
|
|
1760
2046
|
executionContext: (_value) => null,
|
|
2047
|
+
// Attributes MVP — string-string metadata attached to the run.
|
|
2048
|
+
// Rendered as a JSON block; if empty/missing, hidden by the
|
|
2049
|
+
// hasDisplayContent gate above.
|
|
2050
|
+
attributes: (value) => {
|
|
2051
|
+
if (!hasDisplayContent(value))
|
|
2052
|
+
return null;
|
|
2053
|
+
return JsonBlock(value);
|
|
2054
|
+
},
|
|
1761
2055
|
// Dates — wrapped with TimestampTooltip showing UTC/local + relative time
|
|
1762
2056
|
createdAt: timestampWithTooltipOrNull,
|
|
1763
2057
|
startedAt: timestampWithTooltipOrNull,
|
|
@@ -1771,20 +2065,19 @@ const attributeToDisplayFn = {
|
|
|
1771
2065
|
if (!hasDisplayContent(value))
|
|
1772
2066
|
return null;
|
|
1773
2067
|
if (isEncryptedMarker(value))
|
|
1774
|
-
return jsxRuntimeExports.jsx(
|
|
2068
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
1775
2069
|
if (isExpiredMarker(value))
|
|
1776
2070
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1777
2071
|
return JsonBlock(value);
|
|
1778
2072
|
},
|
|
1779
2073
|
input: (value, context) => {
|
|
1780
|
-
if (isEncryptedMarker(value))
|
|
1781
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
2074
|
+
if (isEncryptedMarker(value)) {
|
|
2075
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2076
|
+
}
|
|
1782
2077
|
if (isExpiredMarker(value))
|
|
1783
2078
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1784
2079
|
if (value && typeof value === "object" && "args" in value) {
|
|
1785
2080
|
const { args, closureVars, thisVal } = value;
|
|
1786
|
-
const argCount2 = Array.isArray(args) ? args.length : 0;
|
|
1787
|
-
const argLabel2 = argCount2 === 1 ? "argument" : "arguments";
|
|
1788
2081
|
const hasClosureVars = hasDisplayContent(closureVars);
|
|
1789
2082
|
const hasThisVal = hasDisplayContent(thisVal);
|
|
1790
2083
|
const hasArgs = hasDisplayContent(args);
|
|
@@ -1795,46 +2088,47 @@ const attributeToDisplayFn = {
|
|
|
1795
2088
|
}
|
|
1796
2089
|
}
|
|
1797
2090
|
if (!hasArgs && !hasClosureVars && !hasThisVal) {
|
|
1798
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input (no data)", disabled: true
|
|
2091
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input (no data)", disabled: true });
|
|
1799
2092
|
}
|
|
1800
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(DetailCard, { summary:
|
|
2093
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(DetailCard, { summary: "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(DetailCard, { summary: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(DetailCard, { summary: "Context", children: JsonBlock(thisVal) })] });
|
|
1801
2094
|
}
|
|
1802
|
-
const argCount = Array.isArray(value) ? value.length : 0;
|
|
1803
|
-
const argLabel = argCount === 1 ? "argument" : "arguments";
|
|
1804
2095
|
if (!hasDisplayContent(value)) {
|
|
1805
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input (no data)", disabled: true
|
|
2096
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input (no data)", disabled: true });
|
|
1806
2097
|
}
|
|
1807
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary:
|
|
2098
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input", children: Array.isArray(value) ? value.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(value) });
|
|
1808
2099
|
},
|
|
1809
2100
|
output: (value) => {
|
|
2101
|
+
if (isEncryptedMarker(value)) {
|
|
2102
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Output", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2103
|
+
}
|
|
1810
2104
|
if (!hasDisplayContent(value))
|
|
1811
2105
|
return null;
|
|
1812
|
-
if (isEncryptedMarker(value))
|
|
1813
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
1814
2106
|
if (isExpiredMarker(value))
|
|
1815
2107
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1816
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Output",
|
|
2108
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Output", children: JsonBlock(value) });
|
|
1817
2109
|
},
|
|
1818
2110
|
error: (value) => {
|
|
1819
|
-
if (isEncryptedMarker(value))
|
|
1820
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
2111
|
+
if (isEncryptedMarker(value)) {
|
|
2112
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2113
|
+
}
|
|
1821
2114
|
if (isExpiredMarker(value))
|
|
1822
2115
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1823
2116
|
if (!hasDisplayContent(value))
|
|
1824
2117
|
return null;
|
|
1825
2118
|
if (isStructuredErrorWithStack(value)) {
|
|
1826
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error",
|
|
2119
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(ErrorStackBlock, { value }) });
|
|
1827
2120
|
}
|
|
1828
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error",
|
|
2121
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error", defaultOpen: true, children: JsonBlock(value) });
|
|
1829
2122
|
},
|
|
1830
2123
|
eventData: (value) => {
|
|
1831
|
-
if (isEncryptedMarker(value))
|
|
1832
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
2124
|
+
if (isEncryptedMarker(value)) {
|
|
2125
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2126
|
+
}
|
|
1833
2127
|
if (isExpiredMarker(value))
|
|
1834
2128
|
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1835
2129
|
if (!hasDisplayContent(value))
|
|
1836
2130
|
return null;
|
|
1837
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", children: JsonBlock(value) });
|
|
2131
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", defaultOpen: true, children: JsonBlock(value) });
|
|
1838
2132
|
},
|
|
1839
2133
|
errorCode: (value) => {
|
|
1840
2134
|
if (typeof value !== "string" || value.length === 0)
|
|
@@ -1849,15 +2143,32 @@ const resolvableAttributes = [
|
|
|
1849
2143
|
"metadata",
|
|
1850
2144
|
"eventData"
|
|
1851
2145
|
];
|
|
2146
|
+
const selfHeaderedAttributes = /* @__PURE__ */ new Set([
|
|
2147
|
+
"input",
|
|
2148
|
+
"output",
|
|
2149
|
+
"error",
|
|
2150
|
+
"eventData"
|
|
2151
|
+
]);
|
|
1852
2152
|
const ExpiredDataMessage = () => jsxRuntimeExports.jsx("div", { className: "text-copy-12 rounded-md border p-4 my-2", style: {
|
|
1853
2153
|
borderColor: "var(--ds-gray-300)",
|
|
1854
2154
|
backgroundColor: "var(--ds-gray-100)",
|
|
1855
2155
|
color: "var(--ds-gray-700)"
|
|
1856
2156
|
}, children: jsxRuntimeExports.jsx("span", { children: "The data for this run has expired and is no longer available." }) });
|
|
2157
|
+
const copyableBasicAttributes = /* @__PURE__ */ new Set([
|
|
2158
|
+
"stepId",
|
|
2159
|
+
"hookId",
|
|
2160
|
+
"eventId",
|
|
2161
|
+
"deploymentId"
|
|
2162
|
+
]);
|
|
1857
2163
|
const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
|
|
1858
|
-
const
|
|
2164
|
+
const decryptCtx = reactExports.useContext(DecryptClickContext);
|
|
2165
|
+
const isExpandableLoadingTarget = attribute === "input" || attribute === "output" || attribute === "eventData";
|
|
1859
2166
|
if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
|
|
1860
|
-
|
|
2167
|
+
const label = attribute === "eventData" ? "Event Data" : attribute === "output" ? "Output" : "Input";
|
|
2168
|
+
if (decryptCtx == null ? void 0 : decryptCtx.hasEncryptedData) {
|
|
2169
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: label, defaultOpen: attribute === "eventData", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2170
|
+
}
|
|
2171
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: label });
|
|
1861
2172
|
}
|
|
1862
2173
|
const displayFn = attributeToDisplayFn[attribute];
|
|
1863
2174
|
if (!displayFn) {
|
|
@@ -1870,7 +2181,10 @@ const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }
|
|
|
1870
2181
|
if (inline) {
|
|
1871
2182
|
return jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium", style: { color: "var(--ds-gray-700)" }, children: attribute }), jsxRuntimeExports.jsx("span", { className: "text-[11px]", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] });
|
|
1872
2183
|
}
|
|
1873
|
-
|
|
2184
|
+
if (selfHeaderedAttributes.has(attribute)) {
|
|
2185
|
+
return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: displayValue });
|
|
2186
|
+
}
|
|
2187
|
+
return jsxRuntimeExports.jsxs("div", { className: "relative", children: [typeof isLoading === "boolean" && isLoading && jsxRuntimeExports.jsx("div", { className: "absolute top-9 right-4", children: jsxRuntimeExports.jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2", style: { borderColor: "var(--ds-gray-900)" } }) }), jsxRuntimeExports.jsxs("div", { className: "my-2 flex flex-col gap-0", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-1000 font-medium first-letter:uppercase", children: attribute }), jsxRuntimeExports.jsx("span", { className: "text-xs", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] }, attribute)] });
|
|
1874
2188
|
};
|
|
1875
2189
|
const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
|
|
1876
2190
|
const toast2 = useToast();
|
|
@@ -1895,700 +2209,438 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
|
|
|
1895
2209
|
const present = Object.keys(displayData).filter((key) => resolvableAttributes.includes(key)).sort(sortByAttributeOrder);
|
|
1896
2210
|
if (!isLoading)
|
|
1897
2211
|
return present;
|
|
1898
|
-
|
|
2212
|
+
if (resource === "sleep")
|
|
2213
|
+
return present;
|
|
2214
|
+
const loadingDefaults = ["input", "output"];
|
|
1899
2215
|
for (const key of loadingDefaults) {
|
|
1900
2216
|
if (!present.includes(key)) {
|
|
1901
2217
|
present.push(key);
|
|
1902
2218
|
}
|
|
1903
2219
|
}
|
|
1904
2220
|
return present.sort(sortByAttributeOrder);
|
|
1905
|
-
}, [displayData, isLoading]);
|
|
2221
|
+
}, [displayData, isLoading, resource]);
|
|
1906
2222
|
const visibleBasicAttributes = basicAttributes.filter((attribute) => {
|
|
1907
2223
|
const displayFn = attributeToDisplayFn[attribute];
|
|
1908
2224
|
if (!displayFn)
|
|
1909
2225
|
return false;
|
|
1910
|
-
const displayValue = displayFn(displayData[attribute]);
|
|
1911
|
-
return displayValue !== null;
|
|
1912
|
-
});
|
|
1913
|
-
const orderedBasicAttributes = reactExports.useMemo(() => {
|
|
1914
|
-
const attributes = [...visibleBasicAttributes];
|
|
1915
|
-
const moduleSpecifierIndex = attributes.indexOf("moduleSpecifier");
|
|
1916
|
-
if (moduleSpecifierIndex === -1) {
|
|
1917
|
-
return attributes;
|
|
1918
|
-
}
|
|
1919
|
-
attributes.splice(moduleSpecifierIndex, 1);
|
|
1920
|
-
const workflowNameIndex = attributes.indexOf("workflowName");
|
|
1921
|
-
if (workflowNameIndex !== -1) {
|
|
1922
|
-
attributes.splice(workflowNameIndex + 1, 0, "moduleSpecifier");
|
|
1923
|
-
return attributes;
|
|
1924
|
-
}
|
|
1925
|
-
const stepNameIndex = attributes.indexOf("stepName");
|
|
1926
|
-
if (stepNameIndex !== -1) {
|
|
1927
|
-
attributes.splice(stepNameIndex + 1, 0, "moduleSpecifier");
|
|
1928
|
-
return attributes;
|
|
1929
|
-
}
|
|
1930
|
-
attributes.unshift("moduleSpecifier");
|
|
1931
|
-
return attributes;
|
|
1932
|
-
}, [visibleBasicAttributes]);
|
|
1933
|
-
const displayContext = reactExports.useMemo(() => ({
|
|
1934
|
-
stepName: displayData.stepName
|
|
1935
|
-
}), [displayData.stepName]);
|
|
1936
|
-
const handleCopyModuleSpecifier = reactExports.useCallback((value) => {
|
|
1937
|
-
navigator.clipboard.writeText(value).then(() => {
|
|
1938
|
-
toast2.success("moduleSpecifier copied");
|
|
1939
|
-
}).catch(() => {
|
|
1940
|
-
toast2.error("Failed to copy moduleSpecifier");
|
|
1941
|
-
});
|
|
1942
|
-
}, []);
|
|
1943
|
-
return jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsx(DecryptClickContext.Provider, { value: onDecrypt ? { onDecrypt, isDecrypting } : void 0, children: jsxRuntimeExports.jsxs("div", { children: [visibleBasicAttributes.length > 0 && jsxRuntimeExports.jsxs("div", { className: "mb-3 flex flex-col overflow-hidden rounded-md border", style: {
|
|
1944
|
-
borderColor: "var(--ds-gray-300)"
|
|
1945
|
-
}, children: [orderedBasicAttributes.map((attribute, index) => {
|
|
1946
|
-
var _a;
|
|
1947
|
-
const displayValue = (_a = attributeToDisplayFn[attribute]) == null ? void 0 : _a.call(attributeToDisplayFn, displayData[attribute]);
|
|
1948
|
-
const isModuleSpecifier = attribute === "moduleSpecifier";
|
|
1949
|
-
const moduleSpecifierValue = typeof displayValue === "string" ? displayValue : String(displayValue ?? displayData.moduleSpecifier ?? "");
|
|
1950
|
-
const shouldCapitalizeLabel = attribute !== "workflowCoreVersion";
|
|
1951
|
-
const showResumeAtSkeleton = isLoading && resource === "sleep" && !displayData.resumeAt;
|
|
1952
|
-
const showDivider = index < orderedBasicAttributes.length - 1 || showResumeAtSkeleton;
|
|
1953
|
-
return jsxRuntimeExports.jsxs("div", { className: "py-1", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1", children: [jsxRuntimeExports.jsx("span", { className: shouldCapitalizeLabel ? "text-[14px] first-letter:uppercase" : "text-[14px]", style: { color: "var(--ds-gray-700)" }, children: getAttributeDisplayName(attribute) }), isModuleSpecifier ? jsxRuntimeExports.jsx("button", { type: "button", className: "min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono", style: {
|
|
1954
|
-
color: "var(--ds-gray-1000)",
|
|
1955
|
-
background: "transparent",
|
|
1956
|
-
border: "none",
|
|
1957
|
-
padding: 0
|
|
1958
|
-
}, title: moduleSpecifierValue, onClick: () => handleCopyModuleSpecifier(moduleSpecifierValue), children: moduleSpecifierValue }) : jsxRuntimeExports.jsx("span", { className: "min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] }), showDivider ? jsxRuntimeExports.jsx("div", { className: "mx-2.5 border-b", style: { borderColor: "var(--ds-gray-300)" } }) : null] }, attribute);
|
|
1959
|
-
}), isLoading && resource === "sleep" && !displayData.resumeAt && jsxRuntimeExports.jsx("div", { className: "py-1", children: jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1", children: [jsxRuntimeExports.jsx("span", { className: "text-[14px] first-letter:uppercase", style: { color: "var(--ds-gray-700)" }, children: "resumeAt" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[55%]" })] }) })] }), error ? jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load resource details", details: error.message, className: "my-4" }) : hasExpired ? jsxRuntimeExports.jsx(ExpiredDataMessage, {}) : jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: resolvedAttributes.map((attribute) => jsxRuntimeExports.jsx(AttributeBlock, { isLoading, attribute, value: displayData[attribute], context: displayContext }, attribute)) })] }) }) }) });
|
|
1960
|
-
};
|
|
1961
|
-
const ERROR_EVENT_TYPES = /* @__PURE__ */ new Set(["step_failed", "step_retrying"]);
|
|
1962
|
-
const DATA_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
1963
|
-
"step_created",
|
|
1964
|
-
"step_completed",
|
|
1965
|
-
"step_failed",
|
|
1966
|
-
"step_retrying",
|
|
1967
|
-
"hook_created",
|
|
1968
|
-
"hook_received",
|
|
1969
|
-
"run_created",
|
|
1970
|
-
"run_completed",
|
|
1971
|
-
"run_failed",
|
|
1972
|
-
"wait_created",
|
|
1973
|
-
"wait_completed"
|
|
1974
|
-
]);
|
|
1975
|
-
function EventItem({ event, onLoadEventData, encryptionKey }) {
|
|
1976
|
-
const [loadedData, setLoadedData] = reactExports.useState(null);
|
|
1977
|
-
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
1978
|
-
const [loadError, setLoadError] = reactExports.useState(null);
|
|
1979
|
-
const wasExpandedRef = reactExports.useRef(false);
|
|
1980
|
-
const loadedDataRef = reactExports.useRef(null);
|
|
1981
|
-
const existingData = "eventData" in event && event.eventData != null ? event.eventData : null;
|
|
1982
|
-
const mergedDisplay = loadedData ?? existingData;
|
|
1983
|
-
const canHaveData = DATA_EVENT_TYPES.has(event.eventType);
|
|
1984
|
-
const loadEventData = reactExports.useCallback(async (options) => {
|
|
1985
|
-
if (!onLoadEventData || !event.correlationId || !event.eventId)
|
|
1986
|
-
return;
|
|
1987
|
-
if (!(options == null ? void 0 : options.force) && loadedDataRef.current !== null) {
|
|
1988
|
-
return;
|
|
1989
|
-
}
|
|
1990
|
-
try {
|
|
1991
|
-
setIsLoading(true);
|
|
1992
|
-
setLoadError(null);
|
|
1993
|
-
const data = await onLoadEventData(event.correlationId, event.eventId);
|
|
1994
|
-
loadedDataRef.current = data;
|
|
1995
|
-
setLoadedData(data);
|
|
1996
|
-
} catch (err) {
|
|
1997
|
-
setLoadError(err instanceof Error ? err.message : String(err));
|
|
1998
|
-
} finally {
|
|
1999
|
-
setIsLoading(false);
|
|
2000
|
-
}
|
|
2001
|
-
}, [onLoadEventData, event.correlationId, event.eventId]);
|
|
2002
|
-
const handleExpand = reactExports.useCallback(async () => {
|
|
2003
|
-
if (isLoading)
|
|
2004
|
-
return;
|
|
2005
|
-
wasExpandedRef.current = true;
|
|
2006
|
-
await loadEventData();
|
|
2007
|
-
}, [isLoading, loadEventData]);
|
|
2008
|
-
reactExports.useEffect(() => {
|
|
2009
|
-
if (!encryptionKey || !wasExpandedRef.current)
|
|
2010
|
-
return;
|
|
2011
|
-
loadedDataRef.current = null;
|
|
2012
|
-
setLoadedData(null);
|
|
2013
|
-
void loadEventData({ force: true });
|
|
2014
|
-
}, [encryptionKey, loadEventData]);
|
|
2015
|
-
const createdAt = new Date(event.createdAt);
|
|
2016
|
-
const displayPayload = isLoading ? loadedData : mergedDisplay;
|
|
2017
|
-
return jsxRuntimeExports.jsxs(DetailCard, { summaryClassName: "text-base py-2", summary: jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("span", { className: "font-medium", style: { color: "var(--ds-gray-1000)" }, children: event.eventType }), " ", "-", " ", jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-gray-700)" }, children: localMillisecondTime(createdAt.getTime()) })] }), onToggle: canHaveData ? (open) => {
|
|
2018
|
-
if (open)
|
|
2019
|
-
handleExpand();
|
|
2020
|
-
} : void 0, children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-col divide-y rounded-md border overflow-hidden", style: {
|
|
2021
|
-
borderColor: "var(--ds-gray-300)",
|
|
2022
|
-
backgroundColor: "var(--ds-gray-100)"
|
|
2023
|
-
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 px-2.5 py-1.5", style: { borderColor: "var(--ds-gray-300)" }, children: [jsxRuntimeExports.jsx("span", { className: "text-[13px] font-medium", style: { color: "var(--ds-gray-700)" }, children: "Event ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-[13px] font-mono", style: { color: "var(--ds-gray-1000)" }, title: event.eventId, children: event.eventId })] }), event.correlationId && jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 px-2.5 py-1.5", style: { borderColor: "var(--ds-gray-300)" }, children: [jsxRuntimeExports.jsx("span", { className: "text-[13px] font-medium", style: { color: "var(--ds-gray-700)" }, children: "Correlation ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-[13px] font-mono", style: { color: "var(--ds-gray-1000)" }, title: event.correlationId, children: event.correlationId })] })] }), isLoading && jsxRuntimeExports.jsxs("div", { className: "mt-2 rounded-md border p-3", style: {
|
|
2024
|
-
borderColor: "var(--ds-gray-300)"
|
|
2025
|
-
}, children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[35%]" }), jsxRuntimeExports.jsx(Skeleton, { className: "mt-2 h-4 w-[90%]" }), jsxRuntimeExports.jsx(Skeleton, { className: "mt-2 h-4 w-[75%]" })] }), loadError && jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load event data", details: loadError, className: "mt-2" }), displayPayload != null && jsxRuntimeExports.jsx("div", { className: "mt-2", children: jsxRuntimeExports.jsx(EventDataBlock, { eventType: event.eventType, data: displayPayload }) })] });
|
|
2026
|
-
}
|
|
2027
|
-
function hasOnlyExpiredFields(data, eventType) {
|
|
2028
|
-
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2029
|
-
return false;
|
|
2030
|
-
}
|
|
2031
|
-
const record = data;
|
|
2032
|
-
const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];
|
|
2033
|
-
const presentKeys = refKeys.filter((k) => k in record);
|
|
2034
|
-
return presentKeys.length > 0 && presentKeys.every((k) => isExpiredMarker(record[k]));
|
|
2035
|
-
}
|
|
2036
|
-
function EventDataBlock({ eventType, data }) {
|
|
2037
|
-
if (isExpiredMarker(data) || hasOnlyExpiredFields(data, eventType)) {
|
|
2038
|
-
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
2039
|
-
borderColor: "var(--ds-gray-300)",
|
|
2040
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
2041
|
-
color: "var(--ds-gray-700)"
|
|
2042
|
-
}, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
|
|
2043
|
-
}
|
|
2044
|
-
if (ERROR_EVENT_TYPES.has(eventType) && data != null && typeof data === "object") {
|
|
2045
|
-
const record = data;
|
|
2046
|
-
if (isStructuredErrorWithStack(record.error)) {
|
|
2047
|
-
return jsxRuntimeExports.jsx(ErrorStackBlock, { value: record.error });
|
|
2048
|
-
}
|
|
2049
|
-
if (isStructuredErrorWithStack(record)) {
|
|
2050
|
-
return jsxRuntimeExports.jsx(ErrorStackBlock, { value: record });
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
|
|
2054
|
-
}
|
|
2055
|
-
function EventsList({ events, isLoading = false, error, onLoadEventData, encryptionKey }) {
|
|
2056
|
-
const sortedEvents = reactExports.useMemo(() => [...events].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()), [events]);
|
|
2057
|
-
return jsxRuntimeExports.jsxs("div", { className: "mt-2", style: { color: "var(--ds-gray-1000)" }, children: [jsxRuntimeExports.jsx("h3", { className: "text-label-14 font-medium mt-4 mb-2", style: { color: "var(--ds-gray-1000)" }, children: "Events" }), isLoading ? jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-4", children: [jsxRuntimeExports.jsx(Skeleton, { className: "h-9 w-full rounded-md" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-9 w-full rounded-md" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-9 w-full rounded-md" })] }) : null, !isLoading && !error && sortedEvents.length === 0 && jsxRuntimeExports.jsx("div", { className: "text-sm", children: "No events found" }), sortedEvents.length > 0 && !error ? jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-4", children: sortedEvents.map((event) => jsxRuntimeExports.jsx(EventItem, { event, onLoadEventData, encryptionKey }, event.eventId)) }) : null] });
|
|
2058
|
-
}
|
|
2059
|
-
function isStep(data) {
|
|
2060
|
-
return data !== null && typeof data === "object" && "stepId" in data;
|
|
2061
|
-
}
|
|
2062
|
-
function isWorkflowRun(data) {
|
|
2063
|
-
return data !== null && typeof data === "object" && "runId" in data;
|
|
2064
|
-
}
|
|
2065
|
-
function isHook(data) {
|
|
2066
|
-
return data !== null && typeof data === "object" && "hookId" in data;
|
|
2067
|
-
}
|
|
2068
|
-
function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spanDetailError, spanDetailLoading, onSpanSelect, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan }) {
|
|
2069
|
-
const toast2 = useToast();
|
|
2070
|
-
const [stoppingSleep, setStoppingSleep] = reactExports.useState(false);
|
|
2071
|
-
const [showResolveHookModal, setShowResolveHookModal] = reactExports.useState(false);
|
|
2072
|
-
const [resolvingHook, setResolvingHook] = reactExports.useState(false);
|
|
2073
|
-
const [resolvedHookIds, setResolvedHookIds] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
2074
|
-
const data = selectedSpan == null ? void 0 : selectedSpan.data;
|
|
2075
|
-
const rawEvents = selectedSpan == null ? void 0 : selectedSpan.rawEvents;
|
|
2076
|
-
const rawEventsLength = (rawEvents == null ? void 0 : rawEvents.length) ?? 0;
|
|
2077
|
-
const { resource, resourceId, runId } = reactExports.useMemo(() => {
|
|
2078
|
-
if (!selectedSpan) {
|
|
2079
|
-
return { resource: void 0, resourceId: void 0, runId: void 0 };
|
|
2080
|
-
}
|
|
2081
|
-
const res = selectedSpan.resource;
|
|
2082
|
-
if (res === "step" && isStep(data)) {
|
|
2083
|
-
return { resource: "step", resourceId: data.stepId, runId: data.runId };
|
|
2084
|
-
}
|
|
2085
|
-
if (res === "run" && isWorkflowRun(data)) {
|
|
2086
|
-
return { resource: "run", resourceId: data.runId, runId: void 0 };
|
|
2087
|
-
}
|
|
2088
|
-
if (res === "hook" && isHook(data)) {
|
|
2089
|
-
return { resource: "hook", resourceId: data.hookId, runId: void 0 };
|
|
2090
|
-
}
|
|
2091
|
-
if (res === "sleep") {
|
|
2092
|
-
const waitData = data;
|
|
2093
|
-
return {
|
|
2094
|
-
resource: "sleep",
|
|
2095
|
-
resourceId: selectedSpan.spanId,
|
|
2096
|
-
runId: waitData == null ? void 0 : waitData.runId
|
|
2097
|
-
};
|
|
2098
|
-
}
|
|
2099
|
-
return { resource: void 0, resourceId: void 0, runId: void 0 };
|
|
2100
|
-
}, [selectedSpan, data]);
|
|
2101
|
-
const onSpanSelectRef = reactExports.useRef(onSpanSelect);
|
|
2102
|
-
onSpanSelectRef.current = onSpanSelect;
|
|
2103
|
-
reactExports.useEffect(() => {
|
|
2104
|
-
if (resource && resourceId && ["run", "step", "hook", "sleep"].includes(resource)) {
|
|
2105
|
-
onSpanSelectRef.current({
|
|
2106
|
-
resource,
|
|
2107
|
-
resourceId,
|
|
2108
|
-
runId
|
|
2109
|
-
});
|
|
2110
|
-
}
|
|
2111
|
-
}, [resource, resourceId, runId]);
|
|
2112
|
-
const canWakeUp = reactExports.useMemo(() => {
|
|
2113
|
-
if (resource !== "sleep" || !rawEvents)
|
|
2114
|
-
return false;
|
|
2115
|
-
const terminalStates = ["completed", "failed", "cancelled"];
|
|
2116
|
-
if (terminalStates.includes(run.status))
|
|
2117
|
-
return false;
|
|
2118
|
-
const hasWaitCreated = rawEvents.some((e) => e.eventType === "wait_created");
|
|
2119
|
-
if (!hasWaitCreated)
|
|
2120
|
-
return false;
|
|
2121
|
-
const hasWaitCompleted = rawEvents.some((e) => e.eventType === "wait_completed");
|
|
2122
|
-
return !hasWaitCompleted;
|
|
2123
|
-
}, [resource, rawEvents, rawEventsLength, run.status]);
|
|
2124
|
-
const canResolveHook = reactExports.useMemo(() => {
|
|
2125
|
-
if (resource !== "hook" || !rawEvents || !resourceId)
|
|
2126
|
-
return false;
|
|
2127
|
-
if (resolvedHookIds.has(resourceId))
|
|
2128
|
-
return false;
|
|
2129
|
-
const terminalStates = ["completed", "failed", "cancelled"];
|
|
2130
|
-
if (terminalStates.includes(run.status))
|
|
2131
|
-
return false;
|
|
2132
|
-
const hasHookDisposed = rawEvents.some((e) => e.eventType === "hook_disposed");
|
|
2133
|
-
if (hasHookDisposed)
|
|
2134
|
-
return false;
|
|
2135
|
-
return true;
|
|
2136
|
-
}, [
|
|
2137
|
-
resource,
|
|
2138
|
-
resourceId,
|
|
2139
|
-
rawEvents,
|
|
2140
|
-
rawEventsLength,
|
|
2141
|
-
run.status,
|
|
2142
|
-
resolvedHookIds
|
|
2143
|
-
]);
|
|
2144
|
-
const error = spanDetailError ?? void 0;
|
|
2145
|
-
const loading = spanDetailLoading ?? false;
|
|
2146
|
-
const hookToken = reactExports.useMemo(() => {
|
|
2147
|
-
if (resource !== "hook" || !resourceId)
|
|
2148
|
-
return void 0;
|
|
2149
|
-
if (isHook(spanDetailData) && spanDetailData.token) {
|
|
2150
|
-
return spanDetailData.token;
|
|
2226
|
+
const displayValue = displayFn(displayData[attribute]);
|
|
2227
|
+
return displayValue !== null;
|
|
2228
|
+
});
|
|
2229
|
+
const orderedBasicAttributes = reactExports.useMemo(() => {
|
|
2230
|
+
const attributes = [...visibleBasicAttributes];
|
|
2231
|
+
const moduleSpecifierIndex = attributes.indexOf("moduleSpecifier");
|
|
2232
|
+
if (moduleSpecifierIndex === -1) {
|
|
2233
|
+
return attributes;
|
|
2151
2234
|
}
|
|
2152
|
-
|
|
2153
|
-
|
|
2235
|
+
attributes.splice(moduleSpecifierIndex, 1);
|
|
2236
|
+
const workflowNameIndex = attributes.indexOf("workflowName");
|
|
2237
|
+
if (workflowNameIndex !== -1) {
|
|
2238
|
+
attributes.splice(workflowNameIndex + 1, 0, "moduleSpecifier");
|
|
2239
|
+
return attributes;
|
|
2154
2240
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
toast2.error(`Failed to load ${resource} details`, {
|
|
2160
|
-
description: error.message
|
|
2161
|
-
});
|
|
2241
|
+
const stepNameIndex = attributes.indexOf("stepName");
|
|
2242
|
+
if (stepNameIndex !== -1) {
|
|
2243
|
+
attributes.splice(stepNameIndex + 1, 0, "moduleSpecifier");
|
|
2244
|
+
return attributes;
|
|
2162
2245
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2246
|
+
attributes.unshift("moduleSpecifier");
|
|
2247
|
+
return attributes;
|
|
2248
|
+
}, [visibleBasicAttributes]);
|
|
2249
|
+
const displayContext = reactExports.useMemo(() => ({
|
|
2250
|
+
stepName: displayData.stepName
|
|
2251
|
+
}), [displayData.stepName]);
|
|
2252
|
+
const handleCopyModuleSpecifier = reactExports.useCallback((value) => {
|
|
2253
|
+
navigator.clipboard.writeText(value).then(() => {
|
|
2254
|
+
toast2.success("moduleSpecifier copied");
|
|
2255
|
+
}).catch(() => {
|
|
2256
|
+
toast2.error("Failed to copy moduleSpecifier");
|
|
2257
|
+
});
|
|
2258
|
+
}, []);
|
|
2259
|
+
const outerDecryptCtx = reactExports.useContext(DecryptClickContext);
|
|
2260
|
+
const decryptValue = onDecrypt ? {
|
|
2261
|
+
onDecrypt,
|
|
2262
|
+
isDecrypting,
|
|
2263
|
+
hasEncryptedData: outerDecryptCtx == null ? void 0 : outerDecryptCtx.hasEncryptedData
|
|
2264
|
+
} : outerDecryptCtx;
|
|
2265
|
+
return 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("div", { className: "flex flex-col overflow-hidden divide-y divide-gray-alpha-400 mb-3", children: [orderedBasicAttributes.map((attribute) => {
|
|
2266
|
+
var _a;
|
|
2267
|
+
const displayValue = (_a = attributeToDisplayFn[attribute]) == null ? void 0 : _a.call(attributeToDisplayFn, displayData[attribute]);
|
|
2268
|
+
const isModuleSpecifier = attribute === "moduleSpecifier";
|
|
2269
|
+
const isCopyableBasicAttribute = copyableBasicAttributes.has(attribute) && typeof displayValue === "string";
|
|
2270
|
+
const moduleSpecifierValue = typeof displayValue === "string" ? displayValue : String(displayValue ?? displayData.moduleSpecifier ?? "");
|
|
2271
|
+
return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between py-2", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900", children: getAttributeDisplayName(attribute) }), isModuleSpecifier ? jsxRuntimeExports.jsx("button", { type: "button", className: "min-w-0 max-w-[70%] truncate text-right text-label-13 font-mono", style: {
|
|
2272
|
+
color: "var(--ds-gray-1000)",
|
|
2273
|
+
background: "transparent",
|
|
2274
|
+
border: "none",
|
|
2275
|
+
padding: 0
|
|
2276
|
+
}, title: moduleSpecifierValue, onClick: () => handleCopyModuleSpecifier(moduleSpecifierValue), children: moduleSpecifierValue }) : isCopyableBasicAttribute ? jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 max-w-[70%] items-center justify-end gap-1 text-right text-[13px] font-mono", style: {
|
|
2277
|
+
color: "var(--ds-gray-1000)"
|
|
2278
|
+
}, title: displayValue, children: [jsxRuntimeExports.jsx(MiddleTruncate, { value: displayValue, className: "flex-1" }), jsxRuntimeExports.jsx(CopyButton, { copyText: displayValue, ariaLabel: `Copy ${getAttributeDisplayName(attribute)}`, className: "shrink-0 -mr-1" })] }) : jsxRuntimeExports.jsx("span", { className: "text-right text-label-13 font-mono", children: displayValue })] }, attribute);
|
|
2279
|
+
}), isLoading && resource === "sleep" && !displayData.resumeAt && jsxRuntimeExports.jsx("div", { className: "py-1", children: jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1", children: [jsxRuntimeExports.jsx("span", { className: "text-[14px] first-letter:uppercase", style: { color: "var(--ds-gray-700)" }, children: "resumeAt" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[55%]" })] }) })] }), error ? jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load resource details", details: error.message, className: "my-4" }) : hasExpired ? jsxRuntimeExports.jsx(ExpiredDataMessage, {}) : resolvedAttributes.length > 0 ? jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: resolvedAttributes.map((attribute) => jsxRuntimeExports.jsx(AttributeBlock, { isLoading, attribute, value: displayData[attribute], context: displayContext }, attribute)) }) : null] }) }) });
|
|
2280
|
+
};
|
|
2281
|
+
const ERROR_EVENT_TYPES = /* @__PURE__ */ new Set(["step_failed", "step_retrying"]);
|
|
2282
|
+
const DATA_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
2283
|
+
"step_created",
|
|
2284
|
+
"step_completed",
|
|
2285
|
+
"step_failed",
|
|
2286
|
+
"step_retrying",
|
|
2287
|
+
"hook_created",
|
|
2288
|
+
"hook_received",
|
|
2289
|
+
"run_created",
|
|
2290
|
+
"run_completed",
|
|
2291
|
+
"run_failed",
|
|
2292
|
+
"wait_created",
|
|
2293
|
+
"wait_completed"
|
|
2294
|
+
]);
|
|
2295
|
+
function EventItem({ event, onLoadEventData, encryptionKey }) {
|
|
2296
|
+
const [loadedData, setLoadedData] = reactExports.useState(null);
|
|
2297
|
+
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
2298
|
+
const [loadError, setLoadError] = reactExports.useState(null);
|
|
2299
|
+
const wasExpandedRef = reactExports.useRef(false);
|
|
2300
|
+
const loadedDataRef = reactExports.useRef(null);
|
|
2301
|
+
const existingData = "eventData" in event && event.eventData != null ? event.eventData : null;
|
|
2302
|
+
const mergedDisplay = loadedData ?? existingData;
|
|
2303
|
+
const canHaveData = DATA_EVENT_TYPES.has(event.eventType);
|
|
2304
|
+
const loadEventData = reactExports.useCallback(async (options) => {
|
|
2305
|
+
if (!onLoadEventData || !event.correlationId || !event.eventId)
|
|
2166
2306
|
return;
|
|
2167
|
-
if (!
|
|
2168
|
-
toast2.error("Unable to wake up sleep", {
|
|
2169
|
-
description: "No wake-up handler provided."
|
|
2170
|
-
});
|
|
2307
|
+
if (!(options == null ? void 0 : options.force) && loadedDataRef.current !== null) {
|
|
2171
2308
|
return;
|
|
2172
2309
|
}
|
|
2173
2310
|
try {
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
});
|
|
2180
|
-
} else {
|
|
2181
|
-
toast2.info("Sleep already completed", {
|
|
2182
|
-
description: "This sleep call has already finished."
|
|
2183
|
-
});
|
|
2184
|
-
}
|
|
2311
|
+
setIsLoading(true);
|
|
2312
|
+
setLoadError(null);
|
|
2313
|
+
const data = await onLoadEventData(event.correlationId, event.eventId);
|
|
2314
|
+
loadedDataRef.current = data;
|
|
2315
|
+
setLoadedData(data);
|
|
2185
2316
|
} catch (err) {
|
|
2186
|
-
|
|
2187
|
-
toast2.error("Failed to wake up run", {
|
|
2188
|
-
description: err instanceof Error ? err.message : "An unknown error occurred"
|
|
2189
|
-
});
|
|
2317
|
+
setLoadError(err instanceof Error ? err.message : String(err));
|
|
2190
2318
|
} finally {
|
|
2191
|
-
|
|
2319
|
+
setIsLoading(false);
|
|
2192
2320
|
}
|
|
2193
|
-
};
|
|
2194
|
-
const
|
|
2195
|
-
if (
|
|
2196
|
-
return;
|
|
2197
|
-
if (!onResolveHook) {
|
|
2198
|
-
toast2.error("Unable to resolve hook", {
|
|
2199
|
-
description: "No resolve handler provided."
|
|
2200
|
-
});
|
|
2321
|
+
}, [onLoadEventData, event.correlationId, event.eventId]);
|
|
2322
|
+
const handleExpand = reactExports.useCallback(async () => {
|
|
2323
|
+
if (isLoading)
|
|
2201
2324
|
return;
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2325
|
+
wasExpandedRef.current = true;
|
|
2326
|
+
await loadEventData();
|
|
2327
|
+
}, [isLoading, loadEventData]);
|
|
2328
|
+
reactExports.useLayoutEffect(() => {
|
|
2329
|
+
if (!encryptionKey || !wasExpandedRef.current)
|
|
2207
2330
|
return;
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
setShowResolveHookModal(false);
|
|
2218
|
-
if (resourceId) {
|
|
2219
|
-
setResolvedHookIds((prev) => new Set(prev).add(resourceId));
|
|
2220
|
-
}
|
|
2221
|
-
} catch (err) {
|
|
2222
|
-
console.error("Failed to resolve hook:", err);
|
|
2223
|
-
toast2.error("Failed to resolve hook", {
|
|
2224
|
-
description: err instanceof Error ? err.message : "An unknown error occurred"
|
|
2225
|
-
});
|
|
2226
|
-
} finally {
|
|
2227
|
-
setResolvingHook(false);
|
|
2228
|
-
}
|
|
2229
|
-
}, [onResolveHook, hookToken, resolvingHook, spanDetailData, data]);
|
|
2230
|
-
const displayData = spanDetailData ?? data;
|
|
2231
|
-
const moduleSpecifier = reactExports.useMemo(() => {
|
|
2232
|
-
const displayRecord = displayData;
|
|
2233
|
-
const displayStepName = displayRecord.stepName;
|
|
2234
|
-
const displayWorkflowName = displayRecord.workflowName;
|
|
2235
|
-
if (typeof displayStepName === "string") {
|
|
2236
|
-
return displayStepName;
|
|
2237
|
-
}
|
|
2238
|
-
if (typeof displayWorkflowName === "string") {
|
|
2239
|
-
return displayWorkflowName;
|
|
2240
|
-
}
|
|
2241
|
-
if (typeof run.workflowName === "string") {
|
|
2242
|
-
return run.workflowName;
|
|
2243
|
-
}
|
|
2244
|
-
return void 0;
|
|
2245
|
-
}, [displayData, run.workflowName]);
|
|
2246
|
-
if (!selectedSpan || !resource || !resourceId) {
|
|
2247
|
-
return null;
|
|
2248
|
-
}
|
|
2249
|
-
const hasPendingActions = resource === "sleep" && canWakeUp || resource === "hook" && canResolveHook;
|
|
2250
|
-
return jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col", children: [jsxRuntimeExports.jsx(DecryptClickContext.Provider, { value: onDecrypt ? { onDecrypt, isDecrypting } : void 0, children: jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto px-3 pt-3 pb-8", children: [hasPendingActions && jsxRuntimeExports.jsxs("div", { className: "mb-4 rounded-lg border p-2", style: {
|
|
2251
|
-
borderColor: "var(--ds-gray-300)",
|
|
2252
|
-
backgroundColor: "var(--ds-gray-100)"
|
|
2253
|
-
}, children: [jsxRuntimeExports.jsx("p", { className: "mb-2 px-1 text-[13px] font-medium uppercase tracking-wide", style: { color: "var(--ds-gray-700)" }, children: "Actions" }), jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [resource === "sleep" && canWakeUp && jsxRuntimeExports.jsxs("button", { type: "button", onClick: handleWakeUp, disabled: stoppingSleep, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", stoppingSleep ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
|
|
2254
|
-
background: "var(--ds-amber-200)",
|
|
2255
|
-
color: "var(--ds-amber-900)"
|
|
2256
|
-
}, children: [jsxRuntimeExports.jsx(Zap, { className: "h-4 w-4" }), stoppingSleep ? "Waking up..." : "Wake Up Sleep"] }), resource === "hook" && canResolveHook && jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setShowResolveHookModal(true), disabled: resolvingHook, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", resolvingHook ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
|
|
2257
|
-
background: "var(--ds-gray-1000)",
|
|
2258
|
-
color: "var(--ds-background-100)"
|
|
2259
|
-
}, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsx("section", { children: jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, expiredAt: run.expiredAt, isLoading: loading, error: error ?? void 0, onStreamClick, onRunClick, onDecrypt, isDecrypting, resource }) }), resource !== "run" && rawEvents && jsxRuntimeExports.jsx("section", { children: jsxRuntimeExports.jsx(EventsList, { events: rawEvents, onLoadEventData, encryptionKey }) })] })] }) }), jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: showResolveHookModal, onClose: () => setShowResolveHookModal(false), onSubmit: handleResolveHook, isSubmitting: resolvingHook })] });
|
|
2260
|
-
}
|
|
2261
|
-
const QUERY = "(prefers-reduced-motion: reduce)";
|
|
2262
|
-
const useReducedMotion = () => {
|
|
2263
|
-
const [reduced, setReduced] = reactExports.useState(() => {
|
|
2264
|
-
if (typeof window === "undefined" || !window.matchMedia)
|
|
2265
|
-
return false;
|
|
2266
|
-
return window.matchMedia(QUERY).matches;
|
|
2331
|
+
loadedDataRef.current = null;
|
|
2332
|
+
setLoadedData(null);
|
|
2333
|
+
void loadEventData({ force: true });
|
|
2334
|
+
}, [encryptionKey, loadEventData]);
|
|
2335
|
+
const createdAt = new Date(event.createdAt);
|
|
2336
|
+
const createdAtTime = createdAt.toLocaleTimeString(void 0, {
|
|
2337
|
+
hour: "numeric",
|
|
2338
|
+
minute: "numeric",
|
|
2339
|
+
second: "numeric"
|
|
2267
2340
|
});
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
media.addEventListener("change", onChange);
|
|
2274
|
-
onChange();
|
|
2275
|
-
return () => media.removeEventListener("change", onChange);
|
|
2276
|
-
}, []);
|
|
2277
|
-
return reduced;
|
|
2278
|
-
};
|
|
2279
|
-
function CopyButton({ copyText, ariaLabel, className }) {
|
|
2280
|
-
const [copied, setCopied] = reactExports.useState(false);
|
|
2281
|
-
const timeoutRef = reactExports.useRef(null);
|
|
2282
|
-
reactExports.useEffect(() => {
|
|
2283
|
-
return () => {
|
|
2284
|
-
if (timeoutRef.current) {
|
|
2285
|
-
clearTimeout(timeoutRef.current);
|
|
2286
|
-
}
|
|
2287
|
-
};
|
|
2288
|
-
}, []);
|
|
2289
|
-
return jsxRuntimeExports.jsx("button", { type: "button", "aria-label": ariaLabel, className: cn("cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-none p-1 m-0", className), onClick: (e) => {
|
|
2290
|
-
e.stopPropagation();
|
|
2291
|
-
if (timeoutRef.current) {
|
|
2292
|
-
clearTimeout(timeoutRef.current);
|
|
2293
|
-
}
|
|
2294
|
-
void navigator.clipboard.writeText(copyText).then(() => {
|
|
2295
|
-
setCopied(true);
|
|
2296
|
-
timeoutRef.current = setTimeout(() => setCopied(false), 1e3);
|
|
2297
|
-
});
|
|
2298
|
-
}, 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" }) })] }) });
|
|
2299
|
-
}
|
|
2300
|
-
const WorkflowIcon = () => {
|
|
2301
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", "stroke-linejoin": "round", style: { color: "currentColor" }, viewBox: "0 0 16 16", width: "16", children: jsxRuntimeExports.jsx("path", { d: "M5.75 7L6.4209 7.33594L4.85254 10.4717C5.38789 10.771 5.75 11.3431 5.75 12V14C5.75 14.9665 4.96648 15.75 4 15.75H2C1.03352 15.75 0.25 14.9665 0.25 14V12C0.25 11.0335 1.03352 10.25 2 10.25H3.28711L5.0791 6.66504L5.75 7ZM14 10.25C14.9665 10.25 15.75 11.0335 15.75 12V14C15.75 14.9665 14.9665 15.75 14 15.75H12C11.1185 15.75 10.3909 15.098 10.2695 14.25H7V12.75H10.25V12C10.25 11.0335 11.0335 10.25 12 10.25H14ZM2 11.75C1.86192 11.75 1.75 11.8619 1.75 12V14C1.75 14.1381 1.86192 14.25 2 14.25H4C4.13808 14.25 4.25 14.1381 4.25 14V12C4.25 11.8619 4.13808 11.75 4 11.75H2ZM12 11.75C11.8619 11.75 11.75 11.8619 11.75 12V14C11.75 14.1381 11.8619 14.25 12 14.25H14C14.1381 14.25 14.25 14.1381 14.25 14V12C14.25 11.8619 14.1381 11.75 14 11.75H12ZM9 0.25C9.96649 0.25 10.75 1.03351 10.75 2V4C10.75 4.44642 10.5808 4.85197 10.3057 5.16113L12.2041 8.6416L10.8877 9.36035L8.91895 5.75H7C6.03351 5.75 5.25 4.96649 5.25 4V2C5.25 1.03351 6.03351 0.25 7 0.25H9ZM7 1.75C6.86193 1.75 6.75 1.86193 6.75 2V4C6.75 4.13807 6.86193 4.25 7 4.25H9C9.13807 4.25 9.25 4.13807 9.25 4V2C9.25 1.86193 9.13807 1.75 9 1.75H7Z", fill: "currentColor" }) });
|
|
2302
|
-
};
|
|
2303
|
-
const WebhookIcon = () => {
|
|
2304
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", "stroke-linejoin": "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M5.8349 3.24994C5.14454 4.44567 5.55423 5.97464 6.74996 6.665L7.39465 7.03721L7.02726 7.68466L5.14599 11C5.21289 11.1531 5.25 11.3222 5.25 11.5C5.25 12.1904 4.69036 12.75 4 12.75C3.30964 12.75 2.75 12.1904 2.75 11.5C2.75 10.8634 3.22584 10.338 3.84123 10.26L5.38944 7.5316C3.95909 6.30274 3.55857 4.19264 4.53586 2.49994C5.64043 0.586765 8.08679 -0.0687357 9.99996 1.03583C11.836 2.09584 12.5137 4.39156 11.5892 6.26591L10.4949 4.33754C10.4418 3.53274 10.0009 2.76843 9.24996 2.33487C8.05423 1.64452 6.52525 2.0542 5.8349 3.24994ZM9.146 4.99996C9.21289 4.84686 9.25 4.67776 9.25 4.5C9.25 3.80964 8.69036 3.25 8 3.25C7.30964 3.25 6.75 3.80964 6.75 4.5C6.75 5.13659 7.22586 5.66203 7.84127 5.74002L9.72266 9.05556L10.0956 9.71274L10.75 9.33493C11.9457 8.64458 13.4747 9.05427 14.165 10.25C14.8554 11.4457 14.4457 12.9747 13.25 13.6651C12.5047 14.0953 11.63 14.0983 10.9096 13.75H8.69252C9.85895 15.4685 12.1727 16.0191 14 14.9641C15.9131 13.8595 16.5686 11.4132 15.4641 9.5C14.4886 7.81038 12.4665 7.10169 10.6895 7.71998L9.146 4.99996ZM13.25 11.5C13.25 12.1904 12.6904 12.75 12 12.75C11.591 12.75 11.228 12.5536 10.9999 12.25H7.9298C7.57875 14.1006 5.95279 15.5 4 15.5C1.79086 15.5 0 13.7091 0 11.5C0 9.40018 1.61801 7.67826 3.67529 7.51299L2.58098 9.44147C1.92792 9.89251 1.5 10.6463 1.5 11.5C1.5 12.8807 2.61929 14 4 14C5.38071 14 6.5 12.8807 6.5 11.5V10.75H7.25H10.9999C11.228 10.4464 11.591 10.25 12 10.25C12.6904 10.25 13.25 10.8096 13.25 11.5Z", fill: "currentColor" }) });
|
|
2305
|
-
};
|
|
2306
|
-
const SleepIcon = () => {
|
|
2307
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7.25 1.25V2.03971C5.87928 2.18571 4.62678 2.72736 3.6089 3.54824L3.03033 2.96967L2.5 2.43934L1.43934 3.5L1.96967 4.03033L2.54824 4.6089C1.57979 5.80976 1 7.33717 1 9C1 12.866 4.13401 16 8 16C11.866 16 15 12.866 15 9C15 7.33717 14.4202 5.80976 13.4518 4.6089L14.0303 4.03033L14.5607 3.5L13.5 2.43934L12.9697 2.96967L12.3911 3.54824C11.3732 2.72736 10.1207 2.18571 8.75 2.03971V1.25H9.25H10V-0.25H9.25H8.75H7.25H6.75H6V1.25H6.75H7.25ZM2.5 9C2.5 5.96243 4.96243 3.5 8 3.5C11.0376 3.5 13.5 5.96243 13.5 9C13.5 12.0376 11.0376 14.5 8 14.5C4.96243 14.5 2.5 12.0376 2.5 9ZM8.75 6.75V6H7.25V6.75V9V9.75H8.75V9V6.75Z", fill: "currentColor" }) });
|
|
2308
|
-
};
|
|
2309
|
-
const StepForwardIcon = () => {
|
|
2310
|
-
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.21969 12.5303L4.75002 13.0607L5.81068 12L5.28035 11.4697L1.81068 7.99999L5.28035 4.53032L5.81068 3.99999L4.75002 2.93933L4.21969 3.46966L0.39647 7.29289C0.00594562 7.68341 0.00594562 8.31658 0.39647 8.7071L4.21969 12.5303ZM11.7804 12.5303L11.25 13.0607L10.1894 12L10.7197 11.4697L14.1894 7.99999L10.7197 4.53032L10.1894 3.99999L11.25 2.93933L11.7804 3.46966L15.6036 7.29289C15.9941 7.68341 15.9941 8.31658 15.6036 8.7071L11.7804 12.5303Z", fill: "currentColor" }) });
|
|
2311
|
-
};
|
|
2312
|
-
const ELLIPSIS = "...";
|
|
2313
|
-
const MIN_START = 3;
|
|
2314
|
-
const MIN_END = 3;
|
|
2315
|
-
const MIN_KEPT = MIN_START + MIN_END;
|
|
2316
|
-
const graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
2317
|
-
function toGraphemes(text) {
|
|
2318
|
-
if (graphemeSegmenter) {
|
|
2319
|
-
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
2320
|
-
}
|
|
2321
|
-
return Array.from(text);
|
|
2341
|
+
const displayPayload = isLoading ? loadedData : mergedDisplay;
|
|
2342
|
+
return jsxRuntimeExports.jsxs(DetailCard, { variant: "card", summaryClassName: "px-3 py-2", summary: 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: createdAtTime })] }), onToggle: canHaveData ? (open) => {
|
|
2343
|
+
if (open)
|
|
2344
|
+
handleExpand();
|
|
2345
|
+
} : void 0, children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-col bg-background-200 [&:has(+_*)]:border-b [&:has(+_*)]:border-gray-alpha-400", children: [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 }) })] });
|
|
2322
2346
|
}
|
|
2323
|
-
function
|
|
2324
|
-
if (
|
|
2325
|
-
return
|
|
2326
|
-
prefixText: "",
|
|
2327
|
-
prefixGraphemeCount: 0,
|
|
2328
|
-
suffixText: "",
|
|
2329
|
-
suffixGraphemeCount: 0,
|
|
2330
|
-
text: ELLIPSIS,
|
|
2331
|
-
truncated: true
|
|
2332
|
-
};
|
|
2347
|
+
function hasOnlyExpiredFields(data, eventType) {
|
|
2348
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2349
|
+
return false;
|
|
2333
2350
|
}
|
|
2334
|
-
const
|
|
2335
|
-
const
|
|
2336
|
-
const
|
|
2337
|
-
|
|
2338
|
-
return {
|
|
2339
|
-
prefixText,
|
|
2340
|
-
prefixGraphemeCount,
|
|
2341
|
-
suffixText,
|
|
2342
|
-
suffixGraphemeCount,
|
|
2343
|
-
text: prefixText + ELLIPSIS + suffixText,
|
|
2344
|
-
truncated: true
|
|
2345
|
-
};
|
|
2351
|
+
const record = data;
|
|
2352
|
+
const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];
|
|
2353
|
+
const presentKeys = refKeys.filter((k) => k in record);
|
|
2354
|
+
return presentKeys.length > 0 && presentKeys.every((k) => isExpiredMarker(record[k]));
|
|
2346
2355
|
}
|
|
2347
|
-
function
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
suffixText: "",
|
|
2355
|
-
suffixGraphemeCount: 0,
|
|
2356
|
-
text: fullText,
|
|
2357
|
-
truncated: false
|
|
2358
|
-
};
|
|
2356
|
+
function EventDataBlock({ eventType, data }) {
|
|
2357
|
+
if (isExpiredMarker(data) || hasOnlyExpiredFields(data, eventType)) {
|
|
2358
|
+
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
2359
|
+
borderColor: "var(--ds-gray-300)",
|
|
2360
|
+
backgroundColor: "var(--ds-gray-100)",
|
|
2361
|
+
color: "var(--ds-gray-700)"
|
|
2362
|
+
}, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
|
|
2359
2363
|
}
|
|
2360
|
-
if (
|
|
2361
|
-
return {
|
|
2362
|
-
prefixText: fullText,
|
|
2363
|
-
prefixGraphemeCount: graphemes.length,
|
|
2364
|
-
suffixText: "",
|
|
2365
|
-
suffixGraphemeCount: 0,
|
|
2366
|
-
text: fullText,
|
|
2367
|
-
truncated: false
|
|
2368
|
-
};
|
|
2364
|
+
if (hasEncryptedFields({ eventType, eventData: data })) {
|
|
2365
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
2369
2366
|
}
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
best = mid;
|
|
2378
|
-
lo = mid + 1;
|
|
2379
|
-
} else {
|
|
2380
|
-
hi = mid - 1;
|
|
2367
|
+
if (ERROR_EVENT_TYPES.has(eventType) && data != null && typeof data === "object") {
|
|
2368
|
+
const record = data;
|
|
2369
|
+
if (isStructuredErrorWithStack(record.error)) {
|
|
2370
|
+
return jsxRuntimeExports.jsx(ErrorStackBlock, { value: record.error });
|
|
2371
|
+
}
|
|
2372
|
+
if (isStructuredErrorWithStack(record)) {
|
|
2373
|
+
return jsxRuntimeExports.jsx(ErrorStackBlock, { value: record });
|
|
2381
2374
|
}
|
|
2382
2375
|
}
|
|
2383
|
-
|
|
2384
|
-
return {
|
|
2385
|
-
prefixText: "",
|
|
2386
|
-
prefixGraphemeCount: 0,
|
|
2387
|
-
suffixText: "",
|
|
2388
|
-
suffixGraphemeCount: 0,
|
|
2389
|
-
text: "",
|
|
2390
|
-
truncated: true
|
|
2391
|
-
};
|
|
2392
|
-
}
|
|
2393
|
-
return buildCandidate(graphemes, best);
|
|
2376
|
+
return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
|
|
2394
2377
|
}
|
|
2395
|
-
function
|
|
2396
|
-
const
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
2401
|
-
return value;
|
|
2402
|
-
}
|
|
2403
|
-
const ellipsisStart = prefixText.length;
|
|
2404
|
-
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
2405
|
-
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
2406
|
-
return null;
|
|
2378
|
+
function EventsList({ events, isLoading = false, error, onLoadEventData, encryptionKey }) {
|
|
2379
|
+
const sortedEvents = reactExports.useMemo(() => [...events].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()), [events]);
|
|
2380
|
+
const hasEvents = sortedEvents.length > 0 && !error;
|
|
2381
|
+
if (!hasEvents && !isLoading) {
|
|
2382
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Events", disabled: true });
|
|
2407
2383
|
}
|
|
2408
|
-
|
|
2409
|
-
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
2410
|
-
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
2411
|
-
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
2412
|
-
return originalGraphemes.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount).join("");
|
|
2384
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Events", contentClassName: "mb-0", defaultOpen: true, 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 }, event.eventId)) }) });
|
|
2413
2385
|
}
|
|
2414
|
-
function
|
|
2415
|
-
|
|
2416
|
-
const trimmedSelectionText = selectionText.trim();
|
|
2417
|
-
if (!trimmedSelectionText) {
|
|
2418
|
-
return null;
|
|
2419
|
-
}
|
|
2420
|
-
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
2421
|
-
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
2422
|
-
if (trimmedSelectionText === visibleText) {
|
|
2423
|
-
return leading + value + trailing;
|
|
2424
|
-
}
|
|
2425
|
-
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
2426
|
-
return null;
|
|
2427
|
-
}
|
|
2428
|
-
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
2429
|
-
if (selectionStart === -1) {
|
|
2430
|
-
return null;
|
|
2431
|
-
}
|
|
2432
|
-
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
2433
|
-
const mappedText = getMiddleTruncateCopyText({
|
|
2434
|
-
prefixText,
|
|
2435
|
-
selectionEnd,
|
|
2436
|
-
selectionStart,
|
|
2437
|
-
suffixText,
|
|
2438
|
-
value
|
|
2439
|
-
});
|
|
2440
|
-
return mappedText === null ? null : leading + mappedText + trailing;
|
|
2386
|
+
function isStep(data) {
|
|
2387
|
+
return data !== null && typeof data === "object" && "stepId" in data;
|
|
2441
2388
|
}
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
return {
|
|
2445
|
-
displayText: value,
|
|
2446
|
-
isTruncated: false,
|
|
2447
|
-
prefixGraphemeCount: graphemes.length,
|
|
2448
|
-
prefixText: value,
|
|
2449
|
-
suffixGraphemeCount: 0,
|
|
2450
|
-
suffixText: ""
|
|
2451
|
-
};
|
|
2389
|
+
function isWorkflowRun(data) {
|
|
2390
|
+
return data !== null && typeof data === "object" && "runId" in data;
|
|
2452
2391
|
}
|
|
2453
|
-
function
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
const
|
|
2458
|
-
const [
|
|
2459
|
-
const
|
|
2460
|
-
const
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
return;
|
|
2392
|
+
function isHook(data) {
|
|
2393
|
+
return data !== null && typeof data === "object" && "hookId" in data;
|
|
2394
|
+
}
|
|
2395
|
+
function EntityDetailPanel({ run, onStreamClick, onRunClick, spanDetailData, spanDetailError, spanDetailLoading, onSpanSelect, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan }) {
|
|
2396
|
+
const toast2 = useToast();
|
|
2397
|
+
const [stoppingSleep, setStoppingSleep] = reactExports.useState(false);
|
|
2398
|
+
const [showResolveHookModal, setShowResolveHookModal] = reactExports.useState(false);
|
|
2399
|
+
const [resolvingHook, setResolvingHook] = reactExports.useState(false);
|
|
2400
|
+
const [resolvedHookIds, setResolvedHookIds] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
2401
|
+
const sidebar = useSidebarDataOptional();
|
|
2402
|
+
const hasEncryptedData = Boolean((sidebar == null ? void 0 : sidebar.hasEncryptedData) && !encryptionKey);
|
|
2403
|
+
const data = selectedSpan == null ? void 0 : selectedSpan.data;
|
|
2404
|
+
const rawEvents = selectedSpan == null ? void 0 : selectedSpan.rawEvents;
|
|
2405
|
+
const rawEventsLength = (rawEvents == null ? void 0 : rawEvents.length) ?? 0;
|
|
2406
|
+
const { resource, resourceId, runId } = reactExports.useMemo(() => {
|
|
2407
|
+
if (!selectedSpan) {
|
|
2408
|
+
return { resource: void 0, resourceId: void 0, runId: void 0 };
|
|
2409
|
+
}
|
|
2410
|
+
const res = selectedSpan.resource;
|
|
2411
|
+
if (res === "step" && isStep(data)) {
|
|
2412
|
+
return { resource: "step", resourceId: data.stepId, runId: data.runId };
|
|
2413
|
+
}
|
|
2414
|
+
if (res === "run" && isWorkflowRun(data)) {
|
|
2415
|
+
return { resource: "run", resourceId: data.runId, runId: void 0 };
|
|
2416
|
+
}
|
|
2417
|
+
if (res === "hook" && isHook(data)) {
|
|
2418
|
+
return { resource: "hook", resourceId: data.hookId, runId: void 0 };
|
|
2419
|
+
}
|
|
2420
|
+
if (res === "sleep") {
|
|
2421
|
+
const waitData = data;
|
|
2422
|
+
return {
|
|
2423
|
+
resource: "sleep",
|
|
2424
|
+
resourceId: selectedSpan.spanId,
|
|
2425
|
+
runId: waitData == null ? void 0 : waitData.runId
|
|
2426
|
+
};
|
|
2427
|
+
}
|
|
2428
|
+
return { resource: void 0, resourceId: void 0, runId: void 0 };
|
|
2429
|
+
}, [selectedSpan, data]);
|
|
2430
|
+
const onSpanSelectRef = reactExports.useRef(onSpanSelect);
|
|
2431
|
+
onSpanSelectRef.current = onSpanSelect;
|
|
2432
|
+
reactExports.useEffect(() => {
|
|
2433
|
+
if (resource && resourceId && ["run", "step", "hook", "sleep"].includes(resource)) {
|
|
2434
|
+
onSpanSelectRef.current({
|
|
2435
|
+
resource,
|
|
2436
|
+
resourceId,
|
|
2437
|
+
runId
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
}, [resource, resourceId, runId]);
|
|
2441
|
+
const canWakeUp = reactExports.useMemo(() => {
|
|
2442
|
+
if (resource !== "sleep" || !rawEvents)
|
|
2443
|
+
return false;
|
|
2444
|
+
const terminalStates = ["completed", "failed", "cancelled"];
|
|
2445
|
+
if (terminalStates.includes(run.status))
|
|
2446
|
+
return false;
|
|
2447
|
+
const hasWaitCreated = rawEvents.some((e) => e.eventType === "wait_created");
|
|
2448
|
+
if (!hasWaitCreated)
|
|
2449
|
+
return false;
|
|
2450
|
+
const hasWaitCompleted = rawEvents.some((e) => e.eventType === "wait_completed");
|
|
2451
|
+
return !hasWaitCompleted;
|
|
2452
|
+
}, [resource, rawEvents, rawEventsLength, run.status]);
|
|
2453
|
+
const canResolveHook = reactExports.useMemo(() => {
|
|
2454
|
+
if (resource !== "hook" || !rawEvents || !resourceId)
|
|
2455
|
+
return false;
|
|
2456
|
+
if (resolvedHookIds.has(resourceId))
|
|
2457
|
+
return false;
|
|
2458
|
+
const terminalStates = ["completed", "failed", "cancelled"];
|
|
2459
|
+
if (terminalStates.includes(run.status))
|
|
2460
|
+
return false;
|
|
2461
|
+
const hasHookDisposed = rawEvents.some((e) => e.eventType === "hook_disposed");
|
|
2462
|
+
if (hasHookDisposed)
|
|
2463
|
+
return false;
|
|
2464
|
+
return true;
|
|
2465
|
+
}, [
|
|
2466
|
+
resource,
|
|
2467
|
+
resourceId,
|
|
2468
|
+
rawEvents,
|
|
2469
|
+
rawEventsLength,
|
|
2470
|
+
run.status,
|
|
2471
|
+
resolvedHookIds
|
|
2472
|
+
]);
|
|
2473
|
+
const error = spanDetailError ?? void 0;
|
|
2474
|
+
const loading = spanDetailLoading ?? false;
|
|
2475
|
+
const hookToken = reactExports.useMemo(() => {
|
|
2476
|
+
if (resource !== "hook" || !resourceId)
|
|
2477
|
+
return void 0;
|
|
2478
|
+
if (isHook(spanDetailData) && spanDetailData.token) {
|
|
2479
|
+
return spanDetailData.token;
|
|
2477
2480
|
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
return measureEl.scrollWidth;
|
|
2481
|
-
};
|
|
2482
|
-
const fullWidth = measure(value);
|
|
2483
|
-
if (fullWidth <= available) {
|
|
2484
|
-
updateState(fullState);
|
|
2485
|
-
return;
|
|
2481
|
+
if (isHook(data) && data.token) {
|
|
2482
|
+
return data.token;
|
|
2486
2483
|
}
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
displayText: result.text,
|
|
2490
|
-
isTruncated: result.truncated,
|
|
2491
|
-
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
2492
|
-
prefixText: result.prefixText,
|
|
2493
|
-
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
2494
|
-
suffixText: result.suffixText
|
|
2495
|
-
});
|
|
2496
|
-
}, [fullState, graphemes, updateState, value]);
|
|
2497
|
-
useIsomorphicLayoutEffect(() => {
|
|
2498
|
-
recalculate();
|
|
2499
|
-
}, [recalculate]);
|
|
2484
|
+
return void 0;
|
|
2485
|
+
}, [resource, resourceId, spanDetailData, data]);
|
|
2500
2486
|
reactExports.useEffect(() => {
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2487
|
+
if (error && selectedSpan && resource) {
|
|
2488
|
+
toast2.error(`Failed to load ${resource} details`, {
|
|
2489
|
+
description: error.message
|
|
2490
|
+
});
|
|
2491
|
+
}
|
|
2492
|
+
}, [error, resource, selectedSpan]);
|
|
2493
|
+
const handleWakeUp = async () => {
|
|
2494
|
+
if (stoppingSleep || !resourceId)
|
|
2504
2495
|
return;
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
prefixText: state.prefixText,
|
|
2532
|
-
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
2533
|
-
suffixText: state.suffixText
|
|
2534
|
-
};
|
|
2535
|
-
}
|
|
2536
|
-
function getRangeOffsets(container, range) {
|
|
2537
|
-
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) {
|
|
2538
|
-
return null;
|
|
2539
|
-
}
|
|
2540
|
-
const startRange = document.createRange();
|
|
2541
|
-
startRange.selectNodeContents(container);
|
|
2542
|
-
startRange.setEnd(range.startContainer, range.startOffset);
|
|
2543
|
-
const endRange = document.createRange();
|
|
2544
|
-
endRange.selectNodeContents(container);
|
|
2545
|
-
endRange.setEnd(range.endContainer, range.endOffset);
|
|
2546
|
-
return {
|
|
2547
|
-
end: endRange.toString().length,
|
|
2548
|
-
start: startRange.toString().length
|
|
2496
|
+
if (!onWakeUpSleep) {
|
|
2497
|
+
toast2.error("Unable to wake up sleep", {
|
|
2498
|
+
description: "No wake-up handler provided."
|
|
2499
|
+
});
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
try {
|
|
2503
|
+
setStoppingSleep(true);
|
|
2504
|
+
const result = await onWakeUpSleep(run.runId, resourceId);
|
|
2505
|
+
if (result.stoppedCount > 0) {
|
|
2506
|
+
toast2.success("Run woken up", {
|
|
2507
|
+
description: "The sleep call has been interrupted and the run woken up."
|
|
2508
|
+
});
|
|
2509
|
+
} else {
|
|
2510
|
+
toast2.info("Sleep already completed", {
|
|
2511
|
+
description: "This sleep call has already finished."
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
} catch (err) {
|
|
2515
|
+
console.error("Failed to wake up run:", err);
|
|
2516
|
+
toast2.error("Failed to wake up run", {
|
|
2517
|
+
description: err instanceof Error ? err.message : "An unknown error occurred"
|
|
2518
|
+
});
|
|
2519
|
+
} finally {
|
|
2520
|
+
setStoppingSleep(false);
|
|
2521
|
+
}
|
|
2549
2522
|
};
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
2553
|
-
const visibleRef = reactExports.useRef(null);
|
|
2554
|
-
const handleCopy = reactExports.useCallback((e) => {
|
|
2555
|
-
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
2556
|
-
if (e.defaultPrevented || !isTruncated)
|
|
2523
|
+
const handleResolveHook = reactExports.useCallback(async (payload) => {
|
|
2524
|
+
if (resolvingHook)
|
|
2557
2525
|
return;
|
|
2558
|
-
|
|
2559
|
-
|
|
2526
|
+
if (!onResolveHook) {
|
|
2527
|
+
toast2.error("Unable to resolve hook", {
|
|
2528
|
+
description: "No resolve handler provided."
|
|
2529
|
+
});
|
|
2560
2530
|
return;
|
|
2561
|
-
|
|
2562
|
-
if (!
|
|
2531
|
+
}
|
|
2532
|
+
if (!hookToken) {
|
|
2533
|
+
toast2.error("Unable to resolve hook", {
|
|
2534
|
+
description: "Missing hook token. Try refreshing the run data and retry."
|
|
2535
|
+
});
|
|
2563
2536
|
return;
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
});
|
|
2537
|
+
}
|
|
2538
|
+
try {
|
|
2539
|
+
setResolvingHook(true);
|
|
2540
|
+
const candidate = spanDetailData ?? data;
|
|
2541
|
+
const hook = isHook(candidate) ? candidate : void 0;
|
|
2542
|
+
await onResolveHook(hookToken, payload, hook);
|
|
2543
|
+
toast2.success("Hook resolved", {
|
|
2544
|
+
description: "The payload has been sent and the hook resolved."
|
|
2545
|
+
});
|
|
2546
|
+
setShowResolveHookModal(false);
|
|
2547
|
+
if (resourceId) {
|
|
2548
|
+
setResolvedHookIds((prev) => new Set(prev).add(resourceId));
|
|
2577
2549
|
}
|
|
2550
|
+
} catch (err) {
|
|
2551
|
+
console.error("Failed to resolve hook:", err);
|
|
2552
|
+
toast2.error("Failed to resolve hook", {
|
|
2553
|
+
description: err instanceof Error ? err.message : "An unknown error occurred"
|
|
2554
|
+
});
|
|
2555
|
+
} finally {
|
|
2556
|
+
setResolvingHook(false);
|
|
2578
2557
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
if (
|
|
2586
|
-
return;
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2558
|
+
}, [onResolveHook, hookToken, resolvingHook, spanDetailData, data]);
|
|
2559
|
+
const displayData = spanDetailData ?? data;
|
|
2560
|
+
const moduleSpecifier = reactExports.useMemo(() => {
|
|
2561
|
+
const displayRecord = displayData;
|
|
2562
|
+
const displayStepName = displayRecord.stepName;
|
|
2563
|
+
const displayWorkflowName = displayRecord.workflowName;
|
|
2564
|
+
if (typeof displayStepName === "string") {
|
|
2565
|
+
return displayStepName;
|
|
2566
|
+
}
|
|
2567
|
+
if (typeof displayWorkflowName === "string") {
|
|
2568
|
+
return displayWorkflowName;
|
|
2569
|
+
}
|
|
2570
|
+
if (typeof run.workflowName === "string") {
|
|
2571
|
+
return run.workflowName;
|
|
2572
|
+
}
|
|
2573
|
+
return void 0;
|
|
2574
|
+
}, [displayData, run.workflowName]);
|
|
2575
|
+
if (!selectedSpan || !resource || !resourceId) {
|
|
2576
|
+
return null;
|
|
2577
|
+
}
|
|
2578
|
+
const hasPendingActions = resource === "sleep" && canWakeUp || resource === "hook" && canResolveHook;
|
|
2579
|
+
return jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col", children: [jsxRuntimeExports.jsx(DecryptClickContext.Provider, { value: onDecrypt ? { onDecrypt, isDecrypting, hasEncryptedData } : void 0, children: jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto px-4 pb-8", children: [hasPendingActions && jsxRuntimeExports.jsxs("div", { className: "mb-4 rounded-lg border p-2", style: {
|
|
2580
|
+
borderColor: "var(--ds-gray-300)",
|
|
2581
|
+
backgroundColor: "var(--ds-gray-100)"
|
|
2582
|
+
}, children: [jsxRuntimeExports.jsx("p", { className: "mb-2 px-1 text-[13px] font-medium uppercase tracking-wide", style: { color: "var(--ds-gray-700)" }, children: "Actions" }), jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [resource === "sleep" && canWakeUp && jsxRuntimeExports.jsxs("button", { type: "button", onClick: handleWakeUp, disabled: stoppingSleep, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", stoppingSleep ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
|
|
2583
|
+
background: "var(--ds-amber-200)",
|
|
2584
|
+
color: "var(--ds-amber-900)"
|
|
2585
|
+
}, children: [jsxRuntimeExports.jsx(Zap, { className: "h-4 w-4" }), stoppingSleep ? "Waking up..." : "Wake Up Sleep"] }), resource === "hook" && canResolveHook && jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setShowResolveHookModal(true), disabled: resolvingHook, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", resolvingHook ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
|
|
2586
|
+
background: "var(--ds-gray-1000)",
|
|
2587
|
+
color: "var(--ds-background-100)"
|
|
2588
|
+
}, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, expiredAt: run.expiredAt, isLoading: loading, error: error ?? void 0, onStreamClick, onRunClick, onDecrypt, isDecrypting, resource }), resource !== "run" && rawEvents && jsxRuntimeExports.jsx(EventsList, { events: rawEvents, onLoadEventData, encryptionKey })] }) }), jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: showResolveHookModal, onClose: () => setShowResolveHookModal(false), onSubmit: handleResolveHook, isSubmitting: resolvingHook })] });
|
|
2589
|
+
}
|
|
2590
|
+
const iconButtonVariants = cva([
|
|
2591
|
+
"m-0 inline-flex shrink-0 appearance-none items-center justify-center border-0 bg-transparent p-0 align-baseline font-inherit no-underline [background:none] [-webkit-appearance:none] [-webkit-tap-highlight-color:transparent]",
|
|
2592
|
+
"transition-colors duration-150 ease-in-out",
|
|
2593
|
+
"enabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-40",
|
|
2594
|
+
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] focus-visible:outline-offset-2"
|
|
2595
|
+
], {
|
|
2596
|
+
variants: {
|
|
2597
|
+
variant: {
|
|
2598
|
+
tertiary: "text-gray-900 enabled:hover:bg-gray-alpha-200 enabled:hover:text-gray-1000 enabled:active:bg-gray-alpha-200 focus-visible:text-gray-1000",
|
|
2599
|
+
muted: "text-gray-900 enabled:hover:bg-gray-alpha-200 enabled:hover:text-gray-1000 enabled:active:bg-gray-alpha-200 focus-visible:text-gray-1000"
|
|
2600
|
+
},
|
|
2601
|
+
size: {
|
|
2602
|
+
tiny: "h-6 w-6 rounded-[4px] [&_svg]:h-4 [&_svg]:w-4",
|
|
2603
|
+
small: "h-8 w-8 rounded-md [&_svg]:h-4 [&_svg]:w-4"
|
|
2604
|
+
}
|
|
2605
|
+
},
|
|
2606
|
+
defaultVariants: {
|
|
2607
|
+
variant: "tertiary",
|
|
2608
|
+
size: "tiny"
|
|
2609
|
+
}
|
|
2610
|
+
});
|
|
2611
|
+
function IconButton({ className, variant, size, type = "button", ...props }) {
|
|
2612
|
+
return jsxRuntimeExports.jsx("button", { type, className: cn(iconButtonVariants({ variant, size, className })), ...props });
|
|
2591
2613
|
}
|
|
2614
|
+
const QUERY = "(prefers-reduced-motion: reduce)";
|
|
2615
|
+
const useReducedMotion = () => {
|
|
2616
|
+
const [reduced, setReduced] = reactExports.useState(() => {
|
|
2617
|
+
if (typeof window === "undefined" || !window.matchMedia)
|
|
2618
|
+
return false;
|
|
2619
|
+
return window.matchMedia(QUERY).matches;
|
|
2620
|
+
});
|
|
2621
|
+
reactExports.useEffect(() => {
|
|
2622
|
+
if (typeof window === "undefined" || !window.matchMedia)
|
|
2623
|
+
return;
|
|
2624
|
+
const media = window.matchMedia(QUERY);
|
|
2625
|
+
const onChange = () => setReduced(media.matches);
|
|
2626
|
+
media.addEventListener("change", onChange);
|
|
2627
|
+
onChange();
|
|
2628
|
+
return () => media.removeEventListener("change", onChange);
|
|
2629
|
+
}, []);
|
|
2630
|
+
return reduced;
|
|
2631
|
+
};
|
|
2632
|
+
const WorkflowIcon = () => {
|
|
2633
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", "stroke-linejoin": "round", style: { color: "currentColor" }, viewBox: "0 0 16 16", width: "16", children: jsxRuntimeExports.jsx("path", { d: "M5.75 7L6.4209 7.33594L4.85254 10.4717C5.38789 10.771 5.75 11.3431 5.75 12V14C5.75 14.9665 4.96648 15.75 4 15.75H2C1.03352 15.75 0.25 14.9665 0.25 14V12C0.25 11.0335 1.03352 10.25 2 10.25H3.28711L5.0791 6.66504L5.75 7ZM14 10.25C14.9665 10.25 15.75 11.0335 15.75 12V14C15.75 14.9665 14.9665 15.75 14 15.75H12C11.1185 15.75 10.3909 15.098 10.2695 14.25H7V12.75H10.25V12C10.25 11.0335 11.0335 10.25 12 10.25H14ZM2 11.75C1.86192 11.75 1.75 11.8619 1.75 12V14C1.75 14.1381 1.86192 14.25 2 14.25H4C4.13808 14.25 4.25 14.1381 4.25 14V12C4.25 11.8619 4.13808 11.75 4 11.75H2ZM12 11.75C11.8619 11.75 11.75 11.8619 11.75 12V14C11.75 14.1381 11.8619 14.25 12 14.25H14C14.1381 14.25 14.25 14.1381 14.25 14V12C14.25 11.8619 14.1381 11.75 14 11.75H12ZM9 0.25C9.96649 0.25 10.75 1.03351 10.75 2V4C10.75 4.44642 10.5808 4.85197 10.3057 5.16113L12.2041 8.6416L10.8877 9.36035L8.91895 5.75H7C6.03351 5.75 5.25 4.96649 5.25 4V2C5.25 1.03351 6.03351 0.25 7 0.25H9ZM7 1.75C6.86193 1.75 6.75 1.86193 6.75 2V4C6.75 4.13807 6.86193 4.25 7 4.25H9C9.13807 4.25 9.25 4.13807 9.25 4V2C9.25 1.86193 9.13807 1.75 9 1.75H7Z", fill: "currentColor" }) });
|
|
2634
|
+
};
|
|
2635
|
+
const WebhookIcon = () => {
|
|
2636
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", "stroke-linejoin": "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M5.8349 3.24994C5.14454 4.44567 5.55423 5.97464 6.74996 6.665L7.39465 7.03721L7.02726 7.68466L5.14599 11C5.21289 11.1531 5.25 11.3222 5.25 11.5C5.25 12.1904 4.69036 12.75 4 12.75C3.30964 12.75 2.75 12.1904 2.75 11.5C2.75 10.8634 3.22584 10.338 3.84123 10.26L5.38944 7.5316C3.95909 6.30274 3.55857 4.19264 4.53586 2.49994C5.64043 0.586765 8.08679 -0.0687357 9.99996 1.03583C11.836 2.09584 12.5137 4.39156 11.5892 6.26591L10.4949 4.33754C10.4418 3.53274 10.0009 2.76843 9.24996 2.33487C8.05423 1.64452 6.52525 2.0542 5.8349 3.24994ZM9.146 4.99996C9.21289 4.84686 9.25 4.67776 9.25 4.5C9.25 3.80964 8.69036 3.25 8 3.25C7.30964 3.25 6.75 3.80964 6.75 4.5C6.75 5.13659 7.22586 5.66203 7.84127 5.74002L9.72266 9.05556L10.0956 9.71274L10.75 9.33493C11.9457 8.64458 13.4747 9.05427 14.165 10.25C14.8554 11.4457 14.4457 12.9747 13.25 13.6651C12.5047 14.0953 11.63 14.0983 10.9096 13.75H8.69252C9.85895 15.4685 12.1727 16.0191 14 14.9641C15.9131 13.8595 16.5686 11.4132 15.4641 9.5C14.4886 7.81038 12.4665 7.10169 10.6895 7.71998L9.146 4.99996ZM13.25 11.5C13.25 12.1904 12.6904 12.75 12 12.75C11.591 12.75 11.228 12.5536 10.9999 12.25H7.9298C7.57875 14.1006 5.95279 15.5 4 15.5C1.79086 15.5 0 13.7091 0 11.5C0 9.40018 1.61801 7.67826 3.67529 7.51299L2.58098 9.44147C1.92792 9.89251 1.5 10.6463 1.5 11.5C1.5 12.8807 2.61929 14 4 14C5.38071 14 6.5 12.8807 6.5 11.5V10.75H7.25H10.9999C11.228 10.4464 11.591 10.25 12 10.25C12.6904 10.25 13.25 10.8096 13.25 11.5Z", fill: "currentColor" }) });
|
|
2637
|
+
};
|
|
2638
|
+
const SleepIcon = () => {
|
|
2639
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7.25 1.25V2.03971C5.87928 2.18571 4.62678 2.72736 3.6089 3.54824L3.03033 2.96967L2.5 2.43934L1.43934 3.5L1.96967 4.03033L2.54824 4.6089C1.57979 5.80976 1 7.33717 1 9C1 12.866 4.13401 16 8 16C11.866 16 15 12.866 15 9C15 7.33717 14.4202 5.80976 13.4518 4.6089L14.0303 4.03033L14.5607 3.5L13.5 2.43934L12.9697 2.96967L12.3911 3.54824C11.3732 2.72736 10.1207 2.18571 8.75 2.03971V1.25H9.25H10V-0.25H9.25H8.75H7.25H6.75H6V1.25H6.75H7.25ZM2.5 9C2.5 5.96243 4.96243 3.5 8 3.5C11.0376 3.5 13.5 5.96243 13.5 9C13.5 12.0376 11.0376 14.5 8 14.5C4.96243 14.5 2.5 12.0376 2.5 9ZM8.75 6.75V6H7.25V6.75V9V9.75H8.75V9V6.75Z", fill: "currentColor" }) });
|
|
2640
|
+
};
|
|
2641
|
+
const StepForwardIcon = () => {
|
|
2642
|
+
return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", viewBox: "0 0 16 16", width: "16", style: { color: "currentColor" }, children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.21969 12.5303L4.75002 13.0607L5.81068 12L5.28035 11.4697L1.81068 7.99999L5.28035 4.53032L5.81068 3.99999L4.75002 2.93933L4.21969 3.46966L0.39647 7.29289C0.00594562 7.68341 0.00594562 8.31658 0.39647 8.7071L4.21969 12.5303ZM11.7804 12.5303L11.25 13.0607L10.1894 12L10.7197 11.4697L14.1894 7.99999L10.7197 4.53032L10.1894 3.99999L11.25 2.93933L11.7804 3.46966L15.6036 7.29289C15.9941 7.68341 15.9941 8.31658 15.6036 8.7071L11.7804 12.5303Z", fill: "currentColor" }) });
|
|
2643
|
+
};
|
|
2592
2644
|
const eventStyles = {
|
|
2593
2645
|
run: { icon: WorkflowIcon, className: "text-blue-900" },
|
|
2594
2646
|
step: { icon: StepForwardIcon, className: "text-green-900" },
|
|
@@ -2607,15 +2659,15 @@ function getEventStyle(resource, isErrored) {
|
|
|
2607
2659
|
className: cn(isErrored ? "text-red-900" : style.className)
|
|
2608
2660
|
};
|
|
2609
2661
|
}
|
|
2610
|
-
const EventRow = ({ span, isSelected, onSelectSpan }) => {
|
|
2662
|
+
const EventRow = ({ span, isSelected, isDimmed, onSelectSpan }) => {
|
|
2611
2663
|
const durationMs = getSpanDurationMs(span);
|
|
2612
2664
|
const isErrored = span.attributes.data.status === "failed";
|
|
2613
2665
|
const { icon: Icon, className: tagClassName } = getEventStyle(span.resource, isErrored);
|
|
2614
|
-
return jsxRuntimeExports.jsx("li", { className: cn("relative overflow-clip group
|
|
2666
|
+
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: formatDuration(durationMs) }) })] }) }) });
|
|
2615
2667
|
};
|
|
2616
|
-
const EventList = ({ spans, activeSpanId, onSelectSpan }) => {
|
|
2617
|
-
return jsxRuntimeExports.jsx("ul", { id: "event-list", role: "tree", className: "block min-h-0 overflow-visible", children: spans.map((span) => {
|
|
2618
|
-
return jsxRuntimeExports.jsx(EventRow, { span, isSelected: span.spanId === activeSpanId, onSelectSpan }, span.spanId);
|
|
2668
|
+
const EventList = ({ spans, activeSpanId, searchResult, onSelectSpan }) => {
|
|
2669
|
+
return jsxRuntimeExports.jsx("ul", { id: "event-list", role: "tree", className: "block min-h-0 overflow-visible divide-y divide-gray-alpha-400 border-b border-gray-alpha-400", children: spans.map((span) => {
|
|
2670
|
+
return jsxRuntimeExports.jsx(EventRow, { span, isSelected: span.spanId === activeSpanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelectSpan }, span.spanId);
|
|
2619
2671
|
}) });
|
|
2620
2672
|
};
|
|
2621
2673
|
const GUTTER_PX = 1;
|
|
@@ -2713,7 +2765,7 @@ function DetailPanel({ span, rootStart, onClose }) {
|
|
|
2713
2765
|
const startMs = getHighResInMs(span.startTime);
|
|
2714
2766
|
const durationMs = getSpanDurationMs(span);
|
|
2715
2767
|
const offsetMs = startMs - rootStart;
|
|
2716
|
-
return jsxRuntimeExports.jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), jsxRuntimeExports.jsx(
|
|
2768
|
+
return jsxRuntimeExports.jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Close span details", onClick: onClose, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] }), jsxRuntimeExports.jsx("div", { className: "overflow-y-auto p-3 space-y-3", children: jsxRuntimeExports.jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm", children: [jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Resource" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 font-mono", children: span.resource }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Duration" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 tabular-nums font-mono", children: formatDuration(durationMs) }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Offset" }), jsxRuntimeExports.jsxs("dd", { className: "text-gray-1000 tabular-nums font-mono", children: ["+", formatDuration(offsetMs)] }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Status" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 font-mono", children: span.status.code === 2 ? "Error" : "OK" })] }) })] });
|
|
2717
2769
|
}
|
|
2718
2770
|
const MIN_VIEWPORT_MS = 1e-3;
|
|
2719
2771
|
function useAnimatedViewport(initial) {
|
|
@@ -2783,7 +2835,7 @@ function useSelectedSpanInfo() {
|
|
|
2783
2835
|
spanId: activeSpan.spanId,
|
|
2784
2836
|
rawEvents
|
|
2785
2837
|
};
|
|
2786
|
-
}, [activeSpan, sidebar
|
|
2838
|
+
}, [activeSpan, sidebar]);
|
|
2787
2839
|
}
|
|
2788
2840
|
function NewTraceViewer$1({ trace }) {
|
|
2789
2841
|
return jsxRuntimeExports.jsx(ActiveSpanProvider, { spans: trace.spans, children: jsxRuntimeExports.jsx(NewTraceViewerContent, { trace }) });
|
|
@@ -2793,12 +2845,8 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2793
2845
|
const sidebar = useSidebarDataOptional();
|
|
2794
2846
|
const selectedSpan = useSelectedSpanInfo();
|
|
2795
2847
|
const [searchQuery, setSearchQuery] = reactExports.useState("");
|
|
2796
|
-
const
|
|
2797
|
-
|
|
2798
|
-
if (!q)
|
|
2799
|
-
return trace.spans;
|
|
2800
|
-
return trace.spans.filter((s) => s.name.toLowerCase().includes(q) || s.resource.toLowerCase().includes(q));
|
|
2801
|
-
}, [trace.spans, searchQuery]);
|
|
2848
|
+
const deferredSearchQuery = reactExports.useDeferredValue(searchQuery);
|
|
2849
|
+
const searchResult = reactExports.useMemo(() => searchSpans(trace.spans, deferredSearchQuery), [trace.spans, deferredSearchQuery]);
|
|
2802
2850
|
const root = reactExports.useMemo(() => computeRootBounds(trace.spans), [trace.spans]);
|
|
2803
2851
|
const { viewport, setViewport, animateTo } = useAnimatedViewport({
|
|
2804
2852
|
start: root.startTime,
|
|
@@ -2820,7 +2868,7 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2820
2868
|
return prev;
|
|
2821
2869
|
});
|
|
2822
2870
|
prevRootRef.current = { start: newStart, end: newEnd };
|
|
2823
|
-
}, [root.startTime, root.duration]);
|
|
2871
|
+
}, [root.startTime, root.duration, setViewport]);
|
|
2824
2872
|
const viewDuration = viewport.end - viewport.start;
|
|
2825
2873
|
const timeMarkers = reactExports.useMemo(() => computeTimeMarkers(viewDuration, viewport.start - root.startTime), [viewDuration, viewport.start, root.startTime]);
|
|
2826
2874
|
const resetZoom = reactExports.useCallback(() => {
|
|
@@ -2899,13 +2947,25 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2899
2947
|
]);
|
|
2900
2948
|
const [altHeld, setAltHeld] = reactExports.useState(false);
|
|
2901
2949
|
reactExports.useEffect(() => {
|
|
2950
|
+
const handleSidebarNavKey = (e) => {
|
|
2951
|
+
const target = e.target;
|
|
2952
|
+
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || (target == null ? void 0 : target.isContentEditable)) {
|
|
2953
|
+
return;
|
|
2954
|
+
}
|
|
2955
|
+
const targetId = e.key === "k" ? prevSpanIdRef.current : nextSpanIdRef.current;
|
|
2956
|
+
if (targetId) {
|
|
2957
|
+
e.preventDefault();
|
|
2958
|
+
handleSelectSpanRef.current(targetId);
|
|
2959
|
+
}
|
|
2960
|
+
};
|
|
2902
2961
|
const onKeyDown = (e) => {
|
|
2903
2962
|
if (e.key === "Escape") {
|
|
2904
2963
|
clearActiveSpan();
|
|
2905
|
-
}
|
|
2906
|
-
if (e.key === "Alt") {
|
|
2964
|
+
} else if (e.key === "Alt") {
|
|
2907
2965
|
e.preventDefault();
|
|
2908
2966
|
setAltHeld(true);
|
|
2967
|
+
} else if (e.key === "j" || e.key === "k") {
|
|
2968
|
+
handleSidebarNavKey(e);
|
|
2909
2969
|
}
|
|
2910
2970
|
};
|
|
2911
2971
|
const onKeyUp = (e) => {
|
|
@@ -2969,7 +3029,8 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2969
3029
|
if (e.deltaMode === 1)
|
|
2970
3030
|
dy *= 16;
|
|
2971
3031
|
const cursorFraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
|
|
2972
|
-
const
|
|
3032
|
+
const isMouseWheel = e.deltaMode === 1 || Math.abs(e.deltaY) >= 50;
|
|
3033
|
+
const scaleFactor = Math.pow(2, dy / (isMouseWheel ? 200 : 60));
|
|
2973
3034
|
setViewport((prev) => {
|
|
2974
3035
|
const prevDuration = prev.end - prev.start;
|
|
2975
3036
|
const cursorTime = prev.start + cursorFraction * prevDuration;
|
|
@@ -3009,7 +3070,7 @@ function NewTraceViewerContent({ trace }) {
|
|
|
3009
3070
|
};
|
|
3010
3071
|
el.addEventListener("wheel", onWheel, { passive: false });
|
|
3011
3072
|
return () => el.removeEventListener("wheel", onWheel);
|
|
3012
|
-
}, [root.startTime, root.duration]);
|
|
3073
|
+
}, [root.startTime, root.duration, setViewport]);
|
|
3013
3074
|
const selectedSpanName = reactExports.useMemo(() => {
|
|
3014
3075
|
var _a, _b;
|
|
3015
3076
|
if (!(selectedSpan == null ? void 0 : selectedSpan.data))
|
|
@@ -3022,17 +3083,39 @@ function NewTraceViewerContent({ trace }) {
|
|
|
3022
3083
|
const workflowName = data.workflowName;
|
|
3023
3084
|
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";
|
|
3024
3085
|
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource]);
|
|
3025
|
-
const
|
|
3026
|
-
|
|
3027
|
-
if (!
|
|
3028
|
-
return
|
|
3029
|
-
const
|
|
3030
|
-
if (
|
|
3031
|
-
return
|
|
3086
|
+
const { prevSpanId, nextSpanId } = reactExports.useMemo(() => {
|
|
3087
|
+
var _a, _b;
|
|
3088
|
+
if (!activeSpanId)
|
|
3089
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3090
|
+
const i = trace.spans.findIndex((s) => s.spanId === activeSpanId);
|
|
3091
|
+
if (i === -1)
|
|
3092
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3093
|
+
return {
|
|
3094
|
+
prevSpanId: ((_a = trace.spans[i - 1]) == null ? void 0 : _a.spanId) ?? null,
|
|
3095
|
+
nextSpanId: ((_b = trace.spans[i + 1]) == null ? void 0 : _b.spanId) ?? null
|
|
3096
|
+
};
|
|
3097
|
+
}, [activeSpanId, trace.spans]);
|
|
3098
|
+
const handleSelectPrevSpan = reactExports.useCallback(() => {
|
|
3099
|
+
if (prevSpanId)
|
|
3100
|
+
handleSelectSpan(prevSpanId);
|
|
3101
|
+
}, [prevSpanId, handleSelectSpan]);
|
|
3102
|
+
const handleSelectNextSpan = reactExports.useCallback(() => {
|
|
3103
|
+
if (nextSpanId)
|
|
3104
|
+
handleSelectSpan(nextSpanId);
|
|
3105
|
+
}, [nextSpanId, handleSelectSpan]);
|
|
3106
|
+
const prevSpanIdRef = reactExports.useRef(prevSpanId);
|
|
3107
|
+
const nextSpanIdRef = reactExports.useRef(nextSpanId);
|
|
3108
|
+
const handleSelectSpanRef = reactExports.useRef(handleSelectSpan);
|
|
3109
|
+
prevSpanIdRef.current = prevSpanId;
|
|
3110
|
+
nextSpanIdRef.current = nextSpanId;
|
|
3111
|
+
handleSelectSpanRef.current = handleSelectSpan;
|
|
3112
|
+
return jsxRuntimeExports.jsxs("div", { "data-pane": "pane-root", "data-has-detail": activeSpan ? "" : void 0, className: "grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsxs(SplitPane, { startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center 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) => {
|
|
3113
|
+
if (e.key === "Escape" && searchQuery) {
|
|
3114
|
+
e.preventDefault();
|
|
3115
|
+
e.stopPropagation();
|
|
3116
|
+
setSearchQuery("");
|
|
3032
3117
|
}
|
|
3033
|
-
|
|
3034
|
-
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource, selectedSpan == null ? void 0 : selectedSpan.spanId]);
|
|
3035
|
-
return jsxRuntimeExports.jsxs("div", { "data-pane": "pane-root", "data-has-detail": activeSpan ? "" : void 0, className: "grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsxs(SplitPane, { startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center px-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", onClick: () => setSearchQuery(""), className: "shrink-0 p-0.5 rounded-sm text-gray-800 hover:text-gray-1000 hover:bg-gray-200 transition-colors", children: jsxRuntimeExports.jsx(X, { className: "w-3 h-3" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo }), children: [jsxRuntimeExports.jsx("div", { className: "block overflow-visible", children: jsxRuntimeExports.jsx(EventList, { spans: filteredSpans, activeSpanId, onSelectSpan: handleSelectSpan }) }), jsxRuntimeExports.jsx("div", { ref: timelineRef, className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: filteredSpans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, onSelect: handleSelectSpan, hoverFraction, altHeld }) })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-lg bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[time:120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100", onClick: zoomOut, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[time:120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[time:120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100", onClick: zoomIn, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan && sidebar ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 px-4 pt-4 pb-3", children: jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntimeExports.jsx("span", { className: "text-[15px] font-semibold text-gray-1000 truncate block", children: selectedSpanName }), selectedResourceId && jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center gap-2", children: [selectedResource && jsxRuntimeExports.jsx("span", { className: `inline-flex items-center rounded-md px-1.5 py-0.5 text-[11px] font-medium leading-none shrink-0 ${selectedResource === "step" ? "bg-green-200 text-green-900" : selectedResource === "run" ? "bg-blue-200 text-blue-900" : "bg-gray-200 text-gray-900"}`, children: selectedResource.charAt(0).toUpperCase() + selectedResource.slice(1) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 text-[13px] font-mono text-gray-700 min-w-0", title: selectedResourceId, children: [jsxRuntimeExports.jsx("span", { className: "truncate", children: selectedResourceId }), jsxRuntimeExports.jsx(CopyButton, { copyText: selectedResourceId, ariaLabel: "Copy ID", className: "shrink-0" })] })] })] }), jsxRuntimeExports.jsx("button", { type: "button", className: "p-1 rounded-md text-gray-900 hover:text-gray-1000 hover:bg-gray-alpha-200 transition-colors shrink-0", onClick: clearActiveSpan, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] }) }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan }) }) })] }) : activeSpan ? jsxRuntimeExports.jsx(DetailPanel, { span: activeSpan, rootStart: root.startTime, onClose: clearActiveSpan }) : null] });
|
|
3118
|
+
}, 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", { className: "inline-flex h-5 min-h-5 min-w-5 items-center justify-center rounded border border-gray-alpha-400 bg-background-100 px-1 font-sans text-[13px] font-medium leading-[1.7em] text-gray-900", children: "Esc" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo }), children: [jsxRuntimeExports.jsx("div", { className: "block overflow-visible", children: jsxRuntimeExports.jsx(EventList, { spans: trace.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }) }), jsxRuntimeExports.jsx("div", { ref: timelineRef, className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: trace.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult, onSelect: handleSelectSpan, 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, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan && sidebar ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3", 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.jsx(IconButton, { "aria-label": "Navigate to previous span", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate to next span", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }), 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: clearActiveSpan, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan }) }) })] }) : activeSpan ? jsxRuntimeExports.jsx(DetailPanel, { span: activeSpan, rootStart: root.startTime, onClose: clearActiveSpan }) : null] });
|
|
3036
3119
|
}
|
|
3037
3120
|
const NewTraceViewer = ({ run, events, sidebarData }) => {
|
|
3038
3121
|
const traceWithMeta = reactExports.useMemo(() => {
|