@burdenoff/fluidgrids-fe-sdk 2026.1110.18 → 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-DvL6eNdl.js → ExecutionDetailPage-BLQ9mPPO.js} +308 -43
  2. package/dist/{FailureTriagePanel-D5zBlA9e.js → FailureTriagePanel-DquVHzGD.js} +97 -3
  3. package/dist/{FluidGridsProvider-BafQs01c.js → FluidGridsProvider-Bve22Hxu.js} +1 -1
  4. package/dist/{HistoryPage-DyjBx_WI.js → HistoryPage-CCVLBD8a.js} +3 -3
  5. package/dist/{InsightsPage-CZDkFsba.js → InsightsPage-BCRRKaja.js} +352 -72
  6. package/dist/{ManagedAiPolicyAuthority-BcYnrH6v.js → ManagedAiPolicyAuthority-PhyUARha.js} +6 -6
  7. package/dist/{MissingNodesInstallModal-Batt34qR.js → MissingNodesInstallModal-CkbBf648.js} +2 -2
  8. package/dist/{NodesPage-B9ZeoaQZ.js → NodesPage-XglgbnFQ.js} +2 -2
  9. package/dist/{PublishCustomNodeAction-0xEFoBxJ.js → PublishCustomNodeAction-CtRHgitG.js} +1 -1
  10. package/dist/{TemplateConfigurationModal-CG4yDNkw.js → TemplateConfigurationModal-DPe69XFz.js} +2 -2
  11. package/dist/{TemplateDetailPanel-CQYS4JH1.js → TemplateDetailPanel-ahqcAMmr.js} +2 -2
  12. package/dist/{TemplatesPage-CQr-9jvt.js → TemplatesPage-CRIn51Qa.js} +5 -5
  13. package/dist/{VersionDiffDialog-CG1tfcfU.js → VersionDiffDialog-BejQlKec.js} +1 -1
  14. package/dist/{WorkflowProposalCard-CrKxIjtm.js → WorkflowProposalCard-aoR_tT2f.js} +1 -1
  15. package/dist/{WorkflowSearchRedirect-CN8lZ5u3.js → WorkflowSearchRedirect-5x2HX5tx.js} +10 -10
  16. package/dist/{WorkflowShareDialog-CGWKqXo7.js → WorkflowShareDialog-BONVJpp_.js} +2 -2
  17. package/dist/{WorkflowsList-BQF52YzE.js → WorkflowsList-CDPqtaa3.js} +5 -5
  18. package/dist/{agent-form-BODEyu51.js → agent-form-m8tkBULw.js} +1 -1
  19. package/dist/{agentTools-DKr8aY56.js → agentTools-DxuakWxT.js} +2 -2
  20. package/dist/{codec-client-DnA0YvMv.js → codec-client-aN37SXBf.js} +1 -1
  21. package/dist/executions.js +1 -1
  22. package/dist/{flow-builder-B1lYLhaZ.js → flow-builder-CmJi6XWS.js} +22 -22
  23. package/dist/history.js +1 -1
  24. package/dist/{index-jasafG72.d.ts → index-CpEB91Ys.d.ts} +73 -1
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +24 -24
  27. package/dist/{node-detail-view-Bdx_RBP0.js → node-detail-view-CAUbejnM.js} +6 -6
  28. package/dist/{node-endpoint-configs-BTQbqjEI.js → node-endpoint-configs-BgZARXHI.js} +577 -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-DzcqZ44_.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-BNTXO1c-.js → useAgentDefinitions-BKimckKY.js} +1 -1
  36. package/dist/{useExecutions-DYcTJTZ7.js → useExecutions-BIrUuMlR.js} +3 -2
  37. package/dist/{useObservability-elkf_jwE.js → useObservability-cCsmALjS.js} +2 -2
  38. package/dist/{useRunHistory-DfIj1Akd.js → useRunHistory-DG0Nfolg.js} +2 -2
  39. package/dist/{useWorkflows-CwYurzxn.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,20 +1,20 @@
1
1
  "use client";
2
2
  import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
3
- import { $ as DurableParityRunFieldsDocument, $n as UpdateTaskQueueDocument, Ai as describeOperationError, B as DeleteTaskQueueDocument, Cn as SetWorkerTokenConnectionAllowlistDocument, D as CreateWorkerTokenDocument, E as CreateTaskQueueDocument, Hr as WorkflowRunMetadataDocument, Ji as useExecutionsStore, Kr as WorkflowRunsCountDocument, Li as getFluidGridsConfig, Ln as TaskQueueStatsDocument, Ni as throwIfResultError, Rn as TaskQueuesDocument, Tn as SetWorkflowRunVersioningOverrideDocument, Ur as WorkflowRunPendingDocument, V as DeleteWorkerTokenDocument, an as RotateWorkerTokenDocument, gn as RunLogsDocument, mn as RunLogAppendedDocument, mr as WorkflowBatchOperationUpdatedDocument, on as RunAiUsageDocument, pi as WorkflowWorkersDocument, sr as WorkerTokensDocument, st as ExplainRunDocument, vi as getFluidGridsClient, yi as getFluidGridsClientSafe } from "./node-endpoint-configs-BTQbqjEI.js";
4
- import { $t as runDurationMs, Hn as useDurableFunctionNodesEnabled, Pn as runSignalTargets, Qt as nodeStateDurationMs, Un as useDurableParityEnabled, Yn as useWorkflowTestsEnabled, Zt as formatElapsedMs, jn as durableInterfaceOf, kn as canSignalRun, qn as usePhaseCFlags } from "./FluidGridsProvider-BafQs01c.js";
3
+ import { $ as DurableParityRunFieldsDocument, B as DeleteTaskQueueDocument, D as CreateWorkerTokenDocument, E as CreateTaskQueueDocument, En as SetWorkflowRunVersioningOverrideDocument, Fi as throwIfResultError, Gr as WorkflowRunPendingDocument, Jr as WorkflowRunsCountDocument, Mi as describeOperationError, Rn as TaskQueueStatsDocument, V as DeleteWorkerTokenDocument, Vr as WorkflowRunHierarchyDocument, Wr as WorkflowRunMetadataDocument, Xi as DEFAULT_EXECUTIONS_FILTER, Zi as useExecutionsStore, _n as RunLogsDocument, bi as getFluidGridsClient, cr as WorkerTokensDocument, ct as ExplainRunDocument, er as UpdateTaskQueueDocument, hi as WorkflowWorkersDocument, hn as RunLogAppendedDocument, hr as WorkflowBatchOperationUpdatedDocument, on as RotateWorkerTokenDocument, sn as RunAiUsageDocument, wn as SetWorkerTokenConnectionAllowlistDocument, xi as getFluidGridsClientSafe, zi as getFluidGridsConfig, zn as TaskQueuesDocument } from "./node-endpoint-configs-BgZARXHI.js";
4
+ import { $t as runDurationMs, Hn as useDurableFunctionNodesEnabled, Pn as runSignalTargets, Qt as nodeStateDurationMs, Un as useDurableParityEnabled, Yn as useWorkflowTestsEnabled, Zt as formatElapsedMs, jn as durableInterfaceOf, kn as canSignalRun, qn as usePhaseCFlags } from "./FluidGridsProvider-Bve22Hxu.js";
5
5
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
6
- import { h as useWorkflowDefinitions, v as useWorkflowVersions } from "./useWorkflows-CwYurzxn.js";
6
+ import { h as useWorkflowDefinitions, v as useWorkflowVersions } from "./useWorkflows-CQbVEHc0.js";
7
7
  import { KF as WorkflowUpdateWaitFor, OF as WorkflowQueryRejectCondition, Qu as ErrorType, dF as WorkflowBatchOperationType, fI as useFluidGridsPermission, kF as WorkflowResetType, lI as SdkPermissionButton, oI as FLUIDGRIDS_PERMISSIONS, pP as VersioningBehavior } from "./graphql-types-CulUbQWN.js";
8
- import { _ as statusCountFilter, c as OPERATORS_BY_TYPE, d as STATUS_COUNT_GROUP_BY, f as callbackTone, g as shortRunId, h as runChainLinks, i as useExecutionStats, l as buildSearchAttributeFilter, m as parseMetadataDefinition, n as useExecution, o as useExecutionsWithStore, p as overrideRequestOf, r as useExecutionActions, s as EMPTY_SEARCH_FILTER, t as useAutoRefresh, u as searchFilterConflicts, v as statusCountsOf, y as validateDateRange } from "./useExecutions-DYcTJTZ7.js";
8
+ import { _ as statusCountFilter, c as OPERATORS_BY_TYPE, d as STATUS_COUNT_GROUP_BY, f as callbackTone, g as shortRunId, h as runChainLinks, i as useExecutionStats, l as buildSearchAttributeFilter, m as parseMetadataDefinition, n as useExecution, o as useExecutionsWithStore, p as overrideRequestOf, r as useExecutionActions, s as EMPTY_SEARCH_FILTER, t as useAutoRefresh, u as searchFilterConflicts, v as statusCountsOf, y as validateDateRange } from "./useExecutions-BIrUuMlR.js";
9
9
  import { n as useFluidGridsPageControls } from "./pageControlsBridge-0pX9s-3k.js";
10
10
  import { t as executionsControls } from "./pageControlSpecs-DZJ9K37m.js";
11
11
  import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-iRiufGc2.js";
12
- import { $ as startBatchTerminate, A as fetchBatchOperation, B as jsonArg, F as fetchRunControlFields, G as resetRun, I as fetchRunHistoryArchive, K as resetRunToLastCleanTask, L as fetchRunUpdate, N as fetchCodecServerSettings, O as failActivityById, P as fetchPauseRules, Q as startBatchOperation, R as fetchSearchAttributes, U as queryRun, V as pauseActivities, W as resetActivities, X as sendRunUpdate, Z as startBatchExport, _ as useResource, at as readTyped, c as FieldError, d as NativeSelect, f as RUN_CONTROL_DIALOG_STYLE, g as parseJsonObjectInput, h as parseJsonInput, it as upsertRunSearchAttributes, j as fetchBatchOperations, l as JsonBlock, m as newRunControlId, ot as writeTyped, p as StatusPill, q as revokeSignalToken, rt as updateActivityOptions, s as isAgentNodeType, tt as unpauseActivities, u as JsonField, w as createSignalToken, x as completeActivityById, y as cancelBatchOperation, z as fetchSignalTokens } from "./agent-form-BODEyu51.js";
13
- import { C as useAvailableTags, _ as buildNodeDisplayMap, b as EntityTagPicker, n as useWorkflowProposal, o as canSaveRunAsTestCase, r as saveRunAsTestCase, t as WorkflowProposalCard, v as formatRunVersion, y as nodeDisplayTitle } from "./WorkflowProposalCard-CrKxIjtm.js";
12
+ import { $ as startBatchTerminate, A as fetchBatchOperation, B as jsonArg, F as fetchRunControlFields, G as resetRun, I as fetchRunHistoryArchive, K as resetRunToLastCleanTask, L as fetchRunUpdate, N as fetchCodecServerSettings, O as failActivityById, P as fetchPauseRules, Q as startBatchOperation, R as fetchSearchAttributes, U as queryRun, V as pauseActivities, W as resetActivities, X as sendRunUpdate, Z as startBatchExport, _ as useResource, at as readTyped, c as FieldError, d as NativeSelect, f as RUN_CONTROL_DIALOG_STYLE, g as parseJsonObjectInput, h as parseJsonInput, it as upsertRunSearchAttributes, j as fetchBatchOperations, l as JsonBlock, m as newRunControlId, ot as writeTyped, p as StatusPill, q as revokeSignalToken, rt as updateActivityOptions, s as isAgentNodeType, tt as unpauseActivities, u as JsonField, w as createSignalToken, x as completeActivityById, y as cancelBatchOperation, z as fetchSignalTokens } from "./agent-form-m8tkBULw.js";
13
+ import { C as useAvailableTags, _ as buildNodeDisplayMap, b as EntityTagPicker, n as useWorkflowProposal, o as canSaveRunAsTestCase, r as saveRunAsTestCase, t as WorkflowProposalCard, v as formatRunVersion, y as nodeDisplayTitle } from "./WorkflowProposalCard-aoR_tT2f.js";
14
14
  import { t as AiCreditBalanceSlot } from "./aiCreditsBridge-BuE92tKo.js";
15
- import { a as encodedPayloadBytes, f as EffectBadge, h as useRunPolicyDecisions, i as decodePayloads, l as formatBudgetUsd, n as checkCodecServerUrl, o as isEncodedPayload, r as containsEncodedPayload, t as CodecServerError } from "./codec-client-DnA0YvMv.js";
16
- import { a as fetchRunFailureClusters, i as dismissRunFailureCluster, r as OPEN_STATUSES, t as BUCKET_LABELS } from "./FailureTriagePanel-D5zBlA9e.js";
17
- import { a as useDurableRunFields, i as useDeterminismStatus, n as SignalRunDialog, o as useRunStackTrace, r as terminateDurableRun, s as RunHistoryView, t as useRunHistory } from "./useRunHistory-DfIj1Akd.js";
15
+ import { a as fetchRunFailureClusters, i as dismissRunFailureCluster, o as runListFilterFromSearch, r as OPEN_STATUSES, s as runListLinkKey, t as BUCKET_LABELS } from "./FailureTriagePanel-DquVHzGD.js";
16
+ import { a as encodedPayloadBytes, f as EffectBadge, h as useRunPolicyDecisions, i as decodePayloads, l as formatBudgetUsd, n as checkCodecServerUrl, o as isEncodedPayload, r as containsEncodedPayload, t as CodecServerError } from "./codec-client-aN37SXBf.js";
17
+ import { a as useDurableRunFields, i as useDeterminismStatus, n as SignalRunDialog, o as useRunStackTrace, r as terminateDurableRun, s as RunHistoryView, t as useRunHistory } from "./useRunHistory-DG0Nfolg.js";
18
18
  import { a as formatTokens, o as modelLabel, r as aiCost } from "./ai-usage-CK61EZWc.js";
19
19
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
20
20
  import { Link, useNavigate, useParams, useSearchParams } from "react-router";
@@ -239,6 +239,7 @@ function countActiveFilters(filter, parityEnabled) {
239
239
  filter.durationMaxSeconds !== null,
240
240
  filter.errorType !== "all",
241
241
  filter.nodeId !== "",
242
+ filter.failedNodeType !== "",
242
243
  filter.tagId !== "",
243
244
  parityEnabled && filter.workflowId.trim() !== ""
244
245
  ].filter(Boolean).length;
@@ -280,6 +281,36 @@ function TagFilterSelect({ value, onChange, className }) {
280
281
  }
281
282
 
282
283
  // src/modules/executions/components/ExecutionFilters.tsx
284
+ /**
285
+ * An error type set by a link (Insights, BOFF-9974) that the dropdown offers
286
+ * no option for, so it still shows as selected.
287
+ */
288
+ function LinkedErrorTypeOption({ errorType, offered }) {
289
+ if (errorType === "all" || offered.some(({ value }) => value === errorType)) return null;
290
+ return /* @__PURE__ */ jsx("option", {
291
+ value: errorType,
292
+ children: errorType
293
+ });
294
+ }
295
+ /** The failed-node-type filter (BOFF-9974), set only by links, with its clear button. */
296
+ function FailedNodeTypeChip({ nodeType, onClear }) {
297
+ const tr = useTr();
298
+ if (!nodeType) return null;
299
+ return /* @__PURE__ */ jsxs("span", {
300
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary",
301
+ "data-testid": "runs-failed-node-type-filter",
302
+ children: [tr("fluidgrids.executions.executionFilters.failedNodeType", "Failed node: {{nodeType}}", { nodeType }), /* @__PURE__ */ jsx("button", {
303
+ type: "button",
304
+ onClick: onClear,
305
+ "aria-label": tr("fluidgrids.executions.executionFilters.clearFailedNodeType", "Remove the failed node filter"),
306
+ className: "text-text-secondary hover:text-text-primary",
307
+ children: /* @__PURE__ */ jsx(Icon, {
308
+ icon: "mdi:close",
309
+ width: 14
310
+ })
311
+ })]
312
+ });
313
+ }
283
314
  function ExecutionFilters({ workflows = [], onRefresh }) {
284
315
  const tr = useTr();
285
316
  const statusOptions = useMemo(() => [
@@ -376,8 +407,8 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
376
407
  label: tr("fluidgrids.executions.executionFilters.dateCustomRange", "Custom Range")
377
408
  }
378
409
  ];
379
- const { filter, setStatusFilter, setWorkflowFilter, setDateRange, setSearchQuery, setTriggerTypeFilter, setDurationFilter, setErrorTypeFilter, setNodeFilter, setTagFilter, resetFilters, autoRefresh, setAutoRefresh } = useExecutionsStore();
380
- const [showCustomDate, setShowCustomDate] = useState(false);
410
+ const { filter, setStatusFilter, setWorkflowFilter, setDateRange, setSearchQuery, setTriggerTypeFilter, setDurationFilter, setErrorTypeFilter, setNodeFilter, setFailedNodeTypeFilter, setTagFilter, resetFilters, autoRefresh, setAutoRefresh } = useExecutionsStore();
411
+ const [showCustomDate, setShowCustomDate] = useState(() => filter.dateRange.preset === "custom");
381
412
  const handleDatePresetChange = useCallback((preset) => {
382
413
  const now = /* @__PURE__ */ new Date();
383
414
  let start = null;
@@ -558,13 +589,24 @@ function ExecutionFilters({ workflows = [], onRefresh }) {
558
589
  value: filter.errorType,
559
590
  onChange: (e) => setErrorTypeFilter(e.target.value),
560
591
  className: "px-3 py-2 bg-bg-surface border border-border-default rounded-lg text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg scheme-normal dark:scheme-dark",
561
- children: [/* @__PURE__ */ jsx("option", {
562
- value: "all",
563
- children: tr("fluidgrids.executions.executionFilters.allErrors", "All error types")
564
- }), errorOptions.map(({ value, label }) => /* @__PURE__ */ jsx("option", {
565
- value,
566
- children: label
567
- }, value))]
592
+ children: [
593
+ /* @__PURE__ */ jsx("option", {
594
+ value: "all",
595
+ children: tr("fluidgrids.executions.executionFilters.allErrors", "All error types")
596
+ }),
597
+ errorOptions.map(({ value, label }) => /* @__PURE__ */ jsx("option", {
598
+ value,
599
+ children: label
600
+ }, value)),
601
+ /* @__PURE__ */ jsx(LinkedErrorTypeOption, {
602
+ errorType: filter.errorType,
603
+ offered: errorOptions
604
+ })
605
+ ]
606
+ }),
607
+ /* @__PURE__ */ jsx(FailedNodeTypeChip, {
608
+ nodeType: filter.failedNodeType,
609
+ onClear: () => setFailedNodeTypeFilter("")
568
610
  }),
569
611
  /* @__PURE__ */ jsx("input", {
570
612
  type: "text",
@@ -3577,10 +3619,21 @@ var ExecutionsListPage_exports = /* @__PURE__ */ __exportAll({ ExecutionsListPag
3577
3619
  function ExecutionsListPage() {
3578
3620
  const tr = useTr();
3579
3621
  const navigate = useNavigate();
3580
- const { viewMode, setViewMode, setSelectedExecution, selection, clearSelection, setStatusFilter, setWorkflowFilter, setWorkflowIdFilter, filter, autoRefresh, autoRefreshInterval } = useExecutionsStore();
3622
+ const { viewMode, setViewMode, setSelectedExecution, selection, clearSelection, setStatusFilter, setWorkflowFilter, setWorkflowIdFilter, updateFilter, filter, autoRefresh, autoRefreshInterval } = useExecutionsStore();
3581
3623
  const [searchParams] = useSearchParams();
3582
3624
  const workflowKeyParam = searchParams.get("workflowKey") ?? "";
3583
3625
  const lastWorkflowKeyParam = useRef(null);
3626
+ const linkKey = runListLinkKey(searchParams);
3627
+ const [appliedLinkKey, setAppliedLinkKey] = useState(null);
3628
+ if (appliedLinkKey !== linkKey) {
3629
+ setAppliedLinkKey(linkKey);
3630
+ const linked = runListFilterFromSearch(searchParams);
3631
+ if (linked) updateFilter({
3632
+ ...DEFAULT_EXECUTIONS_FILTER,
3633
+ ...linked,
3634
+ workflowKey: workflowKeyParam
3635
+ });
3636
+ }
3584
3637
  if (lastWorkflowKeyParam.current !== workflowKeyParam) {
3585
3638
  lastWorkflowKeyParam.current = workflowKeyParam;
3586
3639
  if (useExecutionsStore.getState().filter.workflowKey !== workflowKeyParam) setWorkflowFilter(workflowKeyParam);
@@ -4160,6 +4213,232 @@ function useRunLogs(runId, options = {}) {
4160
4213
  };
4161
4214
  }
4162
4215
 
4216
+ // src/modules/executions/utils/run-hierarchy.ts
4217
+ function labelOf(run) {
4218
+ const name = run.workflow?.name?.trim();
4219
+ return {
4220
+ id: run.id,
4221
+ name: name || run.workflowKey,
4222
+ status: run.status,
4223
+ createdAt: run.createdAt,
4224
+ startedAt: run.startedAt ?? null,
4225
+ completedAt: run.completedAt ?? null
4226
+ };
4227
+ }
4228
+ /**
4229
+ * The breadcrumb and child runs of `runId` in `hierarchy`. Null when there is
4230
+ * no tree, or the run is not in it (the service always keeps the requested run,
4231
+ * so that only happens for a tree read for another run).
4232
+ */
4233
+ function runHierarchyView(hierarchy, runId) {
4234
+ if (!hierarchy) return null;
4235
+ const runs = /* @__PURE__ */ new Map([[hierarchy.root.id, hierarchy.root]]);
4236
+ for (const entry of hierarchy.descendants) runs.set(entry.run.id, entry.run);
4237
+ const current = runs.get(runId);
4238
+ if (!current) return null;
4239
+ const ancestors = [];
4240
+ const visited = /* @__PURE__ */ new Set([runId]);
4241
+ let parentId = current.id === hierarchy.root.id ? null : current.parentRunId;
4242
+ while (parentId && !visited.has(parentId)) {
4243
+ const parent = runs.get(parentId);
4244
+ if (!parent) break;
4245
+ visited.add(parentId);
4246
+ ancestors.unshift(labelOf(parent));
4247
+ parentId = parent.id === hierarchy.root.id ? null : parent.parentRunId;
4248
+ }
4249
+ return {
4250
+ ancestors,
4251
+ children: hierarchy.descendants.filter((entry) => entry.run.parentRunId === runId).map((entry) => ({
4252
+ ...labelOf(entry.run),
4253
+ parentNodeId: entry.parentNodeId ?? null
4254
+ })),
4255
+ truncated: hierarchy.truncated
4256
+ };
4257
+ }
4258
+
4259
+ // src/modules/executions/hooks/useRunHierarchy.ts
4260
+ /**
4261
+ * useRunHierarchy — the call tree a run belongs to (`workflowRunHierarchy`,
4262
+ * BOFF-9974), for the run page's breadcrumb and "Child runs" list.
4263
+ *
4264
+ * A plain network read (never the Apollo cache). While `live` (the run can
4265
+ * still start sub-workflows) it is re-read every
4266
+ * {@link RUN_HIERARCHY_POLL_INTERVAL_MS}; a finished run's tree is read once.
4267
+ * A failed read leaves the page on its own parent link: the tree is extra
4268
+ * context, never a reason to show an error.
4269
+ */
4270
+ /** Re-read cadence while the run can still start child runs. */
4271
+ const RUN_HIERARCHY_POLL_INTERVAL_MS = 5e3;
4272
+ async function fetchRunHierarchy(runId) {
4273
+ const result = await getFluidGridsClient().query({
4274
+ query: WorkflowRunHierarchyDocument,
4275
+ variables: { runId },
4276
+ fetchPolicy: "network-only"
4277
+ });
4278
+ throwIfResultError(result);
4279
+ return result.data?.workflowRunHierarchy ?? null;
4280
+ }
4281
+ function useRunHierarchy(runId, { live }) {
4282
+ const [settled, setSettled] = useState(null);
4283
+ const request = useRef(0);
4284
+ const read = useCallback(async () => {
4285
+ if (!runId) return;
4286
+ const id = ++request.current;
4287
+ let view;
4288
+ try {
4289
+ view = runHierarchyView(await fetchRunHierarchy(runId), runId);
4290
+ } catch {
4291
+ view = void 0;
4292
+ }
4293
+ if (id !== request.current) return;
4294
+ setSettled((previous) => {
4295
+ const kept = previous?.runId === runId ? previous.view : null;
4296
+ return {
4297
+ runId,
4298
+ view: view === void 0 ? kept : view
4299
+ };
4300
+ });
4301
+ }, [runId]);
4302
+ useEffect(() => {
4303
+ read();
4304
+ }, [read]);
4305
+ useEffect(() => {
4306
+ if (!live) return;
4307
+ const timer = setInterval(() => void read(), RUN_HIERARCHY_POLL_INTERVAL_MS);
4308
+ return () => clearInterval(timer);
4309
+ }, [live, read]);
4310
+ return settled && settled.runId === runId ? settled.view : null;
4311
+ }
4312
+
4313
+ // src/modules/executions/components/RunHierarchy.tsx
4314
+ /**
4315
+ * Run detail: where the run sits in its call tree (BOFF-9974).
4316
+ *
4317
+ * `RunCallPath` is the breadcrumb above the run's title: the root run, every
4318
+ * run between it and this one, then this run, each linking to its run page.
4319
+ * `ChildRunsPanel` lists the runs this run started (Sub-workflow and AI Agent
4320
+ * workflow-tool calls), with the node that started each. Both render nothing
4321
+ * for a run that has neither a parent nor children.
4322
+ */
4323
+ const runPath = (runId) => `../runs/${encodeURIComponent(runId)}`;
4324
+ function RunCallPath({ view, parentRunId }) {
4325
+ const tr = useTr();
4326
+ const ancestors = view?.ancestors ?? [];
4327
+ if (ancestors.length === 0 && !parentRunId) return null;
4328
+ return /* @__PURE__ */ jsxs("nav", {
4329
+ className: "mb-3 flex flex-wrap items-center gap-x-2 gap-y-1 text-sm",
4330
+ "aria-label": tr("fluidgrids.executions.hierarchy.callPathLabel", "Call path"),
4331
+ "data-testid": "run-call-path",
4332
+ children: [
4333
+ /* @__PURE__ */ jsx(Icon, {
4334
+ icon: "mdi:sitemap",
4335
+ className: "text-chart-12",
4336
+ width: 16
4337
+ }),
4338
+ /* @__PURE__ */ jsx("span", {
4339
+ className: "text-text-secondary",
4340
+ children: tr("fluidgrids.executions.executionDetail.subWorkflowOf", "Sub-workflow of")
4341
+ }),
4342
+ ancestors.length > 0 ? /* @__PURE__ */ jsx("ol", {
4343
+ className: "flex min-w-0 flex-wrap items-center gap-x-1 gap-y-1",
4344
+ children: ancestors.map((run, index) => /* @__PURE__ */ jsxs("li", {
4345
+ className: "flex min-w-0 items-center gap-1",
4346
+ children: [index > 0 && /* @__PURE__ */ jsx(Icon, {
4347
+ icon: "mdi:chevron-right",
4348
+ className: "text-text-tertiary",
4349
+ width: 14,
4350
+ "aria-hidden": true
4351
+ }), /* @__PURE__ */ jsx(Link, {
4352
+ to: runPath(run.id),
4353
+ className: "max-w-[16rem] truncate font-medium text-chart-12 hover:underline",
4354
+ title: run.id,
4355
+ "data-testid": "run-call-path-link",
4356
+ children: run.name
4357
+ })]
4358
+ }, run.id))
4359
+ }) : parentRunId && /* @__PURE__ */ jsxs(Link, {
4360
+ to: runPath(parentRunId),
4361
+ className: "font-medium text-chart-12 hover:underline",
4362
+ "data-testid": "run-call-path-link",
4363
+ children: [
4364
+ tr("fluidgrids.executions.executionDetail.parentRunLinkPrefix", "Parent Run"),
4365
+ " ",
4366
+ parentRunId.slice(0, 12),
4367
+ "..."
4368
+ ]
4369
+ })
4370
+ ]
4371
+ });
4372
+ }
4373
+ function ChildRunsPanel({ view, nodeDisplay, formatDateTime }) {
4374
+ const tr = useTr();
4375
+ const children = view?.children ?? [];
4376
+ if (children.length === 0) return null;
4377
+ return /* @__PURE__ */ jsxs("section", {
4378
+ className: "mb-6 rounded-lg border border-border-secondary bg-background-secondary p-4",
4379
+ "aria-labelledby": "run-child-runs-heading",
4380
+ "data-testid": "run-child-runs",
4381
+ children: [
4382
+ /* @__PURE__ */ jsxs("div", {
4383
+ className: "flex items-center gap-2 text-sm font-medium text-text-primary",
4384
+ children: [
4385
+ /* @__PURE__ */ jsx(Icon, {
4386
+ icon: "mdi:source-branch",
4387
+ width: 18
4388
+ }),
4389
+ /* @__PURE__ */ jsx("h2", {
4390
+ id: "run-child-runs-heading",
4391
+ children: tr("fluidgrids.executions.hierarchy.childRunsTitle", "Child runs")
4392
+ }),
4393
+ /* @__PURE__ */ jsx("span", {
4394
+ className: "rounded-full bg-background-tertiary px-2 py-0.5 text-xs text-text-secondary",
4395
+ children: children.length.toLocaleString()
4396
+ })
4397
+ ]
4398
+ }),
4399
+ view?.truncated && /* @__PURE__ */ jsx("p", {
4400
+ className: "mt-2 text-xs text-text-secondary",
4401
+ children: tr("fluidgrids.executions.hierarchy.truncated", "This call tree has more runs than can be listed here, so some child runs may be missing.")
4402
+ }),
4403
+ /* @__PURE__ */ jsx("ul", {
4404
+ className: "mt-3 divide-y divide-border-secondary",
4405
+ children: children.map((child) => {
4406
+ const node = child.parentNodeId ? nodeDisplay[child.parentNodeId]?.label ?? child.parentNodeId : null;
4407
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Link, {
4408
+ to: runPath(child.id),
4409
+ className: "flex flex-col gap-1 py-2 hover:bg-background-tertiary sm:flex-row sm:items-center sm:gap-3",
4410
+ "data-testid": "run-child-run",
4411
+ children: [
4412
+ /* @__PURE__ */ jsx(ExecutionStatusBadge, {
4413
+ status: child.status,
4414
+ size: "sm"
4415
+ }),
4416
+ /* @__PURE__ */ jsxs("span", {
4417
+ className: "min-w-0 flex-1",
4418
+ children: [/* @__PURE__ */ jsx("span", {
4419
+ className: "block truncate text-sm font-medium text-text-link",
4420
+ children: child.name
4421
+ }), node && /* @__PURE__ */ jsx("span", {
4422
+ className: "block truncate text-xs text-text-secondary",
4423
+ children: tr("fluidgrids.executions.hierarchy.startedByNode", "Started by {{node}}", { node })
4424
+ })]
4425
+ }),
4426
+ /* @__PURE__ */ jsx("span", {
4427
+ className: "text-xs text-text-secondary",
4428
+ children: formatDateTime(child.startedAt ?? child.createdAt)
4429
+ }),
4430
+ /* @__PURE__ */ jsx("span", {
4431
+ className: "w-16 text-xs text-text-secondary sm:text-right",
4432
+ children: formatElapsedMs(runDurationMs(child))
4433
+ })
4434
+ ]
4435
+ }) }, child.id);
4436
+ })
4437
+ })
4438
+ ]
4439
+ });
4440
+ }
4441
+
4163
4442
  // src/modules/human-response/utils/recipient.ts
4164
4443
  /**
4165
4444
  * Who an ask went to, for display (BOFF-7651). An in-app ask stores its responders as user ids
@@ -8795,6 +9074,7 @@ function ExecutionDetailPage() {
8795
9074
  useAutoRefresh(useCallback(() => {
8796
9075
  refetch();
8797
9076
  }, [refetch]), autoRefreshEnabled && isActive, 2e3);
9077
+ const hierarchy = useRunHierarchy(runId, { live: isActive });
8798
9078
  const runLogs = useRunLogs(runId, {
8799
9079
  live: isActive,
8800
9080
  minLevel: minLogLevel
@@ -9040,29 +9320,9 @@ function ExecutionDetailPage() {
9040
9320
  tr("fluidgrids.executions.executionDetail.backToExecutions", "Back to Executions")
9041
9321
  ]
9042
9322
  }),
9043
- execution.parentRunId && /* @__PURE__ */ jsxs("div", {
9044
- className: "flex items-center gap-2 mb-3 text-sm",
9045
- children: [
9046
- /* @__PURE__ */ jsx(Icon, {
9047
- icon: "mdi:sitemap",
9048
- className: "text-chart-12",
9049
- width: 16
9050
- }),
9051
- /* @__PURE__ */ jsx("span", {
9052
- className: "text-text-secondary",
9053
- children: tr("fluidgrids.executions.executionDetail.subWorkflowOf", "Sub-workflow of")
9054
- }),
9055
- /* @__PURE__ */ jsxs(Link, {
9056
- to: `../runs/${execution.parentRunId}`,
9057
- className: "text-chart-12 hover:underline font-medium",
9058
- children: [
9059
- tr("fluidgrids.executions.executionDetail.parentRunLinkPrefix", "Parent Run"),
9060
- " ",
9061
- execution.parentRunId.slice(0, 12),
9062
- "..."
9063
- ]
9064
- })
9065
- ]
9323
+ /* @__PURE__ */ jsx(RunCallPath, {
9324
+ view: hierarchy,
9325
+ parentRunId: execution.parentRunId
9066
9326
  }),
9067
9327
  /* @__PURE__ */ jsxs("div", {
9068
9328
  className: "flex flex-col lg:flex-row lg:items-start lg:justify-between gap-4 mb-6",
@@ -9413,6 +9673,11 @@ function ExecutionDetailPage() {
9413
9673
  }),
9414
9674
  /* @__PURE__ */ jsx(RunDataPrunedNotice, { dataPrunedAt: execution.dataPrunedAt }),
9415
9675
  /* @__PURE__ */ jsx(RunBudgetPanel, { budget: execution.budget }),
9676
+ /* @__PURE__ */ jsx(ChildRunsPanel, {
9677
+ view: hierarchy,
9678
+ nodeDisplay,
9679
+ formatDateTime
9680
+ }),
9416
9681
  /* @__PURE__ */ jsx(RunHumanRequests, { requests: humanRequests }),
9417
9682
  /* @__PURE__ */ jsx(RunPolicyDecisions, {
9418
9683
  decisions: policyDecisions,
@@ -9697,7 +9962,7 @@ function ExecutionDetailPage() {
9697
9962
  className: "text-text-secondary",
9698
9963
  children: tr("fluidgrids.executions.executionDetail.parentRunRow", "Parent Run")
9699
9964
  }), /* @__PURE__ */ jsxs(Link, {
9700
- to: `/runs/${execution.parentRunId}`,
9965
+ to: `../runs/${execution.parentRunId}`,
9701
9966
  className: "text-text-link hover:text-text-linkHover hover:underline font-mono",
9702
9967
  children: [execution.parentRunId.slice(0, 12), "..."]
9703
9968
  })]
@@ -1,12 +1,106 @@
1
1
  "use client";
2
+ import { Cn as SetRunFailureTriageEnabledDocument, Fi as throwIfResultError, X as DismissRunFailureClusterDocument, bi as getFluidGridsClient, dn as RunFailureClustersDocument, fn as RunFailureTriageSettingsDocument, ft as FgTriageFailedRunsDocument } from "./node-endpoint-configs-BgZARXHI.js";
2
3
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
3
- import { Ni as throwIfResultError, Sn as SetRunFailureTriageEnabledDocument, X as DismissRunFailureClusterDocument, dn as RunFailureTriageSettingsDocument, dt as FgTriageFailedRunsDocument, un as RunFailureClustersDocument, vi as getFluidGridsClient } from "./node-endpoint-configs-BTQbqjEI.js";
4
- import { cD as RunFailureClusterStatus } from "./graphql-types-CulUbQWN.js";
4
+ import { Qu as ErrorType, cD as RunFailureClusterStatus } from "./graphql-types-CulUbQWN.js";
5
5
  import { useCallback, useEffect, useState } from "react";
6
6
  import { Icon } from "@iconify/react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { Button } from "@burdenoff/fe-libs/ui";
9
9
 
10
+ // src/modules/executions/utils/run-list-links.ts
11
+ /**
12
+ * Links into the Runs list that carry its filters in the query string
13
+ * (BOFF-9974), and the reading of them on the list.
14
+ *
15
+ * Insights' error panel links each failing node, error type, workflow and day
16
+ * to "the failed runs behind it". The two halves live together so a link and
17
+ * the filter it opens cannot drift apart.
18
+ *
19
+ * ../runs?status=FAILED&failedNodeType=internal%3Ahttp&from=…&to=…
20
+ *
21
+ * `from` / `to` are ISO instants (the list's custom date range); `workflowKey`
22
+ * is read by the list on its own, as it always was.
23
+ */
24
+ /** The filters a link may set; `workflowKey` stays with the list's own sync. */
25
+ const RUN_LIST_LINK_PARAMS = [
26
+ "status",
27
+ "errorType",
28
+ "failedNodeType",
29
+ "from",
30
+ "to"
31
+ ];
32
+ const RUN_STATUSES = [
33
+ "PENDING",
34
+ "RUNNING",
35
+ "COMPLETED",
36
+ "FAILED",
37
+ "CANCELLED",
38
+ "WAITING",
39
+ "TERMINATED"
40
+ ];
41
+ function isRunStatus(value) {
42
+ return RUN_STATUSES.some((status) => status === value);
43
+ }
44
+ /** A classification the service knows (its ErrorType enum). */
45
+ function isErrorType(value) {
46
+ return Object.values(ErrorType).some((type) => type === value);
47
+ }
48
+ function validDate(value) {
49
+ return value instanceof Date && Number.isFinite(value.getTime());
50
+ }
51
+ /** The Runs list with `link`'s filters, relative to an SDK page route. */
52
+ function runListPath(link) {
53
+ const params = new URLSearchParams();
54
+ if (link.workflowKey) params.set("workflowKey", link.workflowKey);
55
+ if (link.status) params.set("status", link.status);
56
+ if (link.errorType) params.set("errorType", link.errorType);
57
+ if (link.failedNodeType) params.set("failedNodeType", link.failedNodeType);
58
+ if (validDate(link.from)) params.set("from", link.from.toISOString());
59
+ if (validDate(link.to)) params.set("to", link.to.toISOString());
60
+ const query = params.toString();
61
+ return query ? `../runs?${query}` : "../runs";
62
+ }
63
+ function parseDate(value) {
64
+ if (!value) return null;
65
+ const date = new Date(value);
66
+ return Number.isFinite(date.getTime()) ? date : null;
67
+ }
68
+ /**
69
+ * The list filters a link's query string sets, or null when it carries none.
70
+ * Unknown values are ignored rather than trusted (the URL is user input); a
71
+ * reversed range is dropped, like the custom range inputs do.
72
+ */
73
+ function runListFilterFromSearch(params) {
74
+ const filter = {};
75
+ const status = params.get("status")?.trim().toUpperCase() ?? "";
76
+ if (isRunStatus(status)) filter.status = status;
77
+ const errorType = params.get("errorType")?.trim().toUpperCase() ?? "";
78
+ if (isErrorType(errorType)) filter.errorType = errorType;
79
+ const failedNodeType = params.get("failedNodeType")?.trim() ?? "";
80
+ if (failedNodeType) filter.failedNodeType = failedNodeType;
81
+ const from = parseDate(params.get("from"));
82
+ const to = parseDate(params.get("to"));
83
+ if ((from || to) && !(from && to && from.getTime() > to.getTime())) filter.dateRange = {
84
+ start: from,
85
+ end: to,
86
+ preset: "custom"
87
+ };
88
+ return Object.keys(filter).length > 0 ? filter : null;
89
+ }
90
+ /** A stable key of the link parameters in `params`, to apply each link once. */
91
+ function runListLinkKey(params) {
92
+ return RUN_LIST_LINK_PARAMS.map((name) => params.get(name) ?? "").join("|");
93
+ }
94
+ /** The UTC day [00:00, 24:00) of an ISO calendar date such as "2026-11-10". */
95
+ function utcDay(date) {
96
+ const from = /* @__PURE__ */ new Date(`${date}T00:00:00.000Z`);
97
+ if (!Number.isFinite(from.getTime())) return null;
98
+ return {
99
+ from,
100
+ to: /* @__PURE__ */ new Date(from.getTime() + 864e5 - 1)
101
+ };
102
+ }
103
+
10
104
  // src/modules/observability/hooks/useFailureTriage.ts
11
105
  /**
12
106
  * Failure triage (BOFF-3698): the opt-in, the caller's failure clusters and a
@@ -307,4 +401,4 @@ function FailureTriagePanel({ canManage, canRetry, onOpenRun, onRetry }) {
307
401
  });
308
402
  }
309
403
 
310
- export { fetchRunFailureClusters as a, dismissRunFailureCluster as i, FailureTriagePanel as n, OPEN_STATUSES as r, BUCKET_LABELS as t };
404
+ export { fetchRunFailureClusters as a, runListPath as c, dismissRunFailureCluster as i, utcDay as l, FailureTriagePanel as n, runListFilterFromSearch as o, OPEN_STATUSES as r, runListLinkKey as s, BUCKET_LABELS as t };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
3
- import { Ai as describeOperationError, Bi as resetFluidGridsExecutionState, Ci as waitForFluidGridsClient, Di as emitFluidGridsEvent, F as CreateWorkflowVersionDocument, Hi as validateTrustedOrigin, Li as getFluidGridsConfig, Ni as throwIfResultError, O as CreateWorkflowDefinitionDocument, Oi as emitOperationErrorEvent, Pi as createLiveTokenReader, Rr as WorkflowRunDocument, Si as setFluidGridsClient, Tt as NodeManifestDocument, Vi as setFluidGridsConfig, Vn as TriggerWorkflowDocument, _i as createFluidGridsClient, er as UpdateWorkflowDefinitionDocument, fn as RunFromNodeDocument, ki as emitRunCompletedOnce, nt as ExecuteStepDocument, rt as ExecutionDetailDocument, t as fetchAllNodeEndpointConfigs, tt as EventRegistrationsDocument, vi as getFluidGridsClient, wi as createFluidGridsTokenRefreshLink, xi as resetFluidGridsClient, yi as getFluidGridsClientSafe, yr as WorkflowDefinitionDocument, zi as resetFluidGridsConfig } from "./node-endpoint-configs-BTQbqjEI.js";
3
+ import { Ai as emitOperationErrorEvent, Ci as resetFluidGridsClient, Ei as createFluidGridsTokenRefreshLink, Et as NodeManifestDocument, F as CreateWorkflowVersionDocument, Fi as throwIfResultError, Hi as resetFluidGridsExecutionState, Hn as TriggerWorkflowDocument, Ii as createLiveTokenReader, Mi as describeOperationError, O as CreateWorkflowDefinitionDocument, Ti as waitForFluidGridsClient, Ui as setFluidGridsConfig, Vi as resetFluidGridsConfig, Wi as validateTrustedOrigin, bi as getFluidGridsClient, br as WorkflowDefinitionDocument, it as ExecutionDetailDocument, ji as emitRunCompletedOnce, ki as emitFluidGridsEvent, nt as EventRegistrationsDocument, pn as RunFromNodeDocument, rt as ExecuteStepDocument, t as fetchAllNodeEndpointConfigs, tr as UpdateWorkflowDefinitionDocument, wi as setFluidGridsClient, xi as getFluidGridsClientSafe, yi as createFluidGridsClient, zi as getFluidGridsConfig, zr as WorkflowRunDocument } from "./node-endpoint-configs-BgZARXHI.js";
4
4
  import { A as nodeAccent, C as nodeAdaptersOf, D as NodeCard, E as resolveOutputHandles, H as useFlowStore, I as partitionStickyNotes, L as resolveStickyColor, N as DEFAULT_STICKY_COLOR, O as NodeCardBody, P as STICKY_COLORS, R as stickySurfaceStyle, T as resolveInputHandles, V as STICKY_NOTE_TYPE, W as isNodeTrigger, _ as LogicNodeCard, b as alignPlainOutputEdges, i as WAIT_FOR_SIGNAL_NODE_TYPE, j as NodeTypeIcon, k as NodeCardHeader, l as interfaceFields, m as readSignalName, n as synchronizeOperationUpdate, p as readCodeWorkflowState, r as CODE_WORKFLOW_NODE_TYPE, t as resolveOperationName, u as interfaceHandlers, v as InputHandles, w as outputHandlesSpacerHeight, x as hasNodeManifest, y as OutputHandles } from "./node-operation-selection-61d6U9qo.js";
5
5
  import { n as FluidGridsTranslationProvider, r as useTr, t as ENGLISH_FALLBACK_TRANSLATOR } from "./TranslationBridge-CX0OMnyn.js";
6
6
  import { createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { d as useRestoreWorkflowVersion, h as useWorkflowDefinitions } from "./useWorkflows-CwYurzxn.js";
3
- import { i as versionsOfWorkflow, t as VersionDiffDialog } from "./VersionDiffDialog-CG1tfcfU.js";
2
+ import { d as useRestoreWorkflowVersion, h as useWorkflowDefinitions } from "./useWorkflows-CQbVEHc0.js";
3
+ import { i as versionsOfWorkflow, t as VersionDiffDialog } from "./VersionDiffDialog-BejQlKec.js";
4
4
  import { r as useTr } from "./TranslationBridge-CX0OMnyn.js";
5
- import { Li as getFluidGridsConfig } from "./node-endpoint-configs-BTQbqjEI.js";
5
+ import { zi as getFluidGridsConfig } from "./node-endpoint-configs-BgZARXHI.js";
6
6
  import { n as useFluidGridsPageControls } from "./pageControlsBridge-0pX9s-3k.js";
7
7
  import { n as historyControls } from "./pageControlSpecs-DZJ9K37m.js";
8
8
  import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-iRiufGc2.js";