@sokeai/cli 1.0.64 → 1.0.66

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.
@@ -1,507 +1,400 @@
1
1
  ---
2
2
  name: soke-course
3
- summary: 授客学堂课程管理(课程创建/更新/发布/查询),集成素材库和课件管理子 skills,完整管理课程生命周期
4
- version: 4.0.0
5
- description: "授客学堂课程管理:完整的课程生命周期管理,包括创建课程分类、上传文件(素材)、创建课件、创建课程、指派部门/学员、查询学员学习状态的全链路流程。集成 soke-material(素材库管理)、soke-lesson(课件管理)、soke-assign(指派管理)子 skills。当用户需要创建课程、上传课件、指派学员、查询学习进度时使用。"
6
- metadata:
7
- requires:
8
- bins: ["soke-cli"]
9
- skills: ["soke-material", "soke-lesson", "soke-assign"]
10
- cliHelp: "soke-cli course --help"
3
+ version: 5.0.0
4
+ description: >
5
+ 线上课创建与发布的端到端编排技能,课程发布主管。
6
+ 负责识别用户意图、选择执行流程、校验前置条件、调度 3 个并列技能完成全链路操作。
7
+ 当用户想创建课程、上传课件、配置设置、发布课程、指派学员时触发。
8
+ author: Soke Team
9
+ tags: [课程管理, 流程编排, 发布管理]
11
10
  ---
12
11
 
13
- # 课程管理 (soke-course)
12
+ # 课程发布主管
14
13
 
15
- **CRITICAL — 开始前 MUST 先用 Read 工具读取 [`./soke-cli安装指南.md`](./soke-cli安装指南.md),其中包含认证、配置、权限处理**
14
+ > **CRITICAL — 开始前 MUST 先用 Read 工具读取 [`./soke-cli安装指南.md`](./soke-cli安装指南.md),其中包含认证、配置、权限处理。**
16
15
 
17
- ## 使用前提
18
-
19
- 1. 已安装 `soke-cli`
20
- 2. 已登录授权: `soke-cli auth login`
21
-
22
- ```bash
23
- soke-cli auth login
24
- soke-cli config show # 验证登录状态
25
- ```
16
+ ## 交互规范(必须遵守)
26
17
 
27
- ## 端到端工作流
18
+ **任何需要用户从固定选项中做选择的场景,必须调用 `ask_user_question` 工具弹窗,禁止纯文本罗列让用户打字。**
28
19
 
29
- 完整创建一门可学习的课程需要以下步骤:
20
+ 适用场景:
21
+ - 选择课程分类(列出所有分类,最后一项为"🆕 新建分类")
22
+ - 歧义消解(不确定用户想做什么时)
23
+ - 确认是否继续("还要加课件吗?"/"调顺序吗?"/"确认发布?")
24
+ - 选择发布对象(部门/用户列表)
25
+ - 中断恢复(从已有课程列表中选择继续哪个)
26
+ - 任何其他有 2-4 个固定选项的决策点
30
27
 
28
+ 弹窗标准格式:
31
29
  ```
32
- ┌──────────────────────────────────────────────────────────────────┐
33
- │ 1. 查询课程分类 → 获取 category-id │
34
- │ 2. 创建课程 → 获取 course-id │
35
- │ 3. 上传素材 → 获取 media-id + 所有文件信息 │
36
- 4. 创建课件 → 关联素材到课程 (至少 1 个) │
37
- 5. (可选)更新课程 补充描述等 │
38
- 6. 发布课程 → 学员可见 │
39
- │ 7. (可选)指派 → 分配给部门/学员 → 学员开始学习 │
40
- │ 8. 查询学习状态 → 查看学员进度/完成率 │
41
- └──────────────────────────────────────────────────────────────────┘
30
+ ask_user_question
31
+ question: "选择课程分类"
32
+ header: "分类"
33
+ options:
34
+ - label: "📁 技术研发" description: "一级分类"
35
+ - label: "📁 企业管理" description: "一级分类"
36
+ - label: "🆕 新建分类" description: "前往管理后台新建分类"
42
37
  ```
43
38
 
44
- ### 数据流转图
45
-
46
- ```
47
- 分类查询 素材上传 (file +upload)
48
- │ │
49
- ▼ ▼
50
- category-id media-id, filename, filesize, object, ext, type
51
- │ │
52
- ▼ ▼
53
- 创建课程 ──→ course-id ──→ 创建课件 (course +lesson-create) ──→ lesson-id
54
-
55
-
56
- 发布课程 ◄── 课件数量 ≥ 1
57
-
58
-
59
- 指派给学员 ◄── assign +create (可选)
60
-
61
-
62
- 学员可开始学习
63
-
64
-
65
- 查询学习记录/进度
66
- ```
67
-
68
- ---
39
+ ## 使用前提
69
40
 
70
- ## 步骤1: 查询课程分类
41
+ 1. 已安装 `soke-cli`
42
+ 2. 已登录授权 — 首次执行时自动检查并引导登录
71
43
 
72
- 创建课程前必须先获取分类 ID。
44
+ **登录状态检查与自动登录(必须执行):**
73
45
 
74
46
  ```bash
75
- soke-cli course +list-categories --page 1 --page-size 100
76
-
77
- # JSON 输出供解析:
78
- soke-cli course +list-categories --format json
47
+ # 第一步:检查登录状态
48
+ soke-cli config show
79
49
  ```
