TRIP and HKLHaoBin
6f9af89583
release: OpenLess 2.0.0-Beta.4+build.20260930 ( #1126 )
...
Integrate ASR/Omni fixes, API Route, Android IME and confirmation-based vocabulary learning. Complete settings transitions and macOS single-item credential storage. Synchronize all application versions to 2.0.0-Beta.4+build.20260930.
Integrated PRs: #1116 , #1120 , #1121 , #1123 , #1124 , #1067 and #1128 . Linux #1117 remains independent and is excluded from automatic release.
Validated: full cross-platform CI, 18 UI motion cases, 112 frontend test files, 1245 Core tests (1 ignored) and 572 macOS native tests.
Co-authored-by: HKLHaoBin <we3q@qq.com >
2026-09-30 20:32:53 +08:00
TRIP
867a0d8ce7
Merge pull request #1059 from Open-Less/fix/omni-view-apple-speech-validation
...
fix(settings): 多模态管线 Omni 视图入口与 Apple 语音验证误报
2026-09-11 13:17:58 +08:00
TRIP
7e2e48b5dd
Merge pull request #1053 from Open-Less/feat/cloud-sync-backend
...
feat(sync): 云同步专用端口 apic.openless.top:9443、按钮间距与云同步服务端交接文档
2026-09-10 21:55:22 +08:00
TRIP
d3aa3c5cbd
Merge pull request #1051 from Open-Less/feat/ui-2.0-model-settings-page
...
2.0 模型设置页与使用页:目录元数据、使用中模型选择、残留清理
2026-09-10 19:50:13 +08:00
TRIP
fe95354e25
Merge pull request #1050 from Open-Less/feat/ui-2.0-model-settings
...
2.0 模型设置界面 + macOS 修复批次(合入 beta 最新四项)
2026-09-10 17:47:28 +08:00
TRIP
2ca2a48c52
chore(cask): update OpenLess to 1.3.17
...
Release follow-up: apply the cask update through the required PR path after the automated direct push was rejected.
2026-08-15 21:19:18 +08:00
TRIP and sim
26f928cad3
fix(local-asr): 下载弹窗全量目录 + 抖动/模糊修复 + HF 模型卡片 ( #928 )
...
* fix(local-asr): 下载弹窗全量目录 + 抖动/模糊修复 + HF 模型卡片
- 下载弹窗左侧空列表死锁:allSidebarEntries 把未下载模型过滤掉了,
零下载用户弹窗内无模型可选、开始下载禁用;改为全目录展示,弹窗
默认选中第一项,开始下载回退到第一个未下载条目
- 弹窗上下抖动 + 画面模糊/清晰闪烁:ol-window-enter 去掉 filter blur
(fill-mode both 保留终帧 + will-change:filter 在 WKWebView 反复重栅
格化),WindowChrome willChange 去 filter;弹窗卡片动画 spring 过冲
改 --ol-motion-soft;弹窗打开时暂停 3s 轮询,遮罩后看板不再跳动
- 右侧直接展示 HF 模型卡片(HF 禁止 iframe 嵌入):新增
local_asr_fetch_hf_card 命令(downloads/likes/cardData.summary,
summary 缺失回退 README 首段),弹窗右侧显示下载量/收藏数/简介
* fix(local-asr): 下载弹窗遮罩误关 + 切换闪烁根治(去 backdrop-filter 死代码 + 卡片预加载)
- 画面「闪一下又恢复」合成层根源:WindowChrome 根节点 backdrop-filter
blur(36px) 在非透明窗口(--ol-window-bg 不透明渐变)是纯开销死代码,
macOS WKWebView 切换模型/下载中高频重渲染时合成层故障 → 整窗瞬间
消失恢复。全平台统一 none,视觉无变化
- 下载弹窗遮罩误关:busyModelId 在下载启动后即清空(Rust 同步返回),
下载中 busy 恒 false → 点遮罩下的「下载与存储设置」落在遮罩上弹窗
直接关闭,像被按了叉。新增 anyDownloadInFlight(progress phase 判定)
驱动弹窗 busy 与「+下载新模型」禁用,下载中遮罩点击不关闭
- 切换闪烁:弹窗打开时预加载全部条目 HF 卡片(缓存),切换选项右侧
直接出数据,无「加载中→内容」替换
- 弹窗左栏对齐设置页:rail 背景 + 200px 宽度,条目去掉外边框
* fix(local-asr): 下载弹窗重写——去入场动画与卡片预加载(WKWebView 闪烁根因),标题改「下载模型」,README 简介提取增强
---------
Co-authored-by: sim <sim@local>
2026-08-06 19:50:02 +08:00
TRIP and sim
b68a5901c3
feat(selection-polish): Linux 支持——fcitx5 插件热键路由 + PRIMARY 选区校验 ( #927 )
...
* feat(selection-polish): Linux 支持——fcitx5 插件热键路由 + PRIMARY 选区校验
- linux_fcitx.rs:新增 SetSelectionPolishHotkeyRaw DBus 方法 + sync_selection_polish_binding;
start_dictation_signal_listener 增加 selection_polish_trigger 参数,监听
SelectionPolishEvent 信号 → HotkeyEvent::SelectionPolishShortcutPressed,
初始同步与 fcitx5 重启重同步均含选区润色触发键
- hotkey.rs Linux adapter:update_modifier_shortcuts 转发 selection_polish_trigger
(移除 disabled on Linux 注释)
- hotkey_loops.rs:Linux 启动 fcitx5 监听时传入 selection_polish_trigger
- selection.rs Linux 分支:is_captured = PRIMARY 读到选区即可;validate 重读
PRIMARY 与捕获文本比较(用户改选/清空即拒绝粘贴);selection_text_matches
cfg 覆盖 linux
- fcitx5 插件 openless.cpp:新增 SelectionPolishEvent 信号 +
SetSelectionPolishHotkeyRaw 方法(INI 持久化 SelectionPolishRawSym/States),
按键分发仿 QA 模式;需重装插件(scripts/inject-fcitx5-plugin.sh)生效
- 注:Linux 代码由 Linux CI 验证编译;fcitx 插件 .so 需 Linux 环境重编译安装
* fix(selection-polish): 补传 selection_polish_trigger 到 fcitx 监听器(第二个调用点)
coordinator.rs 的 hotkey 安装路径调 start_dictation_signal_listener 时漏传
selection_polish_trigger(签名 7 参数只传 6 个),Linux CI E0061。hotkey_loops.rs
已传,此处遗漏导致 Linux 编译失败。
---------
Co-authored-by: sim <sim@local>
2026-08-06 19:32:39 +08:00
TRIP and sim
b62e2324c5
feat(selection-polish): macOS 移植——前台应用+选区文本指纹校验与默认热键 ( #926 )
...
- selection.rs:SelectionInsertionTarget 增加 macos 字段(前台应用名 + pid);
capture/is_captured/validate/reactivate 四函数实现 macOS 分支:
* validate = 前台应用一致性 + 选区重读(AX 直读,失败退化为模拟 Cmd+C)比较
* reactivate = NSRunningApplication activateWithOptions 交还焦点
- types.rs:macOS 默认选中润色热键 = RightAlt(右 Option,CGEventTap keycode
61 可区分左右,不占用 Cmd/Ctrl 常用组合),与 Windows 保持一致
- capabilities:selection-polish-preview 窗口加入默认能力列表(预览窗事件
listen 之前会被 ACL 拒绝)
- SelectionPolishSection:设置入口去掉 os==='win' 门控,macOS 可见
- 单测:selection_text_matches 随 cfg 扩展在 macOS 编译,940 pass
Co-authored-by: sim <sim@local>
2026-08-06 05:08:58 +08:00
TRIP and sim
df1a42c3a9
fix(local-asr): 下载进度全局浮层 + 事件节流 + 取消清理 + 看板过滤 + 3s 文件监测 ( #925 )
...
- 进度浮层全局化:新 GlobalDownloadProgress 自监听三引擎下载事件,挂 App 根,
主窗口所有页面常驻显示;含取消按钮(按引擎分派 cancel 命令)
- Rust 进度事件 ≥150ms 节流(qwen3/sherpa/foundry),修进度条高频抽搐
- 取消下载清理 .partial/.partial.idx(sparse 预分配全长,1.7B 模型残留巨大),
新增 remove_partial_artifacts 单测
- 看板只列已下载/下载中的模型(下载弹窗保留全目录列表),条目行距加大
- 3s 轮询磁盘状态 + 选中瞬间校验 + 下载事件驱动刷新;fetchAll 按平台分支
(macOS 上 sherpa/foundry catalog 命令未注册导致 Promise.all 整体失败)
- 同 provider 切换模型走轻量路径 + 乐观 draft 值,修下拉闪回旧模型
Co-authored-by: sim <sim@local>
2026-08-06 03:52:05 +08:00
TRIP and sim
29e7ecaeda
feat(settings): 模型 ID 直选 ASR 供应商 + 看板右侧布局改版 + 弹窗重合 ( #923 )
...
* feat(settings): 模型 ID 直选 ASR 供应商 + 看板右侧布局改版 + 弹窗重合
- ASR 供应商下拉:本地引擎的已下载模型直接以「引擎:模型ID」选项列出,
选中即使用该模型(不再需要先选引擎再选模型);下载完成后经进度事件自动刷新;
引擎级入口与删除后无匹配的兜底选项保留
- 下载弹窗改为与设置弹窗完全重合:垂直居中、同尺寸 880×600(此前顶部锚定偏高)
- 看板右侧改版:模型名在左上,Hugging Face 仓库/镜像源 pill 在右上;
下载 / 加载并测试 / 打开目录 / 删除 合并为底部一行;测试结果显示在看板里
(此前「加载并测试」无任何反馈,旧 ModelRow 是死代码)
- 删除看板「下载模型会自动出现在上方…」描述文案
* fix(settings): 平台不匹配时去掉重复的本地引擎兜底选项(pr-agent #923)
---------
Co-authored-by: sim <sim@local>
2026-08-05 18:40:58 +08:00
TRIP and sim
a580a8f32a
feat(settings): 本地 ASR 模型管理重构 + 提供商界面颜色/动画统一 ( #922 )
...
* feat(settings): 本地 ASR 模型管理重构——两栏看板 + 下载弹框 + 右上角进度 + 提供商本地模型标注
- 模型管理改为两栏看板:左侧模型选择(竖排,已下载绿勾,全平台 Qwen3 /
sherpa-onnx / foundry 归一化),右侧详情看板(HF 实时抓取的尺寸/文件数/
repo + 状态 + 操作按钮),嵌套在设置里作为单独板块
- 下载弹框:左侧模型选择 + 右侧大小/文件数详情,底部「开始下载」,布局与
看板一致(用户原话:单独的下载界面)
- 右上角下载进度浮层:Qwen3 与 sherpa 下载进度聚合 fixed 显示,完成/取消/
失败即消失
- ASR 提供商界面:本地引擎激活时直接展示本地已下载模型(标注「本地下载
(本地下载)」),可在此选用;Apple 语音显示零模型选择说明
- i18n:新增 19 个 key(5 语言)
* style(settings): 输入框/下拉底色统一 + 提供商下拉去 inputStyle + 检查更新按钮动画
- inputStyle 底色 surface-2 → select-trigger-bg:所有输入框(提供商凭据、
数据存储数字框等)与 SelectLite 下拉(麦克风/胶囊样式)颜色统一
- ProvidersSection 5 处 SelectLite 去掉 inputStyle,改 SelectLite 默认触发器
样式;LLM/ASR 供应商下拉固定 200 宽与麦克风对齐(用户反馈颜色与大小问题)
- CheckUpdateButton:状态图标颜色过渡 + 文案切换淡入动画(ol-select-value-in)
* fix(settings): 弹框 portal 到 body 修复定位/变灰 bug + 本地 ASR 逻辑重构
- DownloadDialog 全页式重设计:createPortal 到 document.body(WindowChrome
的常驻 transform/will-change 会创建 containing block,导致 fixed 弹框相对
设置面板定位、被裁剪且点不到),尺寸与设置弹窗一致、顶部锚定、左侧模型
选择 + 右上角 ✕ 关闭;GlobalDownloadProgress / UpdateDialog 同步 portal,
修复「弹框弹出时设置内容变灰、断层感」的同类 bug
- 本地 ASR 逻辑:删除 Qwen3/Foundry/Sherpa 启用开关与确认 modal——本地引擎
始终可用,激活 = 在 ASR 语音转写选择本地模型供应商(保留「实验性」标记);
供应商下拉直接列出本地引擎(标注「本地」)
- 删除「使用 Apple 语音」卡片:选中 apple-speech 供应商即等于使用
- 镜像源 / 模型存储位置 / 内存引擎收纳进「下载与存储设置」Collapsible(默认收起)
- 模型操作按钮:去掉「设为默认」,保留「加载并测试」(加载即激活为当前模型),
打开目录 + 删除同一行;修复本地模型选项标签「本地下载(本地下载)」文案 bug
- ASR 板块供应商切换时 keyed ol-tab-fade 动画
* fix(asr): sherpa/foundry 分派显式传 alias + 本地模型下拉受控 value
- dispatchEntryAction 的 setTimeout 闭包读的是当前 render 的 selected*Alias,
点非当前选中的模型会操作到上一个模型;四个 handler 改为接受 alias 参数并显式传递
- ProvidersSection 本地模型下拉 value 固定为第一个已下载模型,选择不生效;
新增 selectedLocalModelId 受控状态,随后端 active 模型与已下载列表联动
* fix(asr): 删除当前选中模型后回落选择 + Foundry 下载改顺序执行
- useLayoutEffect 只在 selectedModelId 仍存在于条目列表时提前返回,删除选中
模型后自动落到第一个已下载模型(pr-agent #922)
- Foundry 侧栏「下载」由并行 enable+prepare 改为 handleEnableAndPrepareFoundry
顺序执行:消除 foundryBusy 竞态与 syncFoundryPrefs(true/false) 冲突
---------
Co-authored-by: sim <sim@local>
2026-08-05 17:46:13 +08:00
TRIP and sim
c0e2213840
[cask] openless 1.3.16 (auto from release) [skip ci] ( #921 )
...
Co-authored-by: sim <sim@local>
2026-08-05 16:22:50 +08:00
TRIP and Chris233
d31bf5bbb7
fix(asr): 过滤 GLM-ASR 偶发的纯井号占位转写(#787) ( #916 ) ( #920 )
...
Co-authored-by: Chris233 <h-chris233@outlook.com >
2026-08-05 15:32:30 +08:00
TRIP and sim
b83b566cb4
chore(release): prepare 1.3.16(正式版版本号) ( #919 )
...
1.3.16-Beta.1 → 1.3.16(package.json / package-lock.json / tauri.conf.json /
Cargo.toml [package] / Cargo.lock openless 块;手工编辑,bump-version.sh 不支持
-Beta.N 后缀,keyring 依赖 3.6.3 已锚定 section 未被误改)
Co-authored-by: sim <sim@local>
2026-08-05 15:17:51 +08:00
TRIP and sim
d31cafd2d8
chore(release): prepare 1.3.16-Beta.1 ( #913 )
...
版本号 1.3.15 → 1.3.16-Beta.1(package.json / package-lock.json /
tauri.conf.json / Cargo.toml [package] / Cargo.lock openless 块,手工编辑——
bump-version.sh 不支持 -Beta.N 后缀,keyring 依赖版本 3.6.3 已锚定 section
未被误改)
Co-authored-by: sim <sim@local>
2026-08-04 18:23:47 +08:00
TRIP and sim
1fd9b43da5
fix(capsule): 切换样式立即生效 + 设置动画/视觉统一(Windows 样式切换修复) ( #912 )
...
* fix(capsule): 切换样式立即生效——设置保存即同步样式原子 + prefs:changed 即时下发
修复 Windows/Linux 上「切到默认风格仍显示流光 Siri」:样式原子此前只靠
emit_capsule 主线程闭包 ~30Hz 同步,入场帧 payload 又是同步前克隆的旧值,
Windows 主线程拥塞时闭包延迟会让整场录音下发旧样式。现在 set_settings 保存
时直接同步原子,任何平台下次录音从入场帧起就携带最新样式;胶囊 webview 另
监听 prefs:changed 广播,录音中切换也当帧换肤,并重置胶囊瞬态(退出动画/
插入字数/操作态)
* feat(settings): 录音方式滑动指示 + 静音自动停止展开/收起动画 + 下拉视觉统一
- 录音方式分段选框改为滑动指示块(left/width 过渡),并修复首次进入设置时
因 prefs/platformCaps 异步加载时序导致的高亮块永不定位
- 「静音后自动停止」整组随录音方式切换从下方拉出/收回(grid 0fr→1fr),
不再突然跳出;秒数行随开关展开/收起,开关行不再因内联下拉抽搐
- 静音时长下拉改用 SelectLite 默认底色、固定 200 宽,与麦克风下拉同视觉、
右边缘对齐
- SelectLite 触发器选中值切换动画(ol-select-value-in)
- UpdateDialog 全屏遮罩 0.18→0.05:不再把设置页白色选项行盖成灰色
* test(types): capsuleStyle 配置持久化 roundtrip 单测(默认 Siri + camelCase wire 键)
* fix(settings): 折叠态静音自动停止控件 inert 防键盘误触 + 滑动指示块随重排重测
pr_agent #912 评审两项:
- 录音方式非切换式/开关关闭时,折叠容器内 Toggle 与秒数下拉仍在 tab 顺序
与 a11y 树里,键盘用户可 Tab 到不可见控件 —— 收起时加 inert + aria-hidden
(与 Collapsible 同款方案)
- 语言切换/窗口缩放导致按钮重排时滑动指示块停在旧位置 —— ResizeObserver
监听 track 尺寸变化兜底重测
---------
Co-authored-by: sim <sim@local>
2026-08-04 18:06:56 +08:00
TRIP
d0e190f20c
Merge pull request #911 from Open-Less/docs/readme-sponsor-cleanup
...
docs(readme): remove jiangmuran and Cooper, sync latest stable data
2026-08-04 15:54:22 +08:00
TRIP and sim
856db1473a
[cask] openless 1.3.15 (auto from release) [skip ci] ( #899 )
...
Co-authored-by: sim <sim@local>
2026-08-03 22:36:49 +08:00
TRIP and sim
a3d014b687
chore(release): prepare 1.3.15(正式版版本号)+ 修复 bump 脚本误改依赖版本 ( #893 )
...
* fix(scripts): bump-version.sh 锚定 [package] 段,避免误改依赖版本
* chore(release): prepare 1.3.15
---------
Co-authored-by: sim <sim@local>
2026-08-03 21:27:10 +08:00
TRIP and sim
73e65a4077
chore(release): prepare 1.3.15-Beta.4 ( #889 )
...
Co-authored-by: sim <sim@local>
2026-08-03 16:05:44 +08:00
cd48a037a4
fix(less-computer): restore OpenCode model discovery and execution ( #840 )
...
* fix(less-computer): restore OpenCode model execution
* fix(capsule): gate set_ignore_cursor_events behind #[cfg(not(mobile))]
#887 introduced desktop-only capsule cursor-passthrough logic into the
unconditionally-compiled capsule_focus module, breaking Android cargo check
(E0599: no method set_ignore_cursor_events on tauri::WebviewWindow). Gate the
block to desktop; variables it consumes (classic_style, selection_polish,
visible) are still used on mobile outside the block.
---------
Co-authored-by: sim <sim@local>
Co-authored-by: Chris233 <h-chris233@outlook.com >
2026-08-03 16:03:41 +08:00
TRIP and sim
006cb78a93
feat(capsule): 录音胶囊样式可选(流光 Siri / Openless 默认)+ 修复 beta 构建破坏 ( #887 )
...
* feat(capsule): 录音胶囊样式可选——流光 Siri 风格 / Openless 默认风格
设置 → 录音与输入新增「胶囊样式」下拉(保留显示开关):
- UserPreferences.capsule_style('siri' 默认 / 'classic')随 capsule:state
payload 下发,切换后下一次录音即生效
- Capsule.tsx 双样式分支:siri 保留 SiriGL 光效舞台;classic 恢复 1.3.14
经典毛玻璃药丸(音量条 + 取消/确认按钮 + thinking 扫光 + 翻译徽章),
取消/确认改走 lib/ipc/dictation.ts,退出动画时长按样式区分
- 预览支持 ?style=classic;i18n 五语言新增胶囊样式文案
* fix(settings): 选区润色行适配重构后的 ShortcutRecorder props
beta HEAD 在快捷键录入交互重构(e12c8dcc)合并后遗留的构建破坏:
SelectionPolishSection 仍传已删除的 alignRecordButton / modifierPresets,
tsc 直接报错。改为新 API(value 可空 + onReset 恢复默认快捷键,
等价于旧「启用」按钮),恢复 beta 可构建状态。
* fix(capsule): 评审修复——经典药丸按钮可点 + 音频线程零偏好锁
- 经典样式(Openless 默认)下胶囊窗口长期 set_ignore_cursor_events(true)
(纯光效舞台时代遗留),✕/✓ 按钮实际不可点。现在主线程闭包按
「classic && visible && 非选区润色 && 录音/转写/润色中」关闭鼠标穿透,
终态 toast / 隐藏 / Siri / 选区润色保持穿透;值不变时不重复调用
set_ignore_cursor_events
- emit_capsule 在音频回调线程 ~30Hz 被调,原先直接读 prefs(整份克隆 +
偏好锁被 set() 跨磁盘 I/O 持有)。改为 Inner 上 AtomicU8 样式缓存,
主线程闭包每帧从 prefs 同步(与 show_capsule 同源读取),音频线程零开销
- 恢复「录音胶囊」行的 desc 文案(beta 原有,重构时被误删)
- Capsule.tsx 退出动画注释同步为按样式区分的常量名
* docs(capsule): 注明入场帧 payload 可能滞后一帧样式(防误改回音频线程读 prefs)
---------
Co-authored-by: sim <sim@local>
2026-08-03 14:17:52 +08:00
TRIP
857ea6dc21
Merge pull request #839 from Open-Less/release/1.3.15
...
fix(updater): prepare 1.3.15-Beta.2 after repository transfer
2026-07-21 18:43:09 +08:00
75918e0338
fix(android): protect credentials with Android Keystore ( #838 )
...
* fix(android): protect credentials with Keystore
* fix(android): harden credential migration
* fix(android): recover sanitized credential migration
* fix(ci): target Android x86_64 test variant
* fix(ci): prepare Tauri Android test project
* fix(ci): set Tauri Android build metadata
* fix(ci): isolate Android Keystore test build
* fix(ci): generate Tauri Android Kotlin bridge
* fix(android): harden credential persistence
* fix(android): preserve credential migration roots
* fix(android): recover verified credential writes
* fix(android): clear unrecoverable credential recovery
* fix(ci): accept CRLF in Android credential contract
---------
Co-authored-by: Codex <codex@openai.com >
Co-authored-by: baiqing <lbx12309@icloud.com >
Co-authored-by: Chris233 <h-chris233@outlook.com >
2026-07-18 18:13:34 +08:00
TRIP and sim
033eb5e731
chore(release): prepare 1.3.15-Beta.1 ( #834 )
...
Co-authored-by: sim <sim@local>
2026-07-15 17:22:02 +08:00
TRIP and sim
3143892daa
fix(updater): discover modern Beta release tags ( #833 )
...
* fix(updater): discover modern Beta release tags
Recognize the current -Beta.N-tauri convention while preserving historical lowercase beta tags so desktop and Android resolve the newest prerelease manifest.
* fix(updater): validate complete modern Beta tags
Reject malformed modern feed tags before they can preempt a valid release, while preserving the historical lowercase beta suffix.
---------
Co-authored-by: sim <sim@local>
2026-07-15 16:51:02 +08:00
TRIP and sim
4bdef5d7a3
ci: run all frontend and contract tests ( #832 )
...
Co-authored-by: sim <sim@local>
2026-07-15 15:55:37 +08:00
TRIP and sim
07b2e6a141
fix(security): redact provider URL log secrets ( #831 )
...
Co-authored-by: sim <sim@local>
2026-07-15 15:18:10 +08:00
TRIP and sim
e3e63cad04
fix(security): harden remote pairing PIN persistence ( #821 )
...
* fix(security): harden remote pairing PIN persistence
* fix(security): harden pairing PIN persistence
* test(ci): accept Windows line endings in PIN contract
* fix(linux): declare libc for secure PIN opens
---------
Co-authored-by: sim <sim@local>
2026-07-15 14:46:06 +08:00
TRIP and sim
472b914985
fix(security): authenticate marketplace writes with GitHub OAuth ( #816 )
...
* fix(security): authenticate marketplace writes with OAuth
* fix(security): harden marketplace OAuth lifecycle
* fix(security): enforce marketplace credential invalidation
* fix(security): reject public marketplace redirects
---------
Co-authored-by: sim <sim@local>
2026-07-15 14:20:29 +08:00
TRIP and sim
9991b325b8
test(windows): repair UI config contract ( #829 )
...
Co-authored-by: sim <sim@local>
2026-07-15 13:53:09 +08:00
TRIP and sim
a5a9c7f0b5
test: pin local tsx runner ( #828 )
...
Co-authored-by: sim <sim@local>
2026-07-15 13:44:39 +08:00
TRIP and sim
d6ca07a6b2
fix(android): break IPC settings barrel cycle ( #827 )
...
Co-authored-by: sim <sim@local>
2026-07-15 13:20:57 +08:00
TRIP and sim
fa53f47f08
fix(security): redact Less Computer approval tokens ( #820 )
...
Co-authored-by: sim <sim@local>
2026-07-14 19:07:20 +08:00
TRIP and sim
6aaae670b0
fix(security): bound style-pack ZIP imports ( #819 )
...
* fix(security): bound style pack archive imports
* fix(security): validate physical ZIP directory entries
---------
Co-authored-by: sim <sim@local>
2026-07-14 19:02:03 +08:00
145a0ea17d
feat(asr): add ElevenLabs Scribe v2 provider ( #807 )
...
* fix(asr): 完善 ElevenLabs Scribe 接入
* fix(asr): omit ElevenLabs word timestamps
* fix(qa): treat ElevenLabs cancellation as idle
---------
Co-authored-by: Chris233 <h-chris233@outlook.com >
Co-authored-by: sim <sim@local>
2026-07-14 15:29:16 +08:00
TRIP and sim
66d084792f
fix(security): patch RustSec dependency advisories ( #809 )
...
Co-authored-by: sim <sim@local>
2026-07-14 14:54:05 +08:00
TRIP and sim
ef6f1fadb4
fix(cask): update Homebrew package to v1.3.14 ( #802 )
...
* fix(cask): point Homebrew to v1.3.14
* fix(cask): declare Monterey requirement
---------
Co-authored-by: sim <sim@local>
2026-07-14 14:43:36 +08:00
TRIP and sim
d8789c783d
feat: 统一聊天面板(官方 shadcn)+ 1.3.14 审计修复批 + CVE 补丁 ( #767 )
...
* fix(deps): patch tauri-plugin-shell CVE (GHSA-c9pr-q8gx-3mgp)
@tauri-apps/plugin-shell (npm) 与 tauri-plugin-shell (crate) 的声明下限
——npm `^2.0.1`、crate `"2"`——都落在 GHSA-c9pr-q8gx-3mgp 影响范围
(`< 2.2.1`,CRITICAL:`open` 端点作用域校验绕过,可致 RCE)。本项目
src/lib/ipc/utils.ts 正是通过该 `open` 端点打开外链,属受影响用法。
两个 lockfile 实际已解析到 2.3.5,但清单声明的下限仍是漏洞版本,供应链
扫描(SkillSpector SC4)因此读取到 2.0.1 报警。此处仅把两侧声明下限抬到
最新安全版 2.3.5,使清单与锁定版本一致、扫描不再命中;解析版本不变,无
运行时行为变化。
Closes #668
* fix(audit): 1.3.14 审计修复一批(Apple Speech 取消/IME 保存锁死/侧向键卡死/火山429 等)
- CRIT Apple Speech 取消/超时不终止 SFSpeechRecognitionTask(SendableTask+cancel_flag+[task cancel]+100ms 轮询)
- HIGH windows_ime 未安装分支反致设置保存事务锁死(抽纯函数 keyboard_list_pref_short_circuit)
- HIGH 侧向键 Released 卡死自愈 + macOS flags 类位竞态 + Linux 显式拒绝
- HIGH coordinator/hotkey_loops unused_assignments clippy 回归
- MED 火山 429 限流不重试(RateLimited)/ Heatmap clamp / 授权失败反馈 / SendInput 分类单一真相 / SendInputOptions 收敛
- 清理 删死码 ?? '重启' / side_aware 死字段 / 孤儿 MarketplaceModal
cargo test 552-0 / npm build 绿。windows cfg 部分需 CI 四平台验证。
* feat(chat): 统一聊天面板组件库——官方 shadcn base 组件按 CLI 规则内嵌
@shadcn/react 官方 primitive + base-rhea registry 原文内嵌 components/chat/ui/
(message-scroller/marker/bubble/message/card/empty/input-group/button/input/
textarea/spinner,仅按 CLI 规则改 import 路径;button 保留 3 行 React18 inert
归一)。Tailwind v4 作用域隔离:utilities source(none) + @source 只扫聊天文件、
无层导入压过 global.css;官方主题 shadcn/tailwind.css + tw-animate-css。
胶囊同款思考动画(orbFeed 单 GL 源镜像多头像)、GitHub 头像(CSP img-src 放行)、
出现/消失生命周期 hook。平台门控:非 darwin 构建 DCE 掉 Less Computer chunk。
删除旧自制 Marker/MessageScroller 组件。
* feat(panels): QA/LC 浮窗重写为官方 message-scroller-demo 同款骨架
Card + Empty + InputGroup + MessageScroller 官方组合;QA=Message 带头像形态
(右 GitHub / 左旋转 orb),LC=Marker 工具行形态(无头像)。
语音状态只在输入区:录音红光/转译黑光绕输入组跑圈,问题落定即停;
思考头像行门控在用户消息落定之后(修「AI 头像先出现、动画抽搐」)。
LC 事件空轮自愈 + mount 后 less_computer_sync 重放(webview 冷加载丢
user 事件导致「后端在跑前端空白/用户的话不显示」)。纯白背景、官方
24px 圆角、出现/消失动画(chat-panel:shown/closing)。
* fix(backend): 聊天面板后端配套——命令注册/非激活面板/事件缓冲/生命周期
- 恢复桌面 invoke_handler 的 qa_submit_text / qa_toggle_recording(此前删
qa_window_pin 时误删相邻项,真机报 Command qa_submit_text not found)
- QA/LC 窗口转非激活 NSPanel(胶囊同管线:NonactivatingPanelMask +
CanJoinAllSpaces|FullScreenAuxiliary),chat_panel_focus_keyboard 改主线程
makeKeyAndOrderFront:打字不激活 app、主窗口不再被带出、frontmost 保持
用户原 app(划词选区在多轮期间仍可读)
- Less Computer 事件按全局单调 seq 写入环形缓冲(fresh user 清空、cap 2048
丢最旧),新命令 less_computer_sync 供前端 mount 重放(仅 less-computer
窗口可调);附 2 个单测
- show/hide 生命周期:show 发 chat-panel:shown 并作废挂起 hide;hide 先发
chat-panel:closing、240ms 后真正隐藏(AtomicU64 世代防快速关-开竞态)
- QA/LC 窗口统一固定 420×540;删除 qa_window_pin / less_computer_window_resize
整链(无消费方)
---------
Co-authored-by: sim <sim@local>
2026-07-06 22:21:16 +08:00
2e3c0f5c29
fix(windows-ime): stop explorer.exe AppHang from IME pipe server shutdown ( #764 )
...
OpenLessIme.dll is a system-wide TSF keyboard TIP, so CTF loads it into
every process that has text input (explorer.exe, the taskbar, ...) and
runs it on that process's UI thread. The per-process pipe server blocked
on a synchronous ConnectNamedPipe, and Deactivate() -> Stop() joined that
worker from the host UI thread, relying on a racy CancelSynchronousIo +
self-connect WakePipe() to unblock it. When both lost the race the worker
re-entered ConnectNamedPipe forever and join() froze the host UI thread
indefinitely -> explorer.exe AppHangB1 (taskbar unresponsive, Explorer
restarts). WER reports for the reported hangs show OpenLessIme.dll loaded
in explorer.exe, and disabling the TSF profile stops the hang.
Make every pipe wait deterministically cancelable: open the pipe with
FILE_FLAG_OVERLAPPED and wait on {io_event, stop_event} via
WaitForMultipleObjects. Stop() now just signals stop_event and joins, so
it returns at once, never blocks the host UI thread, and leaks no worker
thread. Connect/read/write go through WaitForClient / RunOverlapped, which
CancelIoEx + drain the overlapped op before the stack OVERLAPPED / buffer
go out of scope. Removes the racy WakePipe / CancelSynchronousIo /
pipe_handle_ / pipe_mutex_.
Pipe name, JSON wire protocol and the Rust client (windows_ime_ipc.rs)
are unchanged.
Fixes #665
Fixes #707
Co-authored-by: appergb <lubaiqing9@gmail.com >
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-06 20:08:29 +08:00
TRIP and sim
95e4cdf203
fix(audio-cue): recover when resume() is rejected or wakes non-running ( #757 )
...
Long sessions park the shared AudioContext in 'suspended' / WebKit
'interrupted' after the system audio session is repeatedly preempted by
ASR and recording. The earlier fix only recreated a 'closed' context: a
rejected resume() was swallowed and a resume() that resolved without
reaching 'running' scheduled voices on a frozen currentTime, both of
which leave the start cue permanently silent until the app restarts.
Treat both "won't wake" states as recoverable — discard the dead context
and retry once on a fresh one, bounded to avoid infinite recreation. The
decision is extracted into the pure, unit-tested cueActionAfterResume.
Co-authored-by: sim <sim@local>
2026-07-06 20:01:40 +08:00
7de0c04ba5
docs: 用协调沉降定律重构 README 能力/增强叙事,凸显开屏即授权完基础设施 ( #765 )
...
- 新增「从工具到基础设施 / From tool to infrastructure」专章:把 OpenLess 定位为
消灭「想法 → 干净文字」之间每一次协调的基础设施——语气沉降成风格包、专有名词
沉降成词典热词、文字落点沉降成插入协议、模型与凭据沉降进系统保管库,开屏授权
一次即为默认协议。
- 改写「更新亮点(增强)」与「当前状态(能力)」两节开场,从功能罗列改为「你授权
一次之后就不必再操心的基础设施层」;其余条目与版本号(v1.3.6)保留不动。
- 中英双 README 同步(README.md + README.zh.md),纯文档改动,不涉及代码/版本门禁。
Co-authored-by: sim <sim@local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-05 21:28:36 +08:00
TRIP and sim
3ca6883d3a
fix(deps): patch tauri-plugin-shell CVE (GHSA-c9pr-q8gx-3mgp) ( #763 )
...
@tauri-apps/plugin-shell (npm) 与 tauri-plugin-shell (crate) 的声明下限
——npm `^2.0.1`、crate `"2"`——都落在 GHSA-c9pr-q8gx-3mgp 影响范围
(`< 2.2.1`,CRITICAL:`open` 端点作用域校验绕过,可致 RCE)。本项目
src/lib/ipc/utils.ts 正是通过该 `open` 端点打开外链,属受影响用法。
两个 lockfile 实际已解析到 2.3.5,但清单声明的下限仍是漏洞版本,供应链
扫描(SkillSpector SC4)因此读取到 2.0.1 报警。此处仅把两侧声明下限抬到
最新安全版 2.3.5,使清单与锁定版本一致、扫描不再命中;解析版本不变,无
运行时行为变化。
Closes #668
Co-authored-by: sim <sim@local>
2026-07-05 00:40:23 +08:00
351e0211bd
集成 1.3.14 → beta(主窗 UI 大改 + 一批 fix/feat) ( #761 )
...
* fix(insertion): macOS 让「恢复剪贴板」开关真正生效,修复被回退的 #525
#525 的 macOS 剪贴板恢复(commit 4b4d219)被 Android 移植 commit 1ea467a
连同 cfg 门控一起回退:整套恢复机制被重新 #[cfg] 排除出 macOS,macOS insert()
退回「只写剪贴板 + Cmd+V」,于是设置里的「恢复剪贴板」开关在 macOS 上完全无效
——无论开关开还是关,剪贴板都被留成转写文字。
- 把共享的剪贴板恢复机制(ClipboardRestorePlan / schedule_clipboard_restore /
restore_clipboard_after_delay / should_restore_clipboard 等)的 cfg 从
not(any(macos,android,ios)) 放宽为 not(any(android,ios)),重新纳入 macOS
(移动端仍排除;Windows/Linux 不变)。
- macOS insert() 改为:保存原剪贴板 → 写转写文字 → Cmd+V → 仅当「恢复剪贴板」
开关开启且粘贴成功时按 CLIPBOARD_RESTORE_DELAY 延迟恢复;粘贴失败则保留转写
文字供手动粘贴、不恢复。开 = 恢复,关 = 保持现状,开关说了算。
- 删除随之失效的 macos_insert_status_after_paste;恢复相关单测在 macOS 也运行。
Windows/Linux 专用项(insert_with_clipboard_restore / paste_keys /
simulate_paste(shortcut) / 其 insertion_success_status 变体)的 macOS 排除保持不变。
* fix(less-computer): 护栏 sudo/dd/chmod/chown 等设为不可批准,修批准注入畸形规则 (#679 )
旧审批流对所有命中 pattern 一律 format!("Bash({p}:*)") 生成 allow 规则:
- 对带空格/参数的子串("sudo " → "Bash(sudo :*)","dd if=" → "Bash(dd if=:*)",
"chmod -r 777 /"、"chown -r")生成的串既不等于 deny "Bash(sudo:*)" 等(故 deny
没被移除、批准静默失效),又把畸形规则注入了 allowed_tools。
改为:新增 guard::deny_rule_for_pattern(pattern),把「可批准」命令(rm -rf / git
push --force / git reset --hard / git clean 等)映射到其在 default_deny_rules 里的
**精确** deny 规则;提权/毁盘/系统级命令(sudo / dd / mkfs / chmod / chown / shutdown
/ reboot / 管道执行 / fork 炸弹)返回 None = 不可批准,即使被批准也保持拦截
(fail-closed),不再注入畸形 allow。审批流用 filter_map 取精确规则,移除的 deny 与
加入的 allow 严格一致。
附单测:每个可批准 pattern 的映射规则确实存在于 default_deny_rules;危险系统命令一律
不可批准。
* fix(ui): unify macOS shell top inset with sidebar/background surface
The 28px top inset that clears the macOS overlay traffic lights sat on the
content wrapper with no background, so it exposed the lighter WindowChrome
glass (--ol-window-bg) as a full-width band above the sidebar and panel —
reading as an extra top row that the Windows build (no inset) doesn't have.
Paint that wrapper with the same --ol-app-shell-bg the sidebar/background
already use, so the inset blends into one continuous surface with the panel
card floating on top. One property; token carries its own light + dark
values; no layout, token, or other UI changes.
* fix(capsule): 胶囊跟随鼠标光标所在屏,修复多屏/多 Space 只在第一块屏显示
多屏 + 多桌面下胶囊只出现在第一块屏、其他屏闪一下就消失。根因:定位
(position_capsule_bottom_center) 用 AX caret 选屏,多数 App 取不到 caret 矩形就
跌回胶囊自己的 current_monitor(第一块屏);而去重缓存 capsule_layout_snapshot 也
用 current_monitor,与定位看的不是同一块屏 → 胶囊一落第一块屏即被判“无变化”跳过
重定位,被锁死。两条路都没跟踪鼠标。
- 新增 mouse_cursor_point():CoreGraphics CGEventGetLocation 取光标,坐标系与 AX
一致、零权限、永远可用
- focused_input_target_monitor → capsule_target_monitor,选屏改“光标优先”(caret
仅兜底),选屏循环抽成 monitor_for_anchor_point
- 定位与去重快照统一走 capsule_target_monitor,彻底消除不一致
- 保留 CAN_JOIN_ALL_SPACES(Spaces 契约强制且本就正确:帧落在光标屏→只那块屏显示)
- 扩展 macos-capsule-spaces 契约测试,grep 守护“光标优先 + 两路共用同一函数”
Windows 路径未动(本就跟随输入 App 屏且快照一致)。
验证:cargo check + lib 纯函数单测 + check:macos-capsule-spaces 全过。
* feat(less-computer): 边缘发光改用 EdgeGlow 式四层模糊堆叠 + iridescent 配色
把 Less Computer 全屏彩虹边缘发光从原来「两条都带模糊的软光带」改成
EdgeGlow(github.com/vector4wang/EdgeGlow,MIT)的实现方式,让彩虹「实线」
更清晰、发光更有层次。
- 4 层模糊堆叠:最内一条 0.5px 锐利彩虹实线(对应 EdgeGlow blur=0 那层,
定义边缘),外面叠 3 层逐渐变宽、变虚的光晕(blur 3/8/15px),得到
霓虹灯管式发光。原生用 CAShapeLayer + 高斯模糊,这里用 CSS「边框遮罩环
+ filter:blur」等价复刻。
- 配色移植 EdgeGlow 默认的 iridescent(Apple Intelligence 高饱和霓虹:
紫→蓝→青→绿→金→橙→红→粉),按 12 段均匀铺满 360°。
- 流光整圈 8s/圈通过 --lcg-angle 旋转(只动渐变角度不动元素形状,GPU 友好),
光晕层各带不同周期呼吸;实线用 normal 保色准,光晕用 screen 叠加增亮。
保留 issue #470 的隐藏即卸载发光层(零 GPU)逻辑、pointer-events:none、
prefers-reduced-motion 降级与 --lcg-radius 圆角变量。纯视觉、仅 macOS、单文件。
* fix(vault): Windows 凭据读取瞬时失败重试,修概率性「火山引擎未配置」
Windows Credential Manager(CredReadW)在登录后/并发下读 manifest+各 chunk 条目
时可能瞬时失败。任一条目读失败会让整组凭据看起来为空 → load_keyring_credentials
返回 Err → load_credentials 回退到空默认值 → 概览页显示「火山引擎未配置」,但下
一次听写重读成功,所以是「概率性」且「实际可正常使用」。凭据 chunk 越多,单次
load 读取次数越多,命中瞬时失败的概率越高。
修法:仅在 Windows 上对非 NoEntry 的读错误做几次短退避重试(4 次 / 60·n ms)。
NoEntry 是确定的「未存储」,立即返回不付重试延迟。macOS/Linux 保持原单次行为
——它们的读错误是 ACL 拒绝,重试无益,且未缓存的错误路径下次调用本就会重读,
加 sleep 只会拖慢 macOS 首次 Keychain 授权流程。纯后端、cfg 隔离,零 PC-macOS 影响。
* fix(asr): 火山引擎连接增加超时与重试,修弱网下无法语音输入
connect_async 此前既无超时也无重试:弱网下 TLS/WebSocket 握手可能挂到 OS 级
TCP 超时(几十秒),期间用户卡在「Starting」;而协调器全局超时只覆盖
await_final_result,不覆盖 open_session,所以握手挂起完全不受约束。单次网络
抖动(连接被重置/瞬时 DNS 失败)也会直接让整次听写失败。
修法:每次握手包 5s 超时,最多 3 次尝试、250·n ms 退避。AuthRejected(凭据被拒)
短路不重试——重试不会变好只会拖慢报错。把请求构造抽成 build_connect_request
(connect_async 消费 request 且 http::Request 非 Clone,需每次重建)。
桌面与安卓共享此路径,改动对两端等效;最坏耗时从「无界(~75s)」降到有界(~15s)
并新增抖动可恢复,对 PC 端只增不减。
* feat(coding-agent): OpenCode CLI 适配器,语音 Agent 可选 OpenCode 后端 (issue #579 )
把 OpenCode 当作与 Claude Code 同类的 coding agent CLI 接入,照既有 coding_agent
适配模式(不另造架构),复用同一套 CodingAgentRequest / CodingAgentEvent /
CodingAgentError / 审批护栏链路。
后端:
- coding_agent/opencode.rs(新):detect_opencode(opencode --version)、
build_opencode_args(opencode run --format json --model --dir
[--dangerously-skip-permissions],prompt 作为 argv)、parse_opencode_json_line
(NDJSON:text/tool_use/error;text 块累计,EOF 合成 Completed)、
run_opencode_agent(取消/超时 kill,护栏经 OPENCODE_CONFIG_CONTENT 注入)。
- coding_agent/args.rs:CodingAgentProvider 枚举(claude-code-cli/opencode-cli,
未知回落 Claude)+ from_pref/default_exe。
- coding_agent/guard.rs:build_opencode_guard_config —— 把高风险 bash 前缀翻译成
OpenCode permission.bash deny glob + webfetch deny,审批放行的前缀显式 allow。
- coordinator/dictation_voice_agent: run_less_computer_once 按 coding_agent_provider
分派 Claude / OpenCode 运行器;两路都 fail-closed(护栏生成失败即中止,不裸跑)。
审批拦截探测/重跑放行链路 provider 无关,自动复用。
- commands: coding_agent_detect_opencode 命令(已注册 lib.rs)。
前端:
- CodingAgentSection: OpenCode 选项从「即将支持」改为可用 + 选中后探测安装状态并提示。
- ipc: codingAgentDetectOpencode + OpenCodeDetection。
- i18n: opencodeReady / opencodeMissing(5 语言,替换 providerOpenCodeSoon)。
验证:cargo check + cargo test(492 通过)+ npm run build 均通过。
Refs #579
(#579 还含「语音润色模型配置」:prefs 字段已存在但全链路未实现/未接 UI,
转写直接进 agent 未经语音润色模型整理 —— 故用 Refs 不用 Closes。)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
* fix(coding-agent): OpenCode 防参数注入 + 可配置 Agent 可执行文件路径 (#638 )
注入风险(@H-Chris233 评审):`opencode run` 的 prompt 作为最后位置参数,但之前缺
end-of-options 分隔。以 `-` / `--` 开头的 prompt(语音转写或被 prompt 注入诱导)会被
OpenCode 当作 flag 解析,可绕过护栏(混入 --dangerously-skip-permissions、--dir 改写
工作目录等)。修复:build_opencode_args 末尾追加 `--`,运行器把 prompt 接在其后;新增单测。
可配置路径(@PR-Agent 指出之前 hardcode "opencode"):新增 prefs.coding_agent_exe,
语音 Agent 路径据此取 exe(留空回退默认 claude / opencode),检测命令亦用配置路径;
设置「高级 → Less Computer」新增「可执行文件路径」输入;补 5 语言 i18n。
* fix(updater): 安装失败可见化 + 手动下载兜底 + 错误写日志 (#706 )
下载完成后若 install() 抛错,旧代码把 status 置成 'error',而 UpdateDialog 不渲染 error 态 → 弹框消失、错误只 console.error,用户表现为「下载后无反应、重启仍旧版」(#706 )。
- 新增独立状态 installError:仅下载/安装失败用它;'error' 仍表示「检查失败」,行为不变(CheckUpdateButton 按钮内轻提示、后台自动检查都不弹框,零回归)。
- 失败弹框留在原地显示真实错误 + 「手动下载」按钮直达 GitHub Releases 兜底。
- 新增 Rust IPC log_client_error,把前端更新错误写进 openless.log(webview console 不入文件日志),便于用户「导出日志」后定位真因。
- 5 个 i18n 文件补 updateDialog.installError / manualDownload。
注意:这是兜底(失败可见 + 可诊断),不解决 ad-hoc/quarantine 机器自动更新真正成功的问题——那需要 Apple Developer ID 签名 + 公证(本次暂缓)。
* 手动补:dictation/ipc 拆分后的 OpenCode + updater 改动迁移
* fix: AutoUpdate 兼容性修复(补回 CheckUpdateOptions + Android 参数类型)
* fix(audio-cue): 重建/唤醒退化的 AudioContext,修「用久了提示音消失」
长时间使用后「开始录音」提示音与设置页「试听」双双静音,且重启才恢复。
根因在 audioCue.ts 的 AudioContext 单例 sharedCtx 从不检查/恢复运行期状态:
- WKWebView/WebView2 在频繁录音抢占音频会话后,ctx 可能转入 WebKit 非标准的
`interrupted` 态。旧代码只判断 `suspended`,interrupted 被当作可直接排期 →
排到非 running 的 ctx 上,无声且不尝试 resume → 永久静默(macOS 最可能根因)。
- ctx 也可能被系统 `closed`。closed 无法复活(resume 必拒、createOscillator 必抛、
被 catch 静默吞掉),而 getContext 从不重建 → 永久静默。
- 胶囊窗口与设置窗口各持一份 ctx,都会这样退化 → 两处提示音同时失效。
修复:
- 新增纯函数 audioContextActionForState(state):closed→recreate / running→ready /
其余(suspended/interrupted/未知非运行态)→resume,单一真相、可单测。
- getContext 在 ctx 为 closed 时丢弃重建(并清空挂在旧 ctx 上的 activeVoices)。
- playRecordStartCue / primeAudioCue 改用该分类器,把 interrupted 一并按 resume 唤醒。
公共 API 签名不变,仅 AudioCue.tsx / RecordingInputSection.tsx 复用,行为向后兼容。
tsc --noEmit 通过;audioCue.test.ts 新增 5 条状态分类断言,全部通过。
* fix(macos): onboarding Accessibility authorization page stuck (#703 follow-up)
Root cause: permissions::request_accessibility() was called in setup(),
which runs BEFORE the AppKit event loop is live. On some macOS versions,
AXIsProcessTrustedWithOptions depends on the run loop for XPC to tccd.
When the event loop isn't ready, TCC may not show the dialog but still
consumes the one-time prompt. Later calls from the onboarding page's
'grant accessibility' button silently return Denied, trapping users on
the onboarding page. Recovery requires System Settings grant + app
restart, but users had no clear restart action — only a text hint.
Changes:
- lib.rs: Remove setup() TCC prompt. The prompt is now exclusively
triggered by user action on the onboarding page, aligning with
Apple HIG (explain why → then prompt).
- Onboarding.tsx:
* onGrantAccessibility now checks the TCC result: skip
openSystemSettings when already granted (previously always opened)
* New tccPromptShown state distinguishes 'never attempted' vs
'already denied' for correct button labels
* Denied state now shows a prominent 'Restart OpenLess' button
calling restartApp()
- PermissionsSection.tsx: Same fix for settings page accessibility
row — check TCC result, guide to System Settings when denied,
show 'Restart App' button
- i18n: Add onboarding.actionRestart + settings.permissions.restart
for zh-CN / zh-TW / en / ja / ko
Closes: macos-onboarding-accessibility-stuck
* chore(release): publish 1.3.13
* fix(audio-cue): recover when resume() is rejected or wakes non-running
Long sessions park the shared AudioContext in 'suspended' / WebKit
'interrupted' after the system audio session is repeatedly preempted by
ASR and recording. The earlier fix only recreated a 'closed' context: a
rejected resume() was swallowed and a resume() that resolved without
reaching 'running' scheduled voices on a frozen currentTime, both of
which leave the start cue permanently silent until the app restarts.
Treat both "won't wake" states as recoverable — discard the dead context
and retry once on a fresh one, bounded to avoid infinite recreation. The
decision is extracted into the pure, unit-tested cueActionAfterResume.
* chore(release): integrate 1.3.14
* fix(ipc): 去除 coding-agent.ts/index.ts 中 OpenCodeDetection 和 codingAgentDetectOpencode 的重复声明
integrate/cloud-sync-20260621 合并后 IPC barrel 出现重复 export(beta 已含 PR #638 的
OpenCode 适配器,integrate 分支又加了一份)。合并去重,npm build 通过。
* style(less-computer): 气泡/审批/发送按钮改用 accent 主题 token
把 LessComputerPanel 里三处硬编码渐变(#3d6bff→#7a55f2)替换为
--ol-accent-solid-bg / --ol-accent-solid-ink,跟随浅/深主题。
* feat(capsule/asr/ui): 胶囊即时显示与预测展开、Apple 语音修复、弹窗全局遮罩
胶囊入场(延迟出现 / 无入场动画 / 亮起→卡→展开):
- 按下热键即「乐观显示」胶囊并播入场动画,不等麦克风就绪;level_handler 首帧 PCM
到达后从预备态翻正式态、光条点亮(新增 warming 标志贯穿 emit_capsule payload)
- 修入场动画被吞:入场帧把发给前端的事件挪到 window.show 之后再 emit
- 预测式展开:光条按历史平均加载时长(EMA + localStorage 跨会话学习)从按下就平滑
展开,就绪早则加速补满、未就绪则慢爬至 90%,消除「亮起→卡→突然展开」
Apple 语音(说中文识别成英文 / 偶发不可用):
- initWithLocale 跟随用户工作语言主语言,修 init 无参落系统首选语言(英文)导致
中文被英文引擎误识别
- on-device 优先(requiresOnDeviceRecognition):离线可用 + 隐私 + 不受网络波动/限流
- isAvailable 就绪轮询等待,修刚 init 时瞬时不可用就报错的竞态
弹窗遮罩:Modal 用 createPortal 到 body,修被 WindowChrome/FloatingShell 常驻
will-change: transform 祖先困住 fixed 遮罩(登录弹窗浮在亮着的设置页上、无全局压暗)
服务页 Apple 语音文案优化(zh-CN/zh-TW)
---------
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
Co-authored-by: sim <sim@local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 23:41:41 +08:00
TRIP
b4636f9620
fix(audio-cue): recover degraded AudioContext
...
Recreate closed AudioContext instances and resume interrupted/suspended contexts before scheduling generated record-start cues. Includes state classification tests.
2026-06-25 13:39:10 +08:00
TRIP
124a49ca05
fix(macos): recover stuck Accessibility onboarding
...
Fix macOS Accessibility onboarding getting stuck after TCC prompt/identity drift. Request permission only from onboarding, add targeted Accessibility TCC reset + restart recovery, and mirror the flow in settings.
2026-06-25 13:38:52 +08:00
e1c1be2942
feat(coding-agent): OpenCode CLI 适配器,语音 Agent 可选 OpenCode 后端 (Refs #579 ) ( #638 )
...
* feat(coding-agent): OpenCode CLI 适配器,语音 Agent 可选 OpenCode 后端 (issue #579 )
把 OpenCode 当作与 Claude Code 同类的 coding agent CLI 接入,照既有 coding_agent
适配模式(不另造架构),复用同一套 CodingAgentRequest / CodingAgentEvent /
CodingAgentError / 审批护栏链路。
后端:
- coding_agent/opencode.rs(新):detect_opencode(opencode --version)、
build_opencode_args(opencode run --format json --model --dir
[--dangerously-skip-permissions],prompt 作为 argv)、parse_opencode_json_line
(NDJSON:text/tool_use/error;text 块累计,EOF 合成 Completed)、
run_opencode_agent(取消/超时 kill,护栏经 OPENCODE_CONFIG_CONTENT 注入)。
- coding_agent/args.rs:CodingAgentProvider 枚举(claude-code-cli/opencode-cli,
未知回落 Claude)+ from_pref/default_exe。
- coding_agent/guard.rs:build_opencode_guard_config —— 把高风险 bash 前缀翻译成
OpenCode permission.bash deny glob + webfetch deny,审批放行的前缀显式 allow。
- coordinator/dictation_voice_agent: run_less_computer_once 按 coding_agent_provider
分派 Claude / OpenCode 运行器;两路都 fail-closed(护栏生成失败即中止,不裸跑)。
审批拦截探测/重跑放行链路 provider 无关,自动复用。
- commands: coding_agent_detect_opencode 命令(已注册 lib.rs)。
前端:
- CodingAgentSection: OpenCode 选项从「即将支持」改为可用 + 选中后探测安装状态并提示。
- ipc: codingAgentDetectOpencode + OpenCodeDetection。
- i18n: opencodeReady / opencodeMissing(5 语言,替换 providerOpenCodeSoon)。
验证:cargo check + cargo test(492 通过)+ npm run build 均通过。
Refs #579
(#579 还含「语音润色模型配置」:prefs 字段已存在但全链路未实现/未接 UI,
转写直接进 agent 未经语音润色模型整理 —— 故用 Refs 不用 Closes。)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
* fix(coding-agent): OpenCode 防参数注入 + 可配置 Agent 可执行文件路径 (#638 )
注入风险(@H-Chris233 评审):`opencode run` 的 prompt 作为最后位置参数,但之前缺
end-of-options 分隔。以 `-` / `--` 开头的 prompt(语音转写或被 prompt 注入诱导)会被
OpenCode 当作 flag 解析,可绕过护栏(混入 --dangerously-skip-permissions、--dir 改写
工作目录等)。修复:build_opencode_args 末尾追加 `--`,运行器把 prompt 接在其后;新增单测。
可配置路径(@PR-Agent 指出之前 hardcode "opencode"):新增 prefs.coding_agent_exe,
语音 Agent 路径据此取 exe(留空回退默认 claude / opencode),检测命令亦用配置路径;
设置「高级 → Less Computer」新增「可执行文件路径」输入;补 5 语言 i18n。
---------
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
Co-authored-by: Claude Fable 5 <noreply@anthropic.com >
Co-authored-by: Chris233 <h-chris233@outlook.com >
2026-06-24 12:30:12 +08:00
TRIP and sim
323f44d450
feat(less-computer): 边缘发光改用 EdgeGlow 式四层模糊堆叠 + iridescent 配色 ( #720 )
...
把 Less Computer 全屏彩虹边缘发光从原来「两条都带模糊的软光带」改成
EdgeGlow(github.com/vector4wang/EdgeGlow,MIT)的实现方式,让彩虹「实线」
更清晰、发光更有层次。
- 4 层模糊堆叠:最内一条 0.5px 锐利彩虹实线(对应 EdgeGlow blur=0 那层,
定义边缘),外面叠 3 层逐渐变宽、变虚的光晕(blur 3/8/15px),得到
霓虹灯管式发光。原生用 CAShapeLayer + 高斯模糊,这里用 CSS「边框遮罩环
+ filter:blur」等价复刻。
- 配色移植 EdgeGlow 默认的 iridescent(Apple Intelligence 高饱和霓虹:
紫→蓝→青→绿→金→橙→红→粉),按 12 段均匀铺满 360°。
- 流光整圈 8s/圈通过 --lcg-angle 旋转(只动渐变角度不动元素形状,GPU 友好),
光晕层各带不同周期呼吸;实线用 normal 保色准,光晕用 screen 叠加增亮。
保留 issue #470 的隐藏即卸载发光层(零 GPU)逻辑、pointer-events:none、
prefers-reduced-motion 降级与 --lcg-radius 圆角变量。纯视觉、仅 macOS、单文件。
Co-authored-by: sim <sim@local>
2026-06-21 10:04:35 +08:00
TRIP
50274d1acd
fix(insertion): macOS 让「恢复剪贴板」开关真正生效,修复被回退的 #525 ( #683 )
...
#525 的 macOS 剪贴板恢复被 Android 移植 commit 1ea467a 用 cfg(not(any(macos,android,ios))) 误伤排除。本 PR 把 40+ 处 cfg 放宽为 not(any(android,ios)),macOS 重新纳入;insert() 改为「保存原剪贴板 → 写转写 → Cmd+V → 按开关决定是否恢复」。
已解决与 beta(#712 安卓集成)在 insert() 签名上的冲突,cargo check 通过,四平台 CI 全绿。
Claude 审核:cfg 边界清晰、三态逻辑正确,无阻塞性问题。Closes #525
2026-06-21 00:27:39 +08:00
TRIP
cfb09b14f8
fix(capsule): 胶囊跟随鼠标光标所在屏,修复多屏/多 Space 只在第一块屏显示 ( #714 )
...
新增 CGEventGetLocation 取鼠标光标位置(零权限),focused_input_target_monitor → capsule_target_monitor,定位与去重快照统一走光标优先选屏,消除「定位用 AX caret、去重用 current_monitor」两套选屏不一致导致的锁屏。
Claude 审核:5 个核心确认点(坐标系一致/选屏逻辑/快照统一/零权限/平台隔离)全部通过,可合并。
2026-06-21 00:05:45 +08:00
TRIP
7a33db0605
fix(less-computer): 护栏高危系统命令设为不可批准,修批准注入畸形规则 ( #688 )
...
deny_rule_for_pattern 只对可安全前缀化的命令(rm -rf / git push --force 等)返回精确 deny 规则;sudo/dd/mkfs/chmod/shutdown 等返回 None,即使被点批准也保持拦截、不注入 allow。修复旧代码 format!("Bash({p}:*)") 对 "sudo " 生成 Bash(sudo :*) 与 deny 规则 Bash(sudo:*) 不匹配导致批准静默失效的问题。
Closes #679
Claude 审核:方向正确,核心修复逻辑无误,无阻塞性问题。
2026-06-21 00:03:56 +08:00
TRIP
fbe40ab583
feat(android): 集成 #704 安卓自动更新 + 同步 PC updater 修复(#705/#708)到安卓 ( #712 )
...
合并 #704(安卓应用内自动更新 + JNI 修复)并把 PC updater 修复同步到安卓:①安卓公钥回退 6F4B5994→1DEAA803(同步#705)②installError 安装失败兜底+去 throw(同步#708)③还原被自动合并误删的桌面 logClientError。桌面机制零变更。CI 全绿 + @claude 审核通过。取代 #704 及 #694 安卓部分。
2026-06-19 13:55:53 +08:00
TRIP and sim
6c99ddf1f7
fix(updater): revert signing pubkey to 1DEAA803 to repair auto-update ( #705 )
...
Auto-update was broken on every platform: builds since aaf4ccc embed pubkey
6F4B5994, but shipped 1.3.8 stable users trust 1DEAA803 and CI now signs with
1DEAA803 again. A key the installed app doesn't trust => download succeeds,
install() signature verification fails => "downloads but never updates".
Revert the desktop updater pubkey to 1DEAA803 so it matches both the CI
signing key and android/updater.rs (which already hardcodes 1DEAA803). This
also repairs Android auto-update, which was signing-vs-verifying mismatched.
One line, no logic change.
Co-authored-by: sim <sim@local>
2026-06-17 23:30:01 +08:00
TRIP and sim
f3467ae5f9
fix(onboarding): require macOS Accessibility grant before first-run completes ( #703 )
...
On macOS the hotkey needs Accessibility, but first-run onboarding could finish
after Microphone only and drop users into the main UI with a dead hotkey
("nothing happens when I press the key").
Cause: desktop onboarding gated completion on the hotkey *capability* flag
(requiresAccessibilityPermission). That flag is null while the capability IPC
loads, so requiresAccessibility was briefly false — if Mic got granted in that
window, refresh() called onComplete() before Accessibility was ever requested.
App.tsx's startup gate, by contrast, always requires Accessibility, so the two
disagreed.
Fix: gate completion on the real permission status, mirroring App.tsx — macOS
returns granted/denied, every other platform returns notApplicable, so this is
timing-independent and cross-platform safe. Also surface the Accessibility step
whenever it is denied (macOS-only state) and drop the capability dependency from
its grant button, so the step always appears and is actionable even before the
capability finishes loading.
No change on Windows/Linux/Android (Accessibility = notApplicable there).
Co-authored-by: sim <sim@local>
2026-06-17 17:39:16 +08:00
TRIP and sim
4903f4442e
fix(ui): unify macOS shell top inset with sidebar/background surface ( #702 )
...
The 28px top inset that clears the macOS overlay traffic lights sat on the
content wrapper with no background, so it exposed the lighter WindowChrome
glass (--ol-window-bg) as a full-width band above the sidebar and panel —
reading as an extra top row that the Windows build (no inset) doesn't have.
Paint that wrapper with the same --ol-app-shell-bg the sidebar/background
already use, so the inset blends into one continuous surface with the panel
card floating on top. One property; token carries its own light + dark
values; no layout, token, or other UI changes.
Co-authored-by: sim <sim@local>
2026-06-17 17:27:15 +08:00
TRIP and sim
a94ea3d05a
refactor(persistence): split persistence.rs into domain modules behind a barrel ( #701 )
...
Behavior-unchanged decomposition of the 2757-line `persistence.rs` god-file
into a `persistence/` module, one file per concern. Everything is re-exported
via glob (`pub use <submodule>::*`) so the `crate::persistence::*` public
surface is byte-for-byte identical and no call site changes.
Layout:
- mod.rs shared fs/io helpers (data_dir, ensure_dir, atomic_write,
read_or_default) + the two cross-cutting consts + re-exports
- paths.rs models / recordings / Foundry roots + migration helpers
- credentials.rs OS credential vault (CredsRoot model, keyring/android/legacy,
CredentialAccount, CredentialsSnapshot, CredentialsVault)
- history.rs HistoryStore
- preferences.rs read_preferences + PreferencesStore
- style_pack.rs StylePackStore + ZIP import/export + prefs reconciliation
- dictionary.rs DictionaryStore + vocab presets
- correction.rs CorrectionRuleStore
Pure move + re-export: no logic, signatures, public API, or UI changed. Unit
tests moved next to the code they now cover. Shared helpers stay private in
`mod.rs` (parent items are visible to child modules), and glob re-exports keep
cfg-gated items (Android/Windows) resolution-safe across every target —
avoiding the explicit-`pub use` breakage seen in the earlier types.rs split.
Verified on macOS: cargo fmt/check/clippy clean (no new persistence warnings),
446 lib tests green. Android/Windows cfg paths verified by CI.
Part of #697 .
Co-authored-by: sim <sim@local>
2026-06-17 16:08:26 +08:00
TRIP
b98e353a2b
refactor(ipc): split lib/ipc.ts into domain modules behind a barrel ( #700 )
...
Behavior-preserving: 1765-line ipc.ts → 22 domain modules + barrel index.ts; all ~118 exports preserved, 0 consumer changes, tsc/build/all-platform CI green. Part of #697 .
2026-06-17 13:38:34 +08:00
TRIP
5aed1e46ed
fix: audit batch 2 — correctness bugs + Android robustness ( #696 )
...
7 medium findings: corrupt-timestamp context truncation, voice_agent flag timing, Volcengine/Bailian ASR cancel-on-error, graceful store-init fallback (no startup panic), Android OVERLAY_VISIBLE desync (Rust+Kotlin onDestroy), JNI null-check, accessibility clipboard restore. All-platform CI green; 446 tests pass.
2026-06-17 11:39:55 +08:00
TRIP
121bb11447
fix: audit batch 1 — critical Android updater + security hardening + bug fixes ( #695 )
...
14 confirmed audit findings: critical Android auto-update fix (SUPPORTED_ABIS), security hardening (exe allowlist, window-scoped approval, update-URL validation, remote PIN rate-limit/entropy, mirror order, prompt sanitization), correctness bugs (prefs race, hotkey spawn race, voice-agent focus clear), build-hygiene, and Android robustness. All-platform CI green; 446 tests pass.
2026-06-17 11:13:27 +08:00
TRIP
0eb69fc0f4
chore: codebase cleanup + behavior-preserving refactor ( #693 )
...
Audit-driven cleanup: 6 issue fixes (#689/#686/#680/#691/#678/#612), Aura skin removal (visually-neutral), dead-code cleanup (98→87 warnings), behavior-preserving modularization (coordinator.rs 6961→3083 + LocalAsr/ + polish/ submodules), and RELEASING.md (admin-only release policy). Gates: cargo test --lib 446 passed, tsc, all-platform build + contract checks green. Supersedes #685/#687/#690/#692/#682/#681.
2026-06-16 23:22:21 +08:00
TRIP and 吕柏青
ee42d1a2e7
perf(onboarding,settings): 权限/热键状态纯事件驱动,去掉高频轮询 ( #673 )
...
* perf(onboarding,settings): 权限/热键状态纯事件驱动,去掉所有高频轮询
issue #470:引导页桌面(1s)/Android(3s)、设置页热键(1s) 的 setInterval 高频权限/热键轮询
全部改为 window focus / visibilitychange 事件驱动,连低频兜底也去掉(纯事件驱动)。
覆盖论证:麦克风前台原生弹窗授予由申请结果回调 + 800ms 兜底覆盖;辅助功能授予必经系统
设置 App、切回 OpenLess 必触发 focus/visibilitychange。并给 onGrantAccessibility 补对称的
void refresh() + 800ms 兜底(与 onRequestMicrophone 对齐)。PermissionsSection 的
refreshPermissions(10s)/refreshNetwork(30s) 保留不动。
* fix(onboarding): DesktopOnboarding effect 内 refresh() 统一加 void
@claude 审查 #673 指出:DesktopOnboarding 的 useEffect 里 refresh()/onFocus/onVisibility
三处 refresh() 是 floating promise(与上方 Android 段的 void refresh() 不一致,IPC 失败会
静默)。统一加 void 明确 fire-and-forget。issue #470。
---------
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 11:10:53 +08:00
TRIP and 吕柏青
001615ebf4
perf(local-asr): 引擎状态改后端事件驱动,前端零轮询 ( #672 )
...
* perf(local-asr): 引擎状态改后端事件驱动,前端零轮询
issue #470:LocalAsr 前端原本 setInterval 每 5s 轮询 refreshEngineStatus。改为后端在每个
状态转换点主动 emit `local-asr:engine-changed`(load: build_local_qwen3 / preload;idle
释放: schedule_local_asr_release 的 release_if_idle==true;手动释放: release_local_asr_engine
汇聚点;keepLoadedSecs 变更),前端 listen 该事件增量更新、删掉 5s 轮询与 engineStatusTimer。
挂载时仍拉一次初值,listener 在 cleanup unlisten。LocalAsrEngineStatus 加 Clone 供 emit 复用。
helper 只用跨平台符号,不碰 Foundry/Sherpa。
* fix(local-asr): emit_local_asr_engine_status 加 Android no-op stub
CI Android cargo check 失败:LocalAsrEngineStatus 不在 android target 编译。给 helper 加
#[cfg(not(target_os="android"))] 真实现 + #[cfg(target_os="android")] no-op stub,
各调用点在所有平台统一编译。issue #470 / #6。
---------
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 11:10:29 +08:00
TRIP and 吕柏青
49a6dc800f
perf(tray): 托盘麦克风设备监听改 OS 原生通知,空闲零唤醒 + 60s 兜底 ( #670 )
...
* perf(tray): 托盘麦克风设备监听改 OS 原生通知,空闲零唤醒 + 60s 兜底
issue #470:原 watcher 每 10s 轮询 list_input_devices()(CoreAudio/WASAPI 全枚举)永不
停歇。新增 device_watch 模块用 OS 原生设备变更通知替代:macOS CoreAudio
AudioObjectAddPropertyListener(kAudioHardwarePropertyDevices) 专用 CFRunLoop 线程常驻;
Windows IMMNotificationClient 经 IMMDeviceEnumerator 注册端点通知。回调复用现有去抖
(microphone_device_signature) + refresh_tray_microphone_menu + emit 收尾。
works 保证:保留一条 60s 全平台慢速兜底轮询无条件运行——原生注册失败/Linux 无原生路径
时退化到它,三平台永远能检测到设备。coreaudio-sys 提升为 macOS 直接依赖(本就在依赖树)。
注:Windows IMMNotificationClient 分支开发机(macOS)无法本地编译,靠 CI 三平台 cargo check
+ 真机验证;60s 兜底保证即使该分支失效也不会漏检设备。Cargo.lock 未提交(macOS check 会
引入大量与本改动无关的环境性条目),cargo 构建时自愈。
* fix(tray): 砍掉无法本机验证的 Windows IMMNotificationClient 原生路径
CI Windows checks 失败:windows-rs 的 IMMNotificationClient_Impl / Win32_UI_Shell_PropertiesSystem
feature 与 implement 宏的 windows_core 路径在开发机(macOS)无法编译验证,靠 CI 反复试代价大。
简化为:macOS 走 CoreAudio 原生通知(已验证),Windows / Linux 统一返回 false → 走 lib.rs
的 60s 慢速兜底轮询(仍比原 10s 少 6 倍唤醒、保证三平台编译通过)。Windows 原生设备通知
留作后续单独项(需 Windows 开发机验证)。issue #470。
---------
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 11:10:22 +08:00
TRIP and 吕柏青
2d783ce337
perf(coordinator): 可选热键 supervisor 注册成功即退出,彻底消除稳态轮询 ( #671 )
...
issue #470:combo/translation/action 三类可选热键 supervisor 原本注册成功后不退出,稳态
每 5s 醒来读 prefs,多线程常驻空转。改为对齐主 hotkey_supervisor_loop 的 exit-on-success
模式——到达「已安装」或「已主动停用」稳态即 return 退出,零轮询。
安全前提(已逐函数确认):用户启用/改/停这些热键时,set_*_hotkey 命令与 persist_settings
diff 都会调 update_*_hotkey_binding,其覆盖「monitor 为 None → 从零 start+spawn」安装路径,
故退出后启停改键无需重启即时生效;ComboHotkeyMonitor 注册后驻留、无运行中自注销,monitor
不会自己死,无需 supervisor 守护。失败重试 sleep(3s)/recv_timeout(5s)/app未就绪 sleep(1s)
等有界路径全部保留。
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 10:56:37 +08:00
TRIP and 吕柏青
16e0f27685
perf(marketplace,localasr): 清理冗余定时器 ( #674 )
...
issue #470:
- Marketplace 上传后双重 setTimeout(1.5s+5s) 去重为单次 5s——乐观更新已即时反映「我的
发布」,延时刷新仅做服务端状态校准,1.5s 那次纯冗余。
- LocalAsr scheduleScrollGuardRestore 三连 setTimeout(0/80/200ms) 仅删等价的 0ms 那枪
(已被紧随的 rAF 覆盖),保留 80/200ms 兜住 rAF 之后的异步重排,避免滚动跳变回归。
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 10:56:32 +08:00
TRIP and 吕柏青
9f3eebcb88
perf(less-computer-glow): 隐藏时卸载全屏发光层,消除空闲 GPU 占用 ( #675 )
...
issue #470:彩虹描边 glow 是全屏 transparent 浮层 + 4 条无限动画(lcg-spin/breathe/
spin-reverse/flow)。原组件无状态无监听,窗口 .hide() 后 webview 仍持续合成发光层、
跑满 4 条动画,GPU 永不释放(Windows 尤其不释放)。
改为后端 show/hide 主动 emit `less-computer-glow:active` 驱动可见状态(不依赖在隐藏
窗口上失灵的 WebView2 visibilitychange):可见时渲染与原来完全一致的 DOM(视觉零变化),
不可见时返回 null 卸载发光层 → 零 GPU。另加 document.hidden 二级兜底(只停不启)。
注:glow 当前为 macOS-only(Windows show/hide 是 no-op),本修复消除 macOS 隐藏态泄漏,
并让组件具备跨平台「隐藏即零 GPU」安全性,为后续 Windows 重启用铺路。
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 10:56:27 +08:00
TRIP and 吕柏青
28ea5123b4
perf(capsule): 删除无效的 translation 徽章 backdrop-filter ( #676 )
...
issue #470:该 backdrop-filter:blur(20px) 作用在浮于透明窗口之上的 translation 徽章
pill 上,背后只有透明窗口=桌面,而 webview 模糊不了窗口背后的桌面(Tauri 上游限制,
本文件上方 pill 已有同款注释)。故它不产生任何模糊效果、纯空耗一次合成。删除零视觉变化。
Co-authored-by: 吕柏青 <lubaiqing9@gmail.com >
2026-06-16 10:56:22 +08:00
TRIP
dbb0676ccb
Merge pull request #656 from Open-Less/revert/aura-ui-to-beta3-keep-features
...
revert(ui): 回退 AURA 界面大改到 beta-3 外观,保留功能与今日修复
2026-06-13 14:12:11 +08:00
TRIP
8142cceebd
Merge pull request #649 from aron-76/codex/macos-capsule-input-monitor
...
Fix macOS capsule monitor targeting
2026-06-13 10:47:00 +08:00
TRIP
8c1e0c50e3
Merge pull request #652 from HKLHaoBin/feat/card-ui-unification
...
fix(ui): 统一卡片样式并修复深色模式可读性
2026-06-13 10:39:37 +08:00
TRIP
19ae8641d6
Merge pull request #621 from Open-Less/fix/aura-ui-polish
...
revert(ui): 回退 aura 皮肤 + 钥匙串/彩虹边框/提示词修复 (1.3.6-3)
2026-06-08 17:43:24 +08:00
TRIP
9b14c031da
Merge pull request #619 from Open-Less/refactor/split-dictation
...
refactor(dictation): dictation.rs 2766→425 拆为 4 个子模块(机械式·零回归)
2026-06-08 13:27:57 +08:00
TRIP
cf1ddae523
Merge pull request #617 from Open-Less/fix/issue-609-security-audit
...
fix(security): 收 #609 安全审计 — SSRF/prompt注入/history HMAC/QA信封 (F-01~F-06)
2026-06-08 13:27:40 +08:00
TRIP
b4038de4f1
Merge pull request #616 from Open-Less/fix/cross-platform-popup
...
fix(popup): 跨端弹窗一致性 — capsule 四边 clamp + Windows 句柄重试(#470 ) + qa 焦点契约(#466 )
2026-06-08 13:27:22 +08:00
TRIP
5da5445a10
Merge pull request #615 from Open-Less/refactor/srp-split-dedup
...
refactor: coordinator.rs/commands.rs 单一职责拆分 + 重复函数合并(机械式·零回归)
2026-06-08 13:26:09 +08:00
TRIP
e9ecc25b7d
Merge pull request #597 from Open-Less/feat/fast-agent
...
feat(less-computer): Less Computer 语音 Agent —— 专用键 + 动作模式 + 流式聊天弹框 + 内联审批(启发式)
2026-06-07 13:07:18 +08:00
TRIP
1b6f0dffe1
Merge pull request #605 from Ltdaaa/view
...
feat: introduce a theme-aware frosted-glass visual system for OpenLess frontend
2026-06-07 12:45:11 +08:00
TRIP
5ca3a80cd6
Merge pull request #581 from aeoform/chore/linux-plugin-check-and-ux-cleanup
...
chore(linux): plugin 路径检查增强 + 去除启动加载界面 + 修正快捷键描述
2026-06-05 08:02:14 +08:00
TRIP
30cf33e2b1
Merge pull request #589 from Open-Less/docs/readme-real-example
...
docs(readme): 实际效果示例换成客户回邮件用例(中英双语)
2026-06-04 19:33:36 +08:00
TRIP
2067367d83
Merge pull request #588 from ig505gi/fix-beta-reset
...
fix(macos): Beta 更新重启前重置 TCC 权限记录
2026-06-04 19:29:46 +08:00
TRIP
61f5416c73
Merge pull request #587 from Open-Less/docs/discord-community-link
...
docs(readme): 顶部加入 Discord 社区入口
2026-06-04 19:00:47 +08:00
TRIP
7cc8175d98
Merge pull request #586 from Open-Less/ci/auto-update-homebrew-cask
...
ci(release): 正式发版自动更新 Homebrew cask(+ 补 cask 到 1.3.5)
2026-06-04 13:08:27 +08:00
TRIP
13a0a03ab3
Merge pull request #584 from Open-Less/fix/audio-cue-missing
...
fix(audioCue): 修复快速录音时录音提示音偶尔丢失
2026-06-04 13:08:19 +08:00
TRIP
85d6ed851f
Merge pull request #583 from Open-Less/fix/polish-context-isolation
...
fix(polish): 对话感知上下文——按风格包隔离 + 翻译会话参与润色(不串味)
2026-06-04 13:08:09 +08:00
TRIP
4bc94ecc5e
Merge pull request #560 from Open-Less/feat/audio-cue-on-record
...
feat(capsule): 录音开始播放合成提示音 + 录音与输入设置开关
2026-05-31 14:01:35 +08:00
TRIP
1b8217eddb
Merge pull request #521 from Open-Less/feat/settings-revamp
...
feat(settings): 设置界面重构 — 分节化 / 精简 / Beta 渠道 / 麦克风 / 市场登录
2026-05-22 23:33:46 +08:00
TRIP
32d7c22a8c
Merge pull request #519 from Open-Less/feat/frosted-glass-overlays
...
feat(ui): 划词追问框与语音胶囊磨砂玻璃质感
2026-05-21 23:54:01 +08:00
TRIP
370eaa858e
Merge pull request #506 from Open-Less/pr2/ui-i18n-refresh
...
refactor(ui): 精简多语言文案 + 设置/风格/市场界面与图标重构
2026-05-20 16:31:31 +08:00
TRIP
e8f8ac0f59
Merge pull request #505 from Open-Less/fix/saved-toast-position
...
fix(ui): 统一 SavedToast 弹框位置与进出方向
2026-05-20 16:29:09 +08:00
TRIP and baiqing
a1d9549db2
fix(startup): autostart catch 块缺 return 导致复活主窗口 ( #468 ) ( #488 )
...
* fix(startup): autostart catch 块缺 return 导致复活主窗口 (#468 )
PR #474 引入的"前端兜底"useEffect 在 webview ready 后读
prefs.startMinimized,true 则跳过 currentWindow.show()。但 catch 块只
console.warn 没有 return,控制流继续走到 show()——等于"prefs 读失败 = 强 show"。
autostart 早期 IPC 抖动时 getSettings() 偶发失败,旧逻辑让用户明明开了
静默启动仍把主窗口弹出来。
修复: catch 块加 return,安全侧默认 = 当作 startMinimized=true 保持隐藏。
宁可让用户从 tray 手动唤起,也不要在 autostart 抖动时强 show 一个白色
/ 透明主窗口。
LSUIElement 不在本 PR 范围: 那是全局 macOS UX 决策,会影响 Finder
双击 / Spotlight / Launchpad 启动场景,应单独 PR + 单独评审。
正确做法是 Rust 端动态切 activationPolicy 而非 plist 静态写死。
Refs #468
* docs(startup): clarify catch rationale + improve warn diagnostics
Both local review and PR-Agent bot flagged the "fallback when settings
read fails" semantic reversal. Re-analysis confirms the change is
correct, but the rationale needs to be explicit in the code:
- Rust `get_settings` signature is `pub fn -> UserPreferences` (not
Result), so this catch is unreachable from a normal first-launch
scenario (returns defaults). Only Tauri IPC infrastructure failures
(e.g. __TAURI_INTERNALS__ not ready during autostart early-mount)
reach this branch.
- Tray is registered by Rust setup() before webview ready, so it remains
the universal fallback entry point — no "user locked out" risk.
- Improved console.warn to include err.message for diagnostics, since
raw err objects serialize as [object Object] in Tauri devtools.
No behavior change; comment + log improvement only.
Refs review of #488
---------
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-18 19:00:28 +08:00
TRIP and baiqing
6e55e3059b
fix(windows): capsule/qa 透明窗口 Acrylic 兜底 ( #487 )
...
* fix(windows): capsule/qa 透明窗口 acrylic 兜底 + CSS 可读性兜底
根因: tauri.conf.json 三个窗口都 transparent: true,但 lib.rs 只对 main
窗口调用 apply_mica。capsule / qa 在 Windows 上是裸 transparent,
Webview2 的 backdrop-filter 只能模糊页面内部 DOM 不能模糊 OS 桌面,
导致用户看到的胶囊 / QA 浮窗几乎完全透出桌面壁纸。
macOS 上 NSVisualEffectView (HudWindow vibrancy) 直接由系统合成器
混合桌面,所以 macOS 不需要额外处理。
修复:
1. lib.rs 在 setup 时对 capsule / qa webview 调用 apply_acrylic(
color=(30,32,38,140)) — 选 Acrylic 而非 Mica 因为 Acrylic 支持
Win10,更适合小浮窗。失败仅 log::warn 不 panic。
2. global.css 末尾追加 @supports not (backdrop-filter) 和
@media (prefers-reduced-transparency: reduce) 兜底,给 html/body
设实色背景。组件层 inline style 无法被覆盖,这只是二级防护。
Note: Capsule.tsx 和 FloatingShell.tsx 的 inline alpha 保留不动;
Acrylic 兜底通常足够。如果 Win10 实测仍偏透(Mica 不支持 Win10),
后续 PR 可考虑给 main 也加 Acrylic 作为 Mica fallback。
* style(windows): drop global html/body fallback rules from acrylic PR
Local code review flagged that `html, body { background: ... }` applies
to ALL windows including `main`, which would clobber the macOS
NSVisualEffectView vibrancy in `prefers-reduced-transparency: reduce`
mode.
Re-analysis confirms both rules are speculative:
- @supports never fires on modern Webview2 / WKWebView / Chromium
(all support backdrop-filter)
- prefers-reduced-transparency triggers OS-level vibrancy neutralization
on macOS already, but the CSS rule would still wrongly land on main
Acrylic in lib.rs is the canonical fix for the user-reported P0
(capsule/qa 透明遮罩看不清). The CSS layer is dropped to keep the PR
scoped to a single concern and avoid the cross-window collateral.
Refs review of #487
---------
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-18 18:57:43 +08:00
TRIP and baiqing
f30a787227
fix(windows): hotkey toggle 二次按键失效 - 串行化 Pressed/Released edge ( #489 )
...
根因: hotkey_bridge_loop 和 combo_hotkey_bridge_loop 把每条 Pressed/Released
边沿独立 async_runtime::spawn 成两个 task,被 tokio work-stealing 调度器
并行执行。Windows WH_KEYBOARD_LL 边沿间隔微秒级,Released task 经常先
swap(true→false),导致下一次 Pressed 看到 was_held=true → toggle 被静默吞掉。
macOS 上 CGEventTap 边沿间隔几十毫秒,race window 极窄,肉眼不可见,
所以仅 Windows 必现。ESC 走 HotkeyEvent::Cancelled 不经过 latch,
是用户唯一能逃出 stuck-latch 的路径。
修复: 用 tauri::async_runtime::block_on 顺序 await 两个 handler,
bridge 线程的 mpsc::Receiver::recv() FIFO 保证 swap 顺序正确。
bridge 在独立 OS 线程而非 tokio worker,block_on 安全。
代价: Hold 模式短按 stop 多 ≤500ms 延迟,被 request_stop_during_starting
覆盖,可接受。qa / translation bridge 不走 handle_*_edge 不受影响。
附带清理 coordinator.rs unreachable_code warning。
Refs #468
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-18 18:54:53 +08:00
TRIP and baiqing
b4e806e3ca
fix(windows): 静默启动 #468 最后一公里 - 前端兜底 ( #474 )
...
* fix(windows): 修复 #466 #468 #469 IME 切回 / 静默启动 / QA 焦点 + #470 capsule 诊断 (#471 )
集中修复 4 个 Windows-only bug:
- #469 IME 切不回 — restore_profile 对称补 legacy TSF ChangeCurrentLanguage + ActivateLanguageProfile,回归点是 c3b59329 升级激活路径时漏改恢复路径。现代 ActivateProfile 失败降为 warn(legacy 已完成视觉切回)。
- #468 Win11 静默启动失效 — single-instance 回调读 start_minimized,true 时跳过 show_main_window;托盘 / CLI intent 路径不受影响。
- #466 QA 弹窗 X/ESC 关不掉 — Win 上从 SW_SHOWNOACTIVATE 切到 Tauri window.show + set_focus,让 webview 拿键盘焦点。配套 focus-dance:begin_qa_session 抓选区前临时把焦点还给用户原 app,抓完再 refocus QA;多轮场景下用 GetWindowThreadProcessId 区分本进程窗口,刷新 qa_focus_target,避免 stale HWND。
- #470 录音胶囊不显示 — 加 per-process 一次性诊断 log(CapsuleState 用 capsule_state_log_name 显式短名,不走 Debug 防字段扩展时泄露),下次能直接定位 prefs / state / Win32 哪一环失败。
pr_agent 五轮迭代到 No major issues + No security concerns;Cloud 评审建议的 begin_qa_session 双锁 TOCTOU 已合并为单 scope。三平台 build + pr_agent CI 全绿。
#470 没标 closes,是 refs—需要真机日志才能定位真因,先 ship 诊断手段。
* chore(release): bump version to 1.3.4-3 (Beta) — Windows #466 #468 #469 修复
* fix(settings-ui): 权限页徽章不换行 + 本地 ASR 区块 Win 灰显
权限页 (Settings → 快捷键 → 权限):
- Pill 组件加 whiteSpace:nowrap + flexShrink:0 → "已安装"徽章在 Win
窄宽下不再被挤成 3 行(每个汉字一行)。
- 行内 message span 加 whiteSpace:nowrap + overflow:hidden +
textOverflow:ellipsis + minWidth:0 → 长文本("Windows 低层键盘 hook
已安装")超宽时省略号收尾,徽章保持完整。
- zh-CN 描述大段精简:descAcc / descNoAcc / micDesc / accDesc /
hotkeyDesc / networkDesc / windowsImeDesc / windowsIme.* 都改短,
减少 Win 上拥挤感(用户反馈 zh 文案过长)。
高级页 (Settings → 高级 → 本地 ASR):
- Windows 上把"本地 ASR 模型(实验性)"标题区 + 警告小字 + Qwen3 行
整组 opacity:0.45 灰显 —— Qwen3 在 Win 是 stub 不支持,那条"实验性"
主线在 Win 没意义;用户视觉关注点应落到下方独立的 Foundry 行(Foundry
保持正常颜色)。Toggle 的 disabled 行为已经在原 onToggle 条件里,本次
纯加视觉灰显。
* fix(windows): 前端 App.tsx 在 show 主窗口前读 startMinimized 兜底
#471 在 Rust 端 setup() / single-instance callback 都加了 start_minimized
suppression,本机日志确认 Rust 路径完全正确("[main] start_minimized=true
→ 跳过初始 show")。但用户在 Win11 1.3.4-3 上仍然「重启进桌面那一刻主
窗口就出来了」。
定位到最后一条遗漏路径在前端:App.tsx 里 mount 时一条 useEffect 无条件
通过 IPC 调 `getCurrentWindow().show()`,把 Rust 端已经 suppress 的窗口
又拉出来 —— 这条路径 Rust log 完全看不见(走的是 plugin-window 的
showWindow IPC,不经过我们的 show_main_window helper)。
那条 useEffect 当初是给 issue #163 引入的:Windows 权限探测可能死锁让
首屏卡灰,所以前端兜底 force show 一次。
修法:show 前先读 prefs.startMinimized,true 就 return。读 prefs 失败
(极少数情况)保持原 show 行为,不让 #163 的兜底语义丢失。
closes #468 (the actual one this time, Rust + JS 双端都收敛了)
---------
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-18 15:29:33 +08:00
TRIP
ceda87f64f
fix(settings-ui): 权限页徽章不换行 + 本地 ASR 区块 Win 灰显 ( #473 )
...
Windows 真机反馈的两条 UI 问题,纯 frontend:
- 权限页徽章 3 行 wrap — Pill 加 whiteSpace:nowrap + flexShrink:0;message span 加 ellipsis 五件套;zh-CN 描述大段精简
- 本地 ASR 区块 Win 灰显不完整 — Win 上标题区 + 警告 + Qwen3 行整组 opacity:0.45,Foundry 保持正常色
cherry-pick from main (be24bb7),PR base=beta 保持双线同步。pr_agent 一轮 clean、Claude LGTM、三平台 CI 全绿。
2026-05-18 13:35:20 +08:00
TRIP
c4bbec9cef
Merge pull request #451 from aeoform/beta
...
feat(linux): fcitx5 plugin for Wayland input + deb packaging
2026-05-18 09:07:13 +08:00
TRIP and baiqing
fe56eb3038
fix(ci): detach HEAD before claude-code-action on fork PR ( #464 )
...
PR #451 (来自 fork aeoform/openless, head ref 也叫 beta) 触发 @claude 时,
claude-code-action 执行 `git fetch origin pull/451/head:beta` 把 PR head
拉到本地 beta 分支,但此时 worktree 正 checkout 在 refs/heads/beta,
git 拒绝 fetch 到已 checkout 的分支:
fatal: refusing to fetch into branch 'refs/heads/beta' checked out at ...
Action failed with error: Command failed: git fetch origin --depth=20 pull/451/head:beta
修复: 在 actions/checkout 后立即 git checkout --detach,释放
refs/heads/<default-branch> 这个本地分支名,让 action 自己 fetch 不撞名.
仅在 fork head ref == base ref name 的 corner case 才会触发问题,
detach 对其他场景无副作用.
失败 run: https://github.com/Open-Less/openless/actions/runs/25978532215
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-17 14:09:58 +08:00
TRIP and baiqing
859fd5370f
feat(updater): Beta 渠道接通 auto-update(Builder.endpoints runtime 切换) ( #465 )
...
* feat(updater): Beta 渠道接通 auto-update(Builder.endpoints runtime 切换)
CLAUDE.md 之前的论断「tauri-plugin-updater 2.10 Builder 不暴露 endpoints()」在
2.10.1 已不成立 —— Builder 现在有 .endpoints(Vec<Url>) -> Result<Self>,build()
里 self.endpoints.unwrap_or_else(|| self.config.endpoints.clone()) 走 runtime 覆盖。
实现 channel-aware 自动更新(不 fork plugin、不写自定义下载/签名校验):
Rust(~100 行新增)
- commands.rs::app_check_update_with_channel:
Stable → webview.updater_builder().build()?.check()(默认 endpoints 从 tauri.conf)
Beta → fetch_latest_beta_release() → 拼镜像 + 直连两份 -beta manifest URL
→ builder.endpoints(urls)?.build()?.check()
- AppUpdateMetadata 字段形状对齐 plugin 的 UpdateMetadata(rid + currentVersion
+ version + body + rawJson),前端 new Update(metadata) 即可复用 plugin 的
download / install / close。
- lib.rs 注册新 command。
前端(~30 行改动)
- AutoUpdate.tsx::checkForUpdates 从 import('@tauri-apps/plugin-updater').check
改为 invoke('app_check_update_with_channel');其余 download / install / close
全走 plugin 原生 JS API(new Update(metadata) 后链式调用)。
- SettingsModal::BetaChannelControl 删掉「打开 GitHub 下载」按钮 ——
auto-update 接管了,手动下载路径冗余;保留「最新 Beta 版本号 + 刷新」做信息透明。
- i18n 5 个 locale 改 betaChannelDesc 文案,把「需要手动下载安装」改成
「自动接收最新 Beta 版本」。betaChannelDownloadBtn 等 i18n key 暂留(无用但无害)。
物理隔离仍生效:Beta tag 的 manifest 文件名带 -beta 后缀,跟 Stable 的
latest-{tgt}-{arch}.json 在 GitHub Release assets 里是分开两份;即使代码逻辑
错把 Beta URL 给 Stable 用户也是 HTTP 404,不会拿到错档。
验证:cargo test --lib serial 270 / 0 / 0;tsc clean;vite build clean。
* feat(settings): BetaChannelControl 加版本比对 + 「立即更新」按钮
之前 BetaChannelControl 在 toggle 打开后,只机械显示「最新 Beta: vX-beta-tauri」,
不管本机版本是不是已经等于那个 tag。用户报告:「显示有最新 Beta,但应该比对版本号」。
修复:
- parseVersionFromBetaTag("v1.3.4-1-beta-tauri") → "1.3.4-1"
- semverGreater(remote, local) 做 SemVer 风格比对(支持 X.Y.Z 和 X.Y.Z-N,覆盖
本仓库实际版本格式;prerelease 按 SemVer 规则 lower than no-prerelease)
- 本机 >= 最新 → 「最新 Beta: vX」 + 蓝色「已是最新」chip
- 本机 < 最新 → 「最新 Beta: vX」 + 「立即更新」按钮(蓝色高亮)
- 「立即更新」点击 → useAutoUpdate.checkForUpdates → 走和全局「检查更新」按钮
完全相同的 download/install 流程,UpdateDialog 直接挂在 BetaChannelControl 内部
- 用户的第二个 feature 诉求:「在 Beta 渠道旁边一键检查 + 自动更新」 = 这个按钮
i18n 5 个 locale 加 4 个 key:betaChannelUpToDate / betaChannelUpdateNow /
betaChannelUpdateNowTitle / betaChannelChecking。
* chore(release): bump 1.3.4-1 → 1.3.4-2 for Beta channel
`-2` 后缀让 appVersion.ts 的 IS_BETA_BUILD 仍判为 Beta,UI BETA 标签照常显示。
配本 PR 的 Beta auto-update + BetaChannelControl「立即更新」按钮,1.3.4-1 用户
切到 Beta 渠道后点检查会发现 1.3.4-2 并走 auto-update 流程一键升上来。
发布 tag:v1.3.4-2-beta-tauri。
---------
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-17 11:15:06 +08:00
TRIP and baiqing
061558a0fa
fix(shell): sidebar 底部翻回两行(版本在上、设置在下) ( #463 )
...
PR #462 把底部折成一行,结果在窄 sidebar 下「设置」被挤成两行
竖字、版本 chip 糊在旁边,可读性大幅退化。改回两行但反过来:
- 上行:[BETA] 版本 v1.3.4-1(容下 BETA 标 + 完整版本号)
- 下行:⚙ 设置(真正落到最底,符合最初诉求)
设置按钮恢复 display:flex + label flex:1 跟上面 nav 按钮统一风格。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-17 10:27:41 +08:00
TRIP and baiqing
0ecb3bd5a4
chore: bump 1.3.4-1 + sidebar 底部行折成单行 ( #462 )
...
* feat(shell): sidebar 底部行折成单行(设置 + 版本)
把 sidebar 底部「⚙ 设置」和「版本 v1.3.x」从上下两行折成一行:
- 设置按钮 display 由 flex 改成 inline-flex,去掉 label 的 flex:1
(不再撑满 sidebar 宽度)
- 版本 chip(含 BETA 标)用 marginLeft: auto 推到行尾
外观更紧凑、纵向更省、视觉重心从两行散开收到一行。
* chore(release): bump version 1.3.3 → 1.3.4-1 for Beta channel
`-1` 后缀让 appVersion.ts 的 IS_BETA_BUILD 自动判为 Beta,UI 上的
BETA 标签会自动恢复显示。bump-version.sh 不收带 dash 的 prerelease
格式,所以这次手动同步 5 个文件(package.json / package-lock.json
root + nested / tauri.conf.json / Cargo.toml / Cargo.lock)。
发布 tag 仍走 v<v>-beta-tauri:v1.3.4-1-beta-tauri。
---------
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-05-17 10:18:21 +08:00