feat(phase-04): Wyoming Satellite integration + OpenClaw HA components

## Voice Pipeline (P3)
- Replace openWakeWord daemon with Wyoming Satellite approach
- Add Wyoming Satellite service on port 10700 for HA voice pipeline
- Update setup.sh with cross-platform sed compatibility (macOS/Linux)
- Add version field to Kokoro TTS voice info
- Update launchd service loader to use Wyoming Satellite

## Home Assistant Integration (P4)
- Add custom conversation agent component (openclaw_conversation)
  - Fix: Use IntentResponse instead of plain strings (HA API requirement)
  - Support both HTTP API and CLI fallback modes
  - Config flow for easy HA UI setup
- Add OpenClaw bridge scripts (Python + Bash)
- Add ha-ctl utility for HA entity control
  - Fix: Use context manager for token file reading
- Add HA configuration examples and documentation

## Infrastructure
- Add mem0 backup automation (launchd + script)
- Add n8n workflow templates (morning briefing, notification router)
- Add VS Code workspace configuration
- Reorganize model files into categorized folders:
  - lmstudio-community/
  - mlx-community/
  - bartowski/
  - mradermacher/

## Documentation
- Update PROJECT_PLAN.md with Wyoming Satellite architecture
- Update TODO.md with completed Wyoming integration tasks
- Add OPENCLAW_INTEGRATION.md for HA setup guide

## Testing
- Verified Wyoming services running (STT:10300, TTS:10301, Satellite:10700)
- Verified OpenClaw CLI accessibility
- Confirmed cross-platform compatibility fixes
This commit is contained in:
Aodhan Collins
2026-03-08 02:06:37 +00:00
parent 9eb5633115
commit 6a0bae2a0b
119 changed files with 780808 additions and 64 deletions

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.homeai.wyoming-satellite</string>
<key>ProgramArguments</key>
<array>
<string>/Users/aodhan/homeai-voice-env/bin/python3</string>
<string>-m</string>
<string>wyoming_satellite</string>
<string>--uri</string>
<string>tcp://0.0.0.0:10700</string>
<string>--name</string>
<string>Mac Mini Living Room</string>
<string>--area</string>
<string>Living Room</string>
<string>--mic-command</string>
<string>rec -q -r 16000 -c 1 -b 16 -t raw -</string>
<string>--snd-command</string>
<string>play -q -r 24000 -c 1 -b 16 -t raw -</string>
<string>--mic-command-rate</string>
<string>16000</string>
<string>--mic-command-width</string>
<string>2</string>
<string>--mic-command-channels</string>
<string>1</string>
<string>--snd-command-rate</string>
<string>24000</string>
<string>--snd-command-width</string>
<string>2</string>
<string>--snd-command-channels</string>
<string>1</string>
<string>--awake-wav</string>
<string>/System/Library/Sounds/Glass.aiff</string>
<string>--done-wav</string>
<string>/System/Library/Sounds/Blow.aiff</string>
<string>--no-zeroconf</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/homeai-wyoming-satellite.log</string>
<key>StandardErrorPath</key>
<string>/tmp/homeai-wyoming-satellite-error.log</string>
<key>ThrottleInterval</key>
<integer>10</integer>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>

View File

@@ -9,7 +9,8 @@ LAUNCH_AGENTS=~/Library/LaunchAgents
PLISTS=(
com.homeai.wyoming-stt.plist
com.homeai.wyoming-tts.plist
com.homeai.wakeword.plist
com.homeai.wyoming-satellite.plist
# com.homeai.wakeword.plist # Disabled - wake word handled by Wyoming satellite + HA
)
for plist in "${PLISTS[@]}"; do

View File