80
50
 
81
- **响应关键字段**:
82
- - `data.list[].uuid` → 分类 ID(创建课程时传入 `--category-id`)
83
- - `data.list[].title` → 分类名称
84
- - `data.list[].parent_id` → 父分类 ID
51
+ 若返回包含 `user_token` → ✅ 已登录,继续。
85
52
 
86
- ---
87
-
88
- ## 步骤2: 创建课程
53
+ 若返回无 `user_token` 或报错 → ⚠️ 未登录,立即执行:
89
54
 
90
55
  ```bash
91
- soke-cli course +create \
92
- --title "课程标题" \
93
- --category-id "CATEGORY-UUID" \
94
- --description "课程描述(可选)"
95
-
96
- # JSON 输出:
97
- soke-cli course +create --title "标题" --category-id "CATEGORY-UUID" --format json
56
+ # 第二步:自动打开浏览器完成 OAuth 授权
57
+ # soke-cli auth login 会自动调用系统默认浏览器打开授权页面
58
+ soke-cli auth login
98
59
  ```
99
60
 
100
- **参数**:
101
- | 参数 | 必填 | 说明 |
102
- |------|------|------|
103
- | `--title` | 是 | 课程标题 |
104
- | `--category-id` | 是 | 分类 ID(从步骤1获取) |
105
- | `--description` | 否 | 课程描述 |
61
+ `soke-cli auth login` 执行后会自动打开浏览器到授客AI开放平台授权页,用户在浏览器中完成登录授权即可。授权成功后 CLI 终端会显示 `✅ 已登录`,Token 自动保存至 `~/.soke-cli/config.json`。
106
62
 
107
- **响应提取**: `data.uuid` → 课程 ID (`course-id`)
63
+ > 如果浏览器没有自动打开,终端会输出授权链接,手动复制到浏览器打开即可完成授权。
108
64
 
109
- ---
65
+ **任何课程操作之前,必须先通过上述两步确认登录状态。未登录时禁止跳过,必须完成登录后再继续。**
110
66
 
111
- ## 步骤3: 上传素材文件
67
+ ## 一、触发描述
112
68
 
113
- > 详见 [`../soke-material/SKILL.md`](../soke-material/SKILL.md)
69
+ ### 触发词
114
70
 
115
- ```bash
116
- # 自动检测文件类型和时长
117
- soke-cli file +upload --file "./video.mp4"
71
+ | 意图 | 触发词 |
72
+ |------|--------|
73
+ | 创建课程 | 创建/新建/做课/开课/生成课程 |
74
+ | 课件管理 | 添加课件/加视频/加音频/加文档/课件排序/调顺序 |
75
+ | 课程设置 | 设置学分/积分/讲师/封面/标签/修改分类/简介 |
76
+ | 高级设置 | 倍速/人脸/提醒/学习模式/解锁/评价/证书/签名/钉钉群 |
77
+ | 收费设置 | 收费/价格/试看/免费/付费 |
78
+ | 发布 | 发布/上线/定时发布/审批 |
79
+ | 指派 | 指派/安排学习/分配学员/必修/选修 |
80
+ | 查询 | 学习进度/完成率/谁学了/谁完成 |
81
+ | 维护 | 关闭/删除/下架/复制/克隆 |
82
+ | 分类管理 | 分类/课程分类/添加分类/新建分类 |
118
83
 
119
- # 指定类型和时长
120
- soke-cli file +upload --file "./audio.mp3" --type audio --length 236
84
+ ### 上下文触发
85
+ - 对话已有 course-id 在当前课程上操作,不创建新课程
86
+ - 用户上传文件 + 提"课件"/"课程" → 课件子流程
121
87
 
122
- # JSON 输出
123
- soke-cli file +upload --file "./video.mp4" --format json
124
- ```
88
+ ### 不触发(交给独立 skill)
89
+ - 纯考试/题库/试卷
90
+ - 学习地图
91
+ - 纯素材浏览(不提课程)
92
+ - 单查学员档案(无课程上下文)
125
93
 
126
- **响应关键字段(全部用于步骤4创建课件)**:
127
- | 字段 | 用途 | 说明 |
128
- |------|------|------|
129
- | `data.uuid` | `--media-id` | 素材 UUID |
130
- | `data.filename` | `--filename` | 文件名 |
131
- | `data.filesize` | `--filesize` | 文件大小(字节) |
132
- | `data.object` | `--object` | OSS 对象路径 |
133
- | `data.ext` | `--ext` | 文件扩展名 |
134
- | `data.type` | `--type` | 文件类型 |
94
+ ## 二、输入要求
135
95
 
136
- **时长默认值**: video→600s, audio→300s, 其他→0s
96
+ ### 创建课程
97
+ 必填: 课程标题 + 课程分类
98
+ 可选: 描述/学分/讲师/标签/封面
137
99
 
138
- ---
100
+ ### 添加课件
101
+ 必填: 课件内容(文件路径或文本)
102
+ 从上下文获取: course-id
139
103
 
140
- ## 步骤4: 创建课件
104
+ ### 发布
105
+ 从上下文获取: course-id
106
+ 前置: Gate Check 全部通过
141
107
 
