feat: add Deepgram v2 (flux) support with wellness analysis - #1691
feat: add Deepgram v2 (flux) support with wellness analysis#1691plutoless wants to merge 1739 commits into
Conversation
* fix: fixing the graphts being ignored in git * fix: getting rid of the old graphts
* fix: recognize soniox end token and ignore it * feat: update manifest.json version to 0.1.3 --------- Co-authored-by: Ethan Zhang <qianze.zhang@hotmail.com>
* feat: openai asr support audio resample * fix: samplerate install * fix: typo * feat: openai asr support config audio sample rate * fix: update websockets version
* feat: add soniox vendor logs * fix: lint * feat: update manifest to 0.2.1 --------- Co-authored-by: Ethan Zhang <qianze.zhang@hotmail.com>
* feat: change log in 11labs tts * feat: update version of 11labs tts * feat: change 11labs tts some log_info to log_debug --------- Co-authored-by: wangyimin <wangyimin@agora.io>
* docs: update default model and agent instructions * refactor(agent-config): simplify agent path resolution logic * refactor(Taskfile): rename AGENT_RAW to AGENT_EXAMPLE for clarity * docs: remove deprecated extensions section from README
* fix: xfyun and deepgram * fix: deepgram lint --------- Co-authored-by: liaochenliang <liaochenliang@agora.io>
* fix: improve ASR logging and fix Google ASR timing issues * feat: enhance ASR extensions with improved logging format * test: update mock client to match new start method signature --------- Co-authored-by: PaulZhang <zhangpeng@agora.io>
Co-authored-by: Ethan Zhang <qianze.zhang@hotmail.com>
* fix: fix tman env issue * fix: add new script to run * fix: finalize the fix
…uages and extensions (#1494)
* feat: upgrade version of asr extensions * feat: tencent signature bugfix --------- Co-authored-by: Ethan Zhang <qianze.zhang@hotmail.com>
* fix: update Google ASR client logging and start_ms logic * feat: update Google ASR manifest.json --------- Co-authored-by: PaulZhang <zhangpeng@agora.io> Co-authored-by: xxxxl_sun <31622273+sunxilin@users.noreply.github.com>
* fix: compatible hotword list config * chore: format * fix: lint error
* fix: send final before non-final * fix: typo
* fix: soniox send finalize_end after final * chore: better finalize end log
* fix: azure tts log format * fix: polly and groq tts log format * chore: update version
* feat: soniox set trailing_silence_ms in asr_finalize * feat: update manifest to 0.2.4 * fix: ut mock
* feat: change log in 11labs tts * feat: change 11labs tts some log_info to log_debug * feat: update google tts log and add turn id for 11labs audio start --------- Co-authored-by: wangyimin <wangyimin@agora.io> Co-authored-by: Ethan Zhang <qianze.zhang@hotmail.com>
Co-authored-by: liaochenliang <liaochenliang@agora.io>
* fix: fix the issue that cannot interrupt tts * chore: adjust the calculation method of ttfb and request_event_interval * feat: update TTS extensions to include current_turn_id in audio start calls
* feat: humeai log * feat: humeai log --------- Co-authored-by: chenyuguo <chenyuguo@agora.io> Co-authored-by: Ethan Zhang <qianze.zhang@hotmail.com>
* feat: humeai log * feat: humeai log * feat: cosy tts log --------- Co-authored-by: chenyuguo <chenyuguo@agora.io>
…for consistency and improvements. (#1515)
* fix: optimise tencent asr reconnect * chore: update version
* fix: update Google ASR client logging and start_ms logic * feat: update Google ASR manifest.json * feat: use silence packets for finalize instead of None signal --------- Co-authored-by: PaulZhang <zhangpeng@agora.io>
* fix: speechmatics audio timeline * fix: format --------- Co-authored-by: liaochenliang <liaochenliang@agora.io>
Root cause: System prompt said "Present all 7 metrics" which caused LLM to proactively call get_wellness_metrics after announcing Hellos, before Apollo was ready. When response had no clinical_indicators field, LLM made up "0%" values instead of waiting. Timeline of bug: 1. 19:35:56 - LLM announces wellness metrics 2. 19:35:58 - LLM calls confirm_announcement(phase='hellos') ✓ 3. 19:35:59 - LLM proactively calls get_wellness_metrics (NO ALERT) 4. 19:35:59 - Response has no clinical_indicators field 5. 19:36:02 - LLM makes up "Depression: 0%, Anxiety: 0%" 6. 19:36:08 - Real [SYSTEM ALERT] arrives, interrupts Fix: Rewrote steps 8-10 to explicitly state: - TWO separate alerts will be sent - WAIT for first alert → announce wellness → confirm → WAIT - WAIT for second alert → announce clinical → confirm - Do NOT proactively call get_wellness_metrics after Hellos property.json:2629 (steps 8-10)
When LLM proactively called get_wellness_metrics before Apollo was ready, the response had no clinical_indicators field. LLM interpreted this as "values are 0%" instead of "not ready yet". Added explicit clarification to tool description: - If clinical_indicators field is PRESENT → announce all 7 metrics - If clinical_indicators field is MISSING → Apollo not ready, announce ONLY wellness metrics and WAIT for [SYSTEM ALERT] - DO NOT make up values when field is missing This is a defensive fix - the primary fix (previous commit) prevents LLM from proactively calling the tool, but this ensures correct behavior if it does call early. extension.py:1769
Created comprehensive optimization plan covering: 1. Log filtering improvements - Exclude verbose get_chat_completions prompt dumps - Recommended alias: tail-thymia for cleaner output 2. Latency timing instrumentation - Add [STT_FINAL], [LLM_START], [LLM_END], [TTS_START], [TTS_END] logs - Measure end-to-end pipeline: STT → LLM → TTS - Target: < 2000ms without HeyGen 3. Deepgram confidence logging - Log confidence scores for interim and final transcripts - Debug phantom word interruptions (confidence < 0.5) 4. New flux_apollo_cartesia graph - Test pipeline without HeyGen latency overhead - Direct Cartesia TTS → RTC audio output - Baseline for latency comparison 5. Logging cleanup strategy - Remove: production clutter, debug logs in hot paths - Comment: verbose tool args, full API responses - Keep: THYMIA_* logs, errors, timing, user I/O Success metrics: - Baseline latency measurement (with/without HeyGen) - Phantom word detection via confidence threshold - Readable tail/grep output ai/optimize.md
Two optimizations for latency and debugging: 1. Remove verbose LLM prompt logging (openai_llm2_python/openai.py:261) - Was dumping entire request (~10KB+) on every LLM call - Includes system prompt, conversation history, all tool definitions - Adds I/O latency and pollutes logs - Replaced with concise summary: model, stream, message count - Comment preserved for deep debugging if needed 2. Add Deepgram Flux STT confidence logging - Extract confidence score from alternatives[0] - Log format: [STT_FINAL] text="..." confidence=0.98 is_final=True - Log format: [STT_INTERIM] text="..." confidence=0.85 is_final=False - Use case: Debug phantom word interruptions (confidence < 0.5) - Changed log level to info (was debug) for visibility Benefits: - Reduced I/O overhead in LLM pipeline - Cleaner logs for tail/grep workflows - Can identify false positive STT triggers via low confidence Related: ai/optimize.md (optimization plan) deepgram_asr_python/extension.py:290-314 openai_llm2_python/openai.py:261-264
Created new graph without HeyGen avatar overhead for latency measurement: Components: - STT: Deepgram Flux (same as flux_thymia_heygen_cartesia) - LLM: OpenAI GPT-4o with Thymia extension (demo_dual mode) - TTS: Cartesia Sonic-3 (speed 1.2, 48kHz) - Audio: Direct RTC output (NO HeyGen WebSocket/avatar processing) Key differences from flux_thymia_heygen_cartesia: - Removed heygen_avatar extension (saves ~500ms+ avatar latency) - TTS audio routed directly to agora_rtc (not through avatar) - Uses updated Thymia prompt with TWO separate alert workflow - Includes Apollo API configuration (mood + reading analysis) Benefits: - Baseline latency measurement (STT → LLM → TTS → user) - No HeyGen rendering/buffering overhead - Direct comparison: flux_apollo_cartesia vs flux_thymia_heygen_cartesia Testing: - User can compare latency between the two graphs - Measure end-to-end voice response time - Identify HeyGen latency contribution Related: ai/optimize.md (task 6 - create flux_apollo_cartesia graph) property.json:2319-2563
…a for A/B testing Made both graphs identical except for audio routing: Changes to flux_apollo_cartesia: - Use same LLM prompt (brief workflow with Cartesia SSML tags) - Use same TTS sample rate (44100 Hz, not 48000 Hz) - Use same thymia_analyzer config (no Apollo API settings) - Use same greeting Now both graphs are identical except: - flux_thymia_heygen_cartesia: TTS → HeyGen → Agora RTC - flux_apollo_cartesia: TTS → Agora RTC (direct) This enables proper latency comparison - only variable is HeyGen overhead. property.json:2369,2395,2432-2444
Changes: 1. Added latency timing instrumentation to main_python extension: - [LATENCY_STT_FINAL] when STT final transcript received - [LATENCY_LLM_FIRST_TOKEN] when first LLM response chunk arrives - [LATENCY_TTS_REQUEST] when first TTS request sent per turn - All timing logs include turn_id to track per-conversation-turn 2. Fixed flux_apollo_cartesia graph for proper A/B testing: - Copied from flux_apollo_cartesia_heygen (correct source) - Removed heygen_avatar extension node - Configured TTS audio to route directly to agora_rtc - Preserves identical configs: voice ID, greeting, prompt, thymia settings This enables latency comparison between with-HeyGen (flux_apollo_cartesia_heygen) and without-HeyGen (flux_apollo_cartesia) pipelines. Timing logs measure: - STT → LLM latency - LLM inference latency - Total pipeline latency
Problems identified: 1. Docs recommended manual frontend restart for graph changes, but this can cause Next.js lock file errors that crash the entire task runner 2. When task run manages both API server and frontend, killing just frontend leaves task runner in bad state 3. Lock file error was not documented as a common issue 4. No clear guidance on when to use nuclear restart vs selective restarts Changes: 1. Updated "After Changing property.json" sections in both docs: - Recommend nuclear restart when adding/removing graphs (safest) - Keep manual restart as alternative with warning about lock issues - Explain why nuclear restart is preferred 2. Added new troubleshooting section "Next.js Lock File Error": - Symptoms and multiple root causes - Explains cascade failure (frontend crash -> task run fails -> API down) - Solution: nuclear restart with lock file cleanup - Prevention: don't manually restart frontend when managed by task run - Key insight about coupling between frontend and API via task run 3. Updated "When to Restart What" table: - Split property.json into two rows (graphs added/removed vs config only) - Explicit recommendation to use nuclear restart for graph changes - Added note about frontend/API coupling 4. Added cross-references to Nuclear Option section These improvements prevent the cascade failure that occurred when attempting to restart just the frontend after adding nova3_apollo_cartesia graph.
…yground error Problem: User reported seeing "missing required error components, refreshing..." error in playground - a Next.js error that has occurred "dozens of times" before. This error completely breaks the playground interface. Root Cause: Next.js development mode creates long-lived server processes that: 1. Can survive container restarts and persist for days 2. Multiple instances can run simultaneously and conflict 3. Conflict over /app/playground/.next/dev directory 4. Cause build manifest errors when corrupted This specific instance was caused by: - Stale next-server process from Nov 10 still running on Nov 11 - Multiple next-server processes (4 total) running simultaneously - Attempted deletion of .next directory while processes were running Solution Implemented: 1. Identified all next-server PIDs with ps aux 2. Killed all next-server processes by PID (kill -9) 3. Clean restart with task run 4. Waited 20 seconds for full .next rebuild Documentation Added: 1. Full troubleshooting section in AI_working_with_ten.md: - Comprehensive symptoms and diagnostics - Step-by-step solution with PID-based killing - Nuclear option if standard approach fails - Prevention guidelines - Root cause explanation 2. Compact version in AI_working_with_ten_compact.md: - Quick diagnosis and solution - Copy-paste commands - Nuclear option fallback Key Insights Added: - Next.js processes are long-lived and survive container restarts - Always check for stale processes before starting (ps aux | grep next-server) - Don't delete .next while server is running - Use proper shutdown procedures (nuclear restart) - Multiple next-server instances cause conflicts This documentation will prevent the issue from recurring by providing clear diagnosis and resolution steps.
…tection Updated all 9 Flux graphs with tighter endpointing parameters: - eot_threshold: 0.8 → 0.9 (require 90% confidence for end-of-turn) - eot_timeout_ms: 3000/5000 → 2000 (2 second max wait time) Affected graphs: - voice_assistant - dgv2_flux_thymia_rimetts - dgv2_flux_thymia_cartesiatts - dgv2_flux_rimetts - dgv2_flux_cartesiatts - flux_thymia_heygen_cartesia - flux_apollo_cartesia - flux_thymia_heygen_rime - flux_apollo_cartesia_heygen Impact: - Higher eot_threshold (0.9) reduces false positives for turn ending - User can speak longer utterances without being cut off prematurely - 2s timeout balances responsiveness with speech completion - Previous 3-5s timeouts caused noticeable delays after user stopped speaking This addresses the issue where Nova-3's aggressive finalization was cutting off users mid-sentence (e.g., "nineteen seven" instead of "nineteen seventy-five"). Flux with high confidence threshold provides better user experience while maintaining low latency.
Removed outdated planning and status documents: - apollo.md - docs_plan.md - hellos_aiohttp_plan.md - optimize.md - status.md - tts_end_plan.md Keeping only the essential documentation: - AI_working_with_ten.md (comprehensive reference) - AI_working_with_ten_compact.md (quick reference)
Add echo cancellation settling period filter that blocks all single-word transcripts during first 10 seconds of session to prevent false positives from agent's own voice during echo cancel warmup. Apply confidence filtering (0.75 threshold) only to single-word results while allowing all multi-word sentences to pass through regardless of confidence, preventing legitimate speech from being dropped. Fix agent_currently_speaking flag not being cleared on TTS completion (reason=1), which was causing wellness and clinical result announcements to be blocked indefinitely after agent speech. Reduce reading phase duration from 30s to 22s to better match actual reading time and minimize user wait time.
Pull Request Review: Deepgram v2 (flux) support with wellness analysisThank you for this substantial contribution! This PR adds significant new functionality including WebSocket-based ASR, wellness analysis, and avatar integrations. Here's my comprehensive review: 📋 SummaryChanges: 17,358 additions across 79 files
✅ Strengths
🔴 Critical Issues1. Security: API Keys in Logs (HIGH PRIORITY)Location: headers = {"Authorization": f"Token {self.config.api_key}"}Issue: API keys could be exposed if headers are logged during debugging. Recommendation:
Example from guidelines: def to_str(self, sensitive_handling: bool = True) -> str:
if not sensitive_handling:
return f"{self}"
config = copy.deepcopy(self)
if config.params and "api_key" in config.params:
config.params["api_key"] = utils.encrypt(config.params["api_key"])
return f"{config}"2. Resource Cleanup: Session Timeout in Exception PathLocation: async with self.session.close(), timeout=5.0:Issue: If session close times out, session object is not set to None, potentially causing issues in subsequent cleanup. Location: try:
await asyncio.wait_for(self.session.close(), timeout=5.0)
except asyncio.TimeoutError:
self.ten_env.log_warn("[DEEPGRAM-WS] Session close timed out")
self.session = None # Good - always sets to NoneRecommendation: Follow Deepgram pattern - always set session/websocket to None even after timeout. 3. Race Condition: Concurrent WebSocket OperationsLocation: async with self.speaking_lock:
if not self.is_speaking:
# ...
if self.recorder and self.recorder.ws_connected():
await self.recorder.interrupt()Issue: Recommendation: async with self.speaking_lock:
if not self.is_speaking and self.recorder:
if self.recorder.ws_connected():
try:
await self.recorder.interrupt()
except Exception as e:
self.ten_env.log_warn(f"Interrupt failed: {e}")4. Subprocess Usage in Async Context (SECURITY & RELIABILITY)Location: # Use curl subprocess to make the request
curl_cmd = ["curl", "-X", "POST", ...]
process = await asyncio.create_subprocess_exec(*curl_cmd, ...)Issues:
Recommendation: Use aiohttp consistently (like async with self.session.post(
f"{self.base_url}/v1/models/mental-wellness",
json=payload
) as response:
if response.status not in (200, 201):
error_text = await response.text()
raise ThymiaAPIError(f"Failed: {response.status} - {error_text}")
return await response.json()
|
| Priority | Count | Must Fix Before Merge |
|---|---|---|
| Critical | 4 | ✅ Yes |
| High | 7 | |
| Medium | 4 | ❌ No |
| Quality | 4 | ❌ No |
Final Notes
This is a substantial and well-structured PR that adds important functionality. The code quality is generally good, following framework patterns correctly. The main concerns are around security (API key logging, command injection) and resource management (race conditions, cleanup). Once the critical issues are addressed, this will be a solid contribution to the project.
Great work on the comprehensive documentation - it will significantly help future developers working with the TEN Framework!
Reviewed by: Claude Code
Review Date: 2025-11-11
Reduce single-word filter window from 10 seconds to 5 seconds to allow earlier user interruptions while still protecting against initial echo cancel false positives during greeting playback.
Code Review: PR #1691 - Add Deepgram Flux v2 & Wellness Analysis FeaturesThank you for this comprehensive PR! I've completed a thorough review covering code quality, potential bugs, performance, security, and test coverage. Overall, this is a well-structured addition with good async patterns and proper configuration handling. 📊 SummaryWhat's Being Added:
Scale: 79 files changed, +17,358 lines ✅ Strengths
🔴 Critical IssuesNone found that would block merging. 🟡 High Priority Issues1. Subprocess Usage in thymia_analyzer_python (Security)File: Currently uses subprocess curl for API calls instead of aiohttp: curl_cmd = ["curl", "-X", "POST", f"{self.base_url}/v1/models/mental-wellness", ...]
process = await asyncio.create_subprocess_exec(*curl_cmd, ...)Issue: Introduces unnecessary security risk and is inconsistent with the aiohttp pattern used elsewhere (apollo_api.py). Recommendation: Replace with aiohttp (pattern already demonstrated in apollo_api.py): async with self.session.post(
f"{self.base_url}/v1/models/mental-wellness",
json=payload,
headers={"x-api-key": self.api_key}
) as response:
if response.status not in (200, 201):
raise ThymiaAPIError(f"Failed: {response.status}")
return await response.json()2. Bug in heygen_avatar_pythonFile: def _dump_audio_if_need(self, buf: bytearray) -> None:
with open("{}_{}.pcm".format("tts", self.config.agora_channel_name), "ab") as dump_file:Issue: References undefined field Recommendation: Remove this dead code entirely. 3. Large File Needs RefactoringFile: Issue: Single file with 123KB of code makes maintenance difficult. Recommendation: Split into modules:
🟠 Medium Priority Issues1. Fire-and-Forget Tasks Without Exception HandlingFound in all extensions:
Pattern: asyncio.create_task(self._some_background_task()) # Not stored or awaitedIssue: Exceptions in background tasks will be silently swallowed. Recommendation: self.background_task = asyncio.create_task(self._some_background_task())
# In on_stop():
if self.background_task:
self.background_task.cancel()
try:
await self.background_task
except asyncio.CancelledError:
pass2. Infinite Loop Without TimeoutFile: async def _wait_for_recorder_ready(self):
while self.recorder.connected is False:
await asyncio.sleep(0.5)Issue: If recorder never connects, loop runs forever. Recommendation: Add timeout: timeout = 30 # seconds
start_time = asyncio.get_event_loop().time()
while self.recorder.connected is False:
if asyncio.get_event_loop().time() - start_time > timeout:
raise TimeoutError("Recorder failed to connect")
await asyncio.sleep(0.5)3. Silent Exception SuppressionFile: except Exception:
passIssue: Silently hides initialization errors. Recommendation: At minimum, log the errors: except Exception as e:
ten_env.log_error(f"Failed to load property: {e}")4. Test Coverage GapsStatus: Only 1 of 4 extensions has tests (heygen_avatar_python). Missing tests:
Recommendation: Add unit tests following the heygen_avatar_python pattern:
🟢 Low Priority / Nice-to-Haves
📈 Performance ConsiderationsPositive:
Potential Improvements:
🔒 Security Assessment✅ Good Practices:
|
| Extension | Tests? | Coverage Level |
|---|---|---|
| deepgram_ws_asr_python | ❌ No | 0% |
| thymia_analyzer_python | ❌ No | 0% (highest risk - 123KB code) |
| heygen_avatar_python | ✅ Yes | Basic unit test |
| generic_video_python | ❌ No | 0% |
| voice-assistant-advanced | ✅ Yes | Integration tests (config validation) |
Overall: 25% extension test coverage (1/4), plus integration tests for the example.
📝 Specific File References
Bugs:
heygen_avatar_python/extension.py:177- Wrong field name in dead code
Security:
thymia_analyzer_python/extension.py:362-406- Subprocess curl usage
Code Quality:
thymia_analyzer_python/extension.py- 2794 lines, needs refactoring- All extensions - Fire-and-forget tasks need exception handling
generic_video_python/extension.py:170-172- Infinite loop without timeout
Tests:
- Add tests to:
deepgram_ws_asr_python/,thymia_analyzer_python/,generic_video_python/
🎯 Recommendations Priority
Before Merge:
- Fix heygen bug (wrong field name) - 5 min fix
- Remove dead code (
_dump_audio_if_need) - 5 min fix
For Next Iteration:
- Replace subprocess curl with aiohttp in thymia (security/consistency)
- Add exception handling to fire-and-forget tasks
- Add timeout to
_wait_for_recorder_readyloop - Add tests for the 3 untested extensions
Long Term:
- Refactor thymia_analyzer_python into modules
- Improve logging consistency across extensions
- Add SSL contexts to WebSocket connections
✅ Conclusion
This is a solid PR that adds significant functionality with good async patterns and proper configuration management. The code is generally well-structured and follows framework conventions.
Recommendation: Approve with minor fixes - The two small bugs (heygen field name, dead code removal) should be fixed before merge. The other issues can be addressed in follow-up PRs as they don't block functionality.
Great work on the comprehensive documentation and integration tests! The voice-assistant-advanced example provides excellent validation of the graph configurations.
Review generated using Claude Code with analysis of all 79 changed files, focusing on code quality, security, performance, and test coverage per repository CLAUDE.md guidelines.
Implement future-proof channel forwarding that automatically injects channel_name into ALL nodes with a "channel" property (not just hardcoded names). Server changes: - http_server.go: Scan all graph nodes for "channel" property - http_server.go: Auto-inject dynamic channel value from request - config.go: Add explanatory comment about property-based injection How it works: 1. Client sends channel_name in /start request 2. Server scans ALL nodes in the selected graph 3. Any node with a "channel" property gets the dynamic value 4. Works with any extension type (audio, video, avatar, analytics) Benefits: - Future-proof: new extensions with "channel" property work automatically - No code changes needed for new extensions requiring channel - Type-safe across all extension types - Enables concurrent sessions with proper channel isolation Includes comprehensive analysis document (ai/channel_plan.md) explaining the issue, data flow, and implementation approach.
Remove all 6 graphs beginning with 'dgv' (dgv1_nova3_rimetts, dgv1_nova3_thymia_rimetts, dgv2_flux_thymia_rimetts, dgv2_flux_thymia_cartesiatts, dgv2_flux_rimetts, dgv2_flux_cartesiatts) leaving 8 active graphs.
Comprehensive Code Review: PR #1691Executive SummaryThis PR adds 81 files with 16,313 additions including 4 new extensions. While showing solid async understanding, there are 5 critical and 7 high-priority issues requiring fixes before merge. 🔴 Critical Issues (Must Fix)1. Untracked Background TasksFiles: thymia_analyzer_python/extension.py (lines 884, 1075, 1149, 1153, 2702) 2. subprocess curl UsageFile: thymia_analyzer_python/extension.py:363-406 3. Race Condition in ConnectionFile: deepgram_ws_asr_python/extension.py:156-197 4. API Keys in Command ArgsFile: thymia_analyzer_python/extension.py:363-377 5. Blocking HTTP CallsFiles: heygen_avatar_python/heygen.py:134-216, generic_video_python/generic.py:240-306 🟠 High Priority1. Wrong requirements.txtFile: thymia_analyzer_python/requirements.txt 2. Missing requirements.txt in ManifestFile: thymia_analyzer_python/manifest.json 3. Missing Version PinsFiles: heygen/generic requirements.txt 4-7. Other High Issues
🟡 Medium Priority12 issues including: debug logging, magic numbers, inefficient resampling, god object pattern (2,794 lines). ✅ Strengths
🎯 RecommendationDo NOT merge until fixing:
Effort: 8-16 hours Claude Code Review | 2025-11-11 | Commit f94189c |
- Add property-based channel injection to auto-inject channel into ALL nodes with "channel" property - Remove 6 deprecated dgv* graphs from property.json - Fix ImportError in openai_llm2_python by removing non-existent imports - Fix AttributeError in openai.py by removing invalid prompt access - Update manifest.json to use cartesia_tts instead of cartesia_tts2 - Add explanatory comments for new dynamic injection behavior This makes channel injection future-proof - any new extension with a "channel" property will automatically receive the dynamic value without code changes.
Replace all instances of hardcoded channel 'agora_g3qhjr' with empty strings. Dynamic channel injection will populate the channel value at runtime.
- Add suppressHydrationWarning to html/body tags to prevent React hydration errors - Truncate long graph names in selector (17 chars + ...) when closed - Show full graph names in dropdown when open - Prevent Connect button from wrapping to new line on mobile - Set min-height 240px on agent view to prevent covering buttons - Ensure microphone/video buttons always visible with flex-shrink-0
- Add 'Full Persistent Startup' section with complete procedure for session-independent startup - Clarify that task run starts BOTH API server AND playground together - Document that playground may use port 3001 if 3000 is busy - Add verification steps with proper wait times (15s for full startup) - Include key points about -d flag keeping processes running after disconnect
PR Review: Deepgram v2 (Flux) Support with Wellness AnalysisSummaryThis is a substantial PR adding 85 files with 16,397 additions that introduces:
✅ Strengths1. Excellent Documentation ⭐
2. Well-Structured Deepgram WebSocket ExtensionFile: Strengths:
Good practices observed: # Line 161: Proper locking for connection state
async with self._connection_lock:
await self.stop_connection()
# Line 286: Smart filtering for false positives
if word_count == 1 and elapsed_time < 5.0:
# Drop single-word results during echo cancel settling3. Robust Audio Processing in Thymia AnalyzerFile:
Performance consideration: # Line 64: Using deque for efficient circular buffer
self.circular_buffer = deque() # O(1) popleft() vs list O(n)4. Server-Side Property Auto-Injection ⭐File: Excellent architectural decision to implement property-based auto-injection:
Benefits:
5. Good Test Coverage
|
| Category | Rating | Notes |
|---|---|---|
| Documentation | ⭐⭐⭐⭐⭐ | Exceptional - comprehensive guides |
| Architecture | ⭐⭐⭐⭐⭐ | Property injection pattern is excellent |
| Error Handling | ⭐⭐⭐☆☆ | Good but inconsistent across extensions |
| Type Safety | ⭐⭐⭐☆☆ | Missing return type hints in places |
| Security | ⭐⭐⭐☆☆ | API keys need better masking |
| Test Coverage | ⭐⭐⭐☆☆ | Basic tests present, needs more coverage |
| Performance | ⭐⭐⭐⭐☆ | Generally good, minor optimizations possible |
🎯 Recommendations Priority
High Priority (Should fix before merge):
- ✅ Mask API keys in logs (security)
- ✅ Fix infinite loops to use cancellable flags
- ✅ Add missing environment variables to .env.example
- ✅ Fix future date in documentation
Medium Priority (Fix soon after merge):
- Add comprehensive unit tests for audio processing
- Standardize configuration validation across extensions
- Extract duplicated code to shared utilities
- Add missing type hints
Low Priority (Nice to have):
- Optimize audio buffer concatenation for large files
- Add integration tests for error scenarios
📝 Summary
This is a high-quality PR that adds significant value to the TEN Framework:
Major Wins:
- ⭐ Exceptional documentation (2,715 lines of comprehensive guides)
- ⭐ Smart server-side property injection architecture
- ✅ Well-structured Deepgram v2 (Flux) implementation
- ✅ Sophisticated audio processing with VAD
- ✅ Good async/await patterns
Areas for Improvement:
- 🔒 API key security (masking in logs)
- 🛡️ Error handling consistency
- 🧪 Test coverage expansion
- 📦 Type safety improvements
Recommendation: APPROVE with minor changes
The core implementation is solid, and the identified issues are mostly polish items that can be addressed incrementally. The documentation alone makes this PR valuable for the community.
Great work! 🚀
Reviewed with: TEN Framework CLAUDE.md conventions
Review Date: 2025-01-12
Code Review: PR #1691OverviewThis PR adds 4 new extensions, voice-assistant-advanced example with 7 graph variants, comprehensive documentation, and playground improvements. Scope: 85 files, 16,398 additions. Assessment: Near production-ready with critical issues that must be addressed Critical Issues (Must Fix)1. Debug File I/O in Production (thymia_analyzer_python)Lines 540-564, 655-670: Synchronous file writes to /tmp in async code
2. Subprocess Security Risk (thymia_analyzer_python)Lines 363-406: Using curl subprocess instead of aiohttp
3. TLS Verification Disabled (server/internal/http_client.go:14)InsecureSkipVerify: true for ALL HTTP calls
High Priority Issues4. Unbounded Queues (heygen/generic_video)asyncio.Queue() with no maxsize can cause OOM 5. AudioBuffer Growth (thymia)No byte-size limit, only 300s duration check 6. Goroutine Leak (worker.go:216-231)No context cancellation in worker monitor 7. CORS Wildcard (middleware.go)Access-Control-Allow-Origin: * allows all origins 8. Frontend Message Cache Leak (rtc.ts:192-289)Messages with total_parts=-1 never cleaned Strengths
Areas for Improvement
Test CoverageGood: deepgram_ws_asr_python, heygen_avatar_python have tests Recommendation: Add tests for API errors, buffer edge cases, async cleanup Performance
Security SummaryCritical: TLS disabled, subprocess risk RecommendationsMust Fix Before Merge:
Should Fix:
Nice to Have:
Scorecard
VerdictSubstantial, valuable contribution with excellent documentation and good practices. However, 3 critical security/stability issues must be fixed before production. Recommendation: Request changes for critical issues, then approve. Great work overall! |
- Remove PERSISTENT_KEYS_CONFIG.md (contained real API keys) - Remove CLAUDE.md (not needed in repo) - Add patterns to .gitignore - Add pre-commit hook to prevent API key commits - Add latency_investigation.md with Groq integration plan CRITICAL: Exposed keys must be rotated: - HEYGEN_API_KEY - THYMIA_API_KEY
6fd7e63 to
c9319fe
Compare
No description provided.