fix: harden generic video extension for ConvoAI compliance#2140
fix: harden generic video extension for ConvoAI compliance#2140
Conversation
|
Code Review - PR 2140 generic_video_python Good overall uplift. The migration to Pydantic, async httpx, per-instance session cache, and comprehensive test suite are solid improvements. A few issues to address before merge. SECURITY Session token logged in plain text (medium) CORRECTNESS normalize_params bypasses Pydantic validators (medium) channel now required without verified migration path (low-medium) Legacy sessions not stopped on cache upgrade (low) MINOR / STYLE vendor_params double-filters (nit): after normalize_params() runs, known keys are already stripped from self.params. The filter in vendor_params against _PASSTHROUGH_EXCLUDED_KEYS is redundant. _ensure_dict dead code (nit): Pydantic coerces params to a dict before normalize_params is called so the None and non-dict branches can never fire. Consider inlining dict(self.params). validate_required vs @model_validator (style): more idiomatic Pydantic v2 would use @model_validator(mode=after). As written validate_required is only called from create_async so tests calling model_validate directly skip the required-field check. TEST COVERAGE create_async not tested: all config tests call model_validate directly. The create_async path (get_property_to_json -> normalize_params -> validate_required) has no test. A mock AsyncTenEnv returning canned JSON would cover it. Timing-based assertion is fragile: test_audio_sender_uses_actual_sample_rate_and_warns_once relies on asyncio.sleep(0.05) to let the task run. This can be flaky under CI load. An asyncio.Event or deterministic queue drain would be more robust. POSITIVE NOTES
|
Summary
Brings
generic_video_pythonup to date with the latest convoai_to_video contract and to the engineering quality bar applied todeepgram_tts.Protocol compliance:
AudioFrame.get_sample_rate()in WebSocketvoice.sampleRateinstead of static config valueareaparam to both session start and WebSocket init payloadssession_tokenin DELETE body for stop-session (required by latest contract)paramsdict forwarded to start/init payloadsConfig normalization:
@dataclassto PydanticBaseModelwith field validatorschannel(aliasagora_channel_name),agora_avatar_uid(aliasagora_video_uid)manifest.jsonquality,video_encoding,areaactivity_idle_timeoutdefault aligned to 120Runtime robustness:
requestswith asynchttpx_audio_taskandlistener_taskinon_stop()/tmpfile)Tests:
test_config.py— aliases, masking, enum validation, params passthroughtest_extension.py— sample rate propagation, mismatch warning, voice_end triggertest_protocol.py— start/stop/init payload shape, WebSocket messages, mock HTTP transportRelated
Test plan
agora_channel_name,agora_video_uid)session_idandsession_tokenin bodyareapresent in start and init payloads