@sokeai/cli 1.0.33 → 1.0.37
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/package.json +1 -1
- package/scripts/install.js +36 -43
- package/scripts/local-test.sh +40 -15
- package/scripts/push.sh +16 -25
- package/scripts/release.sh +7 -0
- package/skills/soke-business-training-report/SKILL.md +0 -57
package/package.json
CHANGED
package/scripts/install.js
CHANGED
|
@@ -491,50 +491,43 @@ function downloadFile(url, dest) {
|
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
// 执行下载
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
if (platform !== 'win32') {
|
|
499
|
-
try {
|
|
500
|
-
fs.chmodSync(binaryPath, 0o755);
|
|
501
|
-
console.log('已设置可执行权限');
|
|
502
|
-
} catch (err) {
|
|
503
|
-
console.error('设置可执行权限失败:', err.message);
|
|
504
|
-
process.exit(1);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
494
|
+
downloadFile(downloadURL, binaryPath)
|
|
495
|
+
.then(() => {
|
|
496
|
+
// 设置可执行权限(非 Windows 平台)
|
|
497
|
+
if (platform !== 'win32') {
|
|
508
498
|
try {
|
|
509
|
-
|
|
510
|
-
|
|
499
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
500
|
+
console.log('已设置可执行权限');
|
|
501
|
+
} catch (err) {
|
|
502
|
+
console.error('设置可执行权限失败:', err.message);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
511
506
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
507
|
+
try {
|
|
508
|
+
syncSkillsToSokeclawWorkspace();
|
|
509
|
+
} catch (_) {}
|
|
515
510
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
console.log('soke-cli 安装成功!');
|
|
520
|
-
console.log(`二进制文件位置: ${binaryPath}`);
|
|
521
|
-
console.log('\n使用方法:');
|
|
522
|
-
console.log(' soke-cli --help');
|
|
523
|
-
console.log(' soke-cli config init');
|
|
524
|
-
console.log(' soke-cli auth login');
|
|
525
|
-
})
|
|
526
|
-
.catch((err) => {
|
|
527
|
-
console.error('\n安装失败:', err.message);
|
|
528
|
-
console.error('\n可能的原因:');
|
|
529
|
-
console.error('1. 网络连接问题');
|
|
530
|
-
console.error('2. GitHub Releases 中不存在该版本的二进制文件');
|
|
531
|
-
console.error('3. 不支持当前平台');
|
|
532
|
-
console.error('\n请访问 https://github.com/sokeai/soke-cli/releases 手动下载');
|
|
533
|
-
process.exit(1);
|
|
534
|
-
});
|
|
535
|
-
}
|
|
511
|
+
try {
|
|
512
|
+
syncSkillsToWorkclawRegistry();
|
|
513
|
+
} catch (_) {}
|
|
536
514
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
515
|
+
return maybeAssistGuiPath();
|
|
516
|
+
})
|
|
517
|
+
.then(() => {
|
|
518
|
+
console.log('soke-cli 安装成功!');
|
|
519
|
+
console.log(`二进制文件位置: ${binaryPath}`);
|
|
520
|
+
console.log('\n使用方法:');
|
|
521
|
+
console.log(' soke-cli --help');
|
|
522
|
+
console.log(' soke-cli config init');
|
|
523
|
+
console.log(' soke-cli auth login');
|
|
524
|
+
})
|
|
525
|
+
.catch((err) => {
|
|
526
|
+
console.error('\n安装失败:', err.message);
|
|
527
|
+
console.error('\n可能的原因:');
|
|
528
|
+
console.error('1. 网络连接问题');
|
|
529
|
+
console.error('2. GitHub Releases 中不存在该版本的二进制文件');
|
|
530
|
+
console.error('3. 不支持当前平台');
|
|
531
|
+
console.error('\n请访问 https://github.com/sokeai/soke-cli/releases 手动下载');
|
|
532
|
+
process.exit(1);
|
|
533
|
+
});
|
package/scripts/local-test.sh
CHANGED
|
@@ -111,25 +111,50 @@ echo ""
|
|
|
111
111
|
echo -e "${YELLOW}[3.5/4] 分发 Skills 到本地 Agent...${NC}"
|
|
112
112
|
if [ "$SKIP_GLOBAL" = false ]; then
|
|
113
113
|
echo -e " 执行 scripts/install.js 同步 Skills..."
|
|
114
|
+
# 注入特殊环境变量或者直接调用 node 执行
|
|
115
|
+
# 我们只想要触发 syncSkillsToSokeclawWorkspace 和 syncSkillsToWorkclawRegistry
|
|
116
|
+
# 但原 install.js 会尝试下载二进制文件,所以我们新建一个临时脚本或修改调用方式
|
|
114
117
|
|
|
115
|
-
#
|
|
118
|
+
# 为了安全起见,这里直接使用 node 运行一小段脚本引入 install.js 中的逻辑
|
|
116
119
|
cat > ./scripts/sync-skills-local.js << 'EOF'
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
const fs = require('fs');
|
|
121
|
+
const path = require('path');
|
|
122
|
+
const installCode = fs.readFileSync(path.join(__dirname, 'install.js'), 'utf8');
|
|
123
|
+
|
|
124
|
+
// 提取需要的函数
|
|
125
|
+
const syncFn1Match = installCode.match(/function syncSkillsToSokeclawWorkspace\(\) \{[\s\S]*?\n\}/);
|
|
126
|
+
const syncFn2Match = installCode.match(/function syncSkillsToWorkclawRegistry\(\) \{[\s\S]*?\n\}/);
|
|
127
|
+
|
|
128
|
+
// 我们更推荐直接利用已经写好的 js 模块(如果它是通过 module.exports 导出的)
|
|
129
|
+
// 但因为 install.js 是直接执行的脚本,我们通过简单的 node 脚本手动拷贝
|
|
130
|
+
const os = require('os');
|
|
131
|
+
function copyDirRecursive(srcDir, destDir) {
|
|
132
|
+
if (!fs.existsSync(srcDir)) return;
|
|
133
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
134
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
137
|
+
const destPath = path.join(destDir, entry.name);
|
|
138
|
+
if (entry.isDirectory()) { copyDirRecursive(srcPath, destPath); continue; }
|
|
139
|
+
fs.copyFileSync(srcPath, destPath);
|
|
140
|
+
}
|
|
125
141
|
}
|
|
126
142
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
143
|
+
const homeDir = os.homedir();
|
|
144
|
+
const defaultSokeclawDir = path.join(homeDir, '.sokeclaw', 'openai-agents', 'workspaces', 'main', 'skills');
|
|
145
|
+
const packageRoot = path.join(__dirname, '..');
|
|
146
|
+
const packagedSkillsDir = path.join(packageRoot, 'skills');
|
|
147
|
+
|
|
148
|
+
if (fs.existsSync(packagedSkillsDir)) {
|
|
149
|
+
const skillNames = fs.readdirSync(packagedSkillsDir).filter(n => n.startsWith('soke-'));
|
|
150
|
+
if (fs.existsSync(defaultSokeclawDir)) {
|
|
151
|
+
for (const skillName of skillNames) {
|
|
152
|
+
const src = path.join(packagedSkillsDir, skillName);
|
|
153
|
+
const dest = path.join(defaultSokeclawDir, skillName);
|
|
154
|
+
copyDirRecursive(src, dest);
|
|
155
|
+
console.log(` ✓ 同步 ${skillName} 到 ${dest}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
133
158
|
}
|
|
134
159
|
EOF
|
|
135
160
|
node ./scripts/sync-skills-local.js
|
package/scripts/push.sh
CHANGED
|
@@ -191,33 +191,24 @@ git commit -m "$commit_info"
|
|
|
191
191
|
# 保存当前分支名(用于后续合并)
|
|
192
192
|
FEATURE_BRANCH=$CURRENT_BRANCH
|
|
193
193
|
|
|
194
|
-
#
|
|
195
|
-
|
|
196
|
-
git checkout master
|
|
194
|
+
# 目标主分支名称
|
|
195
|
+
TARGET_BRANCH="soke-cli"
|
|
197
196
|
|
|
198
|
-
#
|
|
199
|
-
print_info "
|
|
200
|
-
git
|
|
201
|
-
|
|
202
|
-
# 推送到 origin (Aliyun) 的 master 分支
|
|
203
|
-
print_info "推送到 Aliyun 远程仓库 (origin master)..."
|
|
204
|
-
git push origin master
|
|
197
|
+
# 切换到主分支
|
|
198
|
+
print_info "切换到 $TARGET_BRANCH 分支..."
|
|
199
|
+
git checkout $TARGET_BRANCH
|
|
205
200
|
|
|
206
|
-
#
|
|
207
|
-
print_info "
|
|
208
|
-
git
|
|
209
|
-
|
|
210
|
-
# 切换到 main 分支
|
|
211
|
-
print_info "切换到 main 分支..."
|
|
212
|
-
git checkout main
|
|
201
|
+
# 合并功能分支到主分支
|
|
202
|
+
print_info "合并 ${FEATURE_BRANCH} 到 $TARGET_BRANCH..."
|
|
203
|
+
git merge $FEATURE_BRANCH
|
|
213
204
|
|
|
214
|
-
#
|
|
215
|
-
print_info "
|
|
216
|
-
git
|
|
205
|
+
# 推送到 origin (Aliyun) 的主分支
|
|
206
|
+
print_info "推送到 Aliyun 远程仓库 (origin $TARGET_BRANCH)..."
|
|
207
|
+
git push origin $TARGET_BRANCH
|
|
217
208
|
|
|
218
|
-
# 推送到 github
|
|
219
|
-
print_info "推送到 GitHub 远程仓库 (github
|
|
220
|
-
git push github
|
|
209
|
+
# 推送到 github 的主分支
|
|
210
|
+
print_info "推送到 GitHub 远程仓库 (github $TARGET_BRANCH)..."
|
|
211
|
+
git push github $TARGET_BRANCH
|
|
221
212
|
|
|
222
213
|
# 切换回原分支
|
|
223
214
|
print_info "切换回原分支 ${FEATURE_BRANCH}..."
|
|
@@ -234,5 +225,5 @@ if [[ "$IS_RELEASE" == true ]]; then
|
|
|
234
225
|
echo " - 🎉 版本发布: ${GREEN}v${NEW_VERSION}${NC}"
|
|
235
226
|
fi
|
|
236
227
|
|
|
237
|
-
echo " - Aliyun (origin):
|
|
238
|
-
echo " - GitHub (github):
|
|
228
|
+
echo " - Aliyun (origin): $TARGET_BRANCH 分支已更新"
|
|
229
|
+
echo " - GitHub (github): $TARGET_BRANCH 分支已更新"
|
package/scripts/release.sh
CHANGED
|
@@ -48,6 +48,13 @@ check_tools() {
|
|
|
48
48
|
check_git_status() {
|
|
49
49
|
echo -e "${YELLOW}检查 Git 状态...${NC}"
|
|
50
50
|
|
|
51
|
+
# 检查当前分支是否为 soke-cli
|
|
52
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
53
|
+
if [ "$CURRENT_BRANCH" != "soke-cli" ]; then
|
|
54
|
+
echo -e "${RED}错误: 当前分支为 $CURRENT_BRANCH,发布必须在 soke-cli 分支上进行${NC}"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
51
58
|
if [ -n "$(git status --porcelain)" ]; then
|
|
52
59
|
echo -e "${RED}错误: 工作目录有未提交的更改${NC}"
|
|
53
60
|
echo "请先提交或暂存所有更改"
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: soke-business-training-report
|
|
3
|
-
description: 生成某场业务培训考试的整体分析报告,包括参考人数、通过率、平均分、最高分及未通过学员名单。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 培训考试整体分析报告 Skill
|
|
7
|
-
|
|
8
|
-
## 目标
|
|
9
|
-
根据用户提供的培训/考试名称,通过调用开放平台的考试相关 API,自动生成一份结构化的培训考试分析报告。
|
|
10
|
-
|
|
11
|
-
## 触发条件
|
|
12
|
-
当用户提出类似以下问题时,应使用此 Skill:
|
|
13
|
-
- "帮我分析一下本次业务培训的考试情况"
|
|
14
|
-
- "统计一下这次培训的通过率"
|
|
15
|
-
- "输出一份『新员工入职培训』的考试报告"
|
|
16
|
-
|
|
17
|
-
## 执行步骤
|
|
18
|
-
|
|
19
|
-
### 第一步:确认目标考试
|
|
20
|
-
1. 调用 `GET /exam/exam/list` 接口,获取考试列表。
|
|
21
|
-
- **必填参数**:`start_time` 和 `end_time`(Unix 时间戳,单位毫秒),时间差不超过 365 天。
|
|
22
|
-
- 若用户未提供时间范围,自动设置为近 3 个月。
|
|
23
|
-
2. 根据用户提供的培训名称关键词,在返回的 `data.list` 中模糊匹配 `title` 字段。
|
|
24
|
-
- 如果匹配到多个,列出候选供用户选择。
|
|
25
|
-
3. 记录目标考试的 `uuid`、`title`、`total_score`、`pass_score`。
|
|
26
|
-
|
|
27
|
-
### 第二步:获取考试学员成绩列表
|
|
28
|
-
1. 调用 `GET /exam/user/list` 接口,参数 `exam_id` 为考试 UUID。
|
|
29
|
-
2. 提取每个学员的 `pass_status`(passed/unpassed/not_attempt)、`last_score`。
|
|
30
|
-
|
|
31
|
-
### 第三步:计算整体统计指标
|
|
32
|
-
- 参考人数(排除 not_attempt)
|
|
33
|
-
- 通过人数(passed)
|
|
34
|
-
- 通过率、平均分、最高分
|
|
35
|
-
- 未通过学员列表
|
|
36
|
-
|
|
37
|
-
### 第四步:输出报告
|
|
38
|
-
按照以下格式输出:
|
|
39
|
-
|
|
40
|
-
📊 【培训名称】考试分析报告
|
|
41
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
42
|
-
👥 参考人数:XX 人
|
|
43
|
-
✅ 通过人数:XX 人
|
|
44
|
-
📈 通过率:XX%
|
|
45
|
-
📊 平均分:XX 分(满分 XX 分)
|
|
46
|
-
🏆 最高分:XX 分
|
|
47
|
-
❌ 未通过学员:XX 人
|
|
48
|
-
- 学员A(得分:XX)
|
|
49
|
-
...
|
|
50
|
-
|
|
51
|
-
## API 调用与鉴权
|
|
52
|
-
- 基础 URL:`https://oapi.soke.cn`
|
|
53
|
-
- 接口需要 `access_token`,在 Agent 环境中自动获取,无需手动处理。
|
|
54
|
-
|
|
55
|
-
## 注意事项
|
|
56
|
-
- `start_time` 和 `end_time` 必填,Skill 自动生成。
|
|
57
|
-
- 注意区分 `not_attempt`(未参考)、`reviewing`(阅卷中)、`unpassed`(未通过)和 `passed`(通过)。
|