Files
jeremy d901208032 feat: VoiceCoach v2.1 - GPU local, Ollama LLM, settings panel, token server separation
- pipeline.py: switched LLM from OpenClaw/Claude to local Ollama, added settings loading, sentence aggregator, async SpeechBrain, tuned VAD
- main.py: simplified (no more token server thread, just pipeline)
- token_server.py: NEW - standalone token + settings API server
- docker-compose.yml: all services on GPU machine, added token-server service, CUDA speaches, Ollama LLM
- web-client/index.html: added settings panel with sliders
- web-client/app.js: settings management, localStorage persistence, push to server
- web-client/style.css: settings panel styles
- web-client/nginx.conf: proxy to token-server instead of pipecat-agent
- patch_livekit.py: updated with proper indentation-safe patching
2026-04-04 12:27:06 -05:00

59 lines
2.1 KiB
Python

"""Patch pipecat LiveKit transport bugs at build time."""
import pipecat.transports.services.livekit as lk_mod
lk_path = lk_mod.__file__
print(f"Patching {lk_path}")
content = open(lk_path).read()
# FIX 1: Remove direct push_frame(pipecat_audio_frame) that bypasses VAD
old1 = "await self.push_frame(pipecat_audio_frame)"
if old1 in content:
content = content.replace(old1, "pass # PATCHED: removed VAD bypass")
print("FIX 1: Removed push_frame(pipecat_audio_frame) VAD bypass")
# FIX 2: Wrap the on_connected call in connect() method with try/except
# The line is: " await self._callbacks.on_connected()" (12 spaces)
# We replace it with a try/except at the same indentation level
old2 = " await self._callbacks.on_connected()\n"
new2 = (
" try:\n"
" await self._callbacks.on_connected()\n"
" except Exception:\n"
" pass # PATCHED: suppress duplicate callback\n"
)
if old2 in content:
content = content.replace(old2, new2)
print("FIX 2: Wrapped on_connected with try/except")
open(lk_path, "w").write(content)
# Verify syntax
import py_compile
try:
py_compile.compile(lk_path, doraise=True)
print("Syntax check: PASS")
except py_compile.PyCompileError as e:
print(f"Syntax check: FAIL - {e}")
# Show the problematic area
lines = open(lk_path).readlines()
for i in range(130, min(145, len(lines))):
print(f" {i+1}: {lines[i]}", end="")
# FIX 3: Guard set_result on already-resolved Future in livekit SDK
try:
import livekit.rtc.room as room_mod
room_path = room_mod.__file__
room_content = open(room_path).read()
if ("self._first_sid_future.set_result" in room_content and
".done()" not in room_content.split("_first_sid_future")[1][:200]):
room_content = room_content.replace(
"self._first_sid_future.set_result",
"not self._first_sid_future.done() and self._first_sid_future.set_result"
)
open(room_path, "w").write(room_content)
print(f"FIX 3: Patched {room_path}")
except Exception as e:
print(f"FIX 3: Skipped: {e}")
print("All patches complete")