Commit Graph
282 Commits
Author SHA1 Message Date
H-Chris233 6545231d83 Restore mac traffic lights without enabling native chrome on Linux/Windows
Keep custom chrome on non-mac platforms while restoring native traffic lights on macOS. Also remove the extra outer mac shell radius/border to avoid double-rounded corners.

Constraint: macOS must show native traffic lights for issue #183
Constraint: Windows/Linux should keep custom titlebar behavior
Rejected: set decorations=true in tauri.conf globally | enables native chrome on Linux
Confidence: high
Scope-risk: narrow
Directive: Platform-specific window decoration behavior should be controlled at runtime, not by global config
Tested: npm run build (openless-all/app)
Not-tested: manual visual verification on real macOS/Linux/Windows runtimes
2026-05-03 12:22:14 +08:00
Chris233 a2a5605239 Merge pull request #193 from H-Chris233/main
fix(llm): 允许无密钥 LLM 配置
2026-05-03 12:13:50 +08:00
H-Chris233 b85006c9a9 Allow keyless custom LLM endpoints while blocking default Ark fallback leakage
Content flows now allow empty Ark API keys only when a custom Ark endpoint is configured. If both key and endpoint are empty, we fail locally instead of falling back to the public Ark endpoint, preserving the privacy guard while restoring ticket #192 keyless self-hosted behavior.

Constraint: Keep no-key self-hosted OpenAI-compatible LLM support from issue #192
Constraint: Prevent transcript content from being sent to default public Ark endpoint when key is empty
Rejected: unconditional API-key requirement in coordinator | breaks keyless self-hosted usage
Rejected: unconditional default-endpoint fallback | risks accidental data egress on fresh installs
Confidence: high
Scope-risk: narrow
Directive: Any future endpoint fallback change must preserve the blank-key + blank-endpoint local guard for content-sending flows
Tested: rustfmt --edition 2021 --check src/coordinator.rs; cargo test --lib resolve_ark_endpoint_
Not-tested: end-to-end UI interaction for keyless custom endpoint polish/translate/chat
2026-05-03 11:40:52 +08:00
H-Chris233 7e36d0756c Block keyless Ark content flows before default endpoint fallback
Polish, translate, and QA chat now fail locally when ArkApiKey is blank, so fresh installs and keyless LLM setups do not leak transcript content to the default public Ark endpoint. Model discovery remains keyless because it is a separate non-content path.

Constraint: LLM model discovery must stay keyless
Rejected: rely on downstream provider auth failures | leaks user content over the network
Confidence: high
Scope-risk: narrow
Directive: Keep the blank-key guard ahead of any Ark endpoint fallback in content-sending flows
Tested: cargo test --lib require_ark_api_key_rejects_blank_key; rustfmt --edition 2021 --check src/coordinator.rs
Not-tested: full UI settings flow
2026-05-03 10:03:39 +08:00
TRIP 7f64a1b464 fix(ci): allow PR-Agent review on external PRs 2026-05-03 09:55:17 +08:00
H-Chris233 1d0dcef18c Skip auth header for blank-key LLM model discovery
Model discovery now matches the keyless LLM path by omitting Authorization when the stored API key is blank. This keeps Fetch models usable for endpoints that reject empty Bearer credentials while preserving authenticated discovery for configured providers.

Constraint: ASR still requires an API key
Rejected: send a fake or empty Bearer header | breaks keyless endpoints
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce auth headers for blank LLM keys without a provider-specific requirement
Tested: cargo test --lib fetch_provider_models_omits_authorization_when_api_key_is_empty; rustfmt --edition 2021 --check src/commands.rs
Not-tested: full frontend integration flow
2026-05-03 09:51:39 +08:00
H-Chris233 0fe00ced9a Allow LLM validation without a saved API key
Some OpenAI-compatible LLM endpoints do not require an API key, so the LLM validation and runtime polish paths should not invent one or fail early when the key field is blank. The client now omits the Authorization header when the key is empty, the coordinator stops treating a blank LLM key as a hard error, and the settings validation continues to distinguish a missing model from a genuinely failed connection.

