@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.2

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 (235) hide show
  1. package/CHANGELOG.md +508 -0
  2. package/MIGRATION-2.0.md +629 -0
  3. package/README.md +23 -23
  4. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  5. package/dist/adapters/WorkflowAdapter.js +14 -8
  6. package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
  7. package/dist/api/enhanced-client.js +6 -11
  8. package/dist/chat/batchFeedback.d.ts +39 -0
  9. package/dist/chat/batchFeedback.js +51 -0
  10. package/dist/commands/executor.js +15 -1
  11. package/dist/commands/storeIntegration.svelte.d.ts +4 -1
  12. package/dist/commands/storeIntegration.svelte.js +26 -21
  13. package/dist/commands/types.d.ts +2 -0
  14. package/dist/components/App.svelte +163 -192
  15. package/dist/components/App.svelte.d.ts +47 -8
  16. package/dist/components/ConfigForm.svelte +77 -49
  17. package/dist/components/ConfigModal.svelte +7 -2
  18. package/dist/components/ConnectionLine.svelte +4 -2
  19. package/dist/components/Navbar.svelte +61 -1
  20. package/dist/components/NodeSidebar.svelte +27 -45
  21. package/dist/components/NodeStatusOverlay.svelte +94 -6
  22. package/dist/components/NodeSwapPicker.svelte +10 -8
  23. package/dist/components/PipelineStatus.svelte +22 -68
  24. package/dist/components/PipelineStatus.svelte.d.ts +3 -0
  25. package/dist/components/PortCoordinateTracker.svelte +5 -6
  26. package/dist/components/SchemaForm.stories.svelte +1 -3
  27. package/dist/components/SchemaForm.svelte +22 -27
  28. package/dist/components/SchemaForm.svelte.d.ts +0 -8
  29. package/dist/components/SettingsModal.svelte +8 -3
  30. package/dist/components/SettingsPanel.svelte +20 -4
  31. package/dist/components/SwapMappingEditor.svelte +67 -49
  32. package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
  33. package/dist/components/UniversalNode.svelte +9 -7
  34. package/dist/components/WorkflowEditor.svelte +121 -111
  35. package/dist/components/WorkflowEditor.svelte.d.ts +21 -10
  36. package/dist/components/chat/AIChatPanel.svelte +98 -89
  37. package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
  38. package/dist/components/chat/CommandPreview.svelte +2 -1
  39. package/dist/components/console/CommandConsole.svelte +7 -5
  40. package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
  41. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
  42. package/dist/components/console/ConsoleInput.svelte +15 -6
  43. package/dist/components/console/ConsoleOutput.svelte +2 -1
  44. package/dist/components/form/FormArray.svelte +5 -9
  45. package/dist/components/form/FormArray.svelte.d.ts +2 -1
  46. package/dist/components/form/FormAutocomplete.svelte +16 -15
  47. package/dist/components/form/FormField.svelte +4 -2
  48. package/dist/components/form/FormFieldLight.svelte +34 -3
  49. package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
  50. package/dist/components/form/FormMarkdownEditor.svelte +9 -4
  51. package/dist/components/form/FormRangeField.svelte +1 -0
  52. package/dist/components/form/FormTemplateEditor.svelte +11 -3
  53. package/dist/components/form/FormToggle.svelte +5 -12
  54. package/dist/components/form/FormToggle.svelte.d.ts +4 -2
  55. package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
  56. package/dist/components/form/templateAutocomplete.js +1 -5
  57. package/dist/components/form/types.d.ts +1 -14
  58. package/dist/components/interrupt/FormPrompt.svelte +3 -2
  59. package/dist/components/interrupt/InterruptBubble.svelte +25 -17
  60. package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
  61. package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
  62. package/dist/components/layouts/MainLayout.svelte +20 -13
  63. package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
  64. package/dist/components/nodes/AtomNode.svelte +17 -5
  65. package/dist/components/nodes/GatewayNode.svelte +19 -10
  66. package/dist/components/nodes/IdeaNode.svelte +7 -0
  67. package/dist/components/nodes/SimpleNode.svelte +11 -6
  68. package/dist/components/nodes/SquareNode.svelte +15 -8
  69. package/dist/components/nodes/TerminalNode.svelte +9 -4
  70. package/dist/components/nodes/ToolNode.svelte +7 -1
  71. package/dist/components/nodes/WorkflowNode.svelte +16 -7
  72. package/dist/components/playground/ChatInput.svelte +11 -14
  73. package/dist/components/playground/ChatPanel.svelte +6 -49
  74. package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
  75. package/dist/components/playground/ControlPanel.svelte +134 -123
  76. package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
  77. package/dist/components/playground/ExecutionLogs.svelte +11 -9
  78. package/dist/components/playground/InputCollector.svelte +11 -9
  79. package/dist/components/playground/MessageStream.svelte +17 -23
  80. package/dist/components/playground/PipelineKanbanView.svelte +69 -8
  81. package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
  82. package/dist/components/playground/PipelinePanel.svelte +31 -8
  83. package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
  84. package/dist/components/playground/PipelineTableView.svelte +188 -44
  85. package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
  86. package/dist/components/playground/Playground.svelte +154 -105
  87. package/dist/components/playground/Playground.svelte.d.ts +5 -0
  88. package/dist/components/playground/PlaygroundApp.svelte +11 -1
  89. package/dist/components/playground/PlaygroundApp.svelte.d.ts +6 -0
  90. package/dist/components/playground/PlaygroundModal.svelte +18 -3
  91. package/dist/components/playground/PlaygroundModal.svelte.d.ts +6 -0
  92. package/dist/components/playground/PlaygroundStudio.svelte +40 -32
  93. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +6 -0
  94. package/dist/components/playground/SessionManager.svelte +9 -12
  95. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +30 -1
  96. package/dist/components/playground/pipelineViewUtils.svelte.js +40 -3
  97. package/dist/config/endpoints.d.ts +23 -7
  98. package/dist/config/endpoints.js +30 -10
  99. package/dist/core/index.d.ts +5 -6
  100. package/dist/core/index.js +8 -12
  101. package/dist/display/index.d.ts +6 -3
  102. package/dist/display/index.js +7 -5
  103. package/dist/editor/index.d.ts +20 -21
  104. package/dist/editor/index.js +26 -36
  105. package/dist/form/code.d.ts +25 -15
  106. package/dist/form/code.js +44 -41
  107. package/dist/form/fieldRegistry.d.ts +17 -13
  108. package/dist/form/fieldRegistry.js +32 -12
  109. package/dist/form/full.d.ts +19 -14
  110. package/dist/form/full.js +26 -28
  111. package/dist/form/index.d.ts +3 -4
  112. package/dist/form/index.js +6 -5
  113. package/dist/form/markdown.d.ts +13 -8
  114. package/dist/form/markdown.js +22 -23
  115. package/dist/helpers/proximityConnect.d.ts +3 -2
  116. package/dist/helpers/proximityConnect.js +2 -5
  117. package/dist/helpers/workflowEditorHelper.d.ts +14 -5
  118. package/dist/helpers/workflowEditorHelper.js +28 -25
  119. package/dist/index.d.ts +28 -24
  120. package/dist/index.js +27 -50
  121. package/dist/messages/defaults.d.ts +2 -5
  122. package/dist/messages/defaults.js +3 -6
  123. package/dist/messages/index.d.ts +0 -1
  124. package/dist/messages/index.js +0 -1
  125. package/dist/mocks/app-forms.d.ts +6 -2
  126. package/dist/mocks/app-forms.js +11 -4
  127. package/dist/openapi/v1/openapi.yaml +3 -3
  128. package/dist/playground/index.d.ts +4 -5
  129. package/dist/playground/index.js +4 -32
  130. package/dist/playground/mount.d.ts +25 -0
  131. package/dist/playground/mount.js +50 -20
  132. package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
  133. package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
  134. package/dist/registry/builtinFormats.d.ts +9 -18
  135. package/dist/registry/builtinFormats.js +9 -39
  136. package/dist/registry/builtinNodeTypes.d.ts +53 -0
  137. package/dist/registry/builtinNodeTypes.js +67 -0
  138. package/dist/registry/builtinNodes.d.ts +2 -64
  139. package/dist/registry/builtinNodes.js +7 -103
  140. package/dist/registry/index.d.ts +3 -4
  141. package/dist/registry/index.js +4 -6
  142. package/dist/registry/nodeComponentRegistry.d.ts +182 -15
  143. package/dist/registry/nodeComponentRegistry.js +235 -17
  144. package/dist/registry/workflowFormatRegistry.d.ts +14 -9
  145. package/dist/registry/workflowFormatRegistry.js +24 -8
  146. package/dist/{schema → schemas}/index.d.ts +2 -2
  147. package/dist/{schema → schemas}/index.js +2 -2
  148. package/dist/schemas/v1/workflow.schema.json +3 -3
  149. package/dist/services/agentSpecExecutionService.d.ts +0 -2
  150. package/dist/services/agentSpecExecutionService.js +0 -3
  151. package/dist/services/apiVariableService.d.ts +2 -1
  152. package/dist/services/apiVariableService.js +16 -47
  153. package/dist/services/autoSaveService.d.ts +7 -0
  154. package/dist/services/autoSaveService.js +6 -4
  155. package/dist/services/categoriesApi.js +3 -6
  156. package/dist/services/chatService.d.ts +9 -4
  157. package/dist/services/chatService.js +23 -28
  158. package/dist/services/draftStorage.d.ts +129 -13
  159. package/dist/services/draftStorage.js +185 -37
  160. package/dist/services/dynamicSchemaService.d.ts +2 -1
  161. package/dist/services/dynamicSchemaService.js +5 -22
  162. package/dist/services/globalSave.d.ts +13 -12
  163. package/dist/services/globalSave.js +29 -51
  164. package/dist/services/historyService.d.ts +9 -3
  165. package/dist/services/historyService.js +9 -3
  166. package/dist/services/interruptService.d.ts +15 -9
  167. package/dist/services/interruptService.js +35 -37
  168. package/dist/services/nodeExecutionService.d.ts +18 -3
  169. package/dist/services/nodeExecutionService.js +71 -45
  170. package/dist/services/playgroundService.d.ts +16 -10
  171. package/dist/services/playgroundService.js +42 -43
  172. package/dist/services/portConfigApi.js +3 -6
  173. package/dist/services/settingsService.d.ts +9 -4
  174. package/dist/services/settingsService.js +23 -12
  175. package/dist/services/variableService.d.ts +2 -1
  176. package/dist/services/variableService.js +2 -2
  177. package/dist/services/workflowStorage.js +6 -6
  178. package/dist/stores/apiContext.d.ts +56 -0
  179. package/dist/stores/apiContext.js +80 -0
  180. package/dist/stores/categoriesStore.svelte.d.ts +28 -23
  181. package/dist/stores/categoriesStore.svelte.js +69 -64
  182. package/dist/stores/getInstance.svelte.d.ts +39 -0
  183. package/dist/stores/getInstance.svelte.js +65 -0
  184. package/dist/stores/historyStore.svelte.d.ts +77 -93
  185. package/dist/stores/historyStore.svelte.js +134 -160
  186. package/dist/stores/instanceContainer.svelte.d.ts +111 -0
  187. package/dist/stores/instanceContainer.svelte.js +114 -0
  188. package/dist/stores/interruptStore.svelte.d.ts +112 -82
  189. package/dist/stores/interruptStore.svelte.js +253 -226
  190. package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
  191. package/dist/stores/pipelinePanelStore.svelte.js +61 -14
  192. package/dist/stores/playgroundStore.svelte.d.ts +169 -222
  193. package/dist/stores/playgroundStore.svelte.js +513 -580
  194. package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
  195. package/dist/stores/portCoordinateStore.svelte.js +109 -98
  196. package/dist/stores/settingsStore.svelte.d.ts +4 -1
  197. package/dist/stores/settingsStore.svelte.js +47 -12
  198. package/dist/stores/workflowStore.svelte.d.ts +178 -213
  199. package/dist/stores/workflowStore.svelte.js +449 -501
  200. package/dist/stories/EdgeDecorator.svelte +5 -2
  201. package/dist/stories/NodeDecorator.svelte +5 -3
  202. package/dist/svelte-app.d.ts +60 -10
  203. package/dist/svelte-app.js +159 -54
  204. package/dist/types/auth.d.ts +9 -51
  205. package/dist/types/auth.js +4 -54
  206. package/dist/types/events.d.ts +6 -3
  207. package/dist/types/index.d.ts +37 -5
  208. package/dist/types/index.js +0 -1
  209. package/dist/types/navbar.d.ts +7 -0
  210. package/dist/types/playground.d.ts +18 -3
  211. package/dist/types/settings.d.ts +13 -0
  212. package/dist/types/settings.js +1 -0
  213. package/dist/utils/colors.d.ts +47 -21
  214. package/dist/utils/colors.js +69 -68
  215. package/dist/utils/connections.d.ts +9 -15
  216. package/dist/utils/connections.js +13 -32
  217. package/dist/utils/duration.d.ts +13 -0
  218. package/dist/utils/duration.js +45 -0
  219. package/dist/utils/edgeStyling.js +9 -5
  220. package/dist/utils/fetchWithAuth.d.ts +36 -15
  221. package/dist/utils/fetchWithAuth.js +53 -23
  222. package/dist/utils/icons.d.ts +5 -2
  223. package/dist/utils/icons.js +6 -5
  224. package/dist/utils/nodeSwap.d.ts +6 -2
  225. package/dist/utils/nodeSwap.js +62 -126
  226. package/dist/utils/nodeTypes.d.ts +17 -8
  227. package/dist/utils/nodeTypes.js +27 -20
  228. package/dist/utils/performanceUtils.js +7 -0
  229. package/package.json +7 -5
  230. package/dist/messages/deprecation.d.ts +0 -20
  231. package/dist/messages/deprecation.js +0 -33
  232. package/dist/registry/plugin.d.ts +0 -215
  233. package/dist/registry/plugin.js +0 -249
  234. package/dist/services/api.d.ts +0 -129
  235. package/dist/services/api.js +0 -217
