25 Commits
Author SHA1 Message Date
TRIPandHKLHaoBin 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
TRIPandsim 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
baiqing 97fca4abab fix(devex): bump-version 修 BSD sed / lock 失败吞错 / package-lock 未同步
Codex 在 PR #294 上提了 3 个 P2,全部采纳:

P2-A: BSD sed 不支持 GNU 行号范围 0,/.../
  原 sed -E -i.bak "0,/^version = .../s//.../" 在 macOS 默认 BSD sed 上
  会 fail。换成 awk first-match 替换(mac BSD awk + GNU awk 都支持)。

P2-B: Cargo.lock 同步失败被 `|| true` 吞了
  原 cargo update -p openless ... || true 会让脚本继续,validate 又只
  校验 Cargo.toml 不校验 Cargo.lock。删 || true,让 set -euo pipefail
  在 cargo update fail 时立刻退出;同时 validate 加 Cargo.lock 校验。

P2-C: package-lock.json 未跟着同步
  npm 把 root version 也存在 package-lock.json 里(root + packages['']
  两处)。原脚本只 sed package.json 不更 lock,会让 npm ci 在 CI 出现
  EUSAGE。换成 npm version --no-git-tag-version --allow-same-version
  一次更两个文件。

ci.yml 的 verify step 也升级到校验 5 处一致:
  package.json / package-lock.json root+nested / tauri.conf.json /
  Cargo.toml / Cargo.lock 的 [openless] 包。

dry-run 已验证(用当前版本 1.2.20 跑一遍输出全部一致)。
2026-05-06 21:04:28 +08:00
baiqing b997f5fca2 chore(devex): CI 加 mac 矩阵 + version-triplet 校验 + bump-version.sh
审查反馈:
1. CI 缺质量门禁 — 仅 windows-latest 1 job,mac 端 cargo check 路径
   无 PR-time 验证,每次 release-tauri.yml 才暴露平台问题
2. .gitignore 不全 — promo-openless-v2/ 反复出现在 git status;
   node_modules / dist / target 没全局兜底
3. 版本号同步风险 — package.json + tauri.conf.json + Cargo.toml 三处
   人工改,每次发版都担心漏一处

改动:

A. .github/workflows/ci.yml
   - 单一 windows-tauri job → matrix(macos-latest + windows-latest)
   - mac job:cargo check + npm run build 验证跨平台编译
   - Windows job:保留原 preflight + ps1 tokenize
   - 新加 step:Verify version triplet stays in sync(两端都跑)—
     一旦 package.json / tauri.conf.json / Cargo.toml 三处 drift 立刻
     fail,给发版工程加 long-running guard

B. .gitignore
   - 加 promo-openless-v2/(已实测出现在 untracked)
   - 加 node_modules/ + dist/ + target/ 全局兜底(避免某子目录漏配
     时 build artifact 进 PR)
   - 加 .cargo/registry / .cargo/git 兜底

C. scripts/bump-version.sh(新文件)
   - 1 个参数(X.Y.Z),sed 同步改 3 个文件 + cargo update -p openless
     同步 Cargo.lock
   - 验证三处一致后输出后续 git 操作建议
   - 跨 macOS sed / GNU sed 兼容(-i.bak 后 rm)

下次发版:./scripts/bump-version.sh 1.2.21 一行搞定。
未来 PR 漏改版本号 CI 立刻 fail,不需要靠人记忆。
2026-05-06 20:55:03 +08:00
cooperandClaude Sonnet 4.6 27451298da audit(system): 完成系统级多尺度审计 - 发现 3 大架构风险和 13 项技术债务
建立多尺度审计框架(4 个尺度):
- 尺度 1: 系统级(架构、安全、扩展性)
- 尺度 2: 模块级(设计、接口、依赖)
- 尺度 3: 功能级(实现、体验、边界)
- 尺度 4: 代码级(bug、风格、性能)

**系统级审计关键发现**:

