@simonyea/holysheep-cli 1.2.3 → 1.2.4
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/tools/openclaw.js +131 -77
package/package.json
CHANGED
package/src/tools/openclaw.js
CHANGED
|
@@ -8,22 +8,25 @@
|
|
|
8
8
|
* 配置文件: ~/.openclaw/openclaw.json (JSON5 格式)
|
|
9
9
|
* 文档: https://docs.openclaw.ai
|
|
10
10
|
*
|
|
11
|
-
* HolySheep
|
|
12
|
-
*
|
|
11
|
+
* HolySheep 接入方式:
|
|
12
|
+
* 1. 直接写入完整的 openclaw.json(含 auth profile + gateway + 默认模型)
|
|
13
|
+
* 2. 自动启动 Gateway,用户直接打开 http://127.0.0.1:18789/
|
|
14
|
+
* 不需要用户手动跑 onboard / gateway start
|
|
13
15
|
*/
|
|
14
|
-
const fs
|
|
15
|
-
const path
|
|
16
|
-
const os
|
|
16
|
+
const fs = require('fs')
|
|
17
|
+
const path = require('path')
|
|
18
|
+
const os = require('os')
|
|
19
|
+
const crypto = require('crypto')
|
|
17
20
|
const { spawnSync } = require('child_process')
|
|
18
21
|
|
|
19
|
-
const OPENCLAW_DIR
|
|
20
|
-
const CONFIG_FILE
|
|
22
|
+
const OPENCLAW_DIR = path.join(os.homedir(), '.openclaw')
|
|
23
|
+
const CONFIG_FILE = path.join(OPENCLAW_DIR, 'openclaw.json')
|
|
21
24
|
|
|
22
25
|
function readConfig() {
|
|
23
26
|
try {
|
|
24
27
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
25
|
-
// openclaw.json 是 JSON5 格式,先去掉注释再 parse
|
|
26
28
|
const raw = fs.readFileSync(CONFIG_FILE, 'utf8')
|
|
29
|
+
// openclaw.json 是 JSON5 格式,先去掉注释再 parse
|
|
27
30
|
return JSON.parse(raw.replace(/\/\/[^\n]*/g, '').replace(/\/\*[\s\S]*?\*\//g, ''))
|
|
28
31
|
}
|
|
29
32
|
} catch {}
|
|
@@ -35,122 +38,173 @@ function writeConfig(data) {
|
|
|
35
38
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8')
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
/** 生成随机 Gateway token */
|
|
42
|
+
function genToken() {
|
|
43
|
+
return crypto.randomBytes(24).toString('hex')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 构建完整的初始化配置
|
|
48
|
+
* 包含:auth profile(HolySheep Anthropic-compatible)+ gateway + 默认模型 + holysheep provider
|
|
49
|
+
*/
|
|
50
|
+
function buildFullConfig(existing, apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
|
|
51
|
+
const config = JSON.parse(JSON.stringify(existing || {})) // deep clone
|
|
52
|
+
|
|
53
|
+
// ── 1. 环境变量(兼容 Anthropic SDK 自动读取)──────────────────────
|
|
54
|
+
if (!config.env) config.env = {}
|
|
55
|
+
config.env.ANTHROPIC_API_KEY = apiKey
|
|
56
|
+
config.env.ANTHROPIC_BASE_URL = baseUrlAnthropicNoV1 // https://api.holysheep.ai
|
|
57
|
+
|
|
58
|
+
// ── 2. Auth profile(Custom Provider,Anthropic-compatible)────────
|
|
59
|
+
// openclaw 通过 auth profile 管理凭证;写入一个 holysheep profile
|
|
60
|
+
if (!config.auth) config.auth = {}
|
|
61
|
+
if (!config.auth.profiles) config.auth.profiles = {}
|
|
62
|
+
config.auth.profiles.holysheep = {
|
|
63
|
+
type: 'api-key',
|
|
64
|
+
provider: 'anthropic',
|
|
65
|
+
apiKey,
|
|
66
|
+
baseUrl: baseUrlAnthropicNoV1,
|
|
67
|
+
}
|
|
68
|
+
config.auth.default = 'holysheep'
|
|
69
|
+
|
|
70
|
+
// ── 3. 默认模型 ────────────────────────────────────────────────────
|
|
71
|
+
if (!config.agents) config.agents = {}
|
|
72
|
+
if (!config.agents.defaults) config.agents.defaults = {}
|
|
73
|
+
// 总是覆写为 HolySheep sonnet-4-6(用户可以在 /model 命令里切换)
|
|
74
|
+
config.agents.defaults.model = {
|
|
75
|
+
primary: 'anthropic/claude-sonnet-4-6',
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── 4. 自定义 holysheep provider(OpenAI-compatible,支持所有模型)
|
|
79
|
+
if (!config.models) config.models = {}
|
|
80
|
+
config.models.mode = 'merge'
|
|
81
|
+
if (!config.models.providers) config.models.providers = {}
|
|
82
|
+
config.models.providers.holysheep = {
|
|
83
|
+
baseUrl: baseUrlOpenAI, // https://api.holysheep.ai/v1
|
|
84
|
+
apiKey,
|
|
85
|
+
api: 'openai-completions',
|
|
86
|
+
models: [
|
|
87
|
+
{ id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4.6 (HolySheep)' },
|
|
88
|
+
{ id: 'claude-sonnet-4-5-20250929', name: 'Claude Sonnet 4.5 (HolySheep)' },
|
|
89
|
+
{ id: 'claude-sonnet-4-20250514', name: 'Claude Sonnet 4 (HolySheep)' },
|
|
90
|
+
{ id: 'claude-opus-4-5-20251101', name: 'Claude Opus 4.5 (HolySheep)' },
|
|
91
|
+
{ id: 'claude-opus-4-20250514', name: 'Claude Opus 4 (HolySheep)' },
|
|
92
|
+
{ id: 'gpt-4o', name: 'GPT-4o (HolySheep)' },
|
|
93
|
+
{ id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro (HolySheep)' },
|
|
94
|
+
],
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ── 5. Gateway 配置(如未设置则初始化,保留已有配置)────────────────
|
|
98
|
+
if (!config.gateway) config.gateway = {}
|
|
99
|
+
if (!config.gateway.port) config.gateway.port = 18789
|
|
100
|
+
if (!config.gateway.bind) config.gateway.bind = '127.0.0.1'
|
|
101
|
+
// 生成 gateway token(若已有则不覆盖)
|
|
102
|
+
if (!config.gateway.auth) config.gateway.auth = {}
|
|
103
|
+
if (!config.gateway.auth.token) {
|
|
104
|
+
config.gateway.auth.token = genToken()
|
|
105
|
+
config.gateway.auth.mode = 'token'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ── 6. Workspace 默认路径 ─────────────────────────────────────────
|
|
109
|
+
if (!config.workspace) {
|
|
110
|
+
config.workspace = path.join(OPENCLAW_DIR, 'workspace')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return config
|
|
114
|
+
}
|
|
115
|
+
|
|
38
116
|
module.exports = {
|
|
39
117
|
name: 'OpenClaw',
|
|
40
|
-
id:
|
|
118
|
+
id: 'openclaw',
|
|
119
|
+
|
|
41
120
|
checkInstalled() {
|
|
42
121
|
return require('../utils/which').commandExists('openclaw')
|
|
43
122
|
},
|
|
123
|
+
|
|
44
124
|
isConfigured() {
|
|
45
125
|
const c = readConfig()
|
|
46
126
|
return !!(
|
|
47
|
-
c.
|
|
48
|
-
c.
|
|
127
|
+
c.auth?.profiles?.holysheep ||
|
|
128
|
+
c.env?.ANTHROPIC_BASE_URL?.includes('holysheep')
|
|
49
129
|
)
|
|
50
130
|
},
|
|
51
|
-
configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
|
|
52
|
-
const config = readConfig()
|
|
53
131
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
config
|
|
57
|
-
config.env.ANTHROPIC_BASE_URL = baseUrlAnthropicNoV1 // https://api.holysheep.ai
|
|
58
|
-
|
|
59
|
-
// 设置默认模型(如果未配置)
|
|
60
|
-
if (!config.agents) config.agents = {}
|
|
61
|
-
if (!config.agents.defaults) config.agents.defaults = {}
|
|
62
|
-
if (!config.agents.defaults.model) {
|
|
63
|
-
config.agents.defaults.model = { primary: 'anthropic/claude-sonnet-4-5-20250929' }
|
|
64
|
-
}
|
|
132
|
+
configure(apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI) {
|
|
133
|
+
const existing = readConfig()
|
|
134
|
+
const config = buildFullConfig(existing, apiKey, baseUrlAnthropicNoV1, baseUrlOpenAI)
|
|
65
135
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
config.models.mode = 'merge'
|
|
69
|
-
if (!config.models.providers) config.models.providers = {}
|
|
70
|
-
config.models.providers.holysheep = {
|
|
71
|
-
baseUrl: baseUrlOpenAI, // https://api.holysheep.ai/v1
|
|
72
|
-
apiKey,
|
|
73
|
-
api: 'openai-completions',
|
|
74
|
-
models: [
|
|
75
|
-
{ id: 'claude-sonnet-4-5-20250929', name: 'Claude Sonnet 4.5 (HolySheep)' },
|
|
76
|
-
{ id: 'claude-sonnet-4-20250514', name: 'Claude Sonnet 4 (HolySheep)' },
|
|
77
|
-
{ id: 'claude-opus-4-5-20251101', name: 'Claude Opus 4.5 (HolySheep)' },
|
|
78
|
-
{ id: 'claude-opus-4-20250514', name: 'Claude Opus 4 (HolySheep)' },
|
|
79
|
-
{ id: 'gpt-4o', name: 'GPT-4o (HolySheep)' },
|
|
80
|
-
{ id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro (HolySheep)' },
|
|
81
|
-
],
|
|
82
|
-
}
|
|
136
|
+
// 确保 workspace 目录存在(openclaw 首次启动需要)
|
|
137
|
+
fs.mkdirSync(config.workspace, { recursive: true })
|
|
83
138
|
|
|
84
139
|
writeConfig(config)
|
|
85
140
|
|
|
86
|
-
// 自动启动 Gateway
|
|
87
|
-
// 先尝试安装 daemon(系统服务),再 start;失败不阻断配置流程
|
|
141
|
+
// 自动启动 Gateway,用户直接打开浏览器即可
|
|
88
142
|
_autoStartGateway()
|
|
89
143
|
|
|
90
144
|
return { file: CONFIG_FILE, hot: false, _gatewayStarted: true }
|
|
91
145
|
},
|
|
146
|
+
|
|
92
147
|
reset() {
|
|
93
148
|
const config = readConfig()
|
|
94
149
|
if (config.env) {
|
|
95
150
|
delete config.env.ANTHROPIC_API_KEY
|
|
96
151
|
delete config.env.ANTHROPIC_BASE_URL
|
|
97
152
|
}
|
|
98
|
-
if (config.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// 如果默认模型是 anthropic/xxx,清掉
|
|
153
|
+
if (config.auth?.profiles) delete config.auth.profiles.holysheep
|
|
154
|
+
if (config.auth?.default === 'holysheep') delete config.auth.default
|
|
155
|
+
if (config.models?.providers) delete config.models.providers.holysheep
|
|
102
156
|
if (config.agents?.defaults?.model?.primary?.startsWith('anthropic/')) {
|
|
103
157
|
delete config.agents.defaults.model
|
|
104
158
|
}
|
|
105
159
|
writeConfig(config)
|
|
106
160
|
},
|
|
161
|
+
|
|
107
162
|
getConfigPath() { return CONFIG_FILE },
|
|
108
|
-
hint:
|
|
109
|
-
launchCmd:
|
|
163
|
+
hint: 'Gateway 已自动在后台启动,打开浏览器即可使用',
|
|
164
|
+
launchCmd: null,
|
|
110
165
|
launchNote: '🌐 打开浏览器访问 http://127.0.0.1:18789/',
|
|
111
166
|
installCmd: 'npm install -g openclaw@latest',
|
|
112
|
-
docsUrl:
|
|
167
|
+
docsUrl: 'https://docs.openclaw.ai',
|
|
113
168
|
}
|
|
114
169
|
|
|
115
170
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
171
|
+
* 自动在后台启动 OpenClaw Gateway
|
|
172
|
+
*
|
|
173
|
+
* 策略(按顺序尝试):
|
|
174
|
+
* 1. openclaw gateway start — 已有 daemon/service 直接启动
|
|
175
|
+
* 2. openclaw gateway --port 18789 (detached) — 前台守护模式
|
|
176
|
+
*
|
|
177
|
+
* 不调用 onboard,因为配置文件已由 configure() 完整写入。
|
|
120
178
|
*/
|
|
121
179
|
function _autoStartGateway() {
|
|
122
180
|
const chalk = require('chalk')
|
|
123
|
-
const bin
|
|
181
|
+
const bin = 'openclaw'
|
|
124
182
|
|
|
125
183
|
console.log(chalk.gray('\n ⚙️ 正在启动 OpenClaw Gateway...'))
|
|
126
184
|
|
|
127
|
-
//
|
|
128
|
-
const r1 = spawnSync(bin, ['gateway', 'start'], {
|
|
185
|
+
// 先尝试 gateway start(若已注册为系统服务则直接生效)
|
|
186
|
+
const r1 = spawnSync(bin, ['gateway', 'start'], {
|
|
187
|
+
shell: true,
|
|
188
|
+
timeout: 15000,
|
|
189
|
+
stdio: 'pipe',
|
|
190
|
+
})
|
|
129
191
|
if (r1.status === 0) {
|
|
130
192
|
console.log(chalk.green(' ✓ OpenClaw Gateway 已在后台启动'))
|
|
131
193
|
return
|
|
132
194
|
}
|
|
133
195
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
shell:
|
|
138
|
-
|
|
139
|
-
stdio:
|
|
196
|
+
// 没有 daemon → 直接 detached 前台守护运行
|
|
197
|
+
const { spawn } = require('child_process')
|
|
198
|
+
const child = spawn(bin, ['gateway', '--port', '18789'], {
|
|
199
|
+
shell: true,
|
|
200
|
+
detached: true,
|
|
201
|
+
stdio: 'ignore',
|
|
140
202
|
})
|
|
203
|
+
child.unref()
|
|
141
204
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const { spawn } = require('child_process')
|
|
148
|
-
const child = spawn(bin, ['gateway'], {
|
|
149
|
-
shell: true,
|
|
150
|
-
detached: true,
|
|
151
|
-
stdio: 'ignore',
|
|
152
|
-
})
|
|
153
|
-
child.unref()
|
|
154
|
-
console.log(chalk.green(' ✓ OpenClaw Gateway 已启动(前台守护模式)'))
|
|
155
|
-
}
|
|
205
|
+
// 等 2 秒让 gateway 起来
|
|
206
|
+
spawnSync('node', ['-e', 'setTimeout(()=>{},2000)'], { timeout: 3000 })
|
|
207
|
+
|
|
208
|
+
console.log(chalk.green(' ✓ OpenClaw Gateway 已启动'))
|
|
209
|
+
console.log(chalk.cyan(' → 浏览器打开: http://127.0.0.1:18789/'))
|
|
156
210
|
}
|