feat: voice first-class channel + cross-channel guardian notifications#7539
Conversation
Co-authored-by: Claude <noreply@anthropic.com>
…7524) Co-authored-by: Claude <noreply@anthropic.com>
…7529) Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
When a guardian action request is dispatched to telegram/sms/mac channels during a voice call, replies on any of those channels are now intercepted, validated, and used to resume the call: - Channel inbound (telegram/sms): intercept guardian answers early in handleChannelInbound(), with identity verification, single/multi-delivery disambiguation via request codes, and first-writer-wins resolution - Mac thread: intercept in session-process processMessage() before the agent loop, routing the user message as a guardian answer - Guardian dispatch: create mac conversations server-side with getOrCreateConversation() and seed them with the question text - Store: add getPendingDeliveryByConversation() for mac channel routing Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…e settings card (#7536) Add periodic sweep (60s interval) for expired cross-channel guardian action requests. When a request expires: marks request+deliveries as expired, expires pending questions, and sends expiry notices to external channels and mac threads. Allow voice-channel threads to appear in the desktop thread list by updating the session filter in both ThreadSessionRestorer and ThreadManager to pass through sessions with sourceChannel == "voice". Add a Voice (Phone Calls) card to the Settings Connect tab showing Twilio credential and phone number readiness for voice calls. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…-M7 changes (#7538) Reflect the cross-channel guardian architecture in documentation: - SKILL.md: add DTMF callee verification section, update answering questions to describe ASK_GUARDIAN cross-channel dispatch with first-response-wins semantics, note mid-call steering via desktop chat is no longer supported, add accepted regressions section - ARCHITECTURE.md: update outgoing calls intro to describe voice as first-class channel with per-call conversations, replace bridge-based Mermaid diagram flow with guardian dispatch flow, replace call-bridge key component with guardian-dispatch/guardian-action-store/guardian- action-sweep, replace Call Bridge section with Cross-Channel Guardian Consultation, add guardian_action_requests and guardian_action_deliveries SQLite tables, add guardian modules to Channel Guardian Security table Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…K test) Merge main into feature/voice-cross-guardian to resolve two conflicts: - relay-server.ts: integrate CALL_WELCOME_GREETING static greeting skip with DTMF verification (verify first, then check static greeting) - call-orchestrator.test.ts: keep new CALL_OPENING_ACK test from main alongside ASK_GUARDIAN comment rename from feature branch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 17f50c60e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Thanks for the large refactor — I walked through the new voice + guardian flow end-to-end and found a few blocking issues that should be fixed before we rely on this in prod. 1) [P1] Voice-thread transcript/completion data can be dropped when no
|
1. Pass broadcast/assistantId to CallOrchestrator from RelayConnection via
module-level setRelayBroadcast wired in lifecycle.ts, so mac desktop
receives guardian_request_thread_created IPC events and multi-assistant
deployments use the correct assistant ID.
2. Thread bearer token through guardian dispatch deliverToExternalChannel
so gateway /deliver/{channel} calls include Authorization header.
3. Swap resolve/answerCall ordering in channel-routes guardian answer
interception: call answerCall first, resolve only on success, so
failed answers leave the request pending for retry.
4. Use content block array format for addMessage calls in
guardian-dispatch.ts and guardian-action-sweep.ts to match codebase
convention (JSON.stringify([{type:'text',text:'...'}])).
5. Expire deliveries in 'sent' status (not just 'pending') in
expireGuardianActionRequest using inArray.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
All review feedback addressed in #7550:
|
|
Thanks for the fast follow-up — this commit fixes a lot of what I raised (assistant/broadcast wiring, bearer token threading, external-channel answer ordering, delivery expiry status handling). I still see two blocking gaps: 1) [P1] Voice transcript/completion persistence still depends on an active
|
1. Fix mac channel guardian-answer ordering: call answerCall before resolveGuardianActionRequest so failed delivery leaves request pending for retry from another channel (mirrors channel-routes.ts). 2. Persist voice transcripts directly to conversation_store alongside notifier fires so transcript history survives without a live daemon Session listening on the voice thread. 3. Fix SKILL.md codeLength default documentation (4 → 6) to match the actual schema default. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
Follow-up review on I re-checked the two previously open blockers. The mac guardian-answer ordering fix is now correct (
Suggested direction:
|
|
The "Send guardian deliveries with gateway bearer auth" feedback was already addressed in the final merged code. The |
Co-Authored-By: Claude <noreply@anthropic.com>
|
All review feedback from Codex and Devin has been verified as addressed in the merged code. The fix commits (#7550, #7552) cover all identified issues:
No additional code changes required. |
Summary
This feature makes voice a first-class channel and adds cross-channel guardian notifications for AI phone calls.
Key changes:
'voice'added toChannelIdtype with per-call conversations (key pattern:asst:${assistantId}:voice:call:${callSessionId})guardian_action_requests,guardian_action_deliveries) tracking cross-channel dispatch and resolutionMilestones:
Test plan
🤖 Generated with Claude Code