@@ -20,7 +20,7 @@
20
20
  WorkflowNode as WorkflowNodeType
21
21
  } from '../../types/index.js';
22
22
  import { getDataTypeColor } from '../../utils/colors.js';
23
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
23
+ import { getInstance } from '../../stores/getInstance.svelte.js';
24
24
  import { applyPortOrder, isPortVisible } from '../../utils/portUtils.js';
25
25
  import { ProximityConnectHelper } from '../../helpers/proximityConnect.js';
26
26
 
@@ -46,6 +46,9 @@
46
46
 
47
47
  let { data, selected, isProcessing, isError }: Props = $props();
48
48
 
49
+ const fd = getInstance();
50
+ const checker = fd.portCompatibility;
51
+
49
52
  const nodeId = $derived(data.nodeId ?? 'unknown');
50
53
  const nodeType = $derived(data.metadata?.type ?? 'atom');
51
54
 
@@ -94,7 +97,7 @@
94
97
  'input',
95
98
  hiddenPorts,
96
99
  hideUnconnectedHandles,
97
- getConnectedHandles(),
100
+ fd.workflow.connectedHandles,
98
101
  nodeId
99
102
  )
100
103
  )
@@ -104,7 +107,14 @@
104
107
  ProximityConnectHelper.getAllPorts(nodeLike, 'output'),
