From 40ca8cd5aff22cbdd07a8c4141299de3bb7ea08d Mon Sep 17 00:00:00 2001 From: yankun Date: Sun, 2 Aug 2026 15:58:22 +0800 Subject: [PATCH] feat: proxy CutOS agent console --- README.md | 3 ++- lib/client.js | 6 ++---- lib/frpc.js | 15 +++++++++++++-- test/dashboard-info.test.js | 10 ++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 test/dashboard-info.test.js diff --git a/README.md b/README.md index 3f6cde4..3741b0b 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,8 @@ systemd 安装后环境变量文件位于 `/etc/clawd/env`。 切换 Agent 类型前,必须先在云端解绑设备,再修改 `/etc/clawd/env` 中的 `AGENT_TYPE`,重启 `clawd` 后重新绑定。`cutos-agent` 模式会维护 Pi 的 `providers.cutos` -模型配置,但不会读写 OpenClaw 配置、重启 OpenClaw Gateway 或调用 OpenClaw 微信能力。 +模型配置,并将本地 `http://127.0.0.1:30141/` 控制台接入设备 Dashboard 子域名;它不会读写 +OpenClaw 配置、重启 OpenClaw Gateway 或调用 OpenClaw 微信能力。 ## 服务管理 diff --git a/lib/client.js b/lib/client.js index fa310b0..5930e94 100644 --- a/lib/client.js +++ b/lib/client.js @@ -196,9 +196,7 @@ class ClawClient { async _proceedWithConnection() { const [dashInfo] = await Promise.all([ - this._isOpenClaw() - ? getDashboardInfo().catch(e => { log.warn('clawd', 'dashboard 信息获取失败:', e.message); return null; }) - : Promise.resolve({}), + getDashboardInfo(this._agentType).catch(e => { log.warn('clawd', 'dashboard 信息获取失败:', e.message); return null; }), startTtyd().catch(e => log.warn('ttyd', '启动失败:', e.message)), ]); this._dashInfo = dashInfo || {}; @@ -460,7 +458,7 @@ class ClawClient { this._applyStatus(msg); if (msg.frp && msg.frp.server && msg.frp.auth_token) { - this._frpc.start(msg.claw_id, msg.frp, this._cfg.ssh_secret_key ?? null, this._isOpenClaw()).catch(e => { + this._frpc.start(msg.claw_id, msg.frp, this._cfg.ssh_secret_key ?? null, true).catch(e => { log.error('frpc', '启动失败:', e.message); }); } diff --git a/lib/frpc.js b/lib/frpc.js index 7d40554..ba9b0c1 100644 --- a/lib/frpc.js +++ b/lib/frpc.js @@ -7,6 +7,7 @@ const path = require('path'); const https = require('https'); const log = require('./logger'); const { Watchdog } = require('./watchdog'); +const { CUTOS_AGENT } = require('./agent-type'); const CONFIG_DIR = process.env.CLAWD_CONFIG_DIR || (process.getuid && process.getuid() === 0 ? '/etc/clawd' : path.join(os.homedir(), '.clawd')); @@ -15,6 +16,7 @@ const FRPC_CONFIG = path.join(CONFIG_DIR, 'frpc.toml'); const FRP_VERSION = '0.62.0'; const TTYD_PORT = 7681; +const CUTOS_DASHBOARD_PORT = 30141; function findTtydBin() { const candidates = ['/usr/bin/ttyd', '/usr/local/bin/ttyd', path.join(CONFIG_DIR, 'ttyd')]; @@ -49,7 +51,10 @@ function resolveOpenclawConfigFile() { * 直接读取比执行命令更可靠(不依赖 PATH、不需要进程启动等待)。 * systemd 服务的 ProtectHome=read-only 允许读取 /home 下的文件。 */ -function getDashboardInfo() { +function getDashboardInfo(agentType) { + if (agentType === CUTOS_AGENT) { + return Promise.resolve({ dashboard_port: CUTOS_DASHBOARD_PORT }); + } for (const cfgPath of OPENCLAW_JSON_CANDIDATES) { try { const raw = fs.readFileSync(cfgPath, 'utf8'); @@ -226,4 +231,10 @@ class FrpcManager { } } -module.exports = { getDashboardInfo, resolveOpenclawConfigFile, startTtyd, FrpcManager }; +module.exports = { + CUTOS_DASHBOARD_PORT, + getDashboardInfo, + resolveOpenclawConfigFile, + startTtyd, + FrpcManager, +}; diff --git a/test/dashboard-info.test.js b/test/dashboard-info.test.js new file mode 100644 index 0000000..8f4749b --- /dev/null +++ b/test/dashboard-info.test.js @@ -0,0 +1,10 @@ +'use strict'; + +const test = require('node:test'); +const assert = require('node:assert/strict'); +const { CUTOS_DASHBOARD_PORT, getDashboardInfo } = require('../lib/frpc'); + +test('CutOS Agent dashboard uses the fixed local console port without a token', async () => { + assert.equal(CUTOS_DASHBOARD_PORT, 30141); + assert.deepEqual(await getDashboardInfo('cutos-agent'), { dashboard_port: 30141 }); +});