架构风险(3 项):
- 🔴 Coordinator 过于庞大(3462 行)
- 🔴 缺少统一的 ASR Provider trait
- 🔴 测试基础设施缺失(覆盖率接近 0%)

技术债务(13 项):
- P0: 2 项(测试相关)
- P1: 5 项(架构 + 测试 + 代码)
- P2: 4 项(架构 + 文档 + 代码)
- P3: 2 项(文档)
- 预计偿还成本: 14 周(3.5 个月)

**关键决策**:
1. ✅ 需要架构重构
2. ⏸️  暂停低尺度审计(先解决高尺度问题)

**下一步行动**:
1. 编写测试策略文档
2. 编写 Coordinator 拆分设计文档
3. 编写 ASR Provider trait 设计文档

**审计产出**:
- 多尺度审计框架文档
- 架构风险地图
- 技术债务矩阵
- 系统级审计总结
- 系统级审计脚本

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 23:16:12 +08:00
cooperandClaude Sonnet 4.6 7e7b200198 docs(epic): 建立 Cooper 贡献体系 - 两大 EPIC 母体与 Finding 流程
建立完整的贡献规划体系:

**两大 EPIC 母体**:
- EPIC-001: 测试基础设施建设 (41 tasks, 6 weeks)
  - 目标:测试覆盖率 0% → 60%+
  - Phase 1: 核心模块单元测试
  - Phase 2: 集成测试
  - Phase 3: CI 自动化