Constraint: Keep the change minimal and preserve the existing HTTP-status error mapping.
Rejected: Keep key-required behavior for all LLM endpoints | it mislabels keyless endpoints such as local 11443-style servers as invalid.
Confidence: high
Scope-risk: moderate
Directive: Empty LLM API keys are allowed only for the OpenAI-compatible path; ASR remains key-required.
Tested: npm run build; cargo test --lib
Not-tested: Live behavior against a real keyless endpoint outside the test harness
2026-05-02 23:32:27 +08:00
Chris233 280b50ea17 更新 pr-agent.yml 2026-05-02 21:16:12 +08:00
Chris233 dbd0503c55 Merge pull request #187 from H-Chris233/main
fix(settings): 用当前模型验证连接
2026-05-02 20:23:05 +08:00
Chris233 69d7f62161 更新 pr-agent.yml 2026-05-02 20:07:26 +08:00
H-Chris233 e99619948e Treat missing LLM model as unconfigured
The LLM connection check no longer falls back to an Ark-specific default model when the user has not configured one. Instead, it returns a dedicated marker and the settings UI surfaces the empty-state copy, which keeps the validation result aligned with the actual configuration state.

Constraint: Preserve the existing provider-status parsing and keep the change minimal.
Rejected: Keep the deepseek-v3-2 fallback | it creates a false positive for unconfigured non-Ark providers.
Confidence: high
Scope-risk: narrow
Directive: Validation should never invent a model when the user has not saved one.
Tested: npm run build; cargo test --lib
Not-tested: Live provider behavior with a truly empty model field on a real endpoint
2026-05-02 19:59:09 +08:00
Chris233 4027909a8c 更新 pr-agent.yml 2026-05-02 19:23:44 +08:00
Chris233 14149207a4 更新 pr-agent.yml 2026-05-02 19:15:19 +08:00
Chris233 dbb95abab7 更新 pr-agent.yml 2026-05-02 18:55:56 +08:00
Chris233 f7c0c59408 创建 pr-agent.yml 2026-05-02 17:40:27 +08:00
H-Chris233 5725e4433a Preserve provider HTTP markers in LLM validation failures
LLM validation now maps non-2xx completion responses back to the same providerHttpStatus:<code> marker used by the model-listing path. That keeps the settings page on its existing error-copy branch so real API-key, endpoint, and model failures stay diagnosable instead of collapsing into a generic message.