142
- > 详见 [`../soke-lesson/SKILL.md`](../soke-lesson/SKILL.md)
108
+ ### 指派
109
+ 必填: 部门名或用户名 + course-id
143
110
 
144
- ```bash
145
- soke-cli course +lesson-create \
146
- --course-id "COURSE-UUID" \
147
- --title "第一课" \
148
- --media-id "MATERIAL-UUID" \
149
- --type "video" \
150
- --length 600 \
151
- --object "uploads/20260601/video.mp4" \
152
- --filename "video.mp4" \
153
- --ext "mp4" \
154
- --filesize 10485760 \
155
- --sort 0
156
- ```
157
-
158
- **参数来源映射**:
159
- | 参数 | 必填 | 来源 |
160
- |------|------|------|
161
- | `--course-id` | 是 | 步骤2 `data.uuid` |
162
- | `--title` | 是 | 自定义标题 |
163
- | `--media-id` | 是 | 步骤3 `data.uuid` |
164
- | `--type` | 是 | 步骤3 `data.type` |
165
- | `--length` | 否 | 媒体时长(秒) |
166
- | `--object` | 否 | 步骤3 `data.object` |
167
- | `--filename` | 否 | 步骤3 `data.filename` |
168
- | `--ext` | 否 | 步骤3 `data.ext` |
169
- | `--filesize` | 否 | 步骤3 `data.filesize` |
170
- | `--sort` | 否 | 排序值(默认 0) |
111
+ ## 三、执行流程
171
112
 
172
- **关键原则**: 课件参数全部从 `file +upload` 响应提取,无需手动填写。
113
+ ### 3.1 意图路由
173
114
 
174
- ### 批量上传文件
175
-
176
- ```bash
177
- FILES=("lesson1.mp4" "lesson2.mp4" "handout.pdf")
178
-
179
- for file in "${FILES[@]}"; do
180
- RESULT=$(soke-cli file +upload --file "$file" --format json)
181
- MEDIA_ID=$(echo "$RESULT" | jq -r '.data.uuid')
182
- FILE_TYPE=$(echo "$RESULT" | jq -r '.data.type')
183
- FILE_NAME=$(echo "$RESULT" | jq -r '.data.filename')
184
- FILE_SIZE=$(echo "$RESULT" | jq -r '.data.filesize')
185
- OBJECT=$(echo "$RESULT" | jq -r '.data.object')
186
- EXT=$(echo "$RESULT" | jq -r '.data.ext')
187
-
188
- LENGTH=0
189
- [[ "$FILE_TYPE" == "video" ]] && LENGTH=600
190
- [[ "$FILE_TYPE" == "audio" ]] && LENGTH=300
191
-
192
- TITLE=$(basename "$file" | sed 's/\.[^.]*$//')
193
-
194
- soke-cli course +lesson-create \
195
- --course-id "$COURSE_ID" --title "$TITLE" \
196
- --media-id "$MEDIA_ID" --type "$FILE_TYPE" --length "$LENGTH" \
197
- --object "$OBJECT" --filename "$FILE_NAME" --ext "$EXT" --filesize "$FILE_SIZE"
198
- done
199
115
  ```
200
-
201
- ---
202
-
203
- ## 步骤5: 更新课程(可选)
204
-
205
- ```bash
206
- soke-cli course +update \
207
- --course-id "COURSE-UUID" \
208
- --title "新标题" \
209
- --description "课程描述"
116
+ 用户消息 → 关键词 → 意图 → 路由
117
+
118
+ create → 3.2 全流程创建
119
+ add_lesson → 3.3 课件子流程
120
+ settings → 3.4 设置子流程(→ read references/subs/settings/SOP.md)
121
+ publish → 3.5 发布子流程(→ read references/subs/publish/SOP.md)
122
+ assign → 3.6 指派子流程
123
+ query → 3.7 查询子流程(→ read references/subs/query/SOP.md)
124
+ maintain → 3.8 维护子流程
125
+ category → read references/subs/category/SOP.md
210
126
  ```
211
127
 
