baiqing
6e49281519
feat(qa): v2 多轮对话 + 流式输出 + macOS 浮窗修复
issue #118 v2 完整闭环。
## 多轮对话
- QaSessionState 加 messages: Vec<QaChatMessage> + panel_visible flag。
- Cmd+Shift+/ 现在 toggle 浮窗可见性(不再启动录音);浮窗可见时 rightOption
路由到 QA recording,不可见时仍是主听写。open_qa_panel / close_qa_panel 分离。
- 第一轮 user message 嵌选区原文(# 选区原文 / # 我的问题),之后只送提问。
- 前端 QaPanel 渲染气泡列表(user 蓝色靠右 / assistant 灰色 markdown 靠左)。
## 流式输出
- chat_completion_history → chat_completion_history_streaming:开 stream:true
+ SSE chunk 解析,on_delta 回调把每 chunk emit 成 qa:state{kind:"answer_delta"}。
- 前端 streamingAnswer state + StreamingAssistantBubble(带蓝色闪烁 caret)。
- answer 事件落定后清空 buffer,最终 messages 接管。
## macOS 浮窗修复(v1 一直存在的雷)
- capabilities/default.json 加 "qa" 到 windows 数组。否则前端 listen("qa:state")
被 Tauri 权限拦截,浮窗永远收不到事件。
- show_qa_window 用 NSWindow.orderFrontRegardless 替代 window.show()
(后者在 macOS 走 makeKeyAndOrderFront 抢 frontmost)。这样 capture_selection
的 AX read / Cmd+C fallback 能稳定从原 app 读到选区。
- 所有 ObjC msg_send 必须 wrap 进 app.run_on_main_thread —— macOS 26 对
NSWindow 主线程要求是硬断言(违反直接 SIGTRAP)。
- NSWindow.movableByWindowBackground=YES:浮窗任意空白处可拖。
- QA hotkey 注册在主线程:global-hotkey crate 在 macOS 用 Carbon
RegisterEventHotKey,事件回调要靠主 run loop dispatch。
## 胶囊状态同步
- QA 录音 / 转写 / 思考 同步推 capsule:state,让用户在底部胶囊也看到状态。
- schedule_capsule_idle 同时检查 dictation 和 QA 都 Idle 才隐藏,避免旧
dictation Done timer 把 QA 的胶囊误关。
- open_qa_panel 进入时先 emit Idle 清掉 dictation 残留 message + insertedChars。
## 设置页
- SelectionAsk 独立成一级 tab;预设减到 4 个 cmd+shift+ 系列(Option 跟主听写
共用,不放进 QA hotkey)。
- howto / hotkey / privacy 文案重写,反映 v2 的「先开浮窗、再 Option 录音」流程。
- prefs 默认 qaHotkey = cmd+shift+;。
## 后续路线图
- docs/qa-reasoning-roadmap.md:思考能力 v2.2 设计稿(C 路线 reasoner model
切换 + reasoning_content delta + 折叠思考块)。
2026-05-01 17:40:22 +08:00
..
2026-04-30 14:25:51 +08:00
2026-05-01 17:40:22 +08:00
2026-04-30 14:25:51 +08:00
2026-04-30 14:25:51 +08:00