@burdenoff/fluidgrids-fe-sdk 2026.1029.7 → 2026.1029.8

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 (41) hide show
  1. package/dist/{ExecutionDetailPage-L7LZYFOT.js → ExecutionDetailPage-H6R3ZIXN.js} +10 -10
  2. package/dist/{ExecutionsListPage-7NMW6S5A.js → ExecutionsListPage-TLD2E442.js} +7 -7
  3. package/dist/{WorkflowBuilder-RXVUBDZJ.js → WorkflowBuilder-XVHY7XWJ.js} +10 -10
  4. package/dist/{WorkflowsList-5U74DYQ3.js → WorkflowsList-3GXXXURR.js} +7 -7
  5. package/dist/{chunk-FFOZ5VUJ.js → chunk-2NG5VZWI.js} +1 -1
  6. package/dist/{chunk-BZTVAUOQ.js → chunk-6CKDGT2N.js} +3 -3
  7. package/dist/{chunk-OJPJ2QXD.js → chunk-G3KZOX52.js} +2 -2
  8. package/dist/{chunk-YTUIGIVP.js → chunk-GQTEHWWY.js} +12 -8
  9. package/dist/{chunk-TYYSYSAL.js → chunk-H4AZBUWM.js} +1 -1
  10. package/dist/{chunk-AXMEATLG.js → chunk-HWEKWYXQ.js} +2 -2
  11. package/dist/{chunk-RZR3BDDZ.js → chunk-LJGC7RAL.js} +162 -99
  12. package/dist/{chunk-K4BF7PAW.js → chunk-NAYPOEYM.js} +290 -27
  13. package/dist/{chunk-VIZ7W5WJ.js → chunk-NNPXN4DI.js} +5 -5
  14. package/dist/{chunk-4MHWFZJV.js → chunk-NUBPALBK.js} +1 -1
  15. package/dist/{chunk-US4LPOB3.js → chunk-R7VHURPQ.js} +1 -1
  16. package/dist/{chunk-DEGCZCHP.js → chunk-S4JYBJ4X.js} +2 -2
  17. package/dist/{chunk-IDGDMJMJ.js → chunk-T22LICGX.js} +3 -3
  18. package/dist/{chunk-HAFUSBYP.js → chunk-TJ6RUV4R.js} +8 -8
  19. package/dist/{chunk-NL4JQFFA.js → chunk-UIDJT3YK.js} +1 -1
  20. package/dist/{chunk-7CTIVBBA.js → chunk-UWNCFMHV.js} +4 -4
  21. package/dist/{chunk-ZE5KS2YL.js → chunk-V5PA5KGV.js} +2 -2
  22. package/dist/{chunk-SZTKLZZR.js → chunk-VEZ7G2FE.js} +4 -4
  23. package/dist/{chunk-Z4YQTXCD.js → chunk-WEXO3KAY.js} +4 -4
  24. package/dist/{chunk-E7UAY3JJ.js → chunk-WTP343PG.js} +1 -1
  25. package/dist/{chunk-EGIEFGOV.js → chunk-X2J4ZXKD.js} +822 -62
  26. package/dist/{chunk-KANARCPR.js → chunk-XJBCRDWZ.js} +3 -3
  27. package/dist/{chunk-6SZXW2BF.js → chunk-XMKYZP6Q.js} +32 -15
  28. package/dist/{chunk-LAVHDFHI.js → chunk-Z6I6A47T.js} +1 -1
  29. package/dist/executions.js +11 -11
  30. package/dist/history.js +4 -4
  31. package/dist/index.d.ts +76 -3
  32. package/dist/index.js +34 -34
  33. package/dist/nodes.js +2 -2
  34. package/dist/observability.js +5 -5
  35. package/dist/settings.js +6 -6
  36. package/dist/templates.js +9 -9
  37. package/dist/{workflow-builder-CZFczcE7.d.ts → workflow-builder-BMGVSwpy.d.ts} +7 -0
  38. package/dist/workflow-builder.d.ts +1 -1
  39. package/dist/workflow-builder.js +11 -11
  40. package/dist/workflows-list.js +7 -7
  41. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { NodeEndpointConfigsDocument, NodeEndpointConfigDocument, NodeManifestDocument, fetchAllNodeEndpointConfigs } from './chunk-YTUIGIVP.js';
