@burdenoff/fluidgrids-fe-sdk 2026.1111.12 → 2026.1111.13

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.
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { A as DialogTitle, D as DialogHeader, E as DialogFooter, S as Dialog, T as DialogDescription, b as Badge, w as DialogContent } from "./flow-builder-CukxgO65.js";
2
+ import { A as DialogFooter, E as Dialog, O as DialogContent, P as DialogTitle, j as DialogHeader, k as DialogDescription, w as Badge } from "./flow-builder-BvCQAGDR.js";
3
3
  import { i as Button } from "./PublishCustomNodeAction-D2F7oN0S.js";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { AlertTriangle, CheckCircle2, Download, ExternalLink, Loader2, Puzzle, ShoppingCart } from "lucide-react";
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { A as DialogTitle, D as DialogHeader, E as DialogFooter, S as Dialog, T as DialogDescription, b as Badge, vt as Input, w as DialogContent } from "./flow-builder-CukxgO65.js";
2
+ import { A as DialogFooter, E as Dialog, O as DialogContent, P as DialogTitle, St as Input, j as DialogHeader, k as DialogDescription, w as Badge } from "./flow-builder-BvCQAGDR.js";
3
3
  import { i as Button } from "./PublishCustomNodeAction-D2F7oN0S.js";
4
4
  import { t as Label } from "./label-CDy86rIZ.js";
5
5
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { i as Button } from "./PublishCustomNodeAction-D2F7oN0S.js";
3
- import { b as Badge, y as templatePreview } from "./flow-builder-CukxgO65.js";
3
+ import { C as templatePreview, w as Badge } from "./flow-builder-BvCQAGDR.js";
4
4
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
5
5
  import { hI as FLUIDGRIDS_PERMISSIONS, vI as SdkPermissionButton } from "./graphql-types-XcDLtFwU.js";
6
6
  import { Icon } from "@iconify/react";
@@ -2,7 +2,7 @@
2
2
  import { Bi as describeOperationError, Ui as throwIfResultError } from "./node-endpoint-configs-DHFGA5MQ.js";
3
3
  import { Dn as isQuotaExhaustedFailure, E as MyWorkflowTemplateSubmissionsDocument, O as SubmitWorkflowTemplateDocument, Sn as BILLING_PLANS_PATH, hn as emitTemplateUsed, j as WithdrawWorkflowTemplateSubmissionDocument, ln as useFluidGridsAnalytics } from "./FluidGridsProvider-CDZjKmfD.js";
4
4
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
5
- import { I as useImportWorkflowTemplate, L as useWorkflowTemplates, N as useTemplateImportFlow, Y as useGlobalStoreClient, t as FlowBuilderPage, v as TemplateCard } from "./flow-builder-CukxgO65.js";
5
+ import { $ as useGlobalStoreClient, B as useImportWorkflowTemplate, L as useTemplateImportFlow, S as TemplateCard, V as useWorkflowTemplates, t as FlowBuilderPage } from "./flow-builder-BvCQAGDR.js";
6
6
  import { h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, s as useDuplicateWorkflow } from "./useWorkflows-Bwpvfdgv.js";
7
7
  import { k as QuotaExhaustedDialog } from "./WorkflowShareDialog-ByTSWwwR.js";
8
8
  import { YF as WorkflowStatus, hI as FLUIDGRIDS_PERMISSIONS, vI as SdkPermissionButton } from "./graphql-types-XcDLtFwU.js";
@@ -3,7 +3,7 @@ import { Dr as WorkflowDefinitionDocument, Oi as getFluidGridsClient, Ui as thro
3
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";
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 { H as useInstalledNodes, R as buildNodeCheck, St as Input, gt as Card, h as useWorkflowReloadStore, ht as FluidGridsMark, m as releaseLeaseKeptForReload, mt as useNodeSelectedEvent, t as FlowBuilderPage, z as buildRequiredNodeTypes } from "./flow-builder-BvCQAGDR.js";
7
7
  import { t as cn } from "./cn-QqidFIgr.js";
8
8
  import { i as Button } from "./PublishCustomNodeAction-D2F7oN0S.js";
9
9
  import { l as useLazyWorkflowDefinition, m as useWorkflowDefinition, n as useCreateWorkflow } from "./useWorkflows-Bwpvfdgv.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-Ca4f--lw.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);
@@ -1,7 +1,7 @@
1
1
  "use client";
2
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";
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, Ot as isNodeTypeHiddenFromPalette } from "./flow-builder-BvCQAGDR.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-BvCQAGDR.js";
3
+ import { G as paramsFromOperation, K as selectedOperationOf, U as nodeTitle } from "./FluidGridsProvider-CDZjKmfD.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 };