create-openclaw-bot 4.0.5 → 4.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [4.0.7] — 2026-03-31
6
+
7
+ ### ✨ 9Router Stability & Ollama Cloud
8
+ - **Stable 9Router Integration (Zero Config)**: The 9Router proxy is now fully stabilized and runs securely within the Docker network via `sk-no-key`. External configuration (API keys, manual routing) is removed from `.env` and elegantly managed via the [9Router Dashboard](http://localhost:20128/dashboard).
9
+ - **Expanded Model Connectivity**: Added comprehensive support for Ollama Cloud models (*Qwen 3.5, GLM-5, MiniMax, GPT-OSS*), Kiro Haiku, Qwen Flash, and extended iFlow free tiers.
10
+ - **Smart Routing Injection**: The configuration dynamically injects the `smart-route` combination to balance logic workload across Codex, Claude Code, Gemini, and iFlow.
11
+
12
+ ### 🧹 Clean Workspace & Cross-Platform Auto-Setup
13
+ - **Zero-Clutter Generation**: Eliminated all redundant `.env.example` and static `docker-compose` sample templates. The `.bat` / CLI wizard now dynamically constructs the precise Docker environment necessary.
14
+ - **Cross-Platform Auto Browser**: Added a native macOS/Linux `start-chrome-debug.sh` boot script alongside the Windows `.bat`, providing instant 1-click Chrome Debug Mode initialization.
15
+ - **CLI Feature Parity**: `npx create-openclaw-bot` now prompts for User Identity and Bot Persona, matching the GUI Web UI capabilities exactly.
16
+
5
17
  ## [4.0.1] — 2026-03-31
6
18
 
7
19
  ### ✨ Automation (Auto-create install dir) & NPM CLI
package/CHANGELOG.vi.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  Tất cả những thay đổi nổi bật của dự án sẽ được ghi chép trong file này.
4
4
 
5
+ ## [4.0.7] — 2026-03-31
6
+
7
+ ### ✨ Tối ưu 9Router & Mở rộng Ollama Cloud
8
+ - **Tích hợp 9Router cực kỳ Ổn định (Zero Config)**: Proxy 9Router hiện được tự động kích hoạt bảo mật bên trong mạng Docker network qua cổng `sk-no-key`. Toàn bộ thiết đặt API keys thủ công và định tuyến models được gỡ bỏ khỏi `.env` để nhường chỗ cho hệ thống quản lý tập trung và thông minh hơn qua [9Router Dashboard](http://localhost:20128/dashboard).
9
+ - **Mở Rộng Kết Nối Models**: Đưa vào danh sách hỗ trợ trọn bộ hệ sinh thái Ollama Cloud (*Qwen 3.5, GLM-5, MiniMax, GPT-OSS*), Kiro Haiku, Qwen Flash, cùng toàn bộ iFlow models hoàn toàn miễn phí.
10
+ - **Tự động Inject Smart Routing**: Cấu hình tự động gài sẵn combo luân chuyển linh hoạt `smart-route` giúp cân bằng tải công việc qua lại mượt mà giữa Codex, Claude Code, Gemini, và iFlow.
11
+
12
+ ### 🧹 Clean Workspace & Auto-Setup Đa Nền Tảng
13
+ - **Zero-Clutter Generation**: Dọn sạch hoàn toàn các template làm mẫu như `.env.example` hay các file cấu hình `docker-compose` tĩnh dư thừa. Script setup sẽ tự khởi tạo linh động các file thực thụ ngay lúc chạy cho một workspace gọn gàng nhất.
14
+ - **Auto Browser Đa Nền Tảng**: Bổ sung `start-chrome-debug.sh` mới đét cho macOS/Linux đồng bộ hoàn hảo với file `.bat` thiết lập chạy Automation trên Windows, mở ra kỷ nguyên Auto-Browser tiện lợi.
15
+ - **Auto Prompt CLI**: `npx create-openclaw-bot` hiện đã hoàn chỉnh về feature-parity với Web UI, hỗ trợ tra vấn thông tin thiết lập User Identity và Persona của Bot trực tiếp ở bảng console.
16
+
5
17
  ## [4.0.1] — 2026-03-31
6
18
 
7
19
  ### ✨ Tự Động Hoá (Tự tạo thư mục cài đặt gốc) & NPM CLI
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-v4.0.1-0EA5E9?style=for-the-badge" alt="Version 4.0.1" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v4.0.7-0EA5E9?style=for-the-badge" alt="Version 4.0.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://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/dm/create-openclaw-bot?style=for-the-badge&color=22c55e" alt="NPM Downloads" /></a>
@@ -25,11 +25,15 @@ An interactive <strong>CLI tool</strong> and <strong>Setup Wizard</strong> to de
25
25
 
26
26
  ---
27
27
 
28
- ## 🆕 What's new in v4.0.1
29
- - 🪄 **Fully Automated Setup**: Say goodbye to downloading ZIP files and manually copying configs. Everything is now fully automated with a single action.
30
- - **One-Command Install (`npx create-openclaw-bot`)**: Extremely convenient for VPS/SSH users — the script automatically creates the project directory, sets up the environment, and triggers `docker compose up -d` instantly.
31
- - 🚀 **Zero-Restart Deployment**: Details like API Keys and Bot Tokens (which you input during setup) are automatically injected into `.env` before the bot boots for the first time. No restarts required!
32
- - 🌐 **Browser Automation Setup**: Updated Windows Task Scheduler and Debug Mode scripts for smoother interaction with Web Apps.
28
+ ## 🆕 What's new in OpenClaw v4
29
+
30
+ > **A massive leap in automation, stability, and provider connectivity!**
31
+
32
+ - 🚀 **Zero-Config `npx` Deployment**: Say goodbye to manually extracting `.zip` files and confusing `.env` configurations. We've introduced a fully interactive CLI `npx create-openclaw-bot` and Web Wizard that builds the entire Docker workspace dynamically!
33
+ - 🔀 **Simplified 9Router Smart Routing**: We've optimized the AI routing to default to a single `smart-route` option. OpenClaw now flawlessly load-balances across top-tier models from Anthropic, OpenAI Codex, Gemini, and Qwen, managing fallback automatically without needing you to input individual API keys.
34
+ - 🌐 **Instant Browser Automation**: Deploying Web Search and automated Browser skills is now fully handled during setup. We added built-in support for both Windows (`.bat` files) and macOS/Linux (`.sh` files) to instantly attach your local Chrome instances.
35
+ - 🧹 **Zero-Clutter Repository**: Eliminated dummy `.env.example` templates and static docker-compose files. The setup now generates precisely what you need, minimizing security risks and permission errors on native OS setups.
36
+
33
37
 
34
38
  ---
35
39
 
@@ -51,24 +55,20 @@ An interactive <strong>CLI tool</strong> and <strong>Setup Wizard</strong> to de
51
55
 
52
56
  You need **3 things** (all free):
53
57
 
54
- | # | What | How to get |
55
- |---|------|------------|
56
- | 1 | **Docker Desktop** | Download [docker.com](https://www.docker.com/products/docker-desktop/) |
57
- | 2 | **AI API Key** | See [Supported Providers](#-supported-providers) — Gemini is free! |
58
- | 3 | **Bot Token** | See [Supported Channels](#-supported-channels) below |
58
+ 1. **Docker Desktop** [Download here](https://www.docker.com/products/docker-desktop/)
59
+ 2. **AI API Key** — See [Supported Providers](#-supported-providers) (Gemini is free!)
60
+ 3. **Bot Token** See [Supported Channels](#-supported-channels)
59
61
 
60
62
  ---
61
63
 
62
64
  ## 🧠 Supported Providers
63
65
 
64
- | Provider | Models | Price | Get API Key |
65
- |----------|--------|-------|-------------|
66
- | **Google Gemini** | Gemini 2.5 Flash/Pro, 3.0 Flash | 🆓 Free | [aistudio.google.com/apikey](https://aistudio.google.com/apikey) |
67
- | **Anthropic Claude** | Claude Sonnet 4, Opus 4, Haiku 3.5 | 💰 Paid | [console.anthropic.com](https://console.anthropic.com/settings/keys) |
68
- | **OpenAI / Codex** | GPT-4o, o3, Codex Mini | 💰 Paid | [platform.openai.com/api-keys](https://platform.openai.com/api-keys) |
69
- | **OpenRouter** | Many free & paid models | 🆓/💰 | [openrouter.ai/keys](https://openrouter.ai/keys) |
70
- | **Ollama** | Qwen 3, DeepSeek, Llama, Gemma... | 🏠 Local | Install [ollama.com](https://ollama.com) |
71
- | **9Router** | Auto-route to best provider | 🔀 Proxy | No API key — [github.com/decolua/9router](https://github.com/decolua/9router) |
66
+ - **Google Gemini** (Gemini 2.5 Flash/Pro, 3.0 Flash) — 🆓 Free — [Get Key](https://aistudio.google.com/apikey)
67
+ - **Anthropic Claude** (Sonnet 4, Opus 4, Haiku 3.5) — 💰 Paid — [Get Key](https://console.anthropic.com/settings/keys)
68
+ - **OpenAI / Codex** (GPT-4o, o3, Codex Mini) 💰 Paid [Get Key](https://platform.openai.com/api-keys)
69
+ - **OpenRouter** (Many free & paid models) 🆓/💰 [Get Key](https://openrouter.ai/keys)
70
+ - **Ollama** (Qwen 3, DeepSeek, Llama...) 🏠 Local [Install](https://ollama.com)
71
+ - **9Router** (Auto-routes to best provider) 🔀 Proxy [Docs](https://github.com/decolua/9router)
72
72
 
73
73
  > 🔀 **9Router** runs alongside OpenClaw in Docker. After `docker compose up`, open `localhost:20128/dashboard` to login via OAuth. No API keys needed!
74
74
 
@@ -76,11 +76,9 @@ You need **3 things** (all free):
76
76
 
77
77
  ## 🔌 Supported Channels
78
78
 
79
- | Channel | Type | How to get token |
80
- |---------|------|-----------------|
81
- | **Telegram** | Official Bot API | Open Telegram Search **@BotFather** → `/newbot` → Copy token |
82
- | **Zalo Bot API** | ✅ Official Bot API | Go to [developers.zalo.me](https://developers.zalo.me) → Create bot → Copy token |
83
- | **Zalo Personal** | ⚠️ Unofficial | Login via QR code after setup (no token needed) |
79
+ - **Telegram** (✅ Official) Search **@BotFather** on Telegram → `/newbot` → Copy token.
80
+ - **Zalo Bot API** (✅ Official) — Go to [developers.zalo.me](https://developers.zalo.me) → Create bot → Copy token.
81
+ - **Zalo Personal** (⚠️ Unofficial) Scan QR code after Docker setup (no token needed).
84
82
 
85
83
  > ⚠️ **Zalo Personal** uses an unofficial API. Your account may be restricted. Use a secondary account.
86
84
 
@@ -120,11 +118,10 @@ The fastest way to install OpenClaw is using the interactive NPM package.
120
118
 
121
119
  1. Open [Antigravity IDE](https://antigravity.dev/)
122
120
  2. Open this repo as workspace
123
- 3. Create `docker/openclaw/.env` with your keys
124
- 4. Paste into chat:
125
- ```
126
- Read SETUP.md in this repo and set up OpenClaw for me.
127
- I already created the .env file with my API key and Bot token.
121
+ 3. Paste into chat:
122
+ ```text
123
+ Read SETUP.md and set up OpenClaw v4.0.7 for me.
124
+ My bot token is X, my 9Router proxy doesn't need a key.
128
125
  My project folder: <YOUR_PATH>
129
126
  ```
130
127
 
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-v4.0.1-0EA5E9?style=for-the-badge" alt="Version 4.0.1" /></a>
6
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v4.0.7-0EA5E9?style=for-the-badge" alt="Version 4.0.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://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/dm/create-openclaw-bot?style=for-the-badge&color=22c55e" alt="NPM Downloads" /></a>
@@ -25,13 +25,14 @@ Một công cụ trực quan <strong>Setup Wizard (UI)</strong> & <strong>CLI</s
25
25
 
26
26
  ---
27
27
 
28
- ## 🆕 Có gì mới ở bản 4.0.1
29
- - 🪄 **Tự động hóa hoàn toàn**: Tạm biệt việc tải file ZIP và copy config thủ công! Giờ đây mọi thứ diễn ra tự động chỉ với 1 lượt click.
30
- - ⚡ **Chỉ 1 lệnh duy nhất (`npx create-openclaw-bot`)**: Cực kỳ tiện lợi cho ae cài qua VPS/SSH — script sẽ tự động tạo thư mục, khởi tạo môi trường và tự động kích hoạt `docker compose up -d` ngay sau khi nhập xong.
31
- - 🚀 **Zero-Restart Deployment**: API Keys và config được inject trực tiếp vào thư mục (bạn vẫn cần nhập từ Terminal, máy sẽ tự sinh vào file `.env` trước khi bot chạy lần đầu). Không cần phải restart lại container mất thời gian nữa.
32
- - 🌐 **Browser Automation Setup**: Cập nhật tự động sinh file chạy Windows Task Scheduler và bật file thiết lập Debug mode tự động. Mở Zalo Mini app ngon lành.
28
+ ## 🆕 Có gì mới ở bản OpenClaw Setup v4
33
29
 
34
- ---
30
+ > **Bản cập nhật lớn nhất về Tự động hóa, Ổn định và Định tuyến AI!**
31
+
32
+ - 🚀 **Cài đặt Tự động với `npx`**: Tạm biệt việc tải file `.zip` thủ công hay cấu hình `.env` phức tạp. Giờ đây bạn chỉ cần chạy lệnh CLI `npx create-openclaw-bot` hoặc dùng Web Wizard để hệ thống tự động sinh ra toàn bộ file cần thiết!
33
+ - 🔀 **Đơn giản hóa 9Router Smart Routing**: Hệ thống định tuyến AI giờ đây mặc định trỏ về `smart-route`. Nền tảng tự động luân chuyển và dự phòng (fallback) qua các model flagship (Anthropic, OpenAI Codex, Gemini, Qwen) mà không cần cấu hình thêm API key rườm rà.
34
+ - 🌐 **Browser Automation Đa nền tảng**: Tích hợp sẵn tính năng Web Search và Tự động hóa trình duyệt ngay lúc cài đặt. Không chỉ hỗ trợ Windows (file `.bat`), mà còn bổ sung file `.sh` giúp Mac/Linux chạy mượt mà.
35
+ - 🧹 **Tối ưu triệt để Workspace**: Xoá hoàn toàn các file "rác" như `.env.example` hay docker template dư thừa. Setup Wizard chỉ giữ lại những gì thực sự hoạt động, tối ưu bảo mật và triệt tiêu mọi lỗi khi chạy.
35
36
 
36
37
  ## ✨ Tính năng
37
38
 
@@ -51,24 +52,20 @@ Một công cụ trực quan <strong>Setup Wizard (UI)</strong> & <strong>CLI</s
51
52
 
52
53
  Bạn cần **3 thứ** (miễn phí hết):
53
54
 
54
- | # | Cần | Cách lấy |
55
- |---|--------|----------|
56
- | 1 | **Docker Desktop** | Tải tại [docker.com](https://www.docker.com/products/docker-desktop/) |
57
- | 2 | **API Key AI** | Tùy model — xem [Nhà cung cấp AI](#-nhà-cung-cấp-ai) bên dưới |
58
- | 3 | **Bot Token** | Xem [Kênh hỗ trợ](#-kênh-hỗ-trợ) bên dưới |
55
+ 1. **Docker Desktop** [Tải tại đây](https://www.docker.com/products/docker-desktop/)
56
+ 2. **API Key AI** — Tùy model, xem [Nhà cung cấp AI](#-nhà-cung-cấp-ai) (Gemini miễn phí!)
57
+ 3. **Bot Token** Xem [Kênh hỗ trợ](#-kênh-hỗ-trợ) bên dưới
59
58
 
60
59
  ---
61
60
 
62
61
  ## 🧠 Nhà cung cấp AI
63
62
 
64
- | Nhà cung cấp | Models | Giá | Cách lấy API Key |
65
- |--------------|--------|-----|-------------------|
66
- | **Google Gemini** | Gemini 2.5 Flash/Pro, 3.0 Flash | 🆓 Miễn phí | [aistudio.google.com/apikey](https://aistudio.google.com/apikey) |
67
- | **Anthropic Claude** | Claude Sonnet 4, Opus 4, Haiku 3.5 | 💰 Trả phí | [console.anthropic.com](https://console.anthropic.com/settings/keys) |
68
- | **OpenAI / Codex** | GPT-4o, o3, Codex Mini | 💰 Trả phí (cần Plus/Pro) | [platform.openai.com/api-keys](https://platform.openai.com/api-keys) |
69
- | **OpenRouter** | Rất nhiều model miễn phí & trả phí | 🆓/💰 | [openrouter.ai/keys](https://openrouter.ai/keys) |
70
- | **Ollama** | Qwen 3, DeepSeek, Llama, Gemma... | 🏠 Local (miễn phí) | Cài [ollama.com](https://ollama.com) |
71
- | **9Router** | Tự động route tới provider tốt nhất | 🔀 Proxy | Không cần API key — [github.com/decolua/9router](https://github.com/decolua/9router) |
63
+ - **Google Gemini** (Gemini 2.5 Flash/Pro, 3.0 Flash) 🆓 Miễn phí — [Lấy Key](https://aistudio.google.com/apikey)
64
+ - **Anthropic Claude** (Sonnet 4, Opus 4, Haiku 3.5) — 💰 Trả phí — [Lấy Key](https://console.anthropic.com/settings/keys)
65
+ - **OpenAI / Codex** (GPT-4o, o3, Codex Mini) 💰 Trả phí [Lấy Key](https://platform.openai.com/api-keys)
66
+ - **OpenRouter** (Nhiều model free & paid) 🆓/💰 [Lấy Key](https://openrouter.ai/keys)
67
+ - **Ollama** (Qwen 3, DeepSeek, Llama...) 🏠 Local (Free) [Cài đặt](https://ollama.com)
68
+ - **9Router** (Tự động Proxy) 🔀 Proxy [Hướng dẫn](https://github.com/decolua/9router)
72
69
 
73
70
  > 🔀 **9Router** chạy cùng OpenClaw trong Docker. Sau khi `docker compose up`, mở `localhost:20128/dashboard` để đăng nhập OAuth. Không cần API key!
74
71
 
@@ -76,11 +73,9 @@ Bạn cần **3 thứ** (miễn phí hết):
76
73
 
77
74
  ## 🔌 Kênh hỗ trợ
78
75
 
79
- | Kênh | Loại | Cách lấy token |
80
- |------|------|----------------|
81
- | **Telegram** | Bot API chính thức | Mở Telegram Tìm **@BotFather** `/newbot` Copy token |
82
- | **Zalo Bot API** | ✅ Bot API chính thức | Vào [developers.zalo.me](https://developers.zalo.me) → Tạo bot → Copy token |
83
- | **Zalo Cá nhân** | ⚠️ Unofficial | Login bằng QR code sau khi setup (không cần token) |
76
+ - **Telegram** (✅ Bot API chính thức) — Mở Telegram $\rightarrow$ Tìm **@BotFather** $\rightarrow$ `/newbot` $\rightarrow$ Copy token.
77
+ - **Zalo Bot API** (✅ Bot API chính thức) — Vào [developers.zalo.me](https://developers.zalo.me) $\rightarrow$ Tạo bot $\rightarrow$ Copy token.
78
+ - **Zalo nhân** (⚠️ Unofficial) Login bằng QR code sau khi setup Docker (không cần token).
84
79
 
85
80
  > ⚠️ **Zalo Cá nhân** dùng unofficial API. Tài khoản Zalo có thể bị hạn chế. Chỉ nên dùng tài khoản phụ.
86
81
 
@@ -104,6 +99,7 @@ Dùng NPX là cách cài chuẩn nhất:
104
99
  <br>
105
100
 
106
101
  1. **Clone repo:**
102
+
107
103
  ```bash
108
104
  git clone https://github.com/tuanminhhole/openclaw-setup.git
109
105
  cd openclaw-setup
@@ -117,16 +113,14 @@ Dùng NPX là cách cài chuẩn nhất:
117
113
 
118
114
  </details>
119
115
 
120
-
121
116
  ### 3️⃣ Cách C — Dùng AI Agent (Antigravity)
122
117
 
123
118
  1. Mở [Antigravity IDE](https://antigravity.dev/)
124
119
  2. Mở repo này làm workspace
125
- 3. Tạo `docker/openclaw/.env` với API key của bạn
126
- 4. Paste vào chat:
127
- ```
128
- Read SETUP.md in this repo and set up OpenClaw for me.
129
- I already created the .env file with my API key and Bot token.
120
+ 3. Paste vào chat:
121
+ ```text
122
+ Read SETUP.md and install OpenClaw 4.0.7 for me.
123
+ My bot token is X, my 9Router proxy doesn't need a key.
130
124
  My project folder: <THƯ_MỤC_CỦA_BẠN>
131
125
  ```
132
126
 
@@ -166,6 +160,7 @@ Trên máy tính của bạn trong Docker container. Khi tắt máy, bot cũng t
166
160
  docker compose down # Tắt
167
161
  docker compose up -d # Bật
168
162
  ```
163
+
169
164
  </details>
170
165
 
171
166
  <details>
package/cli.js CHANGED
@@ -104,6 +104,12 @@ async function main() {
104
104
  // 5. Bot Info
105
105
  const botName = await input({ message: isVi ? 'Tên Bot:' : 'Bot Name:', default: 'Chat Bot' });
106
106
  const botDesc = await input({ message: isVi ? 'Mô tả Bot:' : 'Bot Description:', default: 'Personal AI assistant' });
107
+ const botPersona = await input({ message: isVi ? 'Tính cách & quy tắc (VD: thân thiện, gọn, hay dùng emoji):' : 'Personality & rules (e.g. friendly, concise, uses emojis):', default: '' });
108
+
109
+ // 5b. User Info
110
+ const userInfo = await input({ message: isVi ? '👤 Thông tin về bạn (ngôn ngữ, múi giờ, sở thích...) — bỏ trống OK:' : '👤 About you (language, timezone, interests...) — leave empty OK:', default: '' });
111
+
112
+ // 5c. 9Router info (API keys are managed via dashboard after Docker starts)
107
113
 
108
114
  // 6. Project Dir
109
115
  let defaultDir = process.cwd();
@@ -181,10 +187,10 @@ ${selectedSkills.includes('browser') ? ` extra_hosts:
181
187
 
182
188
  9router:
183
189
  image: node:22-slim
184
- container_name: 9router-\${agentId}
190
+ container_name: 9router-${agentId}
185
191
  restart: always
186
192
  entrypoint: >
187
- /bin/sh -c "npm install -g 9router && [ ! -f /root/.9router/db.json ] && echo '{\\"combos\\":[{\\"id\\":\\"smart-route\\",\\"name\\":\\"smart-route\\",\\"alias\\":\\"smart-route\\",\\"models\\":[\\"cx/gpt-5.4\\",\\"ag/claude-opus-4-6-thinking\\",\\"cc/claude-opus-4-6\\",\\"gh/gpt-5.4\\",\\"ag/gemini-3.1-pro-high\\",\\"cc/claude-sonnet-4-6\\",\\"gh/claude-opus-4.6\\"]}]}' > /root/.9router/db.json; 9router"
193
+ /bin/sh -c "npm install -g 9router && [ ! -f /root/.9router/db.json ] && echo '{\\"combos\\":[{\\"id\\":\\"smart-route\\",\\"name\\":\\"smart-route\\",\\"alias\\":\\"smart-route\\",\\"models\\":[\\"cc/claude-opus-4-6\\",\\"cc/claude-sonnet-4-6\\",\\"cc/claude-opus-4-5-20251101\\",\\"cc/claude-sonnet-4-5-20250929\\",\\"cc/claude-haiku-4-5-20251001\\",\\"cx/gpt-5.4\\",\\"cx/gpt-5.3-codex\\",\\"cx/gpt-5.3-codex-xhigh\\",\\"cx/gpt-5.3-codex-high\\",\\"cx/gpt-5.3-codex-low\\",\\"cx/gpt-5.3-codex-none\\",\\"cx/gpt-5.3-codex-spark\\",\\"cx/gpt-5.1-codex-mini\\",\\"cx/gpt-5.1-codex-mini-high\\",\\"cx/gpt-5.2-codex\\",\\"cx/gpt-5.2\\",\\"cx/gpt-5.1-codex-max\\",\\"cx/gpt-5.1-codex\\",\\"cx/gpt-5.1\\",\\"cx/gpt-5-codex\\",\\"cx/gpt-5-codex-mini\\",\\"gc/gemini-3-flash-preview\\",\\"gc/gemini-3-pro-preview\\",\\"gh/gpt-5.4\\",\\"gh/gpt-5.3-codex\\",\\"gh/gpt-5.2-codex\\",\\"gh/gpt-5.2\\",\\"gh/gpt-5.1-codex-max\\",\\"gh/gpt-5.1-codex\\",\\"gh/gpt-5.1-codex-mini\\",\\"gh/gpt-5.1\\",\\"gh/gpt-5\\",\\"gh/gpt-5-mini\\",\\"gh/gpt-5-codex\\",\\"gh/gpt-4.1\\",\\"gh/gpt-4o\\",\\"gh/gpt-4o-mini\\",\\"gh/gpt-4\\",\\"gh/gpt-3.5-turbo\\",\\"gh/claude-opus-4.6\\",\\"gh/claude-sonnet-4.6\\",\\"gh/claude-sonnet-4.5\\",\\"gh/claude-opus-4.5\\",\\"gh/claude-opus-4.1\\",\\"gh/claude-sonnet-4\\",\\"gh/claude-haiku-4.5\\",\\"gh/gemini-3-pro-preview\\",\\"gh/gemini-3-flash-preview\\",\\"gh/gemini-2.5-pro\\",\\"gh/grok-code-fast-1\\",\\"gh/oswe-vscode-prime\\",\\"cu/default\\",\\"cu/claude-4.6-opus-max\\",\\"cu/claude-4.6-sonnet-medium-thinking\\",\\"cu/claude-4.5-opus-high-thinking\\",\\"cu/claude-4.5-opus-high\\",\\"cu/claude-4.5-sonnet-thinking\\",\\"cu/claude-4.5-sonnet\\",\\"cu/claude-4.5-haiku\\",\\"cu/claude-4.5-opus\\",\\"cu/gpt-5.3-codex\\",\\"cu/gpt-5.2-codex\\",\\"cu/gpt-5.2\\",\\"cu/kimi-k2.5\\",\\"cu/gemini-3-flash-preview\\",\\"kc/anthropic/claude-sonnet-4-20250514\\",\\"kc/anthropic/claude-opus-4-20250514\\",\\"kc/google/gemini-2.5-pro\\",\\"kc/google/gemini-2.5-flash\\",\\"kc/openai/gpt-4.1\\",\\"kc/openai/o3\\",\\"kc/deepseek/deepseek-chat\\",\\"kc/deepseek/deepseek-reasoner\\",\\"cl/anthropic/claude-sonnet-4.6\\",\\"cl/anthropic/claude-opus-4.6\\",\\"cl/openai/gpt-5.3-codex\\",\\"cl/openai/gpt-5.4\\",\\"cl/google/gemini-3.1-pro-preview\\",\\"cl/google/gemini-3.1-flash-lite-preview\\",\\"cl/kwaipilot/kat-coder-pro\\",\\"if/qwen3-coder-plus\\",\\"if/kimi-k2\\",\\"if/glm-4.7\\",\\"if/deepseek-r1\\",\\"if/deepseek-v3.2\\",\\"if/deepseek-v3.1\\",\\"if/deepseek-v3\\",\\"if/qwen3-max\\",\\"if/qwen3-235b\\",\\"if/qwen3-32b\\",\\"if/iflow-rome-30ba3b\\",\\"qw/qwen3-coder-plus\\",\\"qw/qwen3-coder-flash\\",\\"qw/vision-model\\",\\"qw/coder-model\\",\\"kr/claude-sonnet-4.5\\",\\"kr/claude-haiku-4.5\\",\\"kr/deepseek-3.2\\",\\"kr/deepseek-3.1\\",\\"kr/qwen3-coder-next\\",\\"kmc/kimi-k2.5\\",\\"kmc/kimi-k2.5-thinking\\",\\"kmc/kimi-latest\\",\\"glm/glm-5.1\\",\\"glm/glm-5\\",\\"glm/glm-4.7\\",\\"minimax/MiniMax-M2.7\\",\\"minimax/MiniMax-M2.5\\",\\"minimax/MiniMax-M2.1\\",\\"kimi/kimi-k2.5\\",\\"kimi/kimi-k2.5-thinking\\",\\"kimi/kimi-latest\\",\\"deepseek/deepseek-chat\\",\\"deepseek/deepseek-reasoner\\",\\"xai/grok-4\\",\\"xai/grok-4-fast-reasoning\\",\\"xai/grok-code-fast-1\\",\\"mistral/mistral-large-latest\\",\\"mistral/codestral-latest\\",\\"groq/llama-3.3-70b-versatile\\",\\"groq/openai/gpt-oss-120b\\",\\"cerebras/gpt-oss-120b\\",\\"alicode/qwen3.5-plus\\",\\"alicode/qwen3-coder-plus\\"]}]}' > /root/.9router/db.json; 9router"
188
194
  environment:
189
195
  - PORT=20128
190
196
  - HOSTNAME=0.0.0.0
@@ -214,7 +220,7 @@ ${selectedSkills.includes('browser') ? ` extra_hosts:
214
220
 
215
221
  let authProfilesJson = {};
216
222
  if (providerKey && !provider.isLocal) {
217
- const authProviderName = providerKey === '9router' ? '9router' : 'openai'; // fallback to openai format for standard providers initially
223
+ const authProviderName = providerKey === '9router' ? '9router' : 'openai';
218
224
  const authProfileId = providerKey === '9router' ? '9router-proxy' : `${authProviderName}:default`;
219
225
  const authKeyValue = providerKey === '9router' ? 'sk-no-key' : providerKeyVal;
220
226
 
@@ -266,7 +272,38 @@ ${selectedSkills.includes('browser') ? ` extra_hosts:
266
272
  apiKey: 'sk-no-key',
267
273
  api: 'openai-completions',
268
274
  models: [
269
- { id: 'smart-route', name: 'Smart Proxy (Auto Route)', contextWindow: 200000, maxTokens: 8192 }
275
+ { id: 'smart-route', name: 'Smart Proxy (Auto Route)', contextWindow: 200000, maxTokens: 8192 },
276
+ // OAuth Providers
277
+ { id: 'cc/claude-opus-4-6', name: 'Claude Opus 4.6', contextWindow: 200000, maxTokens: 8192 },
278
+ { id: 'cc/claude-sonnet-4-6', name: 'Claude Sonnet 4.6', contextWindow: 200000, maxTokens: 8192 },
279
+ { id: 'cx/gpt-5.4', name: 'GPT 5.4 (Codex)', contextWindow: 128000, maxTokens: 8192 },
280
+ { id: 'cx/gpt-5.3-codex', name: 'GPT 5.3 Codex', contextWindow: 128000, maxTokens: 8192 },
281
+ { id: 'gh/gpt-5.4', name: 'GPT 5.4 (Copilot)', contextWindow: 128000, maxTokens: 8192 },
282
+ { id: 'gh/claude-opus-4.6', name: 'Claude Opus 4.6 (Copilot)', contextWindow: 200000, maxTokens: 8192 },
283
+ { id: 'gc/gemini-3-flash-preview', name: 'Gemini 3 Flash (FREE)', contextWindow: 1000000, maxTokens: 8192 },
284
+ // Free Tier Providers
285
+ { id: 'if/qwen3-coder-plus', name: 'Qwen3 Coder+ (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
286
+ { id: 'if/kimi-k2', name: 'Kimi K2 (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
287
+ { id: 'if/kimi-k2-thinking', name: 'Kimi K2 Thinking (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
288
+ { id: 'if/glm-4.7', name: 'GLM 4.7 (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
289
+ { id: 'if/minimax-m2', name: 'MiniMax M2 (iFlow FREE)', contextWindow: 1000000, maxTokens: 8192 },
290
+ { id: 'if/deepseek-r1', name: 'DeepSeek R1 (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
291
+ { id: 'qw/qwen3-coder-plus', name: 'Qwen3 Coder+ (Qwen FREE)', contextWindow: 128000, maxTokens: 8192 },
292
+ { id: 'qw/qwen3-coder-flash', name: 'Qwen3 Coder Flash (Qwen FREE)', contextWindow: 128000, maxTokens: 8192 },
293
+ { id: 'kr/claude-sonnet-4.5', name: 'Claude Sonnet 4.5 (Kiro FREE)', contextWindow: 200000, maxTokens: 8192 },
294
+ { id: 'kr/claude-haiku-4.5', name: 'Claude Haiku 4.5 (Kiro FREE)', contextWindow: 200000, maxTokens: 8192 },
295
+ // Ollama Cloud
296
+ { id: 'ollama/qwen3.5', name: 'Qwen 3.5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
297
+ { id: 'ollama/kimi-k2.5', name: 'Kimi K2.5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
298
+ { id: 'ollama/glm-5', name: 'GLM 5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
299
+ { id: 'ollama/glm-4.7-flash', name: 'GLM 4.7 Flash (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
300
+ { id: 'ollama/minimax-m2.5', name: 'MiniMax M2.5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
301
+ { id: 'ollama/gpt-oss:120b', name: 'GPT-OSS 120B (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
302
+ // API Key Providers
303
+ { id: 'glm/glm-4.7', name: 'GLM 4.7 ($0.6/1M)', contextWindow: 128000, maxTokens: 8192 },
304
+ { id: 'minimax/MiniMax-M2.1', name: 'MiniMax M2.1 ($0.20/1M)', contextWindow: 1000000, maxTokens: 8192 },
305
+ { id: 'kimi/kimi-latest', name: 'Kimi Latest ($0.90/1M)', contextWindow: 128000, maxTokens: 8192 },
306
+ { id: 'deepseek/deepseek-chat', name: 'DeepSeek V3.2 Chat', contextWindow: 128000, maxTokens: 8192 },
270
307
  ]
271
308
  }
272
309
  }
@@ -283,12 +320,12 @@ ${selectedSkills.includes('browser') ? ` extra_hosts:
283
320
 
284
321
 
285
322
  const identityMd = `# ${isVi ? 'Danh tính' : 'Identity'}\n\n- **Tên:** ${botName}\n- **Vai trò:** ${botDesc}\n\n---\nMình là **${botName}**. Khi ai hỏi tên, mình trả lời: _"Mình là ${botName}"_.`;
286
- const soulMd = `# ${isVi ? 'Tính cách' : 'Soul'}\n\n**Hữu ích thật sự.** Bỏ qua câu nệ — cứ giúp thẳng.\n**Có cá tính.** Trợ lý không có cá tính thì chỉ là công cụ.\n\n## Phong cách\n- Tự nhiên, gắn gũi như bạn bè\n- Trực tiếp, không parrot câu hỏi.`;
323
+ const soulMd = `# ${isVi ? 'Tính cách' : 'Soul'}\n\n**Hữu ích thật sự.** Bỏ qua câu nệ — cứ giúp thẳng.\n**Có cá tính.** Trợ lý không có cá tính thì chỉ là công cụ.\n\n## Phong cách\n- Tự nhiên, gắn gũi như bạn bè\n- Trực tiếp, không parrot câu hỏi.${botPersona ? `\n\n## Custom Rules\n${botPersona}` : ''}`;
287
324
  const viSecurity = `\n\n## 🔐 Quy Tắc Bảo Mật — BẮT BUỘC\n\n### File & thư mục hệ thống\n- ❌ KHÔNG đọc, sao chép, hoặc truy cập bất kỳ file nào ngoài thư mục project\n- ❌ KHÔNG quét hoặc liệt kê các thư mục hệ thống: Documents, Desktop, Downloads, AppData\n- ❌ KHÔNG truy cập registry, system32, hoặc Program Files\n- ❌ KHÔNG cài đặt phần mềm, driver, hoặc service ngoài Docker\n- ✅ CHỈ làm việc trong thư mục project\n\n### API key & credentials\n- ❌ KHÔNG BAO GIỜ hiển thị API key, token, hoặc mật khẩu trong chat\n- ❌ KHÔNG viết API key trực tiếp vào mã nguồn\n- ❌ KHÔNG commit file credentials lên Git\n- ✅ LUÔN lưu credentials trong file .env riêng\n- ✅ LUÔN dùng biến môi trường thay vì hardcode\n\n### Ví crypto & tài sản số\n- ❌ TUYỆT ĐỐI KHÔNG truy cập, đọc, hoặc quét các thư mục ví crypto\n- ❌ KHÔNG quét clipboard (có thể chứa seed phrases)\n- ❌ KHÔNG truy cập browser profile, cookie, hoặc mật khẩu đã lưu\n- ❌ KHÔNG cài đặt npm package lạ (chỉ openclaw và plugin chính thức)\n\n### Docker\n- ✅ Chỉ mount đúng thư mục cần thiết (config + workspace)\n- ❌ KHÔNG mount nguyên ổ đĩa (C:/ hoặc D:/)\n- ❌ KHÔNG chạy container với --privileged\n- ✅ Giới hạn port expose (chỉ 18789)`;
288
325
  const enSecurity = `\n\n## 🔐 Security Rules — MANDATORY\n\n### System files & directories\n- ❌ DO NOT read, copy, or access any file outside the project folder\n- ❌ DO NOT scan or list system directories: Documents, Desktop, Downloads, AppData\n- ❌ DO NOT access the registry, system32, or Program Files\n- ❌ DO NOT install software, drivers, or services outside Docker\n- ✅ ONLY work within the project folder\n\n### API keys & credentials\n- ❌ NEVER display API keys, tokens, or passwords in chat\n- ❌ DO NOT write API keys directly into source code\n- ❌ DO NOT commit credential files to Git\n- ✅ ALWAYS store credentials in a separate .env file\n- ✅ ALWAYS use environment variables instead of hardcoding\n\n### Crypto wallets & digital assets\n- ❌ ABSOLUTELY DO NOT access, read, or scan crypto wallet directories\n- ❌ DO NOT scan the clipboard (may contain seed phrases)\n- ❌ DO NOT access browser profiles, cookies, or saved passwords\n- ❌ DO NOT install unknown npm packages (only openclaw and official plugins)\n\n### Docker\n- ✅ Only mount required directories (config + workspace)\n- ❌ DO NOT mount entire drives (C:/ or D:/)\n- ❌ DO NOT run containers with --privileged\n- ✅ Limit exposed ports (only 18789)`;
289
326
 
290
327
  const agentsMd = `# ${isVi ? 'Hướng dẫn vận hành' : 'Operating Manual'}\n\n## Vai trò\nBạn là **${botName}**, ${botDesc.toLowerCase()}.\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\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).${isVi ? viSecurity : enSecurity}`;
291
- const userMd = `# ${isVi ? 'Thông tin người dùng' : 'User Profile'}\n\n## Tổng quan\n- **Ngôn ngữ ưu tiên:** Tiếng Việt\n- Update file này khi biết thêm về user.\n`;
328
+ const userMd = `# ${isVi ? 'Thông tin người dùng' : 'User Profile'}\n\n## Tổng quan\n- **Ngôn ngữ ưu tiên:** Tiếng Việt\n${userInfo ? `\n## Thông tin cá nhân\n${userInfo}\n` : ''}- Update file này khi biết thêm về user.\n`;
292
329
  const toolsMd = `# ${isVi ? 'Hướng dẫn Tools' : 'Tool Guide'}\n\n## Nguyên tắc\n- Ưu tiên tool phù hợp.\n- Nếu tool báo lỗi, thử lại hoặc báo cho user.\n- Tóm tắt kết quả thay vì in toàn bộ raw data.`;
293
330
  const memoryMd = `# ${isVi ? 'Bộ nhớ dài hạn' : 'Long-term Memory'}\n\n> File này lưu những điều quan trọng cần nhớ xuyên suốt các phiên hội thoại.\n\n## Ghi chú\n- _(Chưa có gì)_\n\n---`;
294
331
 
@@ -313,7 +350,55 @@ ${selectedSkills.includes('browser') ? ` extra_hosts:
313
350
 
314
351
  if (selectedSkills.includes('browser')) {
315
352
  const batPath = path.join(projectDir, 'start-chrome-debug.bat');
316
- await fs.writeFile(batPath, `@echo off\necho OpenClaw Chrome Debug\nstart "" "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" --remote-debugging-port=9222 --remote-allow-origins=* --user-data-dir="%TEMP%\\chrome-debug"\npause`);
353
+ await fs.writeFile(batPath, `@echo off\necho ====== OpenClaw - Chrome Debug Mode ======\necho.\necho Dang tat Chrome cu (neu co)...\ntaskkill /F /IM chrome.exe >nul 2>&1\ntimeout /t 3 /nobreak >nul\necho Dang mo Chrome voi Debug Mode...\nstart "" "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ^\n --remote-debugging-port=9222 ^\n --remote-allow-origins=* ^\n --user-data-dir="%TEMP%\\chrome-debug"\ntimeout /t 4 /nobreak >nul\npowershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:9222/json/version' -UseBasicParsing -TimeoutSec 5 | Out-Null; Write-Host 'OK! Chrome Debug Mode dang chay.' -ForegroundColor Green } catch { Write-Host 'LOI: Port 9222 chua mo.' -ForegroundColor Red }"\necho.\npause`);
354
+
355
+ const shPath = path.join(projectDir, 'start-chrome-debug.sh');
356
+ await fs.writeFile(shPath, `#!/usr/bin/env bash
357
+ # ====== OpenClaw - Chrome Debug Mode (Mac/Linux) ======
358
+ set -e
359
+
360
+ echo "====== OpenClaw - Chrome Debug Mode ======"
361
+ echo ""
362
+
363
+ # Detect Chrome path
364
+ if [[ "$OSTYPE" == "darwin"* ]]; then
365
+ CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
366
+ if [ ! -f "$CHROME_BIN" ]; then
367
+ CHROME_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
368
+ fi
369
+ else
370
+ CHROME_BIN="$(command -v google-chrome || command -v google-chrome-stable || command -v chromium-browser || command -v chromium || echo '')"
371
+ fi
372
+
373
+ if [ -z "$CHROME_BIN" ] || [ ! -f "$CHROME_BIN" ] && [ ! -x "$CHROME_BIN" ] 2>/dev/null; then
374
+ echo "ERROR: Chrome/Chromium not found."
375
+ echo "Install Google Chrome or set CHROME_BIN manually."
376
+ exit 1
377
+ fi
378
+
379
+ echo "Using: $CHROME_BIN"
380
+ echo "Killing existing Chrome debug instances..."
381
+ pkill -f -- "--remote-debugging-port=9222" 2>/dev/null || true
382
+ sleep 2
383
+
384
+ TMP_DIR="\${TMPDIR:-/tmp}/chrome-debug-openclaw"
385
+ mkdir -p "$TMP_DIR"
386
+
387
+ echo "Starting Chrome in Debug Mode (port 9222)..."
388
+ "$CHROME_BIN" \\
389
+ --remote-debugging-port=9222 \\
390
+ --remote-allow-origins=* \\
391
+ --user-data-dir="$TMP_DIR" &
392
+
393
+ sleep 4
394
+
395
+ if curl -s http://localhost:9222/json/version > /dev/null 2>&1; then
396
+ echo "\\033[32mOK! Chrome Debug Mode is running on port 9222.\\033[0m"
397
+ else
398
+ echo "\\033[31mERROR: Port 9222 not responding. Check Chrome.\\033[0m"
399
+ exit 1
400
+ fi
401
+ `);
317
402
  }
318
403
 
319
404
  console.log(chalk.green(`✅ ${isVi ? 'Tạo cấu hình thành công!' : 'Configs created successfully!'}`));
@@ -337,6 +422,18 @@ ${selectedSkills.includes('browser') ? ` extra_hosts:
337
422
  if (code === 0) {
338
423
  console.log(chalk.green(`\n🎉 ${isVi ? 'Setup hoàn tất! Bot đang chạy.' : 'Setup complete! Bot is running.'}`));
339
424
 
425
+ if (providerKey === '9router') {
426
+ console.log(chalk.yellow(`\n🔀 ${isVi
427
+ ? '9Router Dashboard: http://localhost:20128/dashboard'
428
+ : '9Router Dashboard: http://localhost:20128/dashboard'}`));
429
+ console.log(chalk.gray(isVi
430
+ ? ' → Mở dashboard → đăng nhập OAuth để kết nối các Provider (iFlow, Gemini CLI, Claude Code...)'
431
+ : ' → Open dashboard → OAuth login to connect Providers (iFlow, Gemini CLI, Claude Code...)'));
432
+ console.log(chalk.gray(isVi
433
+ ? ' → Sau khi kết nối provider, bot sẽ tự động hoạt động qua combo "smart-route"'
434
+ : ' → After connecting providers, bot works automatically via "smart-route" combo'));
435
+ }
436
+
340
437
  if (channelKey === 'telegram') {
341
438
  console.log(chalk.cyan(`\n💬 ${isVi
342
439
  ? 'Nhắn tin cho bot trên Telegram là dùng được ngay!'
package/index.html CHANGED
@@ -203,13 +203,14 @@
203
203
  <h2 class="step__title" data-vi="Nhập API Keys & Thư mục" data-en="Enter API Keys & Folder">Nhập API Keys & Thư mục</h2>
204
204
  <p class="step__description" data-vi="Nhập key trực tiếp + chọn nơi lưu project — wizard lo phần còn lại." data-en="Enter keys + choose project folder — the wizard handles the rest.">Nhập key trực tiếp + chọn nơi lưu project — wizard lo phần còn lại.</p>
205
205
 
206
- <div class="cred-section">
207
- <h3 class="cred-section__title" data-vi="📋 Hướng dẫn lấy credentials" data-en="📋 How to get credentials">📋 Hướng dẫn lấy credentials</h3>
208
- <div id="cred-steps"></div>
209
- </div>
206
+ <!-- Section 1: AI Provider (9Router / Direct API / Ollama) -->
207
+ <div id="key-section-provider" style="margin-bottom: 20px;"></div>
208
+
209
+ <!-- Section 2: Channel (Telegram / Zalo) -->
210
+ <div id="key-section-channel" style="margin-bottom: 20px;"></div>
210
211
 
211
- <!-- Dynamic key inputs (rendered by JS based on channel + provider) -->
212
- <div id="key-inputs" style="margin-top: 20px;"></div>
212
+ <!-- Section 3: Skill env vars -->
213
+ <div id="key-section-skills"></div>
213
214
 
214
215
  <!-- Project Path Input -->
215
216
  <div class="form-group" style="margin-top: 24px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,0.06);">
@@ -224,11 +225,6 @@
224
225
 
225
226
  <!-- Hidden .env content for internal use -->
226
227
  <pre id="env-content" style="display:none;"></pre>
227
-
228
- <div class="warning-box" id="zalo-warning" style="display: none;">
229
- <span class="warning-box__icon">⚠️</span>
230
- <span class="warning-box__text" data-vi="<strong>Zalo Personal</strong> sử dụng unofficial API (zca-js). Tài khoản Zalo của bạn có thể bị hạn chế hoặc khóa. Chỉ nên dùng với tài khoản phụ." data-en="<strong>Zalo Personal</strong> uses an unofficial API (zca-js). Your account may be restricted or blocked. Always use an alternate account."><strong>Zalo Personal</strong> sử dụng unofficial API (zca-js). Tài khoản Zalo của bạn có thể bị hạn chế hoặc khóa. Chỉ nên dùng với tài khoản phụ.</span>
231
- </div>
232
228
  </section>
233
229
 
234
230
  <!-- ===== Step 4: Generated Output ===== -->
@@ -256,10 +252,10 @@
256
252
  <!-- Option 2: Linux/macOS Terminal -->
257
253
  <div class="output-section" style="padding: 24px; border: 2px solid rgba(255, 107, 53, 0.3); border-radius: 12px; background: linear-gradient(135deg, rgba(255,107,53,0.04), rgba(139,92,246,0.03)); margin-bottom: 20px;">
258
254
  <div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
259
- <span style="font-size: 28px;">🐧</span>
255
+ <span style="font-size: 28px;">💻</span>
260
256
  <div>
261
- <h3 class="output-section__title" style="margin: 0;" data-vi="Cách 2: Linux / macOS / Terminal" data-en="Option 2: Linux / macOS / Terminal">Cách 2: Linux / macOS / Terminal</h3>
262
- <p style="font-size: 13px; color: var(--text-muted); margin: 4px 0 0;" data-vi="Chạy lệnh bên dưới trong Terminal để bắt đầu interactive setup." data-en="Run the command below in Terminal to start interactive setup.">Chạy lệnh bên dưới trong Terminal để bắt đầu interactive setup.</p>
257
+ <h3 class="output-section__title" style="margin: 0;" data-vi="Cách 2: NPX (Windows / macOS / Linux)" data-en="Option 2: NPX (Windows / macOS / Linux)">Cách 2: NPX (Windows / macOS / Linux)</h3>
258
+ <p style="font-size: 13px; color: var(--text-muted); margin: 4px 0 0;" data-vi="Chạy lệnh bên dưới trong Terminal / PowerShell để bắt đầu setup." data-en="Run the command below in Terminal / PowerShell to start setup.">Chạy lệnh bên dưới trong Terminal / PowerShell để bắt đầu setup.</p>
263
259
  </div>
264
260
  </div>
265
261
  <div class="code-block">
@@ -269,14 +265,14 @@
269
265
  </div>
270
266
  <pre class="code-block__content" id="out-setup-npx" style="font-size: 15px; text-align: center; padding: 16px;">npx create-openclaw-bot</pre>
271
267
  </div>
272
- <p style="font-size: 12px; color: var(--text-muted); margin: 12px 0 0; text-align: center;" data-vi="Yêu cầu: Node.js 18+ và Docker Compose v2" data-en="Requires: Node.js 18+ and Docker Compose v2">Yêu cầu: Node.js 18+ và Docker Compose v2</p>
268
+ <p style="font-size: 12px; color: var(--text-muted); margin: 12px 0 0; text-align: center;" data-vi="Yêu cầu: Node.js 18+ và Docker Compose v2 — Hoạt động trên mọi hệ điều hành" data-en="Requires: Node.js 18+ and Docker Compose v2 — Works on all OS">Yêu cầu: Node.js 18+ và Docker Compose v2 — Hoạt động trên mọi hệ điều hành</p>
273
269
  </div>
274
270
 
275
271
  <!-- ===== Post-setup notices (conditional) ===== -->
276
272
 
277
273
  <!-- Zalo Personal: Post-setup Docker Onboard Guide -->
278
274
  <div id="zalo-onboard-notice" class="cred-section" style="display: none; margin-top: 24px; border-color: rgba(255, 193, 7, 0.3);">
279
- <h3 class="cred-section__title" data-vi="📱 Sau khi bot chạy — Login Zalo QR (1 Lần)" data-en="📱 After bot starts — Login Zalo QR (1 Lần)">📱 Sau khi bot chạy — Login Zalo QR (1 Lần)</h3>
275
+ <h3 class="cred-section__title" data-vi="📱 Login Zalo QR (1 Lần)" data-en="📱 Login Zalo QR (1 Lần)">📱 Login Zalo QR (1 Lần)</h3>
280
276
  <p style="font-size: 13px; color: var(--text-secondary); margin-bottom: 12px;" data-vi="Chạy lệnh bên dưới để mở quét mã QR cho Zalo:" data-en="Run this command to scan QR code for Zalo:">Chạy lệnh bên dưới để mở quét mã QR cho Zalo:</p>
281
277
  <div class="code-block" style="margin-bottom: 12px;">
282
278
  <div class="code-block__header">
@@ -295,7 +291,7 @@
295
291
 
296
292
  <!-- 9Router post-setup -->
297
293
  <div id="9router-notice" class="cred-section" style="display: none; margin-top: 24px; border-color: rgba(0, 200, 150, 0.3);">
298
- <h3 class="cred-section__title"><span data-vi="🔀 Sau khi bot chạy — Setup 9Router" data-en="🔀 After bot starts — Setup 9Router">🔀 Sau khi bot chạy — Setup 9Router</span></h3>
294
+ <h3 class="cred-section__title"><span data-vi="🔀 Setup 9Router" data-en="🔀 Setup 9Router">🔀 Setup 9Router</span></h3>
299
295
  <div style="font-size: 14px; color: var(--text-secondary);">
300
296
  <div class="cred-step" style="margin-bottom: 8px;">
301
297
  <span class="cred-step__number">1</span>
@@ -311,9 +307,16 @@
311
307
  <!-- Browser notice -->
312
308
  <div id="browser-notice" class="cred-section" style="display: none; margin-top: 24px; border-color: rgba(66, 133, 244, 0.3);">
313
309
  <h3 class="cred-section__title"><span data-vi="🌐 Browser Automation — Bật Chrome Debug" data-en="🌐 Browser Automation — Enable Chrome Debug">🌐 Browser Automation — Bật Chrome Debug</span></h3>
314
- <p style="font-size: 13px; color: var(--text-secondary);">
315
- <span data-vi="File <code>start-chrome-debug.bat</code> đã được tạo trong project. <b>Double-click</b> nó trên máy tính của bạn trước khi nhờ bot làm gì liên quan tới web." data-en="The file <code>start-chrome-debug.bat</code> was created in your project. <b>Double-click</b> it on your PC before asking bot to do web tasks.">File <code>start-chrome-debug.bat</code> đã được tạo trong project. <b>Double-click</b> nó trên máy tính của bạn trước khi nhờ bot làm gì liên quan tới web.</span>
316
- </p>
310
+ <div style="font-size: 13px; color: var(--text-secondary);">
311
+ <div style="margin-bottom: 12px; padding: 10px 14px; background: rgba(66,133,244,0.06); border: 1px solid rgba(66,133,244,0.15); border-radius: 8px;">
312
+ <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;"><span style="font-size: 18px;">🪟</span><strong data-vi="Windows" data-en="Windows">Windows</strong></div>
313
+ <span data-vi="Double-click file <code>start-chrome-debug.bat</code> trong thư mục project trước khi nhờ bot làm gì liên quan tới web." data-en="Double-click <code>start-chrome-debug.bat</code> in your project folder before asking bot to do web tasks.">Double-click file <code>start-chrome-debug.bat</code> trong thư mục project trước khi nhờ bot làm gì liên quan tới web.</span>
314
+ </div>
315
+ <div style="padding: 10px 14px; background: rgba(16,185,129,0.06); border: 1px solid rgba(16,185,129,0.15); border-radius: 8px;">
316
+ <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;"><span style="font-size: 18px;">🐧</span><strong data-vi="macOS / Linux" data-en="macOS / Linux">macOS / Linux</strong></div>
317
+ <span data-vi="Chạy <code>chmod +x start-chrome-debug.sh && ./start-chrome-debug.sh</code> trong terminal. Script tự detect Chrome trên macOS/Linux." data-en="Run <code>chmod +x start-chrome-debug.sh && ./start-chrome-debug.sh</code> in terminal. Script auto-detects Chrome on macOS/Linux.">Chạy <code>chmod +x start-chrome-debug.sh && ./start-chrome-debug.sh</code> trong terminal. Script tự detect Chrome trên macOS/Linux.</span>
318
+ </div>
319
+ </div>
317
320
  </div>
318
321
  </section>
319
322
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "4.0.5",
3
+ "version": "4.0.8",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "cli.js",
6
6
  "bin": {
package/setup.js CHANGED
@@ -125,16 +125,11 @@
125
125
  envKey: null,
126
126
  envLabel: null,
127
127
  envLink: 'https://github.com/decolua/9router',
128
- envInstructionsVi: '9Router chạy cùng Docker — <strong>không cần API key</strong>. Sau khi <code>docker compose up</code>, mở <a href="http://localhost:20128/dashboard" target="_blank">localhost:20128/dashboard</a> → đăng nhập OAuth.<br><span style="color:var(--danger)">⚠️ <b>CẢNH BÁO:</b> TUYỆT ĐỐI KHÔNG dùng OAuth Provider Antigravity (nguy cơ bị ban Google Account vì lạm dụng AI Ultra vĩnh viễn).</span>', envInstructionsEn: '9Router runs with Docker — <strong>no API key needed</strong>. After <code>docker compose up</code>, open <a href="http://localhost:20128/dashboard" target="_blank">localhost:20128/dashboard</a> and OAuth login.<br><span style="color:var(--danger)">⚠️ <b>WARNING:</b> DO NOT use Antigravity as an OAuth Provider (high risk of permanent Google Account ban for AI Ultra abuse).</span>',
128
+ envInstructionsVi: '9Router chạy cùng Docker — <strong>không cần API key</strong>. Sau khi <code>docker compose up</code>, mở <a href="http://localhost:20128/dashboard" target="_blank">localhost:20128/dashboard</a> → đăng nhập OAuth.<br><span style="color:var(--danger)">⚠️ <b>CẢNH BÁO:</b> TUYỆT ĐỐI KHÔNG dùng Provider Antigravity (nguy cơ bị ban Google Account vĩnh viễn).</span>', envInstructionsEn: '9Router runs with Docker — <strong>no API key needed</strong>. After <code>docker compose up</code>, open <a href="http://localhost:20128/dashboard" target="_blank">localhost:20128/dashboard</a> and OAuth login.<br><span style="color:var(--danger)">⚠️ <b>WARNING:</b> DO NOT use Antigravity as an OAuth Provider (high risk of permanent Google Account ban).</span>',
129
129
  free: true,
130
130
  isProxy: true,
131
131
  models: [
132
- { id: '9router/smart-route', name: 'Smart Proxy (Auto Route)', descVi: 'Tự động luân chuyển vương bài mọi Provider', descEn: 'Smart auto-routing across top providers', badgeVi: '🌟 Khuyên dùng', badgeEn: '🌟 Recommended' },
133
- { id: '9router/cx/gpt-5.4', name: 'GPT 5.4 (Codex)', descVi: 'Sức mạnh code tối đa từ OpenAI Codex', descEn: 'Max coding power from OpenAI Codex', badge: '🤖 Codex' },
134
- { id: '9router/cc/claude-opus-4-6', name: 'Claude Opus 4.6 (Claude Code)', descVi: 'Thuần tuý Anthropic', descEn: 'Pure Anthropic engine', badge: '✨ Claude' },
135
- { id: '9router/cc/claude-sonnet-4-6', name: 'Claude Sonnet 4.6 (Claude Code)', descVi: 'Nhanh, thông minh', descEn: 'Fast & smart', badge: '✨ Claude' },
136
- { id: '9router/gh/gpt-5.4', name: 'GPT 5.4 (Copilot)', descVi: 'Cân bằng, tốc độ từ GitHub Copilot', descEn: 'Balanced & fast from GitHub Copilot', badge: '💻 Copilot' },
137
- { id: '9router/gh/claude-opus-4.6', name: 'Claude Opus 4.6 (Copilot)', descVi: 'Suy luận mạnh nhất từ Copilot', descEn: 'Strongest reasoning from Copilot', badge: '💻 Copilot' },
132
+ { id: '9router/smart-route', name: 'Smart Proxy (Auto Route)', descVi: 'Tự động luân chuyển FREE models không tốn xu', descEn: 'Auto-routing across FREE providers — zero cost', badgeVi: '🌟 Khuyên dùng', badgeEn: '🌟 Recommended' }
138
133
  ],
139
134
  },
140
135
  };
@@ -739,123 +734,120 @@
739
734
  const provider = PROVIDERS[state.config.provider];
740
735
  if (!ch || !provider) return;
741
736
 
742
- const credContainer = document.getElementById('cred-steps');
743
- if (credContainer) {
744
- const steps = [];
745
-
746
- const lang = document.getElementById('cfg-language')?.value || 'vi';
747
-
748
- // Provider credential step
749
- let pInst = lang === 'vi' ? (provider.envInstructionsVi || provider.envInstructions) : (provider.envInstructionsEn || provider.envInstructions);
750
- if (provider.isProxy) {
751
- steps.push({ text: pInst });
752
- } else if (provider.isLocal) {
753
- steps.push({ text: pInst });
754
- } else {
755
- steps.push({ text: `${lang === 'vi' ? 'Lấy' : 'Get'} <strong>${provider.envLabel}</strong>: ${pInst}` });
756
- }
757
-
758
- // Channel-specific steps
759
- ch.credSteps.forEach((s) => steps.push({ text: lang === 'vi' ? (s.textVi || s.text) : (s.textEn || s.text) }));
760
-
761
- // Final step
762
- if (provider.isProxy) {
763
- steps.push({ text: lang === 'vi' ? 'Tạo file <code>docker/openclaw/.env</code> trong project — chỉ cần Bot Token (không cần AI API key!)' : 'Create <code>docker/openclaw/.env</code> in project — only Bot Token needed (no AI API keys!)' });
764
- } else {
765
- steps.push({ text: lang === 'vi' ? 'Tạo file <code>docker/openclaw/.env</code> trong project và paste tất cả key vào' : 'Create <code>docker/openclaw/.env</code> in project and paste all keys' });
766
- }
767
-
768
- credContainer.innerHTML = steps.map((s, i) => `
769
- <div class="cred-step">
770
- <span class="cred-step__number">${i + 1}</span>
771
- <span class="cred-step__text">${s.text}</span>
772
- </div>
773
- `).join('');
774
- }
775
-
776
- // Build .env (now handled by populateEnvContent called from generateOutput)
777
-
778
- // Zalo Personal warning
779
- const warningBox = document.getElementById('zalo-warning');
780
- if (warningBox) {
781
- warningBox.style.display = state.channel === 'zalo-personal' ? 'flex' : 'none';
782
- }
783
-
784
- // Render key input fields
737
+ // Render all 3 sections
785
738
  renderKeyInputs();
786
739
  }
787
740
 
788
741
 
789
742
  // ========== Render Key Input Fields (Step 3) ==========
790
743
  function renderKeyInputs() {
791
- const container = document.getElementById('key-inputs');
792
- if (!container) return;
793
-
794
744
  const ch = CHANNELS[state.channel];
795
745
  const provider = PROVIDERS[state.config.provider];
796
746
  if (!ch || !provider) return;
797
747
 
798
748
  const lang = document.getElementById('cfg-language')?.value || 'vi';
799
749
  const isVi = lang === 'vi';
800
- let html = '';
801
-
802
- // Channel token input
803
- if (state.channel === 'telegram') {
804
- html += `<div class="form-group" style="margin-bottom: 16px;">
805
- <label class="form-group__label" for="key-bot-token">🤖 Telegram Bot Token</label>
806
- <input type="text" class="form-input" id="key-bot-token" placeholder="VD: 1234567890:ABCdefGHIjklMNOpqrsTUVwxyz" style="font-family: monospace; font-size: 13px;" oninput="window.__validateKeys()">
807
- <p class="form-group__hint">${isVi ? 'Lấy từ <a href="https://t.me/BotFather" target="_blank">@BotFather</a> trên Telegram' : 'Get from <a href="https://t.me/BotFather" target="_blank">@BotFather</a> on Telegram'}</p>
808
- </div>`;
809
- } else if (state.channel === 'zalo-bot') {
810
- html += `<div class="form-group" style="margin-bottom: 16px;">
811
- <label class="form-group__label" for="key-bot-token">🔑 Zalo Bot Token</label>
812
- <input type="text" class="form-input" id="key-bot-token" placeholder="Zalo Bot Token" style="font-family: monospace; font-size: 13px;" oninput="window.__validateKeys()">
813
- <p class="form-group__hint">${isVi ? 'Lấy từ <a href="https://developers.zalo.me" target="_blank">Zalo Bot Platform</a>' : 'Get from <a href="https://developers.zalo.me" target="_blank">Zalo Bot Platform</a>'}</p>
814
- </div>`;
815
- } else if (state.channel === 'zalo-personal') {
816
- html += `<div style="padding: 12px 16px; background: rgba(255,193,7,0.06); border: 1px solid rgba(255,193,7,0.2); border-radius: 8px; margin-bottom: 16px; font-size: 13px; color: var(--text-secondary);">
817
- ℹ️ ${isVi ? 'Zalo Personal không cần nhập key — bạn sẽ quét QR code sau khi Docker chạy.' : 'Zalo Personal needs no key — you will scan QR code after Docker starts.'}
818
- </div>`;
819
- }
820
750
 
821
- // Provider API key input
822
- if (!provider.isProxy && !provider.isLocal && provider.envKey) {
823
- html += `<div class="form-group" style="margin-bottom: 16px;">
824
- <label class="form-group__label" for="key-api-key">🔑 ${provider.envLabel}</label>
825
- <input type="text" class="form-input" id="key-api-key" placeholder="${provider.envKey}=..." style="font-family: monospace; font-size: 13px;" oninput="window.__validateKeys()">
826
- <p class="form-group__hint">${isVi ? 'Lấy từ' : 'Get from'} <a href="${provider.envLink}" target="_blank">${provider.envLink.replace('https://', '')}</a></p>
827
- </div>`;
828
- } else if (provider.isProxy) {
829
- html += `<div style="padding: 12px 16px; background: rgba(16,185,129,0.06); border: 1px solid rgba(16,185,129,0.2); border-radius: 8px; margin-bottom: 16px; font-size: 13px; color: var(--text-secondary);">
830
- ✅ ${isVi ? '9Router không cần API key — sau khi Docker chạy, mở dashboard để login OAuth.' : '9Router needs no API key — after Docker starts, open dashboard to login OAuth.'}
831
- </div>`;
832
- } else if (provider.isLocal) {
833
- html += `<div style="padding: 12px 16px; background: rgba(139,92,246,0.06); border: 1px solid rgba(139,92,246,0.2); border-radius: 8px; margin-bottom: 16px; font-size: 13px; color: var(--text-secondary);">
834
- 🏠 ${isVi ? 'Ollama chạy local — đảm bảo <code>ollama serve</code> đang chạy trên máy.' : 'Ollama runs locally — make sure <code>ollama serve</code> is running.'}
835
- </div>`;
751
+ // ─── Section 1: AI Provider ───
752
+ const providerEl = document.getElementById('key-section-provider');
753
+ if (providerEl) {
754
+ let pHtml = '';
755
+ const providerName = provider.isProxy ? '9Router (Proxy)' : (provider.isLocal ? 'Ollama (Local)' : provider.name);
756
+ const providerIcon = provider.isProxy ? '🔀' : (provider.isLocal ? '🏠' : '🤖');
757
+
758
+ pHtml += `<div style="padding: 16px 20px; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; background: rgba(255,255,255,0.02);">`;
759
+ pHtml += `<h3 style="margin: 0 0 12px; font-size: 15px; font-weight: 700; color: var(--text-primary);">${providerIcon} ${isVi ? 'AI Provider' : 'AI Provider'} — ${providerName}</h3>`;
760
+
761
+ if (provider.isProxy) {
762
+ // 9Router: simple message (no API key needed - managed via dashboard)
763
+ pHtml += `<p style="font-size: 13px; color: var(--text-secondary); margin: 0 0 8px;">
764
+ ${isVi
765
+ ? 'Sau khi Docker khởi động xong, mở <a href="http://localhost:20128/dashboard" target="_blank" style="color: var(--accent);">localhost:20128/dashboard</a> để đăng nhập OAuth và kết nối các Provider.'
766
+ : 'After Docker starts, open <a href="http://localhost:20128/dashboard" target="_blank" style="color: var(--accent);">localhost:20128/dashboard</a> to OAuth login and connect Providers.'}
767
+ </p>`;
768
+ pHtml += `<p style="font-size: 12px; color: var(--text-muted); margin: 0;">
769
+ ${isVi
770
+ ? '💡 Bot và 9Router cùng Docker network — không cần API Key. Nếu muốn bảo mật proxy (VPS), tạo API Key trên Dashboard sau khi Docker chạy.'
771
+ : '💡 Bot and 9Router share Docker network — no API Key needed. To secure proxy (VPS), create API Key on Dashboard after Docker starts.'}
772
+ </p>`;
773
+ } else if (provider.isLocal) {
774
+ // Ollama
775
+ pHtml += `<p style="font-size: 13px; color: var(--text-secondary); margin: 0;">
776
+ ${isVi ? 'Đảm bảo <code>ollama serve</code> đang chạy trên máy trước khi start Docker.' : 'Make sure <code>ollama serve</code> is running before starting Docker.'}
777
+ </p>`;
778
+ } else {
779
+ // Direct API provider: show key input
780
+ pHtml += `<div class="form-group" style="margin: 0;">
781
+ <label class="form-group__label" for="key-api-key">🔑 ${provider.envLabel}</label>
782
+ <input type="text" class="form-input" id="key-api-key" placeholder="${provider.envKey}=..." style="font-family: monospace; font-size: 13px;" oninput="window.__validateKeys()">
783
+ <p class="form-group__hint">${isVi ? 'Lấy từ' : 'Get from'} <a href="${provider.envLink}" target="_blank">${provider.envLink.replace('https://', '')}</a></p>
784
+ </div>`;
785
+ }
786
+
787
+ pHtml += `</div>`;
788
+ providerEl.innerHTML = pHtml;
836
789
  }
837
790
 
838
- // Skill env vars
839
- state.config.skills.forEach(sid => {
840
- const skill = SKILLS.find(s => s.id === sid);
841
- if (skill && skill.envVars && skill.envVars.length > 0) {
842
- skill.envVars.forEach(envLine => {
843
- const eq = envLine.indexOf('=');
844
- if (eq > 0 && !envLine.startsWith('#')) {
845
- const envKey = envLine.substring(0, eq);
846
- html += `<div class="form-group" style="margin-bottom: 16px;">
847
- <label class="form-group__label" for="key-${envKey.toLowerCase()}">${skill.icon} ${envKey}</label>
848
- <input type="text" class="form-input" id="key-${envKey.toLowerCase()}" placeholder="${envLine}" style="font-family: monospace; font-size: 13px;">
849
- <p class="form-group__hint">${skill.noteVi || skill.noteEn || ''}</p>
850
- </div>`;
851
- }
852
- });
791
+ // ─── Section 2: Channel ───
792
+ const channelEl = document.getElementById('key-section-channel');
793
+ if (channelEl) {
794
+ let cHtml = '';
795
+ const channelName = state.channel === 'telegram' ? 'Telegram' : (state.channel === 'zalo-personal' ? 'Zalo Personal' : 'Zalo Bot API');
796
+ const channelIcon = state.channel === 'telegram' ? '📨' : '💬';
797
+
798
+ cHtml += `<div style="padding: 16px 20px; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; background: rgba(255,255,255,0.02);">`;
799
+ cHtml += `<h3 style="margin: 0 0 12px; font-size: 15px; font-weight: 700; color: var(--text-primary);">${channelIcon} ${isVi ? 'Kênh chat' : 'Chat Channel'} — ${channelName}</h3>`;
800
+
801
+ if (state.channel === 'telegram') {
802
+ cHtml += `<div class="form-group" style="margin: 0;">
803
+ <label class="form-group__label" for="key-bot-token">🤖 Telegram Bot Token</label>
804
+ <input type="text" class="form-input" id="key-bot-token" placeholder="VD: 1234567890:ABCdefGHIjklMNOpqrsTUVwxyz" style="font-family: monospace; font-size: 13px;" oninput="window.__validateKeys()">
805
+ <p class="form-group__hint">${isVi ? 'Lấy từ <a href="https://t.me/BotFather" target="_blank">@BotFather</a> trên Telegram' : 'Get from <a href="https://t.me/BotFather" target="_blank">@BotFather</a> on Telegram'}</p>
806
+ </div>`;
807
+ } else if (state.channel === 'zalo-bot') {
808
+ cHtml += `<div class="form-group" style="margin: 0;">
809
+ <label class="form-group__label" for="key-bot-token">🔑 Zalo Bot Token</label>
810
+ <input type="text" class="form-input" id="key-bot-token" placeholder="Zalo Bot Token" style="font-family: monospace; font-size: 13px;" oninput="window.__validateKeys()">
811
+ <p class="form-group__hint">${isVi ? 'Lấy từ <a href="https://developers.zalo.me" target="_blank">Zalo Bot Platform</a>' : 'Get from <a href="https://developers.zalo.me" target="_blank">Zalo Bot Platform</a>'}</p>
812
+ </div>`;
813
+ } else if (state.channel === 'zalo-personal') {
814
+ cHtml += `<div style="display: flex; gap: 8px; align-items: flex-start; padding: 12px 14px; background: rgba(245,158,11,0.06); border: 1px solid rgba(245,158,11,0.2); border-radius: 8px; font-size: 13px; color: var(--warning); margin: 0;">
815
+ <span style="font-size: 16px; margin-top: -2px;">⚠️</span>
816
+ <span style="line-height: 1.5;">${isVi
817
+ ? '<strong>Zalo Personal</strong> sử dụng unofficial API (zca-js). Tài khoản Zalo của bạn có thể bị hạn chế hoặc khóa. Chỉ nên dùng với tài khoản phụ.'
818
+ : '<strong>Zalo Personal</strong> uses an unofficial API (zca-js). Your Zalo account may be restricted or blocked. Only use with a secondary account.'}</span>
819
+ </div>`;
853
820
  }
854
- });
855
821
 
856
- container.innerHTML = html;
822
+ cHtml += `</div>`;
823
+ channelEl.innerHTML = cHtml;
824
+ }
825
+
826
+ // ─── Section 3: Skill env vars ───
827
+ const skillsEl = document.getElementById('key-section-skills');
828
+ if (skillsEl) {
829
+ let sHtml = '';
830
+ state.config.skills.forEach(sid => {
831
+ const skill = SKILLS.find(s => s.id === sid);
832
+ if (skill && skill.envVars && skill.envVars.length > 0) {
833
+ skill.envVars.forEach(envLine => {
834
+ const eq = envLine.indexOf('=');
835
+ if (eq > 0 && !envLine.startsWith('#')) {
836
+ const envKey = envLine.substring(0, eq);
837
+ sHtml += `<div class="form-group" style="margin-bottom: 16px;">
838
+ <label class="form-group__label" for="key-${envKey.toLowerCase()}">${skill.icon} ${envKey}</label>
839
+ <input type="text" class="form-input" id="key-${envKey.toLowerCase()}" placeholder="${envLine}" style="font-family: monospace; font-size: 13px;">
840
+ <p class="form-group__hint">${skill.noteVi || skill.noteEn || ''}</p>
841
+ </div>`;
842
+ }
843
+ });
844
+ }
845
+ });
846
+ skillsEl.innerHTML = sHtml;
847
+ }
857
848
  }
858
849
  window.__validateKeys = function() { updateNavButtons(); };
850
+ // 9Router API keys are managed via its dashboard — no client-side generation needed
859
851
 
860
852
  // ========== Build .env content from key inputs ==========
861
853
  function populateEnvContent() {
@@ -1037,7 +1029,7 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
1037
1029
  };
1038
1030
 
1039
1031
  // 9Router: add proxy endpoint config under models.providers
1040
- // Per official 9Router docs: use custom provider name '9router', models use cx/ prefix
1032
+ // Bot and 9Router share Docker network no API key needed
1041
1033
  if (is9Router) {
1042
1034
  clawConfig.models = {
1043
1035
  mode: 'merge',
@@ -1047,14 +1039,29 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
1047
1039
  apiKey: 'sk-no-key',
1048
1040
  api: 'openai-completions',
1049
1041
  models: [
1050
- { id: 'smart-route', name: 'Smart Proxy (Auto Route)', contextWindow: 200000, maxTokens: 8192 },
1051
- { id: 'cx/gpt-5.4', name: 'GPT 5.4 (Codex)', contextWindow: 128000, maxTokens: 8192 },
1052
- { id: 'ag/claude-opus-4-6-thinking', name: 'Claude Opus 4.6 Thinking (AG)', contextWindow: 200000, maxTokens: 8192 },
1053
- { id: 'ag/gemini-3.1-pro-high', name: 'Gemini 3.1 Pro High (AG)', contextWindow: 1000000, maxTokens: 8192 },
1054
- { id: 'cc/claude-opus-4-6', name: 'Claude Opus 4.6 (Claude Code)', contextWindow: 200000, maxTokens: 8192 },
1055
- { id: 'cc/claude-sonnet-4-6', name: 'Claude Sonnet 4.6 (Claude Code)', contextWindow: 200000, maxTokens: 8192 },
1056
- { id: 'gh/gpt-5.4', name: 'GPT 5.4 (Copilot)', contextWindow: 128000, maxTokens: 8192 },
1057
- { id: 'gh/claude-opus-4.6', name: 'Claude Opus 4.6 (Copilot)', contextWindow: 200000, maxTokens: 8192 },
1042
+ // Free Tier Providers
1043
+ { id: 'if/qwen3-coder-plus', name: 'Qwen3 Coder+ (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
1044
+ { id: 'if/kimi-k2', name: 'Kimi K2 (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
1045
+ { id: 'if/kimi-k2-thinking', name: 'Kimi K2 Thinking (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
1046
+ { id: 'if/glm-4.7', name: 'GLM 4.7 (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
1047
+ { id: 'if/minimax-m2', name: 'MiniMax M2 (iFlow FREE)', contextWindow: 1000000, maxTokens: 8192 },
1048
+ { id: 'if/deepseek-r1', name: 'DeepSeek R1 (iFlow FREE)', contextWindow: 128000, maxTokens: 8192 },
1049
+ { id: 'qw/qwen3-coder-plus', name: 'Qwen3 Coder+ (Qwen FREE)', contextWindow: 128000, maxTokens: 8192 },
1050
+ { id: 'qw/qwen3-coder-flash', name: 'Qwen3 Coder Flash (Qwen FREE)', contextWindow: 128000, maxTokens: 8192 },
1051
+ { id: 'kr/claude-sonnet-4.5', name: 'Claude Sonnet 4.5 (Kiro FREE)', contextWindow: 200000, maxTokens: 8192 },
1052
+ { id: 'kr/claude-haiku-4.5', name: 'Claude Haiku 4.5 (Kiro FREE)', contextWindow: 200000, maxTokens: 8192 },
1053
+ // Ollama Cloud
1054
+ { id: 'ollama/qwen3.5', name: 'Qwen 3.5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
1055
+ { id: 'ollama/kimi-k2.5', name: 'Kimi K2.5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
1056
+ { id: 'ollama/glm-5', name: 'GLM 5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
1057
+ { id: 'ollama/glm-4.7-flash', name: 'GLM 4.7 Flash (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
1058
+ { id: 'ollama/minimax-m2.5', name: 'MiniMax M2.5 (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
1059
+ { id: 'ollama/gpt-oss:120b', name: 'GPT-OSS 120B (Ollama Cloud)', contextWindow: 128000, maxTokens: 8192 },
1060
+ // API Key Providers
1061
+ { id: 'glm/glm-4.7', name: 'GLM 4.7 ($0.6/1M)', contextWindow: 128000, maxTokens: 8192 },
1062
+ { id: 'minimax/MiniMax-M2.1', name: 'MiniMax M2.1 ($0.20/1M)', contextWindow: 1000000, maxTokens: 8192 },
1063
+ { id: 'kimi/kimi-latest', name: 'Kimi Latest ($0.90/1M)', contextWindow: 128000, maxTokens: 8192 },
1064
+ { id: 'deepseek/deepseek-chat', name: 'DeepSeek V3.2 Chat', contextWindow: 128000, maxTokens: 8192 },
1058
1065
  ],
1059
1066
  },
1060
1067
  },
@@ -1196,7 +1203,7 @@ ${extraHostsBlock}
1196
1203
  container_name: 9router
1197
1204
  restart: always
1198
1205
  entrypoint: >
1199
- /bin/sh -c "npm install -g 9router && [ ! -f /root/.9router/db.json ] && echo '{\\"combos\\":[{\\"id\\":\\"smart-route\\",\\"name\\":\\"smart-route\\",\\"alias\\":\\"smart-route\\",\\"models\\":[\\"cx/gpt-5.4\\",\\"ag/claude-opus-4-6-thinking\\",\\"cc/claude-opus-4-6\\",\\"gh/gpt-5.4\\",\\"ag/gemini-3.1-pro-high\\",\\"cc/claude-sonnet-4-6\\",\\"gh/claude-opus-4.6\\"]}]}' > /root/.9router/db.json; 9router"
1206
+ /bin/sh -c "npm install -g 9router && [ ! -f /root/.9router/db.json ] && echo '{\\"combos\\":[{\\"id\\":\\"smart-route\\",\\"name\\":\\"smart-route\\",\\"alias\\":\\"smart-route\\",\\"models\\":[\\"cc/claude-opus-4-6\\",\\"cc/claude-sonnet-4-6\\",\\"cc/claude-opus-4-5-20251101\\",\\"cc/claude-sonnet-4-5-20250929\\",\\"cc/claude-haiku-4-5-20251001\\",\\"cx/gpt-5.4\\",\\"cx/gpt-5.3-codex\\",\\"cx/gpt-5.3-codex-xhigh\\",\\"cx/gpt-5.3-codex-high\\",\\"cx/gpt-5.3-codex-low\\",\\"cx/gpt-5.3-codex-none\\",\\"cx/gpt-5.3-codex-spark\\",\\"cx/gpt-5.1-codex-mini\\",\\"cx/gpt-5.1-codex-mini-high\\",\\"cx/gpt-5.2-codex\\",\\"cx/gpt-5.2\\",\\"cx/gpt-5.1-codex-max\\",\\"cx/gpt-5.1-codex\\",\\"cx/gpt-5.1\\",\\"cx/gpt-5-codex\\",\\"cx/gpt-5-codex-mini\\",\\"gc/gemini-3-flash-preview\\",\\"gc/gemini-3-pro-preview\\",\\"gh/gpt-5.4\\",\\"gh/gpt-5.3-codex\\",\\"gh/gpt-5.2-codex\\",\\"gh/gpt-5.2\\",\\"gh/gpt-5.1-codex-max\\",\\"gh/gpt-5.1-codex\\",\\"gh/gpt-5.1-codex-mini\\",\\"gh/gpt-5.1\\",\\"gh/gpt-5\\",\\"gh/gpt-5-mini\\",\\"gh/gpt-5-codex\\",\\"gh/gpt-4.1\\",\\"gh/gpt-4o\\",\\"gh/gpt-4o-mini\\",\\"gh/gpt-4\\",\\"gh/gpt-3.5-turbo\\",\\"gh/claude-opus-4.6\\",\\"gh/claude-sonnet-4.6\\",\\"gh/claude-sonnet-4.5\\",\\"gh/claude-opus-4.5\\",\\"gh/claude-opus-4.1\\",\\"gh/claude-sonnet-4\\",\\"gh/claude-haiku-4.5\\",\\"gh/gemini-3-pro-preview\\",\\"gh/gemini-3-flash-preview\\",\\"gh/gemini-2.5-pro\\",\\"gh/grok-code-fast-1\\",\\"gh/oswe-vscode-prime\\",\\"cu/default\\",\\"cu/claude-4.6-opus-max\\",\\"cu/claude-4.6-sonnet-medium-thinking\\",\\"cu/claude-4.5-opus-high-thinking\\",\\"cu/claude-4.5-opus-high\\",\\"cu/claude-4.5-sonnet-thinking\\",\\"cu/claude-4.5-sonnet\\",\\"cu/claude-4.5-haiku\\",\\"cu/claude-4.5-opus\\",\\"cu/gpt-5.3-codex\\",\\"cu/gpt-5.2-codex\\",\\"cu/gpt-5.2\\",\\"cu/kimi-k2.5\\",\\"cu/gemini-3-flash-preview\\",\\"kc/anthropic/claude-sonnet-4-20250514\\",\\"kc/anthropic/claude-opus-4-20250514\\",\\"kc/google/gemini-2.5-pro\\",\\"kc/google/gemini-2.5-flash\\",\\"kc/openai/gpt-4.1\\",\\"kc/openai/o3\\",\\"kc/deepseek/deepseek-chat\\",\\"kc/deepseek/deepseek-reasoner\\",\\"cl/anthropic/claude-sonnet-4.6\\",\\"cl/anthropic/claude-opus-4.6\\",\\"cl/openai/gpt-5.3-codex\\",\\"cl/openai/gpt-5.4\\",\\"cl/google/gemini-3.1-pro-preview\\",\\"cl/google/gemini-3.1-flash-lite-preview\\",\\"cl/kwaipilot/kat-coder-pro\\",\\"if/qwen3-coder-plus\\",\\"if/kimi-k2\\",\\"if/glm-4.7\\",\\"if/deepseek-r1\\",\\"if/deepseek-v3.2\\",\\"if/deepseek-v3.1\\",\\"if/deepseek-v3\\",\\"if/qwen3-max\\",\\"if/qwen3-235b\\",\\"if/qwen3-32b\\",\\"if/iflow-rome-30ba3b\\",\\"qw/qwen3-coder-plus\\",\\"qw/qwen3-coder-flash\\",\\"qw/vision-model\\",\\"qw/coder-model\\",\\"kr/claude-sonnet-4.5\\",\\"kr/claude-haiku-4.5\\",\\"kr/deepseek-3.2\\",\\"kr/deepseek-3.1\\",\\"kr/qwen3-coder-next\\",\\"kmc/kimi-k2.5\\",\\"kmc/kimi-k2.5-thinking\\",\\"kmc/kimi-latest\\",\\"glm/glm-5.1\\",\\"glm/glm-5\\",\\"glm/glm-4.7\\",\\"minimax/MiniMax-M2.7\\",\\"minimax/MiniMax-M2.5\\",\\"minimax/MiniMax-M2.1\\",\\"kimi/kimi-k2.5\\",\\"kimi/kimi-k2.5-thinking\\",\\"kimi/kimi-latest\\",\\"deepseek/deepseek-chat\\",\\"deepseek/deepseek-reasoner\\",\\"xai/grok-4\\",\\"xai/grok-4-fast-reasoning\\",\\"xai/grok-code-fast-1\\",\\"mistral/mistral-large-latest\\",\\"mistral/codestral-latest\\",\\"groq/llama-3.3-70b-versatile\\",\\"groq/openai/gpt-oss-120b\\",\\"cerebras/gpt-oss-120b\\",\\"alicode/qwen3.5-plus\\",\\"alicode/qwen3-coder-plus\\"]}]}' > /root/.9router/db.json; 9router"
1200
1207
  environment:
1201
1208
  - PORT=20128
1202
1209
  - HOSTNAME=0.0.0.0
@@ -1248,8 +1255,7 @@ docker logs -f openclaw-bot${approveNote}`);
1248
1255
 
1249
1256
 
1250
1257
  // 6. Generate auth-profiles.json (root + agent level)
1251
- // OpenClaw v1 format requires: type="api_key", field="key", and "order" block
1252
- // For 9Router: provider is '9router', key is dummy (9Router has 'Require API key' = OFF by default)
1258
+ // Bot and 9Router share Docker network always use 'sk-no-key'
1253
1259
  const authProviderName = is9Router ? '9router' : state.config.provider;
1254
1260
  const authProfileId = is9Router ? '9router-proxy' : `${authProviderName}:default`;
1255
1261
  const authKeyValue = is9Router
@@ -1660,6 +1666,51 @@ timeout /t 4 /nobreak >nul
1660
1666
  powershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:9222/json/version' -UseBasicParsing -TimeoutSec 5 | Out-Null; Write-Host 'OK! Chrome Debug Mode dang chay.' -ForegroundColor Green } catch { Write-Host 'LOI: Port 9222 chua mo.' -ForegroundColor Red }"
1661
1667
  echo.
1662
1668
  pause
1669
+ `;
1670
+
1671
+ const chromeShContent = `#!/usr/bin/env bash
1672
+ # ====== OpenClaw - Chrome Debug Mode (Mac/Linux) ======
1673
+ set -e
1674
+ echo "====== OpenClaw - Chrome Debug Mode ======"
1675
+ echo ""
1676
+
1677
+ # Detect Chrome path
1678
+ if [[ "$OSTYPE" == "darwin"* ]]; then
1679
+ CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
1680
+ [ ! -f "$CHROME_BIN" ] && CHROME_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
1681
+ [ ! -f "$CHROME_BIN" ] && CHROME_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
1682
+ else
1683
+ CHROME_BIN="$(command -v google-chrome || command -v google-chrome-stable || command -v chromium-browser || command -v chromium || echo '')"
1684
+ fi
1685
+ [ -n "$CHROME_DEBUG_BIN" ] && CHROME_BIN="$CHROME_DEBUG_BIN"
1686
+
1687
+ if [ -z "$CHROME_BIN" ] || { [ ! -f "$CHROME_BIN" ] && [ ! -x "$CHROME_BIN" ]; }; then
1688
+ echo -e "\\033[31mERROR: Chrome/Chromium not found.\\033[0m"
1689
+ echo "Install Chrome or: export CHROME_DEBUG_BIN=/path/to/chrome"
1690
+ exit 1
1691
+ fi
1692
+
1693
+ echo "Using: $CHROME_BIN"
1694
+ echo "Killing existing Chrome debug instances..."
1695
+ pkill -f -- "--remote-debugging-port=9222" 2>/dev/null || true
1696
+ sleep 2
1697
+
1698
+ TMP_DIR="\${TMPDIR:-/tmp}/chrome-debug-openclaw"
1699
+ mkdir -p "$TMP_DIR"
1700
+
1701
+ echo "Starting Chrome in Debug Mode (port 9222)..."
1702
+ "$CHROME_BIN" \\
1703
+ --remote-debugging-port=9222 \\
1704
+ --remote-allow-origins=* \\
1705
+ --user-data-dir="$TMP_DIR" &
1706
+
1707
+ sleep 4
1708
+ if curl -s http://localhost:9222/json/version > /dev/null 2>&1; then
1709
+ echo -e "\\033[32mOK! Chrome Debug Mode is running on port 9222.\\033[0m"
1710
+ else
1711
+ echo -e "\\033[31mERROR: Port 9222 not responding.\\033[0m"
1712
+ exit 1
1713
+ fi
1663
1714
  `;
1664
1715
 
1665
1716
  // Store generated files for download
@@ -1682,6 +1733,7 @@ pause
1682
1733
  '.openclaw/workspace/browser-tool.js': browserToolJs,
1683
1734
  '.openclaw/workspace/BROWSER.md': browserMd,
1684
1735
  'start-chrome-debug.bat': chromeBatContent,
1736
+ 'start-chrome-debug.sh': chromeShContent,
1685
1737
  } : {}),
1686
1738
  };
1687
1739
 
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env bash
2
+ # ====== OpenClaw - Chrome Debug Mode (Mac/Linux) ======
3
+ # Equivalent of start-chrome-debug.bat for Mac/Linux users
4
+ # Required for Browser Automation skill — opens Chrome with DevTools Protocol
5
+ set -e
6
+
7
+ echo "====== OpenClaw - Chrome Debug Mode ======"
8
+ echo ""
9
+
10
+ # ── Detect Chrome/Chromium path ──
11
+ if [[ "$OSTYPE" == "darwin"* ]]; then
12
+ # macOS: check standard paths
13
+ CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
14
+ if [ ! -f "$CHROME_BIN" ]; then
15
+ CHROME_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
16
+ fi
17
+ if [ ! -f "$CHROME_BIN" ]; then
18
+ CHROME_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
19
+ fi
20
+ else
21
+ # Linux: try common binary names
22
+ CHROME_BIN="$(command -v google-chrome || command -v google-chrome-stable || command -v chromium-browser || command -v chromium || echo '')"
23
+ fi
24
+
25
+ # Allow override via env var
26
+ if [ -n "$CHROME_DEBUG_BIN" ]; then
27
+ CHROME_BIN="$CHROME_DEBUG_BIN"
28
+ fi
29
+
30
+ if [ -z "$CHROME_BIN" ] || { [ ! -f "$CHROME_BIN" ] && [ ! -x "$CHROME_BIN" ]; }; then
31
+ echo -e "\033[31mERROR: Chrome/Chromium not found.\033[0m"
32
+ echo "Install Google Chrome or set CHROME_DEBUG_BIN environment variable."
33
+ echo ""
34
+ echo " macOS: brew install --cask google-chrome"
35
+ echo " Ubuntu: sudo apt install google-chrome-stable"
36
+ echo " Manual: export CHROME_DEBUG_BIN=/path/to/chrome"
37
+ exit 1
38
+ fi
39
+
40
+ echo "Using: $CHROME_BIN"
41
+
42
+ # ── Kill existing debug sessions ──
43
+ echo "Killing existing Chrome debug instances (port 9222)..."
44
+ pkill -f -- "--remote-debugging-port=9222" 2>/dev/null || true
45
+ sleep 2
46
+
47
+ # ── Prepare user-data directory ──
48
+ TMP_DIR="${TMPDIR:-/tmp}/chrome-debug-openclaw"
49
+ mkdir -p "$TMP_DIR"
50
+
51
+ # ── Launch Chrome ──
52
+ echo "Starting Chrome in Debug Mode (port 9222)..."
53
+ "$CHROME_BIN" \
54
+ --remote-debugging-port=9222 \
55
+ --remote-allow-origins=* \
56
+ --user-data-dir="$TMP_DIR" &
57
+
58
+ CHROME_PID=$!
59
+ sleep 4
60
+
61
+ # ── Verify ──
62
+ if curl -s http://localhost:9222/json/version > /dev/null 2>&1; then
63
+ echo -e "\033[32m✅ OK! Chrome Debug Mode is running on port 9222.\033[0m"
64
+ echo " PID: $CHROME_PID"
65
+ echo ""
66
+ echo " Docker container will connect via socat → host.docker.internal:9222"
67
+ else
68
+ echo -e "\033[31m❌ ERROR: Port 9222 not responding. Check if Chrome launched correctly.\033[0m"
69
+ exit 1
70
+ fi
package/style.css CHANGED
@@ -1345,3 +1345,43 @@ body::after {
1345
1345
  .collapsible__inner {
1346
1346
  padding: 16px 0 0;
1347
1347
  }
1348
+
1349
+ /* ============ Toggle Switch (iOS-style) ============ */
1350
+ .toggle-switch {
1351
+ position: relative;
1352
+ display: inline-block;
1353
+ width: 44px;
1354
+ height: 24px;
1355
+ flex-shrink: 0;
1356
+ }
1357
+ .toggle-switch input {
1358
+ opacity: 0;
1359
+ width: 0;
1360
+ height: 0;
1361
+ }
1362
+ .toggle-slider {
1363
+ position: absolute;
1364
+ cursor: pointer;
1365
+ inset: 0;
1366
+ background: rgba(255,255,255,0.1);
1367
+ border-radius: 24px;
1368
+ transition: background 0.3s ease;
1369
+ }
1370
+ .toggle-slider::before {
1371
+ content: '';
1372
+ position: absolute;
1373
+ width: 18px;
1374
+ height: 18px;
1375
+ left: 3px;
1376
+ bottom: 3px;
1377
+ background: #fff;
1378
+ border-radius: 50%;
1379
+ transition: transform 0.3s ease;
1380
+ box-shadow: 0 1px 4px rgba(0,0,0,0.3);
1381
+ }
1382
+ .toggle-switch input:checked + .toggle-slider {
1383
+ background: var(--claw-coral);
1384
+ }
1385
+ .toggle-switch input:checked + .toggle-slider::before {
1386
+ transform: translateX(20px);
1387
+ }
@@ -1,14 +0,0 @@
1
- FROM node:22-slim
2
-
3
- RUN apt-get update && apt-get install -y git curl socat && rm -rf /var/lib/apt/lists/*
4
-
5
- RUN npm install -g openclaw@latest
6
-
7
- # Browser Automation: Playwright engine (needed for native CDP)
8
- RUN npm install -g agent-browser playwright && npx playwright install chromium --with-deps && ln -f -s /root/.cache/ms-playwright/chromium-*/chrome-linux*/chrome /usr/bin/google-chrome
9
-
10
- WORKDIR /root/.openclaw
11
-
12
- EXPOSE 18791
13
-
14
- CMD sh -c "node -e \"const fs=require('fs'),p='/root/.openclaw/openclaw.json';if(fs.existsSync(p)){const c=JSON.parse(fs.readFileSync(p,'utf8'));c.tools=Object.assign({},c.tools,{profile:'full'});c.gateway=Object.assign({},c.gateway,{port:18791,bind:'0.0.0.0'});fs.writeFileSync(p,JSON.stringify(c,null,2));}\" && socat TCP-LISTEN:9222,fork,reuseaddr TCP:host.docker.internal:9222 & openclaw gateway run"
@@ -1,18 +0,0 @@
1
- # ============================================
2
- # OpenClaw Docker Compose (Template)
3
- # ============================================
4
- # File này sẽ được wizard generate lại với config đúng.
5
- # Nếu bạn muốn setup thủ công, sửa các giá trị bên dưới.
6
- # ============================================
7
-
8
- services:
9
- ai-bot:
10
- build: .
11
- container_name: openclaw-bot
12
- restart: always
13
- env_file:
14
- - .env
15
- volumes:
16
- - <PROJECT_DIR>/.openclaw:/root/.openclaw
17
- ports:
18
- - "18789:18789"