@sokeai/cli 1.0.73 → 1.0.75

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/scripts/build-binaries.sh +12 -0
  3. package/scripts/release.sh +50 -1
  4. package/skills/SKILL.md +1 -1
  5. package/skills/ai-coach-director/SKILL.md +379 -45
  6. package/skills/ai-coach-director/coaching/prompt-engineer/parts/part2-roles.md +8 -8
  7. package/skills/ai-coach-director/coaching/prompt-engineer/prompt-engineer.md +70 -43
  8. package/skills/ai-coach-director/platform/adapters/README.md +68 -0
  9. package/skills/ai-coach-director/platform/adapters/qclaw.md +67 -0
  10. package/skills/ai-coach-director/platform/adapters/workbuddy.md +45 -0
  11. package/skills/ai-coach-director/platform/adapters/wukong.md +70 -0
  12. package/skills/ai-coach-director/platform/adapters/zework.md +89 -0
  13. package/skills/ai-coach-director/platform/api-fallback.md +262 -0
  14. package/skills/ai-coach-director/platform/interaction.md +13 -10
  15. package/skills/ai-coach-director/platform/publish-gate.md +44 -0
  16. package/skills/ai-coach-director/platform/resource-finalizer.md +128 -0
  17. package/skills/ai-coach-director/platform/sync-engine.md +217 -90
  18. package/skills/ai-coach-director/references/env-check.md +46 -11
  19. package/skills/ai-coach-director/references/platform-api-pitfalls.md +15 -1
  20. package/skills/ai-coach-director/references/role-resource-matching.md +53 -16
  21. package/skills/ai-coach-director/references/verified-cli-cheatsheet.md +26 -12
  22. package/skills/soke-cli/345/256/211/350/243/205/346/214/207/345/215/227.md +45 -7
  23. package/skills/soke-course/soke-cli/345/256/211/350/243/205/346/214/207/345/215/227.md +44 -6
  24. package/skills/soke-exam-question-pool/SKILL.md +76 -45
  25. package/skills/soke-learning-map/soke-cli/345/256/211/350/243/205/346/214/207/345/215/227.md +45 -7
  26. package/skills/soke-task/SKILL.md +29 -9
  27. package/skills/ai-coach-director/.learnings/LEARNINGS.md +0 -71
