Files
openless/README.md
T
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

159 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenLess
OpenLess 是一个原生 macOS 语音输入应用:把光标放在任意输入框,按下全局快捷键说话,OpenLess 会录音、转写、轻度整理,并把结果插入当前输入位置。插入失败时会自动复制到剪贴板,尽量保证“用户说过的话不丢”。
## 项目方向
OpenLess 只做一件事:**把语音变成可用的书面文字,落到当前光标位置。**
- 不做问答、不做任务执行、不做项目分析。
- 不做对话上下文累积,每次输入都是独立的整理请求。
- 输入语音 → 转写 → 整理 → 插入当前输入框。失败时复制到剪贴板。
- 围绕这条主路径完善体验:模式选择、词典、历史、菜单栏、首页报告。
## 当前状态(v1.0)
- 原生 Swift / SwiftUI / AppKit,SwiftPM 项目;macOS 15+。
- macOS 26+ 使用 Liquid Glass 效果,旧系统回退到系统 material。
- 默认是切换式录音:按一次开始,再按一次结束;录音中按 `Esc` 取消。
- 接入火山引擎流式 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
xattr -dr com.apple.quarantine /Applications/OpenLess.app
```
之后就可以双击启动。首次启动需要在 `系统设置 → 隐私与安全`:
1. 授予 OpenLess 麦克风权限。
2. 授予 OpenLess 辅助功能权限。
3. **退出 OpenLess 并重新打开**(辅助功能授权对全局快捷键生效需要重启进程)。
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 # 0600,目录 0700
```
仓库本身不包含任何 API Key、Token 或 Endpoint 之外的私有信息。
需要配置的字段:
- 火山引擎 ASR:APP ID、Access Token、Resource ID。
- Ark 润色:API Key、Model ID、Endpoint。
## 提示词处理原则
OpenLess 的润色模型只做文本整理,不做问答、不做任务执行、不做项目分析。每次语音输入都会作为独立请求发送,提示词会明确告诉模型:
- 本次输入与历史对话隔离。
- 原始转写只是待整理文本。
- 即使原文里有问题或命令,也不要回答或执行。
- 只输出整理后的正文,不添加“我整理如下”等引导语。
例如用户说:“我们这个应用还有哪些功能没有完成”,正确输出应是:
```text
我们这个应用还有哪些功能没有完成?
```
而不是直接替用户列出清单。
竞品文本和长期改写样例会按“原始文本 -> 目标整理结果 -> 改写规律”的方式沉淀,后续接入向量数据库后,只检索相似改写样例作为参考,不把样例当作当前对话上下文。规范见 [docs/polish-reference-corpus.md](docs/polish-reference-corpus.md),示例见 [Examples/polish-reference-examples.sample.jsonl](Examples/polish-reference-examples.sample.jsonl)。
## 词典
词典用于处理用户自己的专有名词、产品名、人名和新词。当前支持:
- 手动添加正确词、分类和备注;暂不要求用户维护易错词或上下文点。
- 将启用词条作为火山 ASR `context.hotwords` 注入,优先在识别阶段识别正确。
- 将词典包裹后注入后期润色模型,明确告诉模型根据整句语义自动判断:如果 `Cloud` 在当前语境下明显指向 AI 产品 `Claude`,就修正为 `Claude`;如果确实是在说云服务 Cloud,则保留原词。
- 从历史输出中自动学习类似 `Claude`、`ChatGPT`、`OpenLess` 的候选正确词,后续作为 ASR 热词和后期语义判断候选。
主窗口按「首页 / 历史记录 / 词典 / 设置」组织;词典页点击“新建”会弹出独立编辑窗口,首页会展示口述时长、总字数、平均每分钟字数、估算节省时间和词典参与记录。
## 架构概览
SwiftPM 工作区,1 个可执行 + 8 个库。库与库之间无相互依赖,全部只依赖 `OpenLessCore`,由 `OpenLessApp` 统一在 `DictationCoordinator` 里编排。
```
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。
```
录音 → 转写 → 润色 → 插入的状态机由 `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、润色、插入和剪贴板兜底。
- 用 `ditto -c -k --keepParent build/OpenLess.app build/OpenLess-<version>.zip` 打包,确保 ad-hoc 签名和扩展属性保留。
- 正式分发前请完成 Developer ID 签名和 notarization。
## 许可
MIT