MCPcopy
hub / github.com/codeaashu/claude-code / connectVoiceStream

Function connectVoiceStream

src/services/voiceStreamSTT.ts:111–544  ·  view source on GitHub ↗
(
  callbacks: VoiceStreamCallbacks,
  options?: { language?: string; keyterms?: string[] },
)

Source from the content-addressed store, hash-verified

109// ─── Connection ────────────────────────────────────────────────────────
110
111export async function connectVoiceStream(
112 callbacks: VoiceStreamCallbacks,
113 options?: { language?: string; keyterms?: string[] },
114): Promise<VoiceStreamConnection | null> {
115 // Ensure OAuth token is fresh before connecting
116 await checkAndRefreshOAuthTokenIfNeeded()
117
118 const tokens = getClaudeAIOAuthTokens()
119 if (!tokens?.accessToken) {
120 logForDebugging('[voice_stream] No OAuth token available')
121 return null
122 }
123
124 // voice_stream is a private_api route, but /api/ws/ is also exposed on
125 // the api.anthropic.com listener (service_definitions.yaml private-api:
126 // visibility.external: true). We target that host instead of claude.ai
127 // because the claude.ai CF zone uses TLS fingerprinting and challenges
128 // non-browser clients (anthropics/claude-code#34094). Same private-api
129 // pod, same OAuth Bearer auth — just a CF zone that doesn't block us.
130 // Desktop dictation still uses claude.ai (Swift URLSession has a
131 // browser-class JA3 fingerprint, so CF lets it through).
132 const wsBaseUrl =
133 process.env.VOICE_STREAM_BASE_URL ||
134 getOauthConfig()
135 .BASE_API_URL.replace('https://', 'wss://')
136 .replace('http://', 'ws://')
137
138 if (process.env.VOICE_STREAM_BASE_URL) {
139 logForDebugging(
140 `[voice_stream] Using VOICE_STREAM_BASE_URL override: ${process.env.VOICE_STREAM_BASE_URL}`,
141 )
142 }
143
144 const params = new URLSearchParams({
145 encoding: 'linear16',
146 sample_rate: '16000',
147 channels: '1',
148 endpointing_ms: '300',
149 utterance_end_ms: '1000',
150 language: options?.language ?? 'en',
151 })
152
153 // Route through conversation-engine with Deepgram Nova 3 (bypassing
154 // the server's project_bell_v2_config GrowthBook gate). The server
155 // side is anthropics/anthropic#278327 + #281372; this lets us ramp
156 // clients independently.
157 const isNova3 = getFeatureValue_CACHED_MAY_BE_STALE(
158 'tengu_cobalt_frost',
159 false,
160 )
161 if (isNova3) {
162 params.set('use_conversation_engine', 'true')
163 params.set('stt_provider', 'deepgram-nova3')
164 logForDebugging('[voice_stream] Nova 3 gate enabled (tengu_cobalt_frost)')
165 }
166
167 // Append keyterms as query params — the voice_stream proxy forwards
168 // these to the STT service which applies appropriate boosting.

Callers 2

finishRecordingFunction · 0.85
attemptConnectFunction · 0.85

Calls 15

logForDebuggingFunction · 0.85
getOauthConfigFunction · 0.85
getUserAgentFunction · 0.85
getWebSocketTLSOptionsFunction · 0.85
getWebSocketProxyUrlFunction · 0.85
getWebSocketProxyAgentFunction · 0.85
jsonParseFunction · 0.85
jsonStringifyFunction · 0.85
onMethod · 0.80
trimStartMethod · 0.80

Tested by

no test coverage detected