Constraint: Keep the change minimal and preserve the existing settings error-message parser.
Rejected: Teach the frontend to parse LLMError::InvalidResponse text | this would duplicate provider-status semantics and broaden the UI change.
Confidence: high
Scope-risk: narrow
Directive: Validation error strings for provider status should stay normalized at the command boundary.
Tested: cargo test --lib
Not-tested: Live provider error text against a real non-2xx endpoint
2026-05-02 17:03:55 +08:00
Chris233 a259b57d5e Merge branch 'appergb:main' into main 2026-05-02 16:11:42 +08:00
baiqing 89dd4e49bb chore: release 1.2.12 2026-05-02 12:19:28 +08:00
TRIP 7aefb8199e Merge pull request #181 from Cooper-X-Oak/codex/windows-native-titlebar-off
fix(windows): 收紧主窗口 shell 外观契约
2026-05-02 12:18:12 +08:00
Cooper-X-Oak 802ee653c9 fix(windows): 收紧主窗口 shell 外观契约 2026-05-02 12:12:46 +08:00
Cooper-X-Oak 946d842023 fix(windows): restore custom chrome interactions 2026-05-02 12:12:02 +08:00
Cooper-X-Oak 4ea8389ceb fix(windows): align custom shell rounded frame 2026-05-02 12:12:02 +08:00
Cooper-X-Oak f83a5339c7 fix(windows): remove native titlebar before first show 2026-05-02 12:12:02 +08:00
TRIP a2d243f333 Merge pull request #182 from Cooper-X-Oak/codex/windows-capsule-geometry-pr
fix(windows): 收紧 Capsule 几何契约
2026-05-02 12:11:51 +08:00
baiqing 9fd726ec87 test(windows): 对齐 capsule geometry 新契约断言 2026-05-02 12:06:22 +08:00
Cooper-X-Oak 9875e089d8 fix(windows): 收紧 capsule 几何契约 2026-05-02 12:05:09 +08:00
Cooper-X-Oak f8c5337084 docs(windows): 为 issue 142 建立 capsule 占位 2026-05-02 12:04:28 +08:00
TRIP 13d9d29233 Merge pull request #180 from appergb/fix/issue-165-linux-contract-alignment
fix(linux): 收敛平台契约错配与 best-effort 降级
2026-05-02 11:53:24 +08:00
TRIP 9510611a82 Merge pull request #179 from appergb/fix/issue-167-clipboard-restore-queue
fix(windows): 收敛 clipboard restore 并发恢复竞态
2026-05-02 11:49:22 +08:00
TRIP ae6be2defc Merge pull request #178 from appergb/fix/issue-164-qa-window-no-activate
fix(windows): QA 浮窗显示时不再抢前台焦点
2026-05-02 11:49:14 +08:00
TRIP 652b6d7bab Merge pull request #177 from appergb/fix/issue-166-mic-permission-no-activate
fix(mic): dictation 缺麦克风权限时不再抢前台焦点
2026-05-02 11:49:06 +08:00
baiqing dd7c02558f fix(linux): 收敛平台契约错配与 best-effort 降级 (closes #165) 2026-05-02 11:48:15 +08:00
baiqing d74d947106 fix(windows): 收敛 clipboard restore 并发恢复竞态 (closes #167) 2026-05-02 11:41:40 +08:00
baiqing 6a915c762f chore(windows): 补齐 QA no-activate 依赖锁文件 2026-05-02 11:40:06 +08:00
baiqing d4e7a8b4fe fix(windows): QA 浮窗显示时不再抢前台焦点 (closes #164) 2026-05-02 11:38:30 +08:00
baiqing 1fc6d9bd3f fix(mic): 听写路径请求麦克风权限时不再抢前台焦点 (closes #166) 2026-05-02 11:35:45 +08:00
TRIP 0c4fbb9815 Merge pull request #176 from appergb/fix/issue-161-qa-cancel-race
fix(qa): 修划词追问浮窗 4 个取消 race (closes #161)
2026-05-02 11:34:30 +08:00
baiqing db27107e7a fix(qa): 修划词追问浮窗 4 个取消 race (closes #161)
issue #161 4 个子修复合并为一个 PR(取消相关,紧密耦合)。

## 1. Esc 路由
coordinator.rs::handle_window_hotkey_event 之前无条件 cancel_session(dictation
取消),即使在 QA 浮窗里按 Esc 也杀的是 dictation。现在先查 qa_state.panel_visible
+ phase != Idle,是 → close_qa_panel;否 → 走 dictation 取消。

## 2. SSE 流取消旗标
- Inner 加 qa_stream_cancelled: Arc<AtomicBool>
- begin_qa_session 重置 false
- cancel_qa_session set true
- polish.rs::chat_completion_history_streaming 的 SSE loop 每帧检查
  should_cancel() flag,true 时立即 break,避免取消后 LLM 继续 drain
  HTTP body 烧 token

## 3. session_id 守卫
on_delta 闭包捕获本会话的 captured_session_id;emit chunk 前比对当前
qa_state.session_id,不等就跳过。修复"取消后开新会话,旧 LLM 流的
chunk 漏进新气泡"。

## 4. loading 帧
types.ts::QaStateKind 加 'loading';QaPanel.tsx switch 加 case:把 status
切到 'thinking' 视图,避免 ASR finalize 期间 UI 卡 'recording' 几百 ms
反馈缺失。

## API 变化
- polish::answer_chat_streaming<F, C> 签名加 should_cancel: C
- polish::chat_completion_history_streaming<F, C> 同
- coordinator::answer_chat_dispatch<F, C> 同

## 测试
- cargo check ✅
- npm run build ✅
2026-05-02 10:56:40 +08:00
TRIP f5ffd9ef0f Merge pull request #175 from appergb/fix/issue-168-qa-recorder-error-monitor
fix(qa): QA recorder error monitor (closes #168)
2026-05-02 10:51:36 +08:00
TRIP fcd37fbc71 Merge pull request #174 from appergb/fix/issue-169-macos-exit-main-thread
fix(macos): stop_qa_hotkey_listener 包 run_on_main_thread (closes #169)
2026-05-02 10:51:30 +08:00
baiqing 65d4b5243b fix(qa): 加 QA recorder runtime error monitor (closes #168)
QA 录音中麦克风设备消失 / cpal 内部 panic 时,QA 流程之前**没有**对应
runtime error 监听器(recorder_errors 用 _ 弃用),导致:
- QA 浮窗一直显示"录音中"
- 用户按 Option 第二次没反应
- 必须按 Esc 才能脱困

修:
- 新增 spawn_qa_recorder_error_monitor,镜像 dictation 现有 spawn_recorder_error_monitor
- begin_qa_session Recorder::start 成功后启动监听器
- 用 qa_state.session_id 守卫 stale 事件
- 收到 error → finish_qa_with_error("录音设备异常: ..") → emit 错误胶囊 + 浮窗错误状态

测试:
- cargo check ✅
2026-05-02 10:46:03 +08:00
TRIP ca7b68053b Merge pull request #173 from appergb/fix/issue-162-qa-level-listener
fix(qa): QaPanel 加 qa:level 监听 + LevelBar (closes #162)
2026-05-02 10:44:48 +08:00
baiqing 7ac0421a3f fix(macos): stop_qa_hotkey_listener 包 run_on_main_thread (closes #169)
QaHotkeyMonitor::drop 在 macOS 底层调 Carbon RemoveEventHotKey,要求主线程。
RunEvent::Exit 回调不保证在 AppKit 主线程跑——drop 漏到 tokio worker 上
触发 macOS dispatch_assert_queue_fail SIGTRAP,退出时偶发崩溃。

修:
- coordinator.rs::stop_qa_hotkey_listener 把 .take() 包到 run_on_main_thread
- AppHandle 已 None 时(极端 shutdown 序)直接 drop 兜底(最坏崩也是退出时机)

测试:
- cargo check ✅
2026-05-02 10:44:25 +08:00
TRIP e0614e3c7e Merge pull request #172 from appergb/fix/issue-163-windows-startup-gate-timeout
fix(windows): 启动 gate pollHotkeyStatus 加 10s 超时 (closes #163)
2026-05-02 10:43:33 +08:00
baiqing a8f4b891a0 fix(qa): QaPanel 加 qa:level 监听 + LevelBar 电平条 (closes #162)
后端 coordinator.rs:1743 在 QA 录音时每帧 33ms 推 qa:level 事件,
但 QaPanel 之前只 listen qa:state / qa:dismiss,qa:level 完全无人接 →
QA 录音用户看不到电平反馈,不知道麦克风是否收音。

修复:
- QaPanel 加 listen('qa:level') 累积 level state(cleanup 加 unlistenLevel)
- 新增 LevelBar 组件:4px 高蓝色进度条,宽度 = level × 100%
- RecordingHeader / TurnIndicator(recording) 都加 LevelBar 渲染
- 状态切换非 recording 时 setLevel(0) 避免残留

测试:
- npm run build ✅
- macOS 实测:QA 录音电平条跟随声音起伏(同 capsule 体验)
2026-05-02 10:38:44 +08:00
baiqing 4627eb4615 fix(windows): 启动 gate pollHotkeyStatus 加 10s 超时 (closes #163)
Windows 上 OS 拒绝低层键盘 hook 安装(反作弊/EDR/UAC 拦)时,
hotkey 永远 starting → 前端 while(!cancelled) 永不退出 → UI 卡 "正在启动" 灰屏。

加 50 × 200ms = 10s 上限:超时后强 setGate('ready'),让用户能进 Permissions
页看 hotkey_status.lastError 处理(页面已能显示错误 + 重试入口)。

非 Windows 路径不变。

测试:
- npm run build ✅
2026-05-02 10:36:13 +08:00
TRIP 490b391022 Merge pull request #171 from appergb/chore/issue-170-cleanup-warnings
chore: cargo clippy --fix 清理 small lints (closes #170 第一波)
2026-05-02 10:35:20 +08:00
baiqing f9d31b68c8 fix(insertion): 修 clippy --fix 误删的 Duration import 在 Windows/Linux cfg 下被用 2026-05-02 10:30:10 +08:00
baiqing 6fde92417b chore: cargo clippy --fix 自动清理小手术 (closes #170)
cargo clippy --fix 自动修了 8 个 lint,warnings 从 18 降到 16。

改动文件:
- asr/mod.rs / coordinator.rs / hotkey.rs / insertion.rs / polish.rs / types.rs
- 主要是 needless_borrow / single_match / useless_conversion / 多余 cast

build 跑过:
- cargo check ✅
- npm run build ✅

剩余 16 个 warning 都是有意保留的(test-only helpers、future-API placeholder、
类似 TodayMetrics 这种历史接口),不动这些避免破坏 surface。issue #170
里更深层的整洁度(SettingsWriter dedupe / force 参数删除等)后续 PR 跟进。
2026-05-02 10:24:21 +08:00
TRIP 68298d253c Merge pull request #138 from Cooper-X-Oak/codex/auto-update-download-acceleration
fix(tauri): 加速自动更新下载
2026-05-02 09:51:13 +08:00