adds a WebSocket-based display backend that allows the mainline terminal to broadcast frames to web browser clients via HTML5 Canvas #26

Open
david wants to merge 31 commits from klubhaus/sideline:feature/vector_display into main
Contributor

Features

  • WebSocket Display Backend: WebSocketDisplay class broadcasts frame buffers to connected web clients in real-time
  • HTTP Server: Built-in HTTP server serves the HTML client on port 8766
  • HTML5 Canvas Client: Browser-based terminal visualization with:
    • ANSI color parsing (256-color mode support)
    • Fullscreen mode
    • Resizable viewport (columns × rows)
    • Bidirectional resize communication (client → server)
  • Display Abstraction: New Display protocol allows swapping display backends
  • MultiDisplay: New class forwards output to multiple displays simultaneously

Display Modes

Flag Description
--display terminal Terminal only (default)
--display websocket Web only
--display both Both terminal and web

New Files

  • engine/websocket_display.py - WebSocket display server
  • client/index.html - HTML Canvas client

New Tests

  • tests/test_websocket.py - WebSocket display tests
  • tests/e2e/test_web_client.py - Browser e2e tests with Playwright

Usage

# Terminal only (default)
mise run run

# Web only
mise run run-websocket

# Both terminal and web
mise run run-both

# Both + open browser
mise run run-client

Ports

  • 8765: WebSocket server (broadcasts frames)
  • 8766: HTTP server (serves HTML client)

Technical Details

  • Uses websockets Python library for asyncio-based WebSocket server
  • Threaded background servers for non-blocking operation
  • Performance monitoring via existing PerformanceMonitor
  • Configurable via CLI: --websocket, --websocket-port, --display
### Features - **WebSocket Display Backend**: `WebSocketDisplay` class broadcasts frame buffers to connected web clients in real-time - **HTTP Server**: Built-in HTTP server serves the HTML client on port 8766 - **HTML5 Canvas Client**: Browser-based terminal visualization with: - ANSI color parsing (256-color mode support) - Fullscreen mode - Resizable viewport (columns × rows) - Bidirectional resize communication (client → server) - **Display Abstraction**: New `Display` protocol allows swapping display backends - **MultiDisplay**: New class forwards output to multiple displays simultaneously ### Display Modes | Flag | Description | |------|-------------| | `--display terminal` | Terminal only (default) | | `--display websocket` | Web only | | `--display both` | Both terminal and web | ### New Files - `engine/websocket_display.py` - WebSocket display server - `client/index.html` - HTML Canvas client ### New Tests - `tests/test_websocket.py` - WebSocket display tests - `tests/e2e/test_web_client.py` - Browser e2e tests with Playwright ### Usage ```bash # Terminal only (default) mise run run # Web only mise run run-websocket # Both terminal and web mise run run-both # Both + open browser mise run run-client ``` ### Ports - **8765**: WebSocket server (broadcasts frames) - **8766**: HTTP server (serves HTML client) ### Technical Details - Uses `websockets` Python library for asyncio-based WebSocket server - Threaded background servers for non-blocking operation - Performance monitoring via existing `PerformanceMonitor` - Configurable via CLI: `--websocket`, `--websocket-port`, `--display`
david added 11 commits 2026-03-16 04:22:03 +00:00
- Add Config dataclass with get_config()/set_config() for injection
- Add Config.from_args() for CLI argument parsing (testable)
- Add platform font path detection (Darwin/Linux)
- Bound translate cache with @lru_cache(maxsize=500)
- Add fixtures for external dependencies (network, feeds, config)
- Add 15 tests for Config class, from_args, and platform detection

This enables testability by:
- Allowing config injection instead of global mutable state
- Supporting custom argv in from_args() for testing
- Providing reusable fixtures for mocking network/filesystem
- Preventing unbounded memory growth in translation cache

Fixes: _arg_value/_arg_int not accepting custom argv
Split monolithic scroll.py into focused modules:
- viewport.py: terminal size (tw/th), ANSI positioning helpers
- frame.py: FrameTimer class, scroll step calculation
- layers.py: message overlay, ticker zone, firehose rendering
- scroll.py: simplified orchestrator, imports from new modules

Add stream controller and event types for future event-driven architecture:
- controller.py: StreamController for source initialization and stream lifecycle
- events.py: EventType enum and event dataclasses (HeadlineEvent, FrameTickEvent, etc.)

Added tests for new modules:
- test_viewport.py: 8 tests for viewport utilities
- test_frame.py: 10 tests for frame timing
- test_layers.py: 13 tests for layer compositing
- test_events.py: 11 tests for event types
- test_controller.py: 6 tests for stream controller

This enables:
- Testable chunks with clear responsibilities
- Reusable viewport utilities across modules
- Better separation of concerns in render pipeline
- Foundation for future event-driven architecture

