create-openclaw-bot 5.7.8 → 5.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md 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.8-0EA5E9?style=for-the-badge" alt="Version 5.7.8" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.7.10-0EA5E9?style=for-the-badge" alt="Version 5.7.10" /></a>
7
7
  <a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
8
8
  <a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
9
9
  <a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
@@ -24,18 +24,16 @@ 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.8
27
+ ## 🆕 What's new in v5.7.10
28
28
 
29
- - 🧹 **Zalo Mod Plugin Cleanup** — Removed auto-injection of `zalo-mod` into generated configs. The plugin now must be installed manually via ClawHub, eliminating persistent installation loops and Docker permission conflicts.
30
- - 🔧 **Cleaner Docker Build** — `openclaw-zalo-mod` is no longer baked into the Docker image during build or runtime entrypoint, reducing image size and startup errors.
31
- - 📝 **Standardized Release Workflow** — Added `.agent/workflows/update.md` as the canonical release checklist for this repo.
29
+ - 🔧 **Rename Zalo Plugin Reference** — Updated internal string references from `zalo-mod` to `openclaw-zalo-mod` to align with the new NPM package identity.
32
30
 
33
31
  <details>
34
- <summary><b>Previous: What's new in v5.7.7</b></summary>
32
+ <summary><b>Previous: What's new in v5.7.8</b></summary>
35
33
 
36
- - 🛠️ **Infrastructure & Zalo Bot Stabilization** — Automatically pins `openclaw@2026.4.15` across all deployment scripts, eliminating gateway crashes caused by version mismatch when installing Zalo Personal.
37
- - 📦 **Docker Volume & Gateway Deadlock Optimization** Redesigned the `.openclaw` mount mechanism and implemented `tmpfs` for `plugin-runtime-deps`, preventing I/O lock conditions on Windows/WSL2.
38
- - 🔄 **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.
34
+ - 🧹 **Zalo Mod Plugin Cleanup** — Removed auto-injection of `zalo-mod` into generated configs. The plugin now must be installed manually via ClawHub, eliminating persistent installation loops and Docker permission conflicts.
35
+ - 🔧 **Cleaner Docker Build** `openclaw-zalo-mod` is no longer baked into the Docker image during build or runtime entrypoint, reducing image size and startup errors.
36
+ - 📝 **Standardized Release Workflow** — Added `.agent/workflows/update.md` as the canonical release checklist for this repo.
39
37
 
40
38
  ## </details>
41
39
 
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.8-0EA5E9?style=for-the-badge" alt="Version 5.7.8" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.7.10-0EA5E9?style=for-the-badge" alt="Version 5.7.10" /></a>
7
7
  <a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
8
8
  <a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
9
9
  <a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
@@ -24,18 +24,16 @@ 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.8
27
+ ## 🆕 Có gì mới trong v5.7.10
28
28
 
29
- - 🧹 **Dọn dẹp Plugin Zalo Mod** — Gỡ bỏ auto-inject `zalo-mod` khỏi config được generate. Plugin giờ phải cài thủ công qua ClawHub, loại bỏ vòng lặp cài đặt liên tục và xung đột quyền trong Docker.
30
- - 🔧 **Docker Build Sạch Hơn** — `openclaw-zalo-mod` không còn được nhúng vào Docker image khi build hoặc trong entrypoint runtime, giảm kích thước image và lỗi khởi động.
31
- - 📝 **Chuẩn Hóa Workflow Release** — Thêm `.agent/workflows/update.md` làm checklist release chuẩn cho repo này.
29
+ - 🔧 **Cập nhật tham chiếu Plugin Zalo** — Đổi tên `zalo-mod` thành `openclaw-zalo-mod` trong các chuỗi sinh cấu hình test để đồng bộ với package mới.
32
30
 
33
31
  <details>
34
- <summary><b>Trước đó: Có gì mới ở v5.7.7</b></summary>
32
+ <summary><b>Trước đó: Có gì mới ở v5.7.8</b></summary>
35
33
 
36
- - 🛠️ **Ổ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.
37
- - 📦 **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.
38
- - 🔄 **9Router Smart-Sync** — Tự động nhận diện đồ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.
34
+ - 🧹 **Dọn dẹp Plugin Zalo Mod** — Gỡ bỏ auto-inject `zalo-mod` khỏi config được generate. Plugin giờ phải cài thủ công qua ClawHub, loại bỏ vòng lặp cài đặt liên tục xung đột quyền trong Docker.
35
+ - 🔧 **Docker Build Sạch Hơn** — `openclaw-zalo-mod` không còn được nhúng vào Docker image khi build hoặc trong entrypoint runtime, giảm kích thước image lỗi khởi động.
36
+ - 📝 **Chuẩn Hóa Workflow Release** — Thêm `.agent/workflows/update.md` làm checklist release chuẩn cho repo này.
39
37
 
40
38
  ## </details>
41
39
 
package/dist/cli.js CHANGED
@@ -21,9 +21,9 @@ function loadSharedModule(modulePath, globalName) {
21
21
  }
22
22
 
