@xdfnet/ispeak 1.6.7 → 1.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # iSpeak
2
2
 
3
- ![Version](https://img.shields.io/badge/version-1.6.7-blue)
3
+ ![Version](https://img.shields.io/badge/version-1.6.8-blue)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
  [![Go Version](https://img.shields.io/badge/Go-1.26-blue)](https://golang.org/dl/)
6
6
  ![Platform](https://img.shields.io/badge/platform-macOS-green)
@@ -14,12 +14,6 @@ iSpeak 让 AI 编程助手开口说话。你写代码,它播结果——眼睛
14
14
  ```
15
15
  # 默认音色:温柔女声
16
16
  ispeak "Pull request 已合并,3 个测试通过"
17
-
18
- # Claude 模式:专属音色
19
- ispeak-claude "Code review 完成,发现 2 处可优化"
20
-
21
- # Codex 模式:另一种音色
22
- ispeak-codex "构建完成,耗时 12 秒"
23
17
  ```
24
18
 
25
19
  ## 为什么选 iSpeak
@@ -29,7 +23,7 @@ ispeak-codex "构建完成,耗时 12 秒"
29
23
  | AI 生成多条回复,TTS 账单飞涨 | 新消息只保留最新待执行任务,避免无效合成 |
30
24
  | 回复快慢不一,音频播报乱序 | 单 transaction worker,FIFO 顺序稳定 |
31
25
  | 修改配置要重启服务 | 热更新:编辑 `config.json` 立即生效 |
32
- | 默认音色太无聊 | 来源专属音色,Claude Codex 声音不同 |
26
+ | 默认音色太无聊 | hook 按来源前缀选择音色 |
33
27
 
34
28
  ## 快速上手
35
29
 
@@ -113,12 +107,6 @@ ispeak restart # 重启服务
113
107
  ispeak version # 版本
114
108
  ```
115
109
 
116
- 语音专属快捷命令(指向 ispeak 的软链接):
117
- ```bash
118
- ispeak-claude "消息" # Claude 专属音色
119
- ispeak-codex "消息" # Codex 专属音色
120
- ```
121
-
122
110
  ## 配置说明
123
111
 
124
112
  `~/.config/iSpeak/config.json`:
@@ -148,49 +136,9 @@ ispeak-codex "消息" # Codex 专属音色
148
136
 
149
137
  ## 集成说明
150
138
 
151
- ### Claude Code
152
-
153
- 在 `~/.claude/settings.json` 中添加 Stop Hook:
154
-
155
- ```json
156
- {
157
- "hooks": {
158
- "Stop": [{
159
- "hooks": [{
160
- "type": "command",
161
- "command": "bash $HOME/.config/iSpeak/hook-speak.sh claude",
162
- "timeout": 30
163
- }]
164
- }]
165
- }
166
- }
167
- ```
168
-
169
- ### Codex
170
-
171
- 推荐在 `~/.codex/config.toml` 中添加回合结束通知:
172
-
173
- ```toml
174
- notify = ["bash", "/Users/你的用户名/.config/iSpeak/hook-speak.sh", "codex"]
175
- ```
176
-
177
- 如果你启用了 Codex hooks,也可以在 `~/.codex/hooks.json` 中添加 Stop Hook:
178
-
179
- ```json
180
- {
181
- "hooks": {
182
- "Stop": [{
183
- "hooks": [{
184
- "type": "command",
185
- "command": "bash $HOME/.config/iSpeak/hook-speak.sh codex",
186
- "timeout": 30
187
- }]
188
- }]
189
- }
190
- }
191
- ```
139
+ Claude Code 和 Codex 的详细 hook 配置见 [docs/hook-text-extraction.md](/Users/admin/iCode/iSpeak/docs/hook-text-extraction.md)。
192
140
 
193
- `hook-speak.sh` 会按 `turn_id` 做一次去重,所以即使 `notify` 和 `Stop` 都启用,同一回合也只会播一次。
141
+ `hook-speak.sh` 会按 `turn_id` 做一次去重,所以同一回合不会播两次。
194
142
 
195
143
  ## 开发命令
196
144
 
@@ -207,7 +155,7 @@ make help # 显示帮助
207
155
 
208
156
  | 文件 | 用途 |
209
157
  |------|------|
210
- | `~/Library/LaunchAgents/com.iSpeak.plist` | macOS 自动启动服务 |
158
+ | `~/Library/LaunchAgents/com.ispeak.plist` | macOS 自动启动服务 |
211
159
  | `~/.config/iSpeak/ispeak.sock` | Unix Socket |
212
160
  | `~/.config/iSpeak/ispeak.log` | 日志(轮转) |
213
161
  | `~/.config/iSpeak/config.json` | 你的 API Key 和音色配置 |
@@ -3,7 +3,7 @@
3
3
  <plist version="1.0">
4
4
  <dict>
5
5
  <key>Label</key>
6
- <string>com.iSpeak</string>
6
+ <string>com.ispeak</string>
7
7
  <key>ProgramArguments</key>
8
8
  <array>
9
9
  <string>BINARY_PATH_PLACEHOLDER</string>
@@ -180,7 +180,7 @@ pending -> running -> delete
180
180
  └── hook-speak.sh # Claude/Codex Hook
181
181
 
182
182
  ~/Library/LaunchAgents/
183
- └── com.iSpeak.plist # launchd 服务配置
183
+ └── com.ispeak.plist # launchd 服务配置
184
184
  ```
185
185
 
186
186
  ## 稳定性设计
@@ -10,7 +10,8 @@ const root = path.resolve(__dirname, "..");
10
10
  const home = os.homedir();
11
11
  const binDir = path.join(home, ".local", "bin");
12
12
  const configDir = path.join(home, ".config", "iSpeak");
13
- const plistPath = path.join(home, "Library", "LaunchAgents", "com.iSpeak.plist");
13
+ const plistPath = path.join(home, "Library", "LaunchAgents", "com.ispeak.plist");
14
+ const legacyPlistPath = path.join(home, "Library", "LaunchAgents", "com.iSpeak.plist");
14
15
  const socketPath = path.join(configDir, "ispeak.sock");
15
16
  const binaryPath = path.join(binDir, "ispeakd");
16
17
  const cliPath = path.join(binDir, "ispeak");
@@ -136,12 +137,16 @@ function main() {
136
137
  run("go", ["build", "-ldflags=-s -w", "-o", buildPath, "."]);
137
138
 
138
139
  console.log("停止旧服务...");
140
+ run("launchctl", ["unload", legacyPlistPath], { allowFailure: true, stdio: "ignore" });
139
141
  run("launchctl", ["unload", plistPath], { allowFailure: true, stdio: "ignore" });
142
+ try {
143
+ fs.rmSync(legacyPlistPath, { force: true });
144
+ } catch (_) {
145
+ // Ignore migration cleanup failures.
146
+ }
140
147
 
141
148
  copyExecutable(buildPath, binaryPath);
142
149
  copyExecutable(path.join(root, "scripts", "ispeak"), cliPath);
143
- symlinkForce(cliPath, path.join(binDir, "ispeak-claude"));
144
- symlinkForce(cliPath, path.join(binDir, "ispeak-codex"));
145
150
 
146
151
  const configPath = path.join(configDir, "config.json");
147
152
  copyIfMissing(path.join(root, "configs", "config.example.json"), configPath);
@@ -149,7 +154,7 @@ function main() {
149
154
  installHook(path.join(root, "configs", "hook-speak.sh"), path.join(configDir, "hook-speak.sh"));
150
155
 
151
156
  const plist = fs
152
- .readFileSync(path.join(root, "configs", "com.iSpeak.plist"), "utf8")
157
+ .readFileSync(path.join(root, "configs", "com.ispeak.plist"), "utf8")
153
158
  .replaceAll("BINARY_PATH_PLACEHOLDER", binaryPath);
154
159
  fs.writeFileSync(plistPath, plist);
155
160
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xdfnet/ispeak",
3
- "version": "1.6.7",
3
+ "version": "1.6.8",
4
4
  "description": "Local macOS TTS daemon for AI coding assistants, powered by Volcengine streaming TTS.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/xdfnet/iSpeak#readme",
@@ -19,9 +19,7 @@
19
19
  "x64"
20
20
  ],
21
21
  "bin": {
22
- "ispeak": "scripts/ispeak",
23
- "ispeak-claude": "scripts/ispeak",
24
- "ispeak-codex": "scripts/ispeak"
22
+ "ispeak": "scripts/ispeak"
25
23
  },
26
24
  "scripts": {
27
25
  "build": "go build -ldflags=\"-s -w\" -o build/ispeakd .",
@@ -38,7 +36,7 @@
38
36
  "scripts/ispeak",
39
37
  "configs/",
40
38
  "npm/",
41
- "Docs/",
39
+ "docs/",
42
40
  "README.md",
43
41
  "LICENSE"
44
42
  ],
package/scripts/ispeak CHANGED
@@ -2,16 +2,10 @@
2
2
  # ispeak — iSpeak 控制命令
3
3
  set -euo pipefail
4
4
 
5
- VERSION="1.6.7"
5
+ VERSION="1.6.8"
6
6
  SOCK="$HOME/.config/iSpeak/ispeak.sock"
7
- PLIST="$HOME/Library/LaunchAgents/com.iSpeak.plist"
8
- CMD_NAME="$(basename "$0")"
9
- SOURCE_PREFIX=""
10
-
11
- case "$CMD_NAME" in
12
- ispeak-claude) SOURCE_PREFIX="{source:claude}" ;;
13
- ispeak-codex) SOURCE_PREFIX="{source:codex}" ;;
14
- esac
7
+ PLIST="$HOME/Library/LaunchAgents/com.ispeak.plist"
8
+ LEGACY_PLIST="$HOME/Library/LaunchAgents/com.iSpeak.plist"
15
9
 
16
10
  cmd_status() {
17
11
  echo "== iSpeak =="
@@ -28,6 +22,7 @@ cmd_status() {
28
22
  }
29
23
 
30
24
  cmd_restart() {
25
+ launchctl unload "$LEGACY_PLIST" 2>/dev/null || true
31
26
  launchctl unload "$PLIST" 2>/dev/null || true
32
27
  launchctl load "$PLIST"
33
28
  sleep 0.5
@@ -53,6 +48,6 @@ case "${1:-}" in
53
48
  echo " ispeak version 版本"
54
49
  ;;
55
50
  *)
56
- printf "%s%s" "$SOURCE_PREFIX" "$*" | nc -U -w5 "$SOCK" 2>/dev/null || echo "ispeak: socket 不可用" >&2
51
+ printf "%s" "$*" | nc -U -w5 "$SOCK" 2>/dev/null || echo "ispeak: socket 不可用" >&2
57
52
  ;;
58
53
  esac