import { Agent } from '@mastra/core';
import { openai } from '@mastra/openai';
const agent = new Agent({
name: 'voice-assistant',
instructions: 'You are a helpful voice assistant.',
model: openai.gpt4o(),
});
export async function handleVoiceRequest(
audioBlob: Blob,
settings: VoiceSettings,
context: string
) {
// 1. Transcribe audio
const transcription = await openai.audio.transcriptions.create({
file: audioBlob,
model: 'whisper-1',
language: settings.language?.split('-')[0] || 'en',
});
// 2. Add context to the conversation
const contextData = JSON.parse(context);
const systemMessage = `Additional context: ${JSON.stringify(contextData)}`;
// 3. Generate response with agent
const response = await agent.generate([
{ role: 'system', content: systemMessage },
{ role: 'user', content: transcription.text },
]);
// 4. Convert to speech
const speech = await openai.audio.speech.create({
model: 'tts-1',
voice: settings.voiceId || 'alloy',
input: response.text,
speed: settings.rate || 1.0,
});
return {
transcription: transcription.text,
text: response.text,
audioData: await speech.arrayBuffer(),
audioFormat: 'mp3',
};
}
// Example Mastra route setup
// If you configured voiceRoute: '/chat/voice-execute' in Cedar-OS,
// your Mastra backend should handle POST requests to this route:
app.post(
'/chat/voice-execute',
upload.fields([
{ name: 'audio', maxCount: 1 },
{ name: 'settings', maxCount: 1 },
{ name: 'context', maxCount: 1 },
]),
async (req, res) => {
const audioFile = req.files.audio[0];
const settings = JSON.parse(req.body.settings);
const context = req.body.context;
const result = await handleVoiceRequest(
new Blob([audioFile.buffer]),
settings,
context
);
// Return the structured response
res.json(result);
}
);