mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 07:29:42 +02:00
feat(voice): dictate through the server's Claude Code login, no API key
The mic button previously needed a Deepgram API key, or fell back to the browser's Web Speech engine. It can now transcribe through the same speech-to-text service Claude Code's own /voice mode uses, so anyone signed in to Claude Code on the server gets dictation with no third-party account. Claude Code's voice mode cannot be driven directly: it opens the HOST's microphone (sox/arecord), and the CLI runs in a headless tmux pane while the human is in a browser somewhere else. So capture stays in the browser and only the transcription backend is borrowed. Audio goes browser -> Codeman -> Anthropic. The OAuth token never reaches the page: the browser sends PCM16 (16 kHz mono, produced by an AudioWorklet since MediaRecorder cannot emit raw PCM) and receives text. - GET /api/voice/status reports readiness and never the token - GET /ws/voice/stream relays one dictation, with the same Host/Origin upgrade guard as the terminal socket, plus caps on concurrency, stream length and frame size - credentials are read-only: Codeman never refreshes them, since a refresh rotates the refresh token and could sign the user out of their own CLI - claudeVoiceEnabled (synced, default OFF) gates the whole server side - voiceSettings.provider picks auto/claude/deepgram/webspeech; auto prefers Claude, then a configured Deepgram key, then the browser Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,8 @@ export interface ConfigPort {
|
||||
getTerminalHistoryConfig(): Promise<TerminalHistoryConfig>;
|
||||
/** Synced `agentSkillEnabled` app setting (default OFF); gates per-case agent-skill injection. */
|
||||
getAgentSkillEnabled(): Promise<boolean>;
|
||||
/** Synced `claudeVoiceEnabled` app setting (default OFF); gates the Claude voice dictation relay. */
|
||||
getClaudeVoiceEnabled(): Promise<boolean>;
|
||||
getDefaultClaudeMdPath(): Promise<string | undefined>;
|
||||
getLightState(identity?: { username: string; role: 'admin' | 'user' }): unknown;
|
||||
getLightSessionsState(): unknown[];
|
||||
|
||||
Reference in New Issue
Block a user