Fix Vapi webhook - add toolCallId to response

This commit is contained in:
root
2026-02-24 12:09:39 +00:00
parent 247eeb9597
commit 19c4187897
+54 -12
View File
@@ -8,6 +8,13 @@ interface VapiMessage {
type: string; type: string;
role?: string; role?: string;
transcript?: string; transcript?: string;
toolCallList?: Array<{
id: string;
function: {
name: string;
arguments: string;
};
}>;
} }
interface VapiCall { interface VapiCall {
@@ -22,27 +29,55 @@ interface VapiWebhookPayload {
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const body = (await request.json()) as VapiWebhookPayload; const body = (await request.json()) as VapiWebhookPayload;
// Extract transcript from Vapi's format
const message = body.message; const message = body.message;
// Only process final transcripts // Handle tool calls from Vapi
if (!message || message.type !== "transcript" || !message.transcript) { if (message.toolCallList && message.toolCallList.length > 0) {
// Return empty response for non-transcript messages const toolCall = message.toolCallList[0];
return NextResponse.json({ results: [] }); const toolCallId = toolCall.id;
// Get the arguments from the tool call
let args = {};
try {
args = JSON.parse(toolCall.function.arguments || '{}');
} catch (e) {
// If arguments is a string, use it directly
args = { query: toolCall.function.arguments };
} }
const transcript = message.transcript; // Process the voice request
const transcript = args.query || '';
// Call MiniMax brain
const response = await runSiteMenteVoiceTurn({ const response = await runSiteMenteVoiceTurn({
transcript: transcript, transcript: transcript,
}); });
// Return in Vapi's expected format // Return EXACT Vapi format with toolCallId
return NextResponse.json({ return NextResponse.json({
results: [ results: [
{ {
toolCallId: toolCallId,
result: response.reply,
},
],
});
}
// Handle regular transcripts
if (!message || message.type !== "transcript" || !message.transcript) {
return NextResponse.json({ results: [] });
}
const transcript = message.transcript;
const response = await runSiteMenteVoiceTurn({
transcript: transcript,
});
// Return in Vapi's expected format - but we need a toolCallId
// For transcripts without tool calls, we generate one
return NextResponse.json({
results: [
{
toolCallId: `call_${Date.now()}`,
result: response.reply, result: response.reply,
}, },
], ],
@@ -51,8 +86,15 @@ export async function POST(request: Request) {
} catch (error) { } catch (error) {
console.error("[SiteMente][Vapi] Voice route failed", error); console.error("[SiteMente][Vapi] Voice route failed", error);
return NextResponse.json( return NextResponse.json(
{ error: "Failed to generate voice response." }, {
{ status: 500 } results: [
{
toolCallId: `call_${Date.now()}`,
result: "Lo siento, tuve un problema. ¿Puedes repetir?"
}
]
},
{ status: 200 }
); );
} }
} }