@flowdrop/flowdrop 1.4.0 → 1.5.0
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.
- package/README.md +68 -24
- package/dist/adapters/WorkflowAdapter.js +2 -22
- package/dist/adapters/agentspec/autoLayout.d.ts +51 -5
- package/dist/adapters/agentspec/autoLayout.js +120 -23
- package/dist/chat/commandClassifier.d.ts +19 -0
- package/dist/chat/commandClassifier.js +30 -0
- package/dist/chat/index.d.ts +27 -0
- package/dist/chat/index.js +32 -0
- package/dist/chat/responseParser.d.ts +21 -0
- package/dist/chat/responseParser.js +87 -0
- package/dist/commands/batch.d.ts +18 -0
- package/dist/commands/batch.js +56 -0
- package/dist/commands/executor.d.ts +37 -0
- package/dist/commands/executor.js +1044 -0
- package/dist/commands/index.d.ts +14 -0
- package/dist/commands/index.js +17 -0
- package/dist/commands/parser.d.ts +16 -0
- package/dist/commands/parser.js +278 -0
- package/dist/commands/positioner.d.ts +19 -0
- package/dist/commands/positioner.js +33 -0
- package/dist/commands/storeIntegration.svelte.d.ts +16 -0
- package/dist/commands/storeIntegration.svelte.js +67 -0
- package/dist/commands/types.d.ts +343 -0
- package/dist/commands/types.js +45 -0
- package/dist/components/App.svelte +351 -12
- package/dist/components/App.svelte.d.ts +3 -0
- package/dist/components/CanvasController.svelte +38 -0
- package/dist/components/CanvasController.svelte.d.ts +32 -0
- package/dist/components/ConfigMappingRow.svelte +130 -0
- package/dist/components/ConfigMappingRow.svelte.d.ts +8 -0
- package/dist/components/ConfigPanel.svelte +56 -7
- package/dist/components/ConfigPanel.svelte.d.ts +2 -0
- package/dist/components/FlowDropEdge.svelte +2 -10
- package/dist/components/LogsSidebar.svelte +5 -5
- package/dist/components/NodeSidebar.svelte +15 -49
- package/dist/components/NodeSwapPicker.svelte +537 -0
- package/dist/components/NodeSwapPicker.svelte.d.ts +16 -0
- package/dist/components/PortMappingRow.svelte +209 -0
- package/dist/components/PortMappingRow.svelte.d.ts +12 -0
- package/dist/components/SwapMappingEditor.svelte +550 -0
- package/dist/components/SwapMappingEditor.svelte.d.ts +12 -0
- package/dist/components/WorkflowEditor.svelte +99 -4
- package/dist/components/WorkflowEditor.svelte.d.ts +8 -0
- package/dist/components/chat/AIChatPanel.svelte +658 -0
- package/dist/components/chat/AIChatPanel.svelte.d.ts +13 -0
- package/dist/components/chat/CommandPreview.svelte +184 -0
- package/dist/components/chat/CommandPreview.svelte.d.ts +9 -0
- package/dist/components/console/CommandConsole.stories.svelte +93 -0
- package/dist/components/console/CommandConsole.stories.svelte.d.ts +27 -0
- package/dist/components/console/CommandConsole.svelte +259 -0
- package/dist/components/console/CommandConsole.svelte.d.ts +11 -0
- package/dist/components/console/ConsoleAutocomplete.svelte +139 -0
- package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +21 -0
- package/dist/components/console/ConsoleInput.svelte +712 -0
- package/dist/components/console/ConsoleInput.svelte.d.ts +16 -0
- package/dist/components/console/ConsoleOutput.svelte +121 -0
- package/dist/components/console/ConsoleOutput.svelte.d.ts +11 -0
- package/dist/components/console/formatters.d.ts +26 -0
- package/dist/components/console/formatters.js +118 -0
- package/dist/components/interrupt/index.d.ts +1 -0
- package/dist/components/interrupt/index.js +1 -0
- package/dist/config/endpoints.d.ts +8 -0
- package/dist/config/endpoints.js +5 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +9 -0
- package/dist/editor/index.d.ts +3 -1
- package/dist/editor/index.js +4 -2
- package/dist/helpers/proximityConnect.js +8 -1
- package/dist/helpers/workflowEditorHelper.d.ts +3 -53
- package/dist/helpers/workflowEditorHelper.js +13 -228
- package/dist/playground/index.d.ts +1 -1
- package/dist/playground/index.js +1 -1
- package/dist/schemas/v1/workflow.schema.json +107 -22
- package/dist/services/chatService.d.ts +65 -0
- package/dist/services/chatService.js +131 -0
- package/dist/services/historyService.d.ts +6 -4
- package/dist/services/historyService.js +21 -6
- package/dist/stores/interruptStore.svelte.js +6 -1
- package/dist/stores/playgroundStore.svelte.d.ts +1 -1
- package/dist/stores/playgroundStore.svelte.js +11 -2
- package/dist/stores/portCoordinateStore.svelte.d.ts +4 -0
- package/dist/stores/portCoordinateStore.svelte.js +20 -26
- package/dist/stores/workflowStore.svelte.d.ts +31 -2
- package/dist/stores/workflowStore.svelte.js +84 -64
- package/dist/types/chat.d.ts +63 -0
- package/dist/types/chat.js +9 -0
- package/dist/types/events.d.ts +28 -2
- package/dist/types/events.js +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/settings.d.ts +6 -0
- package/dist/types/settings.js +3 -0
- package/dist/utils/edgeStyling.d.ts +42 -0
- package/dist/utils/edgeStyling.js +176 -0
- package/dist/utils/nodeIds.d.ts +31 -0
- package/dist/utils/nodeIds.js +42 -0
- package/dist/utils/nodeSwap.d.ts +221 -0
- package/dist/utils/nodeSwap.js +686 -0
- package/package.json +6 -1
- package/dist/helpers/nodeLayoutHelper.d.ts +0 -14
- package/dist/helpers/nodeLayoutHelper.js +0 -19
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge Styling Utility
|
|
3
|
+
*
|
|
4
|
+
* Standalone functions for determining edge categories and applying
|
|
5
|
+
* visual styling to workflow edges based on source port data types.
|
|
6
|
+
* Used by both the visual editor and the command DSL system.
|
|
7
|
+
*/
|
|
8
|
+
import { MarkerType } from "@xyflow/svelte";
|
|
9
|
+
import { extractPortId } from "../utils/handleIds.js";
|
|
10
|
+
import { isLoopbackEdge } from "../utils/connections.js";
|
|
11
|
+
import { EDGE_MARKER_SIZES } from "../config/constants.js";
|
|
12
|
+
/**
|
|
13
|
+
* Check if a port ID matches a dynamic branch in a Gateway node.
|
|
14
|
+
* Gateway nodes store branches in config.branches array.
|
|
15
|
+
*/
|
|
16
|
+
export function isGatewayBranch(node, portId) {
|
|
17
|
+
const nodeType = node.data?.metadata?.type || node.type;
|
|
18
|
+
if (nodeType !== "gateway") {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const branches = node.data?.config?.branches;
|
|
22
|
+
if (!branches || !Array.isArray(branches)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return branches.some((branch) => branch.name === portId);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the data type of a port from a node's metadata.
|
|
29
|
+
* Also handles dynamic ports like Gateway branches.
|
|
30
|
+
*/
|
|
31
|
+
export function getPortDataType(node, portId, portType) {
|
|
32
|
+
// First, check static ports in metadata
|
|
33
|
+
const ports = portType === "output"
|
|
34
|
+
? node.data?.metadata?.outputs
|
|
35
|
+
: node.data?.metadata?.inputs;
|
|
36
|
+
if (ports && Array.isArray(ports)) {
|
|
37
|
+
const port = ports.find((p) => p.id === portId);
|
|
38
|
+
if (port?.dataType) {
|
|
39
|
+
return port.dataType;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Check dynamic ports from config (dynamicInputs/dynamicOutputs)
|
|
43
|
+
const dynamicKey = portType === "output" ? "dynamicOutputs" : "dynamicInputs";
|
|
44
|
+
const dynamicPorts = node.data?.config?.[dynamicKey];
|
|
45
|
+
if (dynamicPorts && Array.isArray(dynamicPorts)) {
|
|
46
|
+
const dynamicPort = dynamicPorts.find((p) => p.name === portId);
|
|
47
|
+
if (dynamicPort?.dataType) {
|
|
48
|
+
return dynamicPort.dataType;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// For output ports, also check dynamic Gateway branches
|
|
52
|
+
// Gateway branches are always trigger type (control flow)
|
|
53
|
+
if (portType === "output" && isGatewayBranch(node, portId)) {
|
|
54
|
+
return "trigger";
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Determine the edge category based on source port data type.
|
|
60
|
+
* Note: This does not check for loopback edges — use getEdgeCategoryWithLoopback() for that.
|
|
61
|
+
*/
|
|
62
|
+
export function getEdgeCategory(sourcePortDataType) {
|
|
63
|
+
if (sourcePortDataType === "trigger") {
|
|
64
|
+
return "trigger";
|
|
65
|
+
}
|
|
66
|
+
if (sourcePortDataType === "tool") {
|
|
67
|
+
return "tool";
|
|
68
|
+
}
|
|
69
|
+
return "data";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Determine the full edge category including loopback detection.
|
|
73
|
+
* Loopback edges take precedence over source port data type.
|
|
74
|
+
*/
|
|
75
|
+
export function getEdgeCategoryWithLoopback(edge, sourcePortDataType) {
|
|
76
|
+
if (isLoopbackEdge(edge)) {
|
|
77
|
+
return "loopback";
|
|
78
|
+
}
|
|
79
|
+
return getEdgeCategory(sourcePortDataType);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Apply custom styling to a connection edge based on its source/target nodes.
|
|
83
|
+
*
|
|
84
|
+
* Sets:
|
|
85
|
+
* - edge.data.metadata.edgeType (trigger/tool/loopback/data)
|
|
86
|
+
* - edge.style, edge.class, edge.markerEnd based on category
|
|
87
|
+
* - edge.data.targetNodeType and edge.data.targetCategory
|
|
88
|
+
*/
|
|
89
|
+
export function applyConnectionStyling(edge, sourceNode, targetNode) {
|
|
90
|
+
// Extract port ID from sourceHandle
|
|
91
|
+
const sourcePortId = extractPortId(edge.sourceHandle);
|
|
92
|
+
// Get the source port's data type
|
|
93
|
+
const sourcePortDataType = sourcePortId
|
|
94
|
+
? getPortDataType(sourceNode, sourcePortId, "output")
|
|
95
|
+
: null;
|
|
96
|
+
// Determine edge category (loopback takes precedence)
|
|
97
|
+
const edgeCategory = getEdgeCategoryWithLoopback(edge, sourcePortDataType);
|
|
98
|
+
// Apply styling based on edge category
|
|
99
|
+
// Marker colors use CSS custom properties so they respond to theme changes automatically
|
|
100
|
+
switch (edgeCategory) {
|
|
101
|
+
case "loopback":
|
|
102
|
+
edge.style =
|
|
103
|
+
"stroke: var(--fd-edge-loopback); stroke-dasharray: var(--fd-edge-loopback-dasharray); stroke-width: var(--fd-edge-loopback-width); opacity: var(--fd-edge-loopback-opacity);";
|
|
104
|
+
edge.class = "flowdrop--edge--loopback";
|
|
105
|
+
edge.markerEnd = {
|
|
106
|
+
type: MarkerType.ArrowClosed,
|
|
107
|
+
...EDGE_MARKER_SIZES.loopback,
|
|
108
|
+
color: "var(--fd-edge-loopback)",
|
|
109
|
+
};
|
|
110
|
+
break;
|
|
111
|
+
case "trigger":
|
|
112
|
+
edge.style =
|
|
113
|
+
"stroke: var(--fd-edge-trigger); stroke-width: var(--fd-edge-trigger-width);";
|
|
114
|
+
edge.class = "flowdrop--edge--trigger";
|
|
115
|
+
edge.markerEnd = {
|
|
116
|
+
type: MarkerType.ArrowClosed,
|
|
117
|
+
...EDGE_MARKER_SIZES.trigger,
|
|
118
|
+
color: "var(--fd-edge-trigger)",
|
|
119
|
+
};
|
|
120
|
+
break;
|
|
121
|
+
case "tool":
|
|
122
|
+
edge.style = "stroke: var(--fd-edge-tool); stroke-dasharray: 5 3;";
|
|
123
|
+
edge.class = "flowdrop--edge--tool";
|
|
124
|
+
edge.markerEnd = {
|
|
125
|
+
type: MarkerType.ArrowClosed,
|
|
126
|
+
...EDGE_MARKER_SIZES.tool,
|
|
127
|
+
color: "var(--fd-edge-tool)",
|
|
128
|
+
};
|
|
129
|
+
break;
|
|
130
|
+
case "data":
|
|
131
|
+
default:
|
|
132
|
+
edge.style = "stroke: var(--fd-edge-data);";
|
|
133
|
+
edge.class = "flowdrop--edge--data";
|
|
134
|
+
edge.markerEnd = {
|
|
135
|
+
type: MarkerType.ArrowClosed,
|
|
136
|
+
...EDGE_MARKER_SIZES.data,
|
|
137
|
+
color: "var(--fd-edge-data)",
|
|
138
|
+
};
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
// Store metadata in edge data for API and persistence
|
|
142
|
+
edge.data = {
|
|
143
|
+
...edge.data,
|
|
144
|
+
metadata: {
|
|
145
|
+
...(edge.data?.metadata || {}),
|
|
146
|
+
edgeType: edgeCategory,
|
|
147
|
+
sourcePortDataType: sourcePortDataType ?? undefined,
|
|
148
|
+
},
|
|
149
|
+
targetNodeType: targetNode.type,
|
|
150
|
+
targetCategory: targetNode.data.metadata.category,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Update existing edges with custom styling rules.
|
|
155
|
+
* Batch operation that applies styling to all edges using a node map for O(1) lookup.
|
|
156
|
+
*/
|
|
157
|
+
export function updateEdgeStyles(edges, nodes) {
|
|
158
|
+
const nodeMap = new Map(nodes.map((n) => [n.id, n]));
|
|
159
|
+
return edges.map((edge) => {
|
|
160
|
+
const sourceNode = nodeMap.get(edge.source);
|
|
161
|
+
const targetNode = nodeMap.get(edge.target);
|
|
162
|
+
const updatedEdge = { ...edge };
|
|
163
|
+
if (!sourceNode || !targetNode) {
|
|
164
|
+
updatedEdge.data = {
|
|
165
|
+
...updatedEdge.data,
|
|
166
|
+
metadata: {
|
|
167
|
+
...(updatedEdge.data?.metadata || {}),
|
|
168
|
+
edgeType: "data",
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
return updatedEdge;
|
|
172
|
+
}
|
|
173
|
+
applyConnectionStyling(updatedEdge, sourceNode, targetNode);
|
|
174
|
+
return updatedEdge;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared node ID generation and config defaults utilities.
|
|
3
|
+
* Used by both the visual editor and the workflow adapter to ensure
|
|
4
|
+
* consistent behavior across all code paths.
|
|
5
|
+
*/
|
|
6
|
+
import type { ConfigSchema } from "../types/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* Minimal node shape required for ID generation.
|
|
9
|
+
* Both WorkflowNode and StandardNode satisfy this interface.
|
|
10
|
+
*/
|
|
11
|
+
interface NodeWithMetadata {
|
|
12
|
+
id: string;
|
|
13
|
+
data?: {
|
|
14
|
+
metadata?: {
|
|
15
|
+
id?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate a unique node ID based on node type and existing nodes.
|
|
21
|
+
* Format: <node_type>.<number>
|
|
22
|
+
* Example: boolean_gateway.1, calculator.2
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateNodeId(nodeTypeId: string, existingNodes: NodeWithMetadata[]): string;
|
|
25
|
+
/**
|
|
26
|
+
* Extract default config values from a node's configSchema.
|
|
27
|
+
* Iterates configSchema.properties and returns an object with each property's
|
|
28
|
+
* default value (if defined).
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractConfigDefaults(configSchema?: ConfigSchema): Record<string, unknown>;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared node ID generation and config defaults utilities.
|
|
3
|
+
* Used by both the visual editor and the workflow adapter to ensure
|
|
4
|
+
* consistent behavior across all code paths.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generate a unique node ID based on node type and existing nodes.
|
|
8
|
+
* Format: <node_type>.<number>
|
|
9
|
+
* Example: boolean_gateway.1, calculator.2
|
|
10
|
+
*/
|
|
11
|
+
export function generateNodeId(nodeTypeId, existingNodes) {
|
|
12
|
+
// Count how many nodes of this type already exist
|
|
13
|
+
const existingNodeIds = existingNodes
|
|
14
|
+
.filter((node) => node.data?.metadata?.id === nodeTypeId)
|
|
15
|
+
.map((node) => node.id);
|
|
16
|
+
// Extract the numbers from existing IDs with the same prefix
|
|
17
|
+
const existingNumbers = existingNodeIds
|
|
18
|
+
.map((id) => {
|
|
19
|
+
const match = id.match(new RegExp(`^${nodeTypeId}\\.(\\d+)$`));
|
|
20
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
21
|
+
})
|
|
22
|
+
.filter((num) => num > 0);
|
|
23
|
+
// Find the next available number (highest + 1)
|
|
24
|
+
const nextNumber = existingNumbers.length > 0 ? Math.max(...existingNumbers) + 1 : 1;
|
|
25
|
+
return `${nodeTypeId}.${nextNumber}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract default config values from a node's configSchema.
|
|
29
|
+
* Iterates configSchema.properties and returns an object with each property's
|
|
30
|
+
* default value (if defined).
|
|
31
|
+
*/
|
|
32
|
+
export function extractConfigDefaults(configSchema) {
|
|
33
|
+
const config = {};
|
|
34
|
+
if (!configSchema?.properties)
|
|
35
|
+
return config;
|
|
36
|
+
for (const [key, prop] of Object.entries(configSchema.properties)) {
|
|
37
|
+
if (prop && typeof prop === "object" && "default" in prop) {
|
|
38
|
+
config[key] = prop.default;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Swap utilities for FlowDrop
|
|
3
|
+
*
|
|
4
|
+
* Provides logic for swapping a workflow node with a different node type
|
|
5
|
+
* while intelligently remapping compatible port connections.
|
|
6
|
+
*
|
|
7
|
+
* @module utils/nodeSwap
|
|
8
|
+
*/
|
|
9
|
+
import type { WorkflowNode, WorkflowEdge, NodeMetadata, NodePort, ConfigSchema, ConfigValues } from "../types/index.js";
|
|
10
|
+
import type { WorkflowValidationResult } from "./validation.js";
|
|
11
|
+
import type { PortCompatibilityChecker } from "./connections.js";
|
|
12
|
+
/**
|
|
13
|
+
* Describes how a single port was remapped during a swap.
|
|
14
|
+
*/
|
|
15
|
+
export interface PortMapping {
|
|
16
|
+
oldHandleId: string;
|
|
17
|
+
newHandleId: string;
|
|
18
|
+
oldPortId: string;
|
|
19
|
+
newPortId: string;
|
|
20
|
+
direction: "input" | "output";
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* An edge that could not be remapped and will be dropped.
|
|
24
|
+
*/
|
|
25
|
+
export interface DroppedEdge {
|
|
26
|
+
edge: WorkflowEdge;
|
|
27
|
+
reason: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Preview of what a node swap will do before it is executed.
|
|
31
|
+
*/
|
|
32
|
+
export interface SwapPreview {
|
|
33
|
+
/** Edges that will be preserved with their rewritten versions */
|
|
34
|
+
keptEdges: Array<{
|
|
35
|
+
edge: WorkflowEdge;
|
|
36
|
+
newEdge: WorkflowEdge;
|
|
37
|
+
}>;
|
|
38
|
+
/** Edges that will be removed */
|
|
39
|
+
droppedEdges: DroppedEdge[];
|
|
40
|
+
/** True if any connected edges will be lost */
|
|
41
|
+
hasDataLoss: boolean;
|
|
42
|
+
/** The new node ID that will be generated */
|
|
43
|
+
newNodeId: string;
|
|
44
|
+
/** Config keys carried over from the old node */
|
|
45
|
+
configCarriedOver: string[];
|
|
46
|
+
/** Config keys reset to defaults on the new node */
|
|
47
|
+
configReset: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Result of executing a node swap.
|
|
51
|
+
*/
|
|
52
|
+
export interface SwapResult {
|
|
53
|
+
updatedNodes: WorkflowNode[];
|
|
54
|
+
updatedEdges: WorkflowEdge[];
|
|
55
|
+
}
|
|
56
|
+
/** Quality annotation for how a port was matched. */
|
|
57
|
+
export type MatchQuality = "id" | "name" | "type" | "manual" | "unmapped";
|
|
58
|
+
/** Manual override for a single port mapping. */
|
|
59
|
+
export interface PortMappingOverride {
|
|
60
|
+
oldPortId: string;
|
|
61
|
+
newPortId: string | null;
|
|
62
|
+
direction: "input" | "output";
|
|
63
|
+
}
|
|
64
|
+
/** Manual override for a single config mapping. */
|
|
65
|
+
export interface ConfigMappingOverride {
|
|
66
|
+
key: string;
|
|
67
|
+
action: "carry" | "reset" | "set";
|
|
68
|
+
value?: unknown;
|
|
69
|
+
}
|
|
70
|
+
/** Options bag for advanced swap functions. */
|
|
71
|
+
export interface SwapOptions {
|
|
72
|
+
checker?: PortCompatibilityChecker | null;
|
|
73
|
+
portOverrides?: PortMappingOverride[];
|
|
74
|
+
configOverrides?: ConfigMappingOverride[];
|
|
75
|
+
strategies?: SwapStrategy[];
|
|
76
|
+
}
|
|
77
|
+
/** Pluggable strategy passed per-call, not registered globally. */
|
|
78
|
+
export interface SwapStrategy {
|
|
79
|
+
readonly id: string;
|
|
80
|
+
readonly name: string;
|
|
81
|
+
canHandle(ctx: SwapStrategyContext): boolean;
|
|
82
|
+
mapPorts?(ctx: SwapStrategyContext): Record<string, string | null> | undefined;
|
|
83
|
+
mapConfig?(ctx: SwapStrategyContext): Record<string, {
|
|
84
|
+
action: "carry" | "reset" | "set";
|
|
85
|
+
value?: unknown;
|
|
86
|
+
}> | undefined;
|
|
87
|
+
}
|
|
88
|
+
/** Context passed to swap strategies. */
|
|
89
|
+
export interface SwapStrategyContext {
|
|
90
|
+
oldNode: WorkflowNode;
|
|
91
|
+
newMetadata: NodeMetadata;
|
|
92
|
+
edges: WorkflowEdge[];
|
|
93
|
+
allNodes: WorkflowNode[];
|
|
94
|
+
checker: PortCompatibilityChecker | null;
|
|
95
|
+
}
|
|
96
|
+
/** Stable, data-only event context for swap hooks. */
|
|
97
|
+
export interface SwapEventContext {
|
|
98
|
+
oldNode: WorkflowNode;
|
|
99
|
+
newMetadata: NodeMetadata;
|
|
100
|
+
preview: SwapPreview;
|
|
101
|
+
portOverrides: PortMappingOverride[];
|
|
102
|
+
configOverrides: ConfigMappingOverride[];
|
|
103
|
+
}
|
|
104
|
+
/** Error class for swap validation failures. */
|
|
105
|
+
export declare class SwapValidationError extends Error {
|
|
106
|
+
constructor(message: string);
|
|
107
|
+
}
|
|
108
|
+
/** Editable port mapping for the interactive mapping editor. */
|
|
109
|
+
export interface EditablePortMapping {
|
|
110
|
+
oldPort: NodePort;
|
|
111
|
+
edge: WorkflowEdge;
|
|
112
|
+
direction: "input" | "output";
|
|
113
|
+
selectedNewPortId: string | null;
|
|
114
|
+
matchQuality: MatchQuality;
|
|
115
|
+
autoSuggestedPortId: string | null;
|
|
116
|
+
isOverridden: boolean;
|
|
117
|
+
}
|
|
118
|
+
/** Editable config mapping for the interactive mapping editor. */
|
|
119
|
+
export interface EditableConfigMapping {
|
|
120
|
+
key: string;
|
|
121
|
+
title: string;
|
|
122
|
+
oldValue: unknown;
|
|
123
|
+
newDefault: unknown;
|
|
124
|
+
carryOver: boolean;
|
|
125
|
+
autoCarryOver: boolean;
|
|
126
|
+
/** false for nested objects/arrays — shown as read-only, always reset */
|
|
127
|
+
isFlat: boolean;
|
|
128
|
+
}
|
|
129
|
+
/** Full interactive swap state for the mapping editor. */
|
|
130
|
+
export interface InteractiveSwapState {
|
|
131
|
+
oldNode: WorkflowNode;
|
|
132
|
+
newMetadata: NodeMetadata;
|
|
133
|
+
newNodeId: string;
|
|
134
|
+
portMappings: EditablePortMapping[];
|
|
135
|
+
configMappings: EditableConfigMapping[];
|
|
136
|
+
availableNewInputs: NodePort[];
|
|
137
|
+
availableNewOutputs: NodePort[];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Compare two semver-like version strings.
|
|
141
|
+
* Returns positive if a > b, negative if a < b, 0 if equal.
|
|
142
|
+
*
|
|
143
|
+
* Handles pre-release tags: "2.0.0-beta" < "2.0.0"
|
|
144
|
+
*/
|
|
145
|
+
export declare function compareSemver(a: string, b: string): number;
|
|
146
|
+
/**
|
|
147
|
+
* Map config values from an old node to a new node's schema.
|
|
148
|
+
*
|
|
149
|
+
* - Keys present in both old config and new schema: carry over the old value
|
|
150
|
+
* - Keys only in the new schema: use the schema default or newDefaults
|
|
151
|
+
* - Keys only in the old config: discarded
|
|
152
|
+
* - Dynamic port keys (dynamicInputs, dynamicOutputs, branches): never carried over
|
|
153
|
+
*/
|
|
154
|
+
export declare function mapConfig(oldConfig: ConfigValues, newConfigSchema: ConfigSchema | undefined, newDefaults?: Record<string, unknown>): {
|
|
155
|
+
config: ConfigValues;
|
|
156
|
+
carriedOver: string[];
|
|
157
|
+
reset: string[];
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Compute a preview of what will happen when swapping oldNode with newMetadata.
|
|
161
|
+
*
|
|
162
|
+
* This does NOT mutate anything — it returns a preview that can be displayed
|
|
163
|
+
* to the user for confirmation before executing the swap.
|
|
164
|
+
*/
|
|
165
|
+
export declare function computeSwapPreview(oldNode: WorkflowNode, newMetadata: NodeMetadata, edges: WorkflowEdge[], allNodes: WorkflowNode[], checker?: PortCompatibilityChecker | null): SwapPreview;
|
|
166
|
+
/**
|
|
167
|
+
* Execute a node swap using a previously computed preview.
|
|
168
|
+
*
|
|
169
|
+
* Returns new nodes and edges arrays ready for `workflowActions.batchUpdate()`.
|
|
170
|
+
*/
|
|
171
|
+
export declare function executeSwap(oldNode: WorkflowNode, newMetadata: NodeMetadata, preview: SwapPreview, allNodes: WorkflowNode[], allEdges: WorkflowEdge[]): SwapResult;
|
|
172
|
+
/**
|
|
173
|
+
* Check if a newer version of the same node type is available.
|
|
174
|
+
*
|
|
175
|
+
* Compares the node's embedded metadata.version against the same-ID entry
|
|
176
|
+
* in the available nodes list (API returns only the latest version).
|
|
177
|
+
*
|
|
178
|
+
* @returns The newer NodeMetadata if an upgrade is available, null otherwise
|
|
179
|
+
*/
|
|
180
|
+
export declare function getVersionUpgrade(currentMetadata: NodeMetadata, allNodeTypes: NodeMetadata[]): NodeMetadata | null;
|
|
181
|
+
/**
|
|
182
|
+
* Compute a swap preview with full options support (strategies, overrides).
|
|
183
|
+
*
|
|
184
|
+
* Resolution order:
|
|
185
|
+
* 1. Check strategies — first canHandle() match wins for mapPorts()/mapConfig()
|
|
186
|
+
* 2. Fall through to built-in 3-pass for ports not covered by strategy
|
|
187
|
+
* 3. Apply portOverrides on top (highest priority — user's manual overrides)
|
|
188
|
+
* 4. Same cascade for config
|
|
189
|
+
*/
|
|
190
|
+
export declare function computeSwapPreviewWithOptions(oldNode: WorkflowNode, newMetadata: NodeMetadata, edges: WorkflowEdge[], allNodes: WorkflowNode[], options: SwapOptions): SwapPreview;
|
|
191
|
+
/**
|
|
192
|
+
* Compute interactive state for the mapping editor UI.
|
|
193
|
+
*
|
|
194
|
+
* Returns EditablePortMapping and EditableConfigMapping entries
|
|
195
|
+
* with match quality annotations and isFlat flags.
|
|
196
|
+
*/
|
|
197
|
+
export declare function computeInteractiveState(oldNode: WorkflowNode, newMetadata: NodeMetadata, edges: WorkflowEdge[], allNodes: WorkflowNode[], options?: SwapOptions): InteractiveSwapState;
|
|
198
|
+
/**
|
|
199
|
+
* Convert user-edited InteractiveSwapState back into a SwapPreview
|
|
200
|
+
* for executeSwap(). Pure function, no side effects.
|
|
201
|
+
*/
|
|
202
|
+
export declare function buildSwapPreviewFromState(state: InteractiveSwapState, allEdges: WorkflowEdge[]): SwapPreview;
|
|
203
|
+
/**
|
|
204
|
+
* Headless one-shot swap with full validation.
|
|
205
|
+
*
|
|
206
|
+
* Guardrails:
|
|
207
|
+
* - Validates oldNode.id exists in allNodes
|
|
208
|
+
* - Validates format compatibility if newMetadata.formats is set
|
|
209
|
+
* - Computes preview → executes → validates → returns result
|
|
210
|
+
* - Throws SwapValidationError on invalid input
|
|
211
|
+
*/
|
|
212
|
+
export declare function performSwap(oldNode: WorkflowNode, newMetadata: NodeMetadata, allNodes: WorkflowNode[], allEdges: WorkflowEdge[], options?: SwapOptions): SwapResult;
|
|
213
|
+
/**
|
|
214
|
+
* Validate a swap result for structural integrity.
|
|
215
|
+
*
|
|
216
|
+
* Checks:
|
|
217
|
+
* - No dangling edge references (every edge source/target exists in nodes)
|
|
218
|
+
* - No duplicate node IDs
|
|
219
|
+
* - No duplicate edge IDs
|
|
220
|
+
*/
|
|
221
|
+
export declare function validateSwapResult(result: SwapResult): WorkflowValidationResult;
|