@burdenoff/fluidgrids-fe-sdk 2026.1029.6 → 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 (45) hide show
  1. package/dist/ExecutionDetailPage-H6R3ZIXN.js +22 -0
  2. package/dist/{WorkflowsList-VA2HRYFG.js → ExecutionsListPage-TLD2E442.js} +9 -9
  3. package/dist/{WorkflowBuilder-PORH3H6P.js → WorkflowBuilder-XVHY7XWJ.js} +12 -12
  4. package/dist/{ExecutionsListPage-SCPWUXUL.js → WorkflowsList-3GXXXURR.js} +9 -8
  5. package/dist/{chunk-MNY2UNQH.js → chunk-2NG5VZWI.js} +1 -1
  6. package/dist/{chunk-CY6KX4RG.js → chunk-6AMNEX2Y.js} +6 -1
  7. package/dist/{chunk-LPGQTSI2.js → chunk-6CKDGT2N.js} +3 -3
  8. package/dist/{chunk-U6KI4AKI.js → chunk-6TMLIQHB.js} +199 -1
  9. package/dist/{chunk-LTVAUZ3M.js → chunk-G3KZOX52.js} +3 -3
  10. package/dist/{chunk-7PP6CRXS.js → chunk-GQTEHWWY.js} +26 -8
  11. package/dist/{chunk-LB62TAF7.js → chunk-H4AZBUWM.js} +1 -1
  12. package/dist/{chunk-57RS7DXZ.js → chunk-HWEKWYXQ.js} +117 -8
  13. package/dist/{chunk-7B2GRTUL.js → chunk-LJGC7RAL.js} +164 -101
  14. package/dist/{chunk-4TGUNOQQ.js → chunk-NAYPOEYM.js} +391 -112
  15. package/dist/{chunk-BWAUFSHC.js → chunk-NNPXN4DI.js} +5 -5
  16. package/dist/{chunk-QZM6EDGK.js → chunk-NUBPALBK.js} +1 -1
  17. package/dist/{chunk-YSUSSIWU.js → chunk-R7VHURPQ.js} +1 -1
  18. package/dist/{chunk-7SSZUX6E.js → chunk-S4JYBJ4X.js} +2 -2
  19. package/dist/{chunk-WTGBHE3J.js → chunk-T22LICGX.js} +118 -96
  20. package/dist/{chunk-63ZMEHZ4.js → chunk-TJ6RUV4R.js} +937 -26
  21. package/dist/{chunk-H364USFF.js → chunk-UIDJT3YK.js} +1 -1
  22. package/dist/{chunk-4XAPSIHY.js → chunk-UWNCFMHV.js} +183 -26
  23. package/dist/{chunk-MDPBO52Q.js → chunk-V5PA5KGV.js} +2 -2
  24. package/dist/{chunk-MQI7NH4Z.js → chunk-VEZ7G2FE.js} +145 -8
  25. package/dist/{chunk-YHTRCQ5M.js → chunk-WEXO3KAY.js} +4 -4
  26. package/dist/{chunk-7LFAWWVF.js → chunk-WTP343PG.js} +2 -2
  27. package/dist/{chunk-Z6EWB5ZG.js → chunk-X2J4ZXKD.js} +1492 -98
  28. package/dist/{chunk-6XZCYLAQ.js → chunk-XJBCRDWZ.js} +3 -3
  29. package/dist/{chunk-AVMI3XLM.js → chunk-XMKYZP6Q.js} +282 -18
  30. package/dist/{chunk-5GD6OXYW.js → chunk-Z6I6A47T.js} +1 -1
  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 +2588 -26
  35. package/dist/index.js +36 -36
  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-CZFczcE7.d.ts → workflow-builder-BMGVSwpy.d.ts} +7 -0
  41. package/dist/workflow-builder.d.ts +1 -1
  42. package/dist/workflow-builder.js +13 -13
  43. package/dist/workflows-list.js +9 -9
  44. package/package.json +1 -1
  45. package/dist/ExecutionDetailPage-M6JAWY4Q.js +0 -21
@@ -1,19 +1,19 @@
1
1
  import { cn as cn$1 } from './chunk-JL7CASN5.js';
2
2
  import { getGlobalStoreClient, createGlobalStoreClient, setGlobalStoreClient, resetGlobalStoreClient } from './chunk-PXIFUMLA.js';
3
- import { getFluidGridsConfig, validateTrustedOrigin, resetFluidGridsExecutionState, setFluidGridsConfig, resetFluidGridsConfig } from './chunk-CY6KX4RG.js';
3
+ import { getFluidGridsConfig, validateTrustedOrigin, resetFluidGridsExecutionState, setFluidGridsConfig, resetFluidGridsConfig } from './chunk-6AMNEX2Y.js';
4
4
  import { GetMyNodeInstallationsDocument } from './chunk-JUUYPCFY.js';
5
- import { fetchAllNodeEndpointConfigs, NodeManifestDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, ExecuteStepDocument, TriggerWorkflowDocument, RunFromNodeDocument, ExecutionDetailDocument, WorkflowDefinitionDocument, WorkflowRunDocument } from './chunk-7PP6CRXS.js';
5
+ import { fetchAllNodeEndpointConfigs, NodeManifestDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, ExecuteStepDocument, TriggerWorkflowDocument, RunFromNodeDocument, ExecutionDetailDocument, WorkflowDefinitionDocument, WorkflowRunDocument } from './chunk-GQTEHWWY.js';
6
6
  import { useTr, ENGLISH_FALLBACK_TRANSLATOR, FluidGridsTranslationProvider } from './chunk-UULVIT25.js';
7
7
  import { waitForFluidGridsClient, getFluidGridsClient, getFluidGridsClientSafe, createFluidGridsClient, setFluidGridsClient, resetFluidGridsClient } from './chunk-NTWG3CJX.js';
8
+ import * as React2 from 'react';
9
+ import { forwardRef, useState, useImperativeHandle, useRef, useEffect, useMemo, createContext, memo, useCallback, useContext, useSyncExternalStore, cloneElement } from 'react';
10
+ import { useOptionalFeatureFlags } from '@burdenoff/fe-libs/shared/feature-flags';
8
11
  import { CombinedGraphQLErrors, ServerError } from '@apollo/client/errors';
9
12
  import { dispatchUpgradePrompt } from '@burdenoff/fe-libs/shared/components';
10
13
  import { nanoid } from 'nanoid/non-secure';
11
14
  import { addEdge, applyEdgeChanges, applyNodeChanges, useReactFlow, NodeResizer, getConnectedEdges, useStore, Handle, Position, useUpdateNodeInternals, useNodeId } from '@xyflow/react';
12
15
  import { create } from 'zustand';
13
16
  import { produce } from 'immer';
