@simonyea/holysheep-cli 1.7.9 → 1.7.11
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/package.json +1 -1
- package/src/commands/setup.js +49 -12
- package/src/index.js +3 -2
- package/src/tools/codex.js +10 -7
- package/src/utils/shell.js +65 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.11",
|
|
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",
|
package/src/commands/setup.js
CHANGED
|
@@ -7,7 +7,12 @@ const ora = require('ora')
|
|
|
7
7
|
const { execSync, spawnSync } = require('child_process')
|
|
8
8
|
const pkg = require('../../package.json')
|
|
9
9
|
const { saveConfig, getApiKey, BASE_URL_ANTHROPIC, BASE_URL_OPENAI, SHOP_URL } = require('../utils/config')
|
|
10
|
-
const {
|
|
10
|
+
const {
|
|
11
|
+
writeEnvToShell,
|
|
12
|
+
ensureWindowsUserPathHasNpmBin,
|
|
13
|
+
installWindowsCliShims,
|
|
14
|
+
removeWindowsUserEnvVars,
|
|
15
|
+
} = require('../utils/shell')
|
|
11
16
|
const { commandExists } = require('../utils/which')
|
|
12
17
|
const TOOLS = require('../tools')
|
|
13
18
|
|
|
@@ -53,7 +58,7 @@ function getWindowsImmediateLaunchCmd(tool) {
|
|
|
53
58
|
|
|
54
59
|
function getPreferredCliPrefix() {
|
|
55
60
|
if (process.platform === 'win32') {
|
|
56
|
-
return '
|
|
61
|
+
return 'hs'
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
const mainEntry = String(require.main?.filename || '')
|
|
@@ -122,6 +127,14 @@ async function tryAutoInstall(tool) {
|
|
|
122
127
|
}
|
|
123
128
|
|
|
124
129
|
async function setup(options) {
|
|
130
|
+
let windowsCliArtifacts = []
|
|
131
|
+
if (process.platform === 'win32') {
|
|
132
|
+
windowsCliArtifacts = [
|
|
133
|
+
...installWindowsCliShims(),
|
|
134
|
+
...ensureWindowsUserPathHasNpmBin(),
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
|
|
125
138
|
console.log()
|
|
126
139
|
console.log(chalk.bold('🐑 HolySheep CLI — 一键配置 AI 工具'))
|
|
127
140
|
console.log(chalk.gray('━'.repeat(50)))
|
|
@@ -137,8 +150,8 @@ async function setup(options) {
|
|
|
137
150
|
console.log(chalk.gray(` (¥10 起充,按量计费,支持微信/支付宝)`))
|
|
138
151
|
console.log(chalk.gray(`提示:可先运行 ${chalk.cyan('hs login')} 登录并保存 Key,之后 setup 将自动读取。`))
|
|
139
152
|
if (process.platform === 'win32') {
|
|
140
|
-
console.log(chalk.gray(` ⚠️ Windows 用户:如果 ${chalk.cyan('hs')}
|
|
141
|
-
console.log(chalk.gray(` ${chalk.white('npx @simonyea/holysheep-cli login')}
|
|
153
|
+
console.log(chalk.gray(` ⚠️ Windows 用户:如果 ${chalk.cyan('hs')} 命令暂时找不到,请先运行:`))
|
|
154
|
+
console.log(chalk.gray(` ${chalk.white('npx @simonyea/holysheep-cli@latest login')}`))
|
|
142
155
|
console.log(chalk.gray(` 或重启终端后再试`))
|
|
143
156
|
}
|
|
144
157
|
console.log()
|
|
@@ -302,14 +315,25 @@ async function setup(options) {
|
|
|
302
315
|
}
|
|
303
316
|
|
|
304
317
|
// Step 5: 写入通用环境变量
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
318
|
+
const needsAnthropicEnv = toConfigureTools.some(t => t.id === 'claude-code')
|
|
319
|
+
const needsOpenAIEnv = toConfigureTools.some(t => t.id === 'codex' || t.id === 'aider')
|
|
320
|
+
if (needsAnthropicEnv || needsOpenAIEnv || Object.keys(envVarsToWrite).length > 0) {
|
|
321
|
+
if (needsAnthropicEnv) {
|
|
322
|
+
Object.assign(envVarsToWrite, {
|
|
323
|
+
ANTHROPIC_API_KEY: apiKey,
|
|
324
|
+
ANTHROPIC_BASE_URL: BASE_URL_ANTHROPIC,
|
|
325
|
+
})
|
|
326
|
+
}
|
|
327
|
+
if (needsOpenAIEnv) {
|
|
328
|
+
Object.assign(envVarsToWrite, {
|
|
329
|
+
OPENAI_API_KEY: apiKey,
|
|
330
|
+
})
|
|
331
|
+
if (toConfigureTools.some(t => t.id === 'aider')) {
|
|
332
|
+
Object.assign(envVarsToWrite, {
|
|
333
|
+
OPENAI_BASE_URL: BASE_URL_OPENAI,
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
}
|
|
313
337
|
}
|
|
314
338
|
|
|
315
339
|
if (Object.keys(envVarsToWrite).length > 0) {
|
|
@@ -322,6 +346,19 @@ async function setup(options) {
|
|
|
322
346
|
}
|
|
323
347
|
}
|
|
324
348
|
|
|
349
|
+
if (process.platform === 'win32' && toConfigureTools.some(t => t.id === 'codex') && !toConfigureTools.some(t => t.id === 'aider')) {
|
|
350
|
+
const removed = removeWindowsUserEnvVars(['OPENAI_BASE_URL'])
|
|
351
|
+
if (removed.length > 0) {
|
|
352
|
+
console.log(chalk.gray(`已移除过时环境变量: ${removed.map(item => chalk.cyan(item)).join(', ')}`))
|
|
353
|
+
console.log()
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (process.platform === 'win32' && windowsCliArtifacts.length > 0) {
|
|
358
|
+
console.log(chalk.gray(`Windows 启动器已就绪: ${windowsCliArtifacts.map(item => chalk.cyan(item)).join(', ')}`))
|
|
359
|
+
console.log()
|
|
360
|
+
}
|
|
361
|
+
|
|
325
362
|
// Step 6: 保存 API Key
|
|
326
363
|
saveConfig({ apiKey })
|
|
327
364
|
|
package/src/index.js
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
const { program } = require('commander')
|
|
5
5
|
const chalk = require('chalk')
|
|
6
6
|
const pkg = require('../package.json')
|
|
7
|
+
const { installWindowsCliShims, ensureWindowsUserPathHasNpmBin } = require('./utils/shell')
|
|
7
8
|
|
|
8
9
|
// Windows 用户:检测 npm bin 路径是否在 PATH 中
|
|
9
10
|
if (process.platform === 'win32') {
|
|
10
|
-
const { execSync } = require('child_process')
|
|
11
11
|
try {
|
|
12
|
-
|
|
12
|
+
installWindowsCliShims()
|
|
13
|
+
ensureWindowsUserPathHasNpmBin()
|
|
13
14
|
} catch {}
|
|
14
15
|
}
|
|
15
16
|
|
package/src/tools/codex.js
CHANGED
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
* [model_providers.holysheep]
|
|
13
13
|
* name = "HolySheep"
|
|
14
14
|
* base_url = "https://api.holysheep.ai/v1"
|
|
15
|
-
*
|
|
15
|
+
* env_key = "OPENAI_API_KEY"
|
|
16
|
+
* wire_api = "responses"
|
|
16
17
|
*
|
|
17
18
|
* 注意:旧的 config.json 会被 Rust Codex 忽略!
|
|
18
|
-
*
|
|
19
|
+
* 注意:Rust Codex 当前读取 env_key,不读取自定义 api_key 字段。
|
|
19
20
|
*/
|
|
20
21
|
const fs = require('fs')
|
|
21
22
|
const path = require('path')
|
|
@@ -88,7 +89,8 @@ function isConfiguredInToml() {
|
|
|
88
89
|
const content = readTomlConfig()
|
|
89
90
|
return content.includes('model_provider = "holysheep"') &&
|
|
90
91
|
content.includes('base_url') &&
|
|
91
|
-
content.includes('holysheep.ai')
|
|
92
|
+
content.includes('holysheep.ai') &&
|
|
93
|
+
content.includes('env_key = "OPENAI_API_KEY"')
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
/**
|
|
@@ -111,7 +113,8 @@ function writeTomlConfig(apiKey, baseUrlOpenAI, model) {
|
|
|
111
113
|
`[model_providers.holysheep]`,
|
|
112
114
|
`name = "HolySheep"`,
|
|
113
115
|
`base_url = "${baseUrlOpenAI}"`,
|
|
114
|
-
`
|
|
116
|
+
`env_key = "OPENAI_API_KEY"`,
|
|
117
|
+
`wire_api = "responses"`,
|
|
115
118
|
'',
|
|
116
119
|
].join('\n')
|
|
117
120
|
|
|
@@ -135,12 +138,13 @@ function writeJsonConfigIfNeeded(apiKey, baseUrlOpenAI, model) {
|
|
|
135
138
|
jsonConfig.model_providers.holysheep = {
|
|
136
139
|
name: 'HolySheep',
|
|
137
140
|
base_url: baseUrlOpenAI,
|
|
138
|
-
|
|
141
|
+
env_key: 'OPENAI_API_KEY',
|
|
142
|
+
wire_api: 'responses',
|
|
139
143
|
}
|
|
140
144
|
jsonConfig.providers.holysheep = {
|
|
141
145
|
name: 'HolySheep',
|
|
142
146
|
baseURL: baseUrlOpenAI,
|
|
143
|
-
|
|
147
|
+
envKey: 'OPENAI_API_KEY',
|
|
144
148
|
}
|
|
145
149
|
fs.writeFileSync(CONFIG_FILE_JSON, JSON.stringify(jsonConfig, null, 2), 'utf8')
|
|
146
150
|
} catch {}
|
|
@@ -169,7 +173,6 @@ module.exports = {
|
|
|
169
173
|
hot: false,
|
|
170
174
|
envVars: {
|
|
171
175
|
OPENAI_API_KEY: apiKey,
|
|
172
|
-
OPENAI_BASE_URL: baseUrlOpenAI,
|
|
173
176
|
},
|
|
174
177
|
}
|
|
175
178
|
},
|
package/src/utils/shell.js
CHANGED
|
@@ -109,6 +109,46 @@ function ensureWindowsUserPathHasNpmBin() {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
function installWindowsCliShims() {
|
|
113
|
+
if (process.platform !== 'win32') return []
|
|
114
|
+
|
|
115
|
+
const appData = process.env.APPDATA
|
|
116
|
+
if (!appData) return []
|
|
117
|
+
|
|
118
|
+
const npmBin = path.join(appData, 'npm')
|
|
119
|
+
fs.mkdirSync(npmBin, { recursive: true })
|
|
120
|
+
|
|
121
|
+
const cmdContent = [
|
|
122
|
+
'@echo off',
|
|
123
|
+
'setlocal',
|
|
124
|
+
'if exist "%~dp0npx.cmd" (',
|
|
125
|
+
' call "%~dp0npx.cmd" @simonyea/holysheep-cli@latest %*',
|
|
126
|
+
') else (',
|
|
127
|
+
' call npx @simonyea/holysheep-cli@latest %*',
|
|
128
|
+
')',
|
|
129
|
+
''
|
|
130
|
+
].join('\r\n')
|
|
131
|
+
|
|
132
|
+
const ps1Content = [
|
|
133
|
+
'$npxCmd = Join-Path $PSScriptRoot "npx.cmd"',
|
|
134
|
+
'if (Test-Path $npxCmd) {',
|
|
135
|
+
' & $npxCmd "@simonyea/holysheep-cli@latest" @args',
|
|
136
|
+
'} else {',
|
|
137
|
+
' & npx "@simonyea/holysheep-cli@latest" @args',
|
|
138
|
+
'}',
|
|
139
|
+
''
|
|
140
|
+
].join('\r\n')
|
|
141
|
+
|
|
142
|
+
const written = []
|
|
143
|
+
for (const name of ['hs', 'holysheep']) {
|
|
144
|
+
fs.writeFileSync(path.join(npmBin, `${name}.cmd`), cmdContent, 'utf8')
|
|
145
|
+
fs.writeFileSync(path.join(npmBin, `${name}.ps1`), ps1Content, 'utf8')
|
|
146
|
+
written.push(`[启动器] %APPDATA%\\npm\\${name}.cmd`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return written
|
|
150
|
+
}
|
|
151
|
+
|
|
112
152
|
function writeEnvToShell(envVars) {
|
|
113
153
|
// Windows: 用 setx 写入用户级环境变量(需重启终端生效)
|
|
114
154
|
if (process.platform === 'win32') {
|
|
@@ -119,6 +159,7 @@ function writeEnvToShell(envVars) {
|
|
|
119
159
|
written.push(`[系统环境变量] ${k}`)
|
|
120
160
|
} catch {}
|
|
121
161
|
}
|
|
162
|
+
written.push(...installWindowsCliShims())
|
|
122
163
|
written.push(...ensureWindowsUserPathHasNpmBin())
|
|
123
164
|
if (written.length > 0) {
|
|
124
165
|
const chalk = require('chalk')
|
|
@@ -146,6 +187,22 @@ function writeEnvToShell(envVars) {
|
|
|
146
187
|
return written
|
|
147
188
|
}
|
|
148
189
|
|
|
190
|
+
function removeWindowsUserEnvVars(keys = []) {
|
|
191
|
+
if (process.platform !== 'win32') return []
|
|
192
|
+
|
|
193
|
+
const removed = []
|
|
194
|
+
for (const key of keys) {
|
|
195
|
+
try {
|
|
196
|
+
execSync(
|
|
197
|
+
`powershell.exe -NoProfile -Command "[Environment]::SetEnvironmentVariable('${key}', $null, 'User')"`,
|
|
198
|
+
{ stdio: 'ignore' }
|
|
199
|
+
)
|
|
200
|
+
removed.push(`[系统环境变量] ${key}`)
|
|
201
|
+
} catch {}
|
|
202
|
+
}
|
|
203
|
+
return removed
|
|
204
|
+
}
|
|
205
|
+
|
|
149
206
|
function removeEnvFromShell(extraKeys = []) {
|
|
150
207
|
// 默认清理的 key 列表(holysheep 相关的所有环境变量)
|
|
151
208
|
const HS_KEYS = [
|
|
@@ -174,4 +231,11 @@ function escapeRegex(s) {
|
|
|
174
231
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
175
232
|
}
|
|
176
233
|
|
|
177
|
-
module.exports = {
|
|
234
|
+
module.exports = {
|
|
235
|
+
getShellRcFiles,
|
|
236
|
+
writeEnvToShell,
|
|
237
|
+
removeEnvFromShell,
|
|
238
|
+
ensureWindowsUserPathHasNpmBin,
|
|
239
|
+
installWindowsCliShims,
|
|
240
|
+
removeWindowsUserEnvVars
|
|
241
|
+
}
|