105
108
  portOrder.outputs
106
109
  ).filter((p: NodePort) =>
107
- isPortVisible(p, 'output', hiddenPorts, hideUnconnectedHandles, getConnectedHandles(), nodeId)
110
+ isPortVisible(
111
+ p,
112
+ 'output',
113
+ hiddenPorts,
114
+ hideUnconnectedHandles,
115
+ fd.workflow.connectedHandles,
116
+ nodeId
117
+ )
108
118
  )
109
119
  );
110
120
 
@@ -148,12 +158,13 @@
148
158
  }
149
159
  </script>
150
160
 
151
- {#each inPorts as port, index}
161
+ {#each inPorts as port, index (port.id)}
152
162
  <Handle
153
163
  type="target"
154
164
  position={Position.Left}
155
165
  id={`${nodeId}-input-${port.id}`}
156
166
  style="--fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
167
+ checker,
157
168
  port.dataType
158
169
  )}); top: {portTopPct(index, inPorts.length)}%;"
159
170
  />
@@ -178,12 +189,13 @@
178
189
  <span class="flowdrop-atom-node__body" title={display.text}>{display.text}</span>
179
190
  </div>
180
191
 
181
- {#each outPorts as port, index}
192
+ {#each outPorts as port, index (port.id)}
182
193
  <Handle
183
194
  type="source"
184
195
  position={Position.Right}
185
196
  id={`${nodeId}-output-${port.id}`}
186
197
  style="--fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
198
+ checker,
187
199
  port.dataType
188
200
  )}); top: {portTopPct(index, outPorts.length)}%;"
