forked from Rockachopa/Timmy-time-dashboard
fix: Docker-first test suite, UX improvements, and bug fixes (#100)
Dashboard UX: - Restructure nav from 22 flat links to 6 core + MORE dropdown - Add mobile nav section labels (Core, Intelligence, Agents, System, Commerce) - Defer marked.js and dompurify.js loading, consolidate CDN to jsdelivr - Optimize font weights (drop unused 300/500), bump style.css cache buster - Remove duplicate HTMX load triggers from sidebar and health panels Bug fixes: - Fix Timmy showing OFFLINE by registering after swarm recovery sweep - Fix ThinkingEngine await bug with asyncio.run_coroutine_threadsafe - Fix chat auto-scroll by calling scrollChat() after history partial loads - Add missing /voice/button page and /voice/command endpoint - Fix Grok api_key="" treated as falsy falling through to env key - Fix self_modify PROJECT_ROOT using settings.repo_root instead of __file__ Docker test infrastructure: - Bind-mount hands/, docker/, Dockerfiles, and compose files into test container - Add fontconfig + fonts-dejavu-core for creative/assembler TextClip tests - Initialize minimal git repo in Dockerfile.test for GitSafety compatibility - Fix introspection and path resolution tests for Docker /app context All 1863 tests pass in Docker (0 failures, 77 skipped). Co-authored-by: Alexander Payne <apayne@MM.local> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
6e67c3b421
commit
89cfe1be0d
@@ -1,12 +1,16 @@
|
||||
"""Voice routes — /voice/* and /voice/enhanced/* endpoints.
|
||||
|
||||
Provides NLU intent detection, TTS control, and the full voice-to-action
|
||||
pipeline (detect intent → execute → optionally speak).
|
||||
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
|
||||
from fastapi import APIRouter, Form, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from pathlib import Path
|
||||
|
||||
from integrations.voice.nlu import detect_intent, extract_command
|
||||
from timmy.agent import create_timmy
|
||||
@@ -14,6 +18,7 @@ from timmy.agent import create_timmy
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/voice", tags=["voice"])
|
||||
templates = Jinja2Templates(directory=str(Path(__file__).parent.parent / "templates"))
|
||||
|
||||
|
||||
@router.post("/nlu")
|
||||
@@ -56,6 +61,31 @@ async def tts_speak(text: str = Form(...)):
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user