@workflow/web 5.0.0-beta.6 → 5.0.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/client/assets/{encryption-DU49MAQV.js → encryption-C69WMRfh.js} +11 -5
- package/build/client/assets/{highlighted-body-B3W2YXNL-BZLzBNxn.js → highlighted-body-B3W2YXNL-WHMd9MPa.js} +1 -1
- package/build/client/assets/{home-DmK2qlF4.js → home-Cai0GqMt.js} +8 -16
- package/build/client/assets/{manifest-f8f46e3c.js → manifest-127f70fe.js} +1 -1
- package/build/client/assets/{mermaid-3ZIDBTTL-D3hhpLut.js → mermaid-3ZIDBTTL-TNUP6Q3m.js} +356 -219
- package/build/client/assets/root-COvK3yNk.css +1 -0
- package/build/client/assets/{root-DCSDR-Tx.js → root-ORTTXEp6.js} +1 -1
- package/build/client/assets/{run-detail-qu2t8u4x.js → run-detail-DNZJxxPM.js} +1231 -1151
- package/build/client/assets/server-build-DzzvWTSG.css +1 -0
- package/build/client/assets/{workflow-graph-viewer-Bl8eU-PY.js → workflow-graph-viewer-DKqOOMnz.js} +50 -41
- package/build/server/assets/{app-C_Lhht8k.js → app-BxqFvIap.js} +1 -1
- package/build/server/assets/{highlighted-body-B3W2YXNL-DOOlKIMb.js → highlighted-body-B3W2YXNL-BuIiME1D.js} +2 -2
- package/build/server/assets/index-CdMzuwNr.js +89 -0
- package/build/server/assets/{mermaid-3ZIDBTTL-CglyhPap.js → mermaid-3ZIDBTTL-TSh7T1Pv.js} +2 -2
- package/build/server/assets/{server-build-CeQwCbX_.js → server-build-fc5Vuxba.js} +3488 -3014
- package/build/server/assets/{token-CZpVopko.js → token--89oCxEK.js} +2 -2
- package/build/server/assets/{token-util-DUvMx9Gj.js → token-util-N0DDbkKZ.js} +2 -2
- package/build/server/index.js +1 -1
- package/package.json +7 -7
- package/build/client/assets/root-5XHFuftH.css +0 -1
- package/build/client/assets/server-build-olrGumlh.css +0 -1
- package/build/server/assets/index-CRYPN_tt.js +0 -80
|
@@ -1,7 +1,7 @@
|
|
|
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,
|
|
4
|
-
import { decrypt, importKey } from "./encryption-
|
|
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-DKqOOMnz.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, aa as getSpanDurationMs, ab as getHighResInMs, ac as ActiveSpanProvider, ad as useActiveSpan, ae as computeRootBounds, af as computeTimeMarkers, ag as TIMELINE_PADDING_PX, ah as Timeline, ai as TimelineHeader, aj as SidebarDataProvider, ak as hydrateResourceIOWithKey, al as hydrateResourceIO, am as fetchHook, l as fetchEvents, F as fetchRun, an as fetchStep, ao as fetchStreams, ap as Slot, E as useComposedRefs, aq as Slottable, d as cn$1, ar as buttonVariants, as as isEncryptedData, at as hydrateData, au as getWebRevivers, T as Tooltip, a as TooltipTrigger, b as TooltipContent, av as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, aw as fetchEvent, ax as getEncryptionKeyForRun, t as toast, L as LoaderCircle, ay as StreamViewer } from "./mermaid-3ZIDBTTL-TNUP6Q3m.js";
|
|
4
|
+
import { decrypt, importKey } from "./encryption-C69WMRfh.js";
|
|
5
5
|
import "./index-Byi8AWfe.js";
|
|
6
6
|
/**
|
|
7
7
|
* @license lucide-react v0.575.0 - ISC
|
|
@@ -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,1201 +1397,1230 @@ 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
|
-
listStyle: "none"
|
|
1526
|
-
}, children: jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1.5", children: [jsxRuntimeExports.jsx(ChevronRight, { size: 14, className: "shrink-0 transition-transform group-open:rotate-90" }), summary] }) }), jsxRuntimeExports.jsx("div", { className: `mt-2 ${contentClassName ?? ""}`, children })] });
|
|
1527
|
-
}
|
|
1528
|
-
function TabButton({ active, onClick, children }) {
|
|
1529
|
-
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: {
|
|
1530
|
-
// Explicit styles to prevent app-level button overrides when web-shared
|
|
1531
|
-
// is embedded in a self-hosted app.
|
|
1532
|
-
backgroundColor: "transparent",
|
|
1533
|
-
borderTop: "none",
|
|
1534
|
-
borderLeft: "none",
|
|
1535
|
-
borderRight: "none",
|
|
1536
|
-
borderBottom: `2px solid ${active ? "var(--ds-blue-600)" : "transparent"}`,
|
|
1537
|
-
borderRadius: 0,
|
|
1538
|
-
outline: "none",
|
|
1539
|
-
boxShadow: "none",
|
|
1540
|
-
cursor: "pointer",
|
|
1541
|
-
color: active ? "var(--ds-gray-1000)" : "var(--ds-gray-600)"
|
|
1542
|
-
}, children });
|
|
1543
|
-
}
|
|
1544
|
-
function TabbedContainer({ tabs, activeTab, onTabChange, ariaLabel, children }) {
|
|
1545
|
-
const handleKeyDown = reactExports.useCallback((event) => {
|
|
1546
|
-
if (event.key !== "ArrowRight" && event.key !== "ArrowLeft")
|
|
1547
|
-
return;
|
|
1548
|
-
event.preventDefault();
|
|
1549
|
-
const currentIndex = tabs.findIndex((t) => t.id === activeTab);
|
|
1550
|
-
const nextIndex = event.key === "ArrowRight" ? (currentIndex + 1) % tabs.length : (currentIndex - 1 + tabs.length) % tabs.length;
|
|
1551
|
-
onTabChange(tabs[nextIndex].id);
|
|
1552
|
-
}, [tabs, activeTab, onTabChange]);
|
|
1553
|
-
return jsxRuntimeExports.jsxs("div", { className: "rounded-md border", style: {
|
|
1554
|
-
borderColor: "var(--ds-gray-300)",
|
|
1555
|
-
backgroundColor: "transparent"
|
|
1556
|
-
}, children: [jsxRuntimeExports.jsx("div", { className: "flex gap-1 border-b", role: "tablist", "aria-label": ariaLabel, onKeyDown: handleKeyDown, style: {
|
|
1557
|
-
borderColor: "var(--ds-gray-300)",
|
|
1558
|
-
backgroundColor: "transparent"
|
|
1559
|
-
}, children: tabs.map((tab) => jsxRuntimeExports.jsx(TabButton, { active: activeTab === tab.id, onClick: () => onTabChange(tab.id), children: tab.label }, tab.id)) }), jsxRuntimeExports.jsx("div", { role: "tabpanel", children })] });
|
|
1560
|
-
}
|
|
1561
|
-
const conversationTabs = [
|
|
1562
|
-
{ id: "conversation", label: "Conversation" },
|
|
1563
|
-
{ id: "json", label: "Raw JSON" }
|
|
1564
|
-
];
|
|
1565
|
-
function ConversationWithTabs({ conversation, args }) {
|
|
1566
|
-
const [activeTab, setActiveTab] = reactExports.useState("conversation");
|
|
1567
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: `Input (${conversation.length} messages)`, 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
|
-
}
|
|
1569
|
-
function EncryptedFieldBlock() {
|
|
1570
|
-
const ctx = reactExports.useContext(DecryptClickContext);
|
|
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" })] });
|
|
1584
|
-
}
|
|
1585
|
-
function ExpiredFieldBlock() {
|
|
1586
|
-
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
1587
|
-
borderColor: "var(--ds-gray-300)",
|
|
1588
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
1589
|
-
color: "var(--ds-gray-700)"
|
|
1590
|
-
}, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
|
|
1591
|
-
}
|
|
1592
|
-
function JsonBlock(value) {
|
|
1593
|
-
return jsxRuntimeExports.jsx(CopyableDataBlock, { data: value });
|
|
1594
|
-
}
|
|
1595
|
-
const hasDisplayContent = (value) => {
|
|
1596
|
-
if (value == null)
|
|
1597
|
-
return false;
|
|
1598
|
-
if (typeof value === "string")
|
|
1599
|
-
return value.trim().length > 0;
|
|
1600
|
-
if (Array.isArray(value))
|
|
1601
|
-
return value.length > 0;
|
|
1602
|
-
if (typeof value === "object")
|
|
1603
|
-
return Object.keys(value).length > 0;
|
|
1604
|
-
return true;
|
|
1605
|
-
};
|
|
1606
|
-
const attributeOrder = [
|
|
1607
|
-
"workflowName",
|
|
1608
|
-
"moduleSpecifier",
|
|
1609
|
-
"stepName",
|
|
1610
|
-
"status",
|
|
1611
|
-
"stepId",
|
|
1612
|
-
"hookId",
|
|
1613
|
-
"eventId",
|
|
1614
|
-
"runId",
|
|
1615
|
-
"attempt",
|
|
1616
|
-
"token",
|
|
1617
|
-
"receivedCount",
|
|
1618
|
-
"lastReceivedAt",
|
|
1619
|
-
"disposedAt",
|
|
1620
|
-
"correlationId",
|
|
1621
|
-
"eventType",
|
|
1622
|
-
"deploymentId",
|
|
1623
|
-
"specVersion",
|
|
1624
|
-
"workflowCoreVersion",
|
|
1625
|
-
"ownerId",
|
|
1626
|
-
"projectId",
|
|
1627
|
-
"environment",
|
|
1628
|
-
"executionContext",
|
|
1629
|
-
"createdAt",
|
|
1630
|
-
"startedAt",
|
|
1631
|
-
"updatedAt",
|
|
1632
|
-
"completedAt",
|
|
1633
|
-
"expiredAt",
|
|
1634
|
-
"retryAfter",
|
|
1635
|
-
"error",
|
|
1636
|
-
"metadata",
|
|
1637
|
-
"eventData",
|
|
1638
|
-
"input",
|
|
1639
|
-
"output",
|
|
1640
|
-
"resumeAt"
|
|
1641
|
-
];
|
|
1642
|
-
const sortByAttributeOrder = (a, b) => {
|
|
1643
|
-
const aIndex = attributeOrder.indexOf(a) || 0;
|
|
1644
|
-
const bIndex = attributeOrder.indexOf(b) || 0;
|
|
1645
|
-
return aIndex - bIndex;
|
|
1646
|
-
};
|
|
1647
|
-
const attributeDisplayNames = {
|
|
1648
|
-
moduleSpecifier: "Module",
|
|
1649
|
-
workflowName: "Workflow Name",
|
|
1650
|
-
stepName: "Step Name",
|
|
1651
|
-
stepId: "Step ID",
|
|
1652
|
-
hookId: "Hook ID",
|
|
1653
|
-
attempt: "Attempts",
|
|
1654
|
-
eventId: "Event ID",
|
|
1655
|
-
runId: "Run ID",
|
|
1656
|
-
eventType: "Event Type",
|
|
1657
|
-
correlationId: "Correlation ID",
|
|
1658
|
-
deploymentId: "Deployment ID",
|
|
1659
|
-
specVersion: "Spec Version",
|
|
1660
|
-
workflowCoreVersion: "@workflow/core version",
|
|
1661
|
-
createdAt: "Created",
|
|
1662
|
-
startedAt: "Started",
|
|
1663
|
-
updatedAt: "Updated",
|
|
1664
|
-
completedAt: "Completed",
|
|
1665
|
-
expiredAt: "Expired",
|
|
1666
|
-
retryAfter: "Retry After",
|
|
1667
|
-
resumeAt: "Resume",
|
|
1668
|
-
lastReceivedAt: "Last Received",
|
|
1669
|
-
disposedAt: "Disposed",
|
|
1670
|
-
receivedCount: "Times Resolved"
|
|
1671
|
-
};
|
|
1672
|
-
const getAttributeDisplayName = (attribute) => {
|
|
1673
|
-
return attributeDisplayNames[attribute] ?? attribute;
|
|
1674
|
-
};
|
|
1675
|
-
const getModuleSpecifierFromName = (value) => {
|
|
1676
|
-
const raw = String(value);
|
|
1677
|
-
const parsedStep = parseStepName(raw);
|
|
1678
|
-
if (parsedStep) {
|
|
1679
|
-
return parsedStep.moduleSpecifier;
|
|
1680
|
-
}
|
|
1681
|
-
const parsedWorkflow = parseWorkflowName(raw);
|
|
1682
|
-
if (parsedWorkflow) {
|
|
1683
|
-
return parsedWorkflow.moduleSpecifier;
|
|
1684
|
-
}
|
|
1685
|
-
return raw;
|
|
1686
|
-
};
|
|
1687
|
-
const parseDateValue = (value) => {
|
|
1688
|
-
if (value == null) {
|
|
1689
|
-
return null;
|
|
1690
|
-
}
|
|
1691
|
-
if (value instanceof Date) {
|
|
1692
|
-
return Number.isNaN(value.getTime()) ? null : value;
|
|
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;
|
|
1693
1512
|
}
|
|
1694
|
-
if (
|
|
1513
|
+
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
1695
1514
|
return null;
|
|
1696
1515
|
}
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1699
|
-
};
|
|
1700
|
-
const formatLocalMillisecondTime = (date) => date.toLocaleString(void 0, {
|
|
1701
|
-
year: "numeric",
|
|
1702
|
-
month: "numeric",
|
|
1703
|
-
day: "numeric",
|
|
1704
|
-
hour: "numeric",
|
|
1705
|
-
minute: "numeric",
|
|
1706
|
-
second: "numeric",
|
|
1707
|
-
fractionalSecondDigits: 3
|
|
1708
|
-
});
|
|
1709
|
-
const localMillisecondTime = (value) => {
|
|
1710
|
-
const date = parseDateValue(value);
|
|
1711
|
-
if (!date) {
|
|
1712
|
-
return "-";
|
|
1713
|
-
}
|
|
1714
|
-
return formatLocalMillisecondTime(date);
|
|
1715
|
-
};
|
|
1716
|
-
const localMillisecondTimeOrNull = (value) => {
|
|
1717
|
-
const date = parseDateValue(value);
|
|
1718
|
-
if (!date) {
|
|
1516
|
+
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
1517
|
+
if (selectionStart === -1) {
|
|
1719
1518
|
return null;
|
|
1720
1519
|
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
};
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
deploymentId: (value) => String(value),
|
|
1754
|
-
specVersion: (value) => String(value),
|
|
1755
|
-
workflowCoreVersion: (value) => String(value),
|
|
1756
|
-
// Tenancy (we don't show these)
|
|
1757
|
-
ownerId: (_value) => null,
|
|
1758
|
-
projectId: (_value) => null,
|
|
1759
|
-
environment: (_value) => null,
|
|
1760
|
-
executionContext: (_value) => null,
|
|
1761
|
-
// Dates — wrapped with TimestampTooltip showing UTC/local + relative time
|
|
1762
|
-
createdAt: timestampWithTooltipOrNull,
|
|
1763
|
-
startedAt: timestampWithTooltipOrNull,
|
|
1764
|
-
updatedAt: (_value) => null,
|
|
1765
|
-
completedAt: timestampWithTooltipOrNull,
|
|
1766
|
-
expiredAt: (_value) => null,
|
|
1767
|
-
retryAfter: timestampWithTooltipOrNull,
|
|
1768
|
-
resumeAt: timestampWithTooltipOrNull,
|
|
1769
|
-
// Resolved attributes, won't actually use this function
|
|
1770
|
-
metadata: (value) => {
|
|
1771
|
-
if (!hasDisplayContent(value))
|
|
1772
|
-
return null;
|
|
1773
|
-
if (isEncryptedMarker(value))
|
|
1774
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
1775
|
-
if (isExpiredMarker(value))
|
|
1776
|
-
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1777
|
-
return JsonBlock(value);
|
|
1778
|
-
},
|
|
1779
|
-
input: (value, context) => {
|
|
1780
|
-
if (isEncryptedMarker(value))
|
|
1781
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
1782
|
-
if (isExpiredMarker(value))
|
|
1783
|
-
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1784
|
-
if (value && typeof value === "object" && "args" in value) {
|
|
1785
|
-
const { args, closureVars, thisVal } = value;
|
|
1786
|
-
const argCount2 = Array.isArray(args) ? args.length : 0;
|
|
1787
|
-
const argLabel2 = argCount2 === 1 ? "argument" : "arguments";
|
|
1788
|
-
const hasClosureVars = hasDisplayContent(closureVars);
|
|
1789
|
-
const hasThisVal = hasDisplayContent(thisVal);
|
|
1790
|
-
const hasArgs = hasDisplayContent(args);
|
|
1791
|
-
if ((context == null ? void 0 : context.stepName) && isDoStreamStep(context.stepName)) {
|
|
1792
|
-
const conversation = extractConversation(args);
|
|
1793
|
-
if (conversation && conversation.length > 0) {
|
|
1794
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args }), hasClosureVars && jsxRuntimeExports.jsx(DetailCard, { summary: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(DetailCard, { summary: "This Value", children: JsonBlock(thisVal) })] });
|
|
1795
|
-
}
|
|
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;
|
|
1796
1552
|
}
|
|
1797
|
-
|
|
1798
|
-
|
|
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
|
+
});
|
|
1799
1665
|
}
|
|
1800
|
-
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(DetailCard, { summary: `Input (${argCount2} ${argLabel2})`, summaryClassName: "text-label-14 font-medium py-2", contentClassName: "mt-0", 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: "this", children: JsonBlock(thisVal) })] });
|
|
1801
1666
|
}
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
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)
|
|
1824
1701
|
return null;
|
|
1825
|
-
if (
|
|
1826
|
-
return jsxRuntimeExports.jsx(
|
|
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 }) });
|
|
1827
1704
|
}
|
|
1828
|
-
return jsxRuntimeExports.jsx(
|
|
1829
|
-
},
|
|
1830
|
-
eventData: (value) => {
|
|
1831
|
-
if (isEncryptedMarker(value))
|
|
1832
|
-
return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
|
|
1833
|
-
if (isExpiredMarker(value))
|
|
1834
|
-
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
1835
|
-
if (!hasDisplayContent(value))
|
|
1836
|
-
return null;
|
|
1837
|
-
return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", children: JsonBlock(value) });
|
|
1838
|
-
},
|
|
1839
|
-
errorCode: (value) => {
|
|
1840
|
-
if (typeof value !== "string" || value.length === 0)
|
|
1841
|
-
return null;
|
|
1842
|
-
return String(value);
|
|
1705
|
+
return jsxRuntimeExports.jsx("div", { className: "whitespace-pre-wrap break-words", style: { color: "var(--ds-gray-1000)" }, children: part.text });
|
|
1843
1706
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
"metadata",
|
|
1850
|
-
"eventData"
|
|
1851
|
-
];
|
|
1852
|
-
const ExpiredDataMessage = () => jsxRuntimeExports.jsx("div", { className: "text-copy-12 rounded-md border p-4 my-2", style: {
|
|
1853
|
-
borderColor: "var(--ds-gray-300)",
|
|
1854
|
-
backgroundColor: "var(--ds-gray-100)",
|
|
1855
|
-
color: "var(--ds-gray-700)"
|
|
1856
|
-
}, children: jsxRuntimeExports.jsx("span", { children: "The data for this run has expired and is no longer available." }) });
|
|
1857
|
-
const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
|
|
1858
|
-
const isExpandableLoadingTarget = attribute === "input" || attribute === "eventData";
|
|
1859
|
-
if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
|
|
1860
|
-
return jsxRuntimeExports.jsxs("div", { className: `my-2 flex flex-col ${attribute === "input" ? "gap-2 my-3.5" : "gap-0"}`, children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-1000 font-medium first-letter:uppercase", children: attribute }), jsxRuntimeExports.jsx(Skeleton, { className: "h-9 w-full rounded-md" })] });
|
|
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 }) })] });
|
|
1861
1712
|
}
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
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 }) })] });
|
|
1865
1718
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
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
|
+
};
|
|
1869
1753
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1754
|
+
}
|
|
1755
|
+
function parseContent(content) {
|
|
1756
|
+
if (typeof content === "string") {
|
|
1757
|
+
return [{ type: "text", text: content }];
|
|
1872
1758
|
}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
if (!isLoading)
|
|
1897
|
-
return present;
|
|
1898
|
-
const loadingDefaults = ["input"];
|
|
1899
|
-
for (const key of loadingDefaults) {
|
|
1900
|
-
if (!present.includes(key)) {
|
|
1901
|
-
present.push(key);
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
return present.sort(sortByAttributeOrder);
|
|
1905
|
-
}, [displayData, isLoading]);
|
|
1906
|
-
const visibleBasicAttributes = basicAttributes.filter((attribute) => {
|
|
1907
|
-
const displayFn = attributeToDisplayFn[attribute];
|
|
1908
|
-
if (!displayFn)
|
|
1909
|
-
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");
|
|
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: "" };
|
|
1941
1782
|
});
|
|
1942
|
-
}
|
|
1943
|
-
return
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
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
|
+
}
|
|
1960
1805
|
};
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
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) {
|
|
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)
|
|
1988
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 });
|
|
1989
1821
|
}
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
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",
|
|
1841
|
+
borderBottom: `2px solid ${active ? "var(--ds-blue-600)" : "transparent"}`,
|
|
1842
|
+
borderRadius: 0,
|
|
1843
|
+
outline: "none",
|
|
1844
|
+
boxShadow: "none",
|
|
1845
|
+
cursor: "pointer",
|
|
1846
|
+
color: active ? "var(--ds-gray-1000)" : "var(--ds-gray-600)"
|
|
1847
|
+
}, children });
|
|
1848
|
+
}
|
|
1849
|
+
function TabbedContainer({ tabs, activeTab, onTabChange, ariaLabel, children }) {
|
|
1850
|
+
const handleKeyDown = reactExports.useCallback((event) => {
|
|
1851
|
+
if (event.key !== "ArrowRight" && event.key !== "ArrowLeft")
|
|
2010
1852
|
return;
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
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: {
|
|
1853
|
+
event.preventDefault();
|
|
1854
|
+
const currentIndex = tabs.findIndex((t) => t.id === activeTab);
|
|
1855
|
+
const nextIndex = event.key === "ArrowRight" ? (currentIndex + 1) % tabs.length : (currentIndex - 1 + tabs.length) % tabs.length;
|
|
1856
|
+
onTabChange(tabs[nextIndex].id);
|
|
1857
|
+
}, [tabs, activeTab, onTabChange]);
|
|
1858
|
+
return jsxRuntimeExports.jsxs("div", { className: "rounded-md border", style: {
|
|
2021
1859
|
borderColor: "var(--ds-gray-300)",
|
|
2022
|
-
backgroundColor: "
|
|
2023
|
-
}, children: [jsxRuntimeExports.
|
|
2024
|
-
borderColor: "var(--ds-gray-300)"
|
|
2025
|
-
|
|
1860
|
+
backgroundColor: "transparent"
|
|
1861
|
+
}, children: [jsxRuntimeExports.jsx("div", { className: "flex gap-1 border-b", role: "tablist", "aria-label": ariaLabel, onKeyDown: handleKeyDown, style: {
|
|
1862
|
+
borderColor: "var(--ds-gray-300)",
|
|
1863
|
+
backgroundColor: "transparent"
|
|
1864
|
+
}, children: tabs.map((tab) => jsxRuntimeExports.jsx(TabButton, { active: activeTab === tab.id, onClick: () => onTabChange(tab.id), children: tab.label }, tab.id)) }), jsxRuntimeExports.jsx("div", { role: "tabpanel", children })] });
|
|
2026
1865
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
1866
|
+
const conversationTabs = [
|
|
1867
|
+
{ id: "conversation", label: "Conversation" },
|
|
1868
|
+
{ id: "json", label: "Raw JSON" }
|
|
1869
|
+
];
|
|
1870
|
+
function ConversationWithTabs({ conversation, args }) {
|
|
1871
|
+
const [activeTab, setActiveTab] = reactExports.useState("conversation");
|
|
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) }) }) });
|
|
1873
|
+
}
|
|
1874
|
+
function EncryptedFieldBlock() {
|
|
1875
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
1876
|
+
}
|
|
1877
|
+
function ExpiredFieldBlock() {
|
|
1878
|
+
return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
|
|
1879
|
+
borderColor: "var(--ds-gray-300)",
|
|
1880
|
+
backgroundColor: "var(--ds-gray-100)",
|
|
1881
|
+
color: "var(--ds-gray-700)"
|
|
1882
|
+
}, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
|
|
1883
|
+
}
|
|
1884
|
+
function JsonBlock(value) {
|
|
1885
|
+
return jsxRuntimeExports.jsx(CopyableDataBlock, { data: value });
|
|
1886
|
+
}
|
|
1887
|
+
const hasDisplayContent = (value) => {
|
|
1888
|
+
if (value == null)
|
|
2029
1889
|
return false;
|
|
1890
|
+
if (typeof value === "string")
|
|
1891
|
+
return value.trim().length > 0;
|
|
1892
|
+
if (Array.isArray(value))
|
|
1893
|
+
return value.length > 0;
|
|
1894
|
+
if (typeof value === "object")
|
|
1895
|
+
return Object.keys(value).length > 0;
|
|
1896
|
+
return true;
|
|
1897
|
+
};
|
|
1898
|
+
const attributeOrder = [
|
|
1899
|
+
"workflowName",
|
|
1900
|
+
"moduleSpecifier",
|
|
1901
|
+
"stepName",
|
|
1902
|
+
"status",
|
|
1903
|
+
"stepId",
|
|
1904
|
+
"hookId",
|
|
1905
|
+
"eventId",
|
|
1906
|
+
"runId",
|
|
1907
|
+
"attempt",
|
|
1908
|
+
"token",
|
|
1909
|
+
"receivedCount",
|
|
1910
|
+
"lastReceivedAt",
|
|
1911
|
+
"disposedAt",
|
|
1912
|
+
"correlationId",
|
|
1913
|
+
"eventType",
|
|
1914
|
+
"deploymentId",
|
|
1915
|
+
"specVersion",
|
|
1916
|
+
"workflowCoreVersion",
|
|
1917
|
+
"ownerId",
|
|
1918
|
+
"projectId",
|
|
1919
|
+
"environment",
|
|
1920
|
+
"executionContext",
|
|
1921
|
+
"createdAt",
|
|
1922
|
+
"startedAt",
|
|
1923
|
+
"updatedAt",
|
|
1924
|
+
"completedAt",
|
|
1925
|
+
"expiredAt",
|
|
1926
|
+
"retryAfter",
|
|
1927
|
+
"error",
|
|
1928
|
+
"metadata",
|
|
1929
|
+
"eventData",
|
|
1930
|
+
"input",
|
|
1931
|
+
"output",
|
|
1932
|
+
"resumeAt"
|
|
1933
|
+
];
|
|
1934
|
+
const sortByAttributeOrder = (a, b) => {
|
|
1935
|
+
const aIndex = attributeOrder.indexOf(a) || 0;
|
|
1936
|
+
const bIndex = attributeOrder.indexOf(b) || 0;
|
|
1937
|
+
return aIndex - bIndex;
|
|
1938
|
+
};
|
|
1939
|
+
const attributeDisplayNames = {
|
|
1940
|
+
moduleSpecifier: "Module",
|
|
1941
|
+
workflowName: "Workflow Name",
|
|
1942
|
+
stepName: "Step Name",
|
|
1943
|
+
stepId: "Step ID",
|
|
1944
|
+
hookId: "Hook ID",
|
|
1945
|
+
attempt: "Attempts",
|
|
1946
|
+
eventId: "Event ID",
|
|
1947
|
+
runId: "Run ID",
|
|
1948
|
+
token: "Token",
|
|
1949
|
+
eventType: "Event Type",
|
|
1950
|
+
correlationId: "Correlation ID",
|
|
1951
|
+
deploymentId: "Deployment ID",
|
|
1952
|
+
specVersion: "Spec Version",
|
|
1953
|
+
workflowCoreVersion: "@workflow/core version",
|
|
1954
|
+
createdAt: "Created",
|
|
1955
|
+
startedAt: "Started",
|
|
1956
|
+
updatedAt: "Updated",
|
|
1957
|
+
completedAt: "Completed",
|
|
1958
|
+
expiredAt: "Expired",
|
|
1959
|
+
retryAfter: "Retry After",
|
|
1960
|
+
resumeAt: "Resume",
|
|
1961
|
+
lastReceivedAt: "Last Received",
|
|
1962
|
+
disposedAt: "Disposed",
|
|
1963
|
+
receivedCount: "Times Resolved"
|
|
1964
|
+
};
|
|
1965
|
+
const getAttributeDisplayName = (attribute) => {
|
|
1966
|
+
return attributeDisplayNames[attribute] ?? attribute;
|
|
1967
|
+
};
|
|
1968
|
+
const getModuleSpecifierFromName = (value) => {
|
|
1969
|
+
const raw = String(value);
|
|
1970
|
+
const parsedStep = parseStepName(raw);
|
|
1971
|
+
if (parsedStep) {
|
|
1972
|
+
return parsedStep.moduleSpecifier;
|
|
1973
|
+
}
|
|
1974
|
+
const parsedWorkflow = parseWorkflowName(raw);
|
|
1975
|
+
if (parsedWorkflow) {
|
|
1976
|
+
return parsedWorkflow.moduleSpecifier;
|
|
1977
|
+
}
|
|
1978
|
+
return raw;
|
|
1979
|
+
};
|
|
1980
|
+
const parseDateValue = (value) => {
|
|
1981
|
+
if (value == null) {
|
|
1982
|
+
return null;
|
|
1983
|
+
}
|
|
1984
|
+
if (value instanceof Date) {
|
|
1985
|
+
return Number.isNaN(value.getTime()) ? null : value;
|
|
2030
1986
|
}
|
|
2031
|
-
|
|
2032
|
-
|
|
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" }) });
|
|
1987
|
+
if (typeof value === "string" && value.trim().length === 0) {
|
|
1988
|
+
return null;
|
|
2043
1989
|
}
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
1990
|
+
const date = typeof value === "number" ? new Date(value) : new Date(String(value));
|
|
1991
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
1992
|
+
};
|
|
1993
|
+
const formatLocalMillisecondTime = (date) => date.toLocaleString(void 0, {
|
|
1994
|
+
year: "numeric",
|
|
1995
|
+
month: "numeric",
|
|
1996
|
+
day: "numeric",
|
|
1997
|
+
hour: "numeric",
|
|
1998
|
+
minute: "numeric",
|
|
1999
|
+
second: "numeric",
|
|
2000
|
+
fractionalSecondDigits: 3
|
|
2001
|
+
});
|
|
2002
|
+
const localMillisecondTimeOrNull = (value) => {
|
|
2003
|
+
const date = parseDateValue(value);
|
|
2004
|
+
if (!date) {
|
|
2005
|
+
return null;
|
|
2052
2006
|
}
|
|
2053
|
-
return
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2056
|
-
const
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2007
|
+
return formatLocalMillisecondTime(date);
|
|
2008
|
+
};
|
|
2009
|
+
const timestampWithTooltipOrNull = (value) => {
|
|
2010
|
+
const date = parseDateValue(value);
|
|
2011
|
+
if (!date)
|
|
2012
|
+
return null;
|
|
2013
|
+
return jsxRuntimeExports.jsx(TimestampTooltip, { date, children: jsxRuntimeExports.jsx("span", { children: formatLocalMillisecondTime(date) }) });
|
|
2014
|
+
};
|
|
2015
|
+
const attributeToDisplayFn = {
|
|
2016
|
+
// Names that need pretty-printing
|
|
2017
|
+
workflowName: (_value) => null,
|
|
2018
|
+
moduleSpecifier: (value) => getModuleSpecifierFromName(value),
|
|
2019
|
+
stepName: (_value) => null,
|
|
2020
|
+
// IDs
|
|
2021
|
+
runId: (_value) => null,
|
|
2022
|
+
stepId: (value) => String(value),
|
|
2023
|
+
hookId: (value) => String(value),
|
|
2024
|
+
eventId: (value) => String(value),
|
|
2025
|
+
// Run/step details
|
|
2026
|
+
status: (_value) => null,
|
|
2027
|
+
attempt: (value) => String(value),
|
|
2028
|
+
// Hook details
|
|
2029
|
+
token: (value) => String(value),
|
|
2030
|
+
isWebhook: (value) => String(value),
|
|
2031
|
+
isSystem: (value) => String(value),
|
|
2032
|
+
receivedCount: (value) => String(value),
|
|
2033
|
+
lastReceivedAt: localMillisecondTimeOrNull,
|
|
2034
|
+
disposedAt: localMillisecondTimeOrNull,
|
|
2035
|
+
// Event details
|
|
2036
|
+
eventType: (value) => String(value),
|
|
2037
|
+
correlationId: (value) => String(value),
|
|
2038
|
+
// Project details
|
|
2039
|
+
deploymentId: (value) => String(value),
|
|
2040
|
+
specVersion: (value) => String(value),
|
|
2041
|
+
workflowCoreVersion: (value) => String(value),
|
|
2042
|
+
// Tenancy (we don't show these)
|
|
2043
|
+
ownerId: (_value) => null,
|
|
2044
|
+
projectId: (_value) => null,
|
|
2045
|
+
environment: (_value) => null,
|
|
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
|
+
},
|
|
2055
|
+
// Dates — wrapped with TimestampTooltip showing UTC/local + relative time
|
|
2056
|
+
createdAt: timestampWithTooltipOrNull,
|
|
2057
|
+
startedAt: timestampWithTooltipOrNull,
|
|
2058
|
+
updatedAt: (_value) => null,
|
|
2059
|
+
completedAt: timestampWithTooltipOrNull,
|
|
2060
|
+
expiredAt: (_value) => null,
|
|
2061
|
+
retryAfter: timestampWithTooltipOrNull,
|
|
2062
|
+
resumeAt: timestampWithTooltipOrNull,
|
|
2063
|
+
// Resolved attributes, won't actually use this function
|
|
2064
|
+
metadata: (value) => {
|
|
2065
|
+
if (!hasDisplayContent(value))
|
|
2066
|
+
return null;
|
|
2067
|
+
if (isEncryptedMarker(value))
|
|
2068
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
2069
|
+
if (isExpiredMarker(value))
|
|
2070
|
+
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2071
|
+
return JsonBlock(value);
|
|
2072
|
+
},
|
|
2073
|
+
input: (value, context) => {
|
|
2074
|
+
if (isEncryptedMarker(value)) {
|
|
2075
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2080
2076
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2077
|
+
if (isExpiredMarker(value))
|
|
2078
|
+
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2079
|
+
if (value && typeof value === "object" && "args" in value) {
|
|
2080
|
+
const { args, closureVars, thisVal } = value;
|
|
2081
|
+
const hasClosureVars = hasDisplayContent(closureVars);
|
|
2082
|
+
const hasThisVal = hasDisplayContent(thisVal);
|
|
2083
|
+
const hasArgs = hasDisplayContent(args);
|
|
2084
|
+
if ((context == null ? void 0 : context.stepName) && isDoStreamStep(context.stepName)) {
|
|
2085
|
+
const conversation = extractConversation(args);
|
|
2086
|
+
if (conversation && conversation.length > 0) {
|
|
2087
|
+
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args }), hasClosureVars && jsxRuntimeExports.jsx(DetailCard, { summary: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(DetailCard, { summary: "This Value", children: JsonBlock(thisVal) })] });
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
if (!hasArgs && !hasClosureVars && !hasThisVal) {
|
|
2091
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input (no data)", disabled: true });
|
|
2092
|
+
}
|
|
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) })] });
|
|
2084
2094
|
}
|
|
2085
|
-
if (
|
|
2086
|
-
return {
|
|
2095
|
+
if (!hasDisplayContent(value)) {
|
|
2096
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Input (no data)", disabled: true });
|
|
2087
2097
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
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) });
|
|
2099
|
+
},
|
|
2100
|
+
output: (value) => {
|
|
2101
|
+
if (isEncryptedMarker(value)) {
|
|
2102
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Output", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2090
2103
|
}
|
|
2091
|
-
if (
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2104
|
+
if (!hasDisplayContent(value))
|
|
2105
|
+
return null;
|
|
2106
|
+
if (isExpiredMarker(value))
|
|
2107
|
+
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2108
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Output", children: JsonBlock(value) });
|
|
2109
|
+
},
|
|
2110
|
+
error: (value) => {
|
|
2111
|
+
if (isEncryptedMarker(value)) {
|
|
2112
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2098
2113
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
onSpanSelectRef.current({
|
|
2106
|
-
resource,
|
|
2107
|
-
resourceId,
|
|
2108
|
-
runId
|
|
2109
|
-
});
|
|
2114
|
+
if (isExpiredMarker(value))
|
|
2115
|
+
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2116
|
+
if (!hasDisplayContent(value))
|
|
2117
|
+
return null;
|
|
2118
|
+
if (isStructuredErrorWithStack(value)) {
|
|
2119
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error", defaultOpen: true, children: jsxRuntimeExports.jsx(ErrorStackBlock, { value }) });
|
|
2110
2120
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
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;
|
|
2121
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Error", defaultOpen: true, children: JsonBlock(value) });
|
|
2122
|
+
},
|
|
2123
|
+
eventData: (value) => {
|
|
2124
|
+
if (isEncryptedMarker(value)) {
|
|
2125
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", defaultOpen: true, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
|
|
2151
2126
|
}
|
|
2152
|
-
if (
|
|
2153
|
-
return
|
|
2127
|
+
if (isExpiredMarker(value))
|
|
2128
|
+
return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
|
|
2129
|
+
if (!hasDisplayContent(value))
|
|
2130
|
+
return null;
|
|
2131
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", defaultOpen: true, children: JsonBlock(value) });
|
|
2132
|
+
},
|
|
2133
|
+
errorCode: (value) => {
|
|
2134
|
+
if (typeof value !== "string" || value.length === 0)
|
|
2135
|
+
return null;
|
|
2136
|
+
return String(value);
|
|
2137
|
+
}
|
|
2138
|
+
};
|
|
2139
|
+
const resolvableAttributes = [
|
|
2140
|
+
"input",
|
|
2141
|
+
"output",
|
|
2142
|
+
"error",
|
|
2143
|
+
"metadata",
|
|
2144
|
+
"eventData"
|
|
2145
|
+
];
|
|
2146
|
+
const selfHeaderedAttributes = /* @__PURE__ */ new Set([
|
|
2147
|
+
"input",
|
|
2148
|
+
"output",
|
|
2149
|
+
"error",
|
|
2150
|
+
"eventData"
|
|
2151
|
+
]);
|
|
2152
|
+
const ExpiredDataMessage = () => jsxRuntimeExports.jsx("div", { className: "text-copy-12 rounded-md border p-4 my-2", style: {
|
|
2153
|
+
borderColor: "var(--ds-gray-300)",
|
|
2154
|
+
backgroundColor: "var(--ds-gray-100)",
|
|
2155
|
+
color: "var(--ds-gray-700)"
|
|
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
|
+
]);
|
|
2163
|
+
const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
|
|
2164
|
+
const decryptCtx = reactExports.useContext(DecryptClickContext);
|
|
2165
|
+
const isExpandableLoadingTarget = attribute === "input" || attribute === "output" || attribute === "eventData";
|
|
2166
|
+
if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
|
|
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, {}) });
|
|
2154
2170
|
}
|
|
2155
|
-
return
|
|
2156
|
-
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2171
|
+
return jsxRuntimeExports.jsx(DetailCard, { summary: label });
|
|
2172
|
+
}
|
|
2173
|
+
const displayFn = attributeToDisplayFn[attribute];
|
|
2174
|
+
if (!displayFn) {
|
|
2175
|
+
return null;
|
|
2176
|
+
}
|
|
2177
|
+
const displayValue = displayFn(value, context);
|
|
2178
|
+
if (!displayValue) {
|
|
2179
|
+
return null;
|
|
2180
|
+
}
|
|
2181
|
+
if (inline) {
|
|
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 })] });
|
|
2183
|
+
}
|
|
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)] });
|
|
2188
|
+
};
|
|
2189
|
+
const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
|
|
2190
|
+
const toast2 = useToast();
|
|
2191
|
+
const displayData = reactExports.useMemo(() => {
|
|
2192
|
+
const result = { ...data };
|
|
2193
|
+
const execCtx = data.executionContext;
|
|
2194
|
+
if (execCtx == null ? void 0 : execCtx.workflowCoreVersion) {
|
|
2195
|
+
result.workflowCoreVersion = execCtx.workflowCoreVersion;
|
|
2162
2196
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
if (
|
|
2166
|
-
|
|
2167
|
-
if (
|
|
2168
|
-
|
|
2169
|
-
description: "No wake-up handler provided."
|
|
2170
|
-
});
|
|
2171
|
-
return;
|
|
2197
|
+
if (moduleSpecifier) {
|
|
2198
|
+
result.moduleSpecifier = moduleSpecifier;
|
|
2199
|
+
} else if (typeof data.stepName === "string") {
|
|
2200
|
+
result.moduleSpecifier = data.stepName;
|
|
2201
|
+
} else if (typeof data.workflowName === "string") {
|
|
2202
|
+
result.moduleSpecifier = data.workflowName;
|
|
2172
2203
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2204
|
+
return result;
|
|
2205
|
+
}, [data, moduleSpecifier]);
|
|
2206
|
+
const hasExpired = expiredAt != null && new Date(expiredAt) < /* @__PURE__ */ new Date();
|
|
2207
|
+
const basicAttributes = Object.keys(displayData).filter((key) => !resolvableAttributes.includes(key)).sort(sortByAttributeOrder);
|
|
2208
|
+
const resolvedAttributes = reactExports.useMemo(() => {
|
|
2209
|
+
const present = Object.keys(displayData).filter((key) => resolvableAttributes.includes(key)).sort(sortByAttributeOrder);
|
|
2210
|
+
if (!isLoading)
|
|
2211
|
+
return present;
|
|
2212
|
+
if (resource === "sleep")
|
|
2213
|
+
return present;
|
|
2214
|
+
const loadingDefaults = ["input", "output"];
|
|
2215
|
+
for (const key of loadingDefaults) {
|
|
2216
|
+
if (!present.includes(key)) {
|
|
2217
|
+
present.push(key);
|
|
2184
2218
|
}
|
|
2185
|
-
} catch (err) {
|
|
2186
|
-
console.error("Failed to wake up run:", err);
|
|
2187
|
-
toast2.error("Failed to wake up run", {
|
|
2188
|
-
description: err instanceof Error ? err.message : "An unknown error occurred"
|
|
2189
|
-
});
|
|
2190
|
-
} finally {
|
|
2191
|
-
setStoppingSleep(false);
|
|
2192
2219
|
}
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
if (!
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2220
|
+
return present.sort(sortByAttributeOrder);
|
|
2221
|
+
}, [displayData, isLoading, resource]);
|
|
2222
|
+
const visibleBasicAttributes = basicAttributes.filter((attribute) => {
|
|
2223
|
+
const displayFn = attributeToDisplayFn[attribute];
|
|
2224
|
+
if (!displayFn)
|
|
2225
|
+
return false;
|
|
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;
|
|
2202
2234
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
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;
|
|
2240
|
+
}
|
|
2241
|
+
const stepNameIndex = attributes.indexOf("stepName");
|
|
2242
|
+
if (stepNameIndex !== -1) {
|
|
2243
|
+
attributes.splice(stepNameIndex + 1, 0, "moduleSpecifier");
|
|
2244
|
+
return attributes;
|
|
2245
|
+
}
|
|
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)
|
|
2306
|
+
return;
|
|
2307
|
+
if (!(options == null ? void 0 : options.force) && loadedDataRef.current !== null) {
|
|
2207
2308
|
return;
|
|
2208
2309
|
}
|
|
2209
2310
|
try {
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
const
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
description: "The payload has been sent and the hook resolved."
|
|
2216
|
-
});
|
|
2217
|
-
setShowResolveHookModal(false);
|
|
2218
|
-
if (resourceId) {
|
|
2219
|
-
setResolvedHookIds((prev) => new Set(prev).add(resourceId));
|
|
2220
|
-
}
|
|
2311
|
+
setIsLoading(true);
|
|
2312
|
+
setLoadError(null);
|
|
2313
|
+
const data = await onLoadEventData(event.correlationId, event.eventId);
|
|
2314
|
+
loadedDataRef.current = data;
|
|
2315
|
+
setLoadedData(data);
|
|
2221
2316
|
} catch (err) {
|
|
2222
|
-
|
|
2223
|
-
toast2.error("Failed to resolve hook", {
|
|
2224
|
-
description: err instanceof Error ? err.message : "An unknown error occurred"
|
|
2225
|
-
});
|
|
2317
|
+
setLoadError(err instanceof Error ? err.message : String(err));
|
|
2226
2318
|
} finally {
|
|
2227
|
-
|
|
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
|
-
function CopyButton({ copyText, ariaLabel, className }) {
|
|
2262
|
-
const [copied, setCopied] = reactExports.useState(false);
|
|
2263
|
-
const timeoutRef = reactExports.useRef(null);
|
|
2264
|
-
reactExports.useEffect(() => {
|
|
2265
|
-
return () => {
|
|
2266
|
-
if (timeoutRef.current) {
|
|
2267
|
-
clearTimeout(timeoutRef.current);
|
|
2268
|
-
}
|
|
2269
|
-
};
|
|
2270
|
-
}, []);
|
|
2271
|
-
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) => {
|
|
2272
|
-
e.stopPropagation();
|
|
2273
|
-
if (timeoutRef.current) {
|
|
2274
|
-
clearTimeout(timeoutRef.current);
|
|
2319
|
+
setIsLoading(false);
|
|
2275
2320
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
const
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
const
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
2302
|
-
}
|
|
2303
|
-
return Array.from(text);
|
|
2321
|
+
}, [onLoadEventData, event.correlationId, event.eventId]);
|
|
2322
|
+
const handleExpand = reactExports.useCallback(async () => {
|
|
2323
|
+
if (isLoading)
|
|
2324
|
+
return;
|
|
2325
|
+
wasExpandedRef.current = true;
|
|
2326
|
+
await loadEventData();
|
|
2327
|
+
}, [isLoading, loadEventData]);
|
|
2328
|
+
reactExports.useLayoutEffect(() => {
|
|
2329
|
+
if (!encryptionKey || !wasExpandedRef.current)
|
|
2330
|
+
return;
|
|
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"
|
|
2340
|
+
});
|
|
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 }) })] });
|
|
2304
2346
|
}
|
|
2305
|
-
function
|
|
2306
|
-
if (
|
|
2307
|
-
return
|
|
2308
|
-
prefixText: "",
|
|
2309
|
-
prefixGraphemeCount: 0,
|
|
2310
|
-
suffixText: "",
|
|
2311
|
-
suffixGraphemeCount: 0,
|
|
2312
|
-
text: ELLIPSIS,
|
|
2313
|
-
truncated: true
|
|
2314
|
-
};
|
|
2347
|
+
function hasOnlyExpiredFields(data, eventType) {
|
|
2348
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2349
|
+
return false;
|
|
2315
2350
|
}
|
|
2316
|
-
const
|
|
2317
|
-
const
|
|
2318
|
-
const
|
|
2319
|
-
|
|
2320
|
-
return {
|
|
2321
|
-
prefixText,
|
|
2322
|
-
prefixGraphemeCount,
|
|
2323
|
-
suffixText,
|
|
2324
|
-
suffixGraphemeCount,
|
|
2325
|
-
text: prefixText + ELLIPSIS + suffixText,
|
|
2326
|
-
truncated: true
|
|
2327
|
-
};
|
|
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]));
|
|
2328
2355
|
}
|
|
2329
|
-
function
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
suffixText: "",
|
|
2337
|
-
suffixGraphemeCount: 0,
|
|
2338
|
-
text: fullText,
|
|
2339
|
-
truncated: false
|
|
2340
|
-
};
|
|
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" }) });
|
|
2341
2363
|
}
|
|
2342
|
-
if (
|
|
2343
|
-
return {
|
|
2344
|
-
prefixText: fullText,
|
|
2345
|
-
prefixGraphemeCount: graphemes.length,
|
|
2346
|
-
suffixText: "",
|
|
2347
|
-
suffixGraphemeCount: 0,
|
|
2348
|
-
text: fullText,
|
|
2349
|
-
truncated: false
|
|
2350
|
-
};
|
|
2364
|
+
if (hasEncryptedFields({ eventType, eventData: data })) {
|
|
2365
|
+
return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
|
|
2351
2366
|
}
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
best = mid;
|
|
2360
|
-
lo = mid + 1;
|
|
2361
|
-
} else {
|
|
2362
|
-
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 });
|
|
2363
2374
|
}
|
|
2364
2375
|
}
|
|
2365
|
-
|
|
2366
|
-
return {
|
|
2367
|
-
prefixText: "",
|
|
2368
|
-
prefixGraphemeCount: 0,
|
|
2369
|
-
suffixText: "",
|
|
2370
|
-
suffixGraphemeCount: 0,
|
|
2371
|
-
text: "",
|
|
2372
|
-
truncated: true
|
|
2373
|
-
};
|
|
2374
|
-
}
|
|
2375
|
-
return buildCandidate(graphemes, best);
|
|
2376
|
+
return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
|
|
2376
2377
|
}
|
|
2377
|
-
function
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
2383
|
-
return value;
|
|
2384
|
-
}
|
|
2385
|
-
const ellipsisStart = prefixText.length;
|
|
2386
|
-
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
2387
|
-
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
2388
|
-
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 });
|
|
2389
2383
|
}
|
|
2390
|
-
|
|
2391
|
-
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
2392
|
-
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
2393
|
-
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
2394
|
-
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)) }) });
|
|
2395
2385
|
}
|
|
2396
|
-
function
|
|
2397
|
-
|
|
2398
|
-
const trimmedSelectionText = selectionText.trim();
|
|
2399
|
-
if (!trimmedSelectionText) {
|
|
2400
|
-
return null;
|
|
2401
|
-
}
|
|
2402
|
-
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
2403
|
-
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
2404
|
-
if (trimmedSelectionText === visibleText) {
|
|
2405
|
-
return leading + value + trailing;
|
|
2406
|
-
}
|
|
2407
|
-
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
2408
|
-
return null;
|
|
2409
|
-
}
|
|
2410
|
-
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
2411
|
-
if (selectionStart === -1) {
|
|
2412
|
-
return null;
|
|
2413
|
-
}
|
|
2414
|
-
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
2415
|
-
const mappedText = getMiddleTruncateCopyText({
|
|
2416
|
-
prefixText,
|
|
2417
|
-
selectionEnd,
|
|
2418
|
-
selectionStart,
|
|
2419
|
-
suffixText,
|
|
2420
|
-
value
|
|
2421
|
-
});
|
|
2422
|
-
return mappedText === null ? null : leading + mappedText + trailing;
|
|
2386
|
+
function isStep(data) {
|
|
2387
|
+
return data !== null && typeof data === "object" && "stepId" in data;
|
|
2423
2388
|
}
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
return {
|
|
2427
|
-
displayText: value,
|
|
2428
|
-
isTruncated: false,
|
|
2429
|
-
prefixGraphemeCount: graphemes.length,
|
|
2430
|
-
prefixText: value,
|
|
2431
|
-
suffixGraphemeCount: 0,
|
|
2432
|
-
suffixText: ""
|
|
2433
|
-
};
|
|
2389
|
+
function isWorkflowRun(data) {
|
|
2390
|
+
return data !== null && typeof data === "object" && "runId" in data;
|
|
2434
2391
|
}
|
|
2435
|
-
function
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
const
|
|
2440
|
-
const [
|
|
2441
|
-
const
|
|
2442
|
-
const
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
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;
|
|
2459
2480
|
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
return measureEl.scrollWidth;
|
|
2463
|
-
};
|
|
2464
|
-
const fullWidth = measure(value);
|
|
2465
|
-
if (fullWidth <= available) {
|
|
2466
|
-
updateState(fullState);
|
|
2467
|
-
return;
|
|
2481
|
+
if (isHook(data) && data.token) {
|
|
2482
|
+
return data.token;
|
|
2468
2483
|
}
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
displayText: result.text,
|
|
2472
|
-
isTruncated: result.truncated,
|
|
2473
|
-
prefixGraphemeCount: result.prefixGraphemeCount,
|
|
2474
|
-
prefixText: result.prefixText,
|
|
2475
|
-
suffixGraphemeCount: result.suffixGraphemeCount,
|
|
2476
|
-
suffixText: result.suffixText
|
|
2477
|
-
});
|
|
2478
|
-
}, [fullState, graphemes, updateState, value]);
|
|
2479
|
-
useIsomorphicLayoutEffect(() => {
|
|
2480
|
-
recalculate();
|
|
2481
|
-
}, [recalculate]);
|
|
2484
|
+
return void 0;
|
|
2485
|
+
}, [resource, resourceId, spanDetailData, data]);
|
|
2482
2486
|
reactExports.useEffect(() => {
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
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)
|
|
2486
2495
|
return;
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
prefixText: state.prefixText,
|
|
2514
|
-
suffixGraphemeCount: state.suffixGraphemeCount,
|
|
2515
|
-
suffixText: state.suffixText
|
|
2516
|
-
};
|
|
2517
|
-
}
|
|
2518
|
-
function getRangeOffsets(container, range) {
|
|
2519
|
-
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) {
|
|
2520
|
-
return null;
|
|
2521
|
-
}
|
|
2522
|
-
const startRange = document.createRange();
|
|
2523
|
-
startRange.selectNodeContents(container);
|
|
2524
|
-
startRange.setEnd(range.startContainer, range.startOffset);
|
|
2525
|
-
const endRange = document.createRange();
|
|
2526
|
-
endRange.selectNodeContents(container);
|
|
2527
|
-
endRange.setEnd(range.endContainer, range.endOffset);
|
|
2528
|
-
return {
|
|
2529
|
-
end: endRange.toString().length,
|
|
2530
|
-
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
|
+
}
|
|
2531
2522
|
};
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
2535
|
-
const visibleRef = reactExports.useRef(null);
|
|
2536
|
-
const handleCopy = reactExports.useCallback((e) => {
|
|
2537
|
-
onCopyProp == null ? void 0 : onCopyProp(e);
|
|
2538
|
-
if (e.defaultPrevented || !isTruncated)
|
|
2523
|
+
const handleResolveHook = reactExports.useCallback(async (payload) => {
|
|
2524
|
+
if (resolvingHook)
|
|
2539
2525
|
return;
|
|
2540
|
-
|
|
2541
|
-
|
|
2526
|
+
if (!onResolveHook) {
|
|
2527
|
+
toast2.error("Unable to resolve hook", {
|
|
2528
|
+
description: "No resolve handler provided."
|
|
2529
|
+
});
|
|
2542
2530
|
return;
|
|
2543
|
-
|
|
2544
|
-
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
|
+
});
|
|
2545
2536
|
return;
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
const
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
});
|
|
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));
|
|
2559
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);
|
|
2560
2557
|
}
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
if (
|
|
2568
|
-
return;
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
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 })] });
|
|
2573
2589
|
}
|
|
2590
|
+
const QUERY = "(prefers-reduced-motion: reduce)";
|
|
2591
|
+
const useReducedMotion = () => {
|
|
2592
|
+
const [reduced, setReduced] = reactExports.useState(() => {
|
|
2593
|
+
if (typeof window === "undefined" || !window.matchMedia)
|
|
2594
|
+
return false;
|
|
2595
|
+
return window.matchMedia(QUERY).matches;
|
|
2596
|
+
});
|
|
2597
|
+
reactExports.useEffect(() => {
|
|
2598
|
+
if (typeof window === "undefined" || !window.matchMedia)
|
|
2599
|
+
return;
|
|
2600
|
+
const media = window.matchMedia(QUERY);
|
|
2601
|
+
const onChange = () => setReduced(media.matches);
|
|
2602
|
+
media.addEventListener("change", onChange);
|
|
2603
|
+
onChange();
|
|
2604
|
+
return () => media.removeEventListener("change", onChange);
|
|
2605
|
+
}, []);
|
|
2606
|
+
return reduced;
|
|
2607
|
+
};
|
|
2608
|
+
const WorkflowIcon = () => {
|
|
2609
|
+
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" }) });
|
|
2610
|
+
};
|
|
2611
|
+
const WebhookIcon = () => {
|
|
2612
|
+
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" }) });
|
|
2613
|
+
};
|
|
2614
|
+
const SleepIcon = () => {
|
|
2615
|
+
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" }) });
|
|
2616
|
+
};
|
|
2617
|
+
const StepForwardIcon = () => {
|
|
2618
|
+
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" }) });
|
|
2619
|
+
};
|
|
2574
2620
|
const eventStyles = {
|
|
2575
2621
|
run: { icon: WorkflowIcon, className: "text-blue-900" },
|
|
2576
2622
|
step: { icon: StepForwardIcon, className: "text-green-900" },
|
|
2577
|
-
hook: { icon: WebhookIcon, className: "text-
|
|
2623
|
+
hook: { icon: WebhookIcon, className: "text-gray-900" },
|
|
2578
2624
|
sleep: { icon: SleepIcon, className: "text-gray-900" }
|
|
2579
2625
|
};
|
|
2580
2626
|
const defaultStyle = {
|
|
@@ -2593,7 +2639,7 @@ const EventRow = ({ span, isSelected, onSelectSpan }) => {
|
|
|
2593
2639
|
const durationMs = getSpanDurationMs(span);
|
|
2594
2640
|
const isErrored = span.attributes.data.status === "failed";
|
|
2595
2641
|
const { icon: Icon, className: tagClassName } = getEventStyle(span.resource, isErrored);
|
|
2596
|
-
return jsxRuntimeExports.jsx("li", { className: cn("relative overflow-clip group after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-gray-alpha-400", ROW_HEIGHT_CLASS), 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
|
|
2642
|
+
return jsxRuntimeExports.jsx("li", { className: cn("relative overflow-clip group after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-gray-alpha-400", ROW_HEIGHT_CLASS), 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) }) })] }) }) });
|
|
2597
2643
|
};
|
|
2598
2644
|
const EventList = ({ spans, activeSpanId, onSelectSpan }) => {
|
|
2599
2645
|
return jsxRuntimeExports.jsx("ul", { id: "event-list", role: "tree", className: "block min-h-0 overflow-visible", children: spans.map((span) => {
|
|
@@ -2695,7 +2741,7 @@ function DetailPanel({ span, rootStart, onClose }) {
|
|
|
2695
2741
|
const startMs = getHighResInMs(span.startTime);
|
|
2696
2742
|
const durationMs = getSpanDurationMs(span);
|
|
2697
2743
|
const offsetMs = startMs - rootStart;
|
|
2698
|
-
return jsxRuntimeExports.jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), jsxRuntimeExports.jsx("button", { type: "button", className: "p-1 rounded-md text-gray-
|
|
2744
|
+
return jsxRuntimeExports.jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), jsxRuntimeExports.jsx("button", { type: "button", className: "p-1 rounded-md text-gray-1000 hover:bg-gray-alpha-100 transition-colors", onClick: onClose, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] }), jsxRuntimeExports.jsx("div", { className: "overflow-y-auto p-3 space-y-3", children: jsxRuntimeExports.jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm", children: [jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Resource" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 font-mono", children: span.resource }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Duration" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 tabular-nums font-mono", children: formatDuration(durationMs) }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Offset" }), jsxRuntimeExports.jsxs("dd", { className: "text-gray-1000 tabular-nums font-mono", children: ["+", formatDuration(offsetMs)] }), jsxRuntimeExports.jsx("dt", { className: "text-gray-900", children: "Status" }), jsxRuntimeExports.jsx("dd", { className: "text-gray-1000 font-mono", children: span.status.code === 2 ? "Error" : "OK" })] }) })] });
|
|
2699
2745
|
}
|
|
2700
2746
|
const MIN_VIEWPORT_MS = 1e-3;
|
|
2701
2747
|
function useAnimatedViewport(initial) {
|
|
@@ -2703,6 +2749,7 @@ function useAnimatedViewport(initial) {
|
|
|
2703
2749
|
const animRef = reactExports.useRef(null);
|
|
2704
2750
|
const currentRef = reactExports.useRef(initial);
|
|
2705
2751
|
currentRef.current = viewport;
|
|
2752
|
+
const reducedMotion = useReducedMotion();
|
|
2706
2753
|
const cancel = reactExports.useCallback(() => {
|
|
2707
2754
|
if (animRef.current) {
|
|
2708
2755
|
cancelAnimationFrame(animRef.current.raf);
|
|
@@ -2711,6 +2758,11 @@ function useAnimatedViewport(initial) {
|
|
|
2711
2758
|
}, []);
|
|
2712
2759
|
const animateTo = reactExports.useCallback((target) => {
|
|
2713
2760
|
cancel();
|
|
2761
|
+
if (reducedMotion) {
|
|
2762
|
+
currentRef.current = target;
|
|
2763
|
+
setViewportState(target);
|
|
2764
|
+
return;
|
|
2765
|
+
}
|
|
2714
2766
|
const from = currentRef.current;
|
|
2715
2767
|
const anim = { raf: 0, from, to: target, start: performance.now() };
|
|
2716
2768
|
const tick = () => {
|
|
@@ -2727,7 +2779,7 @@ function useAnimatedViewport(initial) {
|
|
|
2727
2779
|
};
|
|
2728
2780
|
animRef.current = anim;
|
|
2729
2781
|
anim.raf = requestAnimationFrame(tick);
|
|
2730
|
-
}, [cancel]);
|
|
2782
|
+
}, [cancel, reducedMotion]);
|
|
2731
2783
|
const setViewport = reactExports.useCallback((update) => {
|
|
2732
2784
|
cancel();
|
|
2733
2785
|
if (typeof update === "function") {
|
|
@@ -2875,13 +2927,25 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2875
2927
|
]);
|
|
2876
2928
|
const [altHeld, setAltHeld] = reactExports.useState(false);
|
|
2877
2929
|
reactExports.useEffect(() => {
|
|
2930
|
+
const handleSidebarNavKey = (e) => {
|
|
2931
|
+
const target = e.target;
|
|
2932
|
+
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || (target == null ? void 0 : target.isContentEditable)) {
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
const targetId = e.key === "k" ? prevSpanIdRef.current : nextSpanIdRef.current;
|
|
2936
|
+
if (targetId) {
|
|
2937
|
+
e.preventDefault();
|
|
2938
|
+
handleSelectSpanRef.current(targetId);
|
|
2939
|
+
}
|
|
2940
|
+
};
|
|
2878
2941
|
const onKeyDown = (e) => {
|
|
2879
2942
|
if (e.key === "Escape") {
|
|
2880
2943
|
clearActiveSpan();
|
|
2881
|
-
}
|
|
2882
|
-
if (e.key === "Alt") {
|
|
2944
|
+
} else if (e.key === "Alt") {
|
|
2883
2945
|
e.preventDefault();
|
|
2884
2946
|
setAltHeld(true);
|
|
2947
|
+
} else if (e.key === "j" || e.key === "k") {
|
|
2948
|
+
handleSidebarNavKey(e);
|
|
2885
2949
|
}
|
|
2886
2950
|
};
|
|
2887
2951
|
const onKeyUp = (e) => {
|
|
@@ -2998,17 +3062,33 @@ function NewTraceViewerContent({ trace }) {
|
|
|
2998
3062
|
const workflowName = data.workflowName;
|
|
2999
3063
|
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";
|
|
3000
3064
|
}, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource]);
|
|
3001
|
-
const
|
|
3002
|
-
|
|
3003
|
-
if (!
|
|
3004
|
-
return
|
|
3005
|
-
const
|
|
3006
|
-
if (
|
|
3007
|
-
return
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3065
|
+
const { prevSpanId, nextSpanId } = reactExports.useMemo(() => {
|
|
3066
|
+
var _a, _b;
|
|
3067
|
+
if (!activeSpanId)
|
|
3068
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3069
|
+
const i = filteredSpans.findIndex((s) => s.spanId === activeSpanId);
|
|
3070
|
+
if (i === -1)
|
|
3071
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
3072
|
+
return {
|
|
3073
|
+
prevSpanId: ((_a = filteredSpans[i - 1]) == null ? void 0 : _a.spanId) ?? null,
|
|
3074
|
+
nextSpanId: ((_b = filteredSpans[i + 1]) == null ? void 0 : _b.spanId) ?? null
|
|
3075
|
+
};
|
|
3076
|
+
}, [activeSpanId, filteredSpans]);
|
|
3077
|
+
const handleSelectPrevSpan = reactExports.useCallback(() => {
|
|
3078
|
+
if (prevSpanId)
|
|
3079
|
+
handleSelectSpan(prevSpanId);
|
|
3080
|
+
}, [prevSpanId, handleSelectSpan]);
|
|
3081
|
+
const handleSelectNextSpan = reactExports.useCallback(() => {
|
|
3082
|
+
if (nextSpanId)
|
|
3083
|
+
handleSelectSpan(nextSpanId);
|
|
3084
|
+
}, [nextSpanId, handleSelectSpan]);
|
|
3085
|
+
const prevSpanIdRef = reactExports.useRef(prevSpanId);
|
|
3086
|
+
const nextSpanIdRef = reactExports.useRef(nextSpanId);
|
|
3087
|
+
const handleSelectSpanRef = reactExports.useRef(handleSelectSpan);
|
|
3088
|
+
prevSpanIdRef.current = prevSpanId;
|
|
3089
|
+
nextSpanIdRef.current = nextSpanId;
|
|
3090
|
+
handleSelectSpanRef.current = handleSelectSpan;
|
|
3091
|
+
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), 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: "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.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("button", { type: "button", "aria-label": "Navigate to previous span", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, className: "p-1 rounded text-gray-1000 transition-colors enabled:hover:bg-gray-alpha-100 disabled:opacity-40 disabled:cursor-not-allowed", children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Navigate to next span", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, className: "p-1 rounded text-gray-1000 transition-colors enabled:hover:bg-gray-alpha-100 disabled:opacity-40 disabled:cursor-not-allowed", 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("button", { type: "button", "aria-label": "Close span details", "aria-keyshortcuts": "Escape", className: "p-1 rounded text-gray-1000 hover:bg-gray-alpha-100 transition-colors", 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] });
|
|
3012
3092
|
}
|
|
3013
3093
|
const NewTraceViewer = ({ run, events, sidebarData }) => {
|
|
3014
3094
|
const traceWithMeta = reactExports.useMemo(() => {
|