@zi.yi/openclaw-easy 1.0.0
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/LICENSE +21 -0
- package/README.md +118 -0
- package/bin/openclaw-easy.mjs +254 -0
- package/lib/config.example.json +7 -0
- package/lib/config.json +5 -0
- package/package.json +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 王子怡 (Ziyi Wang)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @zi.yi/openclaw-easy
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@zi.yi/openclaw-easy)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://packagephobia.com/result?p=@zi.yi/openclaw-easy)
|
|
6
|
+
|
|
7
|
+
> **One-command setup for [OpenClaw](https://github.com/anthropics/openclaw) with built-in API key.**
|
|
8
|
+
|
|
9
|
+
OpenClaw 是一个自托管 AI 助手网关,可以连接 WhatsApp、Telegram、Discord 等聊天应用到 AI 编码助手。这个工具让你一键完成配置,内置 GLM-4-Flash 模型。
|
|
10
|
+
|
|
11
|
+
## 特点
|
|
12
|
+
|
|
13
|
+
- **零配置** - 内置免费 API key,开箱即用
|
|
14
|
+
- **灵活** - 可以选择使用自己的 API key
|
|
15
|
+
- **一键安装** - 一条命令完成所有配置
|
|
16
|
+
- **安全** - API key 加密存储
|
|
17
|
+
|
|
18
|
+
## 快速开始
|
|
19
|
+
|
|
20
|
+
### 安装
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g @zi.yi/openclaw-easy
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 使用
|
|
27
|
+
|
|
28
|
+
**方式一:使用内置福利 API key(推荐)**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
openclaw-easy
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
默认配置:
|
|
35
|
+
- 模型:`glm-4-flash`(通过 zai provider)
|
|
36
|
+
|
|
37
|
+
**方式二:使用自己的 API key**
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 命令行参数
|
|
41
|
+
openclaw-easy --openai-key sk-your-api-key-here
|
|
42
|
+
|
|
43
|
+
# 或环境变量
|
|
44
|
+
export OPENAI_API_KEY=sk-your-api-key-here
|
|
45
|
+
openclaw-easy
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
安装完成后,你可以通过以下方式与 OpenClaw 交互:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# 打开 Web 控制面板
|
|
52
|
+
npx openclaw dashboard
|
|
53
|
+
|
|
54
|
+
# 或使用终端界面
|
|
55
|
+
npx openclaw tui
|
|
56
|
+
|
|
57
|
+
# 或直接发送消息
|
|
58
|
+
npx openclaw agent --message "你好"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 工作原理
|
|
62
|
+
|
|
63
|
+
1. 从内置配置或用户输入获取 API key
|
|
64
|
+
2. 将配置写入 `~/.openclaw/.env`(API key、模型)
|
|
65
|
+
3. 运行 OpenClaw 的 onboarding 流程
|
|
66
|
+
4. 安装并启动 OpenClaw 守护进程
|
|
67
|
+
|
|
68
|
+
## 常见问题
|
|
69
|
+
|
|
70
|
+
### Q: 内置的是什么模型?
|
|
71
|
+
|
|
72
|
+
A: 内置的是 GLM-4-Flash 模型(通过 zai provider),适合日常使用。
|
|
73
|
+
|
|
74
|
+
### Q: 如何更换模型?
|
|
75
|
+
|
|
76
|
+
A: 编辑 `~/.openclaw/.env`,修改 `OPENCLAW_MODEL` 环境变量。
|
|
77
|
+
|
|
78
|
+
### Q: 卸载怎么办?
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm uninstall -g @zi.yi/openclaw-easy
|
|
82
|
+
npx openclaw uninstall # 完全卸载 OpenClaw
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 文档
|
|
86
|
+
|
|
87
|
+
详细使用指南请查看 [USER_GUIDE.md](USER_GUIDE.md)
|
|
88
|
+
|
|
89
|
+
## 开发
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# 克隆仓库
|
|
93
|
+
git clone https://github.com/hzzzzz-1/openclaw-easy.git
|
|
94
|
+
cd openclaw-easy
|
|
95
|
+
|
|
96
|
+
# 安装依赖
|
|
97
|
+
npm install
|
|
98
|
+
|
|
99
|
+
# 本地测试
|
|
100
|
+
npm install -g .
|
|
101
|
+
openclaw-easy
|
|
102
|
+
|
|
103
|
+
# 发布到 npm(需要设置环境变量)
|
|
104
|
+
BUILTIN_API_KEY="your-api-key" BUILTIN_MODEL="glm-4.7-flash" npm publish --access public
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 致谢
|
|
108
|
+
|
|
109
|
+
- [OpenClaw](https://github.com/anthropics/openclaw) - 核心项目
|
|
110
|
+
- [GLM](https://open.bigmodel.cn/) - 提供内置 API 支持
|
|
111
|
+
|
|
112
|
+
## GitHub 仓库
|
|
113
|
+
|
|
114
|
+
https://github.com/hzzzzz-1/openclaw-easy
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
[MIT](LICENSE) © 2026 王子怡 (Ziyi Wang)
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import { createInterface } from "node:readline";
|
|
9
|
+
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
// 内部密钥(混淆)
|
|
14
|
+
const _k = "openclaw-easy-secret-2026";
|
|
15
|
+
const _0 = "d"; // API key
|
|
16
|
+
const _1 = "m"; // model
|
|
17
|
+
const _2 = "v"; // version
|
|
18
|
+
|
|
19
|
+
// 解密函数(与加密工具对应)
|
|
20
|
+
const _d = (s) => {
|
|
21
|
+
try {
|
|
22
|
+
const b = Buffer.from(s, "base64").toString("utf8");
|
|
23
|
+
let r = "";
|
|
24
|
+
for (let i = 0; i < b.length; i++) {
|
|
25
|
+
r += String.fromCharCode(b.charCodeAt(i) ^ _k.charCodeAt(i % _k.length));
|
|
26
|
+
}
|
|
27
|
+
return r;
|
|
28
|
+
} catch (_) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// 获取内置配置
|
|
34
|
+
function getBuiltinConfig() {
|
|
35
|
+
try {
|
|
36
|
+
const configPath = path.join(__dirname, "../lib/config.json");
|
|
37
|
+
const raw = fs.readFileSync(configPath, "utf8");
|
|
38
|
+
const _c = JSON.parse(raw);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
apiKey: _d(_c[_0]),
|
|
42
|
+
model: _d(_c[_1]),
|
|
43
|
+
version: _c[_2]
|
|
44
|
+
};
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error("Configuration error. Please reinstall:\n npm install -g @hzzzzzz/openclaw-easy");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 交互式询问
|
|
52
|
+
function askQuestion(query) {
|
|
53
|
+
const rl = createInterface({
|
|
54
|
+
input: process.stdin,
|
|
55
|
+
output: process.stdout
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
rl.question(query, (answer) => {
|
|
60
|
+
rl.close();
|
|
61
|
+
resolve(answer.trim().toLowerCase());
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const arg = (name) => {
|
|
67
|
+
const i = process.argv.indexOf(name);
|
|
68
|
+
return i >= 0 ? process.argv[i + 1] : undefined;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// 更新 OpenClaw 配置文件,设置模型
|
|
72
|
+
function updateOpenClawConfig(model) {
|
|
73
|
+
const configPath = path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
if (!fs.existsSync(configPath)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
81
|
+
|
|
82
|
+
// 模型 provider 映射
|
|
83
|
+
let modelKey;
|
|
84
|
+
if (model.includes("trinity")) {
|
|
85
|
+
modelKey = `openrouter/${model}`;
|
|
86
|
+
} else if (model.startsWith("glm")) {
|
|
87
|
+
modelKey = `zai/glm-4-flash`;
|
|
88
|
+
} else if (model.startsWith("gpt")) {
|
|
89
|
+
modelKey = `openai/${model}`;
|
|
90
|
+
} else {
|
|
91
|
+
modelKey = model;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
config.agents = config.agents || {};
|
|
95
|
+
config.agents.defaults = config.agents.defaults || {};
|
|
96
|
+
config.agents.defaults.models = {
|
|
97
|
+
[modelKey]: {
|
|
98
|
+
"alias": modelKey.includes("trinity") ? "Trinity" : modelKey.startsWith("zai") ? "GLM" : "GPT"
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
config.agents.defaults.model = {
|
|
102
|
+
"primary": modelKey
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
106
|
+
console.log("\n✓ 已使用内置免费模型");
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error("警告: 无法更新 OpenClaw 配置:", err.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 主流程
|
|
113
|
+
async function main() {
|
|
114
|
+
const builtinConfig = getBuiltinConfig();
|
|
115
|
+
const userApiKey = arg("--openai-key") || process.env.OPENAI_API_KEY;
|
|
116
|
+
|
|
117
|
+
let finalApiKey;
|
|
118
|
+
let finalModel = builtinConfig.model;
|
|
119
|
+
|
|
120
|
+
if (userApiKey) {
|
|
121
|
+
console.log("\n检测到你提供了自己的 API key。");
|
|
122
|
+
console.log(" [1] 使用你自己的 API key");
|
|
123
|
+
console.log(" [2] 使用内置的免费 API key");
|
|
124
|
+
|
|
125
|
+
const choice = await askQuestion("\n请选择 [1/2](默认 1):");
|
|
126
|
+
|
|
127
|
+
if (choice === "2" || choice === "内置" || choice === "福利") {
|
|
128
|
+
finalApiKey = builtinConfig.apiKey;
|
|
129
|
+
console.log("\n✓ 使用内置福利 API key");
|
|
130
|
+
} else {
|
|
131
|
+
finalApiKey = userApiKey;
|
|
132
|
+
console.log("\n✓ 使用你提供的 API key");
|
|
133
|
+
// 用户用自己的 key,不强制使用 GLM 配置
|
|
134
|
+
finalModel = null;
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
finalApiKey = builtinConfig.apiKey;
|
|
138
|
+
console.log("\n✓ 使用内置免费 API key");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 写入 .env 文件
|
|
142
|
+
const envFile = path.join(os.homedir(), ".openclaw", ".env");
|
|
143
|
+
fs.mkdirSync(path.dirname(envFile), { recursive: true });
|
|
144
|
+
|
|
145
|
+
const lines = fs.existsSync(envFile) ? fs.readFileSync(envFile, "utf8").split(/\r?\n/) : [];
|
|
146
|
+
|
|
147
|
+
// 过滤掉旧的配置行(包括看起来像是 API key 延续的行)
|
|
148
|
+
const next = [];
|
|
149
|
+
let skipNext = false;
|
|
150
|
+
for (const line of lines) {
|
|
151
|
+
if (skipNext) {
|
|
152
|
+
skipNext = false;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (line.startsWith("OPENAI_API_KEY=") ||
|
|
156
|
+
line.startsWith("OPENROUTER_API_KEY=") ||
|
|
157
|
+
line.startsWith("ZAI_API_KEY=") ||
|
|
158
|
+
line.startsWith("OPENCLAW_MODEL=")) {
|
|
159
|
+
// 如果这行以 = 结尾但没有内容,可能是换行的 key,跳过下一行
|
|
160
|
+
if (line.endsWith("=") || line.match(/KEY=$/)) {
|
|
161
|
+
skipNext = true;
|
|
162
|
+
}
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
// 跳过看起来像是 API key 延续的行(不以 = 开头且像 base64/key 格式)
|
|
166
|
+
if (line.match(/^[a-zA-Z0-9_-]{20,}$/) && !line.includes("=")) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
next.push(line);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 根据模型选择对应的环境变量
|
|
173
|
+
if (finalModel && finalModel.includes("trinity")) {
|
|
174
|
+
next.push(`OPENROUTER_API_KEY=${finalApiKey}`);
|
|
175
|
+
next.push(`OPENCLAW_MODEL=openrouter/${finalModel}`);
|
|
176
|
+
} else if (finalModel && finalModel.startsWith("glm")) {
|
|
177
|
+
next.push(`ZAI_API_KEY=${finalApiKey}`);
|
|
178
|
+
next.push(`OPENCLAW_MODEL=zai/glm-4-flash`);
|
|
179
|
+
} else {
|
|
180
|
+
next.push(`OPENAI_API_KEY=${finalApiKey}`);
|
|
181
|
+
if (finalModel) {
|
|
182
|
+
next.push(`OPENCLAW_MODEL=${finalModel}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
fs.writeFileSync(envFile, `${next.filter(Boolean).join("\n")}\n`, "utf8");
|
|
186
|
+
|
|
187
|
+
// 调用 OpenClaw onboard
|
|
188
|
+
const openclawCli = require.resolve("openclaw/cli-entry");
|
|
189
|
+
|
|
190
|
+
// 根据模型选择认证方式和 API key 参数
|
|
191
|
+
let authChoice = "openai-api-key";
|
|
192
|
+
let apiKeyParam = "--openai-api-key";
|
|
193
|
+
|
|
194
|
+
if (finalModel && finalModel.includes("trinity")) {
|
|
195
|
+
authChoice = "openrouter-api-key";
|
|
196
|
+
apiKeyParam = "--openrouter-api-key";
|
|
197
|
+
} else if (finalModel && finalModel.startsWith("glm")) {
|
|
198
|
+
authChoice = "zai-api-key";
|
|
199
|
+
apiKeyParam = "--zai-api-key";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const run = spawnSync(
|
|
203
|
+
process.execPath,
|
|
204
|
+
[
|
|
205
|
+
openclawCli,
|
|
206
|
+
"onboard",
|
|
207
|
+
"--non-interactive",
|
|
208
|
+
"--accept-risk",
|
|
209
|
+
"--flow",
|
|
210
|
+
"quickstart",
|
|
211
|
+
"--auth-choice",
|
|
212
|
+
authChoice,
|
|
213
|
+
apiKeyParam,
|
|
214
|
+
finalApiKey,
|
|
215
|
+
"--install-daemon"
|
|
216
|
+
],
|
|
217
|
+
{
|
|
218
|
+
stdio: "inherit",
|
|
219
|
+
env: {
|
|
220
|
+
...process.env,
|
|
221
|
+
...(finalModel && {
|
|
222
|
+
OPENCLAW_MODEL: finalModel.includes("trinity")
|
|
223
|
+
? `openrouter/${finalModel}`
|
|
224
|
+
: finalModel.startsWith("glm")
|
|
225
|
+
? "zai/glm-4-flash"
|
|
226
|
+
: finalModel
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// 如果使用内置配置,更新 openclaw.json
|
|
233
|
+
if (finalModel && run.status === 0) {
|
|
234
|
+
updateOpenClawConfig(finalModel);
|
|
235
|
+
|
|
236
|
+
// 停止 gateway(LaunchAgent 会自动重启)
|
|
237
|
+
console.log("\n正在重启 OpenClaw Gateway...");
|
|
238
|
+
spawnSync(
|
|
239
|
+
process.execPath,
|
|
240
|
+
[openclawCli, "gateway", "--stop"],
|
|
241
|
+
{ stdio: "inherit" }
|
|
242
|
+
);
|
|
243
|
+
console.log("\n✓ 配置完成!Gateway 正在自动启动...");
|
|
244
|
+
console.log("\n运行以下命令打开控制面板:");
|
|
245
|
+
console.log(" npx openclaw dashboard");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
process.exit(run.status ?? 1);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
main().catch((err) => {
|
|
252
|
+
console.error("Error:", err);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
});
|
package/lib/config.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zi.yi/openclaw-easy",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "One-command setup for OpenClaw with built-in API key",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"openclaw-easy": "bin/openclaw-easy.mjs"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"prepack": "node scripts/prepack.mjs",
|
|
11
|
+
"postpack": "rm -f lib/config.json",
|
|
12
|
+
"test": "node bin/openclaw-easy.mjs --help"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"openclaw": "^2026.2.9"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"openclaw",
|
|
19
|
+
"cli",
|
|
20
|
+
"setup",
|
|
21
|
+
"openai"
|
|
22
|
+
],
|
|
23
|
+
"author": "王子怡 (Ziyi Wang) <3597792204@qq.com> (https://github.com/hzzzzz-1)",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18.0.0"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"bin/",
|
|
30
|
+
"lib/"
|
|
31
|
+
]
|
|
32
|
+
}
|