create-openclaw-bot 5.7.5 → 5.7.7

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 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.7.5-0EA5E9?style=for-the-badge" alt="Version 5.7.5" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.7.7-0EA5E9?style=for-the-badge" alt="Version 5.7.7" /></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,22 +24,20 @@ 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.7.5
27
+ ## 🆕 What's new in v5.7.7
28
28
 
29
- - 🐛 **Hotfix: CLI crash on all platforms** — Fixed `ReferenceError: channelKey is not defined` that caused the CLI to crash immediately after completing the setup wizard on every platform (Telegram, Zalo). The `writeWorkspaceFiles()` function now correctly receives `channelKey` as an explicit parameter.
30
- - 🔤 **Fix: Vietnamese text encoding** — Restored proper UTF-8 encoding integrity in `cli.src.js` to prevent double-encoding of Vietnamese characters from Windows tools.
29
+ - 🛠️ **Infrastructure & Zalo Bot Stabilization** — Automatically pins `openclaw@2026.4.15` across all deployment scripts, completely eliminating gateway crashes caused by version mismatch when installing Zalo Personal.
30
+ - 📦 **Docker Volume & Gateway Deadlock Optimization** — Redesigned the `.openclaw` mount mechanism and implemented `tmpfs` for `plugin-runtime-deps`, entirely preventing I/O lock conditions on Windows/WSL2.
31
+ - 🔄 **9Router Smart-Sync** — Automatically detects and syncs models (Gemini, Claude, GPT) from active AI providers directly into the `smart-route` combination every time the system starts up.
31
32
 
32
33
  <details>
33
- <summary><b>Previous: What's new in v5.7.2</b></summary>
34
+ <summary><b>Previous: What's new in v5.7.6</b></summary>
34
35
 
35
- - 🏗️ **Centralized config architecture** — All `openclaw.json`, `.env`, and `exec-approvals.json` generation now flows through a single `bot-config-gen.js` module. Both the Web Wizard and CLI share the same builder, eliminating config drift between surfaces.
36
- - 🔄 **Rolling `@latest` versioning** — Installation scripts now use `openclaw@latest` instead of pinned versions, ensuring users always get the newest release without waiting for a setup update.
37
- - 🧪 **Comprehensive test matrix** — Added 422 new matrix tests covering all OS × Deploy × Channel × Bot Count combinations, plus Wizard IIFE sandbox evaluation and CLI structural validation.
38
- - 🐛 **Removed `autoReply` bug** — The `autoReply: true` field that caused gateway startup crashes on Zalo Personal has been permanently removed from all generators.
39
- - 💬 **Standardized Zalo Personal config** — Zalo Personal (`zalouser`) channel now uses production-matching config with `groups`, `groupPolicy`, `historyLimit`, and proper `bindings`.
36
+ - 🧹 **Automated Uninstall Scripts** — Generates an `uninstall-openclaw` script to cleanly remove system/container resources.
37
+ - 🐛 **Hotfix CLI Crash** — Permanently fixed the `channelKey is not defined` bug and double-encoding issues for Vietnamese texts.
38
+ - 🏗️ **Centralized config architecture** — All config logic is now unified through `bot-config-gen.js`, completely eradicating the `autoReply: true` bug.
40
39
 
41
- </details>
42
- ---
40
+ ## </details>
43
41
 
44
42
  ## ✨ Features
45
43
 
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.7.5-0EA5E9?style=for-the-badge" alt="Version 5.7.5" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.7.7-0EA5E9?style=for-the-badge" alt="Version 5.7.7" /></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,22 +24,20 @@ 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.7.5
27
+ ## 🆕 Có gì mới trong v5.7.7
28
28
 
29
- - 🐛 **Hotfix: CLI crash trên mọi nền tảng** — Sửa lỗi `ReferenceError: channelKey is not defined` khiến CLI crash ngay sau khi hoàn thành wizard trên mọi nền tảng (Telegram, Zalo). Hàm `writeWorkspaceFiles()` giờ nhận `channelKey` như một tham số tường minh.
30
- - 🔤 **Sửa: Encoding tiếng Việt trong CLI** — Khôi phục tính toàn vẹn UTF-8 trong `cli.src.js`, ngăn double-encoding tự tiếng Việt do công cụ Windows gây ra.
29
+ - 🛠️ **Ổn Định Infrastructure & Zalo Bot** — Tự động ghim `openclaw@2026.4.15` cho mọi nền tảng, loại bỏ hoàn toàn các lỗi crash do lệch version khi cài Zalo Personal.
30
+ - 📦 **Tối Ưu Docker Volume & Gateway Deadlock** — Thiết kế lại chế mount thư mục `.openclaw` triển khai `tmpfs` cho `plugin-runtime-deps`, triệt để ngăn chặn tình trạng I/O lock trên Windows/WSL2.
31
+ - 🔄 **9Router Smart-Sync** — Tự động nhận diện và đồng bộ danh sách models (Gemini, Claude, GPT) từ các AI provider đang kích hoạt trực tiếp vào combo `smart-route` mỗi khi khởi động hệ thống.
31
32
 
32
33
  <details>
33
- <summary><b>Trước đó: Có gì mới ở v5.7.2</b></summary>
34
+ <summary><b>Trước đó: Có gì mới ở v5.7.6</b></summary>
34
35
 
35
- - 🏗️ **Kiến trúc config tập trung** — Toàn bộ logic tạo `openclaw.json`, `.env`, và `exec-approvals.json` giờ chạy qua module duy nhất `bot-config-gen.js`. Cả Web Wizard và CLI dùng chung cùng một builder, loại bỏ sai lệch config giữa 2 bề mặt.
36
- - 🔄 **Phiên bản rolling `@latest`** Script cài đặt giờ dùng `openclaw@latest` thay version cố định, đảm bảo người dùng luôn nhận bản mới nhất.
37
- - 🧪 **Bộ test matrix toàn diện** — Thêm 422 test mới phủ tất cả tổ hợp OS × Deploy × Channel × Số bot, kèm sandbox Wizard IIFE kiểm tra cấu trúc CLI.
38
- - 🐛 **Xóa lỗi `autoReply`** — Trường `autoReply: true` gây crash gateway khi khởi động Zalo Personal đã bị loại bỏ vĩnh viễn khỏi mọi generator.
39
- - 💬 **Chuẩn hóa config Zalo Personal** — Kênh Zalo Personal (`zalouser`) giờ dùng config khớp production với `groups`, `groupPolicy`, `historyLimit`, và `bindings` đúng.
36
+ - 🧹 **Tự Động Tạo Script Gỡ Cài Đặt** — Sinh sẵn file `uninstall-openclaw` dọn sạch tài nguyên hệ thống/container.
37
+ - 🐛 **Hotfix CLI Crash**Fix triệt để lỗi `channelKey is not defined` double-encoding tiếng Việt.
38
+ - 🏗️ **Kiến trúc config tập trung** — Toàn bộ logic config giờ hợp nhất qua `bot-config-gen.js`, xoá triệt để lỗi `autoReply: true`.
40
39
 
