groove-dev 0.26.26 → 0.26.28

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.
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <link rel="icon" type="image/png" href="/favicon.png" />
7
7
  <title>Groove GUI</title>
8
- <script type="module" crossorigin src="/assets/index-aIPRNYy7.js"></script>
8
+ <script type="module" crossorigin src="/assets/index--XNm9lTq.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/vendor-C0HXlhrU.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/reactflow-BQPfi37R.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/codemirror-BBL3i_JW.js">
@@ -261,13 +261,13 @@ function AgentTreeInner() {
261
261
  return nodes;
262
262
  }, [agents, tokenTimeline]);
263
263
 
264
- // Build edges
264
+ // Build edges — compute closest handle based on saved node positions
265
265
  const targetEdges = useMemo(() => {
266
266
  const saved = loadPositions();
267
267
  const rootPos = saved[ROOT_ID] || { x: 0, y: 0 };
268
268
 
269
269
  return agents.map((agent, i) => {
270
- const key = agent.id;
270
+ const key = agent.name || agent.id;
271
271
  const row = Math.floor(i / MAX_PER_ROW);
272
272
  const col = i % MAX_PER_ROW;
273
273
  const totalInRow = Math.min(agents.length - row * MAX_PER_ROW, MAX_PER_ROW);
@@ -319,7 +319,32 @@ function AgentTreeInner() {
319
319
  });
320
320
  }, [targetNodes, setNodes]);
321
321
 
322
- useEffect(() => { setEdges(targetEdges); }, [targetEdges, setEdges]);
322
+ // Recalculate edge handles from actual node positions (not saved positions)
323
+ // Runs after nodes settle — handles always match where nodes actually are
324
+ useEffect(() => {
325
+ setEdges(() => {
326
+ const rootNode = nodes.find((n) => n.id === ROOT_ID);
327
+ if (!rootNode) return targetEdges;
328
+ const rootPos = rootNode.position;
329
+
330
+ return targetEdges.map((edge) => {
331
+ const agentNode = nodes.find((n) => n.id === edge.target);
332
+ if (!agentNode) return edge;
333
+
334
+ const dx = agentNode.position.x + NODE_W / 2 - rootPos.x;
335
+ const dy = agentNode.position.y + NODE_H / 2 - rootPos.y;
336
+ let sourceHandle, targetHandle;
337
+ if (Math.abs(dy) > Math.abs(dx)) {
338
+ sourceHandle = dy > 0 ? 'bottom' : 'top';
339
+ targetHandle = dy > 0 ? 'top' : 'bottom';
340
+ } else {
341
+ sourceHandle = dx > 0 ? 'right' : 'left';
342
+ targetHandle = dx > 0 ? 'left' : 'right';
343
+ }
344
+ return { ...edge, sourceHandle, targetHandle };
345
+ });
346
+ });
347
+ }, [targetEdges, nodes, setEdges]);
323
348
 
324
349
  // Only fitView when agents are added — debounced so team launches (multiple spawns)
325
350
  // don't cause repeated zoom/pan jitter