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 +12 -0
- package/CHANGELOG.vi.md +12 -0
- package/README.md +26 -29
- package/README.vi.md +26 -31
- package/cli.js +104 -7
- package/index.html +23 -20
- package/package.json +1 -1
- package/setup.js +169 -117
- package/start-chrome-debug.sh +70 -0
- package/style.css +40 -0
- package/docker/openclaw/Dockerfile +0 -14
- package/docker/openclaw/docker-compose.yml +0 -18
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.
|
|
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
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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 Cá 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.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
|
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\\",\\"
|
|
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';
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
<!--
|
|
212
|
-
<div id="key-
|
|
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;"
|
|
255
|
+
<span style="font-size: 28px;">💻</span>
|
|
260
256
|
<div>
|
|
261
|
-
<h3 class="output-section__title" style="margin: 0;" data-vi="Cách 2:
|
|
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
|
|
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="📱
|
|
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="🔀
|
|
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
|
-
<
|
|
315
|
-
<
|
|
316
|
-
|
|
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
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
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
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
|
-
//
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
1051
|
-
{ id: '
|
|
1052
|
-
{ id: '
|
|
1053
|
-
{ id: '
|
|
1054
|
-
{ id: '
|
|
1055
|
-
{ id: '
|
|
1056
|
-
{ id: '
|
|
1057
|
-
{ id: '
|
|
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\\",\\"
|
|
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
|
-
//
|
|
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"
|