Also includes Phase 1 documentation updates in code comments.
Add typed dataclasses for tuple returns:
- types.py: HeadlineItem, FetchResult, Block dataclasses with legacy tuple converters
- fetch.py: Add type hints and HeadlineTuple type alias

Add pyright for static type checking:
- Add pyright to dependencies
- Verify type coverage with pyright (0 errors in core modules)

This enables:
- Named types instead of raw tuples (better IDE support, self-documenting)
- Type-safe APIs across modules
- Backward compatibility via to_tuple/from_tuple methods

Note: Lazy imports skipped for render.py - startup impact is minimal.
- Add EventBus class with pub/sub messaging (thread-safe)
- Add emitter Protocol classes (EventEmitter, Startable, Stoppable)
- Add event emission to NtfyPoller (NtfyMessageEvent)
- Add event emission to MicMonitor (MicLevelEvent)
- Update StreamController to publish stream start/end events
- Add comprehensive tests for eventbus and emitters modules
david added 2 commits 2026-03-16 04:55:48 +00:00
- Cherry-pick C&C support (ntfy poller for commands, response handling)
- Compact mise.toml with native dependency chaining
- Update AGENTS.md with C&C documentation
- Update README.md with display modes and C&C usage
david added 3 commits 2026-03-16 05:41:35 +00:00
- Implement pure Python Sixel encoder (no C dependency)
- Add SixelDisplay class to display.py with ANSI parsing
- Update controller._get_display() to handle sixel mode
- Add --display sixel CLI flag
- Add mise run-sixel task
- Update docs with display modes
- Create engine/display/ package with registry pattern
- Move displays to engine/display/backends/ (terminal, null, websocket, sixel)
- Add DisplayRegistry with auto-discovery
- Add benchmark.py for performance testing effects × displays matrix
- Add mise tasks: benchmark, benchmark-json, benchmark-report
- Update controller to use new display module
- Fix lint errors and LSP issues in benchmark.py
- Add --hook mode to compare against saved baseline
- Add --baseline flag to save results as baseline
- Add --threshold to configure degradation threshold (default 20%)
- Add benchmark step to pre-push hook in hk.pkl
- Update AGENTS.md with hk documentation links and benchmark runner docs
david force-pushed feature/vector_display from ab3e1766b1 to 7eb3fca935 2026-03-16 05:55:02 +00:00 Compare
david force-pushed feature/vector_display from 7eb3fca935 to dcd31469a5 2026-03-16 05:58:03 +00:00 Compare
david added 1 commit 2026-03-16 06:26:23 +00:00
- Add EffectPlugin ABC with @abstractmethod decorators for interface enforcement
- Add runtime interface checking in discover_plugins() with issubclass()
- Add EffectContext factory with sensible defaults
- Standardize Display __init__ (remove redundant init in TerminalDisplay)
- Document effect behavior when ticker_height=0
- Evaluate legacy effects: document coexistence, no deprecation needed
- Research plugin patterns (VST, Python entry points)
- Fix pysixel dependency (removed broken dependency)

Test coverage improvements:
- Add DisplayRegistry tests
- Add MultiDisplay tests
- Add SixelDisplay tests
- Add controller._get_display tests
- Add effects controller command handling tests
- Add benchmark regression tests (@pytest.mark.benchmark)
- Add pytest marker for benchmark tests in pyproject.toml

Documentation updates:
- Update AGENTS.md with 56% coverage stats and effect plugin docs
- Update README.md with Sixel display mode and benchmark commands
- Add new modules to architecture section
david added 1 commit 2026-03-16 06:56:58 +00:00
- Add KittyDisplay using kitty's native graphics protocol
- Improve cross-platform font detection for SixelDisplay
- Add run-kitty mise task for testing kitty backend
- Add kitty_test.py for testing graphics protocol
david added 1 commit 2026-03-16 07:01:04 +00:00
- Add PygameDisplay for rendering in native application window
- Add pygame to optional dependencies
- Add run-pygame mise task
david added 1 commit 2026-03-16 07:31:01 +00:00
- Add reuse parameter to Display.init() for all backends
- PygameDisplay: reuse existing SDL window via class-level flag
- TerminalDisplay: skip re-init when reuse=True
- WebSocketDisplay: skip server start when reuse=True
- SixelDisplay, KittyDisplay, NullDisplay: ignore reuse (not applicable)
- MultiDisplay: pass reuse to child displays
- Update benchmark.py to reuse pygame display for effect benchmarks
- Add test_websocket_e2e.py with e2e marker
- Register e2e marker in pyproject.toml
david added 1 commit 2026-03-16 07:43:31 +00:00
- Add renderer.py with parse_ansi(), get_default_font_path(), render_to_pil()
- Update KittyDisplay and SixelDisplay to use shared renderer
- Enhance parse_ansi to handle full ANSI color codes (4-bit, 256-color)
- Update tests to use shared renderer functions
david added 1 commit 2026-03-16 07:53:21 +00:00
- Add --demo flag that runs effect showcase with pygame display
- Add HUD effect plugin (effects_plugins/hud.py) that displays:
  - FPS and frame time
  - Current effect name with intensity bar
  - Pipeline order
