{
  "schema_version": 1,
  "diagram_type": "architecture",
  "meta": {
    "title": "MiniMax Voice — Cloud STT and TTS with Local Fallback",
    "output": "docs/minimax-voice-map.html",
    "quality_profile": "showcase",
    "views": [
      {
        "id": "stt-path",
        "label": "Speech to text",
        "focus": ["esp32", "bridge", "stt_shim", "cloud_stt", "agent"],
        "note": "The command reaches the shim, which sends it to the cloud and returns the transcript."
      },
      {
        "id": "fallback-path",
        "label": "Fallback",
        "focus": ["stt_shim", "cloud_stt", "local_stt", "tts_router", "piper"],
        "note": "Cloud failure drops to the local model, so the house never goes silent."
      },
      {
        "id": "tts-path",
        "label": "Text to speech",
        "focus": ["agent", "tts_router", "snapcast", "speakers"],
        "note": "The reply is routed to MiniMax T2A or piper and played through Snapcast."
      }
    ]
  },
  "components": [
    { "id": "esp32", "type": "external", "label": "ESP32-S3", "sublabel": "wake word + mic", "pos": [40, 320], "size": [140, 64] },
    { "id": "bridge", "type": "backend", "label": "voice_bridge", "sublabel": "OpenWakeWord (local)", "pos": [330, 320], "size": [150, 64], "tag": "buffers command" },
    { "id": "stt_shim", "type": "backend", "label": "voice_stt_shim", "sublabel": "POST /transcribe :5001", "pos": [620, 320], "size": [170, 64], "tag": "fallback chain" },
    { "id": "cloud_stt", "type": "cloud", "label": "Cloud STT", "sublabel": "OpenRouter whisper-1 / MiniMax asr-1.0", "pos": [620, 90], "size": [170, 64] },
    { "id": "local_stt", "type": "backend", "label": "voice_whisper_fallback", "sublabel": "faster-whisper base.en :5002", "pos": [620, 560], "size": [170, 64] },
    { "id": "agent", "type": "backend", "label": "voice-agent (Jervis)", "sublabel": "LLM tool-calling :8501", "pos": [940, 320], "size": [170, 64] },
    { "id": "ha", "type": "external", "label": "Home Assistant", "sublabel": "lights, timers, calendar :8123", "pos": [940, 560], "size": [170, 64] },
    { "id": "tts_router", "type": "backend", "label": "tts_router", "sublabel": "MiniMax T2A v2", "pos": [1260, 320], "size": [160, 64], "tag": "speak_direct.sh" },
    { "id": "piper", "type": "backend", "label": "piper_tts", "sublabel": "local fallback", "pos": [1260, 560], "size": [160, 64] },
    { "id": "snapcast", "type": "backend", "label": "Snapcast", "sublabel": "48 kHz stereo :4953", "pos": [1570, 320], "size": [150, 64] },
    { "id": "speakers", "type": "external", "label": "House speakers", "sublabel": "MainAudio group", "pos": [1870, 320], "size": [150, 64] }
  ],
  "boundaries": [
    { "kind": "region", "label": "POST /transcribe contract preserved", "wraps": ["bridge", "stt_shim", "cloud_stt", "local_stt"], "pad": 26 },
    { "kind": "region", "label": "speak_direct.sh contract preserved", "wraps": ["tts_router", "piper"], "pad": 26 }
  ],
  "connections": [
    { "id": "audio-in", "from": "esp32", "to": "bridge", "label": "MQTT audio" },
    { "id": "transcribe", "from": "bridge", "to": "stt_shim", "label": "POST /transcribe" },
    { "id": "primary", "from": "stt_shim", "to": "cloud_stt", "label": "primary", "labelAt": [705, 220] },
    { "id": "fallback", "from": "stt_shim", "to": "local_stt", "label": "fallback", "labelAt": [705, 470] },
    { "id": "transcript", "from": "stt_shim", "to": "agent", "label": "transcript" },
    { "id": "tools", "from": "agent", "to": "ha", "label": "tool calls", "labelAt": [1025, 470] },
    { "id": "reply", "from": "agent", "to": "tts_router", "label": "speak_direct.sh" },
    { "id": "tts-fallback", "from": "tts_router", "to": "piper", "label": "cloud failure", "labelAt": [1340, 470] },
    { "id": "play", "from": "tts_router", "to": "snapcast", "label": "reply audio" },
    { "id": "hear", "from": "snapcast", "to": "speakers" }
  ]
}
