create-openclaw-bot 5.16.5 → 5.16.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  *Run one command → open the dashboard → your bot is live. Windows · macOS · Linux · VPS — Docker-powered, auto-installed for you.*
8
8
 
9
9
  <p align="center">
10
- <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.16.5-0EA5E9?style=for-the-badge" alt="Version 5.16.5" /></a>
10
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.16.6-0EA5E9?style=for-the-badge" alt="Version 5.16.6" /></a>
11
11
  <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>
12
12
  <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>
13
13
  <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>
@@ -37,7 +37,7 @@
37
37
 
38
38
  ---
39
39
 
40
- ## 🆕 What's New in v5.16.5
40
+ ## 🆕 What's New in v5.16.6
41
41
 
42
42
  - 🩹 **Native installs on OpenClaw 2026.8 are smooth from the first run** - this wave patches the remaining chain of issues measured on fresh customer machines: generated configs pass the new strict checks 100%, install steps run in the right order, and restarts/plugin installs no longer get blocked midway.
43
43
  - 🔑 **9Router login works on Docker**: the new 9Router blocks the default password for "remote" access - and inside Docker every request counts as remote, so 123456 could never log in. It works now (still change the password once you're in).
package/README.vi.md CHANGED
@@ -7,7 +7,7 @@
7
7
  *Chạy một lệnh → mở dashboard → bot lên sóng. Windows · macOS · Linux · VPS — chạy trên Docker, tự cài giúp bạn.*
8
8
 
9
9
  <p align="center">
10
- <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.16.5-0EA5E9?style=for-the-badge" alt="Version 5.16.5" /></a>
10
+ <a href="https://github.com/tuanminhhole/openclaw-setup/releases"><img src="https://img.shields.io/badge/RELEASE-v5.16.6-0EA5E9?style=for-the-badge" alt="Version 5.16.6" /></a>
11
11
  <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>
12
12
  <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>
13
13
  <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>
@@ -37,7 +37,7 @@
37
37
 
38
38
  ---
39
39
 
40
- ## 🆕 Có gì mới trong v5.16.5
40
+ ## 🆕 Có gì mới trong v5.16.6
41
41
 
42
42
  - 🩹 **Cài native trên OpenClaw 2026.8 mượt từ phát đầu** - đợt này vá nốt chuỗi lỗi đo được khi dựng máy khách mới: cấu hình sinh ra sạch 100% với bộ soát khắt khe của OpenClaw mới, các bước cài tự chạy đúng thứ tự, và mọi thao tác khởi động lại/cài plugin không còn bị chặn giữa chừng.
43
43
  - 🔑 **Đăng nhập 9Router hoạt động trên Docker**: bản 9Router mới chặn mật khẩu mặc định với truy cập "từ xa" - mà trong Docker thì mọi truy cập đều bị tính là từ xa, nên trước đây không cách nào vào được bằng 123456. Giờ đăng nhập bình thường (vào rồi vẫn nên đổi mật khẩu).
@@ -1794,6 +1794,22 @@ function bindingChannelId(channel = '') {
1794
1794
  return channel;
1795
1795
  }
1796
1796
 
1797
+ // OpenClaw ≥2026.8 materialises a DEFAULT agent `main` ("Trợ lý OpenClaw") the first time a
1798
+ // gateway boots against a roster it considers empty — which is exactly what happens in Docker
1799
+ // mode, where `docker compose up` runs while the project still has zero bots (writeCoreProject
1800
+ // seeds agents with an empty list). The entry is legitimate OpenClaw state and is left alone in
1801
+ // openclaw.json, but it is NOT a bot the operator created: showing it next to the real bot made
1802
+ // customers think a second Zalo bot appeared out of nowhere (measured on vps_tracy-hong, 03/09).
1803
+ //
1804
+ // Identified by disk, not by name: every bot this setup creates gets `workspace` in the config
1805
+ // AND that directory on disk. The materialised default has neither, so an operator who really
1806
+ // does name their bot `main` is never hidden.
1807
+ function isPhantomMainAgent(agent, projectDir, agentCount) {
1808
+ if (!agent || agent.id !== 'main' || agentCount < 2) return false;
1809
+ if (!agent.workspace) return true;
1810
+ return !existsSync(join(projectDir, agent.workspace));
1811
+ }
1812
+
1797
1813
  async function listConfiguredBots(projectDir) {
1798
1814
  const cfgPath = join(projectDir || '', '.openclaw', 'openclaw.json');
1799
1815
  if (!projectDir || !existsSync(cfgPath)) return [];
@@ -1801,7 +1817,8 @@ async function listConfiguredBots(projectDir) {
1801
1817
  const cfg = ensureConfigShape(parseJsonText(raw));
1802
1818
  const normalized = JSON.stringify(cfg, null, 2) + '\n';
1803
1819
  if (normalized !== raw) await fsp.writeFile(cfgPath, normalized, 'utf8');
1804
- const rows = await Promise.all(cfg.agents.list.map(async (agent) => {
1820
+ const roster = cfg.agents.list.filter((agent) => !isPhantomMainAgent(agent, projectDir, cfg.agents.list.length));
1821
+ const rows = await Promise.all(roster.map(async (agent) => {
1805
1822
  const identity = await readAgentIdentity(projectDir, agent);
1806
1823
  const meta = await readBotMeta(projectDir, agent, cfg);
1807
1824
  const env = await readProjectEnv(projectDir);
@@ -2395,10 +2412,32 @@ async function startZaloLogin(projectDir, agentId = "") {
2395
2412
  probeCacheClear(`zalohealth:${projectDir || ''}`);
2396
2413
  const cfgPath = join(projectDir, ".openclaw", "openclaw.json");
2397
2414
  if (!existsSync(cfgPath)) throw httpError(404, "openclaw.json not found");
2398
- const cfg = JSON.parse(await fsp.readFile(cfgPath, "utf8"));
2399
- const binding = (cfg.bindings || []).find((b) =>
2415
+ const raw = await fsp.readFile(cfgPath, "utf8");
2416
+ const cfg = ensureConfigShape(parseJsonText(raw));
2417
+ let binding = (cfg.bindings || []).find((b) =>
2400
2418
  (!agentId || b.agentId === agentId) && b.match?.channel === "zalo-connect"
2401
2419
  );
2420
+ // A roster with more than one agent makes OpenClaw ≥2026.8 refuse any channel operation that
2421
+ // cannot name its owner: `AgentSelectionRequiredError — Multiple agents are configured, but
2422
+ // this operation has no explicit owner`. That is exactly what a Docker project looks like once
2423
+ // the gateway has materialised its default `main` agent alongside the real bot, and the QR
2424
+ // login dies with it (measured on vps_tracy-hong, 03/09).
2425
+ //
2426
+ // `openclaw channels login` has no --agent flag (2026.8.1: only --channel/--account/--verbose),
2427
+ // and neither does the channels.start call it makes into the gateway — so the owner can only be
2428
+ // named the way OpenClaw's own error hint says: through a binding. Pin one to the real bot
2429
+ // before the QR starts. Additive: an existing binding is never rewritten, and the phantom
2430
+ // `main` is never the target.
2431
+ if (!binding) {
2432
+ const roster = (cfg.agents.list || []).filter((a) => !isPhantomMainAgent(a, projectDir, (cfg.agents.list || []).length));
2433
+ const target = (agentId && roster.some((a) => a.id === agentId)) ? agentId : roster[0]?.id;
2434
+ if (target) {
2435
+ binding = { agentId: target, match: { channel: 'zalo-connect', accountId: 'default' } };
2436
+ cfg.bindings = [...(cfg.bindings || []), binding];
2437
+ await fsp.writeFile(cfgPath, JSON.stringify(cfg, null, 2) + '\n', 'utf8');
2438
+ sendLog(`[zalo-connect] No zalo-connect binding found — pinned this QR login to agent [${target}] so OpenClaw knows who owns the channel.`);
2439
+ }
2440
+ }
2402
2441
  return startZaloConnectLogin(projectDir, binding?.match?.accountId || "default");
2403
2442
  }
2404
2443
 
@@ -196,13 +196,15 @@
196
196
  // arbitrary emoji globally would make those channels reject every ack, so other
197
197
  // channels keep their existing behaviour until someone picks a value valid there.
198
198
  //
199
- // 🦞 is sent as a Zalo *custom* reaction (emoji as rIcon + a hash as rType), which
200
- // needs zalo-connect ≥3.0.15 earlier versions only knew the 55 built-ins and would
201
- // drop it silently. Scope "all" covers DMs and groups; in a mention-gated group the
202
- // plugin still only reacts to messages that address the bot, since non-addressed ones
203
- // are buffered as passive context before the reaction step.
199
+ // `/-heart` is one of Zalo's 55 BUILT-IN reactions, so every zalo-connect version can
200
+ // send it. The previous default (🦞) went out as a Zalo *custom* reaction (emoji as
201
+ // rIcon + a hash as rType), which needs zalo-connect ≥3.0.15 on anything older it was
202
+ // dropped silently and the bot looked unresponsive until the reply landed.
203
+ // Scope "all" covers DMs and groups; in a mention-gated group the plugin still only
204
+ // reacts to messages that address the bot, since non-addressed ones are buffered as
205
+ // passive context before the reaction step.
204
206
  if (isZaloPersonal(channelKey)) {
205
- cfg.messages = { ackReaction: '🦞', ackReactionScope: 'all', removeAckAfterReply: false };
207
+ cfg.messages = { ackReaction: '/-heart', ackReactionScope: 'all', removeAckAfterReply: false };
206
208
  }
207
209
 
208
210
  // ── commands ──────────────────────────────────────────────────────────────
@@ -382,8 +382,11 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
382
382
  // seeded. Kept out of the shared migration because zalo-connect reads the GLOBAL
383
383
  // messages.ackReaction, and that same key also feeds Telegram/Discord/Slack/
384
384
  // WhatsApp — which accept only their own fixed reaction sets and would reject an
385
- // arbitrary emoji. Absent-only, so an operator's own choice is never overwritten.
386
- const ackReactionScript = `const fs=require('fs'),path=require('path');const p=path.join(process.cwd(),'.openclaw','openclaw.json');if(fs.existsSync(p)){const c=JSON.parse(fs.readFileSync(p,'utf8'));let ch=false;c.messages=c.messages||{};if(c.messages.ackReaction===undefined){c.messages.ackReaction='🦞';ch=true;}if(c.messages.ackReactionScope===undefined){c.messages.ackReactionScope='all';ch=true;}if(ch)fs.writeFileSync(p,JSON.stringify(c,null,2));}`;
385
+ // arbitrary emoji. Absent-only, so an operator's own choice is never overwritten
386
+ // with one exception: the 🦞 this script itself used to seed is rewritten to
387
+ // `/-heart`. 🦞 only ships as a Zalo CUSTOM reaction (needs zalo-connect ≥3.0.15,
388
+ // silently dropped below that); `/-heart` is a built-in every version can send.
389
+ const ackReactionScript = `const fs=require('fs'),path=require('path');const p=path.join(process.cwd(),'.openclaw','openclaw.json');if(fs.existsSync(p)){const c=JSON.parse(fs.readFileSync(p,'utf8'));let ch=false;c.messages=c.messages||{};if(c.messages.ackReaction===undefined||c.messages.ackReaction==='🦞'){c.messages.ackReaction='/-heart';ch=true;}if(c.messages.ackReactionScope===undefined){c.messages.ackReactionScope='all';ch=true;}if(ch)fs.writeFileSync(p,JSON.stringify(c,null,2));}`;
387
390
  runtimeParts.push(`node - <<'NODE'\n${ackReactionScript}\nNODE`);
388
391
  }
389
392
  // Always-on memory context engine for every bot (see bot-config-gen: plugins.slots
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "5.16.5",
3
+ "version": "5.16.6",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {