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.
This commit is contained in:
baiqing committed 2026-04-27 15:25:28 +08:00
1 parent da14031c83
commit c78bb44c23
4 files changed
+213 -59

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 OpenLess contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+92 -57
View File
@@ -2,76 +2,86 @@
OpenLess 是一个原生 macOS 语音输入应用:把光标放在任意输入框,按下全局快捷键说话,OpenLess 会录音、转写、轻度整理,并把结果插入当前输入位置。插入失败时会自动复制到剪贴板,尽量保证“用户说过的话不丢”。
## 当前状态
## 项目方向
- 原生 Swift / SwiftUI / AppKit,SwiftPM 项目。
- 支持 macOS 15+;macOS 26+ 使用 Liquid Glass 效果,旧系统回退到系统 material。
OpenLess 只做一件事:**把语音变成可用的书面文字,落到当前光标位置。**
- 不做问答、不做任务执行、不做项目分析。
- 不做对话上下文累积,每次输入都是独立的整理请求。
- 输入语音 → 转写 → 整理 → 插入当前输入框。失败时复制到剪贴板。
- 围绕这条主路径完善体验:模式选择、词典、历史、菜单栏、首页报告。
## 当前状态(v1.0)
- 原生 Swift / SwiftUI / AppKit,SwiftPM 项目;macOS 15+。
- macOS 26+ 使用 Liquid Glass 效果,旧系统回退到系统 material。
- 默认是切换式录音:按一次开始,再按一次结束;录音中按 `Esc` 取消。
- 支持火山引擎流式 ASR 和 Ark / DeepSeek 兼容 Chat Completions 润色。
- 支持 4 种输出模式:原文、轻度润色、清晰结构、正式表达。
- 支持 Dock 主窗口、菜单栏控制、底部微型状态胶囊、首页报告、历史记录、词典、设置和剪贴板兜底。
- 接入火山引擎流式 ASR 和 Ark / DeepSeek 兼容 Chat Completions 进行润色。
- 4 种输出模式:原文、轻度润色、清晰结构、正式表达。
- 主窗口按「首页 / 历史记录 / 词典 / 设置」组织;菜单栏常驻;底部有微型状态胶囊。
- 词典支持作为 ASR 热词注入和润色阶段的语义判断。
## 运行方式
## 下载与安装(普通用户)
到 [Releases](../../releases) 下载 `OpenLess-1.0.0.zip`,解压得到 `OpenLess.app`,拖到 `应用程序`。
**重要:** 1.0 是开发期 ad-hoc 签名构建(未做 Apple Developer ID 签名和 notarization)。直接打开会被 Gatekeeper 拦下提示“无法验证开发者”。需要在终端中移除隔离属性:
```bash
./scripts/build-app.sh
open build/OpenLess.app
xattr -dr com.apple.quarantine /Applications/OpenLess.app
```
开发期使用 ad-hoc 签名。每次重新构建后,脚本默认会重置辅助功能、麦克风、AppleEvents 和 ListenEvent 权限,确保 macOS 不继续引用旧二进制授权。
之后就可以双击启动。首次启动需要在 `系统设置 → 隐私与安全`:
首次启动后:
1. 授予 OpenLess 麦克风权限。
2. 授予 OpenLess 辅助功能权限。
3. **退出 OpenLess 并重新打开**(辅助功能授权对全局快捷键生效需要重启进程)。
4. 从 Dock 打开 OpenLess 首页 → 「设置」 → 填入火山引擎 ASR 和 Ark 凭据。
1. 在系统设置中授予 OpenLess 辅助功能权限和麦克风权限。
2. 退出 OpenLess。
3. 重新打开 `build/OpenLess.app`。
4. 从 Dock 打开 OpenLess 首页,在「设置」里填写火山引擎 ASR 和 Ark 凭据。
完整的端用户使用步骤见 [USAGE.md](USAGE.md)。
实时日志:
## 从源码构建(开发者)
```bash
# 库 / 测试构建
swift build
swift test
# 完整 .app 构建(release,ad-hoc 签名,默认重置 TCC)
./scripts/build-app.sh
# 保留已授予的 TCC 权限
RESET_TCC=0 ./scripts/build-app.sh
# 启动
open build/OpenLess.app
# 实时日志
tail -f ~/Library/Logs/OpenLess/OpenLess.log
```
启动参数(在 `AppDelegate.runLaunchActions` 处理):
```bash
open build/OpenLess.app --args --open-settings
open build/OpenLess.app --args --start-recording
```
## 凭据
开发期凭据保存在本机:
凭据保存在本机 Keychain(service = `com.openless.app`)。开发期同时维护一份明文 JSON 兜底,用于在 Keychain 不可用时回退:
```text
~/.openless/credentials.json
~/.openless/credentials.json # 0600,目录 0700
```
文件权限会设置为 `0600`,目录权限为 `0700`。当前没有把 API Key 写入仓库、日志或公开配置。正式发布前建议切换到稳定开发者签名 + Keychain。
仓库本身不包含任何 API Key、Token 或 Endpoint 之外的私有信息。
需要配置:
需要配置的字段:
- 火山引擎 ASR:APP ID、Access Token、Resource ID。
- Ark 润色:API Key、Model ID、Endpoint。
## 图标
图标源文件放在:
```text
Resources/Brand/openless-app-icon-source.jpg
```
生成脚本:
```bash
swift scripts/generate-app-icon.swift
```
脚本会输出:
```text
Resources/AppIcon.png
Resources/AppIcon.icns
Resources/Brand/openless-standard-image.png
```
`Resources/Brand/openless-standard-image.png` 是 1024×1024 的标准品牌图;`scripts/build-app.sh` 会自动生成图标并把 `AppIcon.icns` 写入 `.app` bundle。
## 提示词处理原则
OpenLess 的润色模型只做文本整理,不做问答、不做任务执行、不做项目分析。每次语音输入都会作为独立请求发送,提示词会明确告诉模型:
@@ -102,22 +112,47 @@ OpenLess 的润色模型只做文本整理,不做问答、不做任务执行
主窗口按「首页 / 历史记录 / 词典 / 设置」组织;词典页点击“新建”会弹出独立编辑窗口,首页会展示口述时长、总字数、平均每分钟字数、估算节省时间和词典参与记录。
## 尚未完成的功能
## 架构概览
- 按住说话模式:当前是切换式录音,尚未实现真正的 hold-to-talk。
- 本地 ASR:当前主要接入火山引擎云端 ASR,本地模型路由还没有实现。
- 常用片段 Snippets:需求中有规划,当前没有 UI 和触发逻辑。
- 历史增强:当前能查看和清空历史,尚未支持复制按钮、搜索、重新润色、重新插入。
- 粘贴上一条快捷键:需求中有规划,当前没有独立快捷键。
- 多屏定位:胶囊目前优先显示在主屏底部,尚未按当前输入焦点所在屏幕定位。
- 稳定签名与 Keychain:开发期使用 ad-hoc 签名和本机受保护文件,正式发布前需要开发者签名、notarization 和 Keychain 方案。
- 自动更新和发布流水线:尚未接入 Sparkle、GitHub Release 自动打包或 notarization 流程。
- 更完整测试环境:当前 `swift build` 可验证编译;本机 CommandLineTools 环境缺少 `XCTest`,需要完整 Xcode 环境后跑 `swift test`。
SwiftPM 工作区,1 个可执行 + 8 个库。库与库之间无相互依赖,全部只依赖 `OpenLessCore`,由 `OpenLessApp` 统一在 `DictationCoordinator` 里编排。
## GitHub 发布前检查
```
OpenLessCore // Pure value types: DictationSession, PolishMode, HotkeyBinding,
// AudioConsumer protocol, RawTranscript/FinalText, errors.
OpenLessHotkey // CGEventTap-based modifier-key monitor. Requires Accessibility.
OpenLessRecorder // AVAudioEngine → 16 kHz mono Int16 PCM, 推送到 AudioConsumer.
OpenLessASR // 火山引擎 streaming ASR over WebSocket.
OpenLessPolish // Ark / Doubao chat-completions 客户端 + 模式驱动 prompts。
OpenLessInsertion // AX focused-element 优先;剪贴板 + Cmd+V 兜底;最后 copy-only。
OpenLessPersistence // CredentialsVault (Keychain), HistoryStore, DictionaryStore,
// UserPreferences。
OpenLessUI // SwiftUI 胶囊视图 + 状态枚举(不接窗口)。
OpenLessApp // AppDelegate, 菜单栏, 设置窗口, 胶囊窗口, DictationCoordinator。
```
- 确认没有提交 `.build/`、`build/`、`.DS_Store`、本地凭据或临时截图。
录音 → 转写 → 润色 → 插入的状态机由 `Sources/OpenLessApp/DictationCoordinator.swift` 单一拥有,详见 [CLAUDE.md](CLAUDE.md)。
## 1.0 之后的规划
下面这些功能在需求文档里有规划,但 1.0 没有发布:
- 按住说话模式(hold-to-talk):当前仅支持切换式。
- 本地 ASR:当前仅接入火山引擎云端 ASR。
- 常用片段 Snippets:尚无 UI 和触发逻辑。
- 历史增强:复制按钮、搜索、重新润色、重新插入。
- 粘贴上一条快捷键。
- 多屏定位:胶囊按当前焦点所在屏幕显示。
- Developer ID 签名 + Notarization + Sparkle 自动更新。
## 维护者:发布前检查
- 确认没有提交 `.build/`、`build/`、`.DS_Store`、`~/.openless/credentials.json` 或临时截图。
- 保留 `Resources/Brand/openless-app-icon-source.jpg`、`Resources/AppIcon.png`、`Resources/AppIcon.icns`。
- 运行 `./scripts/build-app.sh`,确认 `build/OpenLess.app` 可启动。
- 在一台干净 macOS 机器上验证权限引导、快捷键、录音、ASR、润色、插入和剪贴板兜底。
- 正式分发前完成 Developer ID 签名和 notarization。
- 用 `ditto -c -k --keepParent build/OpenLess.app build/OpenLess-<version>.zip` 打包,确保 ad-hoc 签名和扩展属性保留。
- 正式分发前请完成 Developer ID 签名和 notarization。
## 许可
MIT
+98
View File
@@ -0,0 +1,98 @@
# OpenLess 使用说明
面向普通用户。开发者和架构信息见 [README.md](README.md) 与 [CLAUDE.md](CLAUDE.md)。
---
## 1. 下载与解除隔离
到 [Releases](../../releases) 下载最新的 `OpenLess-1.0.0.zip`,解压会得到 `OpenLess.app`。把它拖到 `应用程序`。
由于 1.0 是 ad-hoc 签名构建(没有付费 Apple Developer ID),macOS Gatekeeper 会拦下提示「无法验证开发者」。在终端中执行一次:
```bash
xattr -dr com.apple.quarantine /Applications/OpenLess.app
```
之后双击就能启动。
> 这一步只需要做一次。下次升级版本,覆盖 `OpenLess.app` 后再执行一次同样的命令即可。
## 2. 授权
OpenLess 需要两个系统权限:
| 权限 | 在哪里授权 | 用来做什么 |
| --- | --- | --- |
| 麦克风 | 系统设置 → 隐私与安全 → 麦克风 | 录音 |
| 辅助功能 | 系统设置 → 隐私与安全 → 辅助功能 | 监听全局快捷键 + 把文本写入当前输入框 |
**授权辅助功能后必须退出 OpenLess 并重新打开。** macOS 不会把新授权同步给已经在跑的进程,全局快捷键监听需要进程重启才能生效。
## 3. 配置 ASR 和润色凭据
OpenLess 不内置任何云端 Key,需要你自己提供:
- **火山引擎流式 ASR**:APP ID、Access Token、Resource ID。在火山引擎控制台开通「语音技术 → 流式语音识别」后获取。
- **Ark / DeepSeek 兼容 Chat Completions**:API Key、Model ID、Endpoint。Ark 默认 endpoint 是 `https://ark.cn-beijing.volces.com/api/v3/chat/completions`。
在 OpenLess 主窗口的「设置」标签页填入即可。凭据保存在系统 Keychain(service = `com.openless.app`),不会上传也不会写入仓库。
> 如果不填 Ark:OpenLess 会跳过润色,直接插入 ASR 原文。
>
> 如果不填火山:OpenLess 会跑一段 mock 流程,并把占位文本复制到剪贴板(不会插入到输入框)。
## 4. 日常使用
1. 把光标停在任意输入框(聊天框、邮件、代码编辑器、浏览器地址栏……)。
2. 按一次右 `Option`(默认快捷键)开始录音。底部胶囊会变成红色音量条。
3. 说话。
4. 再按一次右 `Option` 结束录音。胶囊会进入「转写 → 润色」状态。
5. 润色完的文字会自动插入到光标所在位置。如果当前应用拒绝写入,会复制到剪贴板,请手动 `Cmd+V`。
6. 按 `Esc` 在录音过程中取消,原始音频不会发送到 ASR。
每一次会话都会保存到「历史记录」标签页,包含:录音时长、原始转写、润色后文本、采用的模式。
## 5. 输出模式
在主窗口顶部切换:
| 模式 | 适合场景 |
| --- | --- |
| 原文 | 不想做任何修改,直接拿 ASR 结果。 |
| 轻度润色 | 去口癖、补标点。最常用。 |
| 清晰结构 | 把连贯口语拆成短句、列表。适合需求/任务描述。 |
| 正式表达 | 用更书面的语气重写。适合邮件、公告。 |
模式只影响润色 prompt,不会让模型「回答你说的话」。详见 README 的「提示词处理原则」。
## 6. 词典
「词典」标签页用来教模型识别你的专有名词、产品名、人名和新词。
- 每个词条只需要填正确写法、分类(可选)、备注(可选)。
- 启用的词条会作为火山 ASR 的 `context.hotwords` 提交,识别阶段就尽量正确。
- 同时会注入润色阶段,让模型根据上下文判断是否需要把同音词修正成你的词。例如词典里有 `Claude`,模型听到 `Cloud` 时会根据语境决定要不要改成 `Claude`。
## 7. 排查
- **按快捷键无反应**:辅助功能没授权,或授权后未重启 OpenLess。
- **录音时胶囊一直是灰色**:麦克风没授权,或被其他应用独占。
- **转写一直在转圈**:火山凭据填错,或网络无法访问火山服务。看日志确认。
- **文字没插入但被复制了**:当前应用拒绝 AX 写入和 Cmd+V,按 `Cmd+V` 手动粘贴。
- **看日志**:
```bash
tail -f ~/Library/Logs/OpenLess/OpenLess.log
```
## 8. 卸载
```bash
rm -rf /Applications/OpenLess.app
rm -rf ~/Library/Application\ Support/OpenLess
rm -rf ~/Library/Logs/OpenLess
rm -rf ~/.openless
```
Keychain 里的凭据可以用「钥匙串访问.app」搜索 `com.openless.app` 删除。
+2 -2
View File
@@ -6,8 +6,8 @@ cd "$(dirname "$0")/.."
APP_NAME="OpenLess"
BUNDLE_ID="com.openless.app"
APP_VERSION="0.1.8"
BUILD_NUMBER="9"
APP_VERSION="1.0.0"
BUILD_NUMBER="1"
BUILD_DIR="build"
APP_DIR="${BUILD_DIR}/${APP_NAME}.app"
BIN_DIR="${APP_DIR}/Contents/MacOS"