Add phone call voice stack support - #16
Merged
Merged
Conversation
This was referenced Aug 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Executive Summary
@inkbox/sdk0.5.9 and strengthens live call CI with voicemail detection disabled.Description
This ports the phone call voice-stack contract across setup, configuration, gateway startup, diagnostics, outbound tools, completion webhooks, and live acceptance coverage.
The setup wizard now presents the three supported stacks, validates an actual Realtime WebSocket session update, configures Voice AI authority without overwriting hosted instructions, preserves validated Realtime credentials when another stack is selected, and immediately reconciles local incoming routing from either the configured gateway public URL or the server-issued identity tunnel public host. Gateway startup reuses the same path-preserving URL normalization for ongoing reconciliation.
Hosted outbound calls require a reason, omit client WebSocket audio, and inherit the server-side saved authority default. Local stacks retain client WebSocket audio.
call.endedevents are acknowledged for every call mode while hosted completion work is strictly mode-gated.Hosted post-call SMS commitments use a private durable journal, canonical caller session, exact authoritative target, provider-settlement boundary, bounded preparation retry, and one correction only for safe pre-send or content rejection failures.
Reason
OpenCode previously exposed one local call path and could not select Inkbox Voice AI or distinguish Realtime from Inkbox TTS/STT through setup. Hosted calls also needed the same post-call action behavior as local Realtime calls, including reliable follow-up after process interruption and protection against wrong-recipient or duplicate sends.
Decisions
INKBOX_VOICE_STACKis the canonical selector; legacy Realtime settings remain compatible.phoneVoiceStackoption.auto_accept, media WebSocket, and webhook routing before setup saves the stack. A configured gateway URL takes precedence; otherwise setup uses only the validated server-issued identity tunnel host and fails closed when neither is valid.call.endedsubscription acknowledges all completed calls; only authoritative hosted calls enter hosted settlement.Testing
Local gates:
npm run typechecknpm test -- --run— 799 tests across 65 filesnpm run lintnpm run buildnpm pack --dry-rungit diff --checkExact-head verification (5218129):
Live acceptance inventory:
Updated —
inbound_inkbox: creates a new baseline-excluded call pair, verifies the exact driver outbound row has voicemail detection disabled, and proves the AUT answered with Inkbox TTS/STT. The assertion stays on the outbound row where voicemail detection is meaningful, avoiding a deterministic false failure on the mirrored inbound carrier row.Updated —
outbound_realtime: requires exactly one baseline-excluded driver leg and one AUT leg after duplicate grace, verifies Realtime flags and voicemail detection on the exact AUT outbound row, and requires persisted transcript evidence. Baseline IDs prevent stale calls from satisfying the scenario. Voicemail configuration is asserted only on the call-capable AUT outbound request; the driver-owned inbound mirror can legitimately expose an unrelated provider default and is retained only for exact two-owner pairing and speech proof.New —
outbound_hosted: requires exactly one baseline-excluded driver leg and one AUT leg after duplicate grace, then verifies those exact legs, hosted mode, reason, saved authority, voicemail detection, pre-hangup transcript plus open action marker, durable completion registry state, exact sender baseline/time, exactly one current marker SMS, and a full 10-second duplicate grace period. This closes acknowledgment-only, stale-message, wrong-leg, delayed-action, and duplicate-send false positives.Updated — live voice driver: hosted calls remain connected for 180 seconds while the test awaits authoritative transcript and open-action persistence and every test-owned call is explicitly hung up. This removes the action-persistence race caused by driver auto-stop.
Updated — live helpers: call matching excludes baseline IDs, applies creation watermarks, and returns the exact AUT call voicemail field. This prevents old or unrelated call records from satisfying a run.
Updated — voice proof helper and unit coverage: generates five distinct NATO-only words and normalizes expected speech punctuation variants while retaining ordered marker tokens, reducing transcription false negatives without permitting loose marker false positives.
Updated — hosted action capture wording: after two exact live calls proved the hosted model heard the full marker but persisted an SMS action summary without its body, the driver now explicitly requires creating the post-call action with the exact SMS body and reading the five stored words back. Strict transcript, open-action, exact-target receipt, and duplicate-grace gates remain unchanged.
Updated — all call-capable workflow boots:
live-a2a,live-channels,live-external-events, andlive-voiceexplicitly setINKBOX_VOICEMAIL_DETECTION=disabled; the AUT launcher passes the value to both OpenCode and the gateway.Updated — bounded live readiness and job diagnostics: every OpenCode and mock-model readiness probe now has one-second connect and three-second request limits, the voice matrix has a 15-minute job cap, and the channel matrix has a 25-minute job cap. Failure diagnostics and artifacts also run when a cap cancels a job. Static contract tests pin every bound. This closes the evidenced TCP-accepted/no-response gap where an unbounded health-check request previously held a runner until manual cancellation.
Updated — setup-time local routing: Realtime and TTS/STT now configure
auto_acceptimmediately from a shared, path-preserving public URL contract. Tests cover server-issued tunnel fallback, configured-URL precedence, reruns with fixed options, malformed/missing hosts, no stack persistence on failure, canonical scheme handling, and credential-redacted diagnostics.Updated — hosted settlement boundary proof: deterministic tests now name timeout, 429/rate-limit, carrier outage, duplicate uncertainty, consent/invalid-recipient outcomes, and restart recovery at queued, dispatch-started, pending, correctable, successful, and pre-dispatch-failure boundaries.
Additional unit coverage exercises wizard loops and precedence, Voice AI authority credentials, transactional remote rollback, local authority drift, credential preservation, real Realtime success/rejection/timeout/redaction and stale-key replacement, incoming-route drift, hosted and local tool schemas, exact-target SMS canonicalization, fail-closed corrupt/unreadable journals, private 0700/0600 state, lock contention and stale recovery, per-turn tool restrictions, phase-aware retries, webhook mode gating, duplicate completion handling, restart recovery, and delivery correction policy.
Related PRs