@kg-ai/kugou-skill 0.1.9 → 0.1.11

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/SKILL.md CHANGED
@@ -32,23 +32,33 @@ description: |
32
32
  1. 检查安装 → npm install -g @kg-ai/kugou-skill
33
33
  2. 检查登录态 → kugou-cli auth status
34
34
  3. 登录决策(按以下优先级严格判断,不要跳步):
35
- ├─ 状态 a:已登录(logged_in: true)→ 跳到第 5
36
- ├─ 状态 b:未登录 + 用户**明确**说"我有 secret" → 调 `kugou-cli auth set-secret "<secret>"` 一次完成 → 跳到第 5
35
+ ├─ 状态 a:已登录(logged_in: true)→ 跳到第 6
36
+ ├─ 状态 b:未登录 + 用户**明确**说"我有 secret" → 调 `kugou-cli auth set-secret "<secret>"` 一次完成 → 跳到第 6
37
37
  ├─ 状态 c:未登录 + 当前环境**无法**渲染远程 URL 图片 **且** 无法读取本地二维码文件 → **强制**走 set-secret(同上)
38
38
  └─ 状态 d:未登录 + 其他所有情况 → 走扫码流程(第 4 步)
39
39
 
40
40
  注意:状态 b/c/d 互斥;不要在用户未明确给 secret 时擅自走 set-secret。
41
41
  4. 引导登录——扫码(详见 references/auth.md):
42
42
  - 执行 `auth login`,从输出读 `qrcode_img_url` 和 `qrcode_img_path`,按当前客户端能力选一种方式把二维码**直接展示给用户**
43
- - **阶段 A(主动轮询)**:图片刚展示,**主动**重试几次 `auth status`(每次隔几秒),覆盖用户秒扫场景
44
- - 任意一次返回 `logged_in: true` → 跳到第 5
45
- - 几次都返回 `waiting` 且未出现 `scanned` → 进入阶段 B
46
- - **阶段 B(等用户回复)**:停下,告诉用户"请用酷狗 APP 扫码登录,扫完后告诉我已扫码",**不再调 status**,等用户**主动回复"已扫码"**
47
- - **阶段 C(验证一次)**:用户回复"已扫码"后,**调一次** `auth status`:
48
- - `logged_in: true` → 完成,跳到第 5
43
+ - **阶段 A(主动轮询)**:图片刚展示,**主动**重试几次 `auth status`(每次隔几秒),覆盖用户秒扫场景
44
+ - 任意一次返回 `logged_in: true` → 跳到第 6
45
+ - 几次都返回 `waiting` 且未出现 `scanned` → 进入阶段 B
46
+ - **阶段 B(等用户回复)**:停下,告诉用户"请用酷狗 APP 扫码登录,扫完后告诉我已扫码",**不再调 status**,等用户**主动回复"已扫码"**
47
+ - **阶段 C(验证一次)**:用户回复"已扫码"后,**调一次** `auth status`:
48
+ - `logged_in: true` → 完成,跳到第 6
49
49
  - `scanned`(已扫但未确认)→ 等几秒再调一次,最多**额外**调几次,仍是 scanned 就告诉用户"手机端是否已点确认?"
50
50
  - `failed` 或 `{"logged_in": false}` → 重新 `auth login` 拿新图,从阶段 A 重新开始
