@d34dman/flowdrop 0.0.61 → 0.0.62

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 (204) hide show
  1. package/README.md +6 -0
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/agentspec/AgentSpecAdapter.js +3 -1
  4. package/dist/api/client.d.ts +4 -0
  5. package/dist/api/client.js +6 -1
  6. package/dist/api/enhanced-client.js +7 -6
  7. package/dist/components/App.svelte +143 -219
  8. package/dist/components/CanvasBanner.stories.svelte +25 -0
  9. package/dist/components/CanvasBanner.stories.svelte.d.ts +27 -0
  10. package/dist/components/CanvasBanner.svelte +2 -2
  11. package/dist/components/ConfigForm.svelte +37 -36
  12. package/dist/components/ConfigPanel.stories.svelte +38 -0
  13. package/dist/components/ConfigPanel.stories.svelte.d.ts +27 -0
  14. package/dist/components/ConfigPanel.svelte +2 -2
  15. package/dist/components/ConnectionLine.svelte +2 -2
  16. package/dist/components/FlowDropZone.svelte +18 -2
  17. package/dist/components/FlowDropZone.svelte.d.ts +2 -0
  18. package/dist/components/LoadingSpinner.stories.svelte +30 -0
  19. package/dist/components/LoadingSpinner.stories.svelte.d.ts +27 -0
  20. package/dist/components/Logo.stories.svelte +22 -0
  21. package/dist/components/Logo.stories.svelte.d.ts +27 -0
  22. package/dist/components/Logo.svelte +33 -13
  23. package/dist/components/Logo.svelte.d.ts +1 -1
  24. package/dist/components/MarkdownDisplay.stories.svelte +21 -0
  25. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +27 -0
  26. package/dist/components/MarkdownDisplay.svelte +4 -3
  27. package/dist/components/Navbar.stories.svelte +41 -0
  28. package/dist/components/Navbar.stories.svelte.d.ts +27 -0
  29. package/dist/components/Navbar.svelte +4 -4
  30. package/dist/components/NodeSidebar.svelte +12 -12
  31. package/dist/components/NodeStatusOverlay.stories.svelte +74 -0
  32. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +27 -0
  33. package/dist/components/PipelineStatus.svelte +11 -4
  34. package/dist/components/PortCoordinateTracker.svelte +1 -1
  35. package/dist/components/SchemaForm.stories.svelte +101 -0
  36. package/dist/components/SchemaForm.stories.svelte.d.ts +27 -0
  37. package/dist/components/SchemaForm.svelte +17 -12
  38. package/dist/components/SettingsModal.svelte +3 -3
  39. package/dist/components/SettingsPanel.svelte +23 -22
  40. package/dist/components/StatusIcon.stories.svelte +60 -0
  41. package/dist/components/StatusIcon.stories.svelte.d.ts +27 -0
  42. package/dist/components/StatusIcon.svelte +7 -0
  43. package/dist/components/StatusLabel.stories.svelte +17 -0
  44. package/dist/components/StatusLabel.stories.svelte.d.ts +27 -0
  45. package/dist/components/ThemeToggle.stories.svelte +25 -0
  46. package/dist/components/ThemeToggle.stories.svelte.d.ts +27 -0
  47. package/dist/components/ThemeToggle.svelte +8 -8
  48. package/dist/components/UniversalNode.svelte +1 -1
  49. package/dist/components/WorkflowEditor.svelte +298 -294
  50. package/dist/components/form/FormAutocomplete.svelte +20 -19
  51. package/dist/components/form/FormCheckboxGroup.stories.svelte +28 -0
  52. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +27 -0
  53. package/dist/components/form/FormField.svelte +3 -3
  54. package/dist/components/form/FormFieldLight.svelte +2 -2
  55. package/dist/components/form/FormFieldWrapper.stories.svelte +31 -0
  56. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +27 -0
  57. package/dist/components/form/FormFieldset.svelte +7 -7
  58. package/dist/components/form/FormNumberField.stories.svelte +33 -0
  59. package/dist/components/form/FormNumberField.stories.svelte.d.ts +27 -0
  60. package/dist/components/form/FormRangeField.stories.svelte +31 -0
  61. package/dist/components/form/FormRangeField.stories.svelte.d.ts +27 -0
  62. package/dist/components/form/FormSelect.stories.svelte +50 -0
  63. package/dist/components/form/FormSelect.stories.svelte.d.ts +27 -0
  64. package/dist/components/form/FormTemplateEditor.svelte +2 -1
  65. package/dist/components/form/FormTextField.stories.svelte +30 -0
  66. package/dist/components/form/FormTextField.stories.svelte.d.ts +27 -0
  67. package/dist/components/form/FormTextarea.stories.svelte +31 -0
  68. package/dist/components/form/FormTextarea.stories.svelte.d.ts +27 -0
  69. package/dist/components/form/FormToggle.stories.svelte +30 -0
  70. package/dist/components/form/FormToggle.stories.svelte.d.ts +27 -0
  71. package/dist/components/form/FormUISchemaRenderer.svelte +1 -1
  72. package/dist/components/form/types.d.ts +15 -47
  73. package/dist/components/interrupt/ChoicePrompt.stories.svelte +43 -0
  74. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +27 -0
  75. package/dist/components/interrupt/ChoicePrompt.svelte +24 -24
  76. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +49 -0
  77. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +27 -0
  78. package/dist/components/interrupt/ConfirmationPrompt.svelte +19 -19
  79. package/dist/components/interrupt/FormPrompt.svelte +15 -15
  80. package/dist/components/interrupt/InterruptBubble.svelte +202 -236
  81. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +1 -1
  82. package/dist/components/interrupt/ReviewPrompt.stories.svelte +46 -0
  83. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +27 -0
  84. package/dist/components/interrupt/ReviewPrompt.svelte +842 -0
  85. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +23 -0
  86. package/dist/components/interrupt/TextInputPrompt.stories.svelte +34 -0
  87. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +27 -0
  88. package/dist/components/interrupt/TextInputPrompt.svelte +21 -21
  89. package/dist/components/nodes/GatewayNode.stories.svelte +76 -0
  90. package/dist/components/nodes/GatewayNode.stories.svelte.d.ts +26 -0
  91. package/dist/components/nodes/GatewayNode.svelte +19 -17
  92. package/dist/components/nodes/IdeaNode.stories.svelte +48 -0
  93. package/dist/components/nodes/IdeaNode.stories.svelte.d.ts +26 -0
  94. package/dist/components/nodes/IdeaNode.svelte +10 -26
  95. package/dist/components/nodes/NotesNode.stories.svelte +69 -0
  96. package/dist/components/nodes/NotesNode.stories.svelte.d.ts +26 -0
  97. package/dist/components/nodes/NotesNode.svelte +8 -8
  98. package/dist/components/nodes/SimpleNode.stories.svelte +101 -0
  99. package/dist/components/nodes/SimpleNode.stories.svelte.d.ts +26 -0
  100. package/dist/components/nodes/SimpleNode.svelte +16 -24
  101. package/dist/components/nodes/SquareNode.stories.svelte +56 -0
  102. package/dist/components/nodes/SquareNode.stories.svelte.d.ts +26 -0
  103. package/dist/components/nodes/SquareNode.svelte +13 -21
  104. package/dist/components/nodes/TerminalNode.stories.svelte +25 -0
  105. package/dist/components/nodes/TerminalNode.stories.svelte.d.ts +26 -0
  106. package/dist/components/nodes/TerminalNode.svelte +6 -6
  107. package/dist/components/nodes/ToolNode.stories.svelte +71 -0
  108. package/dist/components/nodes/ToolNode.stories.svelte.d.ts +26 -0
  109. package/dist/components/nodes/ToolNode.svelte +7 -15
  110. package/dist/components/nodes/WorkflowNode.stories.svelte +50 -0
  111. package/dist/components/nodes/WorkflowNode.stories.svelte.d.ts +26 -0
  112. package/dist/components/nodes/WorkflowNode.svelte +13 -13
  113. package/dist/components/playground/ChatPanel.svelte +48 -48
  114. package/dist/components/playground/ExecutionLogs.svelte +23 -23
  115. package/dist/components/playground/InputCollector.svelte +24 -24
  116. package/dist/components/playground/MessageBubble.stories.svelte +49 -0
  117. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +27 -0
  118. package/dist/components/playground/MessageBubble.svelte +49 -46
  119. package/dist/components/playground/Playground.svelte +194 -129
  120. package/dist/components/playground/PlaygroundModal.svelte +5 -5
  121. package/dist/components/playground/SessionManager.svelte +26 -26
  122. package/dist/config/constants.d.ts +22 -0
  123. package/dist/config/constants.js +22 -0
  124. package/dist/config/endpoints.d.ts +19 -0
  125. package/dist/config/runtimeConfig.js +2 -1
  126. package/dist/core/index.d.ts +5 -2
  127. package/dist/core/index.js +9 -1
  128. package/dist/editor/index.d.ts +13 -9
  129. package/dist/editor/index.js +15 -11
  130. package/dist/form/code.d.ts +2 -1
  131. package/dist/form/code.js +1 -3
  132. package/dist/form/markdown.d.ts +2 -1
  133. package/dist/form/markdown.js +1 -3
  134. package/dist/helpers/workflowEditorHelper.js +13 -9
  135. package/dist/mocks/app-forms.js +1 -0
  136. package/dist/mocks/app-navigation.js +3 -1
  137. package/dist/mocks/app-stores.d.ts +4 -4
  138. package/dist/playground/index.d.ts +4 -3
  139. package/dist/playground/index.js +12 -10
  140. package/dist/playground/mount.js +6 -13
  141. package/dist/services/agentSpecExecutionService.js +2 -1
  142. package/dist/services/api.js +10 -18
  143. package/dist/services/apiVariableService.js +2 -1
  144. package/dist/services/autoSaveService.d.ts +3 -3
  145. package/dist/services/autoSaveService.js +21 -17
  146. package/dist/services/categoriesApi.js +13 -5
  147. package/dist/services/draftStorage.js +5 -4
  148. package/dist/services/dynamicSchemaService.js +4 -4
  149. package/dist/services/globalSave.d.ts +60 -11
  150. package/dist/services/globalSave.js +160 -83
  151. package/dist/services/historyService.d.ts +2 -1
  152. package/dist/services/historyService.js +7 -3
  153. package/dist/services/interruptService.js +9 -8
  154. package/dist/services/nodeExecutionService.js +14 -6
  155. package/dist/services/playgroundService.js +2 -1
  156. package/dist/services/portConfigApi.js +11 -7
  157. package/dist/services/toastService.d.ts +1 -1
  158. package/dist/services/toastService.js +6 -5
  159. package/dist/services/variableService.js +3 -2
  160. package/dist/settings/index.d.ts +1 -1
  161. package/dist/settings/index.js +1 -1
  162. package/dist/stores/{categoriesStore.d.ts → categoriesStore.svelte.d.ts} +3 -3
  163. package/dist/stores/{categoriesStore.js → categoriesStore.svelte.js} +15 -18
  164. package/dist/stores/editorStateMachine.svelte.d.ts +42 -0
  165. package/dist/stores/editorStateMachine.svelte.js +132 -0
  166. package/dist/stores/{historyStore.d.ts → historyStore.svelte.d.ts} +18 -15
  167. package/dist/stores/{historyStore.js → historyStore.svelte.js} +40 -21
  168. package/dist/stores/{interruptStore.d.ts → interruptStore.svelte.d.ts} +16 -15
  169. package/dist/stores/{interruptStore.js → interruptStore.svelte.js} +85 -94
  170. package/dist/stores/{playgroundStore.d.ts → playgroundStore.svelte.d.ts} +41 -33
  171. package/dist/stores/{playgroundStore.js → playgroundStore.svelte.js} +164 -84
  172. package/dist/stores/{portCoordinateStore.d.ts → portCoordinateStore.svelte.d.ts} +10 -4
  173. package/dist/stores/{portCoordinateStore.js → portCoordinateStore.svelte.js} +38 -35
  174. package/dist/stores/{settingsStore.d.ts → settingsStore.svelte.d.ts} +45 -28
  175. package/dist/stores/{settingsStore.js → settingsStore.svelte.js} +169 -128
  176. package/dist/stores/{workflowStore.d.ts → workflowStore.svelte.d.ts} +101 -65
  177. package/dist/stores/{workflowStore.js → workflowStore.svelte.js} +285 -239
  178. package/dist/stories/CanvasDecorator.svelte +50 -0
  179. package/dist/stories/CanvasDecorator.svelte.d.ts +8 -0
  180. package/dist/stories/NodeDecorator.svelte +74 -0
  181. package/dist/stories/NodeDecorator.svelte.d.ts +8 -0
  182. package/dist/stories/utils.d.ts +93 -0
  183. package/dist/stories/utils.js +122 -0
  184. package/dist/styles/base.css +114 -61
  185. package/dist/styles/toast.css +2 -2
  186. package/dist/styles/tokens.css +250 -185
  187. package/dist/svelte-app.d.ts +0 -6
  188. package/dist/svelte-app.js +13 -31
  189. package/dist/types/index.d.ts +2 -0
  190. package/dist/types/interrupt.d.ts +89 -5
  191. package/dist/types/interrupt.js +13 -1
  192. package/dist/types/playground.d.ts +5 -0
  193. package/dist/types/settings.js +1 -1
  194. package/dist/utils/colors.js +4 -4
  195. package/dist/utils/connections.js +33 -8
  196. package/dist/utils/icons.js +1 -1
  197. package/dist/utils/logger.d.ts +47 -0
  198. package/dist/utils/logger.js +72 -0
  199. package/dist/utils/nodeWrapper.js +1 -1
  200. package/dist/utils/sanitize.d.ts +19 -0
  201. package/dist/utils/sanitize.js +31 -0
  202. package/dist/utils/validation.d.ts +29 -0
  203. package/dist/utils/validation.js +39 -0
  204. package/package.json +243 -232