189
201
  />
@@ -18,7 +18,7 @@
18
18
  getCategoryColorToken,
19
19
  getPortBackgroundColor
20
20
  } from '../../utils/colors.js';
21
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
21
+ import { getInstance } from '../../stores/getInstance.svelte.js';
22
22
  import { m } from '../../messages/index.js';
23
23
 
24
24
  interface Props {
@@ -31,6 +31,9 @@
31
31
 
32
32
  let props: Props = $props();
33
33
 
34
+ const fd = getInstance();
35
+ const checker = fd.portCompatibility;
36
+
34
37
  // Hoist the graph branch — three reads in the template, two inside
35
38
  // {#each port} / {#each branch} loops. One getter walk per render.
36
39
  const graph = $derived(m().nodes.graph);
@@ -80,7 +83,7 @@
80
83
 
81
84
  // Check if port is connected
82
85
  const handleId = `${props.data.nodeId}-${type}-${port.id}`;
83
- return getConnectedHandles().has(handleId);
86
+ return fd.workflow.connectedHandles.has(handleId);
84
87
  }
85
88
 
86
89
  /**
@@ -103,7 +106,7 @@
103
106
 
104
107
  // Check if branch output is connected
105
108
  const handleId = `${props.data.nodeId}-output-${branchName}`;
106
- return getConnectedHandles().has(handleId);
109
+ return fd.workflow.connectedHandles.has(handleId);
107
110
  }
108
111
 
109
112
  // Gateway-specific data - branches are calculated at runtime from config
@@ -173,10 +176,10 @@
173
176
  <!-- Node Icon with Squircle Background -->
174
177
  <div
175
178
  class="flowdrop-workflow-node__icon-wrapper"
176
- style="--_icon-color: {getCategoryColorToken(props.data.metadata.category)}"
179
+ style="--_icon-color: {getCategoryColorToken(fd.categories, props.data.metadata.category)}"
177
180
  >
178
181
  <Icon
179
- icon={getNodeIcon(props.data.metadata.icon, props.data.metadata.category)}
182
+ icon={getNodeIcon(fd.categories, props.data.metadata.icon, props.data.metadata.category)}
180
183
  class="flowdrop-workflow-node__icon"
181
184
  />
182
185
  </div>
@@ -208,6 +211,7 @@
208
211
  id={`${props.data.nodeId}-input-${port.id}`}
209
212
  class="flowdrop-workflow-node__handle"
210
213
  style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
214
+ checker,
211
215
  port.dataType
212
216
  )}; --fd-handle-border-color: var(--fd-handle-border);"
213
217
  tabindex={-1}
@@ -220,11 +224,13 @@
220
224
  <span
221
225
  class="flowdrop-badge flowdrop-badge--sm"
222
226
  style="background-color: {getPortBackgroundColor(
227
+ checker,
223
228
  port.dataType,
224
229
  15
225
230
  )}; color: {getDataTypeColorToken(
231
+ checker,
226
232
  port.dataType
227
- )}; border: 1px solid {getPortBackgroundColor(port.dataType, 30)};"
233
+ )}; border: 1px solid {getPortBackgroundColor(checker, port.dataType, 30)};"
228
234
  >
229
235
  {port.dataType}
230
236
  </span>
@@ -250,7 +256,7 @@
250
256
  {#if visibleBranches.length > 0}
251
257
  <div class="flowdrop-workflow-node__ports">
252
258
  <div class="flowdrop-workflow-node__ports-list">
253
- {#each visibleBranches as branch, branchIndex (branch.name)}
259
+ {#each visibleBranches as branch (branch.name)}
254
260
  {@const isActive = isBranchActive(branch.name)}
255
261
  <div class="flowdrop-workflow-node__port">
256
262
  <!-- Port Info: padding lives here so handle position is simple -->
@@ -261,7 +267,7 @@
261
267
  class="flowdrop-flex flowdrop-gap--2 flowdrop-justify--end flowdrop-items--center"
262
268
  >
263
269
  {#if isActive}
264
- <span style="color: {getDataTypeColorToken('trigger')};">
270
+ <span style="color: {getDataTypeColorToken(checker, 'trigger')};">
265
271
  <Icon icon="mdi:check-circle" />
266
272
  </span>
267
273
  {/if}
@@ -274,11 +280,13 @@
274
280
  <span
275
281
  class="flowdrop-badge flowdrop-badge--sm"
276
282
  style="background-color: {getPortBackgroundColor(
283
+ checker,
277
284
  'trigger',
278
285
  15
279
286
  )}; color: {getDataTypeColorToken(
287
+ checker,
280
288
  'trigger'
281
- )}; border: 1px solid {getPortBackgroundColor('trigger', 30)};"
289
+ )}; border: 1px solid {getPortBackgroundColor(checker, 'trigger', 30)};"
282
290
  >
283
291
  trigger
284
292
  </span>
@@ -292,8 +300,9 @@
292
300
  id={`${props.data.nodeId}-output-${branch.name}`}
293
301
  class={`flowdrop-workflow-node__handle ${isActive ? 'flowdrop-workflow-node__handle--active' : ''}`}
294
302
  style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {isActive
295
- ? getDataTypeColorToken('trigger')
303
+ ? getDataTypeColorToken(checker, 'trigger')
296
304
  : getDataTypeColorToken(
305
+ checker,
297
306
  'trigger'
298
307
  )}; --fd-handle-border-color: var(--fd-handle-border);"
299
308
  tabindex={-1}
@@ -11,6 +11,7 @@
11
11
  import type { ConfigValues, NodeMetadata } from '../../types/index.js';
12
12
  import Icon from '@iconify/svelte';
13
13
  import { getDataTypeColor } from '../../utils/colors.js';
14
+ import { getInstance } from '../../stores/getInstance.svelte.js';
14
15
  import { m } from '../../messages/index.js';
15
16
 
16
17
  /**
@@ -34,6 +35,8 @@
34
35
  isError?: boolean;
35
36
  }>();
36
37
 
38
+ const checker = getInstance().portCompatibility;
39
+
37
40
  /**
38
41
  * Instance-specific title override from config.
39
42
  * Falls back to the original label if not set.
@@ -151,6 +154,7 @@
151
154
  type="target"
152
155
  position={Position.Left}
153
156
  style="--fd-handle-fill: {getDataTypeColor(
157
+ checker,
154
158
  IDEA_DATA_TYPE
155
159
  )}; --fd-handle-border-color: var(--fd-handle-border); top: 40px; transform: translateY(-50%); z-index: 30;"
156
160
  id={`${props.data.nodeId}-input-left`}
@@ -163,6 +167,7 @@
163
167
  type="target"
164
168
  position={Position.Top}
165
169
  style="--fd-handle-fill: {getDataTypeColor(
170
+ checker,
166
171
  IDEA_DATA_TYPE
167
172
  )}; --fd-handle-border-color: var(--fd-handle-border); left: 150px; transform: translateX(-50%); z-index: 30;"
168
173
  id={`${props.data.nodeId}-input-top`}
@@ -215,6 +220,7 @@
215
220
  type="source"
216
221
  position={Position.Right}
217
222
  style="--fd-handle-fill: {getDataTypeColor(
223
+ checker,
218
224
  IDEA_DATA_TYPE
219
225
  )}; --fd-handle-border-color: var(--fd-handle-border); top: 40px; transform: translateY(-50%); z-index: 30;"
220
226
  id={`${props.data.nodeId}-output-right`}
@@ -227,6 +233,7 @@
227
233
  type="source"
228
234
  position={Position.Bottom}
229
235
  style="--fd-handle-fill: {getDataTypeColor(
236
+ checker,
230
237
  IDEA_DATA_TYPE
231
238
  )}; --fd-handle-border-color: var(--fd-handle-border); left: 150px; transform: translateX(-50%); z-index: 30;"
232
239
  id={`${props.data.nodeId}-output-bottom`}
@@ -21,7 +21,7 @@
21
21
  import { dynamicPortToNodePort } from '../../types/index.js';
22
22
  import Icon from '@iconify/svelte';
23
23
  import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
24
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
24
+ import { getInstance } from '../../stores/getInstance.svelte.js';
25
25
  import { applyPortOrder, getPortTop, isPortVisible } from '../../utils/portUtils.js';
26
26
  import CogIcon from '../icons/CogIcon.svelte';
27
27
  import AlertCircleIcon from '../icons/AlertCircleIcon.svelte';
@@ -44,6 +44,9 @@
44
44
  isError?: boolean;
45
45
  }>();
46
46
 
47
+ const fd = getInstance();
48
+ const checker = fd.portCompatibility;
49
+
47
50
  /**
48
51
  * Get UI extension settings from extensions, merging node type defaults with instance overrides.
49
52
  */
