@burdenoff/fluidgrids-fe-sdk 2026.801.7 → 2026.801.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/dist/ExecutionDetailPage-2J4HYS5M.js +9 -0
- package/dist/{ExecutionDetailPage-VCVJ2EOP.js.map → ExecutionDetailPage-2J4HYS5M.js.map} +1 -1
- package/dist/ExecutionsListPage-Q5QM5UFT.js +8 -0
- package/dist/{ExecutionsListPage-NXTMFIRZ.js.map → ExecutionsListPage-Q5QM5UFT.js.map} +1 -1
- package/dist/{chunk-TKAS26Q3.js → chunk-5ASKIPC6.js} +40 -12
- package/dist/chunk-5ASKIPC6.js.map +1 -0
- package/dist/{chunk-USFXD36A.js → chunk-AGECCY5V.js} +10 -3
- package/dist/chunk-AGECCY5V.js.map +1 -0
- package/dist/{chunk-6AK7GFWB.js → chunk-VNSIXELY.js} +60 -20
- package/dist/chunk-VNSIXELY.js.map +1 -0
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/dist/ExecutionDetailPage-VCVJ2EOP.js +0 -8
- package/dist/ExecutionsListPage-NXTMFIRZ.js +0 -8
- package/dist/chunk-6AK7GFWB.js.map +0 -1
- package/dist/chunk-TKAS26Q3.js.map +0 -1
- package/dist/chunk-USFXD36A.js.map +0 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { ExecutionDetailPage } from './chunk-5ASKIPC6.js';
|
|
2
|
+
import './chunk-VNSIXELY.js';
|
|
3
|
+
import './chunk-UIY2HBWA.js';
|
|
4
|
+
import './chunk-3ZYUGTIT.js';
|
|
5
|
+
import './chunk-XEYNX7YJ.js';
|
|
6
|
+
import './chunk-5BDQNSP3.js';
|
|
7
|
+
import './chunk-WWU2O2SR.js';
|
|
8
|
+
//# sourceMappingURL=ExecutionDetailPage-2J4HYS5M.js.map
|
|
9
|
+
//# sourceMappingURL=ExecutionDetailPage-2J4HYS5M.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"ExecutionDetailPage-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ExecutionDetailPage-2J4HYS5M.js"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { ExecutionsListPage } from './chunk-AGECCY5V.js';
|
|
2
|
+
import './chunk-VNSIXELY.js';
|
|
3
|
+
import './chunk-NMS2QUXG.js';
|
|
4
|
+
import './chunk-XEYNX7YJ.js';
|
|
5
|
+
import './chunk-5BDQNSP3.js';
|
|
6
|
+
import './chunk-WWU2O2SR.js';
|
|
7
|
+
//# sourceMappingURL=ExecutionsListPage-Q5QM5UFT.js.map
|
|
8
|
+
//# sourceMappingURL=ExecutionsListPage-Q5QM5UFT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"ExecutionsListPage-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ExecutionsListPage-Q5QM5UFT.js"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { useExecution, useExecutionActions, useAutoRefresh, ExecutionStatusBadge, NodeTimeline, RunLogViewer } from './chunk-
|
|
1
|
+
import { useExecution, buildNodeDisplayMap, useExecutionActions, useAutoRefresh, ExecutionStatusBadge, formatRunVersion, NodeTimeline, RunLogViewer } from './chunk-VNSIXELY.js';
|
|
2
2
|
import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS } from './chunk-UIY2HBWA.js';
|
|
3
3
|
import { RunLogsDocument, throwIfResultError, RunLogAppendedDocument } from './chunk-XEYNX7YJ.js';
|
|
4
4
|
import { getFluidGridsClientSafe } from './chunk-5BDQNSP3.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getFluidGridsConfig } from './chunk-WWU2O2SR.js';
|
|
6
|
+
import { useState, useMemo, useCallback, useRef, useEffect } from 'react';
|
|
6
7
|
import { useParams, useNavigate, Link } from 'react-router-dom';
|
|
7
8
|
import { Icon } from '@iconify/react';
|
|
8
9
|
import { Button } from '@burdenoff/fe-libs/button';
|
|
9
10
|
import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from '@burdenoff/fe-libs/ui';
|
|
11
|
+
import { useActorProfiles, buildActorFallback } from '@burdenoff/fe-libs/shared';
|
|
10
12
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
11
13
|
|
|
12
14
|
var POLL_INTERVAL_MS = 2e3;
|
|
@@ -170,6 +172,24 @@ function ExecutionDetailPage() {
|
|
|
170
172
|
);
|
|
171
173
|
const [minLogLevel, setMinLogLevel] = useState(null);
|
|
172
174
|
const { execution, loading, error, refetch } = useExecution(runId);
|
|
175
|
+
const nodeDisplay = useMemo(
|
|
176
|
+
() => buildNodeDisplayMap(execution?.workflow?.definitionJson),
|
|
177
|
+
[execution?.workflow?.definitionJson]
|
|
178
|
+
);
|
|
179
|
+
const fgConfig = getFluidGridsConfig();
|
|
180
|
+
const actorInputs = useMemo(
|
|
181
|
+
() => execution?.triggeredById ? [{ actorId: execution.triggeredById, actorType: "user" }] : [],
|
|
182
|
+
[execution?.triggeredById]
|
|
183
|
+
);
|
|
184
|
+
const actorProfiles = useActorProfiles(actorInputs, {
|
|
185
|
+
workspaceId: fgConfig.workspaceId || void 0,
|
|
186
|
+
orgId: fgConfig.organizationId,
|
|
187
|
+
authToken: fgConfig.authToken
|
|
188
|
+
});
|
|
189
|
+
const triggeredByLabel = execution?.triggeredById ? actorProfiles[execution.triggeredById]?.displayName ?? buildActorFallback({
|
|
190
|
+
actorId: execution.triggeredById,
|
|
191
|
+
actorType: "user"
|
|
192
|
+
}).displayName : null;
|
|
173
193
|
const {
|
|
174
194
|
pauseExecution,
|
|
175
195
|
resumeExecution,
|
|
@@ -353,8 +373,7 @@ function ExecutionDetailPage() {
|
|
|
353
373
|
] }),
|
|
354
374
|
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
355
375
|
/* @__PURE__ */ jsx(Icon, { icon: "mdi:tag-outline", width: 16 }),
|
|
356
|
-
|
|
357
|
-
execution.version
|
|
376
|
+
formatRunVersion(execution.version)
|
|
358
377
|
] }),
|
|
359
378
|
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
360
379
|
/* @__PURE__ */ jsx(Icon, { icon: "mdi:clock-outline", width: 16 }),
|
|
@@ -502,7 +521,7 @@ function ExecutionDetailPage() {
|
|
|
502
521
|
] }),
|
|
503
522
|
/* @__PURE__ */ jsxs("div", { className: "bg-background-secondary rounded-lg border border-border-secondary p-4", children: [
|
|
504
523
|
/* @__PURE__ */ jsx("div", { className: "text-sm text-text-secondary", children: "Trigger" }),
|
|
505
|
-
/* @__PURE__ */ jsx("div", { className: "text-lg font-medium text-text-primary mt-1 truncate", children: execution.triggerNodeId })
|
|
524
|
+
/* @__PURE__ */ jsx("div", { className: "text-lg font-medium text-text-primary mt-1 truncate", children: execution.triggerNodeId ? nodeDisplay[execution.triggerNodeId]?.label ?? execution.triggerNodeId : "\u2014" })
|
|
506
525
|
] })
|
|
507
526
|
] }),
|
|
508
527
|
execution.errorMessage && /* @__PURE__ */ jsxs("div", { className: "mb-6 p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg", children: [
|
|
@@ -535,6 +554,7 @@ function ExecutionDetailPage() {
|
|
|
535
554
|
NodeTimeline,
|
|
536
555
|
{
|
|
537
556
|
nodeStates: execution.nodeStates ?? [],
|
|
557
|
+
nodeDisplay,
|
|
538
558
|
triggerNodeId: execution.triggerNodeId ?? void 0,
|
|
539
559
|
onRetryNode: canControlRuns ? handleRetryNode : void 0,
|
|
540
560
|
onViewChildRun: handleViewChildRun
|
|
@@ -546,6 +566,7 @@ function ExecutionDetailPage() {
|
|
|
546
566
|
runId,
|
|
547
567
|
lines: runLogs.lines,
|
|
548
568
|
nodeStates: execution.nodeStates ?? [],
|
|
569
|
+
nodeDisplay,
|
|
549
570
|
loading: runLogs.loading,
|
|
550
571
|
error: runLogs.error,
|
|
551
572
|
hasMore: runLogs.hasMore,
|
|
@@ -574,20 +595,27 @@ function ExecutionDetailPage() {
|
|
|
574
595
|
/* @__PURE__ */ jsx("code", { className: "font-mono text-text-primary", children: execution.id })
|
|
575
596
|
] }),
|
|
576
597
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between py-2 border-b border-border-secondary", children: [
|
|
577
|
-
/* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Workflow
|
|
578
|
-
/* @__PURE__ */ jsx("
|
|
598
|
+
/* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Workflow" }),
|
|
599
|
+
/* @__PURE__ */ jsx("span", { className: "text-text-primary", children: execution.workflow?.name || execution.workflowKey })
|
|
579
600
|
] }),
|
|
580
601
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between py-2 border-b border-border-secondary", children: [
|
|
581
602
|
/* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Workflow Key" }),
|
|
582
|
-
/* @__PURE__ */ jsx("
|
|
603
|
+
/* @__PURE__ */ jsx("code", { className: "font-mono text-text-primary", children: execution.workflowKey })
|
|
583
604
|
] }),
|
|
584
605
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between py-2 border-b border-border-secondary", children: [
|
|
585
606
|
/* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Version" }),
|
|
586
|
-
/* @__PURE__ */ jsx("span", { className: "text-text-primary", children: execution.version })
|
|
607
|
+
/* @__PURE__ */ jsx("span", { className: "text-text-primary", children: formatRunVersion(execution.version) })
|
|
587
608
|
] }),
|
|
588
609
|
execution.triggeredById && /* @__PURE__ */ jsxs("div", { className: "flex justify-between py-2 border-b border-border-secondary", children: [
|
|
589
610
|
/* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Triggered By" }),
|
|
590
|
-
/* @__PURE__ */ jsx(
|
|
611
|
+
/* @__PURE__ */ jsx(
|
|
612
|
+
"span",
|
|
613
|
+
{
|
|
614
|
+
className: "text-text-primary",
|
|
615
|
+
title: execution.triggeredById,
|
|
616
|
+
children: triggeredByLabel
|
|
617
|
+
}
|
|
618
|
+
)
|
|
591
619
|
] }),
|
|
592
620
|
execution.parentRunId && /* @__PURE__ */ jsxs("div", { className: "flex justify-between py-2 border-b border-border-secondary", children: [
|
|
593
621
|
/* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: "Parent Run" }),
|
|
@@ -648,5 +676,5 @@ function ExecutionDetailPage() {
|
|
|
648
676
|
}
|
|
649
677
|
|
|
650
678
|
export { ExecutionDetailPage };
|
|
651
|
-
//# sourceMappingURL=chunk-
|
|
652
|
-
//# sourceMappingURL=chunk-
|
|
679
|
+
//# sourceMappingURL=chunk-5ASKIPC6.js.map
|
|
680
|
+
//# sourceMappingURL=chunk-5ASKIPC6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/modules/executions/hooks/useRunLogs.ts","../src/modules/executions/pages/ExecutionDetailPage.tsx"],"names":["useState","useMemo","useCallback"],"mappings":";;;;;;;;;;;;;AA2BA,IAAM,gBAAA,GAAmB,GAAA;AAGzB,IAAM,SAAA,GAAY,GAAA;AAwCX,SAAS,UAAA,CACd,KAAA,EACA,OAAA,GAA6B,EAAC,EACZ;AAClB,EAAA,MAAM,EAAE,IAAA,GAAO,KAAA,EAAO,WAAW,IAAA,EAAM,gBAAA,GAAmB,OAAM,GAAI,OAAA;AAEpE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA,CAAuB,EAAE,CAAA;AACnD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,KAAK,CAAA;AACtD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAOhD,EAAA,MAAM,OAAA,GAAU,MAAA,iBAAoB,IAAI,GAAA,EAAK,CAAA;AAE7C,EAAA,MAAM,MAAA,GAAS,OAAsB,IAAI,CAAA;AAEzC,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAC,QAAA,KAA2B;AACrD,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAE3B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,EAAE,CAAC,CAAA;AACrE,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACxB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,KAAK,EAAE,CAAA;AAErD,IAAA,QAAA;AAAA,MAAS,CAAC,IAAA;AAAA;AAAA;AAAA;AAAA,QAIR,CAAC,GAAG,IAAA,EAAM,GAAG,KAAK,CAAA,CAAE,IAAA;AAAA,UAAK,CAAC,CAAA,EAAG,CAAA,KAC3B,CAAA,CAAE,SAAA,KAAc,EAAE,SAAA,GACd,CAAA,CAAE,EAAA,CAAG,aAAA,CAAc,EAAE,EAAE,CAAA,GACvB,EAAE,SAAA,CAAU,aAAA,CAAc,EAAE,SAAS;AAAA;AAC3C;AAAA,KACF;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,OAAO,KAAA,KAAwC;AAC7C,MAAA,MAAM,SAAS,uBAAA,EAAwB;AACvC,MAAA,IAAI,CAAC,MAAA,IAAU,CAAC,KAAA,EAAO;AAEvB,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,KAAA,CAAmB;AAAA,QAC7C,KAAA,EAAO,eAAA;AAAA,QACP,SAAA,EAAW;AAAA,UACT,KAAA;AAAA,UACA,KAAA;AAAA,UACA,KAAA,EAAO,SAAA;AAAA,UACP,QAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,WAAA,EAAa;AAAA,OACd,CAAA;AACD,MAAA,kBAAA,CAAmB,MAAM,CAAA;AAEzB,MAAA,MAAM,IAAA,GAAO,OAAO,IAAA,EAAM,eAAA;AAC1B,MAAA,IAAI,CAAC,IAAA,EAAM;AAEX,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,UAAA,CAAW,KAAK,OAAO,CAAA;AACvB,MAAA,eAAA,CAAgB,KAAK,YAAY,CAAA;AACjC,MAAA,IAAI,IAAA,CAAK,UAAA,EAAY,MAAA,CAAO,OAAA,GAAU,IAAA,CAAK,UAAA;AAAA,IAC7C,CAAA;AAAA,IACA,CAAC,KAAA,EAAO,QAAA,EAAU,gBAAA,EAAkB,MAAM;AAAA,GAC5C;AAEA,EAAA,MAAM,OAAA,GAAU,YAAY,YAAY;AACtC,IAAA,OAAA,CAAQ,OAAA,uBAAc,GAAA,EAAI;AAC1B,IAAA,MAAA,CAAO,OAAA,GAAU,IAAA;AACjB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,IAAI;AACF,MAAA,MAAM,UAAU,IAAI,CAAA;AAAA,IACtB,SAAS,GAAA,EAAK;AACZ,MAAA,QAAA,CAAS,GAAY,CAAA;AAAA,IACvB,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,QAAA,GAAW,YAAY,YAAY;AACvC,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,CAAU,OAAO,OAAO,CAAA;AAAA,IAChC,SAAS,GAAA,EAAK;AACZ,MAAA,QAAA,CAAS,GAAY,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAId,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,KAAK,OAAA,EAAQ;AAAA,EACf,CAAA,EAAG,CAAC,KAAA,EAAO,OAAO,CAAC,CAAA;AAGnB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAS,uBAAA,EAAwB;AACvC,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,IAAA,IAAQ,CAAC,MAAA,EAAQ;AAC9B,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,IAAI,IAAA,GAA8C,IAAA;AAElD,IAAA,MAAM,eAAe,MAAY;AAC/B,MAAA,IAAI,QAAQ,SAAA,EAAW;AACvB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAA,GAAO,YAAY,MAAM;AACvB,QAAA,KAAK,SAAA,CAAU,MAAA,CAAO,OAAO,CAAA,CAAE,MAAM,MAAM;AAAA,QAG3C,CAAC,CAAA;AAAA,MACH,GAAG,gBAAgB,CAAA;AAAA,IACrB,CAAA;AAEA,IAAA,MAAM,YAAA,GAAe,OAClB,SAAA,CAA8B;AAAA,MAC7B,KAAA,EAAO,sBAAA;AAAA,MACP,SAAA,EAAW,EAAE,KAAA;AAAM,KACpB,EACA,SAAA,CAAU;AAAA,MACT,IAAA,EAAM,CAAC,EAAE,IAAA,EAAK,KAAM;AAClB,QAAA,IAAI,SAAA,EAAW;AACf,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,MAAA,CAAO,IAAA,EAAM,cAAA,IAAkB,EAAE,CAAA;AAAA,MACnC,CAAA;AAAA,MACA,OAAO,MAAM;AAEX,QAAA,YAAA,EAAa;AAAA,MACf,CAAA;AAAA,MACA,UAAU,MAAM;AACd,QAAA,IAAI,CAAC,WAAW,YAAA,EAAa;AAAA,MAC/B;AAAA,KACD,CAAA;AAKH,IAAA,MAAM,cAAA,GAAiB,UAAA,CAAW,YAAA,EAAc,gBAAA,GAAmB,CAAC,CAAA;AAEpE,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,YAAA,CAAa,cAAc,CAAA;AAC3B,MAAA,IAAI,IAAA,gBAAoB,IAAI,CAAA;AAC5B,MAAA,YAAA,CAAa,WAAA,EAAY;AACzB,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB,CAAA;AAAA,EACF,GAAG,CAAC,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,MAAM,CAAC,CAAA;AAQnC,EAAA,MAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC5B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,QAAQ,OAAA,EAAS;AACtB,IAAA,OAAA,CAAQ,OAAA,GAAU,KAAA;AAElB,IAAA,KAAK,SAAA,CAAU,MAAA,CAAO,OAAO,CAAA,CAAE,MAAM,MAAM;AAAA,IAE3C,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,IAAA,EAAM,SAAS,CAAC,CAAA;AAIpB,EAAA,MAAM,QAAA,GAAW,QAAQ,MAAM;AAC7B,IAAA,IAAI,CAAC,UAAU,OAAO,KAAA;AACtB,IAAA,MAAM,KAAA,GAAuB,CAAC,OAAA,EAAS,MAAA,EAAQ,QAAQ,OAAO,CAAA;AAC9D,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA;AACpC,IAAA,OAAO,KAAA,CAAM,OAAO,CAAC,IAAA,KAAS,MAAM,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,IAAK,KAAK,CAAA;AAAA,EAClE,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,QAAA;AAAA,IACP,OAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACF;AACF;ACvOO,SAAS,mBAAA,GAAsB;AACpC,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,SAAA,EAA6B;AAC/C,EAAA,MAAM,WAAW,WAAA,EAAY;AAE7B,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,SAAoB,UAAU,CAAA;AAChE,EAAA,MAAM,CAAC,kBAAA,EAAoB,qBAAqB,CAAA,GAAIA,SAAS,IAAI,CAAA;AACjE,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAIA,SAAS,KAAK,CAAA;AACpE,EAAA,MAAM,EAAE,OAAA,EAAS,cAAA,EAAe,GAAI,uBAAA;AAAA,IAClC,sBAAA,CAAuB;AAAA,GACzB;AAEA,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIA,SAA6B,IAAI,CAAA;AAGvE,EAAA,MAAM,EAAE,SAAA,EAAW,OAAA,EAAS,OAAO,OAAA,EAAQ,GAAI,aAAa,KAAK,CAAA;AAGjE,EAAA,MAAM,WAAA,GAAcC,OAAAA;AAAA,IAClB,MAAM,mBAAA,CAAoB,SAAA,EAAW,QAAA,EAAU,cAAc,CAAA;AAAA,IAC7D,CAAC,SAAA,EAAW,QAAA,EAAU,cAAc;AAAA,GACtC;AAGA,EAAA,MAAM,WAAW,mBAAA,EAAoB;AACrC,EAAA,MAAM,WAAA,GAAcA,OAAAA;AAAA,IAClB,MACE,SAAA,EAAW,aAAA,GACP,CAAC,EAAE,OAAA,EAAS,SAAA,CAAU,aAAA,EAAe,SAAA,EAAW,MAAA,EAAQ,CAAA,GACxD,EAAC;AAAA,IACP,CAAC,WAAW,aAAa;AAAA,GAC3B;AACA,EAAA,MAAM,aAAA,GAAgB,iBAAiB,WAAA,EAAa;AAAA,IAClD,WAAA,EAAa,SAAS,WAAA,IAAe,MAAA;AAAA,IACrC,OAAO,QAAA,CAAS,cAAA;AAAA,IAChB,WAAW,QAAA,CAAS;AAAA,GACrB,CAAA;AACD,EAAA,MAAM,gBAAA,GAAmB,WAAW,aAAA,GAC/B,aAAA,CAAc,UAAU,aAAa,CAAA,EAAG,eACzC,kBAAA,CAAmB;AAAA,IACjB,SAAS,SAAA,CAAU,aAAA;AAAA,IACnB,SAAA,EAAW;AAAA,GACZ,EAAE,WAAA,GACH,IAAA;AACJ,EAAA,MAAM;AAAA,IACJ,cAAA;AAAA,IACA,eAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAA;AAAA,IACA,kBAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,mBAAA,EAAoB;AAGxB,EAAA,MAAM,QAAA,GACJ,WAAW,MAAA,KAAW,SAAA,IACtB,WAAW,MAAA,KAAW,SAAA,IACtB,WAAW,MAAA,KAAW,SAAA;AAIxB,EAAA,cAAA;AAAA,IACEC,YAAY,MAAM;AAChB,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAAA,IACZ,kBAAA,IAAsB,QAAA;AAAA,IACtB;AAAA,GACF;AAEA,EAAA,MAAM,OAAA,GAAU,WAAW,KAAA,EAAO;AAAA;AAAA;AAAA,IAGhC,IAAA,EAAM,QAAA;AAAA,IACN,QAAA,EAAU;AAAA,GACX,CAAA;AAGD,EAAA,MAAM,cAAc,YAAY;AAC9B,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,eAAe,KAAK,CAAA;AAC1B,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,gBAAgB,KAAK,CAAA;AAC3B,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,gBAAgB,KAAK,CAAA;AAC3B,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,MAAM,kBAAkB,YAAY;AAClC,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,kBAAA,CAAmB,OAAO,iBAAiB,CAAA;AACjD,IAAA,sBAAA,CAAuB,KAAK,CAAA;AAC5B,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,MAAM,eAAA,GAAkB,OAAO,MAAA,KAAmB;AAChD,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,SAAA,CAAU,OAAO,MAAM,CAAA;AAC7B,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqBA,WAAAA;AAAA,IACzB,CAAC,UAAA,KAAuB;AACtB,MAAA,QAAA,CAAS,CAAA,QAAA,EAAW,UAAU,CAAA,CAAE,CAAA;AAAA,IAClC,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAGA,EAAA,MAAM,cAAA,GAAiB,CAAC,EAAA,KAAwB;AAC9C,IAAA,IAAI,CAAC,IAAI,OAAO,GAAA;AAChB,IAAA,IAAI,EAAA,GAAK,GAAA,EAAM,OAAO,CAAA,EAAG,EAAE,CAAA,EAAA,CAAA;AAC3B,IAAA,IAAI,EAAA,GAAK,KAAO,OAAO,CAAA,EAAA,CAAI,KAAK,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AAChD,IAAA,IAAI,EAAA,GAAK,IAAA;AACP,MAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,EAAA,GAAK,GAAK,CAAC,CAAA,EAAA,EAAK,IAAA,CAAK,KAAA,CAAO,EAAA,GAAK,GAAA,GAAS,GAAI,CAAC,CAAA,CAAA,CAAA;AACtE,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,EAAA,GAAK,IAAO,CAAC,CAAA,EAAA,EAAK,IAAA,CAAK,KAAA,CAAO,EAAA,GAAK,IAAA,GAAW,GAAK,CAAC,CAAA,CAAA,CAAA;AAAA,EAC3E,CAAA;AAEA,EAAA,MAAM,cAAA,GAAiB,CAAC,OAAA,KAA6B;AACnD,IAAA,IAAI,CAAC,SAAS,OAAO,GAAA;AACrB,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,OAAO,CAAA;AAC7B,IAAA,OAAO,IAAA,CAAK,eAAe,OAAA,EAAS;AAAA,MAClC,KAAA,EAAO,OAAA;AAAA,MACP,GAAA,EAAK,SAAA;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,SAAA;AAAA,MACN,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH,CAAA;AAGA,EAAA,IAAI,OAAA,IAAW,CAAC,SAAA,EAAW;AACzB,IAAA,2BACG,KAAA,EAAA,EAAI,SAAA,EAAU,iDACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,eAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8CAAA,EAA+C,CAAA;AAAA,sBAC9D,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8CAAA,EAA+C,CAAA;AAAA,sBAC9D,GAAA,CAAC,SAAI,SAAA,EAAU,4CAAA,EACZ,WAAC,GAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA,EAAG,sBACrB,GAAA,CAAC,KAAA,EAAA,EAAY,WAAU,wCAAA,EAAA,EAAb,CAAsD,CACjE,CAAA,EACH,CAAA;AAAA,sBACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCAAA,EAAyC;AAAA,KAAA,EAC1D,CAAA,EACF,CAAA;AAAA,EAEJ;AAGA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+CAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,SAAA;AAAA,UACH,SAAA,EAAU,oEAAA;AAAA,UACX,QAAA,EAAA;AAAA;AAAA,OAED;AAAA,sBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sHAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,kBAAA;AAAA,YACL,SAAA,EAAU,oDAAA;AAAA,YACV,KAAA,EAAO;AAAA;AAAA,SACT;AAAA,wBACA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,gEAAA,EAAiE,QAAA,EAAA,0BAAA,EAE/E,CAAA;AAAA,wBACA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4CAAA,EACV,gBAAM,OAAA,EACT,CAAA;AAAA,4BACC,MAAA,EAAA,EAAO,OAAA,EAAQ,SAAA,EAAU,OAAA,EAAS,SAAS,QAAA,EAAA,WAAA,EAE5C;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AAGA,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+CAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,SAAA;AAAA,UACH,SAAA,EAAU,oEAAA;AAAA,UACX,QAAA,EAAA;AAAA;AAAA,OAED;AAAA,sBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mFAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,uBAAA;AAAA,YACL,SAAA,EAAU,kCAAA;AAAA,YACV,KAAA,EAAO;AAAA;AAAA,SACT;AAAA,wBACA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA,qBAAA,EAE3D,CAAA;AAAA,wBACA,IAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA;AAAA,UAAA,yBAAA;AAAA,UACJ,KAAA;AAAA,UAAM;AAAA,SAAA,EACrC;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,IAAA,GAA8D;AAAA,IAClE,EAAE,EAAA,EAAI,UAAA,EAAY,KAAA,EAAO,UAAA,EAAY,MAAM,cAAA,EAAe;AAAA,IAC1D,EAAE,EAAA,EAAI,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAM,sBAAA,EAAuB;AAAA,IAC1D,EAAE,EAAA,EAAI,OAAA,EAAS,KAAA,EAAO,YAAA,EAAc,MAAM,eAAA,EAAgB;AAAA,IAC1D,EAAE,EAAA,EAAI,SAAA,EAAW,KAAA,EAAO,SAAA,EAAW,MAAM,yBAAA;AAA0B,GACrE;AAEA,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+CAAA,EAEb,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,EAAA,EAAG,SAAA;AAAA,QACH,SAAA,EAAU,oEAAA;AAAA,QACX,QAAA,EAAA;AAAA;AAAA,KAED;AAAA,IAGC,SAAA,CAAU,WAAA,oBACT,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sCAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAK,IAAA,EAAK,aAAA,EAAc,SAAA,EAAU,iBAAA,EAAkB,OAAO,EAAA,EAAI,CAAA;AAAA,sBAChE,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,iBAAA,EAAe,CAAA;AAAA,sBACrD,IAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAI,CAAA,QAAA,EAAW,SAAA,CAAU,WAAW,CAAA,CAAA;AAAA,UACpC,SAAA,EAAU,6CAAA;AAAA,UACX,QAAA,EAAA;AAAA,YAAA,aAAA;AAAA,YACa,SAAA,CAAU,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,YAAE;AAAA;AAAA;AAAA;AACjD,KAAA,EACF,CAAA;AAAA,oBAIF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wEAAA,EACb,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8BAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAG,SAAA,EAAU,kDAAA,EACX,oBAAU,QAAA,EAAU,IAAA,IAAQ,UAAU,WAAA,EACzC,CAAA;AAAA,8BACC,oBAAA,EAAA,EAAqB,MAAA,EAAQ,SAAA,CAAU,MAAA,EAAQ,MAAK,IAAA,EAAK,CAAA;AAAA,UACzD,UAAU,WAAA,oBACT,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6DAA4D,QAAA,EAAA,cAAA,EAE5E;AAAA,SAAA,EAEJ,CAAA;AAAA,wBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+DAAA,EACb,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,yBAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,gBAAA,EAAiB,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,4BACvC,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,WAAA,EAAa,QAAA,EAAA;AAAA,cAAA,SAAA,CAAU,EAAA,CAAG,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,cAAE;AAAA,aAAA,EAAG;AAAA,WAAA,EAC5D,CAAA;AAAA,0BACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,iBAAA,EAAkB,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,YACvC,gBAAA,CAAiB,UAAU,OAAO;AAAA,WAAA,EACrC,CAAA;AAAA,0BACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,mBAAA,EAAoB,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,YACzC,cAAA,CAAe,SAAA,CAAU,SAAA,IAAa,SAAA,CAAU,SAAS;AAAA,WAAA,EAC5D;AAAA,SAAA,EACF;AAAA,OAAA,EACF,CAAA;AAAA,sBAGA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mCAAA,EAEZ,QAAA,EAAA;AAAA,QAAA,QAAA,oBACC,IAAA,CAAC,OAAA,EAAA,EAAM,SAAA,EAAU,0DAAA,EACf,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,UAAA;AAAA,cACL,OAAA,EAAS,kBAAA;AAAA,cACT,UAAU,CAAC,CAAA,KAAM,qBAAA,CAAsB,CAAA,CAAE,OAAO,OAAO,CAAA;AAAA,cACvD,SAAA,EAAU;AAAA;AAAA,WACZ;AAAA,UAAE;AAAA,SAAA,EAEJ,CAAA;AAAA,QAID,cAAA,IAAkB,SAAA,CAAU,MAAA,KAAW,SAAA,oBACtC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAA,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,SAAA;AAAA,cACR,IAAA,EAAK,IAAA;AAAA,cACL,OAAA,EAAS,WAAA;AAAA,cACT,QAAA,EAAU,aAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,QAAK,IAAA,EAAK,WAAA,EAAY,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,gBAAE;AAAA;AAAA;AAAA,WAEvD;AAAA,0BACA,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,SAAA;AAAA,cACR,IAAA,EAAK,IAAA;AAAA,cACL,OAAA,EAAS,YAAA;AAAA,cACT,QAAA,EAAU,aAAA;AAAA,cACV,SAAA,EAAU,sIAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,QAAK,IAAA,EAAK,UAAA,EAAW,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,gBAAE;AAAA;AAAA;AAAA;AAEtD,SAAA,EACF,CAAA;AAAA,QAGD,cAAA,IAAkB,SAAA,CAAU,MAAA,KAAW,SAAA,oBACtC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAA,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,SAAA;AAAA,cACR,IAAA,EAAK,IAAA;AAAA,cACL,OAAA,EAAS,YAAA;AAAA,cACT,QAAA,EAAU,aAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,QAAK,IAAA,EAAK,UAAA,EAAW,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,gBAAE;AAAA;AAAA;AAAA,WAEtD;AAAA,0BACA,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,SAAA;AAAA,cACR,IAAA,EAAK,IAAA;AAAA,cACL,OAAA,EAAS,YAAA;AAAA,cACT,QAAA,EAAU,aAAA;AAAA,cACV,SAAA,EAAU,sIAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,QAAK,IAAA,EAAK,UAAA,EAAW,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,gBAAE;AAAA;AAAA;AAAA;AAEtD,SAAA,EACF,CAAA;AAAA,QAGD,cAAA,IAAkB,SAAA,CAAU,MAAA,KAAW,SAAA,oBACtC,IAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,SAAA;AAAA,YACR,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAS,YAAA;AAAA,YACT,QAAA,EAAU,aAAA;AAAA,YAEV,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,QAAK,IAAA,EAAK,UAAA,EAAW,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,cAAE;AAAA;AAAA;AAAA,SAEtD;AAAA,QAGD,mBACE,SAAA,CAAU,MAAA,KAAW,SAAA,IACpB,SAAA,CAAU,WAAW,SAAA,CAAA,oBACrB,IAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,SAAA;AAAA,YACR,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAS,MAAM,sBAAA,CAAuB,IAAI,CAAA;AAAA,YAC1C,QAAA,EAAU,aAAA;AAAA,YACV,SAAA,EAAU,gIAAA;AAAA,YAEV,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,QAAK,IAAA,EAAK,mBAAA,EAAoB,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,cAAE;AAAA;AAAA;AAAA,SAE/D;AAAA,6BAGH,MAAA,EAAA,EAAO,OAAA,EAAQ,WAAU,IAAA,EAAK,IAAA,EAAK,SAAS,OAAA,EAC3C,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAK,IAAA,EAAK,aAAA,EAAc,SAAA,EAAU,MAAA,EAAO,OAAO,EAAA,EAAI,CAAA;AAAA,UAAE;AAAA,SAAA,EAEzD;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA;AAAA,oBAGA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4CAAA,EACb,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uEAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EAA8B,QAAA,EAAA,UAAA,EAAQ,CAAA;AAAA,4BACpD,KAAA,EAAA,EAAI,SAAA,EAAU,4CACZ,QAAA,EAAA,cAAA,CAAe,SAAA,CAAU,QAAQ,CAAA,EACpC;AAAA,OAAA,EACF,CAAA;AAAA,sBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uEAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EAA8B,QAAA,EAAA,UAAA,EAAQ,CAAA;AAAA,wBACrD,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8BAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gEAAA,EACb,QAAA,kBAAA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,CAAA,OAAA,EACT,SAAA,CAAU,MAAA,KAAW,QAAA,GACjB,sCACA,SAAA,CAAU,MAAA,KAAW,WAAA,GACnB,qCAAA,GACA,kCACR,CAAA,CAAA;AAAA,cACA,OAAO,EAAE,KAAA,EAAO,CAAA,EAAG,SAAA,CAAU,QAAQ,CAAA,CAAA,CAAA;AAAI;AAAA,WAC3C,EACF,CAAA;AAAA,0BACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qCAAA,EACb,QAAA,EAAA;AAAA,YAAA,IAAA,CAAK,KAAA,CAAM,UAAU,QAAQ,CAAA;AAAA,YAAE;AAAA,WAAA,EAClC;AAAA,SAAA,EACF;AAAA,OAAA,EACF,CAAA;AAAA,sBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uEAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EAA8B,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,wBAClD,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8BAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2DAAA,EACb,QAAA,EAAA,SAAA,CAAU,kBAAkB,CAAA,EAC/B,CAAA;AAAA,0BACA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,GAAA,EAAC,CAAA;AAAA,8BACtC,MAAA,EAAA,EAAK,SAAA,EAAU,qCAAA,EACb,QAAA,EAAA,SAAA,CAAU,cAAc,CAAA,EAC3B,CAAA;AAAA,UAAA,CACE,UAAU,WAAA,IAAe,CAAA,IAAK,qBAC9B,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,oDAAA,EAAqD,QAAA,EAAA;AAAA,YAAA,GAAA;AAAA,YACjE,SAAA,CAAU,WAAA;AAAA,YAAY;AAAA,WAAA,EAC1B;AAAA,SAAA,EAEJ;AAAA,OAAA,EACF,CAAA;AAAA,sBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uEAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EAA8B,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,wBACpD,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qDAAA,EACZ,QAAA,EAAA,SAAA,CAAU,aAAA,GACN,WAAA,CAAY,SAAA,CAAU,aAAa,CAAA,EAAG,KAAA,IACvC,SAAA,CAAU,gBACV,QAAA,EACN;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA;AAAA,IAGC,SAAA,CAAU,YAAA,oBACT,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,+GAAA,EACb,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,oEAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,kBAAA,EAAmB,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,wBACzC,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EAAc,QAAA,EAAA;AAAA,UAAA,OAAA;AAAA,UACtB,SAAA,CAAU,SAAA,GAAY,CAAA,EAAA,EAAK,SAAA,CAAU,SAAS,CAAA,CAAA,CAAA,GAAM;AAAA,SAAA,EAC5D;AAAA,OAAA,EACF,CAAA;AAAA,sBACA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uCAAA,EACV,oBAAU,YAAA,EACb;AAAA,KAAA,EACF,CAAA;AAAA,oBAIF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uCAAA,EACb,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mBAAA,EACZ,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,IAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QAEC,OAAA,EAAS,MAAM,YAAA,CAAa,GAAA,CAAI,EAAE,CAAA;AAAA,QAClC,SAAA,EAAW;AAAA;AAAA,gBAAA,EAGP,SAAA,KAAc,GAAA,CAAI,EAAA,GACd,mDAAA,GACA,4FACN;AAAA,cAAA,CAAA;AAAA,QAGF,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,GAAA,CAAI,IAAA,EAAM,OAAO,EAAA,EAAI,CAAA;AAAA,UAChC,GAAA,CAAI;AAAA;AAAA,OAAA;AAAA,MAZA,GAAA,CAAI;AAAA,KAcZ,GACH,CAAA,EACF,CAAA;AAAA,oBAGA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mEAAA,EACZ,QAAA,EAAA;AAAA,MAAA,SAAA,KAAc,UAAA,oBACb,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,YAAA,EACb,QAAA,kBAAA,GAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,UAAA,EAAY,SAAA,CAAU,UAAA,IAAc,EAAC;AAAA,UACrC,WAAA;AAAA,UACA,aAAA,EAAe,UAAU,aAAA,IAAiB,MAAA;AAAA,UAC1C,WAAA,EAAa,iBAAiB,eAAA,GAAkB,MAAA;AAAA,UAChD,cAAA,EAAgB;AAAA;AAAA,OAClB,EACF,CAAA;AAAA,MAGD,SAAA,KAAc,MAAA,oBACb,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,YAAA,EACb,QAAA,kBAAA,GAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,OAAO,OAAA,CAAQ,KAAA;AAAA,UACf,UAAA,EAAY,SAAA,CAAU,UAAA,IAAc,EAAC;AAAA,UACrC,WAAA;AAAA,UACA,SAAS,OAAA,CAAQ,OAAA;AAAA,UACjB,OAAO,OAAA,CAAQ,KAAA;AAAA,UACf,SAAS,OAAA,CAAQ,OAAA;AAAA,UACjB,cAAc,OAAA,CAAQ,YAAA;AAAA,UACtB,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,MAAA,EAAQ,QAAA;AAAA,UACR,QAAA,EAAU,WAAA;AAAA,UACV,gBAAA,EAAkB,cAAA;AAAA,UAClB,UAAA,EAAY,MAAM,KAAK,OAAA,CAAQ,QAAA;AAAS;AAAA,OAC1C,EACF,CAAA;AAAA,MAGD,SAAA,KAAc,OAAA,oBACb,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,YAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA,cAAA,EAE3D,CAAA;AAAA,4BACC,KAAA,EAAA,EAAI,SAAA,EAAU,+DAAA,EACb,QAAA,kBAAA,GAAA,CAAC,SAAI,SAAA,EAAU,qEAAA,EACZ,QAAA,EAAA,IAAA,CAAK,SAAA,CAAU,UAAU,WAAA,IAAe,IAAA,EAAM,IAAA,EAAM,CAAC,GACxD,CAAA,EACF;AAAA,OAAA,EACF,CAAA;AAAA,MAGD,SAAA,KAAc,6BACb,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,YAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uCAAA,EACb,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA,mBAAA,EAE3D,CAAA;AAAA,8BACC,KAAA,EAAA,EAAI,SAAA,EAAU,+DAAA,EACb,QAAA,kBAAA,GAAA,CAAC,SAAI,SAAA,EAAU,qEAAA,EACZ,QAAA,EAAA,IAAA,CAAK,SAAA,CAAU,UAAU,OAAA,IAAW,IAAA,EAAM,IAAA,EAAM,CAAC,GACpD,CAAA,EACF;AAAA,SAAA,EACF,CAAA;AAAA,6BACC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA,mBAAA,EAE3D,CAAA;AAAA,0BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,QAAA,EAAM,CAAA;AAAA,8BAC5C,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6BAAA,EACb,oBAAU,EAAA,EACb;AAAA,aAAA,EACF,CAAA;AAAA,4BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,UAAA,EAAQ,CAAA;AAAA,8BAC9C,GAAA,CAAC,UAAK,SAAA,EAAU,mBAAA,EACb,oBAAU,QAAA,EAAU,IAAA,IAAQ,UAAU,WAAA,EACzC;AAAA,aAAA,EACF,CAAA;AAAA,4BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,cAAA,EAAY,CAAA;AAAA,8BAClD,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6BAAA,EACb,oBAAU,WAAA,EACb;AAAA,aAAA,EACF,CAAA;AAAA,4BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,kCAC5C,MAAA,EAAA,EAAK,SAAA,EAAU,qBACb,QAAA,EAAA,gBAAA,CAAiB,SAAA,CAAU,OAAO,CAAA,EACrC;AAAA,aAAA,EACF,CAAA;AAAA,YACC,SAAA,CAAU,aAAA,oBACT,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,cAAA,EAAY,CAAA;AAAA,8BAClD,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,mBAAA;AAAA,kBACV,OAAO,SAAA,CAAU,aAAA;AAAA,kBAEhB,QAAA,EAAA;AAAA;AAAA;AACH,aAAA,EACF,CAAA;AAAA,YAED,SAAA,CAAU,WAAA,oBACT,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,YAAA,EAAU,CAAA;AAAA,8BAChD,IAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBACC,EAAA,EAAI,CAAA,MAAA,EAAS,SAAA,CAAU,WAAW,CAAA,CAAA;AAAA,kBAClC,SAAA,EAAU,oDAAA;AAAA,kBAET,QAAA,EAAA;AAAA,oBAAA,SAAA,CAAU,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,oBAAE;AAAA;AAAA;AAAA;AACtC,aAAA,EACF,CAAA;AAAA,4BAEF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,kCAC5C,MAAA,EAAA,EAAK,SAAA,EAAU,qBACb,QAAA,EAAA,cAAA,CAAe,SAAA,CAAU,SAAS,CAAA,EACrC;AAAA,aAAA,EACF,CAAA;AAAA,4BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,kCAC5C,MAAA,EAAA,EAAK,SAAA,EAAU,qBACb,QAAA,EAAA,cAAA,CAAe,SAAA,CAAU,SAAS,CAAA,EACrC;AAAA,aAAA,EACF,CAAA;AAAA,YACC,SAAA,CAAU,WAAA,oBACT,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4DAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,WAAA,EAAS,CAAA;AAAA,kCAC9C,MAAA,EAAA,EAAK,SAAA,EAAU,qBACb,QAAA,EAAA,cAAA,CAAe,SAAA,CAAU,WAAW,CAAA,EACvC;AAAA,aAAA,EACF;AAAA,WAAA,EAEJ;AAAA,SAAA,EACF;AAAA,OAAA,EACF,CAAA,EACF;AAAA,KAAA,EAEJ,CAAA;AAAA,oBAEA,GAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAM,mBAAA;AAAA,QACN,YAAA,EAAc,sBAAA;AAAA,QAEd,+BAAC,kBAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,iBAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,oBAAiB,QAAA,EAAA,qBAAA,EAAmB,CAAA;AAAA,4BACrC,GAAA,CAAC,0BAAuB,QAAA,EAAA,iIAAA,EAGxB;AAAA,WAAA,EACF,CAAA;AAAA,+BACC,iBAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,iBAAA,EAAA,EAAkB,QAAA,EAAU,aAAA,EAAe,QAAA,EAAA,QAAA,EAE5C,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,iBAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAS,eAAA;AAAA,gBACT,QAAA,EAAU,aAAA;AAAA,gBACV,SAAA,EAAU,oEAAA;AAAA,gBAET,0BAAgB,gBAAA,GAAmB;AAAA;AAAA;AACtC,WAAA,EACF;AAAA,SAAA,EACF;AAAA;AAAA;AACF,GAAA,EACF,CAAA;AAEJ","file":"chunk-5ASKIPC6.js","sourcesContent":["/**\n * useRunLogs — a GitHub-Actions-style live tail for a workflow run.\n *\n * Two sources feed one ordered list:\n *\n * backfill `workflowRunLogs`, keyset-paginated. The source of truth, and\n * the only thing that can show a run that finished before the page\n * was opened.\n * live `runLogAppended`, which carries ONLY lines appended after the\n * subscription opens — it is a pub/sub stream with no history.\n *\n * So the order matters: query first, then subscribe, then de-duplicate by line\n * `id`. Line ids are assigned by the executor precisely so the live copy and\n * the persisted copy of a line can be matched.\n *\n * If the subscription never connects (a proxy that blocks SSE, a gateway\n * hiccup) the hook falls back to polling the cursor while the run is active,\n * so a live tail degrades to a slower live tail rather than to nothing.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { getFluidGridsClientSafe } from \"../../../graphql/client\";\nimport { throwIfResultError } from \"../../../graphql/errors\";\nimport { RUN_LOGS, RUN_LOG_APPENDED } from \"../graphql/operations\";\nimport type { RunLogLevel, RunLogLine } from \"../types\";\n\n/** How often to re-query when the live subscription is unavailable. */\nconst POLL_INTERVAL_MS = 2000;\n\n/** Page size for backfill. Large enough that a typical run arrives in one round trip. */\nconst PAGE_SIZE = 500;\n\ninterface RunLogsData {\n workflowRunLogs: {\n lines: RunLogLine[];\n nextCursor: string | null;\n hasMore: boolean;\n limitReached: boolean;\n };\n}\n\ninterface RunLogAppendedData {\n runLogAppended: RunLogLine[];\n}\n\nexport interface UseRunLogsOptions {\n /** Keep tailing. Set false once the run reaches a terminal state. */\n live?: boolean;\n /** Server-side severity filter. Applied to backfill; live lines are filtered client-side. */\n minLevel?: RunLogLevel | null;\n /** Include lines from sub-workflow runs nested under this one. */\n includeChildRuns?: boolean;\n}\n\nexport interface UseRunLogsResult {\n lines: RunLogLine[];\n loading: boolean;\n error: Error | null;\n /** True when the run has more lines after the current page — drives \"Load more\". */\n hasMore: boolean;\n /** True when the run hit its log cap and lines were dropped server-side. */\n limitReached: boolean;\n /** True while a live subscription is delivering (as opposed to polling). */\n streaming: boolean;\n /** Fetch the next page, continuing forward from the newest line held. */\n loadMore: () => Promise<void>;\n /** Discard everything and re-read from the start. */\n refetch: () => Promise<void>;\n}\n\nexport function useRunLogs(\n runId: string | undefined,\n options: UseRunLogsOptions = {},\n): UseRunLogsResult {\n const { live = false, minLevel = null, includeChildRuns = false } = options;\n\n const [lines, setLines] = useState<RunLogLine[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [hasMore, setHasMore] = useState(false);\n const [limitReached, setLimitReached] = useState(false);\n const [streaming, setStreaming] = useState(false);\n\n /**\n * Ids already rendered. A line can arrive twice — once live and once in a\n * later backfill page — and the two copies are byte-identical by design, so\n * the id is all that is needed to collapse them.\n */\n const seenIds = useRef<Set<string>>(new Set());\n /** Cursor of the newest line we hold; where the next forward read starts. */\n const cursor = useRef<string | null>(null);\n\n const append = useCallback((incoming: RunLogLine[]) => {\n if (incoming.length === 0) return;\n\n const fresh = incoming.filter((line) => !seenIds.current.has(line.id));\n if (fresh.length === 0) return;\n for (const line of fresh) seenIds.current.add(line.id);\n\n setLines((prev) =>\n // Sort on every append rather than trusting arrival order: live lines and\n // a backfill page can interleave, and a run's nodes are executed by\n // several worker replicas whose batches need not arrive in order.\n [...prev, ...fresh].sort((a, b) =>\n a.timestamp === b.timestamp\n ? a.id.localeCompare(b.id)\n : a.timestamp.localeCompare(b.timestamp),\n ),\n );\n }, []);\n\n /** Read one page forward from `cursor`. */\n const fetchPage = useCallback(\n async (after: string | null): Promise<void> => {\n const client = getFluidGridsClientSafe();\n if (!client || !runId) return;\n\n const result = await client.query<RunLogsData>({\n query: RUN_LOGS,\n variables: {\n runId,\n after,\n limit: PAGE_SIZE,\n minLevel,\n includeChildRuns,\n },\n fetchPolicy: \"network-only\",\n });\n throwIfResultError(result);\n\n const page = result.data?.workflowRunLogs;\n if (!page) return;\n\n append(page.lines);\n setHasMore(page.hasMore);\n setLimitReached(page.limitReached);\n if (page.nextCursor) cursor.current = page.nextCursor;\n },\n [runId, minLevel, includeChildRuns, append],\n );\n\n const refetch = useCallback(async () => {\n seenIds.current = new Set();\n cursor.current = null;\n setLines([]);\n setLoading(true);\n setError(null);\n try {\n await fetchPage(null);\n } catch (err) {\n setError(err as Error);\n } finally {\n setLoading(false);\n }\n }, [fetchPage]);\n\n const loadMore = useCallback(async () => {\n try {\n await fetchPage(cursor.current);\n } catch (err) {\n setError(err as Error);\n }\n }, [fetchPage]);\n\n // Initial load, and a full reset whenever the run or a server-side filter\n // changes — the cursor is only meaningful for one filter combination.\n useEffect(() => {\n if (!runId) {\n setLoading(false);\n return;\n }\n void refetch();\n }, [runId, refetch]);\n\n // Live tail. Falls back to polling when the subscription cannot deliver.\n useEffect(() => {\n const client = getFluidGridsClientSafe();\n if (!runId || !live || !client) {\n setStreaming(false);\n return;\n }\n\n let cancelled = false;\n let poll: ReturnType<typeof setInterval> | null = null;\n\n const startPolling = (): void => {\n if (poll || cancelled) return;\n setStreaming(false);\n poll = setInterval(() => {\n void fetchPage(cursor.current).catch(() => {\n // A transient read failure must not tear down the tail; the next\n // tick retries from the same cursor.\n });\n }, POLL_INTERVAL_MS);\n };\n\n const subscription = client\n .subscribe<RunLogAppendedData>({\n query: RUN_LOG_APPENDED,\n variables: { runId },\n })\n .subscribe({\n next: ({ data }) => {\n if (cancelled) return;\n setStreaming(true);\n append(data?.runLogAppended ?? []);\n },\n error: () => {\n // Subscriptions are an accelerator, never the only path to the data.\n startPolling();\n },\n complete: () => {\n if (!cancelled) startPolling();\n },\n });\n\n // Poll until the first live line proves the stream works. Without this a\n // subscription that connects but never errors (a proxy holding the\n // response open) would silently show nothing.\n const readinessProbe = setTimeout(startPolling, POLL_INTERVAL_MS * 2);\n\n return () => {\n cancelled = true;\n clearTimeout(readinessProbe);\n if (poll) clearInterval(poll);\n subscription.unsubscribe();\n setStreaming(false);\n };\n }, [runId, live, fetchPage, append]);\n\n // One catch-up read when the run stops being live.\n //\n // A run appends its last few lines — the final node completing, `run-complete`\n // — between the last poll and the moment the caller flips `live` to false.\n // Tearing the tail down without this leaves the log visibly short of the run\n // it describes, and only a manual reload would recover it.\n const wasLive = useRef(false);\n useEffect(() => {\n if (live) {\n wasLive.current = true;\n return;\n }\n if (!wasLive.current) return;\n wasLive.current = false;\n\n void fetchPage(cursor.current).catch(() => {\n // Nothing to recover to; the reader can still refetch by hand.\n });\n }, [live, fetchPage]);\n\n // Live lines bypass the server-side filter, so re-apply it here to keep the\n // rendered list consistent with what the query would have returned.\n const filtered = useMemo(() => {\n if (!minLevel) return lines;\n const order: RunLogLevel[] = [\"DEBUG\", \"INFO\", \"WARN\", \"ERROR\"];\n const floor = order.indexOf(minLevel);\n return lines.filter((line) => order.indexOf(line.level) >= floor);\n }, [lines, minLevel]);\n\n return {\n lines: filtered,\n loading,\n error,\n hasMore,\n limitReached,\n streaming,\n loadMore,\n refetch,\n };\n}\n","import { useState, useCallback, useMemo } from \"react\";\nimport { useParams, Link, useNavigate } from \"react-router-dom\";\nimport { Icon } from \"@iconify/react\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"@burdenoff/fe-libs/ui\";\nimport {\n ExecutionStatusBadge,\n NodeTimeline,\n RunLogViewer,\n} from \"../components\";\nimport {\n useExecution,\n useExecutionActions,\n useAutoRefresh,\n} from \"../hooks/useExecutions\";\nimport { useRunLogs } from \"../hooks/useRunLogs\";\nimport type { RunLogLevel } from \"../types\";\nimport { buildNodeDisplayMap, formatRunVersion } from \"../utils/run-display\";\nimport {\n useActorProfiles,\n buildActorFallback,\n type ActorInput,\n} from \"@burdenoff/fe-libs/shared\";\nimport { getFluidGridsConfig } from \"../../../config\";\nimport { useFluidGridsPermission } from \"../../../permissions/PermissionsBridge\";\nimport { FLUIDGRIDS_PERMISSIONS } from \"../../../permissions/constants\";\n\ntype DetailTab = \"timeline\" | \"logs\" | \"input\" | \"context\";\n\nexport function ExecutionDetailPage() {\n const { runId } = useParams<{ runId: string }>();\n const navigate = useNavigate();\n\n const [activeTab, setActiveTab] = useState<DetailTab>(\"timeline\");\n const [autoRefreshEnabled, setAutoRefreshEnabled] = useState(true);\n const [showTerminateDialog, setShowTerminateDialog] = useState(false);\n const { allowed: canControlRuns } = useFluidGridsPermission(\n FLUIDGRIDS_PERMISSIONS.WORKFLOW_RUN_EXECUTE,\n );\n\n const [minLogLevel, setMinLogLevel] = useState<RunLogLevel | null>(null);\n\n // Data fetching\n const { execution, loading, error, refetch } = useExecution(runId);\n\n // nodeId → human label/operation from the run's workflow definition.\n const nodeDisplay = useMemo(\n () => buildNodeDisplayMap(execution?.workflow?.definitionJson),\n [execution?.workflow?.definitionJson],\n );\n\n // Resolve the triggering actor's display name (best-effort, cached).\n const fgConfig = getFluidGridsConfig();\n const actorInputs = useMemo<ActorInput[]>(\n () =>\n execution?.triggeredById\n ? [{ actorId: execution.triggeredById, actorType: \"user\" }]\n : [],\n [execution?.triggeredById],\n );\n const actorProfiles = useActorProfiles(actorInputs, {\n workspaceId: fgConfig.workspaceId || undefined,\n orgId: fgConfig.organizationId,\n authToken: fgConfig.authToken,\n });\n const triggeredByLabel = execution?.triggeredById\n ? (actorProfiles[execution.triggeredById]?.displayName ??\n buildActorFallback({\n actorId: execution.triggeredById,\n actorType: \"user\",\n }).displayName)\n : null;\n const {\n pauseExecution,\n resumeExecution,\n cancelExecution,\n retryNode,\n terminateExecution,\n loading: actionLoading,\n } = useExecutionActions();\n\n // Auto-refresh for running executions\n const isActive =\n execution?.status === \"RUNNING\" ||\n execution?.status === \"PENDING\" ||\n execution?.status === \"WAITING\";\n\n // The log viewer maintains its own live tail (subscription, with a polling\n // fallback), so this only refreshes the run header and node states.\n useAutoRefresh(\n useCallback(() => {\n refetch();\n }, [refetch]),\n autoRefreshEnabled && isActive,\n 2000,\n );\n\n const runLogs = useRunLogs(runId, {\n // Only tail while the run can still produce lines; a finished run's log is\n // complete after the first read.\n live: isActive,\n minLevel: minLogLevel,\n });\n\n // Handlers\n const handlePause = async () => {\n if (!runId) return;\n await pauseExecution(runId);\n refetch();\n };\n\n const handleResume = async () => {\n if (!runId) return;\n await resumeExecution(runId);\n refetch();\n };\n\n const handleCancel = async () => {\n if (!runId) return;\n await cancelExecution(runId);\n refetch();\n };\n\n const handleTerminate = async () => {\n if (!runId) return;\n await terminateExecution(runId, \"User terminated\");\n setShowTerminateDialog(false);\n refetch();\n };\n\n const handleRetryNode = async (nodeId: string) => {\n if (!runId) return;\n await retryNode(runId, nodeId);\n refetch();\n };\n\n const handleViewChildRun = useCallback(\n (childRunId: string) => {\n navigate(`../runs/${childRunId}`);\n },\n [navigate],\n );\n\n // Formatting helpers\n const formatDuration = (ms?: number): string => {\n if (!ms) return \"-\";\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n if (ms < 3600000)\n return `${Math.round(ms / 60000)}m ${Math.round((ms % 60000) / 1000)}s`;\n return `${Math.round(ms / 3600000)}h ${Math.round((ms % 3600000) / 60000)}m`;\n };\n\n const formatDateTime = (dateStr?: string): string => {\n if (!dateStr) return \"-\";\n const date = new Date(dateStr);\n return date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n };\n\n // Loading state\n if (loading && !execution) {\n return (\n <div className=\"p-4 sm:p-6 bg-background-primary min-h-screen\">\n <div className=\"animate-pulse\">\n <div className=\"h-8 w-48 bg-background-tertiary rounded mb-4\" />\n <div className=\"h-4 w-32 bg-background-tertiary rounded mb-8\" />\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4 mb-6\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"h-24 bg-background-tertiary rounded-lg\" />\n ))}\n </div>\n <div className=\"h-96 bg-background-tertiary rounded-lg\" />\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"p-4 sm:p-6 bg-background-primary min-h-screen\">\n <Link\n to=\"../runs\"\n className=\"text-action-primary-text hover:underline text-sm mb-4 inline-block\"\n >\n ← Back to Executions\n </Link>\n <div className=\"bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg p-6 text-center\">\n <Icon\n icon=\"mdi:alert-circle\"\n className=\"mx-auto text-[var(--color-status-error-text)] mb-4\"\n width={48}\n />\n <h2 className=\"text-lg font-medium text-[var(--color-status-error-text)] mb-2\">\n Failed to load execution\n </h2>\n <p className=\"text-[var(--color-status-error-text)] mb-4\">\n {error.message}\n </p>\n <Button variant=\"outline\" onClick={refetch}>\n Try Again\n </Button>\n </div>\n </div>\n );\n }\n\n // Not found state\n if (!execution) {\n return (\n <div className=\"p-4 sm:p-6 bg-background-primary min-h-screen\">\n <Link\n to=\"../runs\"\n className=\"text-action-primary-text hover:underline text-sm mb-4 inline-block\"\n >\n ← Back to Executions\n </Link>\n <div className=\"bg-background-secondary border border-border-secondary rounded-lg p-6 text-center\">\n <Icon\n icon=\"mdi:file-find-outline\"\n className=\"mx-auto text-text-secondary mb-4\"\n width={48}\n />\n <h2 className=\"text-lg font-medium text-text-primary mb-2\">\n Execution not found\n </h2>\n <p className=\"text-text-secondary\">\n The execution with ID "{runId}" could not be found.\n </p>\n </div>\n </div>\n );\n }\n\n const tabs: Array<{ id: DetailTab; label: string; icon: string }> = [\n { id: \"timeline\", label: \"Timeline\", icon: \"mdi:timeline\" },\n { id: \"logs\", label: \"Logs\", icon: \"mdi:text-box-outline\" },\n { id: \"input\", label: \"Input Data\", icon: \"mdi:code-json\" },\n { id: \"context\", label: \"Context\", icon: \"mdi:information-outline\" },\n ];\n\n return (\n <div className=\"p-4 sm:p-6 bg-background-primary min-h-screen\">\n {/* Back link */}\n <Link\n to=\"../runs\"\n className=\"text-action-primary-text hover:underline text-sm mb-4 inline-block\"\n >\n ← Back to Executions\n </Link>\n\n {/* Sub-workflow parent breadcrumb */}\n {execution.parentRunId && (\n <div className=\"flex items-center gap-2 mb-3 text-sm\">\n <Icon icon=\"mdi:sitemap\" className=\"text-indigo-500\" width={16} />\n <span className=\"text-text-secondary\">Sub-workflow of</span>\n <Link\n to={`../runs/${execution.parentRunId}`}\n className=\"text-indigo-600 hover:underline font-medium\"\n >\n Parent Run {execution.parentRunId.slice(0, 12)}...\n </Link>\n </div>\n )}\n\n {/* Header */}\n <div className=\"flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4 mb-6\">\n <div>\n <div className=\"flex items-center gap-3 mb-2\">\n <h1 className=\"text-2xl sm:text-3xl font-bold text-text-primary\">\n {execution.workflow?.name || execution.workflowKey}\n </h1>\n <ExecutionStatusBadge status={execution.status} size=\"lg\" />\n {execution.parentRunId && (\n <span className=\"px-2 py-0.5 text-xs bg-indigo-100 text-indigo-700 rounded\">\n Sub-Workflow\n </span>\n )}\n </div>\n <div className=\"flex flex-wrap items-center gap-4 text-sm text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Icon icon=\"mdi:identifier\" width={16} />\n <code className=\"font-mono\">{execution.id.slice(0, 12)}...</code>\n </span>\n <span className=\"flex items-center gap-1\">\n <Icon icon=\"mdi:tag-outline\" width={16} />\n {formatRunVersion(execution.version)}\n </span>\n <span className=\"flex items-center gap-1\">\n <Icon icon=\"mdi:clock-outline\" width={16} />\n {formatDateTime(execution.startedAt || execution.createdAt)}\n </span>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap items-center gap-2\">\n {/* Auto-refresh toggle */}\n {isActive && (\n <label className=\"flex items-center gap-2 text-sm text-text-secondary mr-4\">\n <input\n type=\"checkbox\"\n checked={autoRefreshEnabled}\n onChange={(e) => setAutoRefreshEnabled(e.target.checked)}\n className=\"w-4 h-4 rounded\"\n />\n Auto-refresh\n </label>\n )}\n\n {/* Control buttons based on status */}\n {canControlRuns && execution.status === \"RUNNING\" && (\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handlePause}\n disabled={actionLoading}\n >\n <Icon icon=\"mdi:pause\" className=\"mr-1\" width={16} />\n Pause\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={actionLoading}\n className=\"border-[var(--color-status-warning-border)] text-[var(--color-status-warning-text)] hover:bg-[var(--color-status-warning-bg-subtle)]\"\n >\n <Icon icon=\"mdi:stop\" className=\"mr-1\" width={16} />\n Cancel\n </Button>\n </>\n )}\n\n {canControlRuns && execution.status === \"WAITING\" && (\n <>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleResume}\n disabled={actionLoading}\n >\n <Icon icon=\"mdi:play\" className=\"mr-1\" width={16} />\n Resume\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={actionLoading}\n className=\"border-[var(--color-status-warning-border)] text-[var(--color-status-warning-text)] hover:bg-[var(--color-status-warning-bg-subtle)]\"\n >\n <Icon icon=\"mdi:stop\" className=\"mr-1\" width={16} />\n Cancel\n </Button>\n </>\n )}\n\n {canControlRuns && execution.status === \"PENDING\" && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleCancel}\n disabled={actionLoading}\n >\n <Icon icon=\"mdi:stop\" className=\"mr-1\" width={16} />\n Cancel\n </Button>\n )}\n\n {canControlRuns &&\n (execution.status === \"RUNNING\" ||\n execution.status === \"WAITING\") && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setShowTerminateDialog(true)}\n disabled={actionLoading}\n className=\"border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] hover:bg-[var(--color-status-error-bg-subtle)]\"\n >\n <Icon icon=\"mdi:close-octagon\" className=\"mr-1\" width={16} />\n Terminate\n </Button>\n )}\n\n <Button variant=\"outline\" size=\"sm\" onClick={refetch}>\n <Icon icon=\"mdi:refresh\" className=\"mr-1\" width={16} />\n Refresh\n </Button>\n </div>\n </div>\n\n {/* Stats Grid */}\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4 mb-6\">\n <div className=\"bg-background-secondary rounded-lg border border-border-secondary p-4\">\n <div className=\"text-sm text-text-secondary\">Duration</div>\n <div className=\"text-xl font-bold text-text-primary mt-1\">\n {formatDuration(execution.duration)}\n </div>\n </div>\n <div className=\"bg-background-secondary rounded-lg border border-border-secondary p-4\">\n <div className=\"text-sm text-text-secondary\">Progress</div>\n <div className=\"flex items-center gap-2 mt-1\">\n <div className=\"flex-1 h-2 bg-background-tertiary rounded-full overflow-hidden\">\n <div\n className={`h-full ${\n execution.status === \"FAILED\"\n ? \"bg-[var(--color-status-error-bg)]\"\n : execution.status === \"COMPLETED\"\n ? \"bg-[var(--color-status-success-bg)]\"\n : \"bg-[var(--color-status-info-bg)]\"\n }`}\n style={{ width: `${execution.progress}%` }}\n />\n </div>\n <span className=\"text-xl font-bold text-text-primary\">\n {Math.round(execution.progress)}%\n </span>\n </div>\n </div>\n <div className=\"bg-background-secondary rounded-lg border border-border-secondary p-4\">\n <div className=\"text-sm text-text-secondary\">Nodes</div>\n <div className=\"flex items-center gap-2 mt-1\">\n <span className=\"text-xl font-bold text-[var(--color-status-success-text)]\">\n {execution.completedNodes ?? 0}\n </span>\n <span className=\"text-text-secondary\">/</span>\n <span className=\"text-xl font-bold text-text-primary\">\n {execution.totalNodes ?? 0}\n </span>\n {(execution.failedNodes ?? 0) > 0 && (\n <span className=\"text-sm text-[var(--color-status-error-text)] ml-2\">\n ({execution.failedNodes} failed)\n </span>\n )}\n </div>\n </div>\n <div className=\"bg-background-secondary rounded-lg border border-border-secondary p-4\">\n <div className=\"text-sm text-text-secondary\">Trigger</div>\n <div className=\"text-lg font-medium text-text-primary mt-1 truncate\">\n {execution.triggerNodeId\n ? (nodeDisplay[execution.triggerNodeId]?.label ??\n execution.triggerNodeId)\n : \"—\"}\n </div>\n </div>\n </div>\n\n {/* Error Banner */}\n {execution.errorMessage && (\n <div className=\"mb-6 p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg\">\n <div className=\"flex items-center gap-2 text-[var(--color-status-error-text)] mb-2\">\n <Icon icon=\"mdi:alert-circle\" width={20} />\n <span className=\"font-medium\">\n Error{execution.errorType ? ` (${execution.errorType})` : \"\"}\n </span>\n </div>\n <p className=\"text-[var(--color-status-error-text)]\">\n {execution.errorMessage}\n </p>\n </div>\n )}\n\n {/* Tabs */}\n <div className=\"border-b border-border-secondary mb-6\">\n <nav className=\"flex gap-4 -mb-px\">\n {tabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`\n flex items-center gap-2 px-4 py-3 border-b-2 text-sm font-medium transition-colors\n ${\n activeTab === tab.id\n ? \"border-action-primary-bg text-action-primary-text\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:border-border-primary\"\n }\n `}\n >\n <Icon icon={tab.icon} width={18} />\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n {/* Tab Content */}\n <div className=\"bg-background-secondary rounded-lg border border-border-secondary\">\n {activeTab === \"timeline\" && (\n <div className=\"p-4 sm:p-6\">\n <NodeTimeline\n nodeStates={execution.nodeStates ?? []}\n nodeDisplay={nodeDisplay}\n triggerNodeId={execution.triggerNodeId ?? undefined}\n onRetryNode={canControlRuns ? handleRetryNode : undefined}\n onViewChildRun={handleViewChildRun}\n />\n </div>\n )}\n\n {activeTab === \"logs\" && (\n <div className=\"p-4 sm:p-6\">\n <RunLogViewer\n runId={runId!}\n lines={runLogs.lines}\n nodeStates={execution.nodeStates ?? []}\n nodeDisplay={nodeDisplay}\n loading={runLogs.loading}\n error={runLogs.error}\n hasMore={runLogs.hasMore}\n limitReached={runLogs.limitReached}\n streaming={runLogs.streaming}\n active={isActive}\n minLevel={minLogLevel}\n onMinLevelChange={setMinLogLevel}\n onLoadMore={() => void runLogs.loadMore()}\n />\n </div>\n )}\n\n {activeTab === \"input\" && (\n <div className=\"p-4 sm:p-6\">\n <h3 className=\"text-lg font-medium text-text-primary mb-4\">\n Trigger Data\n </h3>\n <div className=\"bg-background-primary rounded p-4 max-h-[400px] overflow-auto\">\n <pre className=\"text-sm text-text-primary font-mono whitespace-pre-wrap break-words\">\n {JSON.stringify(execution.triggerData ?? null, null, 2)}\n </pre>\n </div>\n </div>\n )}\n\n {activeTab === \"context\" && (\n <div className=\"p-4 sm:p-6\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <div>\n <h3 className=\"text-lg font-medium text-text-primary mb-4\">\n Execution Context\n </h3>\n <div className=\"bg-background-primary rounded p-4 max-h-[300px] overflow-auto\">\n <pre className=\"text-sm text-text-primary font-mono whitespace-pre-wrap break-words\">\n {JSON.stringify(execution.context ?? null, null, 2)}\n </pre>\n </div>\n </div>\n <div>\n <h3 className=\"text-lg font-medium text-text-primary mb-4\">\n Execution Details\n </h3>\n <div className=\"space-y-3\">\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Run ID</span>\n <code className=\"font-mono text-text-primary\">\n {execution.id}\n </code>\n </div>\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Workflow</span>\n <span className=\"text-text-primary\">\n {execution.workflow?.name || execution.workflowKey}\n </span>\n </div>\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Workflow Key</span>\n <code className=\"font-mono text-text-primary\">\n {execution.workflowKey}\n </code>\n </div>\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Version</span>\n <span className=\"text-text-primary\">\n {formatRunVersion(execution.version)}\n </span>\n </div>\n {execution.triggeredById && (\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Triggered By</span>\n <span\n className=\"text-text-primary\"\n title={execution.triggeredById}\n >\n {triggeredByLabel}\n </span>\n </div>\n )}\n {execution.parentRunId && (\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Parent Run</span>\n <Link\n to={`/runs/${execution.parentRunId}`}\n className=\"text-action-primary-text hover:underline font-mono\"\n >\n {execution.parentRunId.slice(0, 12)}...\n </Link>\n </div>\n )}\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Created</span>\n <span className=\"text-text-primary\">\n {formatDateTime(execution.createdAt)}\n </span>\n </div>\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Started</span>\n <span className=\"text-text-primary\">\n {formatDateTime(execution.startedAt)}\n </span>\n </div>\n {execution.completedAt && (\n <div className=\"flex justify-between py-2 border-b border-border-secondary\">\n <span className=\"text-text-secondary\">Completed</span>\n <span className=\"text-text-primary\">\n {formatDateTime(execution.completedAt)}\n </span>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n <AlertDialog\n open={showTerminateDialog}\n onOpenChange={setShowTerminateDialog}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Terminate Execution</AlertDialogTitle>\n <AlertDialogDescription>\n Are you sure you want to force terminate this execution? This will\n immediately stop the running workflow and cannot be resumed.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={actionLoading}>\n Cancel\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={handleTerminate}\n disabled={actionLoading}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {actionLoading ? \"Terminating...\" : \"Terminate\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useExecutionsStore, useExecutionsWithStore, useExecutionStats, useExecutionActions, useAutoRefresh, ExecutionStats, ExecutionFilters, ExecutionTable, ExecutionCards, ExecutionTimeline, Pagination } from './chunk-
|
|
1
|
+
import { useExecutionsStore, useExecutionsWithStore, useExecutionStats, useExecutionActions, useAutoRefresh, ExecutionStats, ExecutionFilters, ExecutionTable, ExecutionCards, ExecutionTimeline, Pagination } from './chunk-VNSIXELY.js';
|
|
2
2
|
import { useWorkflowDefinitions } from './chunk-NMS2QUXG.js';
|
|
3
3
|
import { useRef, useCallback, useMemo } from 'react';
|
|
4
4
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
|
@@ -65,6 +65,11 @@ function ExecutionsListPage() {
|
|
|
65
65
|
})),
|
|
66
66
|
[workflows]
|
|
67
67
|
);
|
|
68
|
+
const workflowNames = useMemo(() => {
|
|
69
|
+
const map = {};
|
|
70
|
+
for (const w of workflows) map[w.workflowKey] = w.name;
|
|
71
|
+
return map;
|
|
72
|
+
}, [workflows]);
|
|
68
73
|
const handleRowClick = (execution) => {
|
|
69
74
|
setSelectedExecution(execution);
|
|
70
75
|
navigate(`../runs/${execution.id}`);
|
|
@@ -239,6 +244,7 @@ function ExecutionsListPage() {
|
|
|
239
244
|
viewMode === "table" && /* @__PURE__ */ jsx(
|
|
240
245
|
ExecutionTable,
|
|
241
246
|
{
|
|
247
|
+
workflowNames,
|
|
242
248
|
executions,
|
|
243
249
|
loading,
|
|
244
250
|
onRowClick: handleRowClick,
|
|
@@ -248,6 +254,7 @@ function ExecutionsListPage() {
|
|
|
248
254
|
viewMode === "cards" && /* @__PURE__ */ jsx(
|
|
249
255
|
ExecutionCards,
|
|
250
256
|
{
|
|
257
|
+
workflowNames,
|
|
251
258
|
executions,
|
|
252
259
|
loading,
|
|
253
260
|
onCardClick: handleRowClick,
|
|
@@ -268,5 +275,5 @@ function ExecutionsListPage() {
|
|
|
268
275
|
}
|
|
269
276
|
|
|
270
277
|
export { ExecutionsListPage };
|
|
271
|
-
//# sourceMappingURL=chunk-
|
|
272
|
-
//# sourceMappingURL=chunk-
|
|
278
|
+
//# sourceMappingURL=chunk-AGECCY5V.js.map
|
|
279
|
+
//# sourceMappingURL=chunk-AGECCY5V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/modules/executions/pages/ExecutionsListPage.tsx"],"names":[],"mappings":"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","file":"chunk-AGECCY5V.js","sourcesContent":["import { useCallback, useMemo, useRef } from \"react\";\nimport { useNavigate, useSearchParams } from \"react-router-dom\";\nimport { Icon } from \"@iconify/react\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport {\n ExecutionFilters,\n ExecutionStats,\n ExecutionTable,\n ExecutionCards,\n ExecutionTimeline,\n Pagination,\n} from \"../components\";\nimport { useExecutionsStore } from \"../store/executionsStore\";\nimport {\n useExecutionsWithStore,\n useExecutionStats,\n useExecutionActions,\n useAutoRefresh,\n} from \"../hooks/useExecutions\";\nimport { useWorkflowDefinitions } from \"../../../hooks/useWorkflows\";\nimport type { WorkflowRun, RunStatus, ExecutionAction } from \"../types\";\n\nexport function ExecutionsListPage() {\n const navigate = useNavigate();\n\n // Store state\n const {\n viewMode,\n setViewMode,\n setSelectedExecution,\n selection,\n clearSelection,\n setStatusFilter,\n setWorkflowFilter,\n autoRefresh,\n autoRefreshInterval,\n } = useExecutionsStore();\n\n // Seed the workflow filter from the URL (?workflowKey=...) synchronously —\n // BEFORE useExecutionsWithStore() below reads it — so the first runs query\n // already carries the filter and no stale unfiltered request is fired. Lets\n // \"View Runs\" in the builder open this list scoped to one workflow; arriving\n // without the param (e.g. the sidebar \"Runs\" link) clears any stale filter.\n // Sync only when the URL param actually changes (tracked via a ref) so manual\n // dropdown changes — which update the store but not the URL — aren't reverted.\n const [searchParams] = useSearchParams();\n const workflowKeyParam = searchParams.get(\"workflowKey\") ?? \"\";\n const lastWorkflowKeyParam = useRef<string | null>(null);\n if (lastWorkflowKeyParam.current !== workflowKeyParam) {\n lastWorkflowKeyParam.current = workflowKeyParam;\n if (useExecutionsStore.getState().filter.workflowKey !== workflowKeyParam) {\n setWorkflowFilter(workflowKeyParam);\n }\n }\n\n // Data fetching\n const { executions, total, loading, error, refetch } =\n useExecutionsWithStore();\n const {\n stats,\n loading: statsLoading,\n refetch: refetchStats,\n } = useExecutionStats();\n const { workflows } = useWorkflowDefinitions({ limit: 100 });\n const { cancelExecution, pauseExecution, resumeExecution } =\n useExecutionActions();\n\n // Auto-refresh\n useAutoRefresh(\n useCallback(() => {\n refetch();\n refetchStats();\n }, [refetch, refetchStats]),\n autoRefresh,\n autoRefreshInterval,\n );\n\n // Transform stats for component\n const executionStats = useMemo(() => {\n if (!stats) return null;\n return {\n total: stats.runsCountTotal,\n running: stats.runsRunningCount,\n completed: stats.runsCompletedCount,\n failed: stats.runsFailedCount,\n cancelled: stats.runsCancelledCount ?? 0,\n pending: stats.runsPendingCount,\n waiting: stats.runsWaitingCount ?? 0,\n successRate: stats.workflowSuccessRate,\n avgDuration: stats.avgWorkflowExecutionTimeSeconds,\n };\n }, [stats]);\n\n // Transform workflows for filter\n const workflowOptions = useMemo(\n () =>\n workflows.map((w) => ({\n workflowKey: w.workflowKey,\n name: w.name,\n })),\n [workflows],\n );\n\n // workflowKey → name fallback for run rows whose workflow relation is\n // missing (e.g. before the backend include rolled out).\n const workflowNames = useMemo(() => {\n const map: Record<string, string> = {};\n for (const w of workflows) map[w.workflowKey] = w.name;\n return map;\n }, [workflows]);\n\n // Handlers\n const handleRowClick = (execution: WorkflowRun) => {\n setSelectedExecution(execution);\n navigate(`../runs/${execution.id}`);\n };\n\n const handleAction = async (\n action: ExecutionAction,\n execution: WorkflowRun,\n ) => {\n switch (action) {\n case \"cancel\":\n await cancelExecution(execution.id);\n break;\n case \"pause\":\n await pauseExecution(execution.id);\n break;\n case \"resume\":\n await resumeExecution(execution.id);\n break;\n case \"retry\":\n // Navigate to detail page for retry\n navigate(`../runs/${execution.id}`);\n break;\n case \"view\":\n navigate(`../runs/${execution.id}`);\n break;\n }\n refetch();\n };\n\n const handleFilterByStatus = (status: RunStatus | \"all\") => {\n setStatusFilter(status);\n };\n\n const handleBulkAction = async (action: \"cancel\" | \"pause\" | \"resume\") => {\n if (selection.runIds.length === 0) return;\n\n const promises = selection.runIds.map((id) => {\n switch (action) {\n case \"cancel\":\n return cancelExecution(id);\n case \"pause\":\n return pauseExecution(id);\n case \"resume\":\n return resumeExecution(id);\n }\n });\n\n const results = await Promise.allSettled(promises);\n const failures = results.filter((r) => r.status === \"rejected\");\n if (failures.length > 0) {\n console.error(\n `Bulk action partially failed: ${failures.length}/${results.length} failed`,\n );\n }\n clearSelection();\n refetch();\n };\n\n return (\n <div className=\"p-4 sm:p-6 bg-background-primary min-h-screen\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold text-text-primary\">\n Executions\n </h1>\n <p className=\"text-text-secondary mt-1\">\n Monitor and manage your workflow runs\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n {/* View Mode Toggle */}\n <div className=\"flex items-center bg-background-secondary rounded-lg border border-border-secondary p-1\">\n <button\n onClick={() => setViewMode(\"table\")}\n className={`p-2 rounded ${\n viewMode === \"table\"\n ? \"bg-background-tertiary text-text-primary\"\n : \"text-text-secondary hover:text-text-primary\"\n }`}\n title=\"Table View\"\n >\n <Icon icon=\"mdi:table\" width={18} />\n </button>\n <button\n onClick={() => setViewMode(\"cards\")}\n className={`p-2 rounded ${\n viewMode === \"cards\"\n ? \"bg-background-tertiary text-text-primary\"\n : \"text-text-secondary hover:text-text-primary\"\n }`}\n title=\"Card View\"\n >\n <Icon icon=\"mdi:view-grid\" width={18} />\n </button>\n <button\n onClick={() => setViewMode(\"timeline\")}\n className={`p-2 rounded ${\n viewMode === \"timeline\"\n ? \"bg-background-tertiary text-text-primary\"\n : \"text-text-secondary hover:text-text-primary\"\n }`}\n title=\"Timeline View\"\n >\n <Icon icon=\"mdi:timeline\" width={18} />\n </button>\n </div>\n\n <Button variant=\"outline\" onClick={() => navigate(\"../list\")}>\n <Icon icon=\"mdi:arrow-left\" className=\"mr-2\" width={16} />\n Back to Workflows\n </Button>\n </div>\n </div>\n\n {/* Stats Cards */}\n <div className=\"mb-6\">\n <ExecutionStats\n stats={executionStats}\n loading={statsLoading}\n onFilterByStatus={handleFilterByStatus}\n />\n </div>\n\n {/* Filters */}\n <div className=\"mb-6\">\n <ExecutionFilters workflows={workflowOptions} onRefresh={refetch} />\n </div>\n\n {/* Bulk Actions */}\n {selection.runIds.length > 0 && (\n <div className=\"mb-4 p-3 bg-action-primary-bg/10 rounded-lg flex flex-wrap items-center gap-3\">\n <span className=\"text-sm text-text-primary\">\n {selection.runIds.length} execution\n {selection.runIds.length > 1 ? \"s\" : \"\"} selected\n </span>\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleBulkAction(\"cancel\")}\n >\n <Icon icon=\"mdi:stop\" className=\"mr-1\" width={14} />\n Cancel\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleBulkAction(\"pause\")}\n >\n <Icon icon=\"mdi:pause\" className=\"mr-1\" width={14} />\n Pause\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleBulkAction(\"resume\")}\n >\n <Icon icon=\"mdi:play\" className=\"mr-1\" width={14} />\n Resume\n </Button>\n </div>\n <button\n onClick={clearSelection}\n className=\"ml-auto text-sm text-text-secondary hover:text-text-primary\"\n >\n Clear selection\n </button>\n </div>\n )}\n\n {/* Error State */}\n {error && (\n <div className=\"mb-6 p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg\">\n <div className=\"flex items-center gap-2 text-[var(--color-status-error-text)]\">\n <Icon icon=\"mdi:alert-circle\" width={20} />\n <span className=\"font-medium\">Error loading executions</span>\n </div>\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">\n {error.message}\n </p>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={refetch}\n className=\"mt-3 border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] hover:bg-[var(--color-status-error-bg-subtle)]\"\n >\n Retry\n </Button>\n </div>\n )}\n\n {/* Executions View — switches between table, cards, and timeline */}\n {viewMode === \"table\" && (\n <ExecutionTable\n workflowNames={workflowNames}\n executions={executions}\n loading={loading}\n onRowClick={handleRowClick}\n onAction={handleAction}\n />\n )}\n {viewMode === \"cards\" && (\n <ExecutionCards\n workflowNames={workflowNames}\n executions={executions}\n loading={loading}\n onCardClick={handleRowClick}\n onAction={handleAction}\n />\n )}\n {viewMode === \"timeline\" && (\n <ExecutionTimeline\n executions={executions}\n loading={loading}\n onItemClick={handleRowClick}\n onAction={handleAction}\n />\n )}\n\n {/* Pagination */}\n <Pagination totalItems={total} />\n </div>\n );\n}\n"]}
|
|
@@ -695,8 +695,41 @@ function ExecutionStats({
|
|
|
695
695
|
)
|
|
696
696
|
] });
|
|
697
697
|
}
|
|
698
|
+
|
|
699
|
+
// src/modules/executions/utils/run-display.ts
|
|
700
|
+
function formatRunVersion(version) {
|
|
701
|
+
if (!version) return "";
|
|
702
|
+
return version.startsWith("v") ? version : `v${version}`;
|
|
703
|
+
}
|
|
704
|
+
function asString(value) {
|
|
705
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
706
|
+
}
|
|
707
|
+
function buildNodeDisplayMap(definitionJson) {
|
|
708
|
+
const map = {};
|
|
709
|
+
const nodes = definitionJson?.data?.nodes;
|
|
710
|
+
if (!Array.isArray(nodes)) return map;
|
|
711
|
+
for (const node of nodes) {
|
|
712
|
+
const id = asString(node?.id);
|
|
713
|
+
if (!id) continue;
|
|
714
|
+
const label = asString(node?.data?.label) ?? asString(node?.data?.nodeData?.name) ?? asString(node?.type);
|
|
715
|
+
if (!label) continue;
|
|
716
|
+
const operation = asString(node?.data?.operation_name);
|
|
717
|
+
map[id] = {
|
|
718
|
+
label,
|
|
719
|
+
// 'execute' is the internal single-op pseudo-operation — the builder
|
|
720
|
+
// hides it on cards, so the runs screens do too.
|
|
721
|
+
operation: operation === "execute" ? void 0 : operation
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
return map;
|
|
725
|
+
}
|
|
726
|
+
function nodeDisplayTitle(display, fallback) {
|
|
727
|
+
if (!display) return fallback;
|
|
728
|
+
return display.operation ? `${display.label} \xB7 ${display.operation}` : display.label;
|
|
729
|
+
}
|
|
698
730
|
function ExecutionTable({
|
|
699
731
|
executions,
|
|
732
|
+
workflowNames,
|
|
700
733
|
loading,
|
|
701
734
|
onRowClick,
|
|
702
735
|
onAction
|
|
@@ -842,11 +875,8 @@ function ExecutionTable({
|
|
|
842
875
|
}
|
|
843
876
|
) }),
|
|
844
877
|
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
845
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-text-primary", children: execution.workflow?.name || execution.workflowKey }),
|
|
846
|
-
/* @__PURE__ */
|
|
847
|
-
"v",
|
|
848
|
-
execution.version
|
|
849
|
-
] })
|
|
878
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-text-primary", children: execution.workflow?.name || workflowNames?.[execution.workflowKey] || execution.workflowKey }),
|
|
879
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: formatRunVersion(execution.version) })
|
|
850
880
|
] }) }),
|
|
851
881
|
/* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs("span", { className: "text-sm font-mono text-text-secondary", children: [
|
|
852
882
|
execution.id.slice(0, 8),
|
|
@@ -996,6 +1026,7 @@ function getProgressColor(status) {
|
|
|
996
1026
|
}
|
|
997
1027
|
function ExecutionCards({
|
|
998
1028
|
executions,
|
|
1029
|
+
workflowNames,
|
|
999
1030
|
loading,
|
|
1000
1031
|
onCardClick,
|
|
1001
1032
|
onAction
|
|
@@ -1051,11 +1082,8 @@ function ExecutionCards({
|
|
|
1051
1082
|
children: [
|
|
1052
1083
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-3", children: [
|
|
1053
1084
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 mr-2", children: [
|
|
1054
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-text-primary truncate", children: execution.workflowKey }),
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
"v",
|
|
1057
|
-
execution.version
|
|
1058
|
-
] })
|
|
1085
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-text-primary truncate", children: execution.workflow?.name || workflowNames?.[execution.workflowKey] || execution.workflowKey }),
|
|
1086
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-text-tertiary mt-0.5", children: formatRunVersion(execution.version) })
|
|
1059
1087
|
] }),
|
|
1060
1088
|
/* @__PURE__ */ jsx(ExecutionStatusBadge, { status: execution.status, size: "sm" })
|
|
1061
1089
|
] }),
|
|
@@ -1368,6 +1396,7 @@ function orderNodesByExecution(nodeStates, triggerNodeId) {
|
|
|
1368
1396
|
}
|
|
1369
1397
|
function NodeTimeline({
|
|
1370
1398
|
nodeStates,
|
|
1399
|
+
nodeDisplay,
|
|
1371
1400
|
loading,
|
|
1372
1401
|
triggerNodeId,
|
|
1373
1402
|
onRetryNode,
|
|
@@ -1476,7 +1505,17 @@ function NodeTimeline({
|
|
|
1476
1505
|
}
|
|
1477
1506
|
) }),
|
|
1478
1507
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
1479
|
-
/* @__PURE__ */ jsx(
|
|
1508
|
+
/* @__PURE__ */ jsx(
|
|
1509
|
+
"div",
|
|
1510
|
+
{
|
|
1511
|
+
className: "font-medium text-text-primary truncate",
|
|
1512
|
+
title: node.nodeId,
|
|
1513
|
+
children: nodeDisplayTitle(
|
|
1514
|
+
nodeDisplay?.[node.nodeId],
|
|
1515
|
+
node.nodeId
|
|
1516
|
+
)
|
|
1517
|
+
}
|
|
1518
|
+
),
|
|
1480
1519
|
/* @__PURE__ */ jsxs("div", { className: "text-xs text-text-secondary", children: [
|
|
1481
1520
|
node.nodeType,
|
|
1482
1521
|
" v",
|
|
@@ -1597,7 +1636,7 @@ function formatTimestamp(iso) {
|
|
|
1597
1636
|
});
|
|
1598
1637
|
return `${time}.${String(date.getMilliseconds()).padStart(3, "0")}`;
|
|
1599
1638
|
}
|
|
1600
|
-
function groupLines(lines, nodeStates) {
|
|
1639
|
+
function groupLines(lines, nodeStates, nodeDisplay) {
|
|
1601
1640
|
const byNode = /* @__PURE__ */ new Map();
|
|
1602
1641
|
const order = [];
|
|
1603
1642
|
for (const line of lines) {
|
|
@@ -1608,7 +1647,7 @@ function groupLines(lines, nodeStates) {
|
|
|
1608
1647
|
group = {
|
|
1609
1648
|
key,
|
|
1610
1649
|
nodeId: line.nodeId ?? null,
|
|
1611
|
-
label: line.nodeId ? `${line.nodeId}${state?.nodeType ? ` \xB7 ${state.nodeType}` : ""}` : "Run",
|
|
1650
|
+
label: line.nodeId ? `${nodeDisplayTitle(nodeDisplay?.[line.nodeId], line.nodeId)}${state?.nodeType ? ` \xB7 ${state.nodeType}` : ""}` : "Run",
|
|
1612
1651
|
status: state?.status,
|
|
1613
1652
|
lines: [],
|
|
1614
1653
|
hasError: false
|
|
@@ -1625,6 +1664,7 @@ function RunLogViewer({
|
|
|
1625
1664
|
runId,
|
|
1626
1665
|
lines,
|
|
1627
1666
|
nodeStates,
|
|
1667
|
+
nodeDisplay,
|
|
1628
1668
|
loading,
|
|
1629
1669
|
error,
|
|
1630
1670
|
hasMore,
|
|
@@ -1650,8 +1690,8 @@ function RunLogViewer({
|
|
|
1650
1690
|
return lines.filter((line) => line.message.toLowerCase().includes(needle));
|
|
1651
1691
|
}, [lines, search]);
|
|
1652
1692
|
const groups = useMemo(
|
|
1653
|
-
() => groupLines(visible, nodeStates),
|
|
1654
|
-
[visible, nodeStates]
|
|
1693
|
+
() => groupLines(visible, nodeStates, nodeDisplay),
|
|
1694
|
+
[visible, nodeStates, nodeDisplay]
|
|
1655
1695
|
);
|
|
1656
1696
|
const isCollapsed = useCallback(
|
|
1657
1697
|
(group) => {
|
|
@@ -1708,7 +1748,7 @@ function RunLogViewer({
|
|
|
1708
1748
|
}, []);
|
|
1709
1749
|
const downloadRaw = useCallback(() => {
|
|
1710
1750
|
const body = lines.map((line) => {
|
|
1711
|
-
const node = line.nodeId ? ` [${line.nodeId}]` : "";
|
|
1751
|
+
const node = line.nodeId ? ` [${nodeDisplayTitle(nodeDisplay?.[line.nodeId], line.nodeId)}]` : "";
|
|
1712
1752
|
return `${line.timestamp} ${line.level.padEnd(5)}${node} ${line.message}`;
|
|
1713
1753
|
}).join("\n");
|
|
1714
1754
|
const url = URL.createObjectURL(
|
|
@@ -1719,7 +1759,7 @@ function RunLogViewer({
|
|
|
1719
1759
|
anchor.download = `run-${runId}.log`;
|
|
1720
1760
|
anchor.click();
|
|
1721
1761
|
URL.revokeObjectURL(url);
|
|
1722
|
-
}, [lines, runId]);
|
|
1762
|
+
}, [lines, runId, nodeDisplay]);
|
|
1723
1763
|
if (loading && lines.length === 0) {
|
|
1724
1764
|
return /* @__PURE__ */ jsx("div", { className: "space-y-2", "data-testid": "run-log-loading", children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsx(
|
|
1725
1765
|
"div",
|
|
@@ -2418,6 +2458,6 @@ function useAutoRefresh(refetchFn, enabled = true, interval = 5e3) {
|
|
|
2418
2458
|
}, [enabled, interval, refetchFn]);
|
|
2419
2459
|
}
|
|
2420
2460
|
|
|
2421
|
-
export { ExecutionCards, ExecutionFilters, ExecutionStats, ExecutionStatusBadge, ExecutionTable, ExecutionTimeline, NodeTimeline, Pagination, RunLogViewer, useAutoRefresh, useExecution, useExecutionActions, useExecutionStats, useExecutionsStore, useExecutionsWithStore };
|
|
2422
|
-
//# sourceMappingURL=chunk-
|
|
2423
|
-
//# sourceMappingURL=chunk-
|
|
2461
|
+
export { ExecutionCards, ExecutionFilters, ExecutionStats, ExecutionStatusBadge, ExecutionTable, ExecutionTimeline, NodeTimeline, Pagination, RunLogViewer, buildNodeDisplayMap, formatRunVersion, useAutoRefresh, useExecution, useExecutionActions, useExecutionStats, useExecutionsStore, useExecutionsWithStore };
|
|
2462
|
+
//# sourceMappingURL=chunk-VNSIXELY.js.map
|
|
2463
|
+
//# sourceMappingURL=chunk-VNSIXELY.js.map
|