project-graph-mcp 2.3.1 → 2.4.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 (226) hide show
  1. package/package.json +3 -2
  2. package/src/analysis/analysis-cache.ctx +9 -0
  3. package/src/analysis/analysis-cache.js +1 -1
  4. package/src/analysis/complexity.ctx +6 -0
  5. package/src/analysis/complexity.js +1 -1
  6. package/src/analysis/custom-rules.ctx +14 -0
  7. package/src/analysis/custom-rules.js +1 -1
  8. package/src/analysis/db-analysis.ctx +7 -0
  9. package/src/analysis/db-analysis.js +1 -1
  10. package/src/analysis/dead-code.ctx +6 -0
  11. package/src/analysis/dead-code.js +1 -1
  12. package/src/analysis/full-analysis.ctx +9 -0
  13. package/src/analysis/full-analysis.js +1 -1
  14. package/src/analysis/jsdoc-checker.ctx +10 -0
  15. package/src/analysis/jsdoc-checker.js +1 -1
  16. package/src/analysis/jsdoc-generator.ctx +9 -0
  17. package/src/analysis/jsdoc-generator.js +1 -1
  18. package/src/analysis/large-files.ctx +6 -0
  19. package/src/analysis/large-files.js +1 -1
  20. package/src/analysis/outdated-patterns.ctx +7 -0
  21. package/src/analysis/outdated-patterns.js +1 -1
  22. package/src/analysis/similar-functions.ctx +6 -0
  23. package/src/analysis/similar-functions.js +1 -1
  24. package/src/analysis/test-annotations.ctx +11 -0
  25. package/src/analysis/test-annotations.js +1 -1
  26. package/src/analysis/type-checker.ctx +6 -0
  27. package/src/analysis/type-checker.js +1 -1
  28. package/src/analysis/undocumented.ctx +8 -0
  29. package/src/analysis/undocumented.js +1 -1
  30. package/src/cli/cli-handlers.ctx +7 -0
  31. package/src/cli/cli-handlers.js +1 -1
  32. package/src/cli/cli.ctx +6 -0
  33. package/src/cli/cli.js +1 -1
  34. package/src/compact/ai-context.ctx +6 -0
  35. package/src/compact/ai-context.js +1 -1
  36. package/src/compact/compact-migrate.ctx +8 -0
  37. package/src/compact/compact-migrate.js +1 -1
  38. package/src/compact/compact.ctx +11 -0
  39. package/src/compact/compact.js +1 -1
  40. package/src/compact/compress.ctx +7 -0
  41. package/src/compact/compress.js +1 -1
  42. package/src/compact/ctx-resolver.ctx +2 -0
  43. package/src/compact/ctx-resolver.js +1 -1
  44. package/src/compact/ctx-to-jsdoc.ctx +11 -0
  45. package/src/compact/ctx-to-jsdoc.js +1 -1
  46. package/src/compact/doc-dialect.ctx +11 -0
  47. package/src/compact/doc-dialect.js +2 -2
  48. package/src/compact/expand.ctx +14 -0
  49. package/src/compact/expand.js +1 -1
  50. package/src/compact/framework-references.ctx +7 -0
  51. package/src/compact/framework-references.js +1 -1
  52. package/src/compact/instructions.ctx +6 -0
  53. package/src/compact/instructions.js +1 -1
  54. package/src/compact/jsdoc-builder.ctx +4 -0
  55. package/src/compact/jsdoc-builder.js +1 -1
  56. package/src/compact/mode-config.ctx +8 -0
  57. package/src/compact/mode-config.js +1 -1
  58. package/src/compact/split-declarations.ctx +6 -0
  59. package/src/compact/split-declarations.js +1 -1
  60. package/src/compact/validate-pipeline.ctx +12 -0
  61. package/src/compact/validate-pipeline.js +1 -1
  62. package/src/core/event-bus.ctx +9 -0
  63. package/src/core/event-bus.js +1 -1
  64. package/src/core/file-walker.ctx +1 -0
  65. package/src/core/file-walker.js +1 -1
  66. package/src/core/filters.ctx +12 -0
  67. package/src/core/filters.js +1 -1
  68. package/src/core/graph-builder.ctx +7 -0
  69. package/src/core/graph-builder.js +1 -1
  70. package/src/core/parser.ctx +12 -0
  71. package/src/core/parser.js +1 -1
  72. package/src/core/utils.ctx +1 -0
  73. package/src/core/utils.js +1 -1
  74. package/src/core/workspace.ctx +7 -0
  75. package/src/core/workspace.js +1 -1
  76. package/src/lang/lang-go.ctx +8 -0
  77. package/src/lang/lang-go.js +1 -1
  78. package/src/lang/lang-python.ctx +5 -0
  79. package/src/lang/lang-python.js +1 -1
  80. package/src/lang/lang-sql.ctx +10 -0
  81. package/src/lang/lang-sql.js +1 -1
  82. package/src/lang/lang-typescript.ctx +6 -0
  83. package/src/lang/lang-typescript.js +1 -1
  84. package/src/lang/lang-utils.ctx +5 -0
  85. package/src/lang/lang-utils.js +1 -1
  86. package/src/mcp/mcp-server.ctx +6 -0
  87. package/src/mcp/mcp-server.js +1 -1
  88. package/src/mcp/tool-defs.ctx +2 -0
  89. package/src/mcp/tool-defs.js +1 -1
  90. package/src/mcp/tools.ctx +13 -0
  91. package/src/mcp/tools.js +1 -1
  92. package/src/network/backend-lifecycle.ctx +10 -0
  93. package/src/network/backend-lifecycle.js +1 -1
  94. package/src/network/backend.ctx +5 -0
  95. package/src/network/backend.js +1 -1
  96. package/src/network/local-gateway.ctx +9 -0
  97. package/src/network/local-gateway.js +1 -1
  98. package/src/network/mdns.ctx +6 -0
  99. package/src/network/mdns.js +1 -1
  100. package/src/network/server.ctx +2 -0
  101. package/src/network/server.js +2 -2
  102. package/src/network/web-server.ctx +17 -0
  103. package/src/network/web-server.js +2 -2
  104. package/web/follow-controller.js +94 -25
  105. package/web/panels/dep-graph.js +207 -21
  106. package/project-graph-mcp-2.3.0.tgz +0 -0
  107. package/vendor/symbiote-node/CHANGELOG.md +0 -31
  108. package/vendor/symbiote-node/LICENSE +0 -21
  109. package/vendor/symbiote-node/README.md +0 -206
  110. package/vendor/symbiote-node/canvas/AutoLayout.js +0 -725
  111. package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.css.js +0 -73
  112. package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.js +0 -93
  113. package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.tpl.js +0 -9
  114. package/vendor/symbiote-node/canvas/CanvasConnectionRenderer.js +0 -962
  115. package/vendor/symbiote-node/canvas/ConnectionRenderer.js +0 -1468
  116. package/vendor/symbiote-node/canvas/FlowSimulator.js +0 -323
  117. package/vendor/symbiote-node/canvas/ForceLayout.js +0 -189
  118. package/vendor/symbiote-node/canvas/ForceWorker.js +0 -1325
  119. package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.css.js +0 -97
  120. package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.js +0 -176
  121. package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.tpl.js +0 -12
  122. package/vendor/symbiote-node/canvas/LODManager.js +0 -88
  123. package/vendor/symbiote-node/canvas/Minimap/Minimap.css.js +0 -71
  124. package/vendor/symbiote-node/canvas/Minimap/Minimap.js +0 -207
  125. package/vendor/symbiote-node/canvas/Minimap/Minimap.tpl.js +0 -9
  126. package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.css.js +0 -261
  127. package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.js +0 -1840
  128. package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.tpl.js +0 -22
  129. package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.css.js +0 -97
  130. package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.js +0 -132
  131. package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.tpl.js +0 -21
  132. package/vendor/symbiote-node/canvas/NodeViewManager.js +0 -584
  133. package/vendor/symbiote-node/canvas/PinExpansion.js +0 -131
  134. package/vendor/symbiote-node/canvas/PseudoConnection.js +0 -80
  135. package/vendor/symbiote-node/canvas/SubgraphManager.js +0 -201
  136. package/vendor/symbiote-node/canvas/SubgraphRouter.js +0 -443
  137. package/vendor/symbiote-node/canvas/ViewportActions.js +0 -446
  138. package/vendor/symbiote-node/core/Connection.js +0 -45
  139. package/vendor/symbiote-node/core/Editor.js +0 -451
  140. package/vendor/symbiote-node/core/Frame.js +0 -31
  141. package/vendor/symbiote-node/core/GraphMermaid.js +0 -348
  142. package/vendor/symbiote-node/core/GraphText.js +0 -210
  143. package/vendor/symbiote-node/core/Node.js +0 -143
  144. package/vendor/symbiote-node/core/Portal.js +0 -104
  145. package/vendor/symbiote-node/core/Socket.js +0 -185
  146. package/vendor/symbiote-node/core/SubgraphNode.js +0 -125
  147. package/vendor/symbiote-node/index.js +0 -103
  148. package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.css.js +0 -361
  149. package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.js +0 -332
  150. package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.tpl.js +0 -96
  151. package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.css.js +0 -104
  152. package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.js +0 -133
  153. package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.tpl.js +0 -33
  154. package/vendor/symbiote-node/interactions/ConnectFlow.js +0 -307
  155. package/vendor/symbiote-node/interactions/Drag.js +0 -102
  156. package/vendor/symbiote-node/interactions/Selector.js +0 -132
  157. package/vendor/symbiote-node/interactions/SnapGrid.js +0 -65
  158. package/vendor/symbiote-node/interactions/Zoom.js +0 -140
  159. package/vendor/symbiote-node/layout/ActionZone/ActionZone.css.js +0 -88
  160. package/vendor/symbiote-node/layout/ActionZone/ActionZone.js +0 -254
  161. package/vendor/symbiote-node/layout/ActionZone/ActionZone.tpl.js +0 -11
  162. package/vendor/symbiote-node/layout/Layout/Layout.css.js +0 -88
  163. package/vendor/symbiote-node/layout/Layout/Layout.js +0 -622
  164. package/vendor/symbiote-node/layout/Layout/Layout.tpl.js +0 -25
  165. package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.css.js +0 -293
  166. package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.js +0 -467
  167. package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.tpl.js +0 -33
  168. package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.css.js +0 -46
  169. package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.js +0 -102
  170. package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.tpl.js +0 -6
  171. package/vendor/symbiote-node/layout/LayoutRouter/LayoutRouter.js +0 -156
  172. package/vendor/symbiote-node/layout/LayoutRouter/routerSync.js +0 -250
  173. package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.css.js +0 -379
  174. package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.js +0 -263
  175. package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.tpl.js +0 -20
  176. package/vendor/symbiote-node/layout/LayoutSidebar/SidebarSection.js +0 -183
  177. package/vendor/symbiote-node/layout/LayoutTree.js +0 -246
  178. package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.css.js +0 -43
  179. package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.js +0 -89
  180. package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.tpl.js +0 -14
  181. package/vendor/symbiote-node/layout/index.js +0 -16
  182. package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.css.js +0 -61
  183. package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.js +0 -79
  184. package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.tpl.js +0 -19
  185. package/vendor/symbiote-node/node/CtrlItem/CtrlItem.css.js +0 -41
  186. package/vendor/symbiote-node/node/CtrlItem/CtrlItem.js +0 -24
  187. package/vendor/symbiote-node/node/CtrlItem/CtrlItem.tpl.js +0 -16
  188. package/vendor/symbiote-node/node/GraphFrame/GraphFrame.css.js +0 -65
  189. package/vendor/symbiote-node/node/GraphFrame/GraphFrame.js +0 -29
  190. package/vendor/symbiote-node/node/GraphFrame/GraphFrame.tpl.js +0 -13
  191. package/vendor/symbiote-node/node/GraphNode/GraphNode.css.js +0 -683
  192. package/vendor/symbiote-node/node/GraphNode/GraphNode.js +0 -92
  193. package/vendor/symbiote-node/node/GraphNode/GraphNode.tpl.js +0 -17
  194. package/vendor/symbiote-node/node/NodeSocket/NodeSocket.js +0 -25
  195. package/vendor/symbiote-node/node/NodeSocket/NodeSocket.tpl.js +0 -7
  196. package/vendor/symbiote-node/node/PortItem/PortItem.css.js +0 -90
  197. package/vendor/symbiote-node/node/PortItem/PortItem.js +0 -87
  198. package/vendor/symbiote-node/node/PortItem/PortItem.tpl.js +0 -10
  199. package/vendor/symbiote-node/package.json +0 -59
  200. package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.css.js +0 -143
  201. package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.js +0 -131
  202. package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.tpl.js +0 -16
  203. package/vendor/symbiote-node/plugins/History.js +0 -384
  204. package/vendor/symbiote-node/plugins/Readonly.js +0 -59
  205. package/vendor/symbiote-node/shapes/CircleShape.js +0 -80
  206. package/vendor/symbiote-node/shapes/CommentShape.js +0 -35
  207. package/vendor/symbiote-node/shapes/DiamondShape.js +0 -115
  208. package/vendor/symbiote-node/shapes/NodeShape.js +0 -80
  209. package/vendor/symbiote-node/shapes/PillShape.js +0 -91
  210. package/vendor/symbiote-node/shapes/RectShape.js +0 -72
  211. package/vendor/symbiote-node/shapes/SVGShape.js +0 -494
  212. package/vendor/symbiote-node/shapes/index.js +0 -53
  213. package/vendor/symbiote-node/themes/Palette.js +0 -32
  214. package/vendor/symbiote-node/themes/Skin.js +0 -113
  215. package/vendor/symbiote-node/themes/Theme.js +0 -84
  216. package/vendor/symbiote-node/themes/carbon.js +0 -137
  217. package/vendor/symbiote-node/themes/dark.js +0 -137
  218. package/vendor/symbiote-node/themes/ebook.js +0 -138
  219. package/vendor/symbiote-node/themes/grey.js +0 -137
  220. package/vendor/symbiote-node/themes/light.js +0 -137
  221. package/vendor/symbiote-node/themes/neon.js +0 -138
  222. package/vendor/symbiote-node/themes/pcb.js +0 -273
  223. package/vendor/symbiote-node/themes/synthwave.js +0 -137
  224. package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.css.js +0 -86
  225. package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.js +0 -128
  226. package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.tpl.js +0 -29
