Files
claude-voice-experiment/voice-buddy.mjs
mikael-lovqvists-claude-agent a7fa2fd218 Add Pending_Query class and voice interaction improvements
- lib/pending-query.mjs: new state machine for query accumulation
  wake word, silence timer, send/cancel/pause/resume, instant dispatch,
  mode toggle (always listen / stop listening), mode query
- query-demo.mjs: refactored to use Pending_Query; wake word on by default
  with silence timer; chimes for dispatch/working/cancel/activate
- tts-server.mjs: track last_speak_at, expose /activity endpoint,
  chime playback via Python queue (soundfile + librosa), preload on startup
- chatterbox-server.py: chime and preload commands via stdin protocol
- lib/chatterbox-tts.mjs: play_chime and preload_chime methods
- test-chime.mjs: simple chime test script
- voices.yaml: configured ready/cancel/working/dispatch chimes
- CLEANUP-PLAN.md: updated with current state, command vocabulary, future plans

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 03:59:11 +00:00

68 lines
1.7 KiB
JavaScript

// DEPRECATED
/**
* Voice buddy — reads voice queries from stdin (JSON lines) and dispatches
* them to a Claude Code instance via claude-remote.
*
* Usage:
* node query-demo.mjs | node voice-buddy.mjs --window-id 0x1234abc --claude-remote /workspace/claude-remote/claude-remote.mjs
*
* Options:
* --window-id <id> X11 window ID of Claude Code (decimal or 0x hex)
* --claude-remote <path> Path to claude-remote.mjs
*/
import * as readline from 'node:readline'
import { execFileSync } from 'node:child_process'
const args = process.argv.slice(2)
function get_arg(name) {
const i = args.indexOf(name)
if (i === -1 || i + 1 >= args.length) {
process.stderr.write(`Missing argument: ${name}\n`)
process.exit(1)
}
return args[i + 1]
}
const window_id = get_arg('--window-id')
const claude_remote = get_arg('--claude-remote')
function make_prompt(query) {
return [
'[voice-buddy] You have received a voice query.',
'',
'Respond via the `speak` shell command. Keep your response brief and spoken-word natural — this is a voice interface.',
'',
'--- Query ---',
query,
'--- End of query ---',
].join('\n')
}
function dispatch(query) {
const prompt = make_prompt(query)
process.stderr.write(`[voice-buddy] dispatching: ${JSON.stringify(query)}\n`)
execFileSync('node', [claude_remote, '--window-id', window_id], {
input: prompt,
encoding: 'utf8',
stdio: ['pipe', 'inherit', 'inherit'],
})
}
const rl = readline.createInterface({ input: process.stdin })
for await (const line of rl) {
const trimmed = line.trim()
if (!trimmed) {
continue
}
try {
const query = JSON.parse(trimmed)
dispatch(query)
} catch {
process.stderr.write(`[voice-buddy] bad JSON line: ${trimmed}\n`)
}
}