fix: cargo fmt + update docs version to 0.4.0

This commit is contained in:
晴天
2026-03-05 20:57:21 +08:00
parent 79cd15e1c4
commit afb9f8ebe5
2 changed files with 53 additions and 28 deletions

View File

@@ -34,7 +34,7 @@
"description": "OpenClaw AI Agent 可视化管理面板,基于 Tauri v2 的跨平台桌面应用。支持仪表盘监控、多模型配置、实时 AI 聊天、记忆管理、Agent 管理、网关配置、内网穿透等功能。",
"url": "https://claw.qt.cool/",
"downloadUrl": "https://github.com/qingchencloud/clawpanel/releases/latest",
"softwareVersion": "0.3.0",
"softwareVersion": "0.4.0",
"author": {
"@type": "Organization",
"name": "晴辰云 QingchenCloud",
@@ -429,7 +429,7 @@
<div class="orb orb-1" id="orb1"></div>
<div class="orb orb-2" id="orb2"></div>
<div class="hero-inner">
<div class="reveal hero-badge"><span class="pulse"></span> v0.3.0 已发布 — 社区交流 &amp; 高级视觉特效</div>
<div class="reveal hero-badge"><span class="pulse"></span> v0.4.0 已发布 — Gateway 守护、配置同步、流式超时</div>
<h1 class="reveal hero-title">管理你的 <span class="gradient-text shimmer">AI Agent</span><br>从未如此直观</h1>
<p class="reveal hero-subtitle">ClawPanel 是 <strong>OpenClaw</strong> 的可视化管理面板,基于 Tauri v2 构建。<br>仪表盘、模型配置、实时聊天、记忆管理 — 一站式掌控。</p>
<div class="reveal hero-cta">
@@ -696,7 +696,7 @@
<div class="orb orb-2" style="top:auto;bottom:-100px"></div>
<div class="container-sm" style="position:relative;z-index:10">
<div class="section-header">
<div class="reveal download-version"><span class="pulse"></span> v0.3.0 最新版</div>
<div class="reveal download-version"><span class="pulse"></span> v0.4.0 最新版</div>
<h2 class="reveal section-title"><span class="gradient-text">下载安装</span></h2>
<p class="reveal section-desc">选择你的操作系统,一键下载安装</p>
</div>
@@ -706,11 +706,11 @@
<h3>macOS</h3>
<p class="dl-desc">支持 Apple Silicon 和 Intel 芯片</p>
<div class="dl-links">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.3.0_aarch64.dmg" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_aarch64.dmg" target="_blank" rel="noopener">
Apple Silicon (M1/M2/M3/M4)
<span class="dl-format">.dmg</span>
</a>
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.3.0_x64.dmg" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_x64.dmg" target="_blank" rel="noopener">
Intel 芯片
<span class="dl-format">.dmg</span>
</a>
@@ -721,11 +721,11 @@
<h3>Windows</h3>
<p class="dl-desc">支持 Windows 10 及以上版本</p>
<div class="dl-links">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.3.0_x64-setup.exe" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_x64-setup.exe" target="_blank" rel="noopener">
安装程序
<span class="dl-format">.exe</span>
</a>
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.3.0_x64_en-US.msi" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_x64_en-US.msi" target="_blank" rel="noopener">
MSI 安装包
<span class="dl-format">.msi</span>
</a>
@@ -736,11 +736,11 @@
<h3>Linux</h3>
<p class="dl-desc">支持主流 Linux 发行版</p>
<div class="dl-links">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.3.0_amd64.AppImage" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_amd64.AppImage" target="_blank" rel="noopener">
通用版
<span class="dl-format">.AppImage</span>
</a>
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.3.0_amd64.deb" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_amd64.deb" target="_blank" rel="noopener">
Debian / Ubuntu
<span class="dl-format">.deb</span>
</a>

View File

@@ -124,7 +124,8 @@ pub fn write_openclaw_config(config: Value) -> Result<(), String> {
/// 包括:同步 baseUrl/apiKey/api、删除已移除的 provider、删除已移除的 model、
/// 确保 Gateway 运行时不会引用 openclaw.json 中已不存在的模型
fn sync_providers_to_agent_models(config: &Value) {
let src_providers = config.pointer("/models/providers")
let src_providers = config
.pointer("/models/providers")
.and_then(|p| p.as_object());
// 收集 openclaw.json 中所有有效的 provider/model 组合
@@ -133,8 +134,7 @@ fn sync_providers_to_agent_models(config: &Value) {
for (pk, pv) in providers {
if let Some(models) = pv.get("models").and_then(|m| m.as_array()) {
for m in models {
let id = m.get("id").and_then(|v| v.as_str())
.or_else(|| m.as_str());
let id = m.get("id").and_then(|v| v.as_str()).or_else(|| m.as_str());
if let Some(id) = id {
valid_models.insert(format!("{}/{}", pk, id));
}
@@ -161,18 +161,27 @@ fn sync_providers_to_agent_models(config: &Value) {
if !models_path.exists() {
continue;
}
let Ok(content) = fs::read_to_string(&models_path) else { continue };
let Ok(mut models_json) = serde_json::from_str::<Value>(&content) else { continue };
let Ok(content) = fs::read_to_string(&models_path) else {
continue;
};
let Ok(mut models_json) = serde_json::from_str::<Value>(&content) else {
continue;
};
let mut changed = false;
// 同步 providers
if let Some(dst_providers) = models_json.get_mut("providers").and_then(|p| p.as_object_mut()) {
if let Some(dst_providers) = models_json
.get_mut("providers")
.and_then(|p| p.as_object_mut())
{
// 1. 删除 openclaw.json 中已不存在的 provider
if let Some(src) = src_providers {
let to_remove: Vec<String> = dst_providers.keys()
let to_remove: Vec<String> = dst_providers
.keys()
.filter(|k| !src.contains_key(k.as_str()))
.cloned().collect();
.cloned()
.collect();
for k in to_remove {
dst_providers.remove(&k);
changed = true;
@@ -184,26 +193,42 @@ fn sync_providers_to_agent_models(config: &Value) {
if let Some(dst_obj) = dst_provider.as_object_mut() {
// 同步连接信息
for field in ["baseUrl", "apiKey", "api"] {
if let Some(src_val) = src_provider.get(field).and_then(|v| v.as_str()) {
if dst_obj.get(field).and_then(|v| v.as_str()) != Some(src_val) {
dst_obj.insert(field.to_string(), Value::String(src_val.to_string()));
if let Some(src_val) =
src_provider.get(field).and_then(|v| v.as_str())
{
if dst_obj.get(field).and_then(|v| v.as_str()) != Some(src_val)
{
dst_obj.insert(
field.to_string(),
Value::String(src_val.to_string()),
);
changed = true;
}
}
}
// 清理已删除的 models
if let Some(dst_models) = dst_obj.get_mut("models").and_then(|m| m.as_array_mut()) {
if let Some(dst_models) =
dst_obj.get_mut("models").and_then(|m| m.as_array_mut())
{
let src_model_ids: std::collections::HashSet<String> = src_provider
.get("models").and_then(|m| m.as_array())
.map(|arr| arr.iter().filter_map(|m| {
m.get("id").and_then(|v| v.as_str())
.or_else(|| m.as_str())
.map(|s| s.to_string())
}).collect())
.get("models")
.and_then(|m| m.as_array())
.map(|arr| {
arr.iter()
.filter_map(|m| {
m.get("id")
.and_then(|v| v.as_str())
.or_else(|| m.as_str())
.map(|s| s.to_string())
})
.collect()
})
.unwrap_or_default();
let before = dst_models.len();
dst_models.retain(|m| {
let id = m.get("id").and_then(|v| v.as_str())
let id = m
.get("id")
.and_then(|v| v.as_str())
.or_else(|| m.as_str())
.unwrap_or("");
src_model_ids.contains(id)