@flowdrop/flowdrop 1.3.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.
Files changed (114) hide show
  1. package/README.md +68 -24
  2. package/dist/adapters/WorkflowAdapter.js +2 -22
  3. package/dist/adapters/agentspec/autoLayout.d.ts +51 -5
  4. package/dist/adapters/agentspec/autoLayout.js +120 -23
  5. package/dist/chat/commandClassifier.d.ts +19 -0
  6. package/dist/chat/commandClassifier.js +30 -0
  7. package/dist/chat/index.d.ts +27 -0
  8. package/dist/chat/index.js +32 -0
  9. package/dist/chat/responseParser.d.ts +21 -0
  10. package/dist/chat/responseParser.js +87 -0
  11. package/dist/commands/batch.d.ts +18 -0
  12. package/dist/commands/batch.js +56 -0
  13. package/dist/commands/executor.d.ts +37 -0
  14. package/dist/commands/executor.js +1044 -0
  15. package/dist/commands/index.d.ts +14 -0
  16. package/dist/commands/index.js +17 -0
  17. package/dist/commands/parser.d.ts +16 -0
  18. package/dist/commands/parser.js +278 -0
  19. package/dist/commands/positioner.d.ts +19 -0
  20. package/dist/commands/positioner.js +33 -0
  21. package/dist/commands/storeIntegration.svelte.d.ts +16 -0
  22. package/dist/commands/storeIntegration.svelte.js +67 -0
  23. package/dist/commands/types.d.ts +343 -0
  24. package/dist/commands/types.js +45 -0
  25. package/dist/components/App.svelte +431 -17
  26. package/dist/components/App.svelte.d.ts +10 -0
  27. package/dist/components/CanvasBanner.stories.svelte +6 -2
  28. package/dist/components/CanvasController.svelte +38 -0
  29. package/dist/components/CanvasController.svelte.d.ts +32 -0
  30. package/dist/components/ConfigMappingRow.svelte +130 -0
  31. package/dist/components/ConfigMappingRow.svelte.d.ts +8 -0
  32. package/dist/components/ConfigPanel.svelte +56 -7
  33. package/dist/components/ConfigPanel.svelte.d.ts +2 -0
  34. package/dist/components/FlowDropEdge.svelte +8 -57
  35. package/dist/components/Logo.svelte +14 -14
  36. package/dist/components/LogsSidebar.svelte +5 -5
  37. package/dist/components/Navbar.svelte +58 -10
  38. package/dist/components/Navbar.svelte.d.ts +7 -0
  39. package/dist/components/NodeSidebar.svelte +238 -362
  40. package/dist/components/NodeSwapPicker.svelte +537 -0
  41. package/dist/components/NodeSwapPicker.svelte.d.ts +16 -0
  42. package/dist/components/PortMappingRow.svelte +209 -0
  43. package/dist/components/PortMappingRow.svelte.d.ts +12 -0
  44. package/dist/components/SwapMappingEditor.svelte +550 -0
  45. package/dist/components/SwapMappingEditor.svelte.d.ts +12 -0
  46. package/dist/components/WorkflowEditor.svelte +99 -4
  47. package/dist/components/WorkflowEditor.svelte.d.ts +8 -0
  48. package/dist/components/chat/AIChatPanel.svelte +658 -0
  49. package/dist/components/chat/AIChatPanel.svelte.d.ts +13 -0
  50. package/dist/components/chat/CommandPreview.svelte +184 -0
  51. package/dist/components/chat/CommandPreview.svelte.d.ts +9 -0
  52. package/dist/components/console/CommandConsole.stories.svelte +93 -0
  53. package/dist/components/console/CommandConsole.stories.svelte.d.ts +27 -0
  54. package/dist/components/console/CommandConsole.svelte +259 -0
  55. package/dist/components/console/CommandConsole.svelte.d.ts +11 -0
  56. package/dist/components/console/ConsoleAutocomplete.svelte +139 -0
  57. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +21 -0
  58. package/dist/components/console/ConsoleInput.svelte +712 -0
  59. package/dist/components/console/ConsoleInput.svelte.d.ts +16 -0
  60. package/dist/components/console/ConsoleOutput.svelte +121 -0
  61. package/dist/components/console/ConsoleOutput.svelte.d.ts +11 -0
  62. package/dist/components/console/formatters.d.ts +26 -0
  63. package/dist/components/console/formatters.js +118 -0
  64. package/dist/components/interrupt/index.d.ts +1 -0
  65. package/dist/components/interrupt/index.js +1 -0
  66. package/dist/components/nodes/SimpleNode.stories.svelte +64 -0
  67. package/dist/components/nodes/SimpleNode.svelte +27 -11
  68. package/dist/components/nodes/SquareNode.stories.svelte +45 -0
  69. package/dist/components/nodes/SquareNode.svelte +27 -11
  70. package/dist/components/nodes/WorkflowNode.stories.svelte +63 -0
  71. package/dist/config/endpoints.d.ts +8 -0
  72. package/dist/config/endpoints.js +5 -0
  73. package/dist/core/index.d.ts +5 -0
  74. package/dist/core/index.js +9 -0
  75. package/dist/editor/index.d.ts +3 -1
  76. package/dist/editor/index.js +4 -2
  77. package/dist/helpers/proximityConnect.js +8 -1
  78. package/dist/helpers/workflowEditorHelper.d.ts +3 -53
  79. package/dist/helpers/workflowEditorHelper.js +13 -228
  80. package/dist/playground/index.d.ts +1 -1
  81. package/dist/playground/index.js +1 -1
  82. package/dist/schemas/v1/workflow.schema.json +107 -22
  83. package/dist/services/chatService.d.ts +65 -0
  84. package/dist/services/chatService.js +131 -0
  85. package/dist/services/historyService.d.ts +6 -4
  86. package/dist/services/historyService.js +21 -6
  87. package/dist/skins/slate.js +16 -0
  88. package/dist/stores/interruptStore.svelte.js +6 -1
  89. package/dist/stores/playgroundStore.svelte.d.ts +1 -1
  90. package/dist/stores/playgroundStore.svelte.js +11 -2
  91. package/dist/stores/portCoordinateStore.svelte.d.ts +4 -0
  92. package/dist/stores/portCoordinateStore.svelte.js +20 -26
  93. package/dist/stores/workflowStore.svelte.d.ts +31 -2
  94. package/dist/stores/workflowStore.svelte.js +84 -64
  95. package/dist/stories/EdgeDecorator.svelte +4 -4
  96. package/dist/styles/base.css +48 -0
  97. package/dist/svelte-app.d.ts +7 -1
  98. package/dist/svelte-app.js +4 -1
  99. package/dist/types/chat.d.ts +63 -0
  100. package/dist/types/chat.js +9 -0
  101. package/dist/types/events.d.ts +28 -2
  102. package/dist/types/events.js +1 -0
  103. package/dist/types/index.d.ts +8 -0
  104. package/dist/types/settings.d.ts +6 -0
  105. package/dist/types/settings.js +3 -0
  106. package/dist/utils/edgeStyling.d.ts +42 -0
  107. package/dist/utils/edgeStyling.js +176 -0
  108. package/dist/utils/nodeIds.d.ts +31 -0
  109. package/dist/utils/nodeIds.js +42 -0
  110. package/dist/utils/nodeSwap.d.ts +221 -0
  111. package/dist/utils/nodeSwap.js +686 -0
  112. package/package.json +6 -1
  113. package/dist/helpers/nodeLayoutHelper.d.ts +0 -14
  114. package/dist/helpers/nodeLayoutHelper.js +0 -19
