TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/davidmpizarro/QuipuEco-Hackaton/llms.txt
Use this file to discover all available pages before exploring further.
AgenteVoz component is a floating conversational interface that turns QuipuEco into a fully hands-free recycling assistant. Built entirely on the browser-native Web Speech API, it combines continuous speech recognition with text-to-speech synthesis to let Lima residents ask questions like “¿Dónde puedo llevar estas pilas?” or “¿Cómo preparo el cartón?” without touching the screen. The agent is context-aware — it receives the last classification result, the full conversation history, and the user’s GPS coordinates, so responses are specific to both the waste type at hand and the user’s physical location in Lima. When the agent determines that a map or dashboard view is needed, it emits a structured action that the parent App component uses to navigate programmatically.
Opening the Agent
The voice agent can be launched from two entry points:FAB Button
A floating action button (FAB) is visible on every screen except the map view. It pulses with a green glow and shows the QuipuEco mascot avatar. Tapping it opens the agent overlay from any context — even without a prior classification.
Result View Button
Inside the
ClassificationResult view, a “Hablar con el Agente” button (or “Continuar con el Agente” if a conversation is already in progress) opens the agent pre-seeded with the classification context, so the first message is automatically the respuesta_voz field read aloud.Voice Pipeline
User taps the mic button
toggleEscucha() flips escuchaActivaRef to true and calls iniciarEscucha({ manual: true }). A 10-second silence timeout is started; if no speech is detected the mic deactivates automatically and an error hint is shown.SpeechRecognition captures speech
A
webkitSpeechRecognition instance is configured with lang: "es-MX", interimResults: true, and continuous: false. Interim transcripts are shown in a live italic bubble; once isFinal === true, the complete transcript is forwarded to the backend.POST /chat with context
The transcript, the last 10 turns of history, the waste classification context, and the user’s GPS coordinates are sent to the backend:
Response spoken aloud
data.respuesta is added to the chat history and passed to hablar(), which creates a SpeechSynthesisUtterance at rate: 0.95 and pitch: 1. The voice preference chain runs synchronously (see Voice Selection below).API Endpoint
| Response field | Type | Description |
|---|---|---|
respuesta | string | Text spoken aloud and shown as the agent bubble |
accion | "mapa" | "dashboard" | null | Navigation action to trigger after TTS |
accion_data | string | null | Category filter string passed to VistaMapaPuntos (e.g. "electronico") |
punto_cercano | object | null | If set, the map will auto-route to this specific collection point |
Supported Voice Commands
The Python backend uses Gemini to interpret free-form Spanish queries. The table below shows representative intents and their expected agent behaviours.| Example utterance | Agent behaviour |
|---|---|
| ”¿Cómo preparo el cartón para reciclarlo?” | Returns preparation instructions; no navigation action |
| ”¿Dónde llevo esta botella?” | Returns nearby Tambo locations; accion: "mapa", accion_data: "plastico" |
| ”Quiero ver mi impacto” | Returns a brief summary; accion: "dashboard" |
| ”¿Qué pasa si tiro las pilas a la basura?” | Explains environmental risk; no navigation action |
| ”El punto más cercano para electrónicos” | Returns closest Centro Verde; accion: "mapa" with punto_cercano populated |
| ”¿Cuánto CO₂ he ahorrado?” | Reads stats.co2Total from context; no navigation action |
Agent States
The header status indicator and the mic button change appearance to reflect the current agent state in real time.🔇 Idle / Mic Off
Grey mic button (
bg-zinc-700). escuchaActivaRef.current === false. The agent is neither listening nor speaking. Tap the mic to activate.🎙 Listening
Red mic button (
bg-red-500) with scale-110. SpeechRecognition is active. Live interim transcript shown in an italic bubble. Status label: ”🎙 Escuchando…”⏳ Thinking
Mic button disabled (
disabled:opacity-50). Three emerald bouncing dots (bg-emerald-400) shown in the chat area. POST /chat is in flight. Status label: ”⏳ Pensando…” (amber text in the header).🔊 Speaking
Blue mic button (
bg-blue-600) with a Volume2 pulse icon. SpeechSynthesis is active. After the utterance ends, recognition auto-restarts if escuchaActivaRef is still true. Status label: ”🔊 Hablando…”Voice Selection
AgenteVoz resolves the best available Spanish TTS voice using a priority chain. The chain runs both on the initial greeting and on every subsequent agent response:
- Microsoft Sabina — Mexican Spanish, natural female voice (Windows Edge/Chrome)
- Microsoft Laura — Castilian Spanish fallback (Windows)
- Microsoft Helena — Secondary Castilian fallback (Windows)
- Any
es-*voice — Covers Android TTS, macOS, and Linux systems
window.speechSynthesis.getVoices() returns an empty array on first call (common in Chrome), the code defers selection to the onvoiceschanged event.
Conversation Context Persistence
historialAgente is a state array stored in App.jsx and passed to AgenteVoz as historialInicial. This means:
- Navigating to the map and returning does not reset the conversation
- Opening the agent from the result view button resumes where it left off
- Only a fresh classification (
handleResult) clearshistorialAgenteto[]
POST /chat to stay within the backend’s context window while preserving conversational continuity.
Geolocation
On mount,AgenteVoz calls navigator.geolocation.getCurrentPosition() and stores the coordinates in coordsRef. These are attached to every /chat request so the Python backend can calculate distances to collection points and return location-aware answers like “el Centro Verde más cercano está a 800 m”.
Browser Compatibility
| Feature | Chrome | Edge | Firefox | Safari |
|---|---|---|---|---|
SpeechRecognition | ✅ | ✅ | ❌ | ⚠️ Partial |
SpeechSynthesis | ✅ | ✅ | ✅ | ✅ |