@burdenoff/fluidgrids-fe-sdk 2026.1111.12 → 2026.1111.14

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 (33) hide show
  1. package/dist/{ExecutionDetailPage-CDkJeeu2.js → ExecutionDetailPage-itor_whl.js} +4 -4
  2. package/dist/{FluidGridsProvider-CDZjKmfD.js → FluidGridsProvider-B30VcLdX.js} +236 -17
  3. package/dist/{HistoryPage-DnVGN_72.js → HistoryPage-DueEld8g.js} +1 -1
  4. package/dist/{InsightsPage-CGRpZtGu.js → InsightsPage-DQ7KCR9h.js} +2 -2
  5. package/dist/{ManagedAiPolicyAuthority-DbJBledZ.js → ManagedAiPolicyAuthority-C0YPTJMS.js} +2 -2
  6. package/dist/{MissingNodesInstallModal-YI57ImRx.js → MissingNodesInstallModal-Cj31oMDX.js} +1 -1
  7. package/dist/{TemplateConfigurationModal-BimyvVH6.js → TemplateConfigurationModal-BAPCG8y-.js} +1 -1
  8. package/dist/{TemplateDetailPanel-CkwB6vrW.js → TemplateDetailPanel-CZ1uxEQL.js} +1 -1
  9. package/dist/{TemplatesPage-ZK6cMWur.js → TemplatesPage-DWdgZnIH.js} +4 -4
  10. package/dist/{WorkflowSearchRedirect-BHtdF64q.js → WorkflowSearchRedirect-C8vhSZK9.js} +32 -49
  11. package/dist/{WorkflowShareDialog-ByTSWwwR.js → WorkflowShareDialog-DnBQA3V6.js} +1 -1
  12. package/dist/{WorkflowsList-B9F2e8M6.js → WorkflowsList-74jjJFsJ.js} +4 -4
  13. package/dist/{agentTools-Dgrdql-W.js → agentTools-D5AW7zHn.js} +2 -2
  14. package/dist/canvasNoteTools-BqQTTCll.js +136 -0
  15. package/dist/executions.js +1 -1
  16. package/dist/{flow-builder-CukxgO65.js → flow-builder-BR8p5tXG.js} +520 -65
  17. package/dist/history.js +1 -1
  18. package/dist/{index-BES5GtJJ.d.ts → index-CLqh2u28.d.ts} +73 -2
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.js +440 -19
  21. package/dist/{node-detail-view-DRk8Ln5L.js → node-detail-view-Dnhqdn8C.js} +3 -3
  22. package/dist/observability.d.ts +1 -1
  23. package/dist/observability.js +1 -1
  24. package/dist/{quick-config-panel-40_1utiL.js → quick-config-panel-C4tSpCrt.js} +2 -2
  25. package/dist/settings.js +1 -1
  26. package/dist/templates.js +1 -1
  27. package/dist/{useExecutions-BqoD7XWi.js → useExecutions-CNEN1ENQ.js} +1 -1
  28. package/dist/{useObservability-Cs-5_NHh.js → useObservability-CmFFXmKb.js} +1 -1
  29. package/dist/{useRunHistory-CEL-CIz-.js → useRunHistory-DhU_mrzF.js} +1 -1
  30. package/dist/{useWorkflows-Bwpvfdgv.js → useWorkflows-D01LC39Y.js} +1 -1
  31. package/dist/workflow-builder.js +2 -2
  32. package/dist/workflows-list.js +1 -1
  33. package/package.json +1 -1
@@ -1,13 +1,13 @@
1
1
  "use client";
2
2
  import { Dr as WorkflowDefinitionDocument, Oi as getFluidGridsClient, Ui as throwIfResultError, oa as __exportAll, qi as getFluidGridsConfig } from "./node-endpoint-configs-DHFGA5MQ.js";
