Jul 3 16:23 feat: image in ui 14:51 feat: timg -p kitty 06:09 fix: render timg images within Ink's virtual DOM to prevent cursor desync chenbhao +1: Claude Big Pickle timg Unicode-block output was written to stdout via process.stdout.write(),
bypassing Ink's rendering pipeline. Ink's virtual cursor didn't know about
the image rows, causing subsequent UI (prompt, input bar) to render at wrong
positions — overlapping the image and duplicating input bars.
Now the timg ANSI output is passed through the tool data and rendered via
the RawAnsi component within Ink's virtual DOM. Ink's Yoga layout accounts
for the image's width × height, keeping cursor position in sync.
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 03:48 feat: add inline terminal image rendering with Kitty protocol support chenbhao +1: Claude Big Pickle Introduce InlineImage component, ImageShow tool, and image caching/detection
utilities for rendering images directly in the terminal via the Kitty graphics
protocol. Falls back to clickable hyperlinks when protocol is unavailable.
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> Jul 1 15:57 chore: env map config 15:39 docs: add LocationTool unlimited search news and pagination docs chenbhao +1: Claude Big Pickle Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 15:34 feat: remove result limits on LocationTool place searches (Amap/Google) chenbhao +1: Claude Big Pickle - Amap (高德): offset 25 → 1000 per page with pagination loop (≤20 pages)
- Google Places: remove .slice(0,20), add next_page_token pagination (≤3 pages)
- Photos list: remove .slice(0,3) limit
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 14:02 feat: add LocationTool — geographic search with Amap/Google Maps chenbhao +1: Claude Big Pickle Add a new LocationTool supporting geocoding, POI search, directions,
and trip planning. Automatically selects Amap (China) or Google Maps
(international) based on region detection.
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> Jun 30 13:22 chore: docs — add Computer Use Python runtime documentation chenbhao +1: Claude Big Pickle Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 03:01 fix: /friend motion — interrupt hold on new action, drain queue, fix emotion mapping chenbhao +1: Claude Big Pickle - MotionController: interrupt hold when new playAction arrives instead of
queueing, so LLM text-message actions are not blocked by stale 10s hold
- MotionController: drain action queue in hold timer callback to prevent
silent drop of queued actions
- App.tsx: remove hold=true from emotion-only messages — action plays once,
emotion timer handles duration independently
- App.tsx: remove awkward emotion→action mappings (neutral→salute,
relaxed→salute, sad→shy) that caused unnatural gestures
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 02:08 feat: /friend aliveness system, motion controller fix, VAD tuning, high-pass filter chenbhao +1: Claude Big Pickle - Remove redundant files (HistoryPanel, MoodIndicator, vmd-loader, vrm-ik-handler, web-file-picker, FriendScreenObserveTool)
- Add action parameter to friend_emotion for VRM animation playback
- Fix motion-controller: replace broken 'finished' event with frame-accurate completion detection and action queue
- Add aliveness system: breathing, postural sway, speech micro-movements, listening response, micro-expressions, enhanced blink
- Add Silero VAD threshold tuning and high-pass filter for low-frequency noise rejection
- Fix build scripts (vite build instead of tauri build)
- Add LipSync.isActive() for speech-driven animation blending
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> Jun 29 17:39 chore: docs v1.2 — add debug system, feishu integration; update swarm, tavily, provider auth chenbhao +1: Claude Big Pickle New docs:
- docs/cli/debug-system.md — /debug v2.0 DEBUG PROBE workflow, session debug logging
- docs/services/feishu.md — Feishu/Lark bot architecture, access control, TTS
Updated docs:
- docs/coordinator/multi-agent.md — Agent Teams (Swarm topology), Fork Subagent
- docs/tools/overview.md — WebSearch dual-backend (Tavily vs SearXNG)
- docs/architecture/provider-auth.md — OpenCode Zen free models, NVIDIA sidecar
- docs/friend/voice-vad.md — noise suppression, FriendService stricter threshold
- docs/services/overview.md — condensed feishu section to point to new doc
- docs/README.md — index updated with all new entries
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 16:58 fix: prevent TTS replay of historical messages on session resume chenbhao +1: Claude Big Pickle useAutoTTS now detects session switches (resume) via UUID discontinuity
and treats all loaded messages as history to skip TTS. Only subsequent
real-time assistant replies will trigger speech.
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 14:15 chore: remove obsolete test and vendor source, add CLI SDK docs chenbhao +1: Claude Big Pickle - Remove test_feishu_ws.ts (contained secrets)
- Remove vendor/audio-capture-src/index.ts (replaced by
packages/audio-capture-napi)
- Add docs/cli/ build system documentation
- Add src/cli/ SDK transport and handler modules
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 13:53 feat: unify build output paths and extract shared feature flags chenbhao +1: Claude Big Pickle - Always build to dist/VersperClaw with symlink at project root
- Always enable all experimental features (dev mode, no release builds)
- Extract feature flag list to scripts/features.ts, shared by build & dev
- Create scripts/dev.ts to run source with --feature and --define flags
- Copy vendor/ to dist/vendor/ at build time for runtime resolution
- Remove redundant build:dev, build:dev:full, compile scripts
Co-Authored-By: Claude Big Pickle <noreply@anthropic.com> 12:44 feat: /debug v2.0 已将 VersperClaw 的 /debug 从被动日志阅读技能完全替换为 Openclaude /debug-mode 的主动插桩调试工作流。
改动文件
┌───────────────────────────────┬──────┬──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 文件 │ 操作 │ 说明 │
├───────────────────────────────┼──────┼──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ src/tools/DebugSessionTool.ts │ 新建 │ 移植自 Openclaude,管理 .versperclaw-debug/ 目录(init/begin_run/begin_verify/read_log/cleanup) │
├───────────────────────────────┼──────┼──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ src/tools.ts │ 修改 │ 导入并注册 DebugSessionTool 到工具列表 │
├───────────────────────────────┼──────┼─────────────────────────────────────────────────────… Jun 28 12:49 feat: Filter TTS rules based on language 09:21 fix: FriendEmotionTool.call() 08:59 feat: /friend cosplay 07:58 feat: Friend 消息 → 仅使用人设提示词 修改的文件 (5个)
核心流程:Friend 消息 → 仅使用人设提示词
1. src/types/textInputTypes.ts
- 在 QueuedCommand 中添加 overrideSystemPrompt?: string 字段,用于存储替代系统提示词
2. src/skills/bundled/friendPrompt.ts
- 导出 loadPersona() 和 buildVrmSystemPrompt(),供 FriendService 调用
3. src/friend/FriendService.ts
- 在 sendText() 中构建 VRM 人设提示词,作为 overrideSystemPrompt 随消息入队
4. src/utils/handlePromptSubmit.ts
- 在 onQuery 类型中添加 overrideSystemPrompt 参数
- 从 commands[0] 提取并传递给 onQuery
5. src/screens/REPL.tsx
- onQuery 和 onQueryImpl 均接收 overrideSystemPrompt 参数
- 传入 buildEffectiveSystemPrompt(),当该值存在时完全替代默认系统提示词
数据流
FriendService.sendText()
→ buildVrmSystemPrompt() ← 只构建 VRM 人设提示词
→ enqueue({ overrideSystemPrompt, ... })
→ processQueueIfReady()
→ handlePromptSubmit()
→ executeUserInput()
→ onQuery(..., overrideSystemPrompt)
→ onQueryImpl(..., overrideSystemPrompt)
→ buildEffectiveSystemPrompt({ overrideSystemPrompt })
→ 返回 [overrideSystemPrompt] ← 完全绕过 ~900 行 … 07:57 fix: tts not read tool message 06:20 chore: script bun run friend:build Jun 22 14:41 chore: update readme 13:20 chore: docs v1.1 12:38 chore: docs v1.0 11:24 chore: questionnaire rename 11:05 feat: VAD Noise Suppression 代码正确。运行现有测试确保没有破坏。
● Bash(npx vitest run src/friend/__tests__/ 2>&1 | tail -30)
⎿ FAIL src/friend/__tests__/e2e-http-flow.test.ts [ src/friend/__tests__/e2e-http-flow.test.ts ]
Error: Cannot find package 'bun:test' imported from /home/yuki/Code/Agent/VersperClaw/src/friend/__tests__/e2e-http-flow.test.ts
❯ src/friend/__tests__/e2e-http-flow.test.ts:10:1
… +26 lines (ctrl+o to expand)
⎿ (timeout 30s)
● 测试使用 bun,需要 bun test。
● Bash(bun test src/friend/__tests__/ 2>&1 | tail -30)
⎿ bun test v1.3.14-canary.1 (0d9b296a)
src/friend/__tests__/e2e-http-flow.test.ts:
… +15 lines (ctrl+o to expand)
● 4 测试全部通过,15 个 expect() 均无失败。
修改总结
vad-service.ts — 核心 VAD 检测逻辑
阈值调整(减少假阳性):
┌─────────────────────────┬───────────┬────────────┬─────────────────────────────────────┐
│ 参数 │ 旧值 │ 新值 │ 作用 │
├─────────────────────────┼───────────┼────────────┼─────────────────────────────────────┤
│… 10:54 chore: friend and how to use prompt 10:33 chore: no appimage 10:23 fix: tools call or think voice play will stop receive audio 用户说话 → VAD检测说话结束 → _flushVadSegment()
→ sendText(transcript) → 进入CLI对话
→ startAiTurnMute()
├─ muted = true
├─ VAD pause()
└─ 30秒超时(安全网,覆盖AI处理、工具调用、思考等)
AI处理中(WebSearch / 深度思考 / 等) → 音频静音,不收不送
AI回复就绪 → broadcastResponse()
→ TTS生成成功
→ extendMuteForTts(audioId)
├─ 清除30秒安全网
├─ 解析MP3算出精确音频时长
└─ 新定时器 = 精确时长
TTS播放中 → 音频静音
TTS播放完毕 → unmute()
├─ muted = false
├─ VAD start() → 恢复收音
└─ 下一轮对话开始
30 秒兜底防止 AI 不回复(错误等)导致永久静音,extendMuteForTts 在 TTS 生成后会精确定时到音频实际长度 10:12 fix: TTS voice play will stop receive audio 现在 muteForTts 不再靠估算,而是实际解析 MP3 文件头算出精确时长:
1. 找到前两个帧同步(0xFFE0),测量出实际帧间距(144 字节)
2. 用这个帧间距作为步长遍历文件统计帧数
3. 从第一帧头部解析出采样率和每帧采样数
4. duration = frameCount × samplesPerFrame / sampleRate
短句 "你好,这是一段测试语音。" → 2880ms ✓
中等 "你好,这是一段...voice message." → 6024ms ✓
长句 "你好!我是Claude..." → 14400ms ✓
全部精确匹配 ffprobe
静音时长不含推测余量,纯按实际 TTS 音频长度来,用户话音一落地就恢复收音 09:45 fix: echo in VAD STT TTS 回声问题修复
新增静音机制 — 在 AI 通过 TTS 回答期间,暂时阻断麦克风音频进入 STT 和 VAD:
1. muted 标志 + muteTimer — 控制音频采集的静音状态
2. muteForTts(text) — 根据回复文本长度估算 TTS 播放时长,自动管理静音期:
- 估算公式:max(3000ms, text.length × 100ms + 1500ms)
- 中文字符约 125ms/字,英文约 83ms/字符,+1s 生成/网络开销 + 0.5s 余量
- 最短 3 秒
3. clearMute() — 用户按 F2 结束通话时立即清除静音状态
4. arecord 回调中的 feedAudio(c) — 静音时直接 return,音频不进入 STT 也不进入 VAD
完整流程:
用户说话 → 音频 → STT → 转录 → AI → broadcastResponse()
↓ TTS生成成功 + 采集进行中
muteForTts(text)
↓
静音期间所有音频丢弃
↓ (TTS播放完毕)
setTimeout → unmute
↓
恢复音频采集 09:37 feat: VAD 08:51 feat: polling voice create stt 5s 架构变更:浏览器 VAD → 服务器端定时分段
根本问题
onnxruntime-web WASM 后端在 Tauri 的 WebKitGTK
中无法运行(即使所有文件都在本地提供)。这是 WebKitGTK 的一个已知限制。
解决方案
不再尝试在浏览器中运行 VAD。改为服务器端的定时音频分段:
F2 开始 → 服务器用 cpal/arecord 录制音频 → 每 5 秒:
├─ 结束当前 STT 连接 → Groq 转写 → sendText() → CLI 对话
└─ 创建新的 STT 连接,继续录制
F2 结束 → 清理
变更文件
┌──────────────────┬────────────────────────────────────────────────────────────┐
│ 文件 │ 变更 │
├──────────────────┼────────────────────────────────────────────────────────────┤
│ FriendService.ts │ 新增定时分段:_flushSegment() + captureTimer,将音频分段为 │
│ │ 5 秒窗口,自动发送到 CLI │
├──────────────────┼────────────────────────────────────────────────────────────┤
│ useServerStt.ts │ 完全重写:移除浏览器 VAD(@ricky0123/vad-web / │
│ │ onnxruntime-web),新增基于轮询的服务器端语音通话 │
├──────────────────┼─────────────────────────────────────────────────────────… 07:40 feat: VAD but just case choose 00:45 feat: cycle time activate check friend Jun 21 16:31 chore: update news 16:28 feat: /voice use best grop whisper provider free and fast 15:30 feat: grop free stt 14:31 feat: /friend tts add websearch 14:11 feat: friend text tts ok but websearch tts not ok 13:28 fix: Microphone access denied 12:07 feat: inter-process 架构对比
之前: 之后:
CLI TUI CLI TUI (单一进程)
└── /friend start ├── FriendService (in-process, cpal)
├── 服务器子进程 :3456 │ ├── STT via cpal
│ ├── chat-service.ts │ ├── enqueue() → 主 CLI
│ │ └── CLI SDK 子进程│ └── SSE → Tauri
│ ├── arecord 子进程 ├── 轻量 Bun.serve (in-process)
│ └── SSE └── Tauri (thin display only)
└── Tauri (getUserMedia) 08:11 feat: csp null 00:30 feat: full screen friend Jun 20 19:28 fix: friend render 18:20 chore: cancel exc /friend (no content) 17:50 fix: /friend start stop (no content) 17:32 fix: auto esc /friend start stop 17:20 fix: after /friend stop can esc