5.5 Voice & Proactive:语音交互与主动模式

编译开关feature('VOICE_MODE')feature('PROACTIVE') 源码位置src/services/voice.ts(16.7 KB)、src/services/voiceStreamSTT.ts(20.9 KB)、src/proactive/


语音交互(Voice Mode)

一句话理解

Voice 模式让用户直接对着麦克风说话,Claude Code 把语音实时转成文字处理,再把响应读出来——终端里的语音 AI 助手。

系统架构

麦克风录音(native audio capture)
         │
         ▼
语音活动检测(VAD - Voice Activity Detection)
  检测到说话:开始录制
  检测到静音(超过阈值):停止录制
         │
         ▼
流式 STT(voiceStreamSTT.ts)
  WebSocket → Anthropic STT 服务
  实时返回识别文字(边说边出字)
         │
         ▼
文字发送给 Claude(正常 query 流程)
         │
         ▼
响应合成为语音(TTS)
  流式播放

关键文件

文件大小职责
src/services/voice.ts16.7 KB核心协调器:录制状态机、会话管理、与 Claude 集成
src/services/voiceStreamSTT.ts20.9 KB流式 STT 实现:WebSocket + 音频流管理
src/services/voiceKeyterms.ts3.4 KB关键词增强:提高代码词汇识别精度

GrowthBook 远程配置

// 语音识别模型可通过 GrowthBook 远程切换
const sttModel = getFeatureValue_CACHED_MAY_BE_STALE('tengu_cobalt_frost')
  ?? 'nova-3'

tengu_cobalt_frost 用于控制语音识别模型版本,允许 Anthropic 在不发布新版本的情况下切换 STT 模型。

voiceKeyterms:关键词增强

Voice 模式向 STT 服务提供代码/AI 专业词汇列表,提高识别精度:

// 注入技术词汇,让 STT 引擎偏向正确识别
const keyterms = [
  'TypeScript', 'Bun', 'React', 'webpack',
  'KAIROS', 'Claude', 'anthropic',
  'npm', 'async', 'await', 'Promise',
  // ... 数百个技术词汇
]

这解决了通用 STT 系统容易把 "TypeScript" 识别成 "Type Script",把 "async/await" 识别成奇怪内容的问题。


主动模式(Proactive Mode)

一句话理解

不等用户开口,Claude 主动找事情做。没有任务时,调用 SleepTool 等待下一个周期性 <tick> 触发。

激活方式

# CLI 参数
claude --proactive

# 环境变量
CLAUDE_CODE_PROACTIVE=1 claude

两种编译保护:feature('PROACTIVE') || feature('KAIROS')

状态机(src/proactive/index.ts)

type ProactiveState = {
  active: boolean         // 是否激活
  paused: boolean         // 用户按 Esc 暂停;下次用户输入自动恢复
  contextBlocked: boolean // API 错误时阻塞 tick,防止错误循环
}

Proactive System Prompt

激活后,System Prompt 追加:

# Proactive Mode

You are in proactive mode. Take initiative -- explore, act, and make progress
without waiting for instructions.

Start by briefly greeting the user.

You will receive periodic <tick> prompts. These are check-ins. Do whatever
seems most useful, or call Sleep if there's nothing to do.

注意这个 System Prompt 的两个关键点:

  1. 先打招呼:避免 Claude 直接就开始做事让用户莫名其妙
  2. Sleep 授权:明确告诉 Claude 没事做时可以 Sleep

SleepTool:打盹工具

// 只在以下条件下可用
const SleepTool =
  feature('PROACTIVE') || feature('KAIROS')
    ? require('./tools/SleepTool/SleepTool.js').SleepTool
    : null

Sleep 的参数:

{
  duration_ms: number  // 睡多久(受 minSleepDurationMs / maxSleepDurationMs 配置限制)
}

tick 机制

在 Proactive 模式下,Claude 不是真正"持续运行"的——而是定期收到 <tick> 消息:

用户不输入  →  系统每 N 秒注入一条 <tick>  →  Claude 检查有无事可做
                                                   ├── 有任务 → 执行
                                                   └── 无任务 → SleepTool(duration_ms)

contextBlocked 状态用于防止 API 错误时陷入死循环(tick → 错误 → tick → 错误...)。当 API 返回错误时,暂停后续 tick,等待用户手动干预。


Voice + Proactive 的组合使用

理论上可以同时启用两者:

两者都通过 query() 函数进入 Claude 的主循环,架构上是正交的。


下一步