23
23
  const {
24
- OPENCLAW_NPM_SPEC,
25
- OPENCLAW_RUNTIME_PACKAGES,
26
- NINE_ROUTER_PROXY_API_KEY,
24
+ OPENCLAW_NPM_SPEC,
25
+ OPENCLAW_RUNTIME_PACKAGES,
26
+ NINE_ROUTER_PROXY_API_KEY,
27
27
  NINE_ROUTER_API_BASE_URL,
28
28
  SMART_ROUTE_PROVIDER_MODELS,
29
29
  SMART_ROUTE_PROVIDER_ORDER,
@@ -615,10 +615,14 @@ function printNativeDashboardAccessInfo({ isVi, providerKey, projectDir, gateway
615
615
  }
616
616
  }
617
617
 
618
- function printZaloPersonalLoginInfo({ isVi, deployMode, projectDir }) {
619
- const nativeCmd = 'openclaw channels login --channel zalouser --verbose';
620
- const dockerCmd = 'docker exec -it openclaw-bot openclaw channels login --channel zalouser --verbose';
621
- const cmd = deployMode === 'native' ? nativeCmd : dockerCmd;
618
+ function printZaloPersonalLoginInfo({ isVi, deployMode, projectDir }) {
619
+ const nativeCmd = 'openclaw channels login --channel zalouser --verbose';
620
+ const dockerCmd = 'docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose';
621
+ const dockerStopCmd = 'docker compose stop ai-bot';
622
+ const dockerStartCmd = 'docker compose up -d --force-recreate ai-bot';
623
+ const dockerStatusCmd = 'docker compose exec ai-bot openclaw channels status --probe';
624
+ const dockerReloginCmd = 'docker compose run --rm --no-deps ai-bot openclaw channels logout --channel zalouser && docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose';
625
+ const cmd = deployMode === 'native' ? nativeCmd : dockerCmd;
622
626
  const qrPath = deployMode === 'native'
623
627
  ? path.join(os.tmpdir(), 'openclaw', 'openclaw-zalouser-qr-default.png')
624
628
  : '/tmp/openclaw/openclaw-zalouser-qr-default.png';
@@ -630,31 +634,40 @@ function printZaloPersonalLoginInfo({ isVi, deployMode, projectDir }) {
630
634
 
631
635
  console.log(chalk.yellow(`\n📱 ${isVi ? 'Đăng nhập Zalo Personal (1 lần):' : 'Zalo Personal login (one time):'}`));
632
636
  if (deployMode === 'docker') {
633
- console.log(chalk.white(isVi
634
- ? ` 1. cd ${projectDir}/docker/openclaw`
635
- : ` 1. cd ${projectDir}/docker/openclaw`));
636
- console.log(chalk.white(isVi
637
- ? ` 2. ${cmd}`
638
- : ` 2. ${cmd}`));
639
- console.log(chalk.white(isVi
640
- ? ` 3. Tìm file QR trong container: ${qrPath}`
641
- : ` 3. Find QR image in container: ${qrPath}`));
637
+ console.log(chalk.white(isVi
638
+ ? ` 1. cd ${projectDir}/docker/openclaw`
639
+ : ` 1. cd ${projectDir}/docker/openclaw`));
640
+ console.log(chalk.white(isVi
641
+ ? ` 2. ${dockerStopCmd}`
642
+ : ` 2. ${dockerStopCmd}`));
643
+ console.log(chalk.white(isVi
644
+ ? ` 3. ${cmd}`
645
+ : ` 3. ${cmd}`));
646
+ console.log(chalk.white(isVi
647
+ ? ` 4. Tìm file QR trong container: ${qrPath}`
648
+ : ` 4. Find QR image in container: ${qrPath}`));
642
649
  console.log(chalk.gray(isVi
643
650
  ? ` → Mở Docker Desktop > container openclaw-bot > tab Files > tìm file trên`
644
651
  : ` → Open Docker Desktop > container openclaw-bot > Files tab > find file above`));
645
652
  console.log(chalk.gray(isVi
646
653
  ? ` → Hoặc chạy: ${copyCmd}`
647
654
  : ` → Or run: ${copyCmd}`));
648
- console.log(chalk.white(isVi
649
- ? ' 4. Mở app Zalo > Quét QR > quét mã trong file QR'
650
- : ' 4. Open Zalo app > Scan QR > scan the QR image'));
651
- console.log(chalk.white(isVi
652
- ? ' 5. Đợi thấy "Login successful" trong terminal'
653
- : ' 5. Wait for "Login successful" in terminal'));
654
- console.log(chalk.white(isVi
655
- ? ' 6. docker compose restart'
656
- : ' 6. docker compose restart'));
657
- } else {
655
+ console.log(chalk.white(isVi
656
+ ? ' 5. Mở app Zalo > Quét QR > quét mã trong file QR'
657
+ : ' 5. Open Zalo app > Scan QR > scan the QR image'));
658
+ console.log(chalk.white(isVi
659
+ ? ' 6. Đợi thấy "Login successful" trong terminal'
660
+ : ' 6. Wait for "Login successful" in terminal'));
661
+ console.log(chalk.white(isVi
662
+ ? ` 7. ${dockerStartCmd}`
663
+ : ` 7. ${dockerStartCmd}`));
664
+ console.log(chalk.white(isVi
665
+ ? ` 8. ${dockerStatusCmd} # phải thấy: running`
666
+ : ` 8. ${dockerStatusCmd} # should show: running`));
667
+ console.log(chalk.gray(isVi
668
+ ? ` Nếu probe báo chưa auth: ${dockerReloginCmd}`
669
+ : ` If the probe says unauthenticated: ${dockerReloginCmd}`));
670
+ } else {
658
671
  console.log(chalk.white(` cd ${projectDir} ${process.platform === 'win32' ? ';' : '&&'} ${cmd}`));
659
672
  console.log(chalk.gray(isVi
660
673
  ? ` → File QR sẽ tạo tại: ${qrPath}`
@@ -2168,9 +2181,9 @@ async function main() {
2168
2181
  const skillInstallCmd = skillSlugs.length > 0
2169
2182
  ? skillSlugs.map(s => `ensure_skill ${s}`).join('\n')
2170
2183
  : '';
2171
- const relayInstallCmd = (isMultiBot && channelKey === 'telegram')
2172
- ? buildRelayPluginInstallCommand('openclaw')
2173
- : '';
2184
+ const relayInstallCmd = (isMultiBot && channelKey === 'telegram')
2185
+ ? buildRelayPluginInstallCommand('openclaw')
2186
+ : '';
2174
2187
  const deviceApproveLoop = 'while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done >/dev/null 2>&1 &';
2175
2188
 
2176
2189
  // buildDockerArtifacts joins runtimeCommandParts with spaces, then appends 'openclaw gateway run'
@@ -82,7 +82,7 @@
82
82
  historyLimit: 50,
83
83
  },
84
84
  },
85
- pluginInstall: '@openclaw/zalouser',
85
+ pluginInstall: '',
86
86
  },
87
87
  };
88
88
 
@@ -189,7 +189,7 @@
189
189
  cfg.skills = { entries: skillEntries };
190
190
  }
191
191
 
192
- // ── plugins (memory-core dreaming + zalo-mod) ────────────────────────────
192
+ // ── plugins (memory-core dreaming + openclaw-zalo-mod) ────────────────────────────
193
193
  const pluginsConfig = buildPluginsConfig({
194
194
  channelKey,
195
195
  selectedSkills,
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  (function (root) {
3
- const OPENCLAW_NPM_SPEC = 'openclaw@2026.4.15';
3
+ const OPENCLAW_NPM_SPEC = 'openclaw@2026.5.4';
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;
@@ -186,7 +186,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
186
186
 
187
187
  } = options;
188
188
 
189
- const browserAptExtra = hasBrowser ? ' xvfb socat' : '';
189
+ const browserAptExtra = hasBrowser ? ' xvfb socat' : '';
190
190
  const browserInstallLines = hasBrowser && emitBrowserInstall
191
191
  ? [
192
192
  '',
@@ -264,7 +264,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
264
264
  const runtimeScriptB64 = encodeBase64Utf8(runtimeScript);
265
265
  const dockerfile = `FROM node:22-slim
266
266
 
267
- RUN apt-get update && apt-get install -y git curl${browserAptExtra} && rm -rf /var/lib/apt/lists/*
267
+ RUN apt-get update && apt-get install -y git curl python3${browserAptExtra} && rm -rf /var/lib/apt/lists/*
268
268
  ${browserInstallLines}
269
269
  ARG OPENCLAW_VER="${openClawNpmSpec}"
270
270
  ARG CACHE_BUST=""
@@ -249,19 +249,47 @@ const CDP_URL = 'http://127.0.0.1:9222';
249
249
 
250
250
  function buildBrowserDoc(options = {}) {
251
251
  const { isVi = true, variant = 'wizard', workspaceRoot = '' } = options;
252
- // Normalize: strip trailing slash so path joins work cleanly
253
252
  const wsRoot = workspaceRoot.replace(/\/+$/, '');
254
253
  const btPath = wsRoot ? `${wsRoot}/browser-tool.js` : 'browser-tool.js';
255
254
 
256
- if (variant === 'cli-desktop') {
257
- return `# Browser Automation (Desktop Mode)\n\nBot controls your actual Chrome on screen through Chrome Debug at \`http://127.0.0.1:9222\`. Every action is visible.\n\n## Usage (v2)\n\`\`\`bash\n# Navigation\nnode ${btPath} status\nnode ${btPath} open "https://google.com"\nnode ${btPath} get_url\n\n# Content extraction\nnode ${btPath} get_text\nnode ${btPath} get_text 8000 # custom max length\nnode ${btPath} get_links # all links\nnode ${btPath} get_links "/posts/" # filtered\nnode ${btPath} get_posts # Facebook group posts w/ permalinks\nnode ${btPath} evaluate "document.title"\nnode ${btPath} console\n\n# Screenshots & export\nnode ${btPath} screenshot\nnode ${btPath} screenshot_full\nnode ${btPath} pdf\n\n# Interactions\nnode ${btPath} click "button.submit"\nnode ${btPath} fill "input[name='q']" "search"\nnode ${btPath} press "Enter"\nnode ${btPath} hover "a.link"\nnode ${btPath} select "select#country" "VN"\nnode ${btPath} upload "input[type=file]" "/tmp/photo.jpg"\n\n# Scrolling & viewport\nnode ${btPath} scroll\nnode ${btPath} scroll 1500\nnode ${btPath} wait 3000\nnode ${btPath} resize 1920 1080\n\n# Tab management\nnode ${btPath} tabs\nnode ${btPath} new_tab "https://example.com"\nnode ${btPath} switch_tab 1\nnode ${btPath} close_tab 2\n\`\`\`\n\n## MANDATORY RULES\n- NEVER refuse to open the browser when user asks.\n- In Desktop mode, always target the \`host-chrome\` / Chrome Debug session first.\n- If Chrome Debug is unreachable or returns \`ECONNREFUSED\`, tell user to run \`start-chrome-debug.bat\` again.\n- Use \`get_posts\` instead of \`get_text\` when scraping Facebook — it extracts permalinks.\n`;
258
- }
259
- if (variant === 'cli-server') {
260
- return `# Browser Automation (Headless Server Mode)\n\nBot uses a headless Chromium instance running inside the Docker container. No GUI needed!\n\n## Notes\n- Running on Ubuntu Server / VPS (no GUI required)\n- Uses Playwright + Headless Chromium installed inside Docker\n- For Cloudflare bypass, switch to Desktop mode (requires Windows/Mac with Chrome)\n`;
261
- }
262
- return isVi
263
- ? `# Browser Automation\n\nDùng file \`browser-tool.js\` để điều khiển Chrome debug tại \`http://127.0.0.1:9222\`.\nScript: \`${btPath}\`\nPhiên bản v2 hỗ trợ: open, get_text, get_links, get_posts, evaluate, screenshot, pdf, click, fill, press, hover, select, upload, scroll, tabs, và nhiều lệnh khác.`
264
- : `# Browser Automation\n\nUse \`browser-tool.js\` to control Chrome debug on \`http://127.0.0.1:9222\`.\nScript: \`${btPath}\`\nVersion v2 supports: open, get_text, get_links, get_posts, evaluate, screenshot, pdf, click, fill, press, hover, select, upload, scroll, tabs, and more.`;
255
+ return `# Navigation
256
+ node ${btPath} status
257
+ node ${btPath} open "https://google.com"
258
+ node ${btPath} get_url
259
+
260
+ # ⭐ Content extraction — LUÔN dùng get_posts cho Facebook
261
+ node ${btPath} get_posts
262
+ node ${btPath} get_text
263
+ node ${btPath} get_text 8000
264
+ node ${btPath} get_links
265
+ node ${btPath} get_links "/posts/"
266
+ node ${btPath} evaluate "document.title"
267
+ node ${btPath} console
268
+
269
+ # Screenshots & export
270
+ node ${btPath} screenshot
271
+ node ${btPath} screenshot_full
272
+ node ${btPath} pdf
273
+
274
+ # Interactions
275
+ node ${btPath} click "button.submit"
276
+ node ${btPath} fill "input[name='q']" "search"
277
+ node ${btPath} press "Enter"
278
+ node ${btPath} hover "a.link"
279
+ node ${btPath} select "select#id" "value"
280
+ node ${btPath} upload "input[type=file]" "/tmp/photo.jpg"
281
+
282
+ # Scrolling & viewport
283
+ node ${btPath} scroll
284
+ node ${btPath} scroll 1500
285
+ node ${btPath} wait 3000
286
+ node ${btPath} resize 1920 1080
287
+
288
+ # Tab management
289
+ node ${btPath} tabs
290
+ node ${btPath} new_tab "https://example.com"
291
+ node ${btPath} switch_tab 1
292
+ node ${btPath} close_tab 2`;
265
293
  }
266
294
 
267
295
  function buildSecurityRules(isVi = true) {
@@ -299,14 +327,14 @@ const CDP_URL = 'http://127.0.0.1:9222';
299
327
  ? '- If metadata does not clearly say this is a group/supergroup, treat it as a private DM and reply normally.\n'
300
328
  : '';
301
329
  return isVi
302
- ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI'}.\n\n## Quy tắc trả lời\n- Trả lời ngắn gọn, súc tích\n- Ưu tiên tiếng Việt\n- Khi hỏi tên: _\"Mình là ${botName}\"_\n- Không bịa thông tin\n- Bạn ĐÃ biết sẵn danh tính, vai trò, tính cách của mình từ **IDENTITY.md**, **SOUL.md**, **AGENTS.md**\n- KHÔNG hỏi user đặt lại tên, vibe, persona, emoji ký tên, hay \"bạn muốn mình là kiểu trợ lý nào\"\n- KHÔNG tự giới thiệu kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\" hoặc onboarding tương tự\n- Nếu user chỉ nhắn ngắn như \"alo\", hãy chào ngắn gọn và trả lời đúng vai trò hiện tại của bạn\n\n## Khi nào nên trả lời\n${directMessageRuleVi}- Trong group, coi user đang gọi bạn nếu tin nhắn có một trong các alias: ${aliasStr}.\n- Nếu user tag username Telegram của bạn thì luôn trả lời.\n- Nếu group message đang gọi rõ bot khác ${relayTargetNames} thì không cướp lời.\n- Quy tắc im lặng khi không ai được gọi chỉ áp dụng cho group chat, không áp dụng cho DM/chat riêng.\n\n## Tài liệu tham chiếu\n- \uD83D\uDCCB **TOOLS.md** — Danh sách skill/tool đã cài và cách sử dụng\n- \uD83E\uDD1D **TEAMS.md** — Quy tắc phối hợp team, handoff protocol, và anti-pattern\n- \uD83D\uDCAD **MEMORY.md** — Bộ nhớ dài hạn\n- \uD83C\uDFAD **IDENTITY.md** — Danh tính và tính cách${security}`
303
- : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'an AI assistant'}.\n\n## Reply Rules\n- Reply concisely\n- Prefer English\n- When asked your name: _\"I'm ${botName}\"_\n- Do not fabricate information\n- You ALREADY know your identity, role, and personality from **IDENTITY.md**, **SOUL.md**, and **AGENTS.md**\n- DO NOT ask the user to redefine your name, vibe, persona, signature emoji, or \"what kind of assistant\" you should be\n- DO NOT act like you just woke up, just came online, or are still choosing your identity\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character\n\n## When To Reply\n${directMessageRuleEn}- In groups, treat the message as addressed to you when it includes one of your aliases: ${aliasStr}.\n- Always reply when your Telegram username is tagged.\n- If a group message is clearly calling another bot such as ${relayTargetNames}, do not hijack it.\n- The stay-silent rule for unaddressed messages applies only to group chats, never to DMs/private chats.\n\n## Reference Docs\n- \uD83D\uDCCB **TOOLS.md** — Installed skills/tools and usage guide\n- \uD83E\uDD1D **TEAMS.md** — Team coordination rules, handoff protocol, and anti-patterns\n- \uD83D\uDCAD **MEMORY.md** — Long-term memory\n- \uD83C\uDFAD **IDENTITY.md** — Identity and personality${security}`;
330
+ ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI'}.\n\n## Quy tắc trả lời\n- Trả lời ngắn gọn, súc tích\n- Ưu tiên tiếng Việt\n- Khi hỏi tên: _\"Mình là ${botName}\"_\n- Không bịa thông tin\n- Bạn ĐÃ biết sẵn danh tính, vai trò, tính cách của mình từ **IDENTITY.md**, **SOUL.md**, **AGENTS.md**\n- KHÔNG hỏi user đặt lại tên, vibe, persona, emoji ký tên, hay \"bạn muốn mình là kiểu trợ lý nào\"\n- KHÔNG tự giới thiệu kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\" hoặc onboarding tương tự\n- Nếu user chỉ nhắn ngắn như \"alo\", hãy chào ngắn gọn và trả lời đúng vai trò hiện tại của bạn\n\n## Khi nào nên trả lời\n${directMessageRuleVi}- Trong group, coi user đang gọi bạn nếu tin nhắn có một trong các alias: ${aliasStr}.\n- Nếu user tag username Telegram của bạn thì luôn trả lời.\n- Nếu group message đang gọi rõ bot khác ${relayTargetNames} thì không cướp lời.\n- Quy tắc im lặng khi không ai được gọi chỉ áp dụng cho group chat, không áp dụng cho DM/chat riêng.\n\n## Tài liệu tham chiếu\n- 📋 **TOOLS.md** — Danh sách skill/tool đã cài và cách sử dụng\n- 🤝 **TEAMS.md** — Quy tắc phối hợp team, handoff protocol, và anti-pattern\n- 💭 **MEMORY.md** — Bộ nhớ dài hạn\n- 🎭 **IDENTITY.md** — Danh tính và tính cách\n- 🌍 **BROWSER.md** — Hướng dẫn sử dụng Browser Automation\n- 🚀 **BOOT.md** — Hướng dẫn khởi động và thiết lập\n- 🧠 **SOUL.md** — Định hướng phát triển và giá trị cốt lõi\n- ✨ **DREAMS.md** — Mục tiêu dài hạn và ý tưởng\n- 💓 **HEARTBEAT.md** — Nhịp độ hoạt động và cron jobs\n- 👤 **USER.md** — Thông tin và bối cảnh về User\n- 🤖 **AGENTS.md** — Vai trò và quy tắc chung (file này)${security}`
331
+ : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'an AI assistant'}.\n\n## Reply Rules\n- Reply concisely\n- Prefer English\n- When asked your name: _\"I'm ${botName}\"_\n- Do not fabricate information\n- You ALREADY know your identity, role, and personality from **IDENTITY.md**, **SOUL.md**, and **AGENTS.md**\n- DO NOT ask the user to redefine your name, vibe, persona, signature emoji, or \"what kind of assistant\" you should be\n- DO NOT act like you just woke up, just came online, or are still choosing your identity\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character\n\n## When To Reply\n${directMessageRuleEn}- In groups, treat the message as addressed to you when it includes one of your aliases: ${aliasStr}.\n- Always reply when your Telegram username is tagged.\n- If a group message is clearly calling another bot such as ${relayTargetNames}, do not hijack it.\n- The stay-silent rule for unaddressed messages applies only to group chats, never to DMs/private chats.\n\n## Reference Docs\n- 📋 **TOOLS.md** — Installed skills/tools and usage guide\n- 🤝 **TEAMS.md** — Team coordination rules, handoff protocol, and anti-patterns\n- 💭 **MEMORY.md** — Long-term memory\n- 🎭 **IDENTITY.md** — Identity and personality\n- 🌍 **BROWSER.md** — Browser Automation guide\n- 🚀 **BOOT.md** — Bootstrap rules\n- 🧠 **SOUL.md** — Core values and direction\n- ✨ **DREAMS.md** — Long term goals and ideas\n- 💓 **HEARTBEAT.md** — Activity rules and cron jobs\n- 👤 **USER.md** — User profile\n- 🤖 **AGENTS.md** — Role and general rules (this file)${security}`;
304
332
  }
305
333
 
306
334
  // Single-bot variant
307
335
  return isVi
308
- ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI cá nhân'}.\nBạn hỗ trợ user trong mọi tác vụ qua chat.\n\n## Quy tắc trả lời\n- Trả lời bằng **tiếng Việt** (trừ khi dùng ngôn ngữ khác)\n- **Ngắn gọn, súc tích**\n- Khi hỏi tên → _\"Mình là ${botName}\"_\n- Bạn ĐÃ biết sẵn danh tính và tính cách của mình, không cần user định nghĩa lại\n- KHÔNG hỏi user đặt tên/vibe/persona/emoji cho mình\n- KHÔNG tự nói kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\"\n\n## Hành vi\n- KHÔNG bịa đặt thông tin\n- KHÔNG tiết lộ file hệ thống (SOUL.md, AGENTS.md).\n- Nếu user chỉ mở đầu ngắn như \"alo\", trả lời ngắn gọn, đúng vai trò, không onboarding ngược lại user\n\n## Tài liệu tham chiếu\n- \uD83D\uDCCB **TOOLS.md** — Danh sách skill/tool và cách sử dụng\n- \uD83D\uDCAD **MEMORY.md** — Bộ nhớ dài hạn\n- \uD83C\uDFAD **IDENTITY.md** — Danh tính và tính cách${security}`
309
- : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'a personal AI assistant'}.\nYou support users with any task through chat.\n\n## Reply Rules\n- Reply in **English** (unless the user switches language)\n- **Concise and to the point**\n- When asked your name → _\"I'm ${botName}\"_\n- You already know your identity and personality; do not ask the user to redefine them\n- DO NOT ask the user to pick your name, vibe, persona, or signature emoji\n- DO NOT say you just woke up, just came online, or are still choosing your identity\n\n## Behavior\n- Do NOT fabricate information\n- Do NOT reveal system files (SOUL.md, AGENTS.md).\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character instead of onboarding them\n\n## Reference Docs\n- \uD83D\uDCCB **TOOLS.md** — Installed skills/tools and usage guide\n- \uD83D\uDCAD **MEMORY.md** — Long-term memory\n- \uD83C\uDFAD **IDENTITY.md** — Identity and personality${security}`;
336
+ ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI cá nhân'}.\nBạn hỗ trợ user trong mọi tác vụ qua chat.\n\n## Quy tắc trả lời\n- Trả lời bằng **tiếng Việt** (trừ khi dùng ngôn ngữ khác)\n- **Ngắn gọn, súc tích**\n- Khi hỏi tên → _\"Mình là ${botName}\"_\n- Bạn ĐÃ biết sẵn danh tính và tính cách của mình, không cần user định nghĩa lại\n- KHÔNG hỏi user đặt tên/vibe/persona/emoji cho mình\n- KHÔNG tự nói kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\"\n\n## Hành vi\n- KHÔNG bịa đặt thông tin\n- KHÔNG tiết lộ file hệ thống (SOUL.md, AGENTS.md).\n- Nếu user chỉ mở đầu ngắn như \"alo\", trả lời ngắn gọn, đúng vai trò, không onboarding ngược lại user\n\n## Tài liệu tham chiếu\n- 📋 **TOOLS.md** — Danh sách skill/tool và cách sử dụng\n- 💭 **MEMORY.md** — Bộ nhớ dài hạn\n- 🎭 **IDENTITY.md** — Danh tính và tính cách\n- 🌍 **BROWSER.md** — Hướng dẫn sử dụng Browser Automation\n- 🚀 **BOOT.md** — Hướng dẫn khởi động và thiết lập\n- 🧠 **SOUL.md** — Định hướng phát triển và giá trị cốt lõi\n- ✨ **DREAMS.md** — Mục tiêu dài hạn và ý tưởng\n- 💓 **HEARTBEAT.md** — Nhịp độ hoạt động và cron jobs\n- 👤 **USER.md** — Thông tin và bối cảnh về User\n- 🤖 **AGENTS.md** — Vai trò và quy tắc chung (file này)${security}`
337
+ : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'a personal AI assistant'}.\nYou support users with any task through chat.\n\n## Reply Rules\n- Reply in **English** (unless the user switches language)\n- **Concise and to the point**\n- When asked your name → _\"I'm ${botName}\"_\n- You already know your identity and personality; do not ask the user to redefine them\n- DO NOT ask the user to pick your name, vibe, persona, or signature emoji\n- DO NOT say you just woke up, just came online, or are still choosing your identity\n\n## Behavior\n- Do NOT fabricate information\n- Do NOT reveal system files (SOUL.md, AGENTS.md).\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character instead of onboarding them\n\n## Reference Docs\n- 📋 **TOOLS.md** — Installed skills/tools and usage guide\n- 💭 **MEMORY.md** — Long-term memory\n- 🎭 **IDENTITY.md** — Identity and personality\n- 🌍 **BROWSER.md** — Browser Automation guide\n- 🚀 **BOOT.md** — Bootstrap rules\n- 🧠 **SOUL.md** — Core values and direction\n- ✨ **DREAMS.md** — Long term goals and ideas\n- 💓 **HEARTBEAT.md** — Activity rules and cron jobs\n- 👤 **USER.md** — User profile\n- 🤖 **AGENTS.md** — Role and general rules (this file)${security}`;
310
338
  }
