Attach call recording + transcript to the Odoo lead (Phase 3 item)

odoo_client.attach_call_artifacts posts the transcript to the lead's chatter
(readable in place) and attaches transcript_<sid>.txt + the stereo call WAV.
bot.py wires it post-call: extract_and_record now returns the Odoo ref
(persisted_to), the in-call tool path stamps it too, the audiobuffer handler
records the saved WAV path, and the attach runs in a thread after the lead
lands (brief wait for the async WAV write; failures only log — the lead is
already safe). Verified e2e against db1: create -> attach -> verify -> delete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tocmo0nlord
2026-07-04 17:03:00 +00:00
parent 1e7b7844a4
commit bbfff482a3
4 changed files with 96 additions and 3 deletions

View File

@@ -42,6 +42,20 @@ _EXTRACT_INSTRUCTIONS = (
)
def format_transcript(messages, agent_name="AVA") -> str:
"""Plain-text transcript of the call (Caller/agent turns) for chatter/attachments."""
lines = []
for m in messages:
if m.get("role") not in ("user", "assistant"):
continue
content = m.get("content")
if not isinstance(content, str) or not content.strip():
continue
who = "Caller" if m["role"] == "user" else agent_name
lines.append(f"{who}: {content.strip()}")
return "\n".join(lines)
async def extract_and_record(messages, ollama_url, model, call_sid=None, caller_number=None):
"""Extract an appointment from the transcript and persist it. Returns the record
dict if one was saved, else None."""
@@ -136,6 +150,7 @@ async def extract_and_record(messages, ollama_url, model, call_sid=None, caller_
"source": "post_call_extraction",
}
where = persist_appointment(record)
record["persisted_to"] = where # "odoo:<model>:<id>" | "jsonl" — used to attach artifacts
logger.info(
f"Post-call {kind} saved ({where}): {record['patient_name']} / "
f"{record['location']} / reason={record['reason']} / ins={record['insurance']} / "