@simonyea/holysheep-cli 1.6.9 → 1.6.10

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.10** — 将可运行的 OpenClaw runtime(含 npx 回退)视为已安装,避免 Windows/Node 环境下重复提示安装;同时修复 Droid CLI 的 GPT `/v1` 接入地址并同步写入 `~/.factory/config.json`
221
222
  - **v1.6.9** — 保留 OpenClaw 的 MiniMax 配置,并为 MiniMax 使用独立 provider id,避免与 Claude provider 冲突;在 OpenClaw 2026.3.13 下改为提示精确 `/model` 切换命令,而不是停止配置 MiniMax
222
223
  - **v1.6.8** — 修复 Codex 重复写入 `config.toml` 导致的 duplicate key,并修复 OpenClaw 在 Windows 下的安装检测;针对 OpenClaw 2026.3.13 的模型路由回归,临时跳过 MiniMax 避免 `model not allowed`
223
224
  - **v1.6.7** — OpenClaw 配置新增 `MiniMax-M2.7-highspeed`,并补齐节点迁移脚本中的 SSH 代理账号创建逻辑
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.6.9",
3
+ "version": "1.6.10",
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/openai
6
+ * - GPT 走 OpenAI 兼容入口: https://api.holysheep.ai/v1
7
7
  * - Claude 走 Anthropic 入口: https://api.holysheep.ai
8
8
  * - MiniMax 走 Anthropic 入口: https://api.holysheep.ai/minimax
9
9
  */
@@ -13,12 +13,13 @@ 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')
16
17
 
17
18
  const DEFAULT_MODELS = [
18
19
  {
19
20
  model: 'gpt-5.4',
20
21
  id: 'custom:gpt-5.4-0',
21
- baseUrlSuffix: '/openai',
22
+ baseUrlSuffix: '',
22
23
  displayName: 'GPT-5.4',
23
24
  provider: 'openai',
24
25
  },
@@ -66,6 +67,24 @@ function writeSettings(data) {
66
67
  fs.writeFileSync(SETTINGS_FILE, JSON.stringify(data, null, 2), 'utf8')
67
68
  }
68
69
 
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
+
69
88
  function normalizeSelectedModels(selectedModels) {
70
89
  const selected = new Set(
71
90
  Array.isArray(selectedModels) && selectedModels.length > 0
@@ -84,13 +103,17 @@ function normalizeSelectedModels(selectedModels) {
84
103
  return models.length > 0 ? models : DEFAULT_MODELS.map((item, index) => ({ ...item, index }))
85
104
  }
86
105
 
87
- function buildCustomModels(apiKey, baseUrlAnthropic, selectedModels) {
88
- const rootUrl = String(baseUrlAnthropic || '').replace(/\/+$/, '')
106
+ function buildCustomModels(apiKey, baseUrlAnthropic, baseUrlOpenAI, selectedModels) {
107
+ const anthropicRootUrl = String(baseUrlAnthropic || '').replace(/\/+$/, '')
108
+ const openaiRootUrl = String(baseUrlOpenAI || '').replace(/\/+$/, '')
89
109
  return normalizeSelectedModels(selectedModels).map((item) => ({
90
110
  model: item.model,
91
111
  id: item.id,
92
112
  index: item.index,
93
- baseUrl: `${rootUrl}${item.baseUrlSuffix}`,
113
+ baseUrl:
114
+ item.provider === 'openai'
115
+ ? `${openaiRootUrl}${item.baseUrlSuffix}`
116
+ : `${anthropicRootUrl}${item.baseUrlSuffix}`,
94
117
  apiKey,
95
118
  displayName: item.displayName,
96
119
  maxOutputTokens: 64000,
@@ -108,25 +131,37 @@ module.exports = {
108
131
  isConfigured() {
109
132
  const settings = readSettings()
110
133
  const customModels = Array.isArray(settings.customModels) ? settings.customModels : []
111
- return customModels.some((item) =>
112
- typeof item.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai')
113
- )
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)
114
139
  },
115
- configure(apiKey, baseUrlAnthropic, _baseUrlOpenAI, _primaryModel, selectedModels) {
140
+ configure(apiKey, baseUrlAnthropic, baseUrlOpenAI, _primaryModel, selectedModels) {
141
+ const nextModels = buildCustomModels(apiKey, baseUrlAnthropic, baseUrlOpenAI, selectedModels)
142
+
116
143
  const settings = readSettings()
117
144
  const preservedModels = Array.isArray(settings.customModels)
118
- ? settings.customModels.filter(
119
- (item) => !(typeof item.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai'))
120
- )
145
+ ? settings.customModels.filter((item) => !isHolySheepModel(item))
121
146
  : []
122
-
123
147
  settings.customModels = [
124
- ...buildCustomModels(apiKey, baseUrlAnthropic, selectedModels),
148
+ ...nextModels,
125
149
  ...preservedModels,
126
150
  ]
127
151
  settings.logoAnimation = 'off'
128
152
  writeSettings(settings)
129
153
 
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
+
130
165
  return {
131
166
  file: SETTINGS_FILE,
132
167
  hot: true,
@@ -135,11 +170,15 @@ module.exports = {
135
170
  reset() {
136
171
  const settings = readSettings()
137
172
  if (Array.isArray(settings.customModels)) {
138
- settings.customModels = settings.customModels.filter(
139
- (item) => !(typeof item.baseUrl === 'string' && item.baseUrl.includes('api.holysheep.ai'))
140
- )
173
+ settings.customModels = settings.customModels.filter((item) => !isHolySheepModel(item))
141
174
  }
142
175
  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)
143
182
  },
144
183
  getConfigPath() { return SETTINGS_FILE },
145
184
  hint: '已写入 ~/.factory/settings.json;重启 Droid 后可见 HolySheep 模型列表',
@@ -452,7 +452,7 @@ module.exports = {
452
452
  id: 'openclaw',
453
453
 
454
454
  checkInstalled() {
455
- return hasOpenClawBinary()
455
+ return detectRuntime().available
456
456
  },
457
457
 
458
458
  detectRuntime,