skillfree 0.1.66 → 0.1.68
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/install.sh +67 -6
- package/package.json +1 -1
- package/postinstall.js +78 -26
- package/scripts/commands/auth.js +23 -6
package/install.sh
CHANGED
|
@@ -39,7 +39,7 @@ echo -e " ${DIM}─────────────────────
|
|
|
39
39
|
echo ""
|
|
40
40
|
|
|
41
41
|
# ── Step 1: 检查环境 ──────────────────────────────────────────────────────────
|
|
42
|
-
step "[ 1 /
|
|
42
|
+
step "[ 1 / 4 ] 检查环境"
|
|
43
43
|
|
|
44
44
|
if ! command -v node &>/dev/null; then
|
|
45
45
|
err "未检测到 Node.js,请先安装:https://nodejs.org(需要 18+)"
|
|
@@ -55,8 +55,69 @@ if ! command -v npm &>/dev/null; then
|
|
|
55
55
|
fi
|
|
56
56
|
success "npm $(npm -v)"
|
|
57
57
|
|
|
58
|
-
# ── Step 2:
|
|
59
|
-
step "[ 2 /
|
|
58
|
+
# ── Step 2: 选择 AI 平台 ──────────────────────────────────────────────────────
|
|
59
|
+
step "[ 2 / 4 ] 选择你使用的 AI 平台"
|
|
60
|
+
echo ""
|
|
61
|
+
echo -e " SkillFree 将作为 Skill 安装到对应平台,${DIM}可多选,用逗号或空格分隔${NC}"
|
|
62
|
+
echo ""
|
|
63
|
+
|
|
64
|
+
# 自动检测已安装的平台
|
|
65
|
+
DETECTED=()
|
|
66
|
+
[ -d "$HOME/.openclaw" ] && DETECTED+=("openclaw")
|
|
67
|
+
[ -d "$HOME/.claude" ] && DETECTED+=("claude")
|
|
68
|
+
[ -d "$HOME/.codex" ] && DETECTED+=("codex")
|
|
69
|
+
[ -d "$HOME/.continue" ] && DETECTED+=("continue")
|
|
70
|
+
[ -d "$HOME/.cursor/extensions" ] && DETECTED+=("cursor")
|
|
71
|
+
|
|
72
|
+
echo -e " ${BOLD}可选平台:${NC}"
|
|
73
|
+
echo -e " ${CYAN} 1)${NC} OpenClaw ${DIM}→ ~/.openclaw/skills/skillfree/${NC}"
|
|
74
|
+
echo -e " ${CYAN} 2)${NC} Claude Code ${DIM}→ ~/.claude/skills/skillfree/${NC}"
|
|
75
|
+
echo -e " ${CYAN} 3)${NC} Codex CLI ${DIM}→ ~/.codex/skills/skillfree/${NC}"
|
|
76
|
+
echo ""
|
|
77
|
+
|
|
78
|
+
if [ ${#DETECTED[@]} -gt 0 ]; then
|
|
79
|
+
echo -e " ${GREEN}已检测到:${DETECTED[*]}${NC}"
|
|
80
|
+
echo ""
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
printf " 请输入编号(如 1 或 1,2,3),直接回车选全部检测到的平台: "
|
|
84
|
+
read -r PLATFORM_INPUT </dev/tty
|
|
85
|
+
|
|
86
|
+
# 解析选择
|
|
87
|
+
SELECTED_PLATFORMS=()
|
|
88
|
+
|
|
89
|
+
if [ -z "$PLATFORM_INPUT" ]; then
|
|
90
|
+
# 回车 → 使用检测到的平台,没检测到则三个都选
|
|
91
|
+
if [ ${#DETECTED[@]} -gt 0 ]; then
|
|
92
|
+
SELECTED_PLATFORMS=("${DETECTED[@]}")
|
|
93
|
+
else
|
|
94
|
+
SELECTED_PLATFORMS=("openclaw" "claude" "codex")
|
|
95
|
+
fi
|
|
96
|
+
else
|
|
97
|
+
# 解析数字(支持逗号/空格分隔)
|
|
98
|
+
INPUT_CLEAN="${PLATFORM_INPUT//,/ }"
|
|
99
|
+
for num in $INPUT_CLEAN; do
|
|
100
|
+
case "$num" in
|
|
101
|
+
1) SELECTED_PLATFORMS+=("openclaw") ;;
|
|
102
|
+
2) SELECTED_PLATFORMS+=("claude") ;;
|
|
103
|
+
3) SELECTED_PLATFORMS+=("codex") ;;
|
|
104
|
+
esac
|
|
105
|
+
done
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if [ ${#SELECTED_PLATFORMS[@]} -gt 0 ]; then
|
|
109
|
+
echo ""
|
|
110
|
+
echo -e " ${GREEN}将安装到:${SELECTED_PLATFORMS[*]}${NC}"
|
|
111
|
+
else
|
|
112
|
+
echo ""
|
|
113
|
+
warn "未选择平台,仅安装 CLI 命令行工具"
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# 导出给 postinstall.js 使用
|
|
117
|
+
export SKILLFREE_PLATFORMS="${SELECTED_PLATFORMS[*]}"
|
|
118
|
+
|
|
119
|
+
# ── Step 3: 安装 CLI ──────────────────────────────────────────────────────────
|
|
120
|
+
step "[ 3 / 4 ] 安装 SkillFree CLI"
|
|
60
121
|
echo ""
|
|
61
122
|
echo -e " ${DIM}正在从 npm 安装 skillfree...${NC}"
|
|
62
123
|
echo ""
|
|
@@ -91,8 +152,8 @@ if ! command -v skillfree &>/dev/null; then
|
|
|
91
152
|
exit 0
|
|
92
153
|
fi
|
|
93
154
|
|
|
94
|
-
# ── Step
|
|
95
|
-
step "[
|
|
155
|
+
# ── Step 4: 登录(从 /dev/tty 读取,兼容 curl | bash)────────────────────────
|
|
156
|
+
step "[ 4 / 4 ] 登录账号"
|
|
96
157
|
echo ""
|
|
97
158
|
echo -e " 还没有账号?${CYAN}https://skillfree.tech/app${NC} 免费注册,注册即送 ¥5"
|
|
98
159
|
echo -e " 注册后进入控制台 → ${BOLD}API Keys${NC} → 创建一个 Key,粘贴到下方"
|
|
@@ -120,7 +181,7 @@ while true; do
|
|
|
120
181
|
done
|
|
121
182
|
|
|
122
183
|
if [ -n "$API_KEY" ]; then
|
|
123
|
-
SKILLFREE_API_KEY="$API_KEY" skillfree auth save "$API_KEY"
|
|
184
|
+
SKILLFREE_API_KEY="$API_KEY" SKILLFREE_PLATFORMS="$SKILLFREE_PLATFORMS" skillfree auth save "$API_KEY"
|
|
124
185
|
fi
|
|
125
186
|
|
|
126
187
|
# ── 完成 ──────────────────────────────────────────────────────────────────────
|
package/package.json
CHANGED
package/postinstall.js
CHANGED
|
@@ -2,24 +2,54 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* postinstall.js
|
|
4
4
|
* npm install -g skillfree 后自动:
|
|
5
|
-
* 1.
|
|
6
|
-
* 2. 将 API Key 写入
|
|
5
|
+
* 1. 将技能文件部署到各 AI 平台的 skills/skillfree/ 目录
|
|
6
|
+
* 2. 将 API Key 写入 OpenClaw 配置(如果已安装)
|
|
7
|
+
*
|
|
8
|
+
* 支持的平台(通过 SKILLFREE_PLATFORMS 环境变量控制):
|
|
9
|
+
* openclaw → ~/.openclaw/skills/skillfree/ + ~/.agents/skills/skillfree/
|
|
10
|
+
* claude → ~/.claude/skills/skillfree/
|
|
11
|
+
* codex → ~/.codex/skills/skillfree/
|
|
12
|
+
* continue → ~/.continue/skills/skillfree/
|
|
13
|
+
* cursor → ~/.cursor/skills/skillfree/
|
|
7
14
|
*/
|
|
8
15
|
|
|
9
16
|
const fs = require('fs')
|
|
10
17
|
const path = require('path')
|
|
11
18
|
const os = require('os')
|
|
12
19
|
|
|
13
|
-
const PKG_DIR
|
|
14
|
-
const HOME
|
|
15
|
-
const API_KEY
|
|
20
|
+
const PKG_DIR = __dirname
|
|
21
|
+
const HOME = os.homedir()
|
|
22
|
+
const API_KEY = process.env.SKILLFREE_API_KEY || ''
|
|
23
|
+
|
|
24
|
+
// ── 平台 → 技能安装路径映射 ─────────────────────────────────────────────────
|
|
25
|
+
const PLATFORM_PATHS = {
|
|
26
|
+
openclaw: [
|
|
27
|
+
path.join(HOME, '.openclaw', 'skills', 'skillfree'),
|
|
28
|
+
path.join(HOME, '.agents', 'skills', 'skillfree'),
|
|
29
|
+
],
|
|
30
|
+
claude: [
|
|
31
|
+
path.join(HOME, '.claude', 'skills', 'skillfree'),
|
|
32
|
+
],
|
|
33
|
+
codex: [
|
|
34
|
+
path.join(HOME, '.codex', 'skills', 'skillfree'),
|
|
35
|
+
],
|
|
36
|
+
}
|
|
16
37
|
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
38
|
+
// 解析目标平台
|
|
39
|
+
function getTargetPlatforms() {
|
|
40
|
+
const envVal = process.env.SKILLFREE_PLATFORMS || ''
|
|
41
|
+
if (!envVal.trim()) {
|
|
42
|
+
// 未指定时:自动检测已安装的平台
|
|
43
|
+
return Object.keys(PLATFORM_PATHS).filter(p => {
|
|
44
|
+
const baseDir = path.join(HOME, '.' + p)
|
|
45
|
+
return fs.existsSync(baseDir)
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
// 支持空格/逗号分隔
|
|
49
|
+
return envVal.split(/[\s,]+/).filter(p => p && PLATFORM_PATHS[p])
|
|
50
|
+
}
|
|
22
51
|
|
|
52
|
+
// ── 文件部署 ─────────────────────────────────────────────────────────────────
|
|
23
53
|
const FILES = ['SKILL.md', 'package.json']
|
|
24
54
|
const DIRS = ['bin', 'scripts']
|
|
25
55
|
|
|
@@ -48,33 +78,32 @@ function deploySkill(skillDir) {
|
|
|
48
78
|
}
|
|
49
79
|
fs.writeFileSync(
|
|
50
80
|
path.join(skillDir, '.skillfree-installed'),
|
|
51
|
-
JSON.stringify({
|
|
81
|
+
JSON.stringify({
|
|
82
|
+
installedAt: new Date().toISOString(),
|
|
83
|
+
version: require('./package.json').version,
|
|
84
|
+
}, null, 2) + '\n'
|
|
52
85
|
)
|
|
53
86
|
}
|
|
54
87
|
|
|
88
|
+
// ── OpenClaw 特有:写入 openclaw.json ────────────────────────────────────────
|
|
55
89
|
function injectOpenclawConfig(apiKey) {
|
|
56
|
-
// 只在有 openclaw 目录时注入
|
|
57
90
|
const openclawDir = path.join(HOME, '.openclaw')
|
|
58
91
|
if (!fs.existsSync(openclawDir)) return
|
|
59
92
|
|
|
60
93
|
const cfgPath = path.join(openclawDir, 'openclaw.json')
|
|
61
|
-
|
|
62
|
-
// ⚠️ 关键:文件不存在时直接 return,绝不用空对象覆盖
|
|
63
94
|
if (!fs.existsSync(cfgPath)) return
|
|
64
95
|
|
|
65
96
|
let cfg = {}
|
|
66
97
|
try {
|
|
67
98
|
cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'))
|
|
68
99
|
} catch (e) {
|
|
69
|
-
|
|
70
|
-
console.warn('⚠️ openclaw.json 解析失败,跳过自动配置(文件可能损坏)')
|
|
100
|
+
console.warn('⚠️ openclaw.json 解析失败,跳过自动配置')
|
|
71
101
|
return
|
|
72
102
|
}
|
|
73
103
|
|
|
74
104
|
cfg.skills = cfg.skills || {}
|
|
75
105
|
cfg.skills.entries = cfg.skills.entries || {}
|
|
76
106
|
|
|
77
|
-
// 只写 enabled,不覆盖用户已有的 apiKey
|
|
78
107
|
const existing = cfg.skills.entries['skillfree'] || {}
|
|
79
108
|
cfg.skills.entries['skillfree'] = {
|
|
80
109
|
...existing,
|
|
@@ -84,23 +113,46 @@ function injectOpenclawConfig(apiKey) {
|
|
|
84
113
|
|
|
85
114
|
try {
|
|
86
115
|
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n')
|
|
87
|
-
console.log('✅ openclaw.json 已更新,skill 下次启动自动生效')
|
|
116
|
+
console.log(' ✅ openclaw.json 已更新,skill 下次启动自动生效')
|
|
88
117
|
} catch (e) {
|
|
89
118
|
// 权限问题静默跳过
|
|
90
119
|
}
|
|
91
120
|
}
|
|
92
121
|
|
|
122
|
+
// ── 主流程 ───────────────────────────────────────────────────────────────────
|
|
93
123
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
124
|
+
const platforms = getTargetPlatforms()
|
|
125
|
+
|
|
126
|
+
if (platforms.length === 0) {
|
|
127
|
+
// 没有检测到任何平台,保底装到 ~/.agents/skills/
|
|
128
|
+
const fallback = path.join(HOME, '.agents', 'skills', 'skillfree')
|
|
129
|
+
deploySkill(fallback)
|
|
130
|
+
console.log(`✅ SkillFree skill 已安装到 ${fallback}`)
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const installed = []
|
|
135
|
+
|
|
136
|
+
for (const platform of platforms) {
|
|
137
|
+
const targets = PLATFORM_PATHS[platform] || []
|
|
138
|
+
for (const skillDir of targets) {
|
|
139
|
+
deploySkill(skillDir)
|
|
140
|
+
installed.push({ platform, skillDir })
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// OpenClaw 额外注入 openclaw.json
|
|
144
|
+
if (platform === 'openclaw') {
|
|
145
|
+
injectOpenclawConfig(API_KEY)
|
|
146
|
+
}
|
|
97
147
|
}
|
|
98
|
-
console.log('✅ SkillFree skill 已安装到:')
|
|
99
|
-
SKILL_TARGETS.forEach(t => console.log(` ${t}`))
|
|
100
148
|
|
|
101
|
-
|
|
102
|
-
|
|
149
|
+
if (installed.length > 0) {
|
|
150
|
+
console.log('✅ SkillFree skill 已安装到:')
|
|
151
|
+
for (const { platform, skillDir } of installed) {
|
|
152
|
+
console.log(` [${platform}] ${skillDir}`)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
103
155
|
|
|
104
156
|
} catch (e) {
|
|
105
|
-
//
|
|
157
|
+
// 静默失败,不影响正常 npm 安装
|
|
106
158
|
}
|
package/scripts/commands/auth.js
CHANGED
|
@@ -4,15 +4,34 @@ const path = require('path')
|
|
|
4
4
|
const os = require('os')
|
|
5
5
|
const { saveConfig, BASE_URL } = require('../lib/client')
|
|
6
6
|
|
|
7
|
+
// ── 平台 → 技能安装路径映射(与 postinstall.js 保持一致)─────────────────
|
|
8
|
+
const PLATFORM_PATHS = {
|
|
9
|
+
openclaw: [
|
|
10
|
+
path.join(os.homedir(), '.openclaw', 'skills', 'skillfree'),
|
|
11
|
+
path.join(os.homedir(), '.agents', 'skills', 'skillfree'),
|
|
12
|
+
],
|
|
13
|
+
claude: [
|
|
14
|
+
path.join(os.homedir(), '.claude', 'skills', 'skillfree'),
|
|
15
|
+
],
|
|
16
|
+
codex: [
|
|
17
|
+
path.join(os.homedir(), '.codex', 'skills', 'skillfree'),
|
|
18
|
+
],
|
|
19
|
+
continue: [
|
|
20
|
+
path.join(os.homedir(), '.continue', 'skills', 'skillfree'),
|
|
21
|
+
],
|
|
22
|
+
cursor: [
|
|
23
|
+
path.join(os.homedir(), '.cursor', 'skills', 'skillfree'),
|
|
24
|
+
],
|
|
25
|
+
}
|
|
26
|
+
|
|
7
27
|
/**
|
|
8
|
-
* 将 apiKey
|
|
9
|
-
* 同时设置当前进程的 SKILLFREE_API_KEY 环境变量
|
|
28
|
+
* 将 apiKey 写入各平台配置 + shell 环境变量
|
|
10
29
|
*/
|
|
11
30
|
function injectToOpenclaw(apiKey) {
|
|
12
|
-
// 1. 写入 openclaw.json
|
|
31
|
+
// 1. OpenClaw: 写入 openclaw.json
|
|
13
32
|
const openclawDir = path.join(os.homedir(), '.openclaw')
|
|
14
33
|
const cfgPath = path.join(openclawDir, 'openclaw.json')
|
|
15
|
-
if (fs.existsSync(openclawDir)) {
|
|
34
|
+
if (fs.existsSync(openclawDir) && fs.existsSync(cfgPath)) {
|
|
16
35
|
let cfg = {}
|
|
17
36
|
try { cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8')) } catch {}
|
|
18
37
|
cfg.skills = cfg.skills || {}
|
|
@@ -41,7 +60,6 @@ function injectToOpenclaw(apiKey) {
|
|
|
41
60
|
if (fs.existsSync(f)) {
|
|
42
61
|
const content = fs.readFileSync(f, 'utf8')
|
|
43
62
|
if (content.includes('SKILLFREE_API_KEY')) {
|
|
44
|
-
// 替换已有行
|
|
45
63
|
const updated = content.replace(/\nexport SKILLFREE_API_KEY=.*\n?/g, exportLine)
|
|
46
64
|
fs.writeFileSync(f, updated)
|
|
47
65
|
} else {
|
|
@@ -53,7 +71,6 @@ function injectToOpenclaw(apiKey) {
|
|
|
53
71
|
}
|
|
54
72
|
}
|
|
55
73
|
if (!wrote) {
|
|
56
|
-
// 创建 .zshrc
|
|
57
74
|
fs.writeFileSync(shellFiles[0], `# SkillFree API Key${exportLine}`)
|
|
58
75
|
console.log('✅ ~/.zshrc 已创建并写入 SKILLFREE_API_KEY')
|
|
59
76
|
}
|