@kiberon-labs/behave-graph-flow 2.0.0 → 3.0.0

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 (251) hide show
  1. package/.storybook/manager.ts +6 -0
  2. package/.storybook/preview.ts +49 -1
  3. package/.storybook/styles.css +9 -3
  4. package/.turbo/turbo-build.log +1 -1
  5. package/CHANGELOG.md +368 -0
  6. package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
  7. package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
  8. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
  9. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
  10. package/dist/index.css +36 -33
  11. package/dist/index.css.map +1 -1
  12. package/dist/index.d.ts +1865 -550
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +14357 -11221
  15. package/dist/index.js.map +1 -1
  16. package/dist/noteImpl-KkrrWgJd.js +242 -0
  17. package/dist/noteImpl-KkrrWgJd.js.map +1 -0
  18. package/dist/styles.module-CvmpDkZj.css +3 -0
  19. package/dist/styles.module-CvmpDkZj.css.map +1 -0
  20. package/dist/styles.module-DZxg8aW9.js +271 -0
  21. package/dist/styles.module-DZxg8aW9.js.map +1 -0
  22. package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
  23. package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
  24. package/docs/protocol.md +43 -20
  25. package/package.json +5 -9
  26. package/src/components/FloatingToolbar/index.module.css +5 -13
  27. package/src/components/FloatingToolbar/index.tsx +9 -9
  28. package/src/components/Flow.tsx +34 -23
  29. package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
  30. package/src/components/contextMenus/NodePicker.module.css +13 -13
  31. package/src/components/contextMenus/edge.tsx +9 -95
  32. package/src/components/contextMenus/node.tsx +9 -149
  33. package/src/components/contextMenus/selection.tsx +5 -71
  34. package/src/components/controls/any/AnyControlImpl.tsx +14 -0
  35. package/src/components/controls/any/index.tsx +13 -2
  36. package/src/components/edges/index.tsx +75 -69
  37. package/src/components/layoutController/index.module.css +3 -0
  38. package/src/components/layoutController/index.tsx +24 -1
  39. package/src/components/layoutController/utils.ts +46 -3
  40. package/src/components/menubar/defaults.tsx +55 -19
  41. package/src/components/menubar/menuItem.module.css +18 -3
  42. package/src/components/menubar/menuItem.tsx +34 -1
  43. package/src/components/nodes/behave/NodeContainer.module.css +26 -25
  44. package/src/components/nodes/group/index.tsx +3 -3
  45. package/src/components/nodes/wrapper/styles.module.css +6 -32
  46. package/src/components/panels/alignment/index.module.css +0 -10
  47. package/src/components/panels/alignment/index.tsx +4 -4
  48. package/src/components/panels/base/styles.module.css +2 -2
  49. package/src/components/panels/common/PanelHeader.module.css +24 -0
  50. package/src/components/panels/common/PanelHeader.tsx +22 -0
  51. package/src/components/panels/common/SectionTitle.module.css +13 -0
  52. package/src/components/panels/common/SectionTitle.tsx +10 -0
  53. package/src/components/panels/events/EditEventPanel.tsx +14 -5
  54. package/src/components/panels/events/ManageEventsPanel.tsx +11 -8
  55. package/src/components/panels/events/styles.module.css +6 -64
  56. package/src/components/panels/graphProperties/index.tsx +125 -0
  57. package/src/components/panels/history/index.tsx +2 -2
  58. package/src/components/panels/history/styles.module.css +0 -9
  59. package/src/components/panels/keymaps/index.module.css +3 -13
  60. package/src/components/panels/keymaps/index.tsx +1 -2
  61. package/src/components/panels/layers/index.tsx +20 -15
  62. package/src/components/panels/layers/styles.module.css +9 -12
  63. package/src/components/panels/legend/index.tsx +1 -1
  64. package/src/components/panels/logs/index.module.css +25 -19
  65. package/src/components/panels/logs/index.tsx +7 -7
  66. package/src/components/panels/nodeInputs/InputsGroup.tsx +1 -0
  67. package/src/components/panels/nodeInputs/NodeSettings.tsx +2 -2
  68. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +1 -1
  69. package/src/components/panels/nodeInputs/OutputsGroup.tsx +2 -12
  70. package/src/components/panels/nodeInputs/index.module.css +99 -75
  71. package/src/components/panels/nodeInputs/index.tsx +21 -11
  72. package/src/components/panels/nodeInputs/useNodeHandlers.ts +2 -2
  73. package/src/components/panels/nodeInputs/useNodeInputsData.ts +23 -43
  74. package/src/components/panels/nodePicker/index.tsx +8 -8
  75. package/src/components/panels/panel/index.module.css +7 -7
  76. package/src/components/panels/search/index.module.css +0 -50
  77. package/src/components/panels/search/index.tsx +2 -2
  78. package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
  79. package/src/components/panels/systemSettings/index.tsx +221 -176
  80. package/src/components/panels/systemSettings/styles.module.css +135 -8
  81. package/src/components/panels/traces/GridLines.tsx +1 -1
  82. package/src/components/panels/traces/TimeGrid.tsx +3 -3
  83. package/src/components/panels/traces/TraceLane.tsx +1 -1
  84. package/src/components/panels/traces/index.module.css +1 -8
  85. package/src/components/panels/traces/index.tsx +8 -4
  86. package/src/components/panels/traces/useDerivedSpans.ts +241 -146
  87. package/src/components/panels/traces/utils.ts +8 -0
  88. package/src/components/panels/variables/CreateVariableScreen.tsx +3 -3
  89. package/src/components/panels/variables/ManageVariablesScreen.tsx +12 -9
  90. package/src/components/panels/variables/index.tsx +2 -2
  91. package/src/components/panels/variables/styles.module.css +4 -91
  92. package/src/components/primitives/icon.module.css +4 -4
  93. package/src/components/sockets/input/index.tsx +9 -2
  94. package/src/components/sockets/input/styles.module.css +2 -3
  95. package/src/components/sockets/output/index.tsx +10 -3
  96. package/src/components/sockets/output/styles.module.css +1 -6
  97. package/src/css/notes.css +135 -0
  98. package/src/css/prosemirror.css +3 -3
  99. package/src/css/rc-dock.css +143 -43
  100. package/src/css/rc-menu.css +56 -55
  101. package/src/css/themes/kiberon.css +127 -0
  102. package/src/css/vars.css +197 -13
  103. package/src/css/vscode-elements.css +124 -0
  104. package/src/generators/CallSubgraphGenerator.tsx +136 -0
  105. package/src/generators/CustomEventOnTriggeredGenerator.tsx +2 -2
  106. package/src/generators/GraphBoundaryGenerator.module.css +32 -0
  107. package/src/generators/GraphBoundaryGenerator.tsx +193 -0
  108. package/src/generators/SequenceGenerator.tsx +2 -2
  109. package/src/generators/SwitchOnIntegerGenerator.tsx +2 -2
  110. package/src/generators/SwitchOnStringGenerator.tsx +2 -2
  111. package/src/generators/callSubgraphSync.ts +126 -0
  112. package/src/generators/registerDefaultGenerators.ts +21 -0
  113. package/src/generators/registerDefaults.ts +26 -0
  114. package/src/hooks/useBehaveGraphFlow.ts +2 -2
  115. package/src/hooks/useFlowHandlers.ts +47 -9
  116. package/src/hooks/useWasdPan.ts +26 -4
  117. package/src/index.css +4 -16
  118. package/src/index.ts +17 -0
  119. package/src/manifest/contributionRegistry.ts +93 -0
  120. package/src/manifest/index.ts +4 -0
  121. package/src/manifest/loadManifest.ts +82 -0
  122. package/src/manifest/manifestPlugin.ts +29 -0
  123. package/src/manifest/passthroughValueType.ts +40 -0
  124. package/src/plugin/alignment/index.ts +22 -12
  125. package/src/plugin/autosave/controller.ts +366 -0
  126. package/src/plugin/autosave/index.tsx +114 -0
  127. package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
  128. package/src/plugin/autosave/panel/index.tsx +1 -0
  129. package/src/plugin/autosave/panel/styles.module.css +56 -0
  130. package/src/plugin/autosave/settings.ts +65 -0
  131. package/src/plugin/autosave/storage.ts +147 -0
  132. package/src/plugin/docs/index.tsx +2 -4
  133. package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
  134. package/src/plugin/docs/panel/index.tsx +15 -194
  135. package/src/plugin/docs/panel/styles.module.css +8 -8
  136. package/src/plugin/graphrunner/actions.ts +258 -185
  137. package/src/plugin/graphrunner/buttons.tsx +34 -26
  138. package/src/plugin/graphrunner/client.ts +4 -1
  139. package/src/plugin/graphrunner/index.tsx +29 -100
  140. package/src/plugin/graphrunner/panel.tsx +2 -2
  141. package/src/plugin/graphrunner/runController.ts +283 -0
  142. package/src/plugin/graphrunner/runner.ts +21 -192
  143. package/src/plugin/graphrunner/store.ts +14 -24
  144. package/src/plugin/graphrunner/styles.module.css +17 -57
  145. package/src/plugin/graphrunner/transport.ts +26 -0
  146. package/src/plugin/graphrunner/types.ts +21 -0
  147. package/src/plugin/graphrunner-local/execution-utils.ts +260 -80
  148. package/src/plugin/graphrunner-local/index.tsx +8 -2
  149. package/src/plugin/graphrunner-local/panel.tsx +131 -175
  150. package/src/plugin/graphrunner-local/styles.module.css +57 -76
  151. package/src/plugin/graphrunner-local/transport.ts +151 -184
  152. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +2 -0
  153. package/src/plugin/graphrunner-webworker/index.tsx +4 -10
  154. package/src/plugin/graphrunner-webworker/store.ts +9 -0
  155. package/src/plugin/kitchen-sink/index.ts +38 -0
  156. package/src/{layout/dagre.tsx → plugin/layout/dagre.ts} +17 -5
  157. package/src/{layout → plugin/layout}/elk.ts +22 -6
  158. package/src/plugin/layout/index.ts +80 -0
  159. package/src/plugin/notes/FormatToolbar.tsx +200 -0
  160. package/src/plugin/notes/index.tsx +191 -0
  161. package/src/plugin/notes/nodeActions.ts +100 -0
  162. package/src/plugin/notes/note.tsx +20 -0
  163. package/src/plugin/notes/noteImpl.tsx +89 -0
  164. package/src/plugin/realtime/realtimeRunner.ts +58 -4
  165. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +2 -2
  166. package/src/specifics/CustomEventTriggerSpecific.tsx +2 -2
  167. package/src/specifics/VariableGetSpecific.tsx +2 -2
  168. package/src/specifics/VariableSetSpecific.tsx +2 -2
  169. package/src/store/actions.tsx +5 -5
  170. package/src/store/commands.ts +278 -0
  171. package/src/store/contextMenu.ts +192 -0
  172. package/src/store/conversions.ts +47 -0
  173. package/src/store/flow.tsx +23 -38
  174. package/src/store/graphMeta.ts +39 -0
  175. package/src/store/hotKeys.tsx +301 -260
  176. package/src/store/layers.ts +3 -3
  177. package/src/store/registry.ts +12 -4
  178. package/src/store/selection.ts +3 -3
  179. package/src/store/settings.ts +82 -82
  180. package/src/store/settingsSchema.ts +210 -0
  181. package/src/store/tabs.ts +5 -1
  182. package/src/store/traces.ts +3 -3
  183. package/src/system/graph.ts +11 -14
  184. package/src/system/graphSession.ts +172 -0
  185. package/src/system/index.ts +3 -0
  186. package/src/system/notifications.ts +13 -0
  187. package/src/system/persistence.ts +82 -0
  188. package/src/system/plugin.ts +28 -0
  189. package/src/system/provider.tsx +64 -0
  190. package/src/system/system.ts +518 -88
  191. package/src/system/tabLoader.tsx +70 -32
  192. package/src/system/undoRedo.ts +1 -1
  193. package/src/transformers/Uigraph.ts +5 -4
  194. package/src/transformers/contract.ts +87 -0
  195. package/src/transformers/flowToBehave.ts +13 -5
  196. package/src/types/nodes.ts +8 -3
  197. package/src/types.ts +2 -0
  198. package/src/util/autoConvert.ts +200 -0
  199. package/src/util/isValidConnection.ts +23 -2
  200. package/stories/defaults/defaultStoryProvider.tsx +17 -14
  201. package/stories/defaults/systemGenerator.ts +6 -1
  202. package/stories/{components/nodes/comment.stories.tsx → plugins/notes.stories.tsx} +24 -30
  203. package/tests/autoConvert.test.ts +329 -0
  204. package/tests/autosavePlugin.test.ts +204 -0
  205. package/tests/callSubgraphSync.test.ts +148 -0
  206. package/tests/commandRegistry.test.ts +137 -0
  207. package/tests/contract.test.ts +51 -0
  208. package/tests/contractSerialize.test.ts +62 -0
  209. package/tests/deriveSpans.test.ts +71 -0
  210. package/tests/flowToBehave.test.ts +2 -1
  211. package/tests/hotkeys.test.ts +79 -0
  212. package/tests/keepAliveLifecycle.test.ts +167 -0
  213. package/tests/loadManifest.test.ts +113 -0
  214. package/tests/noteMarkdown.test.ts +65 -0
  215. package/tests/notesPlugin.test.ts +162 -0
  216. package/tests/persistence.test.ts +51 -0
  217. package/tests/saveLoad.test.ts +7 -6
  218. package/tests/settings.test.ts +178 -0
  219. package/tests/traceStore.test.ts +46 -0
  220. package/tests/visual/README.md +2 -2
  221. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  222. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  223. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  224. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  225. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  226. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  227. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
  228. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  229. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  230. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  231. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  232. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  233. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  234. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  235. package/tests/visual/panels.visual.test.tsx +3 -3
  236. package/tests/wasdPan.test.ts +71 -0
  237. package/vitest.config.ts +1 -1
  238. package/vitest.visual.config.ts +7 -0
  239. package/.storybook/vscode.css +0 -814
  240. package/src/components/nodes/comment/FormatToolbar.tsx +0 -118
  241. package/src/components/nodes/comment/comment.tsx +0 -103
  242. package/src/components/nodes/comment/styles.module.css +0 -150
  243. package/src/components/panels/conversation/index.module.css +0 -151
  244. package/src/components/panels/conversation/index.tsx +0 -162
  245. package/src/components/panels/events/CustomEventsEditor.tsx +0 -384
  246. package/src/css/vscode.css +0 -13
  247. package/src/hooks/useDetachNodes.ts +0 -39
  248. package/src/plugin/graphrunner-webworker/types.ts +0 -17
  249. package/src/specifics/registerDefaultSpecifics.ts +0 -5
  250. package/src/store/chat.ts +0 -73
  251. package/src/store/graphRunnerClient.ts +0 -110
