enzotar
746b76fe4f
perf: streaming core improvements — batched diffs, RTT tracking, relay merging
...
Runtime improvements:
- Diff batching: multiple signal changes coalesced into 1 WS frame
via _pendingDiffs + microtask Promise.resolve()
- Connection status: _streamConnected, _streamLatency, _streamReconnects,
_streamFrameCount, _streamByteCount tracked for stream health
- RTT tracking: periodic ping/pong every 5s measures round-trip latency
- Removed redundant _streamSync from flush() — diffs are already batched
Relay improvements:
- Diff merging: late joiners receive 1 consolidated sync frame instead
of replaying hundreds of individual diffs
- Version counters merged: conflict resolution preserved across catchup
- Fallback: if JSON parse fails, falls back to raw sync + all diffs
Test updates:
- state_cache_signal_sync verifies merged payload (count: 1)
- All 54 relay tests pass
- All 8 examples pass regression
2026-02-26 18:02:31 -08:00
enzotar
a8235c48b3
feat: stream composition API — select, schema, relay filtering
...
1. Receiver-side `select` clause:
- `stream from "url" { select: field1, field2 }`
- Parser, AST, codegen all updated
- Emits: `_connectStream(url, ["field1","field2"])`
- Client-side _csFilter strips unwanted fields
2. Schema announcement (0x32):
- Sources send output schema on connect
- Lists registered signal names and mode
3. Relay schema cache:
- ChannelState stores schema from 0x32
- Forwarded to late-joining receivers
4. Relay-side subscribe filter (0x33):
- Receivers send wanted fields after connecting
- Relay strips unwanted JSON keys from 0x30/0x31
frames before forwarding — saves bandwidth
Protocol: SchemaAnnounce=0x32, SubscribeFilter=0x33
54 tests pass, all crates build clean.
2026-02-26 10:07:47 -08:00
enzotar
a943d2e2e9
feat: peer mode relay + self-echo filtering for true bidirectional sync
...
- Added /peer/{name} route to relay: all clients are equal peers
- handle_peer: binary broadcast to all other peers, catchup for late joiners
- Simplified runtime: single /peer/ WS replaces dual source+receiver
- _peerId: random 8-char ID prevents self-echo from broadcast
- _pid in each diff JSON, filtered in _applyRemoteDiff
2026-02-25 21:37:17 -08:00
enzotar
cde84ae270
feat: production hardening — relay v1.0.0, receiver protocol completeness
...
Relay v1.0.0:
- Max receivers per channel (default: 64) with rejection counting
- Max channels limit (default: 256) with over-limit rejection
- Channel GC: periodic scan removes idle channels after grace period (30s)
- Source reconnection: cache preserved on disconnect, new input channels
- Stats: peak_receivers, total_connections, rejected_connections, uptime
- ChannelState::is_idle(), grace_period_expired() for lifecycle mgmt
- StateCache::clear(), has_state() for cache introspection
- Banner shows config: max receivers, max channels, grace period
- 54 tests (+8 new: channel_max_limit, idle detection, grace period, cache ops)
Receiver (_connectStream):
- Complete frame type handling: SignalSync (full replace), SignalDiff (merge),
Pixels/Keyframe (emit stream_frame), DeltaPixels (XOR + RLE decode),
Ping (keepalive), StreamEnd (emit stream_end)
- RLE decoder for delta pixel frames
- Exponential backoff reconnect (1s → capped at 10s)
- Connection stats: frames, bytes, reconnects
- Event emissions: stream_frame, stream_end for app-level handling
105 tests, 0 failures across workspace
2026-02-25 18:30:40 -08:00
enzotar
392e478351
feat: WebRTC transport — peer-to-peer data channels with auto-fallback
...
Relay:
- /signal/{channel} path for SDP/ICE exchange via WebSocket
- handle_signaling broadcasts text messages between signaling peers
- signaling_tx broadcast channel in ChannelState
- 46 ds-stream tests (+2 signaling path tests)
JS Runtime:
- _initWebRTC(signalingUrl, streamUrl, mode) with RTCPeerConnection
- Unordered DataChannel (ordered:false, maxRetransmits:0) for low latency
- Auto-fallback: WebSocket starts immediately, WebRTC upgrades in ≤5s
- Data channel override of _streamSend for transparent binary protocol
Parser/AST:
- StreamTransport enum (WebSocket, WebRTC)
- transport field in StreamDecl
- Parses: stream x on url { mode: signal, transport: webrtc }
Codegen:
- WebRTC: emits DS._initWebRTC(sigUrl, streamUrl, mode)
- WebSocket: emits DS._initStream(url, mode) (unchanged)
97 tests, 0 failures
2026-02-25 15:02:31 -08:00
enzotar
0ed76513a6
feat(relay): multi-source routing — /source/{name} and /stream/{name}
...
- ChannelState: per-channel broadcast, input mpsc, cache
- RelayState: HashMap<String, Arc<RwLock<ChannelState>>>
- parse_path: /source/{n}, /stream/{n}, legacy / fallback
- Per-channel stats logging with channel name prefix
- Backward compatible: plain /source and /stream use 'default' channel
- 44 ds-stream tests, 95 total workspace (0 failures)
2026-02-25 14:50:39 -08:00
enzotar
2b2b4ffaec
feat(wasm): add ds-stream-wasm crate — browser codec via WebAssembly
...
- 18KB WASM binary with wasm-bindgen exports
- Header encode/decode, RLE compression, XOR delta
- Message builders for signal diff/sync and input events
- 7 native tests, all passing
- Total workspace: 89 tests, 0 failures
2026-02-25 14:45:51 -08:00
enzotar
69f39746af
feat(ds-stream): RLE compression, input events, keyframe caching
...
- protocol.rs: TouchEvent, GamepadAxisEvent, GamepadButtonEvent, ResizeEvent
with encode/decode and roundtrip tests
- codec.rs: rle_encode/rle_decode for delta frame compression (333x on
unchanged frames), signal_sync_frame/signal_diff_frame builders,
touch/gamepad/stream_end convenience builders
- relay.rs: StateCache for late-joining receivers (keyframe + signal sync +
accumulated diffs), periodic keepalive pings, stats logging every 30s,
diff accumulator with cap at 1000
- BITSTREAM_INTEGRATION.md: compiler integration spec for another agent
- Tests: 17 → 38 (all passing)
2026-02-25 11:04:05 -08:00
enzotar
ea64617569
feat: physics language integration — scene container with Rapier2D WASM
...
- Add scene container to AST, lexer, parser, analyzer, and codegen
- Add circle/rect/line as UI elements for physics body declaration
- Compile scene {} to canvas + async WASM init + Rapier2D PhysicsWorld
- Reactive gravity via DS.effect() — bodies wake on gravity change
- Mouse drag interaction with impulse-based body movement
- Compile-time hex color parsing for body colors
- Fix is_signal_ref matching numeric literals (700.value bug)
- Fix body variable uniqueness (next_node_id per body)
- Fix gravity signal detection (check AST Ident before emit_expr)
- Add physics.ds example with 5 bodies + 4 gravity control buttons
- Update DREAMSTACK.md and IMPLEMENTATION_PLAN.md with Phase 10-11
- 39 tests pass across all crates, 22KB output
2026-02-25 10:58:43 -08:00
enzotar
d7961cdc98
feat: universal bitstream streaming — any input → any output
...
New crate: engine/ds-stream/
- Binary protocol: 16-byte header, typed frame/input enums
- Frame types: Pixels, Delta, Audio, Signal, Neural (0x01-0x43)
- Input types: Pointer, Key, Scroll, Gamepad, MIDI, BCI (0x01-0x90)
- WebSocket relay server (tokio + tungstenite)
- Source → receivers: frame broadcast
- Receivers → source: input routing
- Codec: encode/decode, XOR delta compression, RLE, convenience builders
- 17 unit tests, all passing
Streaming modes (stream-source.html):
1. Pixel mode: raw RGBA framebuffer (~28 MB/s)
2. Delta mode: XOR + RLE compression (~1-9 MB/s, 70-95% savings)
3. Signal mode: compact JSON signal diffs (~2 KB/s, 12000x reduction)
4. Neural mode: procedural SDF pixel generator (concept demo)
5. Audio channel: spring velocity→frequency synthesis
6. Multi-receiver: broadcast to all connected clients
Thin receiver client (stream-receiver.html, ~300 lines):
- Zero framework, zero build step
- Renders any incoming bitstream mode
- Local signal-diff renderer for signal mode
- AudioContext playback for audio frames
- Full input capture: click/drag, keyboard, scroll
- Per-channel bitstream bus visualization
DREAMSTACK.md: Phase 7 section with protocol spec
2026-02-25 10:29:44 -08:00