@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
@@ -0,0 +1,629 @@
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
+ These services also accept the instance's `AuthProvider` as an **optional
84
+ trailing argument** so every request they make is authenticated consistently
85
+ with `fd.api.client` (the typed workflow/node API). The built-in components and
86
+ mount helpers pass `fd.api.authProvider` for you — no action is needed for the
87
+ normal mounted flow. Only direct callers of the service singletons need to
88
+ forward it:
89
+
90
+ ```js
91
+ import { playgroundService } from '@flowdrop/flowdrop/playground';
92
+
93
+ // 2.0 — authenticate playground requests by forwarding the provider
94
+ await playgroundService.listSessions(fd.api.config, workflowId, undefined, fd.api.authProvider);
95
+ await playgroundService.sendMessage(fd.api.config, sessionId, text, undefined, fd.api.authProvider);
96
+ ```
97
+
98
+ The settings-sync entry points gained the same optional provider:
99
+ `setSettingsEndpointConfig(config, authProvider?)` and
100
+ `createSettingsService(config, authProvider?)` — pass an `AuthProvider` if your
101
+ backend's preferences endpoint requires auth.
102
+
103
+ The standalone playground mounts — `mountPlayground`, `mountPlaygroundStudio`,
104
+ and `mountPlaygroundApp` — accept an `authProvider` option that they wire into
105
+ `fd.api` for you (the editor's built-in playground already inherits the
106
+ provider from `mountFlowDropApp`). Pass it so playground requests (sessions,
107
+ messages, polling, interrupts) carry your auth/CSRF headers:
108
+
109
+ ```js
110
+ mountPlayground(el, {
111
+ workflowId,
112
+ endpointConfig: createEndpointConfig('/api/flowdrop'),
113
+ authProvider: new CallbackAuthProvider({ getToken: () => session.getCsrfToken() })
114
+ });
115
+ ```
116
+
117
+ The same plumbing was extended to the editor and pipeline surfaces, which
118
+ previously built unauthenticated API clients from `endpointConfig` alone:
119
+
120
+ - The exported `<WorkflowEditor>` component accepts an `authProvider` prop
121
+ (threaded for you by `mountFlowDropApp` / `mountWorkflowEditor` / `<App>`).
122
+ Pass it when using `<WorkflowEditor>` directly.
123
+ - `<PipelineStatus>` accepts an `authProvider` prop (used when it builds its own
124
+ client from `endpointConfig` / `baseUrl`; ignored when you pass `apiClient`).
125
+ - `PipelineViewProps` — the contract for custom pipeline views registered via
126
+ `pipelineViews` — gained an optional `authProvider`, so custom views can build
127
+ authenticated clients the same way the built-in graph/kanban/table views do.
128
+
129
+ ### `EndpointConfig.auth` is removed — use an `AuthProvider`
130
+
131
+ The `auth` block on `EndpointConfig` (and its header-injection branch) is gone.
132
+ Authentication is supplied exclusively through an `AuthProvider`, passed to the
133
+ mount/`<App>` `authProvider` option (or `fd.api.configure(config, provider)`).
134
+ `StaticAuthProvider` covers the former static-token cases one-to-one:
135
+
136
+ ```js
137
+ // 1.x
138
+ createEndpointConfig('/api/flowdrop', {
139
+ auth: { type: 'bearer', token: TOKEN }
140
+ });
141
+
142
+ // 2.0
143
+ import { StaticAuthProvider } from '@flowdrop/flowdrop';
144
+ mountFlowDropApp(el, {
145
+ endpointConfig: createEndpointConfig('/api/flowdrop'),
146
+ authProvider: new StaticAuthProvider({ type: 'bearer', token: TOKEN })
147
+ });
148
+ ```
149
+
150
+ | 1.x `auth` | 2.0 `AuthProvider` |
151
+ | ----------------------------- | ----------------------------------------------------- |
152
+ | `{ type: 'none' }` | `new NoAuthProvider()` (or omit `authProvider`) |
153
+ | `{ type: 'bearer', token }` | `new StaticAuthProvider({ type: 'bearer', token })` |
154
+ | `{ type: 'api_key', apiKey }` | `new StaticAuthProvider({ type: 'api_key', apiKey })` |
155
+ | `{ type: 'custom', headers }` | `new StaticAuthProvider({ type: 'custom', headers })` |
156
+
157
+ `StaticAuthProvider`'s `api_key` type now accepts an optional `apiKeyHeader` to
158
+ override the header name (defaults to `X-API-Key`):
159
+
160
+ ```js
161
+ new StaticAuthProvider({ type: 'api_key', apiKey: KEY, apiKeyHeader: 'X-Tenant-Key' });
162
+ ```
163
+
164
+ ### `AuthProvider.isAuthenticated()` is removed
165
+
166
+ The `isAuthenticated()` method has been dropped from the `AuthProvider`
167
+ interface and all built-in providers. It was never consulted by the library —
168
+ request authentication is driven entirely by `getAuthHeaders()` and the optional
169
+ `onUnauthorized()` / `onForbidden()` hooks. If you implemented a **custom**
170
+ `AuthProvider`, you can delete the method; no replacement is needed.
171
+
172
+ ```ts
173
+ // 1.x — required
174
+ const provider: AuthProvider = {
175
+ getAuthHeaders: async () => ({ Authorization: `Bearer ${token}` }),
176
+ isAuthenticated: () => Boolean(token) // ← remove this
177
+ };
178
+
179
+ // 2.0
180
+ const provider: AuthProvider = {
181
+ getAuthHeaders: async () => ({ Authorization: `Bearer ${token}` })
182
+ };
183
+ ```
184
+
185
+ ### Auth refresh (`401`) now applies to every request
186
+
187
+ Previously only the typed workflow/node API (`fd.api.client`) refreshed and
188
+ retried on `401`. The per-instance services (playground, chat, interrupt,
189
+ settings, port config, categories) and form autocomplete attached auth headers
190
+ but did **not** invoke `onUnauthorized()`. They now all route through one
191
+ authenticated-fetch path, so a configured `onUnauthorized()` fires — and the
192
+ request retries once with a refreshed token — uniformly across the library.
193
+
194
+ This is not a source change for consumers, but if your `onUnauthorized()` had
195
+ side effects (analytics, redirects) it may now be called from request paths
196
+ where it previously was not. Make it idempotent.
197
+
198
+ ### Swap the auth provider at runtime — `fd.api.setAuthProvider()`
199
+
200
+ The `AuthProvider` is still supplied at mount time, but you no longer have to
201
+ remount to change it (e.g. on login/logout). `ApiContext` gained
202
+ `setAuthProvider()`, which updates the live client and is picked up by services
203
+ on their next request:
204
+
205
+ ```js
206
+ import { getInstance } from '@flowdrop/flowdrop/editor';
207
+ const fd = getInstance();
208
+
209
+ // after the user logs in / refreshes their session
210
+ fd.api.setAuthProvider(new StaticAuthProvider({ type: 'bearer', token: newToken }));
211
+
212
+ // on logout
213
+ fd.api.setAuthProvider(new NoAuthProvider());
214
+ ```
215
+
216
+ ### Instance-scoped port compatibility
217
+
218
+ `initializePortCompatibility()`, `getPortCompatibilityChecker()`, and
219
+ `isPortCompatibilityInitialized()` are removed. Each instance owns a
220
+ `PortCompatibilityChecker` at `fd.portCompatibility`, seeded with
221
+ `DEFAULT_PORT_CONFIG` and re-initialized by mount from the backend's port
222
+ config. The standalone connection helpers (`validateConnection`,
223
+ `getPossibleConnections`, `getConnectionSuggestions`) now take the checker as
224
+ their first argument.
225
+
226
+ ```js
227
+ // 1.x
228
+ import { initializePortCompatibility, validateConnection } from '@flowdrop/flowdrop/editor';
229
+ initializePortCompatibility(portConfig);
230
+ const ok = validateConnection(source, target);
231
+
232
+ // 2.0
233
+ import { getInstance } from '@flowdrop/flowdrop/editor';
234
+ const fd = getInstance();
235
+ const ok = validateConnection(fd.portCompatibility, source, target);
236
+ ```
237
+
238
+ ## 3. Registries are instance-scoped — importing the editor registers nothing
239
+
240
+ In 1.x the node, field, and format registries were module singletons, and the
241
+ editor barrel ran a side-effecting import that registered every builtin node the
242
+ moment you imported it. In 2.0 each registry lives on the instance —
243
+ `fd.nodes`, `fd.fields`, `fd.formats` — seeded in the constructor from read-only
244
+ builtin definitions. There is no longer any import-time registration, and
245
+ `package.json` `sideEffects` is now CSS-only (`["**/*.css"]`).
246
+
247
+ The module-level registration functions and the singleton registry constants are
248
+ removed:
249
+
250
+ - `registerCustomNode()`, `createFlowDropPlugin()` / `registerFlowDropPlugin()`,
251
+ and `plugin.ts` are gone. Registration is now a registry method:
252
+ `fd.nodes.registerCustom(...)`, `fd.nodes.registerPlugin(...)`,
253
+ `fd.nodes.unregisterPlugin(...)`. `createPlugin().register(fd.nodes)` replaces
254
+ the module plugin functions.
255
+ - The exported singleton consts `nodeComponentRegistry`, `fieldComponentRegistry`,
256
+ and `workflowFormatRegistry` are removed. Resolve the instance registry instead.
257
+
258
+ ```js
259
+ // 1.x — module singletons + import-time side effects
260
+ import { registerCustomNode, fieldComponentRegistry } from '@flowdrop/flowdrop/editor';
261
+ registerCustomNode('myapp:color', 'Color Node', ColorNode);
262
+ fieldComponentRegistry.register('color', {
263
+ component: MyColorField,
264
+ matcher: (schema) => schema.format === 'color'
265
+ });
266
+
267
+ // 2.0 — register against the instance after mount
268
+ import { getInstance } from '@flowdrop/flowdrop/editor';
269
+ const fd = getInstance();
270
+ fd.nodes.registerCustom('myapp:color', 'Color Node', ColorNode);
271
+ fd.fields.register('color', {
272
+ component: MyColorField,
273
+ matcher: (schema) => schema.format === 'color'
274
+ });
275
+ ```
276
+
277
+ Because registration is now post-mount by construction, late registrations have
278
+ to invalidate `$derived` reads that already ran. `BaseRegistry` carries a
279
+ `$state` version counter (the `editVersion` pattern) so dependent reads
280
+ re-run when you register after the first paint — no host action required.
281
+
282
+ The heavy form-field installers (`registerCodeEditorField`,
283
+ `registerMarkdownEditorField`, and the template field) now take the **target
284
+ registry explicitly** and re-check registration after their dynamic import
285
+ resolves:
286
+
287
+ ```js
288
+ // 1.x
289
+ import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code';
290
+ registerCodeEditorField();
291
+
292
+ // 2.0
293
+ import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code';
294
+ import { getInstance } from '@flowdrop/flowdrop/editor';
295
+ registerCodeEditorField(getInstance().fields);
296
+ ```
297
+
298
+ Category color/icon helpers likewise take a `CategoriesStore` as an explicit
299
+ parameter — the last global-instance fallback in `utils` is gone.
300
+
301
+ `fd.fields.register()` warns in dev when it overwrites an existing field type.
302
+ Overwriting still works (replacing a built-in field is legitimate); the warning
303
+ flags accidental duplicates.
304
+
305
+ ## 4. Barrel de-duplication and the slim main entry
306
+
307
+ ### Each export keeps a single canonical home
308
+
309
+ The editor barrel no longer re-exports playground internals, and the display
310
+ barrel no longer re-exports `marked`.
311
+
312
+ - **Playground exports** (`Playground`, `PlaygroundModal`, `ChatPanel`,
313
+ `SessionManager`, `InputCollector`, `ExecutionLogs`, `MessageBubble`,
314
+ `PlaygroundService`, `PlaygroundStore`) are removed from
315
+ `@flowdrop/flowdrop/editor`. Import them from `@flowdrop/flowdrop/playground`
316
+ instead.
317
+
318
+ ```js
319
+ // 1.x
320
+ import { Playground, PlaygroundStore } from '@flowdrop/flowdrop/editor';
321
+
322
+ // 2.0
323
+ import { Playground, PlaygroundStore } from '@flowdrop/flowdrop/playground';
324
+ ```
325
+
326
+ - **`marked`** is no longer re-exported from `@flowdrop/flowdrop/display`. If you
327
+ need `marked` directly, install it as a dependency and import it from the
328
+ package:
329
+
330
+ ```js
331
+ // 1.x
332
+ import { marked } from '@flowdrop/flowdrop/display';
333
+
334
+ // 2.0 — `npm install marked`
335
+ import { marked } from 'marked';
336
+ ```
337
+
338
+ ### The main entry is now a minimal front door
339
+
340
+ `@flowdrop/flowdrop` (the main entry) no longer re-exports the entire library.
341
+ In 1.x it bundled every sub-module via `export *`; in 2.0 it exposes only the
342
+ small surface most apps need to bootstrap:
343
+
344
+ - **Values:** `App`, `mountFlowDropApp`, `unmountFlowDropApp`,
345
+ `createFlowDropInstance`, `getInstance`, `provideInstance`,
346
+ `createEndpointConfig`, `defaultEndpointConfig`, `NoAuthProvider`,
347
+ `StaticAuthProvider`, `CallbackAuthProvider`.
348
+ - **Types:** `Workflow`, `WorkflowNode`, `WorkflowEdge`, `NodeMetadata`,
349
+ `ConfigSchema`, `EndpointConfig`, `AuthProvider`, `FlowDropInstance`,
350
+ `FlowDropMountOptions`, `MountedFlowDropApp`, `FlowDropEventHandlers`,
351
+ `Messages`, `MessagesOverride`.
352
+
353
+ Everything else moves to a sub-module. If you imported a name from
354
+ `@flowdrop/flowdrop` that is not in the list above, switch to the sub-module
355
+ that owns it:
356
+
357
+ | Name (1.x main entry) | 2.0 sub-module |
358
+ | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
359
+ | `WorkflowEditor`, `ConfigForm`, `ConfigModal`, `ConfigPanel`, `Navbar`, `NodeSidebar`, node components | `@flowdrop/flowdrop/editor` |
360
+ | `mountWorkflowEditor`, editor helper classes, `EnhancedFlowDropApiClient`, `ApiContext` | `@flowdrop/flowdrop/editor` |
361
+ | `WorkflowStore`, `HistoryStore`, `HistoryService`, `PortCoordinateStore` | `@flowdrop/flowdrop/editor` |
362
+ | `globalSaveWorkflow`, `globalExportWorkflow`, `saveWorkflow`, `getWorkflow`, draft-storage helpers | `@flowdrop/flowdrop/editor` |
363
+ | `fetchPortConfig`, `fetchCategories`, dynamic-schema helpers | `@flowdrop/flowdrop/editor` |
364
+ | `NodeExecutionService`, connection utilities, `PortCompatibilityChecker` | `@flowdrop/flowdrop/editor` |
365
+ | Toast functions (`showSuccess`, `showError`, `showWarning`, `showInfo`, `showLoading`, `dismissToast`, `showPromise`, `showConfirmation`, …) | `@flowdrop/flowdrop/editor` |
366
+ | `SchemaForm`, `FormField`, `FormSelect`, `FormToggle`, `FormArray`, …, `AutocompleteConfig` | `@flowdrop/flowdrop/form` |
367
+ | `FormAutocomplete` | `@flowdrop/flowdrop/form/autocomplete` |
368
+ | `registerCodeEditorField` | `@flowdrop/flowdrop/form/code` |
369
+ | `registerMarkdownEditorField` | `@flowdrop/flowdrop/form/markdown` |
370
+ | `Playground`, `PlaygroundModal`, `ChatPanel`, `mountPlayground`, `PlaygroundService` | `@flowdrop/flowdrop/playground` |
371
+ | `MarkdownDisplay` | `@flowdrop/flowdrop/display` |
372
+ | `setMessages`, `mergeMessages`, `defaultMessages` | `@flowdrop/flowdrop/core` |
373
+ | Theme/skin exports (`defaultTheme`, `minimalTheme`, `resolveTheme`, `defaultSkin`, `slateSkin`) | `@flowdrop/flowdrop/core` |
374
+ | Color-preference helpers (`theme`, `resolvedTheme`, `setTheme`, `toggleTheme`, …) | `@flowdrop/flowdrop/core` |
375
+ | `WorkflowAdapter`, `AgentSpecAdapter`, command DSL, color/icon utilities, all remaining types | `@flowdrop/flowdrop/core` |
376
+ | Settings stores/services/components | `@flowdrop/flowdrop/settings` |
377
+
378
+ ```js
379
+ // 1.x — everything from the main entry
380
+ import { WorkflowEditor, SchemaForm, showSuccess, defaultTheme } from '@flowdrop/flowdrop';
381
+
382
+ // 2.0 — import from the owning sub-module
383
+ import { WorkflowEditor, showSuccess } from '@flowdrop/flowdrop/editor';
384
+ import { SchemaForm } from '@flowdrop/flowdrop/form';
385
+ import { defaultTheme } from '@flowdrop/flowdrop/core';
386
+ ```
387
+
388
+ This also tightens tree-shaking: importing `App` and a couple of types from the
389
+ main entry no longer pulls the form, display, playground, and settings barrels
390
+ into your bundle.
391
+
392
+ ### Keeping heavy dependencies out of the light entries
393
+
394
+ A few more exports moved so that the lightweight entries (`/core`, the light
395
+ `/form`) never statically pull a heavy dependency (CodeMirror, `marked`,
396
+ DOMPurify, `@xyflow/svelte`). These are enforced by a bundle guard in CI, so
397
+ they cannot silently regress.
398
+
399
+ - **`sanitizeHtml` moved from `@flowdrop/flowdrop/core` to
400
+ `@flowdrop/flowdrop/display`.** It is DOMPurify-backed, and `/core` is the
401
+ "zero heavy dependencies" entry, so it now lives alongside `MarkdownDisplay`.
402
+
403
+ ```js
404
+ // before
405
+ import { sanitizeHtml } from '@flowdrop/flowdrop/core';
406
+ // 2.0
407
+ import { sanitizeHtml } from '@flowdrop/flowdrop/display';
408
+ ```
409
+
410
+ - **`FormFieldFull` moved from `@flowdrop/flowdrop/form` to
411
+ `@flowdrop/flowdrop/form/full`.** `FormFieldFull` statically bundles every
412
+ editor (including CodeMirror); keeping it in the light `/form` entry pulled
413
+ CodeMirror into every `SchemaForm` import. The default `FormField` exported
414
+ from `/form` is the registry-based light field factory — register heavy
415
+ editors via `/form/code` / `/form/markdown` (unchanged). Use `/form/full`
416
+ only if you specifically want every editor statically bundled.
417
+
418
+ ```js
419
+ // before
420
+ import { FormFieldFull } from '@flowdrop/flowdrop/form';
421
+ // 2.0
422
+ import { FormFieldFull } from '@flowdrop/flowdrop/form/full';
423
+ ```
424
+
425
+ - **Service singleton _instances_ are no longer exported.**
426
+ `playgroundService` and `interruptService` (`@flowdrop/flowdrop/playground`),
427
+ `nodeExecutionService` (`@flowdrop/flowdrop/editor`), and
428
+ `agentSpecExecutionService` (`@flowdrop/flowdrop/core`) are removed. They were
429
+ module-level instances constructed at import time, which forced the service
430
+ (and its dependencies) to be built the moment the entry was imported. The
431
+ **classes** remain exported (`PlaygroundService`, `InterruptService`,
432
+ `NodeExecutionService`, `AgentSpecExecutionService`). Most apps never touched
433
+ these directly (use `fd.playground` / `fd.interrupts`); if you did, call
434
+ `getInstance()` to obtain the shared instance:
435
+
436
+ ```js
437
+ // before
438
+ import { playgroundService } from '@flowdrop/flowdrop/playground';
439
+ // 2.0
440
+ import { PlaygroundService } from '@flowdrop/flowdrop/playground';
441
+ const playgroundService = PlaygroundService.getInstance();
442
+ ```
443
+
444
+ ## 5. Workflow `metadata` is required and `version` → `schemaVersion`
445
+
446
+ The workflow document's `metadata` object is now **required** on the `Workflow`
447
+ type, and its `version` field has been renamed to `schemaVersion`. The rename
448
+ disambiguates the document's _format_ version from any per-workflow revision
449
+ number you may track yourself (and from `NodeMetadata.version`, the node-type
450
+ version, which is **unchanged**).
451
+
452
+ ```ts
453
+ // 1.x
454
+ interface Workflow {
455
+ /* … */
456
+ metadata?: {
457
+ version: string; // ambiguous
458
+ createdAt: string;
459
+ updatedAt: string;
460
+ /* … */
461
+ };
462
+ }
463
+
464
+ // 2.0
465
+ interface Workflow {
466
+ /* … */
467
+ metadata: {
468
+ schemaVersion: string; // the workflow schema format version
469
+ createdAt: string;
470
+ updatedAt: string;
471
+ /* … */
472
+ };
473
+ }
474
+ ```
475
+
476
+ ### Load-time healing (automatic)
477
+
478
+ You do **not** need to migrate stored workflow JSON by hand. Every workflow
479
+ entry point — `WorkflowStore.initialize` (which backs `mountFlowDropApp`'s
480
+ `workflow` option, drag-and-drop file import, and draft load) and
481
+ `WorkflowAdapter.importWorkflow` — normalizes metadata on the way in:
482
+
483
+ - **Missing `metadata`** → populated with required defaults (`schemaVersion`
484
+ from `WORKFLOW_SCHEMA_VERSION`, fresh `createdAt`/`updatedAt`).
485
+ - **Legacy `metadata.version`** → copied into `schemaVersion` (when
486
+ `schemaVersion` is absent), then the legacy `version` key is dropped.
487
+
488
+ Healing is idempotent: re-running it on an already-healed workflow is a no-op
489
+ (round-trip stable). This mirrors the localStorage key migration in §8 — the
490
+ runtime heals 1.x data on first read so existing documents keep loading.
491
+
492
+ ### What hosts reading workflow JSON need to know
493
+
494
+ If your application reads or writes FlowDrop workflow JSON directly (outside the
495
+ editor), update your code to read `metadata.schemaVersion` instead of
496
+ `metadata.version`. Documents still on disk with the old `version` key continue
497
+ to load through the editor unchanged, but newly serialized workflows will carry
498
+ `schemaVersion`. The Agent Spec export still uses the namespaced
499
+ `flowdrop:version` key (its source is now `metadata.schemaVersion`); that
500
+ external key name is unchanged.
501
+
502
+ The JSON Schema published at `@flowdrop/flowdrop/schema` reflects the rename —
503
+ `WorkflowMetadata.required` is now `[schemaVersion, createdAt, updatedAt]`.
504
+
505
+ ## 6. Removed component props
506
+
507
+ | Component | Removed | Use instead |
508
+ | ------------------------ | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
509
+ | `SchemaForm` | `saveLabel`, `cancelLabel` | `messages.form.schema.save` / `.cancel` |
510
+ | `AIChatPanel` | `placeholder` | `messages.chat.placeholder` |
511
+ | `ChatPanel` | `showChatInput`, `showRunButton` | `MessageStream` directly, or `ControlPanel` (keeps both flags) |
512
+ | `ChatPanel` | `showLogs` | `fd.playground.setShowLogs(...)` |
513
+ | `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. |
514
+ | `App` / `WorkflowEditor` | `readOnly`, `lockWorkflow` | A single `mode` prop — see [section 6.2](#62-mode-prop-replaces-readonly--lockworkflow). |
515
+ | `App` | `eventHandlers` (object) | Flat `on*` props — see [section 6.3](#63-app-event-handlers-are-flat-props). |
516
+
517
+ `FormToggle.onLabel`/`offLabel` and `FormArray.addLabel` were _un_-deprecated:
518
+ they express per-instance labels the global messages system cannot, and are
519
+ now documented overrides.
520
+
521
+ Removed message keys (only the removed ChatPanel branches read them):
522
+ `playground.states.viewOnlyTitle`, `.viewOnlyText`, `.readyTitle`, `.readyText`.
523
+
524
+ ### 6.1 `mountWorkflowEditor` option changes
525
+
526
+ - `workflow` now actually loads the workflow (1.x accepted and ignored it).
527
+ - `nodes` is removed (it fed a prop the editor never read). Use
528
+ `mountFlowDropApp` if you need to pre-seed node metadata.
529
+ - `readOnly` / `lockWorkflow` mount options become a single `mode` option
530
+ (`'edit' | 'readonly' | 'locked'`) — see
531
+ [section 6.2](#62-mode-prop-replaces-readonly--lockworkflow). The grouped
532
+ `eventHandlers` mount option is **unchanged** (an options bag is fine in a JS
533
+ mount API); only the `<App>` _component_ prop is flattened.
534
+
535
+ ### 6.2 `mode` prop replaces `readOnly` + `lockWorkflow`
536
+
537
+ `<App>`, `<WorkflowEditor>`, and the `mountFlowDropApp` options bag no longer
538
+ take the `readOnly` and `lockWorkflow` booleans. They are replaced by a single
539
+ `mode` prop/option:
540
+
541
+ ```ts
542
+ mode?: 'edit' | 'readonly' | 'locked'; // default: 'edit'
543
+ ```
544
+
545
+ **Behavior matrix** (what each mode gates):
546
+
547
+ | mode | node drag / connect / select | proximity-connect | node swap | bottom console panel + toggle |
548
+ | ------------ | ---------------------------- | ----------------- | --------- | ----------------------------- |
549
+ | `'edit'` | enabled | enabled | enabled | available |
550
+ | `'readonly'` | disabled | disabled | disabled | hidden |
551
+ | `'locked'` | disabled | disabled | disabled | hidden |
552
+
553
+ In 1.x, `readOnly` and `lockWorkflow` gated the **exact same** interactions and
554
+ were always combined as `!readOnly && !lockWorkflow`. Any combination of the two
555
+ booleans therefore collapsed to either "edit" (both `false`) or "fully disabled"
556
+ (either `true`) — there was no orthogonal behavior to lose. `'readonly'` and
557
+ `'locked'` behave identically today; the two names are preserved as distinct
558
+ intents so a future release can differentiate them without another breaking
559
+ change.
560
+
561
+ **Old → new mapping** (component prop and mount option are identical):
562
+
563
+ | 1.x | 2.0 |
564
+ | ---------------------------------------------------------- | ------------------------------------------------------ |
565
+ | `readOnly` unset / `false`, `lockWorkflow` unset / `false` | `mode="edit"` (or omit) |
566
+ | `readOnly={true}` | `mode="readonly"` |
567
+ | `lockWorkflow={true}` | `mode="locked"` |
568
+ | both `true` | `mode="readonly"` _or_ `mode="locked"` (same behavior) |
569
+
570
+ ```svelte
571
+ <!-- 1.x -->
572
+ <App readOnly={true} />
573
+ <App lockWorkflow={true} />
574
+
575
+ <!-- 2.0 -->
576
+ <App mode="readonly" />
577
+ <App mode="locked" />
578
+ ```
579
+
580
+ ```js
581
+ // 1.x
582
+ mountFlowDropApp(el, { readOnly: true });
583
+ // 2.0
584
+ mountFlowDropApp(el, { mode: 'readonly' });
585
+ ```
586
+
587
+ ### 6.3 `<App>` event handlers are flat props
588
+
589
+ The `<App>` component no longer takes a grouped `eventHandlers={{ … }}` object.
590
+ The handlers `<App>` consumes are now individual `on*` props, consistent with
591
+ every other component:
592
+
593
+ ```svelte
594
+ <!-- 1.x -->
595
+ <App eventHandlers={{ onApiError, onAfterSave, onWorkflowLoad, onBeforeSwap }} />
596
+
597
+ <!-- 2.0 -->
598
+ <App {onApiError} {onAfterSave} {onWorkflowLoad} {onBeforeSwap} />
599
+ ```
600
+
601
+ Available `<App>` callback props: `onBeforeSave`, `onAfterSave`, `onSaveError`,
602
+ `onApiError`, `onWorkflowLoad`, `onBeforeSwap`, `onAfterSwap`.
603
+
604
+ The **`mountFlowDropApp` / `mountPlayground` options bag is unchanged** — keep
605
+ passing the grouped `eventHandlers` object there. The mount functions wire
606
+ `onDirtyStateChange` / `onWorkflowChange` into the instance store, call
607
+ `onBeforeUnmount` on teardown, and forward the remaining handlers to `<App>`'s
608
+ flat props for you. The `FlowDropEventHandlers` type is still exported for use
609
+ with the mount option.
610
+
611
+ ## 7. localStorage keys are instance-scoped
612
+
613
+ The page-default instance no longer writes bare keys:
614
+
615
+ | 1.x | 2.0 |
616
+ | ----------------------------- | ------------------------------------- |
617
+ | `flowdrop:draft:<workflowId>` | `flowdrop:draft:default:<workflowId>` |
618
+ | `fd-pipeline-panel-open` | `fd-pipeline-panel-open:default` |
619
+
620
+ Existing user data migrates automatically on first read (copy to the scoped
621
+ key, remove the legacy key). Only hosts reading these keys directly need to
622
+ update. `clearAllDrafts()` still removes everything under `flowdrop:draft:`.
623
+
624
+ ## 8. Behavioral notes
625
+
626
+ - `fd.fields.register()` warns in dev when overwriting an existing field type.
627
+ Overwriting still works; the warning flags accidents.
628
+ - Internal `DEV` gates use `esm-env` instead of `import.meta.env`, so the
629
+ package no longer assumes a Vite host.