@burdenoff/fluidgrids-fe-sdk 2026.1104.3 → 2026.1105.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/dist/ExecutionDetailPage-HQB2SWBP.js +28 -0
- package/dist/ExecutionsListPage-RSLL634L.js +22 -0
- package/dist/WorkflowBuilder-E3PNZX74.js +32 -0
- package/dist/WorkflowsList-473FRRP2.js +21 -0
- package/dist/{agentTools-SZZN6TP3.js → agentTools-5N3ZEZDW.js} +8 -7
- package/dist/{chunk-NIY6R42C.js → chunk-2KUZBEWW.js} +7 -5
- package/dist/{chunk-NTWG3CJX.js → chunk-3IXU7WUC.js} +32 -21
- package/dist/{chunk-AAIZ6S6E.js → chunk-3QCRKKTI.js} +70 -88
- package/dist/{chunk-WTV6SQYK.js → chunk-3XUWPDKJ.js} +616 -25
- package/dist/{chunk-XCSCD3IU.js → chunk-5CFCFA6O.js} +8 -7
- package/dist/{chunk-DFIX6YWP.js → chunk-62CCBMDC.js} +40 -21
- package/dist/{chunk-KHXRYQYP.js → chunk-64JN2TVX.js} +4 -3
- package/dist/{chunk-NYBL5WHP.js → chunk-6IS7EXIY.js} +3 -3
- package/dist/{chunk-YYVRBROH.js → chunk-6ZK4MRVA.js} +1 -1
- package/dist/{chunk-4YCMMBSK.js → chunk-AJVU5YW6.js} +3 -3
- package/dist/{chunk-NGXJHYV5.js → chunk-AMXJLVZN.js} +2 -2
- package/dist/{chunk-PXIFUMLA.js → chunk-AU7LACOY.js} +16 -11
- package/dist/{chunk-GEY7RXRZ.js → chunk-CH3YUGWR.js} +4 -4
- package/dist/{chunk-XNU2PLJ2.js → chunk-CNKTQ5MG.js} +189 -9
- package/dist/{chunk-BIB7IH26.js → chunk-EYQ7GJRW.js} +5 -5
- package/dist/{chunk-X6PIU7FE.js → chunk-GKFMK7FF.js} +4 -3
- package/dist/{chunk-NJRCAE6K.js → chunk-HK76ZUAK.js} +5 -5
- package/dist/{chunk-F7LQL43U.js → chunk-IL343FKX.js} +2 -2
- package/dist/{chunk-5D4XS3WJ.js → chunk-J3YQCEP3.js} +18 -4
- package/dist/{chunk-4EUEKSEQ.js → chunk-L2N6DDOI.js} +2 -2
- package/dist/chunk-NZAYYUQ4.js +172 -0
- package/dist/{chunk-ON7LK6QH.js → chunk-O7CJJNW6.js} +278 -197
- package/dist/{chunk-ZDCJPQ5M.js → chunk-OXXXUAWM.js} +2 -2
- package/dist/{chunk-D4WA2M2N.js → chunk-QFC6E3WD.js} +4 -3
- package/dist/{chunk-AFX3EKFN.js → chunk-QFGZXWTM.js} +16 -4
- package/dist/{chunk-IK7IGG6T.js → chunk-QPLFALVV.js} +9 -8
- package/dist/{chunk-MF7JLSJX.js → chunk-SALZ3LQB.js} +11 -2
- package/dist/{chunk-SS7Y66P5.js → chunk-TCIBTMJI.js} +70 -4
- package/dist/{chunk-OMB3WMDQ.js → chunk-TNFBRXU7.js} +11 -10
- package/dist/chunk-UEG2WC3G.js +502 -0
- package/dist/chunk-US5QSLPV.js +316 -0
- package/dist/{chunk-5UHAB75U.js → chunk-W5WML3OO.js} +1 -1
- package/dist/chunk-WZ3EJVS6.js +93 -0
- package/dist/{chunk-Q72EOY4T.js → chunk-X25NCWG2.js} +9 -3
- package/dist/{chunk-VDJFTZ2H.js → chunk-XFH6SLDK.js} +4 -93
- package/dist/{chunk-TBHAZK52.js → chunk-Y6M7K4UG.js} +1 -1
- package/dist/{chunk-AVHBWJRY.js → chunk-Z3ABLERJ.js} +3 -1
- package/dist/client-YVZMLEQX.js +3 -0
- package/dist/config-66FUPSG5.js +1 -0
- package/dist/executions.js +18 -15
- package/dist/global-client-N5EIFW6T.js +3 -0
- package/dist/history.js +9 -8
- package/dist/index.d.ts +172 -133
- package/dist/index.js +95 -74
- package/dist/{node-detail-view-GAGSLHAO.js → node-detail-view-WIWW5N6N.js} +36 -11
- package/dist/nodes.js +5 -3
- package/dist/observability.js +10 -8
- package/dist/{quick-config-panel-44RBX6YR.js → quick-config-panel-O64TXXK3.js} +10 -8
- package/dist/settings.js +11 -9
- package/dist/templates.js +15 -14
- package/dist/{workflow-builder-BMGVSwpy.d.ts → workflow-builder-7vv9dCdp.d.ts} +413 -2
- package/dist/workflow-builder.d.ts +2 -1
- package/dist/workflow-builder.js +17 -16
- package/dist/workflows-list.js +11 -10
- package/package.json +1 -1
- package/dist/ExecutionDetailPage-ND2VMU45.js +0 -25
- package/dist/ExecutionsListPage-EZ65FXER.js +0 -20
- package/dist/WorkflowBuilder-4I44FWII.js +0 -31
- package/dist/WorkflowsList-YFD2RKKQ.js +0 -20
- package/dist/chunk-6AMNEX2Y.js +0 -214
- package/dist/client-EYQDMR4O.js +0 -1
- package/dist/config-3DBXLCK3.js +0 -1
- package/dist/global-client-O2HCG5CJ.js +0 -1
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { useDurableRunFields, useRunHistory, useDeterminismStatus, useRunStackTrace, RunHistoryView, SignalRunDialog, terminateDurableRun } from './chunk-
|
|
2
|
-
import { useDurableParityRunFields, useRunMetadata, useRunPending, ExecutionStatusBadge, NodeTimeline, RunLogViewer, setRunVersioningOverride } from './chunk-
|
|
3
|
-
import { useExecution, useExecutionActions, useAutoRefresh, runChainLinks, shortRunId, callbackTone, parseMetadataDefinition, overrideRequestOf } from './chunk-
|
|
4
|
-
import { fetchRunFailureClusters, OPEN_STATUSES, dismissRunFailureCluster, BUCKET_LABELS } from './chunk-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { useDurableRunFields, useRunHistory, useDeterminismStatus, useRunStackTrace, RunHistoryView, SignalRunDialog, terminateDurableRun } from './chunk-QFC6E3WD.js';
|
|
2
|
+
import { useDurableParityRunFields, hasAgentNodeState, agentNodeTraces, orderNodesByExecution, useRunMetadata, useRunPending, ExecutionStatusBadge, NodeTimeline, RunLogViewer, NodeStatusBadge, setRunVersioningOverride } from './chunk-CNKTQ5MG.js';
|
|
3
|
+
import { useExecution, useExecutionActions, useAutoRefresh, runChainLinks, shortRunId, callbackTone, parseMetadataDefinition, overrideRequestOf } from './chunk-J3YQCEP3.js';
|
|
4
|
+
import { fetchRunFailureClusters, OPEN_STATUSES, dismissRunFailureCluster, BUCKET_LABELS, formatDuration } from './chunk-TCIBTMJI.js';
|
|
5
|
+
import { aiCost, formatTokens, modelLabel } from './chunk-NZAYYUQ4.js';
|
|
6
|
+
import { useRunPolicyDecisions, RunPolicyDecisions } from './chunk-AMXJLVZN.js';
|
|
7
|
+
import { EntityTagPicker, canSaveRunAsTestCase, useWorkflowProposal, WorkflowProposalCard, MAX_CASE_NAME, saveRunAsTestCase } from './chunk-EYQ7GJRW.js';
|
|
8
|
+
import { buildNodeDisplayMap, formatRunVersion, nodeDisplayTitle } from './chunk-IL343FKX.js';
|
|
8
9
|
import { AiCreditBalanceSlot } from './chunk-Y53CVZVV.js';
|
|
9
|
-
import { useWorkflowVersions } from './chunk-
|
|
10
|
-
import {
|
|
10
|
+
import { useWorkflowVersions } from './chunk-QFGZXWTM.js';
|
|
11
|
+
import { useDurableFunctionNodesEnabled, useDurableParityEnabled, runSignalTargets, canSignalRun, useWorkflowTestsEnabled } from './chunk-3QCRKKTI.js';
|
|
11
12
|
import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton } from './chunk-5375NUIO.js';
|
|
12
|
-
import {
|
|
13
|
-
import { RunLogsDocument, RunLogAppendedDocument, ExplainRunDocument } from './chunk-AVHBWJRY.js';
|
|
13
|
+
import { RunLogsDocument, RunLogAppendedDocument, ExplainRunDocument, RunAiUsageDocument } from './chunk-Z3ABLERJ.js';
|
|
14
14
|
import { useTr } from './chunk-UULVIT25.js';
|
|
15
|
-
import { getFluidGridsClient, getFluidGridsClientSafe } from './chunk-
|
|
15
|
+
import { getFluidGridsClient, getFluidGridsClientSafe } from './chunk-3IXU7WUC.js';
|
|
16
|
+
import { throwIfResultError, describeOperationError } from './chunk-US5QSLPV.js';
|
|
17
|
+
import { getFluidGridsConfig } from './chunk-UEG2WC3G.js';
|
|
16
18
|
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
17
|
-
import { useParams, useNavigate, Link } from 'react-router';
|
|
19
|
+
import { useParams, useNavigate, useSearchParams, Link } from 'react-router';
|
|
18
20
|
import { Icon } from '@iconify/react';
|
|
19
21
|
import { toast } from 'sonner';
|
|
20
22
|
import { Button } from '@burdenoff/fe-libs/button';
|
|
@@ -1434,6 +1436,533 @@ function resolveDetailTab(selection, runId, available, fallback) {
|
|
|
1434
1436
|
if (selection.runId !== runId) return fallback;
|
|
1435
1437
|
return available.includes(selection.tab) ? selection.tab : fallback;
|
|
1436
1438
|
}
|
|
1439
|
+
function parseDetailTabParam(value, known) {
|
|
1440
|
+
if (!value) return null;
|
|
1441
|
+
return known.includes(value) ? value : null;
|
|
1442
|
+
}
|
|
1443
|
+
function selectionForRun(selection, runId, requested, fallback) {
|
|
1444
|
+
if (selection.runId === runId) return selection;
|
|
1445
|
+
return { runId, tab: requested ?? fallback };
|
|
1446
|
+
}
|
|
1447
|
+
function AgentTracePanel({
|
|
1448
|
+
traces,
|
|
1449
|
+
nodeDisplay,
|
|
1450
|
+
usage,
|
|
1451
|
+
usageLoading,
|
|
1452
|
+
usageError,
|
|
1453
|
+
onRefreshUsage,
|
|
1454
|
+
focusNodeId
|
|
1455
|
+
}) {
|
|
1456
|
+
const tr = useTr();
|
|
1457
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", "data-testid": "agent-trace-panel", children: [
|
|
1458
|
+
/* @__PURE__ */ jsx(
|
|
1459
|
+
AiUsageRollup,
|
|
1460
|
+
{
|
|
1461
|
+
usage,
|
|
1462
|
+
loading: usageLoading,
|
|
1463
|
+
error: usageError,
|
|
1464
|
+
onRefresh: onRefreshUsage,
|
|
1465
|
+
nodeDisplay,
|
|
1466
|
+
tr
|
|
1467
|
+
}
|
|
1468
|
+
),
|
|
1469
|
+
traces.map((trace) => /* @__PURE__ */ jsx(
|
|
1470
|
+
AgentNodeCard,
|
|
1471
|
+
{
|
|
1472
|
+
trace,
|
|
1473
|
+
title: nodeDisplayTitle(nodeDisplay[trace.nodeId], trace.nodeId),
|
|
1474
|
+
focused: !!focusNodeId && focusNodeId === trace.nodeId,
|
|
1475
|
+
tr
|
|
1476
|
+
},
|
|
1477
|
+
trace.nodeStateId
|
|
1478
|
+
)),
|
|
1479
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: tr(
|
|
1480
|
+
"fluidgrids.executions.executionDetail.agent.traceApiNote",
|
|
1481
|
+
"Each tool call is shown as the agent recorded it. The prompt and completion of each model call, and the timing of each iteration, will appear here once agent tracing is available."
|
|
1482
|
+
) })
|
|
1483
|
+
] });
|
|
1484
|
+
}
|
|
1485
|
+
function CostValue({
|
|
1486
|
+
usage,
|
|
1487
|
+
tr
|
|
1488
|
+
}) {
|
|
1489
|
+
const cost = aiCost(usage);
|
|
1490
|
+
if (cost.kind === "priced") return /* @__PURE__ */ jsx(Fragment, { children: cost.text });
|
|
1491
|
+
if (cost.kind === "unpriced") {
|
|
1492
|
+
return /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children: tr(
|
|
1493
|
+
"fluidgrids.executions.executionDetail.agent.notPricedYet",
|
|
1494
|
+
"Not priced yet"
|
|
1495
|
+
) });
|
|
1496
|
+
}
|
|
1497
|
+
return /* @__PURE__ */ jsx(Fragment, { children: "\u2014" });
|
|
1498
|
+
}
|
|
1499
|
+
function Stat({
|
|
1500
|
+
label,
|
|
1501
|
+
children,
|
|
1502
|
+
detail
|
|
1503
|
+
}) {
|
|
1504
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border-secondary bg-background-primary p-3", children: [
|
|
1505
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: label }),
|
|
1506
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-lg font-semibold text-text-primary break-words", children }),
|
|
1507
|
+
detail && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-text-secondary", children: detail })
|
|
1508
|
+
] });
|
|
1509
|
+
}
|
|
1510
|
+
function AiUsageRollup({
|
|
1511
|
+
usage,
|
|
1512
|
+
loading,
|
|
1513
|
+
error,
|
|
1514
|
+
onRefresh,
|
|
1515
|
+
nodeDisplay,
|
|
1516
|
+
tr
|
|
1517
|
+
}) {
|
|
1518
|
+
const total = usage?.total ?? null;
|
|
1519
|
+
const cost = aiCost(total);
|
|
1520
|
+
return /* @__PURE__ */ jsxs(
|
|
1521
|
+
"section",
|
|
1522
|
+
{
|
|
1523
|
+
"aria-label": tr(
|
|
1524
|
+
"fluidgrids.executions.executionDetail.agent.usageHeading",
|
|
1525
|
+
"AI usage"
|
|
1526
|
+
),
|
|
1527
|
+
className: "space-y-3",
|
|
1528
|
+
children: [
|
|
1529
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
1530
|
+
/* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-text-primary", children: tr(
|
|
1531
|
+
"fluidgrids.executions.executionDetail.agent.usageHeading",
|
|
1532
|
+
"AI usage"
|
|
1533
|
+
) }),
|
|
1534
|
+
/* @__PURE__ */ jsxs(
|
|
1535
|
+
"button",
|
|
1536
|
+
{
|
|
1537
|
+
type: "button",
|
|
1538
|
+
onClick: onRefresh,
|
|
1539
|
+
disabled: loading,
|
|
1540
|
+
className: "flex items-center gap-1 rounded px-2 py-1 text-xs text-text-secondary hover:text-text-primary disabled:opacity-50",
|
|
1541
|
+
children: [
|
|
1542
|
+
/* @__PURE__ */ jsx(
|
|
1543
|
+
Icon,
|
|
1544
|
+
{
|
|
1545
|
+
icon: "mdi:refresh",
|
|
1546
|
+
width: 14,
|
|
1547
|
+
className: loading ? "animate-spin" : void 0
|
|
1548
|
+
}
|
|
1549
|
+
),
|
|
1550
|
+
tr(
|
|
1551
|
+
"fluidgrids.executions.executionDetail.agent.refreshUsage",
|
|
1552
|
+
"Refresh"
|
|
1553
|
+
)
|
|
1554
|
+
]
|
|
1555
|
+
}
|
|
1556
|
+
)
|
|
1557
|
+
] }),
|
|
1558
|
+
error && /* @__PURE__ */ jsx(
|
|
1559
|
+
"div",
|
|
1560
|
+
{
|
|
1561
|
+
role: "alert",
|
|
1562
|
+
className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text",
|
|
1563
|
+
children: tr(
|
|
1564
|
+
"fluidgrids.executions.executionDetail.agent.usageError",
|
|
1565
|
+
"Could not load this run's AI usage: {{message}}",
|
|
1566
|
+
{ message: error }
|
|
1567
|
+
)
|
|
1568
|
+
}
|
|
1569
|
+
),
|
|
1570
|
+
!usage && loading && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", "aria-busy": "true", children: [1, 2, 3, 4].map((item) => /* @__PURE__ */ jsx(
|
|
1571
|
+
"div",
|
|
1572
|
+
{
|
|
1573
|
+
className: "h-20 animate-pulse rounded-lg bg-background-tertiary"
|
|
1574
|
+
},
|
|
1575
|
+
item
|
|
1576
|
+
)) }),
|
|
1577
|
+
total ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1578
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: [
|
|
1579
|
+
/* @__PURE__ */ jsx(
|
|
1580
|
+
Stat,
|
|
1581
|
+
{
|
|
1582
|
+
label: tr(
|
|
1583
|
+
"fluidgrids.executions.executionDetail.agent.modelCalls",
|
|
1584
|
+
"Model calls"
|
|
1585
|
+
),
|
|
1586
|
+
children: total.calls.toLocaleString("en-US")
|
|
1587
|
+
}
|
|
1588
|
+
),
|
|
1589
|
+
/* @__PURE__ */ jsx(
|
|
1590
|
+
Stat,
|
|
1591
|
+
{
|
|
1592
|
+
label: tr(
|
|
1593
|
+
"fluidgrids.executions.executionDetail.agent.inputTokens",
|
|
1594
|
+
"Input tokens"
|
|
1595
|
+
),
|
|
1596
|
+
detail: total.cachedInputTokens > 0 ? tr(
|
|
1597
|
+
"fluidgrids.executions.executionDetail.agent.cachedTokens",
|
|
1598
|
+
"{{count}} cached",
|
|
1599
|
+
{ count: formatTokens(total.cachedInputTokens) }
|
|
1600
|
+
) : null,
|
|
1601
|
+
children: formatTokens(total.inputTokens)
|
|
1602
|
+
}
|
|
1603
|
+
),
|
|
1604
|
+
/* @__PURE__ */ jsx(
|
|
1605
|
+
Stat,
|
|
1606
|
+
{
|
|
1607
|
+
label: tr(
|
|
1608
|
+
"fluidgrids.executions.executionDetail.agent.outputTokens",
|
|
1609
|
+
"Output tokens"
|
|
1610
|
+
),
|
|
1611
|
+
children: formatTokens(total.outputTokens)
|
|
1612
|
+
}
|
|
1613
|
+
),
|
|
1614
|
+
/* @__PURE__ */ jsx(
|
|
1615
|
+
Stat,
|
|
1616
|
+
{
|
|
1617
|
+
label: tr(
|
|
1618
|
+
"fluidgrids.executions.executionDetail.agent.estimatedCost",
|
|
1619
|
+
"Estimated cost"
|
|
1620
|
+
),
|
|
1621
|
+
detail: cost.kind === "priced" && cost.partial ? tr(
|
|
1622
|
+
"fluidgrids.executions.executionDetail.agent.partialCost",
|
|
1623
|
+
"Calls not priced yet: {{count}}",
|
|
1624
|
+
{ count: cost.unpricedCalls }
|
|
1625
|
+
) : null,
|
|
1626
|
+
children: /* @__PURE__ */ jsx(CostValue, { usage: total, tr })
|
|
1627
|
+
}
|
|
1628
|
+
)
|
|
1629
|
+
] }),
|
|
1630
|
+
total.calls === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary", children: tr(
|
|
1631
|
+
"fluidgrids.executions.executionDetail.agent.noModelCalls",
|
|
1632
|
+
"No model calls recorded for this run yet."
|
|
1633
|
+
) }) : usage && usage.lines.length > 0 && /* @__PURE__ */ jsx(
|
|
1634
|
+
UsageLines,
|
|
1635
|
+
{
|
|
1636
|
+
lines: usage.lines,
|
|
1637
|
+
nodeDisplay,
|
|
1638
|
+
tr
|
|
1639
|
+
}
|
|
1640
|
+
)
|
|
1641
|
+
] }) : null
|
|
1642
|
+
]
|
|
1643
|
+
}
|
|
1644
|
+
);
|
|
1645
|
+
}
|
|
1646
|
+
function UsageLines({
|
|
1647
|
+
lines,
|
|
1648
|
+
nodeDisplay,
|
|
1649
|
+
tr
|
|
1650
|
+
}) {
|
|
1651
|
+
return /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border border-border-secondary", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[560px] text-sm", children: [
|
|
1652
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-background-tertiary text-left text-xs text-text-secondary", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1653
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium", children: tr(
|
|
1654
|
+
"fluidgrids.executions.executionDetail.agent.lineNode",
|
|
1655
|
+
"Node"
|
|
1656
|
+
) }),
|
|
1657
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium", children: tr(
|
|
1658
|
+
"fluidgrids.executions.executionDetail.agent.lineModel",
|
|
1659
|
+
"Model"
|
|
1660
|
+
) }),
|
|
1661
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-right font-medium", children: tr(
|
|
1662
|
+
"fluidgrids.executions.executionDetail.agent.lineCalls",
|
|
1663
|
+
"Calls"
|
|
1664
|
+
) }),
|
|
1665
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-right font-medium", children: tr(
|
|
1666
|
+
"fluidgrids.executions.executionDetail.agent.lineTokens",
|
|
1667
|
+
"Tokens in / out"
|
|
1668
|
+
) }),
|
|
1669
|
+
/* @__PURE__ */ jsx("th", { className: "px-3 py-2 text-right font-medium", children: tr(
|
|
1670
|
+
"fluidgrids.executions.executionDetail.agent.lineCost",
|
|
1671
|
+
"Cost"
|
|
1672
|
+
) })
|
|
1673
|
+
] }) }),
|
|
1674
|
+
/* @__PURE__ */ jsx("tbody", { children: lines.map((line) => /* @__PURE__ */ jsxs(
|
|
1675
|
+
"tr",
|
|
1676
|
+
{
|
|
1677
|
+
className: "border-t border-border-secondary",
|
|
1678
|
+
children: [
|
|
1679
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-text-primary", children: nodeDisplayTitle(nodeDisplay[line.nodeId], line.nodeId) }),
|
|
1680
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 font-mono text-xs text-text-secondary", children: modelLabel(line.providerKey, line.modelKey) ?? tr(
|
|
1681
|
+
"fluidgrids.executions.executionDetail.agent.unknownModel",
|
|
1682
|
+
"Unknown model"
|
|
1683
|
+
) }),
|
|
1684
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-right text-text-primary", children: line.usage.calls.toLocaleString("en-US") }),
|
|
1685
|
+
/* @__PURE__ */ jsxs("td", { className: "px-3 py-2 text-right text-text-primary", children: [
|
|
1686
|
+
formatTokens(line.usage.inputTokens),
|
|
1687
|
+
" /",
|
|
1688
|
+
" ",
|
|
1689
|
+
formatTokens(line.usage.outputTokens)
|
|
1690
|
+
] }),
|
|
1691
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-right text-text-primary", children: /* @__PURE__ */ jsx(CostValue, { usage: line.usage, tr }) })
|
|
1692
|
+
]
|
|
1693
|
+
},
|
|
1694
|
+
`${line.nodeId}:${line.operation}:${line.providerKey ?? ""}:${line.modelKey ?? ""}`
|
|
1695
|
+
)) })
|
|
1696
|
+
] }) });
|
|
1697
|
+
}
|
|
1698
|
+
function AgentNodeCard({
|
|
1699
|
+
trace,
|
|
1700
|
+
title,
|
|
1701
|
+
focused,
|
|
1702
|
+
tr
|
|
1703
|
+
}) {
|
|
1704
|
+
const ref = useRef(null);
|
|
1705
|
+
useEffect(() => {
|
|
1706
|
+
if (focused) ref.current?.scrollIntoView({ block: "start" });
|
|
1707
|
+
}, [focused]);
|
|
1708
|
+
return /* @__PURE__ */ jsxs(
|
|
1709
|
+
"section",
|
|
1710
|
+
{
|
|
1711
|
+
ref,
|
|
1712
|
+
"aria-label": title,
|
|
1713
|
+
"data-agent-node": trace.nodeId,
|
|
1714
|
+
className: `rounded-lg border bg-background-primary p-4 ${focused ? "border-action-primary-bg" : "border-border-secondary"}`,
|
|
1715
|
+
children: [
|
|
1716
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
1717
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1718
|
+
/* @__PURE__ */ jsx(
|
|
1719
|
+
Icon,
|
|
1720
|
+
{
|
|
1721
|
+
icon: "mdi:robot-outline",
|
|
1722
|
+
width: 18,
|
|
1723
|
+
className: "shrink-0 text-text-secondary"
|
|
1724
|
+
}
|
|
1725
|
+
),
|
|
1726
|
+
/* @__PURE__ */ jsx("h4", { className: "truncate font-medium text-text-primary", children: title })
|
|
1727
|
+
] }),
|
|
1728
|
+
/* @__PURE__ */ jsx("div", { className: "self-start sm:self-auto", children: /* @__PURE__ */ jsx(NodeStatusBadge, { status: trace.status, size: "sm" }) })
|
|
1729
|
+
] }),
|
|
1730
|
+
/* @__PURE__ */ jsxs("dl", { className: "mt-3 grid grid-cols-2 gap-x-4 gap-y-2 text-sm sm:grid-cols-4", children: [
|
|
1731
|
+
/* @__PURE__ */ jsx(
|
|
1732
|
+
Fact,
|
|
1733
|
+
{
|
|
1734
|
+
label: tr(
|
|
1735
|
+
"fluidgrids.executions.executionDetail.agent.iterations",
|
|
1736
|
+
"Iterations"
|
|
1737
|
+
),
|
|
1738
|
+
value: trace.iterationCount?.toLocaleString("en-US") ?? "\u2014"
|
|
1739
|
+
}
|
|
1740
|
+
),
|
|
1741
|
+
/* @__PURE__ */ jsx(
|
|
1742
|
+
Fact,
|
|
1743
|
+
{
|
|
1744
|
+
label: tr(
|
|
1745
|
+
"fluidgrids.executions.executionDetail.agent.tokensUsed",
|
|
1746
|
+
"Tokens used"
|
|
1747
|
+
),
|
|
1748
|
+
value: trace.tokensUsed === null ? "\u2014" : formatTokens(trace.tokensUsed)
|
|
1749
|
+
}
|
|
1750
|
+
),
|
|
1751
|
+
/* @__PURE__ */ jsx(
|
|
1752
|
+
Fact,
|
|
1753
|
+
{
|
|
1754
|
+
label: tr(
|
|
1755
|
+
"fluidgrids.executions.executionDetail.agent.toolCalls",
|
|
1756
|
+
"Tool calls"
|
|
1757
|
+
),
|
|
1758
|
+
value: trace.steps.length.toLocaleString("en-US")
|
|
1759
|
+
}
|
|
1760
|
+
),
|
|
1761
|
+
/* @__PURE__ */ jsx(
|
|
1762
|
+
Fact,
|
|
1763
|
+
{
|
|
1764
|
+
label: tr(
|
|
1765
|
+
"fluidgrids.executions.executionDetail.agent.duration",
|
|
1766
|
+
"Duration"
|
|
1767
|
+
),
|
|
1768
|
+
value: trace.durationMs === null ? "\u2014" : formatDuration(trace.durationMs / 1e3)
|
|
1769
|
+
}
|
|
1770
|
+
)
|
|
1771
|
+
] }),
|
|
1772
|
+
trace.error && /* @__PURE__ */ jsxs("div", { className: "mt-3 rounded border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text", children: [
|
|
1773
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
1774
|
+
tr("fluidgrids.executions.executionDetail.agent.error", "Error"),
|
|
1775
|
+
":",
|
|
1776
|
+
" "
|
|
1777
|
+
] }),
|
|
1778
|
+
/* @__PURE__ */ jsx("span", { className: "break-words", children: trace.error })
|
|
1779
|
+
] }),
|
|
1780
|
+
trace.waitingForApproval && /* @__PURE__ */ jsx(PendingApprovals, { trace, tr }),
|
|
1781
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
|
|
1782
|
+
/* @__PURE__ */ jsx("h5", { className: "mb-2 text-sm font-medium text-text-primary", children: tr(
|
|
1783
|
+
"fluidgrids.executions.executionDetail.agent.stepsHeading",
|
|
1784
|
+
"Tool calls"
|
|
1785
|
+
) }),
|
|
1786
|
+
trace.steps.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary", children: tr(
|
|
1787
|
+
"fluidgrids.executions.executionDetail.agent.noSteps",
|
|
1788
|
+
"The agent made no tool calls."
|
|
1789
|
+
) }) : /* @__PURE__ */ jsx("ol", { className: "space-y-2", children: trace.steps.map((step) => /* @__PURE__ */ jsx(AgentStepRow, { step, tr }, step.index)) })
|
|
1790
|
+
] }),
|
|
1791
|
+
trace.response && /* @__PURE__ */ jsxs("details", { className: "mt-4", open: true, children: [
|
|
1792
|
+
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-sm font-medium text-text-primary", children: tr(
|
|
1793
|
+
"fluidgrids.executions.executionDetail.agent.finalResponse",
|
|
1794
|
+
"Final response"
|
|
1795
|
+
) }),
|
|
1796
|
+
/* @__PURE__ */ jsx("pre", { className: "mt-2 max-h-80 overflow-auto rounded bg-background-tertiary p-3 font-mono text-xs whitespace-pre-wrap break-words text-text-primary", children: trace.response })
|
|
1797
|
+
] })
|
|
1798
|
+
]
|
|
1799
|
+
}
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
function Fact({ label, value }) {
|
|
1803
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
1804
|
+
/* @__PURE__ */ jsx("dt", { className: "text-xs text-text-secondary", children: label }),
|
|
1805
|
+
/* @__PURE__ */ jsx("dd", { className: "text-text-primary", children: value })
|
|
1806
|
+
] });
|
|
1807
|
+
}
|
|
1808
|
+
function PendingApprovals({
|
|
1809
|
+
trace,
|
|
1810
|
+
tr
|
|
1811
|
+
}) {
|
|
1812
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-3 rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-3", children: [
|
|
1813
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
1814
|
+
/* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-medium text-status-warning-text", children: [
|
|
1815
|
+
/* @__PURE__ */ jsx(Icon, { icon: "mdi:account-clock-outline", width: 16 }),
|
|
1816
|
+
tr(
|
|
1817
|
+
"fluidgrids.executions.executionDetail.agent.awaitingApproval",
|
|
1818
|
+
"Tool calls waiting for approval: {{count}}",
|
|
1819
|
+
{ count: trace.pendingApprovals.length }
|
|
1820
|
+
)
|
|
1821
|
+
] }),
|
|
1822
|
+
/* @__PURE__ */ jsx(
|
|
1823
|
+
Link,
|
|
1824
|
+
{
|
|
1825
|
+
to: "../approvals",
|
|
1826
|
+
className: "text-sm font-medium text-text-link underline-offset-2 hover:text-text-linkHover hover:underline",
|
|
1827
|
+
children: tr(
|
|
1828
|
+
"fluidgrids.executions.executionDetail.agent.reviewApprovals",
|
|
1829
|
+
"Review in Approvals"
|
|
1830
|
+
)
|
|
1831
|
+
}
|
|
1832
|
+
)
|
|
1833
|
+
] }),
|
|
1834
|
+
trace.pendingApprovals.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-2 space-y-2", children: trace.pendingApprovals.map((call) => /* @__PURE__ */ jsxs("li", { className: "rounded bg-background-primary p-2", children: [
|
|
1835
|
+
/* @__PURE__ */ jsx("p", { className: "font-mono text-xs font-medium text-text-primary", children: call.tool }),
|
|
1836
|
+
call.args && /* @__PURE__ */ jsx("pre", { className: "mt-1 max-h-48 overflow-auto font-mono text-xs whitespace-pre-wrap break-words text-text-secondary", children: call.args })
|
|
1837
|
+
] }, call.key)) })
|
|
1838
|
+
] });
|
|
1839
|
+
}
|
|
1840
|
+
function AgentStepRow({ step, tr }) {
|
|
1841
|
+
const marked = step.outcome !== "ok";
|
|
1842
|
+
return /* @__PURE__ */ jsx(
|
|
1843
|
+
"li",
|
|
1844
|
+
{
|
|
1845
|
+
className: `rounded border ${step.outcome === "rejected" ? "border-status-warning-border" : step.outcome === "failed" ? "border-status-error-border" : "border-border-secondary"}`,
|
|
1846
|
+
children: /* @__PURE__ */ jsxs("details", { children: [
|
|
1847
|
+
/* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer flex-wrap items-center gap-2 px-3 py-2 text-sm", children: [
|
|
1848
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-text-secondary", children: [
|
|
1849
|
+
step.index + 1,
|
|
1850
|
+
"."
|
|
1851
|
+
] }),
|
|
1852
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 break-all font-mono text-text-primary", children: step.tool }),
|
|
1853
|
+
step.outcome === "rejected" && /* @__PURE__ */ jsx("span", { className: "rounded bg-status-warning-bg-subtle px-1.5 py-0.5 text-xs text-status-warning-text", children: tr(
|
|
1854
|
+
"fluidgrids.executions.executionDetail.agent.stepRejected",
|
|
1855
|
+
"Rejected"
|
|
1856
|
+
) }),
|
|
1857
|
+
step.outcome === "failed" && /* @__PURE__ */ jsx("span", { className: "rounded bg-status-error-bg-subtle px-1.5 py-0.5 text-xs text-status-error-text", children: tr(
|
|
1858
|
+
"fluidgrids.executions.executionDetail.agent.stepFailed",
|
|
1859
|
+
"Failed"
|
|
1860
|
+
) }),
|
|
1861
|
+
step.durationMs !== null && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs text-text-secondary", children: formatDuration(step.durationMs / 1e3) })
|
|
1862
|
+
] }),
|
|
1863
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 border-t border-border-secondary px-3 py-2", children: [
|
|
1864
|
+
marked && step.reason && /* @__PURE__ */ jsx(
|
|
1865
|
+
"p",
|
|
1866
|
+
{
|
|
1867
|
+
className: `text-sm ${step.outcome === "rejected" ? "text-status-warning-text" : "text-status-error-text"}`,
|
|
1868
|
+
children: step.reason
|
|
1869
|
+
}
|
|
1870
|
+
),
|
|
1871
|
+
/* @__PURE__ */ jsx(
|
|
1872
|
+
StepBlock,
|
|
1873
|
+
{
|
|
1874
|
+
label: tr(
|
|
1875
|
+
"fluidgrids.executions.executionDetail.agent.stepArguments",
|
|
1876
|
+
"Arguments"
|
|
1877
|
+
),
|
|
1878
|
+
value: step.args,
|
|
1879
|
+
empty: tr(
|
|
1880
|
+
"fluidgrids.executions.executionDetail.agent.stepNoArguments",
|
|
1881
|
+
"No arguments"
|
|
1882
|
+
)
|
|
1883
|
+
}
|
|
1884
|
+
),
|
|
1885
|
+
/* @__PURE__ */ jsx(
|
|
1886
|
+
StepBlock,
|
|
1887
|
+
{
|
|
1888
|
+
label: tr(
|
|
1889
|
+
"fluidgrids.executions.executionDetail.agent.stepResult",
|
|
1890
|
+
"Result"
|
|
1891
|
+
),
|
|
1892
|
+
value: step.observation,
|
|
1893
|
+
empty: tr(
|
|
1894
|
+
"fluidgrids.executions.executionDetail.agent.stepNoResult",
|
|
1895
|
+
"No result recorded"
|
|
1896
|
+
)
|
|
1897
|
+
}
|
|
1898
|
+
)
|
|
1899
|
+
] })
|
|
1900
|
+
] })
|
|
1901
|
+
}
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
function StepBlock({
|
|
1905
|
+
label,
|
|
1906
|
+
value,
|
|
1907
|
+
empty
|
|
1908
|
+
}) {
|
|
1909
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
1910
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-text-secondary", children: label }),
|
|
1911
|
+
value ? /* @__PURE__ */ jsx("pre", { className: "mt-1 max-h-64 overflow-auto rounded bg-background-tertiary p-2 font-mono text-xs whitespace-pre-wrap break-words text-text-primary", children: value }) : /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-text-secondary", children: empty })
|
|
1912
|
+
] });
|
|
1913
|
+
}
|
|
1914
|
+
var RUN_AI_USAGE_POLL_INTERVAL_MS = 5e3;
|
|
1915
|
+
async function fetchRunAiUsage(runId) {
|
|
1916
|
+
const result = await getFluidGridsClient().query({
|
|
1917
|
+
query: RunAiUsageDocument,
|
|
1918
|
+
variables: { runId },
|
|
1919
|
+
fetchPolicy: "network-only"
|
|
1920
|
+
});
|
|
1921
|
+
throwIfResultError(result);
|
|
1922
|
+
return result.data?.runAiUsage ?? null;
|
|
1923
|
+
}
|
|
1924
|
+
function useRunAiUsage(runId, { enabled, live }) {
|
|
1925
|
+
const [sent, setSent] = useState(0);
|
|
1926
|
+
const [settled, setSettled] = useState(null);
|
|
1927
|
+
const request = useRef(0);
|
|
1928
|
+
const read = useCallback(async () => {
|
|
1929
|
+
if (!runId || !enabled) return;
|
|
1930
|
+
const id = ++request.current;
|
|
1931
|
+
setSent(id);
|
|
1932
|
+
let next;
|
|
1933
|
+
try {
|
|
1934
|
+
next = { usage: await fetchRunAiUsage(runId), error: null };
|
|
1935
|
+
} catch (err) {
|
|
1936
|
+
next = {
|
|
1937
|
+
usage: null,
|
|
1938
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
if (id !== request.current) return;
|
|
1942
|
+
setSettled((previous) => ({
|
|
1943
|
+
request: id,
|
|
1944
|
+
runId,
|
|
1945
|
+
// A failed refresh keeps the last good read of the same run on screen.
|
|
1946
|
+
usage: next.usage ?? (next.error && previous?.runId === runId ? previous.usage : null),
|
|
1947
|
+
error: next.error
|
|
1948
|
+
}));
|
|
1949
|
+
}, [runId, enabled]);
|
|
1950
|
+
useEffect(() => {
|
|
1951
|
+
void read();
|
|
1952
|
+
}, [read]);
|
|
1953
|
+
useEffect(() => {
|
|
1954
|
+
if (!enabled || !live) return;
|
|
1955
|
+
const timer = setInterval(() => void read(), RUN_AI_USAGE_POLL_INTERVAL_MS);
|
|
1956
|
+
return () => clearInterval(timer);
|
|
1957
|
+
}, [enabled, live, read]);
|
|
1958
|
+
const current = enabled && settled?.runId === runId ? settled : null;
|
|
1959
|
+
return {
|
|
1960
|
+
usage: current?.usage ?? null,
|
|
1961
|
+
loading: enabled && !!runId && (current?.request ?? -1) !== sent,
|
|
1962
|
+
error: current?.error ?? null,
|
|
1963
|
+
refetch: read
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1437
1966
|
function formatTime(value) {
|
|
1438
1967
|
if (!value) return null;
|
|
1439
1968
|
const date = new Date(value);
|
|
@@ -2298,19 +2827,43 @@ function SaveRunAsTestCase({ runId }) {
|
|
|
2298
2827
|
var ALL_DETAIL_TABS = [
|
|
2299
2828
|
"timeline",
|
|
2300
2829
|
"history",
|
|
2830
|
+
"agent",
|
|
2301
2831
|
"logs",
|
|
2302
2832
|
"input",
|
|
2303
2833
|
"context"
|
|
2304
2834
|
];
|
|
2305
|
-
|
|
2306
|
-
(
|
|
2307
|
-
)
|
|
2835
|
+
function availableDetailTabs(isDurableRun, hasAgent) {
|
|
2836
|
+
return ALL_DETAIL_TABS.filter(
|
|
2837
|
+
(tab) => (tab !== "history" || isDurableRun) && (tab !== "agent" || hasAgent)
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2308
2840
|
function ExecutionDetailPage() {
|
|
2309
2841
|
const tr = useTr();
|
|
2310
2842
|
const { runId } = useParams();
|
|
2311
2843
|
const navigate = useNavigate();
|
|
2312
|
-
const [
|
|
2313
|
-
const
|
|
2844
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
2845
|
+
const requestedTab = parseDetailTabParam(
|
|
2846
|
+
searchParams.get("tab"),
|
|
2847
|
+
ALL_DETAIL_TABS
|
|
2848
|
+
);
|
|
2849
|
+
const requestedNodeId = searchParams.get("node");
|
|
2850
|
+
const [tabSelection, setTabSelection] = useState({ runId, tab: requestedTab ?? "timeline" });
|
|
2851
|
+
const [agentFocus, setAgentFocus] = useState({ runId, nodeId: requestedNodeId });
|
|
2852
|
+
const setActiveTab = (tab, focusNodeId = null) => {
|
|
2853
|
+
setTabSelection({ runId, tab });
|
|
2854
|
+
setAgentFocus({ runId, nodeId: focusNodeId });
|
|
2855
|
+
setSearchParams(
|
|
2856
|
+
(params) => {
|
|
2857
|
+
const next = new URLSearchParams(params);
|
|
2858
|
+
if (tab === "timeline") next.delete("tab");
|
|
2859
|
+
else next.set("tab", tab);
|
|
2860
|
+
if (focusNodeId) next.set("node", focusNodeId);
|
|
2861
|
+
else next.delete("node");
|
|
2862
|
+
return next;
|
|
2863
|
+
},
|
|
2864
|
+
{ replace: true }
|
|
2865
|
+
);
|
|
2866
|
+
};
|
|
2314
2867
|
const [autoRefreshEnabled, setAutoRefreshEnabled] = useState(true);
|
|
2315
2868
|
const [showTerminateDialog, setShowTerminateDialog] = useState(false);
|
|
2316
2869
|
const { allowed: canControlRuns } = useFluidGridsPermission(
|
|
@@ -2426,12 +2979,27 @@ function ExecutionDetailPage() {
|
|
|
2426
2979
|
minLevel: minLogLevel
|
|
2427
2980
|
});
|
|
2428
2981
|
const isDurableRun = durableEnabled && execution?.executionKind === "DURABLE_FN";
|
|
2982
|
+
const hasAgent = hasAgentNodeState(execution?.nodeStates);
|
|
2429
2983
|
const activeTab = resolveDetailTab(
|
|
2430
|
-
tabSelection,
|
|
2984
|
+
selectionForRun(tabSelection, runId, requestedTab, "timeline"),
|
|
2431
2985
|
runId,
|
|
2432
|
-
isDurableRun
|
|
2986
|
+
availableDetailTabs(isDurableRun, hasAgent),
|
|
2433
2987
|
"timeline"
|
|
2434
2988
|
);
|
|
2989
|
+
const agentFocusNodeId = agentFocus.runId === runId ? agentFocus.nodeId : requestedNodeId;
|
|
2990
|
+
const runAiUsage = useRunAiUsage(runId, {
|
|
2991
|
+
enabled: hasAgent && activeTab === "agent",
|
|
2992
|
+
live: autoRefreshEnabled && isActive
|
|
2993
|
+
});
|
|
2994
|
+
const agentTraces = useMemo(
|
|
2995
|
+
() => agentNodeTraces(
|
|
2996
|
+
orderNodesByExecution(
|
|
2997
|
+
execution?.nodeStates ?? [],
|
|
2998
|
+
execution?.triggerNodeId ?? void 0
|
|
2999
|
+
)
|
|
3000
|
+
),
|
|
3001
|
+
[execution?.nodeStates, execution?.triggerNodeId]
|
|
3002
|
+
);
|
|
2435
3003
|
const runHistory = useRunHistory(runId, {
|
|
2436
3004
|
enabled: isDurableRun && activeTab === "history",
|
|
2437
3005
|
live: isActive
|
|
@@ -2546,7 +3114,7 @@ function ExecutionDetailPage() {
|
|
|
2546
3114
|
},
|
|
2547
3115
|
[navigate]
|
|
2548
3116
|
);
|
|
2549
|
-
const
|
|
3117
|
+
const formatDuration2 = (ms) => {
|
|
2550
3118
|
if (!ms) return "-";
|
|
2551
3119
|
if (ms < 1e3) return `${ms}ms`;
|
|
2552
3120
|
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
@@ -2676,6 +3244,16 @@ function ExecutionDetailPage() {
|
|
|
2676
3244
|
icon: "mdi:history"
|
|
2677
3245
|
}
|
|
2678
3246
|
] : [],
|
|
3247
|
+
...hasAgent ? [
|
|
3248
|
+
{
|
|
3249
|
+
id: "agent",
|
|
3250
|
+
label: tr(
|
|
3251
|
+
"fluidgrids.executions.executionDetail.agentTab",
|
|
3252
|
+
"Agent"
|
|
3253
|
+
),
|
|
3254
|
+
icon: "mdi:robot-outline"
|
|
3255
|
+
}
|
|
3256
|
+
] : [],
|
|
2679
3257
|
{
|
|
2680
3258
|
id: "logs",
|
|
2681
3259
|
label: tr("fluidgrids.executions.executionDetail.logsTab", "Logs"),
|
|
@@ -3000,7 +3578,7 @@ function ExecutionDetailPage() {
|
|
|
3000
3578
|
"fluidgrids.executions.executionDetail.durationStat",
|
|
3001
3579
|
"Duration"
|
|
3002
3580
|
) }),
|
|
3003
|
-
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold text-text-primary mt-1", children:
|
|
3581
|
+
/* @__PURE__ */ jsx("div", { className: "text-xl font-bold text-text-primary mt-1", children: formatDuration2(execution.duration) })
|
|
3004
3582
|
] }),
|
|
3005
3583
|
/* @__PURE__ */ jsxs("div", { className: "bg-background-secondary rounded-lg border border-border-secondary p-4", children: [
|
|
3006
3584
|
/* @__PURE__ */ jsx("div", { className: "text-sm text-text-secondary", children: tr(
|
|
@@ -3125,12 +3703,12 @@ function ExecutionDetailPage() {
|
|
|
3125
3703
|
onViewChildRun: handleViewChildRun
|
|
3126
3704
|
}
|
|
3127
3705
|
),
|
|
3128
|
-
/* @__PURE__ */ jsx("div", { className: "border-b border-border-secondary mb-6", children: /* @__PURE__ */ jsx("nav", { className: "flex gap-4 -mb-px", children: tabs.map((tab) => /* @__PURE__ */ jsxs(
|
|
3706
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-border-secondary mb-6", children: /* @__PURE__ */ jsx("nav", { className: "flex gap-4 -mb-px overflow-x-auto", children: tabs.map((tab) => /* @__PURE__ */ jsxs(
|
|
3129
3707
|
"button",
|
|
3130
3708
|
{
|
|
3131
3709
|
onClick: () => setActiveTab(tab.id),
|
|
3132
3710
|
className: `
|
|
3133
|
-
flex items-center gap-2 px-4 py-3 border-b-2 text-sm font-medium transition-colors
|
|
3711
|
+
flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 border-b-2 text-sm font-medium transition-colors
|
|
3134
3712
|
${activeTab === tab.id ? "border-action-primary-bg text-action-primary-text" : "border-transparent text-text-secondary hover:text-text-primary hover:border-border-primary"}
|
|
3135
3713
|
`,
|
|
3136
3714
|
children: [
|
|
@@ -3148,7 +3726,20 @@ function ExecutionDetailPage() {
|
|
|
3148
3726
|
nodeDisplay,
|
|
3149
3727
|
triggerNodeId: execution.triggerNodeId ?? void 0,
|
|
3150
3728
|
onRetryNode: canControlRuns ? handleRetryNode : void 0,
|
|
3151
|
-
onViewChildRun: handleViewChildRun
|
|
3729
|
+
onViewChildRun: handleViewChildRun,
|
|
3730
|
+
onViewAgentTrace: (nodeId) => setActiveTab("agent", nodeId)
|
|
3731
|
+
}
|
|
3732
|
+
) }),
|
|
3733
|
+
activeTab === "agent" && hasAgent && /* @__PURE__ */ jsx("div", { className: "p-4 sm:p-6", children: /* @__PURE__ */ jsx(
|
|
3734
|
+
AgentTracePanel,
|
|
3735
|
+
{
|
|
3736
|
+
traces: agentTraces,
|
|
3737
|
+
nodeDisplay,
|
|
3738
|
+
usage: runAiUsage.usage,
|
|
3739
|
+
usageLoading: runAiUsage.loading,
|
|
3740
|
+
usageError: runAiUsage.error,
|
|
3741
|
+
onRefreshUsage: () => void runAiUsage.refetch(),
|
|
3742
|
+
focusNodeId: agentFocusNodeId
|
|
3152
3743
|
}
|
|
3153
3744
|
) }),
|
|
3154
3745
|
activeTab === "history" && isDurableRun && /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-4 sm:p-6", children: [
|