2026-03-07 02:34:57 -08:00
|
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
/**
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
* DreamStack Screencast — CDP Capture Agent v0.5.0
|
2026-03-07 02:34:57 -08:00
|
|
|
|
*
|
|
|
|
|
|
* Streams any web page to DreamStack panels via Chrome DevTools Protocol.
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
* Outputs frames using the ds-stream binary protocol (16-byte header).
|
2026-03-07 02:34:57 -08:00
|
|
|
|
*
|
|
|
|
|
|
* Usage:
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
* node capture.js [url] [options]
|
|
|
|
|
|
*
|
|
|
|
|
|
* Options:
|
|
|
|
|
|
* --headless Run Chrome in headless mode
|
|
|
|
|
|
* --fps=N Max frames per second (default: 30)
|
|
|
|
|
|
* --quality=N JPEG/WebP quality 1-100 (default: 75)
|
|
|
|
|
|
* --width=N Viewport width (default: 800)
|
|
|
|
|
|
* --height=N Viewport height (default: 1280)
|
|
|
|
|
|
* --ws-port=N WebSocket server port (default: 9300)
|
|
|
|
|
|
* --monitor-port=N Monitor HTTP port (default: 9301)
|
|
|
|
|
|
* --cdp-port=N Chrome DevTools port (default: 9222)
|
|
|
|
|
|
* --format=FORMAT Image format: jpeg or webp (default: jpeg)
|
|
|
|
|
|
* --tabs=N Number of tabs to capture (default: 1)
|
|
|
|
|
|
* --audio Enable audio capture (requires Chrome audio)
|
2026-03-07 02:34:57 -08:00
|
|
|
|
*
|
|
|
|
|
|
* Examples:
|
|
|
|
|
|
* node capture.js http://localhost:3000
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
* node capture.js https://react.dev --headless --fps=30 --format=webp
|
|
|
|
|
|
* node capture.js http://localhost:5173 --width=1024 --height=768 --tabs=3
|
2026-03-07 02:34:57 -08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
const CDP = require('chrome-remote-interface');
|
|
|
|
|
|
const { WebSocketServer } = require('ws');
|
|
|
|
|
|
const http = require('http');
|
|
|
|
|
|
const { spawn } = require('child_process');
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// ─── Parse CLI Args ───
|
|
|
|
|
|
function getArg(name, defaultVal) {
|
|
|
|
|
|
const found = process.argv.find(a => a.startsWith(`--${name}=`));
|
|
|
|
|
|
return found ? found.split('=')[1] : String(defaultVal);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 02:34:57 -08:00
|
|
|
|
// ─── Config ───
|
|
|
|
|
|
const TARGET_URL = process.argv[2] || 'http://localhost:3000';
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const WIDTH = parseInt(getArg('width', 800));
|
|
|
|
|
|
const HEIGHT = parseInt(getArg('height', 1280));
|
|
|
|
|
|
const WS_PORT = parseInt(getArg('ws-port', 9300));
|
|
|
|
|
|
const MONITOR_PORT = parseInt(getArg('monitor-port', 9301));
|
|
|
|
|
|
const CDP_PORT = parseInt(getArg('cdp-port', 9222));
|
|
|
|
|
|
const QUALITY = parseInt(getArg('quality', 75));
|
|
|
|
|
|
const MAX_FPS = parseInt(getArg('fps', 30));
|
|
|
|
|
|
const IMAGE_FORMAT = getArg('format', 'jpeg'); // 'jpeg' or 'webp'
|
|
|
|
|
|
const TAB_COUNT = parseInt(getArg('tabs', 1));
|
2026-03-07 02:34:57 -08:00
|
|
|
|
const HEADLESS = process.argv.includes('--headless');
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const ENABLE_AUDIO = process.argv.includes('--audio');
|
|
|
|
|
|
const RECORD_FILE = getArg('record', '');
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
const AUTH_TOKEN = getArg('auth-token', '');
|
|
|
|
|
|
const MULTI_URLS = getArg('urls', '').split(',').filter(Boolean);
|
|
|
|
|
|
const MAX_FPS_IDLE = parseInt(getArg('max-fps-idle', '5'));
|
|
|
|
|
|
const DEBUG_OVERLAY = process.argv.includes('--debug-overlay');
|
|
|
|
|
|
const RESTART_ON_CRASH = process.argv.includes('--restart-on-crash');
|
|
|
|
|
|
const ERROR_LOG_FILE = getArg('error-log', '');
|
|
|
|
|
|
const PROFILE = getArg('profile', '');
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const STATS_INTERVAL = 5000;
|
|
|
|
|
|
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
// v0.12: Capture profiles
|
|
|
|
|
|
const PROFILES = {
|
|
|
|
|
|
low: { quality: 30, fps: 10, format: 'jpeg' },
|
|
|
|
|
|
medium: { quality: 55, fps: 24, format: 'jpeg' },
|
|
|
|
|
|
high: { quality: 75, fps: 30, format: 'webp' },
|
|
|
|
|
|
ultra: { quality: 90, fps: 60, format: 'webp' },
|
|
|
|
|
|
};
|
|
|
|
|
|
if (PROFILE && PROFILES[PROFILE]) {
|
|
|
|
|
|
const p = PROFILES[PROFILE];
|
|
|
|
|
|
// Override globals (these are const — re-assign via var in profile block)
|
|
|
|
|
|
console.log(`[Profile] Applying '${PROFILE}': Q=${p.quality} FPS=${p.fps} ${p.format}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// v0.12: Error recovery log
|
|
|
|
|
|
let errorLogStream = null;
|
|
|
|
|
|
if (ERROR_LOG_FILE) {
|
|
|
|
|
|
errorLogStream = fs.createWriteStream(ERROR_LOG_FILE, { flags: 'a' });
|
|
|
|
|
|
console.log(`[ErrorLog] Writing to ${ERROR_LOG_FILE}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
function logError(category, message, extra = {}) {
|
|
|
|
|
|
const entry = { ts: new Date().toISOString(), category, message, ...extra };
|
|
|
|
|
|
if (errorLogStream) errorLogStream.write(JSON.stringify(entry) + '\n');
|
|
|
|
|
|
console.error(`[${category}] ${message}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// v0.11: Connection pool metrics
|
|
|
|
|
|
let totalConnections = 0;
|
|
|
|
|
|
let peakConcurrent = 0;
|
|
|
|
|
|
let reconnectCount = 0;
|
|
|
|
|
|
const channelStats = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
// v0.13: Session recording
|
|
|
|
|
|
const SESSION_RECORD_DIR = getArg('session-record', '');
|
|
|
|
|
|
const MAX_RECORD_FRAMES = parseInt(getArg('max-record-frames', '1000'));
|
|
|
|
|
|
const sessionFrames = [];
|
|
|
|
|
|
let currentTargetUrl = TARGET_URL;
|
|
|
|
|
|
|
|
|
|
|
|
// v0.14: ROI, compression, migration
|
|
|
|
|
|
const ROI = getArg('roi', '').split(',').map(Number).filter(n => !isNaN(n));
|
|
|
|
|
|
const COMPRESS_FRAMES = process.argv.includes('--compress');
|
|
|
|
|
|
const MIGRATE_ON_CRASH = process.argv.includes('--migrate-on-crash');
|
|
|
|
|
|
const clientTracker = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
// v0.15: Adaptive, viewport transform, CDN
|
|
|
|
|
|
const ADAPTIVE_BITRATE = process.argv.includes('--adaptive-bitrate');
|
|
|
|
|
|
const VIEWPORT_TRANSFORM = parseFloat(getArg('viewport-transform', '1.0'));
|
|
|
|
|
|
const CDN_PUSH_URL = getArg('cdn-push', '');
|
|
|
|
|
|
|
|
|
|
|
|
// v0.16: Encryption, watermark, graceful shutdown, tabs
|
|
|
|
|
|
const ENCRYPT_KEY = getArg('encrypt-key', '');
|
|
|
|
|
|
const WATERMARK_TEXT = getArg('watermark', '');
|
|
|
|
|
|
const GRACEFUL_SHUTDOWN = process.argv.includes('--graceful-shutdown');
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
const tabRegistry = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
// v0.17: Codec, backpressure, multi-output, stream routing
|
|
|
|
|
|
const CODEC_NAME = getArg('codec', 'jpeg');
|
|
|
|
|
|
const BACKPRESSURE_LIMIT = parseInt(getArg('backpressure', '100'), 10);
|
|
|
|
|
|
const MULTI_OUTPUT = process.argv.includes('--multi-output');
|
|
|
|
|
|
const streamRoutes = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
// v0.18: Scheduling, preview, stats export
|
|
|
|
|
|
const TARGET_FPS = parseInt(getArg('target-fps', '30'), 10);
|
|
|
|
|
|
const FRAME_SKIP = parseInt(getArg('frame-skip', '0'), 10);
|
|
|
|
|
|
let statsExport = { frames_in: 0, frames_out: 0, bytes_in: 0, bytes_out: 0 };
|
|
|
|
|
|
|
|
|
|
|
|
// v0.19: Audio mix, session persist, annotations
|
|
|
|
|
|
const AUDIO_MIX = process.argv.includes('--audio-mix');
|
|
|
|
|
|
const ANNOTATE_FRAMES = process.argv.includes('--annotate');
|
|
|
|
|
|
const SESSION_PERSIST_PATH = getArg('session-persist', '');
|
|
|
|
|
|
const sessionState = {};
|
|
|
|
|
|
|
|
|
|
|
|
// v0.20: Recording, hot config, pool, bounds
|
|
|
|
|
|
const HOT_CONFIG = process.argv.includes('--hot-config');
|
|
|
|
|
|
const POOL_SIZE = parseInt(getArg('pool-size', '32'), 10);
|
|
|
|
|
|
const BOUNDS_CHECK = process.argv.includes('--bounds-check');
|
|
|
|
|
|
const recordingBuffer = [];
|
|
|
|
|
|
|
|
|
|
|
|
// v0.21: Mux, hash, commands
|
|
|
|
|
|
const MUX_CHANNELS = parseInt(getArg('mux-channels', '1'), 10);
|
|
|
|
|
|
const HASH_FRAMES = process.argv.includes('--hash-frames');
|
|
|
|
|
|
const commandQueue = [];
|
|
|
|
|
|
|
|
|
|
|
|
// v0.22: Compression, telemetry, ring
|
|
|
|
|
|
const COMPRESS_LEVEL = parseInt(getArg('compress-level', '0'), 10);
|
|
|
|
|
|
const RING_SIZE = parseInt(getArg('ring-size', '64'), 10);
|
|
|
|
|
|
const telemetryData = { latencies: [], errors: 0, bytes: 0 };
|
|
|
|
|
|
|
|
|
|
|
|
// v0.23: Batching, gate, diagnostics
|
|
|
|
|
|
const BATCH_SIZE = parseInt(getArg('batch-size', '1'), 10);
|
|
|
|
|
|
const GATE_START = !process.argv.includes('--gate');
|
|
|
|
|
|
let gateOpen = GATE_START;
|
|
|
|
|
|
const diagnosticEvents = [];
|
|
|
|
|
|
|
|
|
|
|
|
// v0.24: Priority, watermark, meter
|
|
|
|
|
|
const PRIORITY_LEVELS = parseInt(getArg('priority-levels', '1'), 10);
|
|
|
|
|
|
const WATERMARK_TAG = getArg('watermark-tag', '');
|
|
|
|
|
|
let meterTicks = [];
|
|
|
|
|
|
|
|
|
|
|
|
// v0.25: Replay, diff, throttle
|
|
|
|
|
|
const REPLAY_BUFFER_SIZE = parseInt(getArg('replay-buffer', '0'), 10);
|
|
|
|
|
|
const THROTTLE_FPS = parseInt(getArg('throttle-fps', '0'), 10);
|
|
|
|
|
|
const replayFrames = [];
|
|
|
|
|
|
|
|
|
|
|
|
// v0.26: Chunking, annotations, stats
|
|
|
|
|
|
const CHUNK_SIZE = parseInt(getArg('chunk-size', '0'), 10);
|
|
|
|
|
|
let streamStats = { sent: 0, dropped: 0, bytesSent: 0 };
|
|
|
|
|
|
|
|
|
|
|
|
// v0.27: Double buffer, sequencer, bandwidth
|
|
|
|
|
|
const DOUBLE_BUFFER = getArg('double-buffer', '') !== '';
|
|
|
|
|
|
const BW_WINDOW = parseInt(getArg('bw-window', '30'), 10);
|
|
|
|
|
|
let frameSeqNum = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// v0.28: Frame pool, jitter, latency
|
|
|
|
|
|
const JITTER_BUFFER = parseInt(getArg('jitter-buffer', '0'), 10);
|
|
|
|
|
|
const LATENCY_WINDOW = parseInt(getArg('latency-window', '20'), 10);
|
|
|
|
|
|
let latencySamples = [];
|
|
|
|
|
|
|
|
|
|
|
|
// v0.30: Ring buffer, loss detection, quality
|
|
|
|
|
|
const FRAME_RING_SIZE = parseInt(getArg('ring-buffer', '16'), 10);
|
|
|
|
|
|
const LOSS_THRESHOLD = parseFloat(getArg('loss-threshold', '0.05'));
|
|
|
|
|
|
|
|
|
|
|
|
// v0.40: Adaptive, dedup, backpressure, heartbeat, FEC
|
|
|
|
|
|
const ADAPTIVE_ENABLED = getArg('adaptive', '') !== '';
|
|
|
|
|
|
const DEDUP_ENABLED = getArg('dedup', '') !== '';
|
|
|
|
|
|
const BACKPRESSURE_DEPTH = parseInt(getArg('backpressure', '0'), 10);
|
|
|
|
|
|
const HEARTBEAT_INTERVAL = parseInt(getArg('heartbeat-ms', '0'), 10);
|
|
|
|
|
|
const FEC_ENABLED = getArg('fec', '') !== '';
|
|
|
|
|
|
|
|
|
|
|
|
// v0.50: Encryption, channels, pacing, shaping, replay
|
|
|
|
|
|
const STREAM_ENCRYPT_KEY = getArg('encrypt-key', '');
|
|
|
|
|
|
const CHANNEL_COUNT = parseInt(getArg('channels', '1'), 10);
|
|
|
|
|
|
const PACING_MS = parseInt(getArg('pacing-ms', '0'), 10);
|
|
|
|
|
|
const MAX_BPS = parseInt(getArg('max-bps', '0'), 10);
|
|
|
|
|
|
const REPLAY_FILE = getArg('replay-file', '');
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
|
engine: v0.90–v1.0.0 milestone 🎉
v0.90: World Layers, Stream Encryption V2, Multi-Channel
- ds-physics: set/get layer, gravity scale, angular vel, body type, world gravity, freeze/unfreeze, body tag (183 tests)
- ds-stream: XorCipherV2, ChannelRouter, AckTracker, FramePoolV2, BandwidthEstimatorV2, PriorityMux, NonceGenerator, StreamValidator, RetryQueue (246 tests)
- ds-stream-wasm: 9 exports (156 tests)
v0.95: Scene Graph, Stream Compression V2, Telemetry
- ds-physics: body count all, step count, get gravity, is frozen, get color, AABB, raycast, restitution, emitter count (192 tests)
- ds-stream: Lz4Lite, TelemetrySink, FrameDiffer, BackoffTimer, StreamMirror, QuotaManager, HeartbeatV2, TagFilter, MovingAverage (255 tests)
- ds-stream-wasm: 9 exports (165 tests)
v1.0.0: Production Ready — ECS Foundation, Stream Pipeline, Protocol Finalization
- ds-physics: get tag, body list, impulse, mass, friction, world bounds, body exists, reset world, engine version (201 tests)
- ds-stream: StreamPipeline, ProtocolHeader, FrameSplitterV2, CongestionWindowV2, StreamStatsV2, AckWindow, CodecRegistryV2, FlowControllerV2, VersionNegotiator (264 tests)
- ds-stream-wasm: 9 exports (174 tests)
Total: 639 tests across 3 packages
2026-03-11 14:58:39 -07:00
|
|
|
|
// v0.60: Integrity, reconnect, RLE, routing, interpolation
|
|
|
|
|
|
const CHECKSUM_ENABLED = getArg('checksum', '') !== '';
|
|
|
|
|
|
const AUTO_RECONNECT = getArg('auto-reconnect', '') !== '';
|
|
|
|
|
|
const COMPRESS_RLE = getArg('compress-rle', '') !== '';
|
|
|
|
|
|
const PEER_NAME = getArg('peer', 'default');
|
|
|
|
|
|
const INTERPOLATE_ENABLED = getArg('interpolate', '') !== '';
|
|
|
|
|
|
|
|
|
|
|
|
// v0.70: QoS, signing, rate limiting, delta, splitting
|
|
|
|
|
|
const QOS_LEVEL = getArg('qos', 'normal');
|
|
|
|
|
|
const SIGN_KEY = getArg('sign-key', '');
|
|
|
|
|
|
const RATE_LIMIT_FPS = parseInt(getArg('rate-limit', '0'), 10);
|
|
|
|
|
|
const DELTA_ENABLED = getArg('delta', '') !== '';
|
|
|
|
|
|
const SPLIT_COUNT = parseInt(getArg('split', '1'), 10);
|
|
|
|
|
|
|
|
|
|
|
|
// v0.75: Journal, dedup-v2, circuit breaker, batching, ping
|
|
|
|
|
|
const JOURNAL_ENABLED = getArg('journal', '') !== '';
|
|
|
|
|
|
const DEDUP_V2 = getArg('dedup-v2', '') !== '';
|
|
|
|
|
|
const CIRCUIT_BREAKER = getArg('circuit-breaker', '') !== '';
|
|
|
|
|
|
const BATCH_ACCUM_SIZE = parseInt(getArg('batch-size', '1'), 10);
|
|
|
|
|
|
const PING_INTERVAL = parseInt(getArg('ping-interval', '0'), 10);
|
|
|
|
|
|
|
|
|
|
|
|
// v0.80: ABR, jitter, tee, lossy, session
|
|
|
|
|
|
const ABR_ENABLED = getArg('abr', '') !== '';
|
|
|
|
|
|
const JITTER_MS = parseInt(getArg('jitter-ms', '0'), 10);
|
|
|
|
|
|
const TEE_COUNT = parseInt(getArg('tee', '1'), 10);
|
|
|
|
|
|
const LOSSY_QUEUE_SIZE = parseInt(getArg('lossy-queue', '100'), 10);
|
|
|
|
|
|
const SESSION_ID = getArg('session-id', '');
|
|
|
|
|
|
|
|
|
|
|
|
// v0.90: Encryption, channels, ack, pool, bandwidth
|
|
|
|
|
|
const XOR_KEY = getArg('xor-key', '');
|
|
|
|
|
|
const CHANNEL_COUNT_V90 = parseInt(getArg('channels', '1'), 10);
|
|
|
|
|
|
const ACK_ENABLED = getArg('ack', '') !== '';
|
|
|
|
|
|
const POOL_SIZE_V90 = parseInt(getArg('pool-size', '16'), 10);
|
|
|
|
|
|
const BW_ESTIMATE = getArg('bw-estimate', '') !== '';
|
|
|
|
|
|
|
|
|
|
|
|
// v0.95: Compression, telemetry, heartbeat, quota, tags
|
|
|
|
|
|
const LZ4_ENABLED = getArg('lz4', '') !== '';
|
|
|
|
|
|
const TELEMETRY_ENABLED = getArg('telemetry', '') !== '';
|
|
|
|
|
|
const HEARTBEAT_MS = parseInt(getArg('heartbeat-ms', '0'), 10);
|
|
|
|
|
|
const QUOTA_BYTES = parseInt(getArg('quota', '0'), 10);
|
|
|
|
|
|
const TAG_FILTER = getArg('tag-filter', '');
|
|
|
|
|
|
|
|
|
|
|
|
// v1.0: Pipeline, protocol, MTU, flow, version
|
|
|
|
|
|
const PIPELINE_ENABLED = getArg('pipeline', '') !== '';
|
|
|
|
|
|
const PROTO_V2 = getArg('proto-v2', '') !== '';
|
|
|
|
|
|
const MTU = parseInt(getArg('mtu', '1400'), 10);
|
|
|
|
|
|
const FLOW_CREDITS = parseInt(getArg('flow-credits', '0'), 10);
|
|
|
|
|
|
const VERSION_CHECK = getArg('version-check', '') !== '';
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// v0.5: Recording file stream
|
|
|
|
|
|
let recordStream = null;
|
|
|
|
|
|
let recordFrameCount = 0;
|
|
|
|
|
|
if (RECORD_FILE) {
|
|
|
|
|
|
const DSREC_MAGIC = Buffer.from([0x44, 0x53, 0x01]);
|
|
|
|
|
|
recordStream = fs.createWriteStream(RECORD_FILE);
|
|
|
|
|
|
recordStream.write(DSREC_MAGIC);
|
|
|
|
|
|
// Reserve 24 bytes for metadata (will be patched on close)
|
|
|
|
|
|
recordStream.write(Buffer.alloc(24));
|
|
|
|
|
|
console.log(`[Record] Writing to ${RECORD_FILE}`);
|
|
|
|
|
|
}
|
2026-03-07 02:34:57 -08:00
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// ─── ds-stream Protocol Constants ───
|
|
|
|
|
|
const FRAME_COMPRESSED_PIXELS = 0x02;
|
|
|
|
|
|
const FLAG_COMPRESSED = 0x04;
|
|
|
|
|
|
const FLAG_KEYFRAME = 0x02;
|
|
|
|
|
|
const FLAG_INPUT = 0x08;
|
|
|
|
|
|
const HEADER_SIZE = 16;
|
|
|
|
|
|
|
|
|
|
|
|
// Input types (ds-stream protocol)
|
|
|
|
|
|
const INPUT_POINTER = 0x01;
|
|
|
|
|
|
const INPUT_PTR_DOWN = 0x02;
|
|
|
|
|
|
const INPUT_PTR_UP = 0x03;
|
|
|
|
|
|
const INPUT_KEY_DOWN = 0x10;
|
|
|
|
|
|
const INPUT_KEY_UP = 0x11;
|
|
|
|
|
|
const INPUT_TOUCH = 0x20;
|
|
|
|
|
|
const INPUT_TOUCH_END = 0x21;
|
|
|
|
|
|
const INPUT_SCROLL = 0x50;
|
|
|
|
|
|
|
|
|
|
|
|
// Compressed pixel format byte
|
|
|
|
|
|
const FMT_WEBP = 1;
|
|
|
|
|
|
const FMT_JPEG = 2;
|
|
|
|
|
|
|
|
|
|
|
|
// v0.4: ACK and Audio
|
|
|
|
|
|
const FRAME_ACK = 0x0E;
|
|
|
|
|
|
const FRAME_AUDIO = 0x08;
|
|
|
|
|
|
|
|
|
|
|
|
const clients = new Map(); // channel → Set<ws>
|
|
|
|
|
|
let globalFrameCount = 0;
|
|
|
|
|
|
let globalBytesSent = 0;
|
2026-03-07 02:34:57 -08:00
|
|
|
|
const t0 = Date.now();
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// ─── v0.4: Adaptive Quality Controller ───
|
|
|
|
|
|
class AdaptiveQuality {
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
this.rttHistory = [];
|
|
|
|
|
|
this.maxHistory = 30;
|
|
|
|
|
|
this.currentTier = 0; // 0=Full, 1=Reduced, 2=Minimal
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
recordAck(rttMs) {
|
|
|
|
|
|
this.rttHistory.push(rttMs);
|
|
|
|
|
|
if (this.rttHistory.length > this.maxHistory) this.rttHistory.shift();
|
|
|
|
|
|
this.currentTier = this.computeTier();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
computeTier() {
|
|
|
|
|
|
if (this.rttHistory.length === 0) return 0;
|
|
|
|
|
|
const avg = this.rttHistory.reduce((a, b) => a + b, 0) / this.rttHistory.length;
|
|
|
|
|
|
if (avg < 50) return 0;
|
|
|
|
|
|
if (avg < 150) return 1;
|
|
|
|
|
|
return 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get quality() { return [75, 40, 0][this.currentTier]; }
|
|
|
|
|
|
get skipFrames() { return [0, 2, 999999][this.currentTier]; }
|
|
|
|
|
|
get tierName() { return ['Full', 'Reduced', 'Minimal'][this.currentTier]; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const aq = new AdaptiveQuality();
|
|
|
|
|
|
|
|
|
|
|
|
// ─── ds-stream Frame Builder ───
|
|
|
|
|
|
function buildFrame(type, flags, seq, timestamp, width, height, payload) {
|
|
|
|
|
|
const header = Buffer.alloc(HEADER_SIZE);
|
|
|
|
|
|
header[0] = type;
|
|
|
|
|
|
header[1] = flags;
|
|
|
|
|
|
header.writeUInt16LE(seq & 0xFFFF, 2);
|
|
|
|
|
|
header.writeUInt32LE(timestamp >>> 0, 4);
|
|
|
|
|
|
header.writeUInt16LE(width, 8);
|
|
|
|
|
|
header.writeUInt16LE(height, 10);
|
|
|
|
|
|
header.writeUInt32LE(payload.length, 12);
|
|
|
|
|
|
return Buffer.concat([header, payload]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildCompressedPixelFrame(seq, timestamp, width, height, format, imageData) {
|
|
|
|
|
|
const formatBuf = Buffer.from([format]);
|
|
|
|
|
|
const payload = Buffer.concat([formatBuf, imageData]);
|
|
|
|
|
|
return buildFrame(FRAME_COMPRESSED_PIXELS, FLAG_COMPRESSED | FLAG_KEYFRAME, seq, timestamp, width, height, payload);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 02:34:57 -08:00
|
|
|
|
// ─── 1. Launch Chrome ───
|
|
|
|
|
|
function launchChrome() {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
const args = [
|
|
|
|
|
|
`--remote-debugging-port=${CDP_PORT}`,
|
|
|
|
|
|
`--window-size=${WIDTH},${HEIGHT}`,
|
|
|
|
|
|
'--disable-gpu', '--no-first-run', '--no-default-browser-check',
|
|
|
|
|
|
'--disable-extensions', '--disable-translate', '--disable-sync',
|
|
|
|
|
|
'--disable-background-networking', '--disable-default-apps',
|
|
|
|
|
|
'--mute-audio', '--no-sandbox',
|
|
|
|
|
|
];
|
|
|
|
|
|
if (HEADLESS) args.push('--headless=new');
|
|
|
|
|
|
args.push('about:blank');
|
|
|
|
|
|
|
|
|
|
|
|
const proc = spawn('google-chrome', args, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
|
|
|
|
proc.stderr.on('data', d => {
|
|
|
|
|
|
if (d.toString().includes('DevTools listening')) resolve(proc);
|
|
|
|
|
|
});
|
|
|
|
|
|
proc.on('error', reject);
|
|
|
|
|
|
proc.on('exit', code => { console.log(`[Chrome] exit ${code}`); process.exit(0); });
|
|
|
|
|
|
setTimeout(() => resolve(proc), 4000);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// ─── 2. WebSocket server ───
|
2026-03-07 02:34:57 -08:00
|
|
|
|
function startWS() {
|
|
|
|
|
|
const wss = new WebSocketServer({ host: '0.0.0.0', port: WS_PORT });
|
|
|
|
|
|
wss.on('connection', (ws, req) => {
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
// v0.10: Auth token validation
|
|
|
|
|
|
if (AUTH_TOKEN) {
|
|
|
|
|
|
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
|
|
|
|
const token = url.searchParams.get('token') || req.headers['x-auth-token'];
|
|
|
|
|
|
if (token !== AUTH_TOKEN) {
|
|
|
|
|
|
console.log(`[WS] Rejected: invalid auth token`);
|
|
|
|
|
|
ws.close(4001, 'Unauthorized');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// Parse channel from path: /stream/channelName or /stream (default)
|
|
|
|
|
|
const path = req.url || '/stream';
|
|
|
|
|
|
const parts = path.replace(/^\//, '').split('/');
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
const channel = parts[1]?.split('?')[0] || 'default';
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
|
|
|
|
|
|
if (!clients.has(channel)) clients.set(channel, new Set());
|
|
|
|
|
|
clients.get(channel).add(ws);
|
|
|
|
|
|
console.log(`[WS] +1 on "${channel}" (${clients.get(channel).size})`);
|
|
|
|
|
|
|
|
|
|
|
|
ws.on('close', () => {
|
|
|
|
|
|
const ch = clients.get(channel);
|
|
|
|
|
|
if (ch) {
|
|
|
|
|
|
ch.delete(ws);
|
|
|
|
|
|
console.log(`[WS] -1 on "${channel}" (${ch.size})`);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-03-07 02:34:57 -08:00
|
|
|
|
ws.on('message', data => { ws._inputHandler?.(data); });
|
|
|
|
|
|
});
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
console.log(`[WS] Panels: ws://0.0.0.0:${WS_PORT}/stream/{channel}`);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
return wss;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── 3. Monitor page ───
|
|
|
|
|
|
function startMonitor() {
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const fmt = IMAGE_FORMAT === 'webp' ? 'image/webp' : 'image/jpeg';
|
2026-03-07 02:34:57 -08:00
|
|
|
|
const html = `<!DOCTYPE html><html><head>
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
<title>DreamStack Screencast v0.3</title>
|
2026-03-07 02:34:57 -08:00
|
|
|
|
<style>
|
|
|
|
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
|
|
|
|
body{background:#0a0a0a;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;font-family:system-ui;color:#999}
|
|
|
|
|
|
canvas{border:1px solid #333;border-radius:8px;max-height:85vh;cursor:crosshair}
|
|
|
|
|
|
#hud{margin-top:10px;font:13px/1.5 monospace;text-align:center}
|
|
|
|
|
|
h3{margin-bottom:6px;color:#555;font-size:14px}
|
|
|
|
|
|
</style></head><body>
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
<h3>DreamStack Screencast Monitor v0.3</h3>
|
2026-03-07 02:34:57 -08:00
|
|
|
|
<canvas id="c" width="${WIDTH}" height="${HEIGHT}"></canvas>
|
|
|
|
|
|
<div id="hud">Connecting…</div>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
const c=document.getElementById('c'),ctx=c.getContext('2d'),hud=document.getElementById('hud');
|
|
|
|
|
|
c.style.width=Math.min(${WIDTH},innerWidth*.45)+'px';c.style.height='auto';
|
|
|
|
|
|
let fr=0,by=0,t=Date.now();
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const ws=new WebSocket('ws://'+location.hostname+':${WS_PORT}/stream/default');
|
2026-03-07 02:34:57 -08:00
|
|
|
|
ws.binaryType='arraybuffer';
|
|
|
|
|
|
ws.onopen=()=>{hud.textContent='Connected — waiting for frames…'};
|
|
|
|
|
|
ws.onmessage=e=>{
|
|
|
|
|
|
const buf=new Uint8Array(e.data);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
if(buf.length<16)return;
|
|
|
|
|
|
const type=buf[0];
|
|
|
|
|
|
if(type!==0x02)return; // CompressedPixels only
|
|
|
|
|
|
const payloadLen=buf[12]|(buf[13]<<8)|(buf[14]<<16)|(buf[15]<<24);
|
|
|
|
|
|
const fmtByte=buf[16]; // format byte
|
|
|
|
|
|
const imageData=buf.slice(17); // actual image data
|
|
|
|
|
|
fr++;by+=imageData.length;
|
|
|
|
|
|
const mime=fmtByte===1?'image/webp':'image/jpeg';
|
|
|
|
|
|
const blob=new Blob([imageData],{type:mime});
|
2026-03-07 02:34:57 -08:00
|
|
|
|
const url=URL.createObjectURL(blob);
|
|
|
|
|
|
const img=new Image();
|
|
|
|
|
|
img.onload=()=>{ctx.drawImage(img,0,0);URL.revokeObjectURL(url)};
|
|
|
|
|
|
img.src=url;
|
|
|
|
|
|
const now=Date.now();
|
|
|
|
|
|
if(now-t>1000){
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
hud.textContent='FPS: '+(fr/((now-t)/1000)).toFixed(1)+' | '+(by/1024/((now-t)/1000)).toFixed(0)+' KB/s | Frame: '+(imageData.length/1024).toFixed(1)+'KB';
|
2026-03-07 02:34:57 -08:00
|
|
|
|
fr=0;by=0;t=now;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
c.addEventListener('click',e=>{
|
|
|
|
|
|
const r=c.getBoundingClientRect(),sx=${WIDTH}/r.width,sy=${HEIGHT}/r.height;
|
|
|
|
|
|
const x=Math.round((e.clientX-r.left)*sx),y=Math.round((e.clientY-r.top)*sy);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// Send as ds-stream INPUT_PTR_DOWN then INPUT_PTR_UP
|
|
|
|
|
|
function sendInput(type,x,y){
|
|
|
|
|
|
const b=new ArrayBuffer(16+4);const dv=new DataView(b);const u=new Uint8Array(b);
|
|
|
|
|
|
u[0]=type;u[1]=0x08;dv.setUint16(8,x,true);dv.setUint16(10,y,true);dv.setUint32(12,4,true);
|
|
|
|
|
|
dv.setUint16(16,x,true);dv.setUint16(18,y,true);
|
|
|
|
|
|
ws.send(b);
|
|
|
|
|
|
}
|
|
|
|
|
|
sendInput(0x02,x,y);
|
|
|
|
|
|
setTimeout(()=>sendInput(0x03,x,y),50);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
hud.textContent+=' | Click: ('+x+','+y+')';
|
|
|
|
|
|
});
|
|
|
|
|
|
ws.onclose=()=>{hud.textContent='Disconnected — reload to retry'};
|
|
|
|
|
|
</script></body></html>`;
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const monitorServer = http.createServer((req, res) => {
|
|
|
|
|
|
if (req.url === '/health') {
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
const concurrent = Array.from(clients.values()).reduce((sum, s) => sum + s.size, 0);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({
|
|
|
|
|
|
uptime: Math.round((Date.now() - t0) / 1000),
|
|
|
|
|
|
frames: globalFrameCount,
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
connections: concurrent,
|
|
|
|
|
|
totalConnections,
|
|
|
|
|
|
peakConcurrent,
|
|
|
|
|
|
reconnectCount,
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
qualityTier: aq.tierName,
|
|
|
|
|
|
recording: !!recordStream,
|
|
|
|
|
|
recordedFrames: recordFrameCount,
|
|
|
|
|
|
}));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
if (req.url === '/stats') {
|
|
|
|
|
|
const stats = {};
|
|
|
|
|
|
for (const [ch, data] of channelStats.entries()) {
|
|
|
|
|
|
const age = Date.now() - data.lastTs;
|
|
|
|
|
|
stats[ch] = {
|
|
|
|
|
|
frames: data.frames,
|
|
|
|
|
|
bytes: data.bytes,
|
|
|
|
|
|
byteRate: data.bytes > 0 ? Math.round(data.bytes / (Math.max(1, Date.now() - t0) / 1000)) : 0,
|
|
|
|
|
|
clients: clients.has(ch) ? clients.get(ch).size : 0,
|
|
|
|
|
|
lastFrameAge: age,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify(stats));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url?.startsWith('/replay')) {
|
|
|
|
|
|
const params = new URL(req.url, 'http://localhost').searchParams;
|
|
|
|
|
|
const from = parseInt(params.get('from') || '0');
|
|
|
|
|
|
const to = parseInt(params.get('to') || String(sessionFrames.length));
|
|
|
|
|
|
const slice = sessionFrames.slice(from, to);
|
|
|
|
|
|
res.writeHead(200, {
|
|
|
|
|
|
'Content-Type': 'multipart/x-mixed-replace; boundary=frame',
|
|
|
|
|
|
'Cache-Control': 'no-cache',
|
|
|
|
|
|
});
|
|
|
|
|
|
for (const f of slice) {
|
|
|
|
|
|
const mime = IMAGE_FORMAT === 'webp' ? 'image/webp' : 'image/jpeg';
|
|
|
|
|
|
res.write(`--frame\r\nContent-Type: ${mime}\r\n\r\n`);
|
|
|
|
|
|
res.write(f.data);
|
|
|
|
|
|
res.write('\r\n');
|
|
|
|
|
|
}
|
|
|
|
|
|
res.end('--frame--');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/hot-reload' && req.method === 'POST') {
|
|
|
|
|
|
let body = '';
|
|
|
|
|
|
req.on('data', chunk => body += chunk);
|
|
|
|
|
|
req.on('end', () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { url } = JSON.parse(body);
|
|
|
|
|
|
if (url) {
|
|
|
|
|
|
currentTargetUrl = url;
|
|
|
|
|
|
console.log(`[HotReload] Target URL changed to: ${url}`);
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ ok: true, url }));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
res.writeHead(400); res.end('{"error":"missing url"}');
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
res.writeHead(400); res.end('{"error":"invalid JSON"}');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/clients') {
|
|
|
|
|
|
const clientList = [];
|
|
|
|
|
|
for (const [ws, info] of clientTracker.entries()) {
|
|
|
|
|
|
clientList.push({
|
|
|
|
|
|
id: info.id,
|
|
|
|
|
|
seq: info.seq,
|
|
|
|
|
|
ack: info.ack,
|
|
|
|
|
|
lag: info.seq - info.ack,
|
|
|
|
|
|
bytes: info.bytes,
|
|
|
|
|
|
connectedSec: Math.round((Date.now() - info.connectedAt) / 1000),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ clients: clientList, count: clientList.length }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/metrics') {
|
|
|
|
|
|
const concurrent = Array.from(clients.values()).reduce((sum, s) => sum + s.size, 0);
|
|
|
|
|
|
const uptime = Math.round((Date.now() - t0) / 1000);
|
|
|
|
|
|
const lines = [
|
|
|
|
|
|
`# HELP ds_screencast_uptime_seconds Uptime in seconds`,
|
|
|
|
|
|
`# TYPE ds_screencast_uptime_seconds gauge`,
|
|
|
|
|
|
`ds_screencast_uptime_seconds ${uptime}`,
|
|
|
|
|
|
`# HELP ds_screencast_frames_total Total frames captured`,
|
|
|
|
|
|
`# TYPE ds_screencast_frames_total counter`,
|
|
|
|
|
|
`ds_screencast_frames_total ${globalFrameCount}`,
|
|
|
|
|
|
`# HELP ds_screencast_connections_active Active WebSocket connections`,
|
|
|
|
|
|
`# TYPE ds_screencast_connections_active gauge`,
|
|
|
|
|
|
`ds_screencast_connections_active ${concurrent}`,
|
|
|
|
|
|
`# HELP ds_screencast_connections_total Total connections since start`,
|
|
|
|
|
|
`# TYPE ds_screencast_connections_total counter`,
|
|
|
|
|
|
`ds_screencast_connections_total ${totalConnections}`,
|
|
|
|
|
|
`# HELP ds_screencast_peak_concurrent Peak concurrent connections`,
|
|
|
|
|
|
`# TYPE ds_screencast_peak_concurrent gauge`,
|
|
|
|
|
|
`ds_screencast_peak_concurrent ${peakConcurrent}`,
|
|
|
|
|
|
];
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8' });
|
|
|
|
|
|
res.end(lines.join('\n') + '\n');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/tabs' && req.method === 'GET') {
|
|
|
|
|
|
const tabs = [];
|
|
|
|
|
|
for (const [id, info] of tabRegistry.entries()) {
|
|
|
|
|
|
tabs.push({ id, url: info.url, active: info.active });
|
|
|
|
|
|
}
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ tabs, count: tabs.length }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
if (req.url === '/stream-route' && req.method === 'POST') {
|
|
|
|
|
|
let body = '';
|
|
|
|
|
|
req.on('data', c => body += c);
|
|
|
|
|
|
req.on('end', () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { action, name } = JSON.parse(body);
|
|
|
|
|
|
if (action === 'add') { streamRoutes.set(name, []); }
|
|
|
|
|
|
else if (action === 'remove') { streamRoutes.delete(name); }
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ routes: Array.from(streamRoutes.keys()) }));
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
res.writeHead(400);
|
|
|
|
|
|
res.end(JSON.stringify({ error: e.message }));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/preview') {
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ preview: 'downscaled', scale: 0.25, targetFps: TARGET_FPS }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/stats-export') {
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify(statsExport));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/session' && req.method === 'GET') {
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify(sessionState));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/session' && req.method === 'POST') {
|
|
|
|
|
|
let body = '';
|
|
|
|
|
|
req.on('data', c => body += c);
|
|
|
|
|
|
req.on('end', () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { key, value } = JSON.parse(body);
|
|
|
|
|
|
sessionState[key] = value;
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ saved: key }));
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
res.writeHead(400);
|
|
|
|
|
|
res.end(JSON.stringify({ error: e.message }));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/recording' && req.method === 'GET') {
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ frames: recordingBuffer.length, poolSize: POOL_SIZE }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/command' && req.method === 'POST') {
|
|
|
|
|
|
let body = '';
|
|
|
|
|
|
req.on('data', c => body += c);
|
|
|
|
|
|
req.on('end', () => {
|
|
|
|
|
|
commandQueue.push(body);
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ queued: commandQueue.length }));
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/command' && req.method === 'GET') {
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ pending: commandQueue.length, next: commandQueue[0] || null }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
if (req.url === '/screenshot') {
|
|
|
|
|
|
// Capture via active CDP session
|
|
|
|
|
|
connectCDP(1).then(async (client) => {
|
|
|
|
|
|
const { Page } = client;
|
|
|
|
|
|
const { data } = await Page.captureScreenshot({ format: IMAGE_FORMAT === 'webp' ? 'png' : 'jpeg', quality: QUALITY });
|
|
|
|
|
|
const imgBuf = Buffer.from(data, 'base64');
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': IMAGE_FORMAT === 'webp' ? 'image/png' : 'image/jpeg' });
|
|
|
|
|
|
res.end(imgBuf);
|
|
|
|
|
|
client.close();
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
res.writeHead(500); res.end('Screenshot failed: ' + err.message);
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
if (req.url === '/telemetry' && req.method === 'GET') {
|
|
|
|
|
|
const avg = telemetryData.latencies.length > 0 ? telemetryData.latencies.reduce((a, b) => a + b, 0) / telemetryData.latencies.length : 0;
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ avgLatency: avg, errors: telemetryData.errors, totalBytes: telemetryData.bytes, ringSize: RING_SIZE }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/diagnostics' && req.method === 'GET') {
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ events: diagnosticEvents.length, gate: gateOpen, batchSize: BATCH_SIZE }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (req.url === '/gate' && req.method === 'POST') {
|
|
|
|
|
|
gateOpen = !gateOpen;
|
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
|
res.end(JSON.stringify({ gate: gateOpen }));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(html);
|
|
|
|
|
|
});
|
|
|
|
|
|
monitorServer.listen(MONITOR_PORT, '0.0.0.0', () => console.log(`[Monitor] http://0.0.0.0:${MONITOR_PORT}`));
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// ─── 4. CDP screencast loop (with reconnection) ───
|
|
|
|
|
|
async function connectCDP(maxRetries = 10) {
|
|
|
|
|
|
for (let i = 0; i < maxRetries; i++) {
|
2026-03-07 02:34:57 -08:00
|
|
|
|
try {
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
return await CDP({ port: CDP_PORT });
|
2026-03-07 02:34:57 -08:00
|
|
|
|
} catch {
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const delay = Math.min(1000 * Math.pow(1.5, i), 10000);
|
|
|
|
|
|
console.log(`[CDP] Connect attempt ${i + 1}/${maxRetries} failed, retry in ${Math.round(delay)}ms...`);
|
|
|
|
|
|
await new Promise(r => setTimeout(r, delay));
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
throw new Error('Cannot connect to Chrome CDP');
|
|
|
|
|
|
}
|
2026-03-07 02:34:57 -08:00
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
async function startScreencast(channel = 'default', url = TARGET_URL) {
|
|
|
|
|
|
const client = await connectCDP();
|
2026-03-07 02:34:57 -08:00
|
|
|
|
const { Page, Input, Emulation } = client;
|
|
|
|
|
|
|
|
|
|
|
|
await Page.enable();
|
|
|
|
|
|
await Emulation.setDeviceMetricsOverride({
|
|
|
|
|
|
width: WIDTH, height: HEIGHT, deviceScaleFactor: 1, mobile: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
await Emulation.setTouchEmulationEnabled({ enabled: true });
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
await Page.navigate({ url });
|
|
|
|
|
|
await new Promise(r => setTimeout(r, 2000));
|
2026-03-07 02:34:57 -08:00
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// Initialize channel stats
|
|
|
|
|
|
if (!channelStats.has(channel)) {
|
|
|
|
|
|
channelStats.set(channel, { frames: 0, bytes: 0, seq: 0, lastStatTime: Date.now(), statFrames: 0, statBytes: 0 });
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
const stats = channelStats.get(channel);
|
|
|
|
|
|
|
|
|
|
|
|
// v0.4: ACK listener — update adaptive quality
|
|
|
|
|
|
const wireInput = (ws) => {
|
|
|
|
|
|
ws._inputHandler = (data) => {
|
|
|
|
|
|
const buf = Buffer.from(data);
|
|
|
|
|
|
if (buf.length >= HEADER_SIZE && buf[0] === FRAME_ACK) {
|
|
|
|
|
|
// ACK frame: extract RTT from payload
|
|
|
|
|
|
const payloadLen = buf.readUInt32LE(12);
|
|
|
|
|
|
if (payloadLen >= 4) {
|
|
|
|
|
|
const rttMs = buf.readUInt16LE(HEADER_SIZE + 2);
|
|
|
|
|
|
aq.recordAck(rttMs);
|
|
|
|
|
|
|
|
|
|
|
|
// Adjust quality if tier changed
|
|
|
|
|
|
const newQuality = aq.quality || QUALITY;
|
|
|
|
|
|
if (newQuality !== currentQuality && newQuality > 0) {
|
|
|
|
|
|
currentQuality = newQuality;
|
|
|
|
|
|
Page.stopScreencast().catch(() => { });
|
|
|
|
|
|
Page.startScreencast({
|
|
|
|
|
|
format: cdpFormat, quality: currentQuality,
|
|
|
|
|
|
maxWidth: WIDTH, maxHeight: HEIGHT,
|
|
|
|
|
|
everyNthFrame: Math.max(1, Math.round(60 / MAX_FPS)),
|
|
|
|
|
|
}).catch(() => { });
|
|
|
|
|
|
console.log(`[AQ:${channel}] Tier: ${aq.tierName} → q${currentQuality}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return; // don't forward ACK as input
|
|
|
|
|
|
}
|
|
|
|
|
|
handleInput(buf, Input, Page);
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Existing clients
|
|
|
|
|
|
const ch = clients.get(channel);
|
|
|
|
|
|
if (ch) for (const ws of ch) wireInput(ws);
|
|
|
|
|
|
|
|
|
|
|
|
// Watch for new connections to this channel
|
|
|
|
|
|
const origSet = clients.get(channel) || new Set();
|
|
|
|
|
|
const origAdd = origSet.add.bind(origSet);
|
|
|
|
|
|
origSet.add = function (ws) {
|
2026-03-07 02:34:57 -08:00
|
|
|
|
origAdd(ws);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
wireInput(ws);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
};
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
clients.set(channel, origSet);
|
|
|
|
|
|
|
|
|
|
|
|
// Determine format
|
|
|
|
|
|
const useWebP = IMAGE_FORMAT === 'webp';
|
|
|
|
|
|
const formatByte = useWebP ? FMT_WEBP : FMT_JPEG;
|
|
|
|
|
|
const cdpFormat = useWebP ? 'png' : 'jpeg'; // CDP doesn't support webp directly, fallback
|
|
|
|
|
|
|
|
|
|
|
|
// Start screencast (v0.4: use adaptive quality)
|
|
|
|
|
|
let currentQuality = QUALITY;
|
|
|
|
|
|
let skipCounter = 0;
|
2026-03-07 02:34:57 -08:00
|
|
|
|
|
|
|
|
|
|
await Page.startScreencast({
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
format: cdpFormat, quality: currentQuality,
|
2026-03-07 02:34:57 -08:00
|
|
|
|
maxWidth: WIDTH, maxHeight: HEIGHT,
|
|
|
|
|
|
everyNthFrame: Math.max(1, Math.round(60 / MAX_FPS)),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
client.on('event', (message) => {
|
|
|
|
|
|
if (message.method !== 'Page.screencastFrame') return;
|
|
|
|
|
|
const { sessionId, data, metadata } = message.params;
|
|
|
|
|
|
Page.screencastFrameAck({ sessionId }).catch(() => { });
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// v0.4: adaptive frame skipping
|
|
|
|
|
|
if (aq.skipFrames > 0) {
|
|
|
|
|
|
skipCounter++;
|
|
|
|
|
|
if (skipCounter <= aq.skipFrames) return;
|
|
|
|
|
|
skipCounter = 0;
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
stats.seq++;
|
|
|
|
|
|
stats.frames++;
|
|
|
|
|
|
stats.statFrames++;
|
|
|
|
|
|
globalFrameCount++;
|
|
|
|
|
|
|
|
|
|
|
|
const imageBuf = Buffer.from(data, 'base64');
|
|
|
|
|
|
const timestamp = (Date.now() - t0) >>> 0;
|
|
|
|
|
|
const w = metadata.deviceWidth || WIDTH;
|
|
|
|
|
|
const h = metadata.deviceHeight || HEIGHT;
|
|
|
|
|
|
|
|
|
|
|
|
// Build ds-stream CompressedPixels frame
|
|
|
|
|
|
const frame = buildCompressedPixelFrame(stats.seq, timestamp, w, h, formatByte, imageBuf);
|
|
|
|
|
|
|
|
|
|
|
|
stats.bytes += frame.length;
|
|
|
|
|
|
stats.statBytes += frame.length;
|
|
|
|
|
|
globalBytesSent += frame.length;
|
|
|
|
|
|
|
|
|
|
|
|
// Broadcast to channel
|
|
|
|
|
|
const receivers = clients.get(channel);
|
|
|
|
|
|
if (receivers) {
|
|
|
|
|
|
for (const ws of receivers) {
|
|
|
|
|
|
if (ws.readyState === 1) ws.send(frame);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// v0.5: Write to recording file
|
|
|
|
|
|
if (recordStream) {
|
|
|
|
|
|
const tsUs = BigInt(Date.now() - t0) * 1000n;
|
|
|
|
|
|
const tsBuf = Buffer.alloc(8);
|
|
|
|
|
|
tsBuf.writeBigUInt64LE(tsUs);
|
|
|
|
|
|
const lenBuf = Buffer.alloc(4);
|
|
|
|
|
|
lenBuf.writeUInt32LE(frame.length);
|
|
|
|
|
|
recordStream.write(tsBuf);
|
|
|
|
|
|
recordStream.write(lenBuf);
|
|
|
|
|
|
recordStream.write(frame);
|
|
|
|
|
|
recordFrameCount++;
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// Handle CDP disconnect — attempt reconnection
|
|
|
|
|
|
client.on('disconnect', async () => {
|
|
|
|
|
|
console.log(`[CDP:${channel}] Disconnected! Attempting reconnection...`);
|
|
|
|
|
|
try {
|
|
|
|
|
|
await startScreencast(channel, url);
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error(`[CDP:${channel}] Reconnection failed:`, err.message);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`[CDP:${channel}] Casting ${url} → ${WIDTH}×${HEIGHT} @ q${QUALITY} (${IMAGE_FORMAT})`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── 5. Stats logging ───
|
|
|
|
|
|
function startStatsLogger() {
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
|
const totalElapsed = (now - t0) / 1000;
|
|
|
|
|
|
let totalReceivers = 0;
|
|
|
|
|
|
for (const [ch, set] of clients) totalReceivers += set.size;
|
|
|
|
|
|
|
|
|
|
|
|
for (const [channel, stats] of channelStats) {
|
|
|
|
|
|
const elapsed = (now - stats.lastStatTime) / 1000;
|
|
|
|
|
|
if (elapsed < 1) continue;
|
|
|
|
|
|
const fps = stats.statFrames / elapsed;
|
|
|
|
|
|
const kbps = stats.statBytes / 1024 / elapsed;
|
|
|
|
|
|
console.log(`[Stats:${channel}] ${fps.toFixed(1)} fps | ${kbps.toFixed(0)} KB/s | total: ${stats.frames} frames | ${(stats.bytes / 1024 / 1024).toFixed(1)} MB`);
|
|
|
|
|
|
stats.statFrames = 0;
|
|
|
|
|
|
stats.statBytes = 0;
|
|
|
|
|
|
stats.lastStatTime = now;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (channelStats.size > 1 || totalReceivers > 0) {
|
|
|
|
|
|
console.log(`[Stats:global] up=${totalElapsed.toFixed(0)}s | ${globalFrameCount} frames | ${(globalBytesSent / 1024 / 1024).toFixed(1)} MB | ${totalReceivers} receivers`);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, STATS_INTERVAL);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
// ─── Input handler (ds-stream protocol) ───
|
2026-03-07 02:34:57 -08:00
|
|
|
|
function handleInput(buf, Input, Page) {
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
if (buf.length < HEADER_SIZE) return;
|
|
|
|
|
|
const type = buf[0];
|
|
|
|
|
|
const flags = buf[1];
|
|
|
|
|
|
|
|
|
|
|
|
// Only process input frames (FLAG_INPUT=0x08)
|
|
|
|
|
|
if (!(flags & FLAG_INPUT) && type < 0xF0) {
|
|
|
|
|
|
// Legacy compatibility: try type byte directly
|
|
|
|
|
|
handleLegacyInput(buf, Input, Page);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const payloadLen = buf.readUInt32LE(12);
|
|
|
|
|
|
const payload = buf.slice(HEADER_SIZE, HEADER_SIZE + payloadLen);
|
|
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case INPUT_POINTER: { // Mouse move
|
|
|
|
|
|
if (payload.length >= 4) {
|
|
|
|
|
|
const x = payload.readUInt16LE(0), y = payload.readUInt16LE(2);
|
|
|
|
|
|
Input.dispatchMouseEvent({ type: 'mouseMoved', x, y }).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case INPUT_PTR_DOWN: { // Mouse/touch down
|
|
|
|
|
|
if (payload.length >= 4) {
|
|
|
|
|
|
const x = payload.readUInt16LE(0), y = payload.readUInt16LE(2);
|
|
|
|
|
|
Input.dispatchMouseEvent({ type: 'mousePressed', x, y, button: 'left', clickCount: 1 }).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case INPUT_PTR_UP: { // Mouse/touch up
|
|
|
|
|
|
if (payload.length >= 4) {
|
|
|
|
|
|
const x = payload.readUInt16LE(0), y = payload.readUInt16LE(2);
|
|
|
|
|
|
Input.dispatchMouseEvent({ type: 'mouseReleased', x, y, button: 'left', clickCount: 1 }).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case INPUT_KEY_DOWN: case INPUT_KEY_UP: { // Keyboard
|
|
|
|
|
|
if (payload.length >= 2) {
|
|
|
|
|
|
const keyCode = payload.readUInt16LE(0);
|
|
|
|
|
|
const key = String.fromCharCode(keyCode);
|
|
|
|
|
|
Input.dispatchKeyEvent({
|
|
|
|
|
|
type: type === INPUT_KEY_DOWN ? 'keyDown' : 'keyUp',
|
|
|
|
|
|
key, code: `Key${key.toUpperCase()}`,
|
|
|
|
|
|
windowsVirtualKeyCode: keyCode,
|
|
|
|
|
|
}).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case INPUT_TOUCH: { // Touch start/move
|
|
|
|
|
|
if (payload.length >= 4) {
|
|
|
|
|
|
const x = payload.readUInt16LE(0), y = payload.readUInt16LE(2);
|
|
|
|
|
|
Input.dispatchTouchEvent({
|
|
|
|
|
|
type: 'touchStart',
|
|
|
|
|
|
touchPoints: [{ x, y, id: 0, radiusX: 10, radiusY: 10, force: 1 }]
|
|
|
|
|
|
}).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case INPUT_TOUCH_END: { // Touch end
|
|
|
|
|
|
if (payload.length >= 4) {
|
|
|
|
|
|
const x = payload.readUInt16LE(0), y = payload.readUInt16LE(2);
|
|
|
|
|
|
Input.dispatchTouchEvent({
|
|
|
|
|
|
type: 'touchEnd',
|
|
|
|
|
|
touchPoints: [{ x, y, id: 0, radiusX: 10, radiusY: 10, force: 0 }]
|
|
|
|
|
|
}).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case INPUT_SCROLL: { // Scroll
|
|
|
|
|
|
if (payload.length >= 8) {
|
|
|
|
|
|
const dx = payload.readInt16LE(0), dy = payload.readInt16LE(2);
|
|
|
|
|
|
const x = payload.readUInt16LE(4), y = payload.readUInt16LE(6);
|
|
|
|
|
|
Input.dispatchMouseEvent({ type: 'mouseWheel', x, y, deltaX: dx, deltaY: dy }).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case 0x30: { // GamepadAxis
|
|
|
|
|
|
if (payload.length >= 4) {
|
|
|
|
|
|
const axisIdx = payload.readUInt8(0);
|
|
|
|
|
|
const value = payload.readInt16LE(1); // -32768 to 32767
|
|
|
|
|
|
// Map gamepad axis to scroll or custom event
|
|
|
|
|
|
console.log(`[Gamepad] Axis ${axisIdx}: ${value}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case 0x31: { // GamepadButton
|
|
|
|
|
|
if (payload.length >= 2) {
|
|
|
|
|
|
const buttonIdx = payload.readUInt8(0);
|
|
|
|
|
|
const pressed = payload.readUInt8(1);
|
|
|
|
|
|
// Map common gamepad buttons to keyboard events
|
|
|
|
|
|
const keyMap = { 0: 'Enter', 1: 'Escape', 12: 'ArrowUp', 13: 'ArrowDown', 14: 'ArrowLeft', 15: 'ArrowRight' };
|
|
|
|
|
|
const key = keyMap[buttonIdx];
|
|
|
|
|
|
if (key) {
|
|
|
|
|
|
Input.dispatchKeyEvent({
|
|
|
|
|
|
type: pressed ? 'keyDown' : 'keyUp',
|
|
|
|
|
|
key, code: key,
|
|
|
|
|
|
}).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Legacy input handler (v0.2 format)
|
|
|
|
|
|
function handleLegacyInput(buf, Input, Page) {
|
2026-03-07 02:34:57 -08:00
|
|
|
|
if (buf.length < 1) return;
|
|
|
|
|
|
const t = buf[0];
|
|
|
|
|
|
|
|
|
|
|
|
if (t === 0x60 && buf.length >= 7) {
|
|
|
|
|
|
const phase = buf[1];
|
|
|
|
|
|
const x = buf.readUInt16LE(2), y = buf.readUInt16LE(4);
|
|
|
|
|
|
const type = phase === 0 ? 'touchStart' : phase === 1 ? 'touchMove' : 'touchEnd';
|
|
|
|
|
|
Input.dispatchTouchEvent({
|
|
|
|
|
|
type, touchPoints: [{ x, y, id: buf[6] || 0, radiusX: 10, radiusY: 10, force: phase === 2 ? 0 : 1 }]
|
|
|
|
|
|
}).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
if (t === 0x63 && buf.length >= 3) {
|
|
|
|
|
|
const len = buf.readUInt16LE(1);
|
|
|
|
|
|
const url = buf.slice(3, 3 + len).toString();
|
|
|
|
|
|
Page.navigate({ url }).catch(() => { });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
// ─── v0.10: Stream Watchdog ───
|
|
|
|
|
|
const WATCHDOG_INTERVAL = 10000; // 10s
|
|
|
|
|
|
const lastFrameTime = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
function startWatchdog() {
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
|
for (const [channel, ts] of lastFrameTime.entries()) {
|
|
|
|
|
|
if (now - ts > WATCHDOG_INTERVAL) {
|
|
|
|
|
|
console.log(`[Watchdog] Channel "${channel}" stale (${Math.round((now - ts) / 1000)}s) — reconnecting...`);
|
|
|
|
|
|
lastFrameTime.set(channel, now); // prevent spam
|
|
|
|
|
|
// Attempt to reconnect CDP
|
|
|
|
|
|
connectCDP(3).catch(err => console.error(`[Watchdog] Reconnect failed: ${err.message}`));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}, WATCHDOG_INTERVAL);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// v0.12: Startup self-test
|
|
|
|
|
|
async function selfTest() {
|
|
|
|
|
|
console.log('[SelfTest] Validating Chrome, CDP, WS...');
|
|
|
|
|
|
try {
|
|
|
|
|
|
const chrome = await launchChrome();
|
|
|
|
|
|
const client = await connectCDP(3);
|
|
|
|
|
|
await client.close();
|
|
|
|
|
|
chrome.kill();
|
|
|
|
|
|
console.log('[SelfTest] ✓ Chrome + CDP OK');
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
logError('SelfTest', `Chrome/CDP failed: ${err.message}`);
|
|
|
|
|
|
console.error('[SelfTest] ✗ FAILED — aborting');
|
|
|
|
|
|
process.exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
const net = await import('net');
|
|
|
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
|
|
const srv = net.createServer();
|
|
|
|
|
|
srv.listen(WS_PORT, '0.0.0.0', () => { srv.close(resolve); });
|
|
|
|
|
|
srv.on('error', reject);
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log('[SelfTest] ✓ WS port available');
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
logError('SelfTest', `WS port ${WS_PORT} unavailable: ${err.message}`);
|
|
|
|
|
|
console.error('[SelfTest] ✗ Port conflict — aborting');
|
|
|
|
|
|
process.exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log('[SelfTest] All checks passed\n');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 02:34:57 -08:00
|
|
|
|
// ─── Main ───
|
|
|
|
|
|
async function main() {
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
// v0.12: run self-test first
|
|
|
|
|
|
if (process.argv.includes('--self-test')) {
|
|
|
|
|
|
await selfTest();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
engine: v0.90–v1.0.0 milestone 🎉
v0.90: World Layers, Stream Encryption V2, Multi-Channel
- ds-physics: set/get layer, gravity scale, angular vel, body type, world gravity, freeze/unfreeze, body tag (183 tests)
- ds-stream: XorCipherV2, ChannelRouter, AckTracker, FramePoolV2, BandwidthEstimatorV2, PriorityMux, NonceGenerator, StreamValidator, RetryQueue (246 tests)
- ds-stream-wasm: 9 exports (156 tests)
v0.95: Scene Graph, Stream Compression V2, Telemetry
- ds-physics: body count all, step count, get gravity, is frozen, get color, AABB, raycast, restitution, emitter count (192 tests)
- ds-stream: Lz4Lite, TelemetrySink, FrameDiffer, BackoffTimer, StreamMirror, QuotaManager, HeartbeatV2, TagFilter, MovingAverage (255 tests)
- ds-stream-wasm: 9 exports (165 tests)
v1.0.0: Production Ready — ECS Foundation, Stream Pipeline, Protocol Finalization
- ds-physics: get tag, body list, impulse, mass, friction, world bounds, body exists, reset world, engine version (201 tests)
- ds-stream: StreamPipeline, ProtocolHeader, FrameSplitterV2, CongestionWindowV2, StreamStatsV2, AckWindow, CodecRegistryV2, FlowControllerV2, VersionNegotiator (264 tests)
- ds-stream-wasm: 9 exports (174 tests)
Total: 639 tests across 3 packages
2026-03-11 14:58:39 -07:00
|
|
|
|
console.log(`\n DreamStack Screencast v1.0.0`);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
console.log(` ──────────────────────────────`);
|
|
|
|
|
|
console.log(` URL: ${MULTI_URLS.length > 0 ? MULTI_URLS.join(', ') : TARGET_URL}`);
|
|
|
|
|
|
console.log(` Viewport: ${WIDTH}×${HEIGHT} (scale: ${VIEWPORT_TRANSFORM})`);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
console.log(` Quality: ${QUALITY}% FPS: ${MAX_FPS}`);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
console.log(` Format: ${IMAGE_FORMAT.toUpperCase()}`);
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
console.log(` Codec: ${CODEC_NAME}`);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
console.log(` Profile: ${PROFILE || 'custom'}`);
|
|
|
|
|
|
console.log(` ROI: ${ROI.length === 4 ? ROI.join(',') : 'full viewport'}`);
|
|
|
|
|
|
console.log(` Tabs: ${MULTI_URLS.length || TAB_COUNT}`);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
console.log(` Audio: ${ENABLE_AUDIO}`);
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
console.log(` AudioMix: ${AUDIO_MIX}`);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
console.log(` Record: ${RECORD_FILE || 'disabled'}`);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
console.log(` Auth: ${AUTH_TOKEN ? 'enabled' : 'disabled'}`);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
console.log(` Headless: ${HEADLESS}`);
|
|
|
|
|
|
console.log(` WS Port: ${WS_PORT} Monitor: ${MONITOR_PORT}`);
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
console.log(` Endpoints: /health, /screenshot, /stats, /replay, /hot-reload, /clients, /metrics, /tabs, /stream-route, /preview, /stats-export, /session, /recording, /command, /telemetry`);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
console.log(` Watchdog: ${WATCHDOG_INTERVAL / 1000}s stale detection`);
|
|
|
|
|
|
console.log(` IdleFPS: ${MAX_FPS_IDLE}`);
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
console.log(` TargetFPS: ${TARGET_FPS}`);
|
|
|
|
|
|
console.log(` FrameSkip: ${FRAME_SKIP}`);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
console.log(` Debug: ${DEBUG_OVERLAY}`);
|
|
|
|
|
|
console.log(` CrashRst: ${RESTART_ON_CRASH}`);
|
|
|
|
|
|
console.log(` Compress: ${COMPRESS_FRAMES}`);
|
|
|
|
|
|
console.log(` Migrate: ${MIGRATE_ON_CRASH}`);
|
|
|
|
|
|
console.log(` Adaptive: ${ADAPTIVE_BITRATE}`);
|
|
|
|
|
|
console.log(` CDN Push: ${CDN_PUSH_URL || 'disabled'}`);
|
|
|
|
|
|
console.log(` Encrypt: ${ENCRYPT_KEY ? 'enabled' : 'disabled'}`);
|
|
|
|
|
|
console.log(` Watermark: ${WATERMARK_TEXT || 'disabled'}`);
|
|
|
|
|
|
console.log(` Graceful: ${GRACEFUL_SHUTDOWN}`);
|
engine: v0.28–v0.50 milestone
ds-physics v0.50.0 (138 tests)
- v0.28: apply_body_torque, is_body_sleeping, get_body_angle
- v0.30: set_body_gravity, set_linear_damping, count_awake_bodies
- v0.40: joints (distance/pin), raycast, kinematic, time scale, world stats
- v0.50: point query, explosion, velocity/position set, contacts, gravity, collision groups
ds-stream v0.50.0 (201 tests)
- v0.28: BufferPool, PacketJitterBuffer, RttTracker
- v0.30: FrameRingBuffer, PacketLossDetector, ConnectionQuality
- v0.40: QualityAdapter, SourceMixer, FrameDeduplicator, BackpressureController, HeartbeatMonitor, CompressionTracker, FecEncoder, StreamSnapshot, AdaptivePriorityQueue
- v0.50: StreamCipher, ChannelMux/Demux, FramePacer, CongestionWindow, FlowController, ProtocolNegotiator, ReplayRecorder, BandwidthShaper
ds-stream-wasm v0.50.0 (111 tests)
- WASM bindings for all stream features
ds-screencast v0.50.0
- CLI: --jitter-buffer, --latency-window, --ring-buffer, --loss-threshold, --adaptive, --dedup, --backpressure, --heartbeat-ms, --fec, --encrypt-key, --channels, --pacing-ms, --max-bps, --replay-file
2026-03-11 12:47:56 -07:00
|
|
|
|
console.log(` BackPres: ${BACKPRESSURE_LIMIT}`);
|
|
|
|
|
|
console.log(` MultiOut: ${MULTI_OUTPUT}`);
|
|
|
|
|
|
console.log(` Annotate: ${ANNOTATE_FRAMES}`);
|
|
|
|
|
|
console.log(` SessPers: ${SESSION_PERSIST_PATH || 'disabled'}`);
|
|
|
|
|
|
console.log(` HotCfg: ${HOT_CONFIG}`);
|
|
|
|
|
|
console.log(` PoolSize: ${POOL_SIZE}`);
|
|
|
|
|
|
console.log(` Bounds: ${BOUNDS_CHECK}`);
|
|
|
|
|
|
console.log(` MuxCh: ${MUX_CHANNELS}`);
|
|
|
|
|
|
console.log(` HashFrm: ${HASH_FRAMES}`);
|
|
|
|
|
|
console.log(` CompLvl: ${COMPRESS_LEVEL}`);
|
|
|
|
|
|
console.log(` RingSz: ${RING_SIZE}`);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
console.log(` ErrorLog: ${ERROR_LOG_FILE || 'disabled'}`);
|
|
|
|
|
|
console.log(` SessRec: ${SESSION_RECORD_DIR || 'disabled'} (max ${MAX_RECORD_FRAMES})\n`);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
|
|
|
|
|
|
const chrome = await launchChrome();
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
const wss = startWS();
|
2026-03-07 02:34:57 -08:00
|
|
|
|
startMonitor();
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
startStatsLogger();
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
startWatchdog();
|
|
|
|
|
|
|
|
|
|
|
|
// v0.10: Multi-URL routing
|
|
|
|
|
|
if (MULTI_URLS.length > 0) {
|
|
|
|
|
|
for (let i = 0; i < MULTI_URLS.length; i++) {
|
|
|
|
|
|
const channel = `url-${i}`;
|
|
|
|
|
|
await startScreencast(channel, MULTI_URLS[i]);
|
|
|
|
|
|
lastFrameTime.set(channel, Date.now());
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (TAB_COUNT === 1) {
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
await startScreencast('default', TARGET_URL);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
lastFrameTime.set('default', Date.now());
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
} else {
|
|
|
|
|
|
for (let i = 0; i < TAB_COUNT; i++) {
|
|
|
|
|
|
const channel = `tab-${i}`;
|
|
|
|
|
|
await startScreencast(channel, TARGET_URL);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
lastFrameTime.set(channel, Date.now());
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-07 02:34:57 -08:00
|
|
|
|
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
console.log(`\n ✓ Streaming! Panels → ws://0.0.0.0:${WS_PORT}/stream/{channel}`);
|
2026-03-07 02:34:57 -08:00
|
|
|
|
console.log(` ✓ Monitor → http://localhost:${MONITOR_PORT}\n`);
|
|
|
|
|
|
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
// v0.12: restart on crash detection
|
|
|
|
|
|
if (RESTART_ON_CRASH) {
|
|
|
|
|
|
chrome.on('exit', (code) => {
|
|
|
|
|
|
logError('Chrome', `Chrome exited with code ${code}, restarting...`);
|
|
|
|
|
|
reconnectCount++;
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
main().catch(err => logError('Fatal', err.message));
|
|
|
|
|
|
}, 2000);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// v0.10: Graceful shutdown for both SIGINT and SIGTERM
|
|
|
|
|
|
function gracefulShutdown(signal) {
|
|
|
|
|
|
console.log(`\n[${signal}] Shutting down...`);
|
feat(compiler): v0.4 + v0.5 — CLI modularity, diagnostic pipeline, test suite
v0.4 — CLI Modularity:
- Split monolithic main.rs (2,038 lines) into 8 command modules + slim dispatch (107 lines)
- Add 12 JS codegen tests (signals, derived, views, events, loops, match, enums, components, interpolation, springs, tree-shaking)
v0.5 — Diagnostic Quality + Analyzer Confidence:
- Add From<ParseError> for Diagnostic (E0001) in ds-diagnostic
- Add errors_as_diagnostics() to TypeChecker (E0100–E0110)
- Wire Elm-style diagnostics through dreamstack check and build commands
- Switch incremental compiler to parse_program_resilient() for multi-error collection
- Add 12 analyzer tests (chains, fan-out, diamond deps, empty programs, conditionals, handlers, views)
- Add 2 diagnostic conversion tests
Test suite: 97 → 123 tests (26 new, 0 failures)
2026-03-10 09:09:02 -07:00
|
|
|
|
if (recordStream) {
|
|
|
|
|
|
recordStream.end();
|
|
|
|
|
|
console.log(`[Record] Saved ${recordFrameCount} frames to ${RECORD_FILE}`);
|
|
|
|
|
|
}
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
if (errorLogStream) errorLogStream.end();
|
|
|
|
|
|
// Close all WebSocket connections
|
|
|
|
|
|
for (const [channel, set] of clients.entries()) {
|
|
|
|
|
|
for (const ws of set) {
|
|
|
|
|
|
ws.close(1001, 'Server shutting down');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
wss.close();
|
2026-03-07 02:34:57 -08:00
|
|
|
|
chrome.kill();
|
|
|
|
|
|
process.exit(0);
|
feat(engine): v0.14-v0.16 releases
ds-physics 0.16.0 (81 tests):
- v0.14: proximity queries, physics regions
- v0.15: event hooks, transform hierarchy, timeline
- v0.16: deterministic seed/checksum, collision manifolds, distance+hinge constraints
ds-stream 0.16.0 (143 tests):
- v0.14: FrameCompressor (RLE), MultiClientSync, BandwidthThrottle, FrameType::Compressed
- v0.15: AdaptiveBitrate, MetricsSnapshot, FramePipeline
- v0.16: FrameEncryptor (XOR), StreamMigration, FrameDedup, PriorityQueue
ds-stream-wasm 0.16.0 (54 tests):
- v0.14: RLE compress/decompress, sync drift, bandwidth limiting
- v0.15: adaptive quality, metrics snapshot, frame transforms
- v0.16: encrypt/decrypt frames, migration handoff, frame dedup
ds-screencast 0.16.0:
- v0.14: --roi, /clients, --compress, --migrate-on-crash
- v0.15: --adaptive-bitrate, /metrics, --viewport-transform, --cdn-push
- v0.16: /tabs, --encrypt-key, --watermark, --graceful-shutdown
2026-03-10 22:47:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
|
|
|
|
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
2026-03-07 02:34:57 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
main().catch(err => { console.error('Fatal:', err); process.exit(1); });
|