skillfree 0.1.20 → 0.1.22
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/bin/skillfree.js +7 -0
- package/install.sh +127 -108
- package/package.json +1 -1
- package/scripts/commands/auth.js +55 -26
package/bin/skillfree.js
CHANGED
|
@@ -18,6 +18,13 @@ auth
|
|
|
18
18
|
const { authLogin } = require('../scripts/commands/auth')
|
|
19
19
|
await authLogin()
|
|
20
20
|
})
|
|
21
|
+
auth
|
|
22
|
+
.command('save <apiKey>')
|
|
23
|
+
.description('直接保存 API Key(供安装脚本调用)')
|
|
24
|
+
.action(async (apiKey) => {
|
|
25
|
+
const { authSave } = require('../scripts/commands/auth')
|
|
26
|
+
await authSave(apiKey)
|
|
27
|
+
})
|
|
21
28
|
auth
|
|
22
29
|
.command('status')
|
|
23
30
|
.description('查看当前登录状态和积分')
|
package/install.sh
CHANGED
|
@@ -1,136 +1,155 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# curl -fsSL https://
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
# SkillFree 一键安装脚本
|
|
3
|
+
# curl -fsSL https://cdn.jsdelivr.net/gh/ChongC1990/install@main/install.sh | bash
|
|
4
|
+
|
|
5
|
+
# ── 颜色定义 ─────────────────────────────────────────────────────────────────
|
|
6
|
+
CYAN='\033[0;36m'
|
|
7
|
+
BOLD_CYAN='\033[1;36m'
|
|
8
|
+
GREEN='\033[0;32m'
|
|
9
|
+
BOLD_GREEN='\033[1;32m'
|
|
10
|
+
YELLOW='\033[1;33m'
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
BOLD='\033[1m'
|
|
13
|
+
DIM='\033[2m'
|
|
14
|
+
NC='\033[0m'
|
|
15
|
+
|
|
16
|
+
info() { echo -e "${CYAN} →${NC} $*"; }
|
|
17
|
+
success() { echo -e "${BOLD_GREEN} ✓${NC} $*"; }
|
|
18
|
+
warn() { echo -e "${YELLOW} ⚠${NC} $*"; }
|
|
19
|
+
err() { echo -e "${RED} ✗${NC} $*"; exit 1; }
|
|
20
|
+
step() { echo -e "\n${BOLD}$*${NC}"; }
|
|
21
|
+
|
|
22
|
+
# ── ASCII Banner ──────────────────────────────────────────────────────────────
|
|
23
|
+
clear
|
|
24
|
+
echo ""
|
|
25
|
+
echo -e "${BOLD_CYAN}"
|
|
26
|
+
cat << 'EOF'
|
|
27
|
+
███████╗██╗ ██╗██╗██╗ ██╗ ███████╗██████╗ ███████╗███████╗
|
|
28
|
+
██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝██╔══██╗██╔════╝██╔════╝
|
|
29
|
+
███████╗█████╔╝ ██║██║ ██║ █████╗ ██████╔╝█████╗ █████╗
|
|
30
|
+
╚════██║██╔═██╗ ██║██║ ██║ ██╔══╝ ██╔══██╗██╔══╝ ██╔══╝
|
|
31
|
+
███████║██║ ██╗██║███████╗███████╗██║ ██║ ██║███████╗███████╗
|
|
32
|
+
╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝
|
|
33
|
+
EOF
|
|
34
|
+
echo -e "${NC}"
|
|
35
|
+
echo -e " ${DIM}🦞 一个 Key,调用 53+ 顶级 AI 模型${NC}"
|
|
36
|
+
echo -e " ${DIM} Chat · Image · Video · TTS · Music · OCR · Search${NC}"
|
|
13
37
|
echo ""
|
|
14
|
-
echo -e "${
|
|
15
|
-
echo -e " 一个 API,满足所有龙虾技能需求"
|
|
38
|
+
echo -e " ${DIM}────────────────────────────────────────────────────${NC}"
|
|
16
39
|
echo ""
|
|
17
40
|
|
|
18
|
-
# ── 1
|
|
41
|
+
# ── Step 1: 检查环境 ──────────────────────────────────────────────────────────
|
|
42
|
+
step "[ 1 / 3 ] 检查环境"
|
|
43
|
+
|
|
19
44
|
if ! command -v node &>/dev/null; then
|
|
20
|
-
err "
|
|
45
|
+
err "未检测到 Node.js,请先安装:https://nodejs.org(需要 18+)"
|
|
21
46
|
fi
|
|
22
47
|
NODE_VER=$(node -e "process.stdout.write(process.versions.node.split('.')[0])")
|
|
23
|
-
[ "$NODE_VER" -lt 18 ]
|
|
48
|
+
if [ "$NODE_VER" -lt 18 ]; then
|
|
49
|
+
err "Node.js 版本过低(当前 v$(node -v)),需要 18+"
|
|
50
|
+
fi
|
|
51
|
+
success "Node.js $(node -v)"
|
|
24
52
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|| warn "全局安装需要权限,尝试 sudo npm install -g skillfree"
|
|
30
|
-
success "CLI 安装完成"
|
|
53
|
+
if ! command -v npm &>/dev/null; then
|
|
54
|
+
err "未检测到 npm,请检查 Node.js 安装"
|
|
55
|
+
fi
|
|
56
|
+
success "npm $(npm -v)"
|
|
31
57
|
|
|
32
|
-
# ──
|
|
58
|
+
# ── Step 2: 安装 CLI ──────────────────────────────────────────────────────────
|
|
59
|
+
step "[ 2 / 3 ] 安装 SkillFree CLI"
|
|
60
|
+
echo ""
|
|
61
|
+
echo -e " ${DIM}正在从 npm 安装 skillfree...${NC}"
|
|
33
62
|
echo ""
|
|
34
|
-
echo -e " 请前往 ${CYAN}https://skillfree.tech/app${NC} 获取 API Key"
|
|
35
|
-
read -rp " 输入你的 API Key (sk-sf-...): " API_KEY
|
|
36
63
|
|
|
37
|
-
|
|
38
|
-
|
|
64
|
+
INSTALL_OK=false
|
|
65
|
+
if npm install -g skillfree 2>&1 | sed 's/^/ /'; then
|
|
66
|
+
INSTALL_OK=true
|
|
39
67
|
else
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if
|
|
44
|
-
|
|
45
|
-
echo "# SkillFree" >> "$SHELL_RC"
|
|
46
|
-
echo "export SKILLFREE_API_KEY=\"$API_KEY\"" >> "$SHELL_RC"
|
|
47
|
-
else
|
|
48
|
-
sed -i.bak "s/export SKILLFREE_API_KEY=.*/export SKILLFREE_API_KEY=\"$API_KEY\"/" "$SHELL_RC"
|
|
68
|
+
echo ""
|
|
69
|
+
warn "权限不足,尝试 sudo..."
|
|
70
|
+
echo ""
|
|
71
|
+
if sudo npm install -g skillfree 2>&1 | sed 's/^/ /'; then
|
|
72
|
+
INSTALL_OK=true
|
|
49
73
|
fi
|
|
50
|
-
|
|
51
|
-
success "API Key 已写入 $SHELL_RC"
|
|
74
|
+
fi
|
|
52
75
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
76
|
+
if [ "$INSTALL_OK" = false ]; then
|
|
77
|
+
err "安装失败,请手动运行:sudo npm install -g skillfree"
|
|
78
|
+
fi
|
|
56
79
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if [ -f "$NPM_SKILL_MD" ]; then
|
|
60
|
-
cp "$NPM_SKILL_MD" "$SKILL_SRC_DIR/SKILL.md"
|
|
61
|
-
else
|
|
62
|
-
curl -fsSL "https://skillfree.tech/skill/SKILL.md" -o "$SKILL_SRC_DIR/SKILL.md" 2>/dev/null \
|
|
63
|
-
|| echo "# SkillFree\nUse skillfree CLI for AI tasks." > "$SKILL_SRC_DIR/SKILL.md"
|
|
64
|
-
fi
|
|
80
|
+
echo ""
|
|
81
|
+
success "SkillFree CLI 安装完成"
|
|
65
82
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
enabled: true,
|
|
84
|
-
apiKey: '$API_KEY'
|
|
85
|
-
}
|
|
86
|
-
// 确保 ~/.openclaw/skills 在扫描路径里(通常已内置,但加上无妨)
|
|
87
|
-
cfg.skills.load = cfg.skills.load || {}
|
|
88
|
-
fs.mkdirSync(path.dirname(cfgPath), { recursive: true })
|
|
89
|
-
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2))
|
|
90
|
-
console.log('openclaw.json 已更新')
|
|
91
|
-
NODEJS
|
|
92
|
-
success "openclaw.json 已注入 API Key(skill 下次启动自动生效)"
|
|
93
|
-
fi
|
|
83
|
+
# 刷新 PATH
|
|
84
|
+
hash -r 2>/dev/null || true
|
|
85
|
+
export PATH="$(npm root -g)/../bin:$PATH"
|
|
86
|
+
|
|
87
|
+
if ! command -v skillfree &>/dev/null; then
|
|
88
|
+
warn "CLI 已安装,但当前终端 PATH 未更新"
|
|
89
|
+
warn "请新开一个终端窗口,然后运行:skillfree auth login"
|
|
90
|
+
echo ""
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# ── Step 3: 登录(从 /dev/tty 读取,兼容 curl | bash)────────────────────────
|
|
95
|
+
step "[ 3 / 3 ] 登录账号"
|
|
96
|
+
echo ""
|
|
97
|
+
echo -e " 还没有账号?${CYAN}https://skillfree.tech/app${NC} 免费注册"
|
|
98
|
+
echo -e " 注册后进入控制台 → ${BOLD}API Keys${NC} → 创建一个 Key,粘贴到下方"
|
|
99
|
+
echo ""
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
mkdir -p "$HOME/.claude/skills/skillfree"
|
|
107
|
-
cp "$SKILL_SRC_DIR/SKILL.md" "$HOME/.claude/skills/skillfree/SKILL.md"
|
|
108
|
-
success "Claude Code 配置完成 → ~/.claude/skills/skillfree/"
|
|
101
|
+
API_KEY=""
|
|
102
|
+
while true; do
|
|
103
|
+
# 强制从 /dev/tty 读取,避免 curl | bash 时 stdin 被占用
|
|
104
|
+
printf " 请粘贴 API Key (sk-sf-...),输入 q 跳过: "
|
|
105
|
+
read -r API_KEY </dev/tty
|
|
106
|
+
|
|
107
|
+
if [ "$API_KEY" = "q" ] || [ -z "$API_KEY" ]; then
|
|
108
|
+
echo ""
|
|
109
|
+
warn "已跳过登录,稍后可运行 ${CYAN}skillfree auth login${NC} 完成配置"
|
|
110
|
+
API_KEY=""
|
|
111
|
+
break
|
|
109
112
|
fi
|
|
110
113
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
cp "$SKILL_SRC_DIR/SKILL.md" "$HOME/.codex/skills/skillfree/SKILL.md"
|
|
115
|
-
success "Codex 配置完成 → ~/.codex/skills/skillfree/"
|
|
114
|
+
if [[ "$API_KEY" != sk-sf-* ]]; then
|
|
115
|
+
echo -e " ${RED}✗${NC} 格式不对,Key 应以 sk-sf- 开头,请重试\n"
|
|
116
|
+
continue
|
|
116
117
|
fi
|
|
117
118
|
|
|
118
|
-
#
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
# 验证 Key
|
|
120
|
+
printf " 验证中..."
|
|
121
|
+
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
122
|
+
-H "Authorization: Bearer $API_KEY" \
|
|
123
|
+
"https://skillfree.tech/v1/balance")
|
|
124
|
+
|
|
125
|
+
if [ "$HTTP_CODE" = "200" ]; then
|
|
126
|
+
echo -e " ${GREEN}✓${NC}"
|
|
127
|
+
break
|
|
128
|
+
else
|
|
129
|
+
echo -e " ${RED}✗${NC} (HTTP $HTTP_CODE)"
|
|
130
|
+
echo -e " ${RED}✗${NC} Key 无效,请检查后重试\n"
|
|
131
|
+
API_KEY=""
|
|
123
132
|
fi
|
|
133
|
+
done
|
|
134
|
+
|
|
135
|
+
# 有效 Key → 交给 CLI 写入配置
|
|
136
|
+
if [ -n "$API_KEY" ]; then
|
|
137
|
+
SKILLFREE_API_KEY="$API_KEY" skillfree auth save "$API_KEY"
|
|
124
138
|
fi
|
|
125
139
|
|
|
126
|
-
# ──
|
|
140
|
+
# ── 完成 ──────────────────────────────────────────────────────────────────────
|
|
141
|
+
echo ""
|
|
142
|
+
echo -e " ${DIM}────────────────────────────────────────────────────${NC}"
|
|
143
|
+
echo ""
|
|
144
|
+
echo -e "${BOLD_GREEN} 🎉 全部搞定!开始召唤龙虾吧${NC}"
|
|
127
145
|
echo ""
|
|
128
|
-
echo -e "${
|
|
146
|
+
echo -e " ${BOLD}快速体验:${NC}"
|
|
147
|
+
echo -e " ${CYAN} $ skillfree pilot --type chat --prompt \"你好\"${NC}"
|
|
148
|
+
echo -e " ${CYAN} $ skillfree pilot --type image --prompt \"赛博朋克的上海\" --output ./img.png${NC}"
|
|
149
|
+
echo -e " ${CYAN} $ skillfree pilot --type search --prompt \"今天的 AI 新闻\"${NC}"
|
|
129
150
|
echo ""
|
|
130
|
-
echo -e " ${
|
|
131
|
-
echo -e " $
|
|
132
|
-
echo -e " $ skillfree pilot --type image --prompt \"赛博朋克的上海\" --output ./img.png"
|
|
151
|
+
echo -e " ${DIM} skillfree models # 查看所有模型${NC}"
|
|
152
|
+
echo -e " ${DIM} skillfree credits # 查看积分余额${NC}"
|
|
133
153
|
echo ""
|
|
134
|
-
echo -e " ${
|
|
135
|
-
echo -e " ${CYAN}查看文档:${NC} https://skillfree.tech/app/docs"
|
|
154
|
+
echo -e " ${DIM}充值积分:${NC}${CYAN}https://skillfree.tech/app/topup${NC}"
|
|
136
155
|
echo ""
|
package/package.json
CHANGED
package/scripts/commands/auth.js
CHANGED
|
@@ -61,40 +61,68 @@ function injectToOpenclaw(apiKey) {
|
|
|
61
61
|
|
|
62
62
|
async function authLogin() {
|
|
63
63
|
console.log(`\n🦞 SkillFree 登录`)
|
|
64
|
-
console.log(`
|
|
64
|
+
console.log(` 还没有账号?前往注册:${BASE_URL}/app`)
|
|
65
|
+
console.log(` 注册后在控制台 → API Keys → 创建 Key\n`)
|
|
65
66
|
|
|
66
67
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
|
|
67
68
|
const ask = (q) => new Promise(resolve => rl.question(q, resolve))
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
let success = false
|
|
71
|
+
while (!success) {
|
|
72
|
+
const key = (await ask('请粘贴 API Key (sk-sf-...),输入 q 跳过: ')).trim()
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
if (key === 'q' || key === '') {
|
|
75
|
+
console.log('\n⏭ 已跳过登录,稍后可运行 skillfree auth login 完成配置')
|
|
76
|
+
rl.close()
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!key.startsWith('sk-sf-')) {
|
|
81
|
+
console.log('❌ 格式不对,Key 应以 sk-sf- 开头,请重新输入\n')
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 验证 key 是否有效
|
|
86
|
+
process.stdout.write('验证中...')
|
|
87
|
+
try {
|
|
88
|
+
const res = await fetch(`${BASE_URL}/v1/balance`, {
|
|
89
|
+
headers: { 'Authorization': `Bearer ${key}` }
|
|
90
|
+
})
|
|
91
|
+
if (!res.ok) {
|
|
92
|
+
console.log(` ❌ (HTTP ${res.status})`)
|
|
93
|
+
console.log('API Key 无效,请检查后重新输入\n')
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
const data = await res.json()
|
|
97
|
+
saveConfig({ apiKey: key })
|
|
98
|
+
injectToOpenclaw(key)
|
|
99
|
+
console.log(` ✅\n`)
|
|
100
|
+
console.log(`🎉 登录成功!当前积分:${data.credits}`)
|
|
101
|
+
console.log(`\n快速开始:`)
|
|
102
|
+
console.log(` skillfree pilot --type chat --model DeepSeek-V3.2-Fast --prompt "你好"`)
|
|
103
|
+
console.log(` skillfree pilot --type chat --model claude-sonnet-4-6 --prompt "你好"`)
|
|
104
|
+
console.log(` skillfree models # 查看所有可用模型`)
|
|
105
|
+
success = true
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.log(` ❌`)
|
|
108
|
+
console.log(`网络错误(${e.message}),请检查网络后重试\n`)
|
|
109
|
+
}
|
|
76
110
|
}
|
|
77
111
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!res.ok) throw new Error(res.status)
|
|
85
|
-
const data = await res.json()
|
|
86
|
-
saveConfig({ apiKey: key })
|
|
87
|
-
injectToOpenclaw(key)
|
|
88
|
-
console.log(` ✅\n`)
|
|
89
|
-
console.log(`🎉 登录成功!当前积分:${data.credits}`)
|
|
90
|
-
console.log(`\n快速开始:`)
|
|
91
|
-
console.log(` skillfree pilot --type chat --model DeepSeek-V3.2-Fast --prompt "你好"`)
|
|
92
|
-
console.log(` skillfree pilot --type chat --model claude-sonnet-4-6 --prompt "你好"`)
|
|
93
|
-
console.log(` skillfree models # 查看所有可用模型`)
|
|
94
|
-
} catch (e) {
|
|
95
|
-
console.log(` ❌\nAPI Key 无效,请重新检查`)
|
|
112
|
+
rl.close()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function authSave(apiKey) {
|
|
116
|
+
if (!apiKey || !apiKey.startsWith('sk-sf-')) {
|
|
117
|
+
console.error('❌ Key 格式不正确')
|
|
96
118
|
process.exit(1)
|
|
97
119
|
}
|
|
120
|
+
saveConfig({ apiKey })
|
|
121
|
+
injectToOpenclaw(apiKey)
|
|
122
|
+
console.log(`\n🎉 登录成功!`)
|
|
123
|
+
console.log(`\n快速开始:`)
|
|
124
|
+
console.log(` skillfree pilot --type chat --prompt "你好"`)
|
|
125
|
+
console.log(` skillfree models # 查看所有可用模型`)
|
|
98
126
|
}
|
|
99
127
|
|
|
100
128
|
async function authStatus() {
|
|
@@ -117,4 +145,5 @@ async function authStatus() {
|
|
|
117
145
|
console.log(` Key:${key.slice(0, 10)}****${key.slice(-4)}`)
|
|
118
146
|
}
|
|
119
147
|
|
|
120
|
-
module.exports = { authLogin, authStatus }
|
|
148
|
+
module.exports = { authLogin, authSave, authStatus }
|
|
149
|
+
|