test(tui): fix stale mocks + xdist flakes in TUI test suite
All 61 TUI-related tests green across 3 consecutive xdist runs.
tests/tui_gateway/test_protocol.py:
- rename `get_messages` → `get_messages_as_conversation` on mock DB (method
was renamed in the real backend, test was still stubbing the old name)
- update tool-message shape expectation: `{role, name, context}` matches
current `_history_to_messages` output, not the legacy `{role, text}`
tests/hermes_cli/test_tui_resume_flow.py:
- `cmd_chat` grew a first-run provider-gate that bailed to "Run: hermes
setup" before `_launch_tui` was ever reached; 3 tests stubbed
`_resolve_last_session` + `_launch_tui` but not the gate
- factored a `main_mod` fixture that stubs `_has_any_provider_configured`,
reused by all three tests
tests/test_tui_gateway_server.py:
- `test_config_set_personality_resets_history_and_returns_info` was flaky
under xdist because the real `_write_config_key` touches
`~/.hermes/config.yaml`, racing with any other worker that writes
config. Stub it in the test.
This commit is contained in:
@@ -1590,6 +1590,8 @@ class BasePlatformAdapter(ABC):
|
||||
"reset",
|
||||
"background",
|
||||
"restart",
|
||||
"queue",
|
||||
"q",
|
||||
):
|
||||
logger.debug(
|
||||
"[%s] Command '/%s' bypassing active-session guard for %s",
|
||||
|
||||
@@ -235,6 +235,7 @@ class VoiceReceiver:
|
||||
# Calculate dynamic RTP header size (RFC 9335 / rtpsize mode)
|
||||
cc = first_byte & 0x0F # CSRC count
|
||||
has_extension = bool(first_byte & 0x10) # extension bit
|
||||
has_padding = bool(first_byte & 0x20) # padding bit (RFC 3550 §5.1)
|
||||
header_size = 12 + (4 * cc) + (4 if has_extension else 0)
|
||||
|
||||
if len(data) < header_size + 4: # need at least header + nonce
|
||||
@@ -278,6 +279,31 @@ class VoiceReceiver:
|
||||
if ext_data_len and len(decrypted) > ext_data_len:
|
||||
decrypted = decrypted[ext_data_len:]
|
||||
|
||||
# --- Strip RTP padding (RFC 3550 §5.1) ---
|
||||
# When the P bit is set, the last payload byte holds the count of
|
||||
# trailing padding bytes (including itself) that must be removed
|
||||
# before further processing. Skipping this passes padding-contaminated
|
||||
# bytes into DAVE/Opus and corrupts inbound audio.
|
||||
if has_padding:
|
||||
if not decrypted:
|
||||
if self._packet_debug_count <= 10:
|
||||
logger.warning(
|
||||
"RTP padding bit set but no payload (ssrc=%d)", ssrc,
|
||||
)
|
||||
return
|
||||
pad_len = decrypted[-1]
|
||||
if pad_len == 0 or pad_len > len(decrypted):
|
||||
if self._packet_debug_count <= 10:
|
||||
logger.warning(
|
||||
"Invalid RTP padding length %d for payload size %d (ssrc=%d)",
|
||||
pad_len, len(decrypted), ssrc,
|
||||
)
|
||||
return
|
||||
decrypted = decrypted[:-pad_len]
|
||||
if not decrypted:
|
||||
# Padding consumed entire payload — nothing to decode
|
||||
return
|
||||
|
||||
# --- DAVE E2EE decrypt ---
|
||||
if self._dave_session:
|
||||
with self._lock:
|
||||
|
||||
Reference in New Issue
Block a user