Fix voice portal: WebSocket routing, Caddy keepalive, audio pipeline
- Fix app.py: @app.get -> @app.websocket for /ws/voice route (was returning 403) - Fix app.py: create static_dir before mounting it (AttributeError on startup) - Fix voice.html: AudioWorkletNode constructor (was AudioWorkletProcessor) - Fix voice.html: use ScriptProcessor directly (more reliable) - Fix voice.html: send Float32 directly (server expects float32, was sending Int16) - Fix voice.html: auto-detect ws/wss protocol from page URL - Add Caddy reverse proxy keepalive pings every 15s to prevent timeout - Add detailed message type logging in WebSocket receive loop - Strip Jarvis/Sage personas, rename bot to MoltMic - Add /moltmic voice slash command for portal URL - Update portal URL to https://voice.jezzahehn.com
This commit is contained in:
parent
bc580861dd
commit
3450e57ca6
6 changed files with 122 additions and 41 deletions
|
|
@ -1,18 +1,18 @@
|
|||
"""Jarvis Voice Bot - Discord Integration"""
|
||||
"""MoltMic - OpenClaw Voice Bot"""
|
||||
|
||||
from .bot import JarvisVoiceBot, create_bot, run_bot
|
||||
from .bot import MoltMicBot, create_bot, run_bot
|
||||
from .voice_session import VoiceSession, VoiceSessionManager
|
||||
from .audio_bridge import AudioBridge, PipelineAudioSource
|
||||
from .commands import VoiceBotCommands, setup_commands
|
||||
from .commands import MoltMicCommands, setup_commands
|
||||
|
||||
__all__ = [
|
||||
"JarvisVoiceBot",
|
||||
"MoltMicBot",
|
||||
"create_bot",
|
||||
"run_bot",
|
||||
"VoiceSession",
|
||||
"VoiceSessionManager",
|
||||
"AudioBridge",
|
||||
"PipelineAudioSource",
|
||||
"VoiceBotCommands",
|
||||
"MoltMicCommands",
|
||||
"setup_commands",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ from .vad_receiver import VADAudioReceiver
|
|||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class JarvisVoiceBot(discord.Client):
|
||||
"""Discord bot for voice interaction with AI agents."""
|
||||
class MoltMicBot(discord.Client):
|
||||
"""MoltMic - Discord voice bot for OpenClaw."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
|
@ -479,7 +479,7 @@ async def create_bot(
|
|||
stt_transcriber=None,
|
||||
orchestrator=None,
|
||||
audio_output_callbacks=None,
|
||||
) -> JarvisVoiceBot:
|
||||
) -> MoltMicBot:
|
||||
"""
|
||||
Create and initialize the Discord bot.
|
||||
|
||||
|
|
@ -494,7 +494,7 @@ async def create_bot(
|
|||
Returns:
|
||||
Initialized bot instance
|
||||
"""
|
||||
bot = JarvisVoiceBot(
|
||||
bot = MoltMicBot(
|
||||
config=config,
|
||||
openclaw_config=openclaw_config,
|
||||
tts_synthesizer=tts_synthesizer,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,43 @@ class MoltMicCommands(app_commands.Group):
|
|||
logger.exception(f"Status error: {e}")
|
||||
await interaction.followup.send("❌ Error.", ephemeral=True)
|
||||
|
||||
@app_commands.command(name="voice", description="Open voice portal in browser")
|
||||
async def voice(self, interaction: discord.Interaction):
|
||||
"""Generate a voice portal URL for browser-based speech."""
|
||||
await interaction.response.defer(thinking=True)
|
||||
|
||||
try:
|
||||
# Import here to avoid circular dependency
|
||||
from server.voice_ws import create_session_id
|
||||
|
||||
session_id = create_session_id()
|
||||
portal_url = f"https://voice.jezzahehn.com/voice?session={session_id}"
|
||||
|
||||
embed = discord.Embed(
|
||||
title="🎙️ Voice Portal",
|
||||
description="Click below to open the voice portal in your browser",
|
||||
color=discord.Color.blue()
|
||||
)
|
||||
embed.add_field(
|
||||
name="Portal URL",
|
||||
value=f"[Open Voice Portal]({portal_url})",
|
||||
inline=False
|
||||
)
|
||||
embed.add_field(
|
||||
name="Instructions",
|
||||
value="1. Click the link above\n2. Allow microphone access\n3. Start talking! The bot will listen and respond.",
|
||||
inline=False
|
||||
)
|
||||
embed.set_footer(text="The bot will start listening when you connect")
|
||||
|
||||
await interaction.followup.send(embed=embed)
|
||||
|
||||
logger.info(f"Voice portal created for session {session_id}")
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"Voice portal error: {e}")
|
||||
await interaction.followup.send("❌ Failed to create voice portal.", ephemeral=True)
|
||||
|
||||
|
||||
async def setup_commands(bot):
|
||||
"""Register slash commands."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue