Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
8065895
add configurable shortcut bindings
LeslieLeung May 4, 2026
b64b697
merge upstream main into shortcut bindings
LeslieLeung May 4, 2026
f5e828c
Merge branch 'main' into feature/key-binding
LeslieLeung May 4, 2026
13bfe26
Fix Linux hotkey labels and shutdown cleanup
LeslieLeung May 4, 2026
61214aa
Fix hotkey binding replacement validation
LeslieLeung May 4, 2026
913039e
Fix custom dictation hotkey fallbacks
LeslieLeung May 4, 2026
789c6f3
Fix shortcut recording defaults
LeslieLeung May 4, 2026
af3a1a1
Fix preferences load aborting startup on corrupted file
LeslieLeung May 4, 2026
3d64dc2
fix(capsule): center Windows pill within shadow inset
weikeyi May 5, 2026
e0369b1
fix: review issues
LeslieLeung May 5, 2026
5426d87
Merge main: resolve conflicts (hotkeys + local ASR prefs, commands, i…
LeslieLeung May 5, 2026
9660db6
Fix Windows capsule box sizing
weikeyi May 5, 2026
351f956
Merge origin/main into capsule-windows-shadow-inset
weikeyi May 5, 2026
edb1bc5
fix(hotkey): guard shortcut registration conflicts
LeslieLeung May 5, 2026
b85ff30
Merge branch 'main' into feature/key-binding
LeslieLeung May 5, 2026
8b9e594
fix(hotkey): clear stale shortcut latches and block action collisions
LeslieLeung May 5, 2026
fa98608
fix(windows): restore tauri backend compile checks
LeslieLeung May 5, 2026
64d9d5e
Merge branch 'main' into feature/key-binding
LeslieLeung May 5, 2026
ca2536c
Merge main into feature/key-binding
LeslieLeung May 6, 2026
13ccf85
Store credentials in the system vault
H-Chris233 May 6, 2026
64296e3
Avoid Windows vault blob overflow for provider credentials
H-Chris233 May 6, 2026
ddd6528
Preserve legacy credentials when vault migration cannot run
H-Chris233 May 6, 2026
4498bed
Make vault chunk migration crash-safe
H-Chris233 May 6, 2026
9a1461b
Protect vault migrations from stale fallback overwrites
H-Chris233 May 6, 2026
b97a54b
Surface legacy plaintext cleanup failures
H-Chris233 May 6, 2026
579efb0
Keep Linux vault credentials persistent
H-Chris233 May 6, 2026
5bf9d72
Preserve legacy vault entries on partial read failure
H-Chris233 May 6, 2026
c1be1dd
Clean stale vault entries after JSON migration
H-Chris233 May 6, 2026
deb1196
Keep vault updates independent of obsolete JSON cleanup
H-Chris233 May 6, 2026
c06db84
Keep Windows smoke gates compatible with vault storage
H-Chris233 May 6, 2026
1d04131
Preserve strict credential gate for real regression mode
H-Chris233 May 6, 2026
80de078
fix(windows-ime): 静态链接 CRT 防 host 进程 MSVCP140 劫持
May 6, 2026
901e9df
fix(windows-ime): 移除 DisableThreadLibraryCalls — /MT 下需 thread 通知
May 6, 2026
02dd8c5
fix(recording): 录音条出现时 mic 已 capture,不再吞开头字
May 6, 2026
5c5b575
fix(recording): emit Recording 加 race 检查,避免覆盖 stop/cancel
May 6, 2026
96ca966
Merge pull request #287 from appergb/fix/windows-ime-static-crt
appergb May 6, 2026
ab65432
Merge pull request #289 from appergb/fix/recording-no-swallow-first-w…
appergb May 6, 2026
b286837
chore(ci): 暂时搁置 macos-13 (Intel mac) 构建
May 6, 2026
fa30161
fix(startup): splash 透明背景 + 卡片化,避免长启动时左半白屏
May 6, 2026
0505c2f
fix(vault): keyring chunks 用稳定名 + 不再每次 load 都删 legacy
May 6, 2026
08b5b88
Merge pull request #291 from appergb/fix/startup-splash-transparent
appergb May 6, 2026
c0118ee
Merge pull request #290 from appergb/chore/skip-macos-13-runner
appergb May 6, 2026
095e312
Merge pull request #277 from H-Chris233/fix/issue-230-credential-stor…
appergb May 6, 2026
b997f5f
chore(devex): CI 加 mac 矩阵 + version-triplet 校验 + bump-version.sh
May 6, 2026
938c6a7
docs: 工程审计基线 (audit-2026-05-06.md)
May 6, 2026
97fca4a
fix(devex): bump-version 修 BSD sed / lock 失败吞错 / package-lock 未同步
May 6, 2026
b9adb6c
Merge pull request #294 from appergb/chore/ci-quality-gate-and-versio…
appergb May 6, 2026
d5fa5b7
chore(release): 1.2.21
May 6, 2026
94e9686
fix(capsule): restore non-windows box sizing contract
weikeyi May 6, 2026
62005a6
test(capsule): tighten host centering regex
weikeyi May 6, 2026
69e5662
Merge pull request #264 from weikeyi/capsule-windows-shadow-inset
H-Chris233 May 6, 2026
98da597
Merge pull request #236 from LeslieLeung/feature/key-binding
appergb May 7, 2026
1e04433
fix(i18n,ui): 补 ja/ko 缺失 key + SelectionAsk 启用开关右置
May 7, 2026
2c9dca5
Merge pull request #307 from appergb/fix/post-pr236-i18n-selectionask-ui
appergb May 7, 2026
98e3d37
feat(settings): add microphone device selection
sora520 May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
name: CI

# 多平台跨语言质量门禁。release-tauri.yml 是发版流水线(仅打包构建),这里负责
# 在合并前快速验证两件事:
# 1. 前端 typecheck + vite bundle 通过(tsc + vite build,捕获跨 locale 类型 drift)
# 2. Rust 后端在 macOS / Windows 都能 cargo check 过(捕获 cfg 漏分支 / 平台 API 误用)
# 跑 build-mac.sh / windows-package-msvc.ps1 太重;只跑轻量 cargo check + vite build。

on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]

jobs:
windows-tauri:
name: Windows Tauri checks
runs-on: windows-latest
cross-platform:
name: ${{ matrix.label }} checks
strategy:
# 一个平台挂掉不阻塞其他平台拿到验证结果。
fail-fast: false
matrix:
include:
- os: macos-latest
label: macOS
preflight: false
- os: windows-latest
label: Windows
preflight: true
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: openless-all/app
Expand All @@ -32,10 +49,12 @@ jobs:
run: npm ci

- name: Check Windows prerequisites
if: matrix.preflight
shell: pwsh
run: ./scripts/windows-preflight.ps1 -Toolchain msvc

- name: Check PowerShell scripts
if: matrix.preflight
shell: pwsh
run: |
foreach ($script in @("./scripts/windows-preflight.ps1", "./scripts/windows-build-gnu.ps1", "./scripts/windows-runtime-smoke.ps1")) {
Expand All @@ -47,8 +66,38 @@ jobs:
}
}

- name: Build frontend
- name: Build frontend (tsc + vite)
run: npm run build

- name: Check Tauri backend
- name: Check Tauri backend (cargo check)
run: cargo check --manifest-path src-tauri/Cargo.toml

- name: Verify version sync across all 5 files
# 两个平台都跑这个校验:Windows runner 自带 git-bash,跨 shell 表现一致。
# 一旦版本号 drift 立刻 fail,避免发版时再发现漏改。
# 校验 5 处:package.json / package-lock.json (root + nested) /
# tauri.conf.json / Cargo.toml / Cargo.lock 的 [openless] 包。
shell: bash
run: |
PKG=$(node -p "require('./package.json').version")
LOCK_ROOT=$(node -p "require('./package-lock.json').version")
LOCK_NESTED=$(node -p "require('./package-lock.json').packages[''].version")
TAU=$(node -p "require('./src-tauri/tauri.conf.json').version")
CRG=$(grep -E '^version = ' src-tauri/Cargo.toml | head -1 | sed -E 's/^version = "(.+)"$/\1/')
# Cargo.lock:找 [openless] 包紧跟的 version 行
CARGO_LOCK_VER=$(awk 'BEGIN{found=0} /^name = "openless"$/{found=1; next} found && /^version = /{gsub(/"/,""); print $3; exit}' src-tauri/Cargo.lock)
echo "package.json = $PKG"
echo "package-lock root = $LOCK_ROOT"
echo "package-lock nested = $LOCK_NESTED"
echo "tauri.conf.json = $TAU"
echo "Cargo.toml = $CRG"
echo "Cargo.lock openless = $CARGO_LOCK_VER"
mismatch=0
for v in "$LOCK_ROOT" "$LOCK_NESTED" "$TAU" "$CRG" "$CARGO_LOCK_VER"; do
if [ "$v" != "$PKG" ]; then mismatch=1; fi
done
if [ "$mismatch" -ne 0 ]; then
echo "::error::版本号未对齐 — 请用 scripts/bump-version.sh 同步更新"
exit 1
fi
echo "[ok] 全部 5 处版本号一致:$PKG"
13 changes: 9 additions & 4 deletions .github/workflows/release-tauri.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ jobs:
rust-target: aarch64-apple-darwin
updater-target: darwin
updater-arch: aarch64
- platform: macos-13
rust-target: x86_64-apple-darwin
updater-target: darwin
updater-arch: x86_64
# 暂时搁置 Intel mac 构建:GitHub Actions 把 macos-13 标记为 deprecated
# runner,pool 容量紧张到每次 dispatch 都 queue 1-2h 拿不到分配,多次
# release 都因这个 job 卡住整个 run 的 conclusion。等 GH 把 macOS x86_64
# 迁移到非 deprecated runner(macos-14 / macos-15-large)或 macos-13
# pool 缓解后再恢复。Apple Silicon dmg 在 Intel mac 上跑 Rosetta 仍可用。
# - platform: macos-13
# rust-target: x86_64-apple-darwin
# updater-target: darwin
# updater-arch: x86_64
- platform: windows-latest
rust-target: x86_64-pc-windows-msvc
updater-target: windows
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,18 @@ SC/
apps/
promo/
promo-openless/
promo-openless-v2/
docs/old-promo/
.worktrees/

# 派生产物(兜底):项目曾出现 promo-openless-v2/node_modules 等遗漏,
# 这里全局通配,避免某子目录漏配 .gitignore 时把 build artifact 推进 PR。
node_modules/
dist/
target/
.cargo/registry/
.cargo/git/

# Windows TSF IME local build outputs
openless-all/app/windows-ime/OpenLessIme/
openless-all/app/windows-ime/x64/
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ recorder.rs Mic → 16 kHz mono Int16 PCM, RMS
asr/{mod,frame,volcengine,whisper}.rs ASR providers: Volcengine streaming WebSocket + Whisper HTTP
polish.rs OpenAI-compatible chat completions (Ark / DeepSeek / etc.)
insertion.rs AX focused-element write → clipboard + Cmd+V → copy-only fallback
persistence.rs History/preferences/vocab JSON + Keychain credentials
persistence.rs History/preferences/vocab JSON + platform credential vault
coordinator.rs + commands.rs + lib.rs State machine, IPC surface, tray icon, window plumbing
permissions.rs TCC checks (Accessibility / Microphone)

Expand All @@ -91,9 +91,9 @@ Invariants:

### Permissions, credentials, on-disk state

- **Bundle ID `com.openless.app`** is hard-coded in `openless-all/app/src-tauri/tauri.conf.json` and `CredentialsVault.serviceName`. Changing it breaks Keychain lookups *and* every existing TCC grant.
- **Bundle ID `com.openless.app`** is hard-coded in `openless-all/app/src-tauri/tauri.conf.json` and `CredentialsVault.serviceName`. Changing it breaks system credential vault lookups *and* every existing TCC grant.
- **TCC**: Microphone + Accessibility + AppleEvents. `NSMicrophoneUsageDescription` / `NSAccessibilityUsageDescription` / `NSAppleEventsUsageDescription` live in `openless-all/app/src-tauri/Info.plist`. After a fresh build that resets TCC, the app must be **fully quit and relaunched** after granting Accessibility before the global hotkey tap installs.
- **Credentials** live in Keychain under accounts in `CredentialAccount` (`volcengine.app_key`, `volcengine.access_key`, `volcengine.resource_id`, `ark.api_key`, `ark.model_id`, `ark.endpoint`). The plaintext fallback at `~/.openless/credentials.json` is read on first launch so legacy users keep their creds without re-entering. Never hard-code keys.
- **Credentials** live in the OS credential vault (macOS Keychain, Windows Credential Manager, Linux keyring) under service `com.openless.app`. The legacy plaintext JSON (`~/.openless/credentials.json` on macOS/Linux, `%APPDATA%\OpenLess\credentials.json` on Windows) is only a migration source and is removed after a successful vault write. Never hard-code keys or include legacy credential files in logs, exports, build artifacts, or bug reports.
- **Per-user data**:
- macOS: `~/Library/Application Support/OpenLess/{history.json, preferences.json, dictionary.json}` — capped at 200 history entries. **Do not rename `dictionary.json` to `vocab.json`** (drops user data).
- Windows: `%APPDATA%\OpenLess\`
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ recorder.rs Mic → 16 kHz mono Int16 PCM, RMS
asr/{mod,frame,volcengine,whisper}.rs ASR providers: Volcengine streaming WebSocket + Whisper HTTP
polish.rs OpenAI-compatible chat completions (Ark / DeepSeek / etc.)
insertion.rs AX focused-element write → clipboard + Cmd+V → copy-only fallback
persistence.rs History/preferences/vocab JSON + Keychain credentials
persistence.rs History/preferences/vocab JSON + platform credential vault
coordinator.rs + commands.rs + lib.rs State machine, IPC surface, tray icon, window plumbing
permissions.rs TCC checks (Accessibility / Microphone)

Expand All @@ -91,9 +91,9 @@ Invariants:

### Permissions, credentials, on-disk state

- **Bundle ID `com.openless.app`** is hard-coded in `openless-all/app/src-tauri/tauri.conf.json` and `CredentialsVault.serviceName`. Changing it breaks Keychain lookups *and* every existing TCC grant.
- **Bundle ID `com.openless.app`** is hard-coded in `openless-all/app/src-tauri/tauri.conf.json` and `CredentialsVault.serviceName`. Changing it breaks system credential vault lookups *and* every existing TCC grant.
- **TCC**: Microphone + Accessibility + AppleEvents. `NSMicrophoneUsageDescription` / `NSAccessibilityUsageDescription` / `NSAppleEventsUsageDescription` live in `openless-all/app/src-tauri/Info.plist`. After a fresh build that resets TCC, the app must be **fully quit and relaunched** after granting Accessibility before the global hotkey tap installs.
- **Credentials** live in Keychain under accounts in `CredentialAccount` (`volcengine.app_key`, `volcengine.access_key`, `volcengine.resource_id`, `ark.api_key`, `ark.model_id`, `ark.endpoint`). The plaintext fallback at `~/.openless/credentials.json` is read on first launch so legacy users keep their creds without re-entering. Never hard-code keys.
- **Credentials** live in the OS credential vault (macOS Keychain, Windows Credential Manager, Linux keyring) under service `com.openless.app`. The legacy plaintext JSON (`~/.openless/credentials.json` on macOS/Linux, `%APPDATA%\OpenLess\credentials.json` on Windows) is only a migration source and is removed after a successful vault write. Never hard-code keys or include legacy credential files in logs, exports, build artifacts, or bug reports.
- **Per-user data**:
- macOS: `~/Library/Application Support/OpenLess/{history.json, preferences.json, dictionary.json}` — capped at 200 history entries. **Do not rename `dictionary.json` to `vocab.json`** (drops user data).
- Windows: `%APPDATA%\OpenLess\`
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,14 @@ Logs: `~/Library/Logs/OpenLess/openless.log` (macOS) / `%LOCALAPPDATA%\OpenLess\

## Credentials

Credentials live in the local Keychain (service = `com.openless.app`). A plaintext JSON file at `~/.openless/credentials.json` (mode 0600, dir 0700) is kept as a dev-mode fallback when Keychain is unavailable.
Credentials live in the OS credential vault (service = `com.openless.app`): macOS Keychain, Windows Credential Manager, or Linux keyring. A legacy plaintext JSON file is read only as a migration source and removed after a successful vault write:

The repository contains no API keys, tokens, or private endpoints.
```text
macOS / Linux: ~/.openless/credentials.json
Windows: %APPDATA%\OpenLess\credentials.json
```

New credential writes do not persist plaintext secrets. The repository contains no API keys, tokens, or private endpoints.

You'll need:

Expand Down Expand Up @@ -247,7 +252,7 @@ recorder.rs Mic → 16 kHz mono Int16 PCM, RMS callback
asr/ Volcengine streaming ASR (WebSocket) + Whisper HTTP
polish.rs OpenAI-compatible chat-completions (Ark / DeepSeek / etc.)
insertion.rs AX focused-element → clipboard + Cmd+V → copy-only fallback
persistence.rs History / preferences / vocab JSON + Keychain credentials
persistence.rs History / preferences / vocab JSON + platform credential vault
permissions.rs TCC checks (Accessibility / Microphone)
coordinator.rs State machine: Idle → Starting → Listening → Processing
commands.rs Tauri IPC surface
Expand Down
9 changes: 5 additions & 4 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,14 @@ npm run build

