create-openclaw-bot 5.8.1 → 5.8.3

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.
@@ -204,6 +204,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
204
204
  is9Router,
205
205
  isLocal,
206
206
  isMultiBot,
207
+ hasBrowser = false,
207
208
  selectedModel,
208
209
  agentId,
209
210
  allSkills = [],
@@ -321,6 +322,10 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
321
322
  ].join('\n'));
322
323
  runtimeParts.push('openclaw gateway run');
323
324
  const runtimeScript = ['#!/bin/sh', 'set -e', ...runtimeParts].join('\n');
325
+ let browserInstall = '';
326
+ if (hasBrowser) {
327
+ browserInstall = '\n# Install browser and system dependencies for Playwright\nRUN npx playwright install-deps chromium && npx playwright install chromium\n';
328
+ }
324
329
  const dockerfile = `FROM node:22-slim
325
330
 
326
331
  RUN apt-get update && apt-get install -y git curl python3 && rm -rf /var/lib/apt/lists/*
@@ -328,7 +333,7 @@ RUN apt-get update && apt-get install -y git curl python3 && rm -rf /var/lib/apt
328
333
  ARG OPENCLAW_VER="${openClawNpmSpec}"
329
334
  ARG CACHE_BUST=""
330
335
  RUN echo "CACHE_BUST=$CACHE_BUST" && npm install -g $OPENCLAW_VER ${openClawRuntimePackages}${skillLines}${pluginLines}
331
- ${patchLine}
336
+ ${patchLine}${browserInstall}
332
337
 
333
338
  COPY entrypoint.sh /usr/local/bin/openclaw-entrypoint.sh
334
339
  RUN chmod +x /usr/local/bin/openclaw-entrypoint.sh
@@ -628,9 +628,13 @@ node ${btPath} close_tab 2`;
628
628
  ? (isVi
629
629
  ? `\n\n## \u23F0 Cron / Lên lịch nhắc nhở (tool: \`cron\`)
630
630
  - **Tên tool chính xác:** Tên công cụ là \`cron\` (tuyệt đối không nhầm là \`native\` hay command line bên ngoài).
631
+ - **⛔ TUYỆT ĐỐI KHÔNG sửa trực tiếp file JSON** như \`jobs.json\`, \`jobs-state.json\` trong thư mục \`.openclaw/cron/\`. Dữ liệu cron được lưu trong SQLite database, file JSON chỉ là legacy format đã ngưng hỗ trợ. Mọi thao tác PHẢI thông qua tool \`cron\`.
631
632
  - **Khi tạo cronjob mới (action \`add\`):**
632
633
  - **TUYỆT ĐỐI KHÔNG điền trường \`agentId\`** trong object \`job\` (hãy bỏ qua/omitted trường này). Hệ thống OpenClaw sẽ tự động gán chính xác ID của bạn vào job đó.
633
634
  - Tuyệt đối **không tự điền** \`agentId\` là \`"bot"\` hay \`"main"\`, vì làm vậy sẽ khiến cronjob thuộc về agent khác và bạn sẽ mất quyền kiểm soát/xóa nó sau này.
635
+ - **Session:** Luôn dùng \`sessionTarget: "isolated"\` cho các job chạy nền (báo cáo, nhắc nhở, gửi tin nhắn tự động). Chỉ dùng \`"main"\` cho system event/reminder ngắn.
636
+ - **Timezone:** Luôn chỉ định timezone rõ ràng bằng trường \`tz\` (ví dụ: \`"Asia/Ho_Chi_Minh"\`). Nếu không chỉ định, hệ thống sẽ dùng timezone của Gateway host (thường là UTC) và job sẽ chạy sai giờ.
637
+ - **Delivery:** Đối với job cần gửi kết quả ra chat, set \`delivery.mode: "announce"\` kèm \`delivery.channel\` và \`delivery.to\`.
634
638
  - **Khi user yêu cầu tắt/bật/xóa cronjob:**
635
639
  1. **Bước 1 (Tìm kiếm):** Gọi tool \`cron\` với action \`list\` (và \`includeDisabled: true\`) để xem danh sách tất cả cronjob đang chạy trên hệ thống và tìm đúng \`jobId\` phù hợp với yêu cầu.
636
640
  2. **Bước 2 (Xử lý):**
@@ -640,13 +644,18 @@ node ${btPath} close_tab 2`;
640
644
  3. **Tuyên bố trung thực:** Tuyệt đối không bao giờ trả lời "đã xóa" hay "không có" dựa trên suy đoán của bản thân mà chưa gọi tool \`cron\` để kiểm tra thực tế.
641
645
  - Khi user yêu cầu tạo nhắc nhở / lệnh tự động định kỳ, bạn hãy TỰ ĐỘNG dùng tool \`cron\` (action \`add\`) để tạo. **Tuyệt đối không** bắt user dùng crontab hay Task Scheduler chạy tay trên host.
642
646
  - Khi thao tác tool cho cron/scheduler, **không điền \`current\` vào thư mục Session**.
643
- - **QUAN TRỌNG VỀ TARGETING GROUP CHAT**: Khi tạo hoặc cấu hình cron job gửi tin nhắn thông báo (announce mode) đến một Group Chat, giá trị của trường \`delivery.to\` **bắt buộc** phải sử dụng tiền tố \`group:\` trước ID của group (ví dụ: \`group:3815464776067464419\` hoặc \`group:xxxx\`). Tuyệt đối không được chỉ điền ID thuần túy hệ thống sẽ hiểu nhầm đó một DM chat nhân (direct message) gửi sai địa chỉ.
647
+ - **QUAN TRỌNG VỀ TARGETING GROUP CHAT**: Khi tạo hoặc cấu hình cron job gửi tin nhắn thông báo (announce mode) đến một Group Chat, giá trị của trường \`delivery.to\` **bắt buộc** phải sử dụng tiền tố thích hợp trước ID của group. Với kênh Telegram/Matrix/Discord/Slack, dùng tiền tố \`group:\` (ví dụ: \`group:123456\`). RIÊNG với kênh Zalo (\`zalouser\`), **bắt buộc** phải sử dụng tiền tố \`g:\` (ví dụ: \`g:3815464776067464419\`) để tránh bị OpenClaw core lược bỏ tiền tố gửi nhầm vào DM chat nhân.
648
+ - **One-shot job:** Dùng schedule kind \`"at"\` với ISO 8601 timestamp. Job sẽ tự xóa sau khi chạy thành công trừ khi set \`deleteAfterRun: false\`.
644
649
  - Bỏ qua việc tra cứu docs nội bộ như \`cron-jobs.mdx\`; tin tưởng khả năng dùng tool hiện có để hoàn thành yêu cầu.`
645
650
  : `\n\n## \u23F0 Cron / Scheduled Tasks (tool: \`cron\`)
646
651
  - **Exact tool name:** The tool name is \`cron\` (never mistake it for \`native\` or external command lines).
652
+ - **⛔ NEVER edit JSON files directly** such as \`jobs.json\` or \`jobs-state.json\` in \`.openclaw/cron/\`. Cron data is stored in SQLite database; JSON files are legacy format no longer supported. All operations MUST go through the \`cron\` tool.
647
653
  - **When creating a new cronjob (action \`add\`):**
648
654
  - **ABSOLUTELY DO NOT specify the \`agentId\` field** in the \`job\` object (leave this field omitted). The OpenClaw system will automatically assign your correct agent ID to that job.
649
655
  - Never manually specify \`agentId\` as \`"bot"\` or \`"main"\`, as this will cause the cronjob to belong to another agent and you will lose control to manage/delete it later.
656
+ - **Session:** Always use \`sessionTarget: "isolated"\` for background jobs (reports, reminders, automated messages). Only use \`"main"\` for short system events/reminders.
657
+ - **Timezone:** Always specify timezone explicitly via the \`tz\` field (e.g., \`"Asia/Ho_Chi_Minh"\`). If omitted, the system uses the Gateway host timezone (often UTC) and the job will run at the wrong time.
658
+ - **Delivery:** For jobs that should send results to chat, set \`delivery.mode: "announce"\` with \`delivery.channel\` and \`delivery.to\`.
650
659
  - **When the user requests to disable/enable/delete a cronjob:**
651
660
  1. **Step 1 (Search):** Call the \`cron\` tool with action \`list\` (and \`includeDisabled: true\`) to view all cron jobs on the system and find the matching \`jobId\`.
652
661
  2. **Step 2 (Processing):**
@@ -656,7 +665,8 @@ node ${btPath} close_tab 2`;
656
665
  3. **Honest statement:** Never claim a job is "deleted" or "not found" based on guessing without calling the \`cron\` tool to verify the actual state.
657
666
  - When the user asks to schedule tasks or reminders, use the built-in \`cron\` tool (action \`add\`) automatically. Do NOT ask users to run crontab or Task Scheduler manually on the host.
658
667
  - When operating cron/scheduler tools, do **not** put \`current\` into the Session directory.
659
- - **IMPORTANT ABOUT GROUP CHAT TARGETING**: When creating or configuring a cron job to send messages (announce mode) to a Group Chat, the value of the \`delivery.to\` field **must** use the \`group:\` prefix before the group ID (e.g., \`group:3815464776067464419\` or \`group:xxxx\`). Never specify just the numeric ID, as the system will interpret it as a private DM and deliver to the wrong destination.
668
+ - **IMPORTANT ABOUT GROUP CHAT TARGETING**: When creating or configuring a cron job to send messages (announce mode) to a Group Chat, the value of the \`delivery.to\` field **must** use the appropriate prefix before the group ID. For Telegram/Matrix/Discord/Slack, use the \`group:\` prefix (e.g., \`group:123456\`). ESPECIALLY for Zalo (\`zalouser\`), you **must** use the \`g:\` prefix (e.g., \`g:3815464776067464419\`) to prevent the OpenClaw core from stripping the prefix and misrouting the message to a private DM.
669
+ - **One-shot jobs:** Use schedule kind \`"at"\` with an ISO 8601 timestamp. The job auto-deletes after successful run unless \`deleteAfterRun: false\` is set.
660
670
  - Skip internal doc lookups such as \`cron-jobs.mdx\`; rely on the available tools and complete the scheduling task directly.`)
661
671
  : '';
662
672
 
package/dist/setup.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /* ============================================
2
- OpenClaw Setup Wizard — Logic v2
2
+ OpenClaw Setup Wizard Logic v2
3
3
  Multi-model, Multi-plugin, Multi-channel
4
4
  ============================================ */
5
- // AUTO-GENERATED by build.mjs — edit files in src/setup/ instead
5
+ // AUTO-GENERATED by build.mjs edit files in src/setup/ instead
6
6
 
7
7
  (function () {
8
8
  'use strict';
9
9
 
10
- // ── Globals: CDN logos, state, shared utils (setup/data/header.js) ─
10
+ // ── ── Globals: CDN logos, state, shared utils (setup/data/header.js) ──
11
11
  // @ts-nocheck
12
12
  /* eslint-disable no-undef, no-unused-vars */
13
13
  /**
@@ -89,7 +89,7 @@
89
89
  return Array.from(origins);
90
90
  }
91
91
 
92
- // ── PROVIDERS object (setup/data/providers.js) ─────────────────────
92
+ // ── ── PROVIDERS object (setup/data/providers.js) ──────────────────────────────────────────
93
93
  // @ts-nocheck
94
94
  /* eslint-disable no-undef, no-unused-vars */
95
95
  /**
@@ -212,7 +212,7 @@
212
212
  };
213
213
 
214
214
 
215
- // ── CHANNELS, system prompts, security rules (setup/data/channels.js)
215
+ // ── ── CHANNELS, system prompts, security rules (setup/data/channels.js)
216
216
  // @ts-nocheck
217
217
  /* eslint-disable no-undef, no-unused-vars */
218
218
  /**
@@ -383,7 +383,7 @@
383
383
  - ✅ Limit exposed ports (only 38789)`,
384
384
  };
385
385
 
386
- // ── PLUGINS list (setup/data/plugins.js) ───────────────────────────
386
+ // ── ── PLUGINS list (setup/data/plugins.js) ──────────────────────────────────────────────────────
387
387
  // @ts-nocheck
388
388
  /* eslint-disable no-undef, no-unused-vars */
389
389
  /**
@@ -452,7 +452,7 @@
452
452
  ];
453
453
 
454
454
 
455
- // ── SKILLS list (setup/data/skills.js) ─────────────────────────────
455
+ // ── ── SKILLS list (setup/data/skills.js) ──────────────────────────────────────────────────────────
456
456
  // @ts-nocheck
457
457
  /* eslint-disable no-undef, no-unused-vars */
458
458
  /**
@@ -615,7 +615,7 @@
615
615
  }
616
616
 
617
617
 
618
- // ── Shared runtime constants, relay helpers, auth profile builders (setup/shared/common-gen.js)
618
+ // ── ── Shared runtime constants, relay helpers, auth profile builders (setup/shared/common-gen.js)
619
619
  // @ts-nocheck
620
620
  (function (root) {
621
621
  const OPENCLAW_NPM_SPEC = 'openclaw@latest';
@@ -930,7 +930,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
930
930
  Object.assign(exports, globalThis.__openclawCommon);
931
931
  }
932
932
 
933
- // ── Shared workspace file builders (IDENTITY, SOUL, AGENTS, TOOLS, TEAMS...) (setup/shared/workspace-gen.js)
933
+ // ── ── Shared workspace file builders (IDENTITY, SOUL, AGENTS, TOOLS, TEAMS...) (setup/shared/workspace-gen.js)
934
934
  /** @typedef {typeof globalThis & { __openclawWorkspace?: Record<string, Function> }} OpenClawWorkspaceRoot */
935
935
 
936
936
  const workspaceRoot = /** @type {OpenClawWorkspaceRoot} */ (
@@ -1561,9 +1561,13 @@ node ${btPath} close_tab 2`;
1561
1561
  ? (isVi
1562
1562
  ? `\n\n## \u23F0 Cron / Lên lịch nhắc nhở (tool: \`cron\`)
1563
1563
  - **Tên tool chính xác:** Tên công cụ là \`cron\` (tuyệt đối không nhầm là \`native\` hay command line bên ngoài).
1564
+ - **⛔ TUYỆT ĐỐI KHÔNG sửa trực tiếp file JSON** như \`jobs.json\`, \`jobs-state.json\` trong thư mục \`.openclaw/cron/\`. Dữ liệu cron được lưu trong SQLite database, file JSON chỉ là legacy format đã ngưng hỗ trợ. Mọi thao tác PHẢI thông qua tool \`cron\`.
1564
1565
  - **Khi tạo cronjob mới (action \`add\`):**
1565
1566
  - **TUYỆT ĐỐI KHÔNG điền trường \`agentId\`** trong object \`job\` (hãy bỏ qua/omitted trường này). Hệ thống OpenClaw sẽ tự động gán chính xác ID của bạn vào job đó.
1566
1567
  - Tuyệt đối **không tự điền** \`agentId\` là \`"bot"\` hay \`"main"\`, vì làm vậy sẽ khiến cronjob thuộc về agent khác và bạn sẽ mất quyền kiểm soát/xóa nó sau này.
1568
+ - **Session:** Luôn dùng \`sessionTarget: "isolated"\` cho các job chạy nền (báo cáo, nhắc nhở, gửi tin nhắn tự động). Chỉ dùng \`"main"\` cho system event/reminder ngắn.
1569
+ - **Timezone:** Luôn chỉ định timezone rõ ràng bằng trường \`tz\` (ví dụ: \`"Asia/Ho_Chi_Minh"\`). Nếu không chỉ định, hệ thống sẽ dùng timezone của Gateway host (thường là UTC) và job sẽ chạy sai giờ.
1570
+ - **Delivery:** Đối với job cần gửi kết quả ra chat, set \`delivery.mode: "announce"\` kèm \`delivery.channel\` và \`delivery.to\`.
1567
1571
  - **Khi user yêu cầu tắt/bật/xóa cronjob:**
1568
1572
  1. **Bước 1 (Tìm kiếm):** Gọi tool \`cron\` với action \`list\` (và \`includeDisabled: true\`) để xem danh sách tất cả cronjob đang chạy trên hệ thống và tìm đúng \`jobId\` phù hợp với yêu cầu.
1569
1573
  2. **Bước 2 (Xử lý):**
@@ -1573,13 +1577,18 @@ node ${btPath} close_tab 2`;
1573
1577
  3. **Tuyên bố trung thực:** Tuyệt đối không bao giờ trả lời "đã xóa" hay "không có" dựa trên suy đoán của bản thân mà chưa gọi tool \`cron\` để kiểm tra thực tế.
1574
1578
  - Khi user yêu cầu tạo nhắc nhở / lệnh tự động định kỳ, bạn hãy TỰ ĐỘNG dùng tool \`cron\` (action \`add\`) để tạo. **Tuyệt đối không** bắt user dùng crontab hay Task Scheduler chạy tay trên host.
1575
1579
  - Khi thao tác tool cho cron/scheduler, **không điền \`current\` vào thư mục Session**.
1576
- - **QUAN TRỌNG VỀ TARGETING GROUP CHAT**: Khi tạo hoặc cấu hình cron job gửi tin nhắn thông báo (announce mode) đến một Group Chat, giá trị của trường \`delivery.to\` **bắt buộc** phải sử dụng tiền tố \`group:\` trước ID của group (ví dụ: \`group:3815464776067464419\` hoặc \`group:xxxx\`). Tuyệt đối không được chỉ điền ID thuần túy hệ thống sẽ hiểu nhầm đó một DM chat nhân (direct message) gửi sai địa chỉ.
1580
+ - **QUAN TRỌNG VỀ TARGETING GROUP CHAT**: Khi tạo hoặc cấu hình cron job gửi tin nhắn thông báo (announce mode) đến một Group Chat, giá trị của trường \`delivery.to\` **bắt buộc** phải sử dụng tiền tố thích hợp trước ID của group. Với kênh Telegram/Matrix/Discord/Slack, dùng tiền tố \`group:\` (ví dụ: \`group:123456\`). RIÊNG với kênh Zalo (\`zalouser\`), **bắt buộc** phải sử dụng tiền tố \`g:\` (ví dụ: \`g:3815464776067464419\`) để tránh bị OpenClaw core lược bỏ tiền tố gửi nhầm vào DM chat nhân.
1581
+ - **One-shot job:** Dùng schedule kind \`"at"\` với ISO 8601 timestamp. Job sẽ tự xóa sau khi chạy thành công trừ khi set \`deleteAfterRun: false\`.
1577
1582
  - Bỏ qua việc tra cứu docs nội bộ như \`cron-jobs.mdx\`; tin tưởng khả năng dùng tool hiện có để hoàn thành yêu cầu.`
1578
1583
  : `\n\n## \u23F0 Cron / Scheduled Tasks (tool: \`cron\`)
1579
1584
  - **Exact tool name:** The tool name is \`cron\` (never mistake it for \`native\` or external command lines).
1585
+ - **⛔ NEVER edit JSON files directly** such as \`jobs.json\` or \`jobs-state.json\` in \`.openclaw/cron/\`. Cron data is stored in SQLite database; JSON files are legacy format no longer supported. All operations MUST go through the \`cron\` tool.
1580
1586
  - **When creating a new cronjob (action \`add\`):**
1581
1587
  - **ABSOLUTELY DO NOT specify the \`agentId\` field** in the \`job\` object (leave this field omitted). The OpenClaw system will automatically assign your correct agent ID to that job.
1582
1588
  - Never manually specify \`agentId\` as \`"bot"\` or \`"main"\`, as this will cause the cronjob to belong to another agent and you will lose control to manage/delete it later.
1589
+ - **Session:** Always use \`sessionTarget: "isolated"\` for background jobs (reports, reminders, automated messages). Only use \`"main"\` for short system events/reminders.
1590
+ - **Timezone:** Always specify timezone explicitly via the \`tz\` field (e.g., \`"Asia/Ho_Chi_Minh"\`). If omitted, the system uses the Gateway host timezone (often UTC) and the job will run at the wrong time.
1591
+ - **Delivery:** For jobs that should send results to chat, set \`delivery.mode: "announce"\` with \`delivery.channel\` and \`delivery.to\`.
1583
1592
  - **When the user requests to disable/enable/delete a cronjob:**
1584
1593
  1. **Step 1 (Search):** Call the \`cron\` tool with action \`list\` (and \`includeDisabled: true\`) to view all cron jobs on the system and find the matching \`jobId\`.
1585
1594
  2. **Step 2 (Processing):**
@@ -1589,7 +1598,8 @@ node ${btPath} close_tab 2`;
1589
1598
  3. **Honest statement:** Never claim a job is "deleted" or "not found" based on guessing without calling the \`cron\` tool to verify the actual state.
1590
1599
  - When the user asks to schedule tasks or reminders, use the built-in \`cron\` tool (action \`add\`) automatically. Do NOT ask users to run crontab or Task Scheduler manually on the host.
1591
1600
  - When operating cron/scheduler tools, do **not** put \`current\` into the Session directory.
1592
- - **IMPORTANT ABOUT GROUP CHAT TARGETING**: When creating or configuring a cron job to send messages (announce mode) to a Group Chat, the value of the \`delivery.to\` field **must** use the \`group:\` prefix before the group ID (e.g., \`group:3815464776067464419\` or \`group:xxxx\`). Never specify just the numeric ID, as the system will interpret it as a private DM and deliver to the wrong destination.
1601
+ - **IMPORTANT ABOUT GROUP CHAT TARGETING**: When creating or configuring a cron job to send messages (announce mode) to a Group Chat, the value of the \`delivery.to\` field **must** use the appropriate prefix before the group ID. For Telegram/Matrix/Discord/Slack, use the \`group:\` prefix (e.g., \`group:123456\`). ESPECIALLY for Zalo (\`zalouser\`), you **must** use the \`g:\` prefix (e.g., \`g:3815464776067464419\`) to prevent the OpenClaw core from stripping the prefix and misrouting the message to a private DM.
1602
+ - **One-shot jobs:** Use schedule kind \`"at"\` with an ISO 8601 timestamp. The job auto-deletes after successful run unless \`deleteAfterRun: false\` is set.
1593
1603
  - Skip internal doc lookups such as \`cron-jobs.mdx\`; rely on the available tools and complete the scheduling task directly.`)
1594
1604
  : '';
1595
1605
 
@@ -1745,7 +1755,7 @@ if (typeof exports !== 'undefined' && workspaceRoot.__openclawWorkspace) {
1745
1755
  Object.assign(exports, workspaceRoot.__openclawWorkspace);
1746
1756
  }
1747
1757
 
1748
- // ── Centralized bot config builders (openclaw.json, exec-approvals, .env) (setup/shared/bot-config-gen.js)
1758
+ // ── ── Centralized bot config builders (openclaw.json, exec-approvals, .env) (setup/shared/bot-config-gen.js)
1749
1759
  // @ts-nocheck
1750
1760
  /**
1751
1761
  * @fileoverview Centralized bot configuration builders — single source of truth.
@@ -2216,7 +2226,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
2216
2226
  Object.assign(exports, globalThis.__openclawBotConfig);
2217
2227
  }
2218
2228
 
2219
- // ── Shared install artifacts: Chrome debug, uninstall, skill catalog (setup/shared/install-gen.js)
2229
+ // ── ── Shared install artifacts: Chrome debug, uninstall, skill catalog (setup/shared/install-gen.js)
2220
2230
  // @ts-nocheck
2221
2231
  // install-gen.js — Build install/runtime artifacts (Chrome debug, uninstall, skill catalog)
2222
2232
  // Workspace .md files are in workspace-gen.js (single source of truth).
@@ -2784,7 +2794,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
2784
2794
  Object.assign(exports, globalThis.__openclawInstall);
2785
2795
  }
2786
2796
 
2787
- // ── Shared Docker artifact helpers for wizard + CLI (setup/shared/docker-gen.js)
2797
+ // ── ── Shared Docker artifact helpers for wizard + CLI (setup/shared/docker-gen.js)
2788
2798
  // @ts-nocheck
2789
2799
  (function (root) {
2790
2800
  const common = (typeof globalThis !== 'undefined' && globalThis.__openclawCommon) || {};
@@ -2991,6 +3001,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
2991
3001
  is9Router,
2992
3002
  isLocal,
2993
3003
  isMultiBot,
3004
+ hasBrowser = false,
2994
3005
  selectedModel,
2995
3006
  agentId,
2996
3007
  allSkills = [],
@@ -3108,6 +3119,10 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
3108
3119
  ].join('\n'));
3109
3120
  runtimeParts.push('openclaw gateway run');
3110
3121
  const runtimeScript = ['#!/bin/sh', 'set -e', ...runtimeParts].join('\n');
3122
+ let browserInstall = '';
3123
+ if (hasBrowser) {
3124
+ browserInstall = '\n# Install browser and system dependencies for Playwright\nRUN npx playwright install-deps chromium && npx playwright install chromium\n';
3125
+ }
3111
3126
  const dockerfile = `FROM node:22-slim
3112
3127
 
3113
3128
  RUN apt-get update && apt-get install -y git curl python3 && rm -rf /var/lib/apt/lists/*
@@ -3115,7 +3130,7 @@ RUN apt-get update && apt-get install -y git curl python3 && rm -rf /var/lib/apt
3115
3130
  ARG OPENCLAW_VER="${openClawNpmSpec}"
3116
3131
  ARG CACHE_BUST=""
3117
3132
  RUN echo "CACHE_BUST=$CACHE_BUST" && npm install -g $OPENCLAW_VER ${openClawRuntimePackages}${skillLines}${pluginLines}
3118
- ${patchLine}
3133
+ ${patchLine}${browserInstall}
3119
3134
 
3120
3135
  COPY entrypoint.sh /usr/local/bin/openclaw-entrypoint.sh
3121
3136
  RUN chmod +x /usr/local/bin/openclaw-entrypoint.sh
@@ -3357,7 +3372,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
3357
3372
 
3358
3373
 
3359
3374
 
3360
- // ── buildNativeScriptCtx and shared native runtime helpers (setup/generators/native-helpers-gen.js)
3375
+ // ── ── buildNativeScriptCtx and shared native runtime helpers (setup/generators/native-helpers-gen.js)
3361
3376
  // @ts-nocheck
3362
3377
  /* eslint-disable no-undef, no-unused-vars */
3363
3378
  /**
@@ -3772,7 +3787,7 @@ setInterval(sync, INTERVAL);`;
3772
3787
  };
3773
3788
  }
3774
3789
 
3775
- // ── botEnvContent, botConfigContent, botWorkspaceFiles, botFiles, helpers (setup/generators/config-gen.js)
3790
+ // ── ── botEnvContent, botConfigContent, botWorkspaceFiles, botFiles, helpers (setup/generators/config-gen.js)
3776
3791
  // @ts-nocheck
3777
3792
  /* eslint-disable no-undef, no-unused-vars */
3778
3793
  /**
@@ -4001,7 +4016,7 @@ setInterval(sync, INTERVAL);`;
4001
4016
  }));
4002
4017
  }
4003
4018
 
4004
- // ── generateZaloLoginBat, generateZaloLoginSh (unified) (setup/generators/zalo-login-gen.js)
4019
+ // ── ── generateZaloLoginBat, generateZaloLoginSh (unified) (setup/generators/zalo-login-gen.js)
4005
4020
  // @ts-nocheck
4006
4021
  /* eslint-disable no-undef, no-unused-vars */
4007
4022
  /**
@@ -4114,7 +4129,7 @@ function generateZaloLoginSh(opts) {
4114
4129
  ];
4115
4130
  }
4116
4131
 
4117
- // ── generateStartScript wizard wrapper (delegates to install-gen) (setup/generators/gateway-start-gen.js)
4132
+ // ── ── generateStartScript wizard wrapper (delegates to install-gen) (setup/generators/gateway-start-gen.js)
4118
4133
  // @ts-nocheck
4119
4134
  /* eslint-disable no-undef, no-unused-vars */
4120
4135
  /**
@@ -4161,7 +4176,7 @@ function generateStartScript() {
4161
4176
  return null;
4162
4177
  }
4163
4178
 
4164
- // ── generateUninstallScript, setup script download helpers (setup/generators/download-gen.js)
4179
+ // ── ── generateUninstallScript, setup script download helpers (setup/generators/download-gen.js)
4165
4180
  // @ts-nocheck
4166
4181
  /* eslint-disable no-undef, no-unused-vars */
4167
4182
  /**
@@ -4418,7 +4433,7 @@ window.__downloadGen = {
4418
4433
  updateDockerDlLabel,
4419
4434
  };
4420
4435
 
4421
- // ── Windows .bat — if (state.nativeOs === "win") block (setup/os/win-bat.js)
4436
+ // ── ── Windows .bat if (state.nativeOs === "win") block (setup/os/win-bat.js)
4422
4437
  // @ts-nocheck
4423
4438
  /* eslint-disable no-undef, no-unused-vars */
4424
4439
  /**
@@ -4558,7 +4573,7 @@ function generateWinBat(ctx) {
4558
4573
  return { scriptName, scriptContent };
4559
4574
  }
4560
4575
 
4561
- // ── macOS .sh — if (state.nativeOs === "macos") block (setup/os/macos-sh.js)
4576
+ // ── ── macOS .sh if (state.nativeOs === "macos") block (setup/os/macos-sh.js)
4562
4577
  // @ts-nocheck
4563
4578
  /* eslint-disable no-undef, no-unused-vars */
4564
4579
  /**
@@ -4676,7 +4691,7 @@ function generateMacOsSh(ctx) {
4676
4691
  return { scriptName, scriptContent };
4677
4692
  }
4678
4693
 
4679
- // ── VPS/PM2 .sh — if (state.nativeOs === "vps") block (setup/os/vps-sh.js)
4694
+ // ── ── VPS/PM2 .sh if (state.nativeOs === "vps") block (setup/os/vps-sh.js)
4680
4695
  // @ts-nocheck
4681
4696
  /* eslint-disable no-undef, no-unused-vars */
4682
4697
  /**
@@ -4801,7 +4816,7 @@ GWEOF`);
4801
4816
  return { scriptName, scriptContent };
4802
4817
  }
4803
4818
 
4804
- // ── Linux Desktop .sh — if (state.nativeOs === "linux-desktop") block (setup/os/linux-sh.js)
4819
+ // ── ── Linux Desktop .sh if (state.nativeOs === "linux-desktop") block (setup/os/linux-sh.js)
4805
4820
  // @ts-nocheck
4806
4821
  /* eslint-disable no-undef, no-unused-vars */
4807
4822
  /**
@@ -4864,7 +4879,7 @@ function generateLinuxSh(ctx) {
4864
4879
  return { scriptName, scriptContent };
4865
4880
  }
4866
4881
 
4867
- // ── UI init, language/channel/deploy controllers, form rendering (setup/ui/controller.js)
4882
+ // ── ── UI init, language/channel/deploy controllers, form rendering (setup/ui/controller.js)
4868
4883
  // @ts-nocheck
4869
4884
  /* eslint-disable no-undef, no-unused-vars */
4870
4885
  /**
@@ -5513,7 +5528,7 @@ function generateLinuxSh(ctx) {
5513
5528
  envContent.textContent = lines.join('\n');
5514
5529
  }
5515
5530
 
5516
- // ── Multi-bot state + UI (setup/ui/multi-bot.js) ───────────────────
5531
+ // ── ── Multi-bot state + UI (setup/ui/multi-bot.js) ──────────────────────────────────────
5517
5532
  // @ts-nocheck
5518
5533
  /* eslint-disable no-undef, no-unused-vars */
5519
5534
  /**
@@ -5862,7 +5877,7 @@ function generateLinuxSh(ctx) {
5862
5877
 
5863
5878
  // ========== Step 1: Deploy Mode + OS ==========
5864
5879
 
5865
- // ── Step navigation, validation (setup/ui/steps.js) ────────────────
5880
+ // ── ── Step navigation, validation (setup/ui/steps.js) ────────────────────────────────
5866
5881
  // @ts-nocheck
5867
5882
  /* eslint-disable no-undef, no-unused-vars */
5868
5883
  /**
@@ -6022,7 +6037,7 @@ function generateLinuxSh(ctx) {
6022
6037
 
6023
6038
  // ========== Step 2: Bot Config ==========
6024
6039
 
6025
- // ── generateOutput + generateNativeScript + clipboard (setup/ui/output.js)
6040
+ // ── ── generateOutput + generateNativeScript + clipboard (setup/ui/output.js)
6026
6041
  // @ts-nocheck
6027
6042
  /* eslint-disable no-undef, no-unused-vars */
6028
6043
  /**
package/dist/web/app.js CHANGED
@@ -272,6 +272,37 @@ async function pickFolderPathShared() {
272
272
  return null;
273
273
  }
274
274
 
275
+ function topbarActionsHtml() {
276
+ const setupVer = state.system?.versions?.setup;
277
+ const latestSetupVer = state.system?.versions?.latestSetup;
278
+ const hasNewVersion = setupVer && latestSetupVer && setupVer !== latestSetupVer;
279
+ return `
280
+ <div class="seg" role="group" aria-label="theme">
281
+ <button class="seg__btn ${state.theme==='light'?'is-active':''}" data-pref="theme" data-value="light" style="display: inline-flex; align-items: center; gap: 6px;">
282
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:14px; height:14px;"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="4.22" x2="19.78" y2="5.64"/></svg>
283
+ <span>${ui('light')}</span>
284
+ </button>
285
+ <button class="seg__btn ${state.theme==='dark'?'is-active':''}" data-pref="theme" data-value="dark" style="display: inline-flex; align-items: center; gap: 6px;">
286
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:14px; height:14px;"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
287
+ <span>${ui('dark')}</span>
288
+ </button>
289
+ </div>
290
+ <div class="seg" role="group" aria-label="lang" style="display: inline-flex; align-items: center; gap: 4px;">
291
+ <span style="display: inline-flex; align-items: center; justify-content: center; padding: 0 4px; color: var(--muted);">
292
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:15px; height:15px;"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
293
+ </span>
294
+ <button class="seg__btn ${state.lang==='vi'?'is-active':''}" data-pref="lang" data-value="vi">VI</button>
295
+ <button class="seg__btn ${state.lang==='en'?'is-active':''}" data-pref="lang" data-value="en">EN</button>
296
+ </div>
297
+ ${hasNewVersion ? `
298
+ <button class="topbar__btn seg__btn" data-update-setup style="display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 6px; border: 1px solid var(--ok); background: rgba(46, 230, 166, 0.08); color: var(--ok); font-weight: 600; cursor: pointer; transition: background 0.2s;">
299
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:14px; height:14px;"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>
300
+ <span>${t('Cập nhật', 'Update')}</span>
301
+ </button>
302
+ ` : ''}
303
+ `;
304
+ }
305
+
275
306
  function render() {
276
307
  applyPrefs();
277
308
  const tabs = [['dashboard',t('Dashboard','Dashboard')],['setup',ui('setup')],['bot',ui('bot')],['logs',ui('logs')]];
@@ -280,7 +311,7 @@ function render() {
280
311
  if (!mainContainer) {
281
312
  $('#app').innerHTML = `
282
313
  <aside class="sidebar">
283
- <div class="brand"><img src="/openclaw-logo.svg" onerror="this.src='/openclaw-logo.png'" alt="OpenClaw"/><div style="display: flex; flex-direction: column; align-items: center; text-align: center;"><b>OpenClaw Setup</b><span style="display: block; width: 100%; text-align: center; font-size: 13.5px; font-weight: 600; margin-top: 6px; color: var(--muted);">v${state.system?.versions?.setup || '5.8.0'}</span></div></div>
314
+ <div class="brand"><img src="/openclaw-logo.svg" onerror="this.src='/openclaw-logo.png'" alt="OpenClaw"/><div style="display: flex; flex-direction: column; align-items: center; text-align: center;"><b>OpenClaw Setup</b><span id="sidebar-version" style="display: block; width: 100%; text-align: center; font-size: 13.5px; font-weight: 600; margin-top: 6px; color: var(--muted);">v${state.system?.versions?.setup || '...'}</span></div></div>
284
315
  <nav class="sidebar-nav">${tabs.map(([id,label]) => `<button class="nav ${state.tab===id?'active':''}" data-tab="${id}">${icon(id)}<span>${label}</span></button>`).join('')}</nav>
285
316
  ${sidebarExtras()}
286
317
  </aside>
@@ -291,23 +322,7 @@ function render() {
291
322
  <input aria-label="Search" placeholder="${t('T\u00ecm nhanh...', 'Quick search...')}" />
292
323
  </div>
293
324
  <div class="topbar__actions">
294
- <div class="seg" role="group" aria-label="theme">
295
- <button class="seg__btn ${state.theme==='light'?'is-active':''}" data-pref="theme" data-value="light" style="display: inline-flex; align-items: center; gap: 6px;">
296
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:14px; height:14px;"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="4.22" x2="19.78" y2="5.64"/></svg>
297
- <span>${ui('light')}</span>
298
- </button>
299
- <button class="seg__btn ${state.theme==='dark'?'is-active':''}" data-pref="theme" data-value="dark" style="display: inline-flex; align-items: center; gap: 6px;">
300
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:14px; height:14px;"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
301
- <span>${ui('dark')}</span>
302
- </button>
303
- </div>
304
- <div class="seg" role="group" aria-label="lang" style="display: inline-flex; align-items: center; gap: 4px;">
305
- <span style="display: inline-flex; align-items: center; justify-content: center; padding: 0 4px; color: var(--muted);">
306
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="width:15px; height:15px;"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
307
- </span>
308
- <button class="seg__btn ${state.lang==='vi'?'is-active':''}" data-pref="lang" data-value="vi">VI</button>
309
- <button class="seg__btn ${state.lang==='en'?'is-active':''}" data-pref="lang" data-value="en">EN</button>
310
- </div>
325
+ ${topbarActionsHtml()}
311
326
  </div>
312
327
  </header>
313
328
  <header class="top"><div><p class="eyebrow">${ui('installer')}</p><h1 id="app-page-title">${title()}</h1></div></header>
@@ -331,9 +346,15 @@ function render() {
331
346
  const titleEl = $('#app-page-title');
332
347
  if (titleEl) titleEl.innerHTML = title();
333
348
 
349
+ const sidebarVerEl = $('#sidebar-version');
350
+ if (sidebarVerEl) sidebarVerEl.textContent = `v${state.system?.versions?.setup || '...'}`;
351
+
334
352
  const panelEl = $('.panel');
335
353
  if (panelEl) panelEl.innerHTML = content();
336
354
 
355
+ const actionsEl = $('.topbar__actions');
356
+ if (actionsEl) actionsEl.innerHTML = topbarActionsHtml();
357
+
337
358
  document.querySelectorAll('.sidebar-nav button, .bottom-nav button').forEach(btn => {
338
359
  const active = btn.dataset.tab === state.tab;
339
360
  btn.classList.toggle('active', active);
@@ -759,7 +780,7 @@ function filesView() { return `<div class="files">${state.files.map(f=>`<article
759
780
  function botSkillsPanel() {
760
781
  const flags = state.featureFlags || {};
761
782
  const skills = [
762
- { id: 'cron', title: 'Cron', desc: 'Cron guide in TOOLS.md' },
783
+ { id: 'cron', title: 'Cron', desc: 'Native scheduler (SQLite) — cron guide in TOOLS.md' },
763
784
  ];
764
785
  const plugins = [
765
786
  { id: 'openclaw-browser-automation', title: 'openclaw-browser-automation', desc: 'Smart Search + Browser (headless & Chrome thật)' },
@@ -915,7 +936,18 @@ document.querySelectorAll('[data-project-pick-folder]').forEach(btn => btn.oncli
915
936
  showToast(t('Lỗi kết nối', 'Connection error'), err.message, 'error');
916
937
  render();
917
938
  }));
918
- document.querySelectorAll('[data-update-app]').forEach(btn => btn.onclick = () => withButtonLoading(btn, async () => {
939
+ document.querySelectorAll('[data-update-setup]').forEach(btn => btn.onclick = () => withButtonLoading(btn, async () => {
940
+ state.tab = 'logs';
941
+ render();
942
+ try {
943
+ showToast(t('Đang cập nhật...', 'Updating...'), t('Đang tiến hành cập nhật Setup Wizard.', 'Updating Setup Wizard now.'), 'info');
944
+ await api('/api/setup/update', { method: 'POST' });
945
+ showToast(t('Khởi động cập nhật', 'Update started'), t('Đang kéo code mới và nâng cấp trong nền.', 'Pulling new code and upgrading in the background.'), 'success');
946
+ } catch (err) {
947
+ showToast(t('Cập nhật thất bại', 'Update failed'), err.message, 'error');
948
+ }
949
+ }));
950
+ document.querySelectorAll('[data-update-app]').forEach(btn => btn.onclick = () => withButtonLoading(btn, async () => {
919
951
  await api('/api/runtime/update', { method: 'POST', body: { target: 'openclaw' } });
920
952
  await loadSystem();
921
953
  await loadStatus();
package/package.json CHANGED
@@ -1,40 +1,40 @@
1
- {
2
- "name": "create-openclaw-bot",
3
- "version": "5.8.1",
4
- "description": "Interactive CLI installer for OpenClaw Bot",
5
- "main": "dist/cli.js",
6
- "bin": {
7
- "create-openclaw-bot": "./dist/cli.js"
8
- },
9
- "files": [
10
- "dist"
11
- ],
12
- "scripts": {
13
- "build": "node src/build.mjs --deploy",
14
- "dev": "node src/build.mjs --deploy --watch",
15
- "start": "node dist/cli.js",
16
- "test": "node src/tests/smoke-cli-logic.mjs && node src/tests/test-generation.mjs && node src/tests/test-matrix.mjs && node src/tests/test-local-server.mjs",
17
- "bump": "node src/bump-version.mjs"
18
- },
19
- "keywords": [
20
- "openclaw",
21
- "cli",
22
- "bot",
23
- "zalo",
24
- "telegram",
25
- "ai"
26
- ],
27
- "author": "tuanminhhole",
28
- "license": "MIT",
29
- "dependencies": {
30
- "@inquirer/prompts": "^4.3.1",
31
- "chalk": "^5.3.0",
32
- "fs-extra": "^11.2.0"
33
- },
34
- "bundleDependencies": [
35
- "@inquirer/prompts",
36
- "chalk",
37
- "fs-extra"
38
- ],
39
- "type": "module"
40
- }
1
+ {
2
+ "name": "create-openclaw-bot",
3
+ "version": "5.8.3",
4
+ "description": "Interactive CLI installer for OpenClaw Bot",
5
+ "main": "dist/cli.js",
6
+ "bin": {
7
+ "create-openclaw-bot": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "node docs_dev/tests/build.mjs --deploy",
14
+ "dev": "node docs_dev/tests/build.mjs --deploy --watch",
15
+ "start": "node dist/cli.js",
16
+ "test": "node docs_dev/tests/smoke-cli-logic.mjs && node docs_dev/tests/test-generation.mjs && node docs_dev/tests/test-matrix.mjs && node docs_dev/tests/test-local-server.mjs",
17
+ "bump": "node docs_dev/tests/bump-version.mjs"
18
+ },
19
+ "keywords": [
20
+ "openclaw",
21
+ "cli",
22
+ "bot",
23
+ "zalo",
24
+ "telegram",
25
+ "ai"
26
+ ],
27
+ "author": "tuanminhhole",
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@inquirer/prompts": "^4.3.1",
31
+ "chalk": "^5.3.0",
32
+ "fs-extra": "^11.2.0"
33
+ },
34
+ "bundleDependencies": [
35
+ "@inquirer/prompts",
36
+ "chalk",
37
+ "fs-extra"
38
+ ],
39
+ "type": "module"
40
+ }