create-openclaw-bot 5.6.8 → 5.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -19
- package/README.vi.md +18 -19
- package/dist/cli.js +192 -123
- package/dist/setup/data/channels.js +11 -1
- package/dist/setup/shared/common-gen.js +86 -0
- package/dist/setup/shared/docker-gen.js +73 -30
- package/dist/setup/shared/install-gen.js +23 -3
- package/dist/setup.js +217 -121
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# 🦞 OpenClaw Setup
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.
|
|
6
|
+
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.6.10-0EA5E9?style=for-the-badge" alt="Version 5.6.9" /></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,24 +24,23 @@ An interactive **CLI tool** and **Setup Wizard** to deploy your own free AI Bot
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
## 🆕 What's new in v5.6.
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
<details>
|
|
36
|
-
<summary><b>Previous: What's new in v5.
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
## 🆕 What's new in v5.6.10
|
|
28
|
+
|
|
29
|
+
- 🔧 **OpenAI Codex provider fix** — Updated Codex model registry to match OpenAI's current API. Removed 6 deprecated models, retained 4 active ones: `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2`, `gpt-5.4-mini`.
|
|
30
|
+
- 🔀 **9Router API mode switch** — Switched from `openai-completions` to `openai-responses` to align with OpenAI's Responses API.
|
|
31
|
+
- 🩹 **Auto-patch 9Router** — New `patch-9router.js` automatically patches 9Router source files on setup, upgrade, and before every launch to stay compatible with Codex API changes.
|
|
32
|
+
- 🎯 **Direct Codex model targeting** — 9Router config now exposes individual Codex models alongside `smart-route` so users can pick a specific model.
|
|
33
|
+
- 💬 **Zalo Personal group config** — Added `defaultAccount`, `groupAllowFrom`, `historyLimit`, wildcard group config and `autoReply` for better out-of-the-box group handling.
|
|
34
|
+
|
|
35
|
+
<details>
|
|
36
|
+
<summary><b>Previous: What's new in v5.6.0</b></summary>
|
|
37
|
+
|
|
38
|
+
- 🧠 **Memory & Dreaming enabled by default** — Long-term Memory skill is now pre-selected for all new installations. The `memory-core` plugin with `dreaming.enabled: true` is auto-injected into `openclaw.json`, and `DREAMS.md` is seeded in every workspace.
|
|
39
|
+
- 🤝 **Relay plugin card auto-shows** — When selecting Telegram multi-bot (≥2 bots), the Relay plugin card appears with an "Auto-enabled" badge and locked checkbox. Switching back to 1 bot hides it.
|
|
40
|
+
- 🔑 **Relay trigger keywords in TEAMS.md** — `TEAMS.md` now documents all relay trigger keywords (question/task/reminder patterns) from the v5.0.9 relay plugin, helping bots understand and coordinate cross-bot communication.
|
|
41
|
+
- 🌍 **Proper Vietnamese diacritics** — All workspace `.md` files now use proper UTF-8 Vietnamese with full diacritics, eliminating mojibake.
|
|
42
|
+
- 👍 **Tool-based reaction** — `TOOLS.md` mandates bots call the `react` action with 👍 before replying, replacing unreliable gateway auto-ack.
|
|
43
|
+
|
|
45
44
|
</details>
|
|
46
45
|
|
|
47
46
|
---
|
package/README.vi.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# 🦞 OpenClaw Setup
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.
|
|
6
|
+
<a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.6.10-0EA5E9?style=for-the-badge" alt="Version 5.6.9" /></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,24 +24,23 @@ Công cụ **CLI tương tác** và **Setup Wizard** để tự triển khai Bot
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
## 🆕 Có gì mới trong v5.6.
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
<details>
|
|
36
|
-
<summary><b>Trước đó: Có gì mới ở v5.
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
## 🆕 Có gì mới trong v5.6.10
|
|
28
|
+
|
|
29
|
+
- 🔧 **Sửa provider OpenAI Codex** — Cập nhật registry model Codex phù hợp API hiện tại của OpenAI. Loại 6 model đã dừng, giữ 4 model đang hoạt động: `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2`, `gpt-5.4-mini`.
|
|
30
|
+
- 🔀 **Chuyển chế độ API 9Router** — Đổi từ `openai-completions` sang `openai-responses` cho khớp với Responses API mới của OpenAI.
|
|
31
|
+
- 🩹 **Tự động patch 9Router** — Script `patch-9router.js` mới tự vá source files 9Router khi setup, upgrade và trước mỗi lần khởi động để tương thích thay đổi API Codex.
|
|
32
|
+
- 🎯 **Chọn model Codex trực tiếp** — Config 9Router giờ hiển thị từng model Codex bên cạnh `smart-route` để người dùng có thể chọn model cụ thể.
|
|
33
|
+
- 💬 **Config nhóm Zalo Personal** — Bổ sung `defaultAccount`, `groupAllowFrom`, `historyLimit`, wildcard group config và `autoReply` để xử lý nhóm tốt hơn ngay từ đầu.
|
|
34
|
+
|
|
35
|
+
<details>
|
|
36
|
+
<summary><b>Trước đó: Có gì mới ở v5.6.0</b></summary>
|
|
37
|
+
|
|
38
|
+
- 🧠 **Memory & Dreaming bật mặc định** — Long-term Memory skill giờ được bật sẵn cho mọi cài đặt mới. Plugin `memory-core` với `dreaming.enabled: true` được inject tự động vào `openclaw.json`, `DREAMS.md` được tạo sẵn trong workspace.
|
|
39
|
+
- 🤝 **Card Relay plugin tự động hiển thị** — Khi chọn Telegram multi-bot (≥2 bots), card Relay plugin hiện ra với badge "Tự động bật" và checkbox bị khóa. Chuyển về 1 bot sẽ ẩn card.
|
|
40
|
+
- 🔑 **Từ khóa relay trong TEAMS.md** — `TEAMS.md` giờ liệt kê đầy đủ từ khóa kích hoạt relay (hỏi/giao việc/nhắc nhở) từ plugin v5.0.9, giúp bot hiểu và phối hợp tốt hơn.
|
|
41
|
+
- 🌍 **Tiếng Việt có dấu chuẩn** — Tất cả file `.md` workspace giờ dùng UTF-8 chuẩn với dấu tiếng Việt đầy đủ, hết lỗi mojibake.
|
|
42
|
+
- 👍 **Tool-based reaction** — `TOOLS.md` bắt buộc bot gọi action `react` thả 👍 trước khi trả lời, thay vì dùng gateway auto-ack không ổn định.
|
|
43
|
+
|
|
45
44
|
</details>
|
|
46
45
|
|
|
47
46
|
---
|
package/dist/cli.js
CHANGED
|
@@ -20,18 +20,25 @@ function loadSharedModule(modulePath, globalName) {
|
|
|
20
20
|
return globalThis[globalName] || loaded || {};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const {
|
|
24
|
-
OPENCLAW_NPM_SPEC,
|
|
25
|
-
OPENCLAW_RUNTIME_PACKAGES,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
const {
|
|
24
|
+
OPENCLAW_NPM_SPEC,
|
|
25
|
+
OPENCLAW_RUNTIME_PACKAGES,
|
|
26
|
+
NINE_ROUTER_PROXY_API_KEY,
|
|
27
|
+
NINE_ROUTER_API_BASE_URL,
|
|
28
|
+
SMART_ROUTE_PROVIDER_MODELS,
|
|
29
|
+
SMART_ROUTE_PROVIDER_ORDER,
|
|
30
|
+
TELEGRAM_RELAY_PLUGIN_SPEC,
|
|
31
|
+
TELEGRAM_SETUP_GUIDE_FILENAME,
|
|
32
|
+
buildRelayPluginInstallCommand,
|
|
33
|
+
buildTelegramPostInstallChecklist,
|
|
34
|
+
get9RouterBaseUrl,
|
|
35
|
+
build9RouterProviderConfig,
|
|
36
|
+
} = loadSharedModule('./setup/shared/common-gen.js', '__openclawCommon');
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
buildDockerArtifacts,
|
|
40
|
+
build9RouterPatchScript,
|
|
41
|
+
} = loadSharedModule('./setup/shared/docker-gen.js', '__openclawDockerGen');
|
|
35
42
|
|
|
36
43
|
const {
|
|
37
44
|
buildWorkspaceFileMap,
|
|
@@ -195,47 +202,30 @@ function resolveNative9RouterDesktopLaunch() {
|
|
|
195
202
|
|
|
196
203
|
function build9RouterSmartRouteSyncScript(dbPath) {
|
|
197
204
|
const safeDbPath = JSON.stringify(dbPath);
|
|
205
|
+
const safeRouterBaseUrl = JSON.stringify(NINE_ROUTER_API_BASE_URL);
|
|
206
|
+
const safeModelPriority = JSON.stringify(SMART_ROUTE_PROVIDER_MODELS);
|
|
207
|
+
const safeProviderOrder = JSON.stringify(SMART_ROUTE_PROVIDER_ORDER);
|
|
198
208
|
return `function bootstrap() {
|
|
199
209
|
const fs = require('fs');
|
|
200
210
|
const path = require('path');
|
|
201
211
|
const dbPath = ${safeDbPath};
|
|
202
|
-
const ROUTER
|
|
203
|
-
const MODEL_PRIORITY
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
kimi: ['kimi/kimi-k2.5', 'kimi/kimi-k2.5-thinking', 'kimi/kimi-latest'],
|
|
220
|
-
deepseek: ['deepseek/deepseek-chat', 'deepseek/deepseek-reasoner'],
|
|
221
|
-
xai: ['xai/grok-4', 'xai/grok-4-fast-reasoning', 'xai/grok-code-fast-1'],
|
|
222
|
-
mistral: ['mistral/mistral-large-latest', 'mistral/codestral-latest'],
|
|
223
|
-
groq: ['groq/llama-3.3-70b-versatile', 'groq/openai/gpt-oss-120b'],
|
|
224
|
-
cerebras: ['cerebras/gpt-oss-120b'],
|
|
225
|
-
alicode: ['alicode/qwen3.5-plus', 'alicode/qwen3-coder-plus'],
|
|
226
|
-
openai: ['openai/gpt-4o', 'openai/gpt-4.1'],
|
|
227
|
-
anthropic: ['anthropic/claude-sonnet-4', 'anthropic/claude-haiku-3.5'],
|
|
228
|
-
gemini: ['gemini/gemini-2.5-flash', 'gemini/gemini-2.5-pro'],
|
|
229
|
-
};
|
|
230
|
-
const sync = async () => {
|
|
231
|
-
try {
|
|
232
|
-
const response = await fetch(ROUTER + '/api/providers');
|
|
233
|
-
if (!response.ok) return;
|
|
234
|
-
const payload = await response.json();
|
|
235
|
-
const a = (payload.connections || [])
|
|
236
|
-
.filter((item) => item && item.provider && item.isActive !== false && !item.disabled)
|
|
237
|
-
.map((item) => item.provider);
|
|
238
|
-
let db = {};
|
|
212
|
+
const ROUTER=${safeRouterBaseUrl};
|
|
213
|
+
const MODEL_PRIORITY=${safeModelPriority};
|
|
214
|
+
const PREF=${safeProviderOrder};
|
|
215
|
+
const sync = async () => {
|
|
216
|
+
try {
|
|
217
|
+
const response = await fetch(ROUTER + '/api/providers');
|
|
218
|
+
if (!response.ok) return;
|
|
219
|
+
const payload = await response.json();
|
|
220
|
+
const rawConnections = Array.isArray(payload.connections)
|
|
221
|
+
? payload.connections
|
|
222
|
+
: Array.isArray(payload.providerConnections)
|
|
223
|
+
? payload.providerConnections
|
|
224
|
+
: [];
|
|
225
|
+
const a = [...new Set(rawConnections
|
|
226
|
+
.filter((item) => item && item.provider && item.isActive !== false && !item.disabled)
|
|
227
|
+
.map((item) => item.provider))];
|
|
228
|
+
let db = {};
|
|
239
229
|
try {
|
|
240
230
|
db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
|
|
241
231
|
} catch {}
|
|
@@ -249,11 +239,12 @@ function build9RouterSmartRouteSyncScript(dbPath) {
|
|
|
249
239
|
console.log('Removed smart-route (no active providers)');
|
|
250
240
|
}
|
|
251
241
|
};
|
|
252
|
-
if (!a.length) {
|
|
253
|
-
removeSmartRoute();
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
|
|
242
|
+
if (!a.length) {
|
|
243
|
+
removeSmartRoute();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
a.sort((x, y) => (PREF.indexOf(x) === -1 ? 99 : PREF.indexOf(x)) - (PREF.indexOf(y) === -1 ? 99 : PREF.indexOf(y)));
|
|
247
|
+
const m = a.flatMap((provider) => MODEL_PRIORITY[provider] || []);
|
|
257
248
|
if (!m.length) {
|
|
258
249
|
removeSmartRoute();
|
|
259
250
|
return;
|
|
@@ -450,15 +441,69 @@ function resolveCommandOnPath(command) {
|
|
|
450
441
|
}
|
|
451
442
|
}
|
|
452
443
|
|
|
453
|
-
async function writeNative9RouterSyncScript(projectDir) {
|
|
454
|
-
const syncScriptPath = path.join(projectDir, '.openclaw', '9router-smart-route-sync.js');
|
|
455
|
-
await fs.ensureDir(path.dirname(syncScriptPath));
|
|
456
|
-
// Use native home data dir so sync script writes to same place 9router binary reads from
|
|
457
|
-
const nativeDataDir = getNative9RouterDataDir();
|
|
458
|
-
await fs.ensureDir(nativeDataDir);
|
|
459
|
-
await fs.writeFile(syncScriptPath, build9RouterSmartRouteSyncScript(path.join(nativeDataDir, 'db.json')));
|
|
460
|
-
return syncScriptPath;
|
|
461
|
-
}
|
|
444
|
+
async function writeNative9RouterSyncScript(projectDir) {
|
|
445
|
+
const syncScriptPath = path.join(projectDir, '.openclaw', '9router-smart-route-sync.js');
|
|
446
|
+
await fs.ensureDir(path.dirname(syncScriptPath));
|
|
447
|
+
// Use native home data dir so sync script writes to same place 9router binary reads from
|
|
448
|
+
const nativeDataDir = getNative9RouterDataDir();
|
|
449
|
+
await fs.ensureDir(nativeDataDir);
|
|
450
|
+
await fs.writeFile(syncScriptPath, build9RouterSmartRouteSyncScript(path.join(nativeDataDir, 'db.json')));
|
|
451
|
+
return syncScriptPath;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
async function writeNative9RouterPatchScript(projectDir) {
|
|
455
|
+
const patchScriptPath = path.join(projectDir, '.openclaw', 'patch-9router.js');
|
|
456
|
+
await fs.ensureDir(path.dirname(patchScriptPath));
|
|
457
|
+
await fs.writeFile(patchScriptPath, build9RouterPatchScript());
|
|
458
|
+
return patchScriptPath;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
async function patchProject9RouterOpenClawConfig(projectDir) {
|
|
462
|
+
const configPath = path.join(projectDir, '.openclaw', 'openclaw.json');
|
|
463
|
+
if (!await fs.pathExists(configPath)) return false;
|
|
464
|
+
const config = await fs.readJson(configPath);
|
|
465
|
+
const provider = config?.models?.providers?.['9router'];
|
|
466
|
+
if (!provider) return false;
|
|
467
|
+
provider.baseUrl = get9RouterBaseUrl(detectProjectDeployMode(projectDir));
|
|
468
|
+
provider.apiKey = NINE_ROUTER_PROXY_API_KEY;
|
|
469
|
+
provider.api = 'openai-completions';
|
|
470
|
+
provider.models = build9RouterProviderConfig(provider.baseUrl).models;
|
|
471
|
+
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function patchProjectDocker9Router(projectDir) {
|
|
476
|
+
const dockerDir = path.join(projectDir, 'docker', 'openclaw');
|
|
477
|
+
const composePath = path.join(dockerDir, 'docker-compose.yml');
|
|
478
|
+
if (!await fs.pathExists(composePath)) return false;
|
|
479
|
+
|
|
480
|
+
await fs.ensureDir(dockerDir);
|
|
481
|
+
await fs.writeFile(path.join(dockerDir, 'sync.js'), build9RouterSmartRouteSyncScript('/root/.9router/db.json'));
|
|
482
|
+
await fs.writeFile(path.join(dockerDir, 'patch-9router.js'), build9RouterPatchScript());
|
|
483
|
+
let compose = await fs.readFile(composePath, 'utf8');
|
|
484
|
+
compose = compose.replace(
|
|
485
|
+
/node -e "require\('fs'\)\.writeFileSync\('\/tmp\/sync\.js',Buffer\.from\('[^']*','base64'\)\.toString\(\)\)"/,
|
|
486
|
+
"cp /opt/sync.js /tmp/sync.js"
|
|
487
|
+
);
|
|
488
|
+
compose = compose.replace(
|
|
489
|
+
/(npm install -g [^\n]+\n)/,
|
|
490
|
+
`$1 cp /opt/patch-9router.js /tmp/patch-9router.js\n`
|
|
491
|
+
);
|
|
492
|
+
if (!compose.includes('node /tmp/patch-9router.js || true')) {
|
|
493
|
+
compose = compose.replace(
|
|
494
|
+
/(\s*node \/tmp\/sync\.js > \/tmp\/sync\.log 2>&1 &\n)/,
|
|
495
|
+
` node /tmp/patch-9router.js || true\n$1`
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
if (!compose.includes('./sync.js:/opt/sync.js:ro')) {
|
|
499
|
+
compose = compose.replace(
|
|
500
|
+
/(\s*-\s*9router-data:\/root\/\.9router\s*\n)/,
|
|
501
|
+
`$1 - ./sync.js:/opt/sync.js:ro\n - ./patch-9router.js:/opt/patch-9router.js:ro\n`
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
await fs.writeFile(composePath, compose, 'utf8');
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
462
507
|
|
|
463
508
|
function getGatewayAllowedOrigins(port) {
|
|
464
509
|
const normalizedPort = Number(port) || 18791;
|
|
@@ -881,8 +926,26 @@ async function runUpgradeCommand() {
|
|
|
881
926
|
isVi: false,
|
|
882
927
|
}));
|
|
883
928
|
}
|
|
884
|
-
|
|
885
|
-
|
|
929
|
+
|
|
930
|
+
if (is9Router) {
|
|
931
|
+
await writeNative9RouterPatchScript(projectDir);
|
|
932
|
+
await patchProject9RouterOpenClawConfig(projectDir);
|
|
933
|
+
if (deployMode === 'docker') {
|
|
934
|
+
await patchProjectDocker9Router(projectDir);
|
|
935
|
+
} else {
|
|
936
|
+
await writeNative9RouterSyncScript(projectDir);
|
|
937
|
+
try {
|
|
938
|
+
execFileSync(process.execPath, [path.join(projectDir, '.openclaw', 'patch-9router.js')], {
|
|
939
|
+
cwd: projectDir,
|
|
940
|
+
stdio: 'ignore',
|
|
941
|
+
});
|
|
942
|
+
} catch {
|
|
943
|
+
// Best effort: start scripts also retry the patch before launch.
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
console.log(chalk.green('\nUpgrade artifacts refreshed successfully.'));
|
|
886
949
|
if (deployMode === 'docker') {
|
|
887
950
|
console.log(chalk.white(` Next: cd ${path.join(projectDir, 'docker', 'openclaw')} && docker compose up -d --build`));
|
|
888
951
|
} else {
|
|
@@ -892,6 +955,7 @@ async function runUpgradeCommand() {
|
|
|
892
955
|
|
|
893
956
|
function startNative9RouterPm2({ isVi, projectDir, appName, syncScriptPath }) {
|
|
894
957
|
const routerAppName = `${appName}-9router`;
|
|
958
|
+
const syncAppName = `${appName}-9router-sync`;
|
|
895
959
|
const routerLaunch = resolveNative9RouterDesktopLaunch();
|
|
896
960
|
const normalizedProjectDir = projectDir.replace(/\\/g, '/');
|
|
897
961
|
const normalizedSyncScriptPath = syncScriptPath ? syncScriptPath.replace(/\\/g, '/') : '';
|
|
@@ -921,7 +985,6 @@ function startNative9RouterPm2({ isVi, projectDir, appName, syncScriptPath }) {
|
|
|
921
985
|
env: { ...process.env, ...routerLaunch.env }
|
|
922
986
|
});
|
|
923
987
|
if (syncScriptPath) {
|
|
924
|
-
const syncAppName = `${appName}-9router-sync`;
|
|
925
988
|
try {
|
|
926
989
|
execSync(`pm2 delete ${syncAppName}`, {
|
|
927
990
|
cwd: projectDir,
|
|
@@ -2152,13 +2215,13 @@ async function main() {
|
|
|
2152
2215
|
} else if (providerKey === '9router') {
|
|
2153
2216
|
authProfilesJson = {
|
|
2154
2217
|
version: 1,
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2218
|
+
profiles: {
|
|
2219
|
+
'9router-proxy': {
|
|
2220
|
+
provider: '9router',
|
|
2221
|
+
type: 'api_key',
|
|
2222
|
+
key: NINE_ROUTER_PROXY_API_KEY,
|
|
2223
|
+
},
|
|
2224
|
+
},
|
|
2162
2225
|
order: { '9router': ['9router-proxy'] },
|
|
2163
2226
|
};
|
|
2164
2227
|
}
|
|
@@ -2230,21 +2293,14 @@ async function main() {
|
|
|
2230
2293
|
model: { primary: modelsPrimary, fallbacks: [] },
|
|
2231
2294
|
})),
|
|
2232
2295
|
},
|
|
2233
|
-
...(providerKey === '9router' ? {
|
|
2234
|
-
models: {
|
|
2235
|
-
mode: 'merge',
|
|
2236
|
-
providers: {
|
|
2237
|
-
'9router':
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
models: [
|
|
2242
|
-
{ id: 'smart-route', name: 'Smart Proxy (Auto Route)', contextWindow: 200000, maxTokens: 8192 },
|
|
2243
|
-
],
|
|
2244
|
-
},
|
|
2245
|
-
},
|
|
2246
|
-
},
|
|
2247
|
-
} : provider.isLocal ? {
|
|
2296
|
+
...(providerKey === '9router' ? {
|
|
2297
|
+
models: {
|
|
2298
|
+
mode: 'merge',
|
|
2299
|
+
providers: {
|
|
2300
|
+
'9router': build9RouterProviderConfig(get9RouterBaseUrl(deployMode)),
|
|
2301
|
+
},
|
|
2302
|
+
},
|
|
2303
|
+
} : provider.isLocal ? {
|
|
2248
2304
|
models: {
|
|
2249
2305
|
mode: 'merge',
|
|
2250
2306
|
providers: {
|
|
@@ -2299,9 +2355,9 @@ async function main() {
|
|
|
2299
2355
|
sharedConfig.skills = { entries: skillEntries };
|
|
2300
2356
|
}
|
|
2301
2357
|
|
|
2302
|
-
await fs.writeJson(path.join(rootClawDir, 'openclaw.json'), sharedConfig, { spaces: 2 });
|
|
2303
|
-
await fs.writeFile(
|
|
2304
|
-
path.join(projectDir, TELEGRAM_SETUP_GUIDE_FILENAME),
|
|
2358
|
+
await fs.writeJson(path.join(rootClawDir, 'openclaw.json'), sharedConfig, { spaces: 2 });
|
|
2359
|
+
await fs.writeFile(
|
|
2360
|
+
path.join(projectDir, TELEGRAM_SETUP_GUIDE_FILENAME),
|
|
2305
2361
|
buildTelegramPostInstallChecklist({ isVi, bots, groupId }),
|
|
2306
2362
|
'utf8',
|
|
2307
2363
|
);
|
|
@@ -2436,21 +2492,14 @@ async function main() {
|
|
|
2436
2492
|
model: { primary: modelsPrimary, fallbacks: [] }
|
|
2437
2493
|
}]
|
|
2438
2494
|
},
|
|
2439
|
-
...(providerKey === '9router' ? {
|
|
2440
|
-
models: {
|
|
2441
|
-
mode: 'merge',
|
|
2442
|
-
providers: {
|
|
2443
|
-
'9router':
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
models: [
|
|
2448
|
-
{ id: 'smart-route', name: 'Smart Proxy (Auto Route)', contextWindow: 200000, maxTokens: 8192 }
|
|
2449
|
-
]
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
} : provider.isLocal ? {
|
|
2495
|
+
...(providerKey === '9router' ? {
|
|
2496
|
+
models: {
|
|
2497
|
+
mode: 'merge',
|
|
2498
|
+
providers: {
|
|
2499
|
+
'9router': build9RouterProviderConfig(get9RouterBaseUrl(deployMode))
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
} : provider.isLocal ? {
|
|
2454
2503
|
models: {
|
|
2455
2504
|
mode: 'merge',
|
|
2456
2505
|
providers: {
|
|
@@ -2521,19 +2570,30 @@ async function main() {
|
|
|
2521
2570
|
};
|
|
2522
2571
|
}
|
|
2523
2572
|
botConfig.channels['telegram'] = telegramConfig;
|
|
2524
|
-
} else if (hasZaloPersonal(channelKey)) {
|
|
2525
|
-
botConfig.channels['zalouser'] = {
|
|
2526
|
-
enabled: true,
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2573
|
+
} else if (hasZaloPersonal(channelKey)) {
|
|
2574
|
+
botConfig.channels['zalouser'] = {
|
|
2575
|
+
enabled: true,
|
|
2576
|
+
defaultAccount: 'default',
|
|
2577
|
+
dmPolicy: 'open',
|
|
2578
|
+
allowFrom: ['*'],
|
|
2579
|
+
groupPolicy: 'allowlist',
|
|
2580
|
+
groupAllowFrom: ['*'],
|
|
2581
|
+
historyLimit: 50,
|
|
2582
|
+
groups: {
|
|
2583
|
+
'*': {
|
|
2584
|
+
enabled: true,
|
|
2585
|
+
requireMention: false,
|
|
2586
|
+
},
|
|
2587
|
+
},
|
|
2588
|
+
autoReply: true,
|
|
2589
|
+
};
|
|
2530
2590
|
} else if (channelKey === 'zalo-bot') {
|
|
2531
2591
|
botConfig.channels['zalo'] = { enabled: true, provider: 'official_account' };
|
|
2532
2592
|
}
|
|
2533
2593
|
|
|
2534
|
-
await fs.writeJson(path.join(loopBotDir, '.openclaw', 'openclaw.json'), botConfig, { spaces: 2 });
|
|
2535
|
-
|
|
2536
|
-
// ── Workspace files: use shared writeWorkspaceFiles() ──────────────────────
|
|
2594
|
+
await fs.writeJson(path.join(loopBotDir, '.openclaw', 'openclaw.json'), botConfig, { spaces: 2 });
|
|
2595
|
+
|
|
2596
|
+
// ── Workspace files: use shared writeWorkspaceFiles() ──────────────────────
|
|
2537
2597
|
const dockerWorkspaceDir = path.join(loopBotDir, '.openclaw', loopWorkspaceDir);
|
|
2538
2598
|
const dockerOwnAliases = [loopBotName, bots[bIndex]?.slashCmd || '', `bot ${bIndex + 1}`].filter(Boolean);
|
|
2539
2599
|
const dockerOtherAgents = teamRoster
|
|
@@ -2744,10 +2804,19 @@ async function main() {
|
|
|
2744
2804
|
}
|
|
2745
2805
|
}
|
|
2746
2806
|
|
|
2747
|
-
let native9RouterSyncScriptPath = null;
|
|
2748
|
-
if (providerKey === '9router') {
|
|
2749
|
-
|
|
2750
|
-
|
|
2807
|
+
let native9RouterSyncScriptPath = null;
|
|
2808
|
+
if (providerKey === '9router') {
|
|
2809
|
+
await writeNative9RouterPatchScript(projectDir);
|
|
2810
|
+
native9RouterSyncScriptPath = await writeNative9RouterSyncScript(projectDir);
|
|
2811
|
+
try {
|
|
2812
|
+
execFileSync(process.execPath, [path.join(projectDir, '.openclaw', 'patch-9router.js')], {
|
|
2813
|
+
cwd: projectDir,
|
|
2814
|
+
stdio: 'ignore',
|
|
2815
|
+
});
|
|
2816
|
+
} catch {
|
|
2817
|
+
// Start scripts retry this patch before launching 9router.
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2751
2820
|
|
|
2752
2821
|
await ensureProjectRuntimeDirs(projectDir, isVi);
|
|
2753
2822
|
|
|
@@ -2817,10 +2886,10 @@ async function main() {
|
|
|
2817
2886
|
cwd: projectDir,
|
|
2818
2887
|
env: getProjectRuntimeEnv(projectDir, native9RouterLaunch.env)
|
|
2819
2888
|
}).unref();
|
|
2820
|
-
const routerHealth = await waitFor9RouterApiReady();
|
|
2821
|
-
if (native9RouterSyncScriptPath) {
|
|
2822
|
-
spawnBackgroundProcess(process.execPath, [native9RouterSyncScriptPath], {
|
|
2823
|
-
cwd: projectDir
|
|
2889
|
+
const routerHealth = await waitFor9RouterApiReady();
|
|
2890
|
+
if (native9RouterSyncScriptPath) {
|
|
2891
|
+
spawnBackgroundProcess(process.execPath, [native9RouterSyncScriptPath], {
|
|
2892
|
+
cwd: projectDir
|
|
2824
2893
|
}).unref();
|
|
2825
2894
|
}
|
|
2826
2895
|
console.log(chalk.gray(isVi
|
|
@@ -65,15 +65,26 @@
|
|
|
65
65
|
channelConfig: {
|
|
66
66
|
zalouser: {
|
|
67
67
|
enabled: true,
|
|
68
|
+
defaultAccount: 'default',
|
|
68
69
|
accounts: {
|
|
69
70
|
default: {
|
|
70
71
|
dmPolicy: 'open',
|
|
71
72
|
allowFrom: ['*'],
|
|
72
73
|
groupPolicy: 'allowlist',
|
|
74
|
+
groupAllowFrom: ['*'],
|
|
73
75
|
},
|
|
74
76
|
},
|
|
75
77
|
dmPolicy: 'open',
|
|
78
|
+
allowFrom: ['*'],
|
|
76
79
|
groupPolicy: 'allowlist',
|
|
80
|
+
groupAllowFrom: ['*'],
|
|
81
|
+
historyLimit: 50,
|
|
82
|
+
groups: {
|
|
83
|
+
'*': {
|
|
84
|
+
enabled: true,
|
|
85
|
+
requireMention: false,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
77
88
|
},
|
|
78
89
|
},
|
|
79
90
|
pluginInstall: '@openclaw/zalouser',
|
|
@@ -161,4 +172,3 @@
|
|
|
161
172
|
- ❌ DO NOT run containers with --privileged
|
|
162
173
|
- ✅ Limit exposed ports (only 38789)`,
|
|
163
174
|
};
|
|
164
|
-
|