Add Soniox fallback keys to cloud v2#3222
Conversation
📋 PR Review Helper📱 Mobile App Build⏳ Waiting for build... 🕶️ ASG Client Build⏳ Waiting for build... 🔀 Test Locallygh pr checkout 3222 |
There was a problem hiding this comment.
💡 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".
|
Related Soniox fallback PRs:
Current prod/main hotfix head: e06781b. |
4ea084a to
43e2846
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ 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); |
There was a problem hiding this comment.
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.
Reviewed by Cursor Bugbot for commit 43e2846. Configure here.
| lower.includes("usage limit") || | ||
| lower.includes("monthly limit") | ||
| ) { | ||
| return { kind: "quota", cooldownMs: QUOTA_COOLDOWN_MS }; |
There was a problem hiding this comment.
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.
Reviewed by Cursor Bugbot for commit 43e2846. Configure here.


Summary
SONIOX_FALLBACK_API_KEYSin the Cloud V2 Doppler runbookWhy
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_KEYSfrom legacymentraos-cloudDoppler configs into Cloud V2 configs:devdev_awsdev_debugstagingprodSecret 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.tscd cloud-v2/packages/runtime && bunx tsc -p tsconfig.json --noEmitcd 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.tsgit diff --checkNotes
cd cloud-v2 && bun run typecheckis 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-separatedSONIOX_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.tsno longer uses a single shared SDK client: it keeps one client per key fingerprint, routes initial connect, connect retries, and self-heal reconnects throughconnectFreshSession(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 fromstt-rt-v5(exported asDEFAULT_SONIOX_MODEL);SONIOX_MODELstill overrides.The Doppler runbook lists
SONIOX_FALLBACK_API_KEYSandSONIOX_MODELalongsideSONIOX_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-v5and documentsSONIOX_FALLBACK_API_KEYSandSONIOX_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‑separatedSONIOX_FALLBACK_API_KEYS.stt-rt-v5withSONIOX_MODELoverride.Bug Fixes
402budget/quota separately from429rate limits and improves message matching for concurrency errors.Written for commit 43e2846. Summary will update on new commits.