@@ -141,7 +144,7 @@
141
144
  'input',
142
145
  hiddenPorts,
143
146
  hideUnconnectedHandles,
144
- getConnectedHandles(),
147
+ fd.workflow.connectedHandles,
145
148
  props.data.nodeId
146
149
  )
147
150
  )
@@ -160,7 +163,7 @@
160
163
  'output',
161
164
  hiddenPorts,
162
165
  hideUnconnectedHandles,
163
- getConnectedHandles(),
166
+ fd.workflow.connectedHandles,
164
167
  props.data.nodeId
165
168
  )
166
169
  )
@@ -178,11 +181,12 @@
178
181
  </script>
179
182
 
180
183
  <!-- Input Handles: 1 port centered at 40px; N ports at 20px start, 40px gap -->
181
- {#each visibleInputPorts as port, index}
184
+ {#each visibleInputPorts as port, index (port.id)}
182
185
  <Handle
183
186
  type="target"
184
187
  position={Position.Left}
185
188
  style="--fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
189
+ checker,
186
190
  port.dataType
187
191
  )}); --fd-handle-border-color: var(--fd-handle-border); top: {getPortTop(
188
192
  index,
@@ -214,7 +218,7 @@
214
218
  <!-- Node Icon (circle dot) — visibility controlled by --fd-node-circle-display -->
215
219
  <span
216
220
  class="flowdrop-simple-node__color-dot"
217
- style="background: {getCategoryColorToken(props.data.metadata?.category)}"
221
+ style="background: {getCategoryColorToken(fd.categories, props.data.metadata?.category)}"
218
222
  ></span>
219
223
 
220
224
  <!-- Node Title -->
@@ -256,11 +260,12 @@
256
260
  </div>
257
261
 
258
262
  <!-- Output Handles: 1 port centered at 40px; N ports at 20px start, 40px gap -->
259
- {#each visibleOutputPorts as port, index}
263
+ {#each visibleOutputPorts as port, index (port.id)}
260
264
  <Handle
261
265
  type="source"
262
266
  position={Position.Right}
263
267
  style="--fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
268
+ checker,
264
269
  port.dataType
265
270
  )}); --fd-handle-border-color: var(--fd-handle-border); top: {getPortTop(
266
271
  index,
@@ -22,7 +22,7 @@
22
22
  import Icon from '@iconify/svelte';
23
23
  import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
24
24
  import { getNodeIcon } from '../../utils/icons.js';
25
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
25
+ import { getInstance } from '../../stores/getInstance.svelte.js';
26
26
  import { applyPortOrder, getPortTop, isPortVisible } from '../../utils/portUtils.js';
27
27
  import CogIcon from '../icons/CogIcon.svelte';
28
28
  import AlertCircleIcon from '../icons/AlertCircleIcon.svelte';
@@ -45,6 +45,9 @@
45
45
  isError?: boolean;
46
46
  }>();
47
47
 
48
+ const fd = getInstance();
49
+ const checker = fd.portCompatibility;
50
+
48
51
  /**
49
52
  * Get UI extension settings from extensions, merging node type defaults with instance overrides.
50
53
  */
@@ -66,13 +69,15 @@
66
69
  * Get icon using the same resolution as WorkflowNode
67
70
  * Uses getNodeIcon utility with category fallback
68
71
  */
69
- let squareIcon = $derived(getNodeIcon(props.data.metadata?.icon, props.data.metadata?.category));
72
+ let squareIcon = $derived(
73
+ getNodeIcon(fd.categories, props.data.metadata?.icon, props.data.metadata?.category)
74
+ );
70
75
 
71
76
  /**
72
77
  * Get icon color using category-based color tokens for consistency
73
78
  * Falls back to primary color if category not available
74
79
  */
75
- let squareColor = $derived(getCategoryColorToken(props.data.metadata?.category));
80
+ let squareColor = $derived(getCategoryColorToken(fd.categories, props.data.metadata?.category));
76
81
 
77
82
  // Handle configuration sidebar - now using global ConfigSidebar
78
83
  function openConfigSidebar(): void {
@@ -129,7 +134,7 @@
129
134
  'input',
130
135
  hiddenPorts,
131
136
  hideUnconnectedHandles,
132
- getConnectedHandles(),
137
+ fd.workflow.connectedHandles,
133
138
  props.data.nodeId
134
139
  )
135
140
  )
@@ -148,7 +153,7 @@
148
153
  'output',
149
154
  hiddenPorts,
150
155
  hideUnconnectedHandles,
151
- getConnectedHandles(),
156
+ fd.workflow.connectedHandles,
152
157
  props.data.nodeId
153
158
  )
