@simonyea/holysheep-cli 2.1.40 → 2.1.41

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.
Files changed (45) hide show
  1. package/dist/configure-worker.js +4491 -0
  2. package/dist/index.js +9591 -0
  3. package/dist/process-proxy-inject.js +117 -0
  4. package/package.json +20 -7
  5. package/.gitea/workflows/sanity.yml +0 -125
  6. package/scripts/check-tarball-size.js +0 -44
  7. package/src/commands/balance.js +0 -57
  8. package/src/commands/claude-proxy.js +0 -248
  9. package/src/commands/claude.js +0 -135
  10. package/src/commands/doctor.js +0 -282
  11. package/src/commands/login.js +0 -211
  12. package/src/commands/openclaw.js +0 -258
  13. package/src/commands/reset.js +0 -53
  14. package/src/commands/setup.js +0 -493
  15. package/src/commands/upgrade.js +0 -168
  16. package/src/commands/webui.js +0 -622
  17. package/src/index.js +0 -226
  18. package/src/tools/aider.js +0 -78
  19. package/src/tools/antigravity.js +0 -42
  20. package/src/tools/claude-code.js +0 -228
  21. package/src/tools/claude-process-proxy.js +0 -1030
  22. package/src/tools/codex.js +0 -254
  23. package/src/tools/continue.js +0 -146
  24. package/src/tools/cursor.js +0 -71
  25. package/src/tools/droid.js +0 -281
  26. package/src/tools/env-config.js +0 -185
  27. package/src/tools/gemini-cli.js +0 -82
  28. package/src/tools/hermes.js +0 -354
  29. package/src/tools/index.js +0 -13
  30. package/src/tools/openclaw-bridge.js +0 -987
  31. package/src/tools/openclaw.js +0 -925
  32. package/src/tools/opencode.js +0 -227
  33. package/src/tools/process-proxy-inject.js +0 -142
  34. package/src/utils/config.js +0 -54
  35. package/src/utils/shell.js +0 -342
  36. package/src/utils/which.js +0 -176
  37. package/src/webui/aionui-runtime-fetcher.js +0 -429
  38. package/src/webui/aionui-runtime.js +0 -139
  39. package/src/webui/aionui-wrapper.js +0 -734
  40. package/src/webui/configure-worker.js +0 -67
  41. package/src/webui/server.js +0 -1572
  42. package/src/webui/workspace-runtime.js +0 -288
  43. package/src/webui/workspace-store.js +0 -325
  44. /package/{src/webui → dist}/index.html +0 -0
  45. /package/{src/tools → dist}/pty-hermes-wrapper.py +0 -0
