fix: 修复 QQ Bot 配置后 Gateway 无法启动的问题

1. 清除旧版 "agent" 废弃键 — 保存 channel 配置时自动删除旧的 agent 键,
   防止 OpenClaw 报 "agent.* was moved" 错误(前端 + 服务端双重防御)
2. Dashboard URL 动态端口探测 — 将硬编码 18789 改为扫描 18789-18799,
   解决端口被占用时打不开 Dashboard 的问题
3. 安装脚本配置格式升级 — install.sh / install.ps1 / install-silent.ps1
   生成的 openclaw.json 从旧的 "agent" 格式迁移到 "agents.defaults.model.primary"
4. 文档示例同步更新 — CLAUDE.md / cloud.html / guide.html 中的配置示例

影响文件: 14 个(portable/, install/, website/, u-claw-app/, usb-release/)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hfshfg
2026-04-09 22:01:09 +08:00
parent 220599584e
commit 690d1b7060
14 changed files with 234 additions and 96 deletions

View File

@@ -603,6 +603,8 @@ async function launchOpenClaw() {
try {
const res = await fetch('/api/config');
const existing = res.ok ? await res.json() : {};
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
delete existing.agent;
existing.channels = Object.assign(existing.channels || {}, channels);
await fetch('/api/config', {
method: 'POST',

View File

@@ -172,21 +172,38 @@ function switchOS(os) {
document.querySelectorAll('.os-tab')[os === 'mac' ? 0 : 1].classList.add('active');
}
// Check if gateway is running
function checkStatus() {
fetch('http://127.0.0.1:18789/', { mode: 'no-cors', cache: 'no-cache' })
.then(() => {
document.getElementById('statusDot').className = 'status-dot on';
document.getElementById('statusText').textContent = 'OpenClaw 运行中';
const link = document.getElementById('statusLink');
link.style.display = 'inline';
link.href = 'http://127.0.0.1:18789/#token=uclaw';
})
.catch(() => {
document.getElementById('statusDot').className = 'status-dot off';
document.getElementById('statusText').textContent = 'OpenClaw 未运行 — 请先双击启动脚本';
document.getElementById('statusLink').style.display = 'none';
});
// Check if gateway is running (scan 18789-18799)
var _gwPort = null;
async function checkStatus() {
var found = null;
if (_gwPort) {
// Fast path: check last known port first
try {
await fetch('http://127.0.0.1:' + _gwPort + '/', { mode: 'no-cors', cache: 'no-cache' });
found = _gwPort;
} catch(e) { _gwPort = null; }
}
if (!found) {
for (var p = 18789; p <= 18799; p++) {
try {
await fetch('http://127.0.0.1:' + p + '/', { mode: 'no-cors', cache: 'no-cache' });
found = p;
_gwPort = p;
break;
} catch(e) {}
}
}
if (found) {
document.getElementById('statusDot').className = 'status-dot on';
document.getElementById('statusText').textContent = 'OpenClaw 运行中 (端口 ' + found + ')';
var link = document.getElementById('statusLink');
link.style.display = 'inline';
link.href = 'http://127.0.0.1:' + found + '/#token=uclaw';
} else {
document.getElementById('statusDot').className = 'status-dot off';
document.getElementById('statusText').textContent = 'OpenClaw 未运行 — 请先双击启动脚本';
document.getElementById('statusLink').style.display = 'none';
}
}
checkStatus();
setInterval(checkStatus, 5000);

View File

@@ -642,6 +642,8 @@ async function saveChannelsAndOpen() {
try {
var res = await fetch('/api/config');
var existing = res.ok ? await res.json() : {};
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
delete existing.agent;
existing.channels = Object.assign(existing.channels || {}, channels);
await fetch('/api/config', {
method: 'POST',
@@ -652,7 +654,7 @@ async function saveChannelsAndOpen() {
} catch(e) {}
}
window.open('http://127.0.0.1:18789/#token=uclaw', '_blank');
window.open(gatewayUrl(), '_blank');
}
// --- View config ---
@@ -677,15 +679,35 @@ function showToast(msg, isError) {
setTimeout(function() { t.className = 'toast'; }, 3000);
}
// --- Find active gateway port (18789-18799) ---
var _gatewayPort = null;
async function findGatewayPort() {
for (var p = 18789; p <= 18799; p++) {
try {
await fetch('http://127.0.0.1:' + p + '/', { mode: 'no-cors' });
_gatewayPort = p;
return p;
} catch(e) {}
}
_gatewayPort = null;
return null;
}
function gatewayUrl() {
var p = _gatewayPort || 18789;
return 'http://127.0.0.1:' + p + '/#token=uclaw';
}
// --- Check gateway status ---
async function checkGateway() {
var dot = document.getElementById('statusDot');
var text = document.getElementById('statusText');
try {
await fetch('http://127.0.0.1:18789/', { mode: 'no-cors' });
var port = await findGatewayPort();
if (port) {
dot.className = 'dot on';
text.innerHTML = 'Gateway 运行中 · <a href="http://127.0.0.1:18789/#token=uclaw" target="_blank">打开 Dashboard →</a>';
} catch(e) {
text.innerHTML = 'Gateway 运行中 (端口 ' + port + ') · <a href="' + gatewayUrl() + '" target="_blank">打开 Dashboard →</a>';
document.getElementById('gatewayUrl').textContent = 'http://127.0.0.1:' + port;
} else {
dot.className = 'dot off';
text.innerHTML = 'Gateway 未启动 · 请先运行 Windows-Start.bat 或 Mac-Start.command';
}

View File

@@ -398,6 +398,8 @@ const server = http.createServer((req, res) => {
req.on('end', () => {
try {
const config = JSON.parse(body);
// 清除旧版废弃键,防止 OpenClaw 报 "agent.* was moved" 错误
delete config.agent;
const dir = path.dirname(CONFIG_PATH);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));