Skip to content

Commit 3c5a0d2

Browse files
committed
chore: release v0.11.6
feat: Skills multi-agent support — agent selector + per-agent skills directory (Rust/Node.js/frontend) feat: Assistant tool mode streaming — typewriter effect + tool_calls chunk accumulation improve: OpenClaw 4.5 compatibility — full agent event stream handling + 3-min ultimate timeout improve: Replace hot-update with stable download links (website/GitHub) fix: Gateway status flapping — dashboard throttle + TCP retry + debounce threshold fix: Assistant empty gray bubbles — SSE 0-chunk detection + stream error capture + render filter
1 parent 35423f4 commit 3c5a0d2

35 files changed

+438
-225
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@
55
格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)
66
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)
77

8+
## [0.11.6] - 2026-04-07
9+
10+
### 新功能 (Features)
11+
12+
- **Skills 多 Agent 支持** — Skills 页面新增 Agent 选择器,不同 Agent 可独立管理各自的 Skills 目录;后端 Rust/Node.js 双端均支持 agent_id 参数路由
13+
- **助手工具模式流式输出** — 晴辰助手工具调用模式从非流式改为流式,AI 文字逐 token 打字机显示,tool_calls 分块累积后再执行
14+
15+
### 改进 (Improvements)
16+
17+
- **OpenClaw 4.5 兼容** — 实时聊天页面支持全部 Agent 事件流(lifecycle / item / plan / approval / thinking / command_output),新增 3 分钟终极超时和实时计时器,解决无回复时 UI 永远卡住的问题
18+
- **热更新替换为稳定版下载** — 关于页和全局更新横幅不再展示热更新/重载,改为引导用户前往官网或 GitHub 下载最新稳定版
19+
20+
### 修复 (Fixes)
21+
22+
- **Gateway 状态抖动** — 仪表盘刷新增加 5 秒节流和并发保护;TCP 端口检测增加重试(1s+2s);Gateway 停止判定从 2 次提高到 3 次连续检测;自动重启前增加 3 秒延迟确认
23+
- **助手空灰色气泡** — 修复流式响应 0 内容块时静默成功导致空消息持久化的 bug;新增流内错误事件捕获、渲染时过滤空消息、finally 块清理机制
24+
825
## [0.11.5] - 2026-04-07
926

1027
### 新功能 (Features)

docs/index.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"description": "OpenClaw AI Agent 可视化管理面板,基于 Tauri v2 的跨平台桌面应用。内置晴辰助手支持工具调用,晴辰云 AI 接口一键接入。支持仪表盘监控、多模型配置、消息渠道管理、内置 QQ 机器人、实时 AI 聊天、记忆管理、Agent 管理、网关配置、内网穿透等功能。支持 11 种语言。",
3535
"url": "https://claw.qt.cool/",
3636
"downloadUrl": "https://github.com/qingchencloud/clawpanel/releases/latest",
37-
"softwareVersion": "0.11.5",
37+
"softwareVersion": "0.11.6",
3838
"author": {
3939
"@type": "Organization",
4040
"name": "晴辰云 QingchenCloud",
@@ -1155,7 +1155,7 @@ <h2 class="reveal section-title" data-i18n="eco.title"><span class="gradient-tex
11551155
<div class="orb orb-2" style="top:auto;bottom:-100px"></div>
11561156
<div class="container-sm" style="position:relative;z-index:10">
11571157
<div class="section-header">
1158-
<div class="reveal download-version"><span class="pulse"></span> <span id="dl-badge" data-i18n="dl.badge">v0.11.5 最新版</span></div>
1158+
<div class="reveal download-version"><span class="pulse"></span> <span id="dl-badge" data-i18n="dl.badge">v0.11.6 最新版</span></div>
11591159
<h2 class="reveal section-title" data-i18n="dl.title"><span class="gradient-text">下载安装</span></h2>
11601160
<p class="reveal section-desc" data-i18n="dl.desc">选择你的操作系统,一键下载安装</p>
11611161
</div>
@@ -1165,11 +1165,11 @@ <h2 class="reveal section-title" data-i18n="dl.title"><span class="gradient-text
11651165
<h3>macOS</h3>
11661166
<p class="dl-desc" data-i18n="dl.mac.d">支持 Apple Silicon 和 Intel 芯片</p>
11671167
<div class="dl-links">
1168-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_aarch64.dmg" target="_blank" rel="noopener">
1168+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_aarch64.dmg" target="_blank" rel="noopener">
11691169
Apple Silicon (M1/M2/M3/M4)
11701170
<span class="dl-format">.dmg</span>
11711171
</a>
1172-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_x64.dmg" target="_blank" rel="noopener">
1172+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_x64.dmg" target="_blank" rel="noopener">
11731173
<span data-i18n="dl.mac.intel">Intel 芯片</span>
11741174
<span class="dl-format">.dmg</span>
11751175
</a>
@@ -1187,15 +1187,15 @@ <h3>macOS</h3>
11871187
<h3>Windows</h3>
11881188
<p class="dl-desc" data-i18n="dl.win.d">支持 Windows 10 及以上版本</p>
11891189
<div class="dl-links">
1190-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_x64-setup.exe" target="_blank" rel="noopener">
1190+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_x64-setup.exe" target="_blank" rel="noopener">
11911191
<span data-i18n="dl.win.exe">安装程序</span>
11921192
<span class="dl-format">.exe</span>
11931193
</a>
1194-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_x64-setup-full.exe" target="_blank" rel="noopener">
1194+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_x64-setup-full.exe" target="_blank" rel="noopener">
11951195
<span data-i18n="dl.win.full">完整包(含 WebView2)</span>
11961196
<span class="dl-format">.exe</span>
11971197
</a>
1198-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_x64_en-US.msi" target="_blank" rel="noopener">
1198+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_x64_en-US.msi" target="_blank" rel="noopener">
11991199
<span data-i18n="dl.win.msi">MSI 安装包</span>
12001200
<span class="dl-format">.msi</span>
12011201
</a>
@@ -1206,11 +1206,11 @@ <h3>Windows</h3>
12061206
<h3>Linux</h3>
12071207
<p class="dl-desc" data-i18n="dl.linux.d">支持主流 Linux 发行版</p>
12081208
<div class="dl-links">
1209-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_amd64.AppImage" target="_blank" rel="noopener">
1209+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_amd64.AppImage" target="_blank" rel="noopener">
12101210
<span data-i18n="dl.linux.ai">通用版</span>
12111211
<span class="dl-format">.AppImage</span>
12121212
</a>
1213-
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.5_amd64.deb" target="_blank" rel="noopener">
1213+
<a class="dl-link" href="https://claw.qt.cool/proxy/dl/github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.11.6_amd64.deb" target="_blank" rel="noopener">
12141214
Debian / Ubuntu
12151215
<span class="dl-format">.deb</span>
12161216
</a>

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "clawpanel",
3-
"version": "0.11.5",
3+
"version": "0.11.6",
44
"private": true,
55
"description": "ClawPanel - OpenClaw 可视化管理面板,基于 Tauri v2 的跨平台桌面应用",
66
"type": "module",

scripts/dev-api.js

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,19 @@ function parseSkillFrontmatterFile(skillMdPath) {
899899
}
900900
}
901901

