Let errors propagate to the caller instead of catching locally,
simplify the request body construction, and snapshot perf.timing
before the fetch to avoid a TOCTOU race.
The PerfState interface was only used twice, so inline it. Move
onChange/onHostLog subscriptions above the route definitions to keep
side-effects grouped. Skip perf.now() in proxy when timing is off.
Colocate the setter with its variable for readability. Remove the
conditional around performance.now() since the call is negligible
and simplifies the timing logic.
Early-return on invalid input, then unify the GET/POST and display
paths so each concern is handled once instead of per-subcommand.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move styles array outside the parse loop in ansiToHtml so styles accumulate across sequences, and use stripAnsi when filtering live logs so search matches visible text.
Merge color and style maps into a unified STYLES table, hoist the
regex to module scope, export stripAnsi for use in log parsing, and
handle SGR 39 (default foreground) by removing only color styles
instead of clearing all styles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multiple SGR parameters in one escape sequence (e.g. bold + color)
were each opening a new span, losing earlier styles. Collect styles
per sequence and emit one span with all of them.
Terminal color codes were rendering as raw escape sequences in the
web UI, making logs hard to read.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
spawnSync blocks the event loop while waiting for ps and du, which
stalls the SSE metrics stream and other requests. Running these
concurrently with async spawn (and Promise.all for du) keeps the
server responsive under load.
The deploy script now builds the CLI binary and copies it to /usr/local/bin.
SSH passes commands as `toes -c "command args"`, so parse that form
before falling through to the interactive shell or normal arg handling.