- EPIC-002: ASR 功能扩展与优化 (71 tasks, 6 weeks)
  - Phase 1: 混淆词纠错层 (对应 #89)
  - Phase 2: 本地 ASR 支持 (对应 #211)
  - Phase 3: ASR 架构优化

**Finding 基础设施**:
- finding-helper.sh: 自动化分析脚本
- 生成 4 份 finding 报告:
  - 测试覆盖率分析
  - ASR 模块分析
  - 依赖关系分析
  - Finding 总结

**工作流程文档**:
- COOPER_README.md: 快速开始指南
- COOPER_WORKFLOW.md: 详细工作流程
- COOPER_CONTRIBUTION_STRATEGY.md: 贡献策略分析

**关键指标**:
- 包含测试的文件数: 15
- 测试函数数: 76
- ASR 模块代码量: 1164 行

下一步:开始实现混淆词纠错层(EPIC-002 Phase 1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 23:00:25 +08:00
baiqing 34d2823961 chore: remove deprecated Swift implementation
项目已全面转型为 Tauri 跨平台版本(openless -all/),
Swift 端(Sources/、Tests/、scripts/、Package.swift、appcast.xml)
已废弃,一并清理。
2026-04-29 22:17:59 +08:00
baiqing ff0c95d99c release: v1.0.08 (build B1007) 2026-04-29 13:42:46 +08:00
baiqing 294e53745b feat(asr): Apple Speech provider + ASR switcher tab
- 新增 AppleSpeechASRProvider:包装 SFSpeechRecognizer,on-device 优先,
  partial / final 走标准 ASRStreamingSession 协议,无需 API key
- 新增 ASRProviderRegistry:M1 预设 volcengine / apple-speech
- CredentialsVault 增加 activeASRProviderId / configuredASRProviderIds
- DictationCoordinator.makeASRProvider 改为按 vault.activeASRProviderId 路由
- 新增 ASR Tab(chip 切换 + 主操作「保存」按钮);侧边栏导航新增 .asr
- scripts/build-app.sh Info.plist 加入 NSSpeechRecognitionUsageDescription
- Tests/OpenLessCoreTests 新增 ASRProviderRegistryTests
2026-04-29 12:46:55 +08:00
baiqing e029f0bb17 release: v1.0.07 (build B1006) 2026-04-28 17:37:18 +08:00
baiqing dd46bd9807 release: v1.0.06 (build B1005) 2026-04-28 13:36:01 +08:00
baiqing 57cd1d3c41 Revert "release: v1.0.05 (build B1004)"
This reverts commit 5ad4d1a593.
2026-04-28 13:31:28 +08:00
baiqing 5ad4d1a593 release: v1.0.05 (build B1004) 2026-04-28 13:28:55 +08:00
baiqing 63d0e4c7ab release: v1.0.04 (build B1003) 2026-04-28 13:20:45 +08:00
baiqing f10ad907ba release: v1.0.03 (build A1005) 2026-04-28 11:16:48 +08:00
baiqing b7b8b2bea2 fix(release): force C locale for RFC 822 pubDate; clean up appcast layout
The first release.sh run wrote a Chinese-locale pubDate ("一, 27 4月 2026 …")
into appcast.xml, which Sparkle's RFC 822 date parser rejects. Force
LC_ALL=C around the date call so future releases produce the standard
"Mon, 27 Apr 2026 11:02:01 +0000" format. Manually fix the v1.0.02
entry's pubDate and move <language> back above <item> for a tidy feed.
2026-04-27 19:03:14 +08:00
baiqing 91e014d8ba release: v1.0.02 (build A1004) 2026-04-27 19:02:01 +08:00
baiqing c79bf015ec fix(release): use sed r-command for appcast item insert (awk failed on multiline) 2026-04-27 19:01:41 +08:00
TRIPandbaiqing f38643f17c feat: Sparkle 2 auto-update
* feat: integrate Sparkle 2 for auto-update

Adds the standard pieces for Sparkle-based silent updates:

- Package.swift: add Sparkle 2 SPM dep, wired into OpenLessApp.
- Sources/OpenLessApp/Updater/UpdaterController.swift: thin wrapper
  around SPUStandardUpdaterController. Owned by AppDelegate so the
  updater starts on app launch.
- AppDelegate: instantiate UpdaterController before installing the
  main menu; pass it to ApplicationMenu so the menu item can target
  it.
- ApplicationMenu: add "检查更新…" as the first item in the OpenLess
  menu when an UpdaterController target is present.
- scripts/build-app.sh: copy Sparkle.framework (with Updater.app +
  XPC services + Autoupdate) from the SPM artifacts dir into
  Contents/Frameworks/, inject SUFeedURL / SUPublicEDKey /
  SUEnableAutomaticChecks / SUEnableInstallerLauncherService /
  SUScheduledCheckInterval into Info.plist, and ad-hoc sign the
  embedded helpers explicitly (deep sign alone is unreliable for
  Sparkle's nested XPC bundles).
- scripts/release.sh: one-shot release pipeline.
  ./scripts/release.sh <version> [<build>] [<notes>]
  Bumps version in build-app.sh, builds, zips, signs the zip with the
  Keychain-stored EdDSA private key (auto-downloads sign_update from
  the Sparkle 2.9.1 release on first run), prepends a new <item> to
  appcast.xml, commits + tags + pushes main, and creates the GitHub
  release with the zip uploaded.
- appcast.xml: empty initial feed file at repo root, served via the
  raw.githubusercontent.com URL referenced by SUFeedURL. Items are
  appended automatically by release.sh.

Public EdDSA key embedded in the build:
iT00+eUw/55obn1suEnWqI7za2pc8mHIFIdRbOWXW1Q=

Private key lives only in the local Keychain on the release machine
(account: macOS login user; service: https://sparkle-project.org).
First-time install still requires the user to remove the quarantine
xattr (no Apple Developer ID); subsequent updates flow through
Sparkle's installer helper and bypass quarantine.

* fix(sparkle): add @executable_path/../Frameworks rpath to OpenLessApp

Without this, the SPM-built executable links Sparkle's symbols but
ships with no rpath that points at the embedded framework, so dyld
fails at launch with:

  Library not loaded: @rpath/Sparkle.framework/Versions/B/Sparkle

…and the user sees the macOS Gatekeeper-styled "请与开发者联系,以确保
OpenLess 可以配合此 macOS 版本使用" error. Inject the rpath via
linkerSettings.unsafeFlags so the binary itself knows where to look.

---------

Co-authored-by: baiqing <lbx12309@icloud.com>
2026-04-27 18:58:37 +08:00
TRIPandbaiqing 56c3e09983 feat: hold-to-talk + UX fixes + structured prompt overhaul
* feat: add hold-to-talk hotkey mode (closes #1)

OpenLessHotkey now emits explicit .pressed / .released edge events on
the modifier-key trigger; the coordinator interprets them per the new
HotkeyMode preference (toggle stays the default, hold = press-and-hold).

Hold mode rules: .pressed on idle starts the session; .released stops
it from .listening; releasing during .starting cancels (no audio
useful was captured yet). Esc-cancel sets a one-shot suppress flag so
the trailing .released after a cancel does not re-trigger end.

Settings hub gets a "录音方式" segmented picker and a one-line hint
explaining the tradeoff. Bump version to 1.1.0; update README roadmap
and USAGE walkthrough to document the new mode.

* test: update HotkeyEventTests for pressed/released split

* chore: tag hold-to-talk build as 1.0.01 / A1003

* fix: stop window-background drag eating text selection; add eye toggle on secret fields

Settings window had isMovableByWindowBackground = true, so any drag
inside the content view dragged the whole window — making it
impossible to select words inside a TextField. Disable it; the native
title-bar strip (with the traffic lights) still drags the window.

PasteableCredentialField now exposes an eye / eye.slash toggle when
secure: true, so users can verify pasted API keys before saving.

* fix: stop pretending polish ran when it was skipped or errored

When the user removes the Ark API key (or the Ark call errors out),
DictationCoordinator was still showing the green "已插入" capsule and
recording the session in history under the originally-selected polish
mode. From the user's side it looked like polish had succeeded, even
though only the raw transcript reached the cursor.

Track a PolishOutcome (ok / skippedNoCredentials / failed) through
insertText. Capsule now uses a new CapsuleState.warning (orange) state
to surface honest messages — "已插入原文 · 未润色" / "润色失败 · 已用原文" —
and history saves the session as PolishMode.raw whenever polish
didn't actually run. The error capsule + 1.5s artificial sleep that
preceded a fake "success" insert is gone; warning state stays for the
normal 2.5s.

* feat(polish): make Structured mode prompt force a 1./1)/a. hierarchy

Some weaker chat models would emit a single flat list when the user
asked for Structured polish, even when the dictation clearly covered
multiple topics. The mode is meant to produce something pasteable as
an AI prompt or a working doc, not a wall of bullets.

Rewrite the .structured system prompt to be prescriptive: when the
input contains ≥2 themes, emit three explicit levels — top "1./2./3."
sections, "1)/2)/3)" sub-points indented 3 spaces, and "a./b./c."
detail items indented another 3 — and to fall back to a plain
paragraph when the input is short / single-topic. Add a concrete
format example so weaker models have a pattern to copy.

---------

Co-authored-by: baiqing <lbx12309@icloud.com>
2026-04-27 18:57:41 +08:00
baiqing c78bb44c23 chore: cut 1.0.0 release with usage docs and MIT license
Bump APP_VERSION to 1.0.0 / BUILD_NUMBER to 1; refresh README to clarify
project direction and add quarantine-removal guidance for the unsigned
release artifact; add USAGE.md as the end-user walkthrough; add MIT LICENSE.
2026-04-27 15:25:28 +08:00
baiqing da14031c83 fix: use app png for status bar icon 2026-04-27 15:17:12 +08:00
baiqing 8965fb4209 feat: add custom svg status bar icon 2026-04-27 15:08:16 +08:00
baiqing 4f8e6b914e feat: add dock main window and fixed navigation 2026-04-27 14:07:12 +08:00
baiqing f5a0c810fa feat: add dictionary hotwords and insights UI 2026-04-27 13:53:18 +08:00