H-Chris233
67bb14ec40
Restore foreground Windows hotkey edges
...
Windows can deliver modifier-only key events to the focused WebView without the low-level hook seeing the same edge, so the main window now forwards only hotkey-relevant DOM key events to the coordinator. Both native hook and window-forwarded events share the same coordinator edge gate so a working hook does not double-trigger toggle sessions.
Constraint: Issue #85 requires OpenLess foreground Right Control to reuse existing pressed/released/cancel semantics without changing global hook behavior
Rejected: Start dictation directly in the frontend | would duplicate coordinator state-machine semantics
Rejected: Keep a separate window-held flag | review found it can double-trigger toggle mode when both DOM and low-level hook report the same physical press
Confidence: medium
Scope-risk: moderate
Tested: cargo check --manifest-path openless-all/app/src-tauri/Cargo.toml
Tested: cargo test --manifest-path openless-all/app/src-tauri/Cargo.toml window_key_matcher_mirrors_windows_trigger_aliases
Tested: npm run build
Tested: git diff --check
Not-tested: Physical Windows foreground Right Control on this Linux host
2026-04-30 18:16:59 +08:00
baiqing
1efc20b2b2
chore(release): bump 1.2.2 -> 1.2.3 + 自有 updater pubkey + 重启前 strip xattr
...
修复 Codex audit 对 main HEAD a9c81e6 的 2 条 HIGH + 把 macOS auto-update 的
"重启后 Gatekeeper 拦截"问题封死。
## HIGH #2 : 版本号不一致
PR #84 没顺手 bump 版本,main 仍自报 1.2.2,下次直接打 v1.2.3-tauri 会让 updater
manifest 自报 1.2.2,已安装的 1.2.2 客户端永远拿不到 "有新版本"。
修:package.json + tauri.conf.json + Cargo.toml 全部改 1.2.3。
## HIGH #1 : updater pubkey 所有权
PR #84 使用的 pubkey 是外部贡献者本地生成的,appergb 不掌握对应 private key。
任何持有那把私钥的人都能签发更新 -> 客户端 OTA 装上恶意版本。
修:
- 用 npx @tauri-apps/cli signer generate --ci 生成 appergb 自己的 keypair
- 新 pubkey: F0FCDE68E08E6D4E (写入 tauri.conf.json plugins.updater.pubkey)
- 私钥已通过 gh secret set TAURI_SIGNING_PRIVATE_KEY 配到 GitHub repo secret
- 私钥本地副本只在 /tmp,不进 git,commit 后会清除
## macOS auto-update 后 strip xattr
restart_app 在 app.restart() 前对 .app bundle 跑 /usr/bin/xattr -cr。这是
Tauri auto-updater + 未公证应用的组合下唯一让"自动更新对用户零摩擦"的解法 —
否则 Gatekeeper 在重启时会拦说"OpenLess 已损坏",用户必须开终端 xattr 才能
继续用,违反 auto-update 的本意。
未来发版逻辑必须保留这一步。release-tauri.yml 上一次 PR (#83 ) 已经在 CI 侧
strip 过一次,本次在 client 侧重启时再 strip 一次,双保险覆盖
"下载 -> 解压 -> 安装 -> 重启"全链路。
2026-04-30 17:41:50 +08:00
baiqing
a9c81e6e0e
feat(updater): 增加应用自动更新入口 ( #84 )
...
H-Chris233: closes #33。
实现 Tauri 内置 updater 集成:
- Cargo: tauri-plugin-updater v2
- tauri.conf.json: 加 updater 配置(pubkey + endpoint 指向 GitHub Releases latest)
- capabilities/default.json: 授予 updater:default 能力
- lib.rs: 注册 updater 插件 + restart_app 命令
- src/pages/Settings.tsx + i18n: 关于区域加'检查'按钮、检查/下载/安装/重启对话框流
- 新脚本 scripts/write-updater-manifest.mjs: release 侧从 build artifact 拉签名生成 manifest
- workflow: TAURI_SIGNING_PRIVATE_KEY env + 各平台 build 时 createUpdaterArtifacts true
注意:下次 v*-tauri tag 必须配 TAURI_SIGNING_PRIVATE_KEY secret,否则 CI 硬失败。
2026-04-30 17:20:32 +08:00
baiqing
786bc574a7
chore(release): bump 1.2.1 → 1.2.2 — 含 PR #82 凭据加载竞态修复
2026-04-30 15:00:00 +08:00
Chris233
df8846913a
fix(settings): 避免凭据加载前被空值覆盖 ( #82 )
...
* Prevent untouched credential fields from clearing secrets
Settings credential inputs can mount empty while readCredential is still pending. The field now waits for a successful read before enabling saves, tracks whether the user actually edited the value, and surfaces read failures without writing an empty credential back to storage.
Constraint: Issue #34 requires preserving existing credentials when the settings page is opened or blurred without edits.
Constraint: Keep secrets out of logs and UI.
Rejected: Add full E2E coverage now | larger test harness work than needed for the minimal bug fix.
Confidence: high
Scope-risk: narrow
Tested: npm install
Tested: npm run build
Tested: cargo check
Tested: git diff --check
* Keep credential fields recoverable after read errors
Review feedback identified that read failures left fields disabled while the temporary status disappeared. Read errors now leave the field interactive with a persistent readError status, and the credential-field status union is named explicitly for safer helper signatures.
Constraint: Preserve the issue #34 guard that only dirty loaded fields save credentials.
Rejected: Broader state-machine rewrite | unnecessary for this targeted review fix.
Confidence: high
Scope-risk: narrow
Tested: npm run build
Tested: cargo check
Tested: git diff --check
2026-04-30 14:58:53 +08:00
TRIP and baiqing
e3f91e849c
ci(release): 显式 strip macOS bundle xattr 作为 defense-in-depth ( #83 )
...
GitHub Actions 输出本来就不带 com.apple.quarantine (actions/upload-artifact
不跨机器持久化 xattr, softprops/action-gh-release 上传 binary stream 也不带),
但加这一步让 "云端 artifact 一定干净" 变成可验证的承诺, 未来 release 不会因
runner 环境变化退化.
用户下载到本地后浏览器/LaunchServices 仍会加 quarantine, 依赖 release notes
里的 xattr -cr 指引或一行安装命令处理.
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 14:56:22 +08:00
TRIP
90141e2731
Merge pull request #81 from appergb/develop
...
release(v1.2.1): 累积外部 PR + 终审 HIGH 修复
2026-04-30 14:31:30 +08:00
baiqing
ca31264b44
chore(release): bump v1.2.0 → v1.2.1
...
包含本轮所有合并:
- Codex 终审两条 HIGH (cancel race) 修复 (PR #79 )
- 6 个 Cooper-X-Oak/Codex bot PRs 自动合并 (#44 #49 #53 #68 #72 #73 )
- 2 个有冲突 PR 本地 rebase 后合并 (#66 cancel + 空转写并存 / #67 Windows docs)
- README 破图修复 (PR #80 )
- workflow-scope 受限的 #48 + #75 由用户在 GitHub UI 直接合并
3 处版本字段同步:package.json + tauri.conf.json + Cargo.toml
2026-04-30 14:31:05 +08:00
TRIP and baiqing
7a3a51a1ed
fix(readme): 修复 README 中破损的图片引用 ( #80 )
...
Resources/AppIcon.png 已在 commit 170283e(清理 Swift 残留)中删除,但 README.md
和 README.zh.md 顶部的 hero 图片仍然指向它,GitHub 上显示破图。
改为指向 Tauri 自身的图标:openless-all/app/src-tauri/icons/128x128@2x.png
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 14:27:46 +08:00
Cooper Oak and Cooper-X-Oak
7797d1479a
docs(windows): 补齐上游交付与测试工作流 ( #67 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:25:51 +08:00
Cooper Oak and Cooper-X-Oak
848cfc35c8
fix(windows): 收口录音会话失败态 ( #66 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:25:43 +08:00
Cooper Oak and Cooper-X-Oak
61177eafc3
ci(release): 补齐 macOS Tauri 产物发布 ( #75 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:21:54 +08:00
Cooper Oak and Cooper-X-Oak
ff694c07c1
fix(windows): 收敛启动和开发产物路径 ( #48 )
...
* fix(windows): 收敛启动和开发产物路径
* ci(windows): 校验运行时 smoke 脚本
---------
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:21:35 +08:00
Cooper Oak and Cooper-X-Oak
96ff66eb80
test(windows): 增加真机回归 smoke 矩阵 ( #73 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:19:29 +08:00
Cooper Oak and Cooper-X-Oak
b8988c3330
fix(windows): 缺失托盘图标时继续启动 ( #72 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:18:54 +08:00
Cooper Oak and Cooper-X-Oak
8de575d8de
fix(ui): 本会话内延后提供商配置提示 ( #68 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:18:18 +08:00
Cooper Oak and Cooper-X-Oak
ce0f00fd54
fix(windows): 校准麦克风权限探测 ( #53 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:17:42 +08:00
Cooper Oak and Cooper-X-Oak
bb7300ee85
fix(settings): 防止凭据字段清空已有密钥 ( #49 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:16:58 +08:00
Cooper Oak and Cooper-X-Oak
3d6870822f
test(windows): 增加低层热键钩子回归 ( #44 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:16:03 +08:00
TRIP
94c8507b5e
Merge pull request #78 from appergb/develop
...
release(v1.2.0): i18n + ASR 数据不丢失 + 状态机修复 + 单实例 + UI 动画补齐
2026-04-30 14:05:24 +08:00
TRIP and baiqing
bcd4d815c8
fix(coordinator): 关闭 cancel race 两处窗口期 — Codex audit HIGH #1 + HIGH #2 ( #79 )
...
closes Codex audit blockers on PR #78
## HIGH #1 — begin_session 内 await 期间 cancel 被覆盖
背景:volcengine open_session().await + Recorder::start 都是异步,期间用户按
Esc 调用 cancel_session 把 phase 改回 Idle 并 cancelled=true。但原代码后续无
条件 `state.phase = SessionPhase::Listening`,把 Idle 又翻回 Listening →
用户的 cancel 被吞掉,session 仍然继续。
修:
- 新增 `cancel_raced_during_starting(inner)` helper:持锁查 cancelled or phase
!= Starting
- ASR open_session().await 后调用:如已 race,asr.cancel() + 回 Idle
- Recorder::start Ok 分支用 BeginOutcome { Started / PendingStop / CancelRaced }
原子在同一 lock 内决定,CancelRaced 时清理 recorder + asr 资源不进 Listening
## HIGH #2 — cancelled check 与 inserter.insert 之间的窗口
背景:end_session 检查 cancelled 后到调用 inserter.insert 之间释放了 lock,
此时 Esc 触发 cancel_session 设 cancelled=true 已经晚了 — Cmd+V 即将发出,
撤销不掉。但 cancel_session 仍然 emit "已取消" → UI 与实际行为相反(已插入但
显示已取消)。
修:
- 新增 SessionPhase::Inserting:表示「已过最后一次 cancel 检查、即将/正在
调用 inserter.insert」的窗口
- end_session:把 polish 后的 cancel check + phase 转换 atomic 在同一 lock
内:cancelled → Idle + return;否则 → phase=Inserting 后 release lock 走 insert
- cancel_session:phase==Inserting → 直接 return(不设 cancelled、不 emit 取
消)。理由:物理上无法撤销 Cmd+V,硬装"已取消"只会让 UI 撒谎
cargo check 通过,13 个 warnings 全部是 pre-existing。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 14:05:04 +08:00
baiqing
d0d2da27a5
chore: merge origin/main into develop — 拉回 PR #45 的 polish 推理清理
2026-04-30 13:49:14 +08:00
TRIP and baiqing
e99fe6cfbd
fix(capsule): 终止态后 2 秒自动隐藏 — 覆盖 Done / Cancelled / Error 全部路径 ( #77 )
...
之前只有 Done 路径有 700ms 自动隐藏,cancel / 各种 error 都让胶囊一直挂着。
用户反馈:不论点 ✕ / ✓ / 中途出错 / 按 Esc,2 秒后底部胶囊都应自动消失。
修改:
- 新增 CAPSULE_AUTO_HIDE_DELAY_MS = 2000 + schedule_capsule_idle(inner, ms) helper
延迟后再次检查 phase==Idle 才 emit Idle,避免覆盖期间用户重新触发的 Recording
- Done 路径:原 700ms inline schedule 替换为 helper 调用 (2s)
- Cancelled 路径:cancel_session 末尾追加 schedule_capsule_idle
- Error 路径 5 处:mic 权限失败 / ASR 连接失败 / 录音启动失败 /
await_final 失败 / Whisper transcribe 失败,全部追加 schedule_capsule_idle
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:45:34 +08:00
TRIP and baiqing
1e101a3147
fix(coordinator): 会话状态机修复 — Starting 阶段补偿热键边沿 + Esc 取消支持 Processing ( #76 )
...
closes #51 , #52
## #51 — Starting 阶段忽略热键边沿
握手 ASR 期间(phase=Starting)的"停止"边沿(toggle 第二次按 / hold 松开)
之前被直接 _ => {} 掉,会话锁死直到用户再按一次或重启 app。
修:
- SessionState 加 pending_stop: bool
- handle_pressed Toggle/Starting → pending_stop = true
- handle_released Hold/Starting → pending_stop = true
- begin_session 转 phase=Listening 时 mem::replace 取出 pending_stop,
若为 true 立即 await end_session
## #52 — Esc 取消在 Processing 阶段无效
用户按 Esc 时若 end_session 已进入 Processing(润色 / 插入进行中),cancel
信号被忽略,文本仍插入到光标位置 → 数据无意写入用户当前 app。
修:
- SessionState 加 cancelled: bool
- cancel_session 设 cancelled=true(不再仅 Idle 之外 = 转 Idle)
Processing 阶段保持 phase=Processing 让 end_session 自己走完检查 + 收尾
- end_session 在 ASR 完成后、polish 之前 + polish 完成后、insert 之前
各检查一次 cancelled,命中即跳过 insert/history.append
新会话 begin_session 入口清两个 flag,避免遗留触发奇怪行为。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:36:39 +08:00
TRIP and baiqing
fea402dd15
fix(asr): 保证用户的话不丢 — partial 缓存 + 末帧排队 + Whisper 失败保留 buffer ( #74 )
...
closes #54 , #55 , #56
三件事,同一目标:用户的口述内容不能因为网络抖动 / 服务端关连接 / 凭证错误
而消失。
## #54 partial cache (volcengine.rs)
- SyncState 加 last_partial_text;每次非 final result 缓存当前累积文本
- 服务端 close(无 final 帧)和 receive loop Err(网络中断)路径不再直接 NoFinalResult
- 新增 fallback_to_partial_or_error:有 partial 就 signal_success(RawTranscript),
没有才 signal_error;外层 await_final_result 拿到的是已识别那段文字而非空
- 实测命中:网络抖动断线,用户至少拿到断线前那段已识别的话
## #55 audio finalize race (volcengine.rs)
- 新增 pending_sends: AtomicUsize + send_done: Notify
- consume_pcm_chunk 每个 spawn fetch_add(1),spawn 内发送完毕 fetch_sub(1) + notify
- send_last_frame 进函数先 await pending_sends == 0(800ms 上限避网络极端场景)
再发 leftover + NegativeSequence 末帧
- 防止:fire-and-forget 的 chunk-send 与末帧并发,末帧先到服务端 → 后续 chunk
被当成"流已结束"后多余帧丢弃 → 尾句吞掉
## #56 Whisper buffer 保留 (whisper.rs)
- 之前 transcribe 一进函数就 mem::take 把 buffer 清空,凭证错 / 网络挂 / 解析失败
都让 PCM 直接消失,无法重试也无法 fallback
- 改为先 clone (~960 KB / 30s 音频) → transcribe_inner → 成功才 clear buffer
- 失败时 buffer 保持,给上层"再试一次"或"留失败历史记录"留余地
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:33:54 +08:00
TRIP and baiqing
0d5bfa9b11
fix(infra): 接入 tauri-plugin-single-instance — 防止两份 OpenLess 共存导致重复粘贴 ( #71 )
...
closes #50
现象:/Applications/OpenLess.app 与 dev build 同时存在时,两个进程各自注册
macOS CGEventTap 监听全局热键。用户按 Right Option 一次:
- A 实例捕获 → ASR session 1 → polish → Cmd+V
- B 实例同时捕获 → ASR session 2 → polish → Cmd+V
结果:用户口述被插入两份。
修复:
- Cargo.toml: 加入 tauri-plugin-single-instance v2
- lib.rs: builder 第一个 plugin 即注册它;第二个进程启动时回调聚焦已有主窗口
激活信号通过 plugin 内部 socket 传递,无需额外 IPC 设计。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:28:50 +08:00
TRIP and baiqing
707eaa639b
fix(settings): 移除 SiliconFlow ASR 选项 — 后端未实现,选了必然失败 ( #70 )
...
closes #58
后端 coordinator.rs 只把 active_asr=='whisper' 路由到 WhisperBatchASR,其他全部
走 VolcengineStreamingASR + 火山凭证。设置页之前暴露 SiliconFlow 选项,用户选后
ASR 必然失败。
修复:从 ASR_PRESETS 删除 siliconflow 条目 + 删除 asrProvider==='siliconflow' 的
凭证字段分支。重新启用方案:在后端实现真正的 SiliconFlow ASR provider 后再加回。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:27:12 +08:00
baiqing
3640924c23
feat(animations): 全局补齐过渡反馈 — 22 处 transition + 页面切换淡入 + ProviderPrompt 弹窗动画
...
按 Codex agent A 的前端审计 fix-now 列表批量补齐:
**hover/active/focus 反馈(一行 transition 即可)**
- WindowChrome winBtnStyle: bg + color
- _atoms Btn: bg + color + border + shadow + transform
- FloatingShell sidebar nav / FooterIcon / 检查更新 / ProviderPrompt 两按钮
- History filter chip / 列表行
- Vocab input / chip
- Style 卡片 / 单卡 toggle / 整体 toggle
- Settings 分区 nav / 录音方式 segmented / Toggle / inputStyle / iconBtnStyle
- Capsule cancel/confirm(opacity + bg + transform)
- Onboarding 授权按钮
- Overview WeekChart bars(height + opacity)
**新增入场动画**
- 页面 tab 切换 ol-page-fade 0.18s(每次 setCurrentTab 重 mount key 触发淡入 + 上滑 4px)
- ProviderSetupPrompt ol-prompt-fade(背景)+ ol-prompt-pop(卡片)
- Vocab chip ol-chip-in(添加新词条时缩放淡入)
**保持不变**
- Capsule 自身的 audio bars 动画(上一轮已优化)
- SettingsModal 的 ol-modal-fade / ol-modal-pop(已有)
零功能变化、零 bug 风险。仅 CSS / inline style 添加。
2026-04-30 13:22:54 +08:00
Chris233
af9b2b62c0
Merge pull request #45 from H-Chris233/main
...
fix(polish): 过滤模型深度思考输出
2026-04-30 13:17:23 +08:00
baiqing
c3e434faa7
fix(modal): 设置弹窗去掉所有不能点的空壳,每个可见控件都接到真实后端
...
之前设置弹窗里有一组占位组件(SegSimple/SwitchLite/SelectLite),看起来可点
但只切换内部 useState,不影响任何实际行为。这次按 issue #69 的清单全清。
移除:
- AccountSection 整个 tab —— 没有账号系统,"登录/同步" 按钮无 onClick
- PersonalizeSection 的「外观(跟随系统/浅色/深色)」—— 没有 dark mode CSS
- PersonalizeSection 的「启动时打开(概览/上次位置)」—— 无对应 preference
- PersonalizeSection 的「开机自启」—— 无 autostart 集成
- 不再 import SegSimple / SwitchLite / SelectLite
接通:
- modal sub-nav 的「帮助中心」「版本说明」点击实际打开 GitHub README / Releases
- AboutMini 的「检查」「文档 ↗」「GitHub Issues ↗」三个按钮接到 openExternal
- modal nav 按钮加入 transition 动画(background/color 0.12s ease-out)
- 关闭按钮加 hover 反馈
保留可用:
- PersonalizeSection 的「界面语言」+「毛玻璃强度」—— 都已正常工作,保留
后续 issue:#69 跟踪未来要补回来的功能(账号 / 主题 / 启动项 / autostart)。
2026-04-30 13:13:36 +08:00
H-Chris233
32eb406d0b
Keep reasoning cleanup linear and conservative
...
Review feedback pointed out that repeated replace_range passes could become quadratic and that provider tags may vary by casing or attributes. The parser now scans the response once, allocates only when a complete think block is removed, and recognizes explicit think tags with optional attributes and ASCII casing variants.
Constraint: Keep cleanup conservative and avoid localized heading stripping.
Rejected: Regex dependency | unnecessary for one small tag parser.
Rejected: Strip broad reasoning headings | can remove valid user-facing prose.
Confidence: medium
Scope-risk: narrow
Tested: cargo test polish::tests -- --nocapture
Tested: cargo check
Tested: npm run build
2026-04-30 13:10:21 +08:00
baiqing
eb9fbabce0
fix: 胶囊波形/玻璃随电平实时跳动 + 词汇本命中后实时刷新
...
修三件事:
1. **波形不动** — 后端电平回调 ~185 Hz emit,CSS 0.12s transition 导致 22 个并行
transition 互相覆盖、视觉上被平均成静止。
- coordinator.rs: 节流 emit 到 30 Hz(33ms 最少间隔)
- Capsule.tsx: bars transition 改 0.06s linear,每次 emit 完整跳到目标高度
2. **玻璃静止** — 加电平驱动的微缩放 + 投影增强(≤2%),录音态整个胶囊在呼吸。
transition: transform 0.06s linear, box-shadow 0.06s linear。
3. **词汇本不实时** — record_hits 改完 dictionary.json 但前端不知道,需切 tab 才更新。
- coordinator.rs: total_hits > 0 时 emit('vocab:updated', total_hits)
- Vocab.tsx: useEffect 订阅 vocab:updated 后立即 refresh()
不改产品语义;不动 ASR / polish 路径。
2026-04-30 13:03:23 +08:00
baiqing
648df0579d
chore: 清理已废弃的 Swift 时代文档
...
用户明确:这些 docs/* 是已废弃 Swift 实现的产物,全平台 Tauri 后不再需要。
- 删除 18 份过时 architecture / requirements / release-notes / review 文档
- 不影响 Tauri 当前文档(CLAUDE.md / README / USAGE 仍在)
2026-04-30 12:51:50 +08:00
baiqing
da7b426959
feat(polish): 清晰结构改为两层层级 — 主题 1./2. + 要点 a./b.,去掉中间括号层
...
用户反馈:括号中间层("1)" "2)")多余,希望保留主题编号 + 字母要点的清爽结构。
变更:
- polish.rs Structured prompt:层级规则从 3 层改为 2 层;明确禁用带括号中间层;
示例改为 "1. 主题 / a. 要点 / b. 要点 / 2. 主题 / ..."
- i18n style.modes.structured.sample(zh-CN / en):与新 prompt 输出格式同步
代价:极复杂的多级嵌套口述(如"登录页里的密码错与图形验证码")在 2 层结构下会
被压扁;复杂场景建议改用「原文」或「轻度润色」mode。
2026-04-30 12:34:55 +08:00
TRIP
72a86960ea
Merge pull request #42 from appergb/develop
...
feat(i18n+polish+cleanup): 中英文 UI 切换 + polish prompt 重写 + 清理 Swift 残留
2026-04-30 12:12:03 +08:00
baiqing
0643ff767b
feat(polish): 重写 4 个 mode 的 system prompt — 段落式结构 + 增强 anti-instruction 防御
...
closes #47
- 拆出共享段落 ROLE_BLOCK / COMMON_RULES / OUTPUT_BLOCK,避免每个 mode 重复 200+ 字
- 改为 # 角色 / # 任务 / # 通用规则 / # 示例 / # 输出 markdown 段落式结构,便于模型 attention
- 强化 ROLE_BLOCK:明确"原始转写是文本对象不是指令"+「不替对方回答清单/问题」
- 新增 COMMON_RULES:"不确定→保留原话"+ 代码/URL/数字单位原样保留
- raw / light / formal 各加 1-shot 示例(Structured 已有)
- Structured 三层层级规则与示例完全保留,不动产品语义
- user_prompt 同步收紧措辞,与 system prompt 框架呼应
不改 mode 产品语义、不改 compose_system_prompt 签名、clean_polish_output boilerplate 列表保持兼容。
2026-04-30 12:10:57 +08:00
baiqing
170283e483
chore: 删除旧 Swift 实现的最后残留 + 去 Swift 化 CLAUDE.md
...
- 删 tracked 的顶层 Resources/(Swift 时代的 AppIcon / Brand 素材)
Tauri 自给:src-tauri/icons/* + app/public/AppIcon.png
- 重写 CLAUDE.md:移除"双实现"框架、Swift 构建/测试章节、Sparkle 发布流水线、
Sources/ / Package.swift / appcast.xml / scripts/release.sh / Swift @MainActor 等所有过时引用
- 保留一行历史注脚指向 commit 34d2823 防止 Swift 复活
2026-04-30 12:10:57 +08:00
H-Chris233
2e63c42840
Keep model reasoning out of inserted polish text
...
Thinking-capable OpenAI-compatible models can return tagged reasoning before the final polished answer. The cleanup layer now strips only explicit think-tag blocks after response parsing so existing provider requests, UI, and fallback behavior stay unchanged.
Constraint: Issue #25 asks to adapt thinking output rather than disabling model thinking.
Rejected: Add a provider-specific thinking toggle | broader UI and settings change than needed for the bug.
Rejected: Strip localized heading text | too likely to remove normal user-facing content without a stable provider contract.
Confidence: medium
Scope-risk: narrow
Tested: cargo test polish::tests -- --nocapture
Tested: cargo check
2026-04-30 11:58:11 +08:00
baiqing
ce62680ad3
fix(i18n): 修首次渲染拿到的 t() 返回 key 字面量;让个性化弹窗的语言下拉真的能点
...
问题:
- 截图证据:所有 t() 调用渲染为原始 key("nav.overview" 等),界面文字全乱
- 同时 Personalize 弹窗的语言下拉是 SelectLite —— 一个纯展示 div,点击无任何反应
根因:
- LanguageDetector 异步 init + react-i18next useSuspense=false 默认下首次渲染拿到 key
- SelectLite 不接受任何点击/选择事件
修复:
- 干掉 i18next-browser-languagedetector,手写 4 行 detectSystemLocale + getStoredLocale
- 显式 react: { useSuspense: false } + partialBundledLanguages: true
- main.tsx 改为 i18n 就绪后再 ReactDOM.render(双保险,避免任何竞态)
- Personalize 弹窗的语言行替换为可用的原生 <select> LanguagePicker,与 Settings → Language 共享同一 localStorage 偏好
2026-04-30 11:49:49 +08:00
baiqing
e1c0957631
chore: merge origin/main into develop
...
将 main 的 PR #41(coordinator hotkey 测试基础设施)合入 develop。
保留 develop 上的 i18n 变更与 main 的 hotkey 测试改动,无冲突。
2026-04-30 11:38:41 +08:00
Chris233
ac611d5151
Merge pull request #41 from H-Chris233/main
...
test(hotkey): 补齐热键自动注入门禁
2026-04-30 11:37:15 +08:00
baiqing
99d2e9d831
feat(i18n): 引入语言包系统,支持 zh-CN / en 切换 + 跟随系统
...
- 接入 react-i18next + i18next-browser-languagedetector,资源以 TS 模块静态打包
- 资源 src/i18n/{zh-CN,en}.ts;en.ts 通过 typeof 绑定 zh-CN 形状,缺 key 编译报错
- 全部 UI 表面(胶囊、Onboarding、主窗口侧栏/页脚、Overview/History/Vocab/Style 页、设置弹窗、设置页各分区、WindowChrome)改走 t() 查找
- SettingsSectionId 从 zh-CN 字面量切换为稳定 EN id(recording/providers/...);ModalSectionId 同改
- 设置 → 语言 分区新增「跟随系统 / 简体中文 / English」切换器,localStorage 'ol.locale' 持久化
- 首启检测顺序 localStorage → navigator.language;fallback 永远 zh-CN
- lib/hotkey.ts 改用 i18n.t 直接渲染触发键 / 适配器名称
Closes #40
2026-04-30 11:36:16 +08:00
H-Chris233
8df0fb1f6c
Prove coordinator hotkey handling without physical keys
...
Windows regression currently depends on a tester pressing a real modifier key, which cannot distinguish OS-hook delivery failures from coordinator state-machine failures. Add a debug/test-only injection path that drives handle_pressed and handle_released, logs the coordinator hotkey edge, and cancels the dry-run session automatically.
Constraint: Must not rely on SendInput or a physical keyboard for the coordinator gate.
Constraint: Keep physical hotkey testing as the OS hook coverage layer.
Rejected: Fake log-only gate | would not exercise the coordinator hotkey path.
Rejected: Production IPC command | unnecessary surface area for a test/dev-only gate.
Confidence: high
Scope-risk: narrow
Tested: npm run check:hotkey-injection
Tested: npm run build
Tested: cargo check
Tested: cargo check --release
Tested: git diff --check
Related: https://github.com/appergb/openless/issues/35
2026-04-30 11:26:26 +08:00
Chris233
4245ddf56f
Merge pull request #1 from appergb/main
...
feat(settings): 硅基流动 ASR/LLM 配置 + 关于页完善 + onAsrProviderChange bug 修复
2026-04-30 11:24:07 +08:00
baiqing
4a0d8efead
feat(settings): 硅基流动 ASR/LLM 配置 + 关于页完善 + onAsrProviderChange bug 修复
...
- LLM 供应商新增「硅基流动」(https://api.siliconflow.cn/v1,默认模型 Qwen2.5-7B)
- ASR 供应商新增「硅基流动 SenseVoice」(Whisper 兼容,默认模型 FunAudioLLM/SenseVoiceSmall)
- 修复 onAsrProviderChange 调用未定义 setPrefsState/setSettings 的 bug,改用 updatePrefs
- 关于页:新增源码入口(GitHub 链接)、QQ 群号 1078960553(可一键复制)
2026-04-30 10:54:05 +08:00
Chris233
85045c3ff4
chore(repo): 统一项目目录命名 ( #39 )
...
* Remove fragile space from active app path
The Tauri app lived under a path containing a literal space, which made CI paths and local commands easy to quote incorrectly. Rename the active tree to openless-all and update repository references so scripts, docs, and release workflows use the same space-free path.
Constraint: Preserve the existing app layout and move only the containing directory name.
Rejected: Add compatibility symlinks | would keep two app paths and leave quoting hazards in place.
Confidence: high
Scope-risk: moderate
Tested: npm run build
Tested: cargo clean && cargo check
Tested: git diff --check
Tested: grep -R for old openless -all and openless%20-all references
* Keep Windows build docs aligned with space-free path
The app directory was renamed to openless-all, but the GNU/MinGW route still described the new name as if it contained a space. Update the wording so the rationale matches the current path and keeps the helper-script guidance focused on consistent GNU setup.
Constraint: Documentation-only code review follow-up.
Confidence: high
Scope-risk: narrow
Tested: git diff --check
2026-04-30 10:44:31 +08:00
baiqing
7f83bca5b6
docs: 更新 README / USAGE / CLAUDE.md 至 Tauri v1.1 现状
...
- 两个 README 改为描述 Tauri 2 + Rust + React/TS,macOS 12+ 和 Windows
- Badges:去掉 Swift/macOS15+,加 Tauri/Rust/Windows/macOS12+
- 状态章节:v1.0 Swift → v1.1 Tauri
- 构建说明:Tauri 优先,Swift 降为 legacy
- 架构章节:更新为 Tauri 模块表
- Roadmap:删除已完成项(Developer ID + Sparkle)
- 下载说明:更新为 DMG/MSI 安装流程
- 发布检查:更新为 tag CI 流程
- 新增 USAGE.md(快速上手指南,中文)
- QQ 群号 1078960553 加入显眼位置(README 标题区 + USAGE)
- CLAUDE.md:补充 whisper ASR、HotkeySettingsContext、cargo check
2026-04-30 09:12:31 +08:00
baiqing
cecbb31c22
feat: ASR 供应商切换 + 设置页自动保存
...
- 新增 Whisper 批量 ASR:录音完毕后将 PCM 编码为 WAV,POST 到任意 OpenAI 兼容端点
- persistence: 增加 AsrApiKey / AsrEndpoint / AsrModel 凭据账户,支持活跃 ASR 供应商读写
- coordinator: 引入 ActiveAsr 枚举,begin/end/cancel_session 按 active.asr 路由到 Volcengine(流式)或 Whisper(批量)
- 设置页"提供商"新增 ASR 供应商下拉(火山引擎 / Whisper),切换后自动更新凭据与偏好
- CredentialField 改为防抖 300ms 自动保存,失焦立即保存;设置关闭前不再丢数据
2026-04-30 09:12:31 +08:00
Chris233
82a24faa83
fix(hotkey): 收口桌面热键适配边界 ( #38 )
...
统一热键适配边界:macOS 保留 CGEventTap,Windows 改用原生 WH_KEYBOARD_LL hook,前端热键展示改为读取后端 capability/status。
2026-04-30 08:58:55 +08:00
baiqing
eec4c37c38
feat: LLM 供应商选择、胶囊焦点修复、默认配置填入
...
- 设置 > 提供商:新增供应商下拉(ARK / DeepSeek / OpenAI / 自定义)
切换供应商自动填入 Base URL,凭据字段随供应商 key 重挂载
- ASR Resource ID:空值时显示填入默认按钮(默认值 volc.bigasr.sauc.duration)
- 焦点 bug:胶囊 show() 后若 OpenLess 已是前台 app 则用 makeKeyWindow
还原主窗口焦点,不调 NSApp.activate,不抢其他 app 光标
- 后端:新增 set_active_llm_provider 命令,更新 credentials.json active.llm
2026-04-29 22:50:44 +08:00