1
0
This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/src/dashboard/routes/voice.py
Kimi Agent fdc5b861ca fix: replace 59 bare except clauses with proper logging (#25)
All `except Exception:` now catch as `except Exception as exc:` with
appropriate logging (warning for critical paths, debug for graceful degradation).

Added logger setup to 4 files that lacked it:
- src/timmy/memory/vector_store.py
- src/dashboard/middleware/csrf.py
- src/dashboard/middleware/security_headers.py
- src/spark/memory.py

31 files changed across timmy core, dashboard, infrastructure, integrations.
Zero bare excepts remain. 1340 tests passing.
2026-03-14 19:07:14 -04:00

154 lines
4.8 KiB
Python

"""Voice routes — /voice/* and /voice/enhanced/* endpoints.
Provides NLU intent detection, TTS control, the full voice-to-action
pipeline (detect intent → execute → optionally speak), and the voice
button UI page.
"""
import logging
from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse
from dashboard.templating import templates
from integrations.voice.nlu import detect_intent, extract_command
from timmy.agent import create_timmy
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/voice", tags=["voice"])
@router.post("/nlu")
async def nlu_detect(text: str = Form(...)):
"""Detect intent from a text utterance."""
intent = detect_intent(text)
command = extract_command(text)
return {
"intent": intent.name,
"confidence": intent.confidence,
"entities": intent.entities,
"command": command,
"raw_text": intent.raw_text,
}
@router.get("/tts/status")
async def tts_status():
"""Check TTS engine availability."""
try:
from timmy_serve.voice_tts import voice_tts
return {
"available": voice_tts.available,
"voices": voice_tts.get_voices() if voice_tts.available else [],
}
except Exception as exc:
logger.debug("Voice config error: %s", exc)
return {"available": False, "voices": []}
@router.post("/tts/speak")
async def tts_speak(text: str = Form(...)):
"""Speak text aloud via TTS."""
try:
from timmy_serve.voice_tts import voice_tts
if not voice_tts.available:
return {"spoken": False, "reason": "TTS engine not available"}
voice_tts.speak(text)
return {"spoken": True, "text": text}
except Exception as exc:
return {"spoken": False, "reason": str(exc)}
# ── Voice button page ────────────────────────────────────────────────────
@router.get("/button", response_class=HTMLResponse)
async def voice_button_page(request: Request):
"""Render the voice button UI."""
return templates.TemplateResponse(request, "voice_button.html")
@router.post("/command")
async def voice_command(text: str = Form(...)):
"""Process a voice command (used by voice_button.html).
Wraps the enhanced pipeline and returns the result in the format
the voice button template expects.
"""
result = await process_voice_input(text=text, speak_response=False)
return {
"command": {
"intent": result["intent"],
"response": result["response"] or result.get("error", "No response"),
}
}
# ── Enhanced voice pipeline ──────────────────────────────────────────────
@router.post("/enhanced/process")
async def process_voice_input(
text: str = Form(...),
speak_response: bool = Form(False),
):
"""Process a voice input: detect intent -> execute -> optionally speak.
This is the main entry point for voice-driven interaction with Timmy.
"""
intent = detect_intent(text)
response_text = None
error = None
try:
if intent.name == "status":
response_text = "Agent is operational and running locally. All systems nominal."
elif intent.name == "help":
response_text = (
"Available commands: chat with me, check status, "
"manage the swarm, create tasks, or adjust voice settings. "
"Everything runs locally — no cloud, no permission needed."
)
elif intent.name == "swarm":
response_text = "Swarm module is not currently active."
elif intent.name == "voice":
response_text = "Voice settings acknowledged. TTS is available for spoken responses."
elif intent.name == "code":
response_text = "Self-modification module is not currently active."
else:
# Default: chat with Timmy
agent = create_timmy()
run = agent.run(text, stream=False)
response_text = run.content if hasattr(run, "content") else str(run)
except Exception as exc:
error = f"Processing failed: {exc}"
logger.error("Voice processing error: %s", exc)
# Optionally speak the response
if speak_response and response_text:
try:
from timmy_serve.voice_tts import voice_tts
if voice_tts.available:
voice_tts.speak(response_text)
except Exception as exc:
logger.debug("Voice TTS error: %s", exc)
pass
return {
"intent": intent.name,
"confidence": intent.confidence,
"response": response_text,
"error": error,
"spoken": speak_response and response_text is not None,
}