@@ -1,254 +0,0 @@
1
- /**
2
- * Codex CLI 适配器 (@openai/codex v0.111+, Rust 版)
3
- *
4
- * ⚠️ 重要:v0.111.0 起 Codex 已切换到 Rust 实现(codex-rs)
5
- * 配置文件变更:~/.codex/config.toml(TOML 格式,不是 JSON!)
6
- *
7
- * 正确格式(config.toml):
8
- *
9
- * model = "gpt-5.4"
10
- * model_provider = "holysheep"
11
- *
12
- * [model_providers.holysheep]
13
- * name = "HolySheep"
14
- * base_url = "https://api.holysheep.ai/v1"
15
- * wire_api = "responses"
16
- *
17
- * [model_providers.holysheep.http_headers]
18
- * Authorization = "Bearer cr_xxx"
19
- *
20
- * 注意:Codex RS 不支持 api_key 字段,env_key 需要环境变量(Windows 需重启终端)。
21
- * 改用 http_headers 直接设置 Authorization header,配置即生效。
22
- */
23
- const fs = require('fs')
24
- const path = require('path')
25
- const os = require('os')
26
-
27
- const CONFIG_DIR = path.join(os.homedir(), '.codex')
28
- const CONFIG_FILE = path.join(CONFIG_DIR, 'config.toml')
29
- // 保留 JSON 兼容性(老版本 TypeScript Codex 用)
30
- const CONFIG_FILE_JSON = path.join(CONFIG_DIR, 'config.json')
31
- const AUTH_FILE = path.join(CONFIG_DIR, 'auth.json')
32
-
33
- function normalizeToml(content) {
34
- return String(content || '').replace(/\r\n/g, '\n')
35
- }
36
-
37
- function cleanupToml(content) {
38
- return normalizeToml(content)
39
- .replace(/\n{3,}/g, '\n\n')
40
- .trim()
41
- }
42
-
43
- function stripManagedTomlConfig(content) {
44
- const lines = normalizeToml(content).split('\n')
45
- const output = []
46
- let currentSection = null
47
- let skipHolySheepBlock = false
48
-
49
- for (const line of lines) {
50
- const trimmed = line.trim()
51
-
52
- if (/^\[[^\]]+\]$/.test(trimmed)) {
53
- if (trimmed === '[model_providers.holysheep]' ||
54
- trimmed === '[model_providers.holysheep.http_headers]') {
55
- currentSection = trimmed
56
- skipHolySheepBlock = true
57
- continue
58
- }
59
-
60
- currentSection = trimmed
61
- skipHolySheepBlock = false
62
- }
63
-
64
- if (skipHolySheepBlock) continue
65
-
66
- if (!currentSection) {
67
- if (/^model\s*=\s*"[^"]*"\s*$/.test(trimmed)) continue
68
- if (/^model_provider\s*=/.test(trimmed)) continue
69
- if (/^preferred_auth_method\s*=/.test(trimmed)) continue
70
- }
71
-
72
- output.push(line)
73
- }
74
-
75
- return cleanupToml(output.join('\n'))
76
- }
77
-
78
- /**
79
- * 读取 TOML config(简单解析,不依赖 toml 库)
80
- */
81
- function readTomlConfig() {
82
- try {
83
- if (fs.existsSync(CONFIG_FILE)) {
84
- return fs.readFileSync(CONFIG_FILE, 'utf8')
85
- }
86
- } catch {}
87
- return ''
88
- }
89
-
90
- /**
91
- * 检查 TOML 里是否已配置 holysheep
92
- */
93
- function isConfiguredInToml() {
94
- const content = readTomlConfig()
95
- return content.includes('model_provider = "holysheep"') &&
96
- content.includes('base_url') &&
97
- content.includes('holysheep.ai')
98
- }
99
-
100
- /**
101
- * 写入 TOML config(合并方式:保留已有内容,只更新 holysheep 部分)
102
- */
103
- function writeTomlConfig(apiKey, baseUrlOpenAI, model) {
104
- if (!fs.existsSync(CONFIG_DIR)) {
105
- fs.mkdirSync(CONFIG_DIR, { recursive: true })
106
- }
107
-
108
- const content = stripManagedTomlConfig(readTomlConfig())
109
-
110
- // 在开头插入 holysheep 配置
111
- // 使用 http_headers 直接设置 Authorization,不依赖环境变量
112
- const newConfig = [
113
- `model = "${model || 'gpt-5.4'}"`,
114
- `model_provider = "holysheep"`,
115
- '',
116
- content,
117
- '',
118
- `[model_providers.holysheep]`,
119
- `name = "HolySheep"`,
120
- `base_url = "${baseUrlOpenAI}"`,
121
- `wire_api = "responses"`,
122
- '',
123
- `[model_providers.holysheep.http_headers]`,
124
- `Authorization = "Bearer ${apiKey}"`,
125
- '',
126
- ].join('\n')
127
-
128
- fs.writeFileSync(CONFIG_FILE, cleanupToml(newConfig) + '\n', 'utf8')
129
- }
130
-
131
- /**
132
- * 同时写 JSON(兼容旧版 TypeScript Codex,如果存在的话)
133
- */
134
- function writeJsonConfigIfNeeded(apiKey, baseUrlOpenAI, model) {
135
- try {
136
- let jsonConfig = {}
137
- if (fs.existsSync(CONFIG_FILE_JSON)) {
138
- jsonConfig = JSON.parse(fs.readFileSync(CONFIG_FILE_JSON, 'utf8'))
139
- }
140
- jsonConfig.model = model || 'gpt-5.4'
141
- jsonConfig.model_provider = 'holysheep'
142
- jsonConfig.provider = 'holysheep'
143
- if (!jsonConfig.model_providers) jsonConfig.model_providers = {}
144
- if (!jsonConfig.providers) jsonConfig.providers = {}
145
- jsonConfig.model_providers.holysheep = {
146
- name: 'HolySheep',
147
- base_url: baseUrlOpenAI,
148
- api_key: apiKey,
149
- wire_api: 'responses',
150
- }
151
- jsonConfig.providers.holysheep = {
152
- name: 'HolySheep',
153
- baseURL: baseUrlOpenAI,
154
- apiKey: apiKey,
155
- }
156
- fs.writeFileSync(CONFIG_FILE_JSON, JSON.stringify(jsonConfig, null, 2), 'utf8')
157
- } catch {}
158
- }
159
-
160
- /**
161
- * 清除 auth.json 中的 ChatGPT OAuth 认证,避免干扰 holysheep provider
162
- * Codex RS bug: auth_mode=chatgpt 时 OAuth token 会覆盖自定义 provider 的 api_key
163
- *
164
- * Windows: Defender occasionally holds an open handle to auth.json during the
165
- * first post-install scan, so an immediate `unlinkSync` returns EBUSY. Retry
166
- * up to 5 times with a short backoff. On non-Windows a single pass suffices.
167
- */
168
- function neutralizeAuthJson() {
169
- const MAX_ATTEMPTS = process.platform === 'win32' ? 5 : 1
170
- for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
171
- try {
172
- fs.unlinkSync(AUTH_FILE)
173
- return
174
- } catch (e) {
175
- if (e && e.code === 'ENOENT') return // already gone — success
176
- if (attempt === MAX_ATTEMPTS) {
177
- // Last try failed — on Windows fall back to truncating the file to
178
- // an empty JSON object. Codex RS treats `{}` as "no chatgpt session",
179
- // so the config.toml's `http_headers.Authorization` takes over.
180
- try { fs.writeFileSync(AUTH_FILE, '{}\n', 'utf8') } catch {}
181
- return
182
- }
183
- // Sleep ~200ms via a synchronous shell command. We avoid pulling in a
184
- // new dep or using Atomics.wait here to keep the tool footprint small.
185
- try {
186
- require('child_process').execSync(
187
- process.platform === 'win32'
188
- ? 'powershell -NoProfile -Command "Start-Sleep -Milliseconds 200"'
189
- : 'sleep 0.2',
190
- { stdio: 'ignore' }
191
- )
192
- } catch {}
193
- }
194
- }
195
- }
196
-
197
- module.exports = {
198
- name: 'Codex CLI',
199
- id: 'codex',
200
- checkInstalled() {
201
- return require('../utils/which').commandExists('codex')
202
- },
203
- isConfigured() {
204
- return isConfiguredInToml()
205
- },
206
- configure(apiKey, _baseUrlAnthropicNoV1, baseUrlOpenAI) {
207
- const model = 'gpt-5.4'
208
-
209
- // 写入 TOML(Rust Codex v0.111+ 使用)
210
- // Codex RS 不支持 api_key 字段,必须用 env_key 指向环境变量
211
- writeTomlConfig(apiKey, baseUrlOpenAI, model)
212
-
213
- // 同时写 JSON(兼容旧版 TypeScript Codex)
214
- writeJsonConfigIfNeeded(apiKey, baseUrlOpenAI, model)
215
-
216
- // 清除 auth.json 中的 ChatGPT OAuth 认证,避免干扰
217
- neutralizeAuthJson()
218
-
219
- return {
220
- file: CONFIG_FILE,
221
- hot: false,
222
- }
223
- },
224
- reset() {
225
- // 清理 TOML
226
- if (fs.existsSync(CONFIG_FILE)) {
227
- const content = stripManagedTomlConfig(readTomlConfig())
228
- fs.writeFileSync(CONFIG_FILE, (content ? content + '\n' : ''), 'utf8')
229
- }
230
- // 清理 JSON
231
- if (fs.existsSync(CONFIG_FILE_JSON)) {
232
- try {
233
- const c = JSON.parse(fs.readFileSync(CONFIG_FILE_JSON, 'utf8'))
234
- if (c.model_provider === 'holysheep') {
235
- delete c.model_provider
236
- }
237
- if (c.provider === 'holysheep') {
238
- delete c.provider
239
- }
240
- delete c.model_providers?.holysheep
241
- delete c.providers?.holysheep
242
- if (c.model_providers && Object.keys(c.model_providers).length === 0) delete c.model_providers
243
- if (c.providers && Object.keys(c.providers).length === 0) delete c.providers
244
- fs.writeFileSync(CONFIG_FILE_JSON, JSON.stringify(c, null, 2), 'utf8')
245
- } catch {}
246
- }
247
- },
248
- getConfigPath() { return CONFIG_FILE },
249
- hint: '切换后重开终端生效;Rust Codex (v0.111+) 使用 config.toml',
250
- launchCmd: 'codex',
251
- installCmd: 'npm install -g @openai/codex',
252
- docsUrl: 'https://github.com/openai/codex',
253
- envVarFormat: 'openai',
254
- }
@@ -1,146 +0,0 @@
1
- /**
2
- * Continue.dev 适配器 (VS Code / JetBrains 插件)
3
- *
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
17
- */
18
- const fs = require('fs')
19
- const path = require('path')
20
- const os = require('os')
21
-
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
- }
41
-
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() {
48
- try {
49
- if (fs.existsSync(CONFIG_YAML)) return fs.readFileSync(CONFIG_YAML, 'utf8')
50
- } catch {}
51
- return ''
52
- }
53
-
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')
84
- }
85
-
86
- const HS_MODELS = [
87
- { name: 'HolySheep — Claude Sonnet', model: 'claude-sonnet-4-6' },
88
- { name: 'HolySheep — Claude Opus', model: 'claude-opus-4-6' },
89
- ]
90
-
91
- module.exports = {
92
- name: 'Continue.dev',
93
- id: 'continue',
94
- checkInstalled() {
95
- return fs.existsSync(CONTINUE_DIR)
96
- },
97
- isConfigured() {
98
- if (fs.existsSync(CONFIG_YAML)) {
99
- return readYamlRaw().includes('holysheep')
100
- }
101
- const c = readJsonConfig()
102
- return (c.models || []).some(m => m.apiBase?.includes('holysheep'))
103
- },
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
- }
127
- },
128
- reset() {
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
- }
139
- },
140
- getConfigPath() { return fs.existsSync(CONFIG_YAML) ? CONFIG_YAML : CONFIG_JSON },
141
- hint: '新版使用 config.yaml;配置后在 VS Code Continue 面板选择 HolySheep 模型',
142
- launchCmd: null, // VS Code 插件,在编辑器内使用
143
- launchNote: '在 VS Code 侧边栏打开 Continue 面板即可使用',
144
- installCmd: 'VS Code 插件市场搜索 "Continue"',
145
- docsUrl: 'https://continue.dev',
146
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * Cursor 适配器
3
- *
4
- * ⚠️ 重要:Cursor 新版本(2025+)必须登录官方账号才能使用,
5
- * 即使是「自带 API Key」模式也需要先登录 Cursor 账号。
6
- * Cursor 的 API Key 和 Base URL 存储在加密的 secret storage 中,
7
- * CLI 无法直接写入,且官方越来越绑定自己的账号体系。
8
- *
9
- * 推荐替代方案:
10
- * - Continue(VS Code/JetBrains 插件,完全支持自定义 API)
11
- * - Claude Code(命令行,官方支持自定义 base_url)
12
- * - Aider(命令行,完全支持自定义 API)
13
- *
14
- * 如果仍要手动配置 Cursor:
15
- * Settings → Models → Override OpenAI Base URL + OpenAI API Key
16
- */
17
- const fs = require('fs')
18
- const path = require('path')
19
- const os = require('os')
20
- const { execSync } = require('child_process')
21
-
22
- function getCursorUserDir() {
23
- const p = process.platform
24
- if (p === 'darwin') return path.join(os.homedir(), 'Library', 'Application Support', 'Cursor', 'User')
25
- if (p === 'win32') return path.join(os.homedir(), 'AppData', 'Roaming', 'Cursor', 'User')
26
- return path.join(os.homedir(), '.config', 'Cursor', 'User')
27
- }
28
-
29
- function checkCursorInstalled() {
30
- const p = process.platform
31
- if (p === 'darwin') return fs.existsSync('/Applications/Cursor.app') || fs.existsSync(path.join(os.homedir(), 'Applications', 'Cursor.app'))
32
- if (p === 'win32') return fs.existsSync(path.join(os.homedir(), 'AppData', 'Local', 'Programs', 'cursor', 'Cursor.exe'))
33
- try { execSync('which cursor', { stdio: 'ignore' }); return true } catch {}
34
- return false
35
- }
36
-
37
- module.exports = {
38
- name: 'Cursor',
39
- id: 'cursor',
40
- checkInstalled() { return checkCursorInstalled() },
41
- isConfigured() {
42
- return false // 无法检测(加密存储)
43
- },
44
- configure(apiKey, _baseUrlAnthropicNoV1, baseUrlOpenAI) {
45
- // Cursor 需要登录官方账号,且 API Key 存储在加密区域,CLI 无法写入
46
- // 返回 manual + warning
47
- return {
48
- manual: true,
49
- steps: [
50
- '⚠️ Cursor 新版本需要先登录官方账号(免费账号即可)',
51
- '打开 Cursor → Settings(⌘+, / Ctrl+,)→ 左侧 Models',
52
- '找到 "OpenAI API Key" 区域,勾选 "Enable OpenAI API Key"',
53
- `填入 API Key: ${apiKey}`,
54
- `填入 Override OpenAI Base URL: ${baseUrlOpenAI}`,
55
- '点击 "Verify" 验证连接,然后在模型列表中选择 claude-* 模型',
56
- '💡 推荐使用 Continue(VS Code 插件)替代,配置更简单',
57
- ],
58
- }
59
- },
60
- reset() {
61
- return {
62
- manual: true,
63
- steps: ['打开 Cursor Settings → Models → 清除 API Key 和 Override Base URL'],
64
- }
65
- },
66
- getConfigPath() { return getCursorUserDir() },
67
- hint: '需要登录 Cursor 账号 + 在 GUI 中手动配置(推荐用 Continue 替代)',
68
- installCmd: '访问 https://cursor.sh 下载安装',
69
- docsUrl: 'https://cursor.sh',
70
- unsupported: true,
71
- }