## 凭据

凭据保存在本机 Keychain(service = `com.openless.app`)。开发期同时维护一份明文 JSON 兜底,用于在 Keychain 不可用时回退
凭据保存在系统凭据库(service = `com.openless.app`):macOS Keychain、Windows Credential Manager 或 Linux keyring。旧版明文 JSON 只作为迁移来源读取,成功写入系统凭据库后会被删除

```text
~/.openless/credentials.json # 0600,目录 0700
macOS / Linux: ~/.openless/credentials.json
Windows: %APPDATA%\OpenLess\credentials.json
```

仓库本身不包含任何 API Key、Token 或 Endpoint 之外的私有信息。
新的凭据写入不会继续保存明文 secrets。仓库本身不包含任何 API Key、Token 或 Endpoint 之外的私有信息。

需要配置的字段:

Expand Down Expand Up @@ -254,7 +255,7 @@ recorder.rs 麦克风 → 16 kHz 单声道 Int16 PCM,RMS 回调
asr/ 火山引擎流式 ASR(WebSocket)+ Whisper HTTP
polish.rs OpenAI 兼容 chat-completions(Ark / DeepSeek 等)
insertion.rs AX focused-element → 剪贴板 + Cmd+V → 仅复制兜底
persistence.rs 历史记录 / 偏好设置 / 词典 JSON + Keychain 凭据
persistence.rs 历史记录 / 偏好设置 / 词典 JSON + 系统凭据库
permissions.rs TCC 权限检查(辅助功能 / 麦克风)
coordinator.rs 状态机:Idle → Starting → Listening → Processing
commands.rs Tauri IPC 接口
Expand Down
Loading
Loading