@@ -2,8 +2,8 @@ import type { System } from '../../system/system';
2
2
  import type { StoreApi } from 'zustand';
3
3
  import type { GraphRunnerClientStore } from './store';
4
4
  import { GraphRunnerClient } from './client';
5
- import { buildUIGraphJSON } from '../../transformers/Uigraph';
6
5
  import { setupClientEventListeners } from './actions';
6
+ import type { GraphRunController } from './runController';
7
7
 
8
8
  declare module '@/system/system' {
9
9
  interface System {
@@ -11,15 +11,32 @@ declare module '@/system/system' {
11
11
  }
12
12
  }
13
13
 
14
+ /**
15
+ * Shared connection to the graph runner server. Owns the client, connection
16
+ * lifecycle and server metadata; per-graph run state and run lifecycle live on
17
+ * {@link GraphRunController}. Incoming server messages are dispatched back to the
18
+ * owning controller via {@link GraphRunner.runIndex}, keyed by run id, so
19
+ * multiple graphs can run concurrently and independently.
20
+ */
14
21
  export class GraphRunner {
15
22
  private system: System;
16
23
  public readonly store: StoreApi<GraphRunnerClientStore>;
24
+ /** runId -> the controller that started it. */
25
+ public readonly runIndex = new Map<string, GraphRunController>();
17
26
 
18
27
  constructor(system: System, store: StoreApi<GraphRunnerClientStore>) {
19
28
  this.system = system;
20
29
  this.store = store;
21
30
  }
22
31
 
32
+ registerRun(runId: string, controller: GraphRunController): void {
33
+ this.runIndex.set(runId, controller);
34
+ }
35
+
36
+ unregisterRun(runId: string): void {
37
+ this.runIndex.delete(runId);
38
+ }
39
+
23
40
  /**
24
41
  * Connect to the graph runner server
25
42
  */
@@ -54,8 +71,9 @@ export class GraphRunner {
54
71
 
55
72
  await theClient.connect();
56
73
 
57
- // Setup persistent event listeners for trace, logs, and run completion
58
- setupClientEventListeners(theClient, this.system, this.store);
74
+ // Setup persistent event listeners for trace, logs, and run completion.
75
+ // Messages are routed to the originating session by run id.
76
+ setupClientEventListeners(theClient, this);
59
77
 
60
78
  setConnectionState('connected');
61
79
  setConnectionInfo({
@@ -166,193 +184,4 @@ export class GraphRunner {
166
184
  setError(error instanceof Error ? error.message : String(error));
167
185
  }
168
186
  }
169
-
170
- /**
171
- * Run a graph remotely
172
- */
173
- async runRemotely(
174
- graphId: string,
175
- options?: { graph?: unknown; inputs?: unknown }
176
- ): Promise<void> {
177
- const {
178
- client,
179
- setCurrentRunId,
180
- setCurrentGraphId,
181
- setIsExecuting,
182
- setIsPaused,
183
- isExecuting,
184
- enableTracing
185
- } = this.store.getState();
186
-
187
- if (!client) {
188
- this.system.notifications.error('No graph runner connection');
189
- throw new Error('No graph runner connection');
190
- }
191
- //already running
192
- if (isExecuting) {
193
- return;
194
- }
195
-
196
- try {
197
- const runId = await client.runGraph(graphId, {
198
- ...options,
199
- trace: enableTracing
200
- });
201
-
202
- setCurrentRunId(runId);
203
- setCurrentGraphId(graphId);
204
- setIsExecuting(true);
205
- setIsPaused(false);
206
-
207
- this.system.notifications.info(`Graph execution started: ${graphId}`);
208
- } catch (error) {
209
- const errorMessage =
210
- error instanceof Error ? error.message : String(error);
211
- setIsPaused(false);
212
- this.system.notifications.error(`Failed to run graph: ${errorMessage}`);
213
- setIsExecuting(false);
214
- setCurrentRunId(null);
215
- setCurrentGraphId(null);
216
- throw error;
217
- }
218
- }
219
-
220
- /**
221
- * Stop the current graph execution
222
- */
223
- async stop(): Promise<void> {
224
- const {
225
- client,
226
- currentRunId,
227
- setIsExecuting,
228
- setCurrentRunId,
229
- setCurrentGraphId,
230
- setIsPaused
231
- } = this.store.getState();
232
-
233
- if (!client || !currentRunId) {
234
- return;
235
- }
236
-
237
- try {
238
- await client.stopGraph(currentRunId);
239
- this.system.notifications.info('Stopping graph execution');
240
- setIsExecuting(false);
241
- setCurrentRunId(null);
242
- setCurrentGraphId(null);
243
- setIsPaused(false);
244
- } catch (error) {
245
- const errorMessage =
246
- error instanceof Error ? error.message : String(error);
247
- this.system.notifications.error(`Failed to stop graph: ${errorMessage}`);
248
- }
249
- }
250
-
251
- /**
252
- * Play the current graph
253
- */
254
- async play(): Promise<void> {
255
- const { clearLogsOnRun, clearTracesOnRun } = this.store.getState();
256
-
257
- // Clear logs if enabled
258
- if (clearLogsOnRun) {
259
- this.system.logsStore.getState().clear();
260
- }
261
-
262
- // Clear traces if enabled
263
- if (clearTracesOnRun) {
264
- this.system.traceStore.getState().clear();
265
- }
266
-
267
- const graphId = 'current';
268
- const uiGraphData = buildUIGraphJSON(this.system);
269
- const graphData = uiGraphData.flow;
270
-
271
- try {
272
- await this.runRemotely(graphId, { graph: graphData });
273
- } catch {
274
- // Error already handled in runRemotely
275
- }
276
- }
277
-
278
- /**
279
- * Pause the current graph execution
280
- */
281
- async pause(): Promise<void> {
282
- const { client, currentRunId, setIsPaused } = this.store.getState();
283
-
284
- if (!client || !currentRunId) {
285
- return;
286
- }
287
-
288
- try {
289
- // Check if the client's transport is LocalTransport with pause support
290
- const transport = (client as any).transport;
291
- if (transport && typeof transport.pauseExecution === 'function') {
292
- transport.pauseExecution(currentRunId);
293
- setIsPaused(true);
294
- this.system.notifications.info('Execution paused');
295
- } else {
296
- // Fallback to stop for remote transports
297
- await this.stop();
298
- }
299
- } catch (error) {
300
- const errorMessage =
301
- error instanceof Error ? error.message : String(error);
302
- this.system.notifications.error(`Failed to pause graph: ${errorMessage}`);
303
- }
304
- }
305
-
306
- /**
307
- * Resume paused execution
308
- */
309
- async resume(): Promise<void> {
310
- const { client, currentRunId, setIsPaused } = this.store.getState();
311
-
312
- if (!client || !currentRunId) {
313
- return;
314
- }
315
-
316
- try {
317
- const transport = (client as any).transport;
318
- if (transport && typeof transport.resumeExecution === 'function') {
319
- setIsPaused(false);
320
- this.system.notifications.info('Resuming execution');
321
- await transport.resumeExecution(currentRunId);
322
- }
323
- } catch (error) {
324
- const errorMessage =
325
- error instanceof Error ? error.message : String(error);
326
- this.system.notifications.error(
327
- `Failed to resume graph: ${errorMessage}`
328
- );
329
- }
330
- }
331
-
332
- /**
333
- * Execute one step forward
334
- */
335
- async step(): Promise<void> {
336
- const { client, currentRunId, setIsPaused } = this.store.getState();
337
-
338
- if (!client || !currentRunId) {
339
- return;
340
- }
341
-
342
- try {
343
- const transport = (client as any).transport;
344
- if (transport && typeof transport.stepExecution === 'function') {
345
- setIsPaused(true); // Ensure we stay paused after stepping
346
- await transport.stepExecution(currentRunId);
347
- } else {
348
- this.system.notifications.info(
349
- 'Step execution not supported for this transport'
350
- );
351
- }
352
- } catch (error) {
353
- const errorMessage =
354
- error instanceof Error ? error.message : String(error);
355
- this.system.notifications.error(`Failed to step graph: ${errorMessage}`);
356
- }
357
- }
358
187
  }
@@ -55,13 +55,7 @@ export interface GraphRunnerClientStore {
55
55
  messageActivity: MessageActivity[];
56
56
  maxActivityMessages: number;
57
57
 
58
- // Execution state
59
- currentRunId: string | null;
60
- currentGraphId: string | null;
61
- isExecuting: boolean;
62
- isPaused: boolean;
63
-
64
- // Execution preferences
58
+ // Execution preferences (global defaults applied to every run)
65
59
  clearLogsOnRun: boolean;
66
60
  clearTracesOnRun: boolean;
67
61
  enableTracing: boolean;
@@ -83,10 +77,6 @@ export interface GraphRunnerClientStore {
83
77
  message: GraphRunnerMessage
84
78
  ) => void;
85
79
  clearMessageActivity: () => void;
86
- setCurrentRunId: (runId: string | null) => void;
87
- setCurrentGraphId: (graphId: string | null) => void;
88
- setIsExecuting: (isExecuting: boolean) => void;
89
- setIsPaused: (isPaused: boolean) => void;
90
80
  setClearLogsOnRun: (clear: boolean) => void;
91
81
  setClearTracesOnRun: (clear: boolean) => void;
92
82
  setEnableTracing: (enable: boolean) => void;
@@ -117,13 +107,12 @@ export const graphRunnerClientStoreFactory = (
117
107
  nodeTypes: [],
118
108
  messageActivity: [],
119
109
  maxActivityMessages: 50,
120
- currentRunId: null,
121
- currentGraphId: null,
122
- isExecuting: false,
123
- isPaused: false,
124
110
  clearLogsOnRun: true,
125
111
  clearTracesOnRun: true,
126
- enableTracing: true,
112
+ // Off by default: tracing costs two events per node execution and is the
113
+ // single biggest per-frame overhead for display-rate graphs. Opt in via the
114
+ // "Enable execution tracing" checkbox in the graph runner panel.
115
+ enableTracing: false,
127
116
 
128
117
  // Actions
129
118
  setConnectionConfig: (config) =>
@@ -174,6 +163,15 @@ export const graphRunnerClientStoreFactory = (
174
163
 
175
164
  addMessageActivity: (direction, message) =>
176
165
  set((state) => {
166
+ // Trace traffic is high-frequency (per node execution / per frame) and
167
+ // has its own dedicated panel; recording it here allocated a new
168
+ // activity array per event and instantly evicted every other message
169
+ // from the 50-entry ring. Received server messages are cast into this
170
+ // union by the callers, so compare the raw type string.
171
+ const type = (message as { type: string }).type;
172
+ if (type === 'trace' || type === 'traceBatch') {
173
+ return state;
174
+ }
177
175
  const activity: MessageActivity = {
178
176
  id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
179
177
  timestamp: Date.now(),
@@ -189,14 +187,6 @@ export const graphRunnerClientStoreFactory = (
189
187
 
190
188
  clearMessageActivity: () => set({ messageActivity: [] }),
191
189
 
192
- setCurrentRunId: (currentRunId) => set({ currentRunId }),
193
-
194
- setCurrentGraphId: (currentGraphId) => set({ currentGraphId }),
195
-
196
- setIsExecuting: (isExecuting) => set({ isExecuting }),
197
-
198
- setIsPaused: (isPaused) => set({ isPaused }),
199
-
200
190
  setClearLogsOnRun: (clearLogsOnRun) => set({ clearLogsOnRun }),
201
191
 
202
192
  setClearTracesOnRun: (clearTracesOnRun) => set({ clearTracesOnRun }),
@@ -44,18 +44,18 @@
44
44
 
45
45
  .errorBox {
46
46
  padding: 0.75rem;
47
- background-color: var(--vscode-inputValidation-errorBackground);
48
- border: 1px solid var(--vscode-inputValidation-errorBorder);
47
+ background-color: var(--ds-error-bg);
48
+ border: 1px solid var(--ds-error-border);
49
49
  border-radius: 4px;
50
50
  font-size: 0.875rem;
51
- color: var(--vscode-inputValidation-errorForeground);
51
+ color: var(--ds-error-fg);
52
52
  word-break: break-word;
53
53
  }
54
54
 
55
55
  .infoBox {
56
56
  padding: 0.75rem;
57
- background-color: var(--vscode-inputValidation-infoBackground);
58
- border: 1px solid var(--vscode-inputValidation-infoBorder);
57
+ background-color: var(--ds-info-bg);
58
+ border: 1px solid var(--ds-info-border);
59
59
  border-radius: 4px;
60
60
  font-size: 0.875rem;
61
61
  display: flex;
@@ -67,24 +67,6 @@
67
67
  word-break: break-word;
68
68
  }
69
69
 
70
- .tabs {
71
- border-bottom: 1px solid var(--vscode-panel-border);
72
- overflow-x: auto;
73
- gap: 0.25rem;
74
- }
75
-
76
-
77
- .tabContent {
78
- flex: 1;
79
- min-height: 0;
80
- display: flex;
81
- flex-direction: column;
82
- }
83
-
84
- .tabPanel {
85
- overflow: auto;
86
- }
87
-
88
70
  .tabPanelGap {
89
71
  overflow: auto;
90
72
  display: flex;
@@ -99,28 +81,19 @@
99
81
  gap: 0.75rem;
100
82
  }
101
83
 
102
- .connectionMessage {
103
- font-size: 0.875rem;
104
- padding: 0.5rem 0;
105
- }
106
-
107
- .connectionMessage p {
108
- margin: 0;
109
- }
110
-
111
84
  .emptyMessage {
112
85
  font-size: 0.875rem;
113
- color: var(--vscode-descriptionForeground);
86
+ color: var(--ds-fg-muted);
114
87
  margin: 0;
115
88
  }
116
89
 
117
90
  .codeBlock {
118
91
  font-size: 0.75rem;
119
- font-family: var(--vscode-editor-font-family);
120
- color: var(--vscode-editor-foreground);
92
+ font-family: var(--ds-font-mono);
93
+ color: var(--ds-editor-fg);
121
94
  margin: 0;
122
95
  padding: 0.5rem;
123
- background-color: var(--vscode-textCodeBlock-background);
96
+ background-color: var(--ds-code-bg);
124
97
  border-radius: 2px;
125
98
  overflow: auto;
126
99
  }
@@ -133,22 +106,22 @@
133
106
  gap: 0.5rem;
134
107
  position: sticky;
135
108
  top: 0;
136
- background-color: var(--vscode-editor-background);
109
+ background-color: var(--ds-editor-bg);
137
110
  padding-bottom: 0.5rem;
138
- border-bottom: 1px solid var(--vscode-panel-border);
111
+ border-bottom: 1px solid var(--ds-panel-border);
139
112
  z-index: 1;
140
113
  }
141
114
 
142
115
  .messagesCount {
143
116
  font-size: 0.875rem;
144
- color: var(--vscode-descriptionForeground);
117
+ color: var(--ds-fg-muted);
145
118
  }
146
119
 
147
120
  .messageCard {
148
121
  padding: 0.75rem;
149
- border: 1px solid var(--vscode-panel-border);
122
+ border: 1px solid var(--ds-panel-border);
150
123
  border-radius: 4px;
151
- background-color: var(--vscode-editor-background);
124
+ background-color: var(--ds-editor-bg);
152
125
  font-size: 0.875rem;
153
126
  }
154
127
 
@@ -176,7 +149,7 @@
176
149
  }
177
150
 
178
151
  .messageTime {
179
- color: var(--vscode-descriptionForeground);
152
+ color: var(--ds-fg-muted);
180
153
  font-size: 0.75rem;
181
154
  white-space: nowrap;
182
155
  }
@@ -184,28 +157,15 @@
184
157
  .messageContent {
185
158
  margin: 0;
186
159
  padding: 0.5rem;
187
- background-color: var(--vscode-textCodeBlock-background);
160
+ background-color: var(--ds-code-bg);
188
161
  border-radius: 2px;
189
162
  font-size: 0.75rem;
190
- font-family: var(--vscode-editor-font-family);
163
+ font-family: var(--ds-font-mono);
191
164
  overflow: auto;
192
165
  max-height: 200px;
193
166
  word-break: break-all;
194
167
  }
195
168
 
196
- .treeItemContent {
197
- display: flex;
198
- flex-direction: column;
199
- gap: 0.25rem;
200
- padding: 0.25rem 0;
201
- }
202
-
203
169
  .treeItemTitle {
204
170
  font-weight: 500;
205
- }
206
-
207
- .treeItemDescription {
208
- font-size: 0.875rem;
209
- color: var(--vscode-descriptionForeground);
210
- margin-top: 0.25rem;
211
171
  }
@@ -61,6 +61,32 @@ export interface ITransport<
61
61
  */
62
62
  removeAllHandlers(): void;
63
63
  }
64
+
65
+ /**
66
+ * Optional capability: a transport that can interactively control a run
67
+ * (pause / resume / step). Remote transports may not support it; the client
68
+ * detects support via {@link supportsExecutionControl} rather than reaching into
69
+ * transport internals.
70
+ */
71
+ export interface IExecutionControl {
72
+ pauseExecution(runId: string): void;
73
+ resumeExecution(runId: string): Promise<void>;
74
+ stepExecution(runId: string): Promise<void>;
75
+ isPaused(runId: string): boolean;
76
+ }
77
+
78
+ /** Type guard: does this transport implement {@link IExecutionControl}? */
79
+ export function supportsExecutionControl(
80
+ transport: unknown
81
+ ): transport is IExecutionControl {
82
+ return (
83
+ !!transport &&
84
+ typeof (transport as IExecutionControl).pauseExecution === 'function' &&
85
+ typeof (transport as IExecutionControl).resumeExecution === 'function' &&
86
+ typeof (transport as IExecutionControl).stepExecution === 'function'
87
+ );
88
+ }
89
+
64
90
  /**
65
91
  * WebSocket transport implementation
66
92
  */
@@ -184,6 +184,26 @@ export interface TraceMessage {
184
184
  timestamp: number;
185
185
  }
186
186
 
187
+ /** A single node-execution event inside a {@link TraceBatchMessage}. */
188
+ export interface TraceBatchEvent {
189
+ nodeId: string;
190
+ event: string;
191
+ data?: unknown;
192
+ timestamp: number;
193
+ }
194
+
195
+ /**
196
+ * Coalesced trace events for one run. Runners buffer per-node execution events
197
+ * and flush them roughly once per frame, so a tick that executes hundreds of
198
+ * nodes costs one message instead of hundreds.
199
+ */
200
+ export interface TraceBatchMessage {
201
+ type: 'traceBatch';
202
+ runId: string;
203
+ graphId: string;
204
+ events: TraceBatchEvent[];
205
+ }
206
+
187
207
  export interface LogMessage {
188
208
  type: 'log';
189
209
  runId: string;
@@ -289,6 +309,7 @@ export type ServerGraphRunnerMessage =
289
309
  | ValidationResultMessage
290
310
  // Events
291
311
  | TraceMessage
312
+ | TraceBatchMessage
292
313
  | LogMessage
293
314
  | VariableChangedMessage
294
315
  | CompletedMessage