@burdenoff/fluidgrids-fe-sdk 2026.1112.4 → 2026.1112.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AiStudioPage-C-jio5Bz.js → AiStudioPage-BNmXx6LB.js} +10 -10
- package/dist/{ApprovalInboxPage-D8vhnloO.js → ApprovalInboxPage-QAJim81n.js} +3 -2
- package/dist/{DataSinkDashboardPage-CRBsNjoS.js → DataSinkDashboardPage-kyzcjpzL.js} +4 -4
- package/dist/{DataTablesPage-DoVBkb_T.js → DataTablesPage-Dm-dzVPD.js} +4 -4
- package/dist/{EntityTagPicker-Dk3CufFt.js → EntityTagPicker-dxfzv8aO.js} +1 -1
- package/dist/{ExecutionDetailPage-Cw4zyaIG.js → ExecutionDetailPage-B9eEep77.js} +977 -509
- package/dist/{ExecutionsListPage-BgeqwVr2.js → ExecutionsListPage-DuuPSVEj.js} +831 -146
- package/dist/{FailureTriagePanel-BzD4UJU5.js → FailureTriagePanel-D4lJ4zqQ.js} +1 -1
- package/dist/{FluidGridsProvider-BFfTxl9m.js → FluidGridsProvider-B1hgCbxG.js} +7 -7
- package/dist/{HistoryPage-DktteURI.js → HistoryPage-C7NwkVNC.js} +4 -4
- package/dist/{HumanRequestCard-mOhr-Ic9.js → HumanRequestCard-lbWDpWd7.js} +4 -216
- package/dist/{InsightsPage-2jnYlozA.js → InsightsPage-D9B_qW8e.js} +10 -10
- package/dist/{MissingNodesInstallModal-C0wPwR0Q.js → MissingNodesInstallModal-BkkgeFeN.js} +1 -1
- package/dist/{NodesPage-Dhg5Q2R5.js → NodesPage-BEeUbIts.js} +4 -4
- package/dist/{QuotaExhaustedDialog-BKZ9moP8.js → QuotaExhaustedDialog-Bj7AG_0y.js} +1 -1
- package/dist/{RunnersPage-CLCOCclc.js → RunnersPage-D9Bgod_d.js} +4 -4
- package/dist/{SettingsPage-BaM98QU_.js → SettingsPage-k21044-Z.js} +16 -16
- package/dist/{TagFilterSelect-VC6JMK3F.js → TagFilterSelect-CqhxcDjh.js} +1 -1
- package/dist/{TaskQueuesPage-C3R5ZoKs.js → TaskQueuesPage-B86p51gH.js} +2 -2
- package/dist/{TemplateCard-DYDVNYo6.js → TemplateCard-DanOe65C.js} +3 -3
- package/dist/{TemplateConfigurationModal-BzdkGWim.js → TemplateConfigurationModal-CeMpPEhT.js} +3 -3
- package/dist/{TemplateDetailPanel-s4EqQhra.js → TemplateDetailPanel-DnoA6mC3.js} +2 -2
- package/dist/{TemplatePreview-B_-zS_Mm.js → TemplatePreview-CBwvi0ga.js} +4 -4
- package/dist/{TemplatesPage-OIMd6cIl.js → TemplatesPage-C7f2xq12.js} +14 -14
- package/dist/{VariablesPage-67WR_lVE.js → VariablesPage-BtoLjmUA.js} +1 -1
- package/dist/{VersionDiffDialog-Cp2doV3f.js → VersionDiffDialog-pLpG_I1r.js} +4 -4
- package/dist/{WorkflowBuilder-B2tIOPi0.js → WorkflowBuilder-DDgWgnwH.js} +7 -7
- package/dist/{WorkflowBuilder-DD4UIAjC.js → WorkflowBuilder-DmYS5JEY.js} +12 -12
- package/dist/{WorkflowProposalCard-U31u1qcw.js → WorkflowProposalCard-BjYAZH3q.js} +1 -1
- package/dist/{WorkflowSearchRedirect-BhXzWDj7.js → WorkflowSearchRedirect-iPQBL6WO.js} +1 -1
- package/dist/{WorkflowShareDialog-Dv46nAyh.js → WorkflowShareDialog-DB-qJLB2.js} +1 -1
- package/dist/{WorkflowsList-BV-2J_gG.js → WorkflowsList-rOxlI49U.js} +13 -13
- package/dist/{agentTools-EVdEThES.js → agentTools-B4Gjf8R7.js} +4 -4
- package/dist/{api-DwaHAJtA.js → api-Dvitj1aT.js} +1 -1
- package/dist/{api-C8WmUejq.js → api-JpNuowX4.js} +1 -1
- package/dist/{canvasNoteTools-C5Vf0pxu.js → canvasNoteTools-Bve4Fo7R.js} +3 -3
- package/dist/{code-editor-field-o7qp9eTq.js → code-editor-field-yJZEDJBi.js} +2 -2
- package/dist/{constants-B2lhWNoN.js → constants-dcxg6zG6.js} +2 -2
- package/dist/{definition-canvas-F8DGty5m.js → definition-canvas-Bshn_dSP.js} +1 -1
- package/dist/executions.js +2 -2
- package/dist/{flow-builder-Dn4PCWuf.js → flow-builder-BPe5YNF6.js} +48 -48
- package/dist/{graphql-operation-types-BdU65FNm.js → graphql-operation-types-z2oXfQvM.js} +10 -1
- package/dist/history.js +1 -1
- package/dist/{index-DbTgk7dK.d.ts → index-u-kM0seP.d.ts} +3 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +40 -39
- package/dist/{node-detail-view-kWiwJEKr.js → node-detail-view-oAotM2EI.js} +18 -18
- package/dist/{node-editor-tab-body-C71Y0fRJ.js → node-editor-tab-body-DIcmar84.js} +6 -6
- package/dist/{node-endpoint-configs-BrzQMy10.js → node-endpoint-configs-typvqw2c.js} +1 -1
- package/dist/{node-operation-selection-icAhaNza.js → node-operation-selection-DAbS6jSY.js} +4 -4
- package/dist/nodes.js +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/{popover-v7g8TWmm.js → popover-DOeSGQOG.js} +3 -3
- package/dist/{quick-config-panel-C84vsDYD.js → quick-config-panel-Pm5nkZVr.js} +6 -6
- package/dist/{schedule-panel-BrNKy9DY.js → schedule-panel-Dizqz9eA.js} +29 -29
- package/dist/settings.js +1 -1
- package/dist/{sidebar-node-editor-D-2lPHwq.js → sidebar-node-editor-BNub2vUq.js} +4 -4
- package/dist/templates.js +2 -2
- package/dist/{useAgentDefinitions-DSU8Eek4.js → useAgentDefinitions-Uy6nhpKN.js} +1 -1
- package/dist/{useDurableParity-fFmfa97r.js → useDurableParity-Cb9nOdE8.js} +191 -4
- package/dist/{useEntityTags-C8rPBi6W.js → useEntityTags-D5C0tdLs.js} +1 -1
- package/dist/{useExecutions-DNGW4yxG.js → useExecutions-DJXtbA15.js} +59 -48
- package/dist/useHumanRequests-ZiR0sSzS.js +218 -0
- package/dist/{useObservability-u-MZCWUV.js → useObservability-Dfgh4yjv.js} +1 -1
- package/dist/{useRunHistory-x9bVUB9T.js → useRunHistory-BZQ3t68Q.js} +2 -2
- package/dist/{useWorkflowCodeExport-CV3SZeKm.js → useWorkflowCodeExport-D0zapXXm.js} +2 -2
- package/dist/{useWorkflows-CVb5zXKt.js → useWorkflows-CP-d3ygY.js} +2 -2
- package/dist/workflow-builder.js +5 -5
- package/dist/workflow-host.js +1 -1
- package/dist/workflow-pages.d.ts +1 -1
- package/dist/workflow-pages.js +19 -19
- package/dist/workflow-preview.js +4 -4
- package/dist/workflows-list.js +1 -1
- package/package.json +1 -1
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
|
-
import { i as useRunPending, n as useDurableParityRunFields, o as ExecutionStatusBadge, r as useRunMetadata, s as
|
|
3
|
+
import { c as TechnicalDetails, d as errorAdvice, f as needsReconnect, i as useRunPending, m as NodeStatusBadge, n as useDurableParityRunFields, o as ConfirmStopRunDialog, p as ExecutionStatusBadge, r as useRunMetadata, s as RunActionsMenu, t as setRunVersioningOverride } from "./useDurableParity-Cb9nOdE8.js";
|
|
4
4
|
import { n as formatRunVersion, r as nodeDisplayTitle, t as buildNodeDisplayMap } from "./run-display-BycKYSU0.js";
|
|
5
5
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
6
6
|
import { s as isAgentNodeType } from "./agent-form-Bfvm32j1.js";
|
|
7
|
-
import { An as runSignalTargets, Dn as durableInterfaceOf, I as describeRunError, L as describeRunStep, Tn as canSignalRun, dn as runDurationMs, ln as formatElapsedMs, un as nodeStateDurationMs } from "./FluidGridsProvider-
|
|
7
|
+
import { An as runSignalTargets, Dn as durableInterfaceOf, I as describeRunError, L as describeRunStep, Tn as canSignalRun, dn as runDurationMs, ln as formatElapsedMs, un as nodeStateDurationMs } from "./FluidGridsProvider-B1hgCbxG.js";
|
|
8
8
|
import { n as useFgAskable, r as useFgAskableSelection } from "./askAboutBridge-BV8m95kk.js";
|
|
9
|
-
import {
|
|
9
|
+
import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
|
|
10
|
+
import { _ as shortRunId, g as runChainLinks, h as parseMetadataDefinition, m as overrideRequestOf, n as useExecution, p as callbackTone, r as useExecutionActions, s as buildRetryTriggerInput, t as useAutoRefresh } from "./useExecutions-DJXtbA15.js";
|
|
10
11
|
import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient, r as getFluidGridsClientSafe, x as getFluidGridsConfig } from "./client-C9XSzSXr.js";
|
|
11
|
-
import { Cn as RunLogsDocument, Zr as WorkflowRunHierarchyDocument, ft as ExplainRunDocument, o as AgentStepUpdatedDocument, pn as RunAiUsageDocument, s as AgentTraceDocument, xn as RunLogAppendedDocument } from "./graphql-operation-types-
|
|
12
|
-
import { i as SdkPermissionButton, s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-
|
|
13
|
-
import { t as EntityTagPicker } from "./EntityTagPicker-
|
|
14
|
-
import {
|
|
12
|
+
import { Cn as RunLogsDocument, Zr as WorkflowRunHierarchyDocument, ft as ExplainRunDocument, o as AgentStepUpdatedDocument, pn as RunAiUsageDocument, s as AgentTraceDocument, xn as RunLogAppendedDocument } from "./graphql-operation-types-z2oXfQvM.js";
|
|
13
|
+
import { i as SdkPermissionButton, s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
|
|
14
|
+
import { t as EntityTagPicker } from "./EntityTagPicker-dxfzv8aO.js";
|
|
15
|
+
import { i as useRecipientLabel, n as channelLabel, r as ApprovalApprovers } from "./HumanRequestCard-lbWDpWd7.js";
|
|
16
|
+
import { r as useRunHumanRequests } from "./useHumanRequests-ZiR0sSzS.js";
|
|
15
17
|
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-CJ95Rmqo.js";
|
|
16
|
-
import { n as useWorkflowProposal, o as canSaveRunAsTestCase, r as saveRunAsTestCase, t as WorkflowProposalCard } from "./WorkflowProposalCard-
|
|
18
|
+
import { n as useWorkflowProposal, o as canSaveRunAsTestCase, r as saveRunAsTestCase, t as WorkflowProposalCard } from "./WorkflowProposalCard-BjYAZH3q.js";
|
|
17
19
|
import { t as AiCreditBalanceSlot } from "./aiCreditsBridge-BuE92tKo.js";
|
|
18
|
-
import { a as fetchRunFailureClusters, i as dismissRunFailureCluster, r as OPEN_STATUSES, t as BUCKET_LABELS } from "./FailureTriagePanel-
|
|
19
|
-
import { a as useDurableRunFields, i as useDeterminismStatus, n as SignalRunDialog, o as useRunStackTrace, r as terminateDurableRun, s as RunHistoryView, t as useRunHistory } from "./useRunHistory-
|
|
20
|
+
import { a as fetchRunFailureClusters, i as dismissRunFailureCluster, r as OPEN_STATUSES, t as BUCKET_LABELS } from "./FailureTriagePanel-D4lJ4zqQ.js";
|
|
21
|
+
import { a as useDurableRunFields, i as useDeterminismStatus, n as SignalRunDialog, o as useRunStackTrace, r as terminateDurableRun, s as RunHistoryView, t as useRunHistory } from "./useRunHistory-BZQ3t68Q.js";
|
|
20
22
|
import { $P as VersioningBehavior, FI as WorkflowUpdateWaitFor, L as AgentStepKind, _I as WorkflowQueryRejectCondition, jd as ErrorType } from "./graphql-types-v6CTGwA0.js";
|
|
21
23
|
import { a as formatTokens, d as formatMicroUsd, o as modelLabel, r as aiCost } from "./ai-usage-bmUn-gJP.js";
|
|
22
24
|
import { c as useDurableParityEnabled, f as usePhaseCFlags, m as useWorkflowTestsEnabled, s as useDurableFunctionNodesEnabled } from "./feature-flags-DM5myWaD.js";
|
|
23
|
-
import { A as revokeSignalToken, B as updateActivityOptions, D as resetActivities, E as queryRun, N as sendRunUpdate, O as resetRun, R as unpauseActivities, S as fetchSignalTokens, V as upsertRunSearchAttributes, _ as fetchPauseRules, b as fetchRunUpdate, d as failActivityById, g as fetchCodecServerSettings, i as completeActivityById, k as resetRunToLastCleanTask, s as createSignalToken, v as fetchRunControlFields, w as pauseActivities, y as fetchRunHistoryArchive } from "./api-
|
|
24
|
-
import { a as fetchTaskQueueStats } from "./api-
|
|
25
|
+
import { A as revokeSignalToken, B as updateActivityOptions, D as resetActivities, E as queryRun, N as sendRunUpdate, O as resetRun, R as unpauseActivities, S as fetchSignalTokens, V as upsertRunSearchAttributes, _ as fetchPauseRules, b as fetchRunUpdate, d as failActivityById, g as fetchCodecServerSettings, i as completeActivityById, k as resetRunToLastCleanTask, s as createSignalToken, v as fetchRunControlFields, w as pauseActivities, y as fetchRunHistoryArchive } from "./api-Dvitj1aT.js";
|
|
26
|
+
import { a as fetchTaskQueueStats } from "./api-JpNuowX4.js";
|
|
25
27
|
import { a as RUN_CONTROL_DIALOG_STYLE, c as parseJsonInput, i as NativeSelect, l as parseJsonObjectInput, n as JsonBlock, o as StatusPill, r as JsonField, s as newRunControlId, t as FieldError, u as useResource } from "./shared-CMfn30xT.js";
|
|
26
|
-
import { v as useWorkflowVersions } from "./useWorkflows-
|
|
28
|
+
import { v as useWorkflowVersions } from "./useWorkflows-CP-d3ygY.js";
|
|
27
29
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
28
30
|
import { Link, useNavigate, useParams, useSearchParams } from "react-router";
|
|
29
31
|
import { Icon } from "@iconify/react";
|
|
30
32
|
import { cn } from "@burdenoff/fe-libs/utils";
|
|
31
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
33
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
32
34
|
import { toast } from "sonner";
|
|
33
35
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, Label, Switch, Textarea } from "@burdenoff/fe-libs/ui";
|
|
34
36
|
import { Button as Button$1 } from "@burdenoff/fe-libs/button";
|
|
@@ -36,6 +38,127 @@ import { FlaskConical } from "lucide-react";
|
|
|
36
38
|
import { buildActorFallback, useActorProfiles } from "@burdenoff/fe-libs/shared";
|
|
37
39
|
import ReactMarkdown from "react-markdown";
|
|
38
40
|
|
|
41
|
+
// src/modules/human-response/utils/answer-rows.ts
|
|
42
|
+
/**
|
|
43
|
+
* What a person answered to a free-text or form ask, as label/value rows — the answer that drove
|
|
44
|
+
* the run, kept visible for audit. Approvals need none: the outcome line already says which.
|
|
45
|
+
*/
|
|
46
|
+
function answerRows(request, tr) {
|
|
47
|
+
if (request.status !== "RESPONDED" || request.responseType === "APPROVAL") return [];
|
|
48
|
+
const data = request.response?.data;
|
|
49
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) return [];
|
|
50
|
+
const values = data;
|
|
51
|
+
const show = (value) => {
|
|
52
|
+
if (Array.isArray(value)) return value.map(String).join(", ");
|
|
53
|
+
if (value === null || value === void 0) return "";
|
|
54
|
+
return String(value);
|
|
55
|
+
};
|
|
56
|
+
if (request.responseType === "FREE_TEXT") return [{
|
|
57
|
+
key: "text",
|
|
58
|
+
label: tr("fluidgrids.humanResponse.answerLabel", "Response"),
|
|
59
|
+
value: show(values.text)
|
|
60
|
+
}];
|
|
61
|
+
return request.fields.filter((field) => values[field.name] !== void 0).map((field) => ({
|
|
62
|
+
key: field.name,
|
|
63
|
+
label: field.label || field.name,
|
|
64
|
+
value: show(values[field.name])
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/modules/human-response/components/RunHumanRequests.tsx
|
|
69
|
+
/**
|
|
70
|
+
* Run detail: the asks a "Send and Wait for Response" node made (BOFF-7651) — who was asked, by
|
|
71
|
+
* which channel, until when, and what came back. An approval lists its approvers with each one's
|
|
72
|
+
* answer and comment (BOFF-9956). Renders nothing for runs that asked nobody.
|
|
73
|
+
*/
|
|
74
|
+
function outcome(request, tr, plain) {
|
|
75
|
+
const when = request.respondedAt ? new Date(request.respondedAt).toLocaleString() : "";
|
|
76
|
+
switch (request.status) {
|
|
77
|
+
case "RESPONDED": return request.decision === "declined" ? tr("fluidgrids.humanResponse.outcomeDeclined", "Declined {{when}}", { when }) : request.decision === "approved" ? tr("fluidgrids.humanResponse.outcomeApproved", "Approved {{when}}", { when }) : tr("fluidgrids.humanResponse.outcomeResponded", "Answered {{when}}", { when });
|
|
78
|
+
case "TIMED_OUT":
|
|
79
|
+
if (plain) return tr("fluidgrids.humanResponse.outcomeTimedOutPlain", "No one answered in time");
|
|
80
|
+
return tr("fluidgrids.humanResponse.outcomeTimedOut", "Nobody answered in time — continued down Timed out");
|
|
81
|
+
case "CANCELLED":
|
|
82
|
+
if (plain) return tr("fluidgrids.humanResponse.outcomeCancelledPlain", "Withdrawn because the step was run again or the run stopped");
|
|
83
|
+
return tr("fluidgrids.humanResponse.outcomeCancelled", "Withdrawn (the node was retried or the run stopped)");
|
|
84
|
+
default: return request.expiresAt ? tr("fluidgrids.humanResponse.waitingUntil", "Waiting until {{time}}", { time: new Date(request.expiresAt).toLocaleString() }) : tr("fluidgrids.humanResponse.waiting", "Waiting for a response");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function RunHumanRequests({ requests }) {
|
|
88
|
+
const tr = useTr();
|
|
89
|
+
const v2 = useNavigationV2();
|
|
90
|
+
if (requests.length === 0) return null;
|
|
91
|
+
const pending = requests.some((request) => request.status === "PENDING");
|
|
92
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
93
|
+
className: "mb-6 space-y-2 rounded-lg border border-border-secondary bg-background-secondary p-4",
|
|
94
|
+
"data-testid": "run-human-requests",
|
|
95
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
96
|
+
className: "flex items-center gap-2 text-sm font-medium text-text-primary",
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
99
|
+
icon: "mdi:account-clock-outline",
|
|
100
|
+
width: 18
|
|
101
|
+
}),
|
|
102
|
+
pending ? tr("fluidgrids.humanResponse.runHeading", "Waiting on people") : tr("fluidgrids.humanResponse.runHeadingDone", "People asked"),
|
|
103
|
+
v2 && pending && /* @__PURE__ */ jsx(Link, {
|
|
104
|
+
to: "../approvals",
|
|
105
|
+
"data-testid": "run-answer-in-approvals",
|
|
106
|
+
className: "ml-auto text-sm font-medium text-text-link underline-offset-2 hover:text-text-linkHover hover:underline",
|
|
107
|
+
children: tr("fluidgrids.humanResponse.answerInApprovals", "Answer in Approvals")
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
}), requests.map((request) => /* @__PURE__ */ jsx(RunHumanRequestRow, {
|
|
111
|
+
request,
|
|
112
|
+
plain: v2
|
|
113
|
+
}, request.id))]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function RunHumanRequestRow({ request, plain }) {
|
|
117
|
+
const tr = useTr();
|
|
118
|
+
const answer = answerRows(request, tr);
|
|
119
|
+
const recipient = useRecipientLabel(request, tr("fluidgrids.humanResponse.anyMember", "any workspace member"));
|
|
120
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
121
|
+
className: "flex flex-col gap-0.5 text-sm sm:flex-row sm:flex-wrap sm:items-baseline sm:gap-x-2",
|
|
122
|
+
"data-testid": "run-human-request",
|
|
123
|
+
"data-status": request.status,
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsx("span", {
|
|
126
|
+
className: "font-medium text-text-primary",
|
|
127
|
+
children: request.title
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ jsxs("span", {
|
|
130
|
+
className: "text-text-secondary",
|
|
131
|
+
children: [
|
|
132
|
+
tr("fluidgrids.humanResponse.askedVia", "Asked {{recipient}} via {{channel}}", {
|
|
133
|
+
recipient,
|
|
134
|
+
channel: channelLabel(request.channel, tr)
|
|
135
|
+
}),
|
|
136
|
+
" · ",
|
|
137
|
+
outcome(request, tr, plain)
|
|
138
|
+
]
|
|
139
|
+
}),
|
|
140
|
+
(request.approvals?.length ?? 0) > 0 && /* @__PURE__ */ jsx("div", {
|
|
141
|
+
className: "mt-1 w-full sm:mt-0",
|
|
142
|
+
children: /* @__PURE__ */ jsx(ApprovalApprovers, { request })
|
|
143
|
+
}),
|
|
144
|
+
answer.length > 0 && /* @__PURE__ */ jsx("dl", {
|
|
145
|
+
className: "mt-1 w-full space-y-0.5 text-xs sm:mt-0",
|
|
146
|
+
"data-testid": "run-human-answer",
|
|
147
|
+
children: answer.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
148
|
+
className: "flex gap-2",
|
|
149
|
+
children: [/* @__PURE__ */ jsxs("dt", {
|
|
150
|
+
className: "shrink-0 font-medium text-text-secondary",
|
|
151
|
+
children: [row.label, ":"]
|
|
152
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
153
|
+
className: "whitespace-pre-wrap break-words text-text-primary",
|
|
154
|
+
children: row.value
|
|
155
|
+
})]
|
|
156
|
+
}, row.key))
|
|
157
|
+
})
|
|
158
|
+
]
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
39
162
|
// src/modules/executions/utils/agent-trace.ts
|
|
40
163
|
/**
|
|
41
164
|
* The run page's Agent tab (BOFF-9937): what an AI Agent node did, read from
|
|
@@ -290,15 +413,12 @@ function orderNodesByExecution(nodeStates, triggerNodeId) {
|
|
|
290
413
|
}
|
|
291
414
|
function NodeTimeline({ nodeStates, nodeDisplay, loading, triggerNodeId, onRetryNode, onViewChildRun, onViewAgentTrace, askRun }) {
|
|
292
415
|
const tr = useTr();
|
|
293
|
-
const
|
|
416
|
+
const v2 = useNavigationV2();
|
|
417
|
+
const [toggledNodes, setToggledNodes] = useState(/* @__PURE__ */ new Map());
|
|
294
418
|
const [selectedTab, setSelectedTab] = useState("output");
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (newSet.has(nodeId)) newSet.delete(nodeId);
|
|
299
|
-
else newSet.add(nodeId);
|
|
300
|
-
return newSet;
|
|
301
|
-
});
|
|
419
|
+
const isNodeOpen = (node) => toggledNodes.get(node.id) ?? (v2 && node.status === "FAILED");
|
|
420
|
+
const toggleNode = (node) => {
|
|
421
|
+
setToggledNodes((prev) => new Map(prev).set(node.id, !isNodeOpen(node)));
|
|
302
422
|
};
|
|
303
423
|
const formatTime = (dateStr) => {
|
|
304
424
|
if (!dateStr) return "-";
|
|
@@ -321,6 +441,67 @@ function NodeTimeline({ nodeStates, nodeDisplay, loading, triggerNodeId, onRetry
|
|
|
321
441
|
if (!metadata || typeof metadata !== "object") return false;
|
|
322
442
|
return Object.keys(metadata).length > 0;
|
|
323
443
|
};
|
|
444
|
+
/** The Output / Input toggle and the JSON it shows. */
|
|
445
|
+
const renderStepData = (node) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
446
|
+
className: "flex gap-2 mt-3 mb-3",
|
|
447
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
448
|
+
onClick: () => setSelectedTab("output"),
|
|
449
|
+
className: `px-3 py-1.5 text-sm rounded ${selectedTab === "output" ? "bg-action-primary-bg text-action-primary-text" : "bg-background-tertiary text-text-secondary"}`,
|
|
450
|
+
children: tr("fluidgrids.executions.nodeTimeline.outputTab", "Output")
|
|
451
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
452
|
+
onClick: () => setSelectedTab("input"),
|
|
453
|
+
className: `px-3 py-1.5 text-sm rounded ${selectedTab === "input" ? "bg-action-primary-bg text-action-primary-text" : "bg-background-tertiary text-text-secondary"}`,
|
|
454
|
+
children: tr("fluidgrids.executions.nodeTimeline.inputTab", "Input")
|
|
455
|
+
})]
|
|
456
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
457
|
+
className: "bg-background-primary rounded p-3 max-h-64 overflow-auto",
|
|
458
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
459
|
+
className: "text-xs text-text-primary whitespace-pre-wrap break-words font-mono",
|
|
460
|
+
children: selectedTab === "output" ? formatJsonData(node.output) : formatJsonData(node.inputArgs)
|
|
461
|
+
})
|
|
462
|
+
})] });
|
|
463
|
+
/** View sub-workflow run, View trace and Retry this step. */
|
|
464
|
+
const renderStepActions = (node) => /* @__PURE__ */ jsxs("div", {
|
|
465
|
+
className: "mt-3 flex flex-wrap justify-end gap-2",
|
|
466
|
+
children: [
|
|
467
|
+
node.childRunId && onViewChildRun && /* @__PURE__ */ jsxs("button", {
|
|
468
|
+
onClick: () => onViewChildRun(node.childRunId),
|
|
469
|
+
className: "px-3 py-1.5 text-sm bg-chart-12 text-action-primary-text rounded hover:bg-chart-12/90 flex items-center gap-1.5",
|
|
470
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
471
|
+
icon: "mdi:sitemap",
|
|
472
|
+
width: 16
|
|
473
|
+
}), tr("fluidgrids.executions.nodeTimeline.viewSubWorkflowRun", "View Sub-Workflow Run")]
|
|
474
|
+
}),
|
|
475
|
+
onViewAgentTrace && isAgentNodeType(node.nodeType) && /* @__PURE__ */ jsxs("button", {
|
|
476
|
+
type: "button",
|
|
477
|
+
onClick: () => onViewAgentTrace(node.nodeId),
|
|
478
|
+
className: "px-3 py-1.5 text-sm border border-border-secondary text-text-primary rounded hover:bg-background-tertiary flex items-center gap-1.5",
|
|
479
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
480
|
+
icon: "mdi:robot-outline",
|
|
481
|
+
width: 16
|
|
482
|
+
}), tr("fluidgrids.executions.nodeTimeline.viewAgentTrace", "View trace")]
|
|
483
|
+
}),
|
|
484
|
+
node.status === "FAILED" && onRetryNode && /* @__PURE__ */ jsxs("button", {
|
|
485
|
+
"data-agent": "confirm",
|
|
486
|
+
onClick: () => onRetryNode(node.nodeId),
|
|
487
|
+
className: "px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded hover:bg-action-primary-bgHover flex items-center gap-1.5",
|
|
488
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
489
|
+
icon: "mdi:refresh",
|
|
490
|
+
width: 16
|
|
491
|
+
}), tr("fluidgrids.executions.nodeTimeline.retryNodeButton", "Retry Node")]
|
|
492
|
+
})
|
|
493
|
+
]
|
|
494
|
+
});
|
|
495
|
+
const renderStepMetadata = (node) => /* @__PURE__ */ jsx(Fragment$1, { children: hasMetadata(node.metadata) && /* @__PURE__ */ jsxs("details", {
|
|
496
|
+
className: "mt-3",
|
|
497
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
498
|
+
className: "text-xs text-text-secondary cursor-pointer hover:text-text-primary",
|
|
499
|
+
children: tr("fluidgrids.executions.nodeTimeline.metadataSummary", "Metadata")
|
|
500
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
501
|
+
className: "mt-2 text-xs text-text-secondary bg-background-tertiary p-2 rounded overflow-auto max-h-32",
|
|
502
|
+
children: formatJsonData(node.metadata)
|
|
503
|
+
})]
|
|
504
|
+
}) });
|
|
324
505
|
const sortedNodes = orderNodesByExecution(nodeStates, triggerNodeId);
|
|
325
506
|
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
326
507
|
className: "space-y-4",
|
|
@@ -342,7 +523,7 @@ function NodeTimeline({ nodeStates, nodeDisplay, loading, triggerNodeId, onRetry
|
|
|
342
523
|
children: [/* @__PURE__ */ jsx("div", { className: "absolute left-4 top-8 bottom-8 w-0.5 bg-border-secondary" }), /* @__PURE__ */ jsx("div", {
|
|
343
524
|
className: "space-y-4",
|
|
344
525
|
children: sortedNodes.map((node, index) => {
|
|
345
|
-
const isExpanded =
|
|
526
|
+
const isExpanded = isNodeOpen(node);
|
|
346
527
|
const nodeError = node.error;
|
|
347
528
|
const hasError = node.status === "FAILED" || Boolean(nodeError);
|
|
348
529
|
const isRunning = node.status === "RUNNING";
|
|
@@ -378,155 +559,172 @@ function NodeTimeline({ nodeStates, nodeDisplay, loading, triggerNodeId, onRetry
|
|
|
378
559
|
flex-1 rounded-lg border transition-all
|
|
379
560
|
${hasError ? "bg-[var(--color-status-error-bg-subtle)] border-[var(--color-status-error-border)]" : isRunning ? "bg-[var(--color-status-info-bg-subtle)] border-[var(--color-status-info-border)]" : "bg-background-secondary border-border-secondary"}
|
|
380
561
|
`,
|
|
381
|
-
children: [
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
status: node.status,
|
|
390
|
-
size: "sm",
|
|
391
|
-
showLabel: false
|
|
392
|
-
})
|
|
393
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
394
|
-
className: "min-w-0",
|
|
562
|
+
children: [
|
|
563
|
+
/* @__PURE__ */ jsxs("button", {
|
|
564
|
+
type: "button",
|
|
565
|
+
onClick: () => toggleNode(node),
|
|
566
|
+
"aria-expanded": isExpanded,
|
|
567
|
+
className: "w-full px-4 py-3 flex items-center justify-between text-left",
|
|
568
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
569
|
+
className: "flex items-center gap-3 min-w-0",
|
|
395
570
|
children: [/* @__PURE__ */ jsx("div", {
|
|
396
|
-
className: "
|
|
397
|
-
|
|
398
|
-
|
|
571
|
+
className: "flex-shrink-0",
|
|
572
|
+
children: /* @__PURE__ */ jsx(NodeStatusBadge, {
|
|
573
|
+
status: node.status,
|
|
574
|
+
size: "sm",
|
|
575
|
+
showLabel: false
|
|
576
|
+
})
|
|
399
577
|
}), /* @__PURE__ */ jsxs("div", {
|
|
400
|
-
className: "
|
|
401
|
-
children: [
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
node.
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
children: [/* @__PURE__ */ jsx("div", { children: formatTime(node.startTime) }), /* @__PURE__ */ jsx("div", { children: formatElapsedMs(nodeStateDurationMs(node)) })]
|
|
414
|
-
}),
|
|
415
|
-
hasChildRun && /* @__PURE__ */ jsxs("span", {
|
|
416
|
-
className: "px-2 py-0.5 text-xs bg-chart-12/10 text-chart-12 rounded flex items-center gap-1",
|
|
417
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
418
|
-
icon: "mdi:sitemap",
|
|
419
|
-
width: 12
|
|
420
|
-
}), tr("fluidgrids.executions.nodeTimeline.subWorkflowBadge", "Sub-workflow")]
|
|
421
|
-
}),
|
|
422
|
-
isWaitingSubworkflow && /* @__PURE__ */ jsx("span", {
|
|
423
|
-
className: "px-2 py-0.5 text-xs bg-chart-3/10 text-chart-3 rounded animate-pulse",
|
|
424
|
-
children: tr("fluidgrids.executions.nodeTimeline.waitingBadge", "Waiting...")
|
|
425
|
-
}),
|
|
426
|
-
node.attemptCount > 1 && /* @__PURE__ */ jsxs("span", {
|
|
427
|
-
className: "px-2 py-0.5 text-xs bg-[var(--color-status-warning-bg-subtle)] text-[var(--color-status-warning-text)] rounded",
|
|
428
|
-
children: [
|
|
429
|
-
tr("fluidgrids.executions.nodeTimeline.attemptLabel", "Attempt"),
|
|
430
|
-
" ",
|
|
431
|
-
node.attemptCount
|
|
432
|
-
]
|
|
433
|
-
}),
|
|
434
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
435
|
-
icon: isExpanded ? "mdi:chevron-up" : "mdi:chevron-down",
|
|
436
|
-
className: "text-text-secondary",
|
|
437
|
-
width: 20
|
|
438
|
-
})
|
|
439
|
-
]
|
|
440
|
-
})]
|
|
441
|
-
}), isExpanded && /* @__PURE__ */ jsxs("div", {
|
|
442
|
-
className: "px-4 pb-4 border-t border-border-secondary/50",
|
|
443
|
-
children: [
|
|
444
|
-
/* @__PURE__ */ jsxs("div", {
|
|
445
|
-
className: "flex gap-2 mt-3 mb-3",
|
|
446
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
447
|
-
onClick: () => setSelectedTab("output"),
|
|
448
|
-
className: `px-3 py-1.5 text-sm rounded ${selectedTab === "output" ? "bg-action-primary-bg text-action-primary-text" : "bg-background-tertiary text-text-secondary"}`,
|
|
449
|
-
children: tr("fluidgrids.executions.nodeTimeline.outputTab", "Output")
|
|
450
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
451
|
-
onClick: () => setSelectedTab("input"),
|
|
452
|
-
className: `px-3 py-1.5 text-sm rounded ${selectedTab === "input" ? "bg-action-primary-bg text-action-primary-text" : "bg-background-tertiary text-text-secondary"}`,
|
|
453
|
-
children: tr("fluidgrids.executions.nodeTimeline.inputTab", "Input")
|
|
454
|
-
})]
|
|
455
|
-
}),
|
|
456
|
-
/* @__PURE__ */ jsx("div", {
|
|
457
|
-
className: "bg-background-primary rounded p-3 max-h-64 overflow-auto",
|
|
458
|
-
children: /* @__PURE__ */ jsx("pre", {
|
|
459
|
-
className: "text-xs text-text-primary whitespace-pre-wrap break-words font-mono",
|
|
460
|
-
children: selectedTab === "output" ? formatJsonData(node.output) : formatJsonData(node.inputArgs)
|
|
461
|
-
})
|
|
462
|
-
}),
|
|
463
|
-
node.error && /* @__PURE__ */ jsxs(AskableSelectionDiv, {
|
|
464
|
-
describe: describeStep,
|
|
465
|
-
className: "mt-3 p-3 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded",
|
|
466
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
467
|
-
className: "flex items-center gap-2 text-[var(--color-status-error-text)] mb-1",
|
|
468
|
-
children: [
|
|
469
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
470
|
-
icon: "mdi:alert-circle",
|
|
471
|
-
width: 16
|
|
472
|
-
}),
|
|
473
|
-
/* @__PURE__ */ jsx("span", {
|
|
474
|
-
className: "font-medium text-sm",
|
|
475
|
-
children: tr("fluidgrids.executions.nodeTimeline.errorLabel", "Error")
|
|
476
|
-
}),
|
|
477
|
-
node.errorType && /* @__PURE__ */ jsx("span", {
|
|
478
|
-
className: "text-xs bg-[var(--color-status-error-bg)] px-2 py-0.5 rounded",
|
|
479
|
-
children: node.errorType
|
|
480
|
-
})
|
|
481
|
-
]
|
|
482
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
483
|
-
className: "text-sm text-[var(--color-status-error-text)]",
|
|
484
|
-
children: node.error
|
|
578
|
+
className: "min-w-0",
|
|
579
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
580
|
+
className: "font-medium text-text-primary truncate",
|
|
581
|
+
title: node.nodeId,
|
|
582
|
+
children: nodeDisplayTitle(nodeDisplay?.[node.nodeId], node.nodeId)
|
|
583
|
+
}), !v2 && /* @__PURE__ */ jsxs("div", {
|
|
584
|
+
className: "text-xs text-text-secondary",
|
|
585
|
+
children: [
|
|
586
|
+
node.nodeType,
|
|
587
|
+
" v",
|
|
588
|
+
node.nodeVersion
|
|
589
|
+
]
|
|
590
|
+
})]
|
|
485
591
|
})]
|
|
486
|
-
}),
|
|
487
|
-
|
|
488
|
-
className: "mt-3 flex flex-wrap justify-end gap-2",
|
|
592
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
593
|
+
className: "flex items-center gap-4 flex-shrink-0",
|
|
489
594
|
children: [
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
595
|
+
!v2 && /* @__PURE__ */ jsxs("div", {
|
|
596
|
+
className: "text-right text-xs text-text-secondary hidden sm:block",
|
|
597
|
+
children: [/* @__PURE__ */ jsx("div", { children: formatTime(node.startTime) }), /* @__PURE__ */ jsx("div", { children: formatElapsedMs(nodeStateDurationMs(node)) })]
|
|
598
|
+
}),
|
|
599
|
+
!v2 && hasChildRun && /* @__PURE__ */ jsxs("span", {
|
|
600
|
+
className: "px-2 py-0.5 text-xs bg-chart-12/10 text-chart-12 rounded flex items-center gap-1",
|
|
493
601
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
494
602
|
icon: "mdi:sitemap",
|
|
495
|
-
width:
|
|
496
|
-
}), tr("fluidgrids.executions.nodeTimeline.
|
|
603
|
+
width: 12
|
|
604
|
+
}), tr("fluidgrids.executions.nodeTimeline.subWorkflowBadge", "Sub-workflow")]
|
|
497
605
|
}),
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
606
|
+
!v2 && isWaitingSubworkflow && /* @__PURE__ */ jsx("span", {
|
|
607
|
+
className: "px-2 py-0.5 text-xs bg-chart-3/10 text-chart-3 rounded animate-pulse",
|
|
608
|
+
children: tr("fluidgrids.executions.nodeTimeline.waitingBadge", "Waiting...")
|
|
609
|
+
}),
|
|
610
|
+
!v2 && node.attemptCount > 1 && /* @__PURE__ */ jsxs("span", {
|
|
611
|
+
className: "px-2 py-0.5 text-xs bg-[var(--color-status-warning-bg-subtle)] text-[var(--color-status-warning-text)] rounded",
|
|
612
|
+
children: [
|
|
613
|
+
tr("fluidgrids.executions.nodeTimeline.attemptLabel", "Attempt"),
|
|
614
|
+
" ",
|
|
615
|
+
node.attemptCount
|
|
616
|
+
]
|
|
506
617
|
}),
|
|
507
|
-
|
|
508
|
-
"
|
|
509
|
-
|
|
510
|
-
|
|
618
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
619
|
+
icon: isExpanded ? "mdi:chevron-up" : "mdi:chevron-down",
|
|
620
|
+
className: "text-text-secondary",
|
|
621
|
+
width: 20
|
|
622
|
+
})
|
|
623
|
+
]
|
|
624
|
+
})]
|
|
625
|
+
}),
|
|
626
|
+
isExpanded && v2 && /* @__PURE__ */ jsxs("div", {
|
|
627
|
+
className: "px-4 pb-4 border-t border-border-secondary/50",
|
|
628
|
+
children: [
|
|
629
|
+
hasError && /* @__PURE__ */ jsx(AskableSelectionDiv, {
|
|
630
|
+
describe: describeStep,
|
|
631
|
+
className: "mt-3 p-3 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded",
|
|
632
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
633
|
+
className: "flex items-center gap-2 text-[var(--color-status-error-text)]",
|
|
511
634
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
512
|
-
icon: "mdi:
|
|
635
|
+
icon: "mdi:alert-circle",
|
|
513
636
|
width: 16
|
|
514
|
-
}),
|
|
637
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
638
|
+
className: "text-sm font-medium",
|
|
639
|
+
"data-testid": "run-step-advice",
|
|
640
|
+
children: errorAdvice(tr, node.errorType)
|
|
641
|
+
})]
|
|
515
642
|
})
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
643
|
+
}),
|
|
644
|
+
renderStepActions(node),
|
|
645
|
+
/* @__PURE__ */ jsxs(TechnicalDetails, {
|
|
646
|
+
className: "mt-3",
|
|
647
|
+
"data-testid": "run-step-technical",
|
|
648
|
+
children: [
|
|
649
|
+
/* @__PURE__ */ jsxs("dl", {
|
|
650
|
+
className: "mb-3 grid grid-cols-1 gap-x-6 gap-y-1 text-xs text-text-secondary sm:grid-cols-2",
|
|
651
|
+
children: [
|
|
652
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
653
|
+
node.nodeType,
|
|
654
|
+
" v",
|
|
655
|
+
node.nodeVersion
|
|
656
|
+
] }),
|
|
657
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
658
|
+
formatTime(node.startTime),
|
|
659
|
+
" ·",
|
|
660
|
+
" ",
|
|
661
|
+
formatElapsedMs(nodeStateDurationMs(node))
|
|
662
|
+
] }),
|
|
663
|
+
node.attemptCount > 1 && /* @__PURE__ */ jsxs("div", { children: [
|
|
664
|
+
tr("fluidgrids.executions.nodeTimeline.attemptLabel", "Attempt"),
|
|
665
|
+
" ",
|
|
666
|
+
node.attemptCount
|
|
667
|
+
] }),
|
|
668
|
+
hasChildRun && /* @__PURE__ */ jsx("div", { children: tr("fluidgrids.executions.nodeTimeline.subWorkflowBadge", "Sub-workflow") }),
|
|
669
|
+
isWaitingSubworkflow && /* @__PURE__ */ jsx("div", { children: tr("fluidgrids.executions.nodeTimeline.waitingBadge", "Waiting...") })
|
|
670
|
+
]
|
|
671
|
+
}),
|
|
672
|
+
node.error && /* @__PURE__ */ jsxs(AskableSelectionDiv, {
|
|
673
|
+
describe: describeStep,
|
|
674
|
+
className: "mb-3 p-3 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded",
|
|
675
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
676
|
+
className: "flex items-center gap-2 text-[var(--color-status-error-text)] mb-1",
|
|
677
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
678
|
+
className: "font-medium text-sm",
|
|
679
|
+
children: tr("fluidgrids.executions.nodeTimeline.errorLabel", "Error")
|
|
680
|
+
}), node.errorType && /* @__PURE__ */ jsx("span", {
|
|
681
|
+
className: "text-xs bg-[var(--color-status-error-bg)] px-2 py-0.5 rounded",
|
|
682
|
+
children: node.errorType
|
|
683
|
+
})]
|
|
684
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
685
|
+
className: "text-sm text-[var(--color-status-error-text)] break-words",
|
|
686
|
+
children: node.error
|
|
687
|
+
})]
|
|
688
|
+
}),
|
|
689
|
+
renderStepData(node),
|
|
690
|
+
renderStepMetadata(node)
|
|
691
|
+
]
|
|
692
|
+
})
|
|
693
|
+
]
|
|
694
|
+
}),
|
|
695
|
+
isExpanded && !v2 && /* @__PURE__ */ jsxs("div", {
|
|
696
|
+
className: "px-4 pb-4 border-t border-border-secondary/50",
|
|
697
|
+
children: [
|
|
698
|
+
renderStepData(node),
|
|
699
|
+
node.error && /* @__PURE__ */ jsxs(AskableSelectionDiv, {
|
|
700
|
+
describe: describeStep,
|
|
701
|
+
className: "mt-3 p-3 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded",
|
|
702
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
703
|
+
className: "flex items-center gap-2 text-[var(--color-status-error-text)] mb-1",
|
|
704
|
+
children: [
|
|
705
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
706
|
+
icon: "mdi:alert-circle",
|
|
707
|
+
width: 16
|
|
708
|
+
}),
|
|
709
|
+
/* @__PURE__ */ jsx("span", {
|
|
710
|
+
className: "font-medium text-sm",
|
|
711
|
+
children: tr("fluidgrids.executions.nodeTimeline.errorLabel", "Error")
|
|
712
|
+
}),
|
|
713
|
+
node.errorType && /* @__PURE__ */ jsx("span", {
|
|
714
|
+
className: "text-xs bg-[var(--color-status-error-bg)] px-2 py-0.5 rounded",
|
|
715
|
+
children: node.errorType
|
|
716
|
+
})
|
|
717
|
+
]
|
|
718
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
719
|
+
className: "text-sm text-[var(--color-status-error-text)]",
|
|
720
|
+
children: node.error
|
|
721
|
+
})]
|
|
722
|
+
}),
|
|
723
|
+
renderStepActions(node),
|
|
724
|
+
renderStepMetadata(node)
|
|
725
|
+
]
|
|
726
|
+
})
|
|
727
|
+
]
|
|
530
728
|
})]
|
|
531
729
|
}, node.id);
|
|
532
730
|
})
|
|
@@ -919,6 +1117,121 @@ function RunLogViewer({ runId, lines, nodeStates, nodeDisplay, loading, error, h
|
|
|
919
1117
|
});
|
|
920
1118
|
}
|
|
921
1119
|
|
|
1120
|
+
// src/modules/executions/components/RunSummaryCard.tsx
|
|
1121
|
+
/**
|
|
1122
|
+
* "What happened" at the top of a run (BOFF-11846): one plain sentence and the
|
|
1123
|
+
* next-step buttons (Run again, Open workflow, Reconnect), above the step list
|
|
1124
|
+
* and any tab. Navigation v2 only.
|
|
1125
|
+
*/
|
|
1126
|
+
const TONE = {
|
|
1127
|
+
FAILED: "border-[var(--color-status-error-border)] bg-[var(--color-status-error-bg-subtle)]",
|
|
1128
|
+
CANCELLED: "border-[var(--color-status-warning-border)] bg-[var(--color-status-warning-bg-subtle)]",
|
|
1129
|
+
TERMINATED: "border-[var(--color-status-warning-border)] bg-[var(--color-status-warning-bg-subtle)]",
|
|
1130
|
+
COMPLETED: "border-[var(--color-status-success-border)] bg-[var(--color-status-success-bg-subtle)]"
|
|
1131
|
+
};
|
|
1132
|
+
function RunSummaryCard({ status, sentence, onRunAgain, runAgainBusy, onOpenWorkflow, reconnectTo }) {
|
|
1133
|
+
const tr = useTr();
|
|
1134
|
+
const tone = TONE[status] ?? "border-border-secondary bg-background-secondary";
|
|
1135
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
1136
|
+
"aria-label": tr("fluidgrids.executions.runSummary.heading", "What happened"),
|
|
1137
|
+
"data-testid": "run-summary-card",
|
|
1138
|
+
"data-status": status,
|
|
1139
|
+
className: `mb-6 rounded-lg border p-4 ${tone}`,
|
|
1140
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
1141
|
+
className: "text-base font-medium text-text-primary",
|
|
1142
|
+
children: sentence
|
|
1143
|
+
}), (onRunAgain || onOpenWorkflow || reconnectTo) && /* @__PURE__ */ jsxs("div", {
|
|
1144
|
+
className: "mt-3 flex flex-wrap items-center gap-2",
|
|
1145
|
+
children: [
|
|
1146
|
+
reconnectTo && /* @__PURE__ */ jsx(Button$1, {
|
|
1147
|
+
asChild: true,
|
|
1148
|
+
size: "sm",
|
|
1149
|
+
"data-testid": "run-reconnect",
|
|
1150
|
+
children: /* @__PURE__ */ jsxs(Link, {
|
|
1151
|
+
to: reconnectTo,
|
|
1152
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1153
|
+
icon: "mdi:link-variant",
|
|
1154
|
+
className: "mr-1",
|
|
1155
|
+
width: 16
|
|
1156
|
+
}), tr("fluidgrids.executions.executionDetail.reconnectButton", "Reconnect")]
|
|
1157
|
+
})
|
|
1158
|
+
}),
|
|
1159
|
+
onRunAgain && /* @__PURE__ */ jsxs(Button$1, {
|
|
1160
|
+
"data-agent": "confirm",
|
|
1161
|
+
size: "sm",
|
|
1162
|
+
variant: reconnectTo ? "outline" : "default",
|
|
1163
|
+
onClick: onRunAgain,
|
|
1164
|
+
disabled: runAgainBusy,
|
|
1165
|
+
"data-testid": "run-again",
|
|
1166
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1167
|
+
icon: "mdi:refresh",
|
|
1168
|
+
className: "mr-1",
|
|
1169
|
+
width: 16
|
|
1170
|
+
}), tr("fluidgrids.executions.executionDetail.runAgainButton", "Run again")]
|
|
1171
|
+
}),
|
|
1172
|
+
onOpenWorkflow && /* @__PURE__ */ jsxs(Button$1, {
|
|
1173
|
+
variant: "outline",
|
|
1174
|
+
size: "sm",
|
|
1175
|
+
onClick: onOpenWorkflow,
|
|
1176
|
+
"data-testid": "run-open-workflow",
|
|
1177
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1178
|
+
icon: "mdi:open-in-new",
|
|
1179
|
+
className: "mr-1",
|
|
1180
|
+
width: 16
|
|
1181
|
+
}), tr("fluidgrids.executions.executionDetail.openWorkflowButton", "Open workflow")]
|
|
1182
|
+
})
|
|
1183
|
+
]
|
|
1184
|
+
})]
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
// src/modules/executions/utils/run-summary.ts
|
|
1189
|
+
function summarizeRun(tr, input) {
|
|
1190
|
+
const none = {
|
|
1191
|
+
errorType: null,
|
|
1192
|
+
failedNodeId: null
|
|
1193
|
+
};
|
|
1194
|
+
switch (input.status) {
|
|
1195
|
+
case "FAILED": {
|
|
1196
|
+
const failed = input.nodeStates.find((node) => node.status === "FAILED");
|
|
1197
|
+
const errorType = input.errorType ?? failed?.errorType ?? "UNKNOWN";
|
|
1198
|
+
const advice = errorAdvice(tr, errorType);
|
|
1199
|
+
return {
|
|
1200
|
+
sentence: failed ? tr("fluidgrids.executions.runSummary.failedAtStep", "This run stopped at “{{step}}”. {{advice}}", {
|
|
1201
|
+
step: input.stepLabel(failed.nodeId),
|
|
1202
|
+
advice
|
|
1203
|
+
}) : tr("fluidgrids.executions.runSummary.failed", "This run didn't finish. {{advice}}", { advice }),
|
|
1204
|
+
errorType,
|
|
1205
|
+
failedNodeId: failed?.nodeId ?? null
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
case "CANCELLED": return {
|
|
1209
|
+
...none,
|
|
1210
|
+
sentence: tr("fluidgrids.executions.runSummary.stopped", "This run was stopped.")
|
|
1211
|
+
};
|
|
1212
|
+
case "TERMINATED": return {
|
|
1213
|
+
...none,
|
|
1214
|
+
sentence: tr("fluidgrids.executions.runSummary.forceStopped", "This run was force-stopped.")
|
|
1215
|
+
};
|
|
1216
|
+
case "WAITING": return {
|
|
1217
|
+
...none,
|
|
1218
|
+
sentence: input.awaitingPerson ? tr("fluidgrids.executions.runSummary.onHoldPerson", "This run is on hold until someone answers.") : tr("fluidgrids.executions.runSummary.onHold", "This run is on hold.")
|
|
1219
|
+
};
|
|
1220
|
+
case "COMPLETED": return {
|
|
1221
|
+
...none,
|
|
1222
|
+
sentence: tr("fluidgrids.executions.runSummary.succeeded", "This run succeeded.")
|
|
1223
|
+
};
|
|
1224
|
+
case "RUNNING": return {
|
|
1225
|
+
...none,
|
|
1226
|
+
sentence: tr("fluidgrids.executions.runSummary.running", "This run is in progress.")
|
|
1227
|
+
};
|
|
1228
|
+
default: return {
|
|
1229
|
+
...none,
|
|
1230
|
+
sentence: tr("fluidgrids.executions.runSummary.startingSoon", "This run will start soon.")
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
922
1235
|
// src/modules/executions/hooks/useRunLogs.ts
|
|
923
1236
|
/**
|
|
924
1237
|
* useRunLogs — a GitHub-Actions-style live tail for a workflow run.
|
|
@@ -1273,156 +1586,53 @@ function ChildRunsPanel({ view, nodeDisplay, formatDateTime }) {
|
|
|
1273
1586
|
width: 18
|
|
1274
1587
|
}),
|
|
1275
1588
|
/* @__PURE__ */ jsx("h2", {
|
|
1276
|
-
id: "run-child-runs-heading",
|
|
1277
|
-
children: tr("fluidgrids.executions.hierarchy.childRunsTitle", "Child runs")
|
|
1278
|
-
}),
|
|
1279
|
-
/* @__PURE__ */ jsx("span", {
|
|
1280
|
-
className: "rounded-full bg-background-tertiary px-2 py-0.5 text-xs text-text-secondary",
|
|
1281
|
-
children: children.length.toLocaleString()
|
|
1282
|
-
})
|
|
1283
|
-
]
|
|
1284
|
-
}),
|
|
1285
|
-
view?.truncated && /* @__PURE__ */ jsx("p", {
|
|
1286
|
-
className: "mt-2 text-xs text-text-secondary",
|
|
1287
|
-
children: tr("fluidgrids.executions.hierarchy.truncated", "This call tree has more runs than can be listed here, so some child runs may be missing.")
|
|
1288
|
-
}),
|
|
1289
|
-
/* @__PURE__ */ jsx("ul", {
|
|
1290
|
-
className: "mt-3 divide-y divide-border-secondary",
|
|
1291
|
-
children: children.map((child) => {
|
|
1292
|
-
const node = child.parentNodeId ? nodeDisplay[child.parentNodeId]?.label ?? child.parentNodeId : null;
|
|
1293
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Link, {
|
|
1294
|
-
to: runPath(child.id),
|
|
1295
|
-
className: "flex flex-col gap-1 py-2 hover:bg-background-tertiary sm:flex-row sm:items-center sm:gap-3",
|
|
1296
|
-
"data-testid": "run-child-run",
|
|
1297
|
-
children: [
|
|
1298
|
-
/* @__PURE__ */ jsx(ExecutionStatusBadge, {
|
|
1299
|
-
status: child.status,
|
|
1300
|
-
size: "sm"
|
|
1301
|
-
}),
|
|
1302
|
-
/* @__PURE__ */ jsxs("span", {
|
|
1303
|
-
className: "min-w-0 flex-1",
|
|
1304
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
1305
|
-
className: "block truncate text-sm font-medium text-text-link",
|
|
1306
|
-
children: child.name
|
|
1307
|
-
}), node && /* @__PURE__ */ jsx("span", {
|
|
1308
|
-
className: "block truncate text-xs text-text-secondary",
|
|
1309
|
-
children: tr("fluidgrids.executions.hierarchy.startedByNode", "Started by {{node}}", { node })
|
|
1310
|
-
})]
|
|
1311
|
-
}),
|
|
1312
|
-
/* @__PURE__ */ jsx("span", {
|
|
1313
|
-
className: "text-xs text-text-secondary",
|
|
1314
|
-
children: formatDateTime(child.startedAt ?? child.createdAt)
|
|
1315
|
-
}),
|
|
1316
|
-
/* @__PURE__ */ jsx("span", {
|
|
1317
|
-
className: "w-16 text-xs text-text-secondary sm:text-right",
|
|
1318
|
-
children: formatElapsedMs(runDurationMs(child))
|
|
1319
|
-
})
|
|
1320
|
-
]
|
|
1321
|
-
}) }, child.id);
|
|
1322
|
-
})
|
|
1323
|
-
})
|
|
1324
|
-
]
|
|
1325
|
-
});
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
// src/modules/human-response/utils/answer-rows.ts
|
|
1329
|
-
/**
|
|
1330
|
-
* What a person answered to a free-text or form ask, as label/value rows — the answer that drove
|
|
1331
|
-
* the run, kept visible for audit. Approvals need none: the outcome line already says which.
|
|
1332
|
-
*/
|
|
1333
|
-
function answerRows(request, tr) {
|
|
1334
|
-
if (request.status !== "RESPONDED" || request.responseType === "APPROVAL") return [];
|
|
1335
|
-
const data = request.response?.data;
|
|
1336
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) return [];
|
|
1337
|
-
const values = data;
|
|
1338
|
-
const show = (value) => {
|
|
1339
|
-
if (Array.isArray(value)) return value.map(String).join(", ");
|
|
1340
|
-
if (value === null || value === void 0) return "";
|
|
1341
|
-
return String(value);
|
|
1342
|
-
};
|
|
1343
|
-
if (request.responseType === "FREE_TEXT") return [{
|
|
1344
|
-
key: "text",
|
|
1345
|
-
label: tr("fluidgrids.humanResponse.answerLabel", "Response"),
|
|
1346
|
-
value: show(values.text)
|
|
1347
|
-
}];
|
|
1348
|
-
return request.fields.filter((field) => values[field.name] !== void 0).map((field) => ({
|
|
1349
|
-
key: field.name,
|
|
1350
|
-
label: field.label || field.name,
|
|
1351
|
-
value: show(values[field.name])
|
|
1352
|
-
}));
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
// src/modules/human-response/components/RunHumanRequests.tsx
|
|
1356
|
-
/**
|
|
1357
|
-
* Run detail: the asks a "Send and Wait for Response" node made (BOFF-7651) — who was asked, by
|
|
1358
|
-
* which channel, until when, and what came back. An approval lists its approvers with each one's
|
|
1359
|
-
* answer and comment (BOFF-9956). Renders nothing for runs that asked nobody.
|
|
1360
|
-
*/
|
|
1361
|
-
function outcome(request, tr) {
|
|
1362
|
-
const when = request.respondedAt ? new Date(request.respondedAt).toLocaleString() : "";
|
|
1363
|
-
switch (request.status) {
|
|
1364
|
-
case "RESPONDED": return request.decision === "declined" ? tr("fluidgrids.humanResponse.outcomeDeclined", "Declined {{when}}", { when }) : request.decision === "approved" ? tr("fluidgrids.humanResponse.outcomeApproved", "Approved {{when}}", { when }) : tr("fluidgrids.humanResponse.outcomeResponded", "Answered {{when}}", { when });
|
|
1365
|
-
case "TIMED_OUT": return tr("fluidgrids.humanResponse.outcomeTimedOut", "Nobody answered in time — continued down Timed out");
|
|
1366
|
-
case "CANCELLED": return tr("fluidgrids.humanResponse.outcomeCancelled", "Withdrawn (the node was retried or the run stopped)");
|
|
1367
|
-
default: return request.expiresAt ? tr("fluidgrids.humanResponse.waitingUntil", "Waiting until {{time}}", { time: new Date(request.expiresAt).toLocaleString() }) : tr("fluidgrids.humanResponse.waiting", "Waiting for a response");
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
function RunHumanRequests({ requests }) {
|
|
1371
|
-
const tr = useTr();
|
|
1372
|
-
if (requests.length === 0) return null;
|
|
1373
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1374
|
-
className: "mb-6 space-y-2 rounded-lg border border-border-secondary bg-background-secondary p-4",
|
|
1375
|
-
"data-testid": "run-human-requests",
|
|
1376
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
1377
|
-
className: "flex items-center gap-2 text-sm font-medium text-text-primary",
|
|
1378
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1379
|
-
icon: "mdi:account-clock-outline",
|
|
1380
|
-
width: 18
|
|
1381
|
-
}), requests.some((request) => request.status === "PENDING") ? tr("fluidgrids.humanResponse.runHeading", "Waiting on people") : tr("fluidgrids.humanResponse.runHeadingDone", "People asked")]
|
|
1382
|
-
}), requests.map((request) => /* @__PURE__ */ jsx(RunHumanRequestRow, { request }, request.id))]
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
function RunHumanRequestRow({ request }) {
|
|
1386
|
-
const tr = useTr();
|
|
1387
|
-
const answer = answerRows(request, tr);
|
|
1388
|
-
const recipient = useRecipientLabel(request, tr("fluidgrids.humanResponse.anyMember", "any workspace member"));
|
|
1389
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1390
|
-
className: "flex flex-col gap-0.5 text-sm sm:flex-row sm:flex-wrap sm:items-baseline sm:gap-x-2",
|
|
1391
|
-
"data-testid": "run-human-request",
|
|
1392
|
-
"data-status": request.status,
|
|
1393
|
-
children: [
|
|
1394
|
-
/* @__PURE__ */ jsx("span", {
|
|
1395
|
-
className: "font-medium text-text-primary",
|
|
1396
|
-
children: request.title
|
|
1397
|
-
}),
|
|
1398
|
-
/* @__PURE__ */ jsxs("span", {
|
|
1399
|
-
className: "text-text-secondary",
|
|
1400
|
-
children: [
|
|
1401
|
-
tr("fluidgrids.humanResponse.askedVia", "Asked {{recipient}} via {{channel}}", {
|
|
1402
|
-
recipient,
|
|
1403
|
-
channel: channelLabel(request.channel, tr)
|
|
1589
|
+
id: "run-child-runs-heading",
|
|
1590
|
+
children: tr("fluidgrids.executions.hierarchy.childRunsTitle", "Child runs")
|
|
1404
1591
|
}),
|
|
1405
|
-
|
|
1406
|
-
|
|
1592
|
+
/* @__PURE__ */ jsx("span", {
|
|
1593
|
+
className: "rounded-full bg-background-tertiary px-2 py-0.5 text-xs text-text-secondary",
|
|
1594
|
+
children: children.length.toLocaleString()
|
|
1595
|
+
})
|
|
1407
1596
|
]
|
|
1408
1597
|
}),
|
|
1409
|
-
|
|
1410
|
-
className: "mt-
|
|
1411
|
-
children:
|
|
1598
|
+
view?.truncated && /* @__PURE__ */ jsx("p", {
|
|
1599
|
+
className: "mt-2 text-xs text-text-secondary",
|
|
1600
|
+
children: tr("fluidgrids.executions.hierarchy.truncated", "This call tree has more runs than can be listed here, so some child runs may be missing.")
|
|
1412
1601
|
}),
|
|
1413
|
-
|
|
1414
|
-
className: "mt-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
className: "
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1602
|
+
/* @__PURE__ */ jsx("ul", {
|
|
1603
|
+
className: "mt-3 divide-y divide-border-secondary",
|
|
1604
|
+
children: children.map((child) => {
|
|
1605
|
+
const node = child.parentNodeId ? nodeDisplay[child.parentNodeId]?.label ?? child.parentNodeId : null;
|
|
1606
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(Link, {
|
|
1607
|
+
to: runPath(child.id),
|
|
1608
|
+
className: "flex flex-col gap-1 py-2 hover:bg-background-tertiary sm:flex-row sm:items-center sm:gap-3",
|
|
1609
|
+
"data-testid": "run-child-run",
|
|
1610
|
+
children: [
|
|
1611
|
+
/* @__PURE__ */ jsx(ExecutionStatusBadge, {
|
|
1612
|
+
status: child.status,
|
|
1613
|
+
size: "sm"
|
|
1614
|
+
}),
|
|
1615
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1616
|
+
className: "min-w-0 flex-1",
|
|
1617
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1618
|
+
className: "block truncate text-sm font-medium text-text-link",
|
|
1619
|
+
children: child.name
|
|
1620
|
+
}), node && /* @__PURE__ */ jsx("span", {
|
|
1621
|
+
className: "block truncate text-xs text-text-secondary",
|
|
1622
|
+
children: tr("fluidgrids.executions.hierarchy.startedByNode", "Started by {{node}}", { node })
|
|
1623
|
+
})]
|
|
1624
|
+
}),
|
|
1625
|
+
/* @__PURE__ */ jsx("span", {
|
|
1626
|
+
className: "text-xs text-text-secondary",
|
|
1627
|
+
children: formatDateTime(child.startedAt ?? child.createdAt)
|
|
1628
|
+
}),
|
|
1629
|
+
/* @__PURE__ */ jsx("span", {
|
|
1630
|
+
className: "w-16 text-xs text-text-secondary sm:text-right",
|
|
1631
|
+
children: formatElapsedMs(runDurationMs(child))
|
|
1632
|
+
})
|
|
1633
|
+
]
|
|
1634
|
+
}) }, child.id);
|
|
1635
|
+
})
|
|
1426
1636
|
})
|
|
1427
1637
|
]
|
|
1428
1638
|
});
|
|
@@ -2603,12 +2813,12 @@ function AgentTracePanel({ traces, nodeDisplay, usage, usageLoading, usageError,
|
|
|
2603
2813
|
}
|
|
2604
2814
|
function CostValue({ usage, tr }) {
|
|
2605
2815
|
const cost = aiCost(usage);
|
|
2606
|
-
if (cost.kind === "priced") return /* @__PURE__ */ jsx(Fragment, { children: cost.text });
|
|
2816
|
+
if (cost.kind === "priced") return /* @__PURE__ */ jsx(Fragment$1, { children: cost.text });
|
|
2607
2817
|
if (cost.kind === "unpriced") return /* @__PURE__ */ jsx("span", {
|
|
2608
2818
|
className: "text-text-secondary",
|
|
2609
2819
|
children: tr("fluidgrids.executions.executionDetail.agent.notPricedYet", "Not priced yet")
|
|
2610
2820
|
});
|
|
2611
|
-
return /* @__PURE__ */ jsx(Fragment, { children: "—" });
|
|
2821
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: "—" });
|
|
2612
2822
|
}
|
|
2613
2823
|
function Stat({ label, children, detail }) {
|
|
2614
2824
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -2668,7 +2878,7 @@ function AiUsageRollup({ usage, loading, error, onRefresh, nodeDisplay, tr }) {
|
|
|
2668
2878
|
4
|
|
2669
2879
|
].map((item) => /* @__PURE__ */ jsx("div", { className: "h-20 animate-pulse rounded-lg bg-background-tertiary" }, item))
|
|
2670
2880
|
}),
|
|
2671
|
-
total ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
2881
|
+
total ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
2672
2882
|
className: "grid grid-cols-2 gap-3 lg:grid-cols-4",
|
|
2673
2883
|
children: [
|
|
2674
2884
|
/* @__PURE__ */ jsx(Stat, {
|
|
@@ -2985,11 +3195,11 @@ function StepBlock({ label, value, empty }) {
|
|
|
2985
3195
|
})] });
|
|
2986
3196
|
}
|
|
2987
3197
|
function StepCost({ value, tr }) {
|
|
2988
|
-
if (value === null) return /* @__PURE__ */ jsx(Fragment, { children: tr("fluidgrids.executions.executionDetail.agent.notPricedYet", "Not priced yet") });
|
|
2989
|
-
return /* @__PURE__ */ jsx(Fragment, { children: formatMicroUsd(value) });
|
|
3198
|
+
if (value === null) return /* @__PURE__ */ jsx(Fragment$1, { children: tr("fluidgrids.executions.executionDetail.agent.notPricedYet", "Not priced yet") });
|
|
3199
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: formatMicroUsd(value) });
|
|
2990
3200
|
}
|
|
2991
3201
|
function TokensInOut({ tokensIn, tokensOut, tr }) {
|
|
2992
|
-
return /* @__PURE__ */ jsx(Fragment, { children: tr("fluidgrids.executions.executionDetail.agent.tokensInOut", "{{input}} in / {{output}} out tokens", {
|
|
3202
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: tr("fluidgrids.executions.executionDetail.agent.tokensInOut", "{{input}} in / {{output}} out tokens", {
|
|
2993
3203
|
input: formatTokens(tokensIn),
|
|
2994
3204
|
output: formatTokens(tokensOut)
|
|
2995
3205
|
}) });
|
|
@@ -3857,7 +4067,7 @@ function ActivityActionDialog({ runId, action, activity, onClose, onDone }) {
|
|
|
3857
4067
|
error: parsedResult.ok ? null : parsedResult.error,
|
|
3858
4068
|
testId: "activity-complete-result"
|
|
3859
4069
|
}),
|
|
3860
|
-
action === "fail" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
4070
|
+
action === "fail" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
3861
4071
|
className: "space-y-1.5",
|
|
3862
4072
|
children: [/* @__PURE__ */ jsx(Label, {
|
|
3863
4073
|
htmlFor: "activity-fail-message",
|
|
@@ -4443,7 +4653,7 @@ function ResetRunForm({ runId, point, onOpenChange, onReset }) {
|
|
|
4443
4653
|
"data-testid": "run-reset-reason"
|
|
4444
4654
|
})]
|
|
4445
4655
|
}),
|
|
4446
|
-
point.kind === "seq" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("label", {
|
|
4656
|
+
point.kind === "seq" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("label", {
|
|
4447
4657
|
className: "flex items-center justify-between gap-3 text-sm text-text-primary",
|
|
4448
4658
|
children: [tr("fluidgrids.runControl.reset.reapplySignals", "Re-apply the signals received after it"), /* @__PURE__ */ jsx(Switch, {
|
|
4449
4659
|
checked: reapplySignals,
|
|
@@ -5886,7 +6096,7 @@ function SaveRunAsTestCase({ runId }) {
|
|
|
5886
6096
|
setSaving(false);
|
|
5887
6097
|
}
|
|
5888
6098
|
};
|
|
5889
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SdkPermissionButton, {
|
|
6099
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SdkPermissionButton, {
|
|
5890
6100
|
permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_UPDATE,
|
|
5891
6101
|
deniedTooltip: tr("fluidgrids.executions.saveAsTestCase.denied", "You need edit access to this workflow to save test cases"),
|
|
5892
6102
|
children: /* @__PURE__ */ jsxs(Button$1, {
|
|
@@ -5961,15 +6171,26 @@ const ALL_DETAIL_TABS = [
|
|
|
5961
6171
|
* The tabs a run offers: History only on a durable-function run, Agent
|
|
5962
6172
|
* (BOFF-9937) only when the run has an AI Agent node state.
|
|
5963
6173
|
*/
|
|
5964
|
-
function availableDetailTabs(isDurableRun, hasAgent) {
|
|
5965
|
-
return ALL_DETAIL_TABS.filter((tab) => (tab !== "history" || isDurableRun) && (tab !== "agent" || hasAgent));
|
|
6174
|
+
function availableDetailTabs(isDurableRun, hasAgent, v2) {
|
|
6175
|
+
return ALL_DETAIL_TABS.filter((tab) => (tab !== "history" || isDurableRun) && (tab !== "agent" || hasAgent) && (tab !== "context" || !v2));
|
|
6176
|
+
}
|
|
6177
|
+
/**
|
|
6178
|
+
* Where "Reconnect" goes: the host's connections page. It sits outside the
|
|
6179
|
+
* workflows module, so the link is absolute (Navigation v2, FluidGrids only).
|
|
6180
|
+
*/
|
|
6181
|
+
const CONNECTIONS_ROUTE = "/integrations/connections";
|
|
6182
|
+
/** The URL's `#…` fragment; empty where there is no window (server render). */
|
|
6183
|
+
function searchHash() {
|
|
6184
|
+
return typeof window === "undefined" ? "" : window.location.hash;
|
|
5966
6185
|
}
|
|
5967
6186
|
function ExecutionDetailPage() {
|
|
5968
6187
|
const tr = useTr();
|
|
5969
6188
|
const { runId } = useParams();
|
|
5970
6189
|
const navigate = useNavigate();
|
|
5971
6190
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
5972
|
-
const
|
|
6191
|
+
const v2 = useNavigationV2();
|
|
6192
|
+
const requestedTabParam = parseDetailTabParam(searchParams.get("tab"), ALL_DETAIL_TABS);
|
|
6193
|
+
const requestedTab = v2 && requestedTabParam === "context" ? "input" : requestedTabParam ?? (v2 && /^#L/.test(searchHash()) ? "logs" : null);
|
|
5973
6194
|
const requestedNodeId = searchParams.get("node");
|
|
5974
6195
|
const [tabSelection, setTabSelection] = useState({
|
|
5975
6196
|
runId,
|
|
@@ -6063,7 +6284,7 @@ function ExecutionDetailPage() {
|
|
|
6063
6284
|
actorId: execution.triggeredById,
|
|
6064
6285
|
actorType: "user"
|
|
6065
6286
|
}).displayName : null;
|
|
6066
|
-
const {
|
|
6287
|
+
const { controlExecution, retryExecution, retryNode, replayExecution, terminateExecution, loading: actionLoading } = useExecutionActions();
|
|
6067
6288
|
const isActive = runCanChange;
|
|
6068
6289
|
const isHistoricalTestRun = execution?.mode === "TEST" && (execution.status === "COMPLETED" || execution.status === "FAILED" || execution.status === "CANCELLED" || execution.status === "TERMINATED");
|
|
6069
6290
|
useAutoRefresh(useCallback(() => {
|
|
@@ -6076,7 +6297,7 @@ function ExecutionDetailPage() {
|
|
|
6076
6297
|
});
|
|
6077
6298
|
const isDurableRun = durableEnabled && execution?.executionKind === "DURABLE_FN";
|
|
6078
6299
|
const hasAgent = hasAgentNodeState(execution?.nodeStates);
|
|
6079
|
-
const activeTab = resolveDetailTab(selectionForRun(tabSelection, runId, requestedTab, "timeline"), runId, availableDetailTabs(isDurableRun, hasAgent), "timeline");
|
|
6300
|
+
const activeTab = resolveDetailTab(selectionForRun(tabSelection, runId, requestedTab, "timeline"), runId, availableDetailTabs(isDurableRun, hasAgent, v2), "timeline");
|
|
6080
6301
|
const agentFocusNodeId = agentFocus.runId === runId ? agentFocus.nodeId : requestedNodeId;
|
|
6081
6302
|
const runAiUsage = useRunAiUsage(runId, {
|
|
6082
6303
|
enabled: hasAgent && activeTab === "agent",
|
|
@@ -6119,21 +6340,20 @@ function ExecutionDetailPage() {
|
|
|
6119
6340
|
}, [durableEnabled, execution]);
|
|
6120
6341
|
const canSendSignal = canControlRuns && canSignalRun(signalTargets);
|
|
6121
6342
|
const waitingOnSignal = !isDurableRun && signalTargets.targets.some((target) => !!target.nodeId);
|
|
6122
|
-
const
|
|
6123
|
-
if (!runId) return;
|
|
6124
|
-
await pauseExecution(runId);
|
|
6125
|
-
refetch();
|
|
6126
|
-
};
|
|
6127
|
-
const handleResume = async () => {
|
|
6343
|
+
const handleControl = async (action) => {
|
|
6128
6344
|
if (!runId) return;
|
|
6129
|
-
await
|
|
6345
|
+
const result = await controlExecution(action, runId);
|
|
6346
|
+
if (!result.ok) toast.error(action === "pause" ? tr("fluidgrids.executions.executionDetail.pauseFailed", "Could not pause this run") : action === "resume" ? tr("fluidgrids.executions.executionDetail.resumeFailed", "Could not resume this run") : tr("fluidgrids.executions.executionDetail.cancelFailed", "Could not cancel this run"), { description: result.message });
|
|
6130
6347
|
refetch();
|
|
6131
6348
|
};
|
|
6132
|
-
const
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6349
|
+
const [showStopDialog, setShowStopDialog] = useState(false);
|
|
6350
|
+
const requestCancel = () => {
|
|
6351
|
+
if (v2) setShowStopDialog(true);
|
|
6352
|
+
else handleCancel();
|
|
6136
6353
|
};
|
|
6354
|
+
const handlePause = () => handleControl("pause");
|
|
6355
|
+
const handleResume = () => handleControl("resume");
|
|
6356
|
+
const handleCancel = () => handleControl("cancel");
|
|
6137
6357
|
const handleTerminate = async () => {
|
|
6138
6358
|
if (!runId) return;
|
|
6139
6359
|
if (isDurableRun) {
|
|
@@ -6141,7 +6361,7 @@ function ExecutionDetailPage() {
|
|
|
6141
6361
|
setShowTerminateDialog(false);
|
|
6142
6362
|
return;
|
|
6143
6363
|
}
|
|
6144
|
-
await terminateExecution(runId, "User terminated");
|
|
6364
|
+
if (!await terminateExecution(runId, "User terminated")) toast.error(tr("fluidgrids.executions.executionDetail.terminateFailed", "Could not terminate this run"));
|
|
6145
6365
|
setShowTerminateDialog(false);
|
|
6146
6366
|
refetch();
|
|
6147
6367
|
};
|
|
@@ -6157,7 +6377,7 @@ function ExecutionDetailPage() {
|
|
|
6157
6377
|
};
|
|
6158
6378
|
const handleRetryNode = async (nodeId) => {
|
|
6159
6379
|
if (!runId) return;
|
|
6160
|
-
await retryNode(runId, nodeId);
|
|
6380
|
+
if (!await retryNode(runId, nodeId)) toast.error(tr("fluidgrids.executions.executionDetail.retryNodeFailed", "Could not retry this step"));
|
|
6161
6381
|
refetch();
|
|
6162
6382
|
};
|
|
6163
6383
|
const handleReplay = async () => {
|
|
@@ -6170,6 +6390,21 @@ function ExecutionDetailPage() {
|
|
|
6170
6390
|
toast.success(tr("fluidgrids.executions.executionDetail.replayStarted", "Replay started in test mode"));
|
|
6171
6391
|
navigate(`../runs/${replayed.runId}`);
|
|
6172
6392
|
};
|
|
6393
|
+
const handleRunAgain = async () => {
|
|
6394
|
+
if (!execution) return;
|
|
6395
|
+
const result = await retryExecution(execution);
|
|
6396
|
+
if (!result.ok) {
|
|
6397
|
+
toast.error(tr("fluidgrids.executions.executionsList.retryFailed", "Could not start a new run"), { description: result.message });
|
|
6398
|
+
return;
|
|
6399
|
+
}
|
|
6400
|
+
toast.success(tr("fluidgrids.executions.executionsList.retryStarted", "New run started"));
|
|
6401
|
+
navigate(`../runs/${result.run.runId}`);
|
|
6402
|
+
};
|
|
6403
|
+
const handleOpenWorkflow = () => {
|
|
6404
|
+
if (!execution?.workflowKey) return;
|
|
6405
|
+
const base = `../workflow/${encodeURIComponent(execution.workflowKey)}`;
|
|
6406
|
+
navigate(execution.version ? `${base}/${encodeURIComponent(execution.version)}` : base);
|
|
6407
|
+
};
|
|
6173
6408
|
const handleLoadInBuilder = () => {
|
|
6174
6409
|
if (!execution || execution.mode !== "TEST" || !execution.workflowKey || !execution.version) return;
|
|
6175
6410
|
const builderPath = `../workflow/${encodeURIComponent(execution.workflowKey)}/${encodeURIComponent(execution.version)}`;
|
|
@@ -6228,7 +6463,14 @@ function ExecutionDetailPage() {
|
|
|
6228
6463
|
}),
|
|
6229
6464
|
/* @__PURE__ */ jsx("p", {
|
|
6230
6465
|
className: "text-[var(--color-status-error-text)] mb-4",
|
|
6231
|
-
children:
|
|
6466
|
+
children: tr("fluidgrids.executions.executionDetail.loadErrorDescription", "We couldn't load this run. Try again in a moment.")
|
|
6467
|
+
}),
|
|
6468
|
+
/* @__PURE__ */ jsx(TechnicalDetails, {
|
|
6469
|
+
className: "mb-4 text-[var(--color-status-error-text)]",
|
|
6470
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
6471
|
+
className: "text-sm font-mono break-words",
|
|
6472
|
+
children: error.message
|
|
6473
|
+
})
|
|
6232
6474
|
}),
|
|
6233
6475
|
/* @__PURE__ */ jsx(Button$1, {
|
|
6234
6476
|
variant: "outline",
|
|
@@ -6278,7 +6520,7 @@ function ExecutionDetailPage() {
|
|
|
6278
6520
|
const tabs = [
|
|
6279
6521
|
{
|
|
6280
6522
|
id: "timeline",
|
|
6281
|
-
label: tr("fluidgrids.executions.executionDetail.timelineTab", "Timeline"),
|
|
6523
|
+
label: v2 ? tr("fluidgrids.executions.executionDetail.stepsTab", "Steps") : tr("fluidgrids.executions.executionDetail.timelineTab", "Timeline"),
|
|
6282
6524
|
icon: "mdi:timeline"
|
|
6283
6525
|
},
|
|
6284
6526
|
...isDurableRun ? [{
|
|
@@ -6298,15 +6540,236 @@ function ExecutionDetailPage() {
|
|
|
6298
6540
|
},
|
|
6299
6541
|
{
|
|
6300
6542
|
id: "input",
|
|
6301
|
-
label: tr("fluidgrids.executions.executionDetail.inputTab", "Input Data"),
|
|
6543
|
+
label: v2 ? tr("fluidgrids.executions.executionDetail.dataTab", "Data") : tr("fluidgrids.executions.executionDetail.inputTab", "Input Data"),
|
|
6302
6544
|
icon: "mdi:code-json"
|
|
6303
6545
|
},
|
|
6304
|
-
{
|
|
6546
|
+
...v2 ? [] : [{
|
|
6305
6547
|
id: "context",
|
|
6306
6548
|
label: tr("fluidgrids.executions.executionDetail.contextTab", "Context"),
|
|
6307
6549
|
icon: "mdi:information-outline"
|
|
6308
|
-
}
|
|
6550
|
+
}]
|
|
6309
6551
|
];
|
|
6552
|
+
const contextJsonBlock = /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
6553
|
+
className: "text-lg font-medium text-text-primary mb-4",
|
|
6554
|
+
children: tr("fluidgrids.executions.executionDetail.executionContextHeading", "Execution Context")
|
|
6555
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
6556
|
+
className: "bg-background-primary rounded p-4 max-h-[300px] overflow-auto",
|
|
6557
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
6558
|
+
className: "text-sm text-text-primary font-mono whitespace-pre-wrap break-words",
|
|
6559
|
+
children: JSON.stringify(execution.context ?? null, null, 2)
|
|
6560
|
+
})
|
|
6561
|
+
})] });
|
|
6562
|
+
const contextDetailsBlock = /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
6563
|
+
className: "text-lg font-medium text-text-primary mb-4",
|
|
6564
|
+
children: tr("fluidgrids.executions.executionDetail.executionDetailsHeading", "Execution Details")
|
|
6565
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
6566
|
+
className: "space-y-3",
|
|
6567
|
+
children: [
|
|
6568
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6569
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6570
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6571
|
+
className: "text-text-secondary",
|
|
6572
|
+
children: tr("fluidgrids.executions.executionDetail.runIdRow", "Run ID")
|
|
6573
|
+
}), /* @__PURE__ */ jsx("code", {
|
|
6574
|
+
className: "font-mono text-text-primary",
|
|
6575
|
+
children: execution.id
|
|
6576
|
+
})]
|
|
6577
|
+
}),
|
|
6578
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6579
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6580
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6581
|
+
className: "text-text-secondary",
|
|
6582
|
+
children: tr("fluidgrids.executions.executionDetail.workflowRow", "Workflow")
|
|
6583
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6584
|
+
className: "text-text-primary",
|
|
6585
|
+
children: execution.workflow?.name || execution.workflowKey
|
|
6586
|
+
})]
|
|
6587
|
+
}),
|
|
6588
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6589
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6590
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6591
|
+
className: "text-text-secondary",
|
|
6592
|
+
children: tr("fluidgrids.executions.executionDetail.workflowKeyRow", "Workflow Key")
|
|
6593
|
+
}), /* @__PURE__ */ jsx("code", {
|
|
6594
|
+
className: "font-mono text-text-primary",
|
|
6595
|
+
children: execution.workflowKey
|
|
6596
|
+
})]
|
|
6597
|
+
}),
|
|
6598
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6599
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6600
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6601
|
+
className: "text-text-secondary",
|
|
6602
|
+
children: tr("fluidgrids.executions.executionDetail.versionRow", "Version")
|
|
6603
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6604
|
+
className: "text-text-primary",
|
|
6605
|
+
children: formatRunVersion(execution.version)
|
|
6606
|
+
})]
|
|
6607
|
+
}),
|
|
6608
|
+
isDurableRun && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6609
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6610
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6611
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6612
|
+
className: "text-text-secondary",
|
|
6613
|
+
children: tr("fluidgrids.executions.executionDetail.workflowFnRow", "Function")
|
|
6614
|
+
}), /* @__PURE__ */ jsx("code", {
|
|
6615
|
+
className: "font-mono text-text-primary",
|
|
6616
|
+
children: execution.workflowFn ?? "—"
|
|
6617
|
+
})]
|
|
6618
|
+
}),
|
|
6619
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6620
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6621
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6622
|
+
className: "text-text-secondary",
|
|
6623
|
+
children: tr("fluidgrids.executions.executionDetail.taskQueueRow", "Task queue")
|
|
6624
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6625
|
+
className: "text-text-primary",
|
|
6626
|
+
children: execution.taskQueue ?? "—"
|
|
6627
|
+
})]
|
|
6628
|
+
}),
|
|
6629
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6630
|
+
className: "flex justify-between gap-4 py-2 border-b border-border-secondary",
|
|
6631
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6632
|
+
className: "text-text-secondary",
|
|
6633
|
+
children: tr("fluidgrids.executions.executionDetail.buildIdRow", "Build")
|
|
6634
|
+
}), /* @__PURE__ */ jsx("code", {
|
|
6635
|
+
className: "truncate font-mono text-text-primary",
|
|
6636
|
+
title: execution.buildId ?? void 0,
|
|
6637
|
+
children: execution.buildId ?? "—"
|
|
6638
|
+
})]
|
|
6639
|
+
}),
|
|
6640
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6641
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6642
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6643
|
+
className: "text-text-secondary",
|
|
6644
|
+
children: tr("fluidgrids.executions.executionDetail.historyLengthRow", "History events")
|
|
6645
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6646
|
+
className: "text-text-primary",
|
|
6647
|
+
children: execution.historyLength ?? 0
|
|
6648
|
+
})]
|
|
6649
|
+
})
|
|
6650
|
+
] }),
|
|
6651
|
+
execution.triggeredById && /* @__PURE__ */ jsxs("div", {
|
|
6652
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6653
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6654
|
+
className: "text-text-secondary",
|
|
6655
|
+
children: tr("fluidgrids.executions.executionDetail.triggeredByRow", "Triggered By")
|
|
6656
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6657
|
+
className: "text-text-primary",
|
|
6658
|
+
title: execution.triggeredById,
|
|
6659
|
+
children: triggeredByLabel
|
|
6660
|
+
})]
|
|
6661
|
+
}),
|
|
6662
|
+
execution.parentRunId && /* @__PURE__ */ jsxs("div", {
|
|
6663
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6664
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6665
|
+
className: "text-text-secondary",
|
|
6666
|
+
children: tr("fluidgrids.executions.executionDetail.parentRunRow", "Parent Run")
|
|
6667
|
+
}), /* @__PURE__ */ jsxs(Link, {
|
|
6668
|
+
to: `../runs/${execution.parentRunId}`,
|
|
6669
|
+
className: "text-text-link hover:text-text-linkHover hover:underline font-mono",
|
|
6670
|
+
children: [execution.parentRunId.slice(0, 12), "..."]
|
|
6671
|
+
})]
|
|
6672
|
+
}),
|
|
6673
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6674
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6675
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6676
|
+
className: "text-text-secondary",
|
|
6677
|
+
children: tr("fluidgrids.executions.executionDetail.createdRow", "Created")
|
|
6678
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6679
|
+
className: "text-text-primary",
|
|
6680
|
+
children: formatDateTime(execution.createdAt)
|
|
6681
|
+
})]
|
|
6682
|
+
}),
|
|
6683
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6684
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6685
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6686
|
+
className: "text-text-secondary",
|
|
6687
|
+
children: tr("fluidgrids.executions.executionDetail.startedRow", "Started")
|
|
6688
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6689
|
+
className: "text-text-primary",
|
|
6690
|
+
children: formatDateTime(execution.startedAt)
|
|
6691
|
+
})]
|
|
6692
|
+
}),
|
|
6693
|
+
execution.completedAt && /* @__PURE__ */ jsxs("div", {
|
|
6694
|
+
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6695
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
6696
|
+
className: "text-text-secondary",
|
|
6697
|
+
children: tr("fluidgrids.executions.executionDetail.completedRow", "Completed")
|
|
6698
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
6699
|
+
className: "text-text-primary",
|
|
6700
|
+
children: formatDateTime(execution.completedAt)
|
|
6701
|
+
})]
|
|
6702
|
+
})
|
|
6703
|
+
]
|
|
6704
|
+
})] });
|
|
6705
|
+
const triggerDataBlock = /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
6706
|
+
className: "text-lg font-medium text-text-primary mb-4",
|
|
6707
|
+
children: tr("fluidgrids.executions.executionDetail.triggerDataHeading", "Trigger Data")
|
|
6708
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
6709
|
+
className: "bg-background-primary rounded p-4 max-h-[400px] overflow-auto",
|
|
6710
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
6711
|
+
className: "text-sm text-text-primary font-mono whitespace-pre-wrap break-words",
|
|
6712
|
+
children: JSON.stringify(execution.triggerData ?? null, null, 2)
|
|
6713
|
+
})
|
|
6714
|
+
})] });
|
|
6715
|
+
const orderedSteps = orderNodesByExecution(execution.nodeStates ?? [], execution.triggerNodeId ?? void 0);
|
|
6716
|
+
const summary = v2 ? summarizeRun(tr, {
|
|
6717
|
+
status: execution.status,
|
|
6718
|
+
errorType: execution.errorType,
|
|
6719
|
+
nodeStates: orderedSteps,
|
|
6720
|
+
stepLabel: (nodeId) => nodeDisplayTitle(nodeDisplay[nodeId], nodeId),
|
|
6721
|
+
awaitingPerson
|
|
6722
|
+
}) : null;
|
|
6723
|
+
const canRunAgain = canControlRuns && (execution.status === "FAILED" || execution.status === "CANCELLED" || execution.status === "TERMINATED") && buildRetryTriggerInput(execution) !== null;
|
|
6724
|
+
const copyReference = async (reference) => {
|
|
6725
|
+
try {
|
|
6726
|
+
await navigator.clipboard.writeText(reference);
|
|
6727
|
+
toast.success(tr("fluidgrids.executions.executionDetail.referenceCopied", "Reference copied"));
|
|
6728
|
+
} catch {
|
|
6729
|
+
toast.error(tr("fluidgrids.executions.executionDetail.referenceCopyFailed", "Could not copy the reference"));
|
|
6730
|
+
}
|
|
6731
|
+
};
|
|
6732
|
+
const menuItems = [];
|
|
6733
|
+
if (canControlRuns && execution.status === "RUNNING" && !isDurableRun) menuItems.push({
|
|
6734
|
+
id: "pause",
|
|
6735
|
+
icon: "mdi:pause",
|
|
6736
|
+
label: tr("fluidgrids.executions.executionDetail.pauseButton", "Pause"),
|
|
6737
|
+
onSelect: () => void handlePause(),
|
|
6738
|
+
disabled: actionLoading
|
|
6739
|
+
});
|
|
6740
|
+
if (canSendSignal) menuItems.push({
|
|
6741
|
+
id: "signal",
|
|
6742
|
+
icon: "mdi:bell-ring-outline",
|
|
6743
|
+
label: tr("fluidgrids.executions.executionDetail.signalButton", "Signal"),
|
|
6744
|
+
onSelect: () => setShowSignalDialog(true)
|
|
6745
|
+
});
|
|
6746
|
+
if (canControlRuns && !isDurableRun && execution.status !== "RUNNING" && execution.status !== "PENDING" && execution.status !== "WAITING") menuItems.push({
|
|
6747
|
+
id: "replay",
|
|
6748
|
+
icon: "mdi:replay",
|
|
6749
|
+
label: tr("fluidgrids.executions.executionDetail.replayButton", "Replay in test mode"),
|
|
6750
|
+
onSelect: () => void handleReplay(),
|
|
6751
|
+
disabled: actionLoading
|
|
6752
|
+
});
|
|
6753
|
+
if (isHistoricalTestRun && execution.workflowKey && execution.version) menuItems.push({
|
|
6754
|
+
id: "open-in-editor",
|
|
6755
|
+
icon: "mdi:open-in-new",
|
|
6756
|
+
label: tr("fluidgrids.executions.executionDetail.loadTestRunButton", "Load TEST run in builder"),
|
|
6757
|
+
onSelect: handleLoadInBuilder
|
|
6758
|
+
});
|
|
6759
|
+
if ((isDurableRun ? canTerminateDurable : canControlRuns) && (execution.status === "RUNNING" || execution.status === "WAITING")) menuItems.push({
|
|
6760
|
+
id: "terminate",
|
|
6761
|
+
icon: "mdi:close-octagon",
|
|
6762
|
+
label: tr("fluidgrids.executions.executionDetail.terminateButton", "Terminate"),
|
|
6763
|
+
onSelect: () => setShowTerminateDialog(true),
|
|
6764
|
+
disabled: actionLoading,
|
|
6765
|
+
destructive: true
|
|
6766
|
+
});
|
|
6767
|
+
const menuToggles = isActive ? [{
|
|
6768
|
+
id: "live-updates",
|
|
6769
|
+
label: tr("fluidgrids.executions.executionDetail.liveUpdates", "Live updates"),
|
|
6770
|
+
checked: autoRefreshEnabled,
|
|
6771
|
+
onCheckedChange: setAutoRefreshEnabled
|
|
6772
|
+
}] : [];
|
|
6310
6773
|
const askRun = {
|
|
6311
6774
|
runId: execution.id,
|
|
6312
6775
|
status: execution.status,
|
|
@@ -6328,7 +6791,19 @@ function ExecutionDetailPage() {
|
|
|
6328
6791
|
tr("fluidgrids.executions.executionDetail.backToExecutions", "Back to Executions")
|
|
6329
6792
|
]
|
|
6330
6793
|
}),
|
|
6331
|
-
/* @__PURE__ */
|
|
6794
|
+
v2 ? execution.parentRunId && /* @__PURE__ */ jsxs("p", {
|
|
6795
|
+
className: "mb-4 text-sm text-text-secondary",
|
|
6796
|
+
"data-testid": "run-started-by-workflow",
|
|
6797
|
+
children: [
|
|
6798
|
+
tr("fluidgrids.executions.executionDetail.startedByWorkflow", "Started by another workflow"),
|
|
6799
|
+
" · ",
|
|
6800
|
+
/* @__PURE__ */ jsx(Link, {
|
|
6801
|
+
to: `../runs/${execution.parentRunId}`,
|
|
6802
|
+
className: "text-text-link hover:text-text-linkHover hover:underline",
|
|
6803
|
+
children: tr("fluidgrids.executions.executionDetail.openParentRun", "Open it")
|
|
6804
|
+
})
|
|
6805
|
+
]
|
|
6806
|
+
}) : /* @__PURE__ */ jsx(RunCallPath, {
|
|
6332
6807
|
view: hierarchy,
|
|
6333
6808
|
parentRunId: execution.parentRunId
|
|
6334
6809
|
}),
|
|
@@ -6346,7 +6821,12 @@ function ExecutionDetailPage() {
|
|
|
6346
6821
|
status: execution.status,
|
|
6347
6822
|
size: "lg"
|
|
6348
6823
|
}),
|
|
6349
|
-
execution.
|
|
6824
|
+
v2 && execution.mode === "TEST" && /* @__PURE__ */ jsx("span", {
|
|
6825
|
+
className: "px-2 py-0.5 text-xs border border-border-default text-text-secondary rounded",
|
|
6826
|
+
"data-testid": "run-test-badge",
|
|
6827
|
+
children: tr("fluidgrids.executions.executionDetail.testBadge", "Test")
|
|
6828
|
+
}),
|
|
6829
|
+
!v2 && execution.parentRunId && /* @__PURE__ */ jsx("span", {
|
|
6350
6830
|
className: "px-2 py-0.5 text-xs bg-chart-12/10 text-chart-12 rounded",
|
|
6351
6831
|
children: tr("fluidgrids.executions.executionDetail.subWorkflowBadge", "Sub-Workflow")
|
|
6352
6832
|
})
|
|
@@ -6357,7 +6837,7 @@ function ExecutionDetailPage() {
|
|
|
6357
6837
|
"data-testid": "run-summary",
|
|
6358
6838
|
children: parityRun.summary
|
|
6359
6839
|
}),
|
|
6360
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6840
|
+
!v2 && /* @__PURE__ */ jsxs("div", {
|
|
6361
6841
|
className: "flex flex-wrap items-center gap-4 text-sm text-text-secondary",
|
|
6362
6842
|
children: [
|
|
6363
6843
|
/* @__PURE__ */ jsxs("span", {
|
|
@@ -6398,7 +6878,95 @@ function ExecutionDetailPage() {
|
|
|
6398
6878
|
})
|
|
6399
6879
|
]
|
|
6400
6880
|
}),
|
|
6401
|
-
/* @__PURE__ */
|
|
6881
|
+
v2 && /* @__PURE__ */ jsxs("div", {
|
|
6882
|
+
className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-text-secondary",
|
|
6883
|
+
"data-testid": "run-header-meta",
|
|
6884
|
+
children: [
|
|
6885
|
+
execution.triggeredById && /* @__PURE__ */ jsx("span", {
|
|
6886
|
+
title: execution.triggeredById,
|
|
6887
|
+
children: tr("fluidgrids.executions.executionDetail.startedByPerson", "Started by {{name}}", { name: triggeredByLabel ?? "" })
|
|
6888
|
+
}),
|
|
6889
|
+
/* @__PURE__ */ jsxs("span", {
|
|
6890
|
+
className: "flex items-center gap-1",
|
|
6891
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
6892
|
+
icon: "mdi:clock-outline",
|
|
6893
|
+
width: 16
|
|
6894
|
+
}), formatDateTime(execution.startedAt || execution.createdAt)]
|
|
6895
|
+
}),
|
|
6896
|
+
execution.completedAt && /* @__PURE__ */ jsx("span", { children: tr("fluidgrids.executions.executionDetail.finishedAt", "Finished {{when}}", { when: formatDateTime(execution.completedAt) }) })
|
|
6897
|
+
]
|
|
6898
|
+
}),
|
|
6899
|
+
v2 && /* @__PURE__ */ jsx(TechnicalDetails, {
|
|
6900
|
+
className: "mt-3",
|
|
6901
|
+
"data-testid": "run-technical",
|
|
6902
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
6903
|
+
className: "space-y-2 text-sm text-text-secondary",
|
|
6904
|
+
children: [
|
|
6905
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6906
|
+
className: "flex flex-wrap items-center gap-3",
|
|
6907
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
6908
|
+
className: "flex items-center gap-1",
|
|
6909
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
6910
|
+
icon: "mdi:identifier",
|
|
6911
|
+
width: 16
|
|
6912
|
+
}), /* @__PURE__ */ jsx("code", {
|
|
6913
|
+
className: "font-mono break-all",
|
|
6914
|
+
children: execution.id
|
|
6915
|
+
})]
|
|
6916
|
+
}), /* @__PURE__ */ jsxs(Button$1, {
|
|
6917
|
+
variant: "outline",
|
|
6918
|
+
size: "sm",
|
|
6919
|
+
onClick: () => void copyReference(execution.id),
|
|
6920
|
+
"data-testid": "run-copy-reference",
|
|
6921
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
6922
|
+
icon: "mdi:content-copy",
|
|
6923
|
+
className: "mr-1",
|
|
6924
|
+
width: 14
|
|
6925
|
+
}), tr("fluidgrids.executions.executionDetail.copyReference", "Copy reference")]
|
|
6926
|
+
})]
|
|
6927
|
+
}),
|
|
6928
|
+
parityRun?.businessId && /* @__PURE__ */ jsxs("span", {
|
|
6929
|
+
className: "flex items-center gap-1",
|
|
6930
|
+
"data-testid": "run-workflow-id",
|
|
6931
|
+
title: parityRun.businessId,
|
|
6932
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
6933
|
+
icon: "mdi:key-outline",
|
|
6934
|
+
width: 16
|
|
6935
|
+
}), /* @__PURE__ */ jsx("code", {
|
|
6936
|
+
className: "max-w-[16rem] truncate font-mono",
|
|
6937
|
+
children: parityRun.businessId
|
|
6938
|
+
})]
|
|
6939
|
+
}),
|
|
6940
|
+
/* @__PURE__ */ jsxs("span", {
|
|
6941
|
+
className: "flex items-center gap-1",
|
|
6942
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
6943
|
+
icon: "mdi:tag-outline",
|
|
6944
|
+
width: 16
|
|
6945
|
+
}), formatRunVersion(execution.version)]
|
|
6946
|
+
}),
|
|
6947
|
+
execution.parentRunId && /* @__PURE__ */ jsx("span", {
|
|
6948
|
+
className: "flex items-center gap-2",
|
|
6949
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
6950
|
+
className: "px-2 py-0.5 text-xs bg-chart-12/10 text-chart-12 rounded",
|
|
6951
|
+
children: tr("fluidgrids.executions.executionDetail.subWorkflowBadge", "Sub-Workflow")
|
|
6952
|
+
})
|
|
6953
|
+
}),
|
|
6954
|
+
/* @__PURE__ */ jsx(RunCallPath, {
|
|
6955
|
+
view: hierarchy,
|
|
6956
|
+
parentRunId: execution.parentRunId
|
|
6957
|
+
}),
|
|
6958
|
+
/* @__PURE__ */ jsx("div", {
|
|
6959
|
+
"data-testid": "run-tags",
|
|
6960
|
+
children: /* @__PURE__ */ jsx(EntityTagPicker, {
|
|
6961
|
+
entityType: "FLUIDGRIDS_RUN",
|
|
6962
|
+
entityId: execution.id,
|
|
6963
|
+
readOnly: !canTagRun
|
|
6964
|
+
})
|
|
6965
|
+
})
|
|
6966
|
+
]
|
|
6967
|
+
})
|
|
6968
|
+
}),
|
|
6969
|
+
!v2 && /* @__PURE__ */ jsx("div", {
|
|
6402
6970
|
className: "mt-3",
|
|
6403
6971
|
"data-testid": "run-tags",
|
|
6404
6972
|
children: /* @__PURE__ */ jsx(EntityTagPicker, {
|
|
@@ -6410,7 +6978,7 @@ function ExecutionDetailPage() {
|
|
|
6410
6978
|
] }), /* @__PURE__ */ jsxs("div", {
|
|
6411
6979
|
className: "flex flex-wrap items-center gap-2",
|
|
6412
6980
|
children: [
|
|
6413
|
-
isActive && /* @__PURE__ */ jsxs("label", {
|
|
6981
|
+
!v2 && isActive && /* @__PURE__ */ jsxs("label", {
|
|
6414
6982
|
className: "flex items-center gap-2 text-sm text-text-secondary mr-4",
|
|
6415
6983
|
children: [/* @__PURE__ */ jsx("input", {
|
|
6416
6984
|
type: "checkbox",
|
|
@@ -6419,7 +6987,7 @@ function ExecutionDetailPage() {
|
|
|
6419
6987
|
className: "w-4 h-4 rounded"
|
|
6420
6988
|
}), tr("fluidgrids.executions.executionDetail.autoRefreshToggle", "Auto-refresh")]
|
|
6421
6989
|
}),
|
|
6422
|
-
canControlRuns && execution.status === "RUNNING" && /* @__PURE__ */ jsxs(Fragment, { children: [!isDurableRun && /* @__PURE__ */ jsxs(Button$1, {
|
|
6990
|
+
canControlRuns && execution.status === "RUNNING" && /* @__PURE__ */ jsxs(Fragment$1, { children: [!v2 && !isDurableRun && /* @__PURE__ */ jsxs(Button$1, {
|
|
6423
6991
|
"data-agent": "confirm",
|
|
6424
6992
|
variant: "outline",
|
|
6425
6993
|
size: "sm",
|
|
@@ -6434,7 +7002,7 @@ function ExecutionDetailPage() {
|
|
|
6434
7002
|
"data-agent": "confirm",
|
|
6435
7003
|
variant: "outline",
|
|
6436
7004
|
size: "sm",
|
|
6437
|
-
onClick:
|
|
7005
|
+
onClick: requestCancel,
|
|
6438
7006
|
disabled: actionLoading,
|
|
6439
7007
|
className: "border-[var(--color-status-warning-border)] text-[var(--color-status-warning-text)] hover:bg-[var(--color-status-warning-bg-subtle)]",
|
|
6440
7008
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
@@ -6443,7 +7011,7 @@ function ExecutionDetailPage() {
|
|
|
6443
7011
|
width: 16
|
|
6444
7012
|
}), tr("fluidgrids.executions.executionDetail.cancelButton", "Cancel")]
|
|
6445
7013
|
})] }),
|
|
6446
|
-
canControlRuns && execution.status === "WAITING" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7014
|
+
canControlRuns && execution.status === "WAITING" && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6447
7015
|
humanRequestsCurrent && !awaitingPerson && !isDurableRun && !waitingOnSignal && /* @__PURE__ */ jsxs(Button$1, {
|
|
6448
7016
|
"data-agent": "confirm",
|
|
6449
7017
|
variant: "outline",
|
|
@@ -6474,7 +7042,7 @@ function ExecutionDetailPage() {
|
|
|
6474
7042
|
"data-agent": "confirm",
|
|
6475
7043
|
variant: "outline",
|
|
6476
7044
|
size: "sm",
|
|
6477
|
-
onClick:
|
|
7045
|
+
onClick: requestCancel,
|
|
6478
7046
|
disabled: actionLoading,
|
|
6479
7047
|
className: "border-[var(--color-status-warning-border)] text-[var(--color-status-warning-text)] hover:bg-[var(--color-status-warning-bg-subtle)]",
|
|
6480
7048
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
@@ -6488,7 +7056,7 @@ function ExecutionDetailPage() {
|
|
|
6488
7056
|
"data-agent": "confirm",
|
|
6489
7057
|
variant: "outline",
|
|
6490
7058
|
size: "sm",
|
|
6491
|
-
onClick:
|
|
7059
|
+
onClick: requestCancel,
|
|
6492
7060
|
disabled: actionLoading,
|
|
6493
7061
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
6494
7062
|
icon: "mdi:stop",
|
|
@@ -6496,7 +7064,7 @@ function ExecutionDetailPage() {
|
|
|
6496
7064
|
width: 16
|
|
6497
7065
|
}), tr("fluidgrids.executions.executionDetail.cancelButton", "Cancel")]
|
|
6498
7066
|
}),
|
|
6499
|
-
canSendSignal && /* @__PURE__ */ jsxs(Button$1, {
|
|
7067
|
+
!v2 && canSendSignal && /* @__PURE__ */ jsxs(Button$1, {
|
|
6500
7068
|
variant: "outline",
|
|
6501
7069
|
size: "sm",
|
|
6502
7070
|
onClick: () => setShowSignalDialog(true),
|
|
@@ -6507,7 +7075,7 @@ function ExecutionDetailPage() {
|
|
|
6507
7075
|
width: 16
|
|
6508
7076
|
}), tr("fluidgrids.executions.executionDetail.signalButton", "Signal")]
|
|
6509
7077
|
}),
|
|
6510
|
-
(isDurableRun ? canTerminateDurable : canControlRuns) && (execution.status === "RUNNING" || execution.status === "WAITING") && /* @__PURE__ */ jsxs(Button$1, {
|
|
7078
|
+
!v2 && (isDurableRun ? canTerminateDurable : canControlRuns) && (execution.status === "RUNNING" || execution.status === "WAITING") && /* @__PURE__ */ jsxs(Button$1, {
|
|
6511
7079
|
variant: "outline",
|
|
6512
7080
|
size: "sm",
|
|
6513
7081
|
onClick: () => setShowTerminateDialog(true),
|
|
@@ -6519,7 +7087,7 @@ function ExecutionDetailPage() {
|
|
|
6519
7087
|
width: 16
|
|
6520
7088
|
}), tr("fluidgrids.executions.executionDetail.terminateButton", "Terminate")]
|
|
6521
7089
|
}),
|
|
6522
|
-
isHistoricalTestRun && execution.workflowKey && execution.version && /* @__PURE__ */ jsxs(Button$1, {
|
|
7090
|
+
!v2 && isHistoricalTestRun && execution.workflowKey && execution.version && /* @__PURE__ */ jsxs(Button$1, {
|
|
6523
7091
|
variant: "outline",
|
|
6524
7092
|
size: "sm",
|
|
6525
7093
|
onClick: handleLoadInBuilder,
|
|
@@ -6529,7 +7097,7 @@ function ExecutionDetailPage() {
|
|
|
6529
7097
|
width: 16
|
|
6530
7098
|
}), tr("fluidgrids.executions.executionDetail.loadTestRunButton", "Load TEST run in builder")]
|
|
6531
7099
|
}),
|
|
6532
|
-
canControlRuns && !isDurableRun && execution.status !== "RUNNING" && execution.status !== "PENDING" && execution.status !== "WAITING" && /* @__PURE__ */ jsxs(Button$1, {
|
|
7100
|
+
!v2 && canControlRuns && !isDurableRun && execution.status !== "RUNNING" && execution.status !== "PENDING" && execution.status !== "WAITING" && /* @__PURE__ */ jsxs(Button$1, {
|
|
6533
7101
|
"data-agent": "confirm",
|
|
6534
7102
|
variant: "outline",
|
|
6535
7103
|
size: "sm",
|
|
@@ -6556,10 +7124,22 @@ function ExecutionDetailPage() {
|
|
|
6556
7124
|
className: "mr-1",
|
|
6557
7125
|
width: 16
|
|
6558
7126
|
}), tr("fluidgrids.executions.executionDetail.refreshButton", "Refresh")]
|
|
7127
|
+
}),
|
|
7128
|
+
v2 && /* @__PURE__ */ jsx(RunActionsMenu, {
|
|
7129
|
+
items: menuItems,
|
|
7130
|
+
toggles: menuToggles
|
|
6559
7131
|
})
|
|
6560
7132
|
]
|
|
6561
7133
|
})]
|
|
6562
7134
|
}),
|
|
7135
|
+
summary && /* @__PURE__ */ jsx(RunSummaryCard, {
|
|
7136
|
+
status: execution.status,
|
|
7137
|
+
sentence: summary.sentence,
|
|
7138
|
+
onRunAgain: canRunAgain ? () => void handleRunAgain() : void 0,
|
|
7139
|
+
runAgainBusy: actionLoading,
|
|
7140
|
+
onOpenWorkflow: execution.workflowKey ? handleOpenWorkflow : void 0,
|
|
7141
|
+
reconnectTo: needsReconnect(summary.errorType) ? CONNECTIONS_ROUTE : void 0
|
|
7142
|
+
}),
|
|
6563
7143
|
/* @__PURE__ */ jsxs("div", {
|
|
6564
7144
|
className: "grid grid-cols-2 sm:grid-cols-4 gap-4 mb-6",
|
|
6565
7145
|
children: [
|
|
@@ -6637,7 +7217,24 @@ function ExecutionDetailPage() {
|
|
|
6637
7217
|
})
|
|
6638
7218
|
]
|
|
6639
7219
|
}),
|
|
6640
|
-
execution.errorMessage && /* @__PURE__ */
|
|
7220
|
+
v2 && execution.errorMessage && /* @__PURE__ */ jsx(AskableDiv, {
|
|
7221
|
+
describe: () => describeRunError(askRun),
|
|
7222
|
+
"data-testid": "run-error-banner",
|
|
7223
|
+
className: "mb-6",
|
|
7224
|
+
children: /* @__PURE__ */ jsx(TechnicalDetails, { children: /* @__PURE__ */ jsx(AskableSelectionDiv, {
|
|
7225
|
+
describe: () => describeRunError(askRun),
|
|
7226
|
+
children: /* @__PURE__ */ jsxs("p", {
|
|
7227
|
+
className: "text-sm text-[var(--color-status-error-text)] break-words",
|
|
7228
|
+
children: [
|
|
7229
|
+
tr("fluidgrids.executions.executionDetail.errorLabel", "Error"),
|
|
7230
|
+
execution.errorType ? ` (${execution.errorType})` : "",
|
|
7231
|
+
": ",
|
|
7232
|
+
execution.errorMessage
|
|
7233
|
+
]
|
|
7234
|
+
})
|
|
7235
|
+
}) })
|
|
7236
|
+
}),
|
|
7237
|
+
!v2 && execution.errorMessage && /* @__PURE__ */ jsxs(AskableDiv, {
|
|
6641
7238
|
describe: () => describeRunError(askRun),
|
|
6642
7239
|
"data-testid": "run-error-banner",
|
|
6643
7240
|
className: "mb-6 p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg",
|
|
@@ -6847,7 +7444,19 @@ function ExecutionDetailPage() {
|
|
|
6847
7444
|
onLoadMore: () => void runLogs.loadMore()
|
|
6848
7445
|
})
|
|
6849
7446
|
}),
|
|
6850
|
-
activeTab === "input" && /* @__PURE__ */ jsxs("div", {
|
|
7447
|
+
activeTab === "input" && v2 && /* @__PURE__ */ jsxs("div", {
|
|
7448
|
+
className: "space-y-6 p-4 sm:p-6",
|
|
7449
|
+
"data-testid": "run-data-tab",
|
|
7450
|
+
children: [
|
|
7451
|
+
triggerDataBlock,
|
|
7452
|
+
contextJsonBlock,
|
|
7453
|
+
/* @__PURE__ */ jsx(TechnicalDetails, {
|
|
7454
|
+
"data-testid": "run-context-details",
|
|
7455
|
+
children: contextDetailsBlock
|
|
7456
|
+
})
|
|
7457
|
+
]
|
|
7458
|
+
}),
|
|
7459
|
+
activeTab === "input" && !v2 && /* @__PURE__ */ jsxs("div", {
|
|
6851
7460
|
className: "p-4 sm:p-6",
|
|
6852
7461
|
children: [/* @__PURE__ */ jsx("h3", {
|
|
6853
7462
|
className: "text-lg font-medium text-text-primary mb-4",
|
|
@@ -6860,162 +7469,11 @@ function ExecutionDetailPage() {
|
|
|
6860
7469
|
})
|
|
6861
7470
|
})]
|
|
6862
7471
|
}),
|
|
6863
|
-
activeTab === "context" && /* @__PURE__ */ jsx("div", {
|
|
7472
|
+
activeTab === "context" && !v2 && /* @__PURE__ */ jsx("div", {
|
|
6864
7473
|
className: "p-4 sm:p-6",
|
|
6865
7474
|
children: /* @__PURE__ */ jsxs("div", {
|
|
6866
7475
|
className: "grid grid-cols-1 lg:grid-cols-2 gap-6",
|
|
6867
|
-
children: [
|
|
6868
|
-
className: "text-lg font-medium text-text-primary mb-4",
|
|
6869
|
-
children: tr("fluidgrids.executions.executionDetail.executionContextHeading", "Execution Context")
|
|
6870
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
6871
|
-
className: "bg-background-primary rounded p-4 max-h-[300px] overflow-auto",
|
|
6872
|
-
children: /* @__PURE__ */ jsx("pre", {
|
|
6873
|
-
className: "text-sm text-text-primary font-mono whitespace-pre-wrap break-words",
|
|
6874
|
-
children: JSON.stringify(execution.context ?? null, null, 2)
|
|
6875
|
-
})
|
|
6876
|
-
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
6877
|
-
className: "text-lg font-medium text-text-primary mb-4",
|
|
6878
|
-
children: tr("fluidgrids.executions.executionDetail.executionDetailsHeading", "Execution Details")
|
|
6879
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
6880
|
-
className: "space-y-3",
|
|
6881
|
-
children: [
|
|
6882
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6883
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6884
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6885
|
-
className: "text-text-secondary",
|
|
6886
|
-
children: tr("fluidgrids.executions.executionDetail.runIdRow", "Run ID")
|
|
6887
|
-
}), /* @__PURE__ */ jsx("code", {
|
|
6888
|
-
className: "font-mono text-text-primary",
|
|
6889
|
-
children: execution.id
|
|
6890
|
-
})]
|
|
6891
|
-
}),
|
|
6892
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6893
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6894
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6895
|
-
className: "text-text-secondary",
|
|
6896
|
-
children: tr("fluidgrids.executions.executionDetail.workflowRow", "Workflow")
|
|
6897
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
6898
|
-
className: "text-text-primary",
|
|
6899
|
-
children: execution.workflow?.name || execution.workflowKey
|
|
6900
|
-
})]
|
|
6901
|
-
}),
|
|
6902
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6903
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6904
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6905
|
-
className: "text-text-secondary",
|
|
6906
|
-
children: tr("fluidgrids.executions.executionDetail.workflowKeyRow", "Workflow Key")
|
|
6907
|
-
}), /* @__PURE__ */ jsx("code", {
|
|
6908
|
-
className: "font-mono text-text-primary",
|
|
6909
|
-
children: execution.workflowKey
|
|
6910
|
-
})]
|
|
6911
|
-
}),
|
|
6912
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6913
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6914
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6915
|
-
className: "text-text-secondary",
|
|
6916
|
-
children: tr("fluidgrids.executions.executionDetail.versionRow", "Version")
|
|
6917
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
6918
|
-
className: "text-text-primary",
|
|
6919
|
-
children: formatRunVersion(execution.version)
|
|
6920
|
-
})]
|
|
6921
|
-
}),
|
|
6922
|
-
isDurableRun && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6923
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6924
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6925
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6926
|
-
className: "text-text-secondary",
|
|
6927
|
-
children: tr("fluidgrids.executions.executionDetail.workflowFnRow", "Function")
|
|
6928
|
-
}), /* @__PURE__ */ jsx("code", {
|
|
6929
|
-
className: "font-mono text-text-primary",
|
|
6930
|
-
children: execution.workflowFn ?? "—"
|
|
6931
|
-
})]
|
|
6932
|
-
}),
|
|
6933
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6934
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6935
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6936
|
-
className: "text-text-secondary",
|
|
6937
|
-
children: tr("fluidgrids.executions.executionDetail.taskQueueRow", "Task queue")
|
|
6938
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
6939
|
-
className: "text-text-primary",
|
|
6940
|
-
children: execution.taskQueue ?? "—"
|
|
6941
|
-
})]
|
|
6942
|
-
}),
|
|
6943
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6944
|
-
className: "flex justify-between gap-4 py-2 border-b border-border-secondary",
|
|
6945
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6946
|
-
className: "text-text-secondary",
|
|
6947
|
-
children: tr("fluidgrids.executions.executionDetail.buildIdRow", "Build")
|
|
6948
|
-
}), /* @__PURE__ */ jsx("code", {
|
|
6949
|
-
className: "truncate font-mono text-text-primary",
|
|
6950
|
-
title: execution.buildId ?? void 0,
|
|
6951
|
-
children: execution.buildId ?? "—"
|
|
6952
|
-
})]
|
|
6953
|
-
}),
|
|
6954
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6955
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6956
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6957
|
-
className: "text-text-secondary",
|
|
6958
|
-
children: tr("fluidgrids.executions.executionDetail.historyLengthRow", "History events")
|
|
6959
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
6960
|
-
className: "text-text-primary",
|
|
6961
|
-
children: execution.historyLength ?? 0
|
|
6962
|
-
})]
|
|
6963
|
-
})
|
|
6964
|
-
] }),
|
|
6965
|
-
execution.triggeredById && /* @__PURE__ */ jsxs("div", {
|
|
6966
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6967
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6968
|
-
className: "text-text-secondary",
|
|
6969
|
-
children: tr("fluidgrids.executions.executionDetail.triggeredByRow", "Triggered By")
|
|
6970
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
6971
|
-
className: "text-text-primary",
|
|
6972
|
-
title: execution.triggeredById,
|
|
6973
|
-
children: triggeredByLabel
|
|
6974
|
-
})]
|
|
6975
|
-
}),
|
|
6976
|
-
execution.parentRunId && /* @__PURE__ */ jsxs("div", {
|
|
6977
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6978
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6979
|
-
className: "text-text-secondary",
|
|
6980
|
-
children: tr("fluidgrids.executions.executionDetail.parentRunRow", "Parent Run")
|
|
6981
|
-
}), /* @__PURE__ */ jsxs(Link, {
|
|
6982
|
-
to: `../runs/${execution.parentRunId}`,
|
|
6983
|
-
className: "text-text-link hover:text-text-linkHover hover:underline font-mono",
|
|
6984
|
-
children: [execution.parentRunId.slice(0, 12), "..."]
|
|
6985
|
-
})]
|
|
6986
|
-
}),
|
|
6987
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6988
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6989
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
6990
|
-
className: "text-text-secondary",
|
|
6991
|
-
children: tr("fluidgrids.executions.executionDetail.createdRow", "Created")
|
|
6992
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
6993
|
-
className: "text-text-primary",
|
|
6994
|
-
children: formatDateTime(execution.createdAt)
|
|
6995
|
-
})]
|
|
6996
|
-
}),
|
|
6997
|
-
/* @__PURE__ */ jsxs("div", {
|
|
6998
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
6999
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
7000
|
-
className: "text-text-secondary",
|
|
7001
|
-
children: tr("fluidgrids.executions.executionDetail.startedRow", "Started")
|
|
7002
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
7003
|
-
className: "text-text-primary",
|
|
7004
|
-
children: formatDateTime(execution.startedAt)
|
|
7005
|
-
})]
|
|
7006
|
-
}),
|
|
7007
|
-
execution.completedAt && /* @__PURE__ */ jsxs("div", {
|
|
7008
|
-
className: "flex justify-between py-2 border-b border-border-secondary",
|
|
7009
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
7010
|
-
className: "text-text-secondary",
|
|
7011
|
-
children: tr("fluidgrids.executions.executionDetail.completedRow", "Completed")
|
|
7012
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
7013
|
-
className: "text-text-primary",
|
|
7014
|
-
children: formatDateTime(execution.completedAt)
|
|
7015
|
-
})]
|
|
7016
|
-
})
|
|
7017
|
-
]
|
|
7018
|
-
})] })]
|
|
7476
|
+
children: [contextJsonBlock, contextDetailsBlock]
|
|
7019
7477
|
})
|
|
7020
7478
|
})
|
|
7021
7479
|
]
|
|
@@ -7037,12 +7495,22 @@ function ExecutionDetailPage() {
|
|
|
7037
7495
|
onOpenChange: setShowOverrideDialog,
|
|
7038
7496
|
onChanged: () => void refetch()
|
|
7039
7497
|
}),
|
|
7498
|
+
v2 && /* @__PURE__ */ jsx(ConfirmStopRunDialog, {
|
|
7499
|
+
open: showStopDialog,
|
|
7500
|
+
workflowName: execution.workflow?.name || execution.workflowKey,
|
|
7501
|
+
busy: actionLoading,
|
|
7502
|
+
onConfirm: () => {
|
|
7503
|
+
setShowStopDialog(false);
|
|
7504
|
+
handleCancel();
|
|
7505
|
+
},
|
|
7506
|
+
onOpenChange: setShowStopDialog
|
|
7507
|
+
}),
|
|
7040
7508
|
/* @__PURE__ */ jsx(AlertDialog, {
|
|
7041
7509
|
open: showTerminateDialog,
|
|
7042
7510
|
onOpenChange: setShowTerminateDialog,
|
|
7043
7511
|
children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: tr("fluidgrids.executions.executionDetail.terminateDialogTitle", "Terminate Execution") }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: tr("fluidgrids.executions.executionDetail.terminateDialogDescription", "Are you sure you want to force terminate this execution? This will immediately stop the running workflow and cannot be resumed.") })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, {
|
|
7044
7512
|
disabled: actionLoading,
|
|
7045
|
-
children: tr("fluidgrids.executions.executionDetail.
|
|
7513
|
+
children: tr("fluidgrids.executions.executionDetail.terminateKeepButton", "Keep run")
|
|
7046
7514
|
}), /* @__PURE__ */ jsx(AlertDialogAction, {
|
|
7047
7515
|
onClick: handleTerminate,
|
|
7048
7516
|
disabled: actionLoading,
|