212
- ---
128
+ 歧义消解: 上下文有 course-id → 当前课程操作 | 有文件附件 → 倾向课件 | 不确定 → `ask_user_question` 弹窗列出可能的操作让用户点选(如"创建课程"/"添加课件"/"修改设置")
129
+
130
+ ### 3.2 全流程创建(主链路)
131
+
132
+ > 完整 SOP 见 references/sop-full-workflow.md
133
+
134
+ #### Phase 1: 创建课程骨架
135
+
136
+ Step 1.1 权限检查(自动登录)
137
+ exec: soke-cli config show
138
+ → 有 user_token → ✅ 跳过登录
139
+ → 无 user_token → exec: soke-cli auth login(自动打开浏览器)
140
+ 等待用户在浏览器中完成授权
141
+ 再次 exec: soke-cli config show 确认 user_token 已写入
142
+ 登录完成 → 继续下一步
143
+
144
+ Step 1.2 获取分类
145
+ → read references/subs/category/SOP.md 执行
146
+ 执行: soke course +list-categories 获取分类树
147
+ 策略:
148
+ 1. 用户已指定分类名 → 精确/模糊匹配到唯一结果 → 直接使用
149
+ 2. 匹配到多个结果 → `ask_user_question` 弹窗让用户选一个,最后加一项"🆕 新建分类"
150
+ 3. 用户未指定 → `ask_user_question` 弹窗列出所有一级分类,最后加一项"🆕 新建分类"
151
+ 4. 用户说"随便" → 取第一个一级分类
152
+ → 用户选"🆕 新建分类" → 告知:"CLI 暂不支持新建分类,请前往管理后台 → 课程管理 → 分类设置 → 新增分类" → 新建完成后说"分类建好了"再继续
153
+ 提取: category-id → 存上下文
154
+
155
+ Step 1.3 创建课程
156
+ 自身: course +create --title "xxx" --category-id "xxx"
157
+ 提取: course-id → 存上下文
158
+
159
+ Step 1.4 选择模板(创建课程后立即触发)
160
+ → read references/subs/template/SOP.md 执行
161
+ 弹窗: `ask_user_question` 列出 7 个模板(含"7. 不选择模板")
162
+ 用户选 1-6 → 输出该模板的配置清单(标注后台路径) → 确认后继续
163
+ 用户选 7 → 不输出配置,直接进入路由弹窗
164
+ 详见: references/subs/template/SOP.md
165
+
166
+ Gate 1→2: ✅ 有 course-id
167
+
168
+ Phase 1 完成后 → `ask_user_question` 弹窗: "下一步?" → ["添加课件"/"先做设置"/"直接发布"]
169
+ 选"添加课件" → 进入 Phase 2
170
+ 选"先做设置" → 跳到 Phase 3
171
+ 选"直接发布" → 跳到 Phase 4(需通过 Gate Check)
172
+
173
+ #### Phase 2: 构建课件
174
+
175
+ Step 2.1 选择素材来源
176
+ → `ask_user_question` 弹窗: "从哪儿添加课件素材?" → ["📁 本地上传"/"📚 素材库选择"]
177
+ 选"本地上传" → 进入 Step 2.2
178
+ 选"素材库选择" → 进入 Step 2.2b
213
179
 
214
- ## 步骤6: 发布课程
180
+ Step 2.2 本地上传
181
+ 可上传: 视频(.mp4/.avi/.mov/.mkv/.webm)、音频(.mp3/.wav/.ogg/.flac/.aac)、文档(.pdf/.ppt/.pptx/.doc/.docx/.xls/.xlsx)
182
+ ⚠️ 不支持 CLI: 图片/文章/外链/小测验/作业 → 告知后台路径
183
+ → 用户提供本地文件路径
184
+ → 调度 soke-material: file +upload(自动根据扩展名判断类型)
185
+ 提取: media-id + 全字段信息 → 存 media_ids[]
186
+ → 进入 Step 2.3
215
187
 
216
- **前提**: 课程至少包含 1 个课件。
188
+ Step 2.2b 素材库选择
189
+ → 调度 soke-material
190
+ exec: soke file list-files(分页拉取全量素材列表)
191
+ 展示: 文件名 / 类型 / 大小 / 日期(分页或截取前 20 条)
192
+ 告知用户: "输入关键词搜索素材(文件名模糊匹配),或输入序号选择"
193
+ 用户输入关键词 → 在素材列表中模糊匹配 → 弹窗列匹配项
194
+ 用户选序号 → 确认该素材 → 提取全字段信息 → 存 media_ids[]
195
+ 无目标素材 → 弹窗: "素材库中没找到,要不要切换到本地上传?" → ["切本地上传"/"重新搜索"]
196
+ 选"切本地上传" → 回到 Step 2.2
197
+ → 进入 Step 2.3
217
198
 
218
- ```bash
219
- soke-cli course +publish --course-id "COURSE-UUID"
220
- ```
199
+ Step 2.3 创建课件
200
+ 调度 soke-lesson
201
+ 参数全部来自 Step 2.2 或 Step 2.2b 的返回
202
+ 提取: lesson-id
203
+ 存: lesson_ids[]
221
204
 
222
- ---
205
+ Step 2.4 循环
206
+ → `ask_user_question` 弹窗: "还要加课件吗?" → ["继续加课件"/"不了,进入下一步"]
223
207
 
224
- ## 步骤7: 指派课程(可选)
208
+ Step 2.5 排序(可选)
209
+ → `ask_user_question` 弹窗: "需要调整课件顺序吗?" → ["调整顺序"/"保持现状"]
210
+ 选"调整" → 调度 soke-lesson 排序
225
211
 
226
- > 详见 [`../soke-assign/SKILL.md`](../soke-assign/SKILL.md)
212
+ Gate 2→3: ✅ 课件 ≥ 1
227
213
 
228
- 发布后指派给部门或学员,学员才能看到并学习。
214
+ #### Phase 3: 课程设置
229
215
 
230
- ### 7.1 查询可用部门/用户
216
+ read references/subs/settings/SOP.md 执行
217
+ 基础: title/description(course +update)
231
218
 
