Skip to content

Commit b65bae1

Browse files
committed
feat: refactor text refinement flow
1 parent 431c614 commit b65bae1

34 files changed

Lines changed: 1123 additions & 558 deletions

electron/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
主进程核心模块:
2020

2121
- `main.ts` - 应用入口、窗口管理、IPC 处理、PTT 流程编排
22-
- `audio/` - 音频处理流水线(录音会话、转换、ASR、LLM 润色、注入)
22+
- `audio/` - 音频处理流水线(录音会话、转换、ASR、文本润色、注入)
2323
- `hotkey/` - 快捷键解析与 PTT 行为绑定
2424
- `ipc/` - IPC 处理器(配置、会话、历史、日志、更新、浮窗)
2525
- `tray/` - 托盘菜单与本地化刷新
@@ -31,7 +31,7 @@
3131
- `hotkey-manager.ts` - 全局快捷键管理(基于 `globalShortcut`
3232
- `iohook-manager.ts` - 低级键盘钩子(基于 `uiohook-napi`
3333
- `asr-provider.ts` - GLM ASR 服务封装
34-
- `llm-provider.ts` - GLM 文本润色服务封装(Chat Completions HTTP API,复用 ASR 区域与 Key
34+
- `refine/` - 文本润色模块(手动 OpenAI-compatible 配置、请求解析与连接测试
3535
- `text-injector.ts` - 文本注入模拟(基于 `nut-js`
3636
- `logger.ts` - 主进程日志与保留策略
3737
- `updater-manager.ts` - 版本检查与更新跳转
@@ -47,7 +47,7 @@ IPC 桥接层:
4747
跨进程共享代码:
4848

4949
- `types.ts` - TypeScript 类型定义、IPC 通道常量
50-
- `constants.ts` - 应用级常量(GLM API 配置、默认快捷键、音频参数)
50+
- `constants.ts` - 应用级常量(GLM API 预设、通用 Chat 默认参数、默认快捷键、音频参数)
5151

5252
## 根文件
5353

@@ -65,13 +65,13 @@ Electron 环境类型声明
6565
4. **数据传输** - 渲染进程将音频数据发送回主进程
6666
5. **格式转换** - `fluent-ffmpeg` 转换 WebM → MP3
6767
6. **语音识别** - `asr-provider` 调用 GLM API 转录
68-
7. **文本润色** - `llm-provider` 调用 GLM Chat Completions API 进行后处理(失败回退原文)
68+
7. **文本润色** - `refine/service` 根据手动填写的 OpenAI-compatible 配置调用 Chat Completions API 进行后处理(失败回退原文)
6969
8. **文本注入** - `text-injector` 模拟键盘输入到活动窗口
7070

7171
### 配置管理
7272

7373
- 配置存储路径:`~/.config/voice-key/voice-key-config.json`(macOS/Linux)或 `%APPDATA%/voice-key/...`(Windows)
74-
- 内容:ASR 配置、LLM 润色开关配置、快捷键配置
74+
- 内容:ASR 配置、文本润色配置、快捷键配置
7575
- 通过 IPC 与设置页面同步
7676

7777
### IPC 通信架构

electron/main/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# main/
22

3-
Electron 主进程目录,负责窗口管理、IPC、录音流程、ASR/LLM 调用与文本注入
3+
Electron 主进程目录,负责窗口管理、IPC、录音流程、ASR/文本润色调用与文本注入
44

55
## 文件列表
66

7-
- `main.ts` - 应用入口;创建后台/设置/浮窗窗口、托盘菜单与 IPC 处理,协调 PTT 录音 → 转录 → LLM 润色 → 注入流程、会话取消与 FFmpeg 初始化,并向音频处理器注入 ASR/低音量模式配置(系统语言随窗口聚焦同步)。
7+
- `main.ts` - 应用入口;创建后台/设置/浮窗窗口、托盘菜单与 IPC 处理,协调 PTT 录音 → 转录 → 文本润色 → 注入流程、会话取消与 FFmpeg 初始化,并向音频处理器注入 ASR/润色服务(系统语言随窗口聚焦同步)。
88
- `i18n.ts` - 主进程 i18next 初始化与语言切换,广播语言快照到各窗口。
99
- `env.ts` - 运行时环境与资源路径解析(开发/生产)。
10-
- `config-manager.ts` - 使用 `electron-store` 持久化应用偏好、ASR 配置、LLM 润色开关与快捷键配置
10+
- `config-manager.ts` - 使用 `electron-store` 持久化应用偏好、ASR 配置、文本润色配置与快捷键配置
1111
- `logger.ts` - 初始化 `electron-log`,统一控制台写入与日志保留/轮转策略。
1212
- `history-manager.ts` - 录音历史存储(固定保留最近 90 天),提供增删清空与统计接口。
1313
- `hotkey-manager.ts` - 基于 `globalShortcut` 的全局快捷键注册/注销。
1414
- `iohook-manager.ts` - 基于 `uiohook-napi` 的键盘钩子,检测 PTT 组合键按住状态。
1515
- `asr-provider.ts` - 调用 GLM ASR API(axios + FormData)上传音频并返回转录结果。
16-
- `llm-provider.ts` - GLM Chat Completions 文本润色适配层(axios HTTP),复用 ASR 区域与 API Key
16+
- `refine/` - 文本润色模块;将手动填写的 OpenAI-compatible 配置解析成统一 Chat Completions 请求,并执行润色与连接测试
1717
- `text-injector.ts` - 基于 `@nut-tree-fork/nut-js` 注入文本;Windows 使用剪贴板粘贴,macOS 校验辅助功能权限。
1818
- `updater-manager.ts` - 调用 GitHub Releases API 检查新版本,缓存结果并打开发布页下载链接。
1919
- `audio/` - 录音会话、音频转换与转写处理流水线。

electron/main/__tests__/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
- `config-manager.test.ts` - 配置管理器单元测试。
66
- `asr-provider.test.ts` - ASR Provider 请求与错误映射测试。
7-
- `llm-provider.test.ts` - GLM LLM Provider 端点解析、重试回退与错误映射测试
7+
- `refine/__tests__/service.test.ts` - 文本润色服务的手动配置解析、endpoint 规范化、错误映射与连接测试
88
- `text-injector.test.ts` - 文本注入与权限检查测试。
99
- `iohook-manager.test.ts` - 按键状态判定与修饰键精确匹配测试。
1010
- `history-manager.test.ts` - 历史记录增删清理与保留天数裁剪测试。

electron/main/__tests__/config-manager.test.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,97 @@ describe('ConfigManager', () => {
107107
it('returns default llm refine config', async () => {
108108
const configManager = await createManager()
109109
const config = configManager.getLLMRefineConfig()
110-
expect(config.enabled).toBe(LLM_REFINE.ENABLED)
110+
expect(config).toEqual({
111+
enabled: LLM_REFINE.ENABLED,
112+
endpoint: LLM_REFINE.ENDPOINT,
113+
model: LLM_REFINE.MODEL,
114+
apiKey: LLM_REFINE.API_KEY,
115+
})
111116
})
112117

113118
it('persists partial llm refine config', async () => {
114119
const configManager = await createManager()
115120
configManager.setLLMRefineConfig({
116121
enabled: false,
122+
endpoint: 'https://example.com/v1',
123+
model: 'gpt-4.1-mini',
124+
apiKey: 'test-key',
125+
})
126+
expect(configManager.getLLMRefineConfig()).toMatchObject({
127+
enabled: false,
128+
endpoint: 'https://example.com/v1',
129+
model: 'gpt-4.1-mini',
130+
apiKey: 'test-key',
131+
})
132+
})
133+
134+
it('migrates legacy openai-compatible refine config to flat schema', async () => {
135+
seedData = {
136+
llmRefine: {
137+
enabled: true,
138+
provider: 'openai-compatible',
139+
openaiCompatible: {
140+
endpoint: 'https://example.com/v1',
141+
model: 'gpt-4.1-mini',
142+
apiKey: 'test-key',
143+
},
144+
},
145+
}
146+
const configManager = await createManager()
147+
expect(configManager.getLLMRefineConfig()).toMatchObject({
148+
enabled: true,
149+
endpoint: 'https://example.com/v1',
150+
model: 'gpt-4.1-mini',
151+
apiKey: 'test-key',
117152
})
153+
})
154+
155+
it('migrates legacy glm-shared refine config to disabled manual config', async () => {
156+
seedData = {
157+
llmRefine: {
158+
enabled: true,
159+
provider: 'glm-shared',
160+
},
161+
}
162+
const configManager = await createManager()
118163
expect(configManager.getLLMRefineConfig()).toMatchObject({
119164
enabled: false,
165+
endpoint: '',
166+
model: '',
167+
apiKey: '',
168+
})
169+
})
170+
171+
it('migrates legacy boolean-only refine config to disabled manual config', async () => {
172+
seedData = {
173+
llmRefine: {
174+
enabled: true,
175+
},
176+
}
177+
const configManager = await createManager()
178+
expect(configManager.getLLMRefineConfig()).toMatchObject({
179+
enabled: false,
180+
endpoint: '',
181+
model: '',
182+
apiKey: '',
183+
})
184+
})
185+
186+
it('decrypts encrypted llm refine api keys on read', async () => {
187+
seedData = {
188+
llmRefine: {
189+
enabled: true,
190+
endpoint: 'https://example.com/v1',
191+
model: 'gpt-4.1-mini',
192+
apiKey: `enc:${Buffer.from('encrypted:refine-key').toString('base64')}`,
193+
},
194+
}
195+
const configManager = await createManager()
196+
expect(configManager.getLLMRefineConfig()).toMatchObject({
197+
enabled: true,
198+
endpoint: 'https://example.com/v1',
199+
model: 'gpt-4.1-mini',
200+
apiKey: 'refine-key',
120201
})
121202
})
122203

electron/main/__tests__/llm-provider.test.ts

Lines changed: 0 additions & 155 deletions
This file was deleted.

0 commit comments

Comments
 (0)