fix: dictation cloud path — bearer subprotocol, access_token grant field

Two live-verified Deepgram facts from the first real mic-test round:
- /v1/auth/grant returns { access_token }, not { token } — the route now
  parses the right field.
- Minted JWTs authenticate over the WebSocket via the "bearer"
  subprotocol; ["token", jwt] is rejected at the handshake (token is
  for raw API keys only, as in the pi dictate extension).

Also documents the env-precedence gotcha in docs/research/stt.md: a
DEEPGRAM_API_KEY exported in the shell (e.g. .zshrc) silently beats
.env.local in next dev and the desktop authEnv() seam.
This commit is contained in:
amosblomqvist
2026-09-17 19:44:35 +03:00
parent e3bdbc2f2c
commit 573e369db5
3 changed files with 17 additions and 4 deletions
+4 -1
View File
@@ -137,7 +137,10 @@ export function useDictation({ append }: { append: (text: string) => void }): Di
/** Open the Deepgram socket and wire its messages. `gen` guards staleness. */
const openSocket = useCallback(
(gen: number, token: string) => {
const ws = new WebSocket(DG_URL, ["token", token]);
// Minted JWTs authenticate via the "bearer" subprotocol — ["token",
// jwt] is rejected at the handshake (verified live; "token" is for
// raw API keys only, as in the owner's pi dictate extension).
const ws = new WebSocket(DG_URL, ["bearer", token]);
wsRef.current = ws;
ws.addEventListener("open", () => {