51
- 5. 按请求类型分流:
51
+ 5. **首次要展示歌曲/歌单前探测本机客户端可用性**(详见 [references/control.md §13](references/control.md#13-client-detection-control-detect)):
52
+ - **触发时机**:本会话中第一次要向用户展示歌曲列表、歌单列表或歌单内歌曲列表之前。后续展示**复用本次探测结果**(会话内探测一次即可,不要每条命令前都跑)
53
+ - **命令**:`kugou-cli control detect`(零副作用,不启动客户端、不抢焦点)
54
+ - **判定**:
55
+ - 退出码 `0` → 本机有客户端,标记 `client_available = true`
56
+ - 退出码 `2` → 本机没装客户端,标记 `client_available = false`
57
+ - 退出码 `1` → 探测过程出错(注册表权限等),按 `false` 处理并继续
58
+ - **不影响 control 命令本身**:当用户主动要求 `control play` 等命令时,仍按原本的 `control` 错误处理(找不到客户端会由 `control start` 报"handshake file not found",不要用探测结果跳过 `control` 调用)
59
+ - **何时不探测**:用户请求只查询统计数据、查收藏/最近播放、看错误页等**不展示歌曲列表**的纯查询场景;登录流程本身;debug / 排错场景
60
+
61
+ 6. 按请求类型分流:
52
62
  - **请求类型 A:控制已有歌 / 歌单 / 收藏**(用户已有 mixsongid 或 global_id)→ 直接执行 `control` 命令(详见 [references/control.md](references/control.md)),不需要先调 `music` 拿 ID
53
63
  - 例:`control play`、`control player --action pause`、`control favorite song --mixsongid <id>`、`control play-playlist --global-id <id>`
54
64
  - **请求类型 B:搜索后做某件事**(搜索歌曲/推荐/榜单 → 拿到 ID 后再做后续动作,如播放、收藏、建歌单)→ 先执行 `music` 命令拿数据,再按需转 `control`,详见 [references/music.md](references/music.md)
@@ -56,7 +66,7 @@ description: |
56
66
  - 例:先 `music search-playlist` 拿 global_id,再 `control play-playlist` 播放
57
67
  - 例:先 `music search` 拿 mixsongids,再 `control playlist create --mixsongids` 创建客户端歌单
58
68
  - **请求类型 C:纯查询 / 统计 / 榜单**(不涉及本地客户端)→ 只走 `music` 命令
59
- 6. 解析 JSON 输出,按展示规范展示给用户(详见 [references/output-format.md](references/output-format.md))
69
+ 7. 解析 JSON 输出,按展示规范展示给用户(详见 [references/output-format.md](references/output-format.md))
60
70
  ```
61
71
 
62
72
  > **关键提醒**:**不要**在没有 mixsongid / global_id 的情况下盲目调用 `control` 命令(如 `control play --mixsongid ""`)—— `control` 命令在 ID 缺失时会报错。先用 `music` 命令把 ID 查出来,再传给 `control`。
@@ -111,7 +121,7 @@ description: |
111
121
  2. **直接**引导用户重新登录:先问"你手上是否已有新 secret?",有则 `auth set-secret`,没有则 `auth login` 走扫码
112
122
  3. 重新登录后,**先调 `auth status` 确认** `logged_in: true`,再重试之前失败的 `music` 命令
113
123
 
114
- > Agent 不应依赖 stderr 文案字面量判断错误类型——以退出码和 references/error-handling.md 中的错误码说明为准。
124
+ > 错误判定以退出码 + references/error-handling.md 中的错误码说明为准,**不要**依赖 stderr 文案字面量匹配。
115
125
 
116
126
  ### 音乐命令依赖登录
117
127
 
@@ -121,16 +131,53 @@ description: |
121
131
 
122
132
  所有命令输出原始 JSON 到 stdout,错误输出到 stderr。**成功判定以退出码和 JSON 内的成功状态字段为准**(详见 [references/output-format.md](references/output-format.md))。
123
133
 
124
- ### 歌曲展示规范
134
+ ### 歌曲/歌单展示规范
125
135
 
126
- 向用户展示音乐命令返回的歌曲列表时(详见 [references/output-format.md](references/output-format.md)):
136
+ 向用户展示音乐命令返回的歌曲列表或歌单列表时,按以下规则(详见 [references/output-format.md §1](references/output-format.md)):
127
137
 
128
- - **禁止**只返回歌曲名、歌手名
129
- - **必须**以 Markdown 链接格式展示播放链接
130
- - 正确格式:`[歌曲名 - 歌手名](https://www.kugou.com/...)`
131
- - 禁止格式:`晴天 - 周杰伦`(无链接)、`歌曲名: 晴天, 歌手: 周杰伦`(无链接)
138
+ - **结果 ≥ 2 条** → 用 Markdown 表格展示
139
+ - 歌曲表格列:`| 序号 | 歌曲名 | 歌手 |`
140
+ - 歌单表格列:`| 序号 | 歌单名 | 创建人昵称 |`
141
+ - **表格内的歌曲名 / 歌单名一律不加链接**(避免列宽过长、可读性差;详见下方解释)
142
+ - **结果 = 1 条** → 用单行 Markdown 链接展示
143
+ - 有客户端(探测结果 `client_available = true`)→ 歌曲名/歌单名**不加链接**(可直接调 `control play` 等本地命令)
144
+ - 无客户端(探测结果 `client_available = false`)→ 歌曲名/歌单名**必须加链接**,方便用户手动打开
145
+ - 歌曲正确格式:`[歌曲名 - 歌手名](https://www.kugou.com/...)`
146
+ - 歌单正确格式:`[歌单名](<song_list_url>)`
147
+ - **结果 = 0 条** → 告诉用户"未找到结果",不需要展示表格或链接
132
148
 
133
- ### 推荐理由规范
149
+ #### 为什么表格不加链接?
150
+
151
+ - 表格单元格加 Markdown 链接会让列宽自适应 URL,中文长字符串下表的可读性变差
152
+ - 表格场景下用户通常是要**浏览/筛选**,ID 由 agent 内部持有,等用户明确说"播放这首" / "打开这个歌单"再走对应命令
153
+
154
+ #### 客户端可用性探测怎么用?
155
+
156
+ - **首次**要展示歌曲/歌单列表前,按工作流第 5 步跑 `kugou-cli control detect`,记下 `client_available`
157
+ - 单条结果(= 1)时根据 `client_available` 决定加不加链接
158
+ - 表格结果(≥ 2)时**无视** `client_available`,表格单元格不加链接
159
+ - 探测结果**不**影响用户主动调用 `control *` 命令的逻辑——那是另一条独立路径(由 `control start` 自己报错)
160
+
161
+ ### 播放 / 切歌后必须告知当前曲目
162
+
163
+ **触发条件**:以下命令**成功后**必须告知用户当前正在播放的歌曲:
164
+
165
+ - `control play`(播放单首)
166
+ - `control play-playlist`(播放整个歌单)
167
+ - `control continue-play`(续播另一设备列表)
168
+ - `control player --action next/prev`(切歌)
169
+
170
+ **操作**:调用 `kugou-cli control current` 拿到 `song_name` / `singer_name`,向用户输出:
171
+
172
+ > � 正在播放:<歌曲名> - <歌手>
173
+
174
+ **注意**:
175
+ - **必须**用 `control current` 重新拿当前曲目,**不要**用 `control play` 命令里 `--song-name` / `--singer-name` 字段直接展示——后者只是客户端展示用的标签,**不保证与实际播放一致**(特别是播放歌单 / 续播 / 切歌之后)
176
+ - 若 `control current` 返回非 `code: 0`(如客户端断开 / 命令未支持),告知用户"已开始播放(无法读取当前曲目详情)",不要假装知道
177
+
178
+ 详见 [references/control.md §3 current](./references/control.md#3-current--获取当前播放)。
179
+
180
+ ### 推荐理由规范
134
181
 
135
182
  仅在 agent **主动推荐**场景下,歌曲列表之后**必须**追加一段 220-260 字的推荐理由(详见 [references/output-format.md#5-推荐理由主动推荐场景必写](references/output-format.md#5-推荐理由主动推荐场景必写)):
136
183
 
@@ -181,7 +228,7 @@ description: |
181
228
  - **二进制命令**: kugou-cli
182
229
  - **安装方式**: `npm install -g @kg-ai/kugou-skill`
183
230
 
184
- > 关于更新:CLI 安装后会自动保持最新。具体更新机制与关闭开关见 [references/update.md](references/update.md)。如有版本相关问题,向该文档查证。
231
+ > 关于更新:CLI 安装后会自动保持最新。具体行为与关闭开关见 [references/update.md](references/update.md)。如有版本相关问题,向该文档查证。
185
232
 
186
233
  ---
187
234
 
@@ -193,7 +240,7 @@ description: |
193
240
  | [references/music.md](references/music.md) | 音乐命令:搜索、推荐、收藏、统计、榜单、创建歌单 |
194
241
  | [references/control.md](references/control.md) | 控制命令:控制 PC/Mac 客户端播放、暂停、切歌、收藏、创建歌单等 |
195
242
  | [references/install.md](references/install.md) | 安装命令:SKILL.md 安装到各平台 |
196
- | [references/update.md](references/update.md) | 更新机制、版本检查、关闭自动更新 |
243
+ | [references/update.md](references/update.md) | 更新行为、版本检查、关闭自动更新 |
197
244
  | [references/output-format.md](references/output-format.md) | 输出格式与展示规范 |
198
245
  | [references/error-handling.md](references/error-handling.md) | 错误处理与常见错误 |
199
246
 
@@ -204,7 +251,6 @@ description: |
204
251
  ```bash
205
252
  # 1. 登录(详见 references/auth.md)
206
253
  kugou-cli auth login # 获取二维码
207
- # auth status 不会内部轮询;Agent 按"阶段 A → 阶段 B → 阶段 C"自行循环
208
254
  kugou-cli auth status
209
255
 
210
256
  # 1'. 或者直接导入已持有的 secret(跳过扫码)
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kg-ai/kugou-skill",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Kugou Skill CLI",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -163,10 +163,6 @@ secret cannot be empty
163
163
  - 所有 `music` 子命令立即可用,无需任何额外步骤
164
164
  - nickname 字段为空(因为导入途径不带昵称),不影响功能
165
165
 
166
- **上游校验时机**:
167
- - CLI 不做本地格式校验(不做 base64 解码、不解密),只做"非空"检查
168
- - secret 实际有效性在**第一次**调用 `music <sub>` 时由上游校验
169
-
170
166
  **登录态过期处理**:
171
167
  - 当任意 `music` 命令遇到登录态过期时,CLI 会**自动清理**本地登录态,并在 stderr 输出 `账号登录过期,请重新登录`,以非 0 exit code 退出
172
168
  - Agent 收到该错误后应**直接引导用户重新登录**(`auth login` 走扫码,或 `auth set-secret` 导入新 secret),无需手动清理本地文件
@@ -67,7 +67,7 @@ kugou-cli control: not logged in, run `kugou-cli auth login` first: auth file no
67
67
 
68
68
  ## 2. status — 获取客户端状态
69
69
 
70
- 查询本地酷狗客户端的协议版本、登录态和能力列表。对应 `GET /v1/status`。
70
+ 查询本地酷狗客户端的协议版本、登录态和能力列表。
71
71
 
72
72
  ```bash
73
73
  kugou-cli control status
@@ -89,7 +89,7 @@ kugou-cli control status
89
89
 
90
90
  ## 3. current — 获取当前播放
91
91
 
92
- 查询当前播放歌曲详情,包括歌名、歌手、进度、音量和收藏状态。对应 `GET /v1/player/current`。
92
+ 查询当前播放歌曲详情,包括歌名、歌手、进度、音量和收藏状态。
93
93
 
94
94
  ```bash
95
95
  kugou-cli control current
@@ -131,6 +131,8 @@ kugou-cli control play --mix-song-id 32100650 --mode "append_queue"
131
131
  | `--singer-name` | 歌手显示名(可选) |
132
132
  | `--mode` | 播放模式:`append_queue`(追加队列)、`next_play`(下一首播放) |
133
133
 
134
+ > 🎵 **AI 必读**:命令成功后**必须**调 `control current` 拿到当前歌曲名/歌手,告知用户。**不要**直接展示 `--song-name` / `--singer-name` 参数——那只是客户端展示标签,与实际播放可能不一致。
135
+
134
136
  **输出示例**:
135
137
  ```json
136
138
  {"code":0,"data":{"accepted":true}}
@@ -140,7 +142,7 @@ kugou-cli control play --mix-song-id 32100650 --mode "append_queue"
140
142
 
141
143
  ## 5. player — 播放器控制
142
144
 
143
- 发送传输控制动作到播放器(播放/暂停/切歌等)。对应 `POST /v1/player/control`。
145
+ 发送传输控制动作到播放器(播放/暂停/切歌等)。
144
146
 
145
147
  ```bash
146
148
  kugou-cli control player --action pause
@@ -156,6 +158,8 @@ kugou-cli control player --action resume
156
158
 
157
159
  `prev` 和 `previous` 视为同义词。
158
160
 
161
+ > 🎵 **AI 必读**:使用 `next` / `prev` / `previous` **切歌后**必须调 `control current` 拿到当前歌曲名/歌手,告知用户。`play` / `pause` / `resume` / `toggle` / `stop` 等切换播放状态的动作不需要告知曲目(曲目未变)。
162
+
159
163
  **输出示例**:
160
164
  ```json
161
165
  {"code":0,"data":{"accepted":true}}
@@ -165,7 +169,7 @@ kugou-cli control player --action resume
165
169
 
166
170
  ## 5.1 continue-play — 拉取另一设备续播列表并播放
167
171
 
168
- 拉取云端"另一设备最近播放"的续播列表(酷狗首页的"续接播放"入口),并在本地客户端开始播放。对应 `POST /v1/player/continue_play`。
172
+ 拉取云端"另一设备最近播放"的续播列表(酷狗首页的"续接播放"入口),并在本地客户端开始播放。
169
173
 
170
174
  ```bash
171
175
  # 默认:替换当前队列,从头播放
@@ -184,6 +188,8 @@ kugou-cli control continue-play --mode next_play
184
188
  |------|------|
185
189
  | `--mode` | 队列策略:空(默认,替换队列)/ `append_queue`(追加队列尾部)/ `next_play`(下一首播放) |
186
190
 
191
+ > 🎵 **AI 必读**:命令成功后**必须**调 `control current` 拿到当前歌曲名/歌手,告知用户。
192
+
187
193
  **前置条件**:
188
194
  - 已登录:`kugou-cli auth login`
189
195
  - 客户端内已登录(否则返回 409/4091"login required",见错误场景 §2)
@@ -198,7 +204,7 @@ kugou-cli control continue-play --mode next_play
198
204
 
199
205
  ## 6. seek — 进度控制
200
206
 
201
- 控制当前播放歌曲的进度。对应 `POST /v1/player/seek`。
207
+ 控制当前播放歌曲的进度。
202
208
 
203
209
  ```bash
204
210
  # 快进 30 秒
@@ -223,7 +229,7 @@ kugou-cli control seek --action set --position-ms 120000
223
229
 
224
230
  ## 7. volume — 音量控制
225
231
 
226
- 调整客户端音量或静音状态。对应 `POST /v1/player/volume`。
232
+ 调整客户端音量或静音状态。
227
233
 
228
234
  ```bash
229
235
  # 音量增加 5 格
@@ -257,7 +263,7 @@ kugou-cli control volume --action toggle_mute
257
263
 
258
264
  ## 8. favorite song — 收藏歌曲
259
265
 
260
- 收藏或取消收藏一首歌曲。对应 `POST /v1/favorite`(target_type=song)。
266
+ 收藏或取消收藏一首歌曲。
261
267
 
262
268
  ```bash
263
269
  # 收藏歌曲
@@ -280,7 +286,7 @@ kugou-cli control favorite song --action remove --mixsongid 32100650
280
286
 
281
287
  ## 9. favorite songlist — 收藏歌单
282
288
 
283
- 收藏或取消收藏一个歌单。对应 `POST /v1/favorite`(target_type=songlist)。
289
+ 收藏或取消收藏一个歌单。
284
290
 
285
291
  ```bash
286
292
  # 收藏歌单(action=add 时必填 --list-name 与 --owner-user-id)
@@ -313,7 +319,7 @@ kugou-cli control favorite songlist --action remove --global-collection-id abcde
313
319
 
314
320
  > ✅ **创建歌单的首选路径**。Agent 在用户同意创建歌单时**必须**先尝试本命令;只有当客户端不可用(Linux / 客户端未运行 / 握手失败 / 调用失败)时才回退到云端备选 [`music create-playlist`](./music.md#71-接口说明云端备选仅在-70-第-4-条任一条件成立时使用)。完整决策逻辑见 [music.md §7 创建歌单](./music.md#7-创建歌单)。
315
321
 
316
- 在本地客户端创建一个新歌单,并可选地添加歌曲。对应 `POST /v1/songlist/create`。
322
+ 在本地客户端创建一个新歌单,并可选地添加歌曲。
317
323
 
318
324
  ```bash
319
325
  kugou-cli control playlist create --name "周杰伦精选" --mixsongids "32100650,32068120"
@@ -381,7 +387,7 @@ kugou-cli control play-playlist --global-id "<global_id>" --playlist-mode append
381
387
 
382
388
  ## 11. open — 打开客户端页面
383
389
 
384
- 在酷狗客户端中打开指定页面(非静默,客户端主窗口会切换到对应视图)。对应 `POST /v1/open`。`silent` 字段硬编码为 `false`。
390
+ 在酷狗客户端中打开指定页面(非静默,客户端主窗口会切换到对应视图)。`silent` 字段硬编码为 `false`。
385
391
 
386
392
  ```bash
387
393
  # 打开主界面
@@ -456,28 +462,12 @@ kugou-cli control play-playlist --global-id "..." --playlist-mode next_play
456
462
  | `append_queue` | `"append_queue"` | 歌单追加到播放队列尾部,不打断当前播放 | 不打断当前歌曲,排队播放 |
457
463
  | `next_play` | `"next_play"` | 歌单插入到当前曲目之后立即播放,后续队列顺延 | 听完这首就想听歌单 |
458
464
 
459
- **请求协议**:
460
-
461
- 1. CLI 组装一次请求体,仅含 `list_gid`(默认模式不含 `play_mode`):
462
- ```json
463
- { "list_gid": "collection_3_938985631_304_0" }
464
- ```
465
- 2. `POST /v1/player/play` 单次请求发给本地客户端。该接口为**异步**:本地客户端在收到请求后联网拉歌单歌曲,待拉取完成后才回复 HTTP 响应。CLI 端无需等待联网。
466
- 3. 失败(HTTP 非 200 或传输错误)→ stderr 报错并 exit 1。**HTTP 状态码与 body 子码区分**:
467
- - HTTP 状态码(如 `400` / `500`):CLI 打印 `HTTP <code>` 到 stderr
468
- - 响应 body 的 `code` 子码(如 `4000` / `5001`):CLI 透传 body 到 stdout,由调用方解析;CLI 自身只判断 HTTP 状态
469
- - 常见场景:
470
- - `HTTP 400`(body 可能含 `code: 4000` `missing songs`):客户端未传 `list_gid` 也没传 `songs`(CLI 几乎不会触发)
471
- - `HTTP 500`(body 可能含 `code: 5001`):客户端拉歌单失败(网络/歌单不存在/内容为空/能力不可用)
472
- - 其它 5xx:客户端拒绝,错误信息原样输出到 stderr
473
-
474
- > **无数量上限**:本命令对 `list_gid` 没有大小限制,由客户端协议层自行分页。超大歌单若被客户端拒绝,错误原样输出到 stderr。
465
+ > 🎵 **AI 必读**:命令成功后**必须**调 `control current` 拿到当前歌曲名/歌手,告知用户。本命令是异步的——客户端拉歌单歌曲可能要等几秒;如 `control current` 一开始返回 `code: 非 0`,等 1-2 秒再试一次。
475
466
 
476
467
  **前置条件**:
477
468
 
478
469
  - 已登录:`kugou-cli auth login`
479
470
  - 酷狗桌面客户端在后台运行,且握手健康:`kugou-cli control start`
480
- - **不需要联网**:歌单内容由本地客户端在响应 `POST /v1/player/play` 后异步拉取(只要客户端本身能访问外网即可)
481
471
 
482
472
  **典型联动**:
483
473
 
@@ -667,6 +657,63 @@ music search "歌手" → 提取 mix_song_id → control play --mixsongid <i
667
657
 
668
658
  ---
669
659
 
660
+ ## 13. Client Detection (`control detect`)
661
+
662
+ > **零副作用探测**,**不启动客户端、不抢焦点**——和 `control start` 不同,本命令只读 OS 端的"URL scheme 注册"等信号。
663
+
664
+ ### 用法
665
+
666
+ ```bash
667
+ kugou-cli control detect # 默认 JSON 输出
668
+ kugou-cli control detect --json=false # 人类可读一行
669
+ ```
670
+
671
+ ### 退出码(Agent 编程消费)
672
+
673
+ | 退出码 | 含义 |
674
+ |---|---|
675
+ | `0` | 客户端已安装(`installed: true`) |
676
+ | `1` | 探测过程出错(系统权限等) |
677
+ | `2` | 客户端没装(`installed: false`) |
678
+
679
+ > Linux/BSD 上 `installed: false` 但 `error: ""` —— 不支持是正常情况,不是错误。
680
+
681
+ ### JSON 输出示例(Windows,有客户端)
682
+
683
+ ```json
684
+ {
685
+ "installed": true,
686
+ "scheme_registered": true,
687
+ "scheme": "kugou",
688
+ "exe_path": "C:\\Program Files\\KuGou\\KGMusic\\KuGou.exe",
689
+ "version": "20.1.40.27866",
690
+ "handshake_exists": true,
691
+ "handshake_path": "C:\\Users\\alice\\.config\\kugou-cli\\handshake.json",
692
+ "platform": "windows",
693
+ "checked_at": "2026-08-11T15:25:01+08:00",
694
+ "strategies": {
695
+ "scheme_registry": {"ok": true, "evidence": "HKCR\\kugou\\shell\\open\\command -> ..."},
696
+ "install_path_scan": {"ok": true, "evidence": "C:\\Program Files\\KuGou\\KGMusic\\KuGou.exe exists"},
697
+ "handshake_file": {"ok": true, "evidence": "...handshake.json present"}
698
+ }
699
+ }
700
+ ```
701
+
702
+ ### 与 `control start` 的区别
703
+
704
+ | 维度 | `control detect` | `control start` |
705
+ |---|---|---|
706
+ | 副作用 | **零**(只读 OS 信号) | 会启动客户端 + 抢焦点 |
707
+ | 触发客户端启动? | ❌ | ✅(若握手文件不存在) |
708
+
709
+ ### 在 AI 工作流里的位置
710
+
711
+ 详见 [SKILL.md §5](../SKILL.md) —— **首次**要向用户展示歌曲列表/歌单列表前探测一次,记下 `client_available`;后续展示复用本次结果。
712
+
713
+ `control detect` **不**替代 `control start` —— 后者仍负责建立 handshake + 启动客户端,是 `control play` 等命令的前置。
714
+
715
+ ---
716
+
670
717
  ## 相关文档
671
718
 
672
719
  - [references/output-format.md](./output-format.md) — 输出格式与展示规范
@@ -1,11 +1,7 @@
1
1
  # 错误处理
2
2
 
3
- 错误信息输出到 stderr,程序 exit code 1:
4
-
5
- ```bash
6
- kugou-cli music search "xxx" 2>&1
7
- echo $? # 非 0 表示出错
8
- ```
3
+ > **判定优先级**:退出码(非 0 = 失败)→ stdout body 的 `errcode` 字段 → stderr 文案。
4
+ > Agent **不应依赖 stderr 文案字面量**判断错误类型——文案可能随版本变化;以退出码和下表为准。
9
5
 
10
6
  ---
11
7
 
@@ -399,8 +399,8 @@ kugou-cli music search-playlist "钢琴" --filter 2 # 只搜非 UGC
399
399
  - `list_id`: 歌单 ID(数字 string)
400
400
  - `global_id`: 全局歌单 ID(字符串,跨客户端兼容的稳定标识)
401
401
  - `name`: 歌单名
402
- - `creator_id`: 创建者用户 ID(字符串)
403
- - `creator_name`: 创建者昵称
402
+ - `creator_id`: 创建人用户 ID(字符串)
403
+ - `creator_name`: 创建人昵称
404
404
  - `intro`: 歌单简介
405
405
  - `song_list_url`: 歌单链接(H5),格式 `https://m.kugou.com/songlist/gcid_{encoded(global_id)}`;`global_id` 为空时返回空字符串
406
406
 
@@ -468,7 +468,7 @@ kugou-cli music recommend-playlist --module-id 6 # 我-最近播放-歌单下
468
468
  **关键字段(list[])**:
469
469
  - 与歌单搜索([第 8 章](#8-搜索歌单))共用同一套 `PlaylistInfo` 基础字段(`list_id` / `global_id` / `name` / `creator_id` / `creator_name` / `intro` / `song_list_url`),调用方可使用同一套反序列化逻辑
470
470
  - 已登录时上游根据 userid 做个性化推荐;未登录时可能返回空数据或通用推荐
471
- - 上游可能附带 `cache` 等字段,CLI 不解析、不保证
471
+ - 上游可能附带 `cache` 等额外字段,**未在 `PlaylistInfo` 中列出的字段请勿依赖**
472
472
 
473
473
  ---
474
474
 
@@ -25,13 +25,108 @@
25
25
 
26
26
  向用户展示结果时,**必须遵循以下规范**:
27
27
 
28
- ### 1. 歌曲列表展示(强制要求)
28
+ ### 1. 歌曲/歌单列表展示(批量优先用表格)
29
29
 
30
- - **禁止**只返回歌曲名、歌手名
31
- - **必须**以 Markdown 链接格式展示播放链接
32
- - 正确格式:`[歌曲名 - 歌手名](https://www.kugou.com/...)`
33
- - 禁止格式:`晴天 - 周杰伦`(无链接)、`歌曲名: 晴天, 歌手: 周杰伦`(无链接)
34
- - **仅适用于 `music` 命令返回的歌曲列表**;`control` 操作响应(如 play / favorite)没有 play_link,按 control 协议原样展示即可
30
+ > **强制规则**:结果 ≥ 2 条 → 表格;结果 = 1 条 → 单行链接(按客户端可用性决定是否加链接)。
31
+
32
+ #### 1.1 客户端可用性探测(前置条件)
33
+
34
+ **首次**要向用户展示歌曲列表、歌单列表或歌单内歌曲列表之前,**必须**先探测本机是否有可用的酷狗客户端(详见 [SKILL.md#5-首次要展示歌曲歌单前探测本机客户端可用性](../SKILL.md)):
35
+
36
+ ```bash
37
+ kugou-cli control detect
38
+ ```
39
+
40
+ 根据退出码记下 `client_available`:
41
+
42
+ | 退出码 | 含义 | `client_available` |
43
+ |---|---|---|
44
+ | `0` | 已安装 | `true` |
45
+ | `1` | 探测出错(注册表权限等) | `false`(按没客户端处理) |
46
+ | `2` | 没装客户端 | `false` |
47
+
48
+ **会话内只探测一次**,后续展示复用本次结果。`control detect` 是零副作用探测,不会启动客户端、不会抢焦点。
49
+
50
+ #### 1.2 规则总览
51
+
52
+ | 结果条数 | 展示形式 | 客户端可用? | 歌曲名/歌单名是否加链接 |
53
+ |---|---|---|---|
54
+ | **≥ 2** | Markdown 表格(**必须**) | 无关 | **一律不加**(保持列宽整洁) |
55
+ | **= 1** | 单行 Markdown 链接 | 是 | **不加**(可直接走 `control play`) |
56
+ | **= 1** | 单行 Markdown 链接 | 否 | **必须加**(用户手动打开) |
57
+ | **= 0** | 自然语言提示 | 无关 | 不适用 |
58
+
59
+ #### 1.3 表格格式(结果 ≥ 2 条)
60
+
61
+ **歌曲列表**(来自 `search` / `recommend guess|similar|text` / `charts` / `favorites` / `recent` / `playlist-songs`):
62
+
63
+ ```markdown
64
+ | 序号 | 歌曲名 | 歌手 |
65
+ |------|--------|------|
66
+ | 1 | 晴天 | 周杰伦 |
67
+ | 2 | 七里香 | 周杰伦 |
68
+ | 3 | 稻香 | 周杰伦 |
69
+ ```
70
+
71
+ **歌单列表**(来自 `search-playlist` / `recommend-playlist`):
72
+
73
+ ```markdown
74
+ | 序号 | 歌单名 | 创建人昵称 |
75
+ |------|--------|------------|
76
+ | 1 | 周杰伦经典30首 | 酷狗小编 |
77
+ | 2 | 慢摇车载DJ | DJ阿圣 |
78
+ ```
79
+
80
+ **硬性规则**:
81
+
82
+ - 表格单元格里的歌曲名/歌单名**不加** Markdown 链接——加了会让列宽自适应 URL,可读性反而变差
83
+ - 表格里也不列 `play_link` / `song_list_url` / `mix_song_id` / `global_id`——这些字段是给后续 `control *` 命令用的,由 agent 内部持有,**不展示给用户**
84
+ - 序号从 1 开始连续递增
85
+ - 如果返回总条数 > 表格展示条数(例如 `search` 默认 20 条),**只展示实际返回的那部分**,不要截断也不要用省略号
86
+
87
+ #### 1.4 单条结果格式(结果 = 1 条)
88
+
89
+ **有客户端时**(`client_available = true`)—— 歌曲名/歌单名**不加链接**:
90
+
91
+ ```markdown
92
+ 晴天 - 周杰伦
93
+ ```
94
+
95
+ ```markdown
96
+ 周杰伦经典30首 —— 酷狗小编
97
+ ```
98
+
99
+ **无客户端时**(`client_available = false`)—— 歌曲名/歌单名**必须加链接**:
100
+
101
+ ```markdown
102
+ [晴天 - 周杰伦](https://www.kugou.com/mixsong/xxxx.html)
103
+ ```
104
+
105
+ ```markdown
106
+ [周杰伦经典30首](https://www.kugou.com/songlist/xxxx.html)
107
+ ```
108
+
109
+ #### 1.5 为什么表格不加链接?
110
+
111
+ - 表格的目标是**浏览/筛选**,不是立即跳转;用户在表格里通常要做的是"挑一首播放"或"挑一个歌单打开",而非"挨个点开"
112
+ - 加链接会让列宽按 URL 自适应,中文长字符串场景下整张表可读性急剧下降
113
+ - ID(`mix_song_id` / `global_id`)由 agent 内部持有,等用户明确说"播放第 3 首" / "打开第 2 个歌单"时再走 `control play` / `control play-playlist` 或浏览器跳转
114
+
115
+ #### 1.6 反例(禁止)
116
+
117
+ | 禁止 | 错误原因 |
118
+ |---|---|
119
+ | 表格里写 `[晴天](https://...)` 形式的可点击单元格 | 列宽爆炸、可读性差 |
120
+ | 表格里把 `play_link` / `global_id` 也单列出来 | ID 是 agent 内部数据,不该展示给用户 |
121
+ | 结果 ≥ 2 条却用列表式 `[歌名 - 歌手](link)` 堆叠 | 表格才是 ≥ 2 条的标准形式 |
122
+ | 单条结果(= 1)时仍用表格 | 杀鸡用牛刀,单行更直接 |
123
+ | 单条无客户端时不加链接 | 用户没有客户端可控制,必须给链接让用户手动打开 |
124
+ | 单条有客户端时仍加链接 | 既然有客户端可以直接 `control play`,加链接反而多余 |
125
+ | 不探测就硬性决定加不加链接 | 必须先 `control detect`,不能凭猜测 |
126
+
127
+ #### 1.7 control 操作响应不受本节约束
128
+
129
+ `control play` / `control favorite song` 等**操作响应**不包含 `play_link`,按 control 协议原始 JSON 字段原样展示即可(见 [references/control.md](./control.md))。本节规范只适用于 `music *` 命令返回的列表类结果。
35
130
 
36
131
  ### 2. 统计数据
37
132
 
@@ -12,9 +12,9 @@
12
12
 
13
13
  ---
14
14
 
15
- ## 工作机制
15
+ ## 启动时自动检查
16
16
 
17
- ### 1. 启动时检查
17
+ ### 1. 检查行为
18
18
 
19
19
  每次执行任意 `kugou-cli` 命令时,**后台异步**检查 npm registry 上的最新版本。
20
20
 
@@ -43,6 +43,7 @@ const skillDirs = [
43
43
  path.join(os.homedir(), '.openclaw', 'skills', 'kugou-skill'),
44
44
  path.join(os.homedir(), '.codex', 'skills', 'kugou-skill'),
45
45
  path.join(os.homedir(), '.workbuddy', 'skills', 'kugou-skill'),
46
+ path.join(os.homedir(), '.workbuddy', 'skills', 'kugou-skill__skillhub'),
46
47
  ];
47
48
 
48
49
  if (fs.existsSync(skillSrc)) {
@@ -52,6 +53,10 @@ if (fs.existsSync(skillSrc)) {
52
53
  // 只在 skills 目录存在时才复制,不创建目录
53
54
  const parentDir = path.dirname(skillDir);
54
55
  if (fs.existsSync(parentDir)) {
56
+ // __skillhub 子目录是 opt-in:仅在已存在时同步,绝不自动创建
57
+ if (path.basename(skillDir) === 'kugou-skill__skillhub' && !fs.existsSync(skillDir)) {
58
+ continue;
59
+ }
55
60
  try {
56
61
  if (!fs.existsSync(skillDir)) {
57
62
  fs.mkdirSync(skillDir, { recursive: true });