晴天
b2146b54cb
feat(hermes): add tirith security settings
2026-05-24 22:08:12 +08:00
晴天
7be0ec66cc
feat(hermes): add unauthorized dm policy form
2026-05-24 21:41:17 +08:00
晴天
2de5d1e38a
feat(hermes): add quick commands config form
2026-05-24 21:21:16 +08:00
晴天
01f17f0a2a
feat(hermes): add skills config form
2026-05-24 20:54:29 +08:00
晴天
d9fc9a8783
feat(hermes): add memory flush setting
2026-05-24 20:34:12 +08:00
晴天
56e41dd512
feat(hermes): add terminal execution config form
2026-05-24 20:06:50 +08:00
晴天
122d7a63be
feat(hermes): add execution limits config form
2026-05-24 19:28:30 +08:00
晴天
c0b40070c0
feat(hermes): add channel display settings form
2026-05-24 18:42:34 +08:00
晴天
a1307716dd
feat(hermes): add streaming config form
2026-05-24 08:40:53 +08:00
晴天
1883e18f02
feat(hermes): add memory config form
2026-05-24 08:04:31 +08:00
晴天
18ca140af8
feat(hermes): add tool loop guardrails form
2026-05-24 07:38:42 +08:00
晴天
5dd6f1be40
feat(hermes): add compression config form
2026-05-24 07:16:00 +08:00
晴天
f500da39c1
feat(hermes): add session runtime config form
2026-05-24 06:49:17 +08:00
晴天
4c29ed68ab
fix(hermes): validate raw config saves
2026-05-24 06:10:07 +08:00
晴天
ff4da27eeb
feat(hermes): add bundled plugin channel configs
2026-05-24 05:12:17 +08:00
晴天
7b32b533fb
feat(channels): add Tlon config compatibility
2026-05-24 02:03:55 +08:00
晴天
7e3bb71fca
feat(channels): add IRC config compatibility
2026-05-24 00:57:37 +08:00
晴天
326c5597df
feat(channels): add Nostr config compatibility
2026-05-23 09:25:07 +08:00
晴天
dcc3751ded
feat(channels): add Twitch config compatibility
2026-05-23 08:42:54 +08:00
晴天
8623efd49c
feat(channels): add Nextcloud Talk config compatibility
2026-05-23 08:25:34 +08:00
晴天
579d706075
feat(channels): add ClickClack config compatibility
2026-05-23 08:07:39 +08:00
晴天
d933177ec3
feat(channels): restore WhatsApp config compatibility
2026-05-23 07:51:16 +08:00
晴天
8d745e7543
feat(channels): add iMessage config compatibility
2026-05-23 07:31:06 +08:00
晴天
6c947a1fec
feat(hermes): support Discord plugin runtime config
2026-05-23 06:41:49 +08:00
晴天
f188bb85f7
feat(channels): improve Microsoft Teams config compatibility
2026-05-23 06:22:23 +08:00
晴天
49be118c5f
feat(channels): improve Signal config compatibility
2026-05-23 05:56:59 +08:00
晴天
09bc45ae4c
feat(channels): add Synology and Google Chat config
2026-05-23 05:37:06 +08:00
晴天
53fe25a277
feat(channels): add LINE and Mattermost config
2026-05-23 05:08:51 +08:00
晴天
780b1bdde5
feat(channels): add Zalo channel configuration
2026-05-23 04:38:49 +08:00
晴天
067389d65f
fix(channels): add generic channel diagnostics
2026-05-23 04:14:45 +08:00
晴天
d3d527ca34
feat(hermes): add dingtalk channel config
2026-05-23 03:48:33 +08:00
晴天
e2eee18e05
fix(channels): preserve Discord application id
2026-05-23 03:25:22 +08:00
晴天
b6a353d622
fix(channels): stabilize default account selection
2026-05-23 03:12:40 +08:00
晴天
01dff38a97
fix(channels): save multi-account platform configs
2026-05-23 03:06:52 +08:00
晴天
f7518ae4b3
fix(hermes): align channel secrets with runtime env
2026-05-23 02:49:31 +08:00
晴天
6aa7a05f36
fix(channels): preserve SecretRef credentials
2026-05-23 02:23:52 +08:00
晴天
eccf91ed1e
feat(hermes): add channel configuration editor
2026-05-23 01:51:08 +08:00
晴天
27b35b6298
fix(channels): normalize OpenClaw channel config policies
2026-05-23 01:14:42 +08:00
晴天
f4d644ea06
fix(web): support openclaw path conflict scan
2026-05-23 00:20:47 +08:00
晴天
d0f0d1f6b7
fix(gateway): release 0.16.5
2026-05-22 20:42:16 +08:00
晴天
7d75486a53
feat(gateway): surface negotiated handshake protocol version in UI
...
Users have reported confusion about "when will ClawPanel update its
gateway protocol to v4". This is actually a misreading: ClawPanel v0.15+
already advertises `minProtocol=3, maxProtocol=4` in its connect frame,
and negotiates v4 transparently when the kernel is >= 2026.5.12. The
`v3|` prefix users were seeing in dev-api.js is the device signature
payload string schema version, which is a completely separate concept
from the handshake protocol version.
Make this visible and unambiguous:
UI
- Add a "Proto v4" badge next to the Gateway service name in
/services once the WS handshake succeeds, with a tooltip explaining
that this is the WS handshake protocol version (not the device
signature payload v3 format).
- Add the same protocol info to the WebSocket row in /chat-debug.
API
- WsClient now exposes `negotiatedProtocol` which prefers the explicit
field from the hello payload (`protocol` / `protocolVersion` /
`negotiatedProtocol`) and falls back to inferring from serverVersion:
kernels >= 2026.5.12 are reported as v4, older as v3. This matches
the panel's advertised range of [3, 4].
- KernelSnapshot grows a `protocol` field so feature gates and UIs that
already consume the snapshot can read it without touching wsClient.
Comments
- Expand the KERNEL_TARGET comment in feature-catalog.js to spell out
the two-distinct-version-numbers rule explicitly.
- Add matching clarifying comments next to the `v3|...` payload string
in both scripts/dev-api.js and src-tauri/src/commands/device.rs, so
the next reader does not confuse payload schema with handshake.
## Verification
- node --check on all touched JS files
- npm run build
- cargo fmt --check && cargo check (clippy errors that surface are
pre-existing debt in config.rs, untouched here)
- Playwright /services: mock wsClient state, observe `协议 v4` badge
rendered with `rgba(99, 102, 241, 0.1)` background and accent color,
for both the explicit-protocol path and the version-inferred path.
2026-05-16 13:02:08 +08:00
晴天
e1eda2db55
feat(models): import external client configs
...
Add a model client import flow that scans local Codex, Claude Code, Gemini CLI, and common environment variable configurations without reading or copying OAuth tokens.
The new backend command returns safe import candidates with provider metadata, model IDs, and API key environment-variable references. Tauri and Web/dev-api both implement the scanner, and Web mode keeps the scan local even when a remote instance is active.
The Models page now offers an import wizard that lets users select importable candidates, adds providers without overwriting existing keys, preserves secrets as ${ENV_VAR} references, and leaves OAuth-only Codex entries as guidance rather than direct OpenClaw imports.
## Verification
- node --check src/pages/models.js
- node --check src/lib/tauri-api.js
- node --check src/locales/modules/models.js
- node --check scripts/dev-api.js
- cargo fmt --check
- cargo check
- npm run build
2026-05-15 23:18:50 +08:00
晴天
6af9819b89
fix(ui): sync latest upgrade copy in locale bundles
...
The runtime locale JSON bundles still contained the older About/Services policy copy even after the module-level strings were updated, so the About page could continue to show the old "recommended only" message in Chinese.
This syncs the zh-CN/en locale bundles with the latest-upstream upgrade copy and mirrors the suffixed OpenClaw version comparison fix in the Web dev API.
## Verification
- npm run build
- node --check scripts/dev-api.js
- cargo check
2026-05-15 19:31:44 +08:00
晴天
8b690cb6a7
fix(openclaw): update recommended kernel target and delta protocol handling
...
面板原本只声明 maxProtocol=3 的握手范围,且 chat delta 处理只接受前缀扩展。
连接到 2026.5.12+ 内核时会出现握手兼容问题;agent 输出在内容回滚或重排场景也会
丢失最新文本,前端 streaming 气泡停留在旧前缀。
## Connect 握手协议范围
- 将桌面端 connect frame 的 maxProtocol 从 3 扩展到 4
- 将 Web 模式 connect frame 的 maxProtocol 从 3 扩展到 4
- minProtocol 继续保留 3,用于兼容历史内核
- 范围 [3, 4] 同时覆盖旧内核和 5.12+ 内核,不需要按版本分支
## Chat delta replace 语义
- 当 payload.replace=true 时,无条件覆盖当前 AI 文本缓存
- 保留前缀扩展场景的增量更新逻辑
- 修复内容回滚或重排时文本长度变短导致 UI 不刷新的问题
## 推荐内核版本
- official 推荐目标升到 2026.5.12
- chinese 推荐目标升到 2026.5.12-zh.1
- KERNEL_FLOOR 不变,继续兼容历史安装
## 验证
- cargo check:PASS
- npm run build:PASS
2026-05-15 18:30:04 +08:00
晴天
0b4ef11971
fix(hermes): restore gateway message sending dependencies
...
Hermes Gateway 能启动但消息发送链路仍可能不可用:工具安装环境缺少运行时依赖,
同时自定义端点场景下 provider 字段可能被省略,导致消息路由继续落到错误 provider。
## 补齐运行时依赖
- uv tool install 固定带上 HTTP 客户端依赖
- 补齐 OpenAI SDK 依赖
- 补齐 Gateway HTTP server 所需 aiohttp
- 补齐 browser/dialog 等工具链会触发的 websocket 依赖
- 安装日志同步展示完整安装参数,便于用户排查环境问题
## 明确 custom provider
- 自定义 base_url 时显式写入 provider: custom
- 如果 model 段已有 provider,则覆盖为 custom
- 如果 model 段缺少 provider,则补写 provider: custom
- 继续保留 OPENAI_API_KEY alias 自愈,确保辅助客户端和主流程读取同一份凭证
## 范围
- 桌面 Tauri 安装与配置自愈逻辑
- Web dev API 安装与配置自愈逻辑
2026-05-15 17:32:56 +08:00
晴天
583f5401ac
fix(hermes): stabilize gateway provider routing and startup
...
Hermes Gateway 之前容易出现两类问题:配置里的 provider 与 base_url 不一致,
以及多个启动入口并发触发 Gateway start,导致日志里反复出现启动流程,运行状态也不稳定。
## Provider / base_url 自愈
- 归一化 provider URL(去掉尾斜杠和常见 API path 后缀)
- 当 openrouter provider 搭配自定义 base_url 时,自动切换为 custom provider
- 在读取配置、写入模型配置、启动 Gateway 前都执行一次自愈
- Web 模式同步实现相同逻辑,避免桌面端和浏览器端行为不一致
## API Key 别名兼容
- custom provider 优先读取 OPENAI_API_KEY
- 当 .env 只有 CUSTOM_API_KEY 时,自动补齐 OPENAI_API_KEY
- 避免辅助客户端读取不到凭证或落到错误 provider
## Gateway 启动互斥
- 增加 Gateway start guard,串行化启动流程
- 如果已有启动流程在进行中,直接复用健康检查结果
- 避免重复 Gateway 进程、重复日志和竞态状态覆盖
## 范围
- 桌面 Tauri 命令
- Web dev API 运行时
- Hermes provider 注册表
2026-05-15 17:32:38 +08:00
晴天
b9a7c043d2
fix(audit): 复查发现的 5 个 bug — 双 listener / duplicate stub / timer leak / i18n
...
逐项排错盘点(OpenClaw + Hermes 引擎 + 共享层全面复查)。
## Bug #1 — Hermes 引擎双 listener 数组混用
src/engines/hermes/index.js
onStateChange / onReadyChange 共用一个 `_listeners` 数组:
```js
onStateChange(fn) { _listeners.push(fn); ... }
onReadyChange(fn) { _listeners.push(fn); ... } ← 同一数组
```
main.js 注册 sidebar 渲染回调时两个都注册:
```js
_engineStateUnsub = engine.onStateChange(() => renderSidebar(sidebar))
_engineReadyUnsub = engine.onReadyChange(() => renderSidebar(sidebar))
```
结果:每次 detectHermesStatus(15s 一次 poll)触发,sidebar 被
renderSidebar 调两遍。OpenClaw 引擎用的 lib/app-state.js 早就是分开
两个数组(_gwListeners + _listeners),Hermes 是退化实现。
修复:
- 拆成 _stateListeners / _readyListeners 两个数组
- 加 prevReady / prevRunning 做 diff,仅在状态实际变化时通知
## Bug #2 — Web 模式下 check_panel_update 永远返回 false
scripts/dev-api.js
`check_panel_update` 在 line 6785 有完整实现(fetch GitHub/Gitee
release API),但 line 8586 又 stub 了一次:
```js
check_panel_update() { return { hasUpdate: false } }
```
Object literal 后定义覆盖前定义,Web 模式下用户永远看不到「有新版」
提示,必须升级到桌面客户端才能查更新。
修复:删掉重复 stub,留注释说明真实实现位置。
esbuild 之前就在 build 里 warn `Duplicate key "check_panel_update"
in object literal`,现在 warning 也消失了。
## Bug #3 — engine-select.js setTimeout 不在 cleanup 时清
src/pages/engine-select.js
choose 动画里两个 setTimeout (600ms + 1300ms) 没保存 id,路由
cleanup 时不清。极端情况:用户点完 OpenClaw 后立刻点 secondary
"稍后再说" → 1300ms 后被强制 navigate 回原 targetRoute,把用户拉走。
修复:
- 模块级 _animTimers 数组追踪所有动画 setTimeout id
- cleanup 时 clearTimeout 全清
- stage.dataset 防御性访问(路由切走后 stage 可能已不在 DOM)
## Bug #4 — router.js 三处中文硬编码
src/router.js
之前页面 loading / 加载失败 / 重新加载按钮直接写死"加载中..."
"页面加载失败" "重新加载"。i18n 里 `common.loading` /
`common.pageLoadFailed` / `common.reloadRetry` 早已存在但没用上。
修复:import t() + 三处替换。
## Bug #5 — dashboard.js Promise 超时 Error 写死中文
src/pages/dashboard.js
`new Error(\`超时(${ms/1000}s)\`)` — 这条错误最后被 humanizeError
处理后展示给用户,本来应该走 i18n。改成英文 `Timed out after Xs`,
统一与日志聚合(其他地方都是英文)。
## 验证
- npm run build:PASS(1.85s, 无 duplicate-key warning)
- cargo fmt --check:PASS(无改动)
- 受影响场景:
- 引擎切换 sidebar 性能(Hermes 双重渲染消失)
- Web 模式更新提示(恢复正常)
- engine-select 动画中途切走(不再被强拉回)
- 加载/错误页(i18n 完整)
2026-05-14 07:17:28 +08:00
晴天
1873e23371
fix(critical): 5 个用户报告的真 bug 一次性修
...
## P0 Bug 1: chat.js `t is not defined` (页面渲染崩溃)
- chat.js 用了 30+ 处 t() 但**完全忘记 import i18n**
- 路由进入 /h/chat 立即抛 ReferenceError,整页渲染失败
- 修复:补 `import { t } from '../../../lib/i18n.js'`
## P0 Bug 2: i18n 嵌套对象解析失败 (所有 humanizeError 显示原始 key)
- 用户截图:`common.errorHint.generic` 直接显示而非翻译
- 根因:buildLocales() 不递归嵌套对象,把 common.error / errorHint /
errorAction 这种嵌套 dict 当作 _() 翻译对象处理 →
`result[lang].common.errorHint = 'errorHint'` (字符串)
- 影响:t('common.errorHint.network'/auth/timeout/...) 全部返回 key 自身
→ toast 用 humanizeError 的所有页面都看到原始 key
- 修复:buildLocales 加 _isTranslationObject + _materialize 递归
## P0 Bug 3: dev-api.js `Dynamic require of "node:fs" is not supported`
- 用户截图:文件管理器红字 "Dynamic require of node:fs"
- 根因:我之前在 hermes_fs_* / _validateFsPath / _hermesHome 用了
`const fs = require('node:fs')` —— 但 Vite 插件运行在 ESM 上下文,
CommonJS dynamic require 不支持
- 修复:删除所有 require('node:fs/path/os') —— 文件顶部已经 ESM
`import fs from 'fs'` 等,直接复用即可
## P1 Bug 4: profiles/kanban/oauth fetch failed 错误丑陋
- 用户截图:3 个页面都显示红字 "fetch failed"(无任何上下文)
- 修复 1(dev-api.js):hermes_dashboard_api_proxy 把 ECONNREFUSED /
fetch failed 转成 "Hermes Dashboard 未运行(端口 9119 无服务)。
请在桌面端 ClawPanel 启动 Hermes Agent" — 含「未运行」关键字会被
humanizeError 的 gatewayDown 正则匹配
- 修复 2(3 个页面):用 humanizeError 拆出 message + hint + 折叠 raw,
渲染统一的 .page-inline-error 卡片(icon + 主行 + 副提示 + 技术详情
details)。错误对象不再 stringify,保留给 humanizeError 完整识别
## P2 Bug 5: 重复的 require('node:path') in hermes_fs_list
- 同 Bug 3,循环里又 require 了一次 path,现已用顶部 import
## 影响面
✅ /h/chat 不再崩溃,profile switcher 正常显示
✅ 所有用 humanizeError 的 toast 看到正确翻译(不再显示原始 key)
✅ 文件管理器 Web 模式正常列出 ~/.hermes 目录
✅ Profile / Kanban / OAuth 显示「Hermes Dashboard 未运行」+
「请前往仪表盘启动 Gateway 后重试」+ 折叠原始错误(点击展开)
✅ npm build pass
2026-05-14 06:35:20 +08:00
晴天
129d8c0ac1
feat(hermes): Batch 3 §L - 文件管理器(限定在 ~/.hermes 子树内)
...
校对:Hermes 没有 file HTTP API,必须自建。
## Rust 后端:3 个安全 fs 命令(~180 行)
### 安全策略
- 所有路径必须在 hermes_home() 子树内(防 path traversal)
- canonicalize 后用 starts_with 验证
- 拒绝绝对路径跳出 + .. 跳出
- 5 MB 文件大小上限
- 单次列目录最多 2000 条
### 命令
- hermes_fs_list(path) → { path, entries: [{name, kind, size, modified}] }
· 隐藏文件默认不显示(.env 除外)
· 排序:目录在前,文件在后,按名字
- hermes_fs_read(path) → { path, size, text?, binary_b64? }
· UTF-8 文本 → text
· 二进制 → 内置 base64 编码(不引新依赖)
- hermes_fs_write(path, content) → { path, size }
· 父目录必须存在
· 5 MB 上限
## 前端 /h/files 页面(~270 行)
### UI 布局
- 左侧:面包屑 + 目录树(点目录进入 / 点文件选中)
- 右侧:编辑器(文本)/ 预览(图片)/ 元信息(其他二进制)
### 文件树
- 文件图标按扩展名(📁 /🔗 /🖼️ /📝 /⚙️ /📄 )
- 文件大小显示(B/KB/MB)
- ".." 返回上级
- 选中态高亮
### 编辑器
- textarea 编辑,monospace 字体
- "保存 *" 状态标记 dirty
- 切目录/文件前 showConfirm 「丢弃未保存修改?」
- 保存成功 toast
### 二进制预览
- 图片 (png/jpg/gif/webp/svg) → 用 data: URL 显示
- 其他 → 「二进制文件(不可编辑)」+ 文件大小
## sidebar
- 「管理」section 加文件管理器入口(folder icon)
- /h/files 路由注册(含意外的 routes 顺序修复)
### dev-api.js
- Web 模式走 Node fs.readdirSync/readFileSync/writeFileSync
- 同样的安全策略:根目录 hermes_home() = process.env.HERMES_HOME 或 ~/.hermes
- realpath 验证 + 5 MB 限制
### CSS(~165 行)
- .hm-files-layout: grid 双栏(响应式 → 单栏)
- .hm-files-tree: 左侧树,breadcrumb + entry 列表
- .hm-files-pane: 右侧编辑器/预览
- .hm-files-editor: 全宽 textarea,monospace
- 响应式:768px 以下单栏
### i18n
- 12 个新键 × 3 语言(hermesFiles*)
## 修复
- src/engines/hermes/index.js 末尾多余 `}` 删除(之前 edit 留下)
## 累计
- Rust ~180 行 + 前端 ~270 行 + CSS ~165 行 + dev-api ~55 行
- 12 个 i18n × 3 语言
- cargo check ✓ + npm build ✓
2026-05-14 05:36:50 +08:00
晴天
0d6c4614e4
feat(hermes): Batch 2 §G - 多 Gateway 看板(同时运行多 profile Gateway)
...
设计:让用户给多个 profile 各自配 Gateway 实例,同时运行。
端口完全由 profile 的 config.yaml model.gateway.port 决定,ClawPanel 只负责 spawn + PID 跟踪。
## Rust 后端(~350 行)
### 数据结构
- MULTI_GW_PIDS: Mutex<Option<HashMap<String, u32>>> 全局 PID 表
- 持久化在 panelConfig.hermes.multiGateways: [{name, profile}]
### Helper 函数
- multi_gw_pids_get/set/remove: 线程安全 PID 表读写
- read_multi_gateways_config / write_multi_gateways_config: panel config R/W(保留其他字段)
- read_profile_gateway_port(profile): 缩进感知解析 profile config.yaml 的 model.gateway.port
- pid_is_alive(pid): Windows 用 tasklist /FI,Unix 用 kill -0 检测
### 5 个新 Tauri 命令
- hermes_multi_gateway_list() → [{name, profile, port, running, pid, owned}]
· running = PID 存活 || TCP 探测可达
· owned = ClawPanel spawn(可控制)vs 外部进程占着端口
- hermes_multi_gateway_add(name, profile) - 写入 panel config,名称合法性检查
- hermes_multi_gateway_remove(name) - 先停掉,再从配置删除
- hermes_multi_gateway_start(name) - spawn `hermes --profile <name> gateway run`
· 注入 profile 的 .env
· 等待端口可达(8 秒超时)
· 记 PID
- hermes_multi_gateway_stop(name) - taskkill /F /PID (Windows) 或 kill -TERM (Unix)
### 发射 hermes-multi-gateway-changed 事件(前端可监听刷新)
## 前端(~230 行)
### /h/gateways 页面
- 顶部 + 添加 按钮
- 卡片网格(复用 .lazy-deps-grid)显示每个 Gateway:
· name + status badge (运行中/已停止)
· profile + port + PID + owned 提示
· 启动 / 停止 / 删除 按钮
- 添加弹窗:name 输入 + profile 下拉(拉自 hermesProfilesList)
- 停止 / 删除均有 showConfirm(带 in-flight 警告)
- 外部进程占端口时 stop 按钮 disabled + tooltip
### sidebar
- 「管理」section 加 Gateways 入口(gateway icon)
- /h/gateways 路由注册
### dev-api.js
- Web 模式 fallback: 多 Gateway 不支持本地进程管理(throw friendly error)
### i18n
- 26 个新键 × 3 语言(hermesGateway*)
## 累计
- Rust ~350 行 + 前端 ~230 行 + i18n 78 字符串 + 路由/sidebar
- cargo check ✓ + npm build ✓
2026-05-14 05:30:18 +08:00