@simonyea/holysheep-cli 1.1.0 → 1.1.1

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
@@ -40,7 +40,7 @@ Instead of manually editing config files and environment variables for each tool
40
40
  | [Codex CLI](https://github.com/openai/codex) | `npm i -g @openai/codex` | `~/.codex/config.toml` | ✅ Auto |
41
41
  | [Aider](https://aider.chat) | `pip install aider-install && aider-install` | `~/.aider.conf.yml` | ✅ Auto |
42
42
  | [Continue.dev](https://continue.dev) | VS Code marketplace | `~/.continue/config.yaml` | ✅ Auto |
43
- | [OpenCode](https://github.com/sst/opencode) | `npm i -g opencode-ai` | `~/.config/opencode/config.json` | ✅ Auto |
43
+ | [OpenCode](https://opencode.ai) | `brew install anomalyco/tap/opencode` | `~/.config/opencode/opencode.json` | ✅ Auto |
44
44
  | [OpenClaw](https://github.com/iOfficeAI/AionUi) | Download from website | `~/.openclaw/settings.json` | ✅ Auto |
45
45
  | [Cursor](https://cursor.sh) | Download from website | GUI only (encrypted storage) | ⚠️ Manual |
46
46
  | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `npm i -g @google/gemini-cli` | Google protocol only | ❌ Not supported |
@@ -134,7 +134,7 @@ HolySheep 是面向中国开发者的 Claude/GPT/Gemini 官方 API 中转服务
134
134
  | [Codex CLI](https://github.com/openai/codex) | `npm i -g @openai/codex` | `~/.codex/config.toml` | ✅ 自动 |
135
135
  | [Aider](https://aider.chat) | `pip install aider-install && aider-install` | `~/.aider.conf.yml` | ✅ 自动 |
136
136
  | [Continue.dev](https://continue.dev) | VS Code 插件市场 | `~/.continue/config.yaml` | ✅ 自动 |
137
- | [OpenCode](https://github.com/sst/opencode) | `npm i -g opencode-ai` | `~/.config/opencode/config.json` | ✅ 自动 |
137
+ | [OpenCode](https://opencode.ai) | `brew install anomalyco/tap/opencode` | `~/.config/opencode/opencode.json` | ✅ 自动 |
138
138
  | [OpenClaw](https://github.com/iOfficeAI/AionUi) | 官网下载 | `~/.openclaw/settings.json` | ✅ 自动 |
139
139
  | [Cursor](https://cursor.sh) | 官网下载 | GUI 手动配置(加密存储) | ⚠️ 手动 |
140
140
  | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `npm i -g @google/gemini-cli` | 仅支持 Google 官方协议 | ❌ 不支持 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "一键配置所有 AI 编程工具接入 HolySheep API — Claude Code / Codex / Gemini CLI / OpenCode / OpenClaw / Aider / Cursor",
5
5
  "keywords": [
6
6
  "claude",
@@ -44,10 +44,11 @@ module.exports = {
44
44
  const content = readConfig()
45
45
  return content.includes('holysheep')
46
46
  },
47
- configure(apiKey, baseUrlOpenAI) {
47
+ configure(apiKey, _baseUrlAnthropicNoV1, baseUrlOpenAI) {
48
48
  let content = readConfig()
49
49
  content = removeHsBlock(content)
50
- // Aider 用 openai-api-base (不带 /v1 的后缀) 或完整带 /v1
50
+ // Aider 用 openai-api-base(OpenAI 兼容格式,带 /v1
51
+ // model 格式: openai/<model-name> 表示使用 OpenAI 兼容接口
51
52
  const block = `
52
53
  # holysheep-cli managed — https://shop.holysheep.ai
53
54
  openai-api-key: ${apiKey}
@@ -1,79 +1,144 @@
1
1
  /**
2
2
  * Continue.dev 适配器 (VS Code / JetBrains 插件)
3
- * 配置文件: ~/.continue/config.json
4
3
  *
5
- * Continue 支持自定义 provider,格式:
6
- * {
7
- * "models": [{
8
- * "title": "HolySheep Claude",
9
- * "provider": "openai",
10
- * "model": "claude-sonnet-4-5",
11
- * "apiKey": "cr_xxx",
12
- * "apiBase": "https://api.holysheep.ai/v1"
13
- * }]
14
- * }
4
+ * ⚠️ 重要:Continue 新版本已将配置文件从 config.json 迁移到 config.yaml (YAML格式)
5
+ * 配置文件: ~/.continue/config.yaml (优先) 或 ~/.continue/config.json (旧版兼容)
6
+ *
7
+ * YAML 格式示例:
8
+ * models:
9
+ * - name: HolySheep Claude Sonnet
10
+ * provider: openai
11
+ * model: claude-sonnet-4-5
12
+ * apiKey: cr_xxx
13
+ * apiBase: https://api.holysheep.ai/v1
14
+ *
15
+ * Continue 支持 OpenAI 兼容 provider,可接入任何兼容端点
16
+ * 官方文档: https://docs.continue.dev
15
17
  */
16
18
  const fs = require('fs')
17
19
  const path = require('path')
18
20
  const os = require('os')
19
21
 
20
- const CONFIG_FILE = path.join(os.homedir(), '.continue', 'config.json')
22
+ const CONTINUE_DIR = path.join(os.homedir(), '.continue')
23
+ const CONFIG_YAML = path.join(CONTINUE_DIR, 'config.yaml')
24
+ const CONFIG_JSON = path.join(CONTINUE_DIR, 'config.json')
25
+
26
+ function getConfigFile() {
27
+ // 优先使用 config.yaml (新版)
28
+ if (fs.existsSync(CONFIG_YAML)) return { file: CONFIG_YAML, format: 'yaml' }
29
+ if (fs.existsSync(CONFIG_JSON)) return { file: CONFIG_JSON, format: 'json' }
30
+ // 默认创建 yaml
31
+ return { file: CONFIG_YAML, format: 'yaml' }
32
+ }
33
+
34
+ function readJsonConfig() {
35
+ try {
36
+ return JSON.parse(fs.readFileSync(CONFIG_JSON, 'utf8'))
37
+ } catch {
38
+ return { models: [] }
39
+ }
40
+ }
21
41
 
22
- function readConfig() {
42
+ function writeJsonConfig(data) {
43
+ fs.mkdirSync(CONTINUE_DIR, { recursive: true })
44
+ fs.writeFileSync(CONFIG_JSON, JSON.stringify(data, null, 2), 'utf8')
45
+ }
46
+
47
+ function readYamlRaw() {
23
48
  try {
24
- if (fs.existsSync(CONFIG_FILE)) return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'))
49
+ if (fs.existsSync(CONFIG_YAML)) return fs.readFileSync(CONFIG_YAML, 'utf8')
25
50
  } catch {}
26
- return { models: [], tabAutocompleteModel: null }
51
+ return ''
27
52
  }
28
53
 
29
- function writeConfig(data) {
30
- fs.mkdirSync(path.dirname(CONFIG_FILE), { recursive: true })
31
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8')
54
+ /**
55
+ * 写入 YAML 配置(简单字符串追加/替换方式,不依赖 yaml 库)
56
+ * 先移除已有 HolySheep 模型块,再在 models: 下插入新的
57
+ */
58
+ function writeYamlConfig(apiKey, baseUrl, models) {
59
+ fs.mkdirSync(CONTINUE_DIR, { recursive: true })
60
+
61
+ let content = readYamlRaw()
62
+
63
+ // 移除旧的 holysheep 模型块(以 " - name: HolySheep" 开头到下一个 " - " 或 EOF)
64
+ content = content.replace(/ - name: HolySheep[^\n]*\n( [^\n]*\n)*/g, '')
65
+
66
+ // 如果没有 models: 段,则加上
67
+ if (!content.includes('models:')) {
68
+ content = 'models:\n' + content
69
+ }
70
+
71
+ // 构建要插入的模型 YAML 块
72
+ const modelBlocks = models.map(m => [
73
+ ` - name: ${m.name}`,
74
+ ` provider: openai`,
75
+ ` model: ${m.model}`,
76
+ ` apiKey: ${apiKey}`,
77
+ ` apiBase: ${baseUrl}`,
78
+ ].join('\n')).join('\n')
79
+
80
+ // 在 models: 之后插入
81
+ content = content.replace('models:\n', `models:\n${modelBlocks}\n`)
82
+
83
+ fs.writeFileSync(CONFIG_YAML, content.replace(/\n{3,}/g, '\n\n').trimStart(), 'utf8')
32
84
  }
33
85
 
34
- const HS_MODELS = (apiKey, baseUrl) => [
35
- {
36
- title: 'HolySheep — Claude Sonnet',
37
- provider: 'openai',
38
- model: 'claude-sonnet-4-5',
39
- apiKey,
40
- apiBase: baseUrl,
41
- },
42
- {
43
- title: 'HolySheep — Claude Opus',
44
- provider: 'openai',
45
- model: 'claude-opus-4-5',
46
- apiKey,
47
- apiBase: baseUrl,
48
- },
86
+ const HS_MODELS = [
87
+ { name: 'HolySheep — Claude Sonnet', model: 'claude-sonnet-4-5' },
88
+ { name: 'HolySheep — Claude Opus', model: 'claude-opus-4-5' },
49
89
  ]
50
90
 
51
91
  module.exports = {
52
92
  name: 'Continue.dev',
53
93
  id: 'continue',
54
94
  checkInstalled() {
55
- return fs.existsSync(path.join(os.homedir(), '.continue'))
95
+ return fs.existsSync(CONTINUE_DIR)
56
96
  },
57
97
  isConfigured() {
58
- const c = readConfig()
98
+ if (fs.existsSync(CONFIG_YAML)) {
99
+ return readYamlRaw().includes('holysheep')
100
+ }
101
+ const c = readJsonConfig()
59
102
  return (c.models || []).some(m => m.apiBase?.includes('holysheep'))
60
103
  },
61
- configure(apiKey, baseUrlOpenAI) {
62
- const config = readConfig()
63
- // 移除旧的 holysheep models
64
- config.models = (config.models || []).filter(m => !m.apiBase?.includes('holysheep'))
65
- // 插入新的
66
- config.models = [...HS_MODELS(apiKey, baseUrlOpenAI), ...config.models]
67
- writeConfig(config)
68
- return { file: CONFIG_FILE, hot: true }
104
+ configure(apiKey, _baseUrlAnthropicNoV1, baseUrlOpenAI) {
105
+ const { format } = getConfigFile()
106
+
107
+ if (format === 'yaml') {
108
+ writeYamlConfig(apiKey, baseUrlOpenAI, HS_MODELS)
109
+ return { file: CONFIG_YAML, hot: true }
110
+ } else {
111
+ // 兼容旧版 JSON 格式
112
+ const config = readJsonConfig()
113
+ config.models = (config.models || []).filter(m => !m.apiBase?.includes('holysheep'))
114
+ config.models = [
115
+ ...HS_MODELS.map(m => ({
116
+ title: m.name,
117
+ provider: 'openai',
118
+ model: m.model,
119
+ apiKey,
120
+ apiBase: baseUrlOpenAI,
121
+ })),
122
+ ...config.models,
123
+ ]
124
+ writeJsonConfig(config)
125
+ return { file: CONFIG_JSON, hot: true }
126
+ }
69
127
  },
70
128
  reset() {
71
- const config = readConfig()
72
- config.models = (config.models || []).filter(m => !m.apiBase?.includes('holysheep'))
73
- writeConfig(config)
129
+ if (fs.existsSync(CONFIG_YAML)) {
130
+ let content = readYamlRaw()
131
+ content = content.replace(/ - name: HolySheep[^\n]*\n( [^\n]*\n)*/g, '')
132
+ fs.writeFileSync(CONFIG_YAML, content, 'utf8')
133
+ }
134
+ if (fs.existsSync(CONFIG_JSON)) {
135
+ const config = readJsonConfig()
136
+ config.models = (config.models || []).filter(m => !m.apiBase?.includes('holysheep'))
137
+ writeJsonConfig(config)
138
+ }
74
139
  },
75
- getConfigPath() { return CONFIG_FILE },
76
- hint: '配置后在 VS Code Continue 面板选择 HolySheep 模型即可使用',
140
+ getConfigPath() { return fs.existsSync(CONFIG_YAML) ? CONFIG_YAML : CONFIG_JSON },
141
+ hint: '新版使用 config.yaml;配置后在 VS Code Continue 面板选择 HolySheep 模型',
77
142
  installCmd: 'VS Code 插件市场搜索 "Continue"',
78
143
  docsUrl: 'https://continue.dev',
79
144
  }
@@ -1,21 +1,32 @@
1
1
  /**
2
- * OpenCode 适配器 (sst/opencode)
3
- * 配置文件: ~/.config/opencode/config.json 或 ~/.opencode/config.json
4
- * 格式: JSON,支持 providers 数组
2
+ * OpenCode 适配器 (anomalyco/opencode,原 sst/opencode)
3
+ *
4
+ * ⚠️ 重要:OpenCode 仓库已从 sst/opencode 迁移到 anomalyco/opencode
5
+ * 全局配置文件: ~/.config/opencode/opencode.json (不是 config.json!)
6
+ * 格式: JSON/JSONC,provider 配置格式如下:
5
7
  *
6
- * OpenCode provider 格式:
7
8
  * {
8
- * "providers": {
9
+ * "$schema": "https://opencode.ai/config.json",
10
+ * "model": "anthropic/claude-sonnet-4-5",
11
+ * "provider": {
9
12
  * "anthropic": {
10
- * "apiKey": "cr_xxx",
11
- * "baseURL": "https://api.holysheep.ai"
13
+ * "options": {
14
+ * "baseURL": "https://api.holysheep.ai",
15
+ * "apiKey": "cr_xxx"
16
+ * }
12
17
  * },
13
18
  * "openai": {
14
- * "apiKey": "cr_xxx",
15
- * "baseURL": "https://api.holysheep.ai/v1"
19
+ * "options": {
20
+ * "baseURL": "https://api.holysheep.ai/v1",
21
+ * "apiKey": "cr_xxx"
22
+ * }
16
23
  * }
17
24
  * }
18
25
  * }
26
+ *
27
+ * 安装方式(推荐): brew install anomalyco/tap/opencode
28
+ * 或: npm i -g opencode-ai@latest
29
+ * 官方文档: https://opencode.ai/docs/config
19
30
  */
20
31
  const fs = require('fs')
21
32
  const path = require('path')
@@ -23,22 +34,30 @@ const os = require('os')
23
34
 
24
35
  function getConfigFile() {
25
36
  const candidates = [
37
+ // 新版标准路径(官方文档)
38
+ path.join(os.homedir(), '.config', 'opencode', 'opencode.json'),
39
+ // 旧版路径兼容
26
40
  path.join(os.homedir(), '.config', 'opencode', 'config.json'),
41
+ path.join(os.homedir(), '.opencode', 'opencode.json'),
27
42
  path.join(os.homedir(), '.opencode', 'config.json'),
28
43
  // Windows
29
- path.join(os.homedir(), 'AppData', 'Roaming', 'opencode', 'config.json'),
44
+ path.join(os.homedir(), 'AppData', 'Roaming', 'opencode', 'opencode.json'),
30
45
  ]
31
46
  for (const f of candidates) {
32
47
  if (fs.existsSync(f)) return f
33
48
  }
34
- // 默认路径
35
- return path.join(os.homedir(), '.config', 'opencode', 'config.json')
49
+ // 默认路径(新版标准)
50
+ return path.join(os.homedir(), '.config', 'opencode', 'opencode.json')
36
51
  }
37
52
 
38
53
  function readConfig() {
39
54
  const file = getConfigFile()
40
55
  try {
41
- if (fs.existsSync(file)) return JSON.parse(fs.readFileSync(file, 'utf8'))
56
+ if (fs.existsSync(file)) {
57
+ // 支持 JSONC(带注释的 JSON)
58
+ const content = fs.readFileSync(file, 'utf8')
59
+ return JSON.parse(content.replace(/\/\/[^\n]*/g, '').replace(/\/\*[\s\S]*?\*\//g, ''))
60
+ }
42
61
  } catch {}
43
62
  return {}
44
63
  }
@@ -57,33 +76,52 @@ module.exports = {
57
76
  },
58
77
  isConfigured() {
59
78
  const c = readConfig()
60
- return !!(c.providers?.anthropic?.baseURL?.includes('holysheep') ||
61
- c.providers?.openai?.baseURL?.includes('holysheep'))
79
+ return !!(
80
+ c.provider?.anthropic?.options?.baseURL?.includes('holysheep') ||
81
+ c.provider?.openai?.options?.baseURL?.includes('holysheep')
82
+ )
62
83
  },
63
84
  configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
64
85
  const config = readConfig()
65
- if (!config.providers) config.providers = {}
66
- config.providers.anthropic = {
67
- apiKey,
68
- baseURL: baseUrlAnthropicNoV1,
86
+ if (!config.provider) config.provider = {}
87
+
88
+ // 设置 schema(方便编辑器自动补全)
89
+ if (!config['$schema']) config['$schema'] = 'https://opencode.ai/config.json'
90
+
91
+ // 配置 Anthropic provider(Claude 模型)
92
+ config.provider.anthropic = {
93
+ options: {
94
+ baseURL: baseUrlAnthropicNoV1, // https://api.holysheep.ai (无 /v1)
95
+ apiKey,
96
+ },
69
97
  }
70
- config.providers.openai = {
71
- apiKey,
72
- baseURL: baseUrlOpenAI,
98
+
99
+ // 配置 OpenAI provider(GPT 模型)
100
+ config.provider.openai = {
101
+ options: {
102
+ baseURL: baseUrlOpenAI, // https://api.holysheep.ai/v1
103
+ apiKey,
104
+ },
105
+ }
106
+
107
+ // 设置默认模型
108
+ if (!config.model) {
109
+ config.model = 'anthropic/claude-sonnet-4-5'
73
110
  }
111
+
74
112
  writeConfig(config)
75
113
  return { file: getConfigFile(), hot: false }
76
114
  },
77
115
  reset() {
78
116
  const config = readConfig()
79
- if (config.providers) {
80
- delete config.providers.anthropic
81
- delete config.providers.openai
117
+ if (config.provider) {
118
+ delete config.provider.anthropic
119
+ delete config.provider.openai
82
120
  }
83
121
  writeConfig(config)
84
122
  },
85
123
  getConfigPath() { return getConfigFile() },
86
- hint: '切换后重启 OpenCode 生效',
87
- installCmd: 'npm install -g opencode-ai',
88
- docsUrl: 'https://github.com/sst/opencode',
124
+ hint: '切换后重启 OpenCode 生效;配置文件: ~/.config/opencode/opencode.json',
125
+ installCmd: 'brew install anomalyco/tap/opencode # 或: npm i -g opencode-ai@latest',
126
+ docsUrl: 'https://opencode.ai',
89
127
  }