| 106 | |
| 107 | /** Maps a getUserMedia rejection to a normalised error code. */ |
| 108 | const mapMediaError = (err: unknown): VoiceInputErrorCode => { |
| 109 | const name = err instanceof DOMException ? err.name : ''; |
| 110 | if (name === 'NotAllowedError' || name === 'SecurityError') { |
| 111 | return 'not-allowed'; |
| 112 | } |
| 113 | if (name === 'NotFoundError' || name === 'NotReadableError') { |
| 114 | return 'audio-capture'; |
| 115 | } |
| 116 | return 'unknown'; |
| 117 | }; |
| 118 | |
| 119 | /** |
| 120 | * Requests microphone access so the browser permission prompt reliably opens and |