14
- import * as React2 from 'react';
15
- import { forwardRef, useState, useImperativeHandle, useRef, useEffect, useMemo, createContext, memo, useCallback, useSyncExternalStore, useContext, cloneElement } from 'react';
16
- import { useOptionalFeatureFlags } from '@burdenoff/fe-libs/shared/feature-flags';
17
17
  import { Textarea, Input, Button, Card, Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from '@burdenoff/fe-libs/ui';
18
18
  import { cn } from '@burdenoff/fe-libs/utils';
19
19
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -34,6 +34,104 @@ import { useParams, useNavigate } from 'react-router';
34
34
  import { useShallow } from 'zustand/shallow';
35
35
  import { InfoCircledIcon } from '@radix-ui/react-icons';
36
36
 
37
+ // src/feature-flags/durable-nodes.ts
38
+ var DURABLE_FUNCTION_NODE_TYPES = /* @__PURE__ */ new Set([
39
+ "internal:code-workflow",
40
+ "internal:wait-for-signal"
41
+ ]);
42
+ function isDurableFunctionNodeType(nodeType) {
43
+ return !!nodeType && DURABLE_FUNCTION_NODE_TYPES.has(nodeType);
44
+ }
45
+ function isNodeTypeHiddenFromPalette(nodeType, durableFunctionsEnabled = false) {
46
+ return !durableFunctionsEnabled && isDurableFunctionNodeType(nodeType);
47
+ }
48
+ function filterPaletteNodes(nodes, durableFunctionsEnabled = false) {
49
+ if (durableFunctionsEnabled) return nodes;
50
+ if (!nodes.some((node) => isDurableFunctionNodeType(node.type))) return nodes;
51
+ return nodes.filter((node) => !isDurableFunctionNodeType(node.type));
52
+ }
53
+ var FLUIDGRIDS_FLAGS = {
54
+ /**
55
+ * Operational kill switch for log stream destinations (webhook, syslog,
56
+ * Sentry). Defaults on; an admin turning it off hides the Log streaming
57
+ * settings and the backend rejects destination writes with FEATURE_DISABLED.
58
+ */
59
+ logStreams: "fluidgrids.log-streams",
60
+ /**
61
+ * Code-first workflows (BOFF-9902): the builder's Code view, Export as
62
+ * TypeScript / Python and TypeScript import. A rollout gate, not a kill
63
+ * switch, so it defaults OFF: the controls stay hidden until tenant-svc
64
+ * evaluates the flag on for the workspace, including when the shell mounts
65
+ * no FeatureFlagProvider or the evaluation is still loading.
66
+ */
67
+ codeFirst: "fluidgrids.code-first",
68
+ /**
69
+ * Durable functions (BOFF-9905): the Code Workflow and Wait for Signal
70
+ * nodes, run history, signals and the source editor. A rollout gate like
71
+ * `codeFirst`, so it defaults OFF and fails closed. The durable nodes are
72
+ * shown in the palette only while both this flag and `codeFirst` are on.
73
+ */
74
+ durableFunctions: "fluidgrids.durable-functions",
75
+ /**
76
+ * Durable-function parity (BOFF-9905, spec code-first 11): workflow ids and
77
+ * run chains, run metadata, what a run is waiting on, run counts,
78
+ * completion callbacks, versioning (rollouts, drainage, per-run overrides)
79
+ * and the history caps. A rollout gate like `durableFunctions`, so it
80
+ * defaults OFF and fails closed; the parity surfaces show only while this
81
+ * flag, `durableFunctions` and `codeFirst` are all on.
82
+ */
83
+ durableParity: "fluidgrids.durable-parity"
84
+ };
85
+ var FLUIDGRIDS_FLAG_DEFAULTS = {
86
+ [FLUIDGRIDS_FLAGS.logStreams]: true,
87
+ [FLUIDGRIDS_FLAGS.codeFirst]: false,
88
+ [FLUIDGRIDS_FLAGS.durableFunctions]: false,
89
+ [FLUIDGRIDS_FLAGS.durableParity]: false
90
+ };
91
+ var settledEvaluations = /* @__PURE__ */ new WeakMap();
92
+ function evaluationsUsable(context) {
93
+ const { evaluations } = context;
94
+ if (!evaluations) return !context.isLoading;
95
+ const workspace = context.workspaceId ?? null;
96
+ const settledFor = settledEvaluations.get(evaluations);
97
+ if (context.isLoading)
98
+ return settledFor !== void 0 && settledFor === workspace;
99
+ if (settledFor === void 0) {
100
+ settledEvaluations.set(evaluations, workspace);
101
+ return true;
102
+ }
103
+ return settledFor === workspace;
104
+ }
105
+ function resolveFluidGridsFlag(context, flag) {
106
+ const fallback = FLUIDGRIDS_FLAG_DEFAULTS[flag];
107
+ if (!context) return fallback;
108
+ if (fallback) {
109
+ if (context.isLoading) return fallback;
110
+ const evaluation2 = context.getEvaluation(flag);
111
+ return evaluation2 ? Boolean(evaluation2.value) : fallback;
112
+ }
113
+ if (context.error || !evaluationsUsable(context)) return false;
114
+ const evaluation = context.getEvaluation(flag);
115
+ return !!evaluation && !evaluation.errorCode && evaluation.value === true;
116
+ }
117
+ function useFluidGridsFlag(flag) {
118
+ const context = useOptionalFeatureFlags();
119
+ return useMemo(() => resolveFluidGridsFlag(context, flag), [context, flag]);
120
+ }
121
+ function useDurableFunctionNodesEnabled() {
122
+ const context = useOptionalFeatureFlags();
123
+ return useMemo(
124
+ () => resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.codeFirst) && resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.durableFunctions),
125
+ [context]
126
+ );
127
+ }
128
+ function resolveDurableParity(context) {
129
+ return resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.codeFirst) && resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.durableFunctions) && resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.durableParity);
130
+ }
131
+ function useDurableParityEnabled() {
132
+ const context = useOptionalFeatureFlags();
133
+ return useMemo(() => resolveDurableParity(context), [context]);
134
+ }
37
135
  function describeGraphQLError(error) {
38
136
  const code = typeof error.extensions?.code === "string" ? error.extensions.code : void 0;
39
137
  switch (code) {
@@ -1240,88 +1338,6 @@ if (typeof window !== "undefined" && import.meta.env?.DEV) {
1240
1338
  window.__fgFlowStore = useFlowStore;
1241
1339
  }
1242
1340
 
1243
- // src/feature-flags/durable-nodes.ts
1244
- var DURABLE_FUNCTION_NODE_TYPES = /* @__PURE__ */ new Set([
1245
- "internal:code-workflow",
1246
- "internal:wait-for-signal"
1247
- ]);
1248
- function isDurableFunctionNodeType(nodeType) {
1249
- return !!nodeType && DURABLE_FUNCTION_NODE_TYPES.has(nodeType);
1250
- }
1251
- function isNodeTypeHiddenFromPalette(nodeType, durableFunctionsEnabled = false) {
1252
- return !durableFunctionsEnabled && isDurableFunctionNodeType(nodeType);
1253
- }
1254
- function filterPaletteNodes(nodes, durableFunctionsEnabled = false) {
1255
- if (durableFunctionsEnabled) return nodes;
1256
- if (!nodes.some((node) => isDurableFunctionNodeType(node.type))) return nodes;
1257
- return nodes.filter((node) => !isDurableFunctionNodeType(node.type));
1258
- }
1259
- var FLUIDGRIDS_FLAGS = {
1260
- /**
1261
- * Operational kill switch for log stream destinations (webhook, syslog,
1262
- * Sentry). Defaults on; an admin turning it off hides the Log streaming
1263
- * settings and the backend rejects destination writes with FEATURE_DISABLED.
1264
- */
1265
- logStreams: "fluidgrids.log-streams",
1266
- /**
1267
- * Code-first workflows (BOFF-9902): the builder's Code view, Export as
1268
- * TypeScript / Python and TypeScript import. A rollout gate, not a kill
1269
- * switch, so it defaults OFF: the controls stay hidden until tenant-svc
1270
- * evaluates the flag on for the workspace, including when the shell mounts
1271
- * no FeatureFlagProvider or the evaluation is still loading.
1272
- */
1273
- codeFirst: "fluidgrids.code-first",
1274
- /**
1275
- * Durable functions (BOFF-9905): the Code Workflow and Wait for Signal
1276
- * nodes, run history, signals and the source editor. A rollout gate like
1277
- * `codeFirst`, so it defaults OFF and fails closed. The durable nodes are
1278
- * shown in the palette only while both this flag and `codeFirst` are on.
1279
- */
1280
- durableFunctions: "fluidgrids.durable-functions"
1281
- };
1282
- var FLUIDGRIDS_FLAG_DEFAULTS = {
1283
- [FLUIDGRIDS_FLAGS.logStreams]: true,
1284
- [FLUIDGRIDS_FLAGS.codeFirst]: false,
1285
- [FLUIDGRIDS_FLAGS.durableFunctions]: false
1286
- };
1287
- var settledEvaluations = /* @__PURE__ */ new WeakMap();
1288
- function evaluationsUsable(context) {
1289
- const { evaluations } = context;
1290
- if (!evaluations) return !context.isLoading;
1291
- const workspace = context.workspaceId ?? null;
1292
- const settledFor = settledEvaluations.get(evaluations);
1293
- if (context.isLoading)
1294
- return settledFor !== void 0 && settledFor === workspace;
1295
- if (settledFor === void 0) {
1296
- settledEvaluations.set(evaluations, workspace);
1297
- return true;
1298
- }
1299
- return settledFor === workspace;
1300
- }
1301
- function resolveFluidGridsFlag(context, flag) {
1302
- const fallback = FLUIDGRIDS_FLAG_DEFAULTS[flag];
1303
- if (!context) return fallback;
1304
- if (fallback) {
1305
- if (context.isLoading) return fallback;
1306
- const evaluation2 = context.getEvaluation(flag);
1307
- return evaluation2 ? Boolean(evaluation2.value) : fallback;
1308
- }
1309
- if (context.error || !evaluationsUsable(context)) return false;
1310
- const evaluation = context.getEvaluation(flag);
1311
- return !!evaluation && !evaluation.errorCode && evaluation.value === true;
1312
- }
1313
- function useFluidGridsFlag(flag) {
1314
- const context = useOptionalFeatureFlags();
1315
- return useMemo(() => resolveFluidGridsFlag(context, flag), [context, flag]);
1316
- }
1317
- function useDurableFunctionNodesEnabled() {
1318
- const context = useOptionalFeatureFlags();
1319
- return useMemo(
1320
- () => resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.codeFirst) && resolveFluidGridsFlag(context, FLUIDGRIDS_FLAGS.durableFunctions),
1321
- [context]
1322
- );
1323
- }
1324
-
1325
1341
  // src/modules/executions/utils/signal-targets.ts
1326
1342
  function isRecord3(value) {
1327
1343
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -4540,6 +4556,11 @@ function useDeleteNode() {
4540
4556
  [deleteElements, getEdges, getNode, deleteNodes]
4541
4557
  );
4542
4558
  }
4559
+ var BuilderReadOnlyContext = createContext(false);
4560
+ var BuilderReadOnlyProvider = BuilderReadOnlyContext.Provider;
4561
+ function useBuilderReadOnly() {
4562
+ return useContext(BuilderReadOnlyContext);
4563
+ }
4543
4564
 
4544
4565
  // src/builder/contants/symbols.ts
4545
4566
  var NODE_TYPE_DRAG_DATA_FORMAT = "application/flow-builder.node-type";
@@ -4589,6 +4610,7 @@ function StickyNoteNodeComponent({
4589
4610
  const { setNodes, getNode } = useReactFlow();
4590
4611
  const zustandSetNodes = useFlowStore((s) => s.actions.nodes.setNodes);
4591
4612
  const deleteNode = useDeleteNode();
4613
+ const readOnly = useBuilderReadOnly();
4592
4614
  const [editing, setEditing] = useState(false);
4593
4615
  const [showPalette, setShowPalette] = useState(false);
4594
4616
  const [draft, setDraft] = useState(String(data.content ?? ""));
@@ -4664,7 +4686,7 @@ function StickyNoteNodeComponent({
4664
4686
  /* @__PURE__ */ jsx(
4665
4687
  NodeResizer,
4666
4688
  {
4667
- isVisible: !!selected,
4689
+ isVisible: !!selected && !readOnly,
4668
4690
  minWidth: STICKY_MIN_SIZE.width,
4669
4691
  minHeight: STICKY_MIN_SIZE.height,
4670
4692
  lineStyle: { border: "none", zIndex: 20 },
@@ -4682,7 +4704,9 @@ function StickyNoteNodeComponent({
4682
4704
  {
4683
4705
  className: cn(
4684
4706
  "absolute right-1 z-30 flex items-center gap-0.5 rounded-lg border border-border bg-card p-0.5 shadow-md transition-all duration-150",
4685
- selected || showPalette ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0 group-hover:pointer-events-auto group-hover:opacity-100"
4707
+ selected || showPalette ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0 group-hover:pointer-events-auto group-hover:opacity-100",
4708
+ // Nothing to change on a read-only canvas (BOFF-9725).
4709
+ readOnly && "hidden"
4686
4710
  ),
4687
4711
  style: { top: -15 },
4688
4712
  onDoubleClick: (e) => e.stopPropagation(),
@@ -4770,12 +4794,13 @@ function StickyNoteNodeComponent({
4770
4794
  },
4771
4795
  onDoubleClick: (e) => {
4772
4796
  e.stopPropagation();
4773
- startEditing();
4797
+ if (!readOnly) startEditing();
4774
4798
  },
4775
4799
  children: editing ? /* @__PURE__ */ jsx(
4776
4800
  "textarea",
4777
4801
  {
4778
4802
  ref: textareaRef,
4803
+ readOnly,
4779
4804
  value: draft,
4780
4805
  onChange: (e) => setDraft(e.target.value),
4781
4806
  onBlur: commitEdit,
@@ -6564,8 +6589,26 @@ var PERMANENT_ERROR_CODES = /* @__PURE__ */ new Set([
6564
6589
  "FAILED_PRECONDITION",
6565
6590
  "CONFLICT"
6566
6591
  ]);
6592
+ function textOf(value) {
6593
+ return typeof value === "string" && value.length > 0 ? value : null;
6594
+ }
6595
+ function findSaveConflict(error) {
6596
+ const extensions = collectExtensions(error).find(
6597
+ (ext) => ext.code === "CONFLICT" && (ext.reason === "STALE_REVISION" || ext.reason === "EDIT_LEASE_HELD")
6598
+ );
6599
+ if (!extensions) return null;
6600
+ const revision = extensions.currentRevision;
6601
+ return {
6602
+ reason: extensions.reason,
6603
+ currentRevision: typeof revision === "number" && Number.isFinite(revision) ? revision : null,
6604
+ currentStatus: textOf(extensions.currentStatus),
6605
+ updatedById: textOf(extensions.updatedById),
6606
+ holderActorId: textOf(extensions.holderActorId)
6607
+ };
6608
+ }
6567
6609
  function classifySaveFailure(error) {
6568
6610
  if (findQuotaRefusal(error)) return "quota";
6611
+ if (findSaveConflict(error)) return "conflict";
6569
6612
  if (errorCodesOf(error).some((code) => PERMANENT_ERROR_CODES.has(code))) {
6570
6613
  return "permanent";
6571
6614
  }
@@ -6675,6 +6718,196 @@ function editStateOf(baseline, current, now) {
6675
6718
  return "dirty";
6676
6719
  }
6677
6720
 
6721
+ // src/builder/lib/workflow-revisions.ts
6722
+ var known = /* @__PURE__ */ new Map();
6723
+ function rememberRevision(dbId, revision) {
6724
+ if (!dbId || typeof revision !== "number" || !Number.isFinite(revision)) {
6725
+ return;
6726
+ }
6727
+ const current = known.get(dbId);
6728
+ if (current === void 0 || revision > current) known.set(dbId, revision);
6729
+ }
6730
+ function rememberOwnStatusChange(dbId, revision) {
6731
+ if (!dbId || typeof revision !== "number") return;
6732
+ const current = known.get(dbId);
6733
+ if (current !== void 0 && revision === current + 1) {
6734
+ known.set(dbId, revision);
6735
+ }
6736
+ }
6737
+ function revisionOf(dbId) {
6738
+ return dbId ? known.get(dbId) : void 0;
6739
+ }
6740
+
6741
+ // src/builder/lib/edit-session.ts
6742
+ var SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{8,64}$/;
6743
+ function randomSessionId() {
6744
+ const cryptoApi = globalThis.crypto;
6745
+ if (cryptoApi?.randomUUID) return cryptoApi.randomUUID();
6746
+ const bytes = new Uint8Array(16);
6747
+ cryptoApi?.getRandomValues?.(bytes);
6748
+ if (bytes.every((byte) => byte === 0)) {
6749
+ for (let i = 0; i < bytes.length; i += 1) {
6750
+ bytes[i] = Math.floor(Math.random() * 256);
6751
+ }
6752
+ }
6753
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join(
6754
+ ""
6755
+ );
6756
+ }
6757
+ var EDIT_SESSION_ID = randomSessionId();
6758
+ var storageKey = (workflowKey) => `fluidgrids.builder.editSession.${workflowKey}`;
6759
+ function rememberSessionForReload(storage, workflowKey, sessionId) {
6760
+ try {
6761
+ storage?.setItem(storageKey(workflowKey), sessionId);
6762
+ } catch {
6763
+ }
6764
+ }
6765
+ function sessionBeforeReload(storage, workflowKey, currentSessionId = EDIT_SESSION_ID) {
6766
+ try {
6767
+ const stored = storage?.getItem(storageKey(workflowKey)) ?? null;
6768
+ if (!stored || stored === currentSessionId) return null;
6769
+ return SESSION_ID_PATTERN.test(stored) ? stored : null;
6770
+ } catch {
6771
+ return null;
6772
+ }
6773
+ }
6774
+ function forgetSessionForReload(storage, workflowKey) {
6775
+ try {
6776
+ storage?.removeItem(storageKey(workflowKey));
6777
+ } catch {
6778
+ }
6779
+ }
6780
+
6781
+ // src/builder/lib/edit-lease.ts
6782
+ var LEASE_RENEW_MS = 2e4;
6783
+ var LEASE_VIEW_POLL_MS = 1e4;
6784
+ var LEASE_IDLE_RELEASE_MS = 15 * 6e4;
6785
+ function isLocked(phase) {
6786
+ return phase === "viewing" || phase === "lost" || phase === "idle" || phase === "reloading";
6787
+ }
6788
+ function phaseAfterAcquire(previous, answer) {
6789
+ if (!answer.available) {
6790
+ return isLocked(previous) || previous === "holding" ? previous : "unavailable";
6791
+ }
6792
+ if (answer.heldBySelf) return "holding";
6793
+ if (answer.held) return previous === "holding" ? "lost" : "viewing";
6794
+ return previous;
6795
+ }
6796
+ function phaseAfterTakeOver(answer) {
6797
+ if (!answer.available) return "unavailable";
6798
+ return answer.heldBySelf ? "reloading" : "viewing";
6799
+ }
6800
+ function releasesOnClose(phase) {
6801
+ return phase === "starting" || phase === "holding" || phase === "unavailable";
6802
+ }
6803
+ var LEASE_CALL_MAX_WAIT_MS = 15e3;
6804
+ function leaseCallQueue(maxWaitMs = LEASE_CALL_MAX_WAIT_MS) {
6805
+ const tails = /* @__PURE__ */ new Map();
6806
+ return {
6807
+ run(workflowKey, call) {
6808
+ const previous = tails.get(workflowKey) ?? Promise.resolve();
6809
+ const result = previous.then(call);
6810
+ const tail = previous.then(
6811
+ () => new Promise((resolve) => {
6812
+ const timer = setTimeout(resolve, maxWaitMs);
6813
+ const done = () => {
6814
+ clearTimeout(timer);
6815
+ resolve();
6816
+ };
6817
+ result.then(done, done);
6818
+ })
6819
+ );
6820
+ tails.set(workflowKey, tail);
6821
+ void tail.then(() => {
6822
+ if (tails.get(workflowKey) === tail) tails.delete(workflowKey);
6823
+ });
6824
+ return result;
6825
+ }
6826
+ };
6827
+ }
6828
+ function shouldReleaseForIdle(phase, lastInputAt, now) {
6829
+ return phase === "holding" && now - lastInputAt >= LEASE_IDLE_RELEASE_MS;
6830
+ }
6831
+ function tickAction(phase, state, now) {
6832
+ if (phase === "holding" || phase === "unavailable") {
6833
+ return now - state.lastRenewAt >= LEASE_RENEW_MS ? "renew" : "none";
6834
+ }
6835
+ if (phase === "viewing" || phase === "lost" || phase === "idle") {
6836
+ return state.visible && now - state.lastPeekAt >= LEASE_VIEW_POLL_MS ? "peek" : "none";
6837
+ }
6838
+ return "none";
6839
+ }
6840
+ function bannerOf(state) {
6841
+ switch (state.phase) {
6842
+ case "viewing":
6843
+ return state.held ? {
6844
+ kind: "editing",
6845
+ actorId: state.holderActorId,
6846
+ self: state.heldByCaller
6847
+ } : { kind: "free" };
6848
+ case "lost":
6849
+ return {
6850
+ kind: "taken",
6851
+ actorId: state.takenBy,
6852
+ self: state.takenByCaller
6853
+ };
6854
+ case "idle":
6855
+ return { kind: "idle" };
6856
+ case "reloading":
6857
+ return { kind: "reloading" };
6858
+ default:
6859
+ return null;
6860
+ }
6861
+ }
6862
+ var IDLE = {
6863
+ workflowKey: null,
6864
+ phase: "inactive",
6865
+ held: false,
6866
+ holderActorId: null,
6867
+ heldByCaller: false,
6868
+ takenBy: null,
6869
+ takenByCaller: false
6870
+ };
6871
+ function commitFocusedEdit() {
6872
+ if (typeof document === "undefined") return;
6873
+ const focused = document.activeElement;
6874
+ if (!focused || typeof focused.blur !== "function") return;
6875
+ const editable = focused.isContentEditable || typeof focused.matches === "function" && focused.matches("input, textarea, select");
6876
+ if (editable) focused.blur();
6877
+ }
6878
+ var useEditLeaseStore = create()((set, get) => ({
6879
+ ...IDLE,
6880
+ actions: {
6881
+ begin: (workflowKey) => set(
6882
+ (state) => (
6883
+ // A reload of the same workflow keeps "reloading" (and its lock)
6884
+ // until the lease is confirmed again.
6885
+ state.workflowKey === workflowKey && state.phase === "reloading" ? state : { ...IDLE, workflowKey, phase: "starting" }
6886
+ )
6887
+ ),
6888
+ record: (phase, answer) => {
6889
+ if (isLocked(phase) && !isLocked(get().phase)) commitFocusedEdit();
6890
+ set(() => {
6891
+ if (!answer || !answer.available) return { phase };
6892
+ const holderActorId = answer.held ? answer.holderActorId ?? null : null;
6893
+ const heldByCaller = answer.held && !!answer.heldByCaller;
6894
+ const taken = phase !== "lost" ? { takenBy: null, takenByCaller: false } : answer.held ? { takenBy: holderActorId, takenByCaller: heldByCaller } : {};
6895
+ return {
6896
+ phase,
6897
+ held: answer.held,
6898
+ holderActorId,
6899
+ heldByCaller,
6900
+ ...taken
6901
+ };
6902
+ });
6903
+ },
6904
+ reset: () => set({ ...IDLE })
6905
+ }
6906
+ }));
6907
+ function useEditLeaseLocked() {
6908
+ return useEditLeaseStore((s) => isLocked(s.phase));
6909
+ }
6910
+
6678
6911
  // src/builder/lib/workflow-save-snapshot.ts
6679
6912
  function snapshotForSave(workflow, generation, route = {}) {
6680
6913
  const copy = {
@@ -6712,7 +6945,8 @@ var PRISTINE = {
6712
6945
  baseline: null,
6713
6946
  quotaExhausted: false,
6714
6947
  leaveRequest: null,
6715
- autosavePaused: false
6948
+ autosavePaused: false,
6949
+ conflictOpen: false
6716
6950
  };
6717
6951
  var useSaveStatusStore = create()((set) => ({
6718
6952
  ...PRISTINE,
@@ -6729,10 +6963,15 @@ var useSaveStatusStore = create()((set) => ({
6729
6963
  failure: null,
6730
6964
  incomplete: false,
6731
6965
  autosavePaused: false,
6966
+ conflictOpen: false,
6732
6967
  lastSavedAt: at
6733
6968
  } : { saving: false }
6734
6969
  ),
6735
- saveFailed: (failure) => set({ saving: false, failure }),
6970
+ saveFailed: (failure) => set({
6971
+ saving: false,
6972
+ failure,
6973
+ conflictOpen: failure.conflict?.reason === "STALE_REVISION"
6974
+ }),
6736
6975
  clearFailure: () => set({ failure: null }),
6737
6976
  setQuotaExhausted: (quotaExhausted) => set({ quotaExhausted }),
6738
6977
  setAutosaveEnabled: (autosaveEnabled) => {
@@ -6741,6 +6980,7 @@ var useSaveStatusStore = create()((set) => ({
6741
6980
  },
6742
6981
  requestLeave: (leaveRequest) => set({ leaveRequest }),
6743
6982
  setAutosavePaused: (autosavePaused) => set({ autosavePaused }),
6983
+ setConflictOpen: (conflictOpen) => set({ conflictOpen }),
6744
6984
  reset: () => set({ ...PRISTINE })
6745
6985
  }
6746
6986
  }));
@@ -6859,13 +7099,15 @@ function useSaveWorkflow() {
6859
7099
  const { bus, workspaceId } = useFluidGridsAnalytics();
6860
7100
  const setWorkflow = useFlowStore((s) => s.actions.setWorkflow);
6861
7101
  const performSave = useCallback(
6862
- async (snapshot, silent) => {
7102
+ async (snapshot, silent, asNewVersion) => {
6863
7103
  const stillOpen = () => useFlowStore.getState().loadGeneration === snapshot.generation;
6864
7104
  try {
6865
7105
  const { workflow } = snapshot;
6866
7106
  const mintedKey = snapshot.key ? null : v4();
6867
7107
  const workflowKey = snapshot.key || mintedKey || "";
6868
- const isDraft = !workflow.status || workflow.status === "DRAFT";
7108
+ const forkRequested = asNewVersion && !!workflow.dbId;
7109
+ const isDraft = !forkRequested && (!workflow.status || workflow.status === "DRAFT");
7110
+ const expectedRevision = revisionOf(workflow.dbId);
6869
7111
  const client = getFluidGridsClient();
6870
7112
  const { preparedWorkflow, owned } = builderDefinition(
6871
7113
  snapshot,
@@ -6891,7 +7133,11 @@ function useSaveWorkflow() {
6891
7133
  description: workflow.name || "Workflow update",
6892
7134
  // null (not undefined) so an emptied alias field actually
6893
7135
  // CLEARS the alias — undefined is dropped by the resolver.
6894
- alias: workflow.alias?.trim() ? workflow.alias.trim() : null
7136
+ alias: workflow.alias?.trim() ? workflow.alias.trim() : null,
7137
+ // Refused instead of overwriting a change made elsewhere,
7138
+ // or a save from a page that no longer holds the edit lease.
7139
+ ...expectedRevision !== void 0 ? { expectedRevision } : {},
7140
+ editSessionId: EDIT_SESSION_ID
6895
7141
  }
6896
7142
  }
6897
7143
  })
@@ -6901,6 +7147,7 @@ function useSaveWorkflow() {
6901
7147
  }
6902
7148
  savedVersion = data.updateWorkflowDefinition.version;
6903
7149
  savedDbId = data.updateWorkflowDefinition.id;
7150
+ rememberRevision(savedDbId, data.updateWorkflowDefinition.revision);
6904
7151
  operation = "updated";
6905
7152
  if (!silent) {
6906
7153
  toast.success("Workflow saved", {
@@ -6928,6 +7175,7 @@ function useSaveWorkflow() {
6928
7175
  }
6929
7176
  savedVersion = data.createWorkflowDefinition.version;
6930
7177
  savedDbId = data.createWorkflowDefinition.id;
7178
+ rememberRevision(savedDbId, data.createWorkflowDefinition.revision);
6931
7179
  operation = "created";
6932
7180
  emitWorkflowCreated(bus, {
6933
7181
  workspaceId,
@@ -6968,7 +7216,15 @@ function useSaveWorkflow() {
6968
7216
  // pointer — the backend clears it from siblings). Included
6969
7217
  // only when set so saves without an alias don't depend on the
6970
7218
  // new schema field being deployed.
6971
- ...workflow.alias?.trim() ? { alias: workflow.alias.trim() } : {}
7219
+ ...workflow.alias?.trim() ? { alias: workflow.alias.trim() } : {},
7220
+ // A save of an ACTIVE or ARCHIVED version claims it, so two
7221
+ // pages that loaded it never create rival drafts. Keeping
7222
+ // the canvas as a new version on purpose skips the claim.
7223
+ ...forkRequested ? {} : {
7224
+ baseVersion: workflow.version,
7225
+ ...expectedRevision !== void 0 ? { expectedRevision } : {},
7226
+ editSessionId: EDIT_SESSION_ID
7227
+ }
6972
7228
  }
6973
7229
  }
6974
7230
  })
@@ -6981,6 +7237,7 @@ function useSaveWorkflow() {
6981
7237
  const newWorkflow = data.createWorkflowVersion.workflow;
6982
7238
  savedVersion = newWorkflow?.version ?? workflow.version;
6983
7239
  savedDbId = newWorkflow?.id ?? workflow.dbId;
7240
+ rememberRevision(newWorkflow?.id, newWorkflow?.revision);
6984
7241
  operation = "versioned";
6985
7242
  if (stillOpen()) {
6986
7243
  setWorkflow({
@@ -7026,15 +7283,30 @@ function useSaveWorkflow() {
7026
7283
  console.error("Error saving workflow:", message);
7027
7284
  const cause = error instanceof Error ? error.cause : void 0;
7028
7285
  const quotaExhausted2 = isQuotaExhaustedFailure(cause) || isQuotaExhaustedFailure(error);
7029
- if (!quotaExhausted2 && !silent) {
7286
+ const conflict = findSaveConflict(error);
7287
+ if (!quotaExhausted2 && !conflict && !silent) {
7030
7288
  toast.error("Failed to save workflow", {
7031
7289
  description: message
7032
7290
  });
7033
7291
  }
7292
+ if (conflict?.reason === "EDIT_LEASE_HELD" && stillOpen()) {
7293
+ const lease = useEditLeaseStore.getState();
7294
+ const answer = {
7295
+ available: true,
7296
+ held: true,
7297
+ heldBySelf: false,
7298
+ holderActorId: conflict.holderActorId
7299
+ };
7300
+ lease.actions.record(phaseAfterAcquire(lease.phase, answer), answer);
7301
+ }
7034
7302
  return {
7035
7303
  saved: false,
7036
7304
  quotaExhausted: quotaExhausted2,
7037
- failure: { message, kind: classifySaveFailure(error) }
7305
+ failure: {
7306
+ message,
7307
+ kind: classifySaveFailure(error),
7308
+ ...conflict ? { conflict } : {}
7309
+ }
7038
7310
  };
7039
7311
  }
7040
7312
  },
@@ -7050,7 +7322,11 @@ function useSaveWorkflow() {
7050
7322
  statusActions.beginSave();
7051
7323
  statusActions.setQuotaExhausted(false);
7052
7324
  }
7053
- const outcome = await performSave(snapshot, options.silent ?? false);
7325
+ const outcome = await performSave(
7326
+ snapshot,
7327
+ options.silent ?? false,
7328
+ options.asNewVersion ?? false
7329
+ );
7054
7330
  recordSaveOutcome(outcome, {
7055
7331
  open: isOpen(),
7056
7332
  baseline: {
@@ -7824,6 +8100,7 @@ function AdapterPort({
7824
8100
  const onConnect = useFlowStore((s) => s.actions.edges.onConnect);
7825
8101
  const [pickerOpen, setPickerOpen] = useState(false);
7826
8102
  const candidates = useCompatibleSubNodes(adapter);
8103
+ const readOnly = useBuilderReadOnly();
7827
8104
  const connectionCount = edges.filter(
7828
8105
  (e) => e.source === nodeId && e.sourceHandle === adapter.name
7829
8106
  ).length;
@@ -7877,7 +8154,7 @@ function AdapterPort({
7877
8154
  adapter?.required && /* @__PURE__ */ jsx("span", { className: "text-[var(--color-status-error-text)] absolute -right-2 top-[1px]", children: "*" })
7878
8155
  ] }) }),
7879
8156
  /* @__PURE__ */ jsxs("div", { className: "mt-16 flex flex-col items-center gap-1.5", children: [
7880
- !isAtMaxConnections && /* @__PURE__ */ jsx(
8157
+ !isAtMaxConnections && !readOnly && /* @__PURE__ */ jsx(
7881
8158
  "button",
7882
8159
  {
7883
8160
  type: "button",
@@ -8008,6 +8285,7 @@ function SubNodeComponent({
8008
8285
  }) {
8009
8286
  const meta = useMemo(() => getNodeDetail(nodeType), [nodeType]);
8010
8287
  const deleteNode = useDeleteNode();
8288
+ const readOnly = useBuilderReadOnly();
8011
8289
  const [showNodePropertiesOf] = useFlowStore(
8012
8290
  useShallow((s) => [s.actions.sidebar.showNodePropertiesOf])
8013
8291
  );
@@ -8053,7 +8331,7 @@ function SubNodeComponent({
8053
8331
  }
8054
8332
  ),
8055
8333
  /* @__PURE__ */ jsx("span", { className: "mt-1.5 text-xs text-[var(--color-text-secondary)] font-medium text-center max-w-24 leading-tight", children: data?.label || data?.args?.state?.operation || meta.title }),
8056
- /* @__PURE__ */ jsx(
8334
+ !readOnly && /* @__PURE__ */ jsx(
8057
8335
  "button",
8058
8336
  {
8059
8337
  onClick: () => deleteNode(id),
@@ -8125,8 +8403,9 @@ var getNodeMetadata = (value) => {
8125
8403
  s.actions.nodes.endRename
8126
8404
  ])
8127
8405
  );
8406
+ const readOnly = useBuilderReadOnly();
8128
8407
  useEffect(() => {
8129
- if (nodeType !== "integration/channel") return;
8408
+ if (readOnly || nodeType !== "integration/channel") return;
8130
8409
  const nodeData = data;
8131
8410
  const explicitRole = nodeData?.args?.state?.role;
8132
8411
  const hasIncomingEdge = edges.some((e) => e.target === id);
@@ -8153,7 +8432,7 @@ var getNodeMetadata = (value) => {
8153
8432
  zustandSetNodes(updated);
8154
8433
  return updated;
8155
8434
  });
8156
- }, [nodeType, id, edges, data, setNodes, zustandSetNodes]);
8435
+ }, [readOnly, nodeType, id, edges, data, setNodes, zustandSetNodes]);
8157
8436
  const { executeStep } = useNodeExecution();
8158
8437
  const deleteNode = useDeleteNode();
8159
8438
  const handleDeleteNode = () => {
@@ -8311,12 +8590,12 @@ var getNodeMetadata = (value) => {
8311
8590
  onDoubleClick: handleOpenNdv,
8312
8591
  onSettings: handleOpenNdv,
8313
8592
  onExecute: handleExecuteStep,
8314
- onDelete: handleDeleteNode,
8593
+ onDelete: readOnly ? void 0 : handleDeleteNode,
8315
8594
  infoButton: /* @__PURE__ */ jsx(NodeInfoButtonWithModal, { metadata: nodeInfoMetadata }),
8316
8595
  disabled: isDisabled,
8317
- onToggleDisabled: handleToggleDisabled,
8318
- isRenaming: isRenamingThisNode,
8319
- onStartRename: handleStartRename,
8596
+ onToggleDisabled: readOnly ? void 0 : handleToggleDisabled,
8597
+ isRenaming: isRenamingThisNode && !readOnly,
8598
+ onStartRename: readOnly ? void 0 : handleStartRename,
8320
8599
  onCommitRename: handleCommitRename,
8321
8600
  onCancelRename: handleCancelRename
8322
8601
  }
@@ -8345,10 +8624,10 @@ var getNodeMetadata = (value) => {
8345
8624
  isExecuting: isThisNodeExecuting,
8346
8625
  onSettings: handleOpenNdv,
8347
8626
  onExecute: handleExecuteStep,
8348
- onDelete: handleDeleteNode,
8627
+ onDelete: readOnly ? void 0 : handleDeleteNode,
8349
8628
  infoButton: /* @__PURE__ */ jsx(NodeInfoButtonWithModal, { metadata: nodeInfoMetadata }),
8350
8629
  disabled: isDisabled,
8351
- onToggleDisabled: handleToggleDisabled,
8630
+ onToggleDisabled: readOnly ? void 0 : handleToggleDisabled,
8352
8631
  children: [
8353
8632
  /* @__PURE__ */ jsx(
8354
8633
  NodeCardHeader,
@@ -8358,8 +8637,8 @@ var getNodeMetadata = (value) => {
8358
8637
  accentKey: value?.type || meta.title,
8359
8638
  missingCredentials,
8360
8639
  label: nodeLabel,
8361
- isRenaming: isRenamingThisNode,
8362
- onStartRename: handleStartRename,
8640
+ isRenaming: isRenamingThisNode && !readOnly,
8641
+ onStartRename: readOnly ? void 0 : handleStartRename,
8363
8642
  onCommitRename: handleCommitRename,
8364
8643
  onCancelRename: handleCancelRename
8365
8644
  }
@@ -9569,4 +9848,4 @@ function useNodeExecution() {
9569
9848
  };
9570
9849
  }
9571
9850
 
9572
- export { ALLOW_ALL_PERMISSIONS, AUTOSAVE_DEBOUNCE_MS, AUTOSAVE_RETRY_DELAYS_MS, AVAILABLE_NODES, BILLING_PLANS_PATH, CODE_WORKFLOW_NODE_TYPE, ConnectionFormDialog, ConnectionSelector, DURABLE_FUNCTION_NODE_TYPES, ExpressionEditor, FLUIDGRIDS_FLAGS, FLUIDGRIDS_FLAG_DEFAULTS, FLUIDGRIDS_PERMISSIONS, FluidGridsContext, FluidGridsPermissionsProvider, FluidGridsProvider, NODES, NODES_METADATA, NODE_CONFIGS, NODE_OPERATION_DRAG_DATA_FORMAT, NODE_TYPES, NODE_TYPE_DRAG_DATA_FORMAT, NodePropertyPanel, NodeTypeIcon, RUNS_QUOTA_NAME, STICKY_NOTE_TYPE, SdkPermissionButton, SdkPermissionGate, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, WORKFLOWS_QUOTA_NAME, blankWorkflowCreateInput, buildOperationSeed, buildStickyNode, canAutosave, canRenderOperationPanel, canSignalRun, changedSourceFiles, childRunIdOf, classifyCreateRefusal, clearCodeWorkflowDefinitionCache, codeBuildIdOf, components_default, createConfiguredNode, createThenOpen, declaredOutputFields, declaredSignals, defaultSourcePath, describeOperationError, diagnosticsByPath, editStateOf, emitNodeInstalled, emitRunFailed, emitRunLimitHit, emitRunStarted, emitTemplateUsed, emitUpgradeClicked, emitWorkflowCreated, emitWorkflowLimitHit, emitWorkflowPublished, ensureNodeConfigsLoaded, evaluatePermissionCheck, fieldsFromIO, fieldsFromValue, filterPaletteNodes, findQuotaRefusal, formatParameterValue, getNodeDetail, getNodeMetadata, inAppLeaveTarget, interfaceFields, interfaceHandlers, isDurableFunctionNodeType, isEditableSourcePath, isForbiddenError, isImageIcon, isNodeConfigsInitialized, isNodeTrigger, isNodeTypeHiddenFromPalette, isParamVisible, isQuotaExhaustedFailure, isTriggerOperation, leaveNeedsConfirmation, listCustomBlocks, liveInternalOperations, mergeStickyNotes, nodeAccent, nodesOf, onNodeTypesUpdate, openRunQuotaUpgradePrompt, parseParameterValue, parseRawSignalPayload, pathToExpression, payloadFromCardValues, projectLanguage, readCodeWorkflowState, readDisplayOptions, refetchStoreNodes, registerCustomBlock, registerWorkflowNodeTypes, resolveInputHandles, resolveNodeOperation, resolveOperationName, resolveOutputHandles, resolveUiSpec, runPreparationOf, runSignalTargets, runTriggerFromMode, saveIndicatorOf, savesInPlace, signalPayloadCard, snapshotForSave, sourceLanguageOf, stripSubmitActions, structuredParameterType, subscribeWorkflowSaved, synchronizeOperationUpdate, throwIfResultError, toCodeMirrorDiagnostics, useAgentDefinitionList, useAgentDefinitions, useCodeWorkflowInterface, useConnection, useConnections, useConnectionsByProvider, useCreateConnection, useDurableFunctionNodesEnabled, useFlowStore, useFluidGridsAnalytics, useFluidGridsContext, useFluidGridsFlag, useFluidGridsPermission, useInitiateOAuth, useInsertNode, useIsValidConnection, useNodeExecution, useNodeRegistryRevision, useProviders, useSaveStatusStore, useSaveWorkflow, workflowFingerprint };
9851
+ export { ALLOW_ALL_PERMISSIONS, AUTOSAVE_DEBOUNCE_MS, AUTOSAVE_RETRY_DELAYS_MS, AVAILABLE_NODES, BILLING_PLANS_PATH, BuilderReadOnlyProvider, CODE_WORKFLOW_NODE_TYPE, ConnectionFormDialog, ConnectionSelector, DURABLE_FUNCTION_NODE_TYPES, EDIT_SESSION_ID, ExpressionEditor, FLUIDGRIDS_FLAGS, FLUIDGRIDS_FLAG_DEFAULTS, FLUIDGRIDS_PERMISSIONS, FluidGridsContext, FluidGridsPermissionsProvider, FluidGridsProvider, NODES, NODES_METADATA, NODE_CONFIGS, NODE_OPERATION_DRAG_DATA_FORMAT, NODE_TYPES, NODE_TYPE_DRAG_DATA_FORMAT, NodePropertyPanel, NodeTypeIcon, RUNS_QUOTA_NAME, STICKY_NOTE_TYPE, SdkPermissionButton, SdkPermissionGate, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, WORKFLOWS_QUOTA_NAME, bannerOf, blankWorkflowCreateInput, buildOperationSeed, buildStickyNode, canAutosave, canRenderOperationPanel, canSignalRun, changedSourceFiles, childRunIdOf, classifyCreateRefusal, clearCodeWorkflowDefinitionCache, codeBuildIdOf, components_default, createConfiguredNode, createThenOpen, declaredOutputFields, declaredSignals, defaultSourcePath, describeOperationError, diagnosticsByPath, editStateOf, emitNodeInstalled, emitRunFailed, emitRunLimitHit, emitRunStarted, emitTemplateUsed, emitUpgradeClicked, emitWorkflowCreated, emitWorkflowLimitHit, emitWorkflowPublished, ensureNodeConfigsLoaded, evaluatePermissionCheck, fieldsFromIO, fieldsFromValue, filterPaletteNodes, findQuotaRefusal, findSaveConflict, forgetSessionForReload, formatParameterValue, getNodeDetail, getNodeMetadata, inAppLeaveTarget, interfaceFields, interfaceHandlers, isDurableFunctionNodeType, isEditableSourcePath, isForbiddenError, isImageIcon, isLocked, isNodeConfigsInitialized, isNodeTrigger, isNodeTypeHiddenFromPalette, isParamVisible, isQuotaExhaustedFailure, isTriggerOperation, leaseCallQueue, leaveNeedsConfirmation, listCustomBlocks, liveInternalOperations, loadDefinitionJson, mergeStickyNotes, nodeAccent, nodesOf, onNodeTypesUpdate, openRunQuotaUpgradePrompt, parseParameterValue, parseRawSignalPayload, pathToExpression, payloadFromCardValues, phaseAfterAcquire, phaseAfterTakeOver, projectLanguage, readCodeWorkflowState, readDisplayOptions, refetchStoreNodes, registerCustomBlock, registerWorkflowNodeTypes, releasesOnClose, rememberOwnStatusChange, rememberRevision, rememberSessionForReload, resolveInputHandles, resolveNodeOperation, resolveOperationName, resolveOutputHandles, resolveUiSpec, runPreparationOf, runSignalTargets, runTriggerFromMode, saveIndicatorOf, savesInPlace, sessionBeforeReload, shouldReleaseForIdle, signalPayloadCard, snapshotForSave, sourceLanguageOf, stripSubmitActions, structuredParameterType, subscribeWorkflowSaved, synchronizeOperationUpdate, throwIfResultError, tickAction, toCodeMirrorDiagnostics, useAgentDefinitionList, useAgentDefinitions, useBuilderReadOnly, useCodeWorkflowInterface, useConnection, useConnections, useConnectionsByProvider, useCreateConnection, useDurableFunctionNodesEnabled, useDurableParityEnabled, useEditLeaseLocked, useEditLeaseStore, useFlowStore, useFluidGridsAnalytics, useFluidGridsContext, useFluidGridsFlag, useFluidGridsPermission, useInitiateOAuth, useInsertNode, useIsValidConnection, useNodeExecution, useNodeRegistryRevision, useProviders, useSaveStatusStore, useSaveWorkflow, workflowFingerprint };