@simonyea/holysheep-cli 1.6.8 → 1.6.9

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
@@ -218,6 +218,7 @@ A: OpenClaw 需要 Node.js 20+,运行 `node --version` 确认版本后重试
218
218
 
219
219
  ## Changelog
220
220
 
221
+ - **v1.6.9** — 保留 OpenClaw 的 MiniMax 配置,并为 MiniMax 使用独立 provider id,避免与 Claude provider 冲突;在 OpenClaw 2026.3.13 下改为提示精确 `/model` 切换命令,而不是停止配置 MiniMax
221
222
  - **v1.6.8** — 修复 Codex 重复写入 `config.toml` 导致的 duplicate key,并修复 OpenClaw 在 Windows 下的安装检测;针对 OpenClaw 2026.3.13 的模型路由回归,临时跳过 MiniMax 避免 `model not allowed`
222
223
  - **v1.6.7** — OpenClaw 配置新增 `MiniMax-M2.7-highspeed`,并补齐节点迁移脚本中的 SSH 代理账号创建逻辑
223
224
  - **v1.6.6** — 修复 Droid CLI 的 GPT-5.4 配置残留问题,同时同步 `~/.factory/settings.json` 和 `~/.factory/config.json`,统一使用 `openai + https://api.holysheep.ai/v1`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
4
4
  "description": "Claude Code/Cursor/Cline API relay for China — ¥1=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