@@ -6,15 +6,14 @@
# - wyoming-faster-whisper — Wyoming STT adapter (port 10300)
# - Kokoro TTS — fast text-to-speech via ONNX
# - wyoming-kokoro — Wyoming TTS adapter (port 10301)
# - Chatterbox TTS — voice cloning (MPS / CUDA)
# - wyoming-satellite — Home Assistant voice satellite (port 10700)
# - openWakeWord — always-on wake word detection
#
# Prerequisites:
# - P1 (homeai-infra) completed — Home Assistant running
# - P2 (homeai-llm) completed — Ollama running
# - Python 3.10+ installed
# - macOS: Xcode Command Line Tools (for whisper.cpp compilation)
# - Linux: build-essential, cmake
# - macOS: Xcode Command Line Tools, SoX audio toolkit
set -euo pipefail
@@ -35,59 +34,156 @@ if ! curl -sf http://localhost:8123 -o /dev/null 2>/dev/null; then
prereq_ok=false
fi
if ! curl -sf http://localhost:11434 -o /dev/null 2>/dev/null; then
log_warn "Ollama (P2) not reachable at :11434"
prereq_ok=false
fi
if ! command_exists python3; then
log_warn "python3 not found — required for STT/TTS adapters"
prereq_ok=false
fi
if [[ "$prereq_ok" == "false" ]]; then
log_warn "Prerequisites not met. Complete P1 and P2 first."
if ! command_exists brew && [[ "$PLATFORM" == "macos" ]]; then
log_warn "Homebrew not found — required for SoX installation"
prereq_ok=false
fi
# ─── TODO: Implementation ──────────────────────────────────────────────────────
cat <<'EOF'
if [[ "$prereq_ok" == "false" ]]; then
log_warn "Some prerequisites not met. Continuing anyway..."
fi
# ─── Install SoX (audio toolkit) ───────────────────────────────────────────────
log_info "Installing SoX audio toolkit..."
if [[ "$PLATFORM" == "macos" ]]; then
if ! command_exists rec || ! command_exists play; then
brew install sox
log_ok "SoX installed"
else
log_ok "SoX already installed"
fi
else
log_warn "Please install SoX manually on Linux: apt-get install sox libsox-fmt-all"
fi
# ─── Create Python virtual environment ─────────────────────────────────────────
VENV_DIR="$HOME/homeai-voice-env"
log_info "Setting up Python environment at $VENV_DIR..."
if [[ ! -d "$VENV_DIR" ]]; then
python3 -m venv "$VENV_DIR"
log_ok "Created virtual environment"
fi
source "$VENV_DIR/bin/activate"
# ─── Install Python packages ───────────────────────────────────────────────────
log_info "Installing Python packages..."
pip install --upgrade pip
# Core Wyoming packages
pip install wyoming>=1.8.0
pip install wyoming-faster-whisper
# Wyoming satellite (note: has strict dependency on wyoming 1.4.1 but works with 1.8+)
pip install wyoming-satellite
# TTS
pip install kokoro-onnx
# Wake word
pip install openwakeword pyaudio
log_ok "Python packages installed"
# ─── Create model directories ──────────────────────────────────────────────────
log_info "Creating model directories..."
mkdir -p "$HOME/models/whisper"
mkdir -p "$HOME/models/kokoro"
mkdir -p "$HOME/models/openwakeword"
# ─── Download models ───────────────────────────────────────────────────────────
log_info "Downloading models..."
# Kokoro TTS model
if [[ ! -f "$HOME/models/kokoro/kokoro-v1.0.onnx" ]]; then
log_info "Downloading Kokoro TTS model..."
curl -L -o "$HOME/models/kokoro/kokoro-v1.0.onnx" \
"https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files/kokoro-v1.0.onnx" || \
log_warn "Failed to download Kokoro model"
fi
if [[ ! -f "$HOME/models/kokoro/voices-v1.0.bin" ]]; then
curl -L -o "$HOME/models/kokoro/voices-v1.0.bin" \
"https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files/voices-v1.0.bin" || \
log_warn "Failed to download Kokoro voices"
fi
log_ok "Models downloaded (or already present)"
# ─── Install launchd services ──────────────────────────────────────────────────
log_info "Installing launchd services..."
LAUNCHD_DIR="$SCRIPT_DIR/scripts/launchd"
LAUNCH_AGENTS="$HOME/Library/LaunchAgents"
mkdir -p "$LAUNCH_AGENTS"
# Fix wyoming-satellite entry point if needed
SATELLITE_BIN="$VENV_DIR/bin/wyoming-satellite"
if [[ -f "$SATELLITE_BIN" ]] && grep -q "__main__.run()" "$SATELLITE_BIN"; then
log_info "Fixing wyoming-satellite entry point..."
# Cross-platform sed (macOS vs Linux)
if [[ "$PLATFORM" == "macos" ]]; then
sed -i '' 's/sys.exit(__main__.run())/import asyncio; asyncio.run(__main__.main())/' "$SATELLITE_BIN"
else
sed -i 's/sys.exit(__main__.run())/import asyncio; asyncio.run(__main__.main())/' "$SATELLITE_BIN"
fi
fi
# Copy plists
for plist in com.homeai.wyoming-stt.plist com.homeai.wyoming-tts.plist \
com.homeai.wakeword.plist com.homeai.wyoming-satellite.plist; do
src="$LAUNCHD_DIR/$plist"
dst="$LAUNCH_AGENTS/$plist"
if [[ -f "$src" ]]; then
cp "$src" "$dst"
log_ok "Installed: $plist"
else
log_warn "Missing: $plist"
fi
done
# ─── Summary ───────────────────────────────────────────────────────────────────
cat <<EOF
┌─────────────────────────────────────────────────────────────────┐
│ P3: homeai-voice — NOT YET IMPLEMENTED
│ P3: homeai-voice — Setup Complete
│ │
Implementation steps (see homeai-voice/PLAN.md):
Services configured:
│ • Wyoming STT → tcp://localhost:10300 (Whisper) │
│ • Wyoming TTS → tcp://localhost:10301 (Kokoro) │
│ • Wake Word Daemon → HTTP on :8080/wake (openWakeWord) │
│ • Wyoming Satellite→ tcp://localhost:10700 (HA satellite) │
│ │
1. whisper/install.sh
- Clone + compile whisper.cpp (Metal/CUDA flags)
- Download models: large-v3, medium.en
│ - Install wyoming-faster-whisper Python package │
Next steps:
1. Download Whisper models:
wyoming-faster-whisper --download-dir ~/models/whisper
│ │
│ 2. tts/install-kokoro.sh
- pip install kokoro-onnx
│ - Install wyoming-kokoro adapter │
2. Load services:
./homeai-voice/scripts/load-all-launchd.sh
│ │
│ 3. tts/install-chatterbox.sh
- pip install chatterbox-tts
- Verify MPS (macOS) or CUDA (Linux) acceleration
3. Configure Home Assistant:
Settings → Integrations → Add Wyoming Protocol
- STT: 10.0.0.199:10300
│ - TTS: 10.0.0.199:10301 │
│ - Satellite: 10.0.0.199:10700 │
│ │
│ 4. wyoming/install.sh
│ - Install wyoming-openwakeword │
│ - Configure wake word: hey_jarvis │
│ │
│ 5. scripts/launchd/ or systemd/ │
│ - wyoming-stt (port 10300) │
│ - wyoming-tts (port 10301) │
│ - wakeword daemon │
│ │
│ 6. wyoming/test-pipeline.sh │
│ - End-to-end smoke test │
4. Create voice assistant pipeline in HA
│ │
│ Interface contracts: │
│ WYOMING_STT_URL=tcp://localhost:10300 │
│ WYOMING_TTS_URL=tcp://localhost:10301 │
│ WYOMING_SATELLITE_URL=tcp://localhost:10700 │
└─────────────────────────────────────────────────────────────────┘
EOF
log_info "P3 is not yet implemented. See homeai-voice/PLAN.md for details."
exit 0
log_ok "P3 setup complete!"

View File

@@ -63,6 +63,7 @@ class KokoroEventHandler(AsyncEventHandler):
attribution=Attribution(name="kokoro", url=""),
installed=True,
languages=["en-us"],
version="1.0",
speakers=[TtsVoiceSpeaker(name=self._default_voice)],
)
],