create-openclaw-bot 4.1.3 → 5.0.0
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 +35 -0
- package/CHANGELOG.vi.md +35 -0
- package/README.md +18 -9
- package/README.vi.md +18 -9
- package/cli.js +124 -11
- package/package.json +29 -29
- package/setup.js +53 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog (English)
|
|
2
2
|
|
|
3
|
+
## [5.0.0] — 2026-04-04
|
|
4
|
+
|
|
5
|
+
### 🚀 Gemma 4 Support — Google's Newest Open Model
|
|
6
|
+
|
|
7
|
+
OpenClaw v5.0.0 adds **support for Gemma 4**, Google DeepMind's brand-new open-weights model family released April 2, 2026.
|
|
8
|
+
|
|
9
|
+
- **Gemma 4 available in 3 sizes via Ollama** — `gemma4:4b` (~6 GB RAM), `gemma4` default (~10 GB), `gemma4:27b` (~18 GB)
|
|
10
|
+
- **Zero manual install** — When you select Local Ollama + a Gemma 4 model, the setup now **auto-generates an `ollama` sidecar service** in `docker-compose.yml`. Docker pulls the model automatically on first `docker compose up`. No separate Ollama installation needed.
|
|
11
|
+
- **OLLAMA_HOST auto-configured** — Points to the Docker sidecar (`http://ollama:11434`) instead of the host machine.
|
|
12
|
+
- **Full model list updated** — Added `gemma4`, `gemma4:27b`, `gemma4:4b` to the Ollama provider in both CLI and Web Wizard.
|
|
13
|
+
|
|
14
|
+
### 📋 Hardware Requirements for Gemma 4
|
|
15
|
+
|
|
16
|
+
| Model | Min RAM/VRAM (4-bit) | Recommended |
|
|
17
|
+
| ------------------ | -------------------- | ----------------------------- |
|
|
18
|
+
| `gemma4:4b` | ~6 GB | Laptop, Mac M1/M2 |
|
|
19
|
+
| `gemma4` (default) | ~10 GB | PC 16 GB RAM |
|
|
20
|
+
| `gemma4:27b` | ~18 GB | Workstation 32 GB / GPU 24 GB |
|
|
21
|
+
|
|
22
|
+
> Gemma 4 is **free, open-weights, Apache 2.0**. No API key required — runs 100% locally via Docker.
|
|
23
|
+
|
|
24
|
+
## [4.1.4] — 2026-04-03
|
|
25
|
+
|
|
26
|
+
### ✨ Improvements
|
|
27
|
+
|
|
28
|
+
- CLI/Wizard parity: synchronized all skills (Browser Automation, Memory, RAG, Code Interpreter, etc.)
|
|
29
|
+
- Browser Automation: added Desktop (Host Chrome) vs Server (Headless Chromium) mode selection for Linux/Ubuntu
|
|
30
|
+
- Fixed Dockerfile WORKDIR issue causing build failures on Linux
|
|
31
|
+
- Skills now install at container **runtime** (not build-time) to avoid ClawHub auth issues
|
|
32
|
+
- Dynamic TOOLS.md: auto-generated listing all installed skills with hints
|
|
33
|
+
- Added `browser-tool.js` (Desktop mode) and `BROWSER.md` for both modes
|
|
34
|
+
- Skills registration in `openclaw.json → skills.entries` at setup time
|
|
35
|
+
- Email SMTP config prompts and `.env` injection
|
|
36
|
+
- Single-source versioning via `bump-version.mjs` — one command to update all files
|
|
37
|
+
|
|
3
38
|
## [4.1.3] — 2026-04-02
|
|
4
39
|
|
|
5
40
|
### ✨ Improvements
|
package/CHANGELOG.vi.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog (Tiếng Việt)
|
|
2
2
|
|
|
3
|
+
## [5.0.0] — 2026-04-04
|
|
4
|
+
|
|
5
|
+
### 🚀 Hỗ trợ Gemma 4 — Model mới nhất của Google
|
|
6
|
+
|
|
7
|
+
OpenClaw v5.0.0 cập nhật **Gemma 4** — dòng model open-weights mới của Google DeepMind, ra mắt 02/04/2026.
|
|
8
|
+
|
|
9
|
+
- **Gemma 4 có sẵn 3 size qua Ollama** — `gemma4:4b` (~6 GB RAM), `gemma4` mặc định (~10 GB), `gemma4:27b` (~18 GB)
|
|
10
|
+
- **Không cần cài Ollama thủ công** — Khi chọn Local Ollama + Gemma 4, setup tự động sinh **service `ollama` sát cạnh trong `docker-compose.yml`**. Docker tự pull model khi `docker compose up`. Không cần cài Ollama trước.
|
|
11
|
+
- **OLLAMA_HOST tự cấu hình** — Trỏ thẳng vào sidecar container (`http://ollama:11434`).
|
|
12
|
+
- **Cập nhật danh sách model** — Thêm `gemma4`, `gemma4:27b`, `gemma4:4b` vào Ollama provider trên cả CLI và Web Wizard.
|
|
13
|
+
|
|
14
|
+
### 💻 Yêu cầu phần cứng cho Gemma 4
|
|
15
|
+
|
|
16
|
+
| Model | RAM/VRAM tối thiểu (4-bit) | Phù hợp |
|
|
17
|
+
| ------------------- | -------------------------- | ------------------------------ |
|
|
18
|
+
| `gemma4:4b` | ~6 GB | Laptop thông thường, Mac M1/M2 |
|
|
19
|
+
| `gemma4` (mặc định) | ~10 GB | PC 16 GB RAM |
|
|
20
|
+
| `gemma4:27b` | ~18 GB | Workstation 32 GB / GPU 24 GB |
|
|
21
|
+
|
|
22
|
+
> Gemma 4 **miễn phí, open-weights, giấy phép Apache 2.0**. Không cần API key — chạy 100% local qua Docker.
|
|
23
|
+
|
|
24
|
+
## [4.1.4] — 2026-04-03
|
|
25
|
+
|
|
26
|
+
### ✨ Cải tiến
|
|
27
|
+
|
|
28
|
+
- CLI/Wizard đồng bộ đầy đủ skills (Browser Automation, Memory, RAG, Code Interpreter, v.v.)
|
|
29
|
+
- Browser Automation: chọn chế độ Desktop (Host Chrome) hoặc Server (Headless Chromium) cho Linux/Ubuntu
|
|
30
|
+
- Sửa lỗi Dockerfile WORKDIR gây lỗi build trên Linux
|
|
31
|
+
- Skills install tại **runtime** container (không phải lúc build) để tránh lỗi ClawHub auth
|
|
32
|
+
- TOOLS.md động: tự sinh theo danh sách skills đã chọn
|
|
33
|
+
- Tự tạo `browser-tool.js` (Desktop mode) và `BROWSER.md`
|
|
34
|
+
- Tự đăng ký skills vào `openclaw.json → skills.entries`
|
|
35
|
+
- Bổ sung prompt cấu hình Email SMTP và inject vào `.env`
|
|
36
|
+
- Single-source version qua `bump-version.mjs` — 1 lệnh cập nhật tất cả file
|
|
37
|
+
|
|
3
38
|
## [4.1.3] — 2026-04-02
|
|
4
39
|
|
|
5
40
|
### ✨ Cải tiến
|
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-
|
|
6
|
+
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.0.0-0EA5E9?style=for-the-badge" alt="Version 5.0.0" /></a>
|
|
7
7
|
<a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
|
|
9
9
|
<a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
|
|
@@ -24,14 +24,23 @@ An interactive <strong>CLI tool</strong> and <strong>Setup Wizard</strong> to de
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
## 🆕 What's new in
|
|
27
|
+
## 🆕 What's new in v5.0.0 — Gemma 4 Support
|
|
28
28
|
|
|
29
|
-
> **
|
|
29
|
+
> **Google just dropped Gemma 4 on April 2, 2026. OpenClaw ships support immediately.**
|
|
30
30
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
31
|
+
- 🧠 **Gemma 4 (Google, Open-weights)** — The newest open model from Google DeepMind. Free, powerful, Apache 2.0. Available in 3 sizes: `gemma4:4b` (6 GB), `gemma4` (10 GB), `gemma4:27b` (18 GB).
|
|
32
|
+
- 🐳 **Auto Ollama Sidecar** — No need to install Ollama separately. When you pick Local Ollama, the setup generates a full `docker-compose.yml` with an **Ollama container** that auto-downloads your chosen model on first launch.
|
|
33
|
+
- 🆓 **Zero cost, zero API key** — Gemma 4 runs 100% locally in Docker. Perfect for privacy-first setups.
|
|
34
|
+
|
|
35
|
+
<details>
|
|
36
|
+
<summary><b>Previous: What's new in OpenClaw v4</b></summary>
|
|
37
|
+
|
|
38
|
+
- 🚀 **Zero-Config `npx` Deployment**: Interactive CLI `npx create-openclaw-bot` and Web Wizard builds the entire Docker workspace dynamically.
|
|
39
|
+
- 🔀 **Simplified 9Router Smart Routing**: Auto load-balances across Anthropic, Codex, Gemini, Qwen. No API keys needed.
|
|
40
|
+
- 🌐 **Instant Browser Automation**: Built-in `.bat` and `.sh` scripts for Chrome Debug Mode on Windows/macOS/Linux.
|
|
41
|
+
- 🧹 **Zero-Clutter Repository**: Generates exactly what you need, nothing more.
|
|
42
|
+
|
|
43
|
+
</details>
|
|
35
44
|
|
|
36
45
|
---
|
|
37
46
|
|
|
@@ -65,7 +74,7 @@ You need **3 things** (all free):
|
|
|
65
74
|
- **Anthropic Claude** (Sonnet 4, Opus 4, Haiku 3.5) — 💰 Paid — [Get Key](https://console.anthropic.com/settings/keys)
|
|
66
75
|
- **OpenAI / Codex** (GPT-4o, o3, Codex Mini) — 💰 Paid — [Get Key](https://platform.openai.com/api-keys)
|
|
67
76
|
- **OpenRouter** (Many free & paid models) — 🆓/💰 — [Get Key](https://openrouter.ai/keys)
|
|
68
|
-
- **Ollama** (
|
|
77
|
+
- **Ollama / Gemma 4** (local models, no API key) — 🏠 Local — **Auto-runs in Docker, no manual install**
|
|
69
78
|
- **9Router** (Auto-routes to best provider) — 🔀 Proxy — [Docs](https://github.com/decolua/9router)
|
|
70
79
|
|
|
71
80
|
> 🔀 **9Router** runs alongside OpenClaw in Docker. After `docker compose up`, open `localhost:20128/dashboard` to login via OAuth. No API keys needed!
|
|
@@ -119,7 +128,7 @@ The fastest way to install OpenClaw is using the interactive NPM package.
|
|
|
119
128
|
2. Open this repo as workspace
|
|
120
129
|
3. Paste into chat:
|
|
121
130
|
```text
|
|
122
|
-
Read SETUP.md and set up OpenClaw
|
|
131
|
+
Read SETUP.md and set up OpenClaw v5.0.0 for me.
|
|
123
132
|
My bot token is X, my 9Router proxy doesn't need a key.
|
|
124
133
|
My project folder: <YOUR_PATH>
|
|
125
134
|
```
|
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-
|
|
6
|
+
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.0.0-0EA5E9?style=for-the-badge" alt="Version 5.0.0" /></a>
|
|
7
7
|
<a href="https://github.com/tuanminhhole/openclaw-setup?tab=MIT-1-ov-file"><img src="https://img.shields.io/badge/LICENSE-MIT-success?style=for-the-badge" alt="MIT License" /></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/create-openclaw-bot"><img src="https://img.shields.io/npm/v/create-openclaw-bot?style=for-the-badge&label=CLI&color=2563EB&logo=npm&logoColor=white" alt="NPM Version" /></a>
|
|
9
9
|
<a href="https://github.com/tuanminhhole/openclaw-setup/stargazers"><img src="https://img.shields.io/github/stars/tuanminhhole/openclaw-setup?style=for-the-badge&color=eab308&logo=github&logoColor=white" alt="GitHub Stars" /></a>
|
|
@@ -24,14 +24,23 @@ Một công cụ trực quan <strong>Setup Wizard (UI)</strong> & <strong>CLI</s
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
## 🆕 Có gì mới ở
|
|
27
|
+
## 🆕 Có gì mới ở v5.0.0 — Gemma 4 ra mắt, OpenClaw Setup nâng cấp ngay lập tức!
|
|
28
28
|
|
|
29
|
-
> **
|
|
29
|
+
> **Google vừa ra mắt Gemma 4 ngày 02/04/2026. OpenClaw Setup nâng cấp hỗ trợ ngay lập tức.**
|
|
30
30
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
31
|
+
- 🧠 **Gemma 4 (Google, Open-weights)** — Model mới nhất của Google DeepMind. Miễn phí, mạnh mẽ, giấy phép Apache 2.0. Có sẵn 3 kích thước: `gemma4:4b` (6 GB), `gemma4` (10 GB), `gemma4:27b` (18 GB).
|
|
32
|
+
- 🐳 **Ollama Sidecar tự động** — Không cần cài Ollama thủ công. Khi chọn Local Ollama, setup tự sinh `docker-compose.yml` có **Ollama container** tự tải model về khi chạy lần đầu.
|
|
33
|
+
- 🆓 **Hoàn toàn miễn phí, không API key** — Gemma 4 chạy 100% local trong Docker. Phù hợp cho setup bảo mật tuyệt đối.
|
|
34
|
+
|
|
35
|
+
<details>
|
|
36
|
+
<summary><b>Trước đó: Có gì mới ở OpenClaw v4</b></summary>
|
|
37
|
+
|
|
38
|
+
- 🚀 **Cài đặt Tự động với `npx`**: CLI `npx create-openclaw-bot` và Web Wizard tự sinh toàn bộ file cần thiết.
|
|
39
|
+
- 🔀 **9Router Smart Routing**: Tự động luân chuyển qua Anthropic, Codex, Gemini, Qwen. Không cần API key.
|
|
40
|
+
- 🌐 **Browser Automation Đa nền tảng**: Hỗ trợ cả `.bat` (Windows) và `.sh` (Mac/Linux).
|
|
41
|
+
- 🧹 **Workspace gọn gàng**: Tự sinh đúng file cần thiết, không thừa template rác.
|
|
42
|
+
|
|
43
|
+
</details>
|
|
35
44
|
|
|
36
45
|
## ✨ Tính năng
|
|
37
46
|
|
|
@@ -63,7 +72,7 @@ Bạn cần **3 thứ** (miễn phí hết):
|
|
|
63
72
|
- **Anthropic Claude** (Sonnet 4, Opus 4, Haiku 3.5) — 💰 Trả phí — [Lấy Key](https://console.anthropic.com/settings/keys)
|
|
64
73
|
- **OpenAI / Codex** (GPT-4o, o3, Codex Mini) — 💰 Trả phí — [Lấy Key](https://platform.openai.com/api-keys)
|
|
65
74
|
- **OpenRouter** (Nhiều model free & paid) — 🆓/💰 — [Lấy Key](https://openrouter.ai/keys)
|
|
66
|
-
- **Ollama** (
|
|
75
|
+
- **Ollama / Gemma 4** (model local, không cần API key) — 🏠 Local — **Tự chạy trong Docker, không cần cài Ollama thủ công**
|
|
67
76
|
- **9Router** (Tự động Proxy) — 🔀 Proxy — [Hướng dẫn](https://github.com/decolua/9router)
|
|
68
77
|
|
|
69
78
|
> 🔀 **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!
|
|
@@ -118,7 +127,7 @@ Dùng NPX là cách cài chuẩn nhất:
|
|
|
118
127
|
2. Mở repo này làm workspace
|
|
119
128
|
3. Paste vào chat:
|
|
120
129
|
```text
|
|
121
|
-
Read SETUP.md and install OpenClaw
|
|
130
|
+
Read SETUP.md and install OpenClaw 5.0.0 for me.
|
|
122
131
|
My bot token is X, my 9Router proxy doesn't need a key.
|
|
123
132
|
My project folder: <THƯ_MỤC_CỦA_BẠN>
|
|
124
133
|
```
|
package/cli.js
CHANGED
|
@@ -41,7 +41,7 @@ async function ensureDocker(isVi) {
|
|
|
41
41
|
execSync('brew install --cask docker', { stdio: 'inherit' });
|
|
42
42
|
} else {
|
|
43
43
|
console.log(chalk.cyan(isVi ? '🐳 Đang cài Docker cho Linux...' : '🐳 Installing Docker for Linux...'));
|
|
44
|
-
execSync('curl -fsSL https://get.docker.com | sh', { stdio: 'inherit' });
|
|
44
|
+
execSync('curl -fsSL https://get.docker.com | sh', { stdio: 'inherit', shell: true });
|
|
45
45
|
}
|
|
46
46
|
console.log(chalk.green(isVi ? '✅ Docker đã cài xong! Vui lòng khởi động Docker Desktop rồi chạy lại lệnh này.' : '✅ Docker installed! Please start Docker Desktop and re-run this command.'));
|
|
47
47
|
if (platform === 'win32' || platform === 'darwin') {
|
|
@@ -230,7 +230,7 @@ async function main() {
|
|
|
230
230
|
// ================= GENERATE FILES =================
|
|
231
231
|
let envContent = '';
|
|
232
232
|
if (provider.isLocal) {
|
|
233
|
-
envContent += 'OLLAMA_HOST=http://
|
|
233
|
+
envContent += 'OLLAMA_HOST=http://ollama:11434\n';
|
|
234
234
|
} else if (!provider.isProxy) {
|
|
235
235
|
envContent += `${provider.envKey}=${providerKeyVal}\n`;
|
|
236
236
|
}
|
|
@@ -259,7 +259,12 @@ async function main() {
|
|
|
259
259
|
|
|
260
260
|
// Browser Playwright (both desktop & server modes need chromium)
|
|
261
261
|
const browserDockerLines = selectedSkills.includes('browser')
|
|
262
|
-
?
|
|
262
|
+
? [
|
|
263
|
+
'# Browser Automation: Playwright + Chromium',
|
|
264
|
+
'RUN npm install -g agent-browser playwright \\',
|
|
265
|
+
' && npx playwright install chromium --with-deps \\',
|
|
266
|
+
' && ln -sf /root/.cache/ms-playwright/chromium-*/chrome-linux*/chrome /usr/bin/google-chrome'
|
|
267
|
+
].join('\n')
|
|
263
268
|
: '';
|
|
264
269
|
// socat only for Desktop mode (bridge to host Chrome)
|
|
265
270
|
const socatApt = hasBrowserDesktop ? ' socat' : '';
|
|
@@ -278,16 +283,19 @@ async function main() {
|
|
|
278
283
|
'',
|
|
279
284
|
`RUN apt-get update && apt-get install -y git curl${socatApt} && rm -rf /var/lib/apt/lists/*`,
|
|
280
285
|
'',
|
|
281
|
-
|
|
286
|
+
|
|
282
287
|
];
|
|
283
288
|
if (browserDockerLines) dockerfileLines.push(browserDockerLines);
|
|
284
289
|
dockerfileLines.push(
|
|
290
|
+
'',
|
|
291
|
+
`ARG CACHEBUST=${Date.now()}`,
|
|
292
|
+
'RUN npm install -g openclaw@latest',
|
|
285
293
|
'',
|
|
286
294
|
'WORKDIR /root/.openclaw',
|
|
287
295
|
'',
|
|
288
296
|
'EXPOSE 18791',
|
|
289
297
|
'',
|
|
290
|
-
`CMD sh -c "node -e \\"eval(Buffer.from('${b64Patch}','base64').toString())\\" && ${skillInstallCmd}${socatBridge}(sleep 5
|
|
298
|
+
`CMD sh -c "node -e \\"eval(Buffer.from('${b64Patch}','base64').toString())\\" && ${skillInstallCmd}${socatBridge}(while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done) & openclaw gateway run"`
|
|
291
299
|
);
|
|
292
300
|
const dockerfile = dockerfileLines.join('\n');
|
|
293
301
|
|
|
@@ -300,7 +308,7 @@ async function main() {
|
|
|
300
308
|
// Every 30s it queries /api/providers, filters for active+enabled providers,
|
|
301
309
|
// and updates the smart-route combo to ONLY include models from those providers.
|
|
302
310
|
const syncComboScript = `const fs=require('fs');const ROUTER='http://localhost:20128';const INTERVAL=30000;const p='/root/.9router/db.json';
|
|
303
|
-
const PM={codex:['cx/gpt-5.4','cx/gpt-5.3-codex','cx/gpt-5.3-codex-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'],'claude-code':['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'],github:['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','gh/gpt-5','gh/gpt-4.1','gh/gpt-4o','gh/claude-opus-4.6','gh/claude-sonnet-4.6','gh/claude-sonnet-4.5','gh/claude-opus-4.5','gh/claude-haiku-4.5','gh/gemini-3-pro-preview','gh/gemini-3-flash-preview','gh/gemini-2.5-pro'],cursor:['cu/default','cu/claude-4.6-opus-max','cu/claude-4.5-opus-high-thinking','cu/claude-4.5-sonnet-thinking','cu/claude-4.5-sonnet','cu/gpt-5.3-codex','cu/gpt-5.2-codex','cu/gemini-3-flash-preview'],kilo:['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/deepseek/deepseek-chat'],cline:['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'],'gemini-cli':['gc/gemini-3-flash-preview','gc/gemini-3-pro-preview'],iflow:['if/qwen3-coder-plus','if/kimi-k2','if/kimi-k2-thinking','if/glm-4.7','if/deepseek-r1','if/deepseek-v3.2','if/deepseek-v3','if/qwen3-max','if/qwen3-235b','if/iflow-rome-30ba3b'],qwen:['qw/qwen3-coder-plus','qw/qwen3-coder-flash','qw/vision-model','qw/coder-model'],kiro:['kr/claude-sonnet-4.5','kr/claude-haiku-4.5','kr/deepseek-3.2','kr/deepseek-3.1','kr/qwen3-coder-next'],ollama:['ollama/qwen3.5','ollama/kimi-k2.5','ollama/glm-5','ollama/glm-4.7-flash','ollama/minimax-m2.5','ollama/gpt-oss:120b'],'kimi-coding':['kmc/kimi-k2.5','kmc/kimi-k2.5-thinking','kmc/kimi-latest'],glm:['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],'glm-cn':['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],minimax:['minimax/MiniMax-M2.7','minimax/MiniMax-M2.5','minimax/MiniMax-M2.1'],kimi:['kimi/kimi-k2.5','kimi/kimi-k2.5-thinking','kimi/kimi-latest'],deepseek:['deepseek/deepseek-chat','deepseek/deepseek-reasoner'],xai:['xai/grok-4','xai/grok-4-fast-reasoning','xai/grok-code-fast-1'],mistral:['mistral/mistral-large-latest','mistral/codestral-latest'],groq:['groq/llama-3.3-70b-versatile','groq/openai/gpt-oss-120b'],cerebras:['cerebras/gpt-oss-120b'],alicode:['alicode/qwen3.5-plus','alicode/qwen3-coder-plus'],openai:['openai/gpt-4o','openai/gpt-4.1'],anthropic:['anthropic/claude-sonnet-4','anthropic/claude-haiku-3.5'],gemini:['gemini/gemini-2.5-flash','gemini/gemini-2.5-pro']};
|
|
311
|
+
const PM={codex:['cx/gpt-5.4','cx/gpt-5.3-codex','cx/gpt-5.3-codex-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'],'claude-code':['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'],github:['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','gh/gpt-5','gh/gpt-4.1','gh/gpt-4o','gh/claude-opus-4.6','gh/claude-sonnet-4.6','gh/claude-sonnet-4.5','gh/claude-opus-4.5','gh/claude-haiku-4.5','gh/gemini-3-pro-preview','gh/gemini-3-flash-preview','gh/gemini-2.5-pro'],cursor:['cu/default','cu/claude-4.6-opus-max','cu/claude-4.5-opus-high-thinking','cu/claude-4.5-sonnet-thinking','cu/claude-4.5-sonnet','cu/gpt-5.3-codex','cu/gpt-5.2-codex','cu/gemini-3-flash-preview'],kilo:['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/deepseek/deepseek-chat'],cline:['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'],'gemini-cli':['gc/gemini-3-flash-preview','gc/gemini-3-pro-preview'],iflow:['if/qwen3-coder-plus','if/kimi-k2','if/kimi-k2-thinking','if/glm-4.7','if/deepseek-r1','if/deepseek-v3.2','if/deepseek-v3','if/qwen3-max','if/qwen3-235b','if/iflow-rome-30ba3b'],qwen:['qw/qwen3-coder-plus','qw/qwen3-coder-flash','qw/vision-model','qw/coder-model'],kiro:['kr/claude-sonnet-4.5','kr/claude-haiku-4.5','kr/deepseek-3.2','kr/deepseek-3.1','kr/qwen3-coder-next'],ollama:['ollama/gemma4','ollama/gemma4:27b','ollama/gemma4:4b','ollama/qwen3.5','ollama/kimi-k2.5','ollama/glm-5','ollama/glm-4.7-flash','ollama/minimax-m2.5','ollama/gpt-oss:120b'],'kimi-coding':['kmc/kimi-k2.5','kmc/kimi-k2.5-thinking','kmc/kimi-latest'],glm:['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],'glm-cn':['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],minimax:['minimax/MiniMax-M2.7','minimax/MiniMax-M2.5','minimax/MiniMax-M2.1'],kimi:['kimi/kimi-k2.5','kimi/kimi-k2.5-thinking','kimi/kimi-latest'],deepseek:['deepseek/deepseek-chat','deepseek/deepseek-reasoner'],xai:['xai/grok-4','xai/grok-4-fast-reasoning','xai/grok-code-fast-1'],mistral:['mistral/mistral-large-latest','mistral/codestral-latest'],groq:['groq/llama-3.3-70b-versatile','groq/openai/gpt-oss-120b'],cerebras:['cerebras/gpt-oss-120b'],alicode:['alicode/qwen3.5-plus','alicode/qwen3-coder-plus'],openai:['openai/gpt-4o','openai/gpt-4.1'],anthropic:['anthropic/claude-sonnet-4','anthropic/claude-haiku-3.5'],gemini:['gemini/gemini-2.5-flash','gemini/gemini-2.5-pro']};
|
|
304
312
|
console.log('[sync-combo] 9Router sync loop started...');
|
|
305
313
|
const sync = async () => {
|
|
306
314
|
try {
|
|
@@ -337,6 +345,20 @@ const sync = async () => {
|
|
|
337
345
|
sync();
|
|
338
346
|
setInterval(sync, INTERVAL);`;
|
|
339
347
|
|
|
348
|
+
// ─── Resolve primary model ───────────────────────────────────────────────────
|
|
349
|
+
let modelsPrimary;
|
|
350
|
+
if (providerKey === '9router') {
|
|
351
|
+
modelsPrimary = '9router/smart-route';
|
|
352
|
+
} else if (providerKey === 'ollama') {
|
|
353
|
+
// Use first model in the ollama provider list as default
|
|
354
|
+
const ollamaModels = provider.models || [];
|
|
355
|
+
modelsPrimary = ollamaModels.length > 0 ? ollamaModels[0] : 'ollama/gemma4';
|
|
356
|
+
} else if (providerKey === 'google') {
|
|
357
|
+
modelsPrimary = 'google/gemini-2.5-flash';
|
|
358
|
+
} else {
|
|
359
|
+
modelsPrimary = 'openai/gpt-4o';
|
|
360
|
+
}
|
|
361
|
+
|
|
340
362
|
let compose = '';
|
|
341
363
|
if (providerKey === '9router') {
|
|
342
364
|
compose = `name: oc-${agentId}
|
|
@@ -351,7 +373,9 @@ services:
|
|
|
351
373
|
- 9router
|
|
352
374
|
${hasBrowserDesktop ? ` extra_hosts:
|
|
353
375
|
- "host.docker.internal:host-gateway"
|
|
354
|
-
` : ''}
|
|
376
|
+
` : ''} ports:
|
|
377
|
+
- "18791:18791"
|
|
378
|
+
volumes:
|
|
355
379
|
- ../../.openclaw:/root/.openclaw
|
|
356
380
|
|
|
357
381
|
9router:
|
|
@@ -379,6 +403,62 @@ ${hasBrowserDesktop ? ` extra_hosts:
|
|
|
379
403
|
|
|
380
404
|
volumes:
|
|
381
405
|
9router-data:`;
|
|
406
|
+
} else if (providerKey === 'ollama') {
|
|
407
|
+
// Auto-run Ollama as a sidecar service — user doesn't need to install Ollama manually
|
|
408
|
+
const ollamaModel = modelsPrimary.replace('ollama/', '');
|
|
409
|
+
compose = `name: oc-${agentId}
|
|
410
|
+
services:
|
|
411
|
+
ai-bot:
|
|
412
|
+
build: .
|
|
413
|
+
container_name: openclaw-${agentId}
|
|
414
|
+
restart: always
|
|
415
|
+
env_file: .env
|
|
416
|
+
depends_on:
|
|
417
|
+
ollama:
|
|
418
|
+
condition: service_healthy
|
|
419
|
+
${hasBrowserDesktop ? ` extra_hosts:
|
|
420
|
+
- "host.docker.internal:host-gateway"
|
|
421
|
+
` : ''} ports:
|
|
422
|
+
- "18791:18791"
|
|
423
|
+
volumes:
|
|
424
|
+
- ../../.openclaw:/root/.openclaw
|
|
425
|
+
|
|
426
|
+
ollama:
|
|
427
|
+
image: ollama/ollama:latest
|
|
428
|
+
container_name: ollama-${agentId}
|
|
429
|
+
restart: always
|
|
430
|
+
# Port NOT exposed to host. Bot connects via Docker network (http://ollama:11434).
|
|
431
|
+
# Safe even if user already has Ollama installed on this machine.
|
|
432
|
+
# Uncomment to expose Ollama externally:
|
|
433
|
+
# ports:
|
|
434
|
+
# - "11434:11434"
|
|
435
|
+
volumes:
|
|
436
|
+
- ollama-data:/root/.ollama
|
|
437
|
+
# NVIDIA GPU (optional). Needs nvidia-container-toolkit on host:
|
|
438
|
+
# deploy:
|
|
439
|
+
# resources:
|
|
440
|
+
# reservations:
|
|
441
|
+
# devices:
|
|
442
|
+
# - driver: nvidia
|
|
443
|
+
# count: all
|
|
444
|
+
# capabilities: [gpu]
|
|
445
|
+
entrypoint:
|
|
446
|
+
- /bin/sh
|
|
447
|
+
- -c
|
|
448
|
+
- |
|
|
449
|
+
ollama serve &
|
|
450
|
+
until ollama list > /dev/null 2>&1; do sleep 1; done
|
|
451
|
+
ollama pull ${ollamaModel}
|
|
452
|
+
wait
|
|
453
|
+
healthcheck:
|
|
454
|
+
test: ["CMD-SHELL", "ollama list > /dev/null 2>&1"]
|
|
455
|
+
interval: 10s
|
|
456
|
+
timeout: 5s
|
|
457
|
+
retries: 10
|
|
458
|
+
start_period: 30s
|
|
459
|
+
|
|
460
|
+
volumes:
|
|
461
|
+
ollama-data:`;
|
|
382
462
|
} else {
|
|
383
463
|
compose = `name: oc-${agentId}
|
|
384
464
|
services:
|
|
@@ -389,7 +469,9 @@ services:
|
|
|
389
469
|
env_file: .env
|
|
390
470
|
${hasBrowserDesktop ? ` extra_hosts:
|
|
391
471
|
- "host.docker.internal:host-gateway"
|
|
392
|
-
` : ''}
|
|
472
|
+
` : ''} ports:
|
|
473
|
+
- "18791:18791"
|
|
474
|
+
volumes:
|
|
393
475
|
- ../../.openclaw:/root/.openclaw`;
|
|
394
476
|
}
|
|
395
477
|
|
|
@@ -420,7 +502,7 @@ ${hasBrowserDesktop ? ` extra_hosts:
|
|
|
420
502
|
}
|
|
421
503
|
}
|
|
422
504
|
|
|
423
|
-
|
|
505
|
+
// modelsPrimary already declared above
|
|
424
506
|
|
|
425
507
|
await fs.ensureDir(path.join(projectDir, '.openclaw', 'agents', agentId, 'agent'));
|
|
426
508
|
if (Object.keys(authProfilesJson).length > 0) {
|
|
@@ -694,7 +776,35 @@ fi
|
|
|
694
776
|
console.log(chalk.yellow(`\n🐳 ${isVi ? 'Đang khởi động Docker (có thể mất vài phút)...' : 'Starting Docker (might take a few minutes)...'}`));
|
|
695
777
|
const dockerPath = path.join(projectDir, 'docker', 'openclaw');
|
|
696
778
|
|
|
697
|
-
|
|
779
|
+
// Auto-detect Docker Compose V2 (plugin) vs V1 (standalone docker-compose).
|
|
780
|
+
// On Ubuntu 24.04 installed via `apt install docker.io`, the Compose V2 plugin
|
|
781
|
+
// is NOT included — `docker compose` subcommand may not exist or may be broken.
|
|
782
|
+
// We test both and use whichever actually works.
|
|
783
|
+
let composeCmd, composeArgs;
|
|
784
|
+
const detectCompose = () => {
|
|
785
|
+
// Test V2 plugin: 'docker compose up --help' exits 0 if plugin works
|
|
786
|
+
try {
|
|
787
|
+
execSync('docker compose up --help', { stdio: 'ignore' });
|
|
788
|
+
return { cmd: 'docker', args: ['compose', 'up', '--detach', '--build'] };
|
|
789
|
+
} catch { /* V2 not available or broken */ }
|
|
790
|
+
// Test V1 standalone: 'docker-compose up --help'
|
|
791
|
+
try {
|
|
792
|
+
execSync('docker-compose up --help', { stdio: 'ignore' });
|
|
793
|
+
return { cmd: 'docker-compose', args: ['up', '--detach', '--build'] };
|
|
794
|
+
} catch { /* V1 also not available */ }
|
|
795
|
+
return null;
|
|
796
|
+
};
|
|
797
|
+
const detected = detectCompose();
|
|
798
|
+
if (!detected) {
|
|
799
|
+
console.log(chalk.red(isVi
|
|
800
|
+
? '\n\u274c Kh\u00f4ng t\u00ecm th\u1ea5y Docker Compose!\n C\u00e0i b\u1eb1ng l\u1ec7nh: sudo apt-get install docker-compose-plugin'
|
|
801
|
+
: '\n\u274c Docker Compose not found!\n Install: sudo apt-get install docker-compose-plugin'));
|
|
802
|
+
process.exit(1);
|
|
803
|
+
}
|
|
804
|
+
composeCmd = detected.cmd;
|
|
805
|
+
composeArgs = detected.args;
|
|
806
|
+
|
|
807
|
+
const child = spawn(composeCmd, composeArgs, {
|
|
698
808
|
cwd: dockerPath,
|
|
699
809
|
stdio: 'inherit'
|
|
700
810
|
});
|
|
@@ -724,7 +834,10 @@ fi
|
|
|
724
834
|
console.log(`cd ${projectDir} && docker compose exec -it openclaw bun run core:onboard`);
|
|
725
835
|
}
|
|
726
836
|
} else {
|
|
727
|
-
console.log(chalk.red(`\n
|
|
837
|
+
console.log(chalk.red(`\n\u274c Docker exited with code ${code}`));
|
|
838
|
+
console.log(chalk.yellow(isVi
|
|
839
|
+
? `\n\ud83d\udca1 N\u1ebfu l\u1ed7i "unknown shorthand flag", ch\u1ea1y: sudo apt-get install docker-compose-plugin\n R\u1ed3i th\u1eed l\u1ea1i: cd ${dockerPath} && docker compose up -d --build`
|
|
840
|
+
: `\n\ud83d\udca1 If "unknown shorthand flag" error, run: sudo apt-get install docker-compose-plugin\n Then retry: cd ${dockerPath} && docker compose up -d --build`));
|
|
728
841
|
}
|
|
729
842
|
});
|
|
730
843
|
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "create-openclaw-bot",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Interactive CLI installer for OpenClaw Bot",
|
|
5
|
-
"main": "cli.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"create-openclaw-bot": "./cli.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
-
"bump": "node bump-version.mjs"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
"openclaw",
|
|
15
|
-
"cli",
|
|
16
|
-
"bot",
|
|
17
|
-
"zalo",
|
|
18
|
-
"telegram",
|
|
19
|
-
"ai"
|
|
20
|
-
],
|
|
21
|
-
"author": "tuanminhhole",
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"@inquirer/prompts": "^4.3.1",
|
|
25
|
-
"chalk": "^5.3.0",
|
|
26
|
-
"fs-extra": "^11.2.0"
|
|
27
|
-
},
|
|
28
|
-
"type": "module"
|
|
29
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "create-openclaw-bot",
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"description": "Interactive CLI installer for OpenClaw Bot",
|
|
5
|
+
"main": "cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-openclaw-bot": "./cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"bump": "node bump-version.mjs"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"openclaw",
|
|
15
|
+
"cli",
|
|
16
|
+
"bot",
|
|
17
|
+
"zalo",
|
|
18
|
+
"telegram",
|
|
19
|
+
"ai"
|
|
20
|
+
],
|
|
21
|
+
"author": "tuanminhhole",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@inquirer/prompts": "^4.3.1",
|
|
25
|
+
"chalk": "^5.3.0",
|
|
26
|
+
"fs-extra": "^11.2.0"
|
|
27
|
+
},
|
|
28
|
+
"type": "module"
|
|
29
|
+
}
|
package/setup.js
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
models: [
|
|
57
57
|
{ id: 'google/gemini-2.5-flash', name: 'Gemini 2.5 Flash', descVi: 'Nhanh, miễn phí, đa năng', descEn: 'Fast, free, versatile', badge: '🆓 Free' },
|
|
58
58
|
{ id: 'google/gemini-2.5-pro', name: 'Gemini 2.5 Pro', descVi: 'Thông minh hơn, phân tích sâu', descEn: 'Smarter, deeper analysis', badge: '🆓 Free' },
|
|
59
|
-
{ id: 'google/gemini-3
|
|
59
|
+
{ id: 'google/gemini-3-flash', name: 'Gemini 3 Flash', descVi: 'Thế hệ mới, cực nhanh', descEn: 'Next gen, extremely fast', badge: '🆓 Free' },
|
|
60
60
|
],
|
|
61
61
|
},
|
|
62
62
|
anthropic: {
|
|
@@ -773,8 +773,15 @@
|
|
|
773
773
|
</p>`;
|
|
774
774
|
} else if (provider.isLocal) {
|
|
775
775
|
// Ollama
|
|
776
|
-
pHtml += `<p style="font-size: 13px; color: var(--text-secondary); margin: 0;">
|
|
777
|
-
${isVi
|
|
776
|
+
pHtml += `<p style="font-size: 13px; color: var(--text-secondary); margin: 0 0 8px;">
|
|
777
|
+
${isVi
|
|
778
|
+
? '🐳 Ollama sẽ tự chạy trong Docker cùng bot. Model được tải tự động khi <code>docker compose up</code>.'
|
|
779
|
+
: '🐳 Ollama runs automatically as a Docker sidecar. Model is pulled automatically on first <code>docker compose up</code>.'}
|
|
780
|
+
</p>`;
|
|
781
|
+
pHtml += `<p style="font-size: 12px; color: var(--text-muted); margin: 0;">
|
|
782
|
+
${isVi
|
|
783
|
+
? '⚠️ macOS Apple Silicon: GPU không khả dụng trong Docker. Chạy trên CPU — hoạt động tốt với gemma4:4b.'
|
|
784
|
+
: '⚠️ macOS Apple Silicon: GPU not available in Docker. Runs on CPU — works well with gemma4:4b.'}
|
|
778
785
|
</p>`;
|
|
779
786
|
} else {
|
|
780
787
|
// Direct API provider: show key input
|
|
@@ -866,7 +873,7 @@
|
|
|
866
873
|
if (provider.isProxy) {
|
|
867
874
|
lines.push('# Không cần AI API key — 9Router xử lý qua dashboard');
|
|
868
875
|
} else if (provider.isLocal) {
|
|
869
|
-
lines.push('OLLAMA_HOST=http://
|
|
876
|
+
lines.push('OLLAMA_HOST=http://ollama:11434');
|
|
870
877
|
} else {
|
|
871
878
|
lines.push(`${provider.envKey}=${apiKeyVal || '<your_' + provider.envKey.toLowerCase() + '>'}`);
|
|
872
879
|
}
|
|
@@ -1140,7 +1147,15 @@ model:
|
|
|
1140
1147
|
// Browser Automation: extra Docker deps
|
|
1141
1148
|
const browserAptExtra = hasBrowser ? ' socat' : '';
|
|
1142
1149
|
const browserInstallLines = hasBrowser
|
|
1143
|
-
?
|
|
1150
|
+
? [
|
|
1151
|
+
'',
|
|
1152
|
+
'# Browser Automation: Playwright engine (needed for native CDP)',
|
|
1153
|
+
'RUN npm install -g agent-browser playwright \\',
|
|
1154
|
+
' && npx playwright install chromium --with-deps \\',
|
|
1155
|
+
' && ln -f -s /root/.cache/ms-playwright/chromium-*/chrome-linux*/chrome /usr/bin/google-chrome',
|
|
1156
|
+
'',
|
|
1157
|
+
''
|
|
1158
|
+
].join('\n')
|
|
1144
1159
|
: '';
|
|
1145
1160
|
|
|
1146
1161
|
// Plugins install at runtime (avoids ClawHub rate limit during build)
|
|
@@ -1152,17 +1167,18 @@ model:
|
|
|
1152
1167
|
? 'socat TCP-LISTEN:9222,fork,reuseaddr TCP:host.docker.internal:9222 & '
|
|
1153
1168
|
: '';
|
|
1154
1169
|
// Patch config on every startup to survive openclaw onboard overwrites
|
|
1155
|
-
const patchCmd = `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',exec:{host:'gateway',security:'full',ask:'off'}});c.gateway=Object.assign({},c.gateway,{port:18791,bind:'0.0.0.0'});fs.writeFileSync(p,JSON.stringify(c,null,2));}\\" && `;
|
|
1170
|
+
const patchCmd = `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',exec:{host:'gateway',security:'full',ask:'off'}});c.gateway=Object.assign({},c.gateway,{port:18791,bind:'custom',customBindHost:'0.0.0.0'});fs.writeFileSync(p,JSON.stringify(c,null,2));}\\" && `;
|
|
1156
1171
|
// Auto-approve device pairing after gateway starts (required since v2026.3.x)
|
|
1157
|
-
const autoApproveCmd = '(sleep 5
|
|
1172
|
+
const autoApproveCmd = '(while true; do sleep 5; openclaw devices approve --latest 2>/dev/null || true; done) & ';
|
|
1158
1173
|
const finalCmd = `CMD sh -c "${pluginInstallCmd}${patchCmd}${browserPrefix}${autoApproveCmd}${gatewayCmd}"`;
|
|
1159
1174
|
|
|
1160
1175
|
const dockerfile = `FROM node:22-slim
|
|
1161
1176
|
|
|
1162
1177
|
RUN apt-get update && apt-get install -y git curl${browserAptExtra} && rm -rf /var/lib/apt/lists/*
|
|
1163
1178
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1179
|
+
|
|
1180
|
+
ARG CACHEBUST=${Date.now()}
|
|
1181
|
+
RUN npm install -g openclaw@latest${skillLines}${browserInstallLines}
|
|
1166
1182
|
WORKDIR /root/.openclaw
|
|
1167
1183
|
|
|
1168
1184
|
EXPOSE 18791
|
|
@@ -1179,7 +1195,7 @@ ${finalCmd}`;
|
|
|
1179
1195
|
// Background loop inside 9Router container every 30s.
|
|
1180
1196
|
// Queries /api/providers → filters connected+enabled → updates smart-route combo.
|
|
1181
1197
|
const syncScript = `const fs=require('fs');const ROUTER='http://localhost:20128';const INTERVAL=30000;const p='/root/.9router/db.json';
|
|
1182
|
-
const PM={codex:['cx/gpt-5.4','cx/gpt-5.3-codex','cx/gpt-5.3-codex-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'],'claude-code':['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'],github:['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','gh/gpt-5','gh/gpt-4.1','gh/gpt-4o','gh/claude-opus-4.6','gh/claude-sonnet-4.6','gh/claude-sonnet-4.5','gh/claude-opus-4.5','gh/claude-haiku-4.5','gh/gemini-3-pro-preview','gh/gemini-3-flash-preview','gh/gemini-2.5-pro'],cursor:['cu/default','cu/claude-4.6-opus-max','cu/claude-4.5-opus-high-thinking','cu/claude-4.5-sonnet-thinking','cu/claude-4.5-sonnet','cu/gpt-5.3-codex','cu/gpt-5.2-codex','cu/gemini-3-flash-preview'],kilo:['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/deepseek/deepseek-chat'],cline:['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'],'gemini-cli':['gc/gemini-3-flash-preview','gc/gemini-3-pro-preview'],iflow:['if/qwen3-coder-plus','if/kimi-k2','if/kimi-k2-thinking','if/glm-4.7','if/deepseek-r1','if/deepseek-v3.2','if/deepseek-v3','if/qwen3-max','if/qwen3-235b','if/iflow-rome-30ba3b'],qwen:['qw/qwen3-coder-plus','qw/qwen3-coder-flash','qw/vision-model','qw/coder-model'],kiro:['kr/claude-sonnet-4.5','kr/claude-haiku-4.5','kr/deepseek-3.2','kr/deepseek-3.1','kr/qwen3-coder-next'],ollama:['ollama/qwen3.5','ollama/kimi-k2.5','ollama/glm-5','ollama/glm-4.7-flash','ollama/minimax-m2.5','ollama/gpt-oss:120b'],'kimi-coding':['kmc/kimi-k2.5','kmc/kimi-k2.5-thinking','kmc/kimi-latest'],glm:['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],'glm-cn':['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],minimax:['minimax/MiniMax-M2.7','minimax/MiniMax-M2.5','minimax/MiniMax-M2.1'],kimi:['kimi/kimi-k2.5','kimi/kimi-k2.5-thinking','kimi/kimi-latest'],deepseek:['deepseek/deepseek-chat','deepseek/deepseek-reasoner'],xai:['xai/grok-4','xai/grok-4-fast-reasoning','xai/grok-code-fast-1'],mistral:['mistral/mistral-large-latest','mistral/codestral-latest'],groq:['groq/llama-3.3-70b-versatile','groq/openai/gpt-oss-120b'],cerebras:['cerebras/gpt-oss-120b'],alicode:['alicode/qwen3.5-plus','alicode/qwen3-coder-plus'],openai:['openai/gpt-4o','openai/gpt-4.1'],anthropic:['anthropic/claude-sonnet-4','anthropic/claude-haiku-3.5'],gemini:['gemini/gemini-2.5-flash','gemini/gemini-2.5-pro']};
|
|
1198
|
+
const PM={codex:['cx/gpt-5.4','cx/gpt-5.3-codex','cx/gpt-5.3-codex-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'],'claude-code':['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'],github:['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','gh/gpt-5','gh/gpt-4.1','gh/gpt-4o','gh/claude-opus-4.6','gh/claude-sonnet-4.6','gh/claude-sonnet-4.5','gh/claude-opus-4.5','gh/claude-haiku-4.5','gh/gemini-3-pro-preview','gh/gemini-3-flash-preview','gh/gemini-2.5-pro'],cursor:['cu/default','cu/claude-4.6-opus-max','cu/claude-4.5-opus-high-thinking','cu/claude-4.5-sonnet-thinking','cu/claude-4.5-sonnet','cu/gpt-5.3-codex','cu/gpt-5.2-codex','cu/gemini-3-flash-preview'],kilo:['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/deepseek/deepseek-chat'],cline:['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'],'gemini-cli':['gc/gemini-3-flash-preview','gc/gemini-3-pro-preview'],iflow:['if/qwen3-coder-plus','if/kimi-k2','if/kimi-k2-thinking','if/glm-4.7','if/deepseek-r1','if/deepseek-v3.2','if/deepseek-v3','if/qwen3-max','if/qwen3-235b','if/iflow-rome-30ba3b'],qwen:['qw/qwen3-coder-plus','qw/qwen3-coder-flash','qw/vision-model','qw/coder-model'],kiro:['kr/claude-sonnet-4.5','kr/claude-haiku-4.5','kr/deepseek-3.2','kr/deepseek-3.1','kr/qwen3-coder-next'],ollama:['ollama/gemma4','ollama/gemma4:27b','ollama/gemma4:4b','ollama/qwen3.5','ollama/kimi-k2.5','ollama/glm-5','ollama/glm-4.7-flash','ollama/minimax-m2.5','ollama/gpt-oss:120b'],'kimi-coding':['kmc/kimi-k2.5','kmc/kimi-k2.5-thinking','kmc/kimi-latest'],glm:['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],'glm-cn':['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],minimax:['minimax/MiniMax-M2.7','minimax/MiniMax-M2.5','minimax/MiniMax-M2.1'],kimi:['kimi/kimi-k2.5','kimi/kimi-k2.5-thinking','kimi/kimi-latest'],deepseek:['deepseek/deepseek-chat','deepseek/deepseek-reasoner'],xai:['xai/grok-4','xai/grok-4-fast-reasoning','xai/grok-code-fast-1'],mistral:['mistral/mistral-large-latest','mistral/codestral-latest'],groq:['groq/llama-3.3-70b-versatile','groq/openai/gpt-oss-120b'],cerebras:['cerebras/gpt-oss-120b'],alicode:['alicode/qwen3.5-plus','alicode/qwen3-coder-plus'],openai:['openai/gpt-4o','openai/gpt-4.1'],anthropic:['anthropic/claude-sonnet-4','anthropic/claude-haiku-3.5'],gemini:['gemini/gemini-2.5-flash','gemini/gemini-2.5-pro']};
|
|
1183
1199
|
console.log('[sync-combo] 9Router sync loop started...');
|
|
1184
1200
|
const sync = async () => {
|
|
1185
1201
|
try {
|
|
@@ -1217,7 +1233,8 @@ setInterval(sync, INTERVAL);`;
|
|
|
1217
1233
|
|
|
1218
1234
|
let compose;
|
|
1219
1235
|
if (is9Router) {
|
|
1220
|
-
compose = `
|
|
1236
|
+
compose = `name: oc-bot
|
|
1237
|
+
services:
|
|
1221
1238
|
ai-bot:
|
|
1222
1239
|
build: .
|
|
1223
1240
|
container_name: openclaw-bot
|
|
@@ -1230,7 +1247,7 @@ ${extraHostsBlock}
|
|
|
1230
1247
|
volumes:
|
|
1231
1248
|
- ../../.openclaw:/root/.openclaw
|
|
1232
1249
|
ports:
|
|
1233
|
-
- "
|
|
1250
|
+
- "18791:18791"
|
|
1234
1251
|
|
|
1235
1252
|
9router:
|
|
1236
1253
|
image: node:22-slim
|
|
@@ -1258,7 +1275,8 @@ ${extraHostsBlock}
|
|
|
1258
1275
|
volumes:
|
|
1259
1276
|
9router-data:`;
|
|
1260
1277
|
} else {
|
|
1261
|
-
compose = `
|
|
1278
|
+
compose = `name: oc-bot
|
|
1279
|
+
services:
|
|
1262
1280
|
ai-bot:
|
|
1263
1281
|
build: .
|
|
1264
1282
|
container_name: openclaw-bot
|
|
@@ -1269,7 +1287,7 @@ ${extraHostsBlock}
|
|
|
1269
1287
|
volumes:
|
|
1270
1288
|
- ../../.openclaw:/root/.openclaw
|
|
1271
1289
|
ports:
|
|
1272
|
-
- "
|
|
1290
|
+
- "18791:18791"`;
|
|
1273
1291
|
}
|
|
1274
1292
|
|
|
1275
1293
|
setOutput('out-compose', compose);
|
|
@@ -1973,16 +1991,29 @@ echo ""
|
|
|
1973
1991
|
script += `CLAWEOF\n\n`;
|
|
1974
1992
|
});
|
|
1975
1993
|
|
|
1976
|
-
//
|
|
1994
|
+
// Files created — confirm then auto-run docker
|
|
1977
1995
|
script += `echo ""\n`;
|
|
1978
|
-
script += `echo "${isVi ? '✅ Tạo xong!
|
|
1979
|
-
script += `echo " .openclaw/ — ${isVi ? 'Config bot' : 'Bot config'}"\n`;
|
|
1980
|
-
script += `echo " docker/openclaw/ — Docker files"\n`;
|
|
1981
|
-
script += `echo ""\n`;
|
|
1982
|
-
script += `echo "${isVi ? '📝 Bước tiếp theo:' : '📝 Next steps:'}"\n`;
|
|
1983
|
-
script += `echo "${isVi ? ' 1. Sửa docker/openclaw/.env → paste API keys thật' : ' 1. Edit docker/openclaw/.env → paste real API keys'}"\n`;
|
|
1984
|
-
script += `echo "${isVi ? ' 2. cd docker/openclaw && docker compose build && docker compose up -d' : ' 2. cd docker/openclaw && docker compose build && docker compose up -d'}"\n`;
|
|
1996
|
+
script += `echo "${isVi ? '✅ Tạo file xong!' : '✅ Files created!'}"\n`;
|
|
1985
1997
|
script += `echo ""\n`;
|
|
1998
|
+
|
|
1999
|
+
// Auto-detect Compose V2 (plugin) vs V1 (standalone docker-compose)
|
|
2000
|
+
// Ubuntu 24.04 with `apt install docker.io` does NOT include docker-compose-plugin.
|
|
2001
|
+
script += `echo "${isVi ? '🐳 Đang khởi động Docker (có thể mất vài phút)...' : '🐳 Starting Docker (may take a few minutes)...'}"\n`;
|
|
2002
|
+
script += `if docker compose version > /dev/null 2>&1; then\n`;
|
|
2003
|
+
script += ` COMPOSE_CMD="docker compose"\n`;
|
|
2004
|
+
script += `elif docker-compose version > /dev/null 2>&1; then\n`;
|
|
2005
|
+
script += ` COMPOSE_CMD="docker-compose"\n`;
|
|
2006
|
+
script += `else\n`;
|
|
2007
|
+
script += ` echo "${isVi ? '❌ Không tìm thấy Docker Compose! Cài bằng: sudo apt-get install docker-compose-plugin' : '❌ Docker Compose not found! Install: sudo apt-get install docker-compose-plugin'}"\n`;
|
|
2008
|
+
script += ` exit 1\n`;
|
|
2009
|
+
script += `fi\n`;
|
|
2010
|
+
script += `cd "docker/openclaw"\n`;
|
|
2011
|
+
script += `$COMPOSE_CMD up --detach --build\n`;
|
|
2012
|
+
script += `if [ $? -ne 0 ]; then\n`;
|
|
2013
|
+
script += ` echo "${isVi ? '❌ Docker build thất bại. Docker đã chạy chưa?' : '❌ Docker build failed. Is Docker running?'}"\n`;
|
|
2014
|
+
script += ` exit 1\n`;
|
|
2015
|
+
script += `fi\n`;
|
|
2016
|
+
script += `echo "${isVi ? '🎉 Setup hoàn tất! Bot đang chạy.' : '🎉 Setup complete! Bot is running.'}"\n`;
|
|
1986
2017
|
script += `echo "🦞 Happy botting!"\n`;
|
|
1987
2018
|
|
|
1988
2019
|
return script;
|