@@ -1,451 +0,0 @@
1
- /**
2
- * NodeEditor — central graph manager with event system
3
- *
4
- * Provides CRUD operations for nodes and connections with
5
- * pre/post event hooks via callback-based event emitter.
6
- * Replaces Rete.js Scope/Signal with simpler emit pattern.
7
- *
8
- * @module symbiote-node/core/Editor
9
- */
10
-
11
- import { Connection } from './Connection.js';
12
- import { Node } from './Node.js';
13
- import { Socket, Input, Output, InputControl } from './Socket.js';
14
- import { Frame } from './Frame.js';
15
-
16
- /**
17
- * @typedef {'nodecreate'|'nodecreated'|'noderemove'|'noderemoved'|
18
- * 'connectioncreate'|'connectioncreated'|'connectionremove'|'connectionremoved'|
19
- * 'framecreate'|'framecreated'|'frameremove'|'frameremoved'|
20
- * 'clear'|'cleared'|'nodeselect'|'nodedeselect'} EditorEvent
21
- */
22
-
23
- export class NodeEditor {
24
- constructor() {
25
- /** @type {Map<string, import('./Node.js').Node>} */
26
- this.nodes = new Map();
27
-
28
- /** @type {Map<string, Connection>} */
29
- this.connections = new Map();
30
-
31
- /** @type {Map<string, import('./Frame.js').Frame>} */
32
- this.frames = new Map();
33
-
34
- /** @type {Object<string, Set<function>>} */
35
- this._listeners = {};
36
- }
37
-
38
- // --- Event System ---
39
-
40
- /**
41
- * Subscribe to editor event
42
- * @param {EditorEvent} event
43
- * @param {function} handler
44
- * @returns {function} Unsubscribe function
45
- */
46
- on(event, handler) {
47
- if (!this._listeners[event]) {
48
- this._listeners[event] = new Set();
49
- }
50
- this._listeners[event].add(handler);
51
- return () => this._listeners[event].delete(handler);
52
- }
53
-
54
- /**
55
- * Emit event to all listeners
56
- * @param {EditorEvent} event
57
- * @param {*} data
58
- * @returns {boolean} - false if any listener returned false (cancel)
59
- */
60
- emit(event, data) {
61
- const handlers = this._listeners[event];
62
- if (!handlers) return true;
63
- for (const handler of handlers) {
64
- if (handler(data) === false) return false;
65
- }
66
- return true;
67
- }
68
-
69
- /**
70
- * Remove all event listeners (for clean teardown)
71
- */
72
- removeAllListeners() {
73
- this._listeners = {};
74
- }
75
-
76
- // --- Node CRUD ---
77
-
78
- /**
79
- * Get node by ID
80
- * @param {string} id
81
- * @returns {import('./Node.js').Node|undefined}
82
- */
83
- getNode(id) {
84
- return this.nodes.get(id);
85
- }
86
-
87
- /**
88
- * Get all nodes
89
- * @returns {import('./Node.js').Node[]}
90
- */
91
- getNodes() {
92
- return [...this.nodes.values()];
93
- }
94
-
95
- /**
96
- * Add node to editor
97
- * @param {import('./Node.js').Node} node
98
- * @returns {boolean}
99
- */
100
- addNode(node) {
101
- if (this.nodes.has(node.id)) throw new Error('node already added');
102
- if (!this.emit('nodecreate', node)) return false;
103
- this.nodes.set(node.id, node);
104
- this.emit('nodecreated', node);
105
- return true;
106
- }
107
-
108
- /**
109
- * Remove node and all its connections
110
- * @param {string} id
111
- * @returns {boolean}
112
- */
113
- removeNode(id) {
114
- const node = this.nodes.get(id);
115
- if (!node) throw new Error('node not found');
116
- if (!this.emit('noderemove', node)) return false;
117
-
118
- // Remove all connections to/from this node
119
- for (const [connId, conn] of this.connections) {
120
- if (conn.from === id || conn.to === id) {
121
- this.removeConnection(connId);
122
- }
123
- }
124
-
125
- this.nodes.delete(id);
126
- this.emit('noderemoved', node);
127
- return true;
128
- }
129
-
130
- // --- Connection CRUD ---
131
-
132
- /**
133
- * Get connection by ID
134
- * @param {string} id
135
- * @returns {Connection|undefined}
136
- */
137
- getConnection(id) {
138
- return this.connections.get(id);
139
- }
140
-
141
- /**
142
- * Get all connections
143
- * @returns {Connection[]}
144
- */
145
- getConnections() {
146
- return [...this.connections.values()];
147
- }
148
-
149
- /**
150
- * Get connections for a specific node
151
- * @param {string} nodeId
152
- * @returns {Connection[]}
153
- */
154
- getNodeConnections(nodeId) {
155
- return this.getConnections().filter(c => c.from === nodeId || c.to === nodeId);
156
- }
157
-
158
- /**
159
- * Add connection
160
- * @param {Connection} connection
161
- * @returns {boolean}
162
- */
163
- addConnection(connection) {
164
- if (this.connections.has(connection.id)) throw new Error('connection already added');
165
- if (!this.emit('connectioncreate', connection)) return false;
166
- this.connections.set(connection.id, connection);
167
- this.emit('connectioncreated', connection);
168
- return true;
169
- }
170
-
171
- /**
172
- * Remove connection
173
- * @param {string} id
174
- * @returns {boolean}
175
- */
176
- removeConnection(id) {
177
- const conn = this.connections.get(id);
178
- if (!conn) return false;
179
- if (!this.emit('connectionremove', conn)) return false;
180
- this.connections.delete(id);
181
- this.emit('connectionremoved', conn);
182
- return true;
183
- }
184
-
185
- // --- Bulk Operations ---
186
-
187
- /**
188
- * Clear all nodes and connections
189
- * @returns {boolean}
190
- */
191
- clear() {
192
- if (!this.emit('clear', null)) return false;
193
- for (const id of [...this.connections.keys()]) {
194
- this.removeConnection(id);
195
- }
196
- for (const id of [...this.nodes.keys()]) {
197
- this.removeNode(id);
198
- }
199
- this.emit('cleared', null);
200
- return true;
201
- }
202
-
203
- // --- Frame CRUD ---
204
-
205
- /**
206
- * Get frame by ID
207
- * @param {string} id
208
- * @returns {import('./Frame.js').Frame|undefined}
209
- */
210
- getFrame(id) {
211
- return this.frames.get(id);
212
- }
213
-
214
- /**
215
- * Get all frames
216
- * @returns {import('./Frame.js').Frame[]}
217
- */
218
- getFrames() {
219
- return [...this.frames.values()];
220
- }
221
-
222
- /**
223
- * Add frame
224
- * @param {import('./Frame.js').Frame} frame
225
- * @returns {boolean}
226
- */
227
- addFrame(frame) {
228
- if (this.frames.has(frame.id)) throw new Error('frame already added');
229
- if (!this.emit('framecreate', frame)) return false;
230
- this.frames.set(frame.id, frame);
231
- this.emit('framecreated', frame);
232
- return true;
233
- }
234
-
235
- /**
236
- * Remove frame
237
- * @param {string} id
238
- * @returns {boolean}
239
- */
240
- removeFrame(id) {
241
- const frame = this.frames.get(id);
242
- if (!frame) return false;
243
- if (!this.emit('frameremove', frame)) return false;
244
- this.frames.delete(id);
245
- this.emit('frameremoved', frame);
246
- return true;
247
- }
248
-
249
- // --- Serialization (agi-graph isomorphic bridge) ---
250
-
251
- /**
252
- * Serialize editor state to agi-graph workflow JSON format.
253
- * Output is directly compatible with engine/Graph.fromJSON().
254
- * @param {Object<string, number[]>} [positions] - Node positions {nodeId: [x, y]}
255
- * @returns {object} Workflow JSON
256
- */
257
- toJSON(positions = {}) {
258
- return {
259
- version: 1,
260
- nodes: this.getNodes().map((n) => {
261
- const obj = {
262
- id: n.id,
263
- type: n.type,
264
- name: n.label,
265
- params: { ...n.params },
266
- };
267
- if (n.category && n.category !== 'default') obj.category = n.category;
268
- if (n.shape && n.shape !== 'rect') obj.shape = n.shape;
269
- if (n.icon) obj.icon = n.icon;
270
- if (n.cacheMode && n.cacheMode !== 'auto') obj.cacheMode = n.cacheMode;
271
-
272
- // Serialize port definitions for round-trip
273
- const inputs = Object.entries(n.inputs);
274
- if (inputs.length > 0) {
275
- obj.inputs = inputs.map(([key, inp]) => ({
276
- name: key,
277
- type: inp.socket?.name || 'any',
278
- label: inp.label || '',
279
- }));
280
- }
281
- const outputs = Object.entries(n.outputs);
282
- if (outputs.length > 0) {
283
- obj.outputs = outputs.map(([key, out]) => ({
284
- name: key,
285
- type: out.socket?.name || 'any',
286
- label: out.label || '',
287
- }));
288
- }
289
- return obj;
290
- }),
291
- connections: this.getConnections().map((c) => ({
292
- id: c.id,
293
- from: c.from,
294
- out: c.out,
295
- to: c.to,
296
- in: c.in,
297
- })),
298
- frames: this.getFrames().map((f) => ({
299
- id: f.id,
300
- label: f.label,
301
- x: f.x,
302
- y: f.y,
303
- width: f.width,
304
- height: f.height,
305
- color: f.color,
306
- })),
307
- ui: {
308
- positions: { ...positions },
309
- },
310
- };
311
- }
312
-
313
- /**
314
- * Reconstruct editor state from agi-graph workflow JSON.
315
- * Enables round-trip: Editor → toJSON → fromJSON → Editor.
316
- * Also accepts output from engine/Graph.toJSON().
317
- * @param {object} data - Workflow JSON
318
- * @param {Object<string, number[]>} [positionsOut] - Optional object to populate with positions
319
- * @returns {NodeEditor} this
320
- */
321
- fromJSON(data, positionsOut) {
322
- // Clear existing state (bypass events for bulk load)
323
- this.nodes.clear();
324
- this.connections.clear();
325
- this.frames.clear();
326
-
327
- // Restore nodes
328
- for (const nd of (data.nodes || [])) {
329
- const node = new Node(nd.name || nd.type, {
330
- id: nd.id,
331
- type: nd.type,
332
- category: nd.category || 'default',
333
- shape: nd.shape || 'rect',
334
- icon: nd.icon || '',
335
- });
336
- node.params = { ...nd.params };
337
- if (nd.cacheMode) node.cacheMode = nd.cacheMode;
338
-
339
- // Auto-create InputControls from params for Inspector display
340
- // Merge driver defaults into params (fills missing keys from handler definitions)
341
- const driverParams = nd.driver?.params;
342
- if (driverParams && !nd.params) nd.params = {};
343
- if (driverParams) {
344
- for (const [key, def] of Object.entries(driverParams)) {
345
- if (!(key in nd.params) && def.default !== undefined) {
346
- nd.params[key] = def.default;
347
- }
348
- }
349
- }
350
-
351
- if (nd.params) {
352
- for (const [key, value] of Object.entries(nd.params)) {
353
- /** @type {'text'|'number'|'textarea'|'select'|'boolean'} */
354
- let controlType = 'text';
355
- let displayValue = value;
356
- let controlOptions = [];
357
-
358
- // Use driver metadata for richer control type detection
359
- const paramMeta = driverParams?.[key];
360
- if (paramMeta?.type === 'boolean' || typeof value === 'boolean') {
361
- controlType = 'boolean';
362
- } else if (paramMeta?.type === 'number' || typeof value === 'number') {
363
- controlType = 'number';
364
- } else if (typeof value === 'string' && value.includes('\n')) {
365
- controlType = 'textarea';
366
- } else if (typeof value === 'object') {
367
- controlType = 'textarea';
368
- displayValue = JSON.stringify(value, null, 2);
369
- }
370
-
371
- // Select type from driver options
372
- if (paramMeta?.options) {
373
- controlType = 'select';
374
- controlOptions = paramMeta.options;
375
- }
376
-
377
- node.addControl(key, new InputControl(controlType, {
378
- initial: displayValue,
379
- label: paramMeta?.description || key,
380
- options: controlOptions,
381
- }));
382
- }
383
- }
384
-
385
- // Restore ports from serialized definitions
386
- if (nd.inputs) {
387
- for (const inp of nd.inputs) {
388
- node.addInput(inp.name, new Input(new Socket(inp.type || 'any'), inp.label || ''));
389
- }
390
- }
391
- if (nd.outputs) {
392
- for (const out of nd.outputs) {
393
- node.addOutput(out.name, new Output(new Socket(out.type || 'any'), out.label || ''));
394
- }
395
- }
396
-
397
- this.nodes.set(node.id, node);
398
- }
399
-
400
- // Restore connections
401
- for (const cd of (data.connections || [])) {
402
- const srcNode = this.nodes.get(cd.from);
403
- const tgtNode = this.nodes.get(cd.to);
404
- if (!srcNode || !tgtNode) continue;
405
-
406
- // Ensure ports exist (auto-create if coming from engine format without port defs)
407
- if (!srcNode.outputs[cd.out]) {
408
- srcNode.addOutput(cd.out, new Output(new Socket('any'), cd.out));
409
- }
410
- if (!tgtNode.inputs[cd.in]) {
411
- tgtNode.addInput(cd.in, new Input(new Socket('any'), cd.in));
412
- }
413
-
414
- const conn = new Connection(srcNode, cd.out, tgtNode, cd.in);
415
- if (cd.id) conn.id = cd.id;
416
- this.connections.set(conn.id, conn);
417
- }
418
-
419
- // Restore frames
420
- for (const fd of (data.frames || [])) {
421
- const frame = new Frame(fd.label, {
422
- id: fd.id,
423
- x: fd.x,
424
- y: fd.y,
425
- width: fd.width,
426
- height: fd.height,
427
- color: fd.color,
428
- });
429
- this.frames.set(frame.id, frame);
430
- }
431
-
432
- // Extract positions
433
- if (positionsOut && data.ui?.positions) {
434
- Object.assign(positionsOut, data.ui.positions);
435
- }
436
-
437
- return this;
438
- }
439
-
440
- /**
441
- * Convert editor state to an engine Graph instance for server-side execution.
442
- * The Graph can be passed directly to Executor.run().
443
- * @param {Object<string, number[]>} [positions] - Node positions
444
- * @returns {import('../engine/Graph.js').Graph}
445
- */
446
- async toGraph(positions = {}) {
447
- const { Graph } = await import('../engine/Graph.js');
448
- const json = this.toJSON(positions);
449
- return new Graph(json);
450
- }
451
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Frame — visual grouping rectangle for nodes
3
- *
4
- * Pure data class (like Node). Stores position, size, color, label.
5
- * Frame does not own nodes — containment is determined by spatial overlap.
6
- *
7
- * @module symbiote-node/core/Frame
8
- */
9
-
10
- import { uid } from './Socket.js';
11
-
12
- export class Frame {
13
- /**
14
- * @param {string} label - Display label
15
- * @param {object} [options]
16
- * @param {string} [options.color='#4a9eff'] - Border/header color
17
- * @param {number} [options.x=0] - X position
18
- * @param {number} [options.y=0] - Y position
19
- * @param {number} [options.width=400] - Width
20
- * @param {number} [options.height=300] - Height
21
- */
22
- constructor(label, options = {}) {
23
- this.id = options.id || uid();
24
- this.label = label;
25
- this.color = options.color || '#4a9eff';
26
- this.x = options.x || 0;
27
- this.y = options.y || 0;
28
- this.width = options.width || 400;
29
- this.height = options.height || 300;
30
- }
31
- }