mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-07 06:12:58 +08:00
feat: v0.9.3 — 9项Bug修复+ARM性能优化+R2 CDN加速+非商用协议
This commit is contained in:
20
CHANGELOG.md
20
CHANGELOG.md
@@ -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.ai),Windows 安装从 3-10 分钟降至 1-2 分钟
|
||||
- **模型添加体验优化** — 快捷添加改为模型选择弹窗,用户可自主勾选需要的模型
|
||||
|
||||
## [0.9.2] - 2026-03-16
|
||||
|
||||
### 新功能 (Features)
|
||||
|
||||
44
LICENSE
44
LICENSE
@@ -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. 免责声明
|
||||
本软件按"现状"提供,不提供任何明示或暗示的保证,包括但不限于适销性、
|
||||
特定用途适用性和非侵权性的保证。在任何情况下,版权所有者均不对因使用
|
||||
本软件而产生的任何直接、间接、附带、特殊或后果性损害承担责任。
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
2
src-tauri/Cargo.lock
generated
@@ -328,7 +328,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clawpanel"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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: '字节跳动旗下云平台,支持豆包等模型' },
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user