- Demo mode cycles through noise, fade, glitch, firehose effects
- Ramps intensity 0→1→0 over 5 seconds per effect
david added 1 commit 2026-03-16 07:54:45 +00:00
david added 1 commit 2026-03-16 07:59:54 +00:00
david added 1 commit 2026-03-16 08:10:21 +00:00
- Fetch real news/poetry content instead of random letters
- Render full ticker zone with scroll, gradients, firehose
- Demo now shows actual effect behavior on real content
david added 1 commit 2026-03-16 08:25:16 +00:00
- Add HUD effect plugin showing FPS, effect name, intensity bar, pipeline
- Add pygame window resize handling (VIDEORESIZE event)
- Move HUD to end of chain so it renders on top
- Fix monitor stats API (returns dict, not object)
- Add tests/test_hud.py for HUD effect verification
david added 1 commit 2026-03-16 08:46:30 +00:00
- Add Camera class with modes: vertical, horizontal, omni, floating
- Refactor scroll.py and demo to use Camera abstraction
- Add vis_offset for horizontal scrolling support
- Add camera_x to EffectContext for effects
- Add pygame window resize handling
- Add HUD effect plugin for demo mode
- Add --demo flag to run demo mode
- Add tests for Camera and vis_offset
david added 1 commit 2026-03-16 08:54:13 +00:00
- Add docs/PIPELINE.md with comprehensive pipeline flowchart
- Document camera modes (vertical, horizontal, omni, floating)
- Update AGENTS.md with pipeline documentation instructions
david added 1 commit 2026-03-16 08:59:03 +00:00
- Add --pipeline-diagram flag to generate mermaid diagrams
- Create engine/pipeline.py with PipelineIntrospector
- Outputs flowchart, sequence diagram, and camera state diagram
- Run with: python mainline.py --pipeline-diagram
david added 1 commit 2026-03-16 09:00:09 +00:00
david added 1 commit 2026-03-16 09:05:02 +00:00
- Add --pipeline-demo flag for ASCII pipeline animation
- Create engine/pipeline_viz.py with animated pipeline graphics
- Shows data flow, camera modes, FPS counter
- Run with: python mainline.py --pipeline-demo --display pygame
david added 4 commits 2026-03-16 18:31:16 +00:00
- Add beautiful-mermaid library (single-file ASCII renderer)
- Update pipeline_viz to generate mermaid graphs and render with beautiful-mermaid
- Creates dimensional network visualization with arrows connecting nodes
- Animates through effects and highlights active camera mode
- Add engine/pipeline/ module with Stage ABC, PipelineContext, PipelineParams
- Stage provides unified interface for sources, effects, displays, cameras
- Pipeline class handles DAG-based execution with dependency resolution
- PipelinePreset for pre-configured pipelines (demo, poetry, pipeline, etc.)
- Add PipelineParams as params layer for animation-driven config
- Add StageRegistry for unified stage registration
- Add sources_v2.py with DataSource.is_dynamic property
- Add animation.py with Preset and AnimationController
- Skip ntfy integration tests by default (require -m integration)
- Skip e2e tests by default (require -m e2e)
- Update pipeline.py with comprehensive introspection methods
- Add RenderStage adapter that handles rendering pipeline
- Add EffectPluginStage with proper EffectContext
- Add DisplayStage with init handling
- Add ItemsStage for pre-fetched items
- Add metrics collection to Pipeline (StageMetrics, FrameMetrics)
- Add get_metrics_summary() and reset_metrics() methods
- Add --pipeline and --pipeline-preset flags for v2 mode
- Add PipelineNode.metrics for self-documenting introspection
- Add introspect_new_pipeline() method with performance data
- Add mise tasks: run-v2, run-v2-demo, run-v2-poetry, run-v2-websocket, run-v2-firehose
- Add TransformDataSource for filtering/mapping source items
- Add MetricsDataSource for rendering live pipeline metrics as ASCII art
- Fix display stage registration in StageRegistry
- Register sources with both class name and simple name aliases
- Fix DisplayStage.init() to pass reuse parameter
- Simplify create_default_pipeline to use DataSourceStage wrapper
- Set pygame as default display
- Remove old pipeline tasks from mise.toml
- Add tests for new pipeline architecture
This pull request has changes conflicting with the target branch.
  • .gitignore
  • README.md
  • cmdline.py
  • effects_plugins/__init__.py
  • effects_plugins/fade.py
  • effects_plugins/firehose.py
  • effects_plugins/glitch.py
  • effects_plugins/noise.py
  • engine/app.py
  • engine/effects/__init__.py
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u feature/vector_display:klubhaus-feature/vector_display
git checkout klubhaus-feature/vector_display
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: genewildish/Mainline#26