Skip to content

Very Big Refactor 2#142

Merged
xingjianll merged 21 commits into
mainfrom
140-refactor-bigly-2
Apr 5, 2026
Merged

Very Big Refactor 2#142
xingjianll merged 21 commits into
mainfrom
140-refactor-bigly-2

Conversation

@xingjianll

Copy link
Copy Markdown
Contributor

Summary

  • Rename add_node/update_node_init_args to add_primitive_node/update_primitive_node_init_args
  • Backend handles edge cleanup on node deletion, only stops downstream nodes
  • Separate graph topology, channel topology, and wiring into three layers
  • _reconcile() returns (sender_plan, receiver_plan) as a pure plan
  • run() creates fresh Sender/Receiver from the plan, stores on Node
  • Receiver registers in __init__, no more _wire/_unwire
  • Extract UI channels into UIChannelBridge with wire() + run(ws)
  • WS controller reduced to accept + bridge.run()
  • Paired encode/decode functions for WS wire format
  • Move SenderKey/ReceiverKey to utils for shared access
  • CompositeComponent uses proper type bounds and tuple I/O
  • Composite boundary slot naming uses disambiguation (slot, Type.slot, Type.slot.N)
  • Frontend edge deletion handled by onEdgesDelete callback, not onEdgesChange

Test plan

  • uv run pytest passes (149/149)
  • uv run mypy src clean
  • uv run ruff check . clean
  • TextInput → TextDisplay pipeline works in browser
  • Node deletion stops downstream nodes correctly
  • CI passes

🤖 Generated with Claude Code

xingjianll and others added 15 commits April 4, 2026 19:04
… node removal

- Rename add_node to add_primitive_node, node_type to type_
- Rename update_node_init_args to update_primitive_node_init_args
- Backend handles edge cleanup on node deletion (not frontend)
- Only stop downstream nodes on delete, not upstream
- Use onEdgesDelete for user-initiated edge removal only

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three-layer separation in GraphManager:
- Graph topology: nodes/edges CRUD (unchanged)
- Channel topology: _reconcile() returns (sender_plan, receiver_plan)
  as a pure plan without touching live handles
- Wiring: run() creates fresh Sender/Receiver from the plan, stores
  on Node.senders/Node.receivers. stop() clears them.

Also:
- Receiver takes (channel, stop_event) in __init__, registers immediately
- Remove _wire/_unwire from Receiver
- Remove _sender_handles, _receiver_handles, _ui_channels from GraphManager
- sender_handles()/receiver_handles() rebuilt from nodes on the fly
- CompositeComponent typed properly instead of Component[Any, Any]
- CompositeComponent boundary naming uses slot name disambiguation
- Only stop downstream nodes on delete_node, not upstream

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… and wiring

- _reconcile() returns (sender_plan, receiver_plan) as a pure plan
- run() creates fresh Sender/Receiver from the plan, stores on Node
- stop() marks senders as stopped, doesn't clear handles
- Receiver registers in __init__, unregisters in __del__
- Remove _wire/_unwire, _sender_handles, _receiver_handles, _ui_channels
- run() accepts optional overrides for composite boundary wiring
- CompositeComponent uses tuple I/O with proper type bounds
- Composite boundary slot naming uses disambiguation (slot, Type.slot, Type.slot.N)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oller

- UIChannelBridge owns WebSocket lifecycle via run(ws)
- wire() creates UI channels and returns overrides for GraphManager.run()
- Paired encode/decode functions for binary and JSON wire formats
- One blocking task per UI output using Receiver properly
- Controller reduced to accept + bridge.run()
- Move SenderKey/ReceiverKey to utils
- CompositeComponent uses tuple I/O with proper type bounds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oller

- UIChannelBridge owns WebSocket lifecycle via run(ws)
- wire() creates UI channels and returns overrides for GraphManager.run()
- Paired encode/decode functions for binary and JSON wire formats
- One blocking task per UI output using Receiver properly
- Controller reduced to accept + bridge.run()
- Move SenderKey/ReceiverKey to utils
- Update all tests for new Receiver(channel, stop_event) signature
- Update tests for update_primitive_node_init_args returning (node, was_running)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…soon_threadsafe

- run(ws) blocks for WS lifetime, stores loop for cross-thread scheduling
- wire() creates channels from sync thread, schedules task spawning on event loop
- Handles all orderings: WS before start, start before WS, config change while running
- WS disconnect cleans up all tasks in run()'s finally block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…otion)

- Sidebar now groups by functionality (Audio/Vision/LLM/Motion/Misc) at top level
- IO tags (Sources/Conduits/Sinks) shown as subsections within each group
- Fix tag names: video→vision, image/movement→motion to match backend
- Add null guard for unknown functionality tags in InfoPanel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ture

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nges

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Apr 5, 2026

Copy link
Copy Markdown

Test Coverage

Target Coverage Covered Lines
Backend 95.91% 9976 / 10401
Frontend 89.02% 1467 / 1648

xingjianll and others added 6 commits April 5, 2026 01:05
- GraphManager section: handles on Node, _reconcile returns plans
- Channel topology: three-layer separation explained
- UI channels: UIChannelBridge owns WS lifecycle, external to GraphManager
- Node CRUD: renamed methods, delete_node only stops downstream
- Frontend: direct backend calls via API_BASE, no proxy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix dev.ts: use --no-default-groups instead of --no-group cuda12
- Add --amd as alias for --rocm
- README: add AMD/ROCm setup instructions with bun run dev -- --amd

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ive sleep, composite non-blocking stop

- DoNothing: break on None (was spinning indefinitely ignoring stop)
- Throttle: use stop_event.wait(interval) instead of time.sleep()
  so stop is detected immediately during the interval
- CompositeComponent.stop(): only signal inner components, don't join —
  prevents cascading join timeouts from blocking outer stop loop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace warmSubtypeCache's N*(N-1) individual /is-subtype calls with
a single /subtype-pairs batch endpoint. Eliminates hundreds of requests
on page load that were lagging the frontend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@xingjianll xingjianll changed the title Refactor: three-layer graph/channel/wiring separation + UI bridge extraction Very Big Refactor 2 Apr 5, 2026
@xingjianll xingjianll merged commit 842f479 into main Apr 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant