Commit Graph
473 Commits
Author SHA1 Message Date
Chris233 7f1df503b9 Merge pull request #276 from H-Chris233/fix/issue-222-pr-agent-hardening
加固 PR-Agent workflow 的 secrets 暴露面
2026-05-06 08:08:40 +08:00
H-Chris233 bd4547b613 Pin PR-Agent runtime while preserving automatic reviews
The workflow must keep reviewing every PR and every pushed commit automatically, including fork PRs, so the hardening focuses on pinning the code that actually runs in the secrets-bearing job. The wrapper action commit still delegates to a mutable Docker tag, so the workflow now calls the PR-Agent container by immutable digest directly.

Constraint: Maintainer preference is automatic PR-Agent coverage for each PR and synchronize event.

Constraint: Issue #222 requires removing mutable third-party execution refs from the secrets-bearing path.

Rejected: Pin only the action repository commit | the wrapper Dockerfile still resolves pragent/pr-agent:github_action at runtime.

Rejected: Require trusted comment triggers for fork PRs | too inconvenient because new commits would not be reviewed automatically.

Confidence: medium

Scope-risk: moderate

Directive: If fork PR automation remains required, keep the runtime container digest-pinned and do not checkout PR head code in this workflow.

Tested: Parsed .github/workflows/pr-agent.yml with PyYAML and asserted docker:// sha256 form; git diff --check; grep confirmed no action ref or github_action tag remains in the workflow.

Not-tested: Live GitHub Actions execution or Docker Hub digest pull from this host.

Related: https://github.com/appergb/openless/issues/222
2026-05-06 07:51:46 +08:00
Chris233 56694db7f6 Merge pull request #275 from Hongbro886/docs
docs(readme): document macOS-only qwen-asr submodule init step
2026-05-06 07:12:31 +08:00
Chris233 f803361b5c Merge pull request #273 from H-Chris233/fix/issue-223-active-asr-credentials
fix(providers): 按 active ASR provider 返回配置状态
2026-05-06 07:11:00 +08:00
whoa bfc718323b docs(readme): document macOS-only qwen-asr submodule init step 2026-05-06 06:29:38 +08:00
H-Chris233 cb60a034b6 让凭据状态按 active provider 判断,修复错误配置提示
get_credentials 不再把 ASR 配置状态硬编码为 Volcengine,而是返回 active provider 与通用 asrConfigured/llmConfigured。前端 provider setup prompt 与 Overview 改为读取通用状态并展示 active provider 名称,避免 Whisper-compatible 用户已配置却持续被提示未配置。配置完成判定统一为 API Key 可空但 endpoint/model 必须存在:云端 ASR 需 endpoint/model,LLM 需 endpoint/model。保留旧字段做兼容过渡。

Constraint: 最小修改原则,保持现有 provider 凭据存储结构不变

Rejected: 只按 ASR API key 标记已配置 | keyless provider 会被误判,且 endpoint/model 缺失仍不可运行

Rejected: 彻底移除旧 volcengineConfigured/arkConfigured 字段 | 需要分阶段兼容前端调用

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Provider configured 表示具备 endpoint/model 基础配置;连接有效性仍由验证按钮负责

Tested: npm run -s build

Tested: cargo test -q (74 passed)

Related: #223
2026-05-06 00:23:19 +08:00
Chris233 b802dc4154 Merge pull request #274 from sora520/feat/mute-during-recording
feat(recording): mute system output while recording
2026-05-06 00:14:57 +08:00
Chris233 fa6d4d15c8 Merge pull request #270 from appergb/fix/local-asr-release-flow
fix(local-asr): 切走/删模型/手动释放时真正归还 RAM
2026-05-06 00:05:57 +08:00
Chris233 d7e3017fa9 Merge pull request #272 from sora520/fix/translation-hotkey-placeholder
fix(i18n): render translation hotkey placeholder
2026-05-06 00:02:32 +08:00
kaku.ki 78a38460ce fix(recording): make QA mute release idempotent 2026-05-06 00:13:44 +09:00
kaku.ki bb0fefc786 fix(recording): share mute guard across sessions 2026-05-05 23:56:26 +09:00
kaku.ki 9511eb6333 feat(recording): mute system output while recording 2026-05-05 23:28:56 +09:00
kaku.ki 72c14bc437 fix(i18n): render translation hotkey placeholder 2026-05-05 22:02:36 +09:00
Chris233 6d1ff0f872 Merge pull request #271 from H-Chris233/feat/ja-ko-output-language
feat(i18n): 增加日语/韩语支持并让输出语言随界面语言联动
2026-05-05 20:47:49 +08:00
H-Chris233 04536830a2 让界面语言直接驱动日文/韩文输出偏好并避免翻译链路冲突
在现有简繁联动基础上扩展 ja/ko 本地化与 outputLanguagePreference,保持不新增额外设置项。前端在语言切换时统一同步 chineseScriptPreference + outputLanguagePreference;后端在 polish/QA 链路注入输出语言偏好,但翻译链路固定以 target_language 为唯一约束,避免 UI 语言与翻译目标冲突。

Constraint: 用户要求最小修改且不新增独立输出语言开关

Rejected: 新增单独输出语言设置项 | 与既定交互约束冲突

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: 翻译链路不要再次注入 output language 偏好,除非先定义与 target_language 的优先级规则

Tested: npm run -s build

Tested: cargo test -q (72 passed)

Not-tested: 真机端到端切换 ja/ko 后的实际模型输出体验
2026-05-05 20:28:38 +08:00
Chris233 5c1a796771 Merge pull request #268 from millionart/codex/register-windows-ime-nsis-installer
fix: register Windows IME from NSIS installer
2026-05-05 20:20:57 +08:00
baiqing 463a6d9716 fix(local-asr): 切走/删模型/手动释放时真正归还 RAM
三个问题合修:

1. 用户点"释放"按钮后活动监视器看 RSS 不下降。原因:encoder f32 weights
   是 malloc 出来的几百 MB,free 后 macOS libmalloc 不会立即把页归还内核。
   修:drop QwenAsrEngine 后调 malloc_zone_pressure_relief(NULL, 0),主动
   归还。decoder bf16 走 mmap 不依赖这个。

2. 切回云端 ASR 后本地引擎仍驻留。set_active_asr_provider 切到非 local
   时未释放,1.2GB+ RAM 一直留到进程退出。

3. 删除已下载的模型时未释放内存里加载的同 id 引擎,留下 mmap 指向已
   unlink 文件 + RAM 不归还的双重问题。

Windows 端本期不上线(cache.rs macOS cfg 块包住改动)。
2026-05-05 20:20:46 +08:00
millionart ec9f658a1d fix: harden Windows IME installer smoke 2026-05-05 19:31:49 +08:00
millionart b303ea405b fix: guard windows installer smoke exits 2026-05-05 19:05:56 +08:00
millionart 4a7a1b6b8c test: cover nsis ime edge cases 2026-05-05 18:51:29 +08:00
millionart eca76deaee fix: require machine nsis installs for ime 2026-05-05 18:50:10 +08:00
millionart dbbe419ffb fix: handle nsis ime installer edge cases 2026-05-05 18:49:36 +08:00
millionart 933e014a80 test: assert nsis uninstall ignores unregister failures 2026-05-05 18:36:17 +08:00
millionart 68ee9dfae4 fix: keep nsis uninstall non-blocking 2026-05-05 18:26:09 +08:00
millionart e67755d04e fix: address Windows IME installer review feedback 2026-05-05 18:16:48 +08:00
millionart 753236dd55 fix: register Windows IME from NSIS installer 2026-05-05 17:38:28 +08:00
Chris233 c4dba80f34 Merge pull request #265 from H-Chris233/feat/zh-tw-script-sync
Align Chinese output script with locale selection (zh-CN/zh-TW)
2026-05-05 17:31:28 +08:00
H-Chris233andOmX 7985476886 Avoid stale locale-script writes when language change awaits i18n switch
Latest review flagged that language handlers captured prefs before awaiting setLocalePreference, then replayed stale snapshots via object spread.

