@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
@@ -0,0 +1,472 @@
1
+ # Migrating to FlowDrop 2.0
2
+
3
+ 2.0's theme is **the explicit-instance era**: every compatibility shim the 1.x
4
+ multi-instance refactor and the 1.8 message migration carried is gone. If your
5
+ 1.x code ran without deprecation warnings in the console, most of this guide
6
+ does not apply to you.
7
+
8
+ The sections are ordered by the shape of the change, from the deepest
9
+ architectural moves (instances, the API client, registries) outward to module
10
+ layout, data formats, component props, and storage. Each has a 1.x → 2.0 code
11
+ example.
12
+
13
+ ## 1. Module-level store APIs are removed (the big one)
14
+
15
+ All ~95 module-level functions that operated on "the" editor are gone:
16
+ `getWorkflowStore()`, `workflowActions`, `historyService`, `getMessages()`,
17
+ `playgroundActions`, `getCategories()`, `getHistoryState()`, and the rest of
18
+ the get*/set*/actions surface from `@flowdrop/flowdrop/editor` and
19
+ `@flowdrop/flowdrop/playground`.
20
+
21
+ **Replacement:** every mount handle exposes its state container.
22
+
23
+ ```js
24
+ // 1.x
25
+ import { workflowActions, historyService, getMessages } from '@flowdrop/flowdrop/editor';
26
+ const app = await mountFlowDropApp(el, options);
27
+ workflowActions.addNode(node);
28
+ historyService.undo();
29
+ const messages = getMessages();
30
+
31
+ // 2.0
32
+ const app = await mountFlowDropApp(el, options);
33
+ app.instance.workflow.actions.addNode(node);
34
+ app.instance.history.undo();
35
+ const messages = app.instance.playground.messages;
36
+ ```
37
+
38
+ Inside Svelte components rendered under `<App>`/`<WorkflowEditor>`, resolve the
39
+ owning instance with `getInstance()` (unchanged — including the browser
40
+ fallback to the page-default instance for single-editor embeds):
41
+
42
+ ```svelte
43
+ <script>
44
+ import { getInstance } from '@flowdrop/flowdrop/editor';
45
+ const fd = getInstance();
46
+ // fd.workflow, fd.history, fd.playground, fd.interrupts, fd.categories, …
47
+ </script>
48
+ ```
49
+
50
+ For hosts that construct state manually, the store classes are now exported:
51
+ `WorkflowStore`, `HistoryStore`, `HistoryService`, `PlaygroundStore`,
52
+ `InterruptStore`, `PortCoordinateStore`, plus `createFlowDropInstance()`.
53
+
54
+ Settings remain page-global by design — `getSettings()` etc. are unchanged.
55
+
56
+ ## 2. API access is instance-scoped (`fd.api`)
57
+
58
+ The module-level API singleton in `services/api.js` is gone:
59
+ `setEndpointConfig()`, `getEndpointConfig()`, `nodeApi`, `workflowApi`, and the
60
+ `api` aggregate are removed. Each instance now owns an `ApiContext` at
61
+ `fd.api`, which holds the endpoint config + auth provider and lazily builds an
62
+ `EnhancedFlowDropApiClient`.
63
+
64
+ ```js
65
+ // 1.x
66
+ import { setEndpointConfig, workflowApi, nodeApi } from '@flowdrop/flowdrop/editor';
67
+ setEndpointConfig(createEndpointConfig('/api/flowdrop'));
68
+ const nodes = await nodeApi.getNodes();
69
+ const wf = await workflowApi.getWorkflow(id);
70
+
71
+ // 2.0 — mount configures fd.api automatically; inside components resolve it:
72
+ import { getInstance } from '@flowdrop/flowdrop/editor';
73
+ const fd = getInstance();
74
+ const nodes = await fd.api.client.getAvailableNodes();
75
+ const wf = await fd.api.client.loadWorkflow(id);
76
+ ```
77
+
78
+ `mountFlowDropApp` / `mountPlayground` / `<App>` call `fd.api.configure(config,
79
+ authProvider)` for you. Services that previously read the singleton (playground,
80
+ interrupt, chat, node-execution, dynamic-schema, variable) now take the endpoint
81
+ config as their first argument — pass `fd.api.config`.
82
+
83
+ ### `EndpointConfig.auth` is removed — use an `AuthProvider`
84
+
85
+ The `auth` block on `EndpointConfig` (and its header-injection branch) is gone.
86
+ Authentication is supplied exclusively through an `AuthProvider`, passed to the
87
+ mount/`<App>` `authProvider` option (or `fd.api.configure(config, provider)`).
88
+ `StaticAuthProvider` covers the former static-token cases one-to-one:
89
+
90
+ ```js
91
+ // 1.x
92
+ createEndpointConfig('/api/flowdrop', {
93
+ auth: { type: 'bearer', token: TOKEN }
94
+ });
95
+
96
+ // 2.0
97
+ import { StaticAuthProvider } from '@flowdrop/flowdrop';
98
+ mountFlowDropApp(el, {
99
+ endpointConfig: createEndpointConfig('/api/flowdrop'),
100
+ authProvider: new StaticAuthProvider({ type: 'bearer', token: TOKEN })
101
+ });
102
+ ```
103
+
104
+ | 1.x `auth` | 2.0 `AuthProvider` |
105
+ | ----------------------------- | ----------------------------------------------------- |
106
+ | `{ type: 'none' }` | `new NoAuthProvider()` (or omit `authProvider`) |
107
+ | `{ type: 'bearer', token }` | `new StaticAuthProvider({ type: 'bearer', token })` |
108
+ | `{ type: 'api_key', apiKey }` | `new StaticAuthProvider({ type: 'api_key', apiKey })` |
109
+ | `{ type: 'custom', headers }` | `new StaticAuthProvider({ type: 'custom', headers })` |
110
+
111
+ ### Instance-scoped port compatibility
112
+
113
+ `initializePortCompatibility()`, `getPortCompatibilityChecker()`, and
114
+ `isPortCompatibilityInitialized()` are removed. Each instance owns a
115
+ `PortCompatibilityChecker` at `fd.portCompatibility`, seeded with
116
+ `DEFAULT_PORT_CONFIG` and re-initialized by mount from the backend's port
117
+ config. The standalone connection helpers (`validateConnection`,
118
+ `getPossibleConnections`, `getConnectionSuggestions`) now take the checker as
119
+ their first argument.
120
+
121
+ ```js
122
+ // 1.x
123
+ import { initializePortCompatibility, validateConnection } from '@flowdrop/flowdrop/editor';
124
+ initializePortCompatibility(portConfig);
125
+ const ok = validateConnection(source, target);
126
+
127
+ // 2.0
128
+ import { getInstance } from '@flowdrop/flowdrop/editor';
129
+ const fd = getInstance();
130
+ const ok = validateConnection(fd.portCompatibility, source, target);
131
+ ```
132
+
133
+ ## 3. Registries are instance-scoped — importing the editor registers nothing
134
+
135
+ In 1.x the node, field, and format registries were module singletons, and the
136
+ editor barrel ran a side-effecting import that registered every builtin node the
137
+ moment you imported it. In 2.0 each registry lives on the instance —
138
+ `fd.nodes`, `fd.fields`, `fd.formats` — seeded in the constructor from read-only
139
+ builtin definitions. There is no longer any import-time registration, and
140
+ `package.json` `sideEffects` is now CSS-only (`["**/*.css"]`).
141
+
142
+ The module-level registration functions and the singleton registry constants are
143
+ removed:
144
+
145
+ - `registerCustomNode()`, `createFlowDropPlugin()` / `registerFlowDropPlugin()`,
146
+ and `plugin.ts` are gone. Registration is now a registry method:
147
+ `fd.nodes.registerCustom(...)`, `fd.nodes.registerPlugin(...)`,
148
+ `fd.nodes.unregisterPlugin(...)`. `createPlugin().register(fd.nodes)` replaces
149
+ the module plugin functions.
150
+ - The exported singleton consts `nodeComponentRegistry`, `fieldComponentRegistry`,
151
+ and `workflowFormatRegistry` are removed. Resolve the instance registry instead.
152
+
153
+ ```js
154
+ // 1.x — module singletons + import-time side effects
155
+ import { registerCustomNode, fieldComponentRegistry } from '@flowdrop/flowdrop/editor';
156
+ registerCustomNode('myapp:color', 'Color Node', ColorNode);
157
+ fieldComponentRegistry.register('color', {
158
+ component: MyColorField,
159
+ matcher: (schema) => schema.format === 'color'
160
+ });
161
+
162
+ // 2.0 — register against the instance after mount
163
+ import { getInstance } from '@flowdrop/flowdrop/editor';
164
+ const fd = getInstance();
165
+ fd.nodes.registerCustom('myapp:color', 'Color Node', ColorNode);
166
+ fd.fields.register('color', {
167
+ component: MyColorField,
168
+ matcher: (schema) => schema.format === 'color'
169
+ });
170
+ ```
171
+
172
+ Because registration is now post-mount by construction, late registrations have
173
+ to invalidate `$derived` reads that already ran. `BaseRegistry` carries a
174
+ `$state` version counter (the `editVersion` pattern) so dependent reads
175
+ re-run when you register after the first paint — no host action required.
176
+
177
+ The heavy form-field installers (`registerCodeEditorField`,
178
+ `registerMarkdownEditorField`, and the template field) now take the **target
179
+ registry explicitly** and re-check registration after their dynamic import
180
+ resolves:
181
+
182
+ ```js
183
+ // 1.x
184
+ import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code';
185
+ registerCodeEditorField();
186
+
187
+ // 2.0
188
+ import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code';
189
+ import { getInstance } from '@flowdrop/flowdrop/editor';
190
+ registerCodeEditorField(getInstance().fields);
191
+ ```
192
+
193
+ Category color/icon helpers likewise take a `CategoriesStore` as an explicit
194
+ parameter — the last global-instance fallback in `utils` is gone.
195
+
196
+ `fd.fields.register()` warns in dev when it overwrites an existing field type.
197
+ Overwriting still works (replacing a built-in field is legitimate); the warning
198
+ flags accidental duplicates.
199
+
200
+ ## 4. Barrel de-duplication and the slim main entry
201
+
202
+ ### Each export keeps a single canonical home
203
+
204
+ The editor barrel no longer re-exports playground internals, and the display
205
+ barrel no longer re-exports `marked`.
206
+
207
+ - **Playground exports** (`Playground`, `PlaygroundModal`, `ChatPanel`,
208
+ `SessionManager`, `InputCollector`, `ExecutionLogs`, `MessageBubble`,
209
+ `PlaygroundService`, `playgroundService`, `PlaygroundStore`) are removed from
210
+ `@flowdrop/flowdrop/editor`. Import them from `@flowdrop/flowdrop/playground`
211
+ instead.
212
+
213
+ ```js
214
+ // 1.x
215
+ import { Playground, playgroundService } from '@flowdrop/flowdrop/editor';
216
+
217
+ // 2.0
218
+ import { Playground, playgroundService } from '@flowdrop/flowdrop/playground';
219
+ ```
220
+
221
+ - **`marked`** is no longer re-exported from `@flowdrop/flowdrop/display`. If you
222
+ need `marked` directly, install it as a dependency and import it from the
223
+ package:
224
+
225
+ ```js
226
+ // 1.x
227
+ import { marked } from '@flowdrop/flowdrop/display';
228
+
229
+ // 2.0 — `npm install marked`
230
+ import { marked } from 'marked';
231
+ ```
232
+
233
+ ### The main entry is now a minimal front door
234
+
235
+ `@flowdrop/flowdrop` (the main entry) no longer re-exports the entire library.
236
+ In 1.x it bundled every sub-module via `export *`; in 2.0 it exposes only the
237
+ small surface most apps need to bootstrap:
238
+
239
+ - **Values:** `App`, `mountFlowDropApp`, `unmountFlowDropApp`,
240
+ `createFlowDropInstance`, `getInstance`, `provideInstance`,
241
+ `createEndpointConfig`, `defaultEndpointConfig`, `NoAuthProvider`,
242
+ `StaticAuthProvider`, `CallbackAuthProvider`.
243
+ - **Types:** `Workflow`, `WorkflowNode`, `WorkflowEdge`, `NodeMetadata`,
244
+ `ConfigSchema`, `EndpointConfig`, `AuthProvider`, `FlowDropInstance`,
245
+ `FlowDropMountOptions`, `MountedFlowDropApp`, `FlowDropEventHandlers`,
246
+ `Messages`, `MessagesOverride`.
247
+
248
+ Everything else moves to a sub-module. If you imported a name from
249
+ `@flowdrop/flowdrop` that is not in the list above, switch to the sub-module
250
+ that owns it:
251
+
252
+ | Name (1.x main entry) | 2.0 sub-module |
253
+ | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
254
+ | `WorkflowEditor`, `ConfigForm`, `ConfigModal`, `ConfigPanel`, `Navbar`, `NodeSidebar`, node components | `@flowdrop/flowdrop/editor` |
255
+ | `mountWorkflowEditor`, editor helper classes, `EnhancedFlowDropApiClient`, `ApiContext` | `@flowdrop/flowdrop/editor` |
256
+ | `WorkflowStore`, `HistoryStore`, `HistoryService`, `PortCoordinateStore` | `@flowdrop/flowdrop/editor` |
257
+ | `globalSaveWorkflow`, `globalExportWorkflow`, `saveWorkflow`, `getWorkflow`, draft-storage helpers | `@flowdrop/flowdrop/editor` |
258
+ | `fetchPortConfig`, `fetchCategories`, dynamic-schema helpers | `@flowdrop/flowdrop/editor` |
259
+ | `NodeExecutionService`, connection utilities, `PortCompatibilityChecker` | `@flowdrop/flowdrop/editor` |
260
+ | Toast functions (`showSuccess`, `showError`, `showWarning`, `showInfo`, `showLoading`, `dismissToast`, `showPromise`, `showConfirmation`, …) | `@flowdrop/flowdrop/editor` |
261
+ | `SchemaForm`, `FormField`, `FormSelect`, `FormToggle`, `FormArray`, …, `AutocompleteConfig` | `@flowdrop/flowdrop/form` |
262
+ | `FormAutocomplete` | `@flowdrop/flowdrop/form/autocomplete` |
263
+ | `registerCodeEditorField` | `@flowdrop/flowdrop/form/code` |
264
+ | `registerMarkdownEditorField` | `@flowdrop/flowdrop/form/markdown` |
265
+ | `Playground`, `PlaygroundModal`, `ChatPanel`, `mountPlayground`, `PlaygroundService` | `@flowdrop/flowdrop/playground` |
266
+ | `MarkdownDisplay` | `@flowdrop/flowdrop/display` |
267
+ | `setMessages`, `mergeMessages`, `defaultMessages` | `@flowdrop/flowdrop/core` |
268
+ | Theme/skin exports (`defaultTheme`, `minimalTheme`, `resolveTheme`, `defaultSkin`, `slateSkin`) | `@flowdrop/flowdrop/core` |
269
+ | Color-preference helpers (`theme`, `resolvedTheme`, `setTheme`, `toggleTheme`, …) | `@flowdrop/flowdrop/core` |
270
+ | `WorkflowAdapter`, `AgentSpecAdapter`, command DSL, color/icon utilities, all remaining types | `@flowdrop/flowdrop/core` |
271
+ | Settings stores/services/components | `@flowdrop/flowdrop/settings` |
272
+
273
+ ```js
274
+ // 1.x — everything from the main entry
275
+ import { WorkflowEditor, SchemaForm, showSuccess, defaultTheme } from '@flowdrop/flowdrop';
276
+
277
+ // 2.0 — import from the owning sub-module
278
+ import { WorkflowEditor, showSuccess } from '@flowdrop/flowdrop/editor';
279
+ import { SchemaForm } from '@flowdrop/flowdrop/form';
280
+ import { defaultTheme } from '@flowdrop/flowdrop/core';
281
+ ```
282
+
283
+ This also tightens tree-shaking: importing `App` and a couple of types from the
284
+ main entry no longer pulls the form, display, playground, and settings barrels
285
+ into your bundle.
286
+
287
+ ## 5. Workflow `metadata` is required and `version` → `schemaVersion`
288
+
289
+ The workflow document's `metadata` object is now **required** on the `Workflow`
290
+ type, and its `version` field has been renamed to `schemaVersion`. The rename
291
+ disambiguates the document's _format_ version from any per-workflow revision
292
+ number you may track yourself (and from `NodeMetadata.version`, the node-type
293
+ version, which is **unchanged**).
294
+
295
+ ```ts
296
+ // 1.x
297
+ interface Workflow {
298
+ /* … */
299
+ metadata?: {
300
+ version: string; // ambiguous
301
+ createdAt: string;
302
+ updatedAt: string;
303
+ /* … */
304
+ };
305
+ }
306
+
307
+ // 2.0
308
+ interface Workflow {
309
+ /* … */
310
+ metadata: {
311
+ schemaVersion: string; // the workflow schema format version
312
+ createdAt: string;
313
+ updatedAt: string;
314
+ /* … */
315
+ };
316
+ }
317
+ ```
318
+
319
+ ### Load-time healing (automatic)
320
+
321
+ You do **not** need to migrate stored workflow JSON by hand. Every workflow
322
+ entry point — `WorkflowStore.initialize` (which backs `mountFlowDropApp`'s
323
+ `workflow` option, drag-and-drop file import, and draft load) and
324
+ `WorkflowAdapter.importWorkflow` — normalizes metadata on the way in:
325
+
326
+ - **Missing `metadata`** → populated with required defaults (`schemaVersion`
327
+ from `WORKFLOW_SCHEMA_VERSION`, fresh `createdAt`/`updatedAt`).
328
+ - **Legacy `metadata.version`** → copied into `schemaVersion` (when
329
+ `schemaVersion` is absent), then the legacy `version` key is dropped.
330
+
331
+ Healing is idempotent: re-running it on an already-healed workflow is a no-op
332
+ (round-trip stable). This mirrors the localStorage key migration in §8 — the
333
+ runtime heals 1.x data on first read so existing documents keep loading.
334
+
335
+ ### What hosts reading workflow JSON need to know
336
+
337
+ If your application reads or writes FlowDrop workflow JSON directly (outside the
338
+ editor), update your code to read `metadata.schemaVersion` instead of
339
+ `metadata.version`. Documents still on disk with the old `version` key continue
340
+ to load through the editor unchanged, but newly serialized workflows will carry
341
+ `schemaVersion`. The Agent Spec export still uses the namespaced
342
+ `flowdrop:version` key (its source is now `metadata.schemaVersion`); that
343
+ external key name is unchanged.
344
+
345
+ The JSON Schema published at `@flowdrop/flowdrop/schema` reflects the rename —
346
+ `WorkflowMetadata.required` is now `[schemaVersion, createdAt, updatedAt]`.
347
+
348
+ ## 6. Removed component props
349
+
350
+ | Component | Removed | Use instead |
351
+ | ------------------------ | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
352
+ | `SchemaForm` | `saveLabel`, `cancelLabel` | `messages.form.schema.save` / `.cancel` |
353
+ | `AIChatPanel` | `placeholder` | `messages.chat.placeholder` |
354
+ | `ChatPanel` | `showChatInput`, `showRunButton` | `MessageStream` directly, or `ControlPanel` (keeps both flags) |
355
+ | `ChatPanel` | `showLogs` | `fd.playground.setShowLogs(...)` |
356
+ | `WorkflowEditor` | `nodes`, `height`, `width`, `isConfigSidebarOpen`, `selectedNodeForConfig`, `closeConfigSidebar` | These never did anything in 1.x. Size via `App`'s `height`/`width` (working since 1.16); node metadata flows through the instance. |
357
+ | `App` / `WorkflowEditor` | `readOnly`, `lockWorkflow` | A single `mode` prop — see [section 6.2](#62-mode-prop-replaces-readonly--lockworkflow). |
358
+ | `App` | `eventHandlers` (object) | Flat `on*` props — see [section 6.3](#63-app-event-handlers-are-flat-props). |
359
+
360
+ `FormToggle.onLabel`/`offLabel` and `FormArray.addLabel` were _un_-deprecated:
361
+ they express per-instance labels the global messages system cannot, and are
362
+ now documented overrides.
363
+
364
+ Removed message keys (only the removed ChatPanel branches read them):
365
+ `playground.states.viewOnlyTitle`, `.viewOnlyText`, `.readyTitle`, `.readyText`.
366
+
367
+ ### 6.1 `mountWorkflowEditor` option changes
368
+
369
+ - `workflow` now actually loads the workflow (1.x accepted and ignored it).
370
+ - `nodes` is removed (it fed a prop the editor never read). Use
371
+ `mountFlowDropApp` if you need to pre-seed node metadata.
372
+ - `readOnly` / `lockWorkflow` mount options become a single `mode` option
373
+ (`'edit' | 'readonly' | 'locked'`) — see
374
+ [section 6.2](#62-mode-prop-replaces-readonly--lockworkflow). The grouped
375
+ `eventHandlers` mount option is **unchanged** (an options bag is fine in a JS
376
+ mount API); only the `<App>` _component_ prop is flattened.
377
+
378
+ ### 6.2 `mode` prop replaces `readOnly` + `lockWorkflow`
379
+
380
+ `<App>`, `<WorkflowEditor>`, and the `mountFlowDropApp` options bag no longer
381
+ take the `readOnly` and `lockWorkflow` booleans. They are replaced by a single
382
+ `mode` prop/option:
383
+
384
+ ```ts
385
+ mode?: 'edit' | 'readonly' | 'locked'; // default: 'edit'
386
+ ```
387
+
388
+ **Behavior matrix** (what each mode gates):
389
+
390
+ | mode | node drag / connect / select | proximity-connect | node swap | bottom console panel + toggle |
391
+ | ------------ | ---------------------------- | ----------------- | --------- | ----------------------------- |
392
+ | `'edit'` | enabled | enabled | enabled | available |
393
+ | `'readonly'` | disabled | disabled | disabled | hidden |
394
+ | `'locked'` | disabled | disabled | disabled | hidden |
395
+
396
+ In 1.x, `readOnly` and `lockWorkflow` gated the **exact same** interactions and
397
+ were always combined as `!readOnly && !lockWorkflow`. Any combination of the two
398
+ booleans therefore collapsed to either "edit" (both `false`) or "fully disabled"
399
+ (either `true`) — there was no orthogonal behavior to lose. `'readonly'` and
400
+ `'locked'` behave identically today; the two names are preserved as distinct
401
+ intents so a future release can differentiate them without another breaking
402
+ change.
403
+
404
+ **Old → new mapping** (component prop and mount option are identical):
405
+
406
+ | 1.x | 2.0 |
407
+ | ---------------------------------------------------------- | ------------------------------------------------------ |
408
+ | `readOnly` unset / `false`, `lockWorkflow` unset / `false` | `mode="edit"` (or omit) |
409
+ | `readOnly={true}` | `mode="readonly"` |
410
+ | `lockWorkflow={true}` | `mode="locked"` |
411
+ | both `true` | `mode="readonly"` _or_ `mode="locked"` (same behavior) |
412
+
413
+ ```svelte
414
+ <!-- 1.x -->
415
+ <App readOnly={true} />
416
+ <App lockWorkflow={true} />
417
+
418
+ <!-- 2.0 -->
419
+ <App mode="readonly" />
420
+ <App mode="locked" />
421
+ ```
422
+
423
+ ```js
424
+ // 1.x
425
+ mountFlowDropApp(el, { readOnly: true });
426
+ // 2.0
427
+ mountFlowDropApp(el, { mode: 'readonly' });
428
+ ```
429
+
430
+ ### 6.3 `<App>` event handlers are flat props
431
+
432
+ The `<App>` component no longer takes a grouped `eventHandlers={{ … }}` object.
433
+ The handlers `<App>` consumes are now individual `on*` props, consistent with
434
+ every other component:
435
+
436
+ ```svelte
437
+ <!-- 1.x -->
438
+ <App eventHandlers={{ onApiError, onAfterSave, onWorkflowLoad, onBeforeSwap }} />
439
+
440
+ <!-- 2.0 -->
441
+ <App {onApiError} {onAfterSave} {onWorkflowLoad} {onBeforeSwap} />
442
+ ```
443
+
444
+ Available `<App>` callback props: `onBeforeSave`, `onAfterSave`, `onSaveError`,
445
+ `onApiError`, `onWorkflowLoad`, `onBeforeSwap`, `onAfterSwap`.
446
+
447
+ The **`mountFlowDropApp` / `mountPlayground` options bag is unchanged** — keep
448
+ passing the grouped `eventHandlers` object there. The mount functions wire
449
+ `onDirtyStateChange` / `onWorkflowChange` into the instance store, call
450
+ `onBeforeUnmount` on teardown, and forward the remaining handlers to `<App>`'s
451
+ flat props for you. The `FlowDropEventHandlers` type is still exported for use
452
+ with the mount option.
453
+
454
+ ## 7. localStorage keys are instance-scoped
455
+
456
+ The page-default instance no longer writes bare keys:
457
+
458
+ | 1.x | 2.0 |
459
+ | ----------------------------- | ------------------------------------- |
460
+ | `flowdrop:draft:<workflowId>` | `flowdrop:draft:default:<workflowId>` |
461
+ | `fd-pipeline-panel-open` | `fd-pipeline-panel-open:default` |
462
+
463
+ Existing user data migrates automatically on first read (copy to the scoped
464
+ key, remove the legacy key). Only hosts reading these keys directly need to
465
+ update. `clearAllDrafts()` still removes everything under `flowdrop:draft:`.
466
+
467
+ ## 8. Behavioral notes
468
+
469
+ - `fd.fields.register()` warns in dev when overwriting an existing field type.
470
+ Overwriting still works; the warning flags accidents.
471
+ - Internal `DEV` gates use `esm-env` instead of `import.meta.env`, so the
472
+ package no longer assumes a Vite host.
package/README.md CHANGED
@@ -50,7 +50,7 @@ No vendor lock-in. No data leaving your walls. No surprise bills.
50
50
  npm install @flowdrop/flowdrop
51
51
  ```
52
52
 
53
- > **Note:** FlowDrop supports **one editor instance per page** (module-level singleton stores). See [Architecture Notes](#architecture-notes) for details.
53
+ > **Note:** FlowDrop supports **multiple editor instances per page** each mount gets its own isolated state container. See [Architecture Notes](#architecture-notes) for details.
54
54
 
55
55
  You get a production-ready workflow UI. You keep full control of everything else.
56
56
 
@@ -58,11 +58,11 @@ You get a production-ready workflow UI. You keep full control of everything else
58
58
 
59
59
  ```svelte
60
60
  <script lang="ts">
61
- import { WorkflowEditor } from '@flowdrop/flowdrop';
61
+ import { App } from '@flowdrop/flowdrop';
62
62
  import '@flowdrop/flowdrop/styles/base.css';
63
63
  </script>
64
64
 
65
- <WorkflowEditor />
65
+ <App />
66
66
  ```
67
67
 
68
68
  **5 lines. One fully-functional workflow editor.**
@@ -80,7 +80,7 @@ You get a production-ready workflow UI. You keep full control of everything else
80
80
 
81
81
  ## Architecture Notes
82
82
 
83
- - **Single instance per page.** FlowDrop uses module-level singleton stores for state management. Only one FlowDrop editor instance can exist on a page at a time.
83
+ - **Multiple instances per page.** Each mount gets its own `FlowDropInstance` state container (workflow, undo/redo history, playground sessions, registries, API context, drafts), so editors on the same page are fully isolated. In 2.0 there are no module-level store APIs resolve state with `getInstance()` inside the component tree or the mount handle's `.instance` outside it. The first mount without an `instanceId` becomes the page-default instance; pass `instanceId` to additional mounts to scope their draft/panel storage keys. Theme and settings remain page-global by design.
84
84
  - **Svelte 5 required.** FlowDrop uses Svelte 5 runes (`$state`, `$derived`, `$effect`) throughout. Svelte 4 is not supported.
85
85
  - **Modern browsers only.** The library targets ES2020+ and does not include polyfills for older browsers.
86
86
 
@@ -112,12 +112,12 @@ FlowDrop includes a theme system with built-in light/dark support:
112
112
 
113
113
  ```svelte
114
114
  <script lang="ts">
115
- import { WorkflowEditor } from '@flowdrop/flowdrop';
115
+ import { App } from '@flowdrop/flowdrop';
116
116
  import '@flowdrop/flowdrop/styles';
117
117
  </script>
118
118
 
119
119
  <!-- Built-in themes: 'default' or 'minimal' -->
120
- <WorkflowEditor theme="minimal" />
120
+ <App theme="minimal" />
121
121
  ```
122
122
 
123
123
  Themes bundle a visual skin (CSS token palette) with behavioral UI defaults. You can also pass a custom theme object with your own skin tokens for full control over the light and dark palettes.
@@ -136,7 +136,7 @@ const app = await mountFlowDropApp(container, {
136
136
  Every user-facing string flows through a typed `Messages` tree. Pass a callback to override any subset:
137
137
 
138
138
  ```svelte
139
- <FlowDrop messages={() => ({ form: { schema: { save: 'Apply' } } })} />
139
+ <App messages={() => ({ form: { schema: { save: 'Apply' } } })} />
140
140
  ```
141
141
 
142
142
  Wire the callback to your i18n library (paraglide-js, sveltekit-i18n, etc.) — locale changes propagate automatically. See the [i18n & Custom Messages guide](https://docs.flowdrop.io/guides/i18n) for the full shape and a paraglide-js worked example.
@@ -145,20 +145,20 @@ Wire the callback to your i18n library (paraglide-js, sveltekit-i18n, etc.) —
145
145
 
146
146
  FlowDrop provides tree-shakeable sub-module exports so you can import only what you need:
147
147
 
148
- | Export Path | Contents |
149
- | ---------------------------------- | -------------------------------------------------- |
150
- | `@flowdrop/flowdrop` | Full library (components, stores, services, types) |
151
- | `@flowdrop/flowdrop/core` | Types and utilities only (no heavy dependencies) |
152
- | `@flowdrop/flowdrop/editor` | WorkflowEditor, stores, services |
153
- | `@flowdrop/flowdrop/form` | SchemaForm, form fields, registry |
154
- | `@flowdrop/flowdrop/form/code` | Code editor field (CodeMirror) |
155
- | `@flowdrop/flowdrop/form/markdown` | Markdown editor field |
156
- | `@flowdrop/flowdrop/display` | MarkdownDisplay component |
157
- | `@flowdrop/flowdrop/playground` | Playground components and services |
158
- | `@flowdrop/flowdrop/settings` | SettingsPanel, stores, services |
159
- | `@flowdrop/flowdrop/styles` | Base CSS stylesheet |
160
- | `@flowdrop/flowdrop/schema` | Workflow JSON schema |
161
- | `@flowdrop/flowdrop/openapi` | OpenAPI spec (YAML) for the FlowDrop backend API |
148
+ | Export Path | Contents |
149
+ | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
150
+ | `@flowdrop/flowdrop` | Slim front door: `App`, mount functions, `createFlowDropInstance`, `getInstance`, auth providers, core bootstrap types |
151
+ | `@flowdrop/flowdrop/core` | Types and utilities only (no heavy dependencies) |
152
+ | `@flowdrop/flowdrop/editor` | WorkflowEditor, stores, services |
153
+ | `@flowdrop/flowdrop/form` | SchemaForm, form fields, registry |
154
+ | `@flowdrop/flowdrop/form/code` | Code editor field (CodeMirror) |
155
+ | `@flowdrop/flowdrop/form/markdown` | Markdown editor field |
156
+ | `@flowdrop/flowdrop/display` | MarkdownDisplay component |
157
+ | `@flowdrop/flowdrop/playground` | Playground components and services |
158
+ | `@flowdrop/flowdrop/settings` | SettingsPanel, stores, services |
159
+ | `@flowdrop/flowdrop/styles` | Base CSS stylesheet |
160
+ | `@flowdrop/flowdrop/schema` | Workflow JSON schema |
161
+ | `@flowdrop/flowdrop/openapi` | OpenAPI spec (YAML) for the FlowDrop backend API |
162
162
 
163
163
  ### OpenAPI spec
164
164
 
@@ -170,12 +170,12 @@ The full OpenAPI spec for the FlowDrop backend API ships with the package, versi
170
170
 
171
171
  ```svelte
172
172
  <script>
173
- import { WorkflowEditor, NodeSidebar } from '@flowdrop/flowdrop';
173
+ import { WorkflowEditor, NodeSidebar } from '@flowdrop/flowdrop/editor';
174
174
  </script>
175
175
 
176
176
  <div class="flex h-screen">
177
177
  <NodeSidebar {nodes} />
178
- <WorkflowEditor {nodes} />
178
+ <WorkflowEditor />
179
179
  </div>
180
180
  ```
181
181
 
@@ -50,7 +50,7 @@ export interface StandardWorkflow {
50
50
  nodes: StandardNode[];
51
51
  edges: StandardEdge[];
52
52
  metadata?: {
53
- version: string;
53
+ schemaVersion: string;
54
54
  createdAt: string;
55
55
  updatedAt: string;
56
56
  author?: string;
@@ -13,6 +13,7 @@
13
13
  * - External applications that want to integrate with FlowDrop
14
14
  * - Systems that need to generate or modify workflows programmatically
15
15
  */
16
+ import { WORKFLOW_SCHEMA_VERSION } from '../schemas/index.js';
16
17
  import { v4 as uuidv4 } from 'uuid';
17
18
  import { generateNodeId } from '../utils/nodeIds.js';
18
19
  /**
@@ -35,7 +36,7 @@ export class WorkflowAdapter {
35
36
  nodes: [],
36
37
  edges: [],
37
38
  metadata: {
38
- version: '1.0.0',
39
+ schemaVersion: '1.0.0',
39
40
  createdAt: new Date().toISOString(),
40
41
  updatedAt: new Date().toISOString()
41
42
  }
@@ -222,13 +223,14 @@ export class WorkflowAdapter {
222
223
  if (!validation.valid) {
223
224
  throw new Error(`Invalid workflow: ${validation.errors.join(', ')}`);
224
225
  }
225
- // Update metadata
226
+ // Update metadata — heal legacy 1.x `version` key into `schemaVersion`.
227
+ const incoming = workflow.metadata;
226
228
  workflow.metadata = {
227
- version: workflow.metadata?.version || '1.0.0',
228
- createdAt: workflow.metadata?.createdAt || new Date().toISOString(),
229
+ schemaVersion: incoming?.schemaVersion || incoming?.version || '1.0.0',
230
+ createdAt: incoming?.createdAt || new Date().toISOString(),
229
231
  updatedAt: new Date().toISOString(),
230
- author: workflow.metadata?.author,
231
- tags: workflow.metadata?.tags
232
+ author: incoming?.author,
233
+ tags: incoming?.tags
232
234
  };
233
235
  return workflow;
234
236
  }
@@ -291,7 +293,11 @@ export class WorkflowAdapter {
291
293
  sourceHandle: edge.sourceHandle,
292
294
  targetHandle: edge.targetHandle
293
295
  })),
294
- metadata: workflow.metadata
296
+ metadata: workflow.metadata ?? {
297
+ schemaVersion: WORKFLOW_SCHEMA_VERSION,
298
+ createdAt: new Date().toISOString(),
299
+ updatedAt: new Date().toISOString()
300
+ }
295
301
  };
296
302
  }
297
303
  /**
@@ -337,7 +343,7 @@ export class WorkflowAdapter {
337
343
  cloned.id = uuidv4();
338
344
  cloned.name = newName || `${workflow.name} (Copy)`;
339
345
  cloned.metadata = {
340
- version: cloned.metadata?.version || '1.0.0',
346
+ schemaVersion: cloned.metadata?.schemaVersion || '1.0.0',
341
347
  createdAt: new Date().toISOString(),
342
348
  updatedAt: new Date().toISOString(),
343
349
  author: cloned.metadata?.author,