232
- ```bash
233
- soke-cli assign +list-departments --keyword "关键词"
234
- soke-cli assign +list-users --dept-id "DEPT-ID" --keyword "关键词"
235
- ```
236
-
237
- ### 7.2 创建指派
238
-
239
- ```bash
240
- # 指派给部门
241
- soke-cli assign +create \
242
- --module "course" \
243
- --target-id "COURSE-UUID" \
244
- --dept-ids "DEPT-ID" \
245
- --dept-names "部门名称" \
246
- --learn-type "required"
247
-
248
- # 指派给用户
249
- soke-cli assign +create \
250
- --module "course" \
251
- --target-id "COURSE-UUID" \
252
- --user-ids "USER-ID" \
253
- --user-names "学员姓名" \
254
- --learn-type "required"
255
-
256
- # 同时指派给多个部门和用户
257
- soke-cli assign +create \
258
- --module "course" --target-id "COURSE-UUID" \
259
- --dept-ids "DEPT1,DEPT2" --dept-names "部门1,部门2" \
260
- --user-ids "USER1,USER2" --user-names "学员1,学员2" \
261
- --learn-type "required"
262
- ```
263
-
264
- **指派参数**:
265
- | 参数 | 必填 | 说明 |
266
- |------|------|------|
267
- | `--module` | 是 | 固定 `course` |
268
- | `--target-id` | 是 | 课程 ID |
269
- | `--learn-type` | 是 | `required`(必修) / `optional`(选修) |
270
- | `--dept-ids` | 否 | 部门 ID,逗号分隔 |
271
- | `--dept-names` | 否 | 部门名(与 ids 一一对应) |
272
- | `--user-ids` | 否 | 用户 ID,逗号分隔 |
273
- | `--user-names` | 否 | 用户名(与 ids 一一对应) |
274
-
275
- ---
219
+ → read references/subs/template/SOP.md Step 3 执行
220
+ 将当前所有设置项以表格形式展示(仅「设置项」+「当前值」两列)
221
+ 告知用户: "想修改哪项?直接告诉我就行。"
222
+ 用户指令处理:
223
+ - 标题/描述 → exec: course +update(✅ CLI 支持) → 刷新表格
224
+ - 其他设置 → "已记录: {项} → {新值}(需在后台操作: {路径})" → 刷新表格
225
+ - "可以了"/"继续" → 退出 Phase 3
226
+ 循环直到用户确认
276
227
 
277
- ## 步骤8: 查询学习状态
228
+ Gate 3→4: 无硬阻塞
278
229
 
279
- ### 课程学习记录
230
+ #### Phase 4: 发布
280
231
 
281
- ```bash
282
- soke-cli course +list-course-users --course-id "COURSE-UUID"
232
+ → read references/subs/publish/SOP.md 执行
233
+ Gate Check: 标题/分类/课件数量/转码状态
234
+ 通过 → course +publish
235
+ 定时/审批/批量 → ⚠️ CLI 不支持
283
236
 
284
- # 按用户筛选
285
- soke-cli course +list-course-users \
286
- --course-id "COURSE-UUID" --userid-list "USER1,USER2"
237
+ Gate 4→5: ✅ status=1
287
238
 
288
- # 按完成时间筛选
289
- soke-cli course +list-course-users \
290
- --course-id "COURSE-UUID" \
291
- --finish-start-time 1700000000000 --finish-end-time 1700100000000
292
- ```
239
+ #### Phase 5: 指派学员
293
240
 
294
- ### 学员学习详情
241
+ 调度 soke-assign
242
+
243
+ Step 5.1 拉取部门列表
244
+ exec: soke assign +list-departments
245
+ 提取: 全量部门名称+ID → 存内存
295
246
 
296
- ```bash
297
- soke-cli course +get-course-user \
298
- --course-id "COURSE-UUID" --dept-user-id "DEPT-USER-ID"
299
- ```
247
+ Step 5.2 用户输入关键词搜索
248
+ 告知用户: "请输入要指派的部门名称(支持模糊搜索)"
249
+ 用户输入关键词 在部门列表中模糊匹配(不区分大小写,支持部分匹配)
250
+ 匹配结果:
251
+ - 唯一匹配 → 直接确认使用
252
+ - 多个匹配 → `ask_user_question` 弹窗列出匹配的部门让用户选
253
+ - 无匹配 → 建议换个关键词,或 `ask_user_question` 弹窗列所有部门
300
254
 
301
- 返回: `lesson_finish_num`(已完成)、`lesson_num`(总数)、`progress`(进度%)、`learn_status`
255
+ Step 5.3 确认指派方式
256
+ → `ask_user_question` 弹窗: "必修还是选修?" → ["必修"/"选修"]
302
257
 
303
- ### 课件学习记录
258
+ Step 5.4 执行指派
259
+ exec: soke assign +create --module course --module-id <courseId> --compulsory 1|0 --user-ids "<用部门 ID 查到的人员>"
304
260
 
305
- ```bash
306
- soke-cli course +list-lesson-learns \
307
- --course-id "COURSE-UUID" --lesson-id "LESSON-UUID"
308
- ```
309
-
310
- ### 课件列表
261
+ #### Phase 6: 运营维护
311
262
 
312
- ```bash
313
- # +list-lessons: 支持时间范围
314
- soke-cli course +list-lessons --course-id "ID" --start-time 1700000000000 --end-time 1700100000000
263
+ → read references/subs/query/SOP.md 执行(进度/记录/人脸)
264
+ read references/subs/publish/SOP.md 执行(关闭/删除,⚠️)
265
+ read references/subs/copy/SOP.md 执行(复制,⚠️)
315
266
 
316
- # +lesson-list: 支持类型/关键词筛选
317
- soke-cli course +lesson-list --course-id "ID" --type "video" --keyword "关键词"
318
- ```
267
+ ### 3.3 课件子流程
319
268
 
