@burdenoff/fluidgrids-fe-sdk 2026.1111.1 → 2026.1111.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.
Files changed (42) hide show
  1. package/dist/{ExecutionDetailPage-DpAYZYx2.js → ExecutionDetailPage-BLQ9mPPO.js} +72 -19
  2. package/dist/{FailureTriagePanel-BJoO3lsL.js → FailureTriagePanel-DquVHzGD.js} +97 -3
  3. package/dist/{FluidGridsProvider-CraUhM4E.js → FluidGridsProvider-Bve22Hxu.js} +1 -1
  4. package/dist/{HistoryPage-CYqyngbp.js → HistoryPage-CCVLBD8a.js} +3 -3
  5. package/dist/{InsightsPage-DBnOta71.js → InsightsPage-BCRRKaja.js} +352 -72
  6. package/dist/{ManagedAiPolicyAuthority-D3AYZ5FP.js → ManagedAiPolicyAuthority-PhyUARha.js} +6 -6
  7. package/dist/{MissingNodesInstallModal-LdB_-hSf.js → MissingNodesInstallModal-CkbBf648.js} +2 -2
  8. package/dist/{NodesPage-fEUyUKLC.js → NodesPage-XglgbnFQ.js} +2 -2
  9. package/dist/{PublishCustomNodeAction-C6qkAIjG.js → PublishCustomNodeAction-CtRHgitG.js} +1 -1
  10. package/dist/{TemplateConfigurationModal-CnqJFt2f.js → TemplateConfigurationModal-DPe69XFz.js} +2 -2
  11. package/dist/{TemplateDetailPanel-BWnLqcA7.js → TemplateDetailPanel-ahqcAMmr.js} +2 -2
  12. package/dist/{TemplatesPage-omZCh0-D.js → TemplatesPage-CRIn51Qa.js} +5 -5
  13. package/dist/{VersionDiffDialog-CLgIj_jc.js → VersionDiffDialog-BejQlKec.js} +1 -1
  14. package/dist/{WorkflowProposalCard-CV4kV4_Z.js → WorkflowProposalCard-aoR_tT2f.js} +1 -1
  15. package/dist/{WorkflowSearchRedirect-D34qC1Qm.js → WorkflowSearchRedirect-5x2HX5tx.js} +10 -10
  16. package/dist/{WorkflowShareDialog-DiD8Gqim.js → WorkflowShareDialog-BONVJpp_.js} +2 -2
  17. package/dist/{WorkflowsList-Bgsy1OPw.js → WorkflowsList-CDPqtaa3.js} +5 -5
  18. package/dist/{agent-form-Ci_vxQF5.js → agent-form-m8tkBULw.js} +1 -1
  19. package/dist/{agentTools-D61qQFfw.js → agentTools-DxuakWxT.js} +2 -2
  20. package/dist/{codec-client-Cm4GXmJ9.js → codec-client-aN37SXBf.js} +1 -1
  21. package/dist/executions.js +1 -1
  22. package/dist/{flow-builder-sG8ZsMYV.js → flow-builder-CmJi6XWS.js} +22 -22
  23. package/dist/history.js +1 -1
  24. package/dist/{index-FrgTpWov.d.ts → index-CpEB91Ys.d.ts} +33 -1
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +24 -24
  27. package/dist/{node-detail-view-pyTakx4l.js → node-detail-view-CAUbejnM.js} +6 -6
  28. package/dist/{node-endpoint-configs-DXCKkK_9.js → node-endpoint-configs-BgZARXHI.js} +264 -4
  29. package/dist/nodes.js +1 -1
  30. package/dist/observability.d.ts +1 -1
  31. package/dist/observability.js +1 -1
  32. package/dist/{quick-config-panel-Zpsh2brj.js → quick-config-panel-BxM7KKaU.js} +2 -2
  33. package/dist/settings.js +1 -1
  34. package/dist/templates.js +1 -1
  35. package/dist/{useAgentDefinitions-Czl2aHJb.js → useAgentDefinitions-BKimckKY.js} +1 -1
  36. package/dist/{useExecutions-CZuOL3RI.js → useExecutions-BIrUuMlR.js} +3 -2
  37. package/dist/{useObservability-D402nqXD.js → useObservability-cCsmALjS.js} +2 -2
  38. package/dist/{useRunHistory-CsXQohcH.js → useRunHistory-DG0Nfolg.js} +2 -2
  39. package/dist/{useWorkflows-UyKrrkX-.js → useWorkflows-CQbVEHc0.js} +2 -2
  40. package/dist/workflow-builder.js +2 -2
  41. package/dist/workflows-list.js +1 -1
  42. package/package.json +1 -1
@@ -1,12 +1,12 @@
1
1
  "use client";
2
- import { At as OptimisationSuggestionsDocument, Fr as WorkflowProposalDocument, Lt as ProposeOptimisationDocument, On as SnoozeOptimisationSuggestionDocument, Pi as throwIfResultError, S as ContinuousOptimisationSettingsDocument, Y as DismissOptimisationSuggestionDocument, hi as WorkspaceAiUsageDocument, ut as FgRunOptimisationScanDocument, xn as SetContinuousOptimisationEnabledDocument, yi as getFluidGridsClient } from "./node-endpoint-configs-DXCKkK_9.js";
3
- import { Vn as useContinuousOptimisationEnabled } from "./FluidGridsProvider-CraUhM4E.js";
2
+ import { Fi as throwIfResultError, Ir as WorkflowProposalDocument, Rt as ProposeOptimisationDocument, S as ContinuousOptimisationSettingsDocument, Sn as SetContinuousOptimisationEnabledDocument, Y as DismissOptimisationSuggestionDocument, bi as getFluidGridsClient, dt as FgRunOptimisationScanDocument, gi as WorkspaceAiUsageDocument, jt as OptimisationSuggestionsDocument, kn as SnoozeOptimisationSuggestionDocument, tt as ErrorAnalyticsDocument } from "./node-endpoint-configs-BgZARXHI.js";
3
+ import { Vn as useContinuousOptimisationEnabled } from "./FluidGridsProvider-Bve22Hxu.js";
4
4
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
5
5
  import { BC as OptimisationSuggestionStatus, RC as OptimisationDismissReason, fI as useFluidGridsPermission, lI as SdkPermissionButton, oI as FLUIDGRIDS_PERMISSIONS, zC as OptimisationKind } from "./graphql-types-CulUbQWN.js";
