mirror of
https://github.com/dtzp555-max/ocm.git
synced 2026-07-19 09:43:37 +00:00
init
This commit is contained in:
+30
@@ -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
|
||||||
@@ -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 key(zh + 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` 等),而新款 NAS(Synology 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 key(zh + 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-dashboard(12 页布局之一)、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 Badge(openclaw 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 3:MAIN_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 2:Agent 模型下拉菜单只有"使用全局默认"
|
||||||
|
- **症状**: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`
|
||||||
@@ -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、Google(OAuth)、GitHub Copilot(Device 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
|
||||||
Executable
+54
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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": {}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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[@]}"
|
||||||
Reference in New Issue
Block a user