Commit Graph

122 Commits

Author SHA1 Message Date
Christian Gick
b65d04389b fix: Switch E2EE to per-participant keys instead of shared key
Element Call uses per-participant keys, not shared key mode.
Bot now generates its own key, publishes it, and sets both
keys via key_provider.set_key() after connecting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 06:41:20 +02:00
Christian Gick
ced2783a09 fix: Enable E2EE with caller's key as shared key
Element Call now rejects unencrypted audio. Use caller's key
as shared_key so both sides encrypt/decrypt with the same key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:51:43 +02:00
Christian Gick
4a93827de3 revert: Restore voice.py and bot.py to last known working state (9aef846)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:47:51 +02:00
Christian Gick
463286a61e revert: Disable E2EE at LiveKit level — shared key incompatible with Element Call
Element Call uses per-participant keys, LiveKit Python SDK shared key mode
cannot properly decrypt. Reverting to working state (no LiveKit E2EE).
Bot still publishes keys so Element Call shows encryption indicator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:44:32 +02:00
Christian Gick
2d8a7b4420 fix: Use same shared key for both directions (caller key reuse)
Both bot and caller must use the same key in shared key mode.
Bot now reuses caller's key and publishes it back, instead of
generating a separate bot key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:41:23 +02:00
Christian Gick
2fa13c4958 fix: Use caller key as shared_key at connect time for immediate decryption
Per-participant set_key alone with empty shared_key caused silent incoming audio.
Now connects with caller key as shared_key, then overlays per-participant keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:35:55 +02:00
Christian Gick
5f3e733ba5 feat: Voice prompt with model transparency, datetime, auto language
- Bot tells which model it uses when asked
- Injects current UTC datetime into prompt
- Responds in users language instead of always German

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:28:13 +02:00
Christian Gick
939324ca76 chore: Switch voice to George (warm, captivating)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 20:20:27 +02:00
Christian Gick
e3ede3fc2c fix: Voice bot identifies as Agiliton Assistant, not Claude
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:40:24 +02:00
Christian Gick
533847c952 fix: Switch E2EE from shared key to per-participant key mode
Element Call uses per-participant keys via MatrixKeyProvider.onSetEncryptionKey(),
not shared key mode. This was causing silence with E2EE enabled.

- Set bot's own key and caller's key separately via e2ee_manager.key_provider.set_key()
- Live-update caller key when received after connect
- Fallback to set_shared_key if per-participant API unavailable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:50:19 +02:00
Christian Gick
9aef846619 fix: disable E2EE to get working voice pipeline, E2EE fix deferred
Audio pipeline confirmed working without E2EE. E2EE key derivation
mismatch with Element Call needs separate investigation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:30:11 +02:00
Christian Gick
67f4b8159e fix: match Element Call HKDF params (ratchetWindowSize=10, keyringSize=256)
Re-enable E2EE with corrected parameters matching Element Call defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:22:54 +02:00
Christian Gick
96183a8ccd test: temporarily disable E2EE to isolate audio pipeline issue
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:38:57 +02:00
Christian Gick
1bc044eaae fix: republish caller E2EE key as shared key, fallback to no-E2EE
Bot now publishes the same key as the caller so both sides can decrypt.
Falls back to no-encryption if no caller key received.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:35:31 +02:00
Christian Gick
08f4e115b9 fix: filter own key events, fix RoomOptions None, wait for participant
- Skip bot own encryption_keys events in on_unknown handler
- Always pass valid RoomOptions to AgentSession.start()
- Wait up to 10s for remote participant to connect before starting pipeline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:33:12 +02:00
Christian Gick
6e1e9839cc fix: use timeline events for E2EE key exchange (not state events)
Element Call distributes encryption keys as timeline events, not room
state events. Changed bot to publish keys via room_send and fetch from
/messages endpoint instead of /state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:28:56 +02:00
Christian Gick
4e1e372ca2 fix: use caller's E2EE key (not own), fetch via HTTP API
All participants must use the SAME shared key. Bot was generating
its own key which couldn't decrypt user's audio. Now:
1. Fetch caller's key from room state via HTTP API
2. Fall back to waiting for key via sync handler
3. Publish the SAME key back (not a new one)
4. Only connect with E2EE if key available

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:17:33 +02:00
Christian Gick
753d6543d4 fix: generate and publish E2EE key, always connect with encryption
Element Call encrypts media by default. Bot must:
1. Generate its own 32-byte E2EE key
2. Publish it to room state (io.element.call.encryption_keys)
3. Connect to LiveKit with HKDF E2EE enabled
4. Use caller's key when received, own key as fallback

This fixes: Nicht verschlüsselt warning, silent audio (encrypted
frames couldn't be decoded by VAD/STT)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:06:34 +02:00
Christian Gick
74758a3f13 debug: enable livekit.agents debug logging for STT/VAD diagnosis
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:02:24 +02:00
Christian Gick
75970fc06b fix: link AgentSession to remote participant + debug speech events
- Pass participant_identity via RoomOptions so AgentSession knows
  which audio track to consume (was silently ignoring user audio)
- Add USER_SPEECH and AGENT_SPEECH event handlers for debugging
- Simplify greeting to exact text to prevent hallucination
- Use httpx for room state scan (nio API was unreliable)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:03:24 +02:00
Christian Gick
85df4b295f fix: E2EE key timing + verbose logging + shorter greeting
- Reorder: send call member event BEFORE creating VoiceSession
- Store VoiceSession BEFORE start so sync handler can forward keys
- Increase E2EE key wait from 3s to 10s
- Add INFO-level logging for key lookup + room state scan via HTTP API
- Tighten voice system prompt to prevent long rambling greetings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:55:52 +02:00
Christian Gick
e5e8b56482 fix(e2ee): Add E2EE HKDF to voice.py, bot uses patched Dockerfile
voice.py runs in bot container, not agent container.
- Wait 3s for encryption key before connecting
- Build E2EE options with HKDF when key received
- Bot container now uses patched Dockerfile (needs FFI)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 17:13:53 +02:00