154
159
  )
@@ -167,11 +172,12 @@
167
172
  </script>
168
173
 
169
174
  <!-- Input Handles: 1 port centered at 40px; N ports at 20px start, 40px gap -->
170
- {#each visibleInputPorts as port, index}
175
+ {#each visibleInputPorts as port, index (port.id)}
171
176
  <Handle
172
177
  type="target"
173
178
  position={Position.Left}
174
179
  style="--fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
180
+ checker,
175
181
  port.dataType
176
182
  )}); --fd-handle-border-color: var(--fd-handle-border); top: {getPortTop(
177
183
  index,
@@ -203,7 +209,7 @@
203
209
  <!-- Circle dot — visibility controlled by --fd-node-circle-display -->
204
210
  <span
205
211
  class="flowdrop-square-node__color-dot"
206
- style="background: {getCategoryColorToken(props.data.metadata?.category)}"
212
+ style="background: {getCategoryColorToken(fd.categories, props.data.metadata?.category)}"
207
213
  ></span>
208
214
  </div>
209
215
 
@@ -232,11 +238,12 @@
232
238
  </div>
233
239
 
234
240
  <!-- Output Handles: 1 port centered at 40px; N ports at 20px start, 40px gap -->
235
- {#each visibleOutputPorts as port, index}
241
+ {#each visibleOutputPorts as port, index (port.id)}
236
242
  <Handle
237
243
  type="source"
238
244
  position={Position.Right}
239
245
  style="--fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
246
+ checker,
240
247
  port.dataType
241
248
  )}); --fd-handle-border-color: var(--fd-handle-border); top: {getPortTop(
242
249
  index,
@@ -15,7 +15,7 @@
15
15
  import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
16
16
  import { getNodeIcon } from '../../utils/icons.js';
17
17
  import { getCircleHandlePosition } from '../../utils/handlePositioning.js';
18
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
18
+ import { getInstance } from '../../stores/getInstance.svelte.js';
19
19
 
20
20
  /**
21
21
  * Terminal node variant types
@@ -83,6 +83,9 @@
83
83
  isError?: boolean;
84
84
  }>();
85
85
 
86
+ const fd = getInstance();
87
+ const checker = fd.portCompatibility;
88
+
86
89
  /**
87
90
  * Determine terminal variant from config or metadata
88
91
  * Priority: config.variant > metadata tag detection > default to "start"
@@ -156,7 +159,7 @@
156
159
  return true;
157
160
  }
158
161
  const handleId = `${props.data.nodeId}-${type}-${port.id}`;
159
- return getConnectedHandles().has(handleId);
162
+ return fd.workflow.connectedHandles.has(handleId);
160
163
  }
161
164
 
162
165
  /**
@@ -165,7 +168,7 @@
165
168
  */
166
169
  let terminalIcon = $derived(
167
170
  props.data.metadata?.icon
168
- ? getNodeIcon(props.data.metadata.icon, props.data.metadata?.category)
171
+ ? getNodeIcon(fd.categories, props.data.metadata.icon, props.data.metadata?.category)
169
172
  : variantConfig.icon
170
173
  );
171
174
 
@@ -175,7 +178,7 @@
175
178
  */
176
179
  let terminalColor = $derived(
177
180
  props.data.metadata?.category
178
- ? getCategoryColorToken(props.data.metadata.category)
181
+ ? getCategoryColorToken(fd.categories, props.data.metadata.category)
179
182
  : variantConfig.color
180
183
  );
181
184
 
@@ -363,6 +366,7 @@
363
366
  type="target"
364
367
  position={Position.Left}
365
368
  style="--fd-handle-fill: {getDataTypeColor(
369
+ checker,
366
370
  port.dataType
367
371
  )}; --fd-handle-border-color: var(--fd-handle-border); left: {pos.left}px; top: {pos.top}px; transform: translate(-50%, -50%); z-index: 30;"
368
372
  id={`${props.data.nodeId}-input-${port.id}`}
@@ -386,6 +390,7 @@
386
390
  position={Position.Right}
387
391
  id={`${props.data.nodeId}-output-${port.id}`}
388
392
  style="--fd-handle-fill: {getDataTypeColor(
393
+ checker,
389
394
  port.dataType
390
395
  )}; --fd-handle-border-color: var(--fd-handle-border); left: {pos.left}px; top: {pos.top}px; transform: translate(-50%, -50%); z-index: 30;"
