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 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
- metadata: {"openclaw": {"primaryEnv": "SKILLFREE_API_KEY", "emoji": "🦞", "homepage": "https://skillfree.tech", "requires": {"bins": ["skillfree"], "env": ["SKILLFREE_API_KEY"]}}}
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" ] && 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")
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillfree",
3
- "version": "0.1.68",
3
+ "version": "0.1.70",
4
4
  "description": "🦞 一个 API,满足所有龙虾技能需求",
5
5
  "main": "bin/skillfree.js",
6
6
  "bin": {
package/postinstall.js CHANGED
@@ -33,6 +33,9 @@ const PLATFORM_PATHS = {
33
33
  codex: [
34
34
  path.join(HOME, '.codex', 'skills', 'skillfree'),
35
35
  ],
36
+ hermes: [
37
+ path.join(HOME, '.hermes', 'skills', 'skillfree'),
38
+ ],
36
39
  }
37
40
 
38
41
  // 解析目标平台
@@ -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 写入各平台配置 + shell 环境变量
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
- // 1. OpenClaw: 写入 openclaw.json
32
- const openclawDir = path.join(os.homedir(), '.openclaw')
33
- const cfgPath = path.join(openclawDir, 'openclaw.json')
34
- if (fs.existsSync(openclawDir) && fs.existsSync(cfgPath)) {
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(cfgPath, 'utf8')) } catch {}
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(cfgPath, JSON.stringify(cfg, null, 2) + '\n')
46
- console.log('✅ openclaw.json 已更新,OpenClaw 下次启动自动识别 skillfree skill')
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('⚠️ 无法写入 openclaw.json(权限问题?):', e.message)
80
+ console.warn('⚠️ [Codex] 无法写入 config.json', e.message)
49
81
  }
50
82
  }
51
83
 
52
- // 2. 写入 shell 配置文件(~/.zshrc 或 ~/.bash_profile)
84
+ // ── 5. 通用:写入 shell 配置文件 ───────────────────────────────────────────
53
85
  const exportLine = `\nexport SKILLFREE_API_KEY="${apiKey}"\n`
54
86
  const shellFiles = [
55
- path.join(os.homedir(), '.zshrc'),
56
- path.join(os.homedir(), '.bash_profile'),
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
- const updated = content.replace(/\nexport SKILLFREE_API_KEY=.*\n?/g, exportLine)
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() {