320
- ---
269
+ 前提: 上下文有 course-id
270
+ 流程: = Phase 2(判断类型→上传→创建→循环→排序)
321
271
 
322
- ## 可用命令全览
272
+ ### 3.4 设置子流程
323
273
 
324
- ### 课程管理
274
+ 前提: 上下文有 course-id
275
+ 流程: read references/subs/settings/SOP.md + references/subs/charge/SOP.md 执行
325
276
 
326
- | 命令 | 说明 | 风险 |
327
- |------|------|------|
328
- | `+list-categories` | 查询课程分类列表 | read |
329
- | `+list-courses` | 查询课程列表 | read |
330
- | `+get-course` | 查询课程详情 | read |
331
- | `+create` | 创建课程 | write |
332
- | `+update` | 更新课程 | write |
333
- | `+publish` | 发布课程 | write |
277
+ ### 3.5 发布子流程
334
278
 
335
- ### 课件管理
279
+ 前提: course-id + status=0
280
+ 流程: read references/subs/publish/SOP.md 执行 → Gate Check → 发布 → 询问指派
336
281
 
337
- | 命令 | 说明 | 风险 |
338
- |------|------|------|
339
- | `+lesson-create` | 创建课件 | write |
340
- | `+lesson-get` | 查询课件详情 | read |
341
- | `+lesson-list` | 查询课件列表(type/keyword) | read |
342
- | `+list-lessons` | 查询课件列表(时间范围) | read |
282
+ ### 3.6 指派子流程
343
283
 
344
- ### 素材管理 (soke-material)
284
+ 前提: course-id + status=1
285
+ 流程: 调度 soke-assign → 拉全量部门 → 用户输入关键词搜索 → 确认 → 指派
345
286
 
346
- | 命令 | 说明 |
347
- |------|------|
348
- | `file +upload` | 上传文件到素材库 |
349
- | `file +create` | 手动创建素材记录 |
350
- | `file +list-files` | 查询素材列表 |
351
- | `file +get-info` | 查询素材详情 |
352
- | `file +download` | 获取下载链接 |
353
- | `file +list-categories` | 查询素材分类 |
287
+ ### 3.7 查询子流程
354
288
 
355
- ### 学习记录查询
289
+ 前提: course-id
290
+ 流程: read references/subs/query/SOP.md 执行 → 进度/记录/人脸
356
291
 
357
- | 命令 | 说明 |
358
- |------|------|
359
- | `+list-course-users` | 课程学员学习记录 |
360
- | `+get-course-user` | 学员个人详情 |
361
- | `+list-lesson-learns` | 课件学习记录 |
362
- | `+list-lesson-faces` | 人脸识别记录 |
292
+ ### 3.8 维护子流程
363
293
 
364
- ### 指派管理 (soke-assign)
294
+ 流程: read references/subs/publish/SOP.md(关闭/删除)/ references/subs/copy/SOP.md(复制)/ references/subs/category/SOP.md(分类)
365
295
 
366
- | 命令 | 说明 |
367
- |------|------|
368
- | `assign +list-departments` | 查询可用部门 |
369
- | `assign +list-users` | 查询可用用户 |
370
- | `assign +create` | 创建指派 |
371
- | `assign +list` | 查询指派记录 |
296
+ ### SOP 执行 5 步法
372
297
 
373
- ---
298
+ 1. READ `references/subs/<name>/SOP.md` → 理解输入输出
299
+ 2. BUILD 从上下文提取参数
300
+ 3. EXEC 按 SOP 流程调用 CLI
301
+ 4. PARSE 按 SOP 输出标准解析
302
+ 5. STORE 关键值写入上下文
374
303
 
375
- ## 调试与故障排除
304
+ 上下文变量: course_id / category_id / lesson_ids[] / media_ids[] / course_status / current_phase
376
305
 
377
- ### 常见错误速查
306
+ ## 四、输出标准
378
307
 
379
- | 错误 | 原因 | 解决 |
380
- |------|------|------|
381
- | `未登录授权` | Token 过期 | `soke-cli auth login` |
382
- | `参数错误` | 必填参数缺失 | `soke-cli course <cmd> --help` |
383
- | `文件不存在` | 上传路径错误 | 使用绝对路径 |
384
- | `课程发布失败` | 无课件 | 先创建至少 1 个课件 |
385
- | `分类不存在` | category-id 无效 | 查询 `+list-categories` |
386
- | `素材不存在` | media-id 无效 | 确认上传成功 |
387
- | `指派失败` | 资源未发布 | 先发布课程 |
308
+ ### 每步即时输出
309
+ ```
310
+ <做了什么>
311
+ 📋 <关键数据>
312
+ ⏭️ <下一步建议>
313
+ ```
388
314
 
389
- ### 调试检查清单
315
+ ### 阶段状态报告
316
+ ```
317
+ 📋 课程: <标题> (id: <uuid>)
318
+ Phase 1 ✅ 已创建
319
+ Phase 2 🔄 课件 3 个
320
+ ├─ ✅ 第1课: 环境搭建 (video, 转码完成)
321
+ ├─ ✅ 第2课: Pandas (video, 转码中)
322
+ └─ ✅ 第3课: 数据清洗.pdf (document)
323
+ Phase 3 ⏸️ 设置
324
+ Phase 4 ⏸️ 发布(阻塞: 第2课转码中)
325
+ Phase 5 ⏸️ 指派
326
+ 下一步: 等转码完成后发布
327
+ ```
390
328
 
