This commit is contained in:
2026-02-24 20:01:15 +10:00
commit 8ef619ebdd
8 changed files with 4517 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
# Local configuration (machine-specific paths, do not commit)
manager-config.json
# OpenClaw config backups
*.bak
*.bak.*
*.v*.bak.js
# Temporary / build
/tmp/
*.tar.gz
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Linux
*~
# Node (just in case)
node_modules/
npm-debug.log*
yarn-error.log*
.env.local
+483
View File
@@ -0,0 +1,483 @@
# OpenClaw Manager — 开发日志
> 最后更新:2026-02-24
> 当前版本:v0.5.0
---
## v0.5 更新日志(2026-02-24
### 新功能
**认证页简化为引导模式**
- 移除了不稳定的 API Key 提交表单(通过 stdin 管道传 CLI 的方案不可靠)
- 改为引导页:点击 Provider 显示清晰的操作步骤 + 一键复制 CLI 命令
- 已配置的 Provider 在网格中显示 ✅ 标记
- 每个 Provider 指引末尾都提示运行 `openclaw onboard` 注册可用模型
- 删除了 `runWithStdin()` 函数和 `POST /api/auth/run` 端点
**模型页精简**
- 移除「添加模型」和「删除模型」功能(模型应由 `openclaw onboard` 管理)
- 只保留 Primary Model 选择器和 Fallback Chain 编辑
- 删除了 `POST /api/models``DELETE /api/models/:id` 端点
**API 费用追踪(Token Cost Monitor)— 📊 Stats 标签页**
- 新增 `GET /api/stats` 端点,解析 `logs/gateway.log` 中的 token 用量
- 支持 JSON 日志和文本格式日志(`input_tokens: N, output_tokens: N`
- 按模型和按天汇总统计,显示 Token 用量和估计成本
- 可视化:四张汇总卡片 + CSS 柱状图(按日) + 模型明细卡片
- 支持自定义模型定价(存 `manager-config.json``modelPricing` 字段)
- 时间范围过滤:7 / 30 / 90 天
- 点击标签页时懒加载,不影响首屏性能
**Cron 任务管理 — ⏰ Cron 标签页**
- 新增 `GET/POST/PUT/DELETE /api/cron` 四个端点,操作系统 crontab
- 只展示包含 `openclaw``ocm` 关键词的 cron 条目
- 支持:查看、添加、启用/禁用(注释/取消注释)、手动触发、删除
- 与 NAS 备份的 cron 条目联动(同样显示)
- 添加任务支持自定义 Cron 表达式 + 命令 + 标签
**Workspace 文件浏览器(全文件 + 可编辑)**
- 重写 `GET /api/workspace/:id`:动态扫描 workspace 目录下所有文件(不再硬编码 4 个文件名)
- 每个文件显示大小和最后修改时间
- 默认只读视图(`<pre>` 代码块),点击「编辑」按钮切换为 `<textarea>` 编辑模式
- 编辑后可保存或取消,保存调用已有的 `PUT /api/workspace/:id/:file`
- 大文件(> 512KB)只显示 stat 不加载内容,防止页面卡顿
**CLI Tab 补全**
- 在 CLI 终端输入框按 Tab 键触发前缀匹配自动补全
- 补全源:OpenClaw 子命令词表 + 预设命令列表 + 历史命令
- 单一匹配时直接补全;多个匹配时先补全公共前缀,同时弹出候选列表
- 候选列表最多 12 项,点击即选中;按 Escape 关闭
- 支持多词命令的最后一个词补全
**国际化(i18n)补全**
- 新增 30+ 个 i18n keyzh + en)覆盖 Stats、Cron、Workspace、Auth 引导等所有新功能
- 删除了不再使用的 `models.add``models.registered``auth.select` 等 key
### 移除
- `POST /api/auth/run` — API Key 提交端点(不可靠)
- `POST /api/models` — 添加模型端点
- `DELETE /api/models/:id` — 删除模型端点
- `runWithStdin()` — stdin 管道传值工具函数
- 前端:API Key 输入表单、添加模型弹窗、注册模型列表、删除模型按钮
### 技术说明
- **Stats 日志解析**:同时支持 JSON 格式(`{"input_tokens":N, "output_tokens":N}`)和文本格式(`input_tokens: N`),按时间戳过滤,按模型名和日期聚合
- **Cron 管理**:通过 `crontab -l` 读取和 `crontab -` 管道写入,不依赖任何外部库。启用/禁用通过添加/移除行首 `#` 注释实现
- **Tab 补全实现**:纯前端 JS,不需要 PTY。维护子命令词表 + 预设列表 + 历史记录三层候选源,使用最长公共前缀算法
- **Workspace 文件扫描**:使用 `fsp.readdir()` + `fsp.stat()` 动态列出,512KB 以上文件只返回 stat 不读内容
---
## v0.4 更新日志(2026-02-21
### 新功能
**安全状态指示器**
- Header 区域新增健康 badge(🔴/🟡),定期运行 `openclaw doctor` 自动检测问题
- 鼠标悬停展开 tooltip,显示全部 warning/error 详情
- 每 60 秒自动轮询,若后台问题消失,badge 自动隐藏
- 新增服务端 `GET /api/health` 端点,解析 doctor 输出中的 error / warn / missing / fail 关键词
**CLI 终端面板改进**
- **预设下拉菜单移至 header 区域**(Clear 按钮左侧),符合操作习惯,自然向上展开
- **默认命令扩充至 15 条**:新增 `gateway start/stop/logs``models auth list``agents sync``backup create/list``config validate``update`
- 修正 `openclaw version``openclaw --version`
**备份模块完全重设计**
- 旧的 3 步向导替换为**单页表单**:主机/端口、用户名、认证方式、路径、一键操作
- **认证方式**:密码(直接填,不存储)或 SSH Key(可一键生成)可切换
- **老设备兼容复选框**:勾选后自动附加 Legacy CBC 加密参数,解决老款 Synology 等 NAS cipher 协商失败问题(`aes128-cbc``diffie-hellman-group14-sha1` 等)
- **备份内容选择**:全量(整个 `.openclaw`,约 55MB)或仅重要数据(配置+API Key+记忆,不含日志/对话历史,约 10MB)
- 备份产物改为 tarball`openclaw-full-TIMESTAMP.tar.gz`),通过 rsync 传输,比直接 rsync 目录更安全、可校验
- 新增端口字段(默认 22),支持自定义 SSH 端口
- 定时备份支持自定义时间(时间选择器),不再写死 3:00
**国际化(i18n)补全**
- `renderAgents` 全面接入 i18n:主 Agent / subagent 标签、已绑群、保存模型、查看文件、删除,切换语言立即生效
- `renderChannels` 全面接入 i18n:无绑定提示、匹配所有、绑定索引、删除绑定
- `buildModelOpts` 接入 i18n:「使用全局默认」→「Use Global Default」;「自定义」→「custom」
### 修复
- Agents / Channels 页面切英文后按钮仍显示中文(根本原因:`renderAgents` / `renderChannels` 模板字符串内使用硬编码中文)
- 备份旧流程 UX 混乱(步骤2填用户名,步骤1填密码)
### 技术说明
- **老 NAS 密文兼容**`-o Ciphers=aes128-cbc,aes256-cbc,aes192-cbc,3des-cbc -o KexAlgorithms=diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 -o HostKeyAlgorithms=+ssh-rsa,+ssh-dss`
- **重要数据定义**`openclaw.json` + `.env` + `credentials/` + `agents/*/agent/`(含 API Key,排除 sessions+ `memory/main.sqlite`
- **全量备份排除**`logs/`(运行时重建)、`ocm/*.bak.js`(旧版本备份文件)
- 服务端新增 `GET /api/health` 端点,使用 `spawnSync` 同步运行 `openclaw doctor`3 秒超时,解析 error/warn 行返回结构化 JSON
---
## v0.4.1 热修复(2026-02-21
### 修复
**SSH Key 生成界面崩溃(MAIN_HTML `\n` 转义错误)**
- **症状**:首页点击无响应,F12 报 `Uncaught SyntaxError: Invalid or unexpected token at line 1785`,随后 `enterApp is not defined`
- **根本原因**`nasGenKey()` 函数中 `box.textContent = '公钥...\n' + r.pubKey``\n` 在 Node.js 评估 MAIN_HTML 模板字符串时被转为真实换行符,浏览器收到的 JS 里字符串字面量跨行 → SyntaxError → 整段脚本解析失败
- **修复**`'\n'``'\\n'`,源码里双反斜杠,Node 模板字符串评估后浏览器收到 `\n` 合法转义
- **规律**MAIN_HTML 模板字符串内所有 JS 字符串字面量里的 `\n` 都必须写成 `\\n`;每次新加代码后用 `node --check` 验证服务端,再提取 browser script 单独 `node --check` 验证浏览器端
---
## v0.4.2 热修复(2026-02-22
### 修复
**NAS 备份失败:sshpass 位置错误(直接原因)**
- **症状**:SSH 连接测试通过,但"立即备份"返回 `Permission denied, please try again` + rsync `unexpected end of file`
- **根本原因**:旧代码把 `sshpass -p "pwd"` 塞入 rsync 的 `-e` 参数内,双引号与外层引号互相冲突,导致 sshpass 无法正确读取密码
```bash
# ❌ 旧:引号冲突,password 被 shell 当作单独的 token
rsync -avz -e "sshpass -p "password" ssh -p 22 ..." ...
# ✅ 新:sshpass 包裹整个 rsync 命令,-e 里只有干净的 ssh
sshpass -p 'password' rsync -avz -e "ssh -p 22 ..." ...
```
- **修复位置**`nas-now`、`nas-cron`、`nas-test` 三处均修正
- **附加**:新增 `mkdir -p REMOTE_PATH` 预建远端目录步骤(避免因目录不存在导致 rsync 失败);密码改用单引号包裹 + `'\\''` 转义
**NAS SSH 兼容模式完全重设计**
- **旧问题**:兼容模式只强制 CBC 加密(`aes128-cbc,3des-cbc` 等),而新款 NASSynology DSM 7.x 等)已默认**禁用** CBC,导致勾选后反而无法连接
- **旧问题 2**`-o HostKeyAlgorithms=+ssh-rsa,+ssh-dss` 在新版 OpenSSH 上语法无效(`+` 前缀不能用于逗号分隔的多值列表),报 `Bad key types`
- **新策略**:兼容模式同时列出**现代算法 + 旧算法**,SSH 自动选双方都支持的最强项:
- Ciphers`aes256-gcm, aes128-gcm, chacha20-poly1305, aes256-ctr, aes192-ctr, aes128-ctr`(现代)+ `aes256-cbc, aes192-cbc, aes128-cbc, 3des-cbc`(旧款)
- KexAlgorithms`curve25519-sha256, ecdh-sha2-nistp256, dh-group14-sha256`(现代)+ `dh-group14-sha1, dh-group1-sha1`(旧款)
- HostKeyAlgorithms`ssh-ed25519, ecdsa-sha2-nistp256, rsa-sha2-256, rsa-sha2-512, ssh-rsa`(去掉 `+` 前缀)
- **结论**:兼容模式现在对新旧服务器均有效;新服务器默认关闭即可(SSH 自动协商)
**NAS 备份 Modal 全面 i18n**
- 所有标签、按钮、提示文字接入 `t()` + `data-i18n` 属性,切换语言立即生效
- 新增 21 个 i18n keyzh + en):`nas.title`, `nas.host`, `nas.user`, `nas.authLabel`, `nas.pwLabel`, `nas.pwHint`, `nas.keyLabel`, `nas.genKey`, `nas.pubkeyHint`, `nas.remotePath`, `nas.compat`, `nas.content`, `nas.full`, `nas.essential`, `nas.btnTest/Now/Cron/Close`, `nas.cronTime`, `nas.btnSaveCron`, `nas.testing/testOk/testFail`, `nas.backing/backupOk/backupFail`, `nas.keyGenOk/Fail`, `nas.cronOk/Toast`, `nas.backupToast`, `nas.errNoHost`
- `applyLang()` 新增 `data-i18n-placeholder` 属性支持,密码输入框提示也随语言切换
- Checkbox 文字从「老设备兼容模式(Legacy CBC...)」改为「兼容模式(添加旧版 SSH 加密方案,适用于旧款 NAS / 旧服务器)」,更准确描述用途
### 技术说明
- **sshpass 用法规范**:密码认证时,`sshpass -p 'pwd' rsync -e "ssh ..."` 是正确形式;`rsync -e "sshpass ... ssh ..."` 是错误形式(所有三处:test / now / cron 均已修正)
- **密码安全转义**`password.replace(/'/g, "'\\''")` 处理密码中含单引号的情况
- **PreferredAuthentications=password,PubkeyAuthentication=no**:密码认证时明确禁用公钥,防止 SSH 在无 key 时尝试公钥认证导致不必要的交互提示
---
## v0.5 规划(竞品分析后)
> 调研了 GitHub 上 7 个同类项目后,提炼出最值得借鉴、且与 OCM"零依赖+单文件"哲学兼容的三个方向。
### 优先级 1 — API 费用追踪(Token Cost Monitor
**来源**tugcantopaloglu/openclaw-dashboard、mudrii/openclaw-dashboard、adamevers/openclaw-dashboard 均有此功能,说明这是 power user 高频需求。
**实现思路**(零依赖):
- 解析 `logs/gateway.log`,提取各 session 的 token 用量行(OpenClaw 日志里已有 token 计数)
- 在内存中汇总(按模型、按天)—— 无需 SQLite,用 JS 对象即可
- 新增「Stats」浮层或在 header 右侧加费用小数字,点击展开明细
- 可选:支持自定义各模型单价(存 manager-config.json
**预计新增代码量**:约 100 行服务端(日志解析)+ 150 行前端(展示)
---
### 优先级 2 — Cron Job 管理页面
**来源**actionagentai/openclaw-dashboard12 页布局之一)、tugcantopaloglu/openclaw-dashboard 均有完整 cron 管理。
**实现思路**(零依赖):
- 在「操作」菜单或独立标签页列出系统 crontab(`crontab -l`)里所有 `openclaw` 相关的条目
- 支持:查看 / 启用 / 禁用 / 手动触发(直接 spawn 命令)/ 修改时间
- 读写通过 `crontab -l` + `crontab -` 管道实现,不依赖任何库
- 也可显示 OCM 自己设置的备份 cron,与 NAS 备份模块联动
**预计新增代码量**:约 80 行服务端(crontab CRUD+ 120 行前端
---
### 优先级 3 — Memory 文件浏览器
**来源**tugcantopaloglu/openclaw-dashboard 支持浏览和编辑 MEMORY.md / HEARTBEAT.md 等 Agent 记忆文件。
**实现思路**(零依赖):
- 在 Agents 卡片的「查看文件」按钮旁,或在文件浏览 modal 里增加编辑模式(`<textarea>`
- 保存时直接写回文件(已有 `writeFile` 工具函数)
- 可选:显示文件大小和最后修改时间
**预计新增代码量**:约 20 行服务端(`PUT /api/agent/:id/file`+ 60 行前端
---
### 竞品没有的 OCM 独特优势(保持并强化)
| OCM 特性 | 状态 |
|---------|------|
| 真单文件 / 零 npm 依赖 | ✅ 保持 |
| 内置 CLI 终端(实时流、预设、收藏) | ✅ 独有 |
| NAS SFTP 备份(含老设备密文兼容) | ✅ 独有 |
| 中英文 i18n | ✅ 独有 |
| Windows + macOS 双平台一键启动 | ✅ 独有 |
| Health Badgeopenclaw doctor 可视化) | ✅ 独有 |
---
## 一、项目概述
**OpenClaw Manager** 是一个零依赖本地 Web 管理界面,用于可视化管理 OpenClaw AI 助理的 Agent、模型、认证配置等,免去手动编辑 JSON 文件。
- 运行方式:`node openclaw-manager.js`,浏览器访问 `http://localhost:3333`
- 依赖:仅 Node.js >= 18 内置模块(`http`、`fs`、`path`、`os`、`child_process`),零 npm 依赖
- 平台:macOS / Linux / Windows
---
## 零、v0.3 更新日志(2026-02-21
### 新功能
**Landing 页面 + 语言切换**
- 首次进入显示模式选择页,两个入口:Sub-agent 模式(可用)和 Multi-agent 模式(占位,敬请期待)
- 语言切换(中文/English),存储在 localStorage,刷新记忆
- 每个模式卡片显示简介和所需条件
- 点击 Logo 可随时返回选择页
**Channels 管理页面**
- 新增「Channels」标签页,显示 openclaw.json 里所有 bindings
- 支持添加绑定(选 Agent、频道类型、Peer 类型、Peer ID
- 支持删除绑定
- 创建/删除 Agent 后自动刷新 Channel 列表
**主 Agent 模型选择**
- main agent 卡片现在也显示模型选择器和「保存模型」按钮
- 可以为 main agent 独立设置模型,不再只能跟随全局默认
**认证页面重做**
- 修正了所有 Provider 的 CLI 命令(原命令 `openclaw auth add` 是错误的)
- 正确命令:`openclaw models auth paste-token --provider <provider>`
- 新增 Provider 选择网格,点击选中后显示操作区
- Token 类 Provider:可在界面直接输入 API Key,由后台通过 stdin 管道传给 CLI 执行(Key 不存储到配置文件)
- OAuth 类(Google):显示正确命令和复制按钮
- Device Flow 类(GitHub Copilot):显示分步操作指引
- 底部仍显示已配置认证列表
**重启 GW 交互优化**
- 横幅新增「稍后」按钮:点击后横幅消失,页面左下角出现常驻橙色「重启 Gateway」浮动按钮
- 执行重启后浮动按钮消失
- 「忽略」按钮:直接关闭横幅,不显示浮动按钮
**NAS 备份设置**
- 「操作」菜单新增「NAS 备份设置」入口
- 三步引导界面:SSH Key 生成 → NAS 连接配置 → 备份操作
- SSH Key:一键生成专用 Key,公钥可复制,支持一次性密码部署(密码不存储)
- 配置:NAS 主机 IP、用户名、SSH Key 路径、远端备份目录,保存到 manager-config.json
- 操作:测试连接、立即备份(rsync)、配置每日 3:00 Cron 任务
**默认 SOUL.md 更新**
- 新建 Subagent 时,留空性格关键词则使用新的默认成长型提示词,体现"你是我生活中的客人"理念
- 性格关键词有值时,仍使用关键词列表模式
### 修复
- AUTH_PROVIDERS 的所有 `docCmd` 字段已修正为正确的 `openclaw models auth paste-token --provider X` 格式
- 新增 `spawn` 到 require(用于 stdin 管道传入 API Key
---
## 二、文件结构
```
~/ocm/ ← 项目目录(用户自选位置)
├── openclaw-manager.js ← 主程序(服务端 + 前端 HTML 全合一,~2360行)
├── start.sh ← macOS/Linux 启动脚本
├── start.bat ← Windows 启动脚本
├── openclaw-manager.command ← macOS Finder 双击启动
├── manager-config.json ← 本地路径配置(已 .gitignore,不上传)
├── package.json ← GitHub 项目元数据
├── .gitignore ← 排除 manager-config.json、*.bak* 等
├── README.md ← 中英双语说明文档
└── DEVLOG.md ← 本文件
```
**OpenClaw 配置目录**(独立,不在项目里):
```
~/.openclaw/
├── openclaw.json ← OpenClaw 主配置(程序读写的核心文件)
├── agents/ ← 各 Agent 的 config.json
├── workspaces/ ← Agent 工作区(SOUL.md、MEMORY.md 等)
├── logs/gateway.log ← 网关日志
└── openclaw.json.bak.* ← 自动备份文件
```
---
## 三、目录解析优先级
程序启动时按以下顺序确定 OpenClaw 配置目录:
1. `--dir` 命令行参数
2. `OPENCLAW_DIR` 环境变量
3. 同目录下的 `manager-config.json``{ "dir": "~/.openclaw" }`
4. 默认值 `~/.openclaw`
`~` 在所有平台会自动展开(`os.homedir()`),Windows 用户填 `~/.openclaw` 即可。
---
## 四、已实现功能
### 🤖 Agents 标签页
- 列出所有 Agent(含 main
- 每个 Agent 卡片显示:模型、群组绑定状态、Workspace 路径
- **内联模型切换**:每个 Agent 有独立下拉菜单,直接保存不需要重建
- 4 步向导新建 Subagent:群组ID → 名称/描述 → 选模型 → 确认创建
- 自动创建 workspace 目录、SOUL.md、MEMORY.md
- 自动在 openclaw.json 添加 agent + binding(插入在 main 之前)
- 创建前自动备份 openclaw.json
- 删除 Agent(自动备份,可回滚)
- 查看 Workspace 文件(SOUL.md / MEMORY.md
### 🧠 模型标签页
- 显示当前全局主模型,可下拉修改
- Fallback 链可视化编辑(增删 tag)
- 列出所有已配置模型,可添加自定义模型 ID
- 移除模型
### 🔑 认证标签页
支持的认证方式:
| Provider | 模式 |
|---|---|
| Anthropic | API Token |
| OpenAI | API Token |
| DeepSeek | API Token |
| Kimi (Moonshot) | API Token |
| Groq | API Token |
| Mistral | API Token |
| Together AI | API Token |
| Perplexity | API Token |
| Google | OAuth |
| GitHub Copilot | Device Flow |
| 自定义 | API Token |
### ⚡ 顶部工具栏(下拉菜单)
- 重启 Gateway(调用 `openclaw gateway restart`
- 实时日志(每 2 秒刷新,查看 `logs/gateway.log`
- 手动备份
- 备份回滚(列出最近 20 个备份,一键恢复,恢复前自动保存当前状态)
- 健康检查(`openclaw doctor`
- 打开配置目录(调用系统文件管理器)
- 切换 OpenClaw 目录(运行时切换,写入 manager-config.json
### 其他
- 配置修改后顶部显示橙色"建议重启 Gateway"横幅
- Toast 通知(成功/失败提示)
- 深色主题 UI`#0f1117` 背景,`#6c63ff` 强调色)
---
## 五、已修复的 Bug
### Bug 1:浏览器 SyntaxError(启动即崩溃)
- **症状**:页面打开后"加载中..."一直卡着,F12 控制台显示 `Uncaught SyntaxError: Invalid or unexpected token`
- **根本原因**`MAIN_HTML` 是服务端的模板字符串(反引号),里面有一行:
```javascript
document.getElementById('cmdOutput').textContent='❌ '+e.message+'\n\n请在终端手动运行:\nopenclaw gateway restart';
```
Node.js 在评估模板字符串时把 `\n` 变成了真实换行符,浏览器收到的 JS 里单引号字符串跨行,导致解析失败。
- **修复**:将 `'\n\n...\n...'` 改为 `'\\n\\n...\\n...'`,让浏览器收到正确的 `\n` 转义序列。
- **位置**`openclaw-manager.js` 约第 1473 行。
### Bug 3MAIN_HTML 模板字符串 `\n` 转义(反复出现)
- **症状**:首页点击无响应,`Uncaught SyntaxError: Invalid or unexpected token` + `enterApp is not defined`
- **根本原因**:在 `const MAIN_HTML = \`...\`` 模板字符串内,JS 字符串字面量里的 `\n`(如 `'msg\n'`)会被 Node.js 在求值模板字符串时转成真实换行符,导致浏览器 JS 解析失败
- **修复模式**:MAIN_HTML 里所有字符串字面量中的 `\n` 必须写成 `\\n`
- **已出现次数**v0.3`cmdOutput` 错误文本)、v0.4 末尾(`cliAppend` 命令行前后缀)、v0.4.1`nasGenKey` 公钥显示)
- **预防**:每次修改后运行 `node --check` + 提取 browser script 再 `node --check`;用扫描脚本检测 MAIN_HTML 内所有单反斜杠 `\n`
### Bug 2Agent 模型下拉菜单只有"使用全局默认"
- **症状**Agents 页面每个 Agent 的模型选择器里只有一个选项
- **根本原因**`loadAgents()` 和 `loadModels()` 并行执行(`Promise.all`),`renderAgents()` 先跑完时 `S.knownModels` 还是空数组,`buildModelOpts()` 只能生成默认选项。`buildModelDropdowns()` 函数本来用于在模型加载完后重填下拉菜单,但实现为空函数 `{}`。
- **修复**:补全 `buildModelDropdowns()` 实现,遍历所有 Agent,用当时已填充的 `S.knownModels` 重建每个 `msel-{id}` select 元素的选项。
- **位置**`openclaw-manager.js` 约第 1458 行。
---
## 六、重要技术细节
### openclaw.json 结构要点
- `peer.id` 在 bindings 里必须是**字符串**`"-1003893176648"`),不是整数
- `"main"` 是保留 agent ID,不能用作自定义 agent
- 文件修改后 300ms 内自动热重载,大多数情况不需要重启 gateway
- 新 agent 的 binding 要插入在 `main` 的 catch-all binding **之前**
### 备份命名规则
```
openclaw.json.bak.{label}.{timestamp}
```
label 可以是:`create` / `edit` / `delete` / `models` / `auth` / `manual` / `before-restore`
### 跨平台注意
- 启动浏览器:`open`macOS)、`start ""`Windows)、`xdg-open`Linux
- 运行 openclaw 命令:Windows 用 `openclaw.cmd`,其他用 `openclaw`
- `manager-config.json` 路径支持 `~` 前缀,所有平台通用
### KNOWN_MODELS 列表(代码内置)
GitHub Copilot、Anthropic、OpenAI、Google、DeepSeek、Kimi、Groq、Mistral、Together AI 共约 20 个模型。
---
## 七、待改进 / 已知问题
### 功能增强(用户提出过,暂未做)
- [ ] SOUL.md 可视化编辑器(当前只能查看,不能在界面里修改内容)
- [ ] 工作区文件内容在浏览器里直接编辑保存
- [ ] Agent 热切换模型(不重建,只改配置)
- [ ] 多 Bot 账号支持
- [ ] SSH 远程服务器管理
- [ ] 从零引导安装 OpenClaw 的向导
### 代码质量
- [ ] 前端代码目前全部内嵌在 `MAIN_HTML` 模板字符串里,文件较长(~1650行),后续可考虑拆分或构建步骤
- [ ] 模型下拉菜单在 `renderAgents` 之后才由 `buildModelDropdowns` 修复,可以改成串行加载(先 `loadModels` 再 `loadAgents`)以更优雅地解决时序问题
### 部署体验
- [ ] `manager-config.json` 目前需要用户手动创建,可以考虑首次启动时通过 UI 向导引导创建(setup wizard 已有框架)
- [ ] README 中加入截图
---
## 八、GitHub 上传准备清单
- [x] `.gitignore` 已排除 `manager-config.json`、`*.bak*`、`.DS_Store` 等
- [x] `package.json` 的 `author` 字段为空(不含个人信息)
- [x] `README.md` 中英双语
- [x] 主程序无硬编码个人信息(API Key、路径、Token 等均运行时读取)
- [ ] 在 `package.json` 的 `author` 填上你的名字/GitHub 用户名(可选)
- [ ] GitHub 新建仓库,`git init → git add . → git commit → git push`
---
## 九、启动方式快速参考
```bash
# 直接启动(自动读取 manager-config.json 或 ~/.openclaw
bash ~/ocm/start.sh
# 指定目录
bash ~/ocm/start.sh --dir /path/to/.openclaw
# 指定端口(默认 3333
bash ~/ocm/start.sh --port 8080
# macOS Finder 双击
openclaw-manager.command
# Windows
start.bat
```
访问 `http://localhost:3333`
+203
View File
@@ -0,0 +1,203 @@
# OpenClaw Manager
> 🦀 A zero-dependency local web UI for managing [OpenClaw](https://github.com/OpenClaw-AI/openclaw) AI agents
>
> 零依赖本地 Web 管理界面,告别手动编辑配置文件
---
[中文](#中文说明) | [English](#english)
---
## 中文说明
### 简介
OpenClaw Manager 是一个运行在本地的轻量级 Web 管理界面,帮助你可视化管理 OpenClaw 的 AI 智能体(Agent)、模型配置和认证信息。**无需安装任何 npm 依赖**,只需要 Node.js 18+。
### 功能
- 🤖 **Agent 管理** — 新建子智能体(含向导)、内联切换模型、查看工作区文件、删除(自动备份)
- 🧠 **模型管理** — 修改全局主模型、编辑 Fallback 链、添加 / 删除自定义模型
- 🔑 **认证管理** — 支持 Anthropic、OpenAI、DeepSeek、Kimi、Groq、Mistral、Together、Perplexity、GoogleOAuth)、GitHub CopilotDevice Flow
- 🔄 **备份 & 回滚** — 每次写入前自动备份 `openclaw.json`,支持一键回滚
- 📋 **网关操作** — 重启 Gateway、实时查看日志
- 🖥️ **跨平台** — macOS / Linux / Windows
### 系统要求
- Node.js **>= 18**[下载](https://nodejs.org/)
- 已安装并配置好的 [OpenClaw](https://github.com/OpenClaw-AI/openclaw)
### 安装
```bash
git clone https://github.com/你的用户名/openclaw-manager.git
cd openclaw-manager
```
不需要 `npm install`,直接启动即可。
### 启动方式
#### 方式一:脚本启动(推荐)
```bash
# macOS / Linux
bash start.sh
# Windows
start.bat
```
#### 方式二:macOS 双击启动
在 Finder 中双击 `openclaw-manager.command`(首次可能需要在系统设置 → 隐私与安全 中允许)。
#### 方式三:npm
```bash
npm start
```
#### 方式四:直接运行
```bash
node openclaw-manager.js
```
启动后访问:`http://localhost:3333`
### 指定 OpenClaw 目录
程序按以下优先级查找 `openclaw.json`
| 优先级 | 方式 |
|--------|------|
| 1 | `--dir` 命令行参数 |
| 2 | `OPENCLAW_DIR` 环境变量 |
| 3 | 同目录下的 `manager-config.json` |
| 4 | `~/.openclaw`(默认) |
**推荐:** 在项目目录下新建 `manager-config.json`,之后无需每次带参数:
```json
{ "dir": "~/.openclaw" }
```
`~` 在所有平台上会自动展开为当前用户主目录,无需手动填写完整路径。也可以写绝对路径:
| 系统 | 示例 |
|------|------|
| macOS / Linux | `{ "dir": "/Users/yourname/.openclaw" }` |
| Windows(正斜杠)| `{ "dir": "C:/Users/yourname/.openclaw" }` |
| Windows(反斜杠)| `{ "dir": "C:\\Users\\yourname\\.openclaw" }` |
或者直接指定:
```bash
# macOS / Linux
bash start.sh --dir ~/.openclaw
# Windows
start.bat --dir C:/Users/yourname/.openclaw
```
`manager-config.json` 已加入 `.gitignore`,不会被提交。
### 关于 Shell alias(可选)
如果想在终端随时一个命令启动,在 `~/.zshrc``~/.bashrc` 里加一行:
```bash
alias ocm="bash ~/openclaw-manager/start.sh"
```
然后 `source ~/.zshrc`,之后直接敲 `ocm` 即可。
---
## English
### What is this?
OpenClaw Manager is a lightweight, zero-dependency local web UI for [OpenClaw](https://github.com/OpenClaw-AI/openclaw). It lets you visually manage AI agents, model configurations, and auth profiles without editing JSON files by hand.
**No `npm install` needed** — just Node.js 18+.
### Features
- 🤖 **Agent management** — Create subagents (with wizard), switch models inline, browse workspace files, delete with auto-backup
- 🧠 **Model management** — Edit global primary model, manage fallback chain, add/remove custom models
- 🔑 **Auth management** — Anthropic, OpenAI, DeepSeek, Kimi (Moonshot), Groq, Mistral, Together, Perplexity, Google (OAuth), GitHub Copilot (Device Flow)
- 🔄 **Backup & rollback** — Auto-backup `openclaw.json` before every write, one-click restore
- 📋 **Gateway operations** — Restart gateway, tail logs in real time
- 🖥️ **Cross-platform** — macOS / Linux / Windows
### Requirements
- Node.js **>= 18** ([download](https://nodejs.org/))
- A working [OpenClaw](https://github.com/OpenClaw-AI/openclaw) installation
### Install
```bash
git clone https://github.com/your-username/openclaw-manager.git
cd openclaw-manager
# No npm install needed
```
### Start
```bash
# macOS / Linux
bash start.sh
# Windows
start.bat
# macOS: double-click openclaw-manager.command in Finder
# Or directly
node openclaw-manager.js
```
Then open `http://localhost:3333` in your browser.
### Directory configuration
The app resolves the OpenClaw config directory in this order:
1. `--dir` CLI argument
2. `OPENCLAW_DIR` environment variable
3. `manager-config.json` in the same folder as the script
4. `~/.openclaw` (default)
**Recommended:** create `manager-config.json` next to the script so you never need to pass flags:
```json
{ "dir": "/home/yourname/.openclaw" }
```
`manager-config.json` is in `.gitignore` and will not be committed.
### Optional: shell alias
```bash
# Add to ~/.zshrc or ~/.bashrc
alias ocm="bash ~/openclaw-manager/start.sh"
```
### Custom port
```bash
bash start.sh --port 8080
node openclaw-manager.js --port 8080
```
---
## License
MIT
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
# ================================================================
# OpenClaw Manager — macOS 双击启动
#
# 在 Finder 中双击此文件即可在 Terminal 里运行 start.sh
# 特性:
# • 自动 cd 到脚本所在目录(无论从哪里双击)
# • 如果 start.sh 不存在,给出友好提示
# • 窗口标题显示 OpenClaw Manager
# • 运行结束后窗口不会立即关闭
# ================================================================
# 设置窗口标题
printf '\033]0;OpenClaw Manager\007'
# 切换到脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR" || {
echo "❌ 无法进入目录: $SCRIPT_DIR"
echo "按 Enter 关闭..."
read -r
exit 1
}
# 检查 start.sh 是否存在
if [ ! -f "./start.sh" ]; then
echo ""
echo " ❌ 找不到 start.sh"
echo " 当前目录: $SCRIPT_DIR"
echo ""
echo " 请确认以下文件在同一目录下:"
echo " • openclaw-manager.command (本文件)"
echo " • start.sh"
echo " • openclaw-manager.js"
echo ""
echo "按 Enter 关闭..."
read -r
exit 1
fi
# 确保 start.sh 有执行权限
chmod +x ./start.sh 2>/dev/null
# 运行
bash ./start.sh "$@"
EXIT_CODE=$?
# 如果异常退出,保持窗口打开
if [ $EXIT_CODE -ne 0 ]; then
echo ""
echo " 退出码: $EXIT_CODE"
echo " 按 Enter 关闭..."
read -r
fi
+3393
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -0,0 +1,24 @@
{
"name": "openclaw-manager",
"version": "0.4.2",
"description": "A local web UI for managing OpenClaw AI agents — no npm install required",
"main": "openclaw-manager.js",
"scripts": {
"start": "node openclaw-manager.js",
"start:dir": "node openclaw-manager.js --dir"
},
"engines": {
"node": ">=18"
},
"keywords": [
"openclaw",
"ai-agent",
"telegram-bot",
"llm",
"local-ui",
"no-dependencies"
],
"author": "",
"license": "MIT",
"dependencies": {}
}
+170
View File
@@ -0,0 +1,170 @@
@echo off
:: ================================================================
:: OpenClaw Manager v0.5 — Windows 启动脚本
::
:: 特性:
:: * 自动检测 Node.js,未安装时给出安装指引(winget/scoop/官网)
:: * 自动检测 %USERPROFILE%\.openclaw 目录
:: * 首次运行自动创建 manager-config.json
:: * 自动检测端口占用并建议替代端口
:: * 支持 --dir / --port / --help 参数
:: ================================================================
setlocal enabledelayedexpansion
chcp 65001 >nul 2>&1
set "SCRIPT_DIR=%~dp0"
set "MANAGER_JS=%SCRIPT_DIR%openclaw-manager.js"
set "CONFIG_JSON=%SCRIPT_DIR%manager-config.json"
set "MIN_NODE_MAJOR=18"
echo.
echo ===================================
echo OpenClaw Manager v0.5
echo -----------------------------------
echo.
:: ── 检查主文件 ────────────────────────────────────────────────
if not exist "%MANAGER_JS%" (
echo [X] 找不到 openclaw-manager.js
echo 期望路径: %MANAGER_JS%
echo.
pause
exit /b 1
)
:: ── 检查 Node.js ─────────────────────────────────────────────
where node >nul 2>&1
if errorlevel 1 (
echo [X] 未找到 Node.js
echo.
echo 安装方式(选一种即可):
echo.
echo 1^) winget: winget install OpenJS.NodeJS.LTS
echo 2^) scoop: scoop install nodejs-lts
echo 3^) 官网下载: https://nodejs.org/
echo 4^) nvm-windows: https://github.com/coreybutler/nvm-windows
echo.
pause
exit /b 1
)
:: 获取主版本号并检查
for /f "tokens=1 delims=." %%v in ('node -e "process.stdout.write(process.versions.node)"') do (
set "NODE_MAJOR=%%v"
)
if !NODE_MAJOR! LSS %MIN_NODE_MAJOR% (
echo [!] Node.js 版本过低(需要 ^>= v%MIN_NODE_MAJOR%
echo.
echo 安装方式(选一种即可):
echo.
echo 1^) winget: winget install OpenJS.NodeJS.LTS
echo 2^) scoop: scoop install nodejs-lts
echo 3^) 官网下载: https://nodejs.org/
echo.
pause
exit /b 1
)
for /f "tokens=*" %%v in ('node -e "process.stdout.write('v'+process.versions.node)"') do (
echo [OK] Node.js %%v
)
:: ── 解析参数 ─────────────────────────────────────────────────
set "DIR_ARG="
set "PORT_ARG="
set "EXTRA_ARGS="
:parse_args
if "%~1"=="" goto :after_args
if /i "%~1"=="--help" goto :show_help
if /i "%~1"=="-h" goto :show_help
if /i "%~1"=="--dir" (
set "DIR_ARG=%~2"
shift & shift
goto :parse_args
)
if /i "%~1"=="--port" (
set "PORT_ARG=%~2"
shift & shift
goto :parse_args
)
set "EXTRA_ARGS=!EXTRA_ARGS! %~1"
shift
goto :parse_args
:show_help
echo 用法: start.bat [选项]
echo.
echo 选项:
echo --dir ^<路径^> OpenClaw 配置目录(默认 %%USERPROFILE%%\.openclaw
echo --port ^<端口^> 监听端口(默认 3333
echo --help 显示帮助
echo.
exit /b 0
:after_args
:: ── 检测 OpenClaw 配置目录 ───────────────────────────────────
set "OPENCLAW_DIR="
if defined DIR_ARG (
set "OPENCLAW_DIR=!DIR_ARG!"
) else if exist "%CONFIG_JSON%" (
for /f "tokens=*" %%d in ('node -e "try{const c=JSON.parse(require('fs').readFileSync('%CONFIG_JSON%','utf8'));const d=c.openclawDir||c.dir||'';process.stdout.write(d.replace(/^~/,require('os').homedir()))}catch{}"') do (
set "OPENCLAW_DIR=%%d"
)
)
if not defined OPENCLAW_DIR set "OPENCLAW_DIR=%USERPROFILE%\.openclaw"
if exist "!OPENCLAW_DIR!" (
echo [OK] 配置目录: !OPENCLAW_DIR!
) else (
echo [!] 配置目录不存在: !OPENCLAW_DIR!
echo 首次使用?请先运行 openclaw onboard 初始化。
)
:: ── 首次运行:自动创建 manager-config.json ────────────────────
if not exist "%CONFIG_JSON%" (
echo [-^>] 首次运行,创建 manager-config.json
node -e "require('fs').writeFileSync('%CONFIG_JSON%',JSON.stringify({dir:'~/.openclaw'},null,2))"
)
:: ── 检查端口可用性 ───────────────────────────────────────────
set "PORT=3333"
if defined PORT_ARG set "PORT=!PORT_ARG!"
netstat -an 2>nul | findstr /r ":%PORT% .*LISTENING" >nul 2>&1
if not errorlevel 1 (
echo [!] 端口 !PORT! 已被占用
for %%p in (3334 3335 3336 8080 8888) do (
netstat -an 2>nul | findstr /r ":%%p .*LISTENING" >nul 2>&1
if errorlevel 1 (
echo 尝试备用端口 %%p...
set "PORT=%%p"
set "PORT_ARG=%%p"
goto :port_ok
)
)
)
:port_ok
:: ── 构建启动命令 ─────────────────────────────────────────────
set "CMD_ARGS="
if defined DIR_ARG set "CMD_ARGS=!CMD_ARGS! --dir "!DIR_ARG!""
if defined PORT_ARG set "CMD_ARGS=!CMD_ARGS! --port !PORT_ARG!"
if defined EXTRA_ARGS set "CMD_ARGS=!CMD_ARGS! !EXTRA_ARGS!"
echo.
echo [^>] 启动中 -^> http://localhost:!PORT!
echo Ctrl+C 停止
echo.
:: ── 启动 ─────────────────────────────────────────────────────
node "%MANAGER_JS%"!CMD_ARGS!
if errorlevel 1 (
echo.
echo [X] 启动失败,请检查上方错误信息。
pause
)
endlocal
Executable
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env bash
# ================================================================
# OpenClaw Manager v0.5 — 跨平台启动脚本 (macOS / Linux)
#
# 特性:
# • 自动检测 Node.js,未安装时给出安装指引
# • 自动检测 ~/.openclaw 目录,不存在时提示
# • 首次运行自动创建 manager-config.json
# • 自动检测端口占用并建议替代端口
# • 支持 --dir / --port / --help 参数
# ================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MANAGER_JS="$SCRIPT_DIR/openclaw-manager.js"
CONFIG_JSON="$SCRIPT_DIR/manager-config.json"
MIN_NODE_MAJOR=18
# ── 颜色 ─────────────────────────────────────────────────────
RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'
CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; RESET='\033[0m'
banner() {
echo ""
echo -e "${CYAN}${BOLD} 🦀 OpenClaw Manager v0.5${RESET}"
echo -e "${DIM} ─────────────────────────────${RESET}"
echo ""
}
banner
# ── 检查主文件 ────────────────────────────────────────────────
if [ ! -f "$MANAGER_JS" ]; then
echo -e "${RED}✗ 找不到 openclaw-manager.js${RESET}"
echo -e " 期望路径: ${DIM}$MANAGER_JS${RESET}"
exit 1
fi
# ── 检查 Node.js ─────────────────────────────────────────────
install_node_hint() {
echo ""
echo -e " ${BOLD}安装方式(选一种即可):${RESET}"
echo ""
if [[ "$(uname)" == "Darwin" ]]; then
echo -e " ${GREEN}1)${RESET} Homebrew: ${CYAN}brew install node${RESET}"
echo -e " ${GREEN}2)${RESET} 官网下载: ${CYAN}https://nodejs.org/${RESET}"
echo -e " ${GREEN}3)${RESET} nvm: ${CYAN}curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash${RESET}"
echo -e " ${DIM}然后 nvm install --lts${RESET}"
else
echo -e " ${GREEN}1)${RESET} apt: ${CYAN}sudo apt install -y nodejs npm${RESET}"
echo -e " ${GREEN}2)${RESET} 官网下载: ${CYAN}https://nodejs.org/${RESET}"
echo -e " ${GREEN}3)${RESET} nvm: ${CYAN}curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash${RESET}"
echo -e " ${DIM}然后 nvm install --lts${RESET}"
fi
echo ""
}
if ! command -v node &>/dev/null; then
echo -e "${RED}✗ 未找到 Node.js${RESET}"
install_node_hint
exit 1
fi
NODE_VER=$(node -e "process.stdout.write(String(process.versions.node.split('.')[0]))")
if [ "$NODE_VER" -lt "$MIN_NODE_MAJOR" ]; then
echo -e "${YELLOW}⚠ Node.js 版本过低(当前 v$(node -v),需要 >= v${MIN_NODE_MAJOR}${RESET}"
install_node_hint
exit 1
fi
echo -e " ${GREEN}${RESET} Node.js $(node -v)"
# ── 解析参数 ─────────────────────────────────────────────────
DIR_ARG=""
PORT_ARG=""
EXTRA_ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--dir) DIR_ARG="$2"; shift 2;;
--dir=*) DIR_ARG="${1#*=}"; shift;;
--port) PORT_ARG="$2"; shift 2;;
--port=*) PORT_ARG="${1#*=}"; shift;;
--help|-h)
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " --dir <路径> OpenClaw 配置目录(默认 ~/.openclaw"
echo " --port <端口> 监听端口(默认 3333"
echo " --help 显示帮助"
exit 0;;
*) EXTRA_ARGS+=("$1"); shift;;
esac
done
# ── 检测 OpenClaw 配置目录 ───────────────────────────────────
# 优先级: --dir 参数 > manager-config.json > 环境变量 > 默认
OPENCLAW_DIR=""
if [ -n "$DIR_ARG" ]; then
OPENCLAW_DIR="${DIR_ARG/#\~/$HOME}"
elif [ -f "$CONFIG_JSON" ]; then
OPENCLAW_DIR=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('$CONFIG_JSON','utf8'));const d=c.openclawDir||c.dir||'';process.stdout.write(d.replace(/^~/,require('os').homedir()))}catch{}" 2>/dev/null)
fi
if [ -z "$OPENCLAW_DIR" ] && [ -n "$OPENCLAW_DIR_ENV" ]; then
OPENCLAW_DIR="$OPENCLAW_DIR_ENV"
fi
[ -z "$OPENCLAW_DIR" ] && OPENCLAW_DIR="$HOME/.openclaw"
if [ -d "$OPENCLAW_DIR" ]; then
echo -e " ${GREEN}${RESET} 配置目录: ${DIM}$OPENCLAW_DIR${RESET}"
else
echo -e " ${YELLOW}${RESET} 配置目录不存在: ${DIM}$OPENCLAW_DIR${RESET}"
echo -e " ${DIM}首次使用?请先运行 openclaw onboard 初始化。${RESET}"
fi
# ── 首次运行:自动创建 manager-config.json ────────────────────
if [ ! -f "$CONFIG_JSON" ]; then
echo -e " ${CYAN}${RESET} 首次运行,创建 ${DIM}manager-config.json${RESET}"
node -e "require('fs').writeFileSync('$CONFIG_JSON',JSON.stringify({dir:'~/.openclaw'},null,2))"
fi
# ── 检查端口可用性 ───────────────────────────────────────────
PORT="${PORT_ARG:-3333}"
check_port() {
if command -v lsof &>/dev/null; then
lsof -i :"$1" -sTCP:LISTEN >/dev/null 2>&1 && return 1
elif command -v ss &>/dev/null; then
ss -tlnp 2>/dev/null | grep -q ":$1 " && return 1
elif command -v netstat &>/dev/null; then
netstat -tlnp 2>/dev/null | grep -q ":$1 " && return 1
fi
return 0
}
if ! check_port "$PORT"; then
echo -e " ${YELLOW}${RESET} 端口 ${PORT} 已被占用"
# 尝试找一个可用端口
for ALT in 3334 3335 3336 8080 8888; do
if check_port "$ALT"; then
echo -e " ${DIM}尝试备用端口 ${ALT}...${RESET}"
PORT="$ALT"
PORT_ARG="$ALT"
break
fi
done
fi
# ── 构建启动命令 ─────────────────────────────────────────────
CMD_ARGS=()
[ -n "$DIR_ARG" ] && CMD_ARGS+=(--dir "$DIR_ARG")
[ -n "$PORT_ARG" ] && CMD_ARGS+=(--port "$PORT_ARG")
CMD_ARGS+=("${EXTRA_ARGS[@]}")
echo ""
echo -e " ${CYAN}${RESET} 启动中 → ${BOLD}http://localhost:${PORT}${RESET}"
echo -e " ${DIM}Ctrl+C 停止${RESET}"
echo ""
# ── 启动 ─────────────────────────────────────────────────────
exec node "$MANAGER_JS" "${CMD_ARGS[@]}"