This adds functional update support to updatePrefs in HotkeySettingsContext and switches both language pickers to merge chineseScriptPreference against current prefs at write time.

Constraint: Keep the fix minimal and avoid refactoring unrelated settings flows
Rejected: Read prefs from IPC again before each write | Adds extra roundtrip and still duplicates merge logic
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Async settings handlers should pass functional updaters whenever they await before persisting
Tested: npm run -s build (openless-all/app)
Not-tested: cargo test -q (no Rust changes in this patch)
Related: https://github.com/appergb/openless/pull/265
Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-05 17:03:22 +08:00
H-Chris233andOmX 1adde82f13 Apply script normalization when translation falls back to raw ASR
Latest PR review flagged that translation-mode failures were bypassing chinese script normalization because of a translation_active guard.

This narrows the condition to normalize only ASR-direct outputs, including translation fallback failures, while still avoiding normalization on successful translation/LLM outputs.

Constraint: Keep successful translation and polished LLM outputs untouched
Rejected: Remove all guards and always normalize final text | Would risk mutating successful non-ASR outputs
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Script normalization should run for any fallback-to-raw path regardless of translation mode
Tested: cargo test -q (openless-all/app/src-tauri)
Not-tested: Manual runtime translation failure simulation in desktop UI
Related: https://github.com/appergb/openless/pull/265
Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-05 16:32:01 +08:00
H-Chris233andOmX 2970451f01 Prevent locale script sync from persisting stale preference snapshots
The review highlighted a race where script auto-sync could persist an older prefs snapshot while concurrent settings updates were queued.

This updates HotkeySettingsContext persistence to resolve the object at queue execution time from latestPrefsRef, then merge chineseScriptPreference into that latest shape for script sync writes.

Constraint: Keep fix minimal and limited to HotkeySettingsContext persistence flow
Rejected: Full settings-store refactor with transactional backend API | Out of scope for this review round
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Any future auto-sync writes must merge against latest prefs before calling setSettings
Tested: npm run -s build (openless-all/app)
Not-tested: Full cargo test rerun (no Rust code changes in this patch)
Related: https://github.com/appergb/openless/pull/265
Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-05 16:06:29 +08:00
H-Chris233andOmX 1075ba463f Keep Chinese output script aligned with the selected UI locale
This change binds locale selection to a persisted chineseScriptPreference so zh-CN and zh-TW drive output script consistently.

It injects script preference into LLM context for polish/translate/QA, removes ASR language-hint submission, and applies script conversion only in pure-ASR fallback paths. It also hardens preference persistence sequencing in HotkeySettingsContext to reduce write-order races.

Constraint: Must keep output script behavior coupled to locale choice without adding a new toggle
Constraint: ASR requests should not send language parameters
Rejected: Add an independent output-script option | Conflicts with required locale-driven behavior
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep zh-CN=>simplified and zh-TW=>traditional mapping consistent in both Settings entry points and backend consumers
Tested: npm run -s build (openless-all/app)
Tested: cargo test -q (openless-all/app/src-tauri)
Not-tested: Live external provider E2E verification across multiple real ASR/LLM vendors
Related: #242
Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-05 16:06:29 +08:00
TRIP c85b1bd4c6 Merge pull request #263 from appergb/fix/local-asr-pr-review-fixes
fix(local-asr): 修 PR #262 review 提的两个 bug
2026-05-05 13:36:55 +08:00
baiqing cd00ebc584 fix(local-asr): 修 PR #262 review 提的两个 bug
(1) 小文件路径 try_download_range_append 的 retry 污染:
  原实现用 append 模式打开 .partial。若上一次 attempt 已写了部分字节后失败,
  retry 拿到的还是完整 chunk → append → 文件比应有大小多 N 字节,永久损坏。
  改成 truncate(effective_start) + seek 写入,每次 attempt 从干净起点重写。
  小文件(≤ 32MB)每个 chunk 是整个文件,重写无成本。

