feat(tap): TapClient WSS pump loop (spec §4.2)

- run_tap_client: drives a connected WebSocketStream with a tokio::select!
  over rx_pcm_in (inbound PCM → audio_in WS frame) and ws.next() (brain
  frame → audio_out mpsc or control handling).
- Handshake: send hello, await brain hello (bounded 2s timeout).
- seq gap detection (log + count, never drop on gap — spec §3.1).
- Hot-path errors (encode/decode failures, send/recv failures) are logged
  + counted; TapClientError is returned only on graceful close, hello
  timeout, or WS errors. The TapEngine (Task 7) decides reconnect policy.
- Pure-helper unit test (elapsed_ms); full pump behavior is exercised
  against the in-process EchoServer in the Task 8 integration test.

Spec ref: 2026-06-28-slice-2-agent-tap-design.md §4.2.
This commit is contained in:
opencode controller
2026-06-28 14:25:15 -04:00
parent 51d5e6b01e
commit 1bb5b7203c
4 changed files with 269 additions and 0 deletions

View File

@@ -30,6 +30,7 @@
pub mod metrics;
pub mod protocol;
pub mod tap_audio_pipe;
pub mod tap_client;
// Re-export PcmFrame so `rutster-tap` consumers (the binary, the echo brain,
// future brains) get it from one canonical home (spec §3.1).
@@ -43,6 +44,7 @@ pub use protocol::{
TapProtoError, PROTOCOL_VERSION, SAMPLES_PER_FRAME as WIRE_SAMPLES_PER_FRAME,
};
pub use tap_audio_pipe::TapAudioPipe;
pub use tap_client::{run_tap_client, TapClientError};
#[cfg(test)]
mod tests {