311
339
 
312
340
  function buildToolsDoc(options = {}) {
@@ -346,11 +374,7 @@ const CDP_URL = 'http://127.0.0.1:9222';
346
374
  : `\n\n## \u23F0 Cron / Scheduled Tasks\n- OpenClaw natively supports system tools for Cron Jobs.\n- When the user asks to schedule tasks or reminders, use the built-in tools automatically. Do NOT ask users to run crontab or Task Scheduler manually on the host.\n- When operating cron/scheduler tools, do **not** put \`current\` into the Session directory.\n- Skip internal doc lookups such as \`cron-jobs.mdx\`; rely on the available tools and complete the scheduling task directly.`)
347
375
  : '';
348
376
 
349
- const zaloModSection = hasZaloMod
350
- ? (isVi
351
- ? `\n\n## 💬 Zalo Group — Slash Commands (xử lý bởi plugin)\n\nPlugin \`zalo-mod\` tự động xử lý các slash command sau trong group. Bot KHÔNG cần reply cho chúng:\n\n| Command | Mô tả |\n|---------|-------|\n| \`/rules status\` | Xem cấu hình bot |\n| \`/rules silent-on/off\` | Bật/tắt silent mode |\n| \`/rules welcome-on/off\` | Bật/tắt welcome message |\n| \`/rules tracking-on/off\` | Bật/tắt ghi log chat |\n| \`/noi-quy\` | Hiện nội quy group |\n| \`/menu\` | Danh sách lệnh |\n| \`/groupid\` | Scan và cập nhật config |\n| \`/report\` | Báo cáo hoạt động group |\n\n### Zalo Sticker & Media\n- Sticker Zalo gửi dạng JSON → plugin tự convert thành \`[Sticker]\`\n- Ảnh/video/file trong group: zalouser channel chỉ forward text, media bị drop`
352
- : `\n\n## 💬 Zalo Group — Slash Commands (handled by plugin)\n\nThe \`zalo-mod\` plugin automatically handles these slash commands in group. Bot does NOT need to reply:\n\n| Command | Description |\n|---------|-------------|\n| \`/rules status\` | View bot config |\n| \`/rules silent-on/off\` | Toggle silent mode |\n| \`/rules welcome-on/off\` | Toggle welcome message |\n| \`/rules tracking-on/off\` | Toggle chat logging |\n| \`/noi-quy\` | Show group rules |\n| \`/menu\` | List commands |\n| \`/groupid\` | Scan and update config |\n| \`/report\` | Group activity report |\n\n### Zalo Sticker & Media\n- Zalo stickers arrive as JSON → plugin auto-converts to \`[Sticker]\`\n- Images/videos/files in groups: zalouser channel only forwards text, media is dropped`)
353
- : '';
377
+ const zaloModSection = '';
354
378
 
