diff --git a/assistant/src/calls/relay-server.ts b/assistant/src/calls/relay-server.ts index c5c86fb1d39..555ebc7a042 100644 --- a/assistant/src/calls/relay-server.ts +++ b/assistant/src/calls/relay-server.ts @@ -713,7 +713,18 @@ export class RelayConnection { if (this.controller) { await this.controller.handleCallerUtterance(msg.voicePrompt, speaker); } else { - // Fallback if controller not yet initialized + // Fallback if controller not yet initialized — persist the caller's + // transcript so it is available in conversation history once setup + // completes. The session pipeline normally handles persistence, but + // this early-utterance path bypasses it entirely. + if (session) { + conversationStore.addMessage( + session.conversationId, + 'user', + JSON.stringify([{ type: 'text', text: msg.voicePrompt }]), + { userMessageChannel: 'voice', assistantMessageChannel: 'voice' }, + ); + } this.sendTextToken('I\'m still setting up. Please hold.', true); } } diff --git a/assistant/src/calls/voice-session-bridge.ts b/assistant/src/calls/voice-session-bridge.ts index 31c550c21aa..0074fbd7b5d 100644 --- a/assistant/src/calls/voice-session-bridge.ts +++ b/assistant/src/calls/voice-session-bridge.ts @@ -137,11 +137,11 @@ function buildVoiceCallControlPrompt(opts: { if (opts.isInbound) { if (opts.isCallerGuardian) { lines.push( - '10. If the latest user turn is [CALL_OPENING], this is your user calling you. Answer casually and briefly, like picking up a call from someone you know well. For example: "Hey!" or "What\'s up?" Do NOT introduce yourself, do NOT say you are calling on behalf of anyone, and do NOT ask how you can help in a formal way. Keep it short and natural.', + '10. If the latest user turn is "(call connected — deliver opening greeting)", this is your user calling you. Answer casually and briefly, like picking up a call from someone you know well. For example: "Hey!" or "What\'s up?" Do NOT introduce yourself, do NOT say you are calling on behalf of anyone, and do NOT ask how you can help in a formal way. Keep it short and natural.', ); } else { lines.push( - '10. If the latest user turn is [CALL_OPENING], greet the caller warmly and ask how you can help. Vary the wording; do not use a fixed template.', + '10. If the latest user turn is "(call connected — deliver opening greeting)", greet the caller warmly and ask how you can help. Vary the wording; do not use a fixed template.', ); } lines.push( @@ -149,7 +149,7 @@ function buildVoiceCallControlPrompt(opts: { ); } else { lines.push( - '10. If the latest user turn is [CALL_OPENING], generate a natural, context-specific opener: briefly introduce yourself once as an assistant, state why you are calling using the Task context, and ask a short permission/check-in question. Vary the wording; do not use a fixed template.', + '10. If the latest user turn is "(call connected — deliver opening greeting)", generate a natural, context-specific opener: briefly introduce yourself once as an assistant, state why you are calling using the Task context, and ask a short permission/check-in question. Vary the wording; do not use a fixed template.', '11. If the latest user turn includes [CALL_OPENING_ACK], treat it as the callee acknowledging your opener and continue the conversation naturally without re-introducing yourself or repeating the initial check-in question.', ); } @@ -209,7 +209,7 @@ export async function startVoiceTurn(opts: VoiceTurnOptions): Promise