391
396
  />
@@ -8,6 +8,7 @@
8
8
  import { Position, Handle } from '@xyflow/svelte';
9
9
  import Icon from '@iconify/svelte';
10
10
  import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors';
11
+ import { getInstance } from '../../stores/getInstance.svelte.js';
11
12
  import type { NodeMetadata, NodePort } from '../../types/index.js';
12
13
  import CogIcon from '../icons/CogIcon.svelte';
13
14
  import AlertCircleIcon from '../icons/AlertCircleIcon.svelte';
@@ -46,6 +47,9 @@
46
47
  isError?: boolean;
47
48
  }>();
48
49
 
50
+ const fd = getInstance();
51
+ const checker = fd.portCompatibility;
52
+
49
53
  // Prioritize metadata over config for tool nodes (metadata is the node definition)
50
54
  let toolIcon = $derived(
51
55
  (props.data.metadata?.icon as string) || (props.data.config?.icon as string) || 'mdi:tools'
@@ -171,6 +175,7 @@
171
175
  position={Position.Left}
172
176
  id={`${props.data.nodeId}-input-${toolInputPort.id}`}
173
177
  style="top: 40px; transform: translateY(-50%); z-index: 30; --fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
178
+ checker,
174
179
  portDataType
175
180
  )}); --fd-handle-border-color: var(--fd-handle-border);"
176
181
  />
@@ -199,7 +204,7 @@
199
204
  <!-- Circle dot — visibility controlled by --fd-node-circle-display -->
200
205
  <span
201
206
  class="flowdrop-tool-node__color-dot"
202
- style="background: {getCategoryColorToken(props.data.metadata?.category)}"
207
+ style="background: {getCategoryColorToken(fd.categories, props.data.metadata?.category)}"
203
208
  ></span>
204
209
 
205
210
  <!-- Tool Info -->
@@ -249,6 +254,7 @@
249
254
  position={Position.Right}
250
255
  id={`${props.data.nodeId}-output-${toolOutputPort.id}`}
251
256
  style="top: 40px; transform: translateY(-50%); z-index: 30; --fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColor(
257
+ checker,
252
258
  portDataType
253
259
  )}); --fd-handle-border-color: var(--fd-handle-border);"
254
260
  />
@@ -22,7 +22,7 @@
22
22
  getCategoryColorToken,
23
23
  getPortBackgroundColor
24
24
  } from '../../utils/colors.js';
25
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
25
+ import { getInstance } from '../../stores/getInstance.svelte.js';
26
26
  import { applyPortOrder } from '../../utils/portUtils.js';
27
27
  import { m } from '../../messages/index.js';
28
28
 
@@ -37,6 +37,9 @@
37
37
  let props: Props = $props();
38
38
  let isHandleInteraction = $state(false);
39
39
 
40
+ const fd = getInstance();
41
+ const checker = fd.portCompatibility;
42
+
40
43
  // Hoist the graph branch — three reads in the template, two of them inside
41
44
  // {#each port} loops where N×M reads add up. One getter walk per render.
42
45
  const graph = $derived(m().nodes.graph);
@@ -145,7 +148,7 @@
145
148
 
146
149
  // Check if port is connected
147
150
  const handleId = `${props.data.nodeId}-${type}-${port.id}`;
148
- return getConnectedHandles().has(handleId);
151
+ return fd.workflow.connectedHandles.has(handleId);
149
152
  }
150
153
 