6
6
  import { t as proposalCanvasPath } from "./useRequestedProposal-B7uPXfZB.js";
7
- import { n as FailureTriagePanel } from "./FailureTriagePanel-BJoO3lsL.js";
7
+ import { c as runListPath, l as utcDay, n as FailureTriagePanel } from "./FailureTriagePanel-DquVHzGD.js";
8
8
  import { a as formatTokens, c as DISMISS_REASONS, d as monthlySavingLabel, f as shortRunId, i as aiSpendPeriod, l as evidenceFacts, r as aiCost, s as runsOfWorkflowPath, t as AI_SPEND_RANGE_DAYS, u as evidenceWindowDays } from "./ai-usage-CK61EZWc.js";
9
- import { n as useDataSinks, o as useRunReplayActions, r as useInsightsData, t as useDataSinkData } from "./useObservability-D402nqXD.js";
9
+ import { n as useDataSinks, o as useRunReplayActions, r as useInsightsData, t as useDataSinkData } from "./useObservability-cCsmALjS.js";
10
10
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
11
11
  import { Link, useNavigate } from "react-router";
12
12
  import { Icon } from "@iconify/react";
@@ -1285,6 +1285,306 @@ function SpendTable({ lines, tr }) {
1285
1285
  });
1286
1286
  }
1287
1287
 
