fix(voice-agent): preserve live call status on transcript/conversation events

upsert_call overwrote status with excluded.status and defaulted to
'unknown', so transcript and conversation-update events (which pass no
status) reset an in-progress call to 'unknown' in the dashboard. Preserve
the prior status when the caller omits one, matching the existing
COALESCE handling for summary/customer_number. Adds a regression test.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
MervinPraisonandClaude Opus 4.8 committed 2026-09-07 19:21:10 +00:00
1 parent b5b640a2b7
commit bfb1eeee06
2 files changed
+37 -3

No files matched your search

@@ -84,7 +84,7 @@ class VoiceCallStore:
def upsert_call(
call_id: str,
*,
status: str = "unknown",
status: str | None = None,
customer_number: str | None = None,
transcript: str | None = None,
summary: str | None = None,
@@ -93,13 +93,17 @@ class VoiceCallStore:
now = datetime.now(timezone.utc).isoformat()
with closing(_connect()) as conn, conn:
row = conn.execute(
"SELECT transcript, summary, metadata_json, customer_number FROM voice_calls WHERE call_id = ?",
"SELECT transcript, summary, metadata_json, customer_number, status FROM voice_calls WHERE call_id = ?",
(call_id,),
).fetchone()
existing_transcript = row[0] if row else ""
existing_summary = row[1] if row else ""
existing_meta = json.loads(row[2]) if row and row[2] else {}
existing_number = row[3] if row else None
existing_status = row[4] if row else None
# Preserve prior status when the caller doesn't supply one (e.g. transcript
# / conversation-update events) so partial updates don't clobber live state.
final_status = status if status is not None else (existing_status or "unknown")
merged_meta = {**existing_meta, **(metadata or {})}
conn.execute(
"""
@@ -116,7 +120,7 @@ class VoiceCallStore:
""",
(
call_id,
status,
final_status,
customer_number or existing_number,
transcript if transcript is not None else existing_transcript,
summary if summary is not None else existing_summary,
+30
View File
@@ -122,6 +122,36 @@ def test_transcript_appends_final_lines():
assert "user: I need the time" in record["transcript"]
def test_transcript_preserves_live_status():
"""A transcript/conversation event must not reset an in-progress call to 'unknown'."""
with _voice_modules() as imp:
processor = imp("integrations.voice.processor")
config = imp("integrations.voice.config")
store = imp("integrations.voice.store")
settings = config.load_voice_settings()
processor.process_voice_webhook(
"status-update",
{"message": {"type": "status-update", "call": {"id": "call-s1"}, "status": "in-progress"}},
settings=settings,
)
processor.process_voice_webhook(
"transcript",
{
"message": {
"type": "transcript",
"call": {"id": "call-s1"},
"role": "user",
"transcriptType": "final",
"transcript": "hello there",
}
},
settings=settings,
)
record = store.VoiceCallStore.get_call("call-s1")
assert record["status"] == "in-progress"
assert "user: hello there" in record["transcript"]
def test_verify_secret_header():
with _voice_modules() as imp:
verify = imp("integrations.voice.verify")