151
154
  /**
@@ -219,17 +222,17 @@
219
222
  <!-- Squircle icon — visibility controlled by --fd-node-icon-display -->
220
223
  <div
221
224
  class="flowdrop-workflow-node__icon-wrapper"
222
- style="--_icon-color: {getCategoryColorToken(props.data.metadata.category)}"
225
+ style="--_icon-color: {getCategoryColorToken(fd.categories, props.data.metadata.category)}"
223
226
  >
224
227
  <Icon
225
- icon={getNodeIcon(props.data.metadata.icon, props.data.metadata.category)}
228
+ icon={getNodeIcon(fd.categories, props.data.metadata.icon, props.data.metadata.category)}
226
229
  class="flowdrop-workflow-node__icon"
227
230
  />
228
231
  </div>
229
232
  <!-- Circle dot — visibility controlled by --fd-node-circle-display -->
230
233
  <span
231
234
  class="flowdrop-workflow-node__color-dot"
232
- style="background: {getCategoryColorToken(props.data.metadata.category)}"
235
+ style="background: {getCategoryColorToken(fd.categories, props.data.metadata.category)}"
233
236
  ></span>
234
237
 
235
238
  <!-- Node Title - Icon and Title on same line -->
@@ -262,6 +265,7 @@
262
265
  id={`${props.data.nodeId}-input-${port.id}`}
263
266
  class="flowdrop-workflow-node__handle"
264
267
  style="top: 50%; transform: translateY(-50%); --fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColorToken(
268
+ checker,
265
269
  port.dataType
266
270
  )}); --fd-handle-border-color: var(--fd-handle-border);"
267
271
  tabindex={-1}
@@ -274,11 +278,13 @@
274
278
  <span
275
279
  class="flowdrop-badge flowdrop-badge--sm"
276
280
  style="background-color: {getPortBackgroundColor(
281
+ checker,
277
282
  port.dataType,
278
283
  15
279
284
  )}; color: {getDataTypeColorToken(
285
+ checker,
280
286
  port.dataType
281
- )}; border: 1px solid {getPortBackgroundColor(port.dataType, 30)};"
287
+ )}; border: 1px solid {getPortBackgroundColor(checker, port.dataType, 30)};"
282
288
  >
283
289
  {port.dataType}
284
290
  </span>
@@ -315,11 +321,13 @@
315
321
  <span
316
322
  class="flowdrop-badge flowdrop-badge--sm"
317
323
  style="background-color: {getPortBackgroundColor(
324
+ checker,
318
325
  port.dataType,
319
326
  15
320
327
  )}; color: {getDataTypeColorToken(
328
+ checker,
321
329
  port.dataType
322
- )}; border: 1px solid {getPortBackgroundColor(port.dataType, 30)};"
330
+ )}; border: 1px solid {getPortBackgroundColor(checker, port.dataType, 30)};"
323
331
  >
324
332
  {port.dataType}
325
333
  </span>
@@ -338,6 +346,7 @@
338
346
  id={`${props.data.nodeId}-output-${port.id}`}
339
347
  class="flowdrop-workflow-node__handle"
340
348
  style="top: 50%; transform: translateY(-50%); --fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColorToken(
349
+ checker,
341
350
  port.dataType
342
351
  )}); --fd-handle-border-color: var(--fd-handle-border);"
343
352
  tabindex={-1}
@@ -12,14 +12,11 @@
12
12
  import Icon from '@iconify/svelte';
13
13
  import { tick, untrack } from 'svelte';
14
14
  import { hasEnableRunFlag } from '../../types/playground.js';
15
- import {
16
- getMessages,
17
- getIsExecuting,
18
- getCanSendMessage,
19
- getCurrentSession
20
- } from '../../stores/playgroundStore.svelte.js';
15
+ import { getInstance } from '../../stores/getInstance.svelte.js';
21
16
  import { m } from '../../messages/index.js';
22
17
 
18
+ const fd = getInstance();
19
+
23
20
  interface Props {
24
21
  placeholder?: string;
25
22
  /** Show the textarea (default: true). When false, only the Run button is shown. */
@@ -65,7 +62,7 @@
65
62
  let seenEnableRunCount = 0;
66
63
 
67
64
  $effect(() => {
68
- const count = getMessages().filter((m) => hasEnableRunFlag(m.metadata)).length;
65
+ const count = fd.playground.messages.filter((m) => hasEnableRunFlag(m.metadata)).length;
69
66
  if (count > seenEnableRunCount) {
70
67
  untrack(() => {
71
68
  seenEnableRunCount = count;
@@ -75,7 +72,7 @@
75
72
  });
76
73
 
77
74
  $effect(() => {
78
- if (getCurrentSession()?.id) {
75
+ if (fd.playground.currentSession?.id) {
79
76
  untrack(() => {
80
77
  seenEnableRunCount = 0;
81
78
  });
@@ -87,7 +84,7 @@
87
84
 
88
85
  /** Auto-focus input when execution completes */
89
86
  $effect(() => {
90
- const nowExecuting = getIsExecuting();
87
+ const nowExecuting = fd.playground.isExecuting;
91
88
  if (wasExecuting && !nowExecuting && inputField) {
92
89
  tick().then(() => inputField?.focus({ preventScroll: true }));
93
90
  }
@@ -98,7 +95,7 @@
98
95
 
99
96
  function handleSend(): void {
100
97
  const trimmedValue = inputValue.trim();
101
- if (!trimmedValue || !getCanSendMessage()) return;
98
+ if (!trimmedValue || !fd.playground.canSendMessage) return;
102
99
 
103
100
  onSendMessage?.(trimmedValue);
104
101
  inputValue = '';
@@ -124,7 +121,7 @@
124
121
  }
125
122
 
126
123
  function handleRun(): void {
127
- if (getIsExecuting() || !runEnabled) return;
124
+ if (fd.playground.isExecuting || !runEnabled) return;
128
125
  runEnabled = false;
129
126
  onSendMessage?.(resolvedPredefinedMessage);
130
127
  }
@@ -153,14 +150,14 @@
153
150
  class="chat-input__textarea"
154
151
  placeholder={resolvedPlaceholder}
155
152
  rows="1"
156
- disabled={getIsExecuting() || !getCurrentSession()}
153
+ disabled={fd.playground.isExecuting || !fd.playground.currentSession}
157
154
  onkeydown={handleKeydown}
158
155
  oninput={handleInput}
159
156
  ></textarea>
160
157
  </div>
161
158
  {/if}
162
159
 
163
- {#if getIsExecuting()}
160
+ {#if fd.playground.isExecuting}
164
161
  <button
165
162
  type="button"
166
163
  class="chat-input__stop-btn"
@@ -176,7 +173,7 @@
176
173
  type="button"
177
174
  class="chat-input__send-btn"
178
175
  onclick={handleSend}
179
- disabled={!inputValue.trim() || !getCanSendMessage()}
176
+ disabled={!inputValue.trim() || !fd.playground.canSendMessage}
180
177
  title={actions.sendTitle}
181
178
  aria-label={actions.sendTitle}
182
179
  >