1
+ import { NodeEndpointConfigsDocument, NodeEndpointConfigDocument, NodeManifestDocument, fetchAllNodeEndpointConfigs } from './chunk-GQTEHWWY.js';
2
2
  import { useTr } from './chunk-UULVIT25.js';
3
3
  import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
4
4
  import { useMemo, useState, useCallback, useEffect } from 'react';
@@ -1,7 +1,7 @@
1
1
  import { REPLAY_WORKFLOW_RUN, RETRY_WORKFLOW_RUNS } from './chunk-5ERAJC2I.js';
2
- import { useFluidGridsAnalytics, throwIfResultError, emitRunStarted, openRunQuotaUpgradePrompt } from './chunk-K4BF7PAW.js';
2
+ import { useFluidGridsAnalytics, throwIfResultError, emitRunStarted, openRunQuotaUpgradePrompt } from './chunk-NAYPOEYM.js';
3
3
  import { useExecutionsStore } from './chunk-6AMNEX2Y.js';
4
- import { ExecutionsListDocument, ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument } from './chunk-YTUIGIVP.js';
4
+ import { ExecutionsListDocument, ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument } from './chunk-GQTEHWWY.js';
5
5
  import { useTr } from './chunk-UULVIT25.js';
6
6
  import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
7
7
  import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
@@ -1,18 +1,18 @@
1
- import { isGuidedTourIntent, pickGuidedTour, withoutGuidedTourIntent, isCreateIntent, CreateWorkflowRefusalDialog, decideMissingWorkflow } from './chunk-FFOZ5VUJ.js';
1
+ import { isGuidedTourIntent, pickGuidedTour, withoutGuidedTourIntent, isCreateIntent, CreateWorkflowRefusalDialog, decideMissingWorkflow } from './chunk-2NG5VZWI.js';
2
2
  import { registerLiveCanvasHandler } from './chunk-PIKYQE7P.js';
3
- import { useInstalledNodes, buildNodeCheck, FlowBuilderPage, buildRequiredNodeTypes } from './chunk-EGIEFGOV.js';
4
- import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-OJPJ2QXD.js';
5
- import { useFlowStore, refetchStoreNodes, BILLING_PLANS_PATH, codeBuildIdOf, mergeStickyNotes, blankWorkflowCreateInput, classifyCreateRefusal, useSaveStatusStore, workflowFingerprint, registerWorkflowNodeTypes, throwIfResultError } from './chunk-K4BF7PAW.js';
3
+ import { useWorkflowReloadStore, releaseLeaseKeptForReload, useInstalledNodes, buildNodeCheck, FlowBuilderPage, buildRequiredNodeTypes } from './chunk-X2J4ZXKD.js';
4
+ import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-G3KZOX52.js';
5
+ import { useFlowStore, refetchStoreNodes, BILLING_PLANS_PATH, codeBuildIdOf, mergeStickyNotes, rememberRevision, blankWorkflowCreateInput, classifyCreateRefusal, useSaveStatusStore, workflowFingerprint, registerWorkflowNodeTypes, throwIfResultError } from './chunk-NAYPOEYM.js';
6
6
  import { getFluidGridsConfig } from './chunk-6AMNEX2Y.js';
7
- import { WorkflowDefinitionDocument } from './chunk-YTUIGIVP.js';
7
+ import { WorkflowDefinitionDocument } from './chunk-GQTEHWWY.js';
8
8
  import { useTr } from './chunk-UULVIT25.js';
9
9
  import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
10
10
  import { useLocation, useNavigate, useParams } from 'react-router';