391
- ```bash
392
- # 1. 认证状态
393
- soke-cli config show # 确认用户凭证不为空
329
+ ### Gate Check 矩阵
394
330
 
395
- # 2. 课程存在
396
- soke-cli course +get-course --course-id "ID" --format json | jq '.data.uuid'
331
+ | # | 检查项 | 获取方式 | 严重度 | 不通过时 |
332
+ |---|--------|---------|--------|---------|
333
+ | 1 | 标题非空 | +get-course.title | 🔴阻塞 | 请设置标题 |
334
+ | 2 | 分类已选 | +get-course.category_id | 🔴阻塞 | 请选择分类 |
335
+ | 3 | 课件≥1 | +lesson-list count | 🔴阻塞 | 至少1个课件 |
336
+ | 4 | 无转码失败 | +lesson-list.transcode_status | 🔴阻塞 | 课件[X]转码失败 |
337
+ | 5 | 无转码中 | +lesson-list.transcode_status | 🟡警告 | 课件[X]转码中,确认发布? |
338
+ | 6 | 付费方式 | 需确认 | 🟡警告 | — |
397
339
 
398
- # 3. 课件数量
399
- soke-cli course +lesson-list --course-id "ID" --format json | jq '.data.list | length'
340
+ ### 最终交付
341
+ ```
342
+ 📦 课程已发布: <标题>
343
+ 🔗 ID: <uuid> | 📊 课件: 5 个 | 👥 已指派: 研发部(32人)
344
+ ⏭️ 查看进度: 说"看看学习进度"
345
+ ```
400
346
 
401
- # 4. 发布状态
402
- soke-cli course +get-course --course-id "ID" --format json | jq '.data.status'
403
- # status=1 表示已发布
347
+ ## 五、注意事项
404
348
 
405
- # 5. 指派状态
406
- soke-cli assign +list --module course --target-id "ID" --format json | jq '.data.list | length'
349
+ ### 硬规则
350
+ 1. 不编造参数 UUID 来自真实返回
351
+ 2. 不跳过 Gate — 发布前逐项校验
352
+ 3. 不静默失败 — 失败: 查排错文档 → 中文告知 → 修复建议 → 保存进度 → 提供选项
353
+ 4. 类型必须匹配 — 课件与素材类型一致
354
+ 5. 一个 course-id 贯穿全部
407
355
 
408
- # 始终用 --format json 获取结构化输出
409
- ```
356
+ ### 架构分工
410
357
 
411
- ---
358
+ **外部并列技能**(独立 skill,通过 skill 调度):
359
+ - 上传文件到素材库 → soke-material
360
+ - 基于素材创建课件 → soke-lesson
361
+ - 将课程指派给学员 → soke-assign
412
362
 
413
- ## 完整示例
363
+ **内嵌 SOP**(references/subs/ 下,按需 read 执行):
364
+ - 管理课程分类 → references/subs/category/SOP.md
365
+ - 配置课程设置 → references/subs/settings/SOP.md
366
+ - 设置收费 → references/subs/charge/SOP.md
367
+ - 发布校验和发布 → references/subs/publish/SOP.md
368
+ - 复制课程 → references/subs/copy/SOP.md
369
+ - 查询学习数据 → references/subs/query/SOP.md
370
+ - AI生成课程 → references/subs/ai/SOP.md
371
+ - 课程模板(7套预置配置) → references/subs/template/SOP.md
414
372
 
415
- ```bash
416
- # === 1. 查询分类 ===
417
- CATEGORY_ID=$(soke-cli course +list-categories --format json | jq -r '.data.list[0].uuid')
418
-
419
- # === 2. 创建课程 ===
420
- COURSE_ID=$(soke-cli course +create \
421
- --title "Python 数据分析实战" \
422
- --category-id "$CATEGORY_ID" \
423
- --format json | jq -r '.data.uuid')
424
-
425
- # === 3. 上传素材 ===
426
- UPLOAD=$(soke-cli file +upload --file "./lesson1.mp4" --format json)
427
- MEDIA_ID=$(echo "$UPLOAD" | jq -r '.data.uuid')
428
- FILE_TYPE=$(echo "$UPLOAD" | jq -r '.data.type')
429
- FILENAME=$(echo "$UPLOAD" | jq -r '.data.filename')
430
- FILESIZE=$(echo "$UPLOAD" | jq -r '.data.filesize')
431
- OBJECT=$(echo "$UPLOAD" | jq -r '.data.object')
432
- EXT=$(echo "$UPLOAD" | jq -r '.data.ext')
433
-
434
- # === 4. 创建课件 ===
435
- soke-cli course +lesson-create \
436
- --course-id "$COURSE_ID" --title "第一课:环境搭建" \
437
- --media-id "$MEDIA_ID" --type "$FILE_TYPE" --length 600 \
438
- --object "$OBJECT" --filename "$FILENAME" --ext "$EXT" --filesize "$FILESIZE"
439
-
440
- # === 5. 发布课程 ===
441
- soke-cli course +publish --course-id "$COURSE_ID"
442
-
443
- # === 6. 指派学员 ===
444
- DEPT_ID=$(soke-cli assign +list-departments --keyword "研发" --format json | jq -r '.data.list[0].uuid')
445
- soke-cli assign +create \
446
- --module "course" --target-id "$COURSE_ID" \
447
- --dept-ids "$DEPT_ID" --dept-names "研发部" \
448
- --learn-type "required"
449
-
450
- # === 7. 验证 ===
451
- soke-cli course +get-course --course-id "$COURSE_ID" --format json | jq .
452
- soke-cli course +lesson-list --course-id "$COURSE_ID" --format json | jq '.data.list'
453
- ```
373
+ ### 已知 CLI 缺失
454
374
 
455
- ---
375
+ 统一话术: "XXX 功能暂不支持 CLI 操作,请在后台手动设置。"
456
376
 
457
- ## API 接口映射
458
-
459
- | CLI 命令 | API 路径 | 方法 |
460
- |----------|----------|------|
461
- | `+list-categories` | `/course/category/list` | GET |
462
- | `+list-courses` | `/course/course/list` | GET |
463
- | `+get-course` | `/course/course/info` | GET |
464
- | `+create` | `/skills/course/create` | POST |
465
- | `+update` | `/skills/course/update/{id}` | PUT |
466
- | `+publish` | `/skills/course/update/{id}` | PUT |
467
- | `+lesson-create` | `/skills/course/lesson/create` | POST |
468
- | `+lesson-get` | `/skills/courseware/get/{id}` | GET |
469
- | `+lesson-list` | `/skills/course/lesson/list` | GET |
470
- | `+list-lessons` | `/course/lesson/list` | GET |
471
- | `+list-course-users` | `/course/user/list` | GET |
472
- | `+get-course-user` | `/course/user/info` | GET |
473
- | `+list-lesson-learns` | `/course/lessonLearn/list` | GET |
474
- | `+list-lesson-faces` | `/course/lessonFace/list` | GET |
475
- | `file +upload` | `/skills/uploadFile/signature` + `/skills/uploadFile/create` | POST |
476
- | `assign +list-departments` | `/skills/department/list` | GET |
477
- | `assign +list-users` | `/skills/user/list` | GET |
478
- | `assign +create` | `/skills/assignLog/create` | POST |
479
- | `assign +list` | `/skills/assignLog/list` | GET |
480
-
481
- ## 权限要求
482
-
483
- | 操作 | 权限范围 |
484
- |------|----------|
485
- | 课程读写 | `course:course:write` / `course:course:readonly` |
486
- | 课件读写 | `course:courseware:write` / `course:courseware:readonly` |
487
- | 素材读写 | `file:file:write` / `file:file:readonly` |
488
- | 指派读写 | `assign:write` / `assign:read` |
489
- | 学习记录 | `course:courseUser:readonly` / `course:lessonLearn:readonly` |
490
-
491
- ## 注意事项
492
-
493
- 1. **课程至少需要 1 个课件才能发布**
494
- 2. **课件参数全部从素材上传响应提取**,不手动构造
495
- 3. **时长根据文件类型自动设置**: video=600s, audio=300s, 其他=0
496
- 4. **课程发布后学员才可见**
497
- 5. **指派是可选的**,未指派时学员看不到课程
498
- 6. **所有时间参数使用毫秒级 Unix 时间戳**
499
-
500
- ## 相关文档
501
-
502
- - [`../soke-shared/SKILL.md`](../soke-shared/SKILL.md) — 认证、配置、权限
503
- - [`../soke-material/SKILL.md`](../soke-material/SKILL.md) — 文件上传和素材管理
504
- - [`../soke-lesson/SKILL.md`](../soke-lesson/SKILL.md) — 课件创建和管理
505
- - [`../soke-assign/SKILL.md`](../soke-assign/SKILL.md) — 指派管理
506
- - [`references/examples.md`](./references/examples.md) — 更多使用示例
507
- - [`references/course-list-courses.md`](./references/course-list-courses.md) — 课程查询参考
377
+ | 类别 | 缺失 |
378
+ |------|------|
379
+ | 课件类型 | image/article/link/quiz/homework |
380
+ | 分类 | 新增分类 |
381
+ | 课程设置 | credit/point/lector_id/tags/cover上传/简介插图 |
382
+ | 高级设置 | 学习模式/倍速/人脸/提醒/评价/证书/签名/钉钉群 |
383
+ | 收费 | 价格/试看 |
384
+ | 发布 | 定时/审批/批量 |
385
+ | 维护 | 关闭/删除/复制 |
386
+
387
+ ### 中断恢复
388
+ 用户"继续"/"接着做": 检查 course-id 有:查状态+课件→报告→继续 | 无:列课程→选→恢复
389
+
390
+ ## 六、交付前自查
391
+
392
+ - [ ] 每步有明确调度目标
393
+ - [ ] 关键返回值已存入上下文
394
+ - [ ] 每步完成有下一步建议
395
+ - [ ] 发布前过完整 Gate Check
396
+ - [ ] CLI 不支持功能已告知替代路径
397
+ - [ ] 失败有修复建议
398
+ - [ ] 所有固定选项的决策点均使用 `ask_user_question` 弹窗(禁止纯文本罗列让用户打字)
399
+ - [ ] 分类选择弹窗最后一项始终为"🆕 新建分类"
400
+ - [ ] 状态报告完整