@simonyea/holysheep-cli 1.7.23 → 1.7.25
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/claude.js +20 -0
- package/src/commands/doctor.js +6 -0
- package/src/commands/setup.js +3 -0
- package/src/tools/claude-code.js +31 -19
- package/src/utils/shell.js +6 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.25",
|
|
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/claude.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { spawn } = require('child_process')
|
|
4
4
|
const {
|
|
5
5
|
BASE_URL_ANTHROPIC,
|
|
6
|
+
BASE_URL_CLAUDE_RELAY,
|
|
6
7
|
getApiKey,
|
|
7
8
|
} = require('../utils/config')
|
|
8
9
|
const {
|
|
@@ -10,7 +11,24 @@ const {
|
|
|
10
11
|
getLocalProxyUrl,
|
|
11
12
|
startProcessProxy,
|
|
12
13
|
readConfig,
|
|
14
|
+
writeConfig,
|
|
13
15
|
} = require('../tools/claude-process-proxy')
|
|
16
|
+
const claudeCodeTool = require('../tools/claude-code')
|
|
17
|
+
|
|
18
|
+
function ensureClaudeProxyConfig(apiKey) {
|
|
19
|
+
const config = readConfig()
|
|
20
|
+
const next = claudeCodeTool.buildBridgeConfig(apiKey, BASE_URL_ANTHROPIC, {
|
|
21
|
+
...config,
|
|
22
|
+
relayUrl: config.relayUrl || BASE_URL_CLAUDE_RELAY,
|
|
23
|
+
})
|
|
24
|
+
const changed = JSON.stringify(next) !== JSON.stringify(config)
|
|
25
|
+
|
|
26
|
+
if (changed) {
|
|
27
|
+
writeConfig(next)
|
|
28
|
+
return next
|
|
29
|
+
}
|
|
30
|
+
return config
|
|
31
|
+
}
|
|
14
32
|
|
|
15
33
|
async function runClaude(args = []) {
|
|
16
34
|
const config = readConfig()
|
|
@@ -19,6 +37,8 @@ async function runClaude(args = []) {
|
|
|
19
37
|
throw new Error('Missing API Key. Run hs setup first.')
|
|
20
38
|
}
|
|
21
39
|
|
|
40
|
+
ensureClaudeProxyConfig(apiKey)
|
|
41
|
+
|
|
22
42
|
const { server, port, sessionId } = startProcessProxy({})
|
|
23
43
|
const proxyUrl = getLocalProxyUrl(port)
|
|
24
44
|
|
package/src/commands/doctor.js
CHANGED
|
@@ -204,9 +204,15 @@ function printClaudeProcessProxyDetails(tool) {
|
|
|
204
204
|
const proxyConfig = typeof tool.getProcessProxyConfig === 'function' ? tool.getProcessProxyConfig() : {}
|
|
205
205
|
const relayUrl = proxyConfig.controlPlaneUrl || proxyConfig.relayUrl || BASE_URL_CLAUDE_RELAY
|
|
206
206
|
const mode = proxyConfig.proxyMode || 'unknown'
|
|
207
|
+
const hasBridgeSecret = Boolean(proxyConfig.bridgeSecret)
|
|
208
|
+
const hasBridgeIds = Boolean(proxyConfig.bridgeId && proxyConfig.deviceId)
|
|
209
|
+
const hasProcessPort = Boolean(proxyConfig.processProxyPort)
|
|
207
210
|
console.log(` ${chalk.gray('↳')} ${chalk.gray(`Claude 启动方式:hs claude`)}`)
|
|
208
211
|
console.log(` ${chalk.gray('↳')} ${chalk.gray(`Claude 代理模式:${mode}`)}`)
|
|
209
212
|
console.log(` ${chalk.gray('↳')} ${chalk.gray(`Claude Relay: ${relayUrl || '未配置'}`)}`)
|
|
213
|
+
console.log(` ${hasBridgeSecret ? chalk.green('↳') : chalk.yellow('↳')} ${hasBridgeSecret ? chalk.green('Bridge secret 已配置') : chalk.yellow('Bridge secret 缺失')}`)
|
|
214
|
+
console.log(` ${hasBridgeIds ? chalk.green('↳') : chalk.yellow('↳')} ${hasBridgeIds ? chalk.green('Bridge ID / Device ID 已配置') : chalk.yellow('Bridge ID / Device ID 缺失')}`)
|
|
215
|
+
console.log(` ${hasProcessPort ? chalk.green('↳') : chalk.yellow('↳')} ${hasProcessPort ? chalk.green(`Claude process proxy 端口:${proxyConfig.processProxyPort}`) : chalk.yellow('Claude process proxy 端口缺失')}`)
|
|
210
216
|
}
|
|
211
217
|
|
|
212
218
|
function maskKey(key) {
|
package/src/commands/setup.js
CHANGED
|
@@ -317,6 +317,9 @@ async function setup(options) {
|
|
|
317
317
|
} else {
|
|
318
318
|
if (result.envVars) Object.assign(envVarsToWrite, result.envVars)
|
|
319
319
|
spinner.succeed(`${chalk.green(tool.name)} ${chalk.gray(result.file ? `→ ${result.file}` : '')}`)
|
|
320
|
+
if (Array.isArray(result.extraFiles) && result.extraFiles.length > 0) {
|
|
321
|
+
console.log(chalk.gray(` ↳ 附加配置: ${result.extraFiles.join(', ')}`))
|
|
322
|
+
}
|
|
320
323
|
results.push({ tool, status: 'ok', result })
|
|
321
324
|
}
|
|
322
325
|
} catch (e) {
|
package/src/tools/claude-code.js
CHANGED
|
@@ -20,6 +20,25 @@ const { readConfig, writeConfig } = require('./claude-process-proxy')
|
|
|
20
20
|
|
|
21
21
|
const SETTINGS_FILE = path.join(os.homedir(), '.claude', 'settings.json')
|
|
22
22
|
|
|
23
|
+
function buildBridgeConfig(apiKey, baseUrl, bridge = {}) {
|
|
24
|
+
const relayUrl = bridge.relayUrl || BASE_URL_CLAUDE_RELAY || ''
|
|
25
|
+
return {
|
|
26
|
+
port: bridge.port || 14555,
|
|
27
|
+
processProxyPort: bridge.processProxyPort || 14556,
|
|
28
|
+
apiKey,
|
|
29
|
+
baseUrlAnthropic: baseUrl || BASE_URL_ANTHROPIC,
|
|
30
|
+
controlPlaneUrl: bridge.controlPlaneUrl || relayUrl || baseUrl || BASE_URL_ANTHROPIC,
|
|
31
|
+
relayUrl: relayUrl || bridge.controlPlaneUrl || baseUrl || BASE_URL_ANTHROPIC,
|
|
32
|
+
bridgeId: bridge.bridgeId || crypto.randomUUID(),
|
|
33
|
+
deviceId: bridge.deviceId || crypto.randomUUID(),
|
|
34
|
+
bridgeSecret: bridge.bridgeSecret || crypto.randomBytes(32).toString('hex'),
|
|
35
|
+
nodeId: bridge.nodeId || '',
|
|
36
|
+
sessionMode: bridge.sessionMode || 'pinned-node',
|
|
37
|
+
installSource: bridge.installSource || 'holysheep-cli',
|
|
38
|
+
proxyMode: 'claude-process',
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
23
42
|
function readSettings() {
|
|
24
43
|
try {
|
|
25
44
|
const raw = fs.readFileSync(SETTINGS_FILE, 'utf8')
|
|
@@ -50,27 +69,15 @@ module.exports = {
|
|
|
50
69
|
s.env?.ANTHROPIC_BASE_URL === BASE_URL_ANTHROPIC &&
|
|
51
70
|
bridge.apiKey &&
|
|
52
71
|
bridge.bridgeSecret &&
|
|
53
|
-
bridge.controlPlaneUrl
|
|
72
|
+
bridge.controlPlaneUrl &&
|
|
73
|
+
bridge.bridgeId &&
|
|
74
|
+
bridge.deviceId &&
|
|
75
|
+
bridge.processProxyPort
|
|
54
76
|
)
|
|
55
77
|
},
|
|
56
78
|
configure(apiKey, baseUrl) {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
writeConfig({
|
|
60
|
-
port: bridge.port || 14555,
|
|
61
|
-
processProxyPort: bridge.processProxyPort || 14556,
|
|
62
|
-
apiKey,
|
|
63
|
-
baseUrlAnthropic: baseUrl || BASE_URL_ANTHROPIC,
|
|
64
|
-
controlPlaneUrl: relayUrl || baseUrl || BASE_URL_ANTHROPIC,
|
|
65
|
-
relayUrl,
|
|
66
|
-
bridgeId: bridge.bridgeId || crypto.randomUUID(),
|
|
67
|
-
deviceId: bridge.deviceId || crypto.randomUUID(),
|
|
68
|
-
bridgeSecret: bridge.bridgeSecret || crypto.randomBytes(32).toString('hex'),
|
|
69
|
-
nodeId: bridge.nodeId || '',
|
|
70
|
-
sessionMode: bridge.sessionMode || 'pinned-node',
|
|
71
|
-
installSource: 'holysheep-cli',
|
|
72
|
-
proxyMode: 'claude-process',
|
|
73
|
-
})
|
|
79
|
+
const bridgeConfig = buildBridgeConfig(apiKey, baseUrl, readConfig())
|
|
80
|
+
writeConfig(bridgeConfig)
|
|
74
81
|
|
|
75
82
|
const settings = readSettings()
|
|
76
83
|
if (!settings.env) settings.env = {}
|
|
@@ -82,7 +89,11 @@ module.exports = {
|
|
|
82
89
|
delete settings.env.ANTHROPIC_API_KEY
|
|
83
90
|
delete settings.env.HOLYSHEEP_CLAUDE_BRIDGE
|
|
84
91
|
writeSettings(settings)
|
|
85
|
-
return {
|
|
92
|
+
return {
|
|
93
|
+
file: SETTINGS_FILE,
|
|
94
|
+
hot: true,
|
|
95
|
+
extraFiles: ['~/.holysheep/claude-proxy.json'],
|
|
96
|
+
}
|
|
86
97
|
},
|
|
87
98
|
reset() {
|
|
88
99
|
const settings = readSettings()
|
|
@@ -106,4 +117,5 @@ module.exports = {
|
|
|
106
117
|
getProcessProxyConfig() {
|
|
107
118
|
return readConfig()
|
|
108
119
|
},
|
|
120
|
+
buildBridgeConfig,
|
|
109
121
|
}
|
package/src/utils/shell.js
CHANGED
|
@@ -5,6 +5,7 @@ const fs = require('fs')
|
|
|
5
5
|
const path = require('path')
|
|
6
6
|
const os = require('os')
|
|
7
7
|
const { execSync } = require('child_process')
|
|
8
|
+
const pkg = require('../../package.json')
|
|
8
9
|
|
|
9
10
|
const MARKER_START = '# >>> holysheep-cli managed >>>'
|
|
10
11
|
const MARKER_END = '# <<< holysheep-cli managed <<<'
|
|
@@ -118,13 +119,14 @@ function installWindowsCliShims() {
|
|
|
118
119
|
const npmBin = path.join(appData, 'npm')
|
|
119
120
|
fs.mkdirSync(npmBin, { recursive: true })
|
|
120
121
|
|
|
122
|
+
const cliSpec = `@simonyea/holysheep-cli@${pkg.version}`
|
|
121
123
|
const cmdContent = [
|
|
122
124
|
'@echo off',
|
|
123
125
|
'setlocal',
|
|
124
126
|
'if exist "%~dp0npx.cmd" (',
|
|
125
|
-
|
|
127
|
+
` call "%~dp0npx.cmd" ${cliSpec} %*`,
|
|
126
128
|
') else (',
|
|
127
|
-
|
|
129
|
+
` call npx ${cliSpec} %*`,
|
|
128
130
|
')',
|
|
129
131
|
''
|
|
130
132
|
].join('\r\n')
|
|
@@ -132,9 +134,9 @@ function installWindowsCliShims() {
|
|
|
132
134
|
const ps1Content = [
|
|
133
135
|
'$npxCmd = Join-Path $PSScriptRoot "npx.cmd"',
|
|
134
136
|
'if (Test-Path $npxCmd) {',
|
|
135
|
-
|
|
137
|
+
` & $npxCmd "${cliSpec}" @args`,
|
|
136
138
|
'} else {',
|
|
137
|
-
|
|
139
|
+
` & npx "${cliSpec}" @args`,
|
|
138
140
|
'}',
|
|
139
141
|
''
|
|
140
142
|
].join('\r\n')
|