@burdenoff/fluidgrids-fe-sdk 2026.1105.1 → 2026.1105.3
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 +30 -0
- package/dist/ExecutionDetailPage-JXGPSLS3.js +30 -0
- package/dist/{WorkflowsList-EV725VG5.js → ExecutionsListPage-U3TC5JUI.js} +11 -8
- package/dist/{WorkflowBuilder-CRR5WP4V.js → WorkflowBuilder-6DOD6WWH.js} +16 -13
- package/dist/{ExecutionsListPage-NQIQXMTY.js → WorkflowsList-XOWRQNST.js} +10 -8
- package/dist/{agentTools-PN4W7QZH.js → agentTools-YQBN33WG.js} +7 -5
- package/dist/{chunk-VFVN7D3A.js → chunk-22U3TUKZ.js} +3 -93
- package/dist/{chunk-XLI75E3D.js → chunk-2WUVF4EQ.js} +2 -2
- package/dist/{chunk-GVIYGJQG.js → chunk-3MZOYJ5I.js} +1 -1
- package/dist/{chunk-L44BRLW5.js → chunk-3ZYRLGDF.js} +612 -22
- package/dist/{chunk-FCT6POFX.js → chunk-4NNF7DIB.js} +1 -1
- package/dist/chunk-5DVP2UYH.js +1924 -0
- package/dist/{chunk-JDQYGH4Q.js → chunk-EKDUYCTS.js} +4 -4
- package/dist/{chunk-6P7DOBVN.js → chunk-EYQ7GJRW.js} +2 -2
- package/dist/{chunk-HLAUK5GM.js → chunk-FVWRGL7S.js} +1 -1
- package/dist/{chunk-AZKVI4YN.js → chunk-G33OMSW6.js} +8 -6
- package/dist/{chunk-D7G5VWSH.js → chunk-G774FI2E.js} +2 -2
- package/dist/{chunk-DANOMJ5I.js → chunk-IJ7UIDCW.js} +7 -6
- package/dist/{chunk-EC2AN74G.js → chunk-IL343FKX.js} +1 -1
- package/dist/chunk-JYYN3CLL.js +32 -0
- package/dist/{chunk-O2EB7UT2.js → chunk-KAWRHIJZ.js} +2 -2
- package/dist/{chunk-JC4D7RQ6.js → chunk-KN37RIFC.js} +5 -4
- package/dist/{chunk-AASHQI77.js → chunk-KZCNJAMK.js} +2 -1
- package/dist/{chunk-BHAKNT5M.js → chunk-LDWBMCX4.js} +4 -3
- package/dist/{chunk-MSQAULLG.js → chunk-MA6I4KY5.js} +186 -7
- package/dist/{chunk-R3Z7W4EX.js → chunk-MP44TAOO.js} +276 -196
- package/dist/{chunk-FJSXXO5W.js → chunk-MY7SEUXM.js} +1 -1
- package/dist/{chunk-I3QPAEL6.js → chunk-NMQENSPW.js} +15 -14
- package/dist/chunk-NZAYYUQ4.js +172 -0
- package/dist/{chunk-6EZJ5J3B.js → chunk-NZFPCTIS.js} +4 -4
- package/dist/{chunk-MZFJL4X3.js → chunk-OXXXUAWM.js} +1 -1
- package/dist/chunk-SDZEAIIE.js +9 -0
- package/dist/{chunk-CGR3AEZU.js → chunk-TCIBTMJI.js} +68 -2
- package/dist/{chunk-4QB6S7YW.js → chunk-TJAG2DQT.js} +9 -38
- package/dist/{chunk-MQN6YDX4.js → chunk-TLHX4DK4.js} +7 -6
- package/dist/{chunk-AG3VC7Y2.js → chunk-VESQH55Q.js} +2 -2
- package/dist/chunk-WZ3EJVS6.js +93 -0
- package/dist/{chunk-OCJTTHTS.js → chunk-Y7FKJJMF.js} +1 -9
- package/dist/{chunk-HOTVUVZG.js → chunk-YGOGJDN4.js} +2 -2
- package/dist/{chunk-AVHBWJRY.js → chunk-Z3ABLERJ.js} +3 -1
- package/dist/{chunk-C26QAWCT.js → chunk-ZBPRNWKY.js} +235 -2146
- package/dist/{chunk-2QOAJF7V.js → chunk-ZLBTUCC2.js} +4 -3
- package/dist/code-editor-field-WWPDMF4O.js +3 -0
- package/dist/executions.js +16 -12
- package/dist/history.js +9 -6
- package/dist/index.d.ts +77 -1
- package/dist/index.js +46 -41
- package/dist/{node-detail-view-3VG7XFIZ.js → node-detail-view-U5HOP2WX.js} +35 -9
- package/dist/nodes.js +2 -2
- package/dist/observability.js +9 -6
- package/dist/{quick-config-panel-GB7SDWHD.js → quick-config-panel-XAISBW6Y.js} +10 -7
- package/dist/settings.js +9 -6
- package/dist/templates.js +15 -12
- package/dist/workflow-builder.js +17 -14
- package/dist/workflow-preview.d.ts +158 -0
- package/dist/workflow-preview.js +721 -0
- package/dist/workflows-list.js +10 -8
- package/package.json +5 -1
- package/dist/ExecutionDetailPage-YBAMVPMB.js +0 -26
- package/dist/code-editor-field-XWUVOKTA.js +0 -2
|
@@ -1,21 +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-
|
|
1
|
+
import { useDurableRunFields, useRunHistory, useDeterminismStatus, useRunStackTrace, RunHistoryView, SignalRunDialog, terminateDurableRun } from './chunk-2WUVF4EQ.js';
|
|
2
|
+
import { useDurableParityRunFields, hasAgentNodeState, agentNodeTraces, orderNodesByExecution, useRunMetadata, useRunPending, ExecutionStatusBadge, NodeTimeline, RunLogViewer, NodeStatusBadge, setRunVersioningOverride } from './chunk-MA6I4KY5.js';
|
|
3
|
+
import { useExecution, useExecutionActions, useAutoRefresh, runChainLinks, shortRunId, callbackTone, parseMetadataDefinition, overrideRequestOf } from './chunk-VESQH55Q.js';
|
|
4
|
+
import { fetchRunFailureClusters, OPEN_STATUSES, dismissRunFailureCluster, BUCKET_LABELS, formatDuration } from './chunk-TCIBTMJI.js';
|
|
5
|
+
import { aiCost, formatTokens, modelLabel } from './chunk-NZAYYUQ4.js';
|
|
5
6
|
import { useRunPolicyDecisions, RunPolicyDecisions } from './chunk-AMXJLVZN.js';
|
|
6
|
-
import { EntityTagPicker, canSaveRunAsTestCase, useWorkflowProposal, WorkflowProposalCard, MAX_CASE_NAME, saveRunAsTestCase } from './chunk-
|
|
7
|
-
import { buildNodeDisplayMap, formatRunVersion } from './chunk-
|
|
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 { useDurableFunctionNodesEnabled, useDurableParityEnabled, runSignalTargets, canSignalRun, useWorkflowTestsEnabled } from './chunk-
|
|
10
|
+
import { useWorkflowVersions } from './chunk-YGOGJDN4.js';
|
|
11
|
+
import { useDurableFunctionNodesEnabled, useDurableParityEnabled, runSignalTargets, canSignalRun, useWorkflowTestsEnabled } from './chunk-ZBPRNWKY.js';
|
|
11
12
|
import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton } from './chunk-5375NUIO.js';
|
|
12
|
-
import { RunLogsDocument, RunLogAppendedDocument, ExplainRunDocument } from './chunk-
|
|
13
|
+
import { RunLogsDocument, RunLogAppendedDocument, ExplainRunDocument, RunAiUsageDocument } from './chunk-Z3ABLERJ.js';
|
|
13
14
|
import { useTr } from './chunk-UULVIT25.js';
|
|
14
15
|
import { getFluidGridsClient, getFluidGridsClientSafe } from './chunk-3IXU7WUC.js';
|
|
15
16
|
import { throwIfResultError, describeOperationError } from './chunk-US5QSLPV.js';
|
|
16
17
|
import { getFluidGridsConfig } from './chunk-UEG2WC3G.js';
|
|
17
18
|
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
18
|
-
import { useParams, useNavigate, Link } from 'react-router';
|
|
19
|
+
import { useParams, useNavigate, useSearchParams, Link } from 'react-router';
|
|
19
20
|
import { Icon } from '@iconify/react';
|
|
20
21
|
import { toast } from 'sonner';
|
|
21
22
|
import { Button } from '@burdenoff/fe-libs/button';
|
|
@@ -1435,6 +1436,533 @@ function resolveDetailTab(selection, runId, available, fallback) {
|
|
|
1435
1436
|
if (selection.runId !== runId) return fallback;
|
|
1436
1437
|
return available.includes(selection.tab) ? selection.tab : fallback;
|
|
1437
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
|
+
}
|
|
1438
1966
|
function formatTime(value) {
|
|
1439
1967
|
if (!value) return null;
|
|
1440
1968
|
const date = new Date(value);
|
|
@@ -2299,19 +2827,43 @@ function SaveRunAsTestCase({ runId }) {
|
|
|
2299
2827
|
var ALL_DETAIL_TABS = [
|
|
2300
2828
|
"timeline",
|
|
2301
2829
|
"history",
|
|
2830
|
+
"agent",
|
|
2302
2831
|
"logs",
|
|
2303
2832
|
"input",
|
|
2304
2833
|
"context"
|
|
2305
2834
|
];
|
|
2306
|
-
|
|
2307
|
-
(
|
|
2308
|
-
)
|
|
2835
|
+
function availableDetailTabs(isDurableRun, hasAgent) {
|
|
2836
|
+
return ALL_DETAIL_TABS.filter(
|
|
2837
|
+
(tab) => (tab !== "history" || isDurableRun) && (tab !== "agent" || hasAgent)
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2309
2840
|
function ExecutionDetailPage() {
|
|
2310
2841
|
const tr = useTr();
|
|
2311
2842
|
const { runId } = useParams();
|
|
2312
2843
|
const navigate = useNavigate();
|
|
2313
|
-
const [
|
|
2314
|
-
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
|
+
};
|
|
2315
2867
|
const [autoRefreshEnabled, setAutoRefreshEnabled] = useState(true);
|
|
2316
2868
|
const [showTerminateDialog, setShowTerminateDialog] = useState(false);
|
|
2317
2869
|
const { allowed: canControlRuns } = useFluidGridsPermission(
|
|
@@ -2427,12 +2979,27 @@ function ExecutionDetailPage() {
|
|
|
2427
2979
|
minLevel: minLogLevel
|
|
2428
2980
|
});
|
|
2429
2981
|
const isDurableRun = durableEnabled && execution?.executionKind === "DURABLE_FN";
|
|
2982
|
+
const hasAgent = hasAgentNodeState(execution?.nodeStates);
|
|
2430
2983
|
const activeTab = resolveDetailTab(
|
|
2431
|
-
tabSelection,
|
|
2984
|
+
selectionForRun(tabSelection, runId, requestedTab, "timeline"),
|
|
2432
2985
|
runId,
|
|
2433
|
-
isDurableRun
|
|
2986
|
+
availableDetailTabs(isDurableRun, hasAgent),
|
|
2434
2987
|
"timeline"
|
|
2435
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
|
+
);
|
|
2436
3003
|
const runHistory = useRunHistory(runId, {
|
|
2437
3004
|
enabled: isDurableRun && activeTab === "history",
|
|
2438
3005
|
live: isActive
|
|
@@ -2547,7 +3114,7 @@ function ExecutionDetailPage() {
|
|
|
2547
3114
|
},
|
|
2548
3115
|
[navigate]
|
|
2549
3116
|
);
|
|
2550
|
-
const
|
|
3117
|
+
const formatDuration2 = (ms) => {
|
|
2551
3118
|
if (!ms) return "-";
|
|
2552
3119
|
if (ms < 1e3) return `${ms}ms`;
|
|
2553
3120
|
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
@@ -2677,6 +3244,16 @@ function ExecutionDetailPage() {
|
|
|
2677
3244
|
icon: "mdi:history"
|
|
2678
3245
|
}
|
|
2679
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
|
+
] : [],
|
|
2680
3257
|
{
|
|
2681
3258
|
id: "logs",
|
|
2682
3259
|
label: tr("fluidgrids.executions.executionDetail.logsTab", "Logs"),
|
|
@@ -3001,7 +3578,7 @@ function ExecutionDetailPage() {
|
|
|
3001
3578
|
"fluidgrids.executions.executionDetail.durationStat",
|
|
3002
3579
|
"Duration"
|
|
3003
3580
|
) }),
|
|
3004
|
-
/* @__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) })
|
|
3005
3582
|
] }),
|
|
3006
3583
|
/* @__PURE__ */ jsxs("div", { className: "bg-background-secondary rounded-lg border border-border-secondary p-4", children: [
|
|
3007
3584
|
/* @__PURE__ */ jsx("div", { className: "text-sm text-text-secondary", children: tr(
|
|
@@ -3126,12 +3703,12 @@ function ExecutionDetailPage() {
|
|
|
3126
3703
|
onViewChildRun: handleViewChildRun
|
|
3127
3704
|
}
|
|
3128
3705
|
),
|
|
3129
|
-
/* @__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(
|
|
3130
3707
|
"button",
|
|
3131
3708
|
{
|
|
3132
3709
|
onClick: () => setActiveTab(tab.id),
|
|
3133
3710
|
className: `
|
|
3134
|
-
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
|
|
3135
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"}
|
|
3136
3713
|
`,
|
|
3137
3714
|
children: [
|
|
@@ -3149,7 +3726,20 @@ function ExecutionDetailPage() {
|
|
|
3149
3726
|
nodeDisplay,
|
|
3150
3727
|
triggerNodeId: execution.triggerNodeId ?? void 0,
|
|
3151
3728
|
onRetryNode: canControlRuns ? handleRetryNode : void 0,
|
|
3152
|
-
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
|
|
3153
3743
|
}
|
|
3154
3744
|
) }),
|
|
3155
3745
|
activeTab === "history" && isDurableRun && /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-4 sm:p-6", children: [
|