create-openclaw-bot 5.8.11 → 5.8.15
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 +2 -2
- package/README.vi.md +2 -2
- package/dist/cli.js +85 -72
- package/dist/server/local-server.js +24 -13
- package/dist/setup/shared/docker-gen.js +1 -1
- package/dist/web/app.js +4 -4
- 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.15-0EA5E9?style=for-the-badge" alt="Version 5.8.15" /></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,7 +23,7 @@ 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.15
|
|
27
27
|
|
|
28
28
|
### 🚀 New Features: Deep Integration of Infographic Image Generator, Zalo Sticker & Auto-Tag Skills, and Workspace Docs Optimization
|
|
29
29
|
|
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.15-0EA5E9?style=for-the-badge" alt="Version 5.8.15" /></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,7 +23,7 @@ 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.15
|
|
27
27
|
|
|
28
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
29
|
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from 'child_process';
|
|
3
2
|
import fs from 'fs';
|
|
4
3
|
import path from 'path';
|
|
5
4
|
import os from 'os';
|
|
6
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
7
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
+
const runCmd = (cmd, cmdArgs, opts = {}) => {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const child = spawn(cmd, cmdArgs, {
|
|
14
|
+
shell: true,
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
...opts
|
|
17
|
+
});
|
|
18
|
+
child.on('close', (code) => {
|
|
19
|
+
if (code === 0) resolve();
|
|
20
|
+
else reject(new Error(`${cmd} exited with code ${code}`));
|
|
21
|
+
});
|
|
22
|
+
child.on('error', reject);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
11
26
|
function isLocalRepo() {
|
|
12
27
|
const pathsToTry = [
|
|
13
28
|
path.resolve(__dirname, '..'),
|
|
@@ -27,95 +42,93 @@ function isLocalRepo() {
|
|
|
27
42
|
return false;
|
|
28
43
|
}
|
|
29
44
|
|
|
45
|
+
const LOGO = `
|
|
46
|
+
╭────────────────────────────────────────╮
|
|
47
|
+
│ 🦞 OpenClaw Setup 🦞 │
|
|
48
|
+
│ by tuanminhhole │
|
|
49
|
+
╰────────────────────────────────────────╯
|
|
50
|
+
`;
|
|
51
|
+
console.log(LOGO);
|
|
52
|
+
|
|
30
53
|
const args = process.argv.slice(2);
|
|
31
54
|
|
|
32
|
-
|
|
55
|
+
const noOpen = args.includes('--no-open');
|
|
56
|
+
const hostArg = args.find((arg) => arg.startsWith('--host='));
|
|
57
|
+
const portArg = args.find((arg) => arg.startsWith('--port='));
|
|
58
|
+
const projectDirArg = args.find((arg) => arg.startsWith('--project-dir='));
|
|
59
|
+
|
|
60
|
+
const defaultProjectDir = process.platform === 'win32'
|
|
61
|
+
? 'C:\\openclaw-setup'
|
|
62
|
+
: path.join(os.homedir(), 'openclaw-setup');
|
|
63
|
+
|
|
64
|
+
let projectDir = projectDirArg ? projectDirArg.slice('--project-dir='.length) : defaultProjectDir;
|
|
65
|
+
|
|
66
|
+
if (!fs.existsSync(projectDir)) {
|
|
67
|
+
try {
|
|
68
|
+
fs.mkdirSync(projectDir, { recursive: true });
|
|
69
|
+
console.log(`Folder setup được tạo tại: ${projectDir}`);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
if (err.code === 'EPERM' || err.code === 'EACCES') {
|
|
72
|
+
const fallbackDir = path.join(os.homedir(), 'openclaw-setup');
|
|
73
|
+
console.warn(`⚠️ Không có quyền tạo thư mục tại: ${projectDir}`);
|
|
74
|
+
console.log(`👉 Đang chuyển sang thư mục mặc định trong User Profile: ${fallbackDir}`);
|
|
75
|
+
try {
|
|
76
|
+
fs.mkdirSync(fallbackDir, { recursive: true });
|
|
77
|
+
projectDir = fallbackDir;
|
|
78
|
+
console.log(`Folder setup được tạo tại: ${projectDir}`);
|
|
79
|
+
} catch (fallbackErr) {
|
|
80
|
+
console.error(`Không thể tự động tạo thư mục project tại ${fallbackDir}:`, fallbackErr.message);
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
console.error(`Không thể tự động tạo thư mục project tại ${projectDir}:`, err.message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (process.env.OPENCLAW_SETUP_WIZARD === 'true' || isLocalRepo()) {
|
|
33
89
|
const { startLocalInstaller } = await import('./server/local-server.js');
|
|
34
|
-
|
|
35
|
-
const noOpen = args.includes('--no-open');
|
|
36
|
-
const hostArg = args.find((arg) => arg.startsWith('--host='));
|
|
37
|
-
const portArg = args.find((arg) => arg.startsWith('--port='));
|
|
38
|
-
const projectDirArg = args.find((arg) => arg.startsWith('--project-dir='));
|
|
39
|
-
|
|
90
|
+
|
|
40
91
|
await startLocalInstaller({
|
|
41
92
|
openBrowser: !noOpen,
|
|
42
93
|
host: hostArg ? hostArg.slice('--host='.length) : '127.0.0.1',
|
|
43
94
|
preferredPort: portArg ? Number(portArg.slice('--port='.length)) : 51789,
|
|
44
|
-
projectDir:
|
|
95
|
+
projectDir: projectDir,
|
|
45
96
|
});
|
|
46
97
|
} else {
|
|
47
|
-
console.log('\n============================================================');
|
|
48
|
-
console.log(' 🦞 OpenClaw Setup — Auto-downloader & Installer');
|
|
49
|
-
console.log('============================================================\n');
|
|
50
|
-
|
|
51
98
|
const targetDirName = '.openclaw-setup';
|
|
52
99
|
const targetPath = path.join(os.homedir(), targetDirName);
|
|
53
100
|
|
|
54
|
-
const runCmd = (cmd, cmdArgs, opts = {}) => {
|
|
55
|
-
return new Promise((resolve, reject) => {
|
|
56
|
-
const child = spawn(cmd, cmdArgs, {
|
|
57
|
-
shell: true,
|
|
58
|
-
stdio: 'inherit',
|
|
59
|
-
...opts
|
|
60
|
-
});
|
|
61
|
-
child.on('close', (code) => {
|
|
62
|
-
if (code === 0) resolve();
|
|
63
|
-
else reject(new Error(`${cmd} exited with code ${code}`));
|
|
64
|
-
});
|
|
65
|
-
child.on('error', reject);
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
|
|
69
101
|
try {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
await new Promise((resolve, reject) => {
|
|
73
|
-
const child = spawn('git', ['--version'], { shell: true, stdio: 'ignore' });
|
|
74
|
-
child.on('close', (code) => {
|
|
75
|
-
if (code === 0) resolve();
|
|
76
|
-
else reject(new Error());
|
|
77
|
-
});
|
|
78
|
-
child.on('error', reject);
|
|
79
|
-
});
|
|
80
|
-
} catch {
|
|
81
|
-
throw new Error('Git is not installed or not found in PATH. Please install Git and try again.');
|
|
102
|
+
if (!fs.existsSync(targetPath)) {
|
|
103
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
82
104
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (!fs.existsSync(targetPath) || !isGitRepo || !hasPackageJson) {
|
|
88
|
-
if (fs.existsSync(targetPath)) {
|
|
89
|
-
console.log(`⚠️ Thư mục cài đặt UI tồn tại ở ${targetPath} nhưng bị lỗi hoặc thiếu tệp (.git / package.json).`);
|
|
90
|
-
console.log(' Đang dọn dẹp thư mục UI ẩn để tiến hành tải mới hoàn toàn...');
|
|
91
|
-
try {
|
|
92
|
-
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
93
|
-
} catch (rmErr) {
|
|
94
|
-
console.warn(' Cảnh báo: Không thể xóa thư mục, sẽ thử tải đè:', rmErr.message);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
console.log(`[1/3] Cloning OpenClaw setup repository to: ${targetPath}...`);
|
|
98
|
-
await runCmd('git', ['clone', 'https://github.com/tuanminhhole/openclaw-setup.git', targetPath]);
|
|
99
|
-
} else {
|
|
100
|
-
console.log(`[1/3] OpenClaw setup folder already exists at: ${targetPath}`);
|
|
101
|
-
console.log(' Updating repository to latest version...');
|
|
102
|
-
try {
|
|
103
|
-
await runCmd('git', ['pull'], { cwd: targetPath });
|
|
104
|
-
} catch (err) {
|
|
105
|
-
console.warn(' Warning: Failed to git pull (continuing anyway):', err.message);
|
|
106
|
-
}
|
|
105
|
+
const pkgPath = path.join(targetPath, 'package.json');
|
|
106
|
+
if (!fs.existsSync(pkgPath)) {
|
|
107
|
+
fs.writeFileSync(pkgPath, JSON.stringify({ name: 'openclaw-setup-container', version: '1.0.0', private: true, dependencies: {} }, null, 2), 'utf8');
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
console.log(
|
|
110
|
-
await runCmd('npm', ['install'], { cwd: targetPath });
|
|
111
|
-
|
|
112
|
-
console.log('\n[3/3] Starting OpenClaw Setup UI...');
|
|
113
|
-
const originalCwd = process.cwd();
|
|
114
|
-
const cliPath = path.join('dist', 'cli.js');
|
|
115
|
-
await runCmd('node', [cliPath, ...args, `--project-dir=${originalCwd}`], { cwd: targetPath });
|
|
110
|
+
console.log(`[1/2] Checking/Installing latest Setup Wizard package in: ${targetPath}...`);
|
|
111
|
+
await runCmd('npm', ['install', 'create-openclaw-bot@latest', '--no-audit', '--no-fund'], { cwd: targetPath });
|
|
116
112
|
|
|
113
|
+
console.log('\n[2/2] Starting Setup Wizard...');
|
|
114
|
+
const cliPath = path.join(targetPath, 'node_modules', 'create-openclaw-bot', 'dist', 'cli.js');
|
|
115
|
+
|
|
116
|
+
const child = spawn(process.argv[0], [cliPath, ...args, `--project-dir=${projectDir}`], {
|
|
117
|
+
cwd: targetPath,
|
|
118
|
+
shell: true,
|
|
119
|
+
stdio: 'inherit',
|
|
120
|
+
env: {
|
|
121
|
+
...process.env,
|
|
122
|
+
OPENCLAW_SETUP_WIZARD: 'true'
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
child.on('close', (code) => {
|
|
126
|
+
process.exit(code);
|
|
127
|
+
});
|
|
117
128
|
} catch (error) {
|
|
118
|
-
console.error('\n❌
|
|
129
|
+
console.error('\n❌ Lỗi khi khởi động Setup Wizard:', error.message);
|
|
119
130
|
process.exit(1);
|
|
120
131
|
}
|
|
121
132
|
}
|
|
133
|
+
|
|
134
|
+
|
|
@@ -68,7 +68,7 @@ async function fetchLatestSetupVersionBg() {
|
|
|
68
68
|
}
|
|
69
69
|
fetchLatestSetupVersionBg().catch(() => {});
|
|
70
70
|
|
|
71
|
-
const DEFAULT_PROJECT_NAME = 'openclaw-
|
|
71
|
+
const DEFAULT_PROJECT_NAME = 'openclaw-setup';
|
|
72
72
|
const STATE_FILE = '.openclaw-setup-state.json';
|
|
73
73
|
const DEFAULT_MODEL = 'smart-route';
|
|
74
74
|
const logClients = new Set();
|
|
@@ -1695,7 +1695,7 @@ async function recreateDockerBot(projectDir) {
|
|
|
1695
1695
|
for (const a of cfg.agents?.list || []) {
|
|
1696
1696
|
const binding = (cfg.bindings || []).find((b) => b.agentId === a.id);
|
|
1697
1697
|
const channel = binding?.match?.channel || 'telegram';
|
|
1698
|
-
if (channel === 'zalo-personal') {
|
|
1698
|
+
if (channel === 'zalo-personal' || channel === 'zalouser') {
|
|
1699
1699
|
const workspaceDir = workspaceRelForAgent(a, cfg, projectDir) || `workspace-${a.id}`;
|
|
1700
1700
|
const mentionsJsPath = join(projectDir, '.openclaw', workspaceDir, 'skills/sticker-mention/mentions.js');
|
|
1701
1701
|
if (existsSync(mentionsJsPath)) {
|
|
@@ -2175,9 +2175,6 @@ async function deleteProjectFolder(projectDir, rootProjectDir) {
|
|
|
2175
2175
|
const rootHome = resolve(os.homedir());
|
|
2176
2176
|
if (!existsSync(join(resolved, '.openclaw', 'openclaw.json'))) throw httpError(404, 'openclaw.json not found in selected project');
|
|
2177
2177
|
if (resolved === home || resolved === rootHome || /^[A-Za-z]:\\?$/.test(resolved)) throw httpError(403, 'Refusing to delete home/root folder');
|
|
2178
|
-
const projects = await discoverProjects(rootProjectDir).catch(() => []);
|
|
2179
|
-
const meta = projects.find((p) => resolve(p.projectDir) === resolved);
|
|
2180
|
-
if (!meta || !meta.botCount) throw httpError(403, 'Refusing to delete a folder that is not a detected bot project');
|
|
2181
2178
|
// Stop and remove Docker containers first to release host folder locks
|
|
2182
2179
|
const dockerComposeDir = join(resolved, 'docker', 'openclaw');
|
|
2183
2180
|
if (existsSync(join(dockerComposeDir, 'docker-compose.yml'))) {
|
|
@@ -2390,7 +2387,7 @@ async function applyFeatureToggle(projectDir, agentId, kind, id, enabled) {
|
|
|
2390
2387
|
} else {
|
|
2391
2388
|
const binding = (cfg.bindings || []).find((b) => b.agentId === a.id);
|
|
2392
2389
|
const channel = binding?.match?.channel || 'telegram';
|
|
2393
|
-
if (channel === 'zalo-personal' && existsSync(jsf.file)) {
|
|
2390
|
+
if ((channel === 'zalo-personal' || channel === 'zalouser') && existsSync(jsf.file)) {
|
|
2394
2391
|
try {
|
|
2395
2392
|
const hasDocker = existsSync(join(projectDir, 'docker', 'openclaw', 'docker-compose.yml'));
|
|
2396
2393
|
if (hasDocker) {
|
|
@@ -2849,28 +2846,42 @@ async function handler(req, res, rootProjectDir) {
|
|
|
2849
2846
|
return json(res, result);
|
|
2850
2847
|
}
|
|
2851
2848
|
if (url.pathname === '/api/setup/update' && req.method === 'POST') {
|
|
2852
|
-
|
|
2853
|
-
const isGit = existsSync(resolve(
|
|
2849
|
+
const installerDir = resolve(__dirname, '../..');
|
|
2850
|
+
const isGit = existsSync(resolve(installerDir, '.git'));
|
|
2851
|
+
const isNpmPack = __dirname.includes('node_modules');
|
|
2854
2852
|
if (isGit) {
|
|
2855
2853
|
sendLog('[update-setup] Git repository detected. Pulling latest code and building...');
|
|
2856
2854
|
setImmediate(async () => {
|
|
2857
2855
|
try {
|
|
2858
|
-
await run('git', ['pull'], { cwd:
|
|
2859
|
-
await run('npm', ['install'], { cwd:
|
|
2860
|
-
await run('npm', ['run', 'build'], { cwd:
|
|
2861
|
-
sendLog('[update-setup] Setup Wizard updated successfully!
|
|
2856
|
+
await run('git', ['pull'], { cwd: installerDir });
|
|
2857
|
+
await run('npm', ['install'], { cwd: installerDir });
|
|
2858
|
+
await run('npm', ['run', 'build'], { cwd: installerDir });
|
|
2859
|
+
sendLog('[update-setup] Setup Wizard updated successfully! Restarting installer...');
|
|
2862
2860
|
restartInstaller();
|
|
2863
2861
|
} catch (err) {
|
|
2864
2862
|
sendLog(`[update-setup] Error updating: ${err.message}`);
|
|
2865
2863
|
}
|
|
2866
2864
|
});
|
|
2867
2865
|
return json(res, { ok: true, mode: 'git' });
|
|
2866
|
+
} else if (isNpmPack) {
|
|
2867
|
+
const installerHome = resolve(__dirname, '../../../..');
|
|
2868
|
+
sendLog(`[update-setup] Published npm package detected. Updating package in: ${installerHome}...`);
|
|
2869
|
+
setImmediate(async () => {
|
|
2870
|
+
try {
|
|
2871
|
+
await run('npm', ['install', 'create-openclaw-bot@latest', '--no-audit', '--no-fund'], { cwd: installerHome });
|
|
2872
|
+
sendLog('[update-setup] Setup Wizard updated successfully! Restarting installer...');
|
|
2873
|
+
restartInstaller();
|
|
2874
|
+
} catch (err) {
|
|
2875
|
+
sendLog(`[update-setup] Error updating: ${err.message}`);
|
|
2876
|
+
}
|
|
2877
|
+
});
|
|
2878
|
+
return json(res, { ok: true, mode: 'npm' });
|
|
2868
2879
|
} else {
|
|
2869
2880
|
sendLog('[update-setup] Global npm package installation detected. Updating via npm...');
|
|
2870
2881
|
setImmediate(async () => {
|
|
2871
2882
|
try {
|
|
2872
2883
|
await run('npm', ['install', '-g', 'create-openclaw-bot@latest'], { cwd: rootProjectDir });
|
|
2873
|
-
sendLog('[update-setup] Setup Wizard updated successfully!
|
|
2884
|
+
sendLog('[update-setup] Setup Wizard updated successfully! Restarting installer...');
|
|
2874
2885
|
restartInstaller();
|
|
2875
2886
|
} catch (err) {
|
|
2876
2887
|
sendLog(`[update-setup] Error updating: ${err.message}`);
|
|
@@ -348,7 +348,7 @@ CMD ["/bin/sh", "/usr/local/bin/openclaw-entrypoint.sh"]`;
|
|
|
348
348
|
const docker9RouterEntrypointScript = build9RouterComposeEntrypointScript(routerPort);
|
|
349
349
|
const extraHostsBlock = ` extra_hosts:\n - "host.docker.internal:host-gateway"`;
|
|
350
350
|
|
|
351
|
-
const appEnvironmentBlock = ` environment:\n - OPENCLAW_HOME=/home/node/project/.openclaw\n - OPENCLAW_STATE_DIR=/home/node/project/.openclaw\n - OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1\n - OPENCLAW_GATEWAY_PORT=${gatewayPort}\n - OPENCLAW_PORT=${gatewayPort}\n tmpfs:\n - /home/node/project/.openclaw/plugin-runtime-deps\n`;
|
|
351
|
+
const appEnvironmentBlock = ` environment:\n - HOME=/home/node/project/.openclaw\n - OPENCLAW_HOME=/home/node/project/.openclaw\n - OPENCLAW_STATE_DIR=/home/node/project/.openclaw\n - OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1\n - OPENCLAW_GATEWAY_PORT=${gatewayPort}\n - OPENCLAW_PORT=${gatewayPort}\n tmpfs:\n - /home/node/project/.openclaw/plugin-runtime-deps\n`;
|
|
352
352
|
|
|
353
353
|
let compose;
|
|
354
354
|
if (isMultiBot) {
|
package/dist/web/app.js
CHANGED
|
@@ -166,7 +166,7 @@ function installModal() {
|
|
|
166
166
|
const draft = refreshInstallDraft();
|
|
167
167
|
const os = draft.os || state.os || sys?.os || 'win';
|
|
168
168
|
const mode = draft.mode || state.installTab || state.mode || sys?.recommendedMode || 'docker';
|
|
169
|
-
const pathExample = os === 'win' ? '
|
|
169
|
+
const pathExample = os === 'win' ? 'C:\\openclaw-setup' : os === 'macos' ? '/Users/you/openclaw-setup' : '/home/you/openclaw-setup';
|
|
170
170
|
const osChoices = OS_OPTIONS.map(o => [o.id, t(o.title, o.title), trChoice(o).subtitle]);
|
|
171
171
|
const modeChoices = [
|
|
172
172
|
['docker', 'Docker', t('\u0043ontainer c\u00f4 l\u1eadp, an to\u00e0n nh\u1ea5t', 'Isolated containers, safest default')],
|
|
@@ -180,7 +180,7 @@ function installModal() {
|
|
|
180
180
|
<div class="install-tabs">${modeChoices.map(([id,label,desc]) => `<button type="button" class="install-tab ${mode===id?'is-active':''}" data-install-set="mode" data-value="${id}"><strong>${escapeHtml(label)}</strong><small>${escapeHtml(desc)}</small></button>`).join('')}</div>
|
|
181
181
|
<div class="install-grid install-grid--compact">
|
|
182
182
|
<div class="field wide"><span>${t('H\u1ec7 \u0111i\u1ec1u h\u00e0nh','Operating system')}</span>${pillGroup('os', os, osChoices)}<small>${t('\u0110\u00e3 ch\u1ecdn s\u1eb5n theo m\u00e1y \u0111ang ch\u1ea1y','Preselected from the current machine')}</small></div>
|
|
183
|
-
<label class="field wide"><span>${t('Đường dẫn project','Project path')}</span><input name="projectDir" placeholder="${escapeHtml(pathExample)}" value="${escapeHtml(draft.projectDir || pathExample)}" /><small>${t('Ví dụ:
|
|
183
|
+
<label class="field wide"><span>${t('Đường dẫn project','Project path')}</span><input name="projectDir" placeholder="${escapeHtml(pathExample)}" value="${escapeHtml(draft.projectDir || pathExample)}" /><small>${t('Ví dụ: C:\\openclaw-setup hoặc /home/you/openclaw-setup. Bạn có thể tự sửa tên folder bot thành tên bất kỳ.','Example: C:\\openclaw-setup or /home/you/openclaw-setup. You can rename folder bot to any name.')}</small></label>
|
|
184
184
|
</div>
|
|
185
185
|
<div class="install-preview">${t('S\u1ebd t\u1ea1o t\u1ea1i','Will create at')} <code data-install-preview>${escapeHtml(draft.projectDir || pathExample)}</code></div>
|
|
186
186
|
<input type="hidden" name="os" value="${escapeHtml(os)}" />
|
|
@@ -241,7 +241,7 @@ function refreshInstallDraft(next = {}) {
|
|
|
241
241
|
const sys = state.system || {};
|
|
242
242
|
const os = next.os || prev.os || state.os || sys.os || 'win';
|
|
243
243
|
const mode = next.mode || prev.mode || state.mode || sys.recommendedMode || 'docker';
|
|
244
|
-
const defaultDir = os === 'win' ? '
|
|
244
|
+
const defaultDir = os === 'win' ? 'C:\\openclaw-setup' : os === 'macos' ? '/Users/you/openclaw-setup' : '/home/you/openclaw-setup';
|
|
245
245
|
|
|
246
246
|
const projectName = String(next.projectName ?? prev.projectName ?? '').trim();
|
|
247
247
|
const projectRoot = String(next.projectRoot ?? prev.projectRoot ?? '').trim();
|
|
@@ -249,7 +249,7 @@ function refreshInstallDraft(next = {}) {
|
|
|
249
249
|
let projectDir = String(next.projectDir ?? prev.projectDir ?? '').trim();
|
|
250
250
|
if (!projectDir) {
|
|
251
251
|
if (projectRoot) {
|
|
252
|
-
projectDir = joinPath(projectRoot, projectName || 'openclaw-
|
|
252
|
+
projectDir = joinPath(projectRoot, projectName || 'openclaw-setup');
|
|
253
253
|
} else {
|
|
254
254
|
projectDir = defaultDir;
|
|
255
255
|
}
|