3
- import { Ct as classifyCreateRefusal, Dt as useSaveStatusStore, G as paramsFromOperation, Jt as codeBuildIdOf, On as useCanvasEdges, P as createConfiguredNode, Qt as workflowFingerprint, Sn as BILLING_PLANS_PATH, Wt as rememberRevision, f as refetchStoreNodes, l as ensureNodeTypesLoaded, m as registerWorkflowNodeTypes, n as FluidGridsProvider, o as NODE_CONFIGS, p as registerNodeManifests, sn as resolveNodeOperation, xt as blankWorkflowCreateInput } from "./FluidGridsProvider-CDZjKmfD.js";
3
+ import { At as useSaveStatusStore, Et as classifyCreateRefusal, J as paramsFromOperation, L as createConfiguredNode, Tn as BILLING_PLANS_PATH, Zt as codeBuildIdOf, g as registerWorkflowNodeTypes, h as registerNodeManifests, jn as useCanvasEdges, m as refetchStoreNodes, n as FluidGridsProvider, o as NODE_CONFIGS, qt as rememberRevision, tn as workflowFingerprint, u as ensureNodeTypesLoaded, un as resolveNodeOperation, wt as blankWorkflowCreateInput } from "./FluidGridsProvider-B30VcLdX.js";
4
4
  import { F as mergeStickyNotes, H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
5
5
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
6
- import { F as buildRequiredNodeTypes, P as buildNodeCheck, R as useInstalledNodes, dt as FluidGridsMark, ft as Card, h as useWorkflowReloadStore, m as releaseLeaseKeptForReload, t as FlowBuilderPage, ut as useNodeSelectedEvent, vt as Input } from "./flow-builder-CukxgO65.js";
6
+ import { B as getWorkflowNodeTypes, Ct as Input, R as buildNodeCheck, U as useInstalledNodes, _t as Card, gt as FluidGridsMark, h as useWorkflowReloadStore, ht as useNodeSelectedEvent, m as releaseLeaseKeptForReload, t as FlowBuilderPage, z as buildRequiredNodeTypes } from "./flow-builder-BR8p5tXG.js";
7
7
  import { t as cn } from "./cn-QqidFIgr.js";
8
8
  import { i as Button } from "./PublishCustomNodeAction-D2F7oN0S.js";
9
- import { l as useLazyWorkflowDefinition, m as useWorkflowDefinition, n as useCreateWorkflow } from "./useWorkflows-Bwpvfdgv.js";
10
- import { O as CreateWorkflowRefusalDialog } from "./WorkflowShareDialog-ByTSWwwR.js";
9
+ import { l as useLazyWorkflowDefinition, m as useWorkflowDefinition, n as useCreateWorkflow } from "./useWorkflows-D01LC39Y.js";
10
+ import { O as CreateWorkflowRefusalDialog } from "./WorkflowShareDialog-DnBQA3V6.js";
11
11
  import { c as withoutGuidedTourIntent, l as decideMissingWorkflow, o as isGuidedTourIntent, s as pickGuidedTour, u as isCreateIntent } from "./firstWorkflow-C_h0KMB2.js";
12
12
  import { t as canvasFromDefinition } from "./definition-canvas--3MPHoP-.js";
13
13
  import { n as registerLiveCanvasHandler } from "./liveCanvas-D5ytXDp8.js";
@@ -1626,7 +1626,7 @@ function GuidedTourStarter({ ready }) {
1626
1626
  }
1627
1627
 
1628
1628
  // src/builder/app/workflow/work/page.tsx
1629
- const LazyMissingNodesInstallModal = lazy(() => import("./MissingNodesInstallModal-YI57ImRx.js").then((m) => ({ default: m.MissingNodesInstallModal })));
1629
+ const LazyMissingNodesInstallModal = lazy(() => import("./MissingNodesInstallModal-Cj31oMDX.js").then((m) => ({ default: m.MissingNodesInstallModal })));
1630
1630
  function WorkflowItem({ readonly = false }) {
1631
1631
  if (readonly) {
1632
1632
  const queryParams = new URLSearchParams(window.location.search);
@@ -1673,7 +1673,6 @@ function WorkflowItem({ readonly = false }) {
1673
1673
  const fetchedWorkflowRef = useRef(null);
1674
1674
  const loadSeqRef = useRef(0);
1675
1675
  const { installedAppIds } = useInstalledNodes();
1676
- const [pendingWorkflow, setPendingWorkflow] = useState(null);
1677
1676
  const [nodeCheck, setNodeCheck] = useState(null);
1678
1677
  const [configModalOpen, setConfigModalOpen] = useState(false);
1679
1678
  const [installing, setInstalling] = useState(false);
@@ -1689,15 +1688,14 @@ function WorkflowItem({ readonly = false }) {
1689
1688
  trRef.current = tr;
1690
1689
  });
1691
1690
  const handleInstallConfirm = useCallback(async () => {
1692
- if (!pendingWorkflow) return;
1693
1691
  const nodesToInstall = (nodeCheck?.missing ?? []).filter((n) => !!n.storeProductId);
1694
1692
  const failed = [];
1695
1693
  if (nodesToInstall.length > 0) {
1696
1694
  setInstalling(true);
1697
1695
  setInstallErrors([]);
1698
1696
  try {
1699
- const { getGlobalStoreClient } = await import("./FluidGridsProvider-CDZjKmfD.js").then((n) => n.dr);
1700
- const { InstallWorkflowNodeDocument } = await import("./FluidGridsProvider-CDZjKmfD.js").then((n) => n._);
1697
+ const { getGlobalStoreClient } = await import("./FluidGridsProvider-B30VcLdX.js").then((n) => n.mr);
1698
+ const { InstallWorkflowNodeDocument } = await import("./FluidGridsProvider-B30VcLdX.js").then((n) => n.y);
1701
1699
  const { getFluidGridsConfig } = await import("./node-endpoint-configs-DHFGA5MQ.js").then((n) => n.Ki);
1702
1700
  const storeClient = getGlobalStoreClient();
1703
1701
  const cfg = getFluidGridsConfig();
@@ -1724,6 +1722,7 @@ function WorkflowItem({ readonly = false }) {
1724
1722
  }
1725
1723
  }
1726
1724
  await refetchStoreNodes();
1725
+ await ensureNodeTypesLoaded(nodesToInstall.map((n) => n.nodeType));
1727
1726
  } finally {
1728
1727
  setInstalling(false);
1729
1728
  setInstallProgress(null);
@@ -1735,17 +1734,12 @@ function WorkflowItem({ readonly = false }) {
1735
1734
  }
1736
1735
  setInstallErrors([]);
1737
1736
  setConfigModalOpen(false);
1738
- setWorkflow(pendingWorkflow);
1739
- setPendingWorkflow(null);
1740
1737
  setNodeCheck(null);
1741
- }, [pendingWorkflow, nodeCheck]);
1738
+ }, [nodeCheck]);
1742
1739
  const handleSkipInstall = useCallback(() => {
1743
- if (!pendingWorkflow) return;
1744
1740
  setConfigModalOpen(false);
1745
- setWorkflow(pendingWorkflow);
1746
- setPendingWorkflow(null);
1747
1741
  setNodeCheck(null);
1748
- }, [pendingWorkflow]);
1742
+ }, []);
1749
1743
  const newWorkflow = useMemo(() => ({
1750
1744
  id: id ?? "",
1751
1745
  workflowKey: id ?? "",
@@ -1778,10 +1772,24 @@ function WorkflowItem({ readonly = false }) {
1778
1772
  if (pendingReloadRef.current === target) pendingReloadRef.current = null;
1779
1773
  return true;
1780
1774
  };
1775
+ const offerMissingNodes = (nodes) => {
1776
+ buildRequiredNodeTypes(nodes).then((requiredNodeTypes) => {
1777
+ if (!mounted || requiredNodeTypes.length === 0) return;
1778
+ const check = doNodeCheckRef.current(requiredNodeTypes);
1779
+ if (check.missing.length > 0 || check.missingPaid.length > 0) {
1780
+ setNodeCheck(check);
1781
+ setConfigModalOpen(true);
1782
+ }
1783
+ }).catch((error) => {
1784
+ console.warn("[WorkflowItem] Missing-nodes check failed:", error);
1785
+ });
1786
+ };
1781
1787
  const loadWorkflow = async () => {
1782
1788
  try {
1783
1789
  resetWorkflow();
1784
1790
  if (mounted) setNotFound(false);
1791
+ if (mounted) setConfigModalOpen(false);
1792
+ if (mounted) setNodeCheck(null);
1785
1793
  if (mounted) setLoadError(null);
1786
1794
  if (mounted) setReloadFailed(false);
1787
1795
  if (version && mounted) setIsLoading(true);
@@ -1796,26 +1804,12 @@ function WorkflowItem({ readonly = false }) {
1796
1804
  nodes: manifest.nodes ?? [],
1797
1805
  edges: manifest.edges ?? []
1798
1806
  };
1799
- let requiredNodeTypes = [];
1800
- try {
1801
- requiredNodeTypes = await buildRequiredNodeTypes(sharedWorkflow.nodes);
1802
- } catch {}
1803
1807
  if (mounted) {
1804
1808
  localStorage.removeItem("pendingSharedWorkflow");
1805
- if (requiredNodeTypes.length > 0) {
1806
- const check = doNodeCheckRef.current(requiredNodeTypes);
1807
- if (check.missing.length > 0 || check.missingPaid.length > 0) {
1808
- setPendingWorkflow(sharedWorkflow);
1809
- setNodeCheck(check);
1810
- setConfigModalOpen(true);
1811
- setIsLoading(false);
1812
- fromSharedLoadedRef.current = true;
1813
- return;
1814
- }
1815
- }
1816
1809
  setWorkflow(sharedWorkflow);
1817
1810
  setIsLoading(false);
1818
1811
  fromSharedLoadedRef.current = true;
1812
+ offerMissingNodes(sharedWorkflow.nodes);
1819
1813
  }
1820
1814
  return;
1821
1815
  } catch (e) {
@@ -1857,7 +1851,6 @@ function WorkflowItem({ readonly = false }) {
1857
1851
  }
1858
1852
  const freshCreate = createIntentRef.current && !creatingRef.current && !fetchedCopy() && !loadRunId;
1859
1853
  const result = freshCreate ? null : await getWorkflow(id, void 0, version);
1860
- if (result?.nodeManifests) registerNodeManifests(result.nodeManifests);
1861
1854
  const definitionJson = result?.definitionJson;
1862
1855
  const defData = definitionJson?.data ?? (definitionJson?.nodes ? definitionJson : void 0);
1863
1856
  if (defData) {
@@ -1874,21 +1867,11 @@ function WorkflowItem({ readonly = false }) {
1874
1867
  codeBuildId: codeBuildIdOf(result?.definitionJson)
1875
1868
  };
1876
1869
  if (recordFetched(workflowState)) rememberRevision(result?.id, result?.revision);
1877
- let requiredNodeTypes = [];
1878
- try {
1879
- requiredNodeTypes = await buildRequiredNodeTypes(workflowState.nodes);
1880
- } catch {}
1881
- if (mounted && requiredNodeTypes.length > 0) {
1882
- const check = doNodeCheckRef.current(requiredNodeTypes);
1883
- if (check.missing.length > 0 || check.missingPaid.length > 0) {
1884
- setPendingWorkflow(workflowState);
1885
- setNodeCheck(check);
1886
- setConfigModalOpen(true);
1887
- setIsLoading(false);
1888
- return;
1889
- }
1870
+ if (Array.isArray(result?.nodeManifests)) registerNodeManifests(result.nodeManifests, getWorkflowNodeTypes(workflowState.nodes));
1871
+ if (mounted) {
1872
+ setWorkflow(workflowState);
1873
+ offerMissingNodes(workflowState.nodes);
1890
1874
  }
1891
- if (mounted) setWorkflow(workflowState);
1892
1875
  return;
1893
1876
  }
1894
1877
  if (mounted) {
@@ -2054,14 +2037,14 @@ function WorkflowItem({ readonly = false }) {
2054
2037
  onBack: () => navigate("../list")
2055
2038
  });
2056
2039
  return /* @__PURE__ */ jsxs(Fragment, { children: [
2057
- configModalOpen && pendingWorkflow && /* @__PURE__ */ jsx(Suspense, {
2040
+ configModalOpen && workflow && /* @__PURE__ */ jsx(Suspense, {
2058
2041
  fallback: null,
2059
2042
  children: /* @__PURE__ */ jsx(LazyMissingNodesInstallModal, {
2060
2043
  open: configModalOpen,
2061
2044
  onOpenChange: (open) => {
2062
2045
  if (!open) handleSkipInstall();
2063
2046
  },
2064
- workflowName: pendingWorkflow.name,
2047
+ workflowName: workflow.name,
2065
2048
  nodeCheckResult: nodeCheck,
2066
2049
  onConfirm: handleInstallConfirm,
2067
2050
  onSkip: handleSkipInstall,
@@ -2085,7 +2068,7 @@ function WorkflowItem({ readonly = false }) {
2085
2068
  }),
2086
2069
  workflow && !isLoading && /* @__PURE__ */ jsx(FlowBuilderPage, { workflow }),
2087
2070
  workflow && !isLoading && /* @__PURE__ */ jsx(AssistantLiveCanvasHost, {}),
2088
- /* @__PURE__ */ jsx(GuidedTourStarter, { ready: Boolean(workflow && !isLoading) })
2071
+ /* @__PURE__ */ jsx(GuidedTourStarter, { ready: Boolean(workflow && !isLoading && !configModalOpen) })
2089
2072
  ] });
2090
2073
  }
2091
2074
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { Bi as describeOperationError, Nn as ShareWorkflowDocument, Oi as getFluidGridsClient, Ui as throwIfResultError, ft as ExportWorkflowCodeDocument, ui as WorkflowSharingDocument } from "./node-endpoint-configs-DHFGA5MQ.js";
3
- import { gn as emitUpgradeClicked, ln as useFluidGridsAnalytics, vn as emitWorkflowLimitHit, wn as WORKFLOWS_QUOTA_NAME } from "./FluidGridsProvider-CDZjKmfD.js";
3
+ import { Dn as WORKFLOWS_QUOTA_NAME, fn as useFluidGridsAnalytics, xn as emitWorkflowLimitHit, yn as emitUpgradeClicked } from "./FluidGridsProvider-B30VcLdX.js";
4
4
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
5
5
  import { CF as WorkflowExportFormat, Fd as FidelityLevel, JF as WorkflowShareRole, hF as WorkflowAccess, nI as WorkflowVisibility, qF as WorkflowSharePrincipalType } from "./graphql-types-XcDLtFwU.js";
6
6
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -1,12 +1,12 @@
1
1
  "use client";
2
- import { c as useImportWorkflow, h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, n as useCreateWorkflow, o as useDeleteWorkflow, s as useDuplicateWorkflow, u as usePreviewN8nImport } from "./useWorkflows-Bwpvfdgv.js";
3
- import { Bn as FLUIDGRIDS_FLAGS, Dn as isQuotaExhaustedFailure, Jn as useFluidGridsFlag, Sn as BILLING_PLANS_PATH, t as FluidGridsContext, wt as createThenOpen } from "./FluidGridsProvider-CDZjKmfD.js";
4
- import { C as readProjectArchive, D as workflowNameFromFile, E as typeScriptModuleFile, O as CreateWorkflowRefusalDialog, S as primaryImportModule, T as typeScriptImportSource, _ as importFileKind, a as downloadWorkflowExport, c as canShareWorkflow, d as MAX_IMPORT_ARCHIVE_BYTES, f as MAX_IMPORT_SOURCE_BYTES, g as importAcceptAttribute, k as QuotaExhaustedDialog, l as CODE_EXPORT_FORMATS, m as checkTypeScriptImport, o as parseWorkflowImport, p as assertImportByteSize, r as useExportWorkflowAs, s as canEditWorkflow, t as WorkflowShareDialog, u as ImportSourceError } from "./WorkflowShareDialog-ByTSWwwR.js";
2
+ import { c as useImportWorkflow, h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, n as useCreateWorkflow, o as useDeleteWorkflow, s as useDuplicateWorkflow, u as usePreviewN8nImport } from "./useWorkflows-D01LC39Y.js";
3
+ import { An as isQuotaExhaustedFailure, Dt as createThenOpen, Tn as BILLING_PLANS_PATH, Un as FLUIDGRIDS_FLAGS, Zn as useFluidGridsFlag, t as FluidGridsContext } from "./FluidGridsProvider-B30VcLdX.js";
4
+ import { C as readProjectArchive, D as workflowNameFromFile, E as typeScriptModuleFile, O as CreateWorkflowRefusalDialog, S as primaryImportModule, T as typeScriptImportSource, _ as importFileKind, a as downloadWorkflowExport, c as canShareWorkflow, d as MAX_IMPORT_ARCHIVE_BYTES, f as MAX_IMPORT_SOURCE_BYTES, g as importAcceptAttribute, k as QuotaExhaustedDialog, l as CODE_EXPORT_FORMATS, m as checkTypeScriptImport, o as parseWorkflowImport, p as assertImportByteSize, r as useExportWorkflowAs, s as canEditWorkflow, t as WorkflowShareDialog, u as ImportSourceError } from "./WorkflowShareDialog-DnBQA3V6.js";
5
5
  import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
6
6
  import { CF as WorkflowExportFormat, gF as WorkflowAccessFilter, hI as FLUIDGRIDS_PERMISSIONS, vI as SdkPermissionButton, xI as useFluidGridsPermission, yI as SdkPermissionGate } from "./graphql-types-XcDLtFwU.js";
7
7
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
8
8
  import { $t as RenameWorkflowFolderDocument, Bi as describeOperationError, Et as MoveWorkflowFolderDocument, K as DeleteWorkflowFolderDocument, M as CreateWorkflowFolderDocument, N as CreateWorkflowProjectDocument, Oi as getFluidGridsClient, Pr as WorkflowFoldersDocument, Ui as throwIfResultError, Ur as WorkflowProjectsDocument, _ as BulkMoveWorkflowsToFolderDocument, en as RenameWorkflowProjectDocument, g as BulkDeleteWorkflowsDocument, h as BulkAssignWorkflowsToProjectDocument, oa as __exportAll, q as DeleteWorkflowProjectDocument } from "./node-endpoint-configs-DHFGA5MQ.js";
9
- import { a as useExecutions } from "./useExecutions-BqoD7XWi.js";
9
+ import { a as useExecutions } from "./useExecutions-CNEN1ENQ.js";
10
10
  import { a as firstWorkflowProgress, i as builderPathFor, r as GUIDED_TOUR_STATE } from "./firstWorkflow-C_h0KMB2.js";
11
11
  import { n as useFluidGridsPageControls } from "./pageControlsBridge-0pX9s-3k.js";
12
12
  import { i as workflowsListControls } from "./pageControlSpecs-DZJ9K37m.js";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { Dt as useSaveStatusStore, G as paramsFromOperation, K as selectedOperationOf, P as createConfiguredNode, U as nodeTitle, V as fixedParameterState, h as registryNodeData, o as NODE_CONFIGS, u as isNodeConfigsInitialized, ut as autosaveAllowedFor, vt as isFlowComplete } from "./FluidGridsProvider-CDZjKmfD.js";
2
+ import { At as useSaveStatusStore, J as paramsFromOperation, K as nodeTitle, L as createConfiguredNode, W as fixedParameterState, Y as selectedOperationOf, _ as registryNodeData, f as isNodeConfigsInitialized, o as NODE_CONFIGS, pt as autosaveAllowedFor, xt as isFlowComplete } from "./FluidGridsProvider-B30VcLdX.js";
3
3
  import { E as resolveOutputHandles, H as useFlowStore, T as resolveInputHandles } from "./node-operation-selection--oy-yEq_.js";
4
- import { M as computeAttachPosition, wt as isNodeTypeHiddenFromPalette } from "./flow-builder-CukxgO65.js";
4
+ import { I as computeAttachPosition, kt as isNodeTypeHiddenFromPalette } from "./flow-builder-BR8p5tXG.js";
5
5
  import { AgentToolError, defineAgentTool } from "@burdenoff/fe-libs/shared/agent-tools";
6
6
  import { z } from "zod";
7
7
 
@@ -0,0 +1,136 @@
1
+ "use client";
2
+ import { g as notesKeyOf, v as useAgentMarksStore, y as toPlainText } from "./flow-builder-BR8p5tXG.js";
3
+ import { J as paramsFromOperation, K as nodeTitle, Y as selectedOperationOf } from "./FluidGridsProvider-B30VcLdX.js";
4
+ import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
5
+ import { AgentToolError, defineAgentTool } from "@burdenoff/fe-libs/shared/agent-tools";
6
+ import { z } from "zod";
7
+
8
+ // src/builder/agentNotes/canvasNoteTools.ts
9
+ const MAX_NOTES_LISTED = 20;
10
+ function workflow() {
11
+ return useFlowStore.getState().workflow;
12
+ }
13
+ function dataOf(node) {
14
+ return node.data && typeof node.data === "object" ? node.data : {};
15
+ }
16
+ const nodeRef = z.string().trim().min(1).max(100).describe("A node id from fg_canvas_read, or the node's exact title.");
17
+ /** A node by id, else by exact title (case-insensitive) when that is unique. */
18
+ function resolveNode(ref) {
19
+ const nodes = workflow().nodes;
20
+ const byId = nodes.find((node) => node.id === ref);
21
+ if (byId) return byId;
22
+ const wanted = ref.toLowerCase();
23
+ const byTitle = nodes.filter((node) => nodeTitle(node).toLowerCase() === wanted);
24
+ if (byTitle.length === 1 && byTitle[0]) return byTitle[0];
25
+ if (byTitle.length > 1) throw new AgentToolError("INVALID_INPUT", `${byTitle.length} nodes are titled "${ref.slice(0, 40)}": ${byTitle.slice(0, 6).map((node) => node.id).join(", ")}. Use the node id.`);
26
+ throw new AgentToolError("NOT_FOUND", `No node "${ref.slice(0, 40)}" on the canvas. Use fg_canvas_read for ids.`, { retryable: true });
27
+ }
28
+ /** The parameter names a node's operation has. */
29
+ function parameterNames(node) {
30
+ return paramsFromOperation(selectedOperationOf(dataOf(node), node.type)).map((parameter) => parameter.name);
31
+ }
32
+ function summary(note, liveIds) {
33
+ return {
34
+ number: note.number,
35
+ nodeId: note.nodeId,
36
+ node: note.nodeLabel,
37
+ ...note.paramKey ? { param: note.paramKey } : {},
38
+ kind: note.kind,
39
+ message: toPlainText(note.message, 120),
40
+ resolved: note.resolved,
41
+ ...liveIds.has(note.nodeId) ? {} : { orphaned: true }
42
+ };
43
+ }
44
+ function createCanvasNoteTools(options = {}) {
45
+ const focus = async (nodeId) => {
46
+ if (!options.focusNode) return false;
47
+ const done = await options.focusNode(nodeId);
48
+ if (done) useAgentMarksStore.getState().actions.flashNode(nodeId);
49
+ return done;
50
+ };
51
+ return [
52
+ defineAgentTool({
53
+ name: "fg_canvas_annotate",
54
+ title: "Pin a note on a node",
55
+ description: "Pins a numbered note on a node of the workflow open in the builder, to show the person what to change or check there (they resolve it). It does not change the workflow. Use kind fix for something they must change, info for an explanation. Name the parameter with param when the note is about one field.",
56
+ input: z.strictObject({
57
+ node: nodeRef,
58
+ message: z.string().trim().min(1).max(280).describe("What to do or know, in one or two plain sentences. No markdown."),
59
+ kind: z.enum(["fix", "info"]).default("fix").describe("fix: the person must change something; info: an explanation."),
60
+ param: z.string().trim().min(1).max(80).optional().describe("A parameter name of the node the note is about; an unknown one lists the valid names."),
61
+ focus: z.boolean().default(true).describe("Bring the node into view (default true).")
62
+ }),
63
+ annotations: {
64
+ readOnly: true,
65
+ untrustedContent: true
66
+ },
67
+ execute: async ({ node: ref, message, kind, param, focus: bringIntoView }) => {
68
+ const node = resolveNode(ref);
69
+ if (param) {
70
+ const names = parameterNames(node);
71
+ if (!names.includes(param)) throw new AgentToolError("INVALID_INPUT", names.length > 0 ? `No parameter "${param.slice(0, 40)}". Parameters: ${names.slice(0, 20).join(", ")}.` : "This node has no parameters; leave param out.");
72
+ }
73
+ const key = notesKeyOf(workflow());
74
+ const note = useAgentMarksStore.getState().actions.addNote({
75
+ workflowKey: key,
76
+ nodeId: node.id,
77
+ nodeLabel: nodeTitle(node),
78
+ paramKey: param ?? null,
79
+ kind,
80
+ message
81
+ });
82
+ if (!note) throw new AgentToolError("CONFLICT", `This workflow already has ${20} notes. Ask the person to resolve some, or clear them with fg_ui_clear_marks.`);
83
+ const focused = bringIntoView ? await focus(node.id) : false;
84
+ return {
85
+ noteNumber: note.number,
86
+ nodeId: node.id,
87
+ node: note.nodeLabel,
88
+ ...note.paramKey ? { param: note.paramKey } : {},
89
+ focused
90
+ };
91
+ }
92
+ }),
93
+ defineAgentTool({
94
+ name: "fg_canvas_notes",
95
+ title: "List the notes on the canvas",
96
+ description: "Lists the notes you pinned on the open workflow: number, node, parameter, message, whether the person resolved it, and orphaned when its node was deleted.",
97
+ input: z.strictObject({}),
98
+ annotations: {
99
+ readOnly: true,
100
+ untrustedContent: true
101
+ },
102
+ execute: () => {
103
+ const current = workflow();
104
+ const key = notesKeyOf(current);
105
+ const liveIds = new Set(current.nodes.map((node) => node.id));
106
+ const notes = useAgentMarksStore.getState().notes.filter((note) => note.workflowKey === key);
107
+ return {
108
+ total: notes.length,
109
+ open: notes.filter((note) => !note.resolved).length,
110
+ notes: notes.slice(0, MAX_NOTES_LISTED).map((note) => summary(note, liveIds))
111
+ };
112
+ }
113
+ }),
114
+ defineAgentTool({
115
+ name: "fg_canvas_focus_node",
116
+ title: "Show a node",
117
+ description: "Pans and zooms the builder canvas to one node and briefly highlights it, so the person can see it. It does not change the workflow.",
118
+ input: z.strictObject({ node: nodeRef }),
119
+ annotations: {
120
+ readOnly: true,
121
+ untrustedContent: true
122
+ },
123
+ execute: async ({ node: ref }) => {
124
+ const node = resolveNode(ref);
125
+ if (!await focus(node.id)) throw new AgentToolError("CONFLICT", "The canvas is not ready yet. Try again in a moment.", { retryable: true });
126
+ return {
127
+ nodeId: node.id,
128
+ node: nodeTitle(node),
129
+ focused: true
130
+ };
131
+ }
132
+ })
133
+ ];
134
+ }
135
+
136
+ export { createCanvasNoteTools };
@@ -1,4 +1,4 @@
1
1
  "use client";
2
- import { t as ExecutionDetailPage, y as ExecutionsListPage } from "./ExecutionDetailPage-CDkJeeu2.js";
2
+ import { t as ExecutionDetailPage, y as ExecutionsListPage } from "./ExecutionDetailPage-itor_whl.js";
3
3
 
4
4
  export { ExecutionDetailPage, ExecutionsListPage };