1288
+ // src/modules/observability/components/ErrorAnalyticsPanel.tsx
1289
+ /**
1290
+ * Insights: the error panel (BOFF-9974). The workspace's failed runs over the
1291
+ * last 30 days, from `errorAnalytics`: how many failed each day, by error type,
1292
+ * the node types that failed most and the workflows that failed most.
1293
+ *
1294
+ * Every bar and row opens the Runs list on the failed runs behind it, over the
1295
+ * same window the panel counted (a day bar on that UTC day). The panel loads
1296
+ * and fails on its own, so the rest of Insights never waits for it.
1297
+ */
1298
+ /** A bar's share of the largest value, never thinner than a visible sliver. */
1299
+ function barWidth(value, largest) {
1300
+ return `${Math.max(8, percentage(value, largest || 1))}%`;
1301
+ }
1302
+ function Ranking({ title, empty, children, testId }) {
1303
+ return /* @__PURE__ */ jsxs("div", {
1304
+ className: "rounded-lg border border-border-secondary bg-background-primary p-4",
1305
+ "data-testid": testId,
1306
+ children: [/* @__PURE__ */ jsx("h3", {
1307
+ className: "mb-3 text-sm font-semibold text-text-primary",
1308
+ children: title
1309
+ }), children.length > 0 ? /* @__PURE__ */ jsx("ul", {
1310
+ className: "space-y-1",
1311
+ children
1312
+ }) : /* @__PURE__ */ jsx("p", {
1313
+ className: "text-sm text-text-secondary",
1314
+ children: empty
1315
+ })]
1316
+ });
1317
+ }
1318
+ function RankingRow({ to, label, detail, count, largest, tone }) {
1319
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Link, {
1320
+ to,
1321
+ className: "flex items-center gap-3 rounded-md px-2 py-1.5 hover:bg-background-tertiary",
1322
+ "data-testid": "error-panel-row",
1323
+ children: [
1324
+ /* @__PURE__ */ jsxs("span", {
1325
+ className: "min-w-0 flex-1",
1326
+ children: [/* @__PURE__ */ jsx("span", {
1327
+ className: "block truncate text-sm text-text-primary",
1328
+ children: label
1329
+ }), detail && /* @__PURE__ */ jsx("span", {
1330
+ className: "block truncate text-xs text-text-secondary",
1331
+ children: detail
1332
+ })]
1333
+ }),
1334
+ /* @__PURE__ */ jsx("span", {
1335
+ className: "h-2 w-24 shrink-0 overflow-hidden rounded-full bg-background-tertiary",
1336
+ children: /* @__PURE__ */ jsx("span", {
1337
+ className: `block h-full rounded-full ${tone === "error" ? "bg-status-error-bg" : "bg-status-warning-bg"}`,
1338
+ style: { width: barWidth(count, largest) }
1339
+ })
1340
+ }),
1341
+ /* @__PURE__ */ jsx("span", {
1342
+ className: "w-8 shrink-0 text-right text-sm font-medium text-text-secondary",
1343
+ children: count.toLocaleString()
1344
+ })
1345
+ ]
1346
+ }) });
1347
+ }
1348
+ function Trend({ trend, link, tr }) {
1349
+ const largest = Math.max(0, ...trend.map((point) => point.count));
1350
+ return /* @__PURE__ */ jsxs("div", {
1351
+ className: "rounded-lg border border-border-secondary bg-background-primary p-4",
1352
+ "data-testid": "error-panel-trend",
1353
+ children: [
1354
+ /* @__PURE__ */ jsx("h3", {
1355
+ className: "mb-3 text-sm font-semibold text-text-primary",
1356
+ children: tr("fluidgrids.insights.errorPanel.trend", "Failed runs per day")
1357
+ }),
1358
+ /* @__PURE__ */ jsx("ol", {
1359
+ className: "flex h-24 items-end gap-0.5",
1360
+ children: trend.map((point) => {
1361
+ const label = tr("fluidgrids.insights.errorPanel.trendDay", "{{date}}: {{count}} failed", {
1362
+ date: point.date,
1363
+ count: point.count.toLocaleString()
1364
+ });
1365
+ const height = point.count > 0 ? `${Math.max(6, percentage(point.count, largest))}%` : "2px";
1366
+ const day = utcDay(point.date);
1367
+ return /* @__PURE__ */ jsx("li", {
1368
+ className: "flex h-full min-w-0 flex-1 items-end",
1369
+ children: point.count > 0 && day ? /* @__PURE__ */ jsx(Link, {
1370
+ to: link({
1371
+ from: day.from,
1372
+ to: day.to
1373
+ }),
1374
+ className: "block w-full rounded-t-sm bg-status-error-bg hover:opacity-80",
1375
+ style: { height },
1376
+ title: label,
1377
+ "aria-label": label,
1378
+ "data-testid": "error-panel-day"
1379
+ }) : /* @__PURE__ */ jsx("span", {
1380
+ className: "block w-full rounded-t-sm bg-background-tertiary",
1381
+ style: { height },
1382
+ title: label
1383
+ })
1384
+ }, point.date);
1385
+ })
1386
+ }),
1387
+ trend.length > 0 && /* @__PURE__ */ jsxs("div", {
1388
+ className: "mt-1 flex justify-between text-xs text-text-secondary",
1389
+ children: [/* @__PURE__ */ jsx("span", { children: trend[0]?.date }), /* @__PURE__ */ jsx("span", { children: trend[trend.length - 1]?.date })]
1390
+ })
1391
+ ]
1392
+ });
1393
+ }
1394
+ function ErrorAnalyticsPanel({ analytics, period, loading, error, onRetry }) {
1395
+ const tr = useTr();
1396
+ const link = (extra) => runListPath({
1397
+ status: "FAILED",
1398
+ from: period?.from,
1399
+ to: period?.to,
1400
+ ...extra
1401
+ });
1402
+ let body;
1403
+ if (error && !analytics) body = /* @__PURE__ */ jsxs("div", {
1404
+ className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-4 text-sm text-status-error-text",
1405
+ role: "alert",
1406
+ children: [
1407
+ /* @__PURE__ */ jsx("p", {
1408
+ className: "font-medium",
1409
+ children: tr("fluidgrids.insights.errorPanel.loadError", "Could not load error analytics")
1410
+ }),
1411
+ /* @__PURE__ */ jsx("p", {
1412
+ className: "mt-1",
1413
+ children: error
1414
+ }),
1415
+ /* @__PURE__ */ jsx(Button$1, {
1416
+ variant: "outline",
1417
+ size: "sm",
1418
+ className: "mt-3",
1419
+ onClick: onRetry,
1420
+ children: tr("fluidgrids.insights.retryLoad", "Try again")
1421
+ })
1422
+ ]
1423
+ });
1424
+ else if (!analytics) body = /* @__PURE__ */ jsx("div", {
1425
+ className: "h-40 animate-pulse rounded-lg bg-background-tertiary",
1426
+ "aria-busy": "true"
1427
+ });
1428
+ else if (analytics.totalErrors === 0) body = /* @__PURE__ */ jsx("p", {
1429
+ className: "text-sm text-text-secondary",
1430
+ children: tr("fluidgrids.insights.noErrors", "No errors in this period.")
1431
+ });
1432
+ else {
1433
+ const byType = [...analytics.errorsByType].sort((a, b) => b.count - a.count);
1434
+ const largestType = byType[0]?.count ?? 0;
1435
+ const largestNode = analytics.topFailingNodes[0]?.failureCount ?? 0;
1436
+ const largestWorkflow = analytics.topFailingWorkflows[0]?.failureCount ?? 0;
1437
+ body = /* @__PURE__ */ jsxs("div", {
1438
+ className: "space-y-4",
1439
+ children: [/* @__PURE__ */ jsx(Trend, {
1440
+ trend: analytics.trend,
1441
+ link,
1442
+ tr
1443
+ }), /* @__PURE__ */ jsxs("div", {
1444
+ className: "grid gap-4 lg:grid-cols-3",
1445
+ children: [
1446
+ /* @__PURE__ */ jsx(Ranking, {
1447
+ title: tr("fluidgrids.insights.errorsByType", "Errors by type"),
1448
+ empty: tr("fluidgrids.insights.noErrors", "No errors in this period."),
1449
+ testId: "error-panel-types",
1450
+ children: byType.map((entry) => /* @__PURE__ */ jsx(RankingRow, {
1451
+ to: link({ errorType: entry.errorType }),
1452
+ label: entry.errorType,
1453
+ count: entry.count,
1454
+ largest: largestType,
1455
+ tone: "error"
1456
+ }, entry.errorType))
1457
+ }),
1458
+ /* @__PURE__ */ jsx(Ranking, {
1459
+ title: tr("fluidgrids.insights.topFailingNodes", "Top failing nodes"),
1460
+ empty: tr("fluidgrids.insights.noFailedNodes", "No node failures in this period."),
1461
+ testId: "error-panel-nodes",
1462
+ children: analytics.topFailingNodes.map((node) => /* @__PURE__ */ jsx(RankingRow, {
1463
+ to: link({ failedNodeType: node.nodeType }),
1464
+ label: node.nodeType,
1465
+ detail: node.sampleError ?? tr("fluidgrids.insights.errorPanel.nodeRate", "{{failures}} of {{total}} executions failed", {
1466
+ failures: node.failureCount.toLocaleString(),
1467
+ total: node.totalExecutions.toLocaleString()
1468
+ }),
1469
+ count: node.failureCount,
1470
+ largest: largestNode,
1471
+ tone: "warning"
1472
+ }, node.nodeType))
1473
+ }),
1474
+ /* @__PURE__ */ jsx(Ranking, {
1475
+ title: tr("fluidgrids.insights.topFailingWorkflows", "Top failing workflows"),
1476
+ empty: tr("fluidgrids.insights.noFailedWorkflows", "No failed workflows in this period."),
1477
+ testId: "error-panel-workflows",
1478
+ children: analytics.topFailingWorkflows.map((workflow) => /* @__PURE__ */ jsx(RankingRow, {
1479
+ to: link({ workflowKey: workflow.workflowKey }),
1480
+ label: workflow.name?.trim() || workflow.workflowKey,
1481
+ detail: tr("fluidgrids.insights.errorPanel.workflowRate", "{{failures}} of {{total}} runs failed", {
1482
+ failures: workflow.failureCount.toLocaleString(),
1483
+ total: workflow.totalRuns.toLocaleString()
1484
+ }),
1485
+ count: workflow.failureCount,
1486
+ largest: largestWorkflow,
1487
+ tone: "error"
1488
+ }, workflow.workflowKey))
1489
+ })
1490
+ ]
1491
+ })]
1492
+ });
1493
+ }
1494
+ return /* @__PURE__ */ jsxs("section", {
1495
+ className: "rounded-xl border border-border-secondary bg-background-secondary p-5",
1496
+ "aria-labelledby": "insights-error-panel-heading",
1497
+ "aria-busy": loading,
1498
+ "data-testid": "insights-error-panel",
1499
+ children: [/* @__PURE__ */ jsxs("div", {
1500
+ className: "mb-4 flex flex-wrap items-baseline justify-between gap-2",
1501
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("h2", {
1502
+ id: "insights-error-panel-heading",
1503
+ className: "flex items-center gap-2 text-base font-semibold text-text-primary",
1504
+ children: [/* @__PURE__ */ jsx(Icon, {
1505
+ icon: "mdi:alert-octagon-outline",
1506
+ width: 18
1507
+ }), tr("fluidgrids.insights.errorPanel.title", "Errors")]
1508
+ }), /* @__PURE__ */ jsx("p", {
1509
+ className: "mt-1 text-sm text-text-secondary",
1510
+ children: tr("fluidgrids.insights.errorPanel.subtitle", "Failed runs in the last 30 days. Select a bar or a row to see the runs behind it.")
1511
+ })] }), analytics && analytics.totalErrors > 0 && /* @__PURE__ */ jsx(Link, {
1512
+ to: link({}),
1513
+ className: "text-sm font-medium text-text-link hover:underline",
1514
+ "data-testid": "error-panel-total",
1515
+ children: tr("fluidgrids.insights.errorPanel.total", "{{count}} failed runs", { count: analytics.totalErrors.toLocaleString() })
1516
+ })]
1517
+ }), body]
1518
+ });
1519
+ }
1520
+
1521
+ // src/modules/observability/hooks/useErrorAnalytics.ts
1522
+ /**
1523
+ * useErrorAnalytics — the workspace's failed runs over the last
1524
+ * {@link ERROR_ANALYTICS_WINDOW_DAYS} days by type, node, workflow and day
1525
+ * (`errorAnalytics`, BOFF-7519), for the Insights error panel (BOFF-9974).
1526
+ *
1527
+ * The window is fixed when the read is made and returned with the data, so
1528
+ * the panel's links open the runs list on exactly the window it counted. A
1529
+ * plain network read per refresh; nothing is read while `enabled` is false.
1530
+ */
1531
+ /** Rows per ranking. */
1532
+ const ERROR_ANALYTICS_LIMIT = 8;
1533
+ function errorAnalyticsWindow(now) {
1534
+ return {
1535
+ from: /* @__PURE__ */ new Date(now.getTime() - 2592e6),
1536
+ to: now
1537
+ };
1538
+ }
1539
+ async function fetchErrorAnalytics(period) {
1540
+ const result = await getFluidGridsClient().query({
1541
+ query: ErrorAnalyticsDocument,
1542
+ variables: { input: {
1543
+ startDate: period.from.toISOString(),
1544
+ endDate: period.to.toISOString(),
1545
+ limit: 8
1546
+ } },
1547
+ fetchPolicy: "network-only"
1548
+ });
1549
+ throwIfResultError(result);
1550
+ return result.data?.errorAnalytics ?? null;
1551
+ }
1552
+ function useErrorAnalytics(enabled) {
1553
+ const [sent, setSent] = useState(0);
1554
+ const [settled, setSettled] = useState(null);
1555
+ const request = useRef(0);
1556
+ const read = useCallback(async () => {
1557
+ if (!enabled) return;
1558
+ const id = ++request.current;
1559
+ setSent(id);
1560
+ const period = errorAnalyticsWindow(/* @__PURE__ */ new Date());
1561
+ let analytics = null;
1562
+ let error = null;
1563
+ try {
1564
+ analytics = await fetchErrorAnalytics(period);
1565
+ } catch (err) {
1566
+ error = err instanceof Error ? err.message : String(err);
1567
+ }
1568
+ if (id !== request.current) return;
1569
+ setSettled((previous) => ({
1570
+ request: id,
1571
+ period: analytics || !previous ? period : previous.period,
1572
+ analytics: analytics ?? (error ? previous?.analytics ?? null : null),
1573
+ error
1574
+ }));
1575
+ }, [enabled]);
1576
+ useEffect(() => {
1577
+ read();
1578
+ }, [read]);
1579
+ return {
1580
+ analytics: settled?.analytics ?? null,
1581
+ period: settled?.period ?? null,
1582
+ loading: enabled && (settled?.request ?? -1) !== sent,
1583
+ error: settled?.error ?? null,
1584
+ refetch: read
1585
+ };
1586
+ }
1587
+
1288
1588
  // src/modules/observability/pages/InsightsPage.tsx