@@ -1,84 +1,146 @@
1
1
  /**
2
2
  * Playground Store
3
3
  *
4
- * Svelte stores for managing playground state including sessions,
4
+ * Svelte 5 rune-based state for managing playground state including sessions,
5
5
  * messages, and execution status.
6
6
  *
7
7
  * @module stores/playgroundStore
8
8
  */
9
- import { writable, derived, get } from 'svelte/store';
10
9
  import { isChatInputNode, defaultIsTerminalStatus } from '../types/playground.js';
10
+ import { logger } from '../utils/logger.js';
11
11
  // =========================================================================
12
- // Core Stores
12
+ // Core State
13
13
  // =========================================================================
14
14
  /**
15
15
  * Currently active playground session
16
16
  */
17
- export const currentSession = writable(null);
17
+ let _currentSession = $state(null);
18
18
  /**
19
19
  * List of all sessions for the current workflow
20
20
  */
21
- export const sessions = writable([]);
21
+ let _sessions = $state([]);
22
22
  /**
23
23
  * Messages in the current session
24
24
  */
25
- export const messages = writable([]);
25
+ let _messages = $state([]);
26
26
  /**
27
27
  * Whether an execution is currently running
28
28
  */
29
- export const isExecuting = writable(false);
29
+ let _isExecuting = $state(false);
30
30
  /**
31
31
  * Whether we are currently loading data
32
32
  */