@@ -58,6 +58,11 @@ export { resolveScopeToKey, keyToScope, generateDefaultUISchema, collectReferenc
58
58
  export { DEFAULT_PORT_CONFIG } from "../config/defaultPortConfig.js";
59
59
  export { defaultEndpointConfig, createEndpointConfig, } from "../config/endpoints.js";
60
60
  // ============================================================================
61
+ // Shared Utilities
62
+ // ============================================================================
63
+ export { generateNodeId, extractConfigDefaults } from "../utils/nodeIds.js";
64
+ export { buildTypeMap, parseCommand, executeCommand, toShortId, toShortTypeId, resolveNode, executeBatch, computeAutoPosition, } from "../commands/index.js";
65
+ // ============================================================================
61
66
  // Adapters
62
67
  // ============================================================================
63
68
  export { WorkflowAdapter } from "../adapters/WorkflowAdapter.js";
@@ -92,3 +97,7 @@ export { sanitizeHtml } from "../utils/sanitize.js";
92
97
  // Logger
93
98
  // ============================================================================
94
99
  export { logger, setLogLevel, getLogLevel } from "../utils/logger.js";
100
+ // ============================================================================
101
+ // Node Swap
102
+ // ============================================================================
103
+ export { computeSwapPreview, computeSwapPreviewWithOptions, executeSwap, mapConfig, getVersionUpgrade, compareSemver, performSwap, validateSwapResult, SwapValidationError, } from "../utils/nodeSwap.js";
@@ -57,6 +57,7 @@ export { default as LogsSidebar } from "../components/LogsSidebar.svelte";
57
57
  export { default as PipelineStatus } from "../components/PipelineStatus.svelte";
58
58
  export { default as Navbar } from "../components/Navbar.svelte";
59
59
  export { default as Logo } from "../components/Logo.svelte";
60
+ export { default as CommandConsole } from "../components/console/CommandConsole.svelte";
60
61
  export { default as Playground } from "../components/playground/Playground.svelte";
61
62
  export { default as PlaygroundModal } from "../components/playground/PlaygroundModal.svelte";
62
63
  export { default as ChatPanel } from "../components/playground/ChatPanel.svelte";
@@ -67,7 +68,7 @@ export { default as MessageBubble } from "../components/playground/MessageBubble
67
68
  export { mountWorkflowEditor, mountFlowDropApp, unmountFlowDropApp, } from "../svelte-app.js";
68
69
  export { nodeComponentRegistry, createNamespacedType, parseNamespacedType, BUILTIN_NODE_COMPONENTS, BUILTIN_NODE_TYPES, FLOWDROP_SOURCE, registerBuiltinNodes, areBuiltinsRegistered, isBuiltinType, getBuiltinTypes, resolveBuiltinAlias, registerFlowDropPlugin, unregisterFlowDropPlugin, registerCustomNode, createPlugin, isValidNamespace, getRegisteredPlugins, getPluginNodeCount, } from "../registry/index.js";
69
70
  export { EdgeStylingHelper, NodeOperationsHelper, WorkflowOperationsHelper, ConfigurationHelper, } from "../helpers/workflowEditorHelper.js";
70
- export { getWorkflowStore, workflowActions, getWorkflowId, getWorkflowName, getWorkflowNodes, getWorkflowEdges, getWorkflowMetadata, getWorkflowFormat, getWorkflowChanged, getWorkflowValidation, getWorkflowMetadataChanged, getConnectedHandles, getIsDirty, isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange, setHistoryEnabled, isHistoryEnabled, setRestoringFromHistory, } from "../stores/workflowStore.svelte.js";
71
+ export { getWorkflowStore, workflowActions, getWorkflowId, getWorkflowName, getWorkflowNodes, getWorkflowEdges, getWorkflowMetadata, getWorkflowFormat, getWorkflowChanged, getWorkflowValidation, getWorkflowMetadataChanged, getConnectedHandles, getIsDirty, isDirty, markAsSaved, getEditVersion, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange, setHistoryEnabled, isHistoryEnabled, setRestoringFromHistory, } from "../stores/workflowStore.svelte.js";
71
72
  export { rebuildAllPortCoordinates, updateNodePortCoordinates, removeNodePortCoordinates, getPortCoordinate, getNodePortCoordinates, getPortCoordinateSnapshot, getPortCoordinates, } from "../stores/portCoordinateStore.svelte.js";
72
73
  export { getHistoryState, getCanUndo, getCanRedo, historyActions, setOnRestoreCallback, cleanupHistorySubscription, historyService, HistoryService, } from "../stores/historyStore.svelte.js";
73
74
  export type { HistoryEntry, HistoryState, PushOptions, } from "../stores/historyStore.svelte.js";
@@ -91,5 +92,6 @@ export type { WorkflowEditorConfig, EditorFeatures, UIConfig, APIConfig, } from
91
92
  export type { AuthProvider, StaticAuthConfig, CallbackAuthConfig, } from "../types/auth.js";
92
93
  export type { FlowDropEventHandlers, FlowDropFeatures, WorkflowChangeType, } from "../types/events.js";
93
94
  export type { EndpointConfig } from "../config/endpoints.js";
95
+ export type { UIAction } from "../commands/types.js";
94
96
  export type { FlowDropMountOptions, MountedFlowDropApp, NavbarAction, } from "../svelte-app.js";
95
97
  export type { NodeComponentProps, NodeComponentRegistration, FlowDropPluginConfig, PluginNodeDefinition, } from "../registry/index.js";
@@ -71,6 +71,8 @@ export { default as LogsSidebar } from "../components/LogsSidebar.svelte";
71
71
  export { default as PipelineStatus } from "../components/PipelineStatus.svelte";
72
72
  export { default as Navbar } from "../components/Navbar.svelte";
73
73
  export { default as Logo } from "../components/Logo.svelte";
74
+ // Console Components
75
+ export { default as CommandConsole } from "../components/console/CommandConsole.svelte";
74
76
  // Playground Components
75
77
  export { default as Playground } from "../components/playground/Playground.svelte";
76
78
  export { default as PlaygroundModal } from "../components/playground/PlaygroundModal.svelte";
@@ -101,8 +103,8 @@ export { EdgeStylingHelper, NodeOperationsHelper, WorkflowOperationsHelper, Conf
101
103
  // Stores
102
104
  // ============================================================================
103
105
  export { getWorkflowStore, workflowActions, getWorkflowId, getWorkflowName, getWorkflowNodes, getWorkflowEdges, getWorkflowMetadata, getWorkflowFormat, getWorkflowChanged, getWorkflowValidation, getWorkflowMetadataChanged, getConnectedHandles,
104
- // Dirty state tracking
105
- getIsDirty, isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange,
106
+ // Dirty state tracking & version counter
107
+ getIsDirty, isDirty, markAsSaved, getEditVersion, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange,
106
108
  // History control
107
109
  setHistoryEnabled, isHistoryEnabled, setRestoringFromHistory, } from "../stores/workflowStore.svelte.js";
108
110
  // Port Coordinate Store (Svelte 5 runes-based)
@@ -239,9 +239,16 @@ export class ProximityConnectHelper {
239
239
  bestIsExact = isExact;
240
240
  }
241
241
  };
242
+ // Cache compatible types per dataType to avoid redundant lookups
243
+ const compatCache = new Map();
244
+ for (const srcPort of draggedOutputs) {
245
+ if (!compatCache.has(srcPort.dataType)) {
246
+ compatCache.set(srcPort.dataType, checker.getCompatibleTypes(srcPort.dataType));
247
+ }
248
+ }
242
249
  // Direction A: dragged outputs → other inputs (only compatible types)
243
250
  for (const srcPort of draggedOutputs) {
244
- const compatibleTypes = checker.getCompatibleTypes(srcPort.dataType);
251
+ const compatibleTypes = compatCache.get(srcPort.dataType);
245
252
  for (const targetType of compatibleTypes) {
246
253
  const targets = otherInputsByType.get(targetType);
247
254
  if (!targets)
@@ -4,12 +4,7 @@
4
4
  */
5
5
  import type { WorkflowNode as WorkflowNodeType, NodeMetadata, Workflow, WorkflowEdge, NodeExecutionInfo } from "../types/index.js";
6
6
  import type { EndpointConfig } from "../config/endpoints.js";
7
- /**
8
- * Generate a unique node ID based on node type and existing nodes
9
- * Format: <node_type>.<number>
10
- * Example: boolean_gateway.1, calculator.2
11
- */
12
- export declare function generateNodeId(nodeTypeId: string, existingNodes: WorkflowNodeType[]): string;
7
+ export { generateNodeId, extractConfigDefaults } from "../utils/nodeIds.js";
13
8
  /**
14
9
  * Edge category type for styling purposes
15
10
  * - trigger: For control flow connections (dataType: "trigger")
@@ -19,61 +14,16 @@ export declare function generateNodeId(nodeTypeId: string, existingNodes: Workfl
19
14
  */
20
15
  export type EdgeCategory = "trigger" | "tool" | "loopback" | "data";
21
16
  /**
22
- * Edge styling configuration based on source port data type
17
+ * Edge styling configuration based on source port data type.
18
+ * Delegates to standalone functions in utils/edgeStyling.ts.
23
19
  */
24
20
  export declare class EdgeStylingHelper {
25
- /**
26
- * Extract the port ID from a handle ID
27
- * @param handleId - The handle ID string (e.g., "sample-node.1-output-trigger" or "trigger")
28
- * @returns The port ID (e.g., "trigger") or the handleId itself for short format
29
- */
30
21
  static extractPortIdFromHandle(handleId: string | undefined): string | null;
31
- /**
32
- * Check if a port ID matches a dynamic branch in a Gateway node
33
- * Gateway nodes store branches in config.branches array
34
- * @param node - The workflow node to check
35
- * @param portId - The port ID to look up
36
- * @returns true if the portId matches a gateway branch
37
- */
38
22
  static isGatewayBranch(node: WorkflowNodeType, portId: string): boolean;
39
- /**
40
- * Get the data type of a port from a node's metadata
41
- * Also handles dynamic ports like Gateway branches
42
- * @param node - The workflow node containing the port
43
- * @param portId - The port ID to look up
44
- * @param portType - Whether to look in "inputs" or "outputs"
45
- * @returns The port's dataType or null if not found
46
- */
47
23
  static getPortDataType(node: WorkflowNodeType, portId: string, portType: "input" | "output"): string | null;
48
- /**
49
- * Determine the edge category based on source port data type
50
- * Note: This method does not check for loopback edges.
51
- * Use getEdgeCategoryWithLoopback() for full edge categorization.
52
- *
53
- * @param sourcePortDataType - The data type of the source output port
54
- * @returns The edge category for styling
55
- */
56
24
  static getEdgeCategory(sourcePortDataType: string | null): EdgeCategory;
57
- /**
58
- * Determine the full edge category including loopback detection
59
- * Loopback edges take precedence over source port data type
60
- *
61
- * @param edge - The edge to categorize
62
- * @param sourcePortDataType - The data type of the source output port
63
- * @returns The edge category for styling
64
- */
65
25
  static getEdgeCategoryWithLoopback(edge: WorkflowEdge, sourcePortDataType: string | null): EdgeCategory;
66
- /**
67
- * Apply custom styling to connection edges based on edge type:
68
- * - Loopback: Dashed gray line for loop iteration (targets loop_back port)
69
- * - Trigger ports: Solid black line with arrow
70
- * - Tool ports: Dashed amber line with arrow
71
- * - Data ports: Normal gray line with arrow
72
- */
73
26
  static applyConnectionStyling(edge: WorkflowEdge, sourceNode: WorkflowNodeType, targetNode: WorkflowNodeType): void;
74
- /**
75
- * Update existing edges with custom styling rules
76
- */
77
27
  static updateEdgeStyles(edges: WorkflowEdge[], nodes: WorkflowNodeType[]): WorkflowEdge[];
78
28
  }
79
29
  /**
@@ -2,8 +2,7 @@
2
2
  * Workflow Editor Helper
3
3
  * Contains business logic for workflow operations
4
4
  */
5
- import { MarkerType } from "@xyflow/svelte";
6
- import { hasCycles, hasInvalidCycles, isLoopbackEdge, } from "../utils/connections.js";
5
+ import { hasCycles, hasInvalidCycles, } from "../utils/connections.js";
7
6
  import { workflowApi, nodeApi, setEndpointConfig } from "../services/api.js";
8
7
  import { v4 as uuidv4 } from "uuid";
9
8
  import { workflowActions } from "../stores/workflowStore.svelte.js";
@@ -12,231 +11,35 @@ import { WorkflowAdapter } from "../adapters/WorkflowAdapter.js";
12
11
  import { AgentSpecAdapter } from "../adapters/agentspec/AgentSpecAdapter.js";
13
12
  import { validateForAgentSpecExport } from "../adapters/agentspec/validator.js";
14
13
  import { extractPortId } from "../utils/handleIds.js";
15
- import { EDGE_MARKER_SIZES } from "../config/constants.js";
16
14
  import { logger } from "../utils/logger.js";
15
+ import { generateNodeId, extractConfigDefaults } from "../utils/nodeIds.js";
16
+ import { applyConnectionStyling as applyConnectionStylingUtil, updateEdgeStyles as updateEdgeStylesUtil, isGatewayBranch as isGatewayBranchUtil, getPortDataType as getPortDataTypeUtil, getEdgeCategory as getEdgeCategoryUtil, getEdgeCategoryWithLoopback as getEdgeCategoryWithLoopbackUtil, } from "../utils/edgeStyling.js";
17
+ export { generateNodeId, extractConfigDefaults } from "../utils/nodeIds.js";
17
18
  /**
18
- * Generate a unique node ID based on node type and existing nodes
19
- * Format: <node_type>.<number>
20
- * Example: boolean_gateway.1, calculator.2
21
- */
22
- export function generateNodeId(nodeTypeId, existingNodes) {
23
- // Count how many nodes of this type already exist
24
- const existingNodeIds = existingNodes
25
- .filter((node) => node.data?.metadata?.id === nodeTypeId)
26
- .map((node) => node.id);
27
- // Extract the numbers from existing IDs with the same prefix
28
- const existingNumbers = existingNodeIds
29
- .map((id) => {
30
- const match = id.match(new RegExp(`^${nodeTypeId}\\.(\\d+)$`));
31
- return match ? parseInt(match[1], 10) : 0;
32
- })
33
- .filter((num) => num > 0);
34
- // Find the next available number (highest + 1)
35
- const nextNumber = existingNumbers.length > 0 ? Math.max(...existingNumbers) + 1 : 1;
36
- return `${nodeTypeId}.${nextNumber}`;
37
- }
38
- /**
39
- * Edge styling configuration based on source port data type
19
+ * Edge styling configuration based on source port data type.
20
+ * Delegates to standalone functions in utils/edgeStyling.ts.
40
21
  */
41
22
  export class EdgeStylingHelper {
42
- /**
43
- * Extract the port ID from a handle ID
44
- * @param handleId - The handle ID string (e.g., "sample-node.1-output-trigger" or "trigger")
45
- * @returns The port ID (e.g., "trigger") or the handleId itself for short format
46
- */
47
23
  static extractPortIdFromHandle(handleId) {
48
24
  return extractPortId(handleId);
49
25
  }
50
- /**
51
- * Check if a port ID matches a dynamic branch in a Gateway node
52
- * Gateway nodes store branches in config.branches array
53
- * @param node - The workflow node to check
54
- * @param portId - The port ID to look up
55
- * @returns true if the portId matches a gateway branch
56
- */
57
26
  static isGatewayBranch(node, portId) {
58
- // Check if this is a gateway node with dynamic branches
59
- const nodeType = node.data?.metadata?.type || node.type;
60
- if (nodeType !== "gateway") {
61
- return false;
62
- }
63
- // Check if the portId matches a branch name in config.branches
64
- const branches = node.data?.config?.branches;
65
- if (!branches || !Array.isArray(branches)) {
66
- return false;
67
- }
68
- return branches.some((branch) => branch.name === portId);
27
+ return isGatewayBranchUtil(node, portId);
69
28
  }
70
- /**
71
- * Get the data type of a port from a node's metadata
72
- * Also handles dynamic ports like Gateway branches
73
- * @param node - The workflow node containing the port
74
- * @param portId - The port ID to look up
75
- * @param portType - Whether to look in "inputs" or "outputs"
76
- * @returns The port's dataType or null if not found
77
- */
78
29
  static getPortDataType(node, portId, portType) {
79
- // First, check static ports in metadata
80
- const ports = portType === "output"
81
- ? node.data?.metadata?.outputs
82
- : node.data?.metadata?.inputs;
83
- if (ports && Array.isArray(ports)) {
84
- const port = ports.find((p) => p.id === portId);
85
- if (port?.dataType) {
86
- return port.dataType;
87
- }
88
- }
89
- // Check dynamic ports from config (dynamicInputs/dynamicOutputs)
90
- const dynamicKey = portType === "output" ? "dynamicOutputs" : "dynamicInputs";
91
- const dynamicPorts = node.data?.config?.[dynamicKey];
92
- if (dynamicPorts && Array.isArray(dynamicPorts)) {
93
- const dynamicPort = dynamicPorts.find((p) => p.name === portId);
94
- if (dynamicPort?.dataType) {
95
- return dynamicPort.dataType;
96
- }
97
- }
98
- // For output ports, also check dynamic Gateway branches
99
- // Gateway branches are always trigger type (control flow)
100
- if (portType === "output" && this.isGatewayBranch(node, portId)) {
101
- return "trigger";
102
- }
103
- return null;
30
+ return getPortDataTypeUtil(node, portId, portType);
104
31
  }
105
- /**
106
- * Determine the edge category based on source port data type
107
- * Note: This method does not check for loopback edges.
108
- * Use getEdgeCategoryWithLoopback() for full edge categorization.
109
- *
110
- * @param sourcePortDataType - The data type of the source output port
111
- * @returns The edge category for styling
112
- */
113
32
  static getEdgeCategory(sourcePortDataType) {
114
- if (sourcePortDataType === "trigger") {
115
- return "trigger";
116
- }
117
- if (sourcePortDataType === "tool") {
118
- return "tool";
119
- }
120
- // All other data types (string, number, boolean, array, etc.) are "data" edges
121
- return "data";
33
+ return getEdgeCategoryUtil(sourcePortDataType);
122
34
  }
123
- /**
124
- * Determine the full edge category including loopback detection
125
- * Loopback edges take precedence over source port data type
126
- *
127
- * @param edge - The edge to categorize
128
- * @param sourcePortDataType - The data type of the source output port
129
- * @returns The edge category for styling
130
- */
131
35
  static getEdgeCategoryWithLoopback(edge, sourcePortDataType) {
132
- // Loopback edges are identified by their target handle
133
- // Check this first as it takes precedence
134
- if (isLoopbackEdge(edge)) {
135
- return "loopback";
136
- }
137
- // Fall back to source port data type categorization
138
- return this.getEdgeCategory(sourcePortDataType);
36
+ return getEdgeCategoryWithLoopbackUtil(edge, sourcePortDataType);
139
37
  }
140
- /**
141
- * Apply custom styling to connection edges based on edge type:
142
- * - Loopback: Dashed gray line for loop iteration (targets loop_back port)
143
- * - Trigger ports: Solid black line with arrow
144
- * - Tool ports: Dashed amber line with arrow
145
- * - Data ports: Normal gray line with arrow
146
- */
147
38
  static applyConnectionStyling(edge, sourceNode, targetNode) {
148
- // Extract port ID from sourceHandle
149
- const sourcePortId = this.extractPortIdFromHandle(edge.sourceHandle);
150
- // Get the source port's data type
151
- const sourcePortDataType = sourcePortId
152
- ? this.getPortDataType(sourceNode, sourcePortId, "output")
153
- : null;
154
- // Determine edge category (loopback takes precedence)
155
- const edgeCategory = this.getEdgeCategoryWithLoopback(edge, sourcePortDataType);
156
- // Apply styling based on edge category
157
- // Marker colors use CSS custom properties so they respond to theme changes automatically
158
- switch (edgeCategory) {
159
- case "loopback":
160
- // Loopback edges: dashed gray line for loop iteration
161
- edge.style =
162
- "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);";
163
- edge.class = "flowdrop--edge--loopback";
164
- edge.markerEnd = {
165
- type: MarkerType.ArrowClosed,
166
- ...EDGE_MARKER_SIZES.loopback,
167
- color: "var(--fd-edge-loopback)",
168
- };
169
- break;
170
- case "trigger":
171
- // Trigger edges: solid dark line for control flow
172
- edge.style =
173
- "stroke: var(--fd-edge-trigger); stroke-width: var(--fd-edge-trigger-width);";
174
- edge.class = "flowdrop--edge--trigger";
175
- edge.markerEnd = {
176
- type: MarkerType.ArrowClosed,
177
- ...EDGE_MARKER_SIZES.trigger,
178
- color: "var(--fd-edge-trigger)",
179
- };
180
- break;
181
- case "tool":
182
- // Tool edges: dashed amber line
183
- edge.style = "stroke: var(--fd-edge-tool); stroke-dasharray: 5 3;";
184
- edge.class = "flowdrop--edge--tool";
185
- edge.markerEnd = {
186
- type: MarkerType.ArrowClosed,
187
- ...EDGE_MARKER_SIZES.tool,
188
- color: "var(--fd-edge-tool)",
189
- };
190
- break;
191
- case "data":
192
- default:
193
- // Data edges: normal gray line
194
- edge.style = "stroke: var(--fd-edge-data);";
195
- edge.class = "flowdrop--edge--data";
196
- edge.markerEnd = {
197
- type: MarkerType.ArrowClosed,
198
- ...EDGE_MARKER_SIZES.data,
199
- color: "var(--fd-edge-data)",
200
- };
201
- break;
202
- }
203
- // Store metadata in edge data for API and persistence
204
- edge.data = {
205
- ...edge.data,
206
- metadata: {
207
- ...(edge.data?.metadata || {}),
208
- edgeType: edgeCategory,
209
- sourcePortDataType: sourcePortDataType ?? undefined,
210
- },
211
- targetNodeType: targetNode.type,
212
- targetCategory: targetNode.data.metadata.category,
213
- };
39
+ applyConnectionStylingUtil(edge, sourceNode, targetNode);
214
40
  }
215
- /**
216
- * Update existing edges with custom styling rules
217
- */
218
41
  static updateEdgeStyles(edges, nodes) {
219
- return edges.map((edge) => {
220
- // Find source and target nodes
221
- const sourceNode = nodes.find((node) => node.id === edge.source);
222
- const targetNode = nodes.find((node) => node.id === edge.target);
223
- // Create a copy of the edge
224
- const updatedEdge = { ...edge };
225
- if (!sourceNode || !targetNode) {
226
- // Set default edgeType even when nodes are not found
227
- updatedEdge.data = {
228
- ...updatedEdge.data,
229
- metadata: {
230
- ...(updatedEdge.data?.metadata || {}),
231
- edgeType: "data",
232
- },
233
- };
234
- return updatedEdge;
235
- }
236
- // Apply full styling when nodes are available
237
- this.applyConnectionStyling(updatedEdge, sourceNode, targetNode);
238
- return updatedEdge;
239
- });
42
+ return updateEdgeStylesUtil(edges, nodes);
240
43
  }
241
44
  }
242
45
  /**
@@ -323,27 +126,9 @@ export class NodeOperationsHelper {
323
126
  else {
324
127
  // New format (direct NodeMetadata)
325
128
  nodeType = parsedData;
326
- // Extract initial config from configSchema
327
- let initialConfig = {};
328
- if (nodeType.configSchema &&
329
- typeof nodeType.configSchema === "object") {
330
- // If configSchema is a JSON Schema, extract default values
331
- if (nodeType.configSchema.properties) {
332
- // JSON Schema format - extract defaults
333
- Object.entries(nodeType.configSchema.properties).forEach(([key, prop]) => {
334
- if (prop && typeof prop === "object" && "default" in prop) {
335
- initialConfig[key] = prop.default;
336
- }
337
- });
338
- }
339
- else {
340
- // Simple object format - use as is
341
- initialConfig = { ...nodeType.configSchema };
342
- }
343
- }
344
129
  nodeData = {
345
130
  label: nodeType.name,
346
- config: initialConfig,
131
+ config: extractConfigDefaults(nodeType.configSchema),
347
132
  metadata: nodeType,
348
133
  };
349
134
  }
@@ -117,7 +117,7 @@ export { default as SessionManager } from "../components/playground/SessionManag
117
117
  export { default as InputCollector } from "../components/playground/InputCollector.svelte";
118
118
  export { default as ExecutionLogs } from "../components/playground/ExecutionLogs.svelte";
119
119
  export { default as MessageBubble } from "../components/playground/MessageBubble.svelte";
120
- export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt, } from "../components/interrupt/index.js";
120
+ export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt, ReviewPrompt, } from "../components/interrupt/index.js";
121
121
  export { PlaygroundService, playgroundService, } from "../services/playgroundService.js";
122
122
  export { InterruptService, interruptService, } from "../services/interruptService.js";
123
123
  export { getCurrentSession, getSessions, getMessages, getIsExecuting, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollTimestamp, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, playgroundActions, createPollingCallback, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestMessageTimestamp, } from "../stores/playgroundStore.svelte.js";
@@ -123,7 +123,7 @@ export { default as MessageBubble } from "../components/playground/MessageBubble
123
123
  // ============================================================================
124
124
  // Interrupt Components (Human-in-the-Loop)
125
125
  // ============================================================================
126
- export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt, } from "../components/interrupt/index.js";
126
+ export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt, ReviewPrompt, } from "../components/interrupt/index.js";
127
127
  // ============================================================================
128
128
  // Playground Service
129
129
  // ============================================================================