feat: v0.9.3 — 9项Bug修复+ARM性能优化+R2 CDN加速+非商用协议

This commit is contained in:
晴天
2026-03-16 23:45:03 +08:00
parent 51e49d0781
commit 20d80c3ec5
15 changed files with 129 additions and 70 deletions

View File

@@ -5,6 +5,26 @@
格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
## [0.9.3] - 2026-03-16
### 修复 (Fixes)
- **仪表盘版本显示"未知"** — 修复 coreP Promise 解构顺序错误config 和 version 互换),导致版本卡片无法正确读取版本信息
- **Agent 管理"暂无 Agent"** — OpenClaw 的 main agent 是隐式的(不在 agents.list 中list_agents 现在始终自动插入 main agent
- **Agent 模型显示 [object Object]** — 正确解析 model 对象的 primary 字段,兼容字符串和对象两种格式
- **定时任务触发/编辑/删除失败** — cron.run/update/remove RPC 参数从 id 修正为 jobId匹配 Gateway schema
- **聊天会话列表消失** — 恢复 chat header 中的 sidebar toggle 按钮PR#88 将按钮移入 sidebar 内导致折叠后无法展开)
- **Gateway 启动失败 Unknown config keys** — stripUiFields 现在清理根层级的 ClawPanel 内部字段version info防止污染 openclaw.json
- **Docker 安装超时** — npm 镜像源不再 fallback 到海外 registry.npmjs.org优先使用国内 npmmirror
- **SkillHub CLI 检测误报"请先安装"** — 检测参数从 --version 修正为 --cli-version
- **消息渠道配置被仪表盘覆盖** — 仪表盘自愈逻辑用缓存 config 覆盖文件导致 channels 丢失,现在先读取最新配置再 patch
### 改进 (Improvements)
- **ARM 设备性能优化** — in-flight 请求去重防止进程堆积、后端 serverCached 缓存、Gateway 轮询降频15s→30s、get_status_summary 改为直接读文件不走 CLI
- **R2 CDN 安装加速** — 新增 Cloudflare R2 预装归档下载dl.qrj.aiWindows 安装从 3-10 分钟降至 1-2 分钟
- **模型添加体验优化** — 快捷添加改为模型选择弹窗,用户可自主勾选需要的模型
## [0.9.2] - 2026-03-16
### 新功能 (Features)

44
LICENSE
View File

@@ -1,21 +1,31 @@
MIT License
ClawPanel License
Copyright (c) 2026 qingchencloud
Copyright (c) 2026 武汉晴辰天下网络科技有限公司 (QingchenCloud)
官网: https://claw.qt.cool
GitHub: https://github.com/qingchencloud/clawpanel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
本软件及其相关文档(以下简称"软件")的使用须遵守以下条款:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
1. 免费使用
允许任何个人或组织免费下载、安装和使用本软件用于非商业目的。
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2. 署名要求
在使用、分发或展示本软件时,必须保留上述版权声明、官网链接和本许可声明。
不得移除或修改软件中的品牌标识、版权信息和官网链接。
3. 禁止商业使用
未经版权所有者书面授权,不得将本软件或其衍生作品用于任何商业目的,包括但不限于:
- 作为付费产品或服务的一部分进行销售或分发
- 集成到商业产品中
- 为商业客户提供基于本软件的托管服务
如需商业授权请联系keh5@vip.qq.com
4. 修改与分发
允许修改本软件源代码用于个人学习和非商业用途。
分发修改版本时,必须保留原始版权声明并注明修改内容。
不得以任何方式暗示修改版本获得了版权所有者的认可。
5. 免责声明
本软件按"现状"提供,不提供任何明示或暗示的保证,包括但不限于适销性、
特定用途适用性和非侵权性的保证。在任何情况下,版权所有者均不对因使用
本软件而产生的任何直接、间接、附带、特殊或后果性损害承担责任。

View File

@@ -1,9 +1,9 @@
{
"version": "0.9.2",
"minAppVersion": "0.9.2",
"hash": "sha256:ac232ccd1035d727234fe94476d2ab5faff8f65be3bae858df07994958f2d058",
"url": "https://github.com/qingchencloud/clawpanel/releases/download/v0.9.2/web-0.9.2.zip",
"size": 1985885,
"changelog": "",
"releasedAt": "2026-03-15T20:37:46Z"
"version": "0.9.3",
"minAppVersion": "0.9.0",
"hash": "",
"url": "https://github.com/qingchencloud/clawpanel/releases/download/v0.9.3/web-0.9.3.zip",
"size": 0,
"changelog": "ARM性能优化、R2 CDN安装加速、定时任务修复、Agent管理修复、Gateway配置污染修复等",
"releasedAt": "2026-03-16T21:00:00Z"
}

View File

@@ -35,6 +35,14 @@
"chinese": {
"recommended": "2026.3.13-zh.1"
}
},
"0.9.3": {
"official": {
"recommended": "2026.3.13"
},
"chinese": {
"recommended": "2026.3.13-zh.1"
}
}
}
}

View File

@@ -1,11 +1,11 @@
{
"name": "clawpanel",
"version": "0.9.2",
"version": "0.9.3",
"private": true,
"description": "ClawPanel - OpenClaw 可视化管理面板,基于 Tauri v2 的跨平台桌面应用",
"type": "module",
"author": "qingchencloud",
"license": "MIT",
"license": "SEE LICENSE IN LICENSE",
"homepage": "https://github.com/qingchencloud/clawpanel",
"repository": {
"type": "git",

View File

@@ -3329,7 +3329,7 @@ const handlers = {
},
skills_skillhub_check() {
try {
const out = execSync('skillhub --version', { encoding: 'utf8', timeout: 5000 })
const out = execSync('skillhub --cli-version', { encoding: 'utf8', timeout: 5000 })
return { installed: true, version: out.trim() }
} catch {
return { installed: false }

2
src-tauri/Cargo.lock generated
View File

@@ -328,7 +328,7 @@ dependencies = [
[[package]]
name = "clawpanel"
version = "0.9.2"
version = "0.9.3"
dependencies = [
"base64 0.22.1",
"chrono",

View File

@@ -1,12 +1,12 @@
[package]
name = "clawpanel"
version = "0.9.2"
version = "0.9.3"
edition = "2021"
description = "ClawPanel - OpenClaw 可视化管理面板"
authors = ["qingchencloud"]
repository = "https://github.com/qingchencloud/clawpanel"
homepage = "https://github.com/qingchencloud/clawpanel"
license = "MIT"
license = "SEE LICENSE IN LICENSE"
[lib]
name = "clawpanel_lib"

View File

@@ -1,5 +1,5 @@
/// Agent 管理命令 — 列表/改名直接读写 openclaw.json创建/删除走 CLI需要创建 workspace 等文件)
use crate::utils::openclaw_command_async;
/// Agent 管理命令 — 调用 openclaw CLI 实现增删改查
use serde_json::Value;
use std::fs;
use std::io::Write;
@@ -102,7 +102,7 @@ pub async fn list_agents() -> Result<Value, String> {
Ok(Value::Array(enriched))
}
/// 创建新 agent
/// 创建新 agent(走 CLI自动创建 workspace/sessions 等文件)
#[tauri::command]
pub async fn add_agent(
name: String,
@@ -124,7 +124,6 @@ pub async fn add_agent(
"--non-interactive".to_string(),
"--workspace".to_string(),
ws.to_string_lossy().to_string(),
"--json".to_string(),
];
if !model.is_empty() {
@@ -149,34 +148,48 @@ pub async fn add_agent(
return Err(format!("创建 Agent 失败: {stderr}"));
}
let stdout = String::from_utf8_lossy(&output.stdout);
serde_json::from_str(&stdout).unwrap_or(Value::String("ok".into()));
// 返回最新列表
list_agents().await
}
/// 删除 agent
/// 删除 agent(直接操作 openclaw.json + 删除 agent 目录,不走 CLI
#[tauri::command]
pub async fn delete_agent(id: String) -> Result<String, String> {
if id == "main" {
return Err("不能删除默认 Agent".into());
}
let output = openclaw_command_async()
.args(["agents", "delete", &id])
.output()
.await
.map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
"OpenClaw CLI 未找到,请确认已安装并重启 ClawPanel。".to_string()
} else {
format!("执行失败: {e}")
}
})?;
// 1. 从 openclaw.json 的 agents.list 中移除
let config_path = super::openclaw_dir().join("openclaw.json");
if config_path.exists() {
let content = fs::read_to_string(&config_path).map_err(|e| format!("读取配置失败: {e}"))?;
let mut config: Value =
serde_json::from_str(&content).map_err(|e| format!("解析 JSON 失败: {e}"))?;
if let Some(list) = config
.get_mut("agents")
.and_then(|a| a.get_mut("list"))
.and_then(|l| l.as_array_mut())
{
list.retain(|a| a.get("id").and_then(|v| v.as_str()) != Some(&id));
}
// 同时清理 agents.profiles 中的配置
if let Some(profiles) = config
.get_mut("agents")
.and_then(|a| a.get_mut("profiles"))
.and_then(|p| p.as_object_mut())
{
profiles.remove(&id);
}
// 备份 + 写回
let bak = super::openclaw_dir().join("openclaw.json.bak");
let _ = fs::copy(&config_path, &bak);
let json = serde_json::to_string_pretty(&config).map_err(|e| format!("序列化失败: {e}"))?;
fs::write(&config_path, &json).map_err(|e| format!("写入失败: {e}"))?;
}
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(format!("删除 Agent 失败: {stderr}"));
// 2. 删除 agent 目录workspace + sessions 等)
let agent_dir = super::openclaw_dir().join("agents").join(&id);
if agent_dir.exists() {
let _ = fs::remove_dir_all(&agent_dir);
}
Ok("已删除".into())

View File

@@ -144,14 +144,14 @@ pub async fn skills_skillhub_check() -> Result<Value, String> {
#[cfg(target_os = "windows")]
let mut cmd = {
let mut c = tokio::process::Command::new("cmd");
c.args(["/c", "skillhub", "--version"]);
c.args(["/c", "skillhub", "--cli-version"]);
c.creation_flags(0x08000000);
c
};
#[cfg(not(target_os = "windows"))]
let mut cmd = {
let mut c = tokio::process::Command::new("skillhub");
c.arg("--version");
c.arg("--cli-version");
c
};
cmd.env("PATH", &path_env);

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json",
"productName": "ClawPanel",
"version": "0.9.2",
"version": "0.9.3",
"identifier": "ai.openclaw.clawpanel",
"build": {
"frontendDist": "../dist",

View File

@@ -13,7 +13,7 @@ export const API_TYPES = [
// 服务商快捷预设
export const PROVIDER_PRESETS = [
{ key: 'qtcool', label: '晴辰云', badge: '推荐', baseUrl: 'https://gpt.qt.cool/v1', api: 'openai-completions', site: 'https://gpt.qt.cool/', desc: '在力所能及的范围内为用户提供不限量的模型支持,动态获取最新可用模型列表' },
{ key: 'qtcool', label: '晴辰云', badge: '推荐', baseUrl: 'https://gpt.qt.cool/v1', api: 'openai-completions', site: 'https://gpt.qt.cool/', desc: '面板用户免费使用部分模型,付费用户享全系列顶级模型支持,全部模型低至 2-3 折' },
{ key: 'shengsuanyun', label: '胜算云', baseUrl: 'https://router.shengsuanyun.com/api/v1', api: 'openai-completions', site: 'https://www.shengsuanyun.com/?from=CH_4BVI0BM2', desc: '国内知名 AI 模型聚合平台,支持多种主流模型' },
{ key: 'siliconflow', label: '硅基流动', baseUrl: 'https://api.siliconflow.cn/v1', api: 'openai-completions', site: 'https://cloud.siliconflow.cn/i/PFrw2an5', desc: '高性价比推理平台,支持 DeepSeek、Qwen 等开源模型' },
{ key: 'volcengine', label: '火山引擎', baseUrl: 'https://ark.cn-beijing.volces.com/api/v3', api: 'openai-completions', site: 'https://volcengine.com/L/Ph1OP5I3_GY', desc: '字节跳动旗下云平台,支持豆包等模型' },

View File

@@ -2570,7 +2570,7 @@ function showSettings() {
<span style="font-size:10px;background:var(--primary);color:#fff;padding:1px 6px;border-radius:8px">推荐</span>
</div>
<div style="font-size:var(--font-size-xs);color:var(--text-secondary);line-height:1.5;margin-bottom:10px">
在力所能及的范围内为用户提供不限量的模型支持。选择模型后一键接入助手
面板用户免费使用部分模型,付费用户享全系列顶级模型,全部低至 2-3 折。选择模型后一键接入。
</div>
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<select id="ast-qtcool-model" class="form-input" style="font-size:12px;padding:5px 10px;min-width:140px;flex:1">

View File

@@ -84,21 +84,29 @@ async function loadDashboardData(page, fullRefresh = false) {
if (servicesRes.status === 'rejected') toast('服务状态加载失败', 'error')
if (versionRes.status === 'rejected') toast('版本信息加载失败', 'error')
// 自愈:补全关键默认值
// 自愈:补全关键默认值(先重新读取最新配置再 patch避免用缓存覆盖其他页面的写入
if (config) {
let patched = false
if (!config.gateway) config.gateway = {}
if (!config.gateway.mode) { config.gateway.mode = 'local'; patched = true }
// 修复旧版错误mode 不应在顶层OpenClaw 不认识)
if (config.mode) { delete config.mode; patched = true }
if (!config.tools || config.tools.profile !== 'full') {
config.tools = { profile: 'full', sessions: { visibility: 'all' }, ...(config.tools || {}) }
config.tools.profile = 'full'
if (!config.tools.sessions) config.tools.sessions = {}
config.tools.sessions.visibility = 'all'
patched = true
let needsPatch = false
if (!config.gateway?.mode) needsPatch = true
if (config.mode) needsPatch = true
if (!config.tools || config.tools.profile !== 'full') needsPatch = true
if (needsPatch) {
try {
const freshConfig = await api.readOpenclawConfig()
let patched = false
if (!freshConfig.gateway) freshConfig.gateway = {}
if (!freshConfig.gateway.mode) { freshConfig.gateway.mode = 'local'; patched = true }
if (freshConfig.mode) { delete freshConfig.mode; patched = true }
if (!freshConfig.tools || freshConfig.tools.profile !== 'full') {
freshConfig.tools = { profile: 'full', sessions: { visibility: 'all' }, ...(freshConfig.tools || {}) }
freshConfig.tools.profile = 'full'
if (!freshConfig.tools.sessions) freshConfig.tools.sessions = {}
freshConfig.tools.sessions.visibility = 'all'
patched = true
}
if (patched) api.writeOpenclawConfig(freshConfig).catch(() => {})
} catch {}
}
if (patched) api.writeOpenclawConfig(config).catch(() => {})
}
renderStatCards(page, services, version, [], config)

View File

@@ -33,7 +33,7 @@ export async function render() {
<span style="font-size:10px;background:var(--primary);color:#fff;padding:1px 6px;border-radius:8px">推荐</span>
</div>
<div style="font-size:var(--font-size-xs);color:var(--text-secondary);line-height:1.5">
在力所能及的范围内为用户提供不限量的模型支持,动态获取最新可用模型列表
面板用户免费使用部分模型,付费用户享全系列顶级模型支持,全部模型低至 2-3 折
</div>
</div>
<div style="display:flex;gap:8px;align-items:center;flex-shrink:0">