41
- </details>
42
- ---
40
+ ## </details>
43
41
 
44
42
  ## ✨ Tính năng
45
43
 
@@ -61,12 +59,12 @@ Công cụ **CLI tương tác** và **Setup Wizard** để tự triển khai Bot
61
59
 
62
60
  > **Không biết nên dùng cách nào?** Bảng dưới đây sẽ giúp bạn:
63
61
 
64
- | Bạn là ai | Môi trường | Cách được đề xuất |
65
- | --- | --- | --- |
66
- | Không quen terminal | Windows / macOS | **Web Wizard** (`index.html`) |
67
- | Không quen terminal | Ubuntu Desktop | **Web Wizard** → chọn Native |
68
- | Quen terminal | Ubuntu / VPS | **CLI** (`npx create-openclaw-bot`) |
69
- | Muốn tự động hóa hoàn toàn | Bất kỳ | **AI Agent** (Antigravity + SETUP.md) |
62
+ | Bạn là ai | Môi trường | Cách được đề xuất |
63
+ | -------------------------- | --------------- | ------------------------------------- |
64
+ | Không quen terminal | Windows / macOS | **Web Wizard** (`index.html`) |
65
+ | Không quen terminal | Ubuntu Desktop | **Web Wizard** → chọn Native |
66
+ | Quen terminal | Ubuntu / VPS | **CLI** (`npx create-openclaw-bot`) |
67
+ | Muốn tự động hóa hoàn toàn | Bất kỳ | **AI Agent** (Antigravity + SETUP.md) |
70
68
 
71
69
  ### 1️⃣ Tùy chọn A — Web Wizard (không cần terminal)
72
70
 
@@ -122,34 +120,34 @@ Chạy trong terminal → làm theo hướng dẫn → script khởi động đ
122
120
 
123
121
  ### Không dùng Docker (Native — khuyến nghị cho Ubuntu/VPS)
124
122
 
