packages/vox-client/README.md

@clankie/vox-client

Apache-2.0 TypeScript process boundary for the AGPL @clankie/vox native media executable.

Each media-enabled active Discord body owns one client and one child; a text-only official-bot process owns neither. Both media-enabled bodies consume primary voice, capture, TTS, and music commands; the user body can concurrently consume screen-watch and Go Live commands. See ADR 0128 and the Discord media guide.

The client resolves the workspace release/debug binary, with CLANKIE_VOX_BIN as an explicit override. It owns child lifecycle, bounded stdout framing, full media-plane commands, a discriminated control-event union, decoded screen-share frames, and capture-correlated binary speaker-audio frames. Listener registration returns independent unsubscribe functions so one process-lifetime client can serve voice, watch, and publish controllers.

process_ready carries VOX_IPC_PROTOCOL_VERSION; the client remains unavailable and refuses commands until that exact version is received. Missing or mismatched binaries enter error and are terminated rather than using a compatibility protocol.

Primary voice has an explicit caller-owned connectionId on joinVoice and on primary ready, connection_state, transport_state, dave_state, and transport-error events. TTS uses playbackId plus ordered finishTtsPlayback: buffered means queued, started means the first audible TTS frame was successfully transmitted, and drained means all finished playback output crossed the sender. Capture uses caller-owned captureId; music uses musicId. Reliable stdin commands never drop under backpressure: bounded overflow fails the client and throws VoxClientError with the applicable playback correlation. process_ready, voice transport readiness, and positive role-scoped DAVE readiness remain separate facts.

Video frame events include their originating transport role. Music failures carry a content-free code and a separate redacted human message.

Discord product policy stays in the consuming body. The client translates typed calls to IPC and reports transport facts; it does not decide who may join, listen, speak, or publish. Account gateway tokens also stay in the body; only Discord-issued short-lived voice/stream connection fields cross IPC.