1289
1589
  function normalizedRate(summary) {
1290
1590
  const supplied = summary.workflowSuccessRate;
@@ -1334,6 +1634,7 @@ function InsightsPage({ showErrors = false }) {
1334
1634
  const { allowed: canManageTriage } = useFluidGridsPermission(FLUIDGRIDS_PERMISSIONS.WORKFLOW_PUBLISH);
1335
1635
  const { allowed: canRetryRuns } = useFluidGridsPermission(FLUIDGRIDS_PERMISSIONS.WORKFLOW_RUN_EXECUTE);
1336
1636
  const [activeTab, setActiveTab] = useState(showErrors ? "errors" : "overview");
1637
+ const errorAnalytics = useErrorAnalytics(activeTab === "errors");
1337
1638
  const failureBreakdown = useMemo(() => getFailureBreakdown(failedRuns), [failedRuns]);
1338
1639
  const topWorkflows = useMemo(() => getTopFailingWorkflows(failedRuns).slice(0, 8), [failedRuns]);
1339
1640
  const topNodes = useMemo(() => getTopFailingNodes(summary?.nodeUsageStats ?? []).slice(0, 8), [summary?.nodeUsageStats]);
@@ -1394,7 +1695,10 @@ function InsightsPage({ showErrors = false }) {
1394
1695
  })
1395
1696
  ] }), /* @__PURE__ */ jsxs(Button$1, {
1396
1697
  variant: "outline",
1397
- onClick: () => void refetch(),
1698
+ onClick: () => {
1699
+ refetch();
1700
+ if (activeTab === "errors") errorAnalytics.refetch();
1701
+ },
1398
1702
  disabled: loading,
1399
1703
  children: [/* @__PURE__ */ jsx(Icon, {
1400
1704
  icon: "mdi:refresh",
@@ -1455,10 +1759,16 @@ function InsightsPage({ showErrors = false }) {
1455
1759
  }) : /* @__PURE__ */ jsx(ErrorContent, {
1456
1760
  summary,
1457
1761
  failedRuns,
1458
- failureBreakdown,
1459
1762
  commonError,
1460
1763
  retry,
1461
1764
  retryLoading,
1765
+ errorPanel: /* @__PURE__ */ jsx(ErrorAnalyticsPanel, {
1766
+ analytics: errorAnalytics.analytics,
1767
+ period: errorAnalytics.period,
1768
+ loading: errorAnalytics.loading,
1769
+ error: errorAnalytics.error,
1770
+ onRetry: () => void errorAnalytics.refetch()
1771
+ }),
1462
1772
  tr
1463
1773
  })
1464
1774
  ]
@@ -1575,73 +1885,43 @@ function InsightList({ title, empty, children }) {
1575
1885
  })]
1576
1886
  });