355
379
  const dmOverride = isVi
356
380
  ? `\n\n## Override: DM và Telegram reaction\n- Nếu metadata không nói rõ đây là group/supergroup, mặc định xem là chat riêng/DM và trả lời bình thường.\n- Quy tắc im lặng khi không ai được gọi chỉ áp dụng cho group chat, không áp dụng cho DM/chat riêng.\n- Trước MỖI phản hồi Telegram nhìn thấy bởi user, nếu turn hiện tại có tool/action reaction native thì ưu tiên dùng nó để thả \`👍\` trước, trừ khi \`👍\` đã có sẵn.\n- Nếu turn hiện tại không expose tool reaction hoặc chat đích không hỗ trợ reaction thật, cứ trả lời đúng vai trò và không được nói là mình đã thả reaction.`
@@ -405,6 +429,7 @@ const CDP_URL = 'http://127.0.0.1:9222';
405
429
  * @property {string} [teamRosterFormatted]
406
430
  * @property {string} [emoji]
407
431
  * @property {boolean} [hasScheduler]
432
+ * @property {boolean} [hasZaloMod]
408
433
  */
409
434
 
410
435
  /**
package/dist/setup.js CHANGED
@@ -297,7 +297,7 @@
297
297
  historyLimit: 50,
298
298
  },
299
299
  },
300
- pluginInstall: '@openclaw/zalouser',
300
+ pluginInstall: '',
301
301
  },
302
302
  };
303
303
 
@@ -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@2026.4.15';
622
+ const OPENCLAW_NPM_SPEC = 'openclaw@2026.5.4';
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;
@@ -1185,19 +1185,47 @@ const CDP_URL = 'http://127.0.0.1:9222';
1185
1185
 
1186
1186
  function buildBrowserDoc(options = {}) {
1187
1187
  const { isVi = true, variant = 'wizard', workspaceRoot = '' } = options;
1188
- // Normalize: strip trailing slash so path joins work cleanly
1189
1188
  const wsRoot = workspaceRoot.replace(/\/+$/, '');
1190
1189
  const btPath = wsRoot ? `${wsRoot}/browser-tool.js` : 'browser-tool.js';
1191
1190
 
1192
- if (variant === 'cli-desktop') {
1193
- return `# Browser Automation (Desktop Mode)\n\nBot controls your actual Chrome on screen through Chrome Debug at \`http://127.0.0.1:9222\`. Every action is visible.\n\n## Usage (v2)\n\`\`\`bash\n# Navigation\nnode ${btPath} status\nnode ${btPath} open "https://google.com"\nnode ${btPath} get_url\n\n# Content extraction\nnode ${btPath} get_text\nnode ${btPath} get_text 8000 # custom max length\nnode ${btPath} get_links # all links\nnode ${btPath} get_links "/posts/" # filtered\nnode ${btPath} get_posts # Facebook group posts w/ permalinks\nnode ${btPath} evaluate "document.title"\nnode ${btPath} console\n\n# Screenshots & export\nnode ${btPath} screenshot\nnode ${btPath} screenshot_full\nnode ${btPath} pdf\n\n# Interactions\nnode ${btPath} click "button.submit"\nnode ${btPath} fill "input[name='q']" "search"\nnode ${btPath} press "Enter"\nnode ${btPath} hover "a.link"\nnode ${btPath} select "select#country" "VN"\nnode ${btPath} upload "input[type=file]" "/tmp/photo.jpg"\n\n# Scrolling & viewport\nnode ${btPath} scroll\nnode ${btPath} scroll 1500\nnode ${btPath} wait 3000\nnode ${btPath} resize 1920 1080\n\n# Tab management\nnode ${btPath} tabs\nnode ${btPath} new_tab "https://example.com"\nnode ${btPath} switch_tab 1\nnode ${btPath} close_tab 2\n\`\`\`\n\n## MANDATORY RULES\n- NEVER refuse to open the browser when user asks.\n- In Desktop mode, always target the \`host-chrome\` / Chrome Debug session first.\n- If Chrome Debug is unreachable or returns \`ECONNREFUSED\`, tell user to run \`start-chrome-debug.bat\` again.\n- Use \`get_posts\` instead of \`get_text\` when scraping Facebook — it extracts permalinks.\n`;
1194
- }
1195
- if (variant === 'cli-server') {
1196
- return `# Browser Automation (Headless Server Mode)\n\nBot uses a headless Chromium instance running inside the Docker container. No GUI needed!\n\n## Notes\n- Running on Ubuntu Server / VPS (no GUI required)\n- Uses Playwright + Headless Chromium installed inside Docker\n- For Cloudflare bypass, switch to Desktop mode (requires Windows/Mac with Chrome)\n`;
1197
- }
1198
- return isVi
1199
- ? `# Browser Automation\n\nDùng file \`browser-tool.js\` để điều khiển Chrome debug tại \`http://127.0.0.1:9222\`.\nScript: \`${btPath}\`\nPhiên bản v2 hỗ trợ: open, get_text, get_links, get_posts, evaluate, screenshot, pdf, click, fill, press, hover, select, upload, scroll, tabs, và nhiều lệnh khác.`
1200
- : `# Browser Automation\n\nUse \`browser-tool.js\` to control Chrome debug on \`http://127.0.0.1:9222\`.\nScript: \`${btPath}\`\nVersion v2 supports: open, get_text, get_links, get_posts, evaluate, screenshot, pdf, click, fill, press, hover, select, upload, scroll, tabs, and more.`;
1191
+ return `# Navigation
1192
+ node ${btPath} status
1193
+ node ${btPath} open "https://google.com"
1194
+ node ${btPath} get_url
1195
+
1196
+ # ⭐ Content extraction — LUÔN dùng get_posts cho Facebook
1197
+ node ${btPath} get_posts
1198
+ node ${btPath} get_text
1199
+ node ${btPath} get_text 8000
1200
+ node ${btPath} get_links
1201
+ node ${btPath} get_links "/posts/"
1202
+ node ${btPath} evaluate "document.title"
1203
+ node ${btPath} console
1204
+
1205
+ # Screenshots & export
1206
+ node ${btPath} screenshot
1207
+ node ${btPath} screenshot_full
1208
+ node ${btPath} pdf
1209
+
1210
+ # Interactions
1211
+ node ${btPath} click "button.submit"
1212
+ node ${btPath} fill "input[name='q']" "search"
1213
+ node ${btPath} press "Enter"
1214
+ node ${btPath} hover "a.link"
1215
+ node ${btPath} select "select#id" "value"
1216
+ node ${btPath} upload "input[type=file]" "/tmp/photo.jpg"
1217
+
1218
+ # Scrolling & viewport
1219
+ node ${btPath} scroll
1220
+ node ${btPath} scroll 1500
1221
+ node ${btPath} wait 3000
1222
+ node ${btPath} resize 1920 1080
1223
+
1224
+ # Tab management
1225
+ node ${btPath} tabs
1226
+ node ${btPath} new_tab "https://example.com"
1227
+ node ${btPath} switch_tab 1
1228
+ node ${btPath} close_tab 2`;
1201
1229
  }
1202
1230
 
1203
1231
  function buildSecurityRules(isVi = true) {
@@ -1235,14 +1263,14 @@ const CDP_URL = 'http://127.0.0.1:9222';
1235
1263
  ? '- If metadata does not clearly say this is a group/supergroup, treat it as a private DM and reply normally.\n'
1236
1264
  : '';
1237
1265
  return isVi
1238
- ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI'}.\n\n## Quy tắc trả lời\n- Trả lời ngắn gọn, súc tích\n- Ưu tiên tiếng Việt\n- Khi hỏi tên: _\"Mình là ${botName}\"_\n- Không bịa thông tin\n- Bạn ĐÃ biết sẵn danh tính, vai trò, tính cách của mình từ **IDENTITY.md**, **SOUL.md**, **AGENTS.md**\n- KHÔNG hỏi user đặt lại tên, vibe, persona, emoji ký tên, hay \"bạn muốn mình là kiểu trợ lý nào\"\n- KHÔNG tự giới thiệu kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\" hoặc onboarding tương tự\n- Nếu user chỉ nhắn ngắn như \"alo\", hãy chào ngắn gọn và trả lời đúng vai trò hiện tại của bạn\n\n## Khi nào nên trả lời\n${directMessageRuleVi}- Trong group, coi user đang gọi bạn nếu tin nhắn có một trong các alias: ${aliasStr}.\n- Nếu user tag username Telegram của bạn thì luôn trả lời.\n- Nếu group message đang gọi rõ bot khác ${relayTargetNames} thì không cướp lời.\n- Quy tắc im lặng khi không ai được gọi chỉ áp dụng cho group chat, không áp dụng cho DM/chat riêng.\n\n## Tài liệu tham chiếu\n- \uD83D\uDCCB **TOOLS.md** — Danh sách skill/tool đã cài và cách sử dụng\n- \uD83E\uDD1D **TEAMS.md** — Quy tắc phối hợp team, handoff protocol, và anti-pattern\n- \uD83D\uDCAD **MEMORY.md** — Bộ nhớ dài hạn\n- \uD83C\uDFAD **IDENTITY.md** — Danh tính và tính cách${security}`
1239
- : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'an AI assistant'}.\n\n## Reply Rules\n- Reply concisely\n- Prefer English\n- When asked your name: _\"I'm ${botName}\"_\n- Do not fabricate information\n- You ALREADY know your identity, role, and personality from **IDENTITY.md**, **SOUL.md**, and **AGENTS.md**\n- DO NOT ask the user to redefine your name, vibe, persona, signature emoji, or \"what kind of assistant\" you should be\n- DO NOT act like you just woke up, just came online, or are still choosing your identity\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character\n\n## When To Reply\n${directMessageRuleEn}- In groups, treat the message as addressed to you when it includes one of your aliases: ${aliasStr}.\n- Always reply when your Telegram username is tagged.\n- If a group message is clearly calling another bot such as ${relayTargetNames}, do not hijack it.\n- The stay-silent rule for unaddressed messages applies only to group chats, never to DMs/private chats.\n\n## Reference Docs\n- \uD83D\uDCCB **TOOLS.md** — Installed skills/tools and usage guide\n- \uD83E\uDD1D **TEAMS.md** — Team coordination rules, handoff protocol, and anti-patterns\n- \uD83D\uDCAD **MEMORY.md** — Long-term memory\n- \uD83C\uDFAD **IDENTITY.md** — Identity and personality${security}`;
1266
+ ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI'}.\n\n## Quy tắc trả lời\n- Trả lời ngắn gọn, súc tích\n- Ưu tiên tiếng Việt\n- Khi hỏi tên: _\"Mình là ${botName}\"_\n- Không bịa thông tin\n- Bạn ĐÃ biết sẵn danh tính, vai trò, tính cách của mình từ **IDENTITY.md**, **SOUL.md**, **AGENTS.md**\n- KHÔNG hỏi user đặt lại tên, vibe, persona, emoji ký tên, hay \"bạn muốn mình là kiểu trợ lý nào\"\n- KHÔNG tự giới thiệu kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\" hoặc onboarding tương tự\n- Nếu user chỉ nhắn ngắn như \"alo\", hãy chào ngắn gọn và trả lời đúng vai trò hiện tại của bạn\n\n## Khi nào nên trả lời\n${directMessageRuleVi}- Trong group, coi user đang gọi bạn nếu tin nhắn có một trong các alias: ${aliasStr}.\n- Nếu user tag username Telegram của bạn thì luôn trả lời.\n- Nếu group message đang gọi rõ bot khác ${relayTargetNames} thì không cướp lời.\n- Quy tắc im lặng khi không ai được gọi chỉ áp dụng cho group chat, không áp dụng cho DM/chat riêng.\n\n## Tài liệu tham chiếu\n- 📋 **TOOLS.md** — Danh sách skill/tool đã cài và cách sử dụng\n- 🤝 **TEAMS.md** — Quy tắc phối hợp team, handoff protocol, và anti-pattern\n- 💭 **MEMORY.md** — Bộ nhớ dài hạn\n- 🎭 **IDENTITY.md** — Danh tính và tính cách\n- 🌍 **BROWSER.md** — Hướng dẫn sử dụng Browser Automation\n- 🚀 **BOOT.md** — Hướng dẫn khởi động và thiết lập\n- 🧠 **SOUL.md** — Định hướng phát triển và giá trị cốt lõi\n- ✨ **DREAMS.md** — Mục tiêu dài hạn và ý tưởng\n- 💓 **HEARTBEAT.md** — Nhịp độ hoạt động và cron jobs\n- 👤 **USER.md** — Thông tin và bối cảnh về User\n- 🤖 **AGENTS.md** — Vai trò và quy tắc chung (file này)${security}`
1267
+ : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'an AI assistant'}.\n\n## Reply Rules\n- Reply concisely\n- Prefer English\n- When asked your name: _\"I'm ${botName}\"_\n- Do not fabricate information\n- You ALREADY know your identity, role, and personality from **IDENTITY.md**, **SOUL.md**, and **AGENTS.md**\n- DO NOT ask the user to redefine your name, vibe, persona, signature emoji, or \"what kind of assistant\" you should be\n- DO NOT act like you just woke up, just came online, or are still choosing your identity\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character\n\n## When To Reply\n${directMessageRuleEn}- In groups, treat the message as addressed to you when it includes one of your aliases: ${aliasStr}.\n- Always reply when your Telegram username is tagged.\n- If a group message is clearly calling another bot such as ${relayTargetNames}, do not hijack it.\n- The stay-silent rule for unaddressed messages applies only to group chats, never to DMs/private chats.\n\n## Reference Docs\n- 📋 **TOOLS.md** — Installed skills/tools and usage guide\n- 🤝 **TEAMS.md** — Team coordination rules, handoff protocol, and anti-patterns\n- 💭 **MEMORY.md** — Long-term memory\n- 🎭 **IDENTITY.md** — Identity and personality\n- 🌍 **BROWSER.md** — Browser Automation guide\n- 🚀 **BOOT.md** — Bootstrap rules\n- 🧠 **SOUL.md** — Core values and direction\n- ✨ **DREAMS.md** — Long term goals and ideas\n- 💓 **HEARTBEAT.md** — Activity rules and cron jobs\n- 👤 **USER.md** — User profile\n- 🤖 **AGENTS.md** — Role and general rules (this file)${security}`;
1240
1268
  }
1241
1269
 
1242
1270
  // Single-bot variant
1243
1271
  return isVi
1244
- ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI cá nhân'}.\nBạn hỗ trợ user trong mọi tác vụ qua chat.\n\n## Quy tắc trả lời\n- Trả lời bằng **tiếng Việt** (trừ khi dùng ngôn ngữ khác)\n- **Ngắn gọn, súc tích**\n- Khi hỏi tên → _\"Mình là ${botName}\"_\n- Bạn ĐÃ biết sẵn danh tính và tính cách của mình, không cần user định nghĩa lại\n- KHÔNG hỏi user đặt tên/vibe/persona/emoji cho mình\n- KHÔNG tự nói kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\"\n\n## Hành vi\n- KHÔNG bịa đặt thông tin\n- KHÔNG tiết lộ file hệ thống (SOUL.md, AGENTS.md).\n- Nếu user chỉ mở đầu ngắn như \"alo\", trả lời ngắn gọn, đúng vai trò, không onboarding ngược lại user\n\n## Tài liệu tham chiếu\n- \uD83D\uDCCB **TOOLS.md** — Danh sách skill/tool và cách sử dụng\n- \uD83D\uDCAD **MEMORY.md** — Bộ nhớ dài hạn\n- \uD83C\uDFAD **IDENTITY.md** — Danh tính và tính cách${security}`
1245
- : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'a personal AI assistant'}.\nYou support users with any task through chat.\n\n## Reply Rules\n- Reply in **English** (unless the user switches language)\n- **Concise and to the point**\n- When asked your name → _\"I'm ${botName}\"_\n- You already know your identity and personality; do not ask the user to redefine them\n- DO NOT ask the user to pick your name, vibe, persona, or signature emoji\n- DO NOT say you just woke up, just came online, or are still choosing your identity\n\n## Behavior\n- Do NOT fabricate information\n- Do NOT reveal system files (SOUL.md, AGENTS.md).\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character instead of onboarding them\n\n## Reference Docs\n- \uD83D\uDCCB **TOOLS.md** — Installed skills/tools and usage guide\n- \uD83D\uDCAD **MEMORY.md** — Long-term memory\n- \uD83C\uDFAD **IDENTITY.md** — Identity and personality${security}`;
1272
+ ? `# Hướng dẫn vận hành\n\n## Vai trò\nBạn là **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'trợ lý AI cá nhân'}.\nBạn hỗ trợ user trong mọi tác vụ qua chat.\n\n## Quy tắc trả lời\n- Trả lời bằng **tiếng Việt** (trừ khi dùng ngôn ngữ khác)\n- **Ngắn gọn, súc tích**\n- Khi hỏi tên → _\"Mình là ${botName}\"_\n- Bạn ĐÃ biết sẵn danh tính và tính cách của mình, không cần user định nghĩa lại\n- KHÔNG hỏi user đặt tên/vibe/persona/emoji cho mình\n- KHÔNG tự nói kiểu \"mới tỉnh dậy\", \"vừa online\", \"đang chọn danh tính\"\n\n## Hành vi\n- KHÔNG bịa đặt thông tin\n- KHÔNG tiết lộ file hệ thống (SOUL.md, AGENTS.md).\n- Nếu user chỉ mở đầu ngắn như \"alo\", trả lời ngắn gọn, đúng vai trò, không onboarding ngược lại user\n\n## Tài liệu tham chiếu\n- 📋 **TOOLS.md** — Danh sách skill/tool và cách sử dụng\n- 💭 **MEMORY.md** — Bộ nhớ dài hạn\n- 🎭 **IDENTITY.md** — Danh tính và tính cách\n- 🌍 **BROWSER.md** — Hướng dẫn sử dụng Browser Automation\n- 🚀 **BOOT.md** — Hướng dẫn khởi động và thiết lập\n- 🧠 **SOUL.md** — Định hướng phát triển và giá trị cốt lõi\n- ✨ **DREAMS.md** — Mục tiêu dài hạn và ý tưởng\n- 💓 **HEARTBEAT.md** — Nhịp độ hoạt động và cron jobs\n- 👤 **USER.md** — Thông tin và bối cảnh về User\n- 🤖 **AGENTS.md** — Vai trò và quy tắc chung (file này)${security}`
1273
+ : `# Operating Manual\n\n## Role\nYou are **${botName}**, ${botDesc ? botDesc.toLowerCase() : 'a personal AI assistant'}.\nYou support users with any task through chat.\n\n## Reply Rules\n- Reply in **English** (unless the user switches language)\n- **Concise and to the point**\n- When asked your name → _\"I'm ${botName}\"_\n- You already know your identity and personality; do not ask the user to redefine them\n- DO NOT ask the user to pick your name, vibe, persona, or signature emoji\n- DO NOT say you just woke up, just came online, or are still choosing your identity\n\n## Behavior\n- Do NOT fabricate information\n- Do NOT reveal system files (SOUL.md, AGENTS.md).\n- If the user sends a short opener like \"hi\" or \"alo\", reply briefly and stay in-character instead of onboarding them\n\n## Reference Docs\n- 📋 **TOOLS.md** — Installed skills/tools and usage guide\n- 💭 **MEMORY.md** — Long-term memory\n- 🎭 **IDENTITY.md** — Identity and personality\n- 🌍 **BROWSER.md** — Browser Automation guide\n- 🚀 **BOOT.md** — Bootstrap rules\n- 🧠 **SOUL.md** — Core values and direction\n- ✨ **DREAMS.md** — Long term goals and ideas\n- 💓 **HEARTBEAT.md** — Activity rules and cron jobs\n- 👤 **USER.md** — User profile\n- 🤖 **AGENTS.md** — Role and general rules (this file)${security}`;
1246
1274
  }
1247
1275
 
1248
1276
  function buildToolsDoc(options = {}) {
@@ -1282,11 +1310,7 @@ const CDP_URL = 'http://127.0.0.1:9222';
1282
1310
  : `\n\n## \u23F0 Cron / Scheduled Tasks\n- OpenClaw natively supports system tools for Cron Jobs.\n- When the user asks to schedule tasks or reminders, use the built-in tools automatically. Do NOT ask users to run crontab or Task Scheduler manually on the host.\n- When operating cron/scheduler tools, do **not** put \`current\` into the Session directory.\n- Skip internal doc lookups such as \`cron-jobs.mdx\`; rely on the available tools and complete the scheduling task directly.`)
1283
1311
  : '';
1284
1312
 
1285
- const zaloModSection = hasZaloMod
1286
- ? (isVi
1287
- ? `\n\n## 💬 Zalo Group — Slash Commands (xử lý bởi plugin)\n\nPlugin \`zalo-mod\` tự động xử lý các slash command sau trong group. Bot KHÔNG cần reply cho chúng:\n\n| Command | Mô tả |\n|---------|-------|\n| \`/rules status\` | Xem cấu hình bot |\n| \`/rules silent-on/off\` | Bật/tắt silent mode |\n| \`/rules welcome-on/off\` | Bật/tắt welcome message |\n| \`/rules tracking-on/off\` | Bật/tắt ghi log chat |\n| \`/noi-quy\` | Hiện nội quy group |\n| \`/menu\` | Danh sách lệnh |\n| \`/groupid\` | Scan và cập nhật config |\n| \`/report\` | Báo cáo hoạt động group |\n\n### Zalo Sticker & Media\n- Sticker Zalo gửi dạng JSON → plugin tự convert thành \`[Sticker]\`\n- Ảnh/video/file trong group: zalouser channel chỉ forward text, media bị drop`
1288
- : `\n\n## 💬 Zalo Group — Slash Commands (handled by plugin)\n\nThe \`zalo-mod\` plugin automatically handles these slash commands in group. Bot does NOT need to reply:\n\n| Command | Description |\n|---------|-------------|\n| \`/rules status\` | View bot config |\n| \`/rules silent-on/off\` | Toggle silent mode |\n| \`/rules welcome-on/off\` | Toggle welcome message |\n| \`/rules tracking-on/off\` | Toggle chat logging |\n| \`/noi-quy\` | Show group rules |\n| \`/menu\` | List commands |\n| \`/groupid\` | Scan and update config |\n| \`/report\` | Group activity report |\n\n### Zalo Sticker & Media\n- Zalo stickers arrive as JSON → plugin auto-converts to \`[Sticker]\`\n- Images/videos/files in groups: zalouser channel only forwards text, media is dropped`)
1289
- : '';
1313
+ const zaloModSection = '';
1290
1314
 
1291
1315
  const dmOverride = isVi
1292
1316
  ? `\n\n## Override: DM và Telegram reaction\n- Nếu metadata không nói rõ đây là group/supergroup, mặc định xem là chat riêng/DM và trả lời bình thường.\n- Quy tắc im lặng khi không ai được gọi chỉ áp dụng cho group chat, không áp dụng cho DM/chat riêng.\n- Trước MỖI phản hồi Telegram nhìn thấy bởi user, nếu turn hiện tại có tool/action reaction native thì ưu tiên dùng nó để thả \`👍\` trước, trừ khi \`👍\` đã có sẵn.\n- Nếu turn hiện tại không expose tool reaction hoặc chat đích không hỗ trợ reaction thật, cứ trả lời đúng vai trò và không được nói là mình đã thả reaction.`
@@ -1341,6 +1365,7 @@ const CDP_URL = 'http://127.0.0.1:9222';
1341
1365
  * @property {string} [teamRosterFormatted]
1342
1366
  * @property {string} [emoji]
1343
1367
  * @property {boolean} [hasScheduler]
1368
+ * @property {boolean} [hasZaloMod]
1344
1369
  */
