- Update TTSManager to accept an optional abort signal, allowing for graceful cancellation of TTS playback. - Implement abort handling in the generateAndWaitForPlayback method to clean up pending playbacks and reject promises when playback is aborted. - Modify Session class to pass the abort signal during TTS generation, improving control over playback interruptions. These changes improve the robustness of the voice assistant's TTS functionality and enhance user experience by allowing for better management of audio playback.
255 lines
7.5 KiB
Markdown
255 lines
7.5 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Voice-controlled terminal assistant using OpenAI's Realtime API (via Whisper STT, GPT-4, and TTS). Single-service architecture combining Express server, React UI, and tmux-based terminal management.
|
|
|
|
## Monorepo Structure
|
|
|
|
This is an npm workspace monorepo:
|
|
|
|
- **Root**: Workspace configuration and shared TypeScript config
|
|
- **packages/voice-assistant**: Main application (only active package currently)
|
|
|
|
## Development Commands
|
|
|
|
All commands run from the repository root:
|
|
|
|
```bash
|
|
# Development (starts Express server with integrated Vite middleware)
|
|
npm run dev
|
|
|
|
# Build everything
|
|
npm run build
|
|
|
|
# Type checking
|
|
npm run typecheck
|
|
|
|
# Production
|
|
npm run start
|
|
```
|
|
|
|
### Voice Assistant Package Commands
|
|
|
|
From `packages/voice-assistant/`:
|
|
|
|
```bash
|
|
# Development
|
|
npm run dev # Watch mode: Express server + Vite HMR
|
|
npm run dev:server # Express server only (port 3000)
|
|
|
|
# Building
|
|
npm run build # Build both UI and server
|
|
npm run build:ui # Vite build � dist/ui
|
|
npm run build:server # TypeScript � dist/server
|
|
|
|
# Production
|
|
npm start # Run built server
|
|
|
|
# Type checking
|
|
npm run typecheck # Check both UI and server
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Overall Structure
|
|
|
|
Single service with three main subsystems:
|
|
|
|
1. **Server Layer** (`src/server/`):
|
|
|
|
- Express HTTP server (port 3000)
|
|
- WebSocket server for bidirectional communication
|
|
- Vite middleware in development, static files in production
|
|
|
|
2. **Agent Layer** (`src/server/agent/`):
|
|
|
|
- `orchestrator.ts`: Main conversation manager
|
|
- `llm-openai.ts`: GPT-4 streaming with tool execution
|
|
- `stt-openai.ts`: Whisper transcription
|
|
- `tts-openai.ts`: OpenAI TTS synthesis
|
|
- `system-prompt.ts`: Agent instructions (voice-first UX focused)
|
|
|
|
3. **Daemon Layer** (`src/server/daemon/`):
|
|
|
|
- `terminal-manager.ts`: High-level terminal operations
|
|
- `tmux.ts`: Low-level tmux integration
|
|
- `tool-definitions.ts`: OpenAI function schemas for LLM
|
|
|
|
4. **UI Layer** (`src/ui/`):
|
|
- React 18 + Vite
|
|
- WebSocket client for real-time communication
|
|
- Audio capture and playback handling
|
|
|
|
### Key Architecture Decisions
|
|
|
|
**Terminal Model**:
|
|
|
|
- Uses tmux session "voice-dev" with windows-as-terminals
|
|
- Each terminal = one tmux window with single pane
|
|
- Terminal ID = tmux window ID (format: `@123`)
|
|
- Terminal names must be unique
|
|
|
|
**Voice-First Design**:
|
|
|
|
- All responses designed for TTS output
|
|
- STT errors handled intelligently (see `agent-prompt.md`)
|
|
- No visual feedback assumptions
|
|
|
|
**Streaming Architecture**:
|
|
|
|
- Audio: Browser � WebSocket � Whisper STT � LLM � TTS � WebSocket � Browser
|
|
- Text chunks streamed for real-time response
|
|
- Tool calls logged as activity events
|
|
|
|
### Data Flow
|
|
|
|
1. **Voice Input**: Browser captures audio � sends chunks via WebSocket � STT transcribes � orchestrator processes
|
|
2. **LLM Processing**: Orchestrator streams GPT-4 responses � executes tool calls � accumulates response
|
|
3. **Voice Output**: Response � TTS synthesis � base64 audio � WebSocket � browser playback
|
|
|
|
## TypeScript Configuration
|
|
|
|
**Three separate configs:**
|
|
|
|
1. `tsconfig.base.json`: Root workspace defaults (ES2020, ESNext modules)
|
|
2. `packages/voice-assistant/tsconfig.json`: UI build config (React JSX, bundler mode, noEmit)
|
|
3. `packages/voice-assistant/tsconfig.server.json`: Server build config (NodeNext modules, outputs to dist/server)
|
|
|
|
**Module System**:
|
|
|
|
- Server: ES modules with `.js` extensions in imports (NodeNext resolution)
|
|
- UI: Vite bundler mode (no file extensions needed)
|
|
|
|
## Environment Variables
|
|
|
|
Required in `packages/voice-assistant/.env`:
|
|
|
|
```bash
|
|
OPENAI_API_KEY=sk-... # Required for GPT-4, Whisper, and TTS
|
|
|
|
# Optional TTS configuration
|
|
TTS_VOICE=alloy # alloy|echo|fable|onyx|nova|shimmer
|
|
TTS_MODEL=tts-1 # tts-1 (fast) | tts-1-hd (quality)
|
|
|
|
# Server config
|
|
PORT=3000
|
|
NODE_ENV=development
|
|
```
|
|
|
|
## Terminal Control (MCP-like Tools)
|
|
|
|
The LLM has access to terminal operations via function calling:
|
|
|
|
- `list_terminals()`: Get all terminals with status
|
|
- `create_terminal(name, workingDirectory, initialCommand?)`: Create new terminal
|
|
- `send_text(terminalId, text, pressEnter, captureOutput?)`: Execute commands
|
|
- `capture_terminal(terminalId, lines?, wait?)`: Read terminal output
|
|
- `kill_terminal(terminalId)`: Remove terminal
|
|
|
|
See `src/server/daemon/tool-definitions.ts` for complete schemas.
|
|
|
|
## WebSocket Protocol
|
|
|
|
Message types (see `src/server/types.ts`):
|
|
|
|
**Client � Server**:
|
|
|
|
- `user_message`: Text input
|
|
- `audio_chunk`: Audio data (base64, includes format and isLast flag)
|
|
- `recording_state`: Recording started/stopped
|
|
- `ping`: Keepalive
|
|
|
|
**Server � Client**:
|
|
|
|
- `activity_log`: Conversation events (transcript, tool calls, errors)
|
|
- `assistant_chunk`: Streaming response text
|
|
- `audio_output`: Complete TTS audio (base64 MP3)
|
|
- `transcription_result`: STT output
|
|
- `status`: Connection state
|
|
- `pong`: Keepalive response
|
|
|
|
## Agent System Prompt
|
|
|
|
Located in `agent-prompt.md` (32KB) - loaded by `system-prompt.ts`.
|
|
|
|
**Critical aspects**:
|
|
|
|
- Voice-first interaction guidelines
|
|
- STT error handling strategies
|
|
- Terminal operation best practices
|
|
- Response brevity requirements (user is on phone)
|
|
|
|
## Testing
|
|
|
|
Currently manual testing:
|
|
|
|
1. Start dev server: `npm run dev`
|
|
2. Open http://localhost:3000
|
|
3. Test WebSocket connection (status indicator)
|
|
4. Test voice recording/playback
|
|
5. Test terminal operations via `/api/test-terminal`
|
|
|
|
Test scripts:
|
|
|
|
- `test-llm.sh`: Direct LLM streaming test
|
|
- `test-orchestrator.js`: Conversation flow test
|
|
|
|
## File Organization
|
|
|
|
```
|
|
packages/voice-assistant/
|
|
|