@simonyea/holysheep-cli 1.5.2 → 1.5.4

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/README.md CHANGED
@@ -188,6 +188,15 @@ A: OpenClaw 需要 Node.js 20+,运行 `node --version` 确认版本后重试
188
188
 
189
189
  ---
190
190
 
191
+ ## Changelog
192
+
193
+ - **v1.5.2** — OpenClaw 安装失败(无 git 环境)时自动降级为 npx 模式继续配置
194
+ - **v1.5.0** — OpenClaw gateway 无需 token,直接浏览器打开 http://127.0.0.1:18789/
195
+ - **v1.4.6** — 基于实测正确配置格式,彻底修复 OpenClaw 401 认证问题
196
+ - **v1.3.x** — OpenClaw 一键配置支持,自动写入配置并启动 Gateway
197
+
198
+ ---
199
+
191
200
  ## License
192
201
 
193
202
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "一键配置所有 AI 编程工具接入 HolySheep API — Claude Code / Codex / Gemini CLI / OpenCode / OpenClaw / Aider / Cursor",
5
5
  "keywords": [
6
6
  "claude",
@@ -17,7 +17,7 @@
17
17
  "ai",
18
18
  "coding"
19
19
  ],
20
- "homepage": "https://shop.holysheep.ai",
20
+ "homepage": "https://holysheep.ai",
21
21
  "repository": {
22
22
  "type": "git",
23
23
  "url": "https://github.com/holysheep123/holysheep-cli"
@@ -72,7 +72,8 @@ async function setup(options) {
72
72
 
73
73
  if (!apiKey) {
74
74
  console.log(chalk.yellow('需要 API Key 才能配置工具。'))
75
- console.log(chalk.cyan(`还没有账号?前往注册:${SHOP_URL}`))
75
+ console.log(chalk.cyan(`👉 免费注册获取 Key:${SHOP_URL}/register`))
76
+ console.log(chalk.gray(` (¥10 起充,按量计费,支持微信/支付宝)`))
76
77
  console.log(chalk.gray(`提示:可先运行 ${chalk.cyan('hs login')} 登录并保存 Key,之后 setup 将自动读取。`))
77
78
  if (process.platform === 'win32') {
78
79
  console.log(chalk.gray(` ⚠️ Windows 用户:如果 ${chalk.cyan('hs')} 命令找不到,请用以下方式运行:`))
@@ -89,9 +90,40 @@ async function setup(options) {
89
90
  }])
90
91
  apiKey = key
91
92
  } else {
92
- console.log(`${chalk.green('✓')} 使用已保存的 API Key: ${chalk.cyan(maskKey(apiKey))}`)
93
+ console.log(`${chalk.green('✓')} 已保存的 API Key: ${chalk.cyan(maskKey(apiKey))}`)
94
+ const { useExisting } = await inquirer.prompt([{
95
+ type: 'confirm',
96
+ name: 'useExisting',
97
+ message: '使用此 Key 继续?(输入 N 可更换)',
98
+ default: true,
99
+ }])
100
+ if (!useExisting) {
101
+ const { key } = await inquirer.prompt([{
102
+ type: 'password',
103
+ name: 'key',
104
+ message: '请输入新的 API Key (cr_xxx):',
105
+ validate: v => v.startsWith('cr_') ? true : '请输入以 cr_ 开头的 API Key',
106
+ }])
107
+ apiKey = key
108
+ saveConfig({ apiKey: key })
109
+ }
93
110
  }
94
111
 
112
+ // Step 1.5: 选择要配置的模型
113
+ const MODEL_CHOICES = [
114
+ { name: 'claude-sonnet-4-6 (Sonnet 4.6, 均衡推荐)', value: 'claude-sonnet-4-6', checked: true },
115
+ { name: 'claude-opus-4-6 (Opus 4.6, 强力旗舰)', value: 'claude-opus-4-6', checked: true },
116
+ { name: 'MiniMax-M2.5-highspeed (高速经济版)', value: 'MiniMax-M2.5-highspeed', checked: true },
117
+ ]
118
+ const { selectedModels } = await inquirer.prompt([{
119
+ type: 'checkbox',
120
+ name: 'selectedModels',
121
+ message: '选择要配置的模型(默认全选,空格取消选中):',
122
+ choices: MODEL_CHOICES,
123
+ pageSize: 5,
124
+ }])
125
+ const primaryModel = selectedModels.find(m => m.startsWith('claude-')) || selectedModels[0] || 'claude-sonnet-4-6'
126
+
95
127
  // Step 2: 选择工具(已安装 + 未安装分组显示)
96
128
  const installedTools = TOOLS.filter(t => t.checkInstalled())
97
129
  const uninstalledTools = TOOLS.filter(t => !t.checkInstalled())
@@ -183,7 +215,7 @@ async function setup(options) {
183
215
  for (const tool of toConfigureTools) {
184
216
  const spinner = ora(`配置 ${tool.name}...`).start()
185
217
  try {
186
- const result = tool.configure(apiKey, BASE_URL_ANTHROPIC, BASE_URL_OPENAI)
218
+ const result = tool.configure(apiKey, BASE_URL_ANTHROPIC, BASE_URL_OPENAI, primaryModel, selectedModels)
187
219
 
188
220
  if (result.manual) {
189
221
  spinner.info(`${chalk.yellow(tool.name)} 需要手动配置:`)
@@ -44,16 +44,17 @@ module.exports = {
44
44
  const content = readConfig()
45
45
  return content.includes('holysheep')
46
46
  },
47
- configure(apiKey, _baseUrlAnthropicNoV1, baseUrlOpenAI) {
47
+ configure(apiKey, _baseUrlAnthropicNoV1, baseUrlOpenAI, primaryModel) {
48
48
  let content = readConfig()
49
49
  content = removeHsBlock(content)
50
50
  // Aider 用 openai-api-base(OpenAI 兼容格式,带 /v1)
51
51
  // model 格式: openai/<model-name> 表示使用 OpenAI 兼容接口
52
+ const model = primaryModel || 'claude-sonnet-4-6'
52
53
  const block = `
53
54
  # holysheep-cli managed — https://holysheep.ai
54
55
  openai-api-key: ${apiKey}
55
56
  openai-api-base: ${baseUrlOpenAI}
56
- model: openai/claude-sonnet-4-5
57
+ model: openai/${model}
57
58
  `
58
59
  content += block
59
60
  fs.writeFileSync(CONFIG_FILE, content.trim() + '\n', 'utf8')
@@ -84,8 +84,8 @@ function writeYamlConfig(apiKey, baseUrl, models) {
84
84
  }
85
85
 
86
86
  const HS_MODELS = [
87
- { name: 'HolySheep — Claude Sonnet', model: 'claude-sonnet-4-5' },
88
- { name: 'HolySheep — Claude Opus', model: 'claude-opus-4-5' },
87
+ { name: 'HolySheep — Claude Sonnet', model: 'claude-sonnet-4-6' },
88
+ { name: 'HolySheep — Claude Opus', model: 'claude-opus-4-6' },
89
89
  ]
90
90
 
91
91
  module.exports = {
@@ -57,7 +57,7 @@ module.exports = {
57
57
  return cfg.includes('holysheep.ai')
58
58
  },
59
59
 
60
- configure(apiKey, baseUrl) {
60
+ configure(apiKey, baseUrl, _baseUrlOpenAI, primaryModel, selectedModels) {
61
61
  const chalk = require('chalk')
62
62
  console.log(chalk.gray('\n ⚙️ 正在配置 OpenClaw...'))
63
63
 
@@ -90,7 +90,7 @@ module.exports = {
90
90
  '--auth-choice', 'custom-api-key',
91
91
  '--custom-base-url', baseUrl,
92
92
  '--custom-api-key', apiKey,
93
- '--custom-model-id', 'claude-sonnet-4-6',
93
+ '--custom-model-id', primaryModel || 'claude-sonnet-4-6',
94
94
  '--custom-compatibility', 'anthropic',
95
95
  '--install-daemon',
96
96
  )
@@ -98,7 +98,7 @@ module.exports = {
98
98
  if (result.status !== 0) {
99
99
  // onboard 失败时 fallback:手写最小化配置
100
100
  console.log(chalk.yellow(' ⚠️ onboard 失败,使用备用配置...'))
101
- _writeFallbackConfig(apiKey, baseUrl)
101
+ _writeFallbackConfig(apiKey, baseUrl, selectedModels, primaryModel)
102
102
  }
103
103
 
104
104
  // 4. 关闭 gateway token 认证(直接打开浏览器无需 token)
@@ -136,12 +136,19 @@ module.exports = {
136
136
  }
137
137
 
138
138
  /** onboard 失败时的备用配置(基于实测的正确格式) */
139
- function _writeFallbackConfig(apiKey, baseUrl) {
139
+ function _writeFallbackConfig(apiKey, baseUrl, selectedModels, primaryModel) {
140
140
  fs.mkdirSync(OPENCLAW_DIR, { recursive: true })
141
141
 
142
142
  const hostname = new URL(baseUrl).hostname.replace(/\./g, '-')
143
143
  const providerName = `custom-api-${hostname}`
144
144
 
145
+ // 默认配置的 Claude 模型列表(只注册 Claude 系列,MiniMax 用独立 provider)
146
+ const claudeModels = (selectedModels || ['claude-sonnet-4-6'])
147
+ .filter(m => m.startsWith('claude-'))
148
+ if (claudeModels.length === 0) claudeModels.push('claude-sonnet-4-6')
149
+
150
+ const primary = primaryModel || claudeModels[0]
151
+
145
152
  const config = {
146
153
  models: {
147
154
  mode: 'merge',
@@ -150,20 +157,20 @@ function _writeFallbackConfig(apiKey, baseUrl) {
150
157
  baseUrl,
151
158
  apiKey,
152
159
  api: 'anthropic-messages',
153
- models: [{
154
- id: 'claude-sonnet-4-6',
155
- name: 'claude-sonnet-4-6 (HolySheep)',
160
+ models: claudeModels.map(id => ({
161
+ id,
162
+ name: `${id} (HolySheep)`,
156
163
  reasoning: false,
157
164
  input: ['text'],
158
165
  contextWindow: 200000,
159
166
  maxTokens: 16000,
160
- }],
167
+ })),
161
168
  }
162
169
  }
163
170
  },
164
171
  agents: {
165
172
  defaults: {
166
- model: { primary: `${providerName}/claude-sonnet-4-6` }
173
+ model: { primary: `${providerName}/${primary}` }
167
174
  }
168
175
  },
169
176
  gateway: {
@@ -81,7 +81,7 @@ module.exports = {
81
81
  c.provider?.openai?.options?.baseURL?.includes('holysheep')
82
82
  )
83
83
  },
84
- configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
84
+ configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI, primaryModel) {
85
85
  const config = readConfig()
86
86
  if (!config.provider) config.provider = {}
87
87
 
@@ -105,9 +105,7 @@ module.exports = {
105
105
  }
106
106
 
107
107
  // 设置默认模型
108
- if (!config.model) {
109
- config.model = 'anthropic/claude-sonnet-4-5'
110
- }
108
+ config.model = `anthropic/${primaryModel || 'claude-sonnet-4-6'}`
111
109
 
112
110
  writeConfig(config)
113
111
  return { file: getConfigFile(), hot: false }