skillfree 0.1.68 → 0.1.70
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/SKILL.md +17 -1
- package/install.sh +13 -5
- package/package.json +1 -1
- package/postinstall.js +3 -0
- package/scripts/commands/auth.js +88 -36
package/SKILL.md
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skillfree
|
|
3
3
|
description: SkillFree — 模型与技能严选平台。只保留每个任务类型最强的模型,按实际用量精确计费。写代码用Claude,文档分析用GPT,多模态用Gemini,生图用nano banana,生视频用Veo,文档OCR用合合,网页搜索用Tavily,做PPT用AI演示文稿。
|
|
4
|
-
|
|
4
|
+
version: 0.1.69
|
|
5
|
+
author: SkillFree
|
|
6
|
+
license: MIT
|
|
7
|
+
metadata:
|
|
8
|
+
openclaw:
|
|
9
|
+
primaryEnv: SKILLFREE_API_KEY
|
|
10
|
+
emoji: "🦞"
|
|
11
|
+
homepage: https://skillfree.tech
|
|
12
|
+
requires:
|
|
13
|
+
bins: [skillfree]
|
|
14
|
+
env: [SKILLFREE_API_KEY]
|
|
15
|
+
hermes:
|
|
16
|
+
tags: [AI, LLM, Image, Video, OCR, PPT, Search, Pharma, Claude, GPT, Gemini]
|
|
17
|
+
homepage: https://skillfree.tech
|
|
18
|
+
prerequisites:
|
|
19
|
+
env: [SKILLFREE_API_KEY]
|
|
20
|
+
commands: [skillfree]
|
|
5
21
|
---
|
|
6
22
|
|
|
7
23
|
# SkillFree — 模型与技能严选平台 🦞
|
package/install.sh
CHANGED
|
@@ -63,18 +63,25 @@ echo ""
|
|
|
63
63
|
|
|
64
64
|
# 自动检测已安装的平台
|
|
65
65
|
DETECTED=()
|
|
66
|
-
[ -d "$HOME/.openclaw" ]
|
|
67
|
-
[ -d "$HOME/.claude" ]
|
|
68
|
-
[ -d "$HOME/.codex" ]
|
|
69
|
-
[ -d "$HOME/.
|
|
70
|
-
[ -d "$HOME/.cursor/extensions" ] && DETECTED+=("cursor")
|
|
66
|
+
[ -d "$HOME/.openclaw" ] && DETECTED+=("openclaw")
|
|
67
|
+
[ -d "$HOME/.claude" ] && DETECTED+=("claude")
|
|
68
|
+
[ -d "$HOME/.codex" ] && DETECTED+=("codex")
|
|
69
|
+
[ -d "$HOME/.hermes" ] && DETECTED+=("hermes")
|
|
71
70
|
|
|
72
71
|
echo -e " ${BOLD}可选平台:${NC}"
|
|
73
72
|
echo -e " ${CYAN} 1)${NC} OpenClaw ${DIM}→ ~/.openclaw/skills/skillfree/${NC}"
|
|
74
73
|
echo -e " ${CYAN} 2)${NC} Claude Code ${DIM}→ ~/.claude/skills/skillfree/${NC}"
|
|
75
74
|
echo -e " ${CYAN} 3)${NC} Codex CLI ${DIM}→ ~/.codex/skills/skillfree/${NC}"
|
|
75
|
+
echo -e " ${CYAN} 4)${NC} Hermes Agent ${DIM}→ ~/.hermes/skills/skillfree/${NC}"
|
|
76
76
|
echo ""
|
|
77
77
|
|
|
78
|
+
# 自动检测已安装的平台(只检测支持的4个)
|
|
79
|
+
DETECTED=()
|
|
80
|
+
[ -d "$HOME/.openclaw" ] && DETECTED+=("openclaw")
|
|
81
|
+
[ -d "$HOME/.claude" ] && DETECTED+=("claude")
|
|
82
|
+
[ -d "$HOME/.codex" ] && DETECTED+=("codex")
|
|
83
|
+
[ -d "$HOME/.hermes" ] && DETECTED+=("hermes")
|
|
84
|
+
|
|
78
85
|
if [ ${#DETECTED[@]} -gt 0 ]; then
|
|
79
86
|
echo -e " ${GREEN}已检测到:${DETECTED[*]}${NC}"
|
|
80
87
|
echo ""
|
|
@@ -101,6 +108,7 @@ else
|
|
|
101
108
|
1) SELECTED_PLATFORMS+=("openclaw") ;;
|
|
102
109
|
2) SELECTED_PLATFORMS+=("claude") ;;
|
|
103
110
|
3) SELECTED_PLATFORMS+=("codex") ;;
|
|
111
|
+
4) SELECTED_PLATFORMS+=("hermes") ;;
|
|
104
112
|
esac
|
|
105
113
|
done
|
|
106
114
|
fi
|
package/package.json
CHANGED
package/postinstall.js
CHANGED
package/scripts/commands/auth.js
CHANGED
|
@@ -4,36 +4,24 @@ 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
|
-
|
|
27
7
|
/**
|
|
28
|
-
* 将 apiKey
|
|
8
|
+
* 将 apiKey 注入到各平台配置 + shell 环境变量
|
|
9
|
+
*
|
|
10
|
+
* 各平台注入方式:
|
|
11
|
+
* openclaw → ~/.openclaw/openclaw.json (skills.entries.skillfree.apiKey)
|
|
12
|
+
* hermes → ~/.hermes/.env (SKILLFREE_API_KEY=xxx)
|
|
13
|
+
* claude → ~/.claude/settings.json (env.SKILLFREE_API_KEY)
|
|
14
|
+
* codex → 无专用配置,走 shell 环境变量即可
|
|
15
|
+
* 通用 → ~/.zshrc / ~/.bash_profile (export SKILLFREE_API_KEY=xxx)
|
|
29
16
|
*/
|
|
30
17
|
function injectToOpenclaw(apiKey) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
const HOME = os.homedir()
|
|
19
|
+
|
|
20
|
+
// ── 1. OpenClaw: 写入 openclaw.json ────────────────────────────────────────
|
|
21
|
+
const openclawCfgPath = path.join(HOME, '.openclaw', 'openclaw.json')
|
|
22
|
+
if (fs.existsSync(path.join(HOME, '.openclaw')) && fs.existsSync(openclawCfgPath)) {
|
|
35
23
|
let cfg = {}
|
|
36
|
-
try { cfg = JSON.parse(fs.readFileSync(
|
|
24
|
+
try { cfg = JSON.parse(fs.readFileSync(openclawCfgPath, 'utf8')) } catch {}
|
|
37
25
|
cfg.skills = cfg.skills || {}
|
|
38
26
|
cfg.skills.entries = cfg.skills.entries || {}
|
|
39
27
|
cfg.skills.entries['skillfree'] = {
|
|
@@ -42,38 +30,102 @@ function injectToOpenclaw(apiKey) {
|
|
|
42
30
|
apiKey,
|
|
43
31
|
}
|
|
44
32
|
try {
|
|
45
|
-
fs.writeFileSync(
|
|
46
|
-
console.log('✅ openclaw.json
|
|
33
|
+
fs.writeFileSync(openclawCfgPath, JSON.stringify(cfg, null, 2) + '\n')
|
|
34
|
+
console.log('✅ [OpenClaw] openclaw.json 已更新')
|
|
35
|
+
} catch (e) {
|
|
36
|
+
console.warn('⚠️ [OpenClaw] 无法写入 openclaw.json:', e.message)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── 2. Hermes: 写入 ~/.hermes/.env ─────────────────────────────────────────
|
|
41
|
+
const hermesDir = path.join(HOME, '.hermes')
|
|
42
|
+
if (fs.existsSync(hermesDir)) {
|
|
43
|
+
const hermesEnvPath = path.join(hermesDir, '.env')
|
|
44
|
+
_injectEnvFile(hermesEnvPath, 'SKILLFREE_API_KEY', apiKey)
|
|
45
|
+
console.log('✅ [Hermes] ~/.hermes/.env 已写入 SKILLFREE_API_KEY')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ── 3. Claude Code: 写入 ~/.claude/settings.json ───────────────────────────
|
|
49
|
+
const claudeDir = path.join(HOME, '.claude')
|
|
50
|
+
if (fs.existsSync(claudeDir)) {
|
|
51
|
+
const claudeSettingsPath = path.join(claudeDir, 'settings.json')
|
|
52
|
+
let settings = {}
|
|
53
|
+
if (fs.existsSync(claudeSettingsPath)) {
|
|
54
|
+
try { settings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf8')) } catch {}
|
|
55
|
+
}
|
|
56
|
+
settings.env = settings.env || {}
|
|
57
|
+
settings.env['SKILLFREE_API_KEY'] = apiKey
|
|
58
|
+
try {
|
|
59
|
+
fs.writeFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2) + '\n')
|
|
60
|
+
console.log('✅ [Claude Code] ~/.claude/settings.json 已写入 SKILLFREE_API_KEY')
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.warn('⚠️ [Claude Code] 无法写入 settings.json:', e.message)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── 4. Codex: 写入 ~/.codex/config.json ────────────────────────────────────
|
|
67
|
+
const codexDir = path.join(HOME, '.codex')
|
|
68
|
+
if (fs.existsSync(codexDir)) {
|
|
69
|
+
const codexCfgPath = path.join(codexDir, 'config.json')
|
|
70
|
+
let cfg = {}
|
|
71
|
+
if (fs.existsSync(codexCfgPath)) {
|
|
72
|
+
try { cfg = JSON.parse(fs.readFileSync(codexCfgPath, 'utf8')) } catch {}
|
|
73
|
+
}
|
|
74
|
+
cfg.env = cfg.env || {}
|
|
75
|
+
cfg.env['SKILLFREE_API_KEY'] = apiKey
|
|
76
|
+
try {
|
|
77
|
+
fs.writeFileSync(codexCfgPath, JSON.stringify(cfg, null, 2) + '\n')
|
|
78
|
+
console.log('✅ [Codex] ~/.codex/config.json 已写入 SKILLFREE_API_KEY')
|
|
47
79
|
} catch (e) {
|
|
48
|
-
console.warn('⚠️ 无法写入
|
|
80
|
+
console.warn('⚠️ [Codex] 无法写入 config.json:', e.message)
|
|
49
81
|
}
|
|
50
82
|
}
|
|
51
83
|
|
|
52
|
-
//
|
|
84
|
+
// ── 5. 通用:写入 shell 配置文件 ───────────────────────────────────────────
|
|
53
85
|
const exportLine = `\nexport SKILLFREE_API_KEY="${apiKey}"\n`
|
|
54
86
|
const shellFiles = [
|
|
55
|
-
path.join(
|
|
56
|
-
path.join(
|
|
87
|
+
path.join(HOME, '.zshrc'),
|
|
88
|
+
path.join(HOME, '.bash_profile'),
|
|
57
89
|
]
|
|
58
90
|
let wrote = false
|
|
59
91
|
for (const f of shellFiles) {
|
|
60
92
|
if (fs.existsSync(f)) {
|
|
61
93
|
const content = fs.readFileSync(f, 'utf8')
|
|
62
94
|
if (content.includes('SKILLFREE_API_KEY')) {
|
|
63
|
-
|
|
64
|
-
fs.writeFileSync(f, updated)
|
|
95
|
+
fs.writeFileSync(f, content.replace(/\nexport SKILLFREE_API_KEY=.*\n?/g, exportLine))
|
|
65
96
|
} else {
|
|
66
97
|
fs.appendFileSync(f, exportLine)
|
|
67
98
|
}
|
|
68
|
-
console.log(`✅ ${path.basename(f)} 已写入 SKILLFREE_API_KEY`)
|
|
99
|
+
console.log(`✅ [Shell] ${path.basename(f)} 已写入 SKILLFREE_API_KEY`)
|
|
69
100
|
wrote = true
|
|
70
101
|
break
|
|
71
102
|
}
|
|
72
103
|
}
|
|
73
104
|
if (!wrote) {
|
|
74
105
|
fs.writeFileSync(shellFiles[0], `# SkillFree API Key${exportLine}`)
|
|
75
|
-
console.log('✅ ~/.zshrc 已创建并写入 SKILLFREE_API_KEY')
|
|
106
|
+
console.log('✅ [Shell] ~/.zshrc 已创建并写入 SKILLFREE_API_KEY')
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 向 .env 文件注入或更新一个 KEY=value 行
|
|
112
|
+
*/
|
|
113
|
+
function _injectEnvFile(envPath, key, value) {
|
|
114
|
+
const line = `${key}="${value}"`
|
|
115
|
+
let content = ''
|
|
116
|
+
if (fs.existsSync(envPath)) {
|
|
117
|
+
content = fs.readFileSync(envPath, 'utf8')
|
|
118
|
+
if (content.includes(key + '=')) {
|
|
119
|
+
// 替换已有行
|
|
120
|
+
content = content.replace(new RegExp(`^${key}=.*$`, 'm'), line)
|
|
121
|
+
} else {
|
|
122
|
+
content = content.trimEnd() + '\n' + line + '\n'
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
content = line + '\n'
|
|
76
126
|
}
|
|
127
|
+
fs.mkdirSync(path.dirname(envPath), { recursive: true })
|
|
128
|
+
fs.writeFileSync(envPath, content)
|
|
77
129
|
}
|
|
78
130
|
|
|
79
131
|
function printQuickExamples() {
|