902-
function collectLocalSkillRoots() {
902+
function resolveAgentSkillsDir(agentId) {
903+
const id = (agentId || '').trim()
904+
if (!id || id === 'main') return null
905+
try {
906+
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'))
907+
const ws = resolveAgentWorkspace(config, id)
908+
return path.join(ws, 'skills')
909+
} catch {
910+
return path.join(OPENCLAW_DIR, 'agents', id, 'workspace', 'skills')
911+
}
912+
}
913+
914+
function collectLocalSkillRoots(agentSkillsDir) {
903915
const roots = []
904916
const seen = new Set()
905917
const pushRoot = (dir, source, bundled = false) => {
@@ -911,7 +923,11 @@ function collectLocalSkillRoots() {
911923
roots.push({ dir: normalized, source, bundled })
912924
}
913925

914-
pushRoot(path.join(OPENCLAW_DIR, 'skills'), 'OpenClaw 自定义', false)
926+
if (agentSkillsDir) {
927+
pushRoot(agentSkillsDir, 'Agent 自定义', false)
928+
} else {
929+
pushRoot(path.join(OPENCLAW_DIR, 'skills'), 'OpenClaw 自定义', false)
930+
}
915931
pushRoot(path.join(homedir(), '.claude', 'skills'), 'Claude 自定义', false)
916932

917933
const cliPath = resolveOpenclawCliPath()
@@ -979,8 +995,8 @@ function scanSingleSkill(root, name) {
979995
return result
980996
}
981997

982-
function scanLocalSkillsFallback(cliError = null) {
983-
const roots = collectLocalSkillRoots()
998+
function scanLocalSkillsFallback(agentSkillsDir = null) {
999+
const roots = collectLocalSkillRoots(agentSkillsDir)
9841000
const skills = []
9851001
const seen = new Set()
9861002
const scannedRoots = []
@@ -5350,12 +5366,14 @@ const handlers = {
53505366
},
53515367

53525368
// Skills 管理(纯本地扫描,不依赖 CLI)
5353-
skills_list() {
5354-
return scanLocalSkillsFallback()
5369+
skills_list({ agent_id } = {}) {
5370+
const agentDir = resolveAgentSkillsDir(agent_id)
5371+
return scanLocalSkillsFallback(agentDir)
53555372
},
5356-
skills_info({ name }) {
5373+
skills_info({ name, agent_id } = {}) {
53575374
const n = String(name || '').trim()
5358-
const fallback = scanLocalSkillsFallback().skills.find(skill => skill.name === n)
5375+
const agentDir = resolveAgentSkillsDir(agent_id)
5376+
const fallback = scanLocalSkillsFallback(agentDir).skills.find(skill => skill.name === n)
53595377
if (fallback) return fallback
53605378
throw new Error(`Skill「${n}」不存在`)
53615379
},
@@ -5384,9 +5402,11 @@ const handlers = {
53845402
throw new Error(`安装失败: ${e.message || e}`)
53855403
}
53865404
},
5387-
skills_uninstall({ name }) {
5405+
skills_uninstall({ name, agent_id } = {}) {
53885406
if (!name || name.includes('..') || name.includes('/') || name.includes('\\')) throw new Error('无效的 Skill 名称')
5389-
const skillDir = path.join(OPENCLAW_DIR, 'skills', name)
5407+
const agentDir = resolveAgentSkillsDir(agent_id)
5408+
const baseDir = agentDir || path.join(OPENCLAW_DIR, 'skills')
5409+
const skillDir = path.join(baseDir, name)
53905410
if (!fs.existsSync(skillDir)) throw new Error(`Skill「${name}」不存在`)
53915411
fs.rmSync(skillDir, { recursive: true, force: true })
53925412
return { success: true, name }
@@ -5398,8 +5418,9 @@ const handlers = {
53985418
async skillhub_index() {
53995419
return await skillhubSdk.fetchIndex()
54005420
},
5401-
async skillhub_install({ slug }) {
5402-
const skillsDir = path.join(OPENCLAW_DIR, 'skills')
5421+
async skillhub_install({ slug, agent_id } = {}) {
5422+
const agentDir = resolveAgentSkillsDir(agent_id)
5423+
const skillsDir = agentDir || path.join(OPENCLAW_DIR, 'skills')
54035424
if (!fs.existsSync(skillsDir)) fs.mkdirSync(skillsDir, { recursive: true })
54045425
const installedPath = await skillhubSdk.install(slug, skillsDir)
54055426
return { success: true, slug, path: installedPath }

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "clawpanel"
3-
version = "0.11.5"
3+
version = "0.11.6"
44
edition = "2021"
55
description = "ClawPanel - OpenClaw 可视化管理面板"
66
authors = ["qingchencloud"]

src-tauri/src/commands/agent.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,11 @@ fn resolve_agent_workspace(id: &str, config: &Value) -> String {
10061006
})
10071007
}
10081008

1009+
/// Public wrapper for expand_user_path, used by skills.rs
1010+
pub fn expand_user_path_pub(raw: &str) -> std::path::PathBuf {
1011+
expand_user_path(raw)
1012+
}
1013+
10091014
fn expand_user_path(raw: &str) -> std::path::PathBuf {
10101015
let trimmed = raw.trim();
10111016
let path = if let Some(rest) = trimmed

src-tauri/src/commands/service.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -568,14 +568,17 @@ mod platform {
568568
Ok(a) => a,
569569
Err(_) => return (false, None),
570570
};
571-
match std::net::TcpStream::connect_timeout(&socket_addr, std::time::Duration::from_secs(1))
572-
{
573-
Ok(_) => {
574-
// 尝试通过 lsof 获取 PID
575-
let pid = get_pid_by_lsof(port);
576-
(true, pid)
577-
}
578-
Err(_) => (false, None),
571+
// 两次尝试:第一次 1 秒,失败后短暂等待再用 2 秒重试,避免瞬态超时误判
572+
let connected = std::net::TcpStream::connect_timeout(&socket_addr, std::time::Duration::from_secs(1)).is_ok()
573+
|| {
574+
std::thread::sleep(std::time::Duration::from_millis(300));
575+
std::net::TcpStream::connect_timeout(&socket_addr, std::time::Duration::from_secs(2)).is_ok()
576+
};
577+
if connected {
578+
let pid = get_pid_by_lsof(port);
579+
(true, pid)
580+
} else {
581+
(false, None)
579582
}
580583
}
581584

@@ -1120,7 +1123,13 @@ mod platform {
11201123
Ok(a) => a,
11211124
Err(_) => return (false, None),
11221125
};
1123-
if std::net::TcpStream::connect_timeout(&socket_addr, Duration::from_secs(1)).is_err() {
1126+
// 两次尝试:第一次 1 秒,失败后短暂等待再用 2 秒重试,避免瞬态超时误判
1127+
let connected = std::net::TcpStream::connect_timeout(&socket_addr, Duration::from_secs(1)).is_ok()
1128+
|| {
1129+
std::thread::sleep(Duration::from_millis(300));
1130+
std::net::TcpStream::connect_timeout(&socket_addr, Duration::from_secs(2)).is_ok()
1131+
};
1132+
if !connected {
11241133
// 端口不通,先清空已知的僵死 PID
11251134
let mut known = LAST_KNOWN_GATEWAY_PID.lock().unwrap();
11261135
*known = None;

0 commit comments

Comments
 (0)