1577
1887
  }
1578
- function ErrorContent({ summary, failedRuns, failureBreakdown, commonError, retry, retryLoading, tr }) {
1888
+ function ErrorContent({ summary, failedRuns, commonError, retry, retryLoading, errorPanel, tr }) {
1579
1889
  return /* @__PURE__ */ jsxs("div", {
1580
1890
  className: "space-y-6",
1581
1891
  "data-tour": "fluidgrids-insights-errors",
1582
- children: [/* @__PURE__ */ jsxs("section", {
1583
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
1584
- children: [
1585
- /* @__PURE__ */ jsx(MetricCard, {
1586
- icon: "mdi:alert-outline",
1587
- label: tr("fluidgrids.insights.failureRate", "Failure rate"),
1588
- value: `${summary ? percentage(summary.runsFailedCount, summary.runsCountTotal).toFixed(1) : "0.0"}%`,
1589
- tone: "text-status-error-text"
1590
- }),
1591
- /* @__PURE__ */ jsx(MetricCard, {
1592
- icon: "mdi:counter",
1593
- label: tr("fluidgrids.insights.failureCount", "Failures captured"),
1594
- value: failedRuns.length.toLocaleString(),
1595
- detail: summary ? `${summary.runsFailedCount.toLocaleString()} total recorded` : void 0
1596
- }),
1597
- /* @__PURE__ */ jsx(MetricCard, {
1598
- icon: "mdi:alert-decagram-outline",
1599
- label: tr("fluidgrids.insights.commonError", "Most common error"),
1600
- value: commonError?.key ?? "—",
1601
- detail: commonError ? `${commonError.count} occurrences` : void 0
1602
- }),
1603
- /* @__PURE__ */ jsx(MetricCard, {
1604
- icon: "mdi:repeat",
1605
- label: tr("fluidgrids.insights.recoveredByRetry", "Recovered by retry"),
1606
- value: "—",
1607
- detail: tr("fluidgrids.insights.retryBaselineMissing", "Retry recovery baseline is not exposed by the service yet."),
1608
- tone: "text-text-secondary"
1609
- })
1610
- ]
1611
- }), /* @__PURE__ */ jsxs("section", {
1612
- className: "grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",
1613
- children: [/* @__PURE__ */ jsxs("div", {
1614
- className: "rounded-xl border border-border-secondary bg-background-secondary p-5",
1615
- children: [/* @__PURE__ */ jsx("h2", {
1616
- className: "mb-4 text-base font-semibold text-text-primary",
1617
- children: tr("fluidgrids.insights.errorsByType", "Errors by type")
1618
- }), /* @__PURE__ */ jsxs("div", {
1619
- className: "space-y-3",
1620
- children: [failureBreakdown.length === 0 && /* @__PURE__ */ jsx("p", {
1621
- className: "text-sm text-text-secondary",
1622
- children: tr("fluidgrids.insights.noErrors", "No errors in this period.")
1623
- }), failureBreakdown.map((entry) => /* @__PURE__ */ jsxs("div", {
1624
- className: "flex items-center gap-3",
1625
- children: [
1626
- /* @__PURE__ */ jsx("span", {
1627
- className: "w-28 truncate text-sm text-text-secondary",
1628
- children: entry.key
1629
- }),
1630
- /* @__PURE__ */ jsx("div", {
1631
- className: "h-2 flex-1 overflow-hidden rounded-full bg-background-tertiary",
1632
- children: /* @__PURE__ */ jsx("div", {
1633
- className: "h-full rounded-full bg-status-error-bg",
1634
- style: { width: `${Math.max(8, percentage(entry.count, failureBreakdown[0]?.count ?? 1))}%` }
1635
- })
1636
- }),
1637
- /* @__PURE__ */ jsx("span", {
1638
- className: "w-8 text-right text-sm font-medium text-text-primary",
1639
- children: entry.count
1640
- })
1641
- ]
1642
- }, entry.key))]
1643
- })]
1644
- }), /* @__PURE__ */ jsxs("div", {
1892
+ children: [
1893
+ /* @__PURE__ */ jsxs("section", {
1894
+ className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
1895
+ children: [
1896
+ /* @__PURE__ */ jsx(MetricCard, {
1897
+ icon: "mdi:alert-outline",
1898
+ label: tr("fluidgrids.insights.failureRate", "Failure rate"),
1899
+ value: `${summary ? percentage(summary.runsFailedCount, summary.runsCountTotal).toFixed(1) : "0.0"}%`,
1900
+ tone: "text-status-error-text"
1901
+ }),
1902
+ /* @__PURE__ */ jsx(MetricCard, {
1903
+ icon: "mdi:counter",
1904
+ label: tr("fluidgrids.insights.failureCount", "Failures captured"),
1905
+ value: failedRuns.length.toLocaleString(),
1906
+ detail: summary ? `${summary.runsFailedCount.toLocaleString()} total recorded` : void 0
1907
+ }),
1908
+ /* @__PURE__ */ jsx(MetricCard, {
1909
+ icon: "mdi:alert-decagram-outline",
1910
+ label: tr("fluidgrids.insights.commonError", "Most common error"),
1911
+ value: commonError?.key ?? "—",
1912
+ detail: commonError ? `${commonError.count} occurrences` : void 0
1913
+ }),
1914
+ /* @__PURE__ */ jsx(MetricCard, {
1915
+ icon: "mdi:repeat",
1916
+ label: tr("fluidgrids.insights.recoveredByRetry", "Recovered by retry"),
1917
+ value: "—",
1918
+ detail: tr("fluidgrids.insights.retryBaselineMissing", "Retry recovery baseline is not exposed by the service yet."),
1919
+ tone: "text-text-secondary"
1920
+ })
1921
+ ]
1922
+ }),
1923
+ errorPanel,
1924
+ /* @__PURE__ */ jsx("section", { children: /* @__PURE__ */ jsxs("div", {
1645
1925
  className: "rounded-xl border border-border-secondary bg-background-secondary p-5",
1646
1926
  children: [/* @__PURE__ */ jsxs("div", {
1647
1927
  className: "mb-4 flex items-center justify-between gap-3",
@@ -1692,8 +1972,8 @@ function ErrorContent({ summary, failedRuns, failureBreakdown, commonError, retr
1692
1972
  ]
1693
1973
  }, run.id))]
1694
1974
  })]
1695
- })]
1696
- })]
1975
+ }) })
1976
+ ]
1697
1977
  });
