@burdenoff/fluidgrids-fe-sdk 2026.1029.5 → 2026.1029.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/ExecutionDetailPage-L7LZYFOT.js +22 -0
  2. package/dist/{WorkflowsList-2OYIXGWQ.js → ExecutionsListPage-7NMW6S5A.js} +9 -9
  3. package/dist/{WorkflowBuilder-EVZGOXZZ.js → WorkflowBuilder-RXVUBDZJ.js} +12 -12
  4. package/dist/{ExecutionsListPage-KC3KRBNS.js → WorkflowsList-5U74DYQ3.js} +9 -8
  5. package/dist/{chunk-5ITN7CKS.js → chunk-4MHWFZJV.js} +1 -1
  6. package/dist/{chunk-CY6KX4RG.js → chunk-6AMNEX2Y.js} +6 -1
  7. package/dist/{chunk-XRHZ3IEL.js → chunk-6SZXW2BF.js} +255 -8
  8. package/dist/{chunk-U6KI4AKI.js → chunk-6TMLIQHB.js} +199 -1
  9. package/dist/{chunk-EAJB5BNF.js → chunk-7CTIVBBA.js} +183 -26
  10. package/dist/{chunk-UZMLMPFJ.js → chunk-AXMEATLG.js} +117 -8
  11. package/dist/{chunk-NM5L7MBJ.js → chunk-BZTVAUOQ.js} +3 -3
  12. package/dist/{chunk-X3LQJLV7.js → chunk-DEGCZCHP.js} +2 -2
  13. package/dist/{chunk-WDTO6ATM.js → chunk-E7UAY3JJ.js} +2 -2
  14. package/dist/{chunk-O24MDGZY.js → chunk-EGIEFGOV.js} +677 -43
  15. package/dist/{chunk-LGGHQ7UE.js → chunk-FFOZ5VUJ.js} +1 -1
  16. package/dist/{chunk-6Y6I2ODM.js → chunk-HAFUSBYP.js} +937 -26
  17. package/dist/{chunk-ZDFDC5YW.js → chunk-IDGDMJMJ.js} +118 -96
  18. package/dist/{chunk-2U56452G.js → chunk-K4BF7PAW.js} +125 -89
  19. package/dist/{chunk-MNPZMFLF.js → chunk-KANARCPR.js} +3 -3
  20. package/dist/{chunk-5GD6OXYW.js → chunk-LAVHDFHI.js} +1 -1
  21. package/dist/{chunk-35SQULD5.js → chunk-NL4JQFFA.js} +1 -1
  22. package/dist/{chunk-SRE2JVSJ.js → chunk-OJPJ2QXD.js} +3 -3
  23. package/dist/{chunk-JUA57OVN.js → chunk-RZR3BDDZ.js} +7 -7
  24. package/dist/{chunk-DASEJQ4G.js → chunk-SZTKLZZR.js} +145 -8
  25. package/dist/{chunk-LB62TAF7.js → chunk-TYYSYSAL.js} +1 -1
  26. package/dist/{chunk-VYH65RLH.js → chunk-US4LPOB3.js} +1 -1
  27. package/dist/{chunk-XTXT4NHE.js → chunk-VIZ7W5WJ.js} +5 -5
  28. package/dist/{chunk-7PP6CRXS.js → chunk-YTUIGIVP.js} +15 -1
  29. package/dist/{chunk-TNPK2LZT.js → chunk-Z4YQTXCD.js} +4 -4
  30. package/dist/{chunk-R4SBXQ2K.js → chunk-ZE5KS2YL.js} +2 -2
  31. package/dist/{config-T7BQ7AO2.js → config-VM7FTHMZ.js} +1 -1
  32. package/dist/executions.js +13 -13
  33. package/dist/history.js +5 -5
  34. package/dist/index.d.ts +2529 -24
  35. package/dist/index.js +118 -51
  36. package/dist/nodes.js +2 -2
  37. package/dist/observability.js +7 -7
  38. package/dist/settings.js +7 -7
  39. package/dist/templates.js +11 -11
  40. package/dist/workflow-builder.js +13 -13
  41. package/dist/workflows-list.js +9 -9
  42. package/package.json +1 -1
  43. package/dist/ExecutionDetailPage-Y4K35GJ7.js +0 -21
@@ -2,18 +2,18 @@ import { deepClone, applyTemplateInputs } from './chunk-GEMNVFPK.js';
2
2
  import { Input } from './chunk-IEVSFCFS.js';
3
3
  import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, DialogFooter } from './chunk-YXMFRQYV.js';
4
4
  import { Badge as Badge$1, Button } from './chunk-BQXVT32O.js';
5
- import { QuotaExhaustedDialog, useWorkflowCodeExport, orderedExportFiles, fileBaseName, downloadWorkflowCodeExport, isLosslessReport, sortFidelityItems, isLossyFidelityItem, lineOfNode } from './chunk-X3LQJLV7.js';
6
- import { EntityTagPicker, useWorkflowProposal, WorkflowProposalCard, useRunHistory, RunHistoryView, SignalRunDialog } from './chunk-ZDFDC5YW.js';
5
+ import { QuotaExhaustedDialog, useWorkflowCodeExport, orderedExportFiles, fileBaseName, downloadWorkflowCodeExport, isLosslessReport, sortFidelityItems, isLossyFidelityItem, lineOfNode } from './chunk-DEGCZCHP.js';
6
+ import { EntityTagPicker, useWorkflowProposal, WorkflowProposalCard, useRunHistory, RunHistoryView, SignalRunDialog } from './chunk-IDGDMJMJ.js';
7
7
  import { AiCreditBalanceSlot } from './chunk-Y53CVZVV.js';
