@simonyea/holysheep-cli 1.7.97 → 1.7.99

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.7.97",
3
+ "version": "1.7.99",
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",
@@ -386,18 +386,20 @@ async function setup(options) {
386
386
  }
387
387
  }
388
388
 
389
- // Step 5: 清理 shell 环境变量(所有工具改用 JSON/config 文件配置,不再写 shell)
390
- const staleKeys = ['ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL']
391
- try {
392
- const cleaned = removeEnvFromShell(staleKeys)
393
- if (cleaned.length > 0) {
394
- console.log(chalk.gray(`已清理 shell 中的过时变量: ${cleaned.map(f => chalk.cyan(f)).join(', ')}`))
395
- }
396
- } catch {}
397
- if (process.platform === 'win32') {
398
- const removed = removeWindowsUserEnvVars(staleKeys)
399
- if (removed.length > 0) {
400
- console.log(chalk.gray(`已移除过时环境变量: ${removed.map(item => chalk.cyan(item)).join(', ')}`))
389
+ // Step 5: 清理 shell 环境变量(跳过已选全局环境变量工具的情况)
390
+ if (!toolIds.includes('env-config')) {
391
+ const staleKeys = ['ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL']
392
+ try {
393
+ const cleaned = removeEnvFromShell(staleKeys)
394
+ if (cleaned.length > 0) {
395
+ console.log(chalk.gray(`已清理 shell 中的过时变量: ${cleaned.map(f => chalk.cyan(f)).join(', ')}`))
396
+ }
397
+ } catch {}
398
+ if (process.platform === 'win32') {
399
+ const removed = removeWindowsUserEnvVars(staleKeys)
400
+ if (removed.length > 0) {
401
+ console.log(chalk.gray(`已移除过时环境变量: ${removed.map(item => chalk.cyan(item)).join(', ')}`))
402
+ }
401
403
  }
402
404
  }
403
405
 
@@ -0,0 +1,94 @@
1
+ /**
2
+ * 全局环境变量适配器
3
+ *
4
+ * 一键将 HolySheep API 配置写入系统环境变量,
5
+ * 让所有读取标准 env 的编程工具(VS Code Claude 扩展、Cursor、Continue、Cline、Windsurf 等)
6
+ * 无需单独配置即可使用 HolySheep 中继。
7
+ *
8
+ * 写入的环境变量:
9
+ * ANTHROPIC_API_KEY — Anthropic SDK 标准 key
10
+ * ANTHROPIC_AUTH_TOKEN — Claude Code 优先读取
11
+ * ANTHROPIC_BASE_URL — Anthropic API 基地址(不带 /v1)
12
+ * OPENAI_API_KEY — OpenAI SDK 标准 key
13
+ * OPENAI_BASE_URL — OpenAI API 基地址(带 /v1)
14
+ *
15
+ * Mac/Linux: 写入 .zshrc / .bashrc / config.fish(holysheep managed 块)
16
+ * Windows: 通过 setx 写入用户级环境变量(需重启终端生效)
17
+ */
18
+ 'use strict'
19
+
20
+ const { writeEnvToShell, removeEnvFromShell, getShellRcFiles } = require('../utils/shell')
21
+ const fs = require('fs')
22
+
23
+ const MANAGED_KEYS = [
24
+ 'ANTHROPIC_API_KEY',
25
+ 'ANTHROPIC_AUTH_TOKEN',
26
+ 'ANTHROPIC_BASE_URL',
27
+ 'OPENAI_API_KEY',
28
+ 'OPENAI_BASE_URL',
29
+ ]
30
+
31
+ const MARKER = '# >>> holysheep-cli managed >>>'
32
+
33
+ function isConfiguredInShell() {
34
+ if (process.platform === 'win32') {
35
+ // Windows: 检查环境变量是否存在且包含 holysheep
36
+ return !!(
37
+ process.env.ANTHROPIC_BASE_URL?.includes('holysheep') ||
38
+ process.env.OPENAI_BASE_URL?.includes('holysheep')
39
+ )
40
+ }
41
+
42
+ // Mac/Linux: 检查 shell rc 文件里是否有 managed 块
43
+ try {
44
+ const files = getShellRcFiles()
45
+ for (const file of files) {
46
+ try {
47
+ const content = fs.readFileSync(file, 'utf8')
48
+ if (content.includes(MARKER) && content.includes('holysheep')) {
49
+ return true
50
+ }
51
+ } catch {}
52
+ }
53
+ } catch {}
54
+ return false
55
+ }
56
+
57
+ module.exports = {
58
+ name: '全局环境变量',
59
+ id: 'env-config',
60
+
61
+ checkInstalled() {
62
+ return true // 不依赖任何 CLI,总是可用
63
+ },
64
+
65
+ isConfigured() {
66
+ return isConfiguredInShell()
67
+ },
68
+
69
+ configure(apiKey, baseUrlAnthropic, baseUrlOpenAI) {
70
+ const envVars = {
71
+ ANTHROPIC_API_KEY: apiKey,
72
+ ANTHROPIC_AUTH_TOKEN: apiKey,
73
+ ANTHROPIC_BASE_URL: baseUrlAnthropic,
74
+ OPENAI_API_KEY: apiKey,
75
+ OPENAI_BASE_URL: baseUrlOpenAI,
76
+ }
77
+
78
+ const written = writeEnvToShell(envVars)
79
+
80
+ return {
81
+ file: written[0] || 'shell env',
82
+ hot: false,
83
+ }
84
+ },
85
+
86
+ reset() {
87
+ removeEnvFromShell(MANAGED_KEYS)
88
+ },
89
+
90
+ getConfigPath() { return null },
91
+ hint: '配置后 VS Code Claude 扩展、Cursor、Continue、Cline、Windsurf 等工具均可直接使用',
92
+ launchCmd: null,
93
+ docsUrl: 'https://holysheep.ai',
94
+ }
@@ -7,4 +7,5 @@ module.exports = [
7
7
  require('./droid'),
8
8
  require('./opencode'),
9
9
  require('./openclaw'),
10
+ require('./env-config'),
10
11
  ]
@@ -41,10 +41,12 @@ process.on('message', (msg) => {
41
41
  process.send({ type: 'progress', message: '已写入环境变量到 shell 配置' })
42
42
  }
43
43
 
44
- // 清理冲突环境变量
45
- try {
46
- removeEnvFromShell(['ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL'])
47
- } catch {}
44
+ // 清理冲突环境变量(env-config 工具本身就是写环境变量的,不清理)
45
+ if (msg.toolId !== 'env-config') {
46
+ try {
47
+ removeEnvFromShell(['ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL'])
48
+ } catch {}
49
+ }
48
50
 
49
51
  process.send({
50
52
  type: 'result',
@@ -402,13 +402,15 @@ async function handleSetup(req, res) {
402
402
  }
403
403
  }
404
404
 
405
- // Step 5: Clean env vars
406
- try {
407
- const cleaned = removeEnvFromShell(['ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL'])
408
- if (cleaned.length) {
409
- sseEmit(res, { type: 'progress', step: 'clean-env', status: 'ok', message: `已清理环境变量: ${cleaned.join(', ')}` })
410
- }
411
- } catch {}
405
+ // Step 5: Clean env vars (skip if env-config tool is selected)
406
+ if (!selectedToolIds.includes('env-config')) {
407
+ try {
408
+ const cleaned = removeEnvFromShell(['ANTHROPIC_API_KEY', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL'])
409
+ if (cleaned.length) {
410
+ sseEmit(res, { type: 'progress', step: 'clean-env', status: 'ok', message: `已清理环境变量: ${cleaned.join(', ')}` })
411
+ }
412
+ } catch {}
413
+ }
412
414
 
413
415
  // Done
414
416
  const ok = results.filter(r => r.status === 'ok').length