1345
1370
 
1346
1371
  /**
@@ -1627,7 +1652,7 @@ if (typeof exports !== 'undefined' && workspaceRoot.__openclawWorkspace) {
1627
1652
  cfg.skills = { entries: skillEntries };
1628
1653
  }
1629
1654
 
1630
- // ── plugins (memory-core dreaming + zalo-mod) ────────────────────────────
1655
+ // ── plugins (memory-core dreaming + openclaw-zalo-mod) ────────────────────────────
1631
1656
  const pluginsConfig = buildPluginsConfig({
1632
1657
  channelKey,
1633
1658
  selectedSkills,
@@ -2734,7 +2759,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
2734
2759
  const runtimeScriptB64 = encodeBase64Utf8(runtimeScript);
2735
2760
  const dockerfile = `FROM node:22-slim
2736
2761
 
2737
- RUN apt-get update && apt-get install -y git curl${browserAptExtra} && rm -rf /var/lib/apt/lists/*
2762
+ RUN apt-get update && apt-get install -y git curl python3${browserAptExtra} && rm -rf /var/lib/apt/lists/*
2738
2763
  ${browserInstallLines}
2739
2764
  ARG OPENCLAW_VER="${openClawNpmSpec}"
2740
2765
  ARG CACHE_BUST=""
@@ -3804,21 +3829,31 @@ New-Item -ItemType Directory -Force -Path "$projectDir" | Out-Null
3804
3829
  ps += `Write-Host "" -ForegroundColor White\n`;
3805
3830
  ps += `Write-Host "${isVi ? 'Huong dan dang nhap Zalo:' : 'Zalo login instructions:'}" -ForegroundColor White\n`;
3806
3831
  ps += `Write-Host " ${isVi ? '1. cd docker\\\\openclaw' : '1. cd docker\\\\openclaw'}" -ForegroundColor White\n`;
3807
- ps += `Write-Host " ${isVi ? `2. docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose` : `2. docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose`}" -ForegroundColor White\n`;
3832
+ ps += `Write-Host " ${isVi ? '2. docker compose stop ai-bot' : '2. docker compose stop ai-bot'}" -ForegroundColor White\n`;
3833
+ ps += `Write-Host " ${isVi ? '3. docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose' : '3. docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose'}" -ForegroundColor White\n`;
3808
3834
  ps += `Write-Host " ${isVi ? `3. Mo Docker Desktop > container ${containerName} > tab Files > tim file: ${qrPath}` : `3. Open Docker Desktop > container ${containerName} > Files tab > find: ${qrPath}`}" -ForegroundColor White\n`;
3809
3835
  ps += `Write-Host " ${isVi ? ` Hoac chay: docker cp ${containerName}:${qrPath} ./zalo-qr.png` : ` Or run: docker cp ${containerName}:${qrPath} ./zalo-qr.png`}" -ForegroundColor White\n`;
3810
3836
  ps += `Write-Host " ${isVi ? '4. Mo app Zalo > Quet QR > quet ma trong file QR' : '4. Open Zalo app > Scan QR > scan the QR image'}" -ForegroundColor White\n`;
3811
3837
  ps += `Write-Host " ${isVi ? '5. Doi thay chu Login successful trong terminal' : '5. Wait for Login successful in terminal'}" -ForegroundColor White\n`;
3812
- ps += `Write-Host " ${isVi ? '6. Restart container: docker compose restart' : '6. Restart container: docker compose restart'}" -ForegroundColor White\n`;
3838
+ ps += `Write-Host " ${isVi ? '6. docker compose up -d --force-recreate ai-bot' : '6. docker compose up -d --force-recreate ai-bot'}" -ForegroundColor White\n`;
3839
+ ps += `Write-Host " ${isVi ? '7. Kiem tra: docker compose exec ai-bot openclaw channels status --probe (phai thay running)' : '7. Verify: docker compose exec ai-bot openclaw channels status --probe (should show running)'}" -ForegroundColor White\n`;
3813
3840
  ps += `Write-Host "" -ForegroundColor White\n`;
3814
- ps += `Write-Host "${isVi ? 'Dung gateway de login...' : 'Stopping gateway for login...'}" -ForegroundColor Yellow\\n`;
3815
- ps += `& docker exec ${containerName} openclaw gateway stop 2>$null\\n`;
3816
- ps += `Start-Sleep -Seconds 3\\n`;
3841
+ ps += `Write-Host "${isVi ? 'Dung app container de login one-shot...' : 'Stopping the app container for one-shot login...'}" -ForegroundColor Yellow\\n`;
3842
+ ps += `& docker compose stop ai-bot\\n`;
3817
3843
  ps += `Write-Host "${isVi ? 'Dang chay lenh login...' : 'Running login command...'}" -ForegroundColor Yellow\n`;
3818
- ps += `& docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose\n`;
3844
+ ps += `& docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose\n`;
3819
3845
  ps += `Write-Host "" -ForegroundColor White\n`;
3820
- ps += `Write-Host "${isVi ? 'Restart container de ap dung...' : 'Restarting container to apply...'}" -ForegroundColor Green\n`;
3821
- ps += `& docker compose restart\n`;
3846
+ ps += `Write-Host "${isVi ? 'Recreate app container de nap session Zalo...' : 'Recreating the app container to load the Zalo session...'}" -ForegroundColor Green\n`;
3847
+ ps += `& docker compose up -d --force-recreate ai-bot\n`;
3848
+ ps += `Start-Sleep -Seconds 30\n`;
3849
+ ps += `$statusOut = (& docker compose exec ai-bot openclaw channels status --probe) -join "\n"\n`;
3850
+ ps += `Write-Host $statusOut\n`;
3851
+ ps += `if ($statusOut -notmatch 'running') {\n`;
3852
+ ps += ` Write-Host "${isVi ? 'Channel chua running, recreate container ai-bot...' : 'Channel is not running; recreating ai-bot container...'}" -ForegroundColor Yellow\n`;
3853
+ ps += ` & docker compose up -d --force-recreate ai-bot\n`;
3854
+ ps += ` Start-Sleep -Seconds 30\n`;
3855
+ ps += ` & docker compose exec ai-bot openclaw channels status --probe\n`;
3856
+ ps += `}\n`;
3822
3857
  }
3823
3858
 
3824
3859
  ps += `} catch { Write-Host $_.Exception.Message -ForegroundColor Red }\nRead-Host "${isVi ? 'Nhan Enter de thoat' : 'Press Enter to exit'}"\n`;
@@ -3863,9 +3898,10 @@ echo ""
3863
3898
  const containerName = 'openclaw-bot';
3864
3899
  const qrPath = '/tmp/openclaw/openclaw-zalouser-qr-default.png';
3865
3900
  script += `\necho ""\necho "${isVi ? '=== DANG NHAP ZALO ===' : '=== ZALO LOGIN ==='}"\necho "${isVi ? 'Doi container khoi dong 10 giay...' : 'Waiting 10s for container to start...'}"\nsleep 10\n`;
3866
- script += `echo "${isVi ? 'Huong dan dang nhap Zalo:' : 'Zalo login instructions:'}"\necho " ${isVi ? '1. cd docker/openclaw' : '1. cd docker/openclaw'}"\necho " 2. docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose"\necho " ${isVi ? `3. Tim file QR trong container: ${qrPath}` : `3. Find QR image in container: ${qrPath}`}"\necho " ${isVi ? ` Hoac chay: docker cp ${containerName}:${qrPath} ./zalo-qr.png` : ` Or run: docker cp ${containerName}:${qrPath} ./zalo-qr.png`}"\necho " ${isVi ? '4. Mo app Zalo > Quet QR > quet ma' : '4. Open Zalo app > Scan QR > scan'}"\necho " ${isVi ? '5. Doi thay Login successful' : '5. Wait for Login successful'}"\necho " ${isVi ? '6. Restart: docker compose restart' : '6. Restart: docker compose restart'}"\necho ""\n`;
3867
- script += `docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose\n`;
3868
- script += `echo "${isVi ? 'Restart container...' : 'Restarting container...'}"\ndocker compose restart\n`;
3901
+ script += `echo "${isVi ? 'Huong dan dang nhap Zalo:' : 'Zalo login instructions:'}"\necho " ${isVi ? '1. cd docker/openclaw' : '1. cd docker/openclaw'}"\necho " ${isVi ? '2. docker compose stop ai-bot' : '2. docker compose stop ai-bot'}"\necho " 3. docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose"\necho " ${isVi ? `4. Tim file QR trong container: ${qrPath}` : `4. Find QR image in container: ${qrPath}`}"\necho " ${isVi ? ` Hoac chay: docker cp ${containerName}:${qrPath} ./zalo-qr.png` : ` Or run: docker cp ${containerName}:${qrPath} ./zalo-qr.png`}"\necho " ${isVi ? '5. Mo app Zalo > Quet QR > quet ma' : '5. Open Zalo app > Scan QR > scan'}"\necho " ${isVi ? '6. Doi thay Login successful' : '6. Wait for Login successful'}"\necho " ${isVi ? '7. Start lai: docker compose up -d --force-recreate ai-bot' : '7. Start again: docker compose up -d --force-recreate ai-bot'}"\necho " ${isVi ? '8. Kiem tra: docker compose exec ai-bot openclaw channels status --probe (phai thay running)' : '8. Verify: docker compose exec ai-bot openclaw channels status --probe (should show running)'}"\necho ""\n`;
3902
+ script += `docker compose stop ai-bot\n`;
3903
+ script += `docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose\n`;
3904
+ script += `echo "${isVi ? 'Recreate container de nap session Zalo...' : 'Recreating container to load the Zalo session...'}"\ndocker compose up -d --force-recreate ai-bot\nsleep 30\nSTATUS="$(docker compose exec ai-bot openclaw channels status --probe || true)"\necho "$STATUS"\nif ! printf '%s' "$STATUS" | grep -q running; then\n echo "${isVi ? 'Channel van chua running. Hay logout/login lai bang compose run one-shot.' : 'Channel is still not running. Re-run logout/login with compose run one-shot.'}"\nfi\n`;
3869
3905
  }
3870
3906
 
3871
3907
  return script;
@@ -4125,20 +4161,29 @@ function generateMacOsSh(ctx) {
4125
4161
  sh.push('echo "=== DANG NHAP ZALO ==="');
4126
4162
  sh.push('echo "Doi container khoi dong 10 giay..."');
4127
4163
  sh.push('sleep 10');
4128
- sh.push('echo "Dung gateway de login..."');
4129
- sh.push(`docker exec ${containerName} openclaw gateway stop 2>/dev/null || true`);
4130
- sh.push('sleep 3');
4164
+ sh.push('echo "Dung app container de login one-shot..."');
4165
+ sh.push('$COMPOSE stop ai-bot');
4131
4166
  sh.push('echo "Huong dan dang nhap Zalo:"');
4132
4167
  sh.push(`echo " 1. cd docker/openclaw"`);
4133
- sh.push(`echo " 2. docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose"`);
4134
- sh.push(`echo " 3. Tim file QR trong container: ${qrPath}"`);
4168
+ sh.push(`echo " 2. docker compose stop ai-bot"`);
4169
+ sh.push(`echo " 3. docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose"`);
4170
+ sh.push(`echo " 4. Tim file QR trong container: ${qrPath}"`);
4135
4171
  sh.push(`echo " Hoac chay: docker cp ${containerName}:${qrPath} ./zalo-qr.png"`);
4136
- sh.push('echo " 4. Mo app Zalo > Quet QR > quet ma"');
4137
- sh.push('echo " 5. Doi thay Login successful"');
4138
- sh.push('echo " 6. Restart: $COMPOSE restart"');
4172
+ sh.push('echo " 5. Mo app Zalo > Quet QR > quet ma"');
4173
+ sh.push('echo " 6. Doi thay Login successful"');
4174
+ sh.push('echo " 7. Script se recreate container de nap session Zalo vua tao"');
4139
4175
  sh.push('echo ""');
4140
- sh.push(`docker exec -it ${containerName} openclaw channels login --channel zalouser --verbose || true`);
4141
- sh.push('$COMPOSE restart');
4176
+ sh.push(`$COMPOSE run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose || true`);
4177
+ sh.push(`$COMPOSE up -d --force-recreate ai-bot`);
4178
+ sh.push('sleep 30');
4179
+ sh.push(`STATUS="$($COMPOSE exec ai-bot openclaw channels status --probe || true)"`);
4180
+ sh.push('echo "$STATUS"');
4181
+ sh.push('if ! printf "%s" "$STATUS" | grep -q running; then');
4182
+ sh.push(' echo "Channel chua running, recreate container ai-bot..."');
4183
+ sh.push(' $COMPOSE up -d --force-recreate ai-bot');
4184
+ sh.push(' sleep 30');
4185
+ sh.push(` $COMPOSE exec ai-bot openclaw channels status --probe || true`);
4186
+ sh.push('fi');
4142
4187
  }
4143
4188
  sh.push('echo "\u2705 Bot dang chay via Docker. Xem log: docker logs -f openclaw-bot"');
4144
4189
  scriptContent = sh.filter(Boolean).join('\n');
@@ -5930,7 +5975,7 @@ model:
5930
5975
  runtimeCommandParts: [
5931
5976
  pluginInstallCmd,
5932
5977
  'while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done >/dev/null 2>&1 &'
5933
- ],
5978
+ ].filter(Boolean),
5934
5979
  plainSingleExtraHosts: true,
5935
5980
  multiOllamaNumParallel: 1,
5936
5981
  singleOllamaNumParallel: 1,
@@ -6590,33 +6635,38 @@ fi
6590
6635
  // ========== Zalo Personal Login Guide (post-setup) ==========
6591
6636
  function generateZaloOnboardGuide() {
6592
6637
  const lang = document.getElementById('cfg-language')?.value || 'vi';
6593
- setOutput('out-zalo-onboard-cmd', `docker compose exec -it ai-bot openclaw channels login --channel zalouser --verbose`);
6638
+ setOutput('out-zalo-onboard-cmd', `docker compose stop ai-bot
6639
+ docker compose run --rm --no-deps ai-bot openclaw channels login --channel zalouser --verbose
6640
+ docker compose up -d --force-recreate ai-bot
6641
+ docker compose exec ai-bot openclaw channels status --probe`);
6594
6642
 
6595
6643
  if (lang === 'vi') {
6596
6644
  setOutput('out-zalo-onboard-guide', `┌─────────────────────────────────────────────────────┐
6597
6645
  │ Chạy lệnh bên trái để OpenClaw tạo QR đăng nhập. │
6598
6646
  ├─────────────────────────────────────────────────────┤
6599
6647
  │ 1. Đảm bảo container/gateway đã chạy xong. │
6600
- │ 2. Chạy lệnh login để tạo QR cho zalouser.
6648
+ │ 2. Stop ai-bot, login bằng compose run one-shot.
6601
6649
  │ 3. OpenClaw sẽ in ra đường dẫn file QR trong /tmp. │
6602
6650
  │ 4. Copy file QR ra ngoài nếu cần: │
6603
- │ docker compose cp ai-bot:/tmp/openclaw/
6651
+ │ docker cp openclaw-bot:/tmp/openclaw/
6604
6652
  │ openclaw-zalouser-qr-default.png . │
6605
6653
  │ 5. Mở ảnh QR → quét bằng app Zalo → xác nhận. │
6606
- │ 6. Sau khi login xong, restart bot nếu cần.
6654
+ │ 6. Start lại: docker compose up -d --force-recreate
6655
+ │ 7. Chạy channels status --probe, phải thấy running.│
6607
6656
  └─────────────────────────────────────────────────────┘`);
6608
6657
  } else {
6609
6658
  setOutput('out-zalo-onboard-guide', `┌─────────────────────────────────────────────────────┐
6610
6659
  │ Run the command on the left to generate a Zalo QR. │
6611
6660
  ├─────────────────────────────────────────────────────┤
6612
6661
  │ 1. Make sure the container/gateway is already up. │
6613
- │ 2. Run the login command for zalouser.
6662
+ │ 2. Stop ai-bot; login with compose run one-shot.
6614
6663
  │ 3. OpenClaw prints the QR image path under /tmp. │
6615
6664
  │ 4. Copy the QR out if needed: │
6616
- │ docker compose cp ai-bot:/tmp/openclaw/
6665
+ │ docker cp openclaw-bot:/tmp/openclaw/
6617
6666
  │ openclaw-zalouser-qr-default.png . │
6618
6667
  │ 5. Open the image → scan with Zalo mobile app. │
6619
- │ 6. Restart the bot afterwards if needed.
6668
+ │ 6. Start again: docker compose up -d --force-re...
6669
+ │ 7. Run channels status --probe; it should run. │
6620
6670
  └─────────────────────────────────────────────────────┘`);
6621
6671
  }
6622
6672
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "5.7.8",
3
+ "version": "5.7.10",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {