@flowdrop/flowdrop 1.14.0 → 2.0.0-beta.1

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 (218) hide show
  1. package/CHANGELOG.md +475 -0
  2. package/MIGRATION-2.0.md +472 -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/chat/batchFeedback.d.ts +39 -0
  8. package/dist/chat/batchFeedback.js +51 -0
  9. package/dist/commands/executor.js +15 -1
  10. package/dist/commands/storeIntegration.svelte.d.ts +4 -1
  11. package/dist/commands/storeIntegration.svelte.js +26 -21
  12. package/dist/commands/types.d.ts +2 -0
  13. package/dist/components/App.svelte +162 -192
  14. package/dist/components/App.svelte.d.ts +47 -8
  15. package/dist/components/ConfigForm.svelte +110 -66
  16. package/dist/components/ConfigModal.svelte +7 -2
  17. package/dist/components/ConnectionLine.svelte +4 -2
  18. package/dist/components/Navbar.svelte +61 -1
  19. package/dist/components/NodeSidebar.svelte +27 -45
  20. package/dist/components/NodeStatusOverlay.svelte +94 -6
  21. package/dist/components/NodeSwapPicker.svelte +10 -8
  22. package/dist/components/PipelineStatus.svelte +16 -67
  23. package/dist/components/PortCoordinateTracker.svelte +5 -6
  24. package/dist/components/SchemaForm.stories.svelte +1 -3
  25. package/dist/components/SchemaForm.svelte +45 -40
  26. package/dist/components/SchemaForm.svelte.d.ts +0 -8
  27. package/dist/components/SettingsModal.svelte +8 -3
  28. package/dist/components/SettingsPanel.svelte +20 -4
  29. package/dist/components/SwapMappingEditor.svelte +67 -49
  30. package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
  31. package/dist/components/UniversalNode.svelte +9 -7
  32. package/dist/components/WorkflowEditor.svelte +118 -111
  33. package/dist/components/WorkflowEditor.svelte.d.ts +18 -10
  34. package/dist/components/chat/AIChatPanel.svelte +93 -89
  35. package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
  36. package/dist/components/chat/CommandPreview.svelte +2 -1
  37. package/dist/components/console/CommandConsole.svelte +7 -5
  38. package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
  39. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
  40. package/dist/components/console/ConsoleInput.svelte +15 -6
  41. package/dist/components/console/ConsoleOutput.svelte +2 -1
  42. package/dist/components/form/FormArray.svelte +5 -9
  43. package/dist/components/form/FormArray.svelte.d.ts +2 -1
  44. package/dist/components/form/FormAutocomplete.svelte +29 -13
  45. package/dist/components/form/FormField.svelte +4 -2
  46. package/dist/components/form/FormFieldLight.svelte +4 -2
  47. package/dist/components/form/FormMarkdownEditor.svelte +9 -4
  48. package/dist/components/form/FormRangeField.svelte +1 -0
  49. package/dist/components/form/FormTemplateEditor.svelte +11 -3
  50. package/dist/components/form/FormToggle.svelte +5 -12
  51. package/dist/components/form/FormToggle.svelte.d.ts +4 -2
  52. package/dist/components/form/templateAutocomplete.js +1 -5
  53. package/dist/components/form/types.d.ts +1 -14
  54. package/dist/components/interrupt/FormPrompt.svelte +3 -2
  55. package/dist/components/interrupt/InterruptBubble.svelte +16 -17
  56. package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
  57. package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
  58. package/dist/components/layouts/MainLayout.svelte +20 -13
  59. package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
  60. package/dist/components/nodes/AtomNode.svelte +292 -0
  61. package/dist/components/nodes/AtomNode.svelte.d.ts +26 -0
  62. package/dist/components/nodes/GatewayNode.svelte +19 -10
  63. package/dist/components/nodes/IdeaNode.svelte +7 -0
  64. package/dist/components/nodes/SimpleNode.svelte +11 -6
  65. package/dist/components/nodes/SquareNode.svelte +15 -8
  66. package/dist/components/nodes/TerminalNode.svelte +9 -4
  67. package/dist/components/nodes/ToolNode.svelte +7 -1
  68. package/dist/components/nodes/WorkflowNode.svelte +16 -7
  69. package/dist/components/playground/ChatInput.svelte +11 -14
  70. package/dist/components/playground/ChatPanel.svelte +6 -49
  71. package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
  72. package/dist/components/playground/ControlPanel.svelte +134 -123
  73. package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
  74. package/dist/components/playground/ExecutionLogs.svelte +11 -9
  75. package/dist/components/playground/InputCollector.svelte +11 -9
  76. package/dist/components/playground/MessageStream.svelte +17 -23
  77. package/dist/components/playground/PipelineKanbanView.svelte +65 -6
  78. package/dist/components/playground/PipelinePanel.svelte +11 -5
  79. package/dist/components/playground/PipelineTableView.svelte +186 -44
  80. package/dist/components/playground/Playground.svelte +95 -92
  81. package/dist/components/playground/Playground.svelte.d.ts +2 -0
  82. package/dist/components/playground/PlaygroundApp.svelte +6 -1
  83. package/dist/components/playground/PlaygroundApp.svelte.d.ts +3 -0
  84. package/dist/components/playground/PlaygroundModal.svelte +13 -3
  85. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -0
  86. package/dist/components/playground/PlaygroundStudio.svelte +34 -32
  87. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -0
  88. package/dist/components/playground/SessionManager.svelte +9 -12
  89. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +28 -0
  90. package/dist/components/playground/pipelineViewUtils.svelte.js +38 -1
  91. package/dist/config/endpoints.d.ts +0 -7
  92. package/dist/config/endpoints.js +2 -10
  93. package/dist/core/index.d.ts +4 -4
  94. package/dist/core/index.js +6 -6
  95. package/dist/display/index.d.ts +0 -2
  96. package/dist/display/index.js +0 -6
  97. package/dist/editor/index.d.ts +19 -20
  98. package/dist/editor/index.js +25 -35
  99. package/dist/form/code.d.ts +25 -15
  100. package/dist/form/code.js +44 -41
  101. package/dist/form/fieldRegistry.d.ts +17 -13
  102. package/dist/form/fieldRegistry.js +32 -12
  103. package/dist/form/full.d.ts +17 -13
  104. package/dist/form/full.js +22 -27
  105. package/dist/form/index.d.ts +3 -3
  106. package/dist/form/index.js +3 -3
  107. package/dist/form/markdown.d.ts +13 -8
  108. package/dist/form/markdown.js +22 -23
  109. package/dist/helpers/proximityConnect.d.ts +7 -3
  110. package/dist/helpers/proximityConnect.js +19 -6
  111. package/dist/helpers/workflowEditorHelper.d.ts +12 -5
  112. package/dist/helpers/workflowEditorHelper.js +27 -25
  113. package/dist/index.d.ts +28 -24
  114. package/dist/index.js +27 -50
  115. package/dist/messages/defaults.d.ts +2 -5
  116. package/dist/messages/defaults.js +3 -6
  117. package/dist/messages/index.d.ts +0 -1
  118. package/dist/messages/index.js +0 -1
  119. package/dist/mocks/app-forms.d.ts +6 -2
  120. package/dist/mocks/app-forms.js +11 -4
  121. package/dist/openapi/v1/openapi.yaml +227 -164
  122. package/dist/playground/index.d.ts +2 -3
  123. package/dist/playground/index.js +2 -30
  124. package/dist/playground/mount.d.ts +15 -0
  125. package/dist/playground/mount.js +46 -20
  126. package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
  127. package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
  128. package/dist/registry/builtinFormats.d.ts +9 -18
  129. package/dist/registry/builtinFormats.js +9 -39
  130. package/dist/registry/builtinNodes.d.ts +1 -26
  131. package/dist/registry/builtinNodes.js +14 -50
  132. package/dist/registry/index.d.ts +3 -4
  133. package/dist/registry/index.js +4 -6
  134. package/dist/registry/nodeComponentRegistry.d.ts +182 -15
  135. package/dist/registry/nodeComponentRegistry.js +235 -17
  136. package/dist/registry/workflowFormatRegistry.d.ts +14 -9
  137. package/dist/registry/workflowFormatRegistry.js +24 -8
  138. package/dist/{schema → schemas}/index.d.ts +2 -2
  139. package/dist/{schema → schemas}/index.js +2 -2
  140. package/dist/schemas/v1/workflow.schema.json +53 -6
  141. package/dist/services/agentSpecExecutionService.js +0 -1
  142. package/dist/services/apiVariableService.d.ts +2 -1
  143. package/dist/services/apiVariableService.js +5 -22
  144. package/dist/services/autoSaveService.d.ts +7 -0
  145. package/dist/services/autoSaveService.js +6 -4
  146. package/dist/services/chatService.d.ts +8 -4
  147. package/dist/services/chatService.js +15 -15
  148. package/dist/services/draftStorage.d.ts +129 -13
  149. package/dist/services/draftStorage.js +185 -37
  150. package/dist/services/dynamicSchemaService.d.ts +2 -1
  151. package/dist/services/dynamicSchemaService.js +5 -22
  152. package/dist/services/globalSave.d.ts +13 -12
  153. package/dist/services/globalSave.js +29 -51
  154. package/dist/services/historyService.d.ts +9 -3
  155. package/dist/services/historyService.js +9 -3
  156. package/dist/services/interruptService.d.ts +14 -9
  157. package/dist/services/interruptService.js +27 -27
  158. package/dist/services/nodeExecutionService.d.ts +18 -3
  159. package/dist/services/nodeExecutionService.js +71 -45
  160. package/dist/services/playgroundService.d.ts +14 -9
  161. package/dist/services/playgroundService.js +31 -30
  162. package/dist/services/variableService.d.ts +2 -1
  163. package/dist/services/variableService.js +2 -2
  164. package/dist/services/workflowStorage.js +6 -6
  165. package/dist/stores/apiContext.d.ts +45 -0
  166. package/dist/stores/apiContext.js +65 -0
  167. package/dist/stores/categoriesStore.svelte.d.ts +28 -23
  168. package/dist/stores/categoriesStore.svelte.js +70 -64
  169. package/dist/stores/getInstance.svelte.d.ts +39 -0
  170. package/dist/stores/getInstance.svelte.js +65 -0
  171. package/dist/stores/historyStore.svelte.d.ts +77 -93
  172. package/dist/stores/historyStore.svelte.js +134 -160
  173. package/dist/stores/instanceContainer.svelte.d.ts +111 -0
  174. package/dist/stores/instanceContainer.svelte.js +114 -0
  175. package/dist/stores/interruptStore.svelte.d.ts +112 -82
  176. package/dist/stores/interruptStore.svelte.js +253 -226
  177. package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
  178. package/dist/stores/pipelinePanelStore.svelte.js +61 -14
  179. package/dist/stores/playgroundStore.svelte.d.ts +169 -216
  180. package/dist/stores/playgroundStore.svelte.js +515 -572
  181. package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
  182. package/dist/stores/portCoordinateStore.svelte.js +109 -98
  183. package/dist/stores/settingsStore.svelte.d.ts +4 -1
  184. package/dist/stores/settingsStore.svelte.js +47 -12
  185. package/dist/stores/workflowStore.svelte.d.ts +178 -213
  186. package/dist/stores/workflowStore.svelte.js +449 -501
  187. package/dist/stories/EdgeDecorator.svelte +5 -2
  188. package/dist/stories/NodeDecorator.svelte +5 -3
  189. package/dist/svelte-app.d.ts +60 -10
  190. package/dist/svelte-app.js +157 -53
  191. package/dist/types/events.d.ts +6 -3
  192. package/dist/types/index.d.ts +71 -6
  193. package/dist/types/navbar.d.ts +7 -0
  194. package/dist/types/playground.d.ts +18 -3
  195. package/dist/types/settings.d.ts +13 -0
  196. package/dist/types/settings.js +1 -0
  197. package/dist/utils/colors.d.ts +47 -21
  198. package/dist/utils/colors.js +69 -68
  199. package/dist/utils/connections.d.ts +9 -15
  200. package/dist/utils/connections.js +13 -32
  201. package/dist/utils/duration.d.ts +13 -0
  202. package/dist/utils/duration.js +45 -0
  203. package/dist/utils/formMerge.d.ts +36 -0
  204. package/dist/utils/formMerge.js +70 -0
  205. package/dist/utils/icons.d.ts +5 -2
  206. package/dist/utils/icons.js +6 -5
  207. package/dist/utils/nodeSwap.d.ts +6 -2
  208. package/dist/utils/nodeSwap.js +62 -126
  209. package/dist/utils/nodeTypes.d.ts +17 -8
  210. package/dist/utils/nodeTypes.js +27 -19
  211. package/dist/utils/performanceUtils.js +7 -0
  212. package/package.json +6 -5
  213. package/dist/messages/deprecation.d.ts +0 -20
  214. package/dist/messages/deprecation.js +0 -33
  215. package/dist/registry/plugin.d.ts +0 -215
  216. package/dist/registry/plugin.js +0 -249
  217. package/dist/services/api.d.ts +0 -129
  218. package/dist/services/api.js +0 -217
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import type { Component } from 'svelte';
12
12
  import type { WorkflowNode } from '../types/index.js';
13
- import { BaseRegistry } from './BaseRegistry.js';
13
+ import { BaseRegistry } from './BaseRegistry.svelte.js';
14
14
  /**
15
15
  * Props interface that all node components must accept.
16
16
  * Any component registered in the registry must be compatible with these props.
@@ -86,6 +86,73 @@ export interface NodeRegistrationFilter {
86
86
  /** Custom filter function */
87
87
  predicate?: (registration: NodeComponentRegistration) => boolean;
88
88
  }
89
+ /**
90
+ * Plugin configuration for external libraries.
91
+ * Use this to register multiple node types from a library.
92
+ */
93
+ export interface FlowDropPluginConfig {
94
+ /**
95
+ * Unique namespace for this plugin.
96
+ * Used to prefix all node types (e.g., "mylib" -> "mylib:nodename").
97
+ * Should be lowercase, alphanumeric with optional hyphens.
98
+ */
99
+ namespace: string;
100
+ /** Display name for the plugin (for UI/debugging purposes) */
101
+ name: string;
102
+ /** Plugin version (optional, for debugging) */
103
+ version?: string;
104
+ /** Description of what this plugin provides */
105
+ description?: string;
106
+ /** Node components to register */
107
+ nodes: PluginNodeDefinition[];
108
+ }
109
+ /**
110
+ * Simplified node definition for plugins.
111
+ * Provides a cleaner API than full NodeComponentRegistration.
112
+ */
113
+ export interface PluginNodeDefinition {
114
+ /**
115
+ * Type identifier for this node.
116
+ * Will be prefixed with the plugin namespace (e.g., "fancy" -> "mylib:fancy").
117
+ */
118
+ type: string;
119
+ /** Display name shown in UI */
120
+ displayName: string;
121
+ /** Description of what this node does */
122
+ description?: string;
123
+ /** The Svelte component to render */
124
+ component: Component<NodeComponentProps>;
125
+ /** Icon in iconify format (e.g., "mdi:star") */
126
+ icon?: string;
127
+ /** Category for organizing in UI */
128
+ category?: NodeComponentCategory;
129
+ /** Status overlay position */
130
+ statusPosition?: StatusPosition;
131
+ /** Status overlay size */
132
+ statusSize?: StatusSize;
133
+ }
134
+ /**
135
+ * Result of plugin registration.
136
+ * Contains information about what was registered and any errors.
137
+ */
138
+ export interface PluginRegistrationResult {
139
+ /** Whether all nodes were registered successfully */
140
+ success: boolean;
141
+ /** The plugin namespace */
142
+ namespace: string;
143
+ /** Array of successfully registered type identifiers (namespaced) */
144
+ registeredTypes: string[];
145
+ /** Array of error messages for failed registrations */
146
+ errors: string[];
147
+ }
148
+ /**
149
+ * Check if a namespace is valid.
150
+ * Must be lowercase alphanumeric with optional hyphens.
151
+ *
152
+ * @param namespace - The namespace to validate
153
+ * @returns true if valid
154
+ */
155
+ export declare function isValidNamespace(namespace: string): boolean;
89
156
  /**
90
157
  * Central registry for node component types.
91
158
  * Allows built-in and third-party components to be registered and resolved.
@@ -95,7 +162,7 @@ export interface NodeRegistrationFilter {
95
162
  * @example
96
163
  * ```typescript
97
164
  * // Register a custom node
98
- * nodeComponentRegistry.register({
165
+ * fd.nodes.register({
99
166
  * type: "myCustomNode",
100
167
  * displayName: "My Custom Node",
101
168
  * component: MyCustomNodeComponent,
@@ -104,14 +171,28 @@ export interface NodeRegistrationFilter {
104
171
  * });
105
172
  *
106
173
  * // Get a component
107
- * const component = nodeComponentRegistry.getComponent("myCustomNode");
174
+ * const component = fd.nodes.getComponent("myCustomNode");
108
175
  * ```
109
176
  */
110
- declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRegistration> {
177
+ export declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRegistration> {
111
178
  /** Default type to use when requested type is not found */
112
179
  private defaultType;
113
180
  /** Initial default type, restored on clear() */
114
181
  private static readonly INITIAL_DEFAULT_TYPE;
182
+ /**
183
+ * @param seed - Optional initial registrations and default type. When
184
+ * omitted the registry starts empty; instances created via
185
+ * `createFlowDropInstance` pass the built-in node components (see
186
+ * `builtinNodes.ts`).
187
+ */
188
+ constructor(seed?: {
189
+ registrations?: NodeComponentRegistration[];
190
+ defaultType?: string;
191
+ });
192
+ /**
193
+ * Clear all registrations and reset default type.
194
+ */
195
+ clear(): void;
115
196
  /**
116
197
  * Register a node component type.
117
198
  *
@@ -121,7 +202,7 @@ declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRe
121
202
  *
122
203
  * @example
123
204
  * ```typescript
124
- * nodeComponentRegistry.register({
205
+ * fd.nodes.register({
125
206
  * type: "fancy",
126
207
  * displayName: "Fancy Node",
127
208
  * component: FancyNode,
@@ -129,10 +210,6 @@ declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRe
129
210
  * });
130
211
  * ```
131
212
  */
132
- /**
133
- * Clear all registrations and reset default type.
134
- */
135
- clear(): void;
136
213
  register(registration: NodeComponentRegistration, overwrite?: boolean): void;
137
214
  /**
138
215
  * Register multiple components at once.
@@ -171,10 +248,10 @@ declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRe
171
248
  * @example
172
249
  * ```typescript
173
250
  * // Get all visual nodes
174
- * const visualNodes = nodeComponentRegistry.filter({ category: "visual" });
251
+ * const visualNodes = fd.nodes.filter({ category: "visual" });
175
252
  *
176
253
  * // Get nodes from a specific library
177
- * const libNodes = nodeComponentRegistry.filter({ source: "mylib" });
254
+ * const libNodes = fd.nodes.filter({ source: "mylib" });
178
255
  * ```
179
256
  */
180
257
  filter(filter: NodeRegistrationFilter): NodeComponentRegistration[];
@@ -214,7 +291,7 @@ declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRe
214
291
  *
215
292
  * @example
216
293
  * ```typescript
217
- * const oneOf = nodeComponentRegistry.getOneOfOptions();
294
+ * const oneOf = fd.nodes.getOneOfOptions();
218
295
  * // Use in configSchema: { type: "string", oneOf }
219
296
  * ```
220
297
  */
@@ -236,9 +313,100 @@ declare class NodeComponentRegistry extends BaseRegistry<string, NodeComponentRe
236
313
  * @returns The status size, or default "md"
237
314
  */
238
315
  getStatusSize(type: string): StatusSize;
316
+ /**
317
+ * Register a single custom node without a full plugin.
318
+ * Useful for project-specific custom nodes.
319
+ *
320
+ * @param type - Type identifier (can be namespaced or plain)
321
+ * @param displayName - Display name for UI
322
+ * @param component - Svelte component
323
+ * @param options - Additional options
324
+ *
325
+ * @example
326
+ * ```typescript
327
+ * fd.nodes.registerCustom("myproject:special", "Special Node", MyNode, {
328
+ * icon: "mdi:star",
329
+ * description: "A special node for my project"
330
+ * });
331
+ * ```
332
+ */
333
+ registerCustom(type: string, displayName: string, component: Component<NodeComponentProps>, options?: {
334
+ description?: string;
335
+ icon?: string;
336
+ category?: NodeComponentCategory;
337
+ source?: string;
338
+ statusPosition?: StatusPosition;
339
+ statusSize?: StatusSize;
340
+ }): void;
341
+ /**
342
+ * Register a FlowDrop plugin with custom node components.
343
+ * All node types are automatically namespaced with the plugin namespace.
344
+ *
345
+ * @param config - Plugin configuration with namespace and node definitions
346
+ * @returns Result object with registered types and any errors
347
+ */
348
+ registerPlugin(config: FlowDropPluginConfig): PluginRegistrationResult;
349
+ /**
350
+ * Unregister all nodes from a plugin by namespace.
351
+ *
352
+ * @param namespace - The plugin namespace to unregister
353
+ * @returns Array of unregistered type identifiers
354
+ */
355
+ unregisterPlugin(namespace: string): string[];
356
+ /**
357
+ * Get all registered plugins (unique namespaces).
358
+ *
359
+ * @returns Array of namespace strings
360
+ */
361
+ getRegisteredPlugins(): string[];
362
+ /**
363
+ * Get the count of nodes registered by a plugin.
364
+ *
365
+ * @param namespace - The plugin namespace
366
+ * @returns Number of nodes registered by this plugin
367
+ */
368
+ getPluginNodeCount(namespace: string): number;
239
369
  }
240
- /** Singleton instance of the node component registry */
241
- export declare const nodeComponentRegistry: NodeComponentRegistry;
370
+ /**
371
+ * Create a plugin builder for a fluent API experience.
372
+ *
373
+ * @param namespace - Plugin namespace
374
+ * @param name - Plugin name
375
+ * @returns Plugin builder with chainable methods
376
+ *
377
+ * @example
378
+ * ```typescript
379
+ * import { createPlugin } from "@flowdrop/flowdrop/editor";
380
+ *
381
+ * createPlugin("awesome", "Awesome Nodes")
382
+ * .version("1.0.0")
383
+ * .node("fancy", "Fancy Node", FancyNode)
384
+ * .node("glow", "Glowing Node", GlowNode, { icon: "mdi:lightbulb" })
385
+ * .register(fd.nodes);
386
+ * ```
387
+ */
388
+ export declare function createPlugin(namespace: string, name: string): {
389
+ /**
390
+ * Set plugin version
391
+ */
392
+ version(v: string): /*elided*/ any;
393
+ /**
394
+ * Set plugin description
395
+ */
396
+ description(desc: string): /*elided*/ any;
397
+ /**
398
+ * Add a node to the plugin
399
+ */
400
+ node(type: string, displayName: string, component: Component<NodeComponentProps>, options?: Partial<Omit<PluginNodeDefinition, "type" | "displayName" | "component">>): /*elided*/ any;
401
+ /**
402
+ * Register the plugin into a node component registry (e.g. `fd.nodes`).
403
+ */
404
+ register(registry: NodeComponentRegistry): PluginRegistrationResult;
405
+ /**
406
+ * Get the config without registering (for testing/inspection)
407
+ */
408
+ getConfig(): FlowDropPluginConfig;
409
+ };
242
410
  /**
243
411
  * Helper function to create a namespaced type identifier.
244
412
  * Use this to avoid conflicts when registering custom nodes.
@@ -273,4 +441,3 @@ export declare function parseNamespacedType(namespacedType: string): {
273
441
  namespace: string;
274
442
  type: string;
275
443
  } | null;
276
- export {};
@@ -8,7 +8,17 @@
8
8
  * - External libraries to contribute node types via plugins
9
9
  * - Runtime switching between different node visualizations
10
10
  */
11
- import { BaseRegistry } from './BaseRegistry.js';
11
+ import { BaseRegistry } from './BaseRegistry.svelte.js';
12
+ /**
13
+ * Check if a namespace is valid.
14
+ * Must be lowercase alphanumeric with optional hyphens.
15
+ *
16
+ * @param namespace - The namespace to validate
17
+ * @returns true if valid
18
+ */
19
+ export function isValidNamespace(namespace) {
20
+ return /^[a-z][a-z0-9-]*$/.test(namespace);
21
+ }
12
22
  /**
13
23
  * Central registry for node component types.
14
24
  * Allows built-in and third-party components to be registered and resolved.
@@ -18,7 +28,7 @@ import { BaseRegistry } from './BaseRegistry.js';
18
28
  * @example
19
29
  * ```typescript
20
30
  * // Register a custom node
21
- * nodeComponentRegistry.register({
31
+ * fd.nodes.register({
22
32
  * type: "myCustomNode",
23
33
  * displayName: "My Custom Node",
24
34
  * component: MyCustomNodeComponent,
@@ -27,14 +37,37 @@ import { BaseRegistry } from './BaseRegistry.js';
27
37
  * });
28
38
  *
29
39
  * // Get a component
30
- * const component = nodeComponentRegistry.getComponent("myCustomNode");
40
+ * const component = fd.nodes.getComponent("myCustomNode");
31
41
  * ```
32
42
  */
33
- class NodeComponentRegistry extends BaseRegistry {
43
+ export class NodeComponentRegistry extends BaseRegistry {
34
44
  /** Default type to use when requested type is not found */
35
45
  defaultType = 'workflowNode';
36
46
  /** Initial default type, restored on clear() */
37
47
  static INITIAL_DEFAULT_TYPE = 'workflowNode';
48
+ /**
49
+ * @param seed - Optional initial registrations and default type. When
50
+ * omitted the registry starts empty; instances created via
51
+ * `createFlowDropInstance` pass the built-in node components (see
52
+ * `builtinNodes.ts`).
53
+ */
54
+ constructor(seed) {
55
+ super();
56
+ if (seed?.registrations) {
57
+ this.registerAll(seed.registrations, true);
58
+ }
59
+ if (seed?.defaultType) {
60
+ this.defaultType = seed.defaultType;
61
+ }
62
+ }
63
+ /**
64
+ * Clear all registrations and reset default type.
65
+ */
66
+ clear() {
67
+ super.clear();
68
+ this.defaultType = NodeComponentRegistry.INITIAL_DEFAULT_TYPE;
69
+ this.touch(); // defaultType changed — invalidate getComponent/getDefaultType reads
70
+ }
38
71
  /**
39
72
  * Register a node component type.
40
73
  *
@@ -44,7 +77,7 @@ class NodeComponentRegistry extends BaseRegistry {
44
77
  *
45
78
  * @example
46
79
  * ```typescript
47
- * nodeComponentRegistry.register({
80
+ * fd.nodes.register({
48
81
  * type: "fancy",
49
82
  * displayName: "Fancy Node",
50
83
  * component: FancyNode,
@@ -52,19 +85,13 @@ class NodeComponentRegistry extends BaseRegistry {
52
85
  * });
53
86
  * ```
54
87
  */
55
- /**
56
- * Clear all registrations and reset default type.
57
- */
58
- clear() {
59
- super.clear();
60
- this.defaultType = NodeComponentRegistry.INITIAL_DEFAULT_TYPE;
61
- }
62
88
  register(registration, overwrite = false) {
63
89
  if (this.items.has(registration.type) && !overwrite) {
64
90
  throw new Error(`Node type "${registration.type}" is already registered. ` +
65
91
  `Use overwrite: true to replace it, or use a namespaced type like "mylib:${registration.type}".`);
66
92
  }
67
93
  this.items.set(registration.type, registration);
94
+ this.touch();
68
95
  this.notifyListeners();
69
96
  }
70
97
  /**
@@ -86,6 +113,7 @@ class NodeComponentRegistry extends BaseRegistry {
86
113
  * @returns The component if found, or the default component
87
114
  */
88
115
  getComponent(type) {
116
+ this.trackVersion(); // reactive dependency (reads items + defaultType directly)
89
117
  const registration = this.items.get(type) ?? this.items.get(this.defaultType);
90
118
  return registration?.component;
91
119
  }
@@ -96,6 +124,7 @@ class NodeComponentRegistry extends BaseRegistry {
96
124
  * @returns The metadata if found, undefined otherwise
97
125
  */
98
126
  getMetadata(type) {
127
+ this.trackVersion(); // reactive dependency (reads items directly)
99
128
  const reg = this.items.get(type);
100
129
  if (!reg)
101
130
  return undefined;
@@ -119,10 +148,10 @@ class NodeComponentRegistry extends BaseRegistry {
119
148
  * @example
120
149
  * ```typescript
121
150
  * // Get all visual nodes
122
- * const visualNodes = nodeComponentRegistry.filter({ category: "visual" });
151
+ * const visualNodes = fd.nodes.filter({ category: "visual" });
123
152
  *
124
153
  * // Get nodes from a specific library
125
- * const libNodes = nodeComponentRegistry.filter({ source: "mylib" });
154
+ * const libNodes = fd.nodes.filter({ source: "mylib" });
126
155
  * ```
127
156
  */
128
157
  filter(filter) {
@@ -168,6 +197,7 @@ class NodeComponentRegistry extends BaseRegistry {
168
197
  throw new Error(`Cannot set default to unregistered type: ${type}`);
169
198
  }
170
199
  this.defaultType = type;
200
+ this.touch(); // defaultType changed — invalidate getComponent/getDefaultType reads
171
201
  }
172
202
  /**
173
203
  * Get the current default type.
@@ -175,6 +205,7 @@ class NodeComponentRegistry extends BaseRegistry {
175
205
  * @returns The default type identifier
176
206
  */
177
207
  getDefaultType() {
208
+ this.trackVersion(); // reactive dependency (reads defaultType directly)
178
209
  return this.defaultType;
179
210
  }
180
211
  /**
@@ -186,7 +217,7 @@ class NodeComponentRegistry extends BaseRegistry {
186
217
  *
187
218
  * @example
188
219
  * ```typescript
189
- * const oneOf = nodeComponentRegistry.getOneOfOptions();
220
+ * const oneOf = fd.nodes.getOneOfOptions();
190
221
  * // Use in configSchema: { type: "string", oneOf }
191
222
  * ```
192
223
  */
@@ -204,6 +235,7 @@ class NodeComponentRegistry extends BaseRegistry {
204
235
  * @returns The status position, or default "top-right"
205
236
  */
206
237
  getStatusPosition(type) {
238
+ this.trackVersion(); // reactive dependency (reads items directly)
207
239
  return this.items.get(type)?.statusPosition ?? 'top-right';
208
240
  }
209
241
  /**
@@ -213,11 +245,197 @@ class NodeComponentRegistry extends BaseRegistry {
213
245
  * @returns The status size, or default "md"
214
246
  */
215
247
  getStatusSize(type) {
248
+ this.trackVersion(); // reactive dependency (reads items directly)
216
249
  return this.items.get(type)?.statusSize ?? 'md';
217
250
  }
251
+ // ==========================================================================
252
+ // Plugin system
253
+ // ==========================================================================
254
+ /**
255
+ * Register a single custom node without a full plugin.
256
+ * Useful for project-specific custom nodes.
257
+ *
258
+ * @param type - Type identifier (can be namespaced or plain)
259
+ * @param displayName - Display name for UI
260
+ * @param component - Svelte component
261
+ * @param options - Additional options
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * fd.nodes.registerCustom("myproject:special", "Special Node", MyNode, {
266
+ * icon: "mdi:star",
267
+ * description: "A special node for my project"
268
+ * });
269
+ * ```
270
+ */
271
+ registerCustom(type, displayName, component, options = {}) {
272
+ this.register({
273
+ type,
274
+ displayName,
275
+ component,
276
+ description: options.description,
277
+ icon: options.icon,
278
+ category: options.category ?? 'custom',
279
+ source: options.source ?? 'custom',
280
+ statusPosition: options.statusPosition,
281
+ statusSize: options.statusSize
282
+ });
283
+ }
284
+ /**
285
+ * Register a FlowDrop plugin with custom node components.
286
+ * All node types are automatically namespaced with the plugin namespace.
287
+ *
288
+ * @param config - Plugin configuration with namespace and node definitions
289
+ * @returns Result object with registered types and any errors
290
+ */
291
+ registerPlugin(config) {
292
+ const result = {
293
+ success: true,
294
+ namespace: config.namespace,
295
+ registeredTypes: [],
296
+ errors: []
297
+ };
298
+ // Validate namespace
299
+ if (!isValidNamespace(config.namespace)) {
300
+ result.success = false;
301
+ result.errors.push(`Invalid namespace "${config.namespace}". ` +
302
+ `Namespace must be lowercase alphanumeric with optional hyphens.`);
303
+ return result;
304
+ }
305
+ // Register each node
306
+ for (const nodeDef of config.nodes) {
307
+ try {
308
+ const namespacedType = createNamespacedType(config.namespace, nodeDef.type);
309
+ const registration = {
310
+ type: namespacedType,
311
+ displayName: nodeDef.displayName,
312
+ description: nodeDef.description,
313
+ component: nodeDef.component,
314
+ icon: nodeDef.icon,
315
+ category: nodeDef.category ?? 'custom',
316
+ source: config.namespace,
317
+ statusPosition: nodeDef.statusPosition,
318
+ statusSize: nodeDef.statusSize
319
+ };
320
+ this.register(registration);
321
+ result.registeredTypes.push(namespacedType);
322
+ }
323
+ catch (error) {
324
+ result.success = false;
325
+ const errorMessage = error instanceof Error ? error.message : String(error);
326
+ result.errors.push(`Failed to register ${config.namespace}:${nodeDef.type}: ${errorMessage}`);
327
+ }
328
+ }
329
+ return result;
330
+ }
331
+ /**
332
+ * Unregister all nodes from a plugin by namespace.
333
+ *
334
+ * @param namespace - The plugin namespace to unregister
335
+ * @returns Array of unregistered type identifiers
336
+ */
337
+ unregisterPlugin(namespace) {
338
+ const unregistered = [];
339
+ const types = this.getTypes();
340
+ for (const type of types) {
341
+ if (type.startsWith(`${namespace}:`)) {
342
+ if (this.unregister(type)) {
343
+ unregistered.push(type);
344
+ }
345
+ }
346
+ }
347
+ return unregistered;
348
+ }
349
+ /**
350
+ * Get all registered plugins (unique namespaces).
351
+ *
352
+ * @returns Array of namespace strings
353
+ */
354
+ getRegisteredPlugins() {
355
+ const sources = new Set();
356
+ for (const reg of this.getAll()) {
357
+ if (reg.source && reg.source !== 'flowdrop') {
358
+ sources.add(reg.source);
359
+ }
360
+ }
361
+ return Array.from(sources);
362
+ }
363
+ /**
364
+ * Get the count of nodes registered by a plugin.
365
+ *
366
+ * @param namespace - The plugin namespace
367
+ * @returns Number of nodes registered by this plugin
368
+ */
369
+ getPluginNodeCount(namespace) {
370
+ return this.getBySource(namespace).length;
371
+ }
372
+ }
373
+ /**
374
+ * Create a plugin builder for a fluent API experience.
375
+ *
376
+ * @param namespace - Plugin namespace
377
+ * @param name - Plugin name
378
+ * @returns Plugin builder with chainable methods
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * import { createPlugin } from "@flowdrop/flowdrop/editor";
383
+ *
384
+ * createPlugin("awesome", "Awesome Nodes")
385
+ * .version("1.0.0")
386
+ * .node("fancy", "Fancy Node", FancyNode)
387
+ * .node("glow", "Glowing Node", GlowNode, { icon: "mdi:lightbulb" })
388
+ * .register(fd.nodes);
389
+ * ```
390
+ */
391
+ export function createPlugin(namespace, name) {
392
+ const config = {
393
+ namespace,
394
+ name,
395
+ nodes: []
396
+ };
397
+ const builder = {
398
+ /**
399
+ * Set plugin version
400
+ */
401
+ version(v) {
402
+ config.version = v;
403
+ return builder;
404
+ },
405
+ /**
406
+ * Set plugin description
407
+ */
408
+ description(desc) {
409
+ config.description = desc;
410
+ return builder;
411
+ },
412
+ /**
413
+ * Add a node to the plugin
414
+ */
415
+ node(type, displayName, component, options = {}) {
416
+ config.nodes.push({
417
+ type,
418
+ displayName,
419
+ component,
420
+ ...options
421
+ });
422
+ return builder;
423
+ },
424
+ /**
425
+ * Register the plugin into a node component registry (e.g. `fd.nodes`).
426
+ */
427
+ register(registry) {
428
+ return registry.registerPlugin(config);
429
+ },
430
+ /**
431
+ * Get the config without registering (for testing/inspection)
432
+ */
433
+ getConfig() {
434
+ return { ...config };
435
+ }
436
+ };
437
+ return builder;
218
438
  }
219
- /** Singleton instance of the node component registry */
220
- export const nodeComponentRegistry = new NodeComponentRegistry();
221
439
  /**
222
440
  * Helper function to create a namespaced type identifier.
223
441
  * Use this to avoid conflicts when registering custom nodes.
@@ -13,7 +13,7 @@
13
13
  */
14
14
  import type { StandardWorkflow } from '../adapters/WorkflowAdapter.js';
15
15
  import type { NodeMetadata, WorkflowFormat } from '../types/index.js';
16
- import { BaseRegistry } from './BaseRegistry.js';
16
+ import { BaseRegistry } from './BaseRegistry.svelte.js';
17
17
  /**
18
18
  * Validation result returned by format adapters.
19
19
  */
@@ -60,13 +60,15 @@ export interface WorkflowFormatAdapter {
60
60
  validate?(workflow: StandardWorkflow): FormatValidationResult;
61
61
  }
62
62
  /**
63
- * Central registry for workflow format adapters.
64
- * Singleton — extends BaseRegistry for shared mechanics.
63
+ * Per-instance registry for workflow format adapters.
64
+ * Extends BaseRegistry for shared mechanics; seeded with the built-in
65
+ * adapters at construction (see `createFlowDropInstance`). Reach it via
66
+ * `fd.formats`, or supply adapters through the `formatAdapters` mount option.
65
67
  *
66
68
  * @example
67
69
  * ```typescript
68
70
  * // Register a custom format
69
- * workflowFormatRegistry.register({
71
+ * fd.formats.register({
70
72
  * id: 'n8n',
71
73
  * name: 'n8n Workflow',
72
74
  * export: (workflow) => JSON.stringify(convertToN8n(workflow)),
@@ -74,10 +76,16 @@ export interface WorkflowFormatAdapter {
74
76
  * });
75
77
  *
76
78
  * // Get an adapter
77
- * const adapter = workflowFormatRegistry.get('n8n');
79
+ * const adapter = fd.formats.get('n8n');
78
80
  * ```
79
81
  */
80
- declare class WorkflowFormatRegistry extends BaseRegistry<string, WorkflowFormatAdapter> {
82
+ export declare class WorkflowFormatRegistry extends BaseRegistry<string, WorkflowFormatAdapter> {
83
+ /**
84
+ * @param seed - Optional initial format adapters. When omitted the registry
85
+ * starts empty; instances created via `createFlowDropInstance` pass the
86
+ * built-in flowdrop + agentspec adapters (see `builtinFormats.ts`).
87
+ */
88
+ constructor(seed?: WorkflowFormatAdapter[]);
81
89
  /**
82
90
  * Register a workflow format adapter.
83
91
  *
@@ -117,6 +125,3 @@ declare class WorkflowFormatRegistry extends BaseRegistry<string, WorkflowFormat
117
125
  title: string;
118
126
  }>;
119
127
  }
120
- /** Singleton instance of the workflow format registry */
121
- export declare const workflowFormatRegistry: WorkflowFormatRegistry;
122
- export {};