skillfree 0.1.19 → 0.1.21
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 +94 -112
- package/package.json +1 -1
- package/scripts/commands/auth.js +42 -27
- package/scripts/lib/client.js +8 -9
package/install.sh
CHANGED
|
@@ -1,136 +1,118 @@
|
|
|
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
|
|
13
24
|
echo ""
|
|
14
|
-
echo -e "${
|
|
15
|
-
|
|
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}"
|
|
16
37
|
echo ""
|
|
38
|
+
echo -e " ${DIM}────────────────────────────────────────────────────${NC}"
|
|
39
|
+
echo ""
|
|
40
|
+
|
|
41
|
+
# ── Step 1: 检查环境 ──────────────────────────────────────────────────────────
|
|
42
|
+
step "[ 1 / 3 ] 检查环境"
|
|
17
43
|
|
|
18
|
-
# ── 1. 检查 Node.js ──────────────────────────────────────────────────────────
|
|
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"
|
|
49
|
-
fi
|
|
50
|
-
export SKILLFREE_API_KEY="$API_KEY"
|
|
51
|
-
success "API Key 已写入 $SHELL_RC"
|
|
52
|
-
|
|
53
|
-
# ── 5. 自动配置各 AI 工具 ────────────────────────────────────────────────────
|
|
54
|
-
SKILL_SRC_DIR="$HOME/.skillfree/skill"
|
|
55
|
-
mkdir -p "$SKILL_SRC_DIR"
|
|
56
|
-
|
|
57
|
-
# 获取已安装包里的 SKILL.md(优先用本地,否则下载)
|
|
58
|
-
NPM_SKILL_MD="$(npm root -g 2>/dev/null)/skillfree/SKILL.md"
|
|
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"
|
|
68
|
+
echo ""
|
|
69
|
+
warn "权限不足,尝试 sudo..."
|
|
70
|
+
echo ""
|
|
71
|
+
if sudo npm install -g skillfree 2>&1 | sed 's/^/ /'; then
|
|
72
|
+
INSTALL_OK=true
|
|
64
73
|
fi
|
|
74
|
+
fi
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
mkdir -p "$OPENCLAW_SKILLS_DIR"
|
|
70
|
-
cp "$SKILL_SRC_DIR/SKILL.md" "$OPENCLAW_SKILLS_DIR/SKILL.md"
|
|
71
|
-
success "OpenClaw skill 已安装 → $OPENCLAW_SKILLS_DIR/"
|
|
76
|
+
if [ "$INSTALL_OK" = false ]; then
|
|
77
|
+
err "安装失败,请手动运行:sudo npm install -g skillfree"
|
|
78
|
+
fi
|
|
72
79
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
node - <<NODEJS
|
|
76
|
-
const fs = require('fs'), path = require('path')
|
|
77
|
-
const cfgPath = '$OPENCLAW_CFG'
|
|
78
|
-
let cfg = {}
|
|
79
|
-
try { cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8')) } catch {}
|
|
80
|
-
cfg.skills = cfg.skills || {}
|
|
81
|
-
cfg.skills.entries = cfg.skills.entries || {}
|
|
82
|
-
cfg.skills.entries['skillfree'] = {
|
|
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
|
|
80
|
+
echo ""
|
|
81
|
+
success "SkillFree CLI 安装完成"
|
|
94
82
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
mkdir -p "$dir/skillfree"
|
|
99
|
-
cp "$SKILL_SRC_DIR/SKILL.md" "$dir/skillfree/SKILL.md"
|
|
100
|
-
success "已同步到 $dir/skillfree/"
|
|
101
|
-
fi
|
|
102
|
-
done
|
|
83
|
+
# 刷新 PATH(nvm 等工具安装后 CLI 可能还不在当前 shell 的 PATH 里)
|
|
84
|
+
hash -r 2>/dev/null || true
|
|
85
|
+
export PATH="$(npm root -g)/../bin:$PATH"
|
|
103
86
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
87
|
+
if ! command -v skillfree &>/dev/null; then
|
|
88
|
+
warn "CLI 已安装,但当前终端 PATH 未更新"
|
|
89
|
+
warn "请新开一个终端窗口,然后运行:skillfree auth login"
|
|
90
|
+
echo ""
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
110
93
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
94
|
+
# ── Step 3: 登录 ──────────────────────────────────────────────────────────────
|
|
95
|
+
step "[ 3 / 3 ] 登录账号"
|
|
96
|
+
echo ""
|
|
97
|
+
echo -e " 还没有账号?${CYAN}https://skillfree.tech/app${NC} 免费注册"
|
|
98
|
+
echo -e " 注册后进入控制台 → API Keys → 创建一个 Key,粘贴到下方"
|
|
99
|
+
echo ""
|
|
117
100
|
|
|
118
|
-
|
|
119
|
-
if [ -d "$HOME/.continue" ]; then
|
|
120
|
-
mkdir -p "$HOME/.continue/skills/skillfree"
|
|
121
|
-
cp "$SKILL_SRC_DIR/SKILL.md" "$HOME/.continue/skills/skillfree/SKILL.md"
|
|
122
|
-
success "Continue.dev 配置完成 → ~/.continue/skills/skillfree/"
|
|
123
|
-
fi
|
|
124
|
-
fi
|
|
101
|
+
skillfree auth login
|
|
125
102
|
|
|
126
|
-
# ──
|
|
103
|
+
# ── 完成 ──────────────────────────────────────────────────────────────────────
|
|
104
|
+
echo ""
|
|
105
|
+
echo -e " ${DIM}────────────────────────────────────────────────────${NC}"
|
|
106
|
+
echo ""
|
|
107
|
+
echo -e "${BOLD_GREEN} 🎉 全部搞定!开始召唤龙虾吧${NC}"
|
|
127
108
|
echo ""
|
|
128
|
-
echo -e "${
|
|
109
|
+
echo -e " ${BOLD}快速体验:${NC}"
|
|
110
|
+
echo -e " ${CYAN} $ skillfree pilot --type chat --prompt \"你好\"${NC}"
|
|
111
|
+
echo -e " ${CYAN} $ skillfree pilot --type image --prompt \"赛博朋克的上海\" --output ./img.png${NC}"
|
|
112
|
+
echo -e " ${CYAN} $ skillfree pilot --type search --prompt \"今天的 AI 新闻\"${NC}"
|
|
129
113
|
echo ""
|
|
130
|
-
echo -e " ${
|
|
131
|
-
echo -e " $
|
|
132
|
-
echo -e " $ skillfree pilot --type image --prompt \"赛博朋克的上海\" --output ./img.png"
|
|
114
|
+
echo -e " ${DIM} skillfree models # 查看所有模型${NC}"
|
|
115
|
+
echo -e " ${DIM} skillfree credits # 查看积分余额${NC}"
|
|
133
116
|
echo ""
|
|
134
|
-
echo -e " ${
|
|
135
|
-
echo -e " ${CYAN}查看文档:${NC} https://skillfree.tech/app/docs"
|
|
117
|
+
echo -e " ${DIM}充值积分:${NC}${CYAN}https://skillfree.tech/app/topup${NC}"
|
|
136
118
|
echo ""
|
package/package.json
CHANGED
package/scripts/commands/auth.js
CHANGED
|
@@ -61,40 +61,55 @@ 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
|
-
|
|
76
|
-
|
|
74
|
+
if (key === 'q' || key === '') {
|
|
75
|
+
console.log('\n⏭ 已跳过登录,稍后可运行 skillfree auth login 完成配置')
|
|
76
|
+
rl.close()
|
|
77
|
+
return
|
|
78
|
+
}
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
+
}
|
|
97
110
|
}
|
|
111
|
+
|
|
112
|
+
rl.close()
|
|
98
113
|
}
|
|
99
114
|
|
|
100
115
|
async function authStatus() {
|
package/scripts/lib/client.js
CHANGED
|
@@ -36,26 +36,25 @@ const LOW_CREDITS_THRESHOLD = 100
|
|
|
36
36
|
|
|
37
37
|
function formatLowCreditsWarning(credits) {
|
|
38
38
|
return `
|
|
39
|
-
⚠️
|
|
39
|
+
⚠️ 积分余额偏低(当前积分:${credits}),建议尽快充值,避免中断使用。
|
|
40
40
|
|
|
41
41
|
💳 充值流程:
|
|
42
42
|
1. 打开浏览器,访问 https://skillfree.tech/app/billing
|
|
43
43
|
2. 选择充值套餐(推荐 ¥30 = 350积分,性价比最高)
|
|
44
44
|
3. 微信扫码支付,积分自动到账(约 3 秒)
|
|
45
|
-
4. 充值后继续使用 skillfree 命令即可
|
|
46
45
|
|
|
47
46
|
📦 套餐参考:
|
|
48
47
|
¥10 → 100 积分
|
|
49
48
|
¥30 → 350 积分(多送 50)
|
|
50
49
|
¥100 → 1300 积分(多送 300)
|
|
51
50
|
¥300 → 4500 积分(多送 1500)
|
|
52
|
-
|
|
53
|
-
积分永不过期,无月费无订阅。`
|
|
51
|
+
`
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
55
|
+
* 主动检查积分余额:
|
|
56
|
+
* < LOW_CREDITS_THRESHOLD → 打印警告,但继续执行(不抛错)
|
|
57
|
+
* 真正积分不够扣时由服务器返回 402,在 request() 里处理
|
|
59
58
|
*/
|
|
60
59
|
async function checkCredits() {
|
|
61
60
|
const apiKey = getApiKey()
|
|
@@ -68,11 +67,11 @@ async function checkCredits() {
|
|
|
68
67
|
const data = await res.json()
|
|
69
68
|
const credits = data.credits ?? data.balance ?? 0
|
|
70
69
|
if (credits < LOW_CREDITS_THRESHOLD) {
|
|
71
|
-
|
|
70
|
+
// 只打印警告,不抛错,继续执行
|
|
71
|
+
console.warn(formatLowCreditsWarning(credits))
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
} catch (e) {
|
|
75
|
-
if (e.message.includes('积分不足')) throw e
|
|
76
75
|
// 网络失败等忽略,不阻塞用户
|
|
77
76
|
}
|
|
78
77
|
}
|
|
@@ -94,7 +93,7 @@ async function request(endpoint, options = {}) {
|
|
|
94
93
|
},
|
|
95
94
|
})
|
|
96
95
|
|
|
97
|
-
if (res.status === 402) throw new Error(
|
|
96
|
+
if (res.status === 402) throw new Error(`❌ 积分不足,本次调用无法完成。\n\n💳 充值流程:\n 1. 访问 https://skillfree.tech/app/billing\n 2. 选择套餐(推荐 ¥30 = 350积分),微信扫码支付,约 3 秒到账`)
|
|
98
97
|
if (res.status === 401) throw new Error('API Key 无效或已过期,请重新登录: skillfree auth login')
|
|
99
98
|
|
|
100
99
|
return res
|