(2) 多文件并发一个失败不 abort 其它 worker:
  原代码只 log "signaling others to stop",没真 set cancel flag。剩下的
  workers 会继续吃带宽直到全部完成才把错误冒上来。
  现在错误时主动 cancel.store(true),再用 self_aborted 标记区分这是"我们
  因错误 abort"还是"用户主动 cancel"——前者 emit Failed,后者 emit Cancelled,
  避免错误被误报成用户取消。

跟踪 PR: #262 review by github-actions PR Reviewer Guide
2026-05-05 12:59:01 +08:00
TRIP 438fce26ab Merge pull request #262 from appergb/feat/local-asr-qwen3
feat(local-asr): 加本地 Qwen3-ASR 引擎(macOS 优先)
2026-05-05 12:53:35 +08:00
baiqing 8c3e4aca0d Merge remote-tracking branch 'origin/main' into feat/local-asr-qwen3
# Conflicts:
#	openless-all/app/src-tauri/src/coordinator.rs
2026-05-05 12:48:13 +08:00
Chris233 a0cc88d2ac Merge pull request #260 from weikeyi/capsule-confirm-overflow
fix(capsule): keep confirm icon inside pill on done/error states
2026-05-05 12:46:39 +08:00
Chris233 f984dec84b Merge pull request #261 from sora520/fix/windows-hotkey-trigger-leak
fix(windows): suppress consumed hotkey trigger events
2026-05-05 12:42:27 +08:00
Chris233 3e1ba69bfc Merge pull request #252 from Cooper-X-Oak/fix/recorder-timeout-238
fix(recorder): 添加 liveness watchdog 和全局超时保护以修复 #238
2026-05-05 12:32:37 +08:00
kaku.ki 9c0ae1495a fix(windows): suppress consumed hotkey trigger events 2026-05-05 13:17:50 +09:00
baiqing 520787b0f7 feat(local-asr): 引擎内存常驻 + 切到本地时预加载 + 释放时机可配
用户痛点:之前每次按 hotkey 都重加载 1.2GB 模型 → 首句词延迟 3-5s。

新流程:
- 新 LocalAsrCache:模型一次 load 后驻留内存,跨多次会话复用
- LocalQwenAsr::new 改成接受 Arc<QwenAsrEngine>(引擎所有权挪到 cache)
- build_local_qwen3 改成 async + spawn_blocking 走 cache.get_or_load()
- 切换 active model 时自动 drop 旧引擎再加载新的
- end_session 后调 cache.touch() + schedule_local_asr_release
  - keep_loaded_secs == 0 → 立即释放
  - keep_loaded_secs > 0 → spawn 一个 sleep+check 任务,到点查 last_used,
    若中间又被使用过则跳过释放

预加载:
- commands::set_active_asr_provider("local-qwen3") 触发 preload_in_background
- 用户在「模型设置」页可手动「立即加载」/「立即释放」
- 实时显示「内存中的引擎: <model id>(约占 1.2-3.4 GB 内存)」
- 5 秒轮询刷新状态

新设置项:
- prefs.local_asr_keep_loaded_secs (u32,默认 300)
- UI 选项:说完话立即释放 / 1 min / 5 min(默认)/ 30 min / 始终保留
- 4 个新 IPC:local_asr_engine_status / release_engine / preload /
  set_keep_loaded_secs
2026-05-05 12:09:55 +08:00
baiqing 8ed674ecaf fix(local-asr): 多文件并发 + 8MB 小块 + aria2 UA — 对齐 hfd/hf_xet 实测
参考 hf-mirror 官方推荐工具 hfd(aria2 包装)+ hf_xet 默认 16 并发:
- PARALLEL_FILES = 3:原本顺序下文件,大 .safetensors 在跑时 6 个小文件
  全在排队;改成最多 3 个文件并发,让小文件不阻塞、大文件 throttle
  时剩余带宽喂别的文件