33
- export const isLoading = writable(false);
33
+ let _isLoading = $state(false);
34
34
  /**
35
35
  * Current error message, if any
36
36
  */
37
- export const error = writable(null);
37
+ let _error = $state(null);
38
38
  /**
39
39
  * Current workflow being tested
40
40
  */
41
- export const currentWorkflow = writable(null);
41
+ let _currentWorkflow = $state(null);
42
42
  /**
43
43
  * Last polling timestamp for incremental message fetching
44
44
  */
45
- export const lastPollTimestamp = writable(null);
45
+ let _lastPollTimestamp = $state(null);
46
46
  // =========================================================================
47
- // Derived Stores
47
+ // Getter Functions (for reactive access in components)
48
48
  // =========================================================================
49
49
  /**
50
- * Derived store for current session status
50
+ * Get the current session
51
51
  */
52
- export const sessionStatus = derived(currentSession, ($session) => $session?.status ?? 'idle');
52
+ export function getCurrentSession() {
53
+ return _currentSession;
54
+ }
55
+ /**
56
+ * Get all sessions
57
+ */
58
+ export function getSessions() {
59
+ return _sessions;
60
+ }
61
+ /**
62
+ * Get all messages
63
+ */
64
+ export function getMessages() {
65
+ return _messages;
66
+ }
67
+ /**
68
+ * Get executing state
69
+ */
70
+ export function getIsExecuting() {
71
+ return _isExecuting;
72
+ }
73
+ /**
74
+ * Get loading state
75
+ */
76
+ export function getIsLoading() {
77
+ return _isLoading;
78
+ }
79
+ /**
80
+ * Get error state
81
+ */
82
+ export function getError() {
83
+ return _error;
84
+ }
85
+ /**
86
+ * Get the current workflow
87
+ */
88
+ export function getCurrentWorkflow() {
89
+ return _currentWorkflow;
90
+ }
91
+ /**
92
+ * Get the last poll timestamp
93
+ */
94
+ export function getLastPollTimestamp() {
95
+ return _lastPollTimestamp;
96
+ }
97
+ // =========================================================================
98
+ // Derived Getters
99
+ // =========================================================================
53
100
  /**
54
- * Derived store for message count
101
+ * Get current session status
55
102
  */
