create-openclaw-bot 5.8.8 → 5.8.10
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 +18 -7
- package/README.vi.md +12 -6
- package/dist/server/local-server.js +64 -18
- package/dist/setup/shared/workspace-gen.js +1218 -1200
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# 🦞 OpenClaw Setup
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.8.
|
|
6
|
+
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.8.10-0EA5E9?style=for-the-badge" alt="Version 5.8.10" /></a>
|
|
7
7
|
<a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
|
|
9
9
|
<a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
|
|
@@ -23,12 +23,18 @@ A next-generation **Web UI Setup** and management dashboard that automates 100%
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
## 🆕 What's New in v5.8.
|
|
26
|
+
## 🆕 What's New in v5.8.10
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
28
|
+
### 🚀 New Features: Deep Integration of Infographic Image Generator, Zalo Sticker & Auto-Tag Skills, and Workspace Docs Optimization
|
|
29
|
+
|
|
30
|
+
- **New: Infographic Poster Generator Skill**: Integrates automatic infographic and poster generation via 9Router API. Automatically generates the helper script `image-generator.js` (synchronizing API credentials from `openclaw.json`) and a comprehensive `SKILL.md` guiding agents on styling rules, Vietnamese font support, layouts, and image generation syntax.
|
|
31
|
+
- **New: Zalo Sticker & Auto-Tag Skill**:
|
|
32
|
+
- Automatically mentions the active sender in group chats (Agent doesn't need to manually prefix with `@Name` anymore, the system handles it).
|
|
33
|
+
- Enables agents to dynamically send Zalo stickers by appending `[Sticker: <keyword>]` at the end of their text responses.
|
|
34
|
+
- Automatically maps emotional keywords (such as `love`, `haha`, `ca khia`, `angry`, `thank you`, etc.) to actual Zalo sticker IDs.
|
|
35
|
+
- Generates the patch script `mentions.js` and a dedicated `SKILL.md` inside the agent's workspace.
|
|
36
|
+
- **Polish: Simplified TOOLS.md generation**: Streamlined the `TOOLS.md` generator to output a concise, static guide focusing on general principles and referencing the `./skills/` directory, rather than generating dynamic lists based on installed plugins.
|
|
37
|
+
- **Polish: Standardized Reference Docs list in AGENTS.md**: Updated the reference docs list in the generated `AGENTS.md` (for both single and relay variants in Vietnamese and English) to match the new structure, removing obsolete files (`TEAMS.md` for single-bot, `BROWSER.md`) and standardizing descriptions to keep exactly 9 core documents.
|
|
32
38
|
|
|
33
39
|
<details>
|
|
34
40
|
<summary><b>Previous: What's new in v5.8.0 (Major Release)</b></summary>
|
|
@@ -60,14 +66,19 @@ A next-generation **Web UI Setup** and management dashboard that automates 100%
|
|
|
60
66
|
## 🗺️ Quick Start
|
|
61
67
|
|
|
62
68
|
### 1️⃣ Method 1: Using NPX (Recommended)
|
|
69
|
+
|
|
63
70
|
Open your terminal and run this single command:
|
|
71
|
+
|
|
64
72
|
```bash
|
|
65
73
|
npx create-openclaw-bot
|
|
66
74
|
```
|
|
67
|
-
|
|
75
|
+
|
|
76
|
+
_The bootstrapper will automatically download package files, launch the local backend server, and open the Setup UI in your browser._
|
|
68
77
|
|
|
69
78
|
### 2️⃣ Method 2: Manual Clone
|
|
79
|
+
|
|
70
80
|
If you downloaded or cloned the repository files locally:
|
|
81
|
+
|
|
71
82
|
```bash
|
|
72
83
|
npm install
|
|
73
84
|
npm start
|
package/README.vi.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# 🦞 OpenClaw Setup
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.8.
|
|
6
|
+
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.8.10-0EA5E9?style=for-the-badge" alt="Version 5.8.10" /></a>
|
|
7
7
|
<a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
|
|
9
9
|
<a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
|
|
@@ -23,12 +23,18 @@ Trình cài đặt và quản trị **Web UI Setup** thế hệ mới giúp tự
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
## 🆕 Có gì mới trong v5.8.
|
|
26
|
+
## 🆕 Có gì mới trong v5.8.10
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
28
|
+
### 🚀 Tính năng mới: Tích hợp sâu Skill Tạo ảnh Infographic, Skill Sticker & Auto-Tag (Zalo) cùng Tối ưu hóa Workspace Docs
|
|
29
|
+
|
|
30
|
+
- **Mới: Hỗ trợ Skill Tạo ảnh Infographic chuyên nghiệp**: Tích hợp hoàn toàn công cụ tạo ảnh infographic, poster tự động thông qua API của 9Router. Tự động sinh mã nguồn script `image-generator.js` đồng bộ API credentials từ `openclaw.json` và hướng dẫn `SKILL.md` cụ thể giúp Agent nắm vững cấu trúc prompt, font chữ tiếng Việt, layout và quy tắc thiết kế ảnh.
|
|
31
|
+
- **Mới: Hỗ trợ Skill Sticker & Auto-Tag (Zalo)**:
|
|
32
|
+
- Tự động tag tên người gửi tin nhắn gần nhất trong group chat Zalo (Agent không cần tự điền `@Tên` ở đầu câu trả lời nữa, hệ thống sẽ tự làm).
|
|
33
|
+
- Cho phép Agent gửi kèm Sticker Zalo trực tiếp trong câu trả lời thông qua thẻ `[Sticker: <từ_khóa>]` đặt ở cuối tin nhắn.
|
|
34
|
+
- Tích hợp bộ giải nghĩa từ khóa cảm xúc thông minh (như `love`, `haha`, `ca khia`, `angry`, `thank you`,...) để tự động map sang sticker Zalo phù hợp.
|
|
35
|
+
- Tự động sinh script vá logic `mentions.js` và tài liệu hướng dẫn `SKILL.md` trong workspace.
|
|
36
|
+
- **Tối ưu hóa: Đơn giản hóa sinh file TOOLS.md**: Điều chỉnh generator của `TOOLS.md` để sinh ra nội dung tĩnh gọn gàng, tập trung định hướng Agent đọc chi tiết các tài liệu hướng dẫn skill tương ứng nằm trong thư mục `./skills/`, loại bỏ các logic sinh danh sách động dựa trên plugin cũ.
|
|
37
|
+
- **Tối ưu hóa: Chuẩn hóa danh sách Tài liệu tham chiếu trong AGENTS.md**: Cập nhật danh sách tài liệu tham chiếu được tạo trong file `AGENTS.md` (cho cả 2 chế độ single/relay và cả tiếng Việt/tiếng Anh) để khớp chính xác cấu trúc mới gồm đúng 9 tài liệu cốt lõi, loại bỏ các file không còn phù hợp (`TEAMS.md` cho single-bot, `BROWSER.md`) và chuẩn hóa phần mô tả.
|
|
32
38
|
|
|
33
39
|
<details>
|
|
34
40
|
<summary><b>Trước đó: Có gì mới trong v5.8.0 (Bản nâng cấp lớn)</b></summary>
|
|
@@ -19,6 +19,31 @@ const { buildDockerArtifacts } = loadSharedModule('../setup/shared/docker-gen.js
|
|
|
19
19
|
const { OPENCLAW_NPM_SPEC, NINE_ROUTER_NPM_SPEC, build9RouterProviderConfig, get9RouterBaseUrl } = loadSharedModule('../setup/shared/common-gen.js', '__openclawCommon');
|
|
20
20
|
const dataExport = loadSharedModule('../setup/data/index.js', '__openclawData');
|
|
21
21
|
|
|
22
|
+
async function syncExecApprovals(projectDir, cfg) {
|
|
23
|
+
const openclawHome = join(projectDir, '.openclaw');
|
|
24
|
+
const agentMetas = (cfg.agents?.list || []).map((a) => ({ agentId: a.id }));
|
|
25
|
+
const approvals = buildExecApprovalsJson({ agentMetas });
|
|
26
|
+
|
|
27
|
+
const path1 = join(openclawHome, 'exec-approvals.json');
|
|
28
|
+
const nestedDir = join(openclawHome, '.openclaw');
|
|
29
|
+
const path2 = join(nestedDir, 'exec-approvals.json');
|
|
30
|
+
|
|
31
|
+
await fsp.mkdir(openclawHome, { recursive: true }).catch(() => {});
|
|
32
|
+
await fsp.writeFile(path1, JSON.stringify(approvals, null, 2), 'utf8');
|
|
33
|
+
|
|
34
|
+
await fsp.mkdir(nestedDir, { recursive: true }).catch(() => {});
|
|
35
|
+
let existing = {};
|
|
36
|
+
if (existsSync(path2)) {
|
|
37
|
+
try {
|
|
38
|
+
existing = JSON.parse(await fsp.readFile(path2, 'utf8'));
|
|
39
|
+
} catch (e) {}
|
|
40
|
+
}
|
|
41
|
+
if (existing.socket) {
|
|
42
|
+
approvals.socket = existing.socket;
|
|
43
|
+
}
|
|
44
|
+
await fsp.writeFile(path2, JSON.stringify(approvals, null, 2), 'utf8');
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
48
|
const WEB_DIR = resolve(__dirname, '../web');
|
|
24
49
|
const SETUP_VERSION = (() => { try { return JSON.parse(fs.readFileSync(resolve(__dirname, '../../package.json'), 'utf8')).version || '0.0.0'; } catch { return '0.0.0'; } })();
|
|
@@ -153,7 +178,9 @@ function recommendedMode(osChoice) {
|
|
|
153
178
|
function commandExists(cmd, args = ['--version']) {
|
|
154
179
|
return new Promise((resolve) => {
|
|
155
180
|
const shell = process.platform === 'win32';
|
|
156
|
-
|
|
181
|
+
const rawBin = resolveBinPath(cmd);
|
|
182
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
183
|
+
execFile(bin, args, { windowsHide: true, timeout: 5000, shell }, (err, stdout, stderr) => {
|
|
157
184
|
resolve({ ok: !err, output: String(stdout || stderr || '').trim() });
|
|
158
185
|
});
|
|
159
186
|
});
|
|
@@ -162,7 +189,10 @@ function commandExists(cmd, args = ['--version']) {
|
|
|
162
189
|
function run(cmd, args, opts = {}) {
|
|
163
190
|
return new Promise((resolve, reject) => {
|
|
164
191
|
sendLog(`$ ${cmd} ${args.join(' ')}`);
|
|
165
|
-
const
|
|
192
|
+
const shell = process.platform === 'win32';
|
|
193
|
+
const rawBin = resolveBinPath(cmd);
|
|
194
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
195
|
+
const child = spawn(bin, args, { cwd: opts.cwd, shell, env: { ...process.env, ...(opts.env || {}) } });
|
|
166
196
|
let stdout = '';
|
|
167
197
|
let resolved = false;
|
|
168
198
|
child.stdout.on('data', (d) => {
|
|
@@ -192,9 +222,12 @@ function run(cmd, args, opts = {}) {
|
|
|
192
222
|
|
|
193
223
|
function startDetached(cmd, args, opts = {}) {
|
|
194
224
|
sendLog(`$ ${cmd} ${args.join(' ')} &`);
|
|
195
|
-
const
|
|
225
|
+
const shell = process.platform === 'win32';
|
|
226
|
+
const rawBin = resolveBinPath(cmd);
|
|
227
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
228
|
+
const child = spawn(bin, args, {
|
|
196
229
|
cwd: opts.cwd,
|
|
197
|
-
shell
|
|
230
|
+
shell,
|
|
198
231
|
detached: true,
|
|
199
232
|
stdio: 'ignore',
|
|
200
233
|
windowsHide: opts.windowsHide ?? true,
|
|
@@ -253,9 +286,12 @@ async function resolveProjectRuntimeVersions(projectDir, mode = state.mode || 'd
|
|
|
253
286
|
|
|
254
287
|
function runStreamed(cmd, args, opts = {}) {
|
|
255
288
|
sendLog(`$ ${cmd} ${args.join(' ')}`);
|
|
256
|
-
const
|
|
289
|
+
const shell = opts.shell ?? process.platform === 'win32';
|
|
290
|
+
const rawBin = resolveBinPath(cmd);
|
|
291
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
292
|
+
const child = spawn(bin, args, {
|
|
257
293
|
cwd: opts.cwd,
|
|
258
|
-
shell
|
|
294
|
+
shell,
|
|
259
295
|
windowsHide: opts.windowsHide ?? true,
|
|
260
296
|
env: { ...process.env, ...(opts.env || {}) },
|
|
261
297
|
});
|
|
@@ -268,9 +304,12 @@ function runStreamed(cmd, args, opts = {}) {
|
|
|
268
304
|
|
|
269
305
|
function runStreamedToLogFile(cmd, args, logFile, opts = {}) {
|
|
270
306
|
sendLog(`$ ${cmd} ${args.join(' ')}`);
|
|
271
|
-
const
|
|
307
|
+
const shell = opts.shell ?? process.platform === 'win32';
|
|
308
|
+
const rawBin = resolveBinPath(cmd);
|
|
309
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
310
|
+
const child = spawn(bin, args, {
|
|
272
311
|
cwd: opts.cwd,
|
|
273
|
-
shell
|
|
312
|
+
shell,
|
|
274
313
|
windowsHide: opts.windowsHide ?? true,
|
|
275
314
|
env: { ...process.env, ...(opts.env || {}) },
|
|
276
315
|
});
|
|
@@ -293,9 +332,12 @@ function runCapture(cmd, args, opts = {}) {
|
|
|
293
332
|
return new Promise((resolve) => {
|
|
294
333
|
let stdout = '';
|
|
295
334
|
let stderr = '';
|
|
296
|
-
const
|
|
335
|
+
const shell = opts.shell ?? process.platform === 'win32';
|
|
336
|
+
const rawBin = resolveBinPath(cmd);
|
|
337
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
338
|
+
const child = spawn(bin, args, {
|
|
297
339
|
cwd: opts.cwd,
|
|
298
|
-
shell
|
|
340
|
+
shell,
|
|
299
341
|
windowsHide: opts.windowsHide ?? true,
|
|
300
342
|
env: { ...process.env, ...(opts.env || {}) },
|
|
301
343
|
});
|
|
@@ -947,6 +989,7 @@ async function deleteBotInProject(projectDir, agentId) {
|
|
|
947
989
|
|
|
948
990
|
if (existsSync(cfgPath)) await fsp.copyFile(cfgPath, `${cfgPath}.bak`);
|
|
949
991
|
await fsp.writeFile(cfgPath, JSON.stringify(cfg, null, 2), 'utf8');
|
|
992
|
+
await syncExecApprovals(projectDir, cfg);
|
|
950
993
|
|
|
951
994
|
// Also clear bot tokens in .env files if deleting the primary bot
|
|
952
995
|
if (agentId === 'bot') {
|
|
@@ -1098,6 +1141,7 @@ async function createBotInProject(projectDir, body = {}, runtime = {}) {
|
|
|
1098
1141
|
validateOpenclawConfig(cfg);
|
|
1099
1142
|
if (existsSync(cfgPath)) await fsp.copyFile(cfgPath, `${cfgPath}.bak`);
|
|
1100
1143
|
await fsp.writeFile(cfgPath, JSON.stringify(cfg, null, 2), 'utf8');
|
|
1144
|
+
await syncExecApprovals(projectDir, cfg);
|
|
1101
1145
|
|
|
1102
1146
|
const hasScheduler = !!(cfg.tools?.alsoAllow || []).includes('group:automation');
|
|
1103
1147
|
const hasImageGen = !!(cfg.skills?.entries?.['image-gen']?.enabled);
|
|
@@ -1109,7 +1153,7 @@ async function createBotInProject(projectDir, body = {}, runtime = {}) {
|
|
|
1109
1153
|
emoji,
|
|
1110
1154
|
userInfo,
|
|
1111
1155
|
agentWorkspaceDir: workspaceDir,
|
|
1112
|
-
workspacePath:
|
|
1156
|
+
workspacePath: `/home/node/project/.openclaw/${workspaceDir}`,
|
|
1113
1157
|
channel,
|
|
1114
1158
|
hasZaloMod: channel === 'zalo-personal',
|
|
1115
1159
|
hasZaloSticker: channel === 'zalo-personal',
|
|
@@ -1175,6 +1219,7 @@ async function updateBotInProject(projectDir, agentId, body = {}, runtime = {})
|
|
|
1175
1219
|
validateOpenclawConfig(cfg);
|
|
1176
1220
|
if (existsSync(cfgPath)) await fsp.copyFile(cfgPath, `${cfgPath}.bak`);
|
|
1177
1221
|
await fsp.writeFile(cfgPath, JSON.stringify(cfg, null, 2), 'utf8');
|
|
1222
|
+
await syncExecApprovals(projectDir, cfg);
|
|
1178
1223
|
|
|
1179
1224
|
// Synchronize the token to .env files for the primary bot to ensure Docker picks it up
|
|
1180
1225
|
if (agentId === 'bot') {
|
|
@@ -1213,7 +1258,7 @@ async function updateBotInProject(projectDir, agentId, body = {}, runtime = {})
|
|
|
1213
1258
|
emoji,
|
|
1214
1259
|
userInfo,
|
|
1215
1260
|
agentWorkspaceDir: workspaceDir,
|
|
1216
|
-
workspacePath:
|
|
1261
|
+
workspacePath: `/home/node/project/.openclaw/${workspaceDir}`,
|
|
1217
1262
|
channel,
|
|
1218
1263
|
hasZaloMod: channel === 'zalo-personal',
|
|
1219
1264
|
hasZaloSticker: channel === 'zalo-personal',
|
|
@@ -1731,11 +1776,9 @@ async function writeCoreProject({ projectDir, osChoice, mode, gatewayPort = 1878
|
|
|
1731
1776
|
const common = { channelKey: 'telegram', providerKey: '9router', model: DEFAULT_MODEL, deployMode: mode, osChoice, selectedSkills, skills: dataExport.SKILLS || [], agentMetas, gatewayPort, routerPort };
|
|
1732
1777
|
const cfg = buildOpenclawJson(common);
|
|
1733
1778
|
const env = buildEnvFileContent({ ...common, apiKey: '', botToken: '' });
|
|
1734
|
-
const approvals = buildExecApprovalsJson({ agentMetas });
|
|
1735
|
-
|
|
1736
1779
|
await fsp.writeFile(join(openclawHome, 'openclaw.json'), JSON.stringify(cfg, null, 2), 'utf8');
|
|
1737
1780
|
await fsp.writeFile(join(projectDir, '.env'), env, 'utf8');
|
|
1738
|
-
await
|
|
1781
|
+
await syncExecApprovals(projectDir, cfg);
|
|
1739
1782
|
|
|
1740
1783
|
if (mode === 'docker') {
|
|
1741
1784
|
const projectName = slugify(basename(projectDir)) || 'bot';
|
|
@@ -2996,10 +3039,13 @@ function restartInstaller() {
|
|
|
2996
3039
|
args.push('--no-open');
|
|
2997
3040
|
}
|
|
2998
3041
|
|
|
2999
|
-
const
|
|
3042
|
+
const shell = process.platform === 'win32';
|
|
3043
|
+
const rawBin = process.argv[0];
|
|
3044
|
+
const bin = shell && rawBin.includes(' ') && !rawBin.startsWith('"') ? `"${rawBin}"` : rawBin;
|
|
3045
|
+
const child = spawn(bin, [entryFile, ...args], {
|
|
3000
3046
|
detached: true,
|
|
3001
3047
|
stdio: 'inherit',
|
|
3002
|
-
shell
|
|
3048
|
+
shell
|
|
3003
3049
|
});
|
|
3004
3050
|
child.unref();
|
|
3005
3051
|
|
|
@@ -3020,7 +3066,7 @@ export async function startLocalInstaller({ host = '127.0.0.1', preferredPort =
|
|
|
3020
3066
|
if (openBrowser) openUrl(url);
|
|
3021
3067
|
}
|
|
3022
3068
|
|
|
3023
|
-
export { createBotInProject, deleteBotInProject, validateOpenclawConfig, startZaloUserLogin, readBotCredentials, resolveProject9RouterApiKey };
|
|
3069
|
+
export { createBotInProject, updateBotInProject, deleteBotInProject, validateOpenclawConfig, startZaloUserLogin, readBotCredentials, resolveProject9RouterApiKey };
|
|
3024
3070
|
|
|
3025
3071
|
|
|
3026
3072
|
|