11
11
  import { toast } from 'sonner';
12
12
  import { Icon } from '@iconify/react';
13
13
  import { lazy, useRef, useEffect, useState, useCallback, useMemo, Suspense } from 'react';
14
- import { useSafeToursContext, usePlayTour } from '@burdenoff/fe-libs/shared/tours';
15
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
+ import { useSafeToursContext, usePlayTour } from '@burdenoff/fe-libs/shared/tours';
16
16
  import { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';
17
17
  import '@xyflow/react/dist/style.css';
18
18
 
@@ -653,7 +653,11 @@ function AssistantLiveCanvasHost() {
653
653
  fetchDefinition,
654
654
  registerNodeTypes: registerWorkflowNodeTypes,
655
655
  notify,
656
- workspaceId: () => getFluidGridsConfig().workspaceId || null
656
+ workspaceId: () => getFluidGridsConfig().workspaceId || null,
657
+ // The merged canvas now holds the stored version, assistant write
658
+ // included, so the next save is based on its revision (BOFF-9725)
659
+ // rather than refused as stale over a change already on screen.
660
+ onSynced: (remote) => rememberRevision(remote.id, remote.revision)
657
661
  });
658
662
  const stopWatching = watchCanvasBase();
659
663
  const unregister = registerLiveCanvasHandler(sync.handle);
@@ -664,6 +668,48 @@ function AssistantLiveCanvasHost() {
664
668
  }, []);
665
669
  return null;
666
670
  }
671
+ function LoadProblem({
672
+ title,
673
+ description,
674
+ retryLabel,
675
+ onRetry,
676
+ backLabel,
677
+ onBack,
678
+ testId
679
+ }) {
680
+ return /* @__PURE__ */ jsxs(
681
+ "div",
682
+ {
683
+ role: "alert",
684
+ "data-testid": testId,
685
+ className: "flex h-full min-h-[60vh] w-full flex-col items-center justify-center gap-3 p-6 text-center",
686
+ children: [
687
+ /* @__PURE__ */ jsx("p", { className: "text-base font-medium text-foreground", children: title }),
688
+ /* @__PURE__ */ jsx("p", { className: "max-w-md text-sm text-foreground/60", children: description }),
689
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
690
+ /* @__PURE__ */ jsx(
691
+ "button",
692
+ {
693
+ type: "button",
694
+ className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
695
+ onClick: onRetry,
696
+ children: retryLabel
697
+ }
698
+ ),
699
+ /* @__PURE__ */ jsx(
700
+ "button",
701
+ {
702
+ type: "button",
703
+ className: "rounded-md border px-4 py-2 text-sm font-medium text-foreground",
704
+ onClick: onBack,
705
+ children: backLabel
706
+ }
707
+ )
708
+ ] })
709
+ ]
710
+ }
711
+ );
712
+ }
667
713
  var START_DELAY_MS = 800;