@@ -0,0 +1,262 @@
1
+ # MentorAI REST API Fallback
2
+
3
+ > 内部规则文件。当 soke-cli 在目标平台不可用或受限时,降级为直接调用 MentorAI REST API 完成平台同步。
4
+ >
5
+ > soke-cli 本质是 MentorAI REST API 的命令行封装。本文件记录 API 的直接调用方式,作为跨平台兜底方案。
6
+
7
+ ## 使用条件
8
+
9
+ 以下任一情况触发 API fallback:
10
+ - soke-cli 未安装且无法安装(受限制的企业环境)
11
+ - soke-cli 执行持续失败(沙箱限制、权限问题)
12
+ - 平台不支持 CLI 执行(纯聊天/IM 环境)
13
+ - 用户明确要求使用 API 方式
14
+
15
+ ## API 基础信息
16
+
17
+ | 项目 | 值 |
18
+ |------|-----|
19
+ | Base URL | `https://api.soke.cn` |
20
+ | 认证方式 | Bearer Token(从 `soke-cli config show` 获取 `user_token`) |
21
+ | Content-Type | `application/json` |
22
+
23
+ ### 获取 Token
24
+
25
+ 若 soke-cli 可用(即使受限无法执行业务命令):
26
+ ```bash
27
+ soke-cli config show
28
+ # 提取 user_token 字段
29
+ ```
30
+
31
+ 若 soke-cli 完全不可用:引导用户从授客AI开放平台获取 API Token。
32
+
33
+ ## API 接口映射
34
+
35
+ soke-cli 命令与 REST API 的对应关系:
36
+
37
+ ### 场景创建 (Part1)
38
+
39
+ **CLI**: `soke-cli ai-training +create-scenario --request-file ./step1-create.json`
40
+
41
+ **API**:
42
+ ```
43
+ POST /api/v1/ai-training/scenarios
44
+ Headers:
45
+ Authorization: Bearer <token>
46
+ Content-Type: application/json
47
+ Body: step1-create.json 内容
48
+ ```
49
+
50
+ **关键字段**: `name`, `description`, `tags`, `key_points`, `language`
51
+
52
+ ### 场景查询
53
+
54
+ **CLI**: `soke-cli ai-training +get-scenario --scenario-id <id> --pretty`
55
+
56
+ **API**:
57
+ ```
58
+ GET /api/v1/ai-training/scenarios/<scenario_id>
59
+ Headers:
60
+ Authorization: Bearer <token>
61
+ ```
62
+
63
+ ### 场景更新 (Part2-5)
64
+
65
+ 每个 Part 对应一个 operations 文件 (`partN-operations.json`)。
66
+
67
+ **CLI**: `soke-cli ai-training +preview-scenario-update ...` → `soke-cli ai-training +apply-scenario-update ...`
68
+
69
+ **API** (两步合一):
70
+ ```
71
+ PATCH /api/v1/ai-training/scenarios/<scenario_id>
72
+ Headers:
73
+ Authorization: Bearer <token>
74
+ Content-Type: application/json
75
+ Body: operations JSON 内容
76
+ ```
77
+
78
+ > ⚠️ operations JSON 中的 `base_updated_at` 必须先通过 GET 查询获取最新平台状态,再填入。禁止使用过期的时间戳。
79
+
80
+ ### 角色头像列表
81
+
82
+ **CLI**: `soke-cli ai-training +list-role-avatars [--gender <gender>] [--age-group <age>]`
83
+
84
+ **API**:
85
+ ```
86
+ GET /api/v1/ai-training/role-avatars?gender=<gender>&age_group=<age>
87
+ Headers:
88
+ Authorization: Bearer <token>
89
+ ```
90
+
91
+ ### 角色语音列表
92
+
93
+ **CLI**: `soke-cli ai-training +list-role-voices [--gender <gender>] [--age-group <age>]`
94
+
95
+ **API**:
96
+ ```
97
+ GET /api/v1/ai-training/role-voices?gender=<gender>&age_group=<age>
98
+ Headers:
99
+ Authorization: Bearer <token>
100
+ ```
101
+
102
+ ### 场景发布
103
+
104
+ **CLI**: `soke-cli ai-training +publish-scenario --scenario-id <id> --version 1`
105
+
106
+ **API**:
107
+ ```
108
+ POST /api/v1/ai-training/scenarios/<scenario_id>/publish
109
+ Headers:
110
+ Authorization: Bearer <token>
111
+ Content-Type: application/json
112
+ Body: {"version": 1, "version_description": "CLI发布"}
113
+ ```
114
+
115
+ ## 资源匹配完整流程(头像 + 声音)
116
+
117
+ > ⚠️ **跨平台关键**:Avatar/voice 匹配在 soke-cli 可用时走 CLI(`role-resource-matching.md`),CLI 不可用时走本节的 REST API 路径。**禁止因 CLI 不可用直接跳过资源匹配**——这会导致角色上线后无头像无声音。
118
+
119
+ ### 匹配时机
120
+
121
+ Part2 完整内容已展示并由用户确认 → 立即执行资源匹配 → 将 avatar URL 与 voice_id 写入角色级 JSON → 逐个角色 PATCH/apply 并回读验证。整个过程不等待用户触发,也不向用户二次确认。与 CLI 路径的时机完全一致。
122
+
123
+ ### 步骤 1:获取 Token
124
+
125
+ ```bash
126
+ soke-cli config show 2>/dev/null | grep user_token
127
+ # 若 soke-cli 完全不可用,引导用户从授客AI开放平台获取
128
+ ```
129
+
130
+ ### 步骤 2:查询头像库
131
+
132
+ ```bash
133
+ # 一阶精准查询(性别+年龄)
134
+ curl -s -H "Authorization: Bearer $TOKEN" \
135
+ "https://api.soke.cn/api/v1/ai-training/role-avatars?gender=female&age_group=middle-aged&lang=zh"
136
+
137
+ # 降级:仅按性别
138
+ curl -s -H "Authorization: Bearer $TOKEN" \
139
+ "https://api.soke.cn/api/v1/ai-training/role-avatars?gender=female&lang=zh"
140
+
141
+ # 降级:无过滤全量
142
+ curl -s -H "Authorization: Bearer $TOKEN" \
143
+ "https://api.soke.cn/api/v1/ai-training/role-avatars?lang=zh"
144
+ ```
145
+
146
+ **返回字段**:`id`(资源 ID,不用于回填)、`url`(头像 CDN URL,**回填时用这个**)、`gender`、`age_group`、`sort`。
147
+
148
+ ### 步骤 3:查询语音库
149
+
150
+ ```bash
151
+ # 一阶精准查询
152
+ curl -s -H "Authorization: Bearer $TOKEN" \
153
+ "https://api.soke.cn/api/v1/ai-training/role-voices?gender=female&age_group=middle-aged&lang=zh"
154
+
155
+ # 降级链路同头像
156
+ ```
157
+
158
+ **返回字段**:`id`(语音资源 ID,**回填时用这个**)、`name`、`gender`、`age_group`、`sample_url`。
159
+
160
+ ### 步骤 4:特征匹配(与 CLI 路径相同的匹配规则)
161
+
162
+ 性别映射 → `../references/role-resource-matching.md`「性别映射表」
163
+ 年龄段映射 → `../references/role-resource-matching.md`「年龄段映射表」
164
+ 匹配优先级 → `../references/role-resource-matching.md` P0-P3 降级链路
165
+
166
+ ### 步骤 5:写入 avatar + voice_id 到角色级 JSON
167
+
168
+ > ⚠️ **必须随角色主体单次写入**,禁止先写角色再分两次补 avatar/voice_id(分开调用导致 updated_at 竞态,第二次可能覆盖第一次结果)。REST API 兜底路径如需 PATCH,也必须把 avatar 与 voice_id 放在同一个角色级操作里。
169
+
170
+ ```bash
171
+ # 1. 先获取最新 updated_at
172
+ curl -s -H "Authorization: Bearer $TOKEN" \
173
+ "https://api.soke.cn/api/v1/ai-training/scenarios/<scenario_id>" \
174
+ | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['data']['updated_at'])"
175
+
176
+ # 2. 写入含 avatar + voice_id 的角色级操作
177
+ curl -s -X PATCH \
178
+ -H "Authorization: Bearer $TOKEN" \
179
+ -H "Content-Type: application/json" \
180
+ -d '{
181
+ "operations": [
182
+ {
183
+ "type": "patch_ai_role",
184
+ "data": {
185
+ "scenario_role_id": "<角色ID>",
186
+ "patch": {
187
+ "role_data": {
188
+ "avatar": "<头像URL>",
189
+ "voice_id": "<语音ID>"
190
+ },
191
+ "customized_fields": ["avatar", "voice_id"]
192
+ }
193
+ }
194
+ }
195
+ ],
196
+ "base_updated_at": "<updated_at>",
197
+ "idempotency_key": "api-<scenario_short>-part2-resources",
198
+ "reason": "Part2: 头像声音资源匹配 (REST API)"
199
+ }' \
200
+ "https://api.soke.cn/api/v1/ai-training/scenarios/<scenario_id>"
201
+ ```
202
+
203
+ ### 步骤 6:强制验证
204
+
205
+ ```bash
206
+ curl -s -H "Authorization: Bearer $TOKEN" \
207
+ "https://api.soke.cn/api/v1/ai-training/scenarios/<scenario_id>" \
208
+ | python3 -c "
209
+ import sys, json
210
+ d = json.load(sys.stdin)
211
+ for r in d['data']['ai_roles']:
212
+ rd = r.get('role_data', {})
213
+ avatar = rd.get('avatar', '')
214
+ voice = rd.get('voice_id', '')
215
+ status = 'OK' if (avatar.startswith('http') and voice) else 'MISSING'
216
+ print(f'{r[\"name\"]}: avatar={avatar[:50]}... voice_id={voice} [{status}]')
217
+ "
218
+ # 期望输出:每个角色 avatar 以 https:// 开头,voice_id 非空
219
+ ```
220
+
221
+ ### 步骤 7:重试与降级
222
+
223
+ - 验证发现 avatar/voice_id 为空 → 重新 GET `updated_at` → 重试 1 次
224
+ - 重试仍失败 → 标注「⚠️ {角色名} 资源匹配未完成 (REST API)」,不阻断 Part3
225
+ - 头像/语音库 API 查询失败(网络/认证错误)→ 跳过资源匹配,标注「资源匹配未完成」
226
+
227
+ ## 执行规则
228
+
229
+ ### 安全规则
230
+
231
+ 1. **Token 安全**:`user_token` 只在内部使用,严禁写入对话窗口、JSON 文件或日志
232
+ 2. **请求验证**:每次 API 调用前,先 GET 获取最新 `updated_at`,避免并发冲突
233
+ 3. **错误处理**:4xx 检查字段格式 → 5xx 重试 1 次 → 仍失败则标注并记录
234
+
235
+ ### API fallback 执行流程
236
+
237
+ ```
238
+ 检测 soke-cli 不可用
239
+ → 获取 Token (soke-cli config show 或引导用户获取)
240
+ → 确认 Token 有效 (GET /api/v1/auth/verify)
241
+ → 按原管线顺序执行:
242
+ Part1: POST 创建场景 → 获取 scenario_id
243
+ Part2: 头像语音匹配(走「资源匹配完整流程」)→ PATCH 更新角色并回读
244
+ Part3: PATCH 更新流程
245
+ Part4: PATCH 更新评分
246
+ Part5: PATCH 更新教练设置
247
+ → Step 6: GET 验证同步完整性
248
+ → Step 7: 质量闸门
249
+ → Step 8: POST 发布场景
250
+ ```
251
+
252
+ ### 与 soke-cli 的差异
253
+
254
+ | 项目 | soke-cli | REST API fallback |
255
+ |------|----------|-------------------|
256
+ | preview 预览 | `+preview-scenario-update` 输出 diff | 无 preview,直接 PATCH(可在 PATCH 前 GET 对比) |
257
+ | 沙箱绕过 | `dangerouslyDisableSandbox: true` | 不适用(HTTP 请求不受沙箱限制) |
258
+ | 命令速查 | `verified-cli-cheatsheet.md` | 本文件 |
259
+ | 字段映射 | `sync-engine.md` 字段映射表 | 相同映射表,JSON 结构一致 |
260
+ | 头像语音查询 | CLI `+list-role-avatars/voices` | GET API 端点 |
261
+
262
+ > API fallback 路径下,JSON 文件结构、字段映射、自查清单与 soke-cli 路径完全一致。差异仅在传输方式:CLI 命令行 vs HTTP 请求。
@@ -26,7 +26,7 @@ AskUserQuestion(
26
26
  - 模糊匹配时优先正向操作(选项 1)
27
27
  -
28
28
  name: interaction
29
- description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用确认模板与微调模板。优先弹窗确认:WebChat 主会话用 render_ui QuestionForm,workbuddy 子 agent 用 AskUserQuestion,纯文本平台降级结构化文本。
29
+ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用确认模板与微调模板。跨平台适配:WorkBuddy AskUserQuestion/render_ui,悟空/QClaw/Zework 用结构化文本编号(统一路由到 platform/adapters/)。
30
30
  ---
31
31
 
32
32
  # 弹窗交互规则
@@ -46,9 +46,12 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
46
46
 
47
47
  1. **Part1 确认后强制同步到平台**:模板 1 不提供"取消"或"跳过同步"选项;用户确认即意味着场景必须创建到平台
48
48
  2. Part2-Part5 确认后自动 preview + apply CLI,立即进入下一个 Part,不等待用户二次确认
49
- 3. 调整/重设/微调分支由用户选择驱动,`prompt-engineer` / `prompt-optimizer` 按返回值分支处理
50
- 4. **优先使用弹窗确认**:弹窗策略按运行环境三分层——① WebChat 主会话:使用 `render_ui` QuestionForm jsonl(参考附录 A);② workbuddy 子 agent:使用 `AskUserQuestion` 工具弹窗(参考附录 A);③ 纯文本平台(群聊、IM 无按钮):降级为结构化文本确认。选项文案和分支路由三平台完全一致
51
- 5. **选项文案和分支路由不因渲染方式而变化**:渲染机制不同但选项名称和路由完全一致,用户始终只需点击按钮或回复编号做出选择
49
+ 3. Part1 封面生成/上传/修正属于后台自动处理步骤;Part2 头像/语音匹配、逐个保守写角色、回读校验也属于后台自动处理步骤。除非失败,不向用户展示过程细节
50
+ 4. Part2-Part5 默认优先走 `--request-file ./partX-update.json` 的完整请求模式;`--operations-file ./partX-operations.json` 仅作为排障/降级模式
51
+ 5. 若 Part3 按标准语义操作 apply 后回读仍为空,必须明确提示当前 CLI/平台版本限制,并引导改走 Web 管理后台补录流程步骤
52
+ 6. 调整/重设/微调分支由用户选择驱动,`prompt-engineer` / `prompt-optimizer` 按返回值分支处理
53
+ 7. **优先使用弹窗确认**:弹窗策略按运行环境自适应——① WorkBuddy:使用 `AskUserQuestion` 工具弹窗(参考附录 B);② WebChat 主会话:使用 `render_ui` 的 QuestionForm jsonl(参考附录 A);③ 悟空/QClaw/Zework:降级为结构化文本编号确认(参考 `adapters/` 对应平台适配器);④ 通用降级:纯文本编号。选项文案和分支路由所有平台完全一致
54
+ 8. **选项文案和分支路由不因渲染方式而变化**:渲染机制不同但选项名称和路由完全一致——WorkBuddy 弹窗按钮、悟空钉钉编号回复、QClaw 微信编号回复、Zework 纯文本编号,用户始终只需回复编号或完整选项文案做出选择
52
55
 
53
56
  ---
54
57
 
@@ -116,7 +119,7 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
116
119
 
117
120
  | # | 选项文案 | 分支动作 |
118
121
  |---|---------|---------|
119
- | 1 | 确认,同步角色(推荐) | 生成 `part2-operations.json` 自动 preview + apply 立即继续 Part3 |
122
+ | 1 | 确认,同步角色(推荐) | 完整展示 Part2 后,后台自动拆分 Part2 为多个角色级同步单元(角色1/角色2/角色3/整体OS),逐个保守写入并回读校验全部成功后继续 Part3 |
120
123
  | 2 | 调整角色设定 | 局部修改后重新用本模板确认 |
121
124
  | 3 | 重设角色设定 | 回到内容层重新生成 Part2,再次用本模板确认 |
122
125
 
@@ -134,7 +137,7 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
134
137
 
135
138
  | # | 选项文案 | 分支动作 |
136
139
  |---|---------|---------|
137
- | 1 | 确认,同步流程设置(推荐) | 生成 `part3-operations.json` → 自动 preview + apply → 立即继续 Part4 |
140
+ | 1 | 确认,同步流程设置(推荐) | 生成 `part3-operations.json` + `part3-update.json` 默认用 `--request-file ./part3-update.json` 自动 preview + apply → 立即继续 Part4;若回读仍为空则提示改走 Web 管理后台补录 |
138
141
  | 2 | 调整流程设置 | 局部修改后重新用本模板确认 |
139
142
  | 3 | 重设流程设置 | 回到内容层重新生成 Part3,再次用本模板确认 |
140
143
 
@@ -152,7 +155,7 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
152
155
 
153
156
  | # | 选项文案 | 分支动作 |
154
157
  |---|---------|---------|
155
- | 1 | 确认,同步评分(推荐) | 生成 `part4-operations.json` → 自动 preview + apply → 继续 Part5 |
158
+ | 1 | 确认,同步评分(推荐) | 生成 `part4-operations.json` + `part4-update.json` 默认用 `--request-file ./part4-update.json` 自动 preview + apply → 继续 Part5 |
156
159
  | 2 | 调整评分标准 | 局部修改后重新用本模板确认 |
157
160
  | 3 | 重设评分标准 | 回到内容层重新生成 Part4,再次用本模板确认 |
158
161
 
@@ -170,7 +173,7 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
170
173
 
171
174
  | # | 选项文案 | 分支动作 |
172
175
  |---|---------|---------|
173
- | 1 | 确认,完成创建(推荐) | 生成 `part5-operations.json` → 自动 preview + apply → 输出完成摘要 |
176
+ | 1 | 确认,完成创建(推荐) | 生成 `part5-operations.json` + `part5-update.json` 默认用 `--request-file ./part5-update.json` 自动 preview + apply → 进入资源完善与发布闸门 → 通过后才输出完成摘要 |
174
177
  | 2 | 调整教练设置 | 局部修改后重新用本模板确认 |
175
178
  | 3 | 重设教练设置 | 回到内容层重新生成 Part5,再次用本模板确认 |
176
179
 
@@ -188,7 +191,7 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
188
191
 
189
192
  | # | 选项文案 | 分支动作 |
190
193
  |---|---------|---------|
191
- | 1 | 确认修改(推荐) | 生成 `optimize-operations.json` → 执行 CLI 同步 |
194
+ | 1 | 确认修改(推荐) | 生成 `optimize-operations.json` + `optimize-update.json` 默认用 `--request-file ./optimize-update.json` 执行 CLI 同步 |
192
195
  | 2 | 保持原样 | 退出微调流程,记录决策到状态快照 |
193
196
  | 3 | 调整诊断 | 局部修改标签归属后重新用本模板确认 |
194
197
 
@@ -252,7 +255,7 @@ description: AI 陪练弹窗交互规则。定义按 Part1-Part5 拆分的通用
252
255
  ### 与 sync-engine.md 的边界
253
256
 
254
257
  - interaction.md:负责确认契约(问题和选项)、确认输出规范、用户响应后的分支路由
255
- - sync-engine.md:负责「确认后」的 JSON 生成、字段映射、CLI 命令拼接
258
+ - sync-engine.md:负责「确认后」的 JSON 生成、字段映射、CLI 命令拼接(默认 `partX-update.json`,排障时退回 `partX-operations.json`)
256
259
  - interaction 确认后 → 调用 sync-engine 对应模板 → 执行 CLI → 返回结果
257
260
 
258
261
  ---
@@ -0,0 +1,44 @@
1
+ # 发布闸门(publish-gate)
2
+
3
+ > 内部规则文件。负责在发布前统一做结构验收、资源验收和平台限制说明。
4
+
5
+ ## 发布前检查清单
6
+
7
+ ### 结构验收
8
+ - Part1 基础字段存在:`name/description/tags/key_points/scene_lang/scenario_cover`
9
+ - Part2 角色回读正常:无 `角色数据异常`
10
+ - Part4 评分配置存在:`scoring_criteria_config.criteria_data.dimensions` 非空
11
+ - Part5 固定配置有效
12
+
13
+ ### 资源验收
14
+ - `scenario_cover` 非默认图
15
+ - 每个角色 `avatar` 非空 URL
16
+ - 每个角色 `voice_id` 非空 ID
17
+
18
+ ### 平台限制说明
19
+ - 若 `conversation_steps` 回读为空,标记:`需后台手动补录流程步骤`
20
+ - 该项默认不阻断发布,但必须进入最终交付摘要
21
+
22
+ ## 阻断规则
23
+
24
+ 以下情况任一成立,禁止发布:
25
+ - 默认封面未替换
26
+ - 任一角色头像为空
27
+ - 任一角色声音为空
28
+ - 任一角色回读为 `角色数据异常`
29
+ - 评分标准为空
30
+
31
+ ## 输出要求
32
+
33
+ ### 可发布
34
+ 输出:
35
+ - `publish_ready = true`
36
+ - 可执行 `soke-cli ai-training +publish-scenario`
37
+
38
+ ### 不可发布
39
+ 输出缺口清单,例如:
40
+ - 封面未补齐
41
+ - 角色何女士缺少 voice_id
42
+ - 角色陆先生缺少 avatar
43
+
44
+ 并停止发布。
@@ -0,0 +1,128 @@
1
+ # 资源完善器(resource-finalizer)
2
+
3
+ > 内部规则文件。作为**最后兜底补救**,仅在 Part1/Part2 的主流程未能写入真实封面/头像/声音时触发。
4
+ > 正常流程下,封面在 Part1 确定、头像和声音在 Part2 与角色一起写入,不需要进入本模块。
5
+ > 本模块默认后台执行,除非修复失败,不向用户暴露执行细节。
6
+ > ⚠️ 本地生成或复用的封面/图片均为后台资源,不得在前台展示图片预览,不得主动输出本地图片路径。只有用户明确要求查看/预览/导出图片时,才可提供路径或展示。
7
+
8
+ ## 目标
9
+
10
+ 避免以下半成品状态进入发布:
11
+ - `scenario_cover` 仍为默认封面或为空
12
+ - 任一角色 `avatar` 为空
13
+ - 任一角色 `voice_id` 为空
14
+
15
+ ## 执行时机
16
+
17
+ 仅在发布闸门检测到资源缺口,且无法通过主流程自动补齐时触发。正常流程默认不进入本模块。
18
+
19
+ ```
20
+ Part1-Part5 主体完成
21
+ → resource-finalizer
22
+ → cover check / fix
23
+ → avatar check / fix
24
+ → voice check / fix
25
+ → resource gate
26
+ → 通过后才允许 publish
27
+ ```
28
+
29
+ ## 资源闸门
30
+
31
+ ### Cover Gate
32
+ 以下任一情况判定为未完成:
33
+ - `scenario_cover` 为空
34
+ - `scenario_cover` 为 `null`
35
+ - URL 包含 `default.png`
36
+
37
+ ### Avatar Gate
38
+ 对每个角色检查:
39
+ - `role_data.avatar` 必须为非空 URL(以 `http` 开头)
40
+
41
+ ### Voice Gate
42
+ 对每个角色检查:
43
+ - `role_data.voice_id` 必须为非空 ID
44
+
45
+ ### Role Integrity Gate
46
+ 对每个角色检查:
47
+ - `role_data.name` 不能等于 `角色数据异常`
48
+ - `role_data.background` 非空
49
+
50
+ ## 封面补齐规则
51
+
52
+ ### 标准流程
53
+ 1. 检查 `scenario_cover` 是否为默认图或为空
54
+ 2. 若是,按以下优先级补齐:
55
+
56
+ **优先级 0:默认固定封面回填**
57
+ - 默认使用:`https://newsokeeditorcdn.soke.cn/public/ai/cover/lingshou_daogou.png`
58
+ - 直接用 `update_basic.scenario_cover` 回填该真实 URL
59
+ - `get-scenario` 验证不再为空且为该固定封面
60
+
61
+ **优先级 1:从平台图片库/已有真实封面库择图**
62
+ - 若业务明确要求替换默认图,再按行业、业务环节、场景气质筛选图片库素材
63
+ - 若当前环境只有场景封面库能力,则执行 `soke-cli ai-training +list-scenarios --page 1 --page-size 50 --status published --pretty`
64
+ - 从结果中筛出非 `default.png` 的 `scenario_cover`,选择与当前场景最匹配的一条
65
+ - 使用 `update_basic.scenario_cover` 回填该真实 URL
66
+ - `get-scenario` 验证不再为空且非默认图
67
+
68
+ **优先级 2:复用工作区已有本地封面文件**
69
+ - 按顺序检查:`./scenario-cover.png` → `./scenario-cover.jpg` → `./cover.png` → `./cover.jpg`
70
+ - 若存在,执行 `soke-cli ai-training +upload-scenario-cover --file <本地文件> --pretty`
71
+ - 使用 `update_basic.scenario_cover` 回填真实 CDN URL
72
+ - `get-scenario` 验证不再是默认图
73
+
74
+ **优先级 3:本地生成封面**
75
+ - 仅当默认图、平台图库/封面库和本地现成图都不可用时,再生成本地封面图 `scenario-cover.png`
76
+ - 生成后仅做后台内部检查,不调用前台图片预览,不向用户展示图片
77
+ - 执行 `soke-cli ai-training +upload-scenario-cover --file ./scenario-cover.png --pretty`
78
+ - 使用 `update_basic.scenario_cover` 回填真实 CDN URL
79
+ - `get-scenario` 验证不再是默认图
80
+ - 若上传失败、未拿到真实 CDN URL、或平台回读仍为空/默认图,则视为“封面未补齐”,禁止发布,不得把“本地已生成文件”误判为已完成
81
+
82
+ **优先级 3:最终兜底**
83
+ 若以上均不可行:
84
+ - 标注 `cover_pending`
85
+ - 禁止发布
86
+ - 在交付摘要中提醒用户手动补封面
87
+
88
+ ### 失败处理
89
+ - 上传失败或平台图库不可用 → 降级到下一优先级
90
+ - 全部降级链路失败 → 标注 `cover_pending`,禁止发布
91
+
92
+ ## 头像补齐规则
93
+
94
+ ### 标准流程
95
+ 1. 对每个角色检查 `avatar`
96
+ 2. 若为空,按 `../references/role-resource-matching.md` 查询头像库并匹配
97
+ 3. 用 `patch_ai_role` 回填 `avatar`
98
+ 4. `get-scenario` 验证头像非空 URL
99
+
100
+ ### 失败处理
101
+ - 查询失败或回填失败 → 标注 `avatar_pending`,禁止发布
102
+
103
+ ## 语音补齐规则
104
+
105
+ ### 标准流程
106
+ 1. 对每个角色检查 `voice_id`
107
+ 2. 若为空,按 `../references/role-resource-matching.md` 查询语音库并匹配
108
+ 3. 用 `patch_ai_role` 回填 `voice_id`
109
+ 4. `get-scenario` 验证语音非空
110
+
111
+ ### 失败处理
112
+ - 查询失败或回填失败 → 标注 `voice_pending`,禁止发布
113
+
114
+ ## 默认回填策略
115
+
116
+ - 头像和语音允许逐个角色回填
117
+ - 若资源库查询结果不足,可使用保守默认资源
118
+ - **宁可回填一套保守默认资源,也不要留空进入发布**
119
+
120
+ ## 发布前最终判定
121
+
122
+ 只有以下全部满足时,才允许执行 `+publish-scenario`:
123
+ - 封面非默认图
124
+ - 所有角色头像非空 URL
125
+ - 所有角色声音非空 ID
126
+ - 无“角色数据异常”
127
+
128
+ 否则输出缺口清单并停止在发布前。