"""Voice synthesis tool: text-to-speech via ElevenLabs through Puter.js.
Delegates synthesis to :func:`bot.voice.router.synthesize`, which routes
through the Puter.js/ElevenLabs shim and returns a path to a generated
audio file.
"""
import traceback
[docs]
def define():
"""Return the tool definition (name, description, JSON parameters).
Returns:
dict: Tool metadata consumed by the tool registry.
"""
return {
"name": "voice_clone",
"description": "Synthesizes voice from text using ElevenLabs via Puter.js. Returns the path to the WAV file generated.",
"parameters": {
"type": "OBJECT",
"properties": {
"voice_name": {
"type": "STRING",
"description": "ElevenLabs Voice ID or Name mapped in the Puter shim.",
},
"text": {"type": "STRING", "description": "Text to speak"},
},
"required": ["voice_name", "text"],
},
}
[docs]
async def execute(kwargs, context):
"""Synthesize speech and, when possible, post the audio to the channel.
Calls :func:`bot.voice.router.synthesize` with ``voice_name`` and ``text``
from ``kwargs``. If ``context`` carries a ``channel_id`` and a usable
``discord_client``, the resulting file is best-effort sent to that
Discord channel; failures to send are swallowed.
Args:
kwargs (dict): Tool arguments with ``voice_name`` and ``text``.
context (dict): Execution context (may include ``channel_id`` and
``discord_client``).
Returns:
dict: ``{"wav_path": <path>}`` on success, or ``{"error", "traceback"}``
on failure.
"""
try:
from bot.voice.router import synthesize
wav_path = await synthesize(kwargs["voice_name"], kwargs["text"])
try:
channel_id = context.get("channel_id")
if channel_id:
client = context.get("discord_client")
if client:
channel = client.get_channel(int(channel_id))
if channel:
import discord
await channel.send(file=discord.File(wav_path))
except Exception:
pass
return {"wav_path": wav_path}
except Exception as e:
return {"error": str(e), "traceback": traceback.format_exc()}