56
- export const messageCount = derived(messages, ($messages) => $messages.length);
103
+ export function getSessionStatus() {
104
+ return _currentSession?.status ?? 'idle';
105
+ }
57
106
  /**
58
- * Derived store for chat messages (excludes log messages)
107
+ * Get message count
59
108
  */
60
- export const chatMessages = derived(messages, ($messages) => $messages.filter((m) => m.role !== 'log'));
109
+ export function getMessageCount() {
110
+ return _messages.length;
111
+ }
61
112
  /**
62
- * Derived store for log messages only
113
+ * Get chat messages (excludes log messages)
63
114
  */
64
- export const logMessages = derived(messages, ($messages) => $messages.filter((m) => m.role === 'log'));
115
+ export function getChatMessages() {
116
+ return _messages.filter((m) => m.role !== 'log');
117
+ }
65
118
  /**
66
- * Derived store for the latest message
119
+ * Get log messages only
67
120
  */
68
- export const latestMessage = derived(messages, ($messages) => $messages.length > 0 ? $messages[$messages.length - 1] : null);
121
+ export function getLogMessages() {
122
+ return _messages.filter((m) => m.role === 'log');
123
+ }
69
124
  /**
70
- * Derived store for input fields from workflow input nodes
125
+ * Get the latest message
126
+ */
127
+ export function getLatestMessage() {
128
+ return _messages.length > 0 ? _messages[_messages.length - 1] : null;
129
+ }
130
+ /**
131
+ * Get input fields from workflow input nodes
71
132
  *
72
133
  * Analyzes the workflow to extract input nodes and their configuration
73
134
  * schemas for auto-generating input forms.
74
135
  */
75
- export const inputFields = derived(currentWorkflow, ($workflow) => {
76
- if (!$workflow) {
136
+ export function getInputFields() {
137
+ const workflow = _currentWorkflow;
138
+ if (!workflow) {
77
139
  return [];
78
140
  }
79
141
  const fields = [];
80
142
  // Find input nodes in the workflow
81
- $workflow.nodes.forEach((node) => {
143
+ workflow.nodes.forEach((node) => {
82
144
  const category = node.data.metadata?.category;
83
145
  const nodeTypeId = node.data.metadata?.id ?? node.type;
84
146
  // Check if this is an input-type node
@@ -128,15 +190,20 @@ export const inputFields = derived(currentWorkflow, ($workflow) => {
128
190
  }
129
191
  });
130
192
  return fields;
131
- });
193
+ }
132
194
  /**
133
- * Derived store for detecting if workflow has a chat input
195
+ * Check if workflow has a chat input
134
196
  */
135
- export const hasChatInput = derived(inputFields, ($fields) => $fields.some((field) => isChatInputNode(field.nodeId) || field.type === 'string'));
197
+ export function getHasChatInput() {
198
+ const fields = getInputFields();
199
+ return fields.some((field) => isChatInputNode(field.nodeId) || field.type === 'string');
200
+ }
136
201
  /**
137
- * Derived store for session count
202
+ * Get session count
138
203
  */
139
- export const sessionCount = derived(sessions, ($sessions) => $sessions.length);
204
+ export function getSessionCount() {
205
+ return _sessions.length;
206
+ }
140
207
  // =========================================================================
141
208
  // Helper Functions
142
209
  // =========================================================================
@@ -184,7 +251,7 @@ export const playgroundActions = {
184
251
  * @param workflow - The workflow to test
185
252
  */
186
253
  setWorkflow: (workflow) => {
187
- currentWorkflow.set(workflow);
254
+ _currentWorkflow = workflow;
188
255
  },
189
256
  /**
190
257
  * Set the current session
@@ -192,10 +259,10 @@ export const playgroundActions = {
192
259
  * @param session - The session to set as active
193
260
  */
194
261
  setCurrentSession: (session) => {
195
- currentSession.set(session);
262
+ _currentSession = session;
196
263
  if (session) {
197
264
  // Update session in the list
198
- sessions.update(($sessions) => $sessions.map((s) => (s.id === session.id ? session : s)));
265
+ _sessions = _sessions.map((s) => (s.id === session.id ? session : s));
199
266
  }
200
267
  },
201
268
  /**
@@ -204,15 +271,13 @@ export const playgroundActions = {
204
271
  * @param status - The new status
205
272
  */
206
273
  updateSessionStatus: (status) => {
207
- currentSession.update(($session) => {
208
- if (!$session)
209
- return null;
210
- return { ...$session, status, updatedAt: new Date().toISOString() };
211
- });
274
+ if (_currentSession) {
275
+ _currentSession = { ..._currentSession, status, updatedAt: new Date().toISOString() };
276
+ }
212
277
  // Also update in sessions list
213
- const session = get(currentSession);
278
+ const session = _currentSession;
214
279
  if (session) {
215
- sessions.update(($sessions) => $sessions.map((s) => (s.id === session.id ? { ...s, status } : s)));
280
+ _sessions = _sessions.map((s) => (s.id === session.id ? { ...s, status } : s));
216
281
  }
217
282
  },
218
283
  /**
@@ -221,7 +286,7 @@ export const playgroundActions = {
221
286
  * @param sessionList - Array of sessions
222
287
  */
223
288
  setSessions: (sessionList) => {
224
- sessions.set(sessionList);
289
+ _sessions = sessionList;
225
290
  },
226
291
  /**
227
292
  * Add a new session to the list
@@ -229,7 +294,7 @@ export const playgroundActions = {
229
294
  * @param session - The session to add
230
295
  */
231
296
  addSession: (session) => {
232
- sessions.update(($sessions) => [session, ...$sessions]);
297
+ _sessions = [session, ..._sessions];
233
298
  },
234
299
  /**
235
300
  * Remove a session from the list
@@ -237,12 +302,11 @@ export const playgroundActions = {
237
302
  * @param sessionId - The session ID to remove
238
303
  */
239
304
  removeSession: (sessionId) => {
240
- sessions.update(($sessions) => $sessions.filter((s) => s.id !== sessionId));
305
+ _sessions = _sessions.filter((s) => s.id !== sessionId);
241
306
  // Clear current session if it was removed
242
- const current = get(currentSession);
243
- if (current?.id === sessionId) {
244
- currentSession.set(null);
245
- messages.set([]);
307
+ if (_currentSession?.id === sessionId) {
308
+ _currentSession = null;
309
+ _messages = [];
246
310
  }
247
311
  },
248
312
  /**
@@ -252,7 +316,7 @@ export const playgroundActions = {
252
316
  * @param messageList - Array of messages
253
317
  */
254
318
  setMessages: (messageList) => {
255
- messages.set(sortMessagesChronologically(messageList));
319
+ _messages = sortMessagesChronologically(messageList);
256
320
  },
257
321
  /**
258
322
  * Add a message to the current session
@@ -261,7 +325,7 @@ export const playgroundActions = {
261
325
  * @param message - The message to add
262
326
  */
263
327
  addMessage: (message) => {
264
- messages.update(($messages) => sortMessagesChronologically([...$messages, message]));
328
+ _messages = sortMessagesChronologically([..._messages, message]);
265
329
  },
266
330
  /**
267
331
  * Add multiple messages to the current session
@@ -272,20 +336,18 @@ export const playgroundActions = {
272
336
  addMessages: (newMessages) => {
273
337
  if (newMessages.length === 0)
274
338
  return;
275
- messages.update(($messages) => {
276
- // Deduplicate by message ID
277
- const existingIds = new Set($messages.map((m) => m.id));
278
- const uniqueNewMessages = newMessages.filter((m) => !existingIds.has(m.id));
279
- // Sort the combined messages chronologically
280
- return sortMessagesChronologically([...$messages, ...uniqueNewMessages]);
281
- });
339
+ // Deduplicate by message ID
340
+ const existingIds = new Set(_messages.map((m) => m.id));
341
+ const uniqueNewMessages = newMessages.filter((m) => !existingIds.has(m.id));
342
+ // Sort the combined messages chronologically
343
+ _messages = sortMessagesChronologically([..._messages, ...uniqueNewMessages]);
282
344
  },
283
345
  /**
284
346
  * Clear all messages
285
347
  */
286
348
  clearMessages: () => {
287
- messages.set([]);
288
- lastPollTimestamp.set(null);
349
+ _messages = [];
350
+ _lastPollTimestamp = null;
289
351
  },
290
352
  /**
291
353
  * Set the executing state
@@ -293,7 +355,7 @@ export const playgroundActions = {
293
355
  * @param executing - Whether execution is in progress
294
356
  */
295
357
  setExecuting: (executing) => {
296
- isExecuting.set(executing);
358
+ _isExecuting = executing;
297
359
  },
298
360
  /**
299
361
  * Set the loading state
@@ -301,7 +363,7 @@ export const playgroundActions = {
301
363
  * @param loading - Whether loading is in progress
302
364
  */
303
365
  setLoading: (loading) => {
304
- isLoading.set(loading);
366
+ _isLoading = loading;
305
367
  },
306
368
  /**
307
369
  * Set an error message
@@ -309,7 +371,7 @@ export const playgroundActions = {
309
371
  * @param errorMessage - The error message or null to clear
310
372
  */
311
373
  setError: (errorMessage) => {
312
- error.set(errorMessage);
374
+ _error = errorMessage;
313
375
  },
314
376
  /**
315
377
  * Update the last poll timestamp
@@ -317,20 +379,20 @@ export const playgroundActions = {
317
379
  * @param timestamp - ISO 8601 timestamp
318
380
  */
319
381
  updateLastPollTimestamp: (timestamp) => {
320
- lastPollTimestamp.set(timestamp);
382
+ _lastPollTimestamp = timestamp;
321
383
  },
322
384
  /**
323
385
  * Reset all playground state
324
386
  */
325
387
  reset: () => {
326
- currentSession.set(null);
327
- sessions.set([]);
328
- messages.set([]);
329
- isExecuting.set(false);
330
- isLoading.set(false);
331
- error.set(null);
332
- currentWorkflow.set(null);
333
- lastPollTimestamp.set(null);
388
+ _currentSession = null;
389
+ _sessions = [];
390
+ _messages = [];
391
+ _isExecuting = false;
392
+ _isLoading = false;
393
+ _error = null;
394
+ _currentWorkflow = null;
395
+ _lastPollTimestamp = null;
334
396
  },
335
397
  /**
336
398
  * Switch to a different session
@@ -338,12 +400,11 @@ export const playgroundActions = {
338
400
  * @param sessionId - The session ID to switch to
339
401
  */
340
402
  switchSession: (sessionId) => {
341
- const sessionList = get(sessions);
342
- const session = sessionList.find((s) => s.id === sessionId);
403
+ const session = _sessions.find((s) => s.id === sessionId);
343
404
  if (session) {
344
- currentSession.set(session);
345
- messages.set([]);
346
- lastPollTimestamp.set(null);
405
+ _currentSession = session;
406
+ _messages = [];
407
+ _lastPollTimestamp = null;
347
408
  }
348
409
  }
349
410
  };
@@ -380,7 +441,7 @@ export function createPollingCallback(isTerminalStatus = defaultIsTerminalStatus
380
441
  * @returns The current session ID or null
381
442
  */
382
443
  export function getCurrentSessionId() {
383
- return get(currentSession)?.id ?? null;
444
+ return _currentSession?.id ?? null;
384
445
  }
385
446
  /**
386
447
  * Check if a specific session is selected
@@ -389,7 +450,7 @@ export function getCurrentSessionId() {
389
450
  * @returns True if the session is currently selected
390
451
  */
391
452
  export function isSessionSelected(sessionId) {
392
- return get(currentSession)?.id === sessionId;
453
+ return _currentSession?.id === sessionId;
393
454
  }
394
455
  /**
395
456
  * Get all messages as a snapshot
@@ -397,7 +458,7 @@ export function isSessionSelected(sessionId) {
397
458
  * @returns Array of all messages
398
459
  */
399
460
  export function getMessagesSnapshot() {
400
- return get(messages);
461
+ return _messages;
401
462
  }
402
463
  /**
403
464
  * Get the latest message timestamp for polling
@@ -405,10 +466,29 @@ export function getMessagesSnapshot() {
405
466
  * @returns ISO 8601 timestamp of the latest message, or null
406
467
  */
407
468
  export function getLatestMessageTimestamp() {
408
- const msgs = get(messages);
409
- if (msgs.length === 0)
469
+ if (_messages.length === 0)
410
470
  return null;
411
- return msgs[msgs.length - 1].timestamp;
471
+ return _messages[_messages.length - 1].timestamp;
472
+ }
473
+ /**
474
+ * Subscribe to session status changes using $effect.root.
475
+ * This is designed for use in non-component contexts (e.g., mount.ts).
476
+ *
477
+ * @param callback - Called when session status changes
478
+ * @returns Cleanup function to stop the subscription
479
+ */
480
+ export function subscribeToSessionStatus(callback) {
481
+ let previousStatus = getSessionStatus();
482
+ const cleanup = $effect.root(() => {
483
+ $effect(() => {
484
+ const status = getSessionStatus();
485
+ if (status !== previousStatus) {
486
+ callback(status, previousStatus);
487
+ previousStatus = status;
488
+ }
489
+ });
490
+ });
491
+ return cleanup;
412
492
  }
413
493
  /**
414
494
  * Refresh messages for the current session
@@ -421,7 +501,7 @@ export function getLatestMessageTimestamp() {
421
501
  * @returns Promise that resolves when messages are refreshed
422
502
  */
423
503
  export async function refreshSessionMessages(fetchMessages, isTerminalStatus) {
424
- const session = get(currentSession);
504
+ const session = _currentSession;
425
505
  if (!session)
426
506
  return;
427
507
  try {
@@ -430,6 +510,6 @@ export async function refreshSessionMessages(fetchMessages, isTerminalStatus) {
430
510
  callback(response);
431
511
  }
432
512
  catch (err) {
433
- console.error('[playgroundStore] Failed to refresh messages:', err);
513
+ logger.error('[playgroundStore] Failed to refresh messages:', err);
434
514
  }
435
515
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Port Coordinate Store
2
+ * Port Coordinate Store (Svelte 5 Runes)
3
3
  *
4
4
  * General-purpose store that maintains absolute canvas-space coordinates
5
5
  * for all port handles in the workflow. Built from SvelteFlow's internal
@@ -14,8 +14,6 @@
14
14
  */
15
15
  import type { WorkflowNode as WorkflowNodeType, PortCoordinate, PortCoordinateMap } from '../types/index.js';
16
16
  import type { InternalNode } from '@xyflow/svelte';
17
- /** Store holding all port absolute coordinates, keyed by handleId */
18
- export declare const portCoordinateStore: import("svelte/store").Writable<PortCoordinateMap>;
19
17
  /**
20
18
  * Rebuild coordinates for ALL nodes from SvelteFlow internals.
21
19
  * Call on initial workflow load (after render) and after bulk changes.
@@ -53,8 +51,16 @@ export declare function getPortCoordinate(handleId: string): PortCoordinate | un
53
51
  */
54
52
  export declare function getNodePortCoordinates(nodeId: string): PortCoordinate[];
55
53
  /**
56
- * Get the current snapshot of all port coordinates (non-reactive).
54
+ * Get the current snapshot of all port coordinates.
55
+ * Returns the reactive SvelteMap directly.
57
56
  *
58
57
  * @returns Current port coordinate map
59
58
  */
60
59
  export declare function getPortCoordinateSnapshot(): PortCoordinateMap;
60
+ /**
61
+ * Get the reactive port coordinates state.
62
+ * Useful for components that need to reactively read the coordinates.
63
+ *
64
+ * @returns The reactive port coordinate map
65
+ */
66
+ export declare function getPortCoordinates(): PortCoordinateMap;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Port Coordinate Store
2
+ * Port Coordinate Store (Svelte 5 Runes)
3
3
  *
4
4
  * General-purpose store that maintains absolute canvas-space coordinates
5
5
  * for all port handles in the workflow. Built from SvelteFlow's internal
@@ -12,10 +12,10 @@
12
12
  * which SvelteFlow already maintains for all node types. This avoids replicating
13
13
  * CSS positioning logic and stays automatically accurate.
14
14
  */
15
- import { writable, get } from 'svelte/store';
15
+ import { SvelteMap } from 'svelte/reactivity';
16
16
  import { ProximityConnectHelper } from '../helpers/proximityConnect.js';
17
- /** Store holding all port absolute coordinates, keyed by handleId */
18
- export const portCoordinateStore = writable(new Map());
17
+ /** Reactive state holding all port absolute coordinates, keyed by handleId */
18
+ let coordinates = $state(new SvelteMap());
19
19
  /**
20
20
  * Parse a handle ID to extract nodeId, direction, and portId.
21
21
  * Handle ID format: ${nodeId}-${direction}-${portId}
@@ -37,7 +37,7 @@ function parseHandleId(handleId) {
37
37
  }
38
38
  /**
39
39
  * Build a dataType lookup map from a node's ports.
40
- * Maps portId dataType for quick lookup when processing handle bounds.
40
+ * Maps portId -> dataType for quick lookup when processing handle bounds.
41
41
  */
42
42
  function buildPortDataTypeLookup(node) {
43
43
  const lookup = new Map();
@@ -64,7 +64,7 @@ function computeNodePortCoordinates(node, internalNode) {
64
64
  return [];
65
65
  const posAbs = internalNode.internals.positionAbsolute;
66
66
  const dataTypeLookup = buildPortDataTypeLookup(node);
67
- const coordinates = [];
67
+ const result = [];
68
68
  const allHandles = [...(handleBounds.source ?? []), ...(handleBounds.target ?? [])];
69
69
  for (const handle of allHandles) {
70
70
  if (!handle.id)
@@ -76,7 +76,7 @@ function computeNodePortCoordinates(node, internalNode) {
76
76
  const dataType = dataTypeLookup.get(lookupKey);
77
77
  if (!dataType)
78
78
  continue;
79
- coordinates.push({
79
+ result.push({
80
80
  x: posAbs.x + handle.x + handle.width / 2,
81
81
  y: posAbs.y + handle.y + handle.height / 2,
82
82
  handleId: handle.id,
@@ -85,7 +85,7 @@ function computeNodePortCoordinates(node, internalNode) {
85
85
  dataType
86
86
  });
87
87
  }
88
- return coordinates;
88
+ return result;
89
89
  }
90
90
  /**
91
91
  * Rebuild coordinates for ALL nodes from SvelteFlow internals.
@@ -95,7 +95,7 @@ function computeNodePortCoordinates(node, internalNode) {
95
95
  * @param getInternalNode - SvelteFlow's getInternalNode function
96
96
  */
97
97
  export function rebuildAllPortCoordinates(nodes, getInternalNode) {
98
- const map = new Map();
98
+ const map = new SvelteMap();
99
99
  for (const node of nodes) {
100
100
  const internalNode = getInternalNode(node.id);
101
101
  if (!internalNode)
@@ -105,7 +105,7 @@ export function rebuildAllPortCoordinates(nodes, getInternalNode) {
105
105
  map.set(coord.handleId, coord);
106
106
  }
107
107
  }
108
- portCoordinateStore.set(map);
108
+ coordinates = map;
109
109
  }
110
110
  /**
111
111
  * Update coordinates for a single node (efficient for drag updates).
@@ -118,21 +118,17 @@ export function updateNodePortCoordinates(node, getInternalNode) {
118
118
  const internalNode = getInternalNode(node.id);
119
119
  if (!internalNode)
120
120
  return;
121
- portCoordinateStore.update((map) => {
122
- // Remove old entries for this node
123
- for (const [key, coord] of map) {
124
- if (coord.nodeId === node.id) {
125
- map.delete(key);
126
- }
121
+ // Remove old entries for this node
122
+ for (const [key, coord] of coordinates) {
123
+ if (coord.nodeId === node.id) {
124
+ coordinates.delete(key);
127
125
  }
128
- // Add new entries
129
- const coords = computeNodePortCoordinates(node, internalNode);
130
- for (const coord of coords) {
131
- map.set(coord.handleId, coord);
132
- }
133
- // Return new reference for reactivity
134
- return new Map(map);
135
- });
126
+ }
127
+ // Add new entries
128
+ const coords = computeNodePortCoordinates(node, internalNode);
129
+ for (const coord of coords) {
130
+ coordinates.set(coord.handleId, coord);
131
+ }
136
132
  }
137
133
  /**
138
134
  * Remove all coordinates for a node (on node delete).
@@ -140,14 +136,11 @@ export function updateNodePortCoordinates(node, getInternalNode) {
140
136
  * @param nodeId - ID of the node to remove
141
137
  */
142
138
  export function removeNodePortCoordinates(nodeId) {
143
- portCoordinateStore.update((map) => {
144
- for (const [key, coord] of map) {
145
- if (coord.nodeId === nodeId) {
146
- map.delete(key);
147
- }
139
+ for (const [key, coord] of coordinates) {
140
+ if (coord.nodeId === nodeId) {
141
+ coordinates.delete(key);
148
142
  }
149
- return new Map(map);
150
- });
143
+ }
151
144
  }
152
145
  /**
153
146
  * Get coordinates for a specific handle.
@@ -156,7 +149,7 @@ export function removeNodePortCoordinates(nodeId) {
156
149
  * @returns The port coordinate or undefined if not found
157
150
  */
158
151
  export function getPortCoordinate(handleId) {
159
- return get(portCoordinateStore).get(handleId);
152
+ return coordinates.get(handleId);
160
153
  }
161
154
  /**
162
155
  * Get all coordinates for a specific node.
@@ -166,7 +159,7 @@ export function getPortCoordinate(handleId) {
166
159
  */
167
160
  export function getNodePortCoordinates(nodeId) {
168
161
  const result = [];
169
- for (const coord of get(portCoordinateStore).values()) {
162
+ for (const coord of coordinates.values()) {
170
163
  if (coord.nodeId === nodeId) {
171
164
  result.push(coord);
172
165
  }
@@ -174,10 +167,20 @@ export function getNodePortCoordinates(nodeId) {
174
167
  return result;
175
168
  }
176
169
  /**
177
- * Get the current snapshot of all port coordinates (non-reactive).
170
+ * Get the current snapshot of all port coordinates.
171
+ * Returns the reactive SvelteMap directly.
178
172
  *
179
173
  * @returns Current port coordinate map
180
174
  */
181
175
  export function getPortCoordinateSnapshot() {
182
- return get(portCoordinateStore);
176
+ return coordinates;
177
+ }
178
+ /**
179
+ * Get the reactive port coordinates state.
180
+ * Useful for components that need to reactively read the coordinates.
181
+ *
182
+ * @returns The reactive port coordinate map
183
+ */
184
+ export function getPortCoordinates() {
185
+ return coordinates;
183
186
  }