1698
1978
  }
1699
1979
  function ErrorAnalyticsPage() {
@@ -1,14 +1,14 @@
1
1
  "use client";
2
- import { Pi as throwIfResultError, Q as DurableHistoryCapsDocument, Qn as UpdateManagedAiWorkspacePolicyDocument, Ri as getFluidGridsConfig, Zn as UpdateDurableHistoryCapsDocument, ji as describeOperationError, xt as ManagedAiWorkspacePolicyDocument, yi as getFluidGridsClient } from "./node-endpoint-configs-DXCKkK_9.js";
3
- import { In as FLUIDGRIDS_FLAGS, Kt as findSaveConflict, Un as useDurableParityEnabled, Wn as useFluidGridsFlag, or as getGlobalStoreClient, qn as usePhaseCFlags, wt as useSaveStatusStore } from "./FluidGridsProvider-CraUhM4E.js";
2
+ import { $n as UpdateManagedAiWorkspacePolicyDocument, Fi as throwIfResultError, Mi as describeOperationError, Q as DurableHistoryCapsDocument, Qn as UpdateDurableHistoryCapsDocument, St as ManagedAiWorkspacePolicyDocument, bi as getFluidGridsClient, zi as getFluidGridsConfig } from "./node-endpoint-configs-BgZARXHI.js";
3
+ import { In as FLUIDGRIDS_FLAGS, Kt as findSaveConflict, Un as useDurableParityEnabled, Wn as useFluidGridsFlag, or as getGlobalStoreClient, qn as usePhaseCFlags, wt as useSaveStatusStore } from "./FluidGridsProvider-Bve22Hxu.js";
4
4
  import { H as useFlowStore } from "./node-operation-selection-61d6U9qo.js";
5
5
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
6
- import { Wt as useWorkflowDefinitionQuery, a as useConnections, n as useAgentDefinitions, qt as useWorkflowDefinitionsQuery, zt as useUpdateWorkflowDefinitionMutation } from "./useAgentDefinitions-Czl2aHJb.js";
6
+ import { Wt as useWorkflowDefinitionQuery, a as useConnections, n as useAgentDefinitions, qt as useWorkflowDefinitionsQuery, zt as useUpdateWorkflowDefinitionMutation } from "./useAgentDefinitions-BKimckKY.js";
7
7
  import { LF as WorkflowSearchAttributeType, fI as useFluidGridsPermission, oI as FLUIDGRIDS_PERMISSIONS } from "./graphql-types-CulUbQWN.js";
8
8
  import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-iRiufGc2.js";
9
- import { C as createSearchAttribute, E as deleteSearchAttribute, J as saveArchiveSettings, N as fetchCodecServerSettings, P as fetchPauseRules, R as fetchSearchAttributes, S as createPauseRule, T as deletePauseRule, Y as saveCodecServerSettings, _ as useResource, a as formToInput$2, b as clearArchiveSettings, c as FieldError, d as NativeSelect, i as emptyAgentForm, k as fetchArchiveSettings, n as agentToForm, o as grantDays, p as StatusPill, r as describeRule, t as AgentFormError } from "./agent-form-Ci_vxQF5.js";
10
- import { c as budgetInputValue, d as withBudgetMode, f as EffectBadge, m as useActionPolicies, n as checkCodecServerUrl, p as effectLabel, s as BUDGET_DIMENSIONS, u as withBudgetLimit } from "./codec-client-Cm4GXmJ9.js";
11
- import { a as useLogStreamDestinations, i as useLogStreamDestinationActions } from "./useObservability-D402nqXD.js";
9
+ import { C as createSearchAttribute, E as deleteSearchAttribute, J as saveArchiveSettings, N as fetchCodecServerSettings, P as fetchPauseRules, R as fetchSearchAttributes, S as createPauseRule, T as deletePauseRule, Y as saveCodecServerSettings, _ as useResource, a as formToInput$2, b as clearArchiveSettings, c as FieldError, d as NativeSelect, i as emptyAgentForm, k as fetchArchiveSettings, n as agentToForm, o as grantDays, p as StatusPill, r as describeRule, t as AgentFormError } from "./agent-form-m8tkBULw.js";
10
+ import { c as budgetInputValue, d as withBudgetMode, f as EffectBadge, m as useActionPolicies, n as checkCodecServerUrl, p as effectLabel, s as BUDGET_DIMENSIONS, u as withBudgetLimit } from "./codec-client-aN37SXBf.js";
11
+ import { a as useLogStreamDestinations, i as useLogStreamDestinationActions } from "./useObservability-cCsmALjS.js";
12
12
  import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
13
13
  import { useNavigate, useParams } from "react-router";
14
14
  import { Icon } from "@iconify/react";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { A as DialogTitle, D as DialogHeader, E as DialogFooter, S as Dialog, T as DialogDescription, b as Badge, w as DialogContent } from "./flow-builder-sG8ZsMYV.js";
3
- import { i as Button } from "./PublishCustomNodeAction-C6qkAIjG.js";
2
+ import { A as DialogTitle, D as DialogHeader, E as DialogFooter, S as Dialog, T as DialogDescription, b as Badge, w as DialogContent } from "./flow-builder-CmJi6XWS.js";
3
+ import { i as Button } from "./PublishCustomNodeAction-CtRHgitG.js";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { AlertTriangle, CheckCircle2, Download, ExternalLink, Loader2, Puzzle, ShoppingCart } from "lucide-react";
6
6
 
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { Ct as NodeEndpointConfigDocument, Tt as NodeManifestDocument, t as fetchAllNodeEndpointConfigs, wt as NodeEndpointConfigsDocument, yi as getFluidGridsClient } from "./node-endpoint-configs-DXCKkK_9.js";
2
+ import { Et as NodeManifestDocument, Tt as NodeEndpointConfigsDocument, bi as getFluidGridsClient, t as fetchAllNodeEndpointConfigs, wt as NodeEndpointConfigDocument } from "./node-endpoint-configs-BgZARXHI.js";
3
3
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
4
- import { t as PublishCustomNodeAction } from "./PublishCustomNodeAction-C6qkAIjG.js";
4
+ import { t as PublishCustomNodeAction } from "./PublishCustomNodeAction-CtRHgitG.js";
5
5
  import { useCallback, useEffect, useMemo, useState } from "react";
6
6
  import { useNavigate } from "react-router";
7
7
  import { Icon } from "@iconify/react";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { Ri as getFluidGridsConfig } from "./node-endpoint-configs-DXCKkK_9.js";
2
+ import { zi as getFluidGridsConfig } from "./node-endpoint-configs-BgZARXHI.js";
3
3
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
4
4
  import { t as cn } from "./cn-QqidFIgr.js";
5
5
  import "react";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { A as DialogTitle, D as DialogHeader, E as DialogFooter, S as Dialog, T as DialogDescription, b as Badge, ht as Input, w as DialogContent } from "./flow-builder-sG8ZsMYV.js";
3
- import { i as Button } from "./PublishCustomNodeAction-C6qkAIjG.js";
2
+ import { A as DialogTitle, D as DialogHeader, E as DialogFooter, S as Dialog, T as DialogDescription, b as Badge, ht as Input, w as DialogContent } from "./flow-builder-CmJi6XWS.js";
3
+ import { i as Button } from "./PublishCustomNodeAction-CtRHgitG.js";
4
4
  import { t as Label } from "./label-CDy86rIZ.js";
5
5
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
6
6
  import { useEffect, useMemo, useState } from "react";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { i as Button } from "./PublishCustomNodeAction-C6qkAIjG.js";
3
- import { b as Badge, y as templatePreview } from "./flow-builder-sG8ZsMYV.js";
2
+ import { i as Button } from "./PublishCustomNodeAction-CtRHgitG.js";
3
+ import { b as Badge, y as templatePreview } from "./flow-builder-CmJi6XWS.js";
4
4
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
5
5
  import { lI as SdkPermissionButton, oI as FLUIDGRIDS_PERMISSIONS } from "./graphql-types-CulUbQWN.js";
6
6
  import { Icon } from "@iconify/react";
@@ -1,10 +1,10 @@
1
1
  "use client";
2
- import { Pi as throwIfResultError, Ri as getFluidGridsConfig, ji as describeOperationError, yi as getFluidGridsClient } from "./node-endpoint-configs-DXCKkK_9.js";
3
- import { C as MyWorkflowTemplateSubmissionsDocument, O as WithdrawWorkflowTemplateSubmissionDocument, S as InstallWorkflowNodeDocument, T as SubmitWorkflowTemplateDocument, fn as emitTemplateUsed, mn as emitWorkflowCreated, on as useFluidGridsAnalytics, t as FluidGridsContext, wn as isQuotaExhaustedFailure, yn as BILLING_PLANS_PATH } from "./FluidGridsProvider-CraUhM4E.js";
2
+ import { Fi as throwIfResultError, Mi as describeOperationError, bi as getFluidGridsClient, zi as getFluidGridsConfig } from "./node-endpoint-configs-BgZARXHI.js";
3
+ import { C as MyWorkflowTemplateSubmissionsDocument, O as WithdrawWorkflowTemplateSubmissionDocument, S as InstallWorkflowNodeDocument, T as SubmitWorkflowTemplateDocument, fn as emitTemplateUsed, mn as emitWorkflowCreated, on as useFluidGridsAnalytics, t as FluidGridsContext, wn as isQuotaExhaustedFailure, yn as BILLING_PLANS_PATH } from "./FluidGridsProvider-Bve22Hxu.js";
4
4
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
5
- import { K as useGlobalStoreClient, N as useWorkflowTemplates, P as useInstallNode, t as FlowBuilderPage, v as TemplateCard } from "./flow-builder-sG8ZsMYV.js";
6
- import { h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, s as useDuplicateWorkflow } from "./useWorkflows-UyKrrkX-.js";
7
- import { k as QuotaExhaustedDialog } from "./WorkflowShareDialog-DiD8Gqim.js";
5
+ import { K as useGlobalStoreClient, N as useWorkflowTemplates, P as useInstallNode, t as FlowBuilderPage, v as TemplateCard } from "./flow-builder-CmJi6XWS.js";
6
+ import { h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, s as useDuplicateWorkflow } from "./useWorkflows-CQbVEHc0.js";
7
+ import { k as QuotaExhaustedDialog } from "./WorkflowShareDialog-BONVJpp_.js";
8
8
  import { BF as WorkflowStatus, lI as SdkPermissionButton, oI as FLUIDGRIDS_PERMISSIONS } from "./graphql-types-CulUbQWN.js";
9
9
  import { n as useFluidGridsPageControls } from "./pageControlsBridge-0pX9s-3k.js";
10
10
  import { r as templatesControls } from "./pageControlSpecs-DZJ9K37m.js";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
3
- import { Pi as throwIfResultError, ji as describeOperationError, ui as WorkflowVersionDiffDocument, yi as getFluidGridsClient, yr as WorkflowDefinitionDocument } from "./node-endpoint-configs-DXCKkK_9.js";
3
+ import { Fi as throwIfResultError, Mi as describeOperationError, bi as getFluidGridsClient, br as WorkflowDefinitionDocument, di as WorkflowVersionDiffDocument } from "./node-endpoint-configs-BgZARXHI.js";
4
4
  import { t as canvasFromDefinition } from "./definition-canvas-D9cWIGEM.js";
5
5
  import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { Background, Controls, Handle, MiniMap, Position, ReactFlow, ReactFlowProvider } from "@xyflow/react";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { Fr as WorkflowProposalDocument, L as DataTablesTagsDocument, Mi as isForbiddenError, N as CreateWorkflowTestCaseDocument, Nn as TagFluidgridsEntityDocument, P as CreateWorkflowTestCaseFromRunDocument, Pi as throwIfResultError, Ri as getFluidGridsConfig, Rt as ProposeRunFixDocument, T as CreateFluidgridsTagDocument, Wt as RejectWorkflowProposalDocument, Yt as ReplaceFluidgridsEntityTagsDocument, _n as RunWorkflowTestsDocument, ai as WorkflowTestCasesDocument, bn as SearchFluidgridsTagsDocument, ci as WorkflowTestRunsDocument, l as AvailableFluidgridsTagsDocument, mt as FluidgridsEntityTagsDocument, o as ApplyWorkflowProposalDocument, oi as WorkflowTestRunDocument, q as DeleteWorkflowTestCaseDocument, qn as UntagFluidgridsEntityDocument, rr as UpdateWorkflowTestCaseDocument, y as CancelWorkflowProposalDocument, yi as getFluidGridsClient, zt as ProposeWorkflowChangeDocument } from "./node-endpoint-configs-DXCKkK_9.js";
2
+ import { Bt as ProposeWorkflowChangeDocument, Fi as throwIfResultError, Gt as RejectWorkflowProposalDocument, Ir as WorkflowProposalDocument, Jn as UntagFluidgridsEntityDocument, L as DataTablesTagsDocument, N as CreateWorkflowTestCaseDocument, Ni as isForbiddenError, P as CreateWorkflowTestCaseFromRunDocument, Pn as TagFluidgridsEntityDocument, T as CreateFluidgridsTagDocument, Xt as ReplaceFluidgridsEntityTagsDocument, bi as getFluidGridsClient, ht as FluidgridsEntityTagsDocument, ir as UpdateWorkflowTestCaseDocument, l as AvailableFluidgridsTagsDocument, li as WorkflowTestRunsDocument, o as ApplyWorkflowProposalDocument, oi as WorkflowTestCasesDocument, q as DeleteWorkflowTestCaseDocument, si as WorkflowTestRunDocument, vn as RunWorkflowTestsDocument, xn as SearchFluidgridsTagsDocument, y as CancelWorkflowProposalDocument, zi as getFluidGridsConfig, zt as ProposeRunFixDocument } from "./node-endpoint-configs-BgZARXHI.js";
3
3
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
4
4
  import { GF as WorkflowTestRunStatus, HF as WorkflowTestAssertionOperator, Qu as ErrorType, UF as WorkflowTestExpectedStatus, WF as WorkflowTestRunSource } from "./graphql-types-CulUbQWN.js";
5
5
  import { a as notifyFluidGridsAiCreditsUpdated } from "./aiCreditsBridge-BuE92tKo.js";