8
- import { useRestoreWorkflowVersion, useWorkflowVersions, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-SRE2JVSJ.js';
9
- import { isAgentNodeType, AgentDefinitionSelectField } from './chunk-5ITN7CKS.js';
8
+ import { useRestoreWorkflowVersion, useWorkflowVersions, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-OJPJ2QXD.js';
9
+ import { isAgentNodeType, AgentDefinitionSelectField } from './chunk-4MHWFZJV.js';
10
10
  import { FluidGridsDocsLink } from './chunk-4VJ3MDOV.js';
11
- import { NODE_CONFIGS, createConfiguredNode, resolveOutputHandles, resolveInputHandles, isNodeConfigsInitialized, useFlowStore, getNodeDetail, useSaveStatusStore, isNodeTypeHiddenFromPalette, liveInternalOperations, resolveNodeOperation, readDisplayOptions, parseParameterValue, canAutosave, STICKY_NOTE_TYPE, isNodeTrigger, resolveUiSpec, RUNS_QUOTA_NAME, throwIfResultError, BILLING_PLANS_PATH, emitUpgradeClicked, FluidGridsContext, emitWorkflowCreated, emitTemplateUsed, ensureNodeConfigsLoaded, registerWorkflowNodeTypes, emitNodeInstalled, useNodeExecution, useDurableFunctionNodesEnabled, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, useIsValidConnection, refetchStoreNodes, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, CODE_WORKFLOW_NODE_TYPE, SdkPermissionButton, FLUIDGRIDS_PERMISSIONS, fieldsFromValue, filterPaletteNodes, useFluidGridsAnalytics, useSaveWorkflow, workflowFingerprint, buildStickyNode, useNodeRegistryRevision, fieldsFromIO, useFluidGridsPermission, readCodeWorkflowState, useCodeWorkflowInterface, clearCodeWorkflowDefinitionCache, isParamVisible, ConnectionSelector, structuredParameterType, nodeAccent, NodeTypeIcon, NODES_METADATA, useConnections, ConnectionFormDialog, useFluidGridsFlag, FLUIDGRIDS_FLAGS, saveIndicatorOf, inAppLeaveTarget, declaredOutputFields, subscribeWorkflowSaved, pathToExpression, diagnosticsByPath, interfaceHandlers, declaredSignals, ExpressionEditor, toCodeMirrorDiagnostics, formatParameterValue, leaveNeedsConfirmation, buildOperationSeed, snapshotForSave, editStateOf, childRunIdOf, defaultSourcePath, describeOperationError, projectLanguage, changedSourceFiles, isEditableSourcePath, sourceLanguageOf, interfaceFields, isImageIcon, NODES, synchronizeOperationUpdate, NodePropertyPanel, openRunQuotaUpgradePrompt, isTriggerOperation, canRenderOperationPanel, runPreparationOf, resolveOperationName, savesInPlace, AUTOSAVE_RETRY_DELAYS_MS, AUTOSAVE_DEBOUNCE_MS } from './chunk-2U56452G.js';
11
+ import { NODE_CONFIGS, createConfiguredNode, resolveOutputHandles, resolveInputHandles, isNodeConfigsInitialized, useFlowStore, getNodeDetail, useSaveStatusStore, isNodeTypeHiddenFromPalette, liveInternalOperations, resolveNodeOperation, readDisplayOptions, parseParameterValue, canAutosave, STICKY_NOTE_TYPE, isNodeTrigger, resolveUiSpec, RUNS_QUOTA_NAME, throwIfResultError, BILLING_PLANS_PATH, emitUpgradeClicked, FluidGridsContext, emitWorkflowCreated, emitTemplateUsed, ensureNodeConfigsLoaded, registerWorkflowNodeTypes, emitNodeInstalled, useNodeExecution, useDurableFunctionNodesEnabled, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, useIsValidConnection, refetchStoreNodes, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, CODE_WORKFLOW_NODE_TYPE, SdkPermissionButton, FLUIDGRIDS_PERMISSIONS, fieldsFromValue, filterPaletteNodes, useFluidGridsAnalytics, useSaveWorkflow, workflowFingerprint, buildStickyNode, useNodeRegistryRevision, fieldsFromIO, useFluidGridsPermission, readCodeWorkflowState, useCodeWorkflowInterface, clearCodeWorkflowDefinitionCache, isParamVisible, ConnectionSelector, structuredParameterType, nodeAccent, NodeTypeIcon, NODES_METADATA, useDurableParityEnabled, useConnections, ConnectionFormDialog, useFluidGridsFlag, FLUIDGRIDS_FLAGS, saveIndicatorOf, inAppLeaveTarget, declaredOutputFields, subscribeWorkflowSaved, pathToExpression, diagnosticsByPath, interfaceHandlers, declaredSignals, ExpressionEditor, toCodeMirrorDiagnostics, formatParameterValue, leaveNeedsConfirmation, buildOperationSeed, describeOperationError, snapshotForSave, editStateOf, childRunIdOf, defaultSourcePath, projectLanguage, changedSourceFiles, isEditableSourcePath, sourceLanguageOf, interfaceFields, isImageIcon, NODES, synchronizeOperationUpdate, NodePropertyPanel, loadDefinitionJson, openRunQuotaUpgradePrompt, isTriggerOperation, canRenderOperationPanel, runPreparationOf, resolveOperationName, savesInPlace, AUTOSAVE_RETRY_DELAYS_MS, AUTOSAVE_DEBOUNCE_MS } from './chunk-K4BF7PAW.js';
12
12
  import { cn } from './chunk-JL7CASN5.js';
13
13
  import { getGlobalStoreClient } from './chunk-PXIFUMLA.js';
14
- import { getFluidGridsConfig } from './chunk-CY6KX4RG.js';
14
+ import { getFluidGridsConfig } from './chunk-6AMNEX2Y.js';
15
15
  import { GetMyNodeInstallationsDocument, BrowseWorkflowTemplatesDocument, InstallWorkflowNodeDocument, InstallPurchasedNodeDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument, GetNodeInstallableVersionsDocument, OrganizationPrivateNodesDocument, InstallOrganizationPrivateNodeDocument, UninstallOrganizationPrivateNodeDocument } from './chunk-JUUYPCFY.js';
16
- import { WorkspaceRunsQuotaDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, WorkflowGenerationTemplatesDocument, WorkflowEnvironmentsDocument, WorkflowPromotionRequestsDocument, DeployWorkflowVersionToDevDocument, RequestWorkflowPromotionDocument, ApproveWorkflowPromotionDocument, RejectWorkflowPromotionDocument, CancelWorkflowPromotionDocument, UpdateWorkflowEnvironmentPolicyDocument, WorkflowGitRepositoryDocument, WorkflowGitPushesDocument, WorkflowGitCommitsDocument, LinkWorkflowGitRepositoryDocument, UnlinkWorkflowGitRepositoryDocument, PushWorkflowToGitDocument, WorkflowGitDiffDocument, RestoreWorkflowFromGitDocument, WorkflowAuthoringDocument, NodeStatesDocument, PreviewScheduleDocument, WorkflowCodeSourceDocument, WorkflowEditLeaseStatusDocument, BuildWorkflowCodeDocument, WebhookTestListenerDocument, StopWebhookTestListenerDocument, ListenForWebhookTestEventDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-7PP6CRXS.js';
16
+ import { WorkspaceRunsQuotaDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, WorkflowGenerationTemplatesDocument, WorkflowEnvironmentsDocument, WorkflowPromotionRequestsDocument, DeployWorkflowVersionToDevDocument, RequestWorkflowPromotionDocument, ApproveWorkflowPromotionDocument, RejectWorkflowPromotionDocument, CancelWorkflowPromotionDocument, UpdateWorkflowEnvironmentPolicyDocument, WorkflowGitRepositoryDocument, WorkflowGitPushesDocument, WorkflowGitCommitsDocument, LinkWorkflowGitRepositoryDocument, UnlinkWorkflowGitRepositoryDocument, PushWorkflowToGitDocument, WorkflowGitDiffDocument, RestoreWorkflowFromGitDocument, WorkflowAuthoringDocument, NodeStatesDocument, PreviewScheduleDocument, WorkflowVersioningDocument, WorkflowVersionDrainageDocument, ActivateWorkflowVersionCheckedDocument, WorkflowCodeSourceDocument, WorkflowEditLeaseStatusDocument, BuildWorkflowCodeDocument, WebhookTestListenerDocument, StopWebhookTestListenerDocument, ListenForWebhookTestEventDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument, SetWorkflowRolloutDocument, DeleteWorkflowRolloutDocument } from './chunk-YTUIGIVP.js';
17
17
  import { useTr } from './chunk-UULVIT25.js';
18
18
  import { getFluidGridsClient, waitForFluidGridsClient, getFluidGridsClientSafe } from './chunk-NTWG3CJX.js';
19
19
  import { __export } from './chunk-62GWEYJ5.js';
@@ -29,7 +29,7 @@ import { useEventBus } from '@burdenoff/fe-libs/shared/events';
29
29
  import { useQuery, useMutation } from '@apollo/client/react';
30
30
  import { gql as gql$1 } from '@apollo/client/core';
31
31
  import 'jszip';
32
- import { Sparkles, Star, Download, Eye, Maximize2, Undo2, Redo2, LayoutGrid, Keyboard, Plus, Trash2, GitBranch, Loader2, AlertCircle, Search, RefreshCw, History, GitCompareArrows, Play, RotateCcw, Layers, Upload, Rocket, ArrowRight, Check, X, Link2, Unlink, GitCompare, ExternalLink, GitCommitHorizontal, CircleHelp, CheckCircle2, Package, Info, Copy, BadgeCheck, DollarSign, Type, Code, Hash, List, Braces, Workflow, PlusCircle, ChevronDown, ChevronRight, AlertTriangle } from 'lucide-react';
32
+ import { Sparkles, Star, Download, Eye, Maximize2, Undo2, Redo2, LayoutGrid, Keyboard, Plus, Trash2, GitBranch, Loader2, AlertCircle, Search, RefreshCw, History, GitCompareArrows, Play, RotateCcw, Layers, Upload, Rocket, ArrowRight, Check, X, Link2, Unlink, GitCompare, ExternalLink, GitCommitHorizontal, CircleHelp, CheckCircle2, Package, SlidersHorizontal, Info, Copy, BadgeCheck, DollarSign, Type, Code, Hash, List, Braces, Workflow, PlusCircle, ChevronDown, ChevronRight, AlertTriangle } from 'lucide-react';
33
33
  import { Icon } from '@iconify/react';
34
34
  import { toast } from 'sonner';
35
35
  import { useShallow, shallow } from 'zustand/shallow';
@@ -25200,7 +25200,7 @@ function DesktopSidebarFragment({
25200
25200
  if (nodesToInstall.length > 0) {
25201
25201
  const { getGlobalStoreClient: getStore } = await import('./global-client-KLOVTVPP.js');
25202
25202
  const { InstallWorkflowNodeDocument: InstallWorkflowNodeDocument2 } = await import('./global-operations-D2USVOPM.js');
25203
- const { getFluidGridsConfig: getFluidGridsConfig3 } = await import('./config-T7BQ7AO2.js');
25203
+ const { getFluidGridsConfig: getFluidGridsConfig3 } = await import('./config-VM7FTHMZ.js');
25204
25204
  const storeClient = getStore();
25205
25205
  const cfg = getFluidGridsConfig3();
25206
25206
  for (let i = 0; i < nodesToInstall.length; i++) {
@@ -25261,7 +25261,7 @@ function DesktopSidebarFragment({
25261
25261
  );
25262
25262
  }
25263
25263
  const { getFluidGridsClient: getFluidGridsClient2 } = await import('./client-T7BHWM2H.js');
25264
- const { getFluidGridsConfig: getFluidGridsConfig2 } = await import('./config-T7BQ7AO2.js');
25264
+ const { getFluidGridsConfig: getFluidGridsConfig2 } = await import('./config-VM7FTHMZ.js');
25265
25265
  const { gql: gql10 } = await import('@apollo/client/core');
25266
25266
  const IMPORT_MUTATION = gql10`
25267
25267
  mutation ImportWorkflowTemplate(
@@ -26743,8 +26743,8 @@ var reducer = (state, action) => {
26743
26743
  if (toastId) {
26744
26744
  addToRemoveQueue(toastId);
26745
26745
  } else {
26746
- state.toasts.forEach((toast17) => {
26747
- addToRemoveQueue(toast17.id);
26746
+ state.toasts.forEach((toast18) => {
26747
+ addToRemoveQueue(toast18.id);
26748
26748
  });
26749
26749
  }
26750
26750
  return {
@@ -28120,7 +28120,7 @@ function VisualMapperContent({
28120
28120
  mapping,
28121
28121
  onMappingChange
28122
28122
  }) {
28123
- const { toast: toast17 } = useToast();
28123
+ const { toast: toast18 } = useToast();
28124
28124
  const tr = useTr();
28125
28125
  const reactFlowWrapper = useRef(null);
28126
28126
  const [selectedSourceNode, setSelectedSourceNode] = useState(null);
@@ -28140,7 +28140,7 @@ function VisualMapperContent({
28140
28140
  targetOperation
28141
28141
  );
28142
28142
  if (generatedNodes.length === 0) {
28143
- toast17({
28143
+ toast18({
28144
28144
  title: tr(
28145
28145
  "fluidgrids.builder.visualMapper.noFieldsFoundTitle",
28146
28146
  "No fields found"
@@ -28166,7 +28166,7 @@ function VisualMapperContent({
28166
28166
  targetNode,
28167
28167
  targetOperation,
28168
28168
  setNodes,
28169
- toast17,
28169
+ toast18,
28170
28170
  tr
28171
28171
  ]);
28172
28172
  useEffect(() => {
@@ -28273,7 +28273,7 @@ function VisualMapperContent({
28273
28273
  }
28274
28274
  onMappingChange(updatedMapping);
28275
28275
  if (isCompatible) {
28276
- toast17({
28276
+ toast18({
28277
28277
  title: tr(
28278
28278
  "fluidgrids.builder.visualMapper.mappingCreatedTitle",
28279
28279
  "Mapping created"
@@ -28281,7 +28281,7 @@ function VisualMapperContent({
28281
28281
  description: `Mapped ${sourcePath} (${sourceType}) to ${targetPath} (${targetType})`
28282
28282
  });
28283
28283
  } else {
28284
- toast17({
28284
+ toast18({
28285
28285
  title: tr(
28286
28286
  "fluidgrids.builder.visualMapper.typeMismatchTitle",
28287
28287
  "Type mismatch warning"
@@ -28291,7 +28291,7 @@ function VisualMapperContent({
28291
28291
  });
28292
28292
  }
28293
28293
  } else {
28294
- toast17({
28294
+ toast18({
28295
28295
  title: tr(
28296
28296
  "fluidgrids.builder.visualMapper.invalidMappingTitle",
28297
28297
  "Invalid mapping"
@@ -28304,7 +28304,7 @@ function VisualMapperContent({
28304
28304
  });
28305
28305
  }
28306
28306
  },
28307
- [nodes, mapping, onMappingChange, toast17, tr, setEdges]
28307
+ [nodes, mapping, onMappingChange, toast18, tr, setEdges]
28308
28308
  );
28309
28309
  const onEdgeDelete = useCallback(
28310
28310
  (edge) => {
@@ -28361,7 +28361,7 @@ function VisualMapperContent({
28361
28361
  const handleSaveMappingDialog = (expression, targetFieldName) => {
28362
28362
  const targetPath = targetFieldName || selectedTargetNode?.data?.path;
28363
28363
  if (!targetPath) {
28364
- toast17({
28364
+ toast18({
28365
28365
  title: tr(
28366
28366
  "fluidgrids.builder.visualMapper.noTargetFieldTitle",
28367
28367
  "No target field specified"
@@ -28393,7 +28393,7 @@ function VisualMapperContent({
28393
28393
  }
28394
28394
  onMappingChange(updatedMapping);
28395
28395
  const mappingType = detectMappingType(expression);
28396
- toast17({
28396
+ toast18({
28397
28397
  title: `${mappingType.charAt(0).toUpperCase() + mappingType.slice(1)} mapping created`,
28398
28398
  description: `${tr("fluidgrids.builder.visualMapper.appliedMappingTo", "Applied mapping to")} ${targetPath}`
28399
28399
  });
@@ -28692,7 +28692,7 @@ function MappingEditor({
28692
28692
  setEdges,
28693
28693
  edgeId
28694
28694
  }) {
28695
- const { toast: toast17 } = useToast();
28695
+ const { toast: toast18 } = useToast();
28696
28696
  const tr = useTr();
28697
28697
  const [mappingJson, setMappingJson] = useState({});
28698
28698
  const [jsonDataString, setJsonDataString] = useState(
@@ -28816,7 +28816,7 @@ function MappingEditor({
28816
28816
  const handleSaveMapping = () => {
28817
28817
  try {
28818
28818
  checkJsonValidity();
28819
- toast17({
28819
+ toast18({
28820
28820
  title: tr(
28821
28821
  "fluidgrids.builder.mappingEditor.mappingSavedTitle",
28822
28822
  "Mapping saved"
@@ -28827,7 +28827,7 @@ function MappingEditor({
28827
28827
  )
28828
28828
  });
28829
28829
  } catch (error62) {
28830
- toast17({
28830
+ toast18({
28831
28831
  title: tr(
28832
28832
  "fluidgrids.builder.mappingEditor.errorSavingTitle",
28833
28833
  "Error saving mapping"
@@ -28846,7 +28846,7 @@ function MappingEditor({
28846
28846
  const parsedData = checkJsonValidity();
28847
28847
  const result = await applyMapping(parsedData, sampleInput);
28848
28848
  setPreviewOutput(result);
28849
- toast17({
28849
+ toast18({
28850
28850
  title: tr(
28851
28851
  "fluidgrids.builder.mappingEditor.mappingTestedTitle",
28852
28852
  "Mapping tested"
@@ -28858,7 +28858,7 @@ function MappingEditor({
28858
28858
  });
28859
28859
  } catch (error62) {
28860
28860
  console.error("Test mapping error:", error62);
28861
- toast17({
28861
+ toast18({
28862
28862
  title: tr(
28863
28863
  "fluidgrids.builder.mappingEditor.mappingTestFailedTitle",
28864
28864
  "Mapping test failed"
@@ -43055,10 +43055,17 @@ var ActivateWorkflowButton = ({
43055
43055
  });
43056
43056
  if (result) {
43057
43057
  setWorkflow({ status: result.status });
43058
- toast.success("Workflow activated", {
43059
- description: `Version ${result.version} is now ACTIVE. Future saves will create a new draft version.`,
43060
- dismissible: true
43061
- });
43058
+ if (result.status === "ACTIVE") {
43059
+ toast.success("Workflow activated", {
43060
+ description: `Version ${result.version} is now ACTIVE. Future saves will create a new draft version.`,
43061
+ dismissible: true
43062
+ });
43063
+ } else {
43064
+ toast.info("Activation is waiting for a replay check", {
43065
+ description: `Version ${result.version} activates once open auto-upgrade runs replay against it. See Versions.`,
43066
+ dismissible: true
43067
+ });
43068
+ }
43062
43069
  }
43063
43070
  } else {
43064
43071
  const result = await deactivateWorkflow(dbId);
@@ -43254,6 +43261,520 @@ function CurrentVersionAiBadge({ iconOnly }) {
43254
43261
  const facts = useCurrentVersionAuthoring();
43255
43262
  return /* @__PURE__ */ jsx(AiAuthoredBadge, { facts, iconOnly });
43256
43263
  }
43264
+ var DRAINAGE_VERSION_LIMIT = 10;
43265
+ async function fetchWorkflowVersioning(workflowKey) {
43266
+ const result = await getFluidGridsClient().query({
43267
+ query: WorkflowVersioningDocument,
43268
+ variables: { workflowKey },
43269
+ fetchPolicy: "network-only"
43270
+ });
43271
+ throwIfResultError(result);
43272
+ return {
43273
+ versions: result.data?.workflowVersions ?? [],
43274
+ rollouts: result.data?.workflowRollouts ?? []
43275
+ };
43276
+ }
43277
+ async function fetchVersionDrainage(workflowKey, version2) {
43278
+ const result = await getFluidGridsClient().query({
43279
+ query: WorkflowVersionDrainageDocument,
43280
+ variables: { workflowKey, version: version2 },
43281
+ fetchPolicy: "network-only"
43282
+ });
43283
+ throwIfResultError(result);
43284
+ return result.data?.workflowVersionDrainage ?? null;
43285
+ }
43286
+ async function saveWorkflowRollout(input2) {
43287
+ const result = await getFluidGridsClient().mutate({
43288
+ mutation: SetWorkflowRolloutDocument,
43289
+ variables: {
43290
+ workflowKey: input2.workflowKey,
43291
+ input: {
43292
+ fromVersion: input2.fromVersion ?? null,
43293
+ toVersion: input2.toVersion,
43294
+ percent: input2.percent,
43295
+ environment: "PROD" /* Prod */
43296
+ }
43297
+ }
43298
+ });
43299
+ throwIfResultError(result);
43300
+ const data = result.data?.setWorkflowRollout;
43301
+ if (!data) throw new Error("The rollout returned no result");
43302
+ return data;
43303
+ }
43304
+ async function removeWorkflowRollout(workflowKey) {
43305
+ const result = await getFluidGridsClient().mutate({
43306
+ mutation: DeleteWorkflowRolloutDocument,
43307
+ variables: { workflowKey, environment: "PROD" /* Prod */ }
43308
+ });
43309
+ throwIfResultError(result);
43310
+ return result.data?.deleteWorkflowRollout ?? false;
43311
+ }
43312
+ async function forceActivateVersion(id) {
43313
+ const result = await getFluidGridsClient().mutate({
43314
+ mutation: ActivateWorkflowVersionCheckedDocument,
43315
+ variables: { id, force: true },
43316
+ refetchQueries: ["WorkflowVersions", "WorkflowDefinitions"]
43317
+ });
43318
+ throwIfResultError(result);
43319
+ const data = result.data?.activateWorkflowDefinition;
43320
+ if (!data) throw new Error("Activation returned no result");
43321
+ return data;
43322
+ }
43323
+ function prodRollout(rollouts) {
43324
+ return rollouts.find(
43325
+ (rollout) => rollout.environment === "PROD" /* Prod */
43326
+ ) ?? null;
43327
+ }
43328
+ function isDurableDefinition(definitionJson) {
43329
+ if (!isRecord6(definitionJson)) return false;
43330
+ const code = definitionJson.code;
43331
+ if (!isRecord6(code) || typeof code.buildId !== "string") return false;
43332
+ const workflows = isRecord6(code.exports) ? code.exports.workflows : null;
43333
+ return isRecord6(workflows) && Object.keys(workflows).length > 0;
43334
+ }
43335
+ function isRecord6(value) {
43336
+ return typeof value === "object" && value !== null && !Array.isArray(value);
43337
+ }
43338
+ var EMPTY_STATE = {
43339
+ durable: false,
43340
+ byVersion: /* @__PURE__ */ new Map(),
43341
+ rollout: null,
43342
+ drainage: /* @__PURE__ */ new Map(),
43343
+ candidates: []
43344
+ };
43345
+ async function durableVersions(workflowKey, versions) {
43346
+ const flags = await Promise.all(
43347
+ versions.map(
43348
+ (version2) => loadDefinitionJson(workflowKey, version2).then(
43349
+ isDurableDefinition,
43350
+ () => false
43351
+ )
43352
+ )
43353
+ );
43354
+ return new Set(versions.filter((_, index) => flags[index]));
43355
+ }
43356
+ function useWorkflowVersioning(workflowKey, versions, enabled) {
43357
+ const [state, setState] = useState(EMPTY_STATE);
43358
+ const [error62, setError] = useState(null);
43359
+ const request = useRef(0);
43360
+ const reference = versions.find((entry) => entry.status === "ACTIVE") ?? versions[0];
43361
+ const newest = versions.slice(0, DRAINAGE_VERSION_LIMIT);
43362
+ const versionsKey = JSON.stringify({
43363
+ reference: reference ? { version: reference.version, status: reference.status ?? null } : null,
43364
+ newest: newest.map((entry) => [entry.version, entry.status ?? null])
43365
+ });
43366
+ const refetch = useCallback(async () => {
43367
+ if (!enabled || !workflowKey) return;
43368
+ const id = ++request.current;
43369
+ const parsed = JSON.parse(versionsKey);
43370
+ if (!parsed.reference) {
43371
+ setState(EMPTY_STATE);
43372
+ setError(null);
43373
+ return;
43374
+ }
43375
+ const active = parsed.reference.status === "ACTIVE" ? parsed.reference.version : null;
43376
+ const checked = [
43377
+ .../* @__PURE__ */ new Set([
43378
+ parsed.reference.version,
43379
+ ...parsed.newest.map(([version2]) => version2)
43380
+ ])
43381
+ ];
43382
+ try {
43383
+ const durable = await durableVersions(workflowKey, checked);
43384
+ if (id !== request.current) return;
43385
+ if (!durable.has(parsed.reference.version)) {
43386
+ setState(EMPTY_STATE);
43387
+ setError(null);
43388
+ return;
43389
+ }
43390
+ const drainable = parsed.newest.map(([version2]) => version2).filter((version2) => durable.has(version2));
43391
+ const [versioning, drained] = await Promise.all([
43392
+ fetchWorkflowVersioning(workflowKey),
43393
+ Promise.all(
43394
+ drainable.map(
43395
+ (version2) => fetchVersionDrainage(workflowKey, version2).catch(() => null)
43396
+ )
43397
+ )
43398
+ ]);
43399
+ if (id !== request.current) return;
43400
+ const drainage = /* @__PURE__ */ new Map();
43401
+ for (const entry of drained)
43402
+ if (entry) drainage.set(entry.version, entry);
43403
+ const checkedSet = new Set(checked);
43404
+ setState({
43405
+ durable: true,
43406
+ // A version known to be canvas gets no parity badges.
43407
+ byVersion: new Map(
43408
+ versioning.versions.filter(
43409
+ (entry) => !checkedSet.has(entry.version) || durable.has(entry.version)
43410
+ ).map((entry) => [entry.version, entry])
43411
+ ),
43412
+ rollout: prodRollout(versioning.rollouts),
43413
+ drainage,
43414
+ candidates: parsed.newest.filter(
43415
+ ([version2, status]) => status === "DRAFT" && version2 !== active && durable.has(version2)
43416
+ ).map(([version2]) => version2)
43417
+ });
43418
+ setError(null);
43419
+ } catch (err) {
43420
+ if (id !== request.current) return;
43421
+ setError(describeOperationError(err));
43422
+ }
43423
+ }, [enabled, workflowKey, versionsKey]);
43424
+ useEffect(() => {
43425
+ void refetch();
43426
+ }, [refetch]);
43427
+ return enabled ? { ...state, error: error62, refetch } : { ...EMPTY_STATE, error: null, refetch };
43428
+ }
43429
+ var CHECK_OPEN = /* @__PURE__ */ new Set([
43430
+ "PENDING" /* Pending */,
43431
+ "VERIFYING" /* Verifying */
43432
+ ]);
43433
+ function visibleActivationCheck(versioning) {
43434
+ const check2 = versioning?.activationCheck;
43435
+ if (!check2) return null;
43436
+ if (CHECK_OPEN.has(check2.status) || check2.status === "REJECTED" /* Rejected */)
43437
+ return check2;
43438
+ return null;
43439
+ }
43440
+ function showDrainage(drainage, isActive) {
43441
+ if (!drainage || isActive) return false;
43442
+ return drainage.status === "DRAINING" /* Draining */ || drainage.rolloutTarget || drainage.lastRunStartedAt !== null;
43443
+ }
43444
+ function VersionParityBadges({
43445
+ versioning,
43446
+ drainage,
43447
+ isActive
43448
+ }) {
43449
+ const tr = useTr();
43450
+ const check2 = visibleActivationCheck(versioning);
43451
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
43452
+ versioning?.versioningBehavior === "AUTO_UPGRADE" /* AutoUpgrade */ && /* @__PURE__ */ jsx(
43453
+ Badge,
43454
+ {
43455
+ variant: "outline",
43456
+ className: "h-5 px-1.5 py-0 text-[10px]",
43457
+ "data-testid": "version-behavior-badge",
43458
+ children: tr("fluidgrids.builder.versionHistory.autoUpgrade", "Auto-upgrade")
43459
+ }
43460
+ ),
43461
+ showDrainage(drainage, isActive) && /* @__PURE__ */ jsx(
43462
+ Badge,
43463
+ {
43464
+ variant: drainage.status === "DRAINING" /* Draining */ ? "secondary" : "outline",
43465
+ className: "h-5 px-1.5 py-0 text-[10px]",
43466
+ "data-testid": "version-drainage-badge",
43467
+ title: tr(
43468
+ "fluidgrids.builder.versionHistory.drainageTooltip",
43469
+ "Open durable-function runs this version's bundle serves"
43470
+ ),
43471
+ children: drainage.status === "DRAINING" /* Draining */ ? tr(
43472
+ "fluidgrids.builder.versionHistory.draining",
43473
+ "Draining \xB7 {{count}} open",
43474
+ { count: drainage.openRuns }
43475
+ ) : drainage.status === "ACTIVE" /* Active */ ? tr("fluidgrids.builder.versionHistory.rolloutTarget", "Rollout") : tr("fluidgrids.builder.versionHistory.drained", "Drained")
43476
+ }
43477
+ ),
43478
+ check2 && /* @__PURE__ */ jsx(
43479
+ Badge,
43480
+ {
43481
+ variant: check2.status === "REJECTED" /* Rejected */ ? "destructive" : "secondary",
43482
+ className: "h-5 px-1.5 py-0 text-[10px]",
43483
+ "data-testid": "version-activation-check",
43484
+ children: check2.status === "REJECTED" /* Rejected */ ? tr(
43485
+ "fluidgrids.builder.versionHistory.checkRejected",
43486
+ "Activation check failed"
43487
+ ) : tr(
43488
+ "fluidgrids.builder.versionHistory.checkRunning",
43489
+ "Activation check running"
43490
+ )
43491
+ }
43492
+ )
43493
+ ] });
43494
+ }
43495
+ function RolloutControl({
43496
+ workflowKey,
43497
+ activeVersion,
43498
+ candidates,
43499
+ rollout,
43500
+ canPublish,
43501
+ onChanged
43502
+ }) {
43503
+ const tr = useTr();
43504
+ const [toVersion, setToVersion] = useState(rollout?.toVersion ?? "");
43505
+ const [percent, setPercent] = useState(rollout?.percent ?? 0);
43506
+ const [saving, setSaving] = useState(false);
43507
+ const [confirmPromote, setConfirmPromote] = useState(false);
43508
+ useEffect(() => {
43509
+ setToVersion(rollout?.toVersion ?? "");
43510
+ setPercent(rollout?.percent ?? 0);
43511
+ }, [rollout?.toVersion, rollout?.percent]);
43512
+ if (!activeVersion || !rollout && candidates.length === 0) return null;
43513
+ const targets = rollout && !candidates.includes(rollout.toVersion) ? [rollout.toVersion, ...candidates] : [...candidates];
43514
+ const unchanged = !!rollout && rollout.toVersion === toVersion && rollout.percent === percent;
43515
+ const locked = !canPublish || saving;
43516
+ const check2 = rollout?.activationCheck;
43517
+ const save = async () => {
43518
+ setSaving(true);
43519
+ try {
43520
+ const saved = await saveWorkflowRollout({
43521
+ workflowKey,
43522
+ toVersion,
43523
+ percent
43524
+ });
43525
+ toast.success(
43526
+ saved.promoted ? tr(
43527
+ "fluidgrids.builder.versionHistory.rolloutPromoted",
43528
+ "Promotion started"
43529
+ ) : tr(
43530
+ "fluidgrids.builder.versionHistory.rolloutSaved",
43531
+ "Rollout saved"
43532
+ )
43533
+ );
43534
+ onChanged();
43535
+ } catch (error62) {
43536
+ toast.error(
43537
+ tr(
43538
+ "fluidgrids.builder.versionHistory.rolloutError",
43539
+ "Could not save the rollout"
43540
+ ),
43541
+ { description: describeOperationError(error62) }
43542
+ );
43543
+ } finally {
43544
+ setSaving(false);
43545
+ setConfirmPromote(false);
43546
+ }
43547
+ };
43548
+ const remove = async () => {
43549
+ setSaving(true);
43550
+ try {
43551
+ await removeWorkflowRollout(workflowKey);
43552
+ toast.success(
43553
+ tr(
43554
+ "fluidgrids.builder.versionHistory.rolloutRemoved",
43555
+ "Rollout removed"
43556
+ )
43557
+ );
43558
+ onChanged();
43559
+ } catch (error62) {
43560
+ toast.error(
43561
+ tr(
43562
+ "fluidgrids.builder.versionHistory.rolloutError",
43563
+ "Could not save the rollout"
43564
+ ),
43565
+ { description: describeOperationError(error62) }
43566
+ );
43567
+ } finally {
43568
+ setSaving(false);
43569
+ }
43570
+ };
43571
+ return /* @__PURE__ */ jsxs(
43572
+ "section",
43573
+ {
43574
+ className: "mb-4 rounded-lg border border-border bg-card p-3",
43575
+ "aria-label": tr(
43576
+ "fluidgrids.builder.versionHistory.rolloutTitle",
43577
+ "Gradual rollout"
43578
+ ),
43579
+ "data-testid": "version-rollout",
43580
+ children: [
43581
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2 text-sm font-semibold", children: [
43582
+ /* @__PURE__ */ jsx(SlidersHorizontal, { className: "size-4" }),
43583
+ tr(
43584
+ "fluidgrids.builder.versionHistory.rolloutTitle",
43585
+ "Gradual rollout"
43586
+ )
43587
+ ] }),
43588
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-muted-foreground", children: tr(
43589
+ "fluidgrids.builder.versionHistory.rolloutHint",
43590
+ "A share of new automatic starts runs another version instead of {{version}}.",
43591
+ { version: activeVersion }
43592
+ ) }),
43593
+ /* @__PURE__ */ jsxs(
43594
+ "select",
43595
+ {
43596
+ value: toVersion,
43597
+ onChange: (event) => setToVersion(event.target.value),
43598
+ disabled: locked,
43599
+ className: "mb-2 h-8 w-full rounded-md border border-border bg-background px-2 text-xs",
43600
+ "aria-label": tr(
43601
+ "fluidgrids.builder.versionHistory.rolloutTarget",
43602
+ "Rollout"
43603
+ ),
43604
+ "data-testid": "version-rollout-target",
43605
+ children: [
43606
+ /* @__PURE__ */ jsx("option", { value: "", children: tr(
43607
+ "fluidgrids.builder.versionHistory.rolloutChoose",
43608
+ "Choose a version"
43609
+ ) }),
43610
+ targets.map((version2) => /* @__PURE__ */ jsx("option", { value: version2, children: version2 }, version2))
43611
+ ]
43612
+ }
43613
+ ),
43614
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
43615
+ /* @__PURE__ */ jsx(
43616
+ "input",
43617
+ {
43618
+ type: "range",
43619
+ min: 0,
43620
+ max: 100,
43621
+ step: 1,
43622
+ value: percent,
43623
+ disabled: locked || !toVersion,
43624
+ onChange: (event) => setPercent(Number(event.target.value)),
43625
+ className: "min-w-0 flex-1 accent-primary",
43626
+ "aria-label": tr(
43627
+ "fluidgrids.builder.versionHistory.rolloutPercent",
43628
+ "Share of new starts"
43629
+ ),
43630
+ "data-testid": "version-rollout-percent"
43631
+ }
43632
+ ),
43633
+ /* @__PURE__ */ jsxs("span", { className: "w-10 text-right font-mono text-xs", children: [
43634
+ percent,
43635
+ "%"
43636
+ ] })
43637
+ ] }),
43638
+ rollout && /* @__PURE__ */ jsxs(
43639
+ "p",
43640
+ {
43641
+ className: "mt-1 text-[11px] text-muted-foreground",
43642
+ "data-testid": "version-rollout-verified",
43643
+ children: [
43644
+ tr(
43645
+ "fluidgrids.builder.versionHistory.rolloutVerified",
43646
+ "In-flight auto-upgrade runs follow {{verified}}% (replay-checked)",
43647
+ { verified: rollout.verifiedPercent }
43648
+ ),
43649
+ check2 && (check2.status === "PENDING" /* Pending */ || check2.status === "VERIFYING" /* Verifying */) ? ` \xB7 ${tr("fluidgrids.builder.versionHistory.checkRunning", "Activation check running")}` : ""
43650
+ ]
43651
+ }
43652
+ ),
43653
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex gap-2", children: [
43654
+ /* @__PURE__ */ jsxs(
43655
+ Button$1,
43656
+ {
43657
+ "data-agent": "confirm",
43658
+ size: "sm",
43659
+ variant: "secondary",
43660
+ className: "flex-1",
43661
+ disabled: locked || !toVersion || unchanged,
43662
+ onClick: () => percent === 100 ? setConfirmPromote(true) : void save(),
43663
+ "data-testid": "version-rollout-save",
43664
+ children: [
43665
+ saving && /* @__PURE__ */ jsx(Loader2, { className: "mr-2 size-3.5 animate-spin" }),
43666
+ tr("fluidgrids.builder.versionHistory.rolloutSave", "Save rollout")
43667
+ ]
43668
+ }
43669
+ ),
43670
+ rollout && /* @__PURE__ */ jsx(
43671
+ Button$1,
43672
+ {
43673
+ "data-agent": "confirm",
43674
+ size: "sm",
43675
+ variant: "ghost",
43676
+ disabled: locked,
43677
+ onClick: () => void remove(),
43678
+ "aria-label": tr(
43679
+ "fluidgrids.builder.versionHistory.rolloutRemove",
43680
+ "Remove rollout"
43681
+ ),
43682
+ "data-testid": "version-rollout-remove",
43683
+ children: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" })
43684
+ }
43685
+ )
43686
+ ] }),
43687
+ /* @__PURE__ */ jsx(AlertDialog, { open: confirmPromote, onOpenChange: setConfirmPromote, children: /* @__PURE__ */ jsxs(AlertDialogContent, { className: "z-[120]", children: [
43688
+ /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
43689
+ /* @__PURE__ */ jsx(AlertDialogTitle, { children: tr(
43690
+ "fluidgrids.builder.versionHistory.promoteTitle",
43691
+ "Promote {{version}}?",
43692
+ { version: toVersion }
43693
+ ) }),
43694
+ /* @__PURE__ */ jsx(AlertDialogDescription, { children: tr(
43695
+ "fluidgrids.builder.versionHistory.promoteBody",
43696
+ "At 100% the version becomes the active one once open auto-upgrade runs replay against it, and the rollout is removed."
43697
+ ) })
43698
+ ] }),
43699
+ /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
43700
+ /* @__PURE__ */ jsx(AlertDialogCancel, { disabled: saving, children: tr(
43701
+ "fluidgrids.builder.versionHistory.deleteDialogCancel",
43702
+ "Cancel"
43703
+ ) }),
43704
+ /* @__PURE__ */ jsx(
43705
+ AlertDialogAction,
43706
+ {
43707
+ "data-agent": "confirm",
43708
+ disabled: saving,
43709
+ onClick: () => void save(),
43710
+ children: tr(
43711
+ "fluidgrids.builder.versionHistory.promoteConfirm",
43712
+ "Promote"
43713
+ )
43714
+ }
43715
+ )
43716
+ ] })
43717
+ ] }) })
43718
+ ]
43719
+ }
43720
+ );
43721
+ }
43722
+ function ForceActivateDialog({
43723
+ version: version2,
43724
+ violations,
43725
+ busy,
43726
+ onConfirm,
43727
+ onCancel
43728
+ }) {
43729
+ const tr = useTr();
43730
+ return /* @__PURE__ */ jsx(
43731
+ AlertDialog,
43732
+ {
43733
+ open: version2 !== null,
43734
+ onOpenChange: (open2) => !open2 && onCancel(),
43735
+ children: /* @__PURE__ */ jsxs(
43736
+ AlertDialogContent,
43737
+ {
43738
+ className: "z-[120]",
43739
+ "data-testid": "force-activate-dialog",
43740
+ children: [
43741
+ /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
43742
+ /* @__PURE__ */ jsx(AlertDialogTitle, { children: tr(
43743
+ "fluidgrids.builder.versionHistory.forceTitle",
43744
+ "Activate {{version}} anyway?",
43745
+ { version: version2 ?? "" }
43746
+ ) }),
43747
+ /* @__PURE__ */ jsx(AlertDialogDescription, { children: tr(
43748
+ "fluidgrids.builder.versionHistory.forceBody",
43749
+ "{{count}} open auto-upgrade runs did not replay against this version. They keep failing their workflow task until a fix ships. The activation is audited.",
43750
+ { count: violations }
43751
+ ) })
43752
+ ] }),
43753
+ /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
43754
+ /* @__PURE__ */ jsx(AlertDialogCancel, { disabled: busy, children: tr(
43755
+ "fluidgrids.builder.versionHistory.deleteDialogCancel",
43756
+ "Cancel"
43757
+ ) }),
43758
+ /* @__PURE__ */ jsx(
43759
+ AlertDialogAction,
43760
+ {
43761
+ "data-agent": "confirm",
43762
+ disabled: busy,
43763
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
43764
+ onClick: onConfirm,
43765
+ children: tr(
43766
+ "fluidgrids.builder.versionHistory.forceConfirm",
43767
+ "Activate anyway"
43768
+ )
43769
+ }
43770
+ )
43771
+ ] })
43772
+ ]
43773
+ }
43774
+ )
43775
+ }
43776
+ );
43777
+ }
43257
43778
  function relativeTime(dateStr) {
43258
43779
  if (!dateStr) return "";
43259
43780
  const then = new Date(dateStr).getTime();
@@ -43365,6 +43886,18 @@ function VersionHistoryPanel({
43365
43886
  const [compareLoading, setCompareLoading] = useState(false);
43366
43887
  const [busy, setBusy] = useState(null);
43367
43888
  const [deleteTarget, setDeleteTarget] = useState(null);
43889
+ const parityEnabled = useDurableParityEnabled();
43890
+ const { allowed: canPublish } = useFluidGridsPermission(
43891
+ FLUIDGRIDS_PERMISSIONS.WORKFLOW_PUBLISH
43892
+ );
43893
+ const versioning = useWorkflowVersioning(
43894
+ workflowKey,
43895
+ versions,
43896
+ parityEnabled
43897
+ );
43898
+ const refetchVersioning = versioning.refetch;
43899
+ const [forceTarget, setForceTarget] = useState(null);
43900
+ const activeVersion = versions.find((entry) => entry.status === "ACTIVE")?.version ?? null;
43368
43901
  useEffect(() => {
43369
43902
  if (versions.length < 2) {
43370
43903
  setCompareFrom("");
@@ -43470,6 +44003,23 @@ function VersionHistoryPanel({
43470
44003
  try {
43471
44004
  const result = await activateWorkflow(id);
43472
44005
  if (!result) throw new Error("Activation returned no result");
44006
+ if (result.status !== "ACTIVE") {
44007
+ toast.info(
44008
+ tr(
44009
+ "fluidgrids.builder.versionHistory.activationHeld",
44010
+ "Activation is waiting for a replay check"
44011
+ ),
44012
+ {
44013
+ description: tr(
44014
+ "fluidgrids.builder.versionHistory.activationHeldDescription",
44015
+ "Open auto-upgrade runs replay against this version first."
44016
+ ),
44017
+ dismissible: true
44018
+ }
44019
+ );
44020
+ await Promise.all([refetch(), refetchVersioning()]);
44021
+ return;
44022
+ }
43473
44023
  toast.success(`Version ${version2} is now ACTIVE`, {
43474
44024
  description: tr(
43475
44025
  "fluidgrids.builder.versionHistory.activateSuccessDescription",
@@ -43502,6 +44052,35 @@ function VersionHistoryPanel({
43502
44052
  setBusy(null);
43503
44053
  }
43504
44054
  };
44055
+ const handleForceActivate = async () => {
44056
+ if (!forceTarget) return;
44057
+ const { id, version: version2 } = forceTarget;
44058
+ setBusy(`activate:${version2}`);
44059
+ try {
44060
+ const result = await forceActivateVersion(id);
44061
+ toast.success(`Version ${version2} is now ${result.status}`, {
44062
+ dismissible: true
44063
+ });
44064
+ if (version2 === currentVersion) setWorkflow({ status: result.status });
44065
+ await Promise.all([refetch(), refetchVersioning()]);
44066
+ } catch (error62) {
44067
+ toast.error(
44068
+ tr(
44069
+ "fluidgrids.builder.versionHistory.activateErrorTitle",
44070
+ "Failed to activate version"
44071
+ ),
44072
+ {
44073
+ description: error62 instanceof Error ? error62.message : tr(
44074
+ "fluidgrids.builder.versionHistory.activateUnknownError",
44075
+ "Unknown error"
44076
+ )
44077
+ }
44078
+ );
44079
+ } finally {
44080
+ setBusy(null);
44081
+ setForceTarget(null);
44082
+ }
44083
+ };
43505
44084
  const handleDelete = async (version2) => {
43506
44085
  setBusy(`delete:${version2}`);
43507
44086
  try {
@@ -43546,7 +44125,10 @@ function VersionHistoryPanel({
43546
44125
  "fluidgrids.builder.versionHistory.triggerButton",
43547
44126
  "Versions"
43548
44127
  ) : void 0,
43549
- onClick: () => refetch(),
44128
+ onClick: () => {
44129
+ void refetch();
44130
+ void refetchVersioning();
44131
+ },
43550
44132
  children: [
43551
44133
  /* @__PURE__ */ jsx(History, { className: "size-4" }),
43552
44134
  !compact && tr("fluidgrids.builder.versionHistory.triggerButton", "Versions")
@@ -43574,6 +44156,20 @@ function VersionHistoryPanel({
43574
44156
  ] })
43575
44157
  ] }),
43576
44158
  /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs("div", { className: "mt-4 overflow-y-auto max-h-[calc(100vh-140px)] pr-1", children: [
44159
+ parityEnabled && versioning.durable && !loading && /* @__PURE__ */ jsx(
44160
+ RolloutControl,
44161
+ {
44162
+ workflowKey,
44163
+ activeVersion,
44164
+ candidates: versioning.candidates,
44165
+ rollout: versioning.rollout,
44166
+ canPublish,
44167
+ onChanged: () => {
44168
+ void refetch();
44169
+ void refetchVersioning();
44170
+ }
44171
+ }
44172
+ ),
43577
44173
  !loading && versions.length > 1 && /* @__PURE__ */ jsxs(
43578
44174
  "section",
43579
44175
  {
@@ -43786,7 +44382,15 @@ function VersionHistoryPanel({
43786
44382
  ]
43787
44383
  }
43788
44384
  ),
43789
- /* @__PURE__ */ jsx(AiAuthoredBadge, { facts: v })
44385
+ /* @__PURE__ */ jsx(AiAuthoredBadge, { facts: v }),
44386
+ parityEnabled && versioning.durable && /* @__PURE__ */ jsx(
44387
+ VersionParityBadges,
44388
+ {
44389
+ versioning: versioning.byVersion.get(v.version),
44390
+ drainage: versioning.drainage.get(v.version),
44391
+ isActive
44392
+ }
44393
+ )
43790
44394
  ] }),
43791
44395
  /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center", children: [
43792
44396
  !isCurrent && /* @__PURE__ */ jsx(
@@ -43815,6 +44419,26 @@ function VersionHistoryPanel({
43815
44419
  onClick: () => handleActivate(v.id, v.version)
43816
44420
  }
43817
44421
  ),
44422
+ parityEnabled && versioning.durable && canPublish && !isActive && visibleActivationCheck(
44423
+ versioning.byVersion.get(v.version)
44424
+ )?.status === "REJECTED" /* Rejected */ && /* @__PURE__ */ jsx(
44425
+ ActionButton,
44426
+ {
44427
+ confirm: true,
44428
+ destructive: true,
44429
+ label: tr(
44430
+ "fluidgrids.builder.versionHistory.actionForce",
44431
+ "Activate anyway"
44432
+ ),
44433
+ icon: /* @__PURE__ */ jsx(Play, { className: "size-3.5" }),
44434
+ disabled: busy !== null,
44435
+ onClick: () => setForceTarget({
44436
+ id: v.id,
44437
+ version: v.version,
44438
+ violations: versioning.byVersion.get(v.version)?.activationCheck?.violations.length ?? 0
44439
+ })
44440
+ }
44441
+ ),
43818
44442
  !isCurrent && /* @__PURE__ */ jsx(
43819
44443
  ActionButton,
43820
44444
  {
@@ -43863,6 +44487,16 @@ function VersionHistoryPanel({
43863
44487
  }) })
43864
44488
  ] }) })
43865
44489
  ] }),
44490
+ parityEnabled && /* @__PURE__ */ jsx(
44491
+ ForceActivateDialog,
44492
+ {
44493
+ version: forceTarget?.version ?? null,
44494
+ violations: forceTarget?.violations ?? 0,
44495
+ busy: busy !== null,
44496
+ onConfirm: () => void handleForceActivate(),
44497
+ onCancel: () => setForceTarget(null)
44498
+ }
44499
+ ),
43866
44500
  /* @__PURE__ */ jsx(
43867
44501
  AlertDialog,
43868
44502
  {
@@ -45949,23 +46583,23 @@ function useAiWorkflowTemplates(enabled) {
45949
46583
 
45950
46584
  // src/builder/lib/ai-draft.ts
45951
46585
  var AI_DRAFT_MAX_PROMPT_LENGTH = 4e3;
45952
- function isRecord6(value) {
46586
+ function isRecord7(value) {
45953
46587
  return typeof value === "object" && value !== null && !Array.isArray(value);
45954
46588
  }
45955
46589
  function stringOr(value, fallback) {
45956
46590
  return typeof value === "string" && value.trim() !== "" ? value : fallback;
45957
46591
  }
45958
46592
  function draftToCanvas(definitionJson) {
45959
- const data = isRecord6(definitionJson) && isRecord6(definitionJson.data) ? definitionJson.data : {};
46593
+ const data = isRecord7(definitionJson) && isRecord7(definitionJson.data) ? definitionJson.data : {};
45960
46594
  const rawNodes = Array.isArray(data.nodes) ? data.nodes : [];
45961
46595
  const rawEdges = Array.isArray(data.edges) ? data.edges : [];
45962
- const nodes = rawNodes.filter(isRecord6).flatMap((raw) => {
46596
+ const nodes = rawNodes.filter(isRecord7).flatMap((raw) => {
45963
46597
  if (typeof raw.id !== "string" || typeof raw.type !== "string") return [];
45964
- const position = isRecord6(raw.position) ? {
46598
+ const position = isRecord7(raw.position) ? {
45965
46599
  x: typeof raw.position.x === "number" ? raw.position.x : 0,
45966
46600
  y: typeof raw.position.y === "number" ? raw.position.y : 0
45967
46601
  } : { x: 0, y: 0 };
45968
- const nodeData = isRecord6(raw.data) ? raw.data : {};
46602
+ const nodeData = isRecord7(raw.data) ? raw.data : {};
45969
46603
  const node2 = {
45970
46604
  ...raw,
45971
46605
  id: raw.id,
@@ -45977,7 +46611,7 @@ function draftToCanvas(definitionJson) {
45977
46611
  return [node2];
45978
46612
  });
45979
46613
  const ids = new Set(nodes.map((node2) => node2.id));
45980
- const edges = rawEdges.filter(isRecord6).flatMap((raw) => {
46614
+ const edges = rawEdges.filter(isRecord7).flatMap((raw) => {
45981
46615
  if (typeof raw.source !== "string" || typeof raw.target !== "string") {
45982
46616
  return [];
45983
46617
  }
@@ -45996,7 +46630,7 @@ function draftToCanvas(definitionJson) {
45996
46630
  }
45997
46631
  function enrichDraftNodes(nodes, seed) {
45998
46632
  return nodes.map((node2) => {
45999
- const data = isRecord6(node2.data) ? node2.data : {};
46633
+ const data = isRecord7(node2.data) ? node2.data : {};
46000
46634
  const rootOperation = node2.operation_name;
46001
46635
  let operationName;
46002
46636
  if (typeof data.operation_name === "string") {
@@ -46007,10 +46641,10 @@ function enrichDraftNodes(nodes, seed) {
46007
46641
  if (!node2.type || !operationName) return node2;
46008
46642
  const seeded = seed(node2.type, operationName, data);
46009
46643
  if (!seeded) return node2;
46010
- const seededArgs = isRecord6(seeded.args) ? seeded.args : {};
46011
- const defaults = isRecord6(seededArgs.state) ? seededArgs.state : {};
46012
- const draftArgs = isRecord6(data.args) ? data.args : {};
46013
- const draftState = isRecord6(draftArgs.state) ? draftArgs.state : {};
46644
+ const seededArgs = isRecord7(seeded.args) ? seeded.args : {};
46645
+ const defaults = isRecord7(seededArgs.state) ? seededArgs.state : {};
46646
+ const draftArgs = isRecord7(data.args) ? data.args : {};
46647
+ const draftState = isRecord7(draftArgs.state) ? draftArgs.state : {};
46014
46648
  return {
46015
46649
  ...node2,
46016
46650
  data: {