- PARALLEL chunks per file = 4 → 8:贴 hf_xet 默认 (16) 的折中
- CHUNK_SIZE = 32MB → 8MB:单连接寿命缩到 5-20s(CDN throttle 临界点之下),
  失败重做成本降 4 倍
- User-Agent: openless/x → aria2/1.36.0:实测 aria2 UA 在 HF / hf-mirror
  反滥用规则里走白名单;自定义 UA 在 sustained 传输后会被切流
  (日志里大量 "end of file before message length reached" 就是这个)

进度计算改成多文件汇总:每个文件 in_flight bytes 用 AtomicU64,全模型
总进度 = sum(in_flight) + already_done。失败时 cancel 标志传播给其它
spawn task 早退。
2026-05-05 11:33:46 +08:00
weikeyi dab04fc345 fix(capsule): keep confirm icon inside pill on done/error states 2026-05-05 11:17:49 +08:00
baiqing 209dc9fece fix(local-asr): 4 并发分块下载 + 取消正确传播 + 残留进度可见可删
四个用户报的问题,逐个修:

(1) 慢——单连接顺序拉,HF CDN 单连接限速明显
  → 4 并发 chunk + sparse 文件 seek+write,每完成一块原子追加 .partial.idx;
    与 huggingface_hub / aria2 / hf_transfer 同款思路;下次启动只下未完成块
  → 走严格 206 协议(并发 seek 模式不能容忍服务端忽略 Range 返 200,否则会
    把整个文件写到 chunk 偏移导致灾难);非 206 直接 fail 让 retry 接手

(2) 取消按钮没反应
  → 原因:旧 download_one 的 chunk loop 在 chunk Err 后 "若有进度就 continue";
    用户取消时也属于"有进度"路径 → cancel 标志被吞
  → 新版每次 spawn task 都拿 Arc<AtomicBool>,每个 chunk + 每个流块都查
    cancel;run_download 主线在 download_one 返回后立刻再查 cancel emit
    Cancelled 事件
  → DownloadManager::cancel 加日志方便诊断

(3) 继续下载丢进度条
  → showProgress 原来只在有 progress 事件时为 true → 重启 app 后看不到 partial
  → 加 hasPartial 判断:downloadedBytes>0 && !isDownloaded 也算 showProgress
  → 按钮文案对应改 "继续下载" / "Resume"

(4) 残留无法删
  → 原本只有 isDownloaded 状态才出 删除按钮
  → 加 hasPartial 状态显示 [继续下载] [删除] 两个按钮
2026-05-05 11:13:41 +08:00
Chris233 c5aa3fef4a Merge pull request #259 from H-Chris233/main
feat(i18n): add full Traditional Chinese (zh-TW) UI support
2026-05-05 11:07:37 +08:00
Chris233 2a472edc59 Merge pull request #253 from sora520/fix/windows-capsule-visuals
fix(windows): stabilize capsule visuals and audio meter
2026-05-05 11:06:09 +08:00
kaku.ki 23d7f44a96 fix(windows): stabilize capsule visuals and audio meter 2026-05-05 11:51:57 +09:00
H-Chris233 e50bc17a15 Add complete Traditional Chinese UI locale support
Add zh-TW locale resources and wire it through language selection,
persistence, and system-locale detection. Also add static shape typing
for zh-TW to prevent future key drift from zh-CN.

Constraint: Keep changes minimal and localized to i18n + language pickers
Rejected: Partial zh-TW translation only for language section | fails full locale support goal
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep zh-TW key shape locked to zh-CN when adding new translation keys
Tested: npm run -s build (openless-all/app)
Not-tested: Manual runtime walkthrough on all platform shells
2026-05-05 10:51:46 +08:00
baiqing 4a3531083b feat(local-asr): HTTP Range 分块下载 + 加载测试按钮
下载彻底重写 (huggingface_hub / aria2 同款思路):
- 之前是"整文件 GET,失败重试整文件"——HF CDN 对长连接不友好,到某个固定时间
  点会强制断流,导致看到"卡 5% 就死"。用户对比别家工具发现这点,确实如此。