125
- | Yêu cầu | Ghi chú |
126
- | --- | --- |
127
- | **Node.js 20/22/24** | [Tải](https://nodejs.org/) · Kiểm tra: `node -v` · Tránh Node 25 hiện tại |
128
- | **AI provider** | 9Router (miễn phí) hoặc Gemini/Claude/GPT-4o |
129
- | **Bot Token** | Từ Telegram BotFather hoặc Zalo Developer |
130
- | **Ollama** _(tùy chọn)_ | Chỉ cần nếu muốn chạy Gemma 4 locally · [Tải](https://ollama.com/) |
123
+ | Yêu cầu | Ghi chú |
124
+ | ----------------------- | ------------------------------------------------------------------------- |
125
+ | **Node.js 20/22/24** | [Tải](https://nodejs.org/) · Kiểm tra: `node -v` · Tránh Node 25 hiện tại |
126
+ | **AI provider** | 9Router (miễn phí) hoặc Gemini/Claude/GPT-4o |
127
+ | **Bot Token** | Từ Telegram BotFather hoặc Zalo Developer |
128
+ | **Ollama** _(tùy chọn)_ | Chỉ cần nếu muốn chạy Gemma 4 locally · [Tải](https://ollama.com/) |
131
129
 
132
130
  ### Dùng Docker (khuyến nghị cho Windows/macOS)
133
131
 
134
- | Yêu cầu | Ghi chú |
135
- | --- | --- |
136
- | **Node.js 20/22/24** | [Tải](https://nodejs.org/) · Kiểm tra: `node -v` · Tránh Node 25 hiện tại |
132
+ | Yêu cầu | Ghi chú |
133
+ | ------------------------------- | ------------------------------------------------------------------------------------------- |
134
+ | **Node.js 20/22/24** | [Tải](https://nodejs.org/) · Kiểm tra: `node -v` · Tránh Node 25 hiện tại |
137
135
  | **Docker Desktop + Compose V2** | [Tải](https://www.docker.com/products/docker-desktop/) · Kiểm tra: `docker compose version` |
138
- | **AI provider** | 9Router chạy như container sidecar — không cần cài riêng |
139
- | **Bot Token** | Từ Telegram BotFather hoặc Zalo Developer |
136
+ | **AI provider** | 9Router chạy như container sidecar — không cần cài riêng |
137
+ | **Bot Token** | Từ Telegram BotFather hoặc Zalo Developer |
140
138
 
141
139
  ---
142
140
 
143
141
  ## 🧠 Các Provider AI được hỗ trợ
144
142
 
145
- | Provider | Chi phí | API Key | Ghi chú |
146
- | --- | --- | --- | --- |
147
- | **9Router** | 🆓 Miễn phí | ❌ OAuth | Khuyến nghị cho người mới. Tự route đến model tốt nhất. Hỗ trợ Claude CLI, Codex, Gemini. |
148
- | **Google Gemini** | 🆓 Free tier | ✅ Có | Chất lượng cao. Free tier rất rộng rãi. |
149
- | **Ollama / Gemma 4** | 🏠 Miễn phí | ❌ Không | Chạy 100% offline. Tự pull model khi khởi động lần đầu. |
150
- | **Anthropic Claude** | 💰 Trả phí | ✅ Có | Chất lượng suy luận và viết tốt nhất. |
151
- | **OpenAI / Codex** | 💰 Trả phí | ✅ Có | GPT-4o, Codex Mini. |
152
- | **OpenRouter** | 🆓/💰 Hỗn hợp | ✅ Có | Nhiều model chung một key. Một số miễn phí. |
143
+ | Provider | Chi phí | API Key | Ghi chú |
144
+ | -------------------- | ------------- | -------- | ----------------------------------------------------------------------------------------- |
145
+ | **9Router** | 🆓 Miễn phí | ❌ OAuth | Khuyến nghị cho người mới. Tự route đến model tốt nhất. Hỗ trợ Claude CLI, Codex, Gemini. |
146
+ | **Google Gemini** | 🆓 Free tier | ✅ Có | Chất lượng cao. Free tier rất rộng rãi. |
147
+ | **Ollama / Gemma 4** | 🏠 Miễn phí | ❌ Không | Chạy 100% offline. Tự pull model khi khởi động lần đầu. |
148
+ | **Anthropic Claude** | 💰 Trả phí | ✅ Có | Chất lượng suy luận và viết tốt nhất. |
149
+ | **OpenAI / Codex** | 💰 Trả phí | ✅ Có | GPT-4o, Codex Mini. |
150
+ | **OpenRouter** | 🆓/💰 Hỗn hợp | ✅ Có | Nhiều model chung một key. Một số miễn phí. |
153
151
 
154
152
  > 🔀 **9Router v0.3.75+** hỗ trợ passthrough cho Claude Code, Codex, Gemini CLI, và Antigravity. Xem [docs/ai-providers.md](docs/ai-providers.md) để biết chi tiết.
155
153
 
@@ -265,12 +263,12 @@ API key của bạn chỉ được lưu trên máy trong file `.env` cục bộ.
265
263
  <details>
266
264
  <summary><b>Cần bao nhiêu RAM cho Gemma 4?</b></summary>
267
265
 
268
- | Model | RAM tối thiểu (Native) | RAM tối thiểu (Docker) |
269
- | --- | --- | --- |
270
- | `gemma4:e2b` | ~4 GB | ~5 GB |
271
- | `gemma4:e4b` | ~8 GB | ~9 GB |
272
- | `gemma4:26b` | ~18 GB | ~20 GB |
273
- | `gemma4:31b` | ~24 GB | ~26 GB |
266
+ | Model | RAM tối thiểu (Native) | RAM tối thiểu (Docker) |
267
+ | ------------ | ---------------------- | ---------------------- |
268
+ | `gemma4:e2b` | ~4 GB | ~5 GB |
269
+ | `gemma4:e4b` | ~8 GB | ~9 GB |
270
+ | `gemma4:26b` | ~18 GB | ~20 GB |
271
+ | `gemma4:31b` | ~24 GB | ~26 GB |
274
272
 
275
273
  Xem [docs/hardware-guide.md](docs/hardware-guide.md) để biết thêm chi tiết kể cả cách cấu hình swap cho VPS.
276
274
 
package/dist/cli.js CHANGED
@@ -488,14 +488,18 @@ async function patchProjectDocker9Router(projectDir) {
488
488
  await fs.writeFile(path.join(dockerDir, 'sync.js'), build9RouterSmartRouteSyncScript('/root/.9router/db.json'));
489
489
  await fs.writeFile(path.join(dockerDir, 'patch-9router.js'), build9RouterPatchScript());
490
490
  let compose = await fs.readFile(composePath, 'utf8');
491
- compose = compose.replace(
492
- /node -e "require\('fs'\)\.writeFileSync\('\/tmp\/sync\.js',Buffer\.from\('[^']*','base64'\)\.toString\(\)\)"/,
493
- "cp /opt/sync.js /tmp/sync.js"
494
- );
495
- compose = compose.replace(
496
- /(npm install -g [^\n]+\n)/,
497
- `$1 cp /opt/patch-9router.js /tmp/patch-9router.js\n`
498
- );
491
+ compose = compose.replace(
492
+ /node -e "require\('fs'\)\.writeFileSync\('\/tmp\/sync\.js',Buffer\.from\('[^']*','base64'\)\.toString\(\)\)"/,
493
+ "cp /opt/sync.js /tmp/sync.js"
494
+ );
495
+ compose = compose.replace(
496
+ /\s*node -e "require\('fs'\)\.writeFileSync\('\/tmp\/patch-9router\.js',Buffer\.from\('[^']*','base64'\)\.toString\(\)\)"\n/,
497
+ ''
498
+ );
499
+ compose = compose.replace(
500
+ /(npm install -g [^\n]+\n)/,
501
+ `$1 cp /opt/patch-9router.js /tmp/patch-9router.js\n`
502
+ );
499
503
  if (!compose.includes('node /tmp/patch-9router.js || true')) {
500
504
  compose = compose.replace(
501
505
  /(\s*node \/tmp\/sync\.js > \/tmp\/sync\.log 2>&1 &\n)/,
@@ -2158,20 +2162,19 @@ async function main() {
2158
2162
 
2159
2163
 
2160
2164
  // ── Docker artifacts: Dockerfile + docker-compose via shared buildDockerArtifacts() ──────
2161
- const skillSlugs = SKILLS
2162
- .filter(s => selectedSkills.includes(s.value) && s.slug)
2163
- .map(s => s.slug);
2164
- const skillInstallCmd = skillSlugs.length > 0
2165
- ? skillSlugs.map(s => `openclaw skills install ${s} 2>/dev/null || true`).join(' && ')
2166
- : '';
2165
+ const skillSlugs = SKILLS
2166
+ .filter(s => selectedSkills.includes(s.value) && s.slug)
2167
+ .map(s => s.slug);
2168
+ const skillInstallCmd = skillSlugs.length > 0
2169
+ ? skillSlugs.map(s => `ensure_skill ${s}`).join('\n')
2170
+ : '';
2167
2171
  const relayInstallCmd = (isMultiBot && channelKey === 'telegram')
2168
2172
  ? buildRelayPluginInstallCommand('openclaw')
2169
2173
  : '';
2170
- const zaloModInstallCmd = hasZaloPersonal(channelKey)
2171
- ? 'openclaw plugins install openclaw-zalo-mod 2>/dev/null || true'
2172
- : '';
2173
- const socatBridge = hasBrowserDesktop ? 'socat TCP-LISTEN:9222,fork,reuseaddr TCP:host.docker.internal:9222 &' : '';
2174
- const deviceApproveLoop = 'while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done >/dev/null 2>&1 &';
2174
+ const zaloModInstallCmd = hasZaloPersonal(channelKey)
2175
+ ? 'ensure_plugin zalo-mod openclaw-zalo-mod'
2176
+ : '';
2177
+ const deviceApproveLoop = 'while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done >/dev/null 2>&1 &';
2175
2178
 
2176
2179
  // buildDockerArtifacts joins runtimeCommandParts with spaces, then appends 'openclaw gateway run'
2177
2180
  // Each part should be a standalone command fragment (no trailing &&)
@@ -2183,15 +2186,14 @@ async function main() {
2183
2186
  isMultiBot,
2184
2187
  hasBrowser: hasBrowserDesktop || hasBrowserServer,
2185
2188
  selectedModel: modelsPrimary,
2186
- agentId,
2187
- runtimeCommandParts: [
2188
- skillInstallCmd ? skillInstallCmd + ' &&' : '',
2189
- relayInstallCmd ? relayInstallCmd + ' &&' : '',
2190
- zaloModInstallCmd ? zaloModInstallCmd + ' &&' : '',
2191
- socatBridge,
2192
- deviceApproveLoop,
2193
- ].filter(Boolean),
2194
- volumeMount: '../../.openclaw:/root/project/.openclaw',
2189
+ agentId,
2190
+ runtimeCommandParts: [
2191
+ zaloModInstallCmd,
2192
+ relayInstallCmd,
2193
+ skillInstallCmd,
2194
+ deviceApproveLoop,
2195
+ ].filter(Boolean),
2196
+ volumeMount: '../..:/root/project',
2195
2197
  singleComposeName: `oc-${agentId}`,
2196
2198
  multiComposeName: 'oc-multibot',
2197
2199
  singleAppContainerName: `openclaw-${agentId}`,
@@ -261,6 +261,14 @@
261
261
  channels.zalouser = {
262
262
  enabled: true,
263
263
  defaultAccount: 'default',
264
+ accounts: {
265
+ default: {
266
+ dmPolicy: 'open',
267
+ allowFrom: ['*'],
268
+ groupPolicy: 'allowlist',
269
+ groupAllowFrom: ['*'],
270
+ },
271
+ },
264
272
  dmPolicy: 'open',
265
273
  allowFrom: ['*'],
266
274
  groupPolicy: 'allowlist',
@@ -304,6 +312,7 @@
304
312
  enabled: true,
305
313
  config: {
306
314
  botName: botName,
315
+ ownerId: "",
307
316
  groupNames: {},
308
317
  zaloDisplayNames: [botName],
309
318
  welcomeEnabled: true,
@@ -311,7 +320,6 @@
311
320
  spamWindowSeconds: 300,
312
321
  },
313
322
  };
314
- entries.zalouser = { enabled: true };
315
323
  }
316
324
 
317
325
  const plugins = { entries };
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  (function (root) {
3
- const OPENCLAW_NPM_SPEC = 'openclaw@latest';
3
+ const OPENCLAW_NPM_SPEC = 'openclaw@2026.4.15';
4
4
  const OPENCLAW_RUNTIME_PACKAGES = 'grammy @grammyjs/runner @grammyjs/transformer-throttler @buape/carbon @larksuiteoapi/node-sdk @slack/web-api';
5
5
  const NINE_ROUTER_NPM_SPEC = '9router@latest';
6
6
  const NINE_ROUTER_PORT = 20128;
@@ -39,11 +39,26 @@ const sync = async () => {
39
39
  if (!res.ok) { console.log('[sync-combo] API not ready, retrying...'); return; }
40
40
  const d = await res.json();
41
41
  const rawConnections = Array.isArray(d.connections) ? d.connections : Array.isArray(d.providerConnections) ? d.providerConnections : [];
42
- const a = [...new Set(rawConnections.filter(c => c && c.provider && c.isActive !== false && !c.disabled).map(c => c.provider))];
43
- if (!a.length) { removeSmartRoute(); return; }
42
+ const activeConns = rawConnections.filter(c => c && c.provider && c.isActive !== false && !c.disabled);
43
+ const a = [...new Set(activeConns.map(c => c.provider))];
44
+ if (!a.length) { console.log('[sync-combo] No active providers reported; keeping existing smart-route'); return; }
44
45
  a.sort((x, y) => (PREF.indexOf(x) === -1 ? 99 : PREF.indexOf(x)) - (PREF.indexOf(y) === -1 ? 99 : PREF.indexOf(y)));
45
- const m = a.flatMap(pv => PM[pv] || []);
46
- if (!m.length) { removeSmartRoute(); return; }
46
+ const m = [];
47
+ for (const pv of a) {
48
+ if (PM[pv]) m.push(...PM[pv]);
49
+ const conns = activeConns.filter(c => c.provider === pv);
50
+ for (const c of conns) {
51
+ if (Array.isArray(c.models)) {
52
+ for (const mdl of c.models) {
53
+ const mdlId = typeof mdl === 'string' ? mdl : mdl.id;
54
+ if (mdlId && !m.includes(mdlId) && !m.includes(pv + '/' + mdlId)) {
55
+ m.push(pv + '/' + mdlId);
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ if (!m.length) { console.log('[sync-combo] No mapped models for active providers; keeping existing smart-route'); return; }
47
62
  const c = { id: 'smart-route', name: 'smart-route', alias: 'smart-route', models: m };
48
63
  const i = db.combos.findIndex(x => x.id === 'smart-route');
49
64
  if (i >= 0) {
@@ -155,7 +170,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
155
170
  dockerfilePlugins = [],
156
171
  dockerfileSkillInstallMode = 'none',
157
172
  runtimeCommandParts = [],
158
- volumeMount = '../..:/root/project',
173
+ volumeMount = '../../.openclaw:/root/project/.openclaw\\n - ../../:/mnt/project',
159
174
  singleComposeName = 'oc-bot',
160
175
  multiComposeName = 'oc-multibot',
161
176
  singleAppContainerName = 'openclaw-bot',
@@ -191,50 +206,50 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
191
206
  : '';
192
207
  const patchLine = `RUN node -e "const fs=require('fs');const path=require('path');const dir='/usr/local/lib/node_modules/openclaw/dist';const from='\\t\\t\\t\\t\\tonAgentRunStart: (runId) => {';const to='\\t\\t\\t\\t\\ttimeoutOverrideSeconds: Math.max(1, Math.ceil(timeoutMs / 1e3)),\\n\\t\\t\\t\\t\\tonAgentRunStart: (runId) => {';const files=fs.readdirSync(dir).filter(n=>/\\.js$/.test(n));let patched=0;for(const file of files){const p=path.join(dir,file);let s='';try{s=fs.readFileSync(p,'utf8');}catch{continue;}if(s.includes(to)||!s.includes(from))continue;s=s.replace(from,to);fs.writeFileSync(p,s);patched++;}if(!patched){process.exit(0);}"`;
193
208
 
194
- // Dynamic runtime configuration: backup config before any first-run install, restore after.
195
- // Missing plugin install may touch openclaw.json, so preserve critical fields.
209
+ // Dynamic runtime configuration: backup config before any first-run install, restore after.
210
+ // Missing plugin install may touch openclaw.json, so preserve critical fields.
196
211
  const backupConfigScript = `const fs=require('fs'),path=require('path'),p=path.join(process.cwd(),'.openclaw','openclaw.json'),b=p.replace('openclaw.json','.openclaw-config-backup.json');if(fs.existsSync(p)){fs.copyFileSync(p,b);}`;
197
212
  const backupConfigB64 = encodeBase64Utf8(backupConfigScript);
198
213
 
199
214
  const restoreConfigScript = `const fs=require('fs'),os=require('os'),path=require('path'),p=path.join(process.cwd(),'.openclaw','openclaw.json'),b=p.replace('openclaw.json','.openclaw-config-backup.json');if(fs.existsSync(p)&&fs.existsSync(b)){const c=JSON.parse(fs.readFileSync(p,'utf8'));const bk=JSON.parse(fs.readFileSync(b,'utf8'));const keep=['agents','channels','bindings','commands','models','browser','skills'];for(const k of keep){if(bk[k]&&!c[k])c[k]=bk[k];}const a=new Set(['http://localhost:18791','http://127.0.0.1:18791','http://0.0.0.0:18791']);for(const entries of Object.values(os.networkInterfaces()||{})){for(const entry of entries||[]){if(!entry||entry.internal||entry.family!=='IPv4'||!entry.address)continue;a.add('http://'+entry.address+':18791');}}c.tools=Object.assign({},c.tools,{profile:'full',exec:{host:'gateway',security:'full',ask:'off'}});c.gateway=Object.assign({},c.gateway,{port:18791,bind:'custom',customBindHost:'0.0.0.0',mode:c.gateway?.mode||bk.gateway?.mode||'local',controlUi:Object.assign({},c.gateway?.controlUi,{allowedOrigins:Array.from(a).filter(Boolean)})});fs.writeFileSync(p,JSON.stringify(c,null,2));fs.unlinkSync(b);}`;
200
215
  const restoreConfigB64 = encodeBase64Utf8(restoreConfigScript);
201
216
 
202
- const runtimeParts = runtimeCommandParts.filter(Boolean);
203
- const runtimePrelude = [
204
- 'export OPENCLAW_HOME="${OPENCLAW_HOME:-$PWD/.openclaw}"',
205
- 'export OPENCLAW_STATE_DIR="${OPENCLAW_STATE_DIR:-$OPENCLAW_HOME}"',
206
- 'mkdir -p "$OPENCLAW_HOME" "$OPENCLAW_STATE_DIR"',
207
- 'if [ "$OPENCLAW_STATE_DIR" != "$OPENCLAW_HOME" ]; then',
208
- ' for path in "$OPENCLAW_HOME"/*; do',
209
- ' [ -e "$path" ] || continue',
210
- ' name="$(basename "$path")"',
211
- ' [ "$name" = "plugin-runtime-deps" ] && continue',
212
- ' [ "$name" = "logs" ] && continue',
213
- ' [ -e "$OPENCLAW_STATE_DIR/$name" ] || ln -s "$path" "$OPENCLAW_STATE_DIR/$name"',
214
- ' done',
215
- 'fi',
216
- 'ensure_plugin() {',
217
- ' id="$1"',
218
- ' spec="$2"',
219
- ' if [ -d "$OPENCLAW_HOME/extensions/$id" ]; then',
220
- ' echo "[entrypoint] plugin $id already installed"',
221
- ' return 0',
222
- ' fi',
223
- ' echo "[entrypoint] plugin $id missing; installing $spec"',
224
- ' openclaw plugins install "$spec" 2>/dev/null || echo "[entrypoint] warning: failed to install plugin $spec"',
225
- '}',
226
- 'ensure_skill() {',
227
- ' id="$1"',
228
- ' if find "$OPENCLAW_HOME" -maxdepth 4 -type d -path "*/skills/$id" -print -quit 2>/dev/null | grep -q .; then',
229
- ' echo "[entrypoint] skill $id already installed"',
230
- ' return 0',
231
- ' fi',
232
- ' echo "[entrypoint] skill $id missing; installing"',
233
- ' openclaw skills install "$id" 2>/dev/null || echo "[entrypoint] warning: failed to install skill $id"',
234
- '}',
235
- 'echo "[entrypoint] ensuring runtime assets, then starting gateway"',
236
- ];
237
- runtimeParts.unshift(...runtimePrelude);
217
+ const runtimeParts = runtimeCommandParts.filter(Boolean);
218
+ const runtimePrelude = [
219
+ 'export OPENCLAW_HOME="${OPENCLAW_HOME:-$PWD/.openclaw}"',
220
+ 'export OPENCLAW_STATE_DIR="${OPENCLAW_STATE_DIR:-$OPENCLAW_HOME}"',
221
+ 'mkdir -p "$OPENCLAW_HOME" "$OPENCLAW_STATE_DIR"',
222
+ 'if [ "$OPENCLAW_STATE_DIR" != "$OPENCLAW_HOME" ]; then',
223
+ ' for path in "$OPENCLAW_HOME"/*; do',
224
+ ' [ -e "$path" ] || continue',
225
+ ' name="$(basename "$path")"',
226
+ ' [ "$name" = "plugin-runtime-deps" ] && continue',
227
+ ' [ "$name" = "logs" ] && continue',
228
+ ' [ -e "$OPENCLAW_STATE_DIR/$name" ] || ln -s "$path" "$OPENCLAW_STATE_DIR/$name"',
229
+ ' done',
230
+ 'fi',
231
+ 'ensure_plugin() {',
232
+ ' id="$1"',
233
+ ' spec="$2"',
234
+ ' if [ -d "$OPENCLAW_HOME/extensions/$id" ]; then',
235
+ ' echo "[entrypoint] plugin $id already installed"',
236
+ ' return 0',
237
+ ' fi',
238
+ ' echo "[entrypoint] plugin $id missing; installing $spec"',
239
+ ' openclaw plugins install "$spec" 2>/dev/null || echo "[entrypoint] warning: failed to install plugin $spec"',
240
+ '}',
241
+ 'ensure_skill() {',
242
+ ' id="$1"',
243
+ ' if find "$OPENCLAW_HOME" -maxdepth 4 -type d -path "*/skills/$id" -print -quit 2>/dev/null | grep -q .; then',
244
+ ' echo "[entrypoint] skill $id already installed"',
245
+ ' return 0',
246
+ ' fi',
247
+ ' echo "[entrypoint] skill $id missing; installing"',
248
+ ' openclaw skills install "$id" 2>/dev/null || echo "[entrypoint] warning: failed to install skill $id"',
249
+ '}',
250
+ 'echo "[entrypoint] ensuring runtime assets, then starting gateway"',
251
+ ];
252
+ runtimeParts.unshift(...runtimePrelude);
238
253
  // Backup config BEFORE plugin installs (runtimeCommandParts may contain plugin install commands)
239
254
  runtimeParts.unshift(`node -e 'eval(Buffer.from("${backupConfigB64}","base64").toString())'`);
240
255
  // Restore config AFTER plugin installs (which may clobber openclaw.json)
@@ -253,7 +268,7 @@ RUN apt-get update && apt-get install -y git curl${browserAptExtra} && rm -rf /v
253
268
  ${browserInstallLines}
254
269
  ARG OPENCLAW_VER="${openClawNpmSpec}"
255
270
  ARG CACHE_BUST=""
256
- RUN npm install -g ${openClawNpmSpec} ${openClawRuntimePackages}${skillLines}${pluginLines}
271
+ RUN echo "CACHE_BUST=$CACHE_BUST" && npm install -g $OPENCLAW_VER ${openClawRuntimePackages}${skillLines}${pluginLines}
257
272
  ${patchLine}
258
273
  RUN node -e "require('fs').writeFileSync('/usr/local/bin/openclaw-entrypoint.sh', Buffer.from('${runtimeScriptB64}','base64').toString())" && chmod +x /usr/local/bin/openclaw-entrypoint.sh
259
274
  WORKDIR /root/project
@@ -264,12 +279,12 @@ CMD ["/bin/sh", "/usr/local/bin/openclaw-entrypoint.sh"]`;
264
279
 
265
280
  const syncScript = build9RouterSmartRouteSyncScript('/root/.9router/db.json');
266
281
  const syncScriptBase64 = encodeBase64Utf8(syncScript);
267
- const patchScript = build9RouterPatchScript();
282
+ const patchScript = build9RouterPatchScript();
268
283
  const patchScriptBase64 = encodeBase64Utf8(patchScript);
269
284
  const docker9RouterEntrypointScript = build9RouterComposeEntrypointScript(syncScriptBase64, patchScriptBase64);
270
285
  const extraHostsBlock = ` extra_hosts:\n - "host.docker.internal:host-gateway"`;
271
286
 
272
- const appEnvironmentBlock = ' environment:\n - OPENCLAW_HOME=/root/project/.openclaw\n - OPENCLAW_STATE_DIR=/var/lib/openclaw-state\n';
287
+ const appEnvironmentBlock = ' environment:\n - OPENCLAW_HOME=/root/project/.openclaw\n - OPENCLAW_STATE_DIR=/root/project/.openclaw\n - OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1\n tmpfs:\n - /root/project/.openclaw/plugin-runtime-deps\n';
273
288
 
274
289
  let compose;
275
290
  if (isMultiBot) {
@@ -462,19 +477,7 @@ ${appEnvironmentBlock}${plainSingleExtraHosts ? `${extraHostsBlock}\n` : ''}
462
477
  - "18791:18791"`;
463
478
  }
464
479
 
465
- compose = compose.replaceAll(
466
- ` - ${volumeMount}`,
467
- ` - ${volumeMount}\n - openclaw-state:/var/lib/openclaw-state`
468
- );
469
- if (compose.includes('\nvolumes:\n')) {
470
- if (!compose.includes(' openclaw-state:')) {
471
- compose = compose.replace('\nvolumes:\n', '\nvolumes:\n openclaw-state:\n');
472
- }
473
- } else {
474
- compose += '\n\nvolumes:\n openclaw-state:';
475
- }
476
-
477
- return {
480
+ return {
478
481
  dockerfile,
479
482
  compose,
480
483
  syncScript,
package/dist/setup.js CHANGED
@@ -619,7 +619,7 @@
619
619
  // ── Shared runtime constants, relay helpers, auth profile builders (setup/shared/common-gen.js)
620
620
  // @ts-nocheck
621
621
  (function (root) {
622
- const OPENCLAW_NPM_SPEC = 'openclaw@latest';
622
+ const OPENCLAW_NPM_SPEC = 'openclaw@2026.4.15';
623
623
  const OPENCLAW_RUNTIME_PACKAGES = 'grammy @grammyjs/runner @grammyjs/transformer-throttler @buape/carbon @larksuiteoapi/node-sdk @slack/web-api';
624
624
  const NINE_ROUTER_NPM_SPEC = '9router@latest';
625
625
  const NINE_ROUTER_PORT = 20128;
@@ -1699,6 +1699,14 @@ if (typeof exports !== 'undefined' && workspaceRoot.__openclawWorkspace) {
1699
1699
  channels.zalouser = {
1700
1700
  enabled: true,
1701
1701
  defaultAccount: 'default',
1702
+ accounts: {
1703
+ default: {
1704
+ dmPolicy: 'open',
1705
+ allowFrom: ['*'],
1706
+ groupPolicy: 'allowlist',
1707
+ groupAllowFrom: ['*'],
1708
+ },
1709
+ },
1702
1710
  dmPolicy: 'open',
1703
1711
  allowFrom: ['*'],
1704
1712
  groupPolicy: 'allowlist',
@@ -1742,6 +1750,7 @@ if (typeof exports !== 'undefined' && workspaceRoot.__openclawWorkspace) {
1742
1750
  enabled: true,
1743
1751
  config: {
1744
1752
  botName: botName,
1753
+ ownerId: "",
1745
1754
  groupNames: {},
1746
1755
  zaloDisplayNames: [botName],
1747
1756
  welcomeEnabled: true,
@@ -1749,7 +1758,6 @@ if (typeof exports !== 'undefined' && workspaceRoot.__openclawWorkspace) {
1749
1758
  spamWindowSeconds: 300,
1750
1759
  },
1751
1760
  };
1752
- entries.zalouser = { enabled: true };
1753
1761
  }
1754
1762
 
1755
1763
  const plugins = { entries };
@@ -2513,11 +2521,26 @@ const sync = async () => {
2513
2521
  if (!res.ok) { console.log('[sync-combo] API not ready, retrying...'); return; }
2514
2522
  const d = await res.json();
2515
2523
  const rawConnections = Array.isArray(d.connections) ? d.connections : Array.isArray(d.providerConnections) ? d.providerConnections : [];
2516
- const a = [...new Set(rawConnections.filter(c => c && c.provider && c.isActive !== false && !c.disabled).map(c => c.provider))];
2517
- if (!a.length) { removeSmartRoute(); return; }
2524
+ const activeConns = rawConnections.filter(c => c && c.provider && c.isActive !== false && !c.disabled);
2525
+ const a = [...new Set(activeConns.map(c => c.provider))];
2526
+ if (!a.length) { console.log('[sync-combo] No active providers reported; keeping existing smart-route'); return; }
2518
2527
  a.sort((x, y) => (PREF.indexOf(x) === -1 ? 99 : PREF.indexOf(x)) - (PREF.indexOf(y) === -1 ? 99 : PREF.indexOf(y)));
2519
- const m = a.flatMap(pv => PM[pv] || []);
2520
- if (!m.length) { removeSmartRoute(); return; }
2528
+ const m = [];
2529
+ for (const pv of a) {
2530
+ if (PM[pv]) m.push(...PM[pv]);
2531
+ const conns = activeConns.filter(c => c.provider === pv);
2532
+ for (const c of conns) {
2533
+ if (Array.isArray(c.models)) {
2534
+ for (const mdl of c.models) {
2535
+ const mdlId = typeof mdl === 'string' ? mdl : mdl.id;
2536
+ if (mdlId && !m.includes(mdlId) && !m.includes(pv + '/' + mdlId)) {
2537
+ m.push(pv + '/' + mdlId);
2538
+ }
2539
+ }
2540
+ }
2541
+ }
2542
+ }
2543
+ if (!m.length) { console.log('[sync-combo] No mapped models for active providers; keeping existing smart-route'); return; }
2521
2544
  const c = { id: 'smart-route', name: 'smart-route', alias: 'smart-route', models: m };
2522
2545
  const i = db.combos.findIndex(x => x.id === 'smart-route');
2523
2546
  if (i >= 0) {
@@ -2629,7 +2652,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
2629
2652
  dockerfilePlugins = [],
2630
2653
  dockerfileSkillInstallMode = 'none',
2631
2654
  runtimeCommandParts = [],
2632
- volumeMount = '../..:/root/project',
2655
+ volumeMount = '../../.openclaw:/root/project/.openclaw\\n - ../../:/mnt/project',
2633
2656
  singleComposeName = 'oc-bot',
2634
2657
  multiComposeName = 'oc-multibot',
2635
2658
  singleAppContainerName = 'openclaw-bot',
@@ -2727,7 +2750,7 @@ RUN apt-get update && apt-get install -y git curl${browserAptExtra} && rm -rf /v
2727
2750
  ${browserInstallLines}
2728
2751
  ARG OPENCLAW_VER="${openClawNpmSpec}"
2729
2752
  ARG CACHE_BUST=""
2730
- RUN npm install -g ${openClawNpmSpec} ${openClawRuntimePackages}${skillLines}${pluginLines}
2753
+ RUN echo "CACHE_BUST=$CACHE_BUST" && npm install -g $OPENCLAW_VER ${openClawRuntimePackages}${skillLines}${pluginLines}
2731
2754
  ${patchLine}
2732
2755
  RUN node -e "require('fs').writeFileSync('/usr/local/bin/openclaw-entrypoint.sh', Buffer.from('${runtimeScriptB64}','base64').toString())" && chmod +x /usr/local/bin/openclaw-entrypoint.sh
2733
2756
  WORKDIR /root/project
@@ -2738,12 +2761,12 @@ CMD ["/bin/sh", "/usr/local/bin/openclaw-entrypoint.sh"]`;
2738
2761
 
2739
2762
  const syncScript = build9RouterSmartRouteSyncScript('/root/.9router/db.json');
2740
2763
  const syncScriptBase64 = encodeBase64Utf8(syncScript);
2741
- const patchScript = build9RouterPatchScript();
2764
+ const patchScript = build9RouterPatchScript();
2742
2765
  const patchScriptBase64 = encodeBase64Utf8(patchScript);
2743
2766
  const docker9RouterEntrypointScript = build9RouterComposeEntrypointScript(syncScriptBase64, patchScriptBase64);
2744
2767
  const extraHostsBlock = ` extra_hosts:\n - "host.docker.internal:host-gateway"`;
2745
2768
 
2746
- const appEnvironmentBlock = ' environment:\n - OPENCLAW_HOME=/root/project/.openclaw\n - OPENCLAW_STATE_DIR=/var/lib/openclaw-state\n';
2769
+ const appEnvironmentBlock = ' environment:\n - OPENCLAW_HOME=/root/project/.openclaw\n - OPENCLAW_STATE_DIR=/root/project/.openclaw\n - OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1\n tmpfs:\n - /root/project/.openclaw/plugin-runtime-deps\n';
2747
2770
 
2748
2771
  let compose;
2749
2772
  if (isMultiBot) {
@@ -2936,18 +2959,6 @@ ${appEnvironmentBlock}${plainSingleExtraHosts ? `${extraHostsBlock}\n` : ''}
2936
2959
  - "18791:18791"`;
2937
2960
  }
2938
2961
 
2939
- compose = compose.replaceAll(
2940
- ` - ${volumeMount}`,
2941
- ` - ${volumeMount}\n - openclaw-state:/var/lib/openclaw-state`
2942
- );
2943
- if (compose.includes('\nvolumes:\n')) {
2944
- if (!compose.includes(' openclaw-state:')) {
2945
- compose = compose.replace('\nvolumes:\n', '\nvolumes:\n openclaw-state:\n');
2946
- }
2947
- } else {
2948
- compose += '\n\nvolumes:\n openclaw-state:';
2949
- }
2950
-
2951
2962
  return {
2952
2963
  dockerfile,
2953
2964
  compose,
@@ -3975,7 +3986,7 @@ function generateWinBat(ctx) {
3975
3986
  'echo [1/5] Kiem tra Node.js...',
3976
3987
  'where node >nul 2>&1 || (echo ERROR: Node.js chua cai! Tai tai: https://nodejs.org && pause && exit /b 1)',
3977
3988
  'echo [2/5] Cai OpenClaw CLI...',
3978
- `call npm install -g openclaw@latest ${openClawRuntimePackages} || goto :fail`,
3989
+ `call npm install -g ${OPENCLAW_NPM_SPEC} ${openClawRuntimePackages} || goto :fail`,
3979
3990
  'echo [OK] OpenClaw da duoc cai dat thanh cong.',
3980
3991
  ];
3981
3992
 
@@ -4165,7 +4176,7 @@ function generateMacOsSh(ctx) {
4165
4176
  'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.zshrc" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.zshrc"',
4166
4177
  'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.profile" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.profile"',
4167
4178
  '# Install openclaw (user-local first, sudo fallback)',
4168
- `npm install -g openclaw@latest ${openClawRuntimePackages} || sudo npm install -g openclaw@latest ${openClawRuntimePackages}`,
4179
+ `npm install -g ${OPENCLAW_NPM_SPEC} ${openClawRuntimePackages} || sudo npm install -g ${OPENCLAW_NPM_SPEC} ${openClawRuntimePackages}`,
4169
4180
  ];
4170
4181
  providerLines(sh, 'sh');
4171
4182
  if (pluginCmd) sh.push(pluginCmd);
@@ -4231,7 +4242,7 @@ function generateVpsSh(ctx) {
4231
4242
  'export DATA_DIR="$PROJECT_DIR/.9router"',
4232
4243
  'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.bashrc" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.bashrc"',
4233
4244
  'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.profile" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.profile"',
4234
- `npm install -g openclaw@latest ${openClawRuntimePackages} pm2@latest`,
4245
+ `npm install -g ${OPENCLAW_NPM_SPEC} ${openClawRuntimePackages} pm2@latest`,
4235
4246
  ];
4236
4247
  providerLines(vps, 'sh');
4237
4248
  if (pluginCmd) vps.push(pluginCmd);
@@ -4354,7 +4365,7 @@ function generateLinuxSh(ctx) {
4354
4365
  'export DATA_DIR="$PROJECT_DIR/.9router"',
4355
4366
  'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.bashrc" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.bashrc"',
4356
4367
  'grep -Fqx \'export PATH="$HOME/.local/bin:$PATH"\' "$HOME/.profile" 2>/dev/null || echo \'export PATH="$HOME/.local/bin:$PATH"\' >> "$HOME/.profile"',
4357
- `npm install -g openclaw@latest ${openClawRuntimePackages}`,
4368
+ `npm install -g ${OPENCLAW_NPM_SPEC} ${openClawRuntimePackages}`,
4358
4369
  ];
4359
4370
  providerLines(lnx, 'sh');
4360
4371
  if (pluginCmd) lnx.push(pluginCmd);
@@ -5844,7 +5855,7 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
5844
5855
  };
5845
5856
  clawConfig.plugins = {
5846
5857
  entries: {
5847
- ...(ch.hasZaloPersonal ? { 'zalo-mod': { enabled: true, config: {} } } : {}),
5858
+ ...(ch.hasZaloPersonal ? { 'zalo-mod': { enabled: true, config: { botName: botName, ownerId: "", groupNames: {}, zaloDisplayNames: [botName], welcomeEnabled: true, spamRepeatN: 3, spamWindowSeconds: 300 } } } : {}),
5848
5859
  'memory-core': {
5849
5860
  config: { dreaming: { enabled: state.config.skills.includes('memory') } },
5850
5861
  },
@@ -5859,7 +5870,18 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
5859
5870
  pluginEntries[plugin.package || pid] = { enabled: true };
5860
5871
  });
5861
5872
  if (ch.hasZaloPersonal) {
5862
- pluginEntries['zalo-mod'] = { enabled: true, config: {} };
5873
+ pluginEntries['zalo-mod'] = {
5874
+ enabled: true,
5875
+ config: {
5876
+ botName: botName,
5877
+ ownerId: "",
5878
+ groupNames: {},
5879
+ zaloDisplayNames: [botName],
5880
+ welcomeEnabled: true,
5881
+ spamRepeatN: 3,
5882
+ spamWindowSeconds: 300
5883
+ }
5884
+ };
5863
5885
  }
5864
5886
  pluginEntries['memory-core'] = {
5865
5887
  config: { dreaming: { enabled: state.config.skills.includes('memory') } },
@@ -5937,7 +5959,6 @@ model:
5937
5959
  dockerfileSkillInstallMode: 'build',
5938
5960
  runtimeCommandParts: [
5939
5961
  pluginInstallCmd,
5940
- hasBrowser ? 'socat TCP-LISTEN:9222,fork,reuseaddr TCP:host.docker.internal:9222 &' : '',
5941
5962
  'while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done >/dev/null 2>&1 &'
5942
5963
  ],
5943
5964
  plainSingleExtraHosts: true,
@@ -6573,7 +6594,7 @@ fi
6573
6594
  : 'Ubuntu / VPS: The script auto-installs Node.js 20 LTS, OpenClaw CLI, and PM2 to keep the bot running after reboot.');
6574
6595
  }
6575
6596
  steps.push(_isVi ? '✅ Kiểm tra Node.js (cài tự động trên Ubuntu/VPS nếu chưa có)' : '✅ Check Node.js (auto-install on Ubuntu/VPS if missing)');
6576
- steps.push(_isVi ? '📦 Cài OpenClaw CLI (<code>npm install -g openclaw@latest</code>)' : '📦 Install OpenClaw CLI (<code>npm install -g openclaw@latest</code>)');
6597
+ steps.push(_isVi ? `📦 Cài OpenClaw CLI (<code>npm install -g ${common.OPENCLAW_NPM_SPEC}</code>)` : `📦 Install OpenClaw CLI (<code>npm install -g ${common.OPENCLAW_NPM_SPEC}</code>)`);
6577
6598
  if (_is9Router) {
6578
6599
  steps.push(_isVi ? '🔀 Cài 9Router (<code>npm install -g 9router</code>) và khởi động tự động' : '🔀 Install 9Router (<code>npm install -g 9router</code>) and start automatically');
6579
6600
  } else if (_isOllama) {
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
- {
2
- "name": "create-openclaw-bot",
3
- "version": "5.7.5",
4
- "description": "Interactive CLI installer for OpenClaw Bot",
5
- "main": "dist/cli.js",
6
- "bin": {
7
- "create-openclaw-bot": "./dist/cli.js"
8
- },
9
- "files": [
10
- "dist"
11
- ],
12
- "scripts": {
13
- "build": "node src/build.mjs --deploy",
14
- "dev": "node src/build.mjs --deploy --watch",
15
- "test": "node src/tests/smoke-cli-logic.mjs && node src/tests/test-generation.mjs && node src/tests/test-matrix.mjs",
16
- "bump": "node src/bump-version.mjs"
17
- },
18
- "keywords": [
19
- "openclaw",
20
- "cli",
21
- "bot",
22
- "zalo",
23
- "telegram",
24
- "ai"
25
- ],
26
- "author": "tuanminhhole",
27
- "license": "MIT",
28
- "dependencies": {
29
- "@inquirer/prompts": "^4.3.1",
30
- "chalk": "^5.3.0",
31
- "fs-extra": "^11.2.0"
32
- },
33
- "bundleDependencies": [
34
- "@inquirer/prompts",
35
- "chalk",
36
- "fs-extra"
37
- ],
38
- "type": "module"
39
- }
1
+ {
2
+ "name": "create-openclaw-bot",
3
+ "version": "5.7.7",
4
+ "description": "Interactive CLI installer for OpenClaw Bot",
5
+ "main": "dist/cli.js",
6
+ "bin": {
7
+ "create-openclaw-bot": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "node src/build.mjs --deploy",
14
+ "dev": "node src/build.mjs --deploy --watch",
15
+ "test": "node src/tests/smoke-cli-logic.mjs && node src/tests/test-generation.mjs && node src/tests/test-matrix.mjs",
16
+ "bump": "node src/bump-version.mjs"
17
+ },
18
+ "keywords": [
19
+ "openclaw",
20
+ "cli",
21
+ "bot",
22
+ "zalo",
23
+ "telegram",
24
+ "ai"
25
+ ],
26
+ "author": "tuanminhhole",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "@inquirer/prompts": "^4.3.1",
30
+ "chalk": "^5.3.0",
31
+ "fs-extra": "^11.2.0"
32
+ },
33
+ "bundleDependencies": [
34
+ "@inquirer/prompts",
35
+ "chalk",
36
+ "fs-extra"
37
+ ],
38
+ "type": "module"
39
+ }