create-openclaw-bot 5.0.3 → 5.0.5

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Changelog (English)
2
2
 
3
- ## [5.0.1] — 2026-04-04
3
+ ## [5.0.5] — 2026-04-06
4
4
 
5
5
  ### 🚀 Native Install Mode — No Docker Required
6
6
 
package/CHANGELOG.vi.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Changelog (Tiếng Việt)
2
2
 
3
- ## [5.0.1] — 2026-04-04
3
+ ## [5.0.5] — 2026-04-06
4
4
 
5
5
  ### 🚀 Chế độ Native Install — Không cần Docker
6
6
 
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.0.1-0EA5E9?style=for-the-badge" alt="Version 5.0.1" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.0.5-0EA5E9?style=for-the-badge" alt="Version 5.0.5" /></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>
@@ -24,7 +24,7 @@ An interactive **CLI tool** and **Setup Wizard** to deploy your own free AI Bot
24
24
 
25
25
  ---
26
26
 
27
- ## 🆕 What's new in v5.0.1
27
+ ## 🆕 What's new in v5.0.5
28
28
 
29
29
  - 💻 **OS-First Setup** — Step 1 is now choosing your OS (Windows, macOS, Ubuntu, VPS). All scripts, configs, and instructions are generated to match.
30
30
  - 🧠 **Gemma 4 — 4 sizes** — `gemma4:e2b` (~4 GB), `gemma4:e4b` (~8 GB), `gemma4:26b` (~18 GB), `gemma4:31b` (~24 GB). Auto-pulled on first launch.
@@ -111,7 +111,7 @@ Run in your terminal → follow the interactive prompts → startup script is ge
111
111
  2. Open this repo as your workspace
112
112
  3. Paste into chat:
113
113
  ```
114
- Read SETUP.md and set up OpenClaw v5.0.1 for me.
114
+ Read SETUP.md and set up OpenClaw v5.0.5 for me.
115
115
  My bot token is X. Use 9Router (no API key).
116
116
  My project folder: <YOUR_PATH>
117
117
  ```
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.0.1-0EA5E9?style=for-the-badge" alt="Version 5.0.1" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.0.5-0EA5E9?style=for-the-badge" alt="Version 5.0.5" /></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>
@@ -24,7 +24,7 @@ Công cụ **CLI tương tác** và **Setup Wizard** để tự triển khai Bot
24
24
 
25
25
  ---
26
26
 
27
- ## 🆕 Có gì mới trong v5.0.1
27
+ ## 🆕 Có gì mới trong v5.0.5
28
28
 
29
29
  - 💻 **OS-First Setup** — Bước đầu tiên bây giờ là chọn hệ điều hành của bạn (Windows, macOS, Ubuntu, VPS). Toàn bộ script, cấu hình và hướng dẫn được tạo ra phù hợp với lựa chọn đó.
30
30
  - 🧠 **Gemma 4 — 4 kích thước** — `gemma4:e2b` (~4 GB), `gemma4:e4b` (~8 GB), `gemma4:26b` (~18 GB), `gemma4:31b` (~24 GB). Tự pull về khi bot khởi động lần đầu.
@@ -111,7 +111,7 @@ Chạy lệnh trên trong Terminal → làm theo các prompt tương tác → sc
111
111
  2. Mở repo này làm workspace
112
112
  3. Paste vào chat:
113
113
  ```
114
- Read SETUP.md and set up OpenClaw v5.0.1 for me.
114
+ Read SETUP.md and set up OpenClaw v5.0.5 for me.
115
115
  My bot token is X. Use 9Router (no API key).
116
116
  My project folder: <THƯ_MỤC_CỦA_BẠN>
117
117
  ```
package/cli.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import { input, select, checkbox, confirm } from '@inquirer/prompts';
4
4
  import fs from 'fs-extra';
5
5
  import path from 'path';
6
+ import os from 'os';
6
7
  import chalk from 'chalk';
