()
| 30 | * cold spawn per refresh is expected. Cheap enough for usage-time checks. |
| 31 | */ |
| 32 | export function hasVoiceAuth(): boolean { |
| 33 | // Voice mode requires Anthropic OAuth — it uses the voice_stream |
| 34 | // endpoint on claude.ai which is not available with API keys, |
| 35 | // Bedrock, Vertex, or Foundry. |
| 36 | if (!isAnthropicAuthEnabled()) { |
| 37 | return false |
| 38 | } |
| 39 | // isAnthropicAuthEnabled only checks the auth *provider*, not whether |
| 40 | // a token exists. Without this check, the voice UI renders but |
| 41 | // connectVoiceStream fails silently when the user isn't logged in. |
| 42 | const tokens = getClaudeAIOAuthTokens() |
| 43 | return Boolean(tokens?.accessToken) |
| 44 | } |
| 45 | |
| 46 | /** |
| 47 | * Full runtime check: auth + GrowthBook kill-switch. Callers: `/voice` |
no test coverage detected