Skip to content

Add phone call voice stack support - #16

Merged
dimavrem22 merged 9 commits into
mainfrom
feat/phone-call-voice-stack-opencode
Aug 1, 2026
Merged

Add phone call voice stack support#16
dimavrem22 merged 9 commits into
mainfrom
feat/phone-call-voice-stack-opencode

Conversation

@dimavrem22

@dimavrem22 dimavrem22 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Executive Summary

  • Adds Inkbox Voice AI, OpenAI Realtime API, and Inkbox TTS/STT setup and runtime behavior to the OpenCode plugin.
  • Adds durable, exact-target hosted-call completion handling with one safe SMS correction and stack-specific outbound call definitions.
  • Releases the plugin as 0.2.8 on exact @inkbox/sdk 0.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.ended events 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_STACK is the canonical selector; legacy Realtime settings remain compatible.
  • Plugin options retain precedence. Setup refuses to claim that a saved environment selection overrides a fixed phoneVoiceStack option.
  • Local Realtime and TTS/STT selections configure 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.
  • Hosted outbound calls omit a per-call authority override so the API applies the saved identity default. Explicit authority changes remain administrative setup operations.
  • Realtime keys, model, and voice are preserved when Voice AI or TTS/STT is selected.
  • One canonical call.ended subscription acknowledges all completed calls; only authoritative hosted calls enter hosted settlement.
  • Normal outbound calls omit voicemail configuration unless explicitly configured. Every call-capable live workflow explicitly disables it.

Testing

Local gates:

  • npm run typecheck
  • npm test -- --run — 799 tests across 65 files
  • npm run lint
  • npm run build
  • npm pack --dry-run
  • Workflow YAML parse and git diff --check

Exact-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, and live-voice explicitly set INKBOX_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_accept immediately 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

@dimavrem22
dimavrem22 merged commit e02faee into main Aug 1, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant