fix: respond to request_contact immediately, send confirmation as text
All checks were successful
Build & Push / build-and-push (push) Successful in 1m43s
All checks were successful
Build & Push / build-and-push (push) Successful in 1m43s
The deferred tool response approach caused Gemini to timeout waiting. Now request_contact responds immediately (telling the agent to wait), and the confirm button sends a text message through the live WebSocket to trigger complete_brief. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -149,7 +149,6 @@ export default function VoiceAgentProvider({ locale, children }: VoiceAgentProvi
|
||||
const turnCompleteRef = useRef(true);
|
||||
const briefSubmittedRef = useRef(false);
|
||||
const pendingContactRef = useRef<PendingContact | null>(null);
|
||||
const pendingContactCallIdRef = useRef('');
|
||||
const reconnectTranscriptRef = useRef<TranscriptEntry[]>([]);
|
||||
const statusRef = useRef<ConnectionStatus>('idle');
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
@@ -217,9 +216,9 @@ export default function VoiceAgentProvider({ locale, children }: VoiceAgentProvi
|
||||
const contact = { name: contactName, email: contactEmail };
|
||||
setPendingContact(contact);
|
||||
pendingContactRef.current = contact;
|
||||
pendingContactCallIdRef.current = callId;
|
||||
// Don't return a tool response yet — wait for user confirmation via confirmContact()
|
||||
return '__DEFERRED__';
|
||||
// Respond immediately so Gemini doesn't timeout waiting for a tool response.
|
||||
// The agent is told to wait — user confirmation comes as a text message via confirmContact().
|
||||
return JSON.stringify({ success: true, message: 'Contact card is now shown on screen. Wait for the user to review and confirm before calling complete_brief. Do not proceed until you hear confirmation.' });
|
||||
}
|
||||
|
||||
if (name === 'complete_brief') {
|
||||
@@ -293,7 +292,6 @@ export default function VoiceAgentProvider({ locale, children }: VoiceAgentProvi
|
||||
setSelections({});
|
||||
setPendingContact(null);
|
||||
pendingContactRef.current = null;
|
||||
pendingContactCallIdRef.current = '';
|
||||
}
|
||||
setCompletedBrief(null);
|
||||
setCompletedFormData(null);
|
||||
@@ -463,13 +461,9 @@ export default function VoiceAgentProvider({ locale, children }: VoiceAgentProvi
|
||||
const responses = [];
|
||||
for (const call of calls) {
|
||||
const result = await handleToolCall(call.name, call.args ?? {}, call.id);
|
||||
if (result !== '__DEFERRED__') {
|
||||
responses.push({ id: call.id, name: call.name, response: { result } });
|
||||
}
|
||||
}
|
||||
if (responses.length > 0) {
|
||||
ws.send(JSON.stringify({ toolResponse: { functionResponses: responses } }));
|
||||
responses.push({ id: call.id, name: call.name, response: { result } });
|
||||
}
|
||||
ws.send(JSON.stringify({ toolResponse: { functionResponses: responses } }));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -543,7 +537,6 @@ export default function VoiceAgentProvider({ locale, children }: VoiceAgentProvi
|
||||
setAgentAmplitude(0);
|
||||
setCanReconnect(false);
|
||||
reconnectTranscriptRef.current = [];
|
||||
pendingContactCallIdRef.current = '';
|
||||
setStatus('idle');
|
||||
}, []);
|
||||
|
||||
@@ -558,19 +551,18 @@ export default function VoiceAgentProvider({ locale, children }: VoiceAgentProvi
|
||||
|
||||
const confirmContact = useCallback(() => {
|
||||
if (!pendingContactRef.current) return;
|
||||
// Send confirmation back through WebSocket so the agent knows
|
||||
// Send a text message to let the agent know the user confirmed their details
|
||||
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
||||
const { name, email } = pendingContactRef.current;
|
||||
wsRef.current.send(JSON.stringify({
|
||||
toolResponse: {
|
||||
functionResponses: [{
|
||||
id: pendingContactCallIdRef.current,
|
||||
name: 'request_contact',
|
||||
response: { result: JSON.stringify({ confirmed: true, name: pendingContactRef.current.name, email: pendingContactRef.current.email }) },
|
||||
}],
|
||||
realtimeInput: {
|
||||
text: `The user has confirmed their contact details on screen. Name: ${name}, Email: ${email}. You may now call complete_brief.`,
|
||||
},
|
||||
}));
|
||||
console.log('[VoiceAgent] Contact confirmed, notified agent');
|
||||
} else {
|
||||
console.warn('[VoiceAgent] Cannot confirm contact — WebSocket not open');
|
||||
}
|
||||
pendingContactCallIdRef.current = '';
|
||||
}, []);
|
||||
|
||||
const reconnect = useCallback(async () => {
|
||||
|
||||
Reference in New Issue
Block a user