5
5
  "keywords": [
6
6
  "openai-china",
@@ -3,7 +3,7 @@
3
3
  * 配置文件: ~/.factory/settings.json
4
4
  *
5
5
  * 使用 Droid 原生 customModels 配置 HolySheep 的多个模型入口:
6
- * - GPT 走 OpenAI 兼容入口: https://api.holysheep.ai/v1
6
+ * - GPT 走 OpenAI 兼容入口: https://api.holysheep.ai/openai
7
7
  * - Claude 走 Anthropic 入口: https://api.holysheep.ai
8
8
  * - MiniMax 走 Anthropic 入口: https://api.holysheep.ai/minimax
9
9
  */
@@ -13,13 +13,12 @@ const os = require('os')
13
13
 
14
14
  const CONFIG_DIR = path.join(os.homedir(), '.factory')
15
15
  const SETTINGS_FILE = path.join(CONFIG_DIR, 'settings.json')
16
- const LEGACY_CONFIG_FILE = path.join(CONFIG_DIR, 'config.json')
17
16
 
18
17
  const DEFAULT_MODELS = [
19
18
  {
20
19
  model: 'gpt-5.4',
21
20
  id: 'custom:gpt-5.4-0',
22
- baseUrlSuffix: '',
21
+ baseUrlSuffix: '/openai',
23
22
  displayName: 'GPT-5.4',
24
23
  provider: 'openai',
25
24
  },
@@ -67,24 +66,6 @@ function writeSettings(data) {
67
66
  fs.writeFileSync(SETTINGS_FILE, JSON.stringify(data, null, 2), 'utf8')
68
67
  }
69
68
 
70
- function readLegacyConfig() {
71
- try {
72
- if (fs.existsSync(LEGACY_CONFIG_FILE)) {
73
- return JSON.parse(fs.readFileSync(LEGACY_CONFIG_FILE, 'utf8'))
74
- }
75
- } catch {}
76
- return {}
77
- }
78
-
79
- function writeLegacyConfig(data) {
80
- fs.mkdirSync(CONFIG_DIR, { recursive: true })
81
- fs.writeFileSync(LEGACY_CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8')
82
- }
83
-
84
- function isHolySheepModel(item) {
85
- return typeof item?.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai')
86
- }
87
-
88
69
  function normalizeSelectedModels(selectedModels) {
89
70
  const selected = new Set(
90
71
  Array.isArray(selectedModels) && selectedModels.length > 0
@@ -103,17 +84,13 @@ function normalizeSelectedModels(selectedModels) {
103
84
  return models.length > 0 ? models : DEFAULT_MODELS.map((item, index) => ({ ...item, index }))
104
85
  }
105
86
 
106
- function buildCustomModels(apiKey, baseUrlAnthropic, baseUrlOpenAI, selectedModels) {
107
- const anthropicRootUrl = String(baseUrlAnthropic || '').replace(/\/+$/, '')
108
- const openaiRootUrl = String(baseUrlOpenAI || '').replace(/\/+$/, '')
87
+ function buildCustomModels(apiKey, baseUrlAnthropic, selectedModels) {
88
+ const rootUrl = String(baseUrlAnthropic || '').replace(/\/+$/, '')
109
89
  return normalizeSelectedModels(selectedModels).map((item) => ({
110
90
  model: item.model,
111
91
  id: item.id,
112
92
  index: item.index,
113
- baseUrl:
114
- item.provider === 'openai'
115
- ? `${openaiRootUrl}${item.baseUrlSuffix}`
116
- : `${anthropicRootUrl}${item.baseUrlSuffix}`,
93
+ baseUrl: `${rootUrl}${item.baseUrlSuffix}`,
117
94
  apiKey,
118
95
  displayName: item.displayName,
119
96
  maxOutputTokens: 64000,
@@ -131,37 +108,25 @@ module.exports = {
131
108
  isConfigured() {
132
109
  const settings = readSettings()
133
110
  const customModels = Array.isArray(settings.customModels) ? settings.customModels : []
134
- if (customModels.some(isHolySheepModel)) return true
135
-
136
- const legacy = readLegacyConfig()
137
- const legacyModels = Array.isArray(legacy.customModels) ? legacy.customModels : []
138
- return legacyModels.some(isHolySheepModel)
111
+ return customModels.some((item) =>
112
+ typeof item.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai')
113
+ )
139
114
  },
140
- configure(apiKey, baseUrlAnthropic, baseUrlOpenAI, _primaryModel, selectedModels) {
141
- const nextModels = buildCustomModels(apiKey, baseUrlAnthropic, baseUrlOpenAI, selectedModels)
142
-
115
+ configure(apiKey, baseUrlAnthropic, _baseUrlOpenAI, _primaryModel, selectedModels) {
143
116
  const settings = readSettings()
144
117
  const preservedModels = Array.isArray(settings.customModels)
145
- ? settings.customModels.filter((item) => !isHolySheepModel(item))
118
+ ? settings.customModels.filter(
119
+ (item) => !(typeof item.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai'))
120
+ )
146
121
  : []
122
+
147
123
  settings.customModels = [
148
- ...nextModels,
124
+ ...buildCustomModels(apiKey, baseUrlAnthropic, selectedModels),
149
125
  ...preservedModels,
150
126
  ]
151
127
  settings.logoAnimation = 'off'
152
128
  writeSettings(settings)
153
129
 
154
- const legacy = readLegacyConfig()
155
- const preservedLegacyModels = Array.isArray(legacy.customModels)
156
- ? legacy.customModels.filter((item) => !isHolySheepModel(item))
157
- : []
158
- legacy.customModels = [
159
- ...nextModels,
160
- ...preservedLegacyModels,
161
- ]
162
- legacy.logoAnimation = 'off'
163
- writeLegacyConfig(legacy)
164
-
165
130
  return {
166
131
  file: SETTINGS_FILE,
167
132
  hot: true,
@@ -170,15 +135,11 @@ module.exports = {
170
135
  reset() {
171
136
  const settings = readSettings()
172
137
  if (Array.isArray(settings.customModels)) {
173
- settings.customModels = settings.customModels.filter((item) => !isHolySheepModel(item))
138
+ settings.customModels = settings.customModels.filter(
139
+ (item) => !(typeof item.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai'))
140
+ )
174
141
  }
175
142
  writeSettings(settings)
176
-
177
- const legacy = readLegacyConfig()
178
- if (Array.isArray(legacy.customModels)) {
179
- legacy.customModels = legacy.customModels.filter((item) => !isHolySheepModel(item))
180
- }
181
- writeLegacyConfig(legacy)
182
143
  },
183
144
  getConfigPath() { return SETTINGS_FILE },
184
145
  hint: '已写入 ~/.factory/settings.json;重启 Droid 后可见 HolySheep 模型列表',
@@ -148,22 +148,12 @@ function isRoutingRegressionVersion(version) {
148
148
  return OPENCLAW_ROUTING_REGRESSION_VERSION.test(String(version || '').trim())
149
149
  }
150
150
 
151
- function sanitizeSelectedModelsForRuntime(selectedModels, runtimeVersion) {
152
- if (!isRoutingRegressionVersion(runtimeVersion)) {
153
- return { models: selectedModels, warning: '' }
151
+ function getRoutingRegressionWarning(runtimeVersion, minimaxModelRef) {
152
+ if (!isRoutingRegressionVersion(runtimeVersion) || !minimaxModelRef) {
153
+ return ''
154
154
  }
155
155
 
156
- const originalModels = Array.isArray(selectedModels) ? selectedModels : []
157
- const filteredModels = originalModels.filter((model) => !model.startsWith('MiniMax-'))
158
-
159
- if (filteredModels.length === originalModels.length) {
160
- return { models: selectedModels, warning: '' }
161
- }
162
-
163
- return {
164
- models: filteredModels,
165
- warning: '当前 OpenClaw 2026.3.13 存在 provider 路由回归,已暂时跳过 MiniMax 模型,避免 /model 和网页切换时报 model not allowed。升级 OpenClaw 后可重新运行 hs setup 恢复。',
166
- }
156
+ return `当前 OpenClaw 2026.3.13 存在 provider 路由回归,但 HolySheep 仍会保留 MiniMax 配置。若网页模型切换失败,请直接输入 /model ${minimaxModelRef},或升级 OpenClaw 后再试。`
167
157
  }
168
158
 
169
159
  function readConfig() {
@@ -293,7 +283,7 @@ function buildManagedPlan(apiKey, baseUrlAnthropic, baseUrlOpenAI, selectedModel
293
283
 
294
284
  const openaiProviderName = buildProviderName(baseUrlOpenAI, 'custom-openai')
295
285
  const anthropicProviderName = buildProviderName(baseUrlAnthropic, 'custom-anthropic')
296
- const minimaxProviderName = buildProviderName(`${baseUrlAnthropic.replace(/\/+$/, '')}/minimax`, 'custom-anthropic')
286
+ const minimaxProviderName = buildProviderName(`${baseUrlAnthropic.replace(/\/+$/, '')}/minimax`, 'custom-minimax')
297
287
 
298
288
  const providers = {
299
289
  [openaiProviderName]: {
@@ -329,6 +319,7 @@ function buildManagedPlan(apiKey, baseUrlAnthropic, baseUrlOpenAI, selectedModel
329
319
  providers,
330
320
  managedModelRefs,
331
321
  primaryRef: `${openaiProviderName}/${OPENCLAW_DEFAULT_MODEL}`,
322
+ minimaxRef: minimaxModels[0] ? `${minimaxProviderName}/${minimaxModels[0]}` : '',
332
323
  }
333
324
  }
334
325
 
@@ -485,11 +476,6 @@ module.exports = {
485
476
  }
486
477
  this._lastRuntimeCommand = runtime.command
487
478
 
488
- const sanitizedSelection = sanitizeSelectedModelsForRuntime(selectedModels, runtime.version)
489
- if (sanitizedSelection.warning) {
490
- console.log(chalk.yellow(` ⚠️ ${sanitizedSelection.warning}`))
491
- }
492
-
493
479
  runOpenClaw(['gateway', 'stop'], { preferNpx: runtime.via === 'npx' })
494
480
 
495
481
  const gatewayPort = findAvailableGatewayPort(DEFAULT_GATEWAY_PORT)
@@ -530,15 +516,20 @@ module.exports = {
530
516
  console.log(chalk.yellow(' ⚠️ onboard 失败,使用备用配置...'))
531
517
  }
532
518
 
533
- writeManagedConfig(
519
+ const plan = writeManagedConfig(
534
520
  result.status === 0 ? readConfig() : {},
535
521
  apiKey,
536
522
  baseUrlAnthropic,
537
523
  baseUrlOpenAI,
538
- sanitizedSelection.models,
524
+ selectedModels,
539
525
  gatewayPort,
540
526
  )
541
527
 
528
+ const routingRegressionWarning = getRoutingRegressionWarning(runtime.version, plan.minimaxRef)
529
+ if (routingRegressionWarning) {
530
+ console.log(chalk.yellow(` ⚠️ ${routingRegressionWarning}`))
531
+ }
532
+
542
533
  _disableGatewayAuth(runtime.via === 'npx')
543
534
  const serviceReady = _installGatewayService(gatewayPort, runtime.via === 'npx')
544
535