668
714
  function StartGuidedTour() {
669
715
  const location = useLocation();
@@ -736,11 +782,17 @@ function WorkflowItem({
736
782
  const [createRefusal, setCreateRefusal] = useState(null);
737
783
  const upgradingRef = useRef(false);
738
784
  const resetWorkflow = useFlowStore((s) => s.actions.resetWorkflow);
785
+ const reloadNonce = useWorkflowReloadStore((s) => s.nonce);
786
+ useEffect(() => () => releaseLeaseKeptForReload(), [id, version]);
787
+ const seenReloadNonceRef = useRef(reloadNonce);
788
+ const pendingReloadRef = useRef(null);
789
+ const [reloadFailed, setReloadFailed] = useState(false);
739
790
  const { getWorkflow } = useLazyWorkflowDefinition();
740
791
  const { createWorkflow } = useCreateWorkflow();
741
792
  const creatingRef = useRef(false);
742
793
  const fromSharedLoadedRef = useRef(false);
743
794
  const fetchedWorkflowRef = useRef(null);
795
+ const loadSeqRef = useRef(0);
744
796
  const { installedAppIds } = useInstalledNodes();
745
797
  const [pendingWorkflow, setPendingWorkflow] = useState(null);
746
798
  const [nodeCheck, setNodeCheck] = useState(
@@ -843,11 +895,27 @@ function WorkflowItem({
843
895
  );
844
896
  useEffect(() => {
845
897
  let mounted = true;
898
+ const target = `${id ?? ""}@${version ?? ""}`;
899
+ loadSeqRef.current += 1;
900
+ const loadSeq = loadSeqRef.current;
901
+ if (reloadNonce !== seenReloadNonceRef.current) {
902
+ seenReloadNonceRef.current = reloadNonce;
903
+ pendingReloadRef.current = target;
904
+ }
905
+ const reloadPending = () => pendingReloadRef.current === target;
906
+ const fetchedCopy = () => fetchedWorkflowRef.current?.target === target ? fetchedWorkflowRef.current.workflow : null;
907
+ const recordFetched = (workflow2) => {
908
+ if (loadSeqRef.current !== loadSeq) return false;
909
+ fetchedWorkflowRef.current = { target, workflow: workflow2 };
910
+ if (pendingReloadRef.current === target) pendingReloadRef.current = null;
911
+ return true;
912
+ };
846
913
  const loadWorkflow = async () => {
847
914
  try {
848
915
  resetWorkflow();
849
916
  if (mounted) setNotFound(false);
850
917
  if (mounted) setLoadError(null);
918
+ if (mounted) setReloadFailed(false);
851
919
  if (version && mounted) {
852
920
  setIsLoading(true);
853
921
  }
@@ -904,7 +972,7 @@ function WorkflowItem({
904
972
  }
905
973
  return;
906
974
  }
907
- const freshCreate = createIntentRef.current && !creatingRef.current && !fetchedWorkflowRef.current && !loadRunId;
975
+ const freshCreate = createIntentRef.current && !creatingRef.current && !fetchedCopy() && !loadRunId;
908
976
  const result = freshCreate ? null : await getWorkflow(id, void 0, version);
909
977
  const definitionJson = result?.definitionJson;
910
978
  const defData = definitionJson?.data ?? (definitionJson?.nodes ? definitionJson : void 0);
@@ -925,7 +993,9 @@ function WorkflowItem({
925
993
  // new version (spec code-first 06 §1).
926
994
  codeBuildId: codeBuildIdOf(result?.definitionJson)
927
995
  };
928
- fetchedWorkflowRef.current = workflowState;
996
+ if (recordFetched(workflowState)) {
997
+ rememberRevision(result?.id, result?.revision);
998
+ }
929
999
  let requiredNodeTypes = [];
930
1000
  try {
931
1001
  requiredNodeTypes = await buildRequiredNodeTypes(
@@ -949,8 +1019,14 @@ function WorkflowItem({
949
1019
  return;
950
1020
  }
951
1021
  if (mounted) {
952
- if (fetchedWorkflowRef.current) {
953
- setWorkflow(fetchedWorkflowRef.current);
1022
+ if (reloadPending()) {
1023
+ setReloadFailed(true);
1024
+ releaseLeaseKeptForReload();
1025
+ return;
1026
+ }
1027
+ const earlier = fetchedCopy();
1028
+ if (earlier) {
1029
+ setWorkflow(earlier);
954
1030
  return;
955
1031
  }
956
1032
  if (loadRunId) {
@@ -999,16 +1075,18 @@ function WorkflowItem({
999
1075
  if (mounted) setCreateRefusal(classifyCreateRefusal(reported));
1000
1076
  return;
1001
1077
  }
1002
- if (mounted) {
1003
- setWorkflow({
1004
- ...newWorkflow,
1005
- id: created.workflowKey,
1006
- workflowKey: created.workflowKey,
1007
- version: created.version,
1008
- dbId: created.id,
1009
- status: created.status ?? "DRAFT"
1010
- });
1078
+ const createdWorkflow = {
1079
+ ...newWorkflow,
1080
+ id: created.workflowKey,
1081
+ workflowKey: created.workflowKey,
1082
+ version: created.version,
1083
+ dbId: created.id,
1084
+ status: created.status ?? "DRAFT"
1085
+ };
1086
+ if (recordFetched(createdWorkflow)) {
1087
+ rememberRevision(created.id, created.revision);
1011
1088
  }
1089
+ if (mounted) setWorkflow(createdWorkflow);
1012
1090
  }
1013
1091
  }
1014
1092
  } catch (error) {
@@ -1018,8 +1096,11 @@ function WorkflowItem({
1018
1096
  setLoadError(
1019
1097
  "The workflow version for this TEST run could not be loaded."
1020
1098
  );
1099
+ } else if (reloadPending()) {
1100
+ setReloadFailed(true);
1101
+ releaseLeaseKeptForReload();
1021
1102
  } else {
1022
- setWorkflow(fetchedWorkflowRef.current ?? newWorkflow);
1103
+ setWorkflow(fetchedCopy() ?? newWorkflow);
1023
1104
  }
1024
1105
  }
1025
1106
  } finally {
@@ -1042,7 +1123,8 @@ function WorkflowItem({
1042
1123
  resetWorkflow,
1043
1124
  navigate,
1044
1125
  loadRunId,
1045
- retryNonce
1126
+ retryNonce,
1127
+ reloadNonce
1046
1128
  // doNodeCheckRef is intentionally omitted — it's a ref (stable by definition)
1047
1129
  // and including doNodeCheck here caused infinite re-runs because installedAppIds
1048
1130
  // produces a new Set reference on every render.
@@ -1083,89 +1165,70 @@ function WorkflowItem({
1083
1165
  /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground/60", children: "Loading workflow..." })
1084
1166
  ] }) })
1085
1167
  );
1168
+ const retryLabel = tr(
1169
+ "fluidgrids.builder.workflowNotFound.retry",
1170
+ "Try again"
1171
+ );
1172
+ const backLabel = tr(
1173
+ "fluidgrids.builder.workflowNotFound.back",
1174
+ "Back to Workflows"
1175
+ );
1086
1176
  if (createRefusal?.kind === "failed")
1087
- return /* @__PURE__ */ jsxs(
1088
- "div",
1177
+ return /* @__PURE__ */ jsx(
1178
+ LoadProblem,
1089
1179
  {
1090
- role: "alert",
1091
- className: "flex h-full min-h-[60vh] w-full flex-col items-center justify-center gap-3 p-6 text-center",
1092
- children: [
1093
- /* @__PURE__ */ jsx("p", { className: "text-base font-medium text-foreground", children: tr(
1094
- "fluidgrids.builder.workflowNotCreated.title",
1095
- "Workflow not created"
1096
- ) }),
1097
- /* @__PURE__ */ jsx("p", { className: "max-w-md text-sm text-foreground/60", children: tr(
1098
- "fluidgrids.builder.workflowNotCreated.description",
1099
- "The new workflow could not be created, so there is nothing to edit yet."
1100
- ) }),
1101
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1102
- /* @__PURE__ */ jsx(
1103
- "button",
1104
- {
1105
- type: "button",
1106
- className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
1107
- onClick: () => {
1108
- setCreateRefusal(null);
1109
- setRetryNonce((n) => n + 1);
1110
- },
1111
- children: tr("fluidgrids.builder.workflowNotFound.retry", "Try again")
1112
- }
1113
- ),
1114
- /* @__PURE__ */ jsx(
1115
- "button",
1116
- {
1117
- type: "button",
1118
- className: "rounded-md border px-4 py-2 text-sm font-medium text-foreground",
1119
- onClick: () => navigate("../list", { replace: true }),
1120
- children: tr(
1121
- "fluidgrids.builder.workflowNotFound.back",
1122
- "Back to Workflows"
1123
- )
1124
- }
1125
- )
1126
- ] })
1127
- ]
1180
+ title: tr(
1181
+ "fluidgrids.builder.workflowNotCreated.title",
1182
+ "Workflow not created"
1183
+ ),
1184
+ description: tr(
1185
+ "fluidgrids.builder.workflowNotCreated.description",
1186
+ "The new workflow could not be created, so there is nothing to edit yet."
1187
+ ),
1188
+ retryLabel,
1189
+ onRetry: () => {
1190
+ setCreateRefusal(null);
1191
+ setRetryNonce((n) => n + 1);
1192
+ },
1193
+ backLabel,
1194
+ onBack: () => navigate("../list", { replace: true })
1128
1195
  }
1129
1196
  );
1130
1197
  if (notFound)
1131
- return /* @__PURE__ */ jsxs(
1132
- "div",
1198
+ return /* @__PURE__ */ jsx(
1199
+ LoadProblem,
1133
1200
  {
1134
- role: "alert",
1135
- className: "flex h-full min-h-[60vh] w-full flex-col items-center justify-center gap-3 p-6 text-center",
1136
- children: [
1137
- /* @__PURE__ */ jsx("p", { className: "text-base font-medium text-foreground", children: tr(
1138
- "fluidgrids.builder.workflowNotFound.title",
1139
- "Workflow not found"
1140
- ) }),
1141
- /* @__PURE__ */ jsx("p", { className: "max-w-md text-sm text-foreground/60", children: tr(
1142
- "fluidgrids.builder.workflowNotFound.description",
1143
- "No workflow with this key exists in this workspace, or it could not be loaded. Nothing was created."
1144
- ) }),
1145
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
1146
- /* @__PURE__ */ jsx(
1147
- "button",
1148
- {
1149
- type: "button",
1150
- className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
1151
- onClick: () => setRetryNonce((n) => n + 1),
1152
- children: tr("fluidgrids.builder.workflowNotFound.retry", "Try again")
1153
- }
1154
- ),
1155
- /* @__PURE__ */ jsx(
1156
- "button",
1157
- {
1158
- type: "button",
1159
- className: "rounded-md border px-4 py-2 text-sm font-medium text-foreground",
1160
- onClick: () => navigate("../list"),
1161
- children: tr(
1162
- "fluidgrids.builder.workflowNotFound.back",
1163
- "Back to Workflows"
1164
- )
1165
- }
1166
- )
1167
- ] })
1168
- ]
1201
+ title: tr(
1202
+ "fluidgrids.builder.workflowNotFound.title",
1203
+ "Workflow not found"
1204
+ ),
1205
+ description: tr(
1206
+ "fluidgrids.builder.workflowNotFound.description",
1207
+ "No workflow with this key exists in this workspace, or it could not be loaded. Nothing was created."
1208
+ ),
1209
+ retryLabel,
1210
+ onRetry: () => setRetryNonce((n) => n + 1),
1211
+ backLabel,
1212
+ onBack: () => navigate("../list")
1213
+ }
1214
+ );
1215
+ if (reloadFailed)
1216
+ return /* @__PURE__ */ jsx(
1217
+ LoadProblem,
1218
+ {
1219
+ testId: "fluidgrids-builder-reload-failed",
1220
+ title: tr(
1221
+ "fluidgrids.builder.reloadFailed.title",
1222
+ "The latest version did not load"
1223
+ ),
1224
+ description: tr(
1225
+ "fluidgrids.builder.reloadFailed.description",
1226
+ "The latest saved version of this workflow could not be loaded, so nothing older is shown in its place. Check your connection and try again."
1227
+ ),
1228
+ retryLabel,
1229
+ onRetry: () => setRetryNonce((n) => n + 1),
1230
+ backLabel,
1231
+ onBack: () => navigate("../list")
1169
1232
  }
1170
1233
  );
1171
1234
  return /* @__PURE__ */ jsxs(Fragment, { children: [