chore: cleanup dead code and unused files
Deleted 7 unused frontend components (ChatBubble, PetZone, Live2DCat, BackgroundScene, Clock, Toolbar, types/index.ts). Deleted unused backend: whisper_stream.py, empty models/ and routers/ dirs. Removed dead code: Message interface, messages/micError/sendText/addMessage, conversation_text handler, 3 unused memory.py methods. Fixed task persistence bug: added 'tasks' to DEFAULT_PREFERENCES. Stale comment in Live2DStage updated.
This commit is contained in:
@@ -383,29 +383,6 @@ async def gemini_voice_ws(websocket: WebSocket):
|
||||
await gemini_ws.send(json.dumps(gemini_msg))
|
||||
continue
|
||||
|
||||
if msg_type == "conversation_text":
|
||||
text = msg.get("text", "").strip()
|
||||
if not text:
|
||||
continue
|
||||
logger.info(f"[{session_id}] User (text): {text}")
|
||||
if gemini_ws and gemini_ws.state.name == "OPEN":
|
||||
user_part = {"text": text}
|
||||
if memory_suffix:
|
||||
user_part = {"text": f"[Context: {memory_suffix}]\n{text}"}
|
||||
gemini_msg = {
|
||||
"clientContent": {
|
||||
"turns": [{"role": "user", "parts": [user_part]}],
|
||||
"turnComplete": True,
|
||||
}
|
||||
}
|
||||
await gemini_ws.send(json.dumps(gemini_msg))
|
||||
await websocket.send_json({
|
||||
"type": "transcript",
|
||||
"role": "user",
|
||||
"text": text,
|
||||
})
|
||||
continue
|
||||
|
||||
if msg_type == "ping":
|
||||
await websocket.send_json({"type": "pong"})
|
||||
|
||||
|
||||
@@ -134,57 +134,12 @@ class KiraMemory:
|
||||
|
||||
return "\n\n---\n### What Kira remembers:" + "".join(parts)
|
||||
|
||||
def store_messages(
|
||||
self,
|
||||
user_message: str,
|
||||
kira_message: str,
|
||||
) -> None:
|
||||
"""Store a conversation exchange in Honcho."""
|
||||
if not self.enabled or not self._session:
|
||||
return
|
||||
|
||||
try:
|
||||
messages = []
|
||||
if self._user_peer:
|
||||
messages.append(
|
||||
self._user_peer.message(user_message)
|
||||
)
|
||||
if self._kira_peer:
|
||||
messages.append(
|
||||
self._kira_peer.message(kira_message)
|
||||
)
|
||||
|
||||
if messages:
|
||||
self._session.add_messages(messages)
|
||||
logger.debug("Stored conversation exchange in Honcho")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to store messages: {e}")
|
||||
|
||||
def store_user_message(self, text: str) -> None:
|
||||
"""Store a single user message."""
|
||||
if not self.enabled or not self._session or not self._user_peer:
|
||||
return
|
||||
try:
|
||||
self._session.add_messages([self._user_peer.message(text)])
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to store user message: {e}")
|
||||
|
||||
def store_kira_message(self, text: str) -> None:
|
||||
"""Store a single Kira message."""
|
||||
if not self.enabled or not self._session or not self._kira_peer:
|
||||
return
|
||||
try:
|
||||
self._session.add_messages([self._kira_peer.message(text)])
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to store Kira message: {e}")
|
||||
|
||||
# ─── User preferences (stored in Honcho peer metadata) ───
|
||||
|
||||
DEFAULT_PREFERENCES: dict[str, str] = {
|
||||
"name": "",
|
||||
"scene": "cozy-room",
|
||||
"outfit": "cozy-hoodie",
|
||||
"accessory": "",
|
||||
"tasks": "[]",
|
||||
}
|
||||
|
||||
def get_user_preferences(self, user_id: str) -> dict[str, str]:
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
"""Realtime streaming transcription service via gpt-realtime-whisper.
|
||||
|
||||
Connects to OpenAI Realtime API via WebSocket, configures the session
|
||||
for pure transcription (no model responses), and streams word-level
|
||||
transcript deltas back. Full utterances are then processed by the
|
||||
cheap LLM + TTS pipeline.
|
||||
"""
|
||||
|
||||
import json
|
||||
import base64
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Callable, Awaitable
|
||||
from config import settings
|
||||
|
||||
logger = logging.getLogger("kira.whisper")
|
||||
|
||||
|
||||
class WhisperStream:
|
||||
"""Streaming transcription via gpt-realtime-whisper over WebSocket."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
on_transcript_delta: Callable[[str], Awaitable[None]],
|
||||
on_transcript_done: Callable[[str], Awaitable[None]],
|
||||
on_ready: Callable[[], Awaitable[None]],
|
||||
on_error: Callable[[str], Awaitable[None]],
|
||||
):
|
||||
self._on_delta = on_transcript_delta
|
||||
self._on_done = on_transcript_done
|
||||
self._on_ready = on_ready
|
||||
self._on_error = on_error
|
||||
self._conn = None
|
||||
self._connected = False
|
||||
self._transcript = ""
|
||||
|
||||
async def connect(self):
|
||||
if self._connected:
|
||||
return
|
||||
|
||||
try:
|
||||
import websockets
|
||||
|
||||
url = "wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview"
|
||||
ws = await websockets.connect(
|
||||
url,
|
||||
additional_headers={
|
||||
"Authorization": f"Bearer {settings.openai_api_key}",
|
||||
},
|
||||
)
|
||||
|
||||
async with ws as conn:
|
||||
self._conn = conn
|
||||
self._connected = True
|
||||
logger.info("Connected to Realtime transcription session")
|
||||
|
||||
# Configure: transcribe only with gpt-realtime-whisper, no model responses
|
||||
await self._send({
|
||||
"type": "session.update",
|
||||
"session": {
|
||||
"input_audio_format": "pcm16",
|
||||
"input_audio_transcription": {
|
||||
"model": "gpt-realtime-whisper",
|
||||
"enabled": True,
|
||||
},
|
||||
"turn_detection": {
|
||||
"type": "server_vad",
|
||||
"threshold": 0.5,
|
||||
"prefix_padding_ms": 300,
|
||||
"silence_duration_ms": 600,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await self._on_ready()
|
||||
|
||||
while self._connected:
|
||||
try:
|
||||
raw = await conn.recv()
|
||||
if isinstance(raw, (str, bytes)):
|
||||
data = json.loads(raw if isinstance(raw, str) else raw.decode())
|
||||
await self._handle(data)
|
||||
except Exception as e:
|
||||
if self._connected:
|
||||
logger.warning(f"recv: {e}")
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Whisper stream error: {e}")
|
||||
await self._on_error(str(e))
|
||||
finally:
|
||||
self._connected = False
|
||||
self._conn = None
|
||||
|
||||
async def _handle(self, data: dict):
|
||||
et = data.get("type", "")
|
||||
|
||||
if et == "input_audio_buffer.speech_started":
|
||||
self._transcript = ""
|
||||
logger.debug("speech_started")
|
||||
|
||||
elif et in ("conversation.item.input_audio_transcription.delta", "input_audio_buffer.transcription.delta"):
|
||||
# Partial streaming transcript
|
||||
delta = data.get("delta", "") or data.get("transcript", "")
|
||||
if delta:
|
||||
self._transcript = delta # or append if cumulative
|
||||
await self._on_delta(delta)
|
||||
|
||||
elif et in ("conversation.item.input_audio_transcription.completed", "input_audio_buffer.transcription.completed", "conversation.item.created"):
|
||||
# Final or item created with transcript
|
||||
item = data.get("item", {})
|
||||
content = item.get("content", []) if item else []
|
||||
transcript = data.get("transcript", "")
|
||||
if not transcript:
|
||||
for part in (content or []):
|
||||
if part.get("type") in ("transcript", "text"):
|
||||
transcript = part.get("transcript", "") or part.get("text", "")
|
||||
break
|
||||
if transcript:
|
||||
self._transcript = transcript
|
||||
await self._on_delta(transcript)
|
||||
await self._on_done(transcript.strip())
|
||||
self._transcript = ""
|
||||
|
||||
elif et == "input_audio_buffer.speech_stopped":
|
||||
if self._transcript.strip():
|
||||
await self._on_done(self._transcript.strip())
|
||||
self._transcript = ""
|
||||
|
||||
elif et == "error":
|
||||
err = data.get("error", {})
|
||||
msg = err.get("message", str(data))
|
||||
logger.warning(f"Whisper error: {msg}")
|
||||
await self._on_error(msg)
|
||||
|
||||
async def send_audio(self, pcm16_bytes: bytes):
|
||||
if not self._connected:
|
||||
return
|
||||
try:
|
||||
b64 = base64.b64encode(pcm16_bytes).decode("utf-8")
|
||||
await self._send({"type": "input_audio_buffer.append", "audio": b64})
|
||||
except Exception as e:
|
||||
logger.warning(f"send audio: {e}")
|
||||
|
||||
async def _send(self, data: dict):
|
||||
try:
|
||||
await self._conn.send(json.dumps(data))
|
||||
except Exception as e:
|
||||
logger.warning(f"send: {e}")
|
||||
|
||||
async def disconnect(self):
|
||||
self._connected = False
|
||||
if self._conn:
|
||||
try:
|
||||
await self._conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
self._conn = None
|
||||
Reference in New Issue
Block a user