7
8
  import { spawn, execSync } from 'child_process';
8
9
  const TELEGRAM_RELAY_PLUGIN_ID = 'openclaw-telegram-multibot-relay';
@@ -31,6 +32,63 @@ function installRelayPluginForProject(projectDir, isVi) {
31
32
  return false;
32
33
  }
33
34
 
35
+ function isOpenClawInstalled() {
36
+ try {
37
+ execSync('openclaw --version', { stdio: 'ignore' });
38
+ return true;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ function isPm2Installed() {
45
+ try {
46
+ execSync('pm2 --version', { stdio: 'ignore' });
47
+ return true;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+
53
+ function installGlobalPackage(pkg, { isVi, osChoice, displayName }) {
54
+ const installCommands = osChoice === 'windows'
55
+ ? [`npm install -g ${pkg}`]
56
+ : [`npm install -g ${pkg}`, `sudo npm install -g ${pkg}`];
57
+
58
+ for (const cmd of installCommands) {
59
+ try {
60
+ execSync(cmd, { stdio: 'inherit', shell: true });
61
+ return true;
62
+ } catch {
63
+ // try next candidate
64
+ }
65
+ }
66
+
67
+ console.log(chalk.yellow(isVi
68
+ ? `⚠️ Không thể tự cài ${displayName}. Chạy thủ công: ${osChoice === 'windows' ? `npm install -g ${pkg}` : `sudo npm install -g ${pkg}`}`
69
+ : `⚠️ Could not auto-install ${displayName}. Run manually: ${osChoice === 'windows' ? `npm install -g ${pkg}` : `sudo npm install -g ${pkg}`}`));
70
+ return false;
71
+ }
72
+
73
+ async function syncLocalConfigToHome(projectDir, isVi) {
74
+ const homedir = os.homedir();
75
+ const globalClawDir = path.join(homedir, '.openclaw');
76
+ const localClawDir = path.join(projectDir, '.openclaw');
77
+ try {
78
+ await fs.ensureDir(globalClawDir);
79
+ await fs.copy(localClawDir, globalClawDir, { overwrite: true });
80
+ console.log(chalk.green(`\n✅ ${isVi
81
+ ? 'Config đã được sync vào ~/.openclaw/ — openclaw sẵn sàng!'
82
+ : 'Config synced to ~/.openclaw/ — openclaw is ready!'}`));
83
+ return true;
84
+ } catch {
85
+ console.log(chalk.yellow(`\n⚠️ ${isVi
86
+ ? `Không thể tự sync config. Chạy thủ công:\n cp -rn ${localClawDir}/. ${globalClawDir}/`
87
+ : `Could not auto-sync config. Run manually:\n cp -rn ${localClawDir}/. ${globalClawDir}/`}`));
88
+ return false;
89
+ }
90
+ }
91
+
34
92
  function buildTelegramPostInstallChecklist({ isVi, bots, groupId }) {
35
93
  const botList = bots.map((bot, idx) => `- **${bot?.name || `Bot ${idx + 1}`}** — token: ${String(bot?.token || '').slice(0, 10)}...`).join('\n');
36
94
 
@@ -1133,18 +1191,18 @@ ${hasBrowserDesktop ? ` extra_hosts:
1133
1191
  );
1134
1192
  // Generate ecosystem.config.js for PM2 native multi-bot
1135
1193
  if (deployMode === 'native') {
1136
- const pm2Apps = agentMetas.map((meta) => [
1137
- ' {',
1138
- ` name: '${meta.agentId}',`,
1139
- ` script: 'openclaw',`,
1140
- ` args: '--agent ${meta.agentId}',`,
1141
- ` cwd: '${projectDir.replace(/\\/g, '/')}',`,
1142
- ` interpreter: 'none',`,
1143
- ` autorestart: true,`,
1144
- ` watch: false,`,
1145
- ` env: { NODE_ENV: 'production' }`,
1146
- ' }',
1147
- ].join('\n')).join(',\n');
1194
+ const pm2Apps = [
1195
+ ' {',
1196
+ ` name: '${botName || 'openclaw-multibot'}',`,
1197
+ ` script: 'openclaw',`,
1198
+ ` args: 'gateway run',`,
1199
+ ` cwd: '${projectDir.replace(/\\/g, '/')}',`,
1200
+ ` interpreter: 'none',`,
1201
+ ` autorestart: true,`,
1202
+ ` watch: false,`,
1203
+ ` env: { NODE_ENV: 'production' }`,
1204
+ ' }',
1205
+ ].join('\n');
1148
1206
  const ecosystemContent = [
1149
1207
  '// PM2 ecosystem — run: pm2 start ecosystem.config.js',
1150
1208
  'module.exports = {',
@@ -1156,7 +1214,6 @@ ${hasBrowserDesktop ? ` extra_hosts:
1156
1214
  ].join('\n');
1157
1215
  await fs.writeFile(path.join(projectDir, 'ecosystem.config.js'), ecosystemContent);
1158
1216
  }
1159
- installRelayPluginForProject(projectDir, isVi);
1160
1217
  if (Object.keys(authProfilesJson).length > 0) {
1161
1218
  await fs.writeJson(path.join(rootClawDir, 'auth-profiles.json'), authProfilesJson, { spaces: 2 });
1162
1219
  }
@@ -1622,14 +1679,116 @@ fi
1622
1679
  if (isMultiBot && channelKey === 'telegram') {
1623
1680
  console.log(chalk.yellow(`\n${isVi ? '📋 Xem hướng dẫn sau cài:' : '📋 Read post-install guide:'} ${path.join(projectDir, 'TELEGRAM-POST-INSTALL.md')}`));
1624
1681
  }
1625
- } else {
1682
+ // ── Auto-install openclaw binary if not present ──────────────────────────
1683
+ const isOpenClawInstalled = () => { try { execSync('openclaw --version', { stdio: 'ignore' }); return true; } catch { return false; } };
1684
+ if (!isOpenClawInstalled()) {
1685
+ console.log(chalk.cyan(isVi
1686
+ ? '\n📦 Đang cài openclaw binary (npm install -g openclaw)...'
1687
+ : '\n📦 Installing openclaw binary (npm install -g openclaw)...'));
1688
+ try {
1689
+ execSync('npm install -g openclaw', { stdio: 'inherit' });
1690
+ console.log(chalk.green(isVi ? '✅ openclaw đã cài xong!' : '✅ openclaw installed!'));
1691
+ } catch {
1692
+ console.log(chalk.yellow(isVi
1693
+ ? '⚠️ Không tự cài được. Chạy thủ công: sudo npm install -g openclaw'
1694
+ : '⚠️ Could not auto-install. Run manually: sudo npm install -g openclaw'));
1695
+ }
1696
+ }
1697
+
1698
+ // ── Auto-sync generated config to ~/.openclaw so `openclaw` picks it up ──
1699
+
1700
+ const homedir = os.homedir();
1701
+ const globalClawDir = path.join(homedir, '.openclaw');
1702
+ const localClawDir = path.join(projectDir, '.openclaw');
1703
+ try {
1704
+ await fs.ensureDir(globalClawDir);
1705
+ await fs.copy(localClawDir, globalClawDir, { overwrite: true });
1706
+ console.log(chalk.green(`\n✅ ${isVi
1707
+ ? `Config đã được sync vào ~/.openclaw/ — openclaw sẵn sàng!`
1708
+ : `Config synced to ~/.openclaw/ — openclaw is ready!`}`));
1709
+ } catch (syncErr) {
1710
+ console.log(chalk.yellow(`\n⚠️ ${isVi
1711
+ ? `Không thể tự sync config. Chạy thủ công:\n cp -rn ${localClawDir}/. ${globalClawDir}/`
1712
+ : `Could not auto-sync config. Run manually:\n cp -rn ${localClawDir}/. ${globalClawDir}/`}`));
1713
+ }
1714
+
1626
1715
  console.log(chalk.cyan(`\n👉 ${isVi ? 'Đã tạo xong file cấu hình native.' : 'Native config files are ready.'}`));
1627
1716
  console.log(chalk.gray(isVi
1628
1717
  ? ` Cấu trúc config: ${isMultiBot && channelKey === 'telegram' ? '.openclaw/ dùng chung + agents/workspace-*' : (isMultiBot ? 'bot1/, bot2/, ...' : '.openclaw/')}`
1629
1718
  : ` Config layout: ${isMultiBot && channelKey === 'telegram' ? 'shared .openclaw/ with agents/workspace-*' : (isMultiBot ? 'bot1/, bot2/, ...' : '.openclaw/')}`));
1719
+
1720
+ // Print exact run commands
1721
+ console.log(chalk.bold.white(`\n🚀 ${isVi ? 'Chạy bot ngay:' : 'Start the bot now:'}`));
1722
+ if (isMultiBot && channelKey === 'telegram') {
1723
+ console.log(chalk.white(` pm2 start ${path.join(projectDir, 'ecosystem.config.js')}`));
1724
+ } else {
1725
+ console.log(chalk.white(` openclaw gateway`));
1726
+ }
1727
+ console.log(chalk.gray(isVi
1728
+ ? `\n Chạy background (PM2):\n npm install -g pm2\n pm2 start "openclaw gateway" --name "${botName || 'openclaw-bot'}" --cwd ${projectDir}\n pm2 save && pm2 startup`
1729
+ : `\n Run in background (PM2):\n npm install -g pm2\n pm2 start "openclaw gateway" --name "${botName || 'openclaw-bot'}" --cwd ${projectDir}\n pm2 save && pm2 startup`));
1730
+
1630
1731
  if (isMultiBot && channelKey === 'telegram') {
1631
1732
  console.log(chalk.yellow(`\n${isVi ? '📋 Xem hướng dẫn sau cài:' : '📋 Read post-install guide:'} ${path.join(projectDir, 'TELEGRAM-POST-INSTALL.md')}`));
1632
1733
  }
1734
+ } else {
1735
+ if (!isOpenClawInstalled()) {
1736
+ console.log(chalk.cyan(isVi
1737
+ ? '\n📦 Dang cai openclaw binary (npm install -g openclaw)...'
1738
+ : '\n📦 Installing openclaw binary (npm install -g openclaw)...'));
1739
+ if (!installGlobalPackage('openclaw', { isVi, osChoice, displayName: 'openclaw' })) {
1740
+ process.exit(1);
1741
+ }
1742
+ console.log(chalk.green(isVi ? '✅ openclaw da cai xong!' : '✅ openclaw installed!'));
1743
+ }
1744
+
1745
+ await syncLocalConfigToHome(projectDir, isVi);
1746
+
1747
+ if (isMultiBot && channelKey === 'telegram') {
1748
+ installRelayPluginForProject(projectDir, isVi);
1749
+ }
1750
+
1751
+ if (osChoice === 'vps') {
1752
+ if (!isPm2Installed()) {
1753
+ console.log(chalk.cyan(isVi ? '\n📦 Dang cai PM2...' : '\n📦 Installing PM2...'));
1754
+ if (!installGlobalPackage('pm2', { isVi, osChoice, displayName: 'PM2' })) {
1755
+ process.exit(1);
1756
+ }
1757
+ }
1758
+
1759
+ if (isMultiBot && channelKey === 'telegram') {
1760
+ execSync('pm2 start ecosystem.config.js && pm2 save', {
1761
+ cwd: projectDir,
1762
+ stdio: 'inherit',
1763
+ shell: true
1764
+ });
1765
+ console.log(chalk.green(`\n🎉 ${isVi ? 'Setup hoan tat! Multi-bot native dang chay qua PM2.' : 'Setup complete! Native multi-bot is running via PM2.'}`));
1766
+ console.log(chalk.gray(isVi ? ` Xem log: pm2 logs ${botName || 'openclaw-multibot'}` : ` View logs: pm2 logs ${botName || 'openclaw-multibot'}`));
1767
+ } else {
1768
+ const appName = botName || 'openclaw';
1769
+ execSync(`pm2 start "openclaw gateway run" --name "${appName}" --cwd "${projectDir.replace(/\\/g, '/')}" && pm2 save`, {
1770
+ cwd: projectDir,
1771
+ stdio: 'inherit',
1772
+ shell: true
1773
+ });
1774
+ console.log(chalk.green(`\n🎉 ${isVi ? 'Setup hoan tat! Bot native dang chay qua PM2.' : 'Setup complete! Native bot is running via PM2.'}`));
1775
+ console.log(chalk.gray(isVi ? ` Xem log: pm2 logs ${appName}` : ` View logs: pm2 logs ${appName}`));
1776
+ }
1777
+ } else {
1778
+ console.log(chalk.yellow(`\n${isVi ? 'Khoi dong native bot (foreground)...' : 'Starting native bot (foreground)...'}`));
1779
+ const child = spawn('openclaw', ['gateway', 'run'], {
1780
+ cwd: projectDir,
1781
+ stdio: 'inherit',
1782
+ shell: process.platform === 'win32'
1783
+ });
1784
+ child.on('close', (code) => process.exit(code ?? 0));
1785
+ return;
1786
+ }
1787
+
1788
+ console.log(chalk.cyan(`\n👉 ${isVi ? 'Native runtime da duoc cai san va khoi dong.' : 'Native runtime is installed and started.'}`));
1789
+ if (isMultiBot && channelKey === 'telegram') {
1790
+ console.log(chalk.yellow(`\n📋 ${isVi ? 'Xem huong dan sau cai:' : 'Read post-install guide:'} ${path.join(projectDir, 'TELEGRAM-POST-INSTALL.md')}`));
1791
+ }
1633
1792
  }
1634
1793
  }
1635
1794
 
@@ -1637,4 +1796,3 @@ main().catch(err => {
1637
1796
  console.error(chalk.red('Error:'), err);
1638
1797
  process.exit(1);
1639
1798
  });
1640
-
@@ -2,7 +2,7 @@
2
2
 
3
3
  Native installation is designed for users who cannot or prefer not to use Docker. This includes deployments on Shared Hosting (cPanel), low-tier VPS environments, or Windows desktops for direct access.
4
4
 
5
- OpenClaw v5.0.1+ natively supports deployment script generation for Windows, Linux, VPS, and Hosting environments.
5
+ OpenClaw v5.0.5+ natively supports deployment script generation for Windows, Linux, VPS, and Hosting environments.
6
6
 
7
7
  ---
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Chế độ Native được thiết kế dành cho những ai không thể hoặc không muốn cài Docker. Chế độ này thường tối ưu cho Shared Hosting (cPanel), các gói VPS cấu hình rất thấp, hoặc cài trực tiếp trên máy Window để chạy cá nhân.
4
4
 
5
- OpenClaw v5.0.1+ tự động sinh sẵn các script cài đặt dành riêng cho Windows, Linux, VPS và Hosting.
5
+ OpenClaw v5.0.5+ tự động sinh sẵn các script cài đặt dành riêng cho Windows, Linux, VPS và Hosting.
6
6
 
7
7
  ---
8
8
 
package/index.html CHANGED
@@ -482,7 +482,7 @@
482
482
  <span style="font-size: 28px;">💻</span>
483
483
  <div>
484
484
  <h3 class="output-section__title" style="margin: 0;" data-vi="Download Script Cài đặt" data-en="Download Setup Script">Download Script Cài đặt</h3>
485
- <p style="font-size: 13px; color: var(--text-muted); margin: 4px 0 0;" id="native-instructions" data-vi="Tải file → chạy để cài bot trực tiếp trên máy (tự động cài 9Router/Ollama nếu đã chọn)" data-en="Download → run to install bot directly on machine (auto-installs 9Router/Ollama if selected)">Tải file → chạy để cài bot trực tiếp trên máy (tự động cài 9Router/Ollama nếu đã chọn)</p>
485
+ <p style="font-size: 13px; color: var(--text-muted); margin: 4px 0 0;" id="native-instructions" data-vi="Tải file → chạy để cài OpenClaw trực tiếp trên máy (tự động cài 9Router/Ollama nếu đã chọn)" data-en="Download → run to install OpenClaw directly on your machine (auto-installs 9Router/Ollama if selected)">Tải file → chạy để cài OpenClaw trực tiếp trên máy (tự động cài 9Router/Ollama nếu đã chọn)</p>
486
486
  </div>
487
487
  </div>
488
488
  <div style="display: flex; justify-content: center; margin: 20px 0 8px;">
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "5.0.3",
3
+ "version": "5.0.5",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "cli.js",
6
6
  "bin": {
7
7
  "create-openclaw-bot": "./cli.js"
8
8
  },
9
9
  "scripts": {
10
- "test": "echo \"Error: no test specified\" && exit 1",
10
+ "test": "node tests/smoke-cli-logic.mjs",
11
11
  "bump": "node bump-version.mjs"
12
12
  },
13
13
  "keywords": [
package/setup.js CHANGED
@@ -728,8 +728,8 @@
728
728
  icon: '🐧',
729
729
  titleVi: 'Ubuntu / VPS — Khuyên dùng Native (Không Docker)',
730
730
  titleEn: 'Ubuntu / VPS — Recommended: Native (No Docker)',
731
- descVi: 'Chạy thẳng trên máy, tiết kiệm RAM, khởi động nhanh. Script tự cài Node.js 20 LTS, PM2, 9Router/Ollama và giữ bot chạy liên tục sau reboot.',
732
- descEn: 'Run directly on machine — lower RAM, faster startup. Script auto-installs Node.js 20 LTS, PM2, 9Router/Ollama and keeps bot running across reboots.',
731
+ descVi: 'Chạy thẳng trên máy, tiết kiệm RAM, khởi động nhanh. Script tự cài Node.js 20 LTS, OpenClaw CLI, PM2, 9Router/Ollama và giữ bot chạy liên tục sau reboot.',
732
+ descEn: 'Run directly on machine — lower RAM, faster startup. Script auto-installs Node.js 20 LTS, OpenClaw CLI, PM2, 9Router/Ollama and keeps bot running across reboots.',
733
733
  deploy: 'native',
734
734
  badgeVi: '💻 Native + PM2',
735
735
  badgeEn: '💻 Native + PM2',
@@ -739,8 +739,8 @@
739
739
  icon: '🖥️',
740
740
  titleVi: 'Linux Desktop — Khuyên dùng Native',
741
741
  titleEn: 'Linux Desktop — Recommended: Native',
742
- descVi: 'Không cần Docker. Script tự cài Node.js 20 LTS nếu chưa có, rồi cài 9Router hoặc Ollama theo lựa chọn provider của bạn.',
743
- descEn: 'No Docker needed. Script auto-installs Node.js 20 LTS if missing, then installs 9Router or Ollama based on your provider choice.',
742
+ descVi: 'Không cần Docker. Script tự cài Node.js 20 LTS nếu chưa có, cài OpenClaw CLI, rồi cài 9Router hoặc Ollama theo provider bạn chọn khởi động bot ngay.',
743
+ descEn: 'No Docker needed. Script auto-installs Node.js 20 LTS if missing, installs OpenClaw CLI, then installs 9Router or Ollama based on your provider choice and starts the bot immediately.',
744
744
  deploy: 'native',
745
745
  badgeVi: '💻 Native',
746
746
  badgeEn: '💻 Native',
@@ -0,0 +1,154 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ const root = process.cwd();
5
+ const cli = fs.readFileSync(path.join(root, 'cli.js'), 'utf8');
6
+ const setup = fs.readFileSync(path.join(root, 'setup.js'), 'utf8');
7
+ const indexHtml = fs.readFileSync(path.join(root, 'index.html'), 'utf8');
8
+
9
+ function expect(condition, message) {
10
+ if (!condition) {
11
+ throw new Error(message);
12
+ }
13
+ }
14
+
15
+ function expectMatch(source, regex, message) {
16
+ expect(regex.test(source), message);
17
+ }
18
+
19
+ function expectOrder(source, before, after, message) {
20
+ const beforeIndex = source.indexOf(before);
21
+ const afterIndex = source.indexOf(after);
22
+ expect(beforeIndex !== -1, `${message} (missing first marker)`);
23
+ expect(afterIndex !== -1, `${message} (missing second marker)`);
24
+ expect(beforeIndex < afterIndex, message);
25
+ }
26
+
27
+ const checks = [];
28
+
29
+ checks.push(() => expectMatch(
30
+ cli,
31
+ /const deployModeDefault = \(osChoice === 'ubuntu' \|\| osChoice === 'vps'\) \? 'native' : 'docker';/,
32
+ 'Ubuntu/VPS must default to native deploy mode'
33
+ ));
34
+
35
+ checks.push(() => expectMatch(
36
+ cli,
37
+ /if \(deployMode === 'docker' && !isDockerInstalled\(\)\)/,
38
+ 'Docker branch must still auto-install Docker when missing'
39
+ ));
40
+
41
+ checks.push(() => expectMatch(
42
+ cli,
43
+ /if \(!isOpenClawInstalled\(\)\) \{[\s\S]*installGlobalPackage\('openclaw', \{ isVi, osChoice, displayName: 'openclaw' \}\)/,
44
+ 'Native branch must auto-install openclaw'
45
+ ));
46
+
47
+ checks.push(() => expectMatch(
48
+ cli,
49
+ /if \(osChoice === 'vps'\) \{[\s\S]*installGlobalPackage\('pm2', \{ isVi, osChoice, displayName: 'PM2' \}\)/,
50
+ 'VPS native branch must auto-install PM2'
51
+ ));
52
+
53
+ checks.push(() => expectMatch(
54
+ cli,
55
+ /execSync\('pm2 start ecosystem\.config\.js && pm2 save'/,
56
+ 'Native Telegram multi-bot must start through PM2 ecosystem'
57
+ ));
58
+
59
+ checks.push(() => expectMatch(
60
+ cli,
61
+ /execSync\(`pm2 start "openclaw gateway run" --name "\$\{appName\}" --cwd "\$\{projectDir\.replace\(\/\\\\\/g, '\/'\)\}" && pm2 save`/,
62
+ 'Native single-bot VPS must start gateway through PM2'
63
+ ));
64
+
65
+ checks.push(() => expectMatch(
66
+ cli,
67
+ /const child = spawn\('openclaw', \['gateway', 'run'\], \{/,
68
+ 'Native desktop flows must start openclaw in foreground'
69
+ ));
70
+
71
+ checks.push(() => expectOrder(
72
+ cli,
73
+ "await syncLocalConfigToHome(projectDir, isVi);",
74
+ "installRelayPluginForProject(projectDir, isVi);",
75
+ 'Relay plugin install must happen after config sync in native flow'
76
+ ));
77
+
78
+ checks.push(() => expectMatch(
79
+ cli,
80
+ /const pm2Apps = \[[\s\S]*args: 'gateway run'/,
81
+ 'Native multi-bot ecosystem must run one gateway process'
82
+ ));
83
+
84
+ checks.push(() => expectMatch(
85
+ setup,
86
+ /Linux Desktop[^]*Script tự cài Node\.js 20 LTS nếu chưa có, cài OpenClaw CLI[^]*khởi động bot ngay/s,
87
+ 'Web wizard Linux Desktop advisory must mention auto-install OpenClaw and immediate start'
88
+ ));
89
+
90
+ checks.push(() => expectMatch(
91
+ setup,
92
+ /Ubuntu \/ VPS[^]*Script tự cài Node\.js 20 LTS, OpenClaw CLI, PM2[^]*giữ bot chạy liên tục sau reboot/s,
93
+ 'Web wizard VPS advisory must mention OpenClaw CLI and PM2'
94
+ ));
95
+
96
+ checks.push(() => expectMatch(
97
+ indexHtml,
98
+ /Tải file → chạy để cài OpenClaw trực tiếp trên máy/,
99
+ 'Native download card copy must mention OpenClaw direct install'
100
+ ));
101
+
102
+ checks.push(() => expectMatch(
103
+ setup,
104
+ /if \(state\.nativeOs === 'win'\) \{[\s\S]*scriptName = isDocker \? 'setup-openclaw-docker-win\.bat' : 'setup-openclaw-win\.bat';[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
105
+ 'Windows native/docker script generation must use the correct file name and start command'
106
+ ));
107
+
108
+ checks.push(() => expectMatch(
109
+ setup,
110
+ /else if \(state\.nativeOs === 'linux'\) \{[\s\S]*scriptName = isDocker \? 'setup-openclaw-docker-macos\.sh' : 'setup-openclaw-macos\.sh';[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
111
+ 'macOS script generation must use the correct file name and start command'
112
+ ));
113
+
114
+ checks.push(() => expectMatch(
115
+ setup,
116
+ /else if \(state\.nativeOs === 'vps'\) \{[\s\S]*scriptName = 'setup-openclaw-vps\.sh';[\s\S]*npm install -g openclaw@latest pm2[\s\S]*pm2 save && pm2 startup/s,
117
+ 'VPS native script generation must install openclaw+pm2 and persist PM2 startup'
118
+ ));
119
+
120
+ checks.push(() => expectMatch(
121
+ setup,
122
+ /else if \(state\.nativeOs === 'vps'\) \{[\s\S]*pm2 start --name openclaw-multibot -- sh -c "openclaw gateway run"[\s\S]*pm2 logs openclaw-multibot/s,
123
+ 'VPS multi-bot native script must start the shared gateway via PM2'
124
+ ));
125
+
126
+ checks.push(() => expectMatch(
127
+ setup,
128
+ /else if \(state\.nativeOs === 'vps'\) \{[\s\S]*pm2 start --name openclaw -- sh -c "openclaw gateway run"[\s\S]*pm2 logs openclaw/s,
129
+ 'VPS single-bot native script must start one bot via PM2'
130
+ ));
131
+
132
+ checks.push(() => expectMatch(
133
+ setup,
134
+ /else if \(state\.nativeOs === 'linux-desktop'\) \{[\s\S]*scriptName = 'setup-openclaw-linux\.sh';[\s\S]*npm install -g openclaw@latest[\s\S]*openclaw gateway run/s,
135
+ 'Linux Desktop native script generation must install openclaw and run the gateway'
136
+ ));
137
+
138
+ checks.push(() => expectMatch(
139
+ setup,
140
+ /instrEl\.innerHTML = state\.nativeOs === 'win'[\s\S]*double-click[\s\S]*chmod \+x \$\{scriptName\} && \.\/\$\{scriptName\}/s,
141
+ 'Native instructions must show double-click for Windows and chmod for shell scripts'
142
+ ));
143
+
144
+ checks.push(() => expectMatch(
145
+ setup,
146
+ /steps\.push\(isVi \? '.*Cài OpenClaw CLI.*' : '.*Install OpenClaw CLI.*'\);/s,
147
+ 'Auto-steps summary must mention OpenClaw CLI installation'
148
+ ));
149
+
150
+ for (const check of checks) {
151
+ check();
152
+ }
153
+
154
+ console.log(`Smoke checks passed: ${checks.length}`);