- 现在 download_one 内按 32MB chunk 跑 Range,每块 4 次指数退避 retry,每次都
  从 .partial 真实长度续传;CDN 中途断流只丢一个 chunk
- 防御服务端忽略 Range 返回 200 + 全文件:检测到就 truncate .partial 重头来,
  避免 append 污染
- client 加 User-Agent (HF 把 no-UA 流量算异常 → 限速)
- pool_idle_timeout 缩短,避免复用已被 CDN 关掉的连接

加载测试按钮(用户:「做好加载模型和测试按钮」):
- 内嵌 antirez 自带的 samples/test_speech.wav(120KB,"Hello. This is a test
  of the Voxtrail speech-to-text system.")
- 严格按 RIFF chunk 链解析(fmt 后面带 LIST/INFO,不能 +44 硬偏移)
- 新 IPC local_asr_test_model:spawn_blocking 跑 qwen_load + transcribe_audio
  分别计时;返回 backend / 原文 / 识别 / load_ms / transcribe_ms
- LocalAsr 页每个已下载模型行加「加载并测试」按钮 + 结果卡片

Backend 标识改为 "Apple Accelerate (AMX/NEON, CPU)"——antirez 引擎不走 Metal
GPU(作者明确选择跳过 MPS),Apple Silicon 上靠 AMX 矩阵协处理器 + NEON 加速。
不撒谎说支持 Metal。
2026-05-05 10:27:48 +08:00
baiqing 25d9e9f3da fix(local-asr): 下载 retry 升级 4 次指数退避 + 已下载列表/删除/性能警告
下载失败修:
- HF 大文件被 CDN 中途断流(end of file before message length reached);
  原 1 次 retry 不够 + 间隔太短两次都失败
- 升到 4 次:1s → 4s → 16s 指数退避;每次都从 .partial 当前长度断点续传
- reqwest client 加 connect_timeout(30s) + pool_idle_timeout(20s) 避免
  连接被复用到已被 CDN 关掉的 socket
- 不设整体 timeout(1GB 文件没意义),只防卡死

UI 补「已下载管理 + 性能预期警告」(用户两条新需求):
- Settings 的 LocalAsrProviderHint 现在列出所有已下载模型 + 每行删除按钮
  (原来只显示当前激活模型 ready/not 状态,没看到其它模型也没法删)
- Settings 与 LocalAsr 页顶部都加 ⚠️ 性能警告卡片:明确"比云端慢/中文准确率
  通常不如火山+turbo/适用于离线/隐私场景",避免用户误判
- i18n 新增 zh+en:localAsrPerformanceWarning / localAsrDownloadedTitle /
  localAsrDelete + LocalAsr.performanceWarning
2026-05-05 10:03:26 +08:00
baiqing 5a58f74c4a fix(local-asr): HF 下载 TLS unexpected_eof + Settings 引导改下载入口
下载层修两件事:
1. 改用 native-tls (macOS = SecureTransport) 而非 rustls:
   HF LFS CDN 经常不发 TLS close_notify 直接关 TCP,rustls 0.22+ 把这当
   致命 unexpected_eof,实测多个 .safetensors 失败。SecureTransport 容错。
   Volcengine WebSocket 不动,继续走 rustls。
2. 单文件失败自动 retry 1 次(带 1s 退避,且尊重 cancel)。
   HF 大文件偶发瞬断很常见,不让用户手点重试。

Settings 引导(按用户反馈):
- ASR 选 'local-qwen3' 时**不**渲染 API key / Base URL / Model 三个填空
- 改为 LocalAsrProviderHint 卡片:
  * 文案"本地 Qwen3-ASR 在本机运行,无需 API Key"
  * 已下载/未下载 Pill 显示当前激活模型状态
  * 一键按钮 → 派发 NAVIGATE_LOCAL_ASR_EVENT
- FloatingShell 监听同事件,关 Settings modal + 切到 'localAsr' tab
- i18n 同步 zh + en
2026-05-05 09:56:54 +08:00