create-openclaw-bot 5.8.0 → 5.8.2
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 +167 -159
- package/README.vi.md +172 -164
- package/dist/cli.js +125 -112
- package/dist/legacy-cli.js +11 -11
- package/dist/server/local-server.js +372 -70
- package/dist/setup/data/index.js +0 -1
- package/dist/setup/data/plugins.js +8 -1
- package/dist/setup/data/skills.js +2 -10
- package/dist/setup/shared/docker-gen.js +576 -576
- package/dist/setup/shared/workspace-gen.js +813 -526
- package/dist/setup.js +367 -324
- package/dist/web/app.js +1276 -1106
- package/dist/web/styles.css +1054 -286
- package/package.json +5 -5
package/dist/setup.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/* ============================================
|
|
2
|
-
OpenClaw Setup Wizard
|
|
2
|
+
OpenClaw Setup Wizard — Logic v2
|
|
3
3
|
Multi-model, Multi-plugin, Multi-channel
|
|
4
4
|
============================================ */
|
|
5
|
-
// AUTO-GENERATED by build.mjs
|
|
5
|
+
// AUTO-GENERATED by build.mjs — edit files in src/setup/ instead
|
|
6
6
|
|
|
7
7
|
(function () {
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
386
|
+
// ── ── PLUGINS list (setup/data/plugins.js) ──────────────────────────────────────────────────────
|
|
387
387
|
// @ts-nocheck
|
|
388
388
|
/* eslint-disable no-undef, no-unused-vars */
|
|
389
389
|
/**
|
|
@@ -406,6 +406,13 @@
|
|
|
406
406
|
*/
|
|
407
407
|
// ========== Available Plugins (npm packages — runtime/channel extensions) ==========
|
|
408
408
|
const PLUGINS = [
|
|
409
|
+
{
|
|
410
|
+
id: 'browser-automation',
|
|
411
|
+
name: 'Browser Automation ⭐',
|
|
412
|
+
icon: '🌐',
|
|
413
|
+
descVi: 'Smart Search + Điều khiển trình duyệt Chrome/Chromium (ẩn & thật)', descEn: 'Smart Search + Chrome/Chromium browser control (headless & real)',
|
|
414
|
+
package: 'openclaw-browser-automation',
|
|
415
|
+
},
|
|
409
416
|
{
|
|
410
417
|
id: 'telegram-multibot-relay',
|
|
411
418
|
name: 'Telegram Multi-Bot Relay',
|
|
@@ -445,7 +452,7 @@
|
|
|
445
452
|
];
|
|
446
453
|
|
|
447
454
|
|
|
448
|
-
//
|
|
455
|
+
// ── ── SKILLS list (setup/data/skills.js) ──────────────────────────────────────────────────────────
|
|
449
456
|
// @ts-nocheck
|
|
450
457
|
/* eslint-disable no-undef, no-unused-vars */
|
|
451
458
|
/**
|
|
@@ -468,14 +475,6 @@
|
|
|
468
475
|
*/
|
|
469
476
|
// ========== Available Skills (ClawHub registry — agent capabilities) ==========
|
|
470
477
|
const SKILLS = [
|
|
471
|
-
{
|
|
472
|
-
id: 'browser',
|
|
473
|
-
name: 'Browser Automation ⭐(Khuyên dùng)',
|
|
474
|
-
icon: '🌐',
|
|
475
|
-
descVi: 'Tự động thao tác trình duyệt (Playwright)', descEn: 'Automated browser control (Playwright)',
|
|
476
|
-
slug: 'browser-automation',
|
|
477
|
-
noteVi: 'Cần bật Chrome Debug Mode trên máy host', noteEn: 'Requires Chrome Debug Mode on host',
|
|
478
|
-
},
|
|
479
478
|
{
|
|
480
479
|
id: 'memory',
|
|
481
480
|
name: 'Long-term Memory ⭐(Khuyên dùng)',
|
|
@@ -574,7 +573,7 @@
|
|
|
574
573
|
className: 'plugin-card__badge plugin-card__badge--recommended'
|
|
575
574
|
};
|
|
576
575
|
}
|
|
577
|
-
if (skill.id === '
|
|
576
|
+
if (skill.id === 'scheduler') {
|
|
578
577
|
return {
|
|
579
578
|
text: isVi ? 'Khuyên dùng' : 'Recommended',
|
|
580
579
|
className: 'plugin-card__badge plugin-card__badge--recommended'
|
|
@@ -616,7 +615,7 @@
|
|
|
616
615
|
}
|
|
617
616
|
|
|
618
617
|
|
|
619
|
-
//
|
|
618
|
+
// ── ── Shared runtime constants, relay helpers, auth profile builders (setup/shared/common-gen.js)
|
|
620
619
|
// @ts-nocheck
|
|
621
620
|
(function (root) {
|
|
622
621
|
const OPENCLAW_NPM_SPEC = 'openclaw@latest';
|
|
@@ -931,7 +930,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
|
|
|
931
930
|
Object.assign(exports, globalThis.__openclawCommon);
|
|
932
931
|
}
|
|
933
932
|
|
|
934
|
-
//
|
|
933
|
+
// ── ── Shared workspace file builders (IDENTITY, SOUL, AGENTS, TOOLS, TEAMS...) (setup/shared/workspace-gen.js)
|
|
935
934
|
/** @typedef {typeof globalThis & { __openclawWorkspace?: Record<string, Function> }} OpenClawWorkspaceRoot */
|
|
936
935
|
|
|
937
936
|
const workspaceRoot = /** @type {OpenClawWorkspaceRoot} */ (
|
|
@@ -1059,6 +1058,226 @@ function buildBootstrapDoc(options = {}) {
|
|
|
1059
1058
|
: `# BOOTSTRAP\n\n## Startup role\n- You are **${botName}**.\n- Your identity, role, and style are already defined in **IDENTITY.md**, **SOUL.md**, and **AGENTS.md**.\n- Use those files as the highest-priority source of truth for your persona in this workspace.\n\n## Mandatory\n- Do not ask the user to redefine your name, vibe, persona, signature emoji, or assistant style.\n- Do not say you just woke up, just came online, are choosing your identity, or any similar onboarding line.\n- Do not behave like a blank freshly-created bot.\n- If the user only sends a short opener like "hi" or "alo", greet briefly and reply in your existing role.\n\n## Telegram\n- Before EVERY user-visible Telegram reply, if the current turn exposes a native reaction tool/action, use it to add \`👍\` first unless \`👍\` is already present.\n- Never claim that you reacted unless the tool actually ran and the reaction is real on the chat.\n- If the target chat does not support real reactions or the tool is not exposed, still reply normally and do not mention the technical limitation.\n`;
|
|
1060
1059
|
}
|
|
1061
1060
|
|
|
1061
|
+
function buildSearchToolJs() {
|
|
1062
|
+
return `/**
|
|
1063
|
+
* search-tool.js — Stealth search via Playwright Headless Chromium or CDP fallback
|
|
1064
|
+
* Zero tokens, no API keys, concurrent multi-engine scraping (Google + Bing + DuckDuckGo).
|
|
1065
|
+
* Usage: node search-tool.js "<query>" [limit]
|
|
1066
|
+
*/
|
|
1067
|
+
let playwright;
|
|
1068
|
+
try {
|
|
1069
|
+
playwright = require('playwright-core');
|
|
1070
|
+
} catch (e) {
|
|
1071
|
+
try {
|
|
1072
|
+
playwright = require('/usr/local/lib/node_modules/openclaw/node_modules/playwright-core');
|
|
1073
|
+
} catch (err) {
|
|
1074
|
+
try {
|
|
1075
|
+
const path = require('path');
|
|
1076
|
+
playwright = require(path.join(process.cwd(), 'node_modules', 'playwright-core'));
|
|
1077
|
+
} catch (x) {
|
|
1078
|
+
console.error(JSON.stringify({ error: 'Playwright not found! Install it or run within OpenClaw environment.' }));
|
|
1079
|
+
process.exit(1);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
const { chromium } = playwright;
|
|
1084
|
+
|
|
1085
|
+
const query = process.argv[2];
|
|
1086
|
+
const limit = parseInt(process.argv[3]) || 5;
|
|
1087
|
+
const CDP_URL = 'http://127.0.0.1:9222';
|
|
1088
|
+
|
|
1089
|
+
if (!query) {
|
|
1090
|
+
console.error(JSON.stringify({ error: 'Usage: node search-tool.js "<query>" [limit]' }));
|
|
1091
|
+
process.exit(1);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
(async () => {
|
|
1095
|
+
let browser;
|
|
1096
|
+
let ctx;
|
|
1097
|
+
let isStandalone = false;
|
|
1098
|
+
try {
|
|
1099
|
+
// Try connecting to active Chrome CDP first
|
|
1100
|
+
try {
|
|
1101
|
+
browser = await chromium.connectOverCDP(CDP_URL, { timeout: 3000 });
|
|
1102
|
+
ctx = browser.contexts()[0];
|
|
1103
|
+
} catch (e) {
|
|
1104
|
+
// Fallback to standalone headless Chromium launch
|
|
1105
|
+
browser = await chromium.launch({
|
|
1106
|
+
headless: true,
|
|
1107
|
+
args: [
|
|
1108
|
+
'--no-sandbox',
|
|
1109
|
+
'--disable-gpu',
|
|
1110
|
+
'--disable-dev-shm-usage',
|
|
1111
|
+
'--disable-blink-features=AutomationControlled'
|
|
1112
|
+
]
|
|
1113
|
+
});
|
|
1114
|
+
isStandalone = true;
|
|
1115
|
+
ctx = await browser.newContext({
|
|
1116
|
+
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// Run search queries concurrently on three search engines
|
|
1121
|
+
const [googleResults, bingResults, ddgResults] = await Promise.all([
|
|
1122
|
+
// Google
|
|
1123
|
+
(async () => {
|
|
1124
|
+
const page = await ctx.newPage();
|
|
1125
|
+
try {
|
|
1126
|
+
await page.goto('https://www.google.com/search?q=' + encodeURIComponent(query) + '&hl=vi', { waitUntil: 'domcontentloaded', timeout: 10000 });
|
|
1127
|
+
const res = await page.evaluate(() => {
|
|
1128
|
+
const list = [];
|
|
1129
|
+
const links = Array.from(document.querySelectorAll('a h3'));
|
|
1130
|
+
for (const head of links) {
|
|
1131
|
+
const a = head.closest('a');
|
|
1132
|
+
if (!a) continue;
|
|
1133
|
+
const url = a.href;
|
|
1134
|
+
const title = head.textContent || '';
|
|
1135
|
+
let snippet = '';
|
|
1136
|
+
let parent = a.parentElement;
|
|
1137
|
+
while (parent && parent.tagName !== 'DIV') {
|
|
1138
|
+
parent = parent.parentElement;
|
|
1139
|
+
}
|
|
1140
|
+
if (parent) {
|
|
1141
|
+
const descEl = parent.parentElement?.querySelector('.VwiC3b, .yHGvwa, div[style*="-webkit-line-clamp"]');
|
|
1142
|
+
if (descEl) {
|
|
1143
|
+
snippet = descEl.textContent || '';
|
|
1144
|
+
} else {
|
|
1145
|
+
const texts = Array.from(parent.parentElement?.querySelectorAll('div, span') || [])
|
|
1146
|
+
.map(el => el.textContent.trim())
|
|
1147
|
+
.filter(txt => txt.length > 30 && !txt.includes(title));
|
|
1148
|
+
if (texts.length > 0) snippet = texts[0];
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
if (url && title) {
|
|
1152
|
+
list.push({ title, url, snippet });
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return list;
|
|
1156
|
+
});
|
|
1157
|
+
await page.close();
|
|
1158
|
+
return res;
|
|
1159
|
+
} catch (e) {
|
|
1160
|
+
if (page) await page.close();
|
|
1161
|
+
return [];
|
|
1162
|
+
}
|
|
1163
|
+
})(),
|
|
1164
|
+
|
|
1165
|
+
// Bing
|
|
1166
|
+
(async () => {
|
|
1167
|
+
const page = await ctx.newPage();
|
|
1168
|
+
try {
|
|
1169
|
+
await page.goto('https://www.bing.com/search?q=' + encodeURIComponent(query), { waitUntil: 'domcontentloaded', timeout: 10000 });
|
|
1170
|
+
const res = await page.evaluate(() => {
|
|
1171
|
+
const list = [];
|
|
1172
|
+
const items = document.querySelectorAll('li.b_algo');
|
|
1173
|
+
for (const item of items) {
|
|
1174
|
+
const titleEl = item.querySelector('h2 a');
|
|
1175
|
+
if (!titleEl) continue;
|
|
1176
|
+
const title = titleEl.textContent || '';
|
|
1177
|
+
const url = titleEl.href;
|
|
1178
|
+
let snippet = '';
|
|
1179
|
+
const snippetEl = item.querySelector('.b_caption p, .b_snippet, p');
|
|
1180
|
+
if (snippetEl) {
|
|
1181
|
+
snippet = snippetEl.textContent || '';
|
|
1182
|
+
}
|
|
1183
|
+
if (url && title) {
|
|
1184
|
+
list.push({ title, url, snippet });
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return list;
|
|
1188
|
+
});
|
|
1189
|
+
await page.close();
|
|
1190
|
+
return res;
|
|
1191
|
+
} catch (e) {
|
|
1192
|
+
if (page) await page.close();
|
|
1193
|
+
return [];
|
|
1194
|
+
}
|
|
1195
|
+
})(),
|
|
1196
|
+
|
|
1197
|
+
// DuckDuckGo
|
|
1198
|
+
(async () => {
|
|
1199
|
+
const page = await ctx.newPage();
|
|
1200
|
+
try {
|
|
1201
|
+
await page.goto('https://html.duckduckgo.com/html/?q=' + encodeURIComponent(query), { waitUntil: 'domcontentloaded', timeout: 10000 });
|
|
1202
|
+
const res = await page.evaluate(() => {
|
|
1203
|
+
const list = [];
|
|
1204
|
+
const elements = document.querySelectorAll('.result');
|
|
1205
|
+
for (const el of elements) {
|
|
1206
|
+
const titleEl = el.querySelector('.result__title a');
|
|
1207
|
+
const snippetEl = el.querySelector('.result__snippet');
|
|
1208
|
+
if (titleEl) {
|
|
1209
|
+
list.push({
|
|
1210
|
+
title: titleEl.textContent.trim(),
|
|
1211
|
+
url: titleEl.href,
|
|
1212
|
+
snippet: snippetEl ? snippetEl.textContent.trim() : ''
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return list;
|
|
1217
|
+
});
|
|
1218
|
+
await page.close();
|
|
1219
|
+
return res;
|
|
1220
|
+
} catch (e) {
|
|
1221
|
+
if (page) await page.close();
|
|
1222
|
+
return [];
|
|
1223
|
+
}
|
|
1224
|
+
})()
|
|
1225
|
+
]);
|
|
1226
|
+
|
|
1227
|
+
// Deduplicate results by normalized URL
|
|
1228
|
+
const allResults = [...googleResults, ...bingResults, ...ddgResults];
|
|
1229
|
+
const uniqueResults = [];
|
|
1230
|
+
const seenUrls = new Set();
|
|
1231
|
+
for (const res of allResults) {
|
|
1232
|
+
if (!res.url || !res.title) continue;
|
|
1233
|
+
let normUrl = res.url.replace(/^(https?:\\/\\/)?(www\\.)?/, '').toLowerCase();
|
|
1234
|
+
if (normUrl.endsWith('/')) normUrl = normUrl.slice(0, -1);
|
|
1235
|
+
if (!seenUrls.has(normUrl)) {
|
|
1236
|
+
seenUrls.add(normUrl);
|
|
1237
|
+
uniqueResults.push(res);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// Score results to prioritize numeric price data for financial queries
|
|
1242
|
+
const isPriceQuery = /giá|vàng|đô|usd|sjc|sh|hôm nay|price|gold|rate|vnd|xe|vnđ/i.test(query);
|
|
1243
|
+
const scoredResults = uniqueResults.map(res => {
|
|
1244
|
+
let score = 0;
|
|
1245
|
+
// Base length score
|
|
1246
|
+
score += Math.min(res.snippet.length / 50, 5);
|
|
1247
|
+
|
|
1248
|
+
if (isPriceQuery) {
|
|
1249
|
+
// Number density check
|
|
1250
|
+
const numCount = (res.snippet.match(/\\d+/g) || []).length;
|
|
1251
|
+
score += Math.min(numCount * 2, 10);
|
|
1252
|
+
|
|
1253
|
+
// Priority keywords boost
|
|
1254
|
+
if (/lượng|chỉ|triệu|nghìn|vnd|usd|sjc|xe|bán|mua|giá/i.test(res.snippet)) {
|
|
1255
|
+
score += 8;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return { ...res, score };
|
|
1259
|
+
});
|
|
1260
|
+
|
|
1261
|
+
// Sort by score desc
|
|
1262
|
+
scoredResults.sort((a, b) => b.score - a.score);
|
|
1263
|
+
|
|
1264
|
+
// Map back to output format and limit
|
|
1265
|
+
const output = scoredResults.map(({ score, ...rest }) => rest).slice(0, limit);
|
|
1266
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1267
|
+
|
|
1268
|
+
} catch (err) {
|
|
1269
|
+
console.error(JSON.stringify({ error: err.message }));
|
|
1270
|
+
} finally {
|
|
1271
|
+
if (browser && isStandalone) {
|
|
1272
|
+
try {
|
|
1273
|
+
await browser.close();
|
|
1274
|
+
} catch(e) {}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
})();
|
|
1278
|
+
`;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1062
1281
|
function buildBrowserToolJs(variant = 'wizard') {
|
|
1063
1282
|
// v2: Full-featured browser-tool.js matching OpenClaw native browser plugin capabilities
|
|
1064
1283
|
// Both 'cli' and 'wizard' variants now use the same full script
|
|
@@ -1185,7 +1404,16 @@ const CDP_URL = 'http://127.0.0.1:9222';
|
|
|
1185
1404
|
const { isVi = true, variant = 'wizard', workspaceRoot = '' } = options;
|
|
1186
1405
|
const wsRoot = workspaceRoot.replace(/\/+$/, '');
|
|
1187
1406
|
const btPath = wsRoot ? `${wsRoot}/browser-tool.js` : 'browser-tool.js';
|
|
1188
|
-
|
|
1407
|
+
let modeHeading = '';
|
|
1408
|
+
if (variant === 'cli-server') {
|
|
1409
|
+
modeHeading = isVi
|
|
1410
|
+
? `# 🌍 Trình duyệt ảo (Browser Automation)\n\n## 💡 Hướng dẫn vận hành:\n- **Script điều khiển:** \`browser-tool.js\` (Mọi câu lệnh browser đều chạy qua script này).\n- **Môi trường chạy:**\n - **Trên VPS / Linux Server (Headless):** Trình duyệt chạy ngầm hoàn toàn độc lập (Headless) bên trong Docker / Server qua Xvfb. Không thể mở màn hình Chrome thật.\n - **Trên Máy tính cá nhân (Windows/Mac) - Dù chạy Docker hay Native:**\n - **Mặc định:** Chạy ngầm (headless) cực kỳ ổn định.\n - **Chế độ quan sát (Xem bot click):** Nếu bạn muốn xem trực tiếp Chrome thật hoạt động trên màn hình, hãy chạy file \`start-chrome-debug.bat\` (trên Windows) hoặc \`start-chrome-debug.sh\` (trên Mac) ở máy của bạn **trước khi** bot kết nối! Bot sẽ tự động chuyển sang điều khiển màn hình Chrome thật của bạn.\n- **Kết nối mặc định:** \`http://127.0.0.1:9222\`\n\n`
|
|
1411
|
+
: `# 🌍 Browser Automation\n\n## 💡 Operating Guide:\n- **Control script:** \`browser-tool.js\` (All browser commands are executed through this script).\n- **Running environment:**\n - **On VPS / Linux Server (Headless Server Mode):** The browser runs fully headless and isolated inside Docker / Server via Xvfb. No GUI Chrome can be launched.\n - **On Personal Computers (Windows/Mac) - Docker or Native:**\n - **Default:** Runs headless and stable in the background.\n - **Observer Mode (Visual Chrome GUI):** If you want to see the real Chrome window being controlled, run \`start-chrome-debug.bat\` (on Windows) or \`start-chrome-debug.sh\` (on Mac) on your host machine **before** the bot connects! The bot will automatically hook into your real desktop Chrome.\n- **Default endpoint:** \`http://127.0.0.1:9222\`\n\n`;
|
|
1412
|
+
} else {
|
|
1413
|
+
modeHeading = isVi
|
|
1414
|
+
? `# 🌍 Hướng dẫn Browser (Chrome CDP)\n- **Script điều khiển:** \`browser-tool.js\`\n- **Kết nối Chrome debug:** \`http://127.0.0.1:9222\`\n- **Xem trực quan:** Hãy chạy file \`start-chrome-debug.bat\` (trên Windows) hoặc \`start-chrome-debug.sh\` (trên Mac) để mở Chrome chế độ Debug.\n\n`
|
|
1415
|
+
: `# 🌍 Browser Guide (Chrome CDP)\n- **Control script:** \`browser-tool.js\`\n- **Chrome debug endpoint:** \`http://127.0.0.1:9222\`\n- **Visual interface:** Run \`start-chrome-debug.bat\` (on Windows) or \`start-chrome-debug.sh\` (on Mac) to open Chrome in Debug mode.\n\n`;
|
|
1416
|
+
}
|
|
1189
1417
|
|
|
1190
1418
|
return `${modeHeading}# Navigation
|
|
1191
1419
|
node ${btPath} status
|
|
@@ -1290,11 +1518,37 @@ node ${btPath} close_tab 2`;
|
|
|
1290
1518
|
const browserRef = hasBrowser
|
|
1291
1519
|
? (browserDocVariant === 'cli-server'
|
|
1292
1520
|
? (isVi
|
|
1293
|
-
? `\n\n##
|
|
1294
|
-
|
|
1521
|
+
? `\n\n## 🌐 Browser Automation
|
|
1522
|
+
- Xem hướng dẫn chi tiết tại **BROWSER.md**
|
|
1523
|
+
- Script điều khiển: \`browser-tool.js\`
|
|
1524
|
+
- Chế độ hiện tại:
|
|
1525
|
+
- **Trên VPS / Linux Server:** Chạy ngầm độc lập qua Docker hoặc Xvfb.
|
|
1526
|
+
- **Trên Windows/Mac (Docker hoặc Native):** Chạy ngầm mặc định, hoặc chạy file \`start-chrome-debug.bat\` / \`start-chrome-debug.sh\` để xem trình duyệt trực quan trên màn hình.
|
|
1527
|
+
- Kết nối mặc định: \`http://127.0.0.1:9222\`
|
|
1528
|
+
- **Tìm kiếm Web:** Nếu không có công cụ Web Search (hoặc Web Search không khả dụng/bị lỗi), hãy **luôn sử dụng ngay công cụ terminal (exec/run_command) để chạy lệnh: \`node search-tool.js "<từ khóa>" 5\`**! Lệnh này sẽ tự động chạy ngầm qua DuckDuckGo/Google/Bing bằng trình duyệt ngầm tàng hình của bạn và trả về kết quả JSON sạch ngay lập tức. Tuyệt đối KHÔNG được mở trình duyệt thủ công, chụp ảnh màn hình hay click tìm kiếm bằng tay từng bước!
|
|
1529
|
+
- Nếu browser lỗi, thử lại 1 lần rồi mới báo user với lỗi cụ thể`
|
|
1530
|
+
: `\n\n## 🌐 Browser Automation
|
|
1531
|
+
- See detailed guide at **BROWSER.md**
|
|
1532
|
+
- Control script: \`browser-tool.js\`
|
|
1533
|
+
- Current mode:
|
|
1534
|
+
- **On VPS / Linux Server:** Runs headless via Docker or Xvfb.
|
|
1535
|
+
- **On Windows/Mac (Docker or Native):** Runs headless by default, or run \`start-chrome-debug.bat\` / \`start-chrome-debug.sh\` to see the GUI.
|
|
1536
|
+
- Default endpoint: \`http://127.0.0.1:9222\`
|
|
1537
|
+
- **Web Searching:** If the Web Search tool is unavailable or fails, **always use your terminal execution tool (exec/run_command) to run: \`node search-tool.js "<query>" 5\`**! This will automatically execute the search via DuckDuckGo/Google/Bing under stealth browser mode and return a clean JSON result immediately. Never open the browser manually, take screenshots, or click the search button step-by-step!
|
|
1538
|
+
- If browser fails, retry once before reporting the concrete error to the user`)
|
|
1295
1539
|
: (isVi
|
|
1296
|
-
? `\n\n##
|
|
1297
|
-
|
|
1540
|
+
? `\n\n## 🌐 Browser Automation
|
|
1541
|
+
- Xem hướng dẫn chi tiết tại **BROWSER.md**
|
|
1542
|
+
- Script điều khiển: \`browser-tool.js\`
|
|
1543
|
+
- Kết nối Chrome debug: \`http://127.0.0.1:9222\`
|
|
1544
|
+
- **Tìm kiếm Web:** Hãy **luôn sử dụng ngay công cụ terminal (exec/run_command) để chạy lệnh: \`node search-tool.js "<từ khóa>" 5\`**! Lệnh này sẽ tự động chạy ngầm qua DuckDuckGo/Google/Bing bằng trình duyệt ngầm tàng hình của bạn và trả về kết quả JSON sạch ngay lập tức. Tuyệt đối KHÔNG được mở trình duyệt thủ công, chụp ảnh màn hình hay click tìm kiếm bằng tay từng bước!
|
|
1545
|
+
- Nếu tool/profile hỏi đường browser desktop, dùng profile \`host-chrome\` trước`
|
|
1546
|
+
: `\n\n## 🌐 Browser Automation
|
|
1547
|
+
- See detailed guide at **BROWSER.md**
|
|
1548
|
+
- Control script: \`browser-tool.js\`
|
|
1549
|
+
- Chrome debug endpoint: \`http://127.0.0.1:9222\`
|
|
1550
|
+
- **Web Searching:** If the Web Search tool is unavailable or fails, **always use your terminal execution tool (exec/run_command) to run: \`node search-tool.js "<query>" 5\`**! This will automatically execute the search via DuckDuckGo/Google/Bing under stealth browser mode and return a clean JSON result immediately. Never open the browser manually, take screenshots, or click the search button step-by-step!
|
|
1551
|
+
- If a desktop browser profile is needed, use the \`host-chrome\` profile first`))
|
|
1298
1552
|
: '';
|
|
1299
1553
|
|
|
1300
1554
|
const telegramSection = (variant === 'relay')
|
|
@@ -1305,8 +1559,38 @@ node ${btPath} close_tab 2`;
|
|
|
1305
1559
|
|
|
1306
1560
|
const cronSection = hasScheduler
|
|
1307
1561
|
? (isVi
|
|
1308
|
-
? `\n\n## \u23F0 Cron / Lên lịch nhắc
|
|
1309
|
-
|
|
1562
|
+
? `\n\n## \u23F0 Cron / Lên lịch nhắc nhở (tool: \`cron\`)
|
|
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
|
+
- **Khi tạo cronjob mới (action \`add\`):**
|
|
1565
|
+
- **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
|
+
- 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.
|
|
1567
|
+
- **Khi user yêu cầu tắt/bật/xóa cronjob:**
|
|
1568
|
+
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
|
+
2. **Bước 2 (Xử lý):**
|
|
1570
|
+
- Để xóa: Gọi action \`remove\` với \`id\` tìm được.
|
|
1571
|
+
- Để tắt/tạm dừng: Gọi action \`update\` với \`id\` và patch \`{"enabled": false}\`.
|
|
1572
|
+
- Để bật lại: Gọi action \`update\` với \`id\` và patch \`{"enabled": true}\`.
|
|
1573
|
+
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
|
+
- 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
|
+
- 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 vì hệ thống sẽ hiểu nhầm đó là một DM chat cá nhân (direct message) và gửi sai địa chỉ.
|
|
1577
|
+
- 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
|
+
: `\n\n## \u23F0 Cron / Scheduled Tasks (tool: \`cron\`)
|
|
1579
|
+
- **Exact tool name:** The tool name is \`cron\` (never mistake it for \`native\` or external command lines).
|
|
1580
|
+
- **When creating a new cronjob (action \`add\`):**
|
|
1581
|
+
- **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
|
+
- 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.
|
|
1583
|
+
- **When the user requests to disable/enable/delete a cronjob:**
|
|
1584
|
+
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
|
+
2. **Step 2 (Processing):**
|
|
1586
|
+
- To delete: Call action \`remove\` with the \`id\` found.
|
|
1587
|
+
- To disable/pause: Call action \`update\` with \`id\` and patch \`{"enabled": false}\`.
|
|
1588
|
+
- To enable: Call action \`update\` with \`id\` and patch \`{"enabled": true}\`.
|
|
1589
|
+
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
|
+
- 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
|
+
- 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.
|
|
1593
|
+
- Skip internal doc lookups such as \`cron-jobs.mdx\`; rely on the available tools and complete the scheduling task directly.`)
|
|
1310
1594
|
: '';
|
|
1311
1595
|
|
|
1312
1596
|
const zaloModSection = '';
|
|
@@ -1322,8 +1606,8 @@ node ${btPath} close_tab 2`;
|
|
|
1322
1606
|
}
|
|
1323
1607
|
|
|
1324
1608
|
return isVi
|
|
1325
|
-
? `# Hướng dẫn sử dụng Tools\n\n## Danh sách skills đã cài\n${skillsSection}\n\n## Nguyên tắc chung\n- Ưu tiên dùng tool/skill phù hợp thay vì tự suy đoán\n- Nếu tool trả về lỗi — thử lại 1 lần, sau đó báo user\n- Không chạy tool liên tục mà không có mục đích rõ ràng\n- Luôn tóm tắt kết quả tool cho user thay vì dump raw output${browserRef}\n\n## Quy ước\n- Web Search:
|
|
1326
|
-
: `# Tool Usage Guide\n\n## Installed Skills\n${skillsSection}\n\n## General Principles\n- Prefer using the right tool/skill over guessing\n- If a tool returns an error — retry once, then report to user\n- Don't run tools repeatedly without a clear purpose\n- Always summarize tool output for user instead of dumping raw data${browserRef}\n\n## Conventions\n- Web Search:
|
|
1609
|
+
? `# Hướng dẫn sử dụng Tools\n\n## Danh sách skills đã cài\n${skillsSection}\n\n## Nguyên tắc chung\n- Ưu tiên dùng tool/skill phù hợp thay vì tự suy đoán\n- Nếu tool trả về lỗi — thử lại 1 lần, sau đó báo user\n- Không chạy tool liên tục mà không có mục đích rõ ràng\n- Luôn tóm tắt kết quả tool cho user thay vì dump raw output${browserRef}\n\n## Quy ước\n- Web Search: TUYỆT ĐỐI KHÔNG dùng tool \`web_search\` native vì nó đã bị vô hiệu hóa hoàn toàn trên hệ thống. Thay vào đó, mỗi khi cần tìm kiếm Internet/Web, bạn BẮT BUỘC phải gọi công cụ \`exec\` để chạy lệnh terminal: \`node search-tool.js "<từ khóa>" 5\`! Lệnh này cực kỳ nhanh, tàng hình và miễn phí.\n- Browser: chỉ mở trang khi user yêu cầu cụ thể\n- Memory: tự ghi nhớ thông tin tự nhiên, không cần user nhắc${cronSection}${zaloModSection}\n\n## \uD83D\uDCC1 File & Workspace\n- Bot có thể đọc/ghi file trong thư mục workspace: \`${workspacePath}\`\n- Dùng để lưu notes, scripts, cấu hình tạm\n\n## \u26A0\uFE0F Tool Error Handling\n- Retry tối đa 2 lần nếu tool lỗi network\n- Nếu vẫn lỗi: báo user kèm mô tả lỗi cụ thể và gợi ý workaround${dmOverride}\n`
|
|
1610
|
+
: `# Tool Usage Guide\n\n## Installed Skills\n${skillsSection}\n\n## General Principles\n- Prefer using the right tool/skill over guessing\n- If a tool returns an error — retry once, then report to user\n- Don't run tools repeatedly without a clear purpose\n- Always summarize tool output for user instead of dumping raw data${browserRef}\n\n## Conventions\n- Web Search: DO NOT use the native \`web_search\` tool as it is completely disabled. Instead, whenever you need to search the Internet/Web, you MUST call the \`exec\` tool to run terminal command: \`node search-tool.js "<query>" 5\`! This is extremely fast, stealthy and free.\n- Browser: only open pages when user specifically requests\n- Memory: proactively remember important info without user prompting${cronSection}${zaloModSection}\n\n## \uD83D\uDCC1 File & Workspace\n- Bot can read/write files in workspace: \`${workspacePath}\`\n\n## \u26A0\uFE0F Tool Error Handling\n- Retry up to 2 times on network errors\n- If still failing: report to user with specific error description and workaround${dmOverride}\n`;
|
|
1327
1611
|
}
|
|
1328
1612
|
function buildTeamsDoc(options = {}) {
|
|
1329
1613
|
const {
|
|
@@ -1418,6 +1702,7 @@ node ${btPath} close_tab 2`;
|
|
|
1418
1702
|
'HEARTBEAT.md': buildHeartbeatDoc({ isVi }),
|
|
1419
1703
|
'BOOTSTRAP.md': buildBootstrapDoc({ isVi, botName }),
|
|
1420
1704
|
'DREAMS.md': buildDreamsDoc({ isVi }),
|
|
1705
|
+
'search-tool.js': buildSearchToolJs(),
|
|
1421
1706
|
};
|
|
1422
1707
|
|
|
1423
1708
|
if (isMultiBot) {
|
|
@@ -1445,6 +1730,7 @@ node ${btPath} close_tab 2`;
|
|
|
1445
1730
|
buildDreamsDoc,
|
|
1446
1731
|
buildHeartbeatDoc,
|
|
1447
1732
|
buildBootstrapDoc,
|
|
1733
|
+
buildSearchToolJs,
|
|
1448
1734
|
buildBrowserToolJs,
|
|
1449
1735
|
buildBrowserDoc,
|
|
1450
1736
|
buildSecurityRules,
|
|
@@ -1459,7 +1745,7 @@ if (typeof exports !== 'undefined' && workspaceRoot.__openclawWorkspace) {
|
|
|
1459
1745
|
Object.assign(exports, workspaceRoot.__openclawWorkspace);
|
|
1460
1746
|
}
|
|
1461
1747
|
|
|
1462
|
-
//
|
|
1748
|
+
// ── ── Centralized bot config builders (openclaw.json, exec-approvals, .env) (setup/shared/bot-config-gen.js)
|
|
1463
1749
|
// @ts-nocheck
|
|
1464
1750
|
/**
|
|
1465
1751
|
* @fileoverview Centralized bot configuration builders — single source of truth.
|
|
@@ -1930,7 +2216,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
|
|
|
1930
2216
|
Object.assign(exports, globalThis.__openclawBotConfig);
|
|
1931
2217
|
}
|
|
1932
2218
|
|
|
1933
|
-
//
|
|
2219
|
+
// ── ── Shared install artifacts: Chrome debug, uninstall, skill catalog (setup/shared/install-gen.js)
|
|
1934
2220
|
// @ts-nocheck
|
|
1935
2221
|
// install-gen.js — Build install/runtime artifacts (Chrome debug, uninstall, skill catalog)
|
|
1936
2222
|
// Workspace .md files are in workspace-gen.js (single source of truth).
|
|
@@ -2498,7 +2784,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
|
|
|
2498
2784
|
Object.assign(exports, globalThis.__openclawInstall);
|
|
2499
2785
|
}
|
|
2500
2786
|
|
|
2501
|
-
//
|
|
2787
|
+
// ── ── Shared Docker artifact helpers for wizard + CLI (setup/shared/docker-gen.js)
|
|
2502
2788
|
// @ts-nocheck
|
|
2503
2789
|
(function (root) {
|
|
2504
2790
|
const common = (typeof globalThis !== 'undefined' && globalThis.__openclawCommon) || {};
|
|
@@ -2705,7 +2991,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
|
|
|
2705
2991
|
is9Router,
|
|
2706
2992
|
isLocal,
|
|
2707
2993
|
isMultiBot,
|
|
2708
|
-
hasBrowser,
|
|
2994
|
+
hasBrowser = false,
|
|
2709
2995
|
selectedModel,
|
|
2710
2996
|
agentId,
|
|
2711
2997
|
allSkills = [],
|
|
@@ -2724,23 +3010,9 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
|
|
|
2724
3010
|
plainSingleExtraHosts = false,
|
|
2725
3011
|
multiOllamaNumParallel = 1,
|
|
2726
3012
|
singleOllamaNumParallel = 1,
|
|
2727
|
-
emitBrowserInstall = true,
|
|
2728
3013
|
gatewayPort = 18789,
|
|
2729
3014
|
routerPort = 20128,
|
|
2730
3015
|
} = options;
|
|
2731
|
-
|
|
2732
|
-
const browserAptExtra = hasBrowser ? ' xvfb socat' : '';
|
|
2733
|
-
const browserInstallLines = hasBrowser && emitBrowserInstall
|
|
2734
|
-
? [
|
|
2735
|
-
'',
|
|
2736
|
-
'# Browser Automation: Playwright engine (needed for native CDP)',
|
|
2737
|
-
'RUN npm install -g agent-browser playwright \\',
|
|
2738
|
-
' && npx playwright install chromium --with-deps \\',
|
|
2739
|
-
' && ln -f -s /root/.cache/ms-playwright/chromium-*/chrome-linux*/chrome /usr/bin/google-chrome',
|
|
2740
|
-
'',
|
|
2741
|
-
''
|
|
2742
|
-
].join('\n')
|
|
2743
|
-
: '';
|
|
2744
3016
|
const skillLines = dockerfileSkillInstallMode === 'build' && allSkills.length > 0
|
|
2745
3017
|
? `\n# Install skills (ClawHub)\n${allSkills.map((skill) => `RUN openclaw skills install ${skill} || echo "Warning: Failed to install ${skill} due to rate limits."`).join('\n')}\n`
|
|
2746
3018
|
: '';
|
|
@@ -2780,6 +3052,20 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
|
|
|
2780
3052
|
' echo "[entrypoint] plugin $id missing; installing $spec"',
|
|
2781
3053
|
' openclaw plugins install "$spec" 2>/dev/null || echo "[entrypoint] warning: failed to install plugin $spec"',
|
|
2782
3054
|
'}',
|
|
3055
|
+
'ensure_zalouser() {',
|
|
3056
|
+
' NPM_DIR="$OPENCLAW_HOME/npm"',
|
|
3057
|
+
' PKG_DIR="$NPM_DIR/node_modules/@openclaw/zalouser"',
|
|
3058
|
+
' if [ -d "$PKG_DIR" ]; then',
|
|
3059
|
+
' echo "[entrypoint] zalouser plugin already installed"',
|
|
3060
|
+
' else',
|
|
3061
|
+
' echo "[entrypoint] zalouser plugin missing; installing via npm"',
|
|
3062
|
+
' mkdir -p "$NPM_DIR"',
|
|
3063
|
+
' cd "$NPM_DIR"',
|
|
3064
|
+
' npm init -y 2>/dev/null || true',
|
|
3065
|
+
' npm install @openclaw/zalouser@latest 2>/dev/null || echo "[entrypoint] warning: failed to install @openclaw/zalouser"',
|
|
3066
|
+
' cd /root/project',
|
|
3067
|
+
' fi',
|
|
3068
|
+
'}',
|
|
2783
3069
|
'ensure_skill() {',
|
|
2784
3070
|
' id="$1"',
|
|
2785
3071
|
' if find "$OPENCLAW_HOME" -maxdepth 4 -type d -path "*/skills/$id" -print -quit 2>/dev/null | grep -q .; then',
|
|
@@ -2805,7 +3091,7 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
|
|
|
2805
3091
|
' sed -i "s/LISTENER_WATCHDOG_MAX_GAP_MS\\\\s*=\\\\s*35e3/LISTENER_WATCHDOG_MAX_GAP_MS = 90e3/" "$ZALO_JS"',
|
|
2806
3092
|
' echo "[entrypoint] patched zalouser watchdog gap: 35s -> 90s"',
|
|
2807
3093
|
'fi',
|
|
2808
|
-
].join('
|
|
3094
|
+
].join('\n'));
|
|
2809
3095
|
runtimeParts.push([
|
|
2810
3096
|
'# Zalo channel auto-restart monitor (background)',
|
|
2811
3097
|
'(',
|
|
@@ -2815,27 +3101,27 @@ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}e
|
|
|
2815
3101
|
' STATUS=$(openclaw channels status 2>/dev/null | grep -i "Zalo Personal" || true)',
|
|
2816
3102
|
' if echo "$STATUS" | grep -qi "stopped"; then',
|
|
2817
3103
|
' echo "[zalo-monitor] Zalo channel stopped - restarting container in 5s"',
|
|
2818
|
-
|
|
3104
|
+
' sleep 5',
|
|
2819
3105
|
' kill 1 2>/dev/null || true',
|
|
2820
3106
|
' fi',
|
|
2821
3107
|
' done',
|
|
2822
3108
|
') &',
|
|
2823
|
-
].join('
|
|
3109
|
+
].join('\n'));
|
|
3110
|
+
runtimeParts.push('openclaw gateway run');
|
|
3111
|
+
const runtimeScript = ['#!/bin/sh', 'set -e', ...runtimeParts].join('\n');
|
|
3112
|
+
let browserInstall = '';
|
|
2824
3113
|
if (hasBrowser) {
|
|
2825
|
-
|
|
2826
|
-
runtimeParts.push('Xvfb :99 -screen 0 1280x720x24 > /dev/null 2>&1 & DISPLAY=:99 openclaw gateway run');
|
|
2827
|
-
} else {
|
|
2828
|
-
runtimeParts.push('openclaw gateway run');
|
|
3114
|
+
browserInstall = '\n# Install browser and system dependencies for Playwright\nRUN npx playwright install-deps chromium && npx playwright install chromium\n';
|
|
2829
3115
|
}
|
|
2830
|
-
const runtimeScript = ['#!/bin/sh', 'set -e', ...runtimeParts].join('\n');
|
|
2831
3116
|
const dockerfile = `FROM node:22-slim
|
|
2832
3117
|
|
|
2833
|
-
RUN apt-get update && apt-get install -y git curl python3
|
|
2834
|
-
|
|
3118
|
+
RUN apt-get update && apt-get install -y git curl python3 && rm -rf /var/lib/apt/lists/*
|
|
3119
|
+
|
|
2835
3120
|
ARG OPENCLAW_VER="${openClawNpmSpec}"
|
|
2836
3121
|
ARG CACHE_BUST=""
|
|
2837
3122
|
RUN echo "CACHE_BUST=$CACHE_BUST" && npm install -g $OPENCLAW_VER ${openClawRuntimePackages}${skillLines}${pluginLines}
|
|
2838
|
-
${patchLine}
|
|
3123
|
+
${patchLine}${browserInstall}
|
|
3124
|
+
|
|
2839
3125
|
COPY entrypoint.sh /usr/local/bin/openclaw-entrypoint.sh
|
|
2840
3126
|
RUN chmod +x /usr/local/bin/openclaw-entrypoint.sh
|
|
2841
3127
|
WORKDIR /root/project
|
|
@@ -2858,7 +3144,7 @@ CMD ["/bin/sh", "/usr/local/bin/openclaw-entrypoint.sh"]`;
|
|
|
2858
3144
|
: isLocal
|
|
2859
3145
|
? ' depends_on:\n ollama:\n condition: service_healthy\n'
|
|
2860
3146
|
: '';
|
|
2861
|
-
const extraHosts =
|
|
3147
|
+
const extraHosts = `${extraHostsBlock}\n`;
|
|
2862
3148
|
if (is9Router) {
|
|
2863
3149
|
compose = `name: ${multiComposeName}
|
|
2864
3150
|
services:
|
|
@@ -2961,7 +3247,7 @@ services:
|
|
|
2961
3247
|
- ../../.env
|
|
2962
3248
|
depends_on:
|
|
2963
3249
|
- 9router
|
|
2964
|
-
${appEnvironmentBlock}${
|
|
3250
|
+
${appEnvironmentBlock}${extraHostsBlock}\n volumes:
|
|
2965
3251
|
- ${volumeMount}
|
|
2966
3252
|
- openclaw-plugins:/root/project/.openclaw/npm
|
|
2967
3253
|
ports:
|
|
@@ -3002,7 +3288,7 @@ services:
|
|
|
3002
3288
|
${appEnvironmentBlock} depends_on:
|
|
3003
3289
|
ollama:
|
|
3004
3290
|
condition: service_healthy
|
|
3005
|
-
${
|
|
3291
|
+
${extraHostsBlock}\n ports:
|
|
3006
3292
|
- "${gatewayPort}:${gatewayPort}"
|
|
3007
3293
|
volumes:
|
|
3008
3294
|
- ${volumeMount}
|
|
@@ -3076,7 +3362,7 @@ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globa
|
|
|
3076
3362
|
|
|
3077
3363
|
|
|
3078
3364
|
|
|
3079
|
-
//
|
|
3365
|
+
// ── ── buildNativeScriptCtx and shared native runtime helpers (setup/generators/native-helpers-gen.js)
|
|
3080
3366
|
// @ts-nocheck
|
|
3081
3367
|
/* eslint-disable no-undef, no-unused-vars */
|
|
3082
3368
|
/**
|
|
@@ -3097,10 +3383,9 @@ function buildNativeScriptCtx(options) {
|
|
|
3097
3383
|
const ch = CHANNELS[state.channel];
|
|
3098
3384
|
const is9Router = !!(provider && provider.isProxy);
|
|
3099
3385
|
const isOllama = !!(provider && provider.isLocal);
|
|
3100
|
-
const hasBrowser = state.config.skills.includes('browser');
|
|
3101
3386
|
const nativeSkillConfigs = state.config.skills
|
|
3102
3387
|
.map((sid) => SKILLS.find((s) => s.id === sid))
|
|
3103
|
-
.filter((skill) => skill && skill.id !== 'scheduler' && skill.slug
|
|
3388
|
+
.filter((skill) => skill && skill.id !== 'scheduler' && skill.slug);
|
|
3104
3389
|
const selectedModel = (state.config.model || 'ollama/gemma4:e2b').replace('ollama/', '');
|
|
3105
3390
|
const isMultiBot = state.botCount > 1 && state.channel === 'telegram';
|
|
3106
3391
|
const projectDir = state.config.projectPath || '.';
|
|
@@ -3120,7 +3405,6 @@ function buildNativeScriptCtx(options) {
|
|
|
3120
3405
|
Object.assign(globalThis, {
|
|
3121
3406
|
isVi,
|
|
3122
3407
|
provider,
|
|
3123
|
-
hasBrowser,
|
|
3124
3408
|
is9Router,
|
|
3125
3409
|
selectedModel,
|
|
3126
3410
|
isMultiBot,
|
|
@@ -3474,7 +3758,6 @@ setInterval(sync, INTERVAL);`;
|
|
|
3474
3758
|
provider,
|
|
3475
3759
|
is9Router,
|
|
3476
3760
|
isOllama,
|
|
3477
|
-
hasBrowser,
|
|
3478
3761
|
selectedModel,
|
|
3479
3762
|
isMultiBot,
|
|
3480
3763
|
projectDir,
|
|
@@ -3494,7 +3777,7 @@ setInterval(sync, INTERVAL);`;
|
|
|
3494
3777
|
};
|
|
3495
3778
|
}
|
|
3496
3779
|
|
|
3497
|
-
//
|
|
3780
|
+
// ── ── botEnvContent, botConfigContent, botWorkspaceFiles, botFiles, helpers (setup/generators/config-gen.js)
|
|
3498
3781
|
// @ts-nocheck
|
|
3499
3782
|
/* eslint-disable no-undef, no-unused-vars */
|
|
3500
3783
|
/**
|
|
@@ -3510,7 +3793,6 @@ setInterval(sync, INTERVAL);`;
|
|
|
3510
3793
|
* @global {boolean} isVi - Vietnamese language mode
|
|
3511
3794
|
* @global {object} provider - Current primary provider config
|
|
3512
3795
|
* @global {boolean} isMultiBot - Multi-bot mode flag
|
|
3513
|
-
* @global {boolean} hasBrowser - Browser plugin selected
|
|
3514
3796
|
* @global {boolean} is9Router - 9Router proxy mode
|
|
3515
3797
|
* @global {string} projectDir - Output project directory path
|
|
3516
3798
|
* @global {Function} getGatewayAllowedOrigins
|
|
@@ -3575,8 +3857,8 @@ setInterval(sync, INTERVAL);`;
|
|
|
3575
3857
|
groupId,
|
|
3576
3858
|
selectedSkills: state.config.skills,
|
|
3577
3859
|
skills: SKILLS,
|
|
3578
|
-
hasBrowserDesktop:
|
|
3579
|
-
hasBrowserServer:
|
|
3860
|
+
hasBrowserDesktop: false,
|
|
3861
|
+
hasBrowserServer: false,
|
|
3580
3862
|
gatewayPort: basePort,
|
|
3581
3863
|
gatewayAllowedOrigins: getGatewayAllowedOrigins(basePort),
|
|
3582
3864
|
osChoice: state.nativeOs || '',
|
|
@@ -3646,7 +3928,7 @@ setInterval(sync, INTERVAL);`;
|
|
|
3646
3928
|
agentWorkspaceDir,
|
|
3647
3929
|
persona: bot.persona || '',
|
|
3648
3930
|
userInfo: state.config.userInfo || '',
|
|
3649
|
-
hasBrowser,
|
|
3931
|
+
hasBrowser: false,
|
|
3650
3932
|
soulVariant: 'wizard',
|
|
3651
3933
|
memoryVariant: 'wizard',
|
|
3652
3934
|
hasZaloMod: state.channel === 'zalo-personal',
|
|
@@ -3724,7 +4006,7 @@ setInterval(sync, INTERVAL);`;
|
|
|
3724
4006
|
}));
|
|
3725
4007
|
}
|
|
3726
4008
|
|
|
3727
|
-
//
|
|
4009
|
+
// ── ── generateZaloLoginBat, generateZaloLoginSh (unified) (setup/generators/zalo-login-gen.js)
|
|
3728
4010
|
// @ts-nocheck
|
|
3729
4011
|
/* eslint-disable no-undef, no-unused-vars */
|
|
3730
4012
|
/**
|
|
@@ -3837,7 +4119,7 @@ function generateZaloLoginSh(opts) {
|
|
|
3837
4119
|
];
|
|
3838
4120
|
}
|
|
3839
4121
|
|
|
3840
|
-
//
|
|
4122
|
+
// ── ── generateStartScript wizard wrapper (delegates to install-gen) (setup/generators/gateway-start-gen.js)
|
|
3841
4123
|
// @ts-nocheck
|
|
3842
4124
|
/* eslint-disable no-undef, no-unused-vars */
|
|
3843
4125
|
/**
|
|
@@ -3884,7 +4166,7 @@ function generateStartScript() {
|
|
|
3884
4166
|
return null;
|
|
3885
4167
|
}
|
|
3886
4168
|
|
|
3887
|
-
//
|
|
4169
|
+
// ── ── generateUninstallScript, setup script download helpers (setup/generators/download-gen.js)
|
|
3888
4170
|
// @ts-nocheck
|
|
3889
4171
|
/* eslint-disable no-undef, no-unused-vars */
|
|
3890
4172
|
/**
|
|
@@ -4141,7 +4423,7 @@ window.__downloadGen = {
|
|
|
4141
4423
|
updateDockerDlLabel,
|
|
4142
4424
|
};
|
|
4143
4425
|
|
|
4144
|
-
//
|
|
4426
|
+
// ── ── Windows .bat — if (state.nativeOs === "win") block (setup/os/win-bat.js)
|
|
4145
4427
|
// @ts-nocheck
|
|
4146
4428
|
/* eslint-disable no-undef, no-unused-vars */
|
|
4147
4429
|
/**
|
|
@@ -4151,7 +4433,7 @@ window.__downloadGen = {
|
|
|
4151
4433
|
*/
|
|
4152
4434
|
function generateWinBat(ctx) {
|
|
4153
4435
|
const {
|
|
4154
|
-
ch, isVi, provider, is9Router, isOllama,
|
|
4436
|
+
ch, isVi, provider, is9Router, isOllama, selectedModel, isMultiBot, projectDir, todayStamp, allPlugins, pluginCmd, nativeSkillInstallCmds, nativeSkillConfigs, providerLines, sharedNativeFileMap, sharedNativeEnvContent, sharedNativeExecApprovalsContent, sharedNativeConfigContent, native9RouterSyncScriptContent, native9RouterServerEntryLookup, windowsHiddenNodeLaunch, generateUninstallScript,
|
|
4155
4437
|
} = ctx;
|
|
4156
4438
|
// state, PROVIDERS, SKILLS, PLUGINS, CHANNELS are IIFE-level globals
|
|
4157
4439
|
let scriptContent;
|
|
@@ -4204,11 +4486,6 @@ function generateWinBat(ctx) {
|
|
|
4204
4486
|
}
|
|
4205
4487
|
|
|
4206
4488
|
providerLines(lines, 'bat');
|
|
4207
|
-
if (hasBrowser) {
|
|
4208
|
-
lines.push('echo Cai Browser Automation runtime...');
|
|
4209
|
-
lines.push('call npm install -g agent-browser playwright || goto :fail');
|
|
4210
|
-
lines.push('call npx playwright install chromium || goto :fail');
|
|
4211
|
-
}
|
|
4212
4489
|
if (nativeSkillInstallCmds.length > 0) {
|
|
4213
4490
|
lines.push('echo Cai skills...');
|
|
4214
4491
|
lines.push(...nativeSkillInstallCmds);
|
|
@@ -4286,7 +4563,7 @@ function generateWinBat(ctx) {
|
|
|
4286
4563
|
return { scriptName, scriptContent };
|
|
4287
4564
|
}
|
|
4288
4565
|
|
|
4289
|
-
//
|
|
4566
|
+
// ── ── macOS .sh — if (state.nativeOs === "macos") block (setup/os/macos-sh.js)
|
|
4290
4567
|
// @ts-nocheck
|
|
4291
4568
|
/* eslint-disable no-undef, no-unused-vars */
|
|
4292
4569
|
/**
|
|
@@ -4296,7 +4573,7 @@ function generateWinBat(ctx) {
|
|
|
4296
4573
|
*/
|
|
4297
4574
|
function generateMacOsSh(ctx) {
|
|
4298
4575
|
const {
|
|
4299
|
-
ch, isVi, provider, is9Router, isOllama,
|
|
4576
|
+
ch, isVi, provider, is9Router, isOllama, selectedModel, isMultiBot, projectDir, todayStamp, allPlugins, pluginCmd, nativeSkillInstallCmds, nativeSkillConfigs, providerLines, sharedNativeFileMap, sharedNativeEnvContent, sharedNativeExecApprovalsContent, sharedNativeConfigContent, native9RouterSyncScriptContent, native9RouterServerEntryLookup, windowsHiddenNodeLaunch, generateUninstallScript,
|
|
4300
4577
|
} = ctx;
|
|
4301
4578
|
// state, PROVIDERS, SKILLS, PLUGINS, CHANNELS are IIFE-level globals
|
|
4302
4579
|
let scriptContent;
|
|
@@ -4404,7 +4681,7 @@ function generateMacOsSh(ctx) {
|
|
|
4404
4681
|
return { scriptName, scriptContent };
|
|
4405
4682
|
}
|
|
4406
4683
|
|
|
4407
|
-
//
|
|
4684
|
+
// ── ── VPS/PM2 .sh — if (state.nativeOs === "vps") block (setup/os/vps-sh.js)
|
|
4408
4685
|
// @ts-nocheck
|
|
4409
4686
|
/* eslint-disable no-undef, no-unused-vars */
|
|
4410
4687
|
/**
|
|
@@ -4414,7 +4691,7 @@ function generateMacOsSh(ctx) {
|
|
|
4414
4691
|
*/
|
|
4415
4692
|
function generateVpsSh(ctx) {
|
|
4416
4693
|
const {
|
|
4417
|
-
ch, isVi, provider, is9Router, isOllama,
|
|
4694
|
+
ch, isVi, provider, is9Router, isOllama, selectedModel, isMultiBot, projectDir, todayStamp, allPlugins, pluginCmd, nativeSkillInstallCmds, nativeSkillConfigs, providerLines, sharedNativeFileMap, sharedNativeEnvContent, sharedNativeExecApprovalsContent, sharedNativeConfigContent, native9RouterSyncScriptContent, native9RouterServerEntryLookup, windowsHiddenNodeLaunch, generateUninstallScript,
|
|
4418
4695
|
} = ctx;
|
|
4419
4696
|
// state, PROVIDERS, SKILLS, PLUGINS, CHANNELS are IIFE-level globals
|
|
4420
4697
|
let scriptContent;
|
|
@@ -4529,7 +4806,7 @@ GWEOF`);
|
|
|
4529
4806
|
return { scriptName, scriptContent };
|
|
4530
4807
|
}
|
|
4531
4808
|
|
|
4532
|
-
//
|
|
4809
|
+
// ── ── Linux Desktop .sh — if (state.nativeOs === "linux-desktop") block (setup/os/linux-sh.js)
|
|
4533
4810
|
// @ts-nocheck
|
|
4534
4811
|
/* eslint-disable no-undef, no-unused-vars */
|
|
4535
4812
|
/**
|
|
@@ -4539,7 +4816,7 @@ GWEOF`);
|
|
|
4539
4816
|
*/
|
|
4540
4817
|
function generateLinuxSh(ctx) {
|
|
4541
4818
|
const {
|
|
4542
|
-
ch, isVi, provider, is9Router, isOllama,
|
|
4819
|
+
ch, isVi, provider, is9Router, isOllama, selectedModel, isMultiBot, projectDir, todayStamp, allPlugins, pluginCmd, nativeSkillInstallCmds, nativeSkillConfigs, providerLines, sharedNativeFileMap, sharedNativeEnvContent, sharedNativeExecApprovalsContent, sharedNativeConfigContent, native9RouterSyncScriptContent, native9RouterServerEntryLookup, windowsHiddenNodeLaunch, generateUninstallScript,
|
|
4543
4820
|
} = ctx;
|
|
4544
4821
|
// state, PROVIDERS, SKILLS, PLUGINS, CHANNELS are IIFE-level globals
|
|
4545
4822
|
let scriptContent;
|
|
@@ -4592,7 +4869,7 @@ function generateLinuxSh(ctx) {
|
|
|
4592
4869
|
return { scriptName, scriptContent };
|
|
4593
4870
|
}
|
|
4594
4871
|
|
|
4595
|
-
//
|
|
4872
|
+
// ── ── UI init, language/channel/deploy controllers, form rendering (setup/ui/controller.js)
|
|
4596
4873
|
// @ts-nocheck
|
|
4597
4874
|
/* eslint-disable no-undef, no-unused-vars */
|
|
4598
4875
|
/**
|
|
@@ -5241,7 +5518,7 @@ function generateLinuxSh(ctx) {
|
|
|
5241
5518
|
envContent.textContent = lines.join('\n');
|
|
5242
5519
|
}
|
|
5243
5520
|
|
|
5244
|
-
//
|
|
5521
|
+
// ── ── Multi-bot state + UI (setup/ui/multi-bot.js) ──────────────────────────────────────
|
|
5245
5522
|
// @ts-nocheck
|
|
5246
5523
|
/* eslint-disable no-undef, no-unused-vars */
|
|
5247
5524
|
/**
|
|
@@ -5590,7 +5867,7 @@ function generateLinuxSh(ctx) {
|
|
|
5590
5867
|
|
|
5591
5868
|
// ========== Step 1: Deploy Mode + OS ==========
|
|
5592
5869
|
|
|
5593
|
-
//
|
|
5870
|
+
// ── ── Step navigation, validation (setup/ui/steps.js) ────────────────────────────────
|
|
5594
5871
|
// @ts-nocheck
|
|
5595
5872
|
/* eslint-disable no-undef, no-unused-vars */
|
|
5596
5873
|
/**
|
|
@@ -5750,7 +6027,7 @@ function generateLinuxSh(ctx) {
|
|
|
5750
6027
|
|
|
5751
6028
|
// ========== Step 2: Bot Config ==========
|
|
5752
6029
|
|
|
5753
|
-
//
|
|
6030
|
+
// ── ── generateOutput + generateNativeScript + clipboard (setup/ui/output.js)
|
|
5754
6031
|
// @ts-nocheck
|
|
5755
6032
|
/* eslint-disable no-undef, no-unused-vars */
|
|
5756
6033
|
/**
|
|
@@ -5794,68 +6071,6 @@ function generateLinuxSh(ctx) {
|
|
|
5794
6071
|
const routerNotice = document.getElementById('9router-notice');
|
|
5795
6072
|
if (routerNotice) routerNotice.style.display = is9Router ? '' : 'none';
|
|
5796
6073
|
|
|
5797
|
-
// Show/hide Browser Automation notice + generate scripts
|
|
5798
|
-
const browserNotice = document.getElementById('browser-notice');
|
|
5799
|
-
const hasBrowserSkill = state.config.skills.includes('browser');
|
|
5800
|
-
if (browserNotice) browserNotice.style.display = hasBrowserSkill ? '' : 'none';
|
|
5801
|
-
|
|
5802
|
-
if (hasBrowserSkill) {
|
|
5803
|
-
// Chrome Debug .bat script
|
|
5804
|
-
const chromeBat = `@echo off
|
|
5805
|
-
echo ============================================
|
|
5806
|
-
echo OpenClaw - Chrome Debug Mode
|
|
5807
|
-
echo ============================================
|
|
5808
|
-
echo.
|
|
5809
|
-
echo Dang tat Chrome cu (neu co)...
|
|
5810
|
-
taskkill /F /IM chrome.exe >nul 2>&1
|
|
5811
|
-
timeout /t 3 /nobreak >nul
|
|
5812
|
-
echo Dang mo Chrome voi Debug Mode...
|
|
5813
|
-
start "" "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ^
|
|
5814
|
-
--remote-debugging-port=9222 ^
|
|
5815
|
-
--remote-allow-origins=* ^
|
|
5816
|
-
--user-data-dir="%TEMP%\\chrome-debug"
|
|
5817
|
-
timeout /t 4 /nobreak >nul
|
|
5818
|
-
powershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:9222/json/version' -UseBasicParsing -TimeoutSec 5 | Out-Null; Write-Host 'OK! Chrome Debug Mode dang chay tren port 9222.' -ForegroundColor Green } catch { Write-Host 'LOI: Port 9222 chua mo. Thu lai.' -ForegroundColor Red }"
|
|
5819
|
-
echo.
|
|
5820
|
-
pause`;
|
|
5821
|
-
setOutput('out-chrome-bat', chromeBat);
|
|
5822
|
-
|
|
5823
|
-
// Task Scheduler PowerShell script
|
|
5824
|
-
const taskPs1 = `# ============================================
|
|
5825
|
-
# OpenClaw - Auto-start Chrome Debug khi logon
|
|
5826
|
-
# Chay script nay 1 lan voi Run as Administrator
|
|
5827
|
-
# ============================================
|
|
5828
|
-
|
|
5829
|
-
# Duong dan toi file .bat
|
|
5830
|
-
$batPath = "$env:USERPROFILE\\start-chrome-debug.bat"
|
|
5831
|
-
|
|
5832
|
-
# Kiem tra file .bat ton tai
|
|
5833
|
-
if (-not (Test-Path $batPath)) {
|
|
5834
|
-
Write-Host "LOI: Khong tim thay $batPath" -ForegroundColor Red
|
|
5835
|
-
Write-Host "Hay luu file start-chrome-debug.bat vao $env:USERPROFILE truoc." -ForegroundColor Yellow
|
|
5836
|
-
exit 1
|
|
5837
|
-
}
|
|
5838
|
-
|
|
5839
|
-
# Tao Scheduled Task
|
|
5840
|
-
$action = New-ScheduledTaskAction -Execute $batPath
|
|
5841
|
-
$trigger = New-ScheduledTaskTrigger -AtLogOn
|
|
5842
|
-
$trigger.Delay = "PT10S" # Delay 10 giay sau khi logon
|
|
5843
|
-
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
|
|
5844
|
-
|
|
5845
|
-
Register-ScheduledTask \\
|
|
5846
|
-
-TaskName "OpenClaw-ChromeDebug" \\
|
|
5847
|
-
-Description "Tu dong bat Chrome Debug Mode cho OpenClaw Browser Automation" \\
|
|
5848
|
-
-Action $action \\
|
|
5849
|
-
-Trigger $trigger \\
|
|
5850
|
-
-Settings $settings \\
|
|
5851
|
-
-Force
|
|
5852
|
-
|
|
5853
|
-
Write-Host ""
|
|
5854
|
-
Write-Host "DONE! Task 'OpenClaw-ChromeDebug' da duoc tao." -ForegroundColor Green
|
|
5855
|
-
Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (delay 10s)." -ForegroundColor Cyan`;
|
|
5856
|
-
setOutput('out-task-ps1', taskPs1);
|
|
5857
|
-
}
|
|
5858
|
-
|
|
5859
6074
|
// Show/hide docker vs native output based on deployMode
|
|
5860
6075
|
const dockerOut = document.getElementById('docker-output');
|
|
5861
6076
|
const nativeOut = document.getElementById('native-output');
|
|
@@ -5884,8 +6099,6 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
|
|
|
5884
6099
|
: 'Script is generated from your choices. Download and run — everything else is handled automatically.';
|
|
5885
6100
|
|
|
5886
6101
|
const agentId = state.config.botName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/-$/, '') || 'chat';
|
|
5887
|
-
|
|
5888
|
-
const hasBrowser = state.config.skills.includes('browser');
|
|
5889
6102
|
// isMultiBot => unified into isMultiBot above
|
|
5890
6103
|
const multiBotAgentMetas = isMultiBot
|
|
5891
6104
|
? state.bots.slice(0, state.botCount).map((bot, idx) => {
|
|
@@ -5974,19 +6187,6 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
|
|
|
5974
6187
|
};
|
|
5975
6188
|
}
|
|
5976
6189
|
|
|
5977
|
-
// Browser Automation: inject browser config
|
|
5978
|
-
if (hasBrowser) {
|
|
5979
|
-
clawConfig.browser = {
|
|
5980
|
-
enabled: true,
|
|
5981
|
-
defaultProfile: 'host-chrome',
|
|
5982
|
-
profiles: {
|
|
5983
|
-
'host-chrome': {
|
|
5984
|
-
cdpUrl: 'http://127.0.0.1:9222',
|
|
5985
|
-
color: '#4285F4',
|
|
5986
|
-
},
|
|
5987
|
-
},
|
|
5988
|
-
};
|
|
5989
|
-
}
|
|
5990
6190
|
|
|
5991
6191
|
// Skills: register all selected skills in openclaw.json → skills.entries
|
|
5992
6192
|
// This makes OpenClaw actually load and enable them at runtime
|
|
@@ -5995,8 +6195,6 @@ Write-Host "Chrome se tu dong bat Debug Mode moi khi ban dang nhap Windows (dela
|
|
|
5995
6195
|
state.config.skills.forEach((sid) => {
|
|
5996
6196
|
const skill = SKILLS.find((s) => s.id === sid);
|
|
5997
6197
|
if (!skill) return;
|
|
5998
|
-
// Native browser tools are loaded automatically via the root 'browser' config
|
|
5999
|
-
if (skill.slug === 'browser-automation') return;
|
|
6000
6198
|
// scheduler is now native cron (not a skill), skip registering in skills.entries
|
|
6001
6199
|
if (skill.id === 'scheduler' || !skill.slug) return;
|
|
6002
6200
|
|
|
@@ -6124,7 +6322,7 @@ model:
|
|
|
6124
6322
|
const allSkills = [];
|
|
6125
6323
|
state.config.skills.forEach((sid) => {
|
|
6126
6324
|
const skill = SKILLS.find((s) => s.id === sid);
|
|
6127
|
-
if (skill && skill.slug
|
|
6325
|
+
if (skill && skill.slug) {
|
|
6128
6326
|
allSkills.push(skill.slug);
|
|
6129
6327
|
}
|
|
6130
6328
|
});
|
|
@@ -6144,7 +6342,6 @@ model:
|
|
|
6144
6342
|
is9Router,
|
|
6145
6343
|
isLocal,
|
|
6146
6344
|
isMultiBot: state.botCount > 1 && (state.channel === 'telegram'),
|
|
6147
|
-
hasBrowser,
|
|
6148
6345
|
selectedModel: state.config.model || 'ollama/gemma4:e2b',
|
|
6149
6346
|
agentId: 'bot',
|
|
6150
6347
|
allSkills,
|
|
@@ -6304,12 +6501,6 @@ _This file is yours to evolve. If someone asks to change it, confirm with the us
|
|
|
6304
6501
|
`;
|
|
6305
6502
|
|
|
6306
6503
|
// ── AGENTS.md — Hướng dẫn vận hành ("operating manual")
|
|
6307
|
-
const browserAgentSection = hasBrowser ? `
|
|
6308
|
-
## Sử dụng Trình Duyệt (Browser Automation)
|
|
6309
|
-
- BẠN SỞ HỮU GIAO DIỆN TRÌNH DUYỆT CHROME THẬT CỦA USER thông qua script \`browser-tool.js\`. ĐỌC NGAY FILE \`BROWSER.md\` để biết cách dùng.
|
|
6310
|
-
- BẮT BUỘC dùng \`bash\` để gõ \`node ~/browser-tool.js ...\` khi có yêu cầu liên quan đến web thay vì dùng web_search!
|
|
6311
|
-
- KHÔNG BAO GIỜ từ chối mở trình duyệt với lý do "không có giao diện" hay "máy chủ không có browser".
|
|
6312
|
-
` : '';
|
|
6313
6504
|
|
|
6314
6505
|
const agentsMd = lang === 'vi'
|
|
6315
6506
|
? `# Hướng dẫn vận hành
|
|
@@ -6337,7 +6528,6 @@ Bạn hỗ trợ người dùng trong mọi tác vụ hàng ngày thông qua tin
|
|
|
6337
6528
|
- Luôn xác nhận kết quả tool trước khi trả lời user
|
|
6338
6529
|
- Nếu tool lỗi → thông báo rõ ràng, đề xuất cách khác
|
|
6339
6530
|
|
|
6340
|
-
${browserAgentSection}
|
|
6341
6531
|
${state.config.securityRules}
|
|
6342
6532
|
`
|
|
6343
6533
|
|
|
@@ -6421,143 +6611,6 @@ _Update this file as you learn more about the user. Ask before changing._
|
|
|
6421
6611
|
// ── MEMORY.md — via scaffold builder
|
|
6422
6612
|
const memoryMd = _scaffold.buildMemoryDoc({ isVi, variant: 'wizard' });
|
|
6423
6613
|
|
|
6424
|
-
// Browser tool files (generated into workspace when hasBrowser)
|
|
6425
|
-
const browserToolJs = `/**
|
|
6426
|
-
* browser-tool.js - Connect to real Windows Chrome via CDP
|
|
6427
|
-
* Flow: Docker -> socat (port 9222) -> host.docker.internal:9222 -> user's Chrome
|
|
6428
|
-
*/
|
|
6429
|
-
const { chromium } = require('/usr/local/lib/node_modules/openclaw/node_modules/playwright-core');
|
|
6430
|
-
const action = process.argv[2];
|
|
6431
|
-
const param1 = process.argv[3];
|
|
6432
|
-
const param2 = process.argv[4];
|
|
6433
|
-
const CDP_URL = 'http://127.0.0.1:9222';
|
|
6434
|
-
(async () => {
|
|
6435
|
-
let browser;
|
|
6436
|
-
try {
|
|
6437
|
-
browser = await chromium.connectOverCDP(CDP_URL, { timeout: 5000 });
|
|
6438
|
-
const ctx = browser.contexts()[0];
|
|
6439
|
-
const pages = ctx.pages();
|
|
6440
|
-
let page = pages.length > 0 ? pages[0] : await ctx.newPage();
|
|
6441
|
-
if (action === 'open') {
|
|
6442
|
-
console.log('[Browser] Mo trang: ' + param1);
|
|
6443
|
-
await page.goto(param1, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
6444
|
-
await page.waitForTimeout(1500);
|
|
6445
|
-
console.log('[Browser] Da mo: ' + (await page.title()) + ' | ' + page.url());
|
|
6446
|
-
} else if (action === 'get_text') {
|
|
6447
|
-
const text = await page.evaluate(() => {
|
|
6448
|
-
document.querySelectorAll('script,style,noscript,svg').forEach(e => e.remove());
|
|
6449
|
-
return document.body.innerText.trim();
|
|
6450
|
-
});
|
|
6451
|
-
console.log(text.substring(0, 4000));
|
|
6452
|
-
} else if (action === 'click') {
|
|
6453
|
-
await page.locator(param1).first().click({ timeout: 5000 });
|
|
6454
|
-
await page.waitForTimeout(600);
|
|
6455
|
-
console.log('[Browser] Da click: ' + param1);
|
|
6456
|
-
} else if (action === 'fill') {
|
|
6457
|
-
await page.locator(param1).first().fill(param2, { timeout: 5000 });
|
|
6458
|
-
console.log('[Browser] Da dien "' + param2 + '" vao: ' + param1);
|
|
6459
|
-
} else if (action === 'press') {
|
|
6460
|
-
await page.keyboard.press(param1);
|
|
6461
|
-
await page.waitForTimeout(1000);
|
|
6462
|
-
console.log('[Browser] Da nhan phim: ' + param1);
|
|
6463
|
-
} else if (action === 'status') {
|
|
6464
|
-
console.log('[Browser] Ket noi Chrome that! Tab: ' + (await page.title()) + ' | ' + page.url());
|
|
6465
|
-
} else {
|
|
6466
|
-
console.log('Lenh: open <url> | get_text | click <sel> | fill <sel> <text> | press <key> | status');
|
|
6467
|
-
}
|
|
6468
|
-
} catch(e) {
|
|
6469
|
-
if (e.message.includes('ECONNREFUSED') || e.message.includes('Timeout')) {
|
|
6470
|
-
console.error('[Browser] Ban chua bat Chrome Debug! Hay click dup vao start-chrome-debug.bat roi thu lai.');
|
|
6471
|
-
} else {
|
|
6472
|
-
console.error('[Browser] Loi:', e.message);
|
|
6473
|
-
}
|
|
6474
|
-
} finally {
|
|
6475
|
-
if (browser) await browser.close();
|
|
6476
|
-
}
|
|
6477
|
-
`;
|
|
6478
|
-
|
|
6479
|
-
const browserMd = `# Dieu Khien Trinh Duyet (Browser Automation)
|
|
6480
|
-
|
|
6481
|
-
Bot dieu khien Chrome THAT tren man hinh Windows cua ban. Moi thao tac hien thi truc tiep!
|
|
6482
|
-
|
|
6483
|
-
## Lenh su dung (chay qua bash)
|
|
6484
|
-
|
|
6485
|
-
\\\`\\\`\\\`bash
|
|
6486
|
-
node ~/browser-tool.js status
|
|
6487
|
-
node ~/browser-tool.js open "https://google.com"
|
|
6488
|
-
node ~/browser-tool.js get_text
|
|
6489
|
-
node ~/browser-tool.js fill "input[name='q']" "tu khoa"
|
|
6490
|
-
node ~/browser-tool.js press "Enter"
|
|
6491
|
-
node ~/browser-tool.js click "#button"
|
|
6492
|
-
\\\`\\\`\\\`
|
|
6493
|
-
|
|
6494
|
-
## QUY TAC BAT BUOC
|
|
6495
|
-
- KHONG BAO GIO tu choi mo trinh duyet.
|
|
6496
|
-
- Neu loi ECONNREFUSED: bao user bat lai start-chrome-debug.bat.
|
|
6497
|
-
- KHONG dung web_search khi user yeu cau browser.
|
|
6498
|
-
`;
|
|
6499
|
-
|
|
6500
|
-
const chromeBatContent = `@echo off
|
|
6501
|
-
echo ====== OpenClaw - Chrome Debug Mode ======
|
|
6502
|
-
echo.
|
|
6503
|
-
echo Dang tat Chrome cu (neu co)...
|
|
6504
|
-
taskkill /F /IM chrome.exe >nul 2>&1
|
|
6505
|
-
timeout /t 3 /nobreak >nul
|
|
6506
|
-
echo Dang mo Chrome voi Debug Mode...
|
|
6507
|
-
start "" "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ^
|
|
6508
|
-
--remote-debugging-port=9222 ^
|
|
6509
|
-
--remote-allow-origins=* ^
|
|
6510
|
-
--user-data-dir="%TEMP%\\chrome-debug"
|
|
6511
|
-
timeout /t 4 /nobreak >nul
|
|
6512
|
-
powershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:9222/json/version' -UseBasicParsing -TimeoutSec 5 | Out-Null; Write-Host 'OK! Chrome Debug Mode dang chay.' -ForegroundColor Green } catch { Write-Host 'LOI: Port 9222 chua mo.' -ForegroundColor Red }"
|
|
6513
|
-
echo.
|
|
6514
|
-
pause
|
|
6515
|
-
`;
|
|
6516
|
-
|
|
6517
|
-
const chromeShContent = `#!/usr/bin/env bash
|
|
6518
|
-
# ====== OpenClaw - Chrome Debug Mode (Mac/Linux) ======
|
|
6519
|
-
set -e
|
|
6520
|
-
echo "====== OpenClaw - Chrome Debug Mode ======"
|
|
6521
|
-
echo ""
|
|
6522
|
-
|
|
6523
|
-
# Detect Chrome path
|
|
6524
|
-
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
6525
|
-
CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
6526
|
-
[ ! -f "$CHROME_BIN" ] && CHROME_BIN="/Applications/Chromium.app/Contents/MacOS/Chromium"
|
|
6527
|
-
[ ! -f "$CHROME_BIN" ] && CHROME_BIN="/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
|
|
6528
|
-
else
|
|
6529
|
-
CHROME_BIN="$(command -v google-chrome || command -v google-chrome-stable || command -v chromium-browser || command -v chromium || echo '')"
|
|
6530
|
-
fi
|
|
6531
|
-
[ -n "$CHROME_DEBUG_BIN" ] && CHROME_BIN="$CHROME_DEBUG_BIN"
|
|
6532
|
-
|
|
6533
|
-
if [ -z "$CHROME_BIN" ] || { [ ! -f "$CHROME_BIN" ] && [ ! -x "$CHROME_BIN" ]; }; then
|
|
6534
|
-
echo -e "\\033[31mERROR: Chrome/Chromium not found.\\033[0m"
|
|
6535
|
-
echo "Install Chrome or: export CHROME_DEBUG_BIN=/path/to/chrome"
|
|
6536
|
-
exit 1
|
|
6537
|
-
fi
|
|
6538
|
-
|
|
6539
|
-
echo "Using: $CHROME_BIN"
|
|
6540
|
-
echo "Killing existing Chrome debug instances..."
|
|
6541
|
-
pkill -f -- "--remote-debugging-port=9222" 2>/dev/null || true
|
|
6542
|
-
sleep 2
|
|
6543
|
-
|
|
6544
|
-
TMP_DIR="\${TMPDIR:-/tmp}/chrome-debug-openclaw"
|
|
6545
|
-
mkdir -p "$TMP_DIR"
|
|
6546
|
-
|
|
6547
|
-
echo "Starting Chrome in Debug Mode (port 9222)..."
|
|
6548
|
-
"$CHROME_BIN" \\
|
|
6549
|
-
--remote-debugging-port=9222 \\
|
|
6550
|
-
--remote-allow-origins=* \\
|
|
6551
|
-
--user-data-dir="$TMP_DIR" &
|
|
6552
|
-
|
|
6553
|
-
sleep 4
|
|
6554
|
-
if curl -s http://localhost:9222/json/version > /dev/null 2>&1; then
|
|
6555
|
-
echo -e "\\033[32mOK! Chrome Debug Mode is running on port 9222.\\033[0m"
|
|
6556
|
-
else
|
|
6557
|
-
echo -e "\\033[31mERROR: Port 9222 not responding.\\033[0m"
|
|
6558
|
-
exit 1
|
|
6559
|
-
fi
|
|
6560
|
-
`;
|
|
6561
6614
|
|
|
6562
6615
|
const envText = (document.getElementById('env-content')?.textContent || '').trim();
|
|
6563
6616
|
const rootEnvContent = envText ? `${envText}\n` : '';
|
|
@@ -6612,10 +6665,6 @@ fi
|
|
|
6612
6665
|
});
|
|
6613
6666
|
sharedFiles[`.openclaw/${meta.workspaceDir}/TEAMS.md`] = _scaffold.buildTeamsDoc({ isVi });
|
|
6614
6667
|
sharedFiles[`.openclaw/${meta.workspaceDir}/MEMORY.md`] = memoryMd;
|
|
6615
|
-
if (hasBrowser) {
|
|
6616
|
-
sharedFiles[`.openclaw/${meta.workspaceDir}/browser-tool.js`] = browserToolJs;
|
|
6617
|
-
sharedFiles[`.openclaw/${meta.workspaceDir}/BROWSER.md`] = browserMd;
|
|
6618
|
-
}
|
|
6619
6668
|
}
|
|
6620
6669
|
state._generatedFiles = sharedFiles;
|
|
6621
6670
|
} else {
|
|
@@ -6635,10 +6684,6 @@ fi
|
|
|
6635
6684
|
}),
|
|
6636
6685
|
[`.openclaw/workspace-${agentId}/MEMORY.md`]: memoryMd,
|
|
6637
6686
|
'.gitignore': isNativeMode ? '.env\nnode_modules/' : '.env\ndocker/openclaw/.env\nnode_modules/',
|
|
6638
|
-
...(hasBrowser ? {
|
|
6639
|
-
[`.openclaw/workspace-${agentId}/browser-tool.js`]: browserToolJs,
|
|
6640
|
-
[`.openclaw/workspace-${agentId}/BROWSER.md`]: browserMd,
|
|
6641
|
-
} : {}),
|
|
6642
6687
|
};
|
|
6643
6688
|
if (rootEnvContent) {
|
|
6644
6689
|
singleFiles['.env'] = rootEnvContent;
|
|
@@ -6660,8 +6705,6 @@ fi
|
|
|
6660
6705
|
// chrome-debug, start-bot, uninstall added ONCE here, not per-bot-mode block
|
|
6661
6706
|
if (isNativeMode) {
|
|
6662
6707
|
const _files = state._generatedFiles;
|
|
6663
|
-
_files['start-chrome-debug.bat'] = chromeBatContent;
|
|
6664
|
-
_files['start-chrome-debug.sh'] = chromeShContent;
|
|
6665
6708
|
_files['start-bot.bat'] = generateStartBotBat({
|
|
6666
6709
|
projectDir: state.config.projectPath || '.',
|
|
6667
6710
|
openclawHome: (state.config.projectPath || '.') + '\\.openclaw',
|