背景
调研了 Wispr Flow Command Mode / Superwhisper Super Mode / Raycast AI / Apple Writing Tools / DeepL / ChatGPT macOS / Cursor Cmd+K / Bob 共 8 个同类工具后形成的方案。
用户工作流
- 用户在任意 app(浏览器、Mail、IDE、PDF reader…)选中一段文字
- 按下配置好的 hotkey(默认 Cmd+Shift+;,可在设置改)
- 新建一个 QA 浮动窗口 出现在屏幕上现有语音胶囊正上方约 8px
- 同时进入语音录音状态(与现有 dictation 共用 ASR 通路),用户对着麦克风提问("这是什么意思 / 总结一下 / 跟 X 有什么区别")
- 按一次 hotkey 停止录音(toggle 行为,跟 dictation 一致)
- ASR 转写问题 + 选区 → LLM → markdown 答案显示在浮窗里
- 用户读完按 Esc / 点外部 / 30s 超时关闭,或按右上角 Pin 钉住久留
已确定的设计决策
| 维度 |
决策 |
理由 |
| 默认 hotkey |
Cmd+Shift+; |
Cmd+Opt+T 跟 macOS Mail/Pages "Show/Hide Fonts" 系统快捷键冲突;Fn+Q 是备选但 Fn 在外接键盘上不稳 |
| 用户可改 |
✅ 4 个预设 + 检测重复 |
不上自定义按键录入界面(实现复杂、用户学习成本高) |
| 取选区策略 |
AX → AppleScript → Cmd+C 静音模拟 三级 fallback |
参考 SelectedTextKit;Electron app(VS Code/Slack/Notion)AX 返回空已知 bug,靠 Cmd+C 兜底 |
| Cmd+C 模拟前 |
snapshot NSPasteboard,调用后 restore |
不污染用户剪贴板(与 issue #111 同款约定) |
| 答案窗口 |
新建 Tauri webview 窗口(不复用胶囊) |
胶囊是 transient state UI,QA 答案是 reading UI(要可滚动、可复制)。不引入 tauri-nspanel 新 dep——普通 webview + alwaysOnTop + skipTaskbar 即可 |
| 答案窗口位置 |
锚在胶囊上方 8px,水平居中对齐 |
Coordinator 拿胶囊 frame 算出 QA frame |
| 答案窗口生命周期 |
Esc / 点外部 / 30s 超时关,可 Pin 久留 |
参考 Raycast Quick AI |
| 答案格式 |
Markdown,≤ 3 段,不超过 ~200 字 |
LLM prompt 硬约束 |
| 没选区 |
静默降级为纯语音问答(不报错) |
参考 Raycast / Superwhisper |
| 静默录音 |
直接 cancel,不调 LLM、不弹窗 |
沿用现有 `.cancelled` 路径 |
| 选区超 4000 字符 |
截首+尾各 2000,加 `[…truncated…]` |
Wispr Flow 是硬拒绝 1000 词,UX 差 |
| 选区持久化 |
不写 history.json,只活到 QA 窗关闭 |
隐私约束 |
| 历史记录 |
Settings 加 toggle "Save Q&A history",默认关 |
用户主动 opt-in |
实现规划(agent teams 并行分工)
Track 1 — Backend: 新 hotkey 注册 + 选区捕获
文件改动:
- `Cargo.toml`:现有 `global-hotkey = "0.6"` 已在 deps,启用之
- `hotkey.rs`:新加 `QaHotkeyMonitor` 模块(独立于现有的 modifier-only `HotkeyMonitor`),用 global-hotkey crate 注册 Cmd+Shift+; 之类组合键
- `coordinator.rs`:加 `SelectionContext { text: String, source_app: Option }` + 新事件 `QaHotkeyEvent::{Pressed, Released}`
- 新文件 `selection.rs`:策略链取选区
- `#[cfg(target_os = "macos")]` AX via objc2-app-kit + Cmd+C fallback
- `#[cfg(target_os = "windows")]` SendInput Ctrl+C + restore clipboard
- `types.rs`:`UserPreferences` 加 `qa_hotkey: Option`,`QaHotkeyBinding { primary: KeyCode, modifiers: ModifiersFlags }`
Track 2 — Backend: QA 通路(ASR → LLM → 浮窗)
文件改动:
- `coordinator.rs`:新增 `SessionKind::QuestionAnswer { selection: SelectionContext }`
- `begin_session` 分流:dictation / translation / qa
- `polish.rs`:新加 `answer_with_selection(question: &str, selection: &str, working_languages: &[String], front_app: Option<&str>) -> Result<String, LLMError>`
- 选区超 4000 字符截断逻辑
Track 3 — Frontend: QA 答案浮窗
新文件:
- `tauri.conf.json`:新加 windows entry `label: "qa"`,`width: 380, height: 280`,`transparent: true`,`alwaysOnTop: true`,`skipTaskbar: true`,`focus: false`,`acceptFirstMouse: true`,`visible: false`
- 新文件 `src/pages/QaPanel.tsx`:
- 加载状态(gradient skeleton + "思考中...")
- 答案区(react-markdown 渲染,已在 deps?没有就加 `marked` 走轻量)
- 关闭按钮(×)+ Pin 按钮(📌)
- 监听 `qa:state` event 接收答案
- 监听全局 Esc + click-outside 关闭逻辑
- `src/App.tsx`:分发 window label `?window=qa` → `QaPanel`
- 答案窗位置:从 Rust 侧 `set_position` 计算 `(capsule.x + (220-380)/2, capsule.y - 280 - 8)`
Track 4 — Settings UI + i18n
文件改动:
- `src/pages/Translation.tsx` 旁边的 `Settings.tsx`:录音 section 加一行"提问模式快捷键"——下拉 4 个预设(Cmd+Shift+; / Cmd+Opt+; / Cmd+Shift+/ / Cmd+Opt+/)
- `src/pages/Settings.tsx` 新增 toggle "保存 Q&A 历史"
- `UserPreferences.qa_hotkey + qa_save_history`
- i18n key 全套:`settings.recording.qaHotkey*`, `qa.thinking`, `qa.error`, `qa.pinTooltip`, `qa.closeTooltip`
Test plan
Out of scope(v1)
- 自定义按键录入界面(用预设下拉)
- 答案分段流式 / SSE
- 多轮对话(每次按 hotkey 是独立 Q&A)
- 答案窗口里点链接打开
- 选区超 4000 字时 "上传完整文本" 选项
- iOS / Linux 实现
背景
调研了 Wispr Flow Command Mode / Superwhisper Super Mode / Raycast AI / Apple Writing Tools / DeepL / ChatGPT macOS / Cursor Cmd+K / Bob 共 8 个同类工具后形成的方案。
用户工作流
已确定的设计决策
实现规划(agent teams 并行分工)
Track 1 — Backend: 新 hotkey 注册 + 选区捕获
文件改动:
Track 2 — Backend: QA 通路(ASR → LLM → 浮窗)
文件改动:
Prompt 模板(中文,沿用现有 chat_completion 通路):
```
用户选中了以下文本:
"""{selection_truncated}"""
用户的语音提问:"{question}"
请基于选中文本回答。如果选中文本与提问无关,按提问独立回答,不要编造选区里没有的信息。
用 Markdown,不超过 3 段,不超过 ~200 字。
```
Track 3 — Frontend: QA 答案浮窗
新文件:
Track 4 — Settings UI + i18n
文件改动:
Test plan
Out of scope(v1)