Skip to content

Add Soniox fallback keys to cloud v2#3222

Open
isaiahb wants to merge 5 commits into
devfrom
codex/cloud-v2-soniox-fallback
Open

Add Soniox fallback keys to cloud v2#3222
isaiahb wants to merge 5 commits into
devfrom
codex/cloud-v2-soniox-fallback

Conversation

@isaiahb

@isaiahb isaiahb commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add Cloud V2 Soniox primary/fallback credential pool with primary-first selection and fallback round-robin
  • retry Soniox session creation/reconnect on alternate credentials when the active key hits auth/quota/rate/concurrency failures
  • document SONIOX_FALLBACK_API_KEYS in the Cloud V2 Doppler runbook

Why

The legacy Cloud v1 hotfix handles Soniox spend/quota exhaustion by falling back to comma-separated backup keys. Cloud V2 uses the same Soniox provider for transcription and translation, so this brings the same operational escape hatch into the rewrite without changing client protocol behavior.

Configuration

Copied SONIOX_FALLBACK_API_KEYS from legacy mentraos-cloud Doppler configs into Cloud V2 configs:

  • dev
  • dev_aws
  • dev_debug
  • staging
  • prod

Secret values were not printed.

Validation

  • bun test cloud-v2/packages/runtime/src/services/audio/providers/soniox.test.ts cloud-v2/packages/runtime/src/services/audio/providers/soniox-key-pool.test.ts
  • cd cloud-v2/packages/runtime && bunx tsc -p tsconfig.json --noEmit
  • cd cloud-v2 && bun test packages/runtime/src/services/audio/providers/soniox-key-pool.test.ts packages/runtime/src/services/audio/providers/soniox.test.ts tests/soniox.integration.test.ts
  • git diff --check

Notes

  • cd cloud-v2 && bun run typecheck is still blocked by an existing unrelated Cloud Client test error: packages/cloud-client/src/client.test.ts(66,39): Cannot find name 'RequestInfo'.

Note

Medium Risk
Changes live audio/STT connectivity and credential failover for all Soniox traffic; misconfiguration or aggressive cooldowns could shift load to fallback keys or briefly interrupt streams during reconnect, but client protocol and injected test clients are unchanged.

Overview
Adds a Soniox credential pool for Cloud V2 so live transcription can keep running when the primary API key is throttled or exhausted, matching the legacy v1 operational escape hatch.

SonioxKeyPool (new) builds a primary plus comma-separated SONIOX_FALLBACK_API_KEYS, prefers the primary when healthy, round-robins fallbacks when keys are on cooldown, deduplicates keys, and classifies failures (auth → disable for process; concurrency / rate / quota / transient → tuned cooldowns). Success does not clear an active cooldown.

soniox.ts no longer uses a single shared SDK client: it keeps one client per key fingerprint, routes initial connect, connect retries, and self-heal reconnects through connectFreshSession (try next credential on connect failure), and records stream errors against the active credential. Logs include credential role/id fingerprints. The default real-time model moves from stt-rt-v5 (exported as DEFAULT_SONIOX_MODEL); SONIOX_MODEL still overrides.

The Doppler runbook lists SONIOX_FALLBACK_API_KEYS and SONIOX_MODEL alongside SONIOX_API_KEY. Unit tests cover the pool and the model default.

Reviewed by Cursor Bugbot for commit 43e2846. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds a primary/fallback Soniox credential pool with automatic failover and reconnects to keep Cloud V2 transcription/translation running under auth/quota/rate/concurrency limits. Sets the default real-time model to stt-rt-v5 and documents SONIOX_FALLBACK_API_KEYS and SONIOX_MODEL; no client protocol changes.

  • New Features

    • SonioxKeyPool: primary-first with round-robin fallbacks, per-failure cooldowns, and permanent disable for invalid keys; parses comma‑separated SONIOX_FALLBACK_API_KEYS.
    • Initial connect and self-heal reconnects retry across keys; one SDK client per key; logs use credential fingerprints; model defaults to stt-rt-v5 with SONIOX_MODEL override.
  • Bug Fixes

    • Classifies 402 budget/quota separately from 429 rate limits and improves message matching for concurrency errors.
    • Prevents a success from clearing an active cooldown; tests added.

Written for commit 43e2846. Summary will update on new commits.

Review in cubic

@github-actions

Copy link
Copy Markdown

📋 PR Review Helper

📱 Mobile App Build

Waiting for build...

🕶️ ASG Client Build

Waiting for build...


🔀 Test Locally

gh pr checkout 3222

Comment thread cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts Outdated
Comment thread cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99a229d8e0

ℹ️ 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".

Comment thread cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts Outdated
Comment thread cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts Outdated
Comment thread cloud-v2/packages/runtime/src/services/audio/providers/soniox-key-pool.ts Outdated
Comment thread cloud-v2/packages/runtime/src/services/audio/providers/soniox.ts Outdated
@isaiahb

isaiahb commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

Related Soniox fallback PRs:

Current prod/main hotfix head: e06781b.

@isaiahb isaiahb force-pushed the codex/cloud-v2-soniox-fallback branch from 4ea084a to 43e2846 Compare June 21, 2026 02:39

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 43e2846. Configure here.

session = candidate.session;
activeCredential = candidate.credential;
wireSession(candidate.session);
recordCredentialSuccess(candidate.credential, context);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handlers attached after connect

High Severity

connectFreshSession awaits connect() before wireSession(), but the previous initial and self-heal paths registered result, error, and disconnected handlers first. Early SDK events during connect can be dropped, so reconnects may miss transcripts or fail to record credential failures.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 43e2846. Configure here.

lower.includes("usage limit") ||
lower.includes("monthly limit")
) {
return { kind: "quota", cooldownMs: QUOTA_COOLDOWN_MS };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

429 bypasses quota classification

Medium Severity

In classifySonioxCredentialFailure, any parsed Soniox error 429 is treated as rate_limit before the quota branch runs, even when the message mentions budget, quota, or billing. Those keys get a 60s cooldown instead of 30 minutes and may be retried while still exhausted.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 43e2846. Configure here.

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