From 2e35df927d96c681a20ec61c36c690b3f0109412 Mon Sep 17 00:00:00 2001 From: coso Date: Mon, 16 Feb 2026 02:54:58 +0800 Subject: [PATCH] release: v0.67.0 --- package.json | 2 +- src-tauri/Cargo.lock | 30 +- src-tauri/Cargo.toml | 4 +- src-tauri/crates/agent/src/session_store.rs | 25 ++ .../crates/config/src/observer/traits.rs | 1 - .../core/src/database/dao/a2ui_form_dao.rs | 4 +- .../core/src/database/dao/material_dao.rs | 22 +- .../core/src/database/dao/persona_dao.rs | 4 +- .../src/database/dao/poster_material_dao.rs | 12 +- .../src/database/dao/publish_config_dao.rs | 2 +- .../core/src/database/dao/template_dao.rs | 14 +- .../crates/core/src/database/migration_v2.rs | 3 +- src-tauri/crates/core/src/memory/manager.rs | 2 +- .../crates/core/src/models/project_model.rs | 27 +- src-tauri/crates/embedding/src/lib.rs | 18 +- src-tauri/crates/mcp/src/manager.rs | 35 +- src-tauri/crates/memory/src/extractor.rs | 14 +- src-tauri/crates/memory/src/feedback.rs | 12 +- src-tauri/crates/memory/src/gatekeeper.rs | 8 +- src-tauri/crates/memory/src/models/unified.rs | 4 +- src-tauri/crates/memory/src/search.rs | 14 +- .../providers/src/providers/openai_custom.rs | 3 +- .../src/content_creator/workflow_service.rs | 19 +- .../crates/services/src/material_service.rs | 77 +++- src-tauri/crates/services/src/mcp_service.rs | 2 +- .../crates/services/src/persona_service.rs | 2 +- .../services/src/project_context_builder.rs | 30 +- .../services/src/provider_pool_service.rs | 14 +- src-tauri/crates/services/src/switch.rs | 6 +- .../crates/services/src/template_service.rs | 2 +- .../crates/voice-core/tests/asr_e2e_tests.rs | 20 +- src-tauri/src/agent/aster_agent.rs | 14 + src-tauri/src/app/bootstrap.rs | 19 +- src-tauri/src/app/runner.rs | 5 + src-tauri/src/app/setup.rs | 2 + src-tauri/src/commands/agent_cmd.rs | 41 +- src-tauri/src/commands/aster_agent_cmd.rs | 31 +- .../commands/ecommerce_review_reply_cmd.rs | 2 +- src-tauri/src/commands/external_tools_cmd.rs | 22 +- src-tauri/src/commands/file_upload_cmd.rs | 21 +- src-tauri/src/commands/kiro_local.rs | 12 +- src-tauri/src/commands/material_cmd.rs | 378 ++++++++++++++++++ src-tauri/src/commands/mcp_cmd.rs | 2 +- src-tauri/src/commands/memory_feedback_cmd.rs | 4 +- .../src/commands/memory_management_cmd.rs | 10 +- src-tauri/src/commands/memory_search_cmd.rs | 47 +-- src-tauri/src/commands/persona_cmd.rs | 2 +- src-tauri/src/commands/skill_exec_cmd.rs | 12 +- src-tauri/src/commands/unified_memory_cmd.rs | 6 +- src-tauri/src/commands/usage_stats_cmd.rs | 6 +- src-tauri/src/commands/voice_test_cmd.rs | 2 +- src-tauri/src/config/tests.rs | 1 + src-tauri/src/tray/menu.rs | 4 +- src-tauri/src/tray/menu_handler.rs | 20 +- src-tauri/tauri.conf.headless.json | 2 +- src-tauri/tauri.conf.json | 2 +- src/components/Sidebar.tsx | 4 +- .../chat/components/ChatModelSelector.tsx | 44 +- src/components/agent/chat/hooks/index.ts | 27 +- .../agent/chat/hooks/useAgentChat.test.tsx | 268 +++++++++++++ .../agent/chat/hooks/useAgentChat.ts | 143 ++++++- .../chat/hooks/useAsterAgentChat.test.tsx | 201 ++++++++++ .../agent/chat/hooks/useAsterAgentChat.ts | 229 +++++++++-- src/components/agent/chat/index.tsx | 24 +- src/components/api-server/ApiServerPage.tsx | 119 +++++- src/components/api-server/LogsTab.tsx | 2 +- .../image-gen/ImageGenPage.test.tsx | 247 ++++++++++++ src/components/image-gen/ImageGenPage.tsx | 232 +++++++++++ src/components/image-gen/test-utils.ts | 70 ++++ src/components/image-gen/types.ts | 4 + .../image-gen/useImageGen.resource.test.tsx | 174 ++++++++ src/components/image-gen/useImageGen.test.ts | 2 + src/components/image-gen/useImageGen.ts | 283 ++++++++++++- .../projects/ProjectSelector.test.ts | 114 ++++++ src/components/projects/ProjectSelector.tsx | 17 +- .../dialogs/MaterialPreviewDialog.tsx | 37 +- .../projects/dialogs/MaterialUploadDialog.tsx | 143 +++++-- .../projects/projectSelectorUtils.ts | 28 ++ src/components/projects/tabs/MaterialTab.tsx | 8 +- .../provider-pool/ProviderPoolPage.tsx | 2 +- src/components/resources/ResourcesPage.tsx | 183 ++++++++- .../resources/services/resourceAdapter.ts | 116 +++++- src/components/settings-v2/_layout/index.tsx | 2 +- .../settings-v2/hooks/useSettingsCategory.ts | 2 +- src/components/settings/AboutSection.tsx | 4 +- src/components/workspace/README.md | 29 ++ .../workspace/WorkbenchPage.test.tsx | 255 ++++++++++++ src/components/workspace/WorkbenchPage.tsx | 348 ++++++++++++++-- .../utils/creationIntentPrompt.test.ts | 99 +++++ .../workspace/utils/creationIntentPrompt.ts | 315 +++++++++++++++ src/hooks/useMaterials.ts | 11 +- src/hooks/useTauri.ts | 2 +- src/i18n/patches/en.json | 42 +- src/i18n/patches/zh.json | 42 +- src/lib/api/agent.ts | 17 + src/lib/resourceProjectSelection.ts | 119 ++++++ src/types/material.ts | 4 + 97 files changed, 4516 insertions(+), 595 deletions(-) create mode 100644 src/components/agent/chat/hooks/useAgentChat.test.tsx create mode 100644 src/components/image-gen/ImageGenPage.test.tsx create mode 100644 src/components/image-gen/test-utils.ts create mode 100644 src/components/image-gen/useImageGen.resource.test.tsx create mode 100644 src/components/projects/ProjectSelector.test.ts create mode 100644 src/components/projects/projectSelectorUtils.ts create mode 100644 src/components/workspace/WorkbenchPage.test.tsx create mode 100644 src/components/workspace/utils/creationIntentPrompt.test.ts create mode 100644 src/components/workspace/utils/creationIntentPrompt.ts create mode 100644 src/lib/resourceProjectSelection.ts diff --git a/package.json b/package.json index 6f705a9cf..a893a0eac 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "proxycast", "private": true, - "version": "0.66.0", + "version": "0.67.0", "type": "module", "repository": { "type": "git", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 97dc99ea4..c8fe03ef3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6621,7 +6621,7 @@ dependencies = [ [[package]] name = "proxycast" -version = "0.66.0" +version = "0.67.0" dependencies = [ "anyhow", "arboard", @@ -6719,7 +6719,7 @@ dependencies = [ [[package]] name = "proxycast-agent" -version = "0.66.0" +version = "0.67.0" dependencies = [ "aster", "async-trait", @@ -6742,7 +6742,7 @@ dependencies = [ [[package]] name = "proxycast-config" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-trait", "parking_lot", @@ -6758,7 +6758,7 @@ dependencies = [ [[package]] name = "proxycast-core" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-trait", "axum 0.7.9", @@ -6797,7 +6797,7 @@ dependencies = [ [[package]] name = "proxycast-credential" -version = "0.66.0" +version = "0.67.0" dependencies = [ "axum 0.7.9", "chrono", @@ -6828,7 +6828,7 @@ dependencies = [ [[package]] name = "proxycast-infra" -version = "0.66.0" +version = "0.67.0" dependencies = [ "chrono", "dashmap 5.5.3", @@ -6848,7 +6848,7 @@ dependencies = [ [[package]] name = "proxycast-mcp" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-trait", "glob", @@ -6879,7 +6879,7 @@ dependencies = [ [[package]] name = "proxycast-processor" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-trait", "parking_lot", @@ -6898,7 +6898,7 @@ dependencies = [ [[package]] name = "proxycast-providers" -version = "0.66.0" +version = "0.67.0" dependencies = [ "anyhow", "async-stream", @@ -6950,7 +6950,7 @@ dependencies = [ [[package]] name = "proxycast-server" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-stream", "axum 0.7.9", @@ -6989,7 +6989,7 @@ dependencies = [ [[package]] name = "proxycast-server-utils" -version = "0.66.0" +version = "0.67.0" dependencies = [ "axum 0.7.9", "futures", @@ -7004,7 +7004,7 @@ dependencies = [ [[package]] name = "proxycast-services" -version = "0.66.0" +version = "0.67.0" dependencies = [ "anyhow", "aster", @@ -7045,7 +7045,7 @@ dependencies = [ [[package]] name = "proxycast-skills" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-trait", "dirs 5.0.1", @@ -7061,7 +7061,7 @@ dependencies = [ [[package]] name = "proxycast-terminal" -version = "0.66.0" +version = "0.67.0" dependencies = [ "async-trait", "base64 0.22.1", @@ -7088,7 +7088,7 @@ dependencies = [ [[package]] name = "proxycast-websocket" -version = "0.66.0" +version = "0.67.0" dependencies = [ "axum 0.7.9", "chrono", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e18db5a27..1779c3b28 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.66.0" +version = "0.67.0" edition = "2021" authors = ["you"] repository = "https://github.com/aiclientproxy/proxycast" @@ -183,7 +183,7 @@ version = "2.4" [package] name = "proxycast" -version = "0.66.0" +version = "0.67.0" description = "AI API Proxy Desktop App" authors = ["you"] edition = "2021" diff --git a/src-tauri/crates/agent/src/session_store.rs b/src-tauri/crates/agent/src/session_store.rs index 98a68e878..adba3d1df 100644 --- a/src-tauri/crates/agent/src/session_store.rs +++ b/src-tauri/crates/agent/src/session_store.rs @@ -143,6 +143,31 @@ pub fn get_session_sync(db: &DbConnection, session_id: &str) -> Result Result<(), String> { + let trimmed_name = name.trim(); + if trimmed_name.is_empty() { + return Err("会话名称不能为空".to_string()); + } + + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + AgentDao::update_title(&conn, session_id, trimmed_name) + .map_err(|e| format!("更新会话标题失败: {e}"))?; + + let now = Utc::now().to_rfc3339(); + AgentDao::update_session_time(&conn, session_id, &now) + .map_err(|e| format!("更新会话时间失败: {e}"))?; + + Ok(()) +} + +/// 删除会话 +pub fn delete_session_sync(db: &DbConnection, session_id: &str) -> Result<(), String> { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + AgentDao::delete_session(&conn, session_id).map_err(|e| format!("删除会话失败: {e}"))?; + Ok(()) +} + /// 将 AgentMessage 转换为 TauriMessage fn convert_agent_message(message: &AgentMessage) -> TauriMessage { let content = match &message.content { diff --git a/src-tauri/crates/config/src/observer/traits.rs b/src-tauri/crates/config/src/observer/traits.rs index 63c225129..1ee3447ae 100644 --- a/src-tauri/crates/config/src/observer/traits.rs +++ b/src-tauri/crates/config/src/observer/traits.rs @@ -140,7 +140,6 @@ where #[cfg(test)] mod tests { use super::*; - use crate::observer::events::{ConfigChangeSource, FullReloadEvent}; struct TestObserver { name: String, diff --git a/src-tauri/crates/core/src/database/dao/a2ui_form_dao.rs b/src-tauri/crates/core/src/database/dao/a2ui_form_dao.rs index febbb2e14..a1d3f62c4 100644 --- a/src-tauri/crates/core/src/database/dao/a2ui_form_dao.rs +++ b/src-tauri/crates/core/src/database/dao/a2ui_form_dao.rs @@ -161,7 +161,7 @@ impl A2UIFormDao { )?; let forms: Vec = stmt - .query_map([message_id], |row| Self::map_row(row))? + .query_map([message_id], Self::map_row)? .filter_map(|r| r.ok()) .collect(); @@ -180,7 +180,7 @@ impl A2UIFormDao { )?; let forms: Vec = stmt - .query_map([session_id], |row| Self::map_row(row))? + .query_map([session_id], Self::map_row)? .filter_map(|r| r.ok()) .collect(); diff --git a/src-tauri/crates/core/src/database/dao/material_dao.rs b/src-tauri/crates/core/src/database/dao/material_dao.rs index 5105cc969..2a7836041 100644 --- a/src-tauri/crates/core/src/database/dao/material_dao.rs +++ b/src-tauri/crates/core/src/database/dao/material_dao.rs @@ -179,7 +179,7 @@ impl MaterialDao { // 按搜索关键词筛选(名称或描述) if let Some(ref query) = f.search_query { sql.push_str(" AND (name LIKE ? OR description LIKE ?)"); - let pattern = format!("%{}%", query); + let pattern = format!("%{query}%"); params_vec.push(Box::new(pattern.clone())); params_vec.push(Box::new(pattern)); } @@ -188,7 +188,7 @@ impl MaterialDao { if let Some(ref tags) = f.tags { for tag in tags { sql.push_str(" AND tags_json LIKE ?"); - params_vec.push(Box::new(format!("%\"{}%", tag))); + params_vec.push(Box::new(format!("%\"{tag}%"))); } } } @@ -202,7 +202,7 @@ impl MaterialDao { params_vec.iter().map(|p| p.as_ref()).collect(); let materials: Vec = stmt - .query_map(params_refs.as_slice(), |row| Self::map_row(row))? + .query_map(params_refs.as_slice(), Self::map_row)? .filter_map(|r| r.ok()) .collect(); @@ -480,7 +480,7 @@ mod tests { for i in 1..=3 { let req = UploadMaterialRequest { project_id: "project-1".to_string(), - name: format!("素材{}", i), + name: format!("素材{i}"), material_type: "document".to_string(), file_path: None, content: None, @@ -517,11 +517,11 @@ mod tests { create_test_project(&conn, "project-1"); // 创建不同类型的素材 - let types = vec!["document", "image", "document", "text"]; + let types = ["document", "image", "document", "text"]; for (i, t) in types.iter().enumerate() { let req = UploadMaterialRequest { project_id: "project-1".to_string(), - name: format!("素材{}", i), + name: format!("素材{i}"), material_type: t.to_string(), file_path: None, content: None, @@ -743,7 +743,7 @@ mod tests { for i in 1..=3 { let req = UploadMaterialRequest { project_id: "project-1".to_string(), - name: format!("素材{}", i), + name: format!("素材{i}"), material_type: "document".to_string(), file_path: None, content: None, @@ -768,9 +768,9 @@ mod tests { for i in 1..=2 { let req = UploadMaterialRequest { project_id: "project-1".to_string(), - name: format!("素材{}", i), + name: format!("素材{i}"), material_type: "document".to_string(), - file_path: Some(format!("/path/to/file{}.pdf", i)), + file_path: Some(format!("/path/to/file{i}.pdf")), content: None, tags: None, description: None, @@ -817,7 +817,7 @@ mod tests { for i in 1..=3 { let req = UploadMaterialRequest { project_id: "project-a".to_string(), - name: format!("A素材{}", i), + name: format!("A素材{i}"), material_type: "document".to_string(), file_path: None, content: None, @@ -830,7 +830,7 @@ mod tests { for i in 1..=2 { let req = UploadMaterialRequest { project_id: "project-b".to_string(), - name: format!("B素材{}", i), + name: format!("B素材{i}"), material_type: "image".to_string(), file_path: None, content: None, diff --git a/src-tauri/crates/core/src/database/dao/persona_dao.rs b/src-tauri/crates/core/src/database/dao/persona_dao.rs index a149c50ca..32209be7c 100644 --- a/src-tauri/crates/core/src/database/dao/persona_dao.rs +++ b/src-tauri/crates/core/src/database/dao/persona_dao.rs @@ -150,7 +150,7 @@ impl PersonaDao { )?; let personas: Vec = stmt - .query_map([project_id], |row| Self::map_row(row))? + .query_map([project_id], Self::map_row)? .filter_map(|r| r.ok()) .collect(); @@ -471,7 +471,7 @@ mod tests { for i in 1..=2 { let req = CreatePersonaRequest { project_id: "project-1".to_string(), - name: format!("人设{}", i), + name: format!("人设{i}"), description: None, style: "测试".to_string(), tone: None, diff --git a/src-tauri/crates/core/src/database/dao/poster_material_dao.rs b/src-tauri/crates/core/src/database/dao/poster_material_dao.rs index 719ca5f39..cea6151f3 100644 --- a/src-tauri/crates/core/src/database/dao/poster_material_dao.rs +++ b/src-tauri/crates/core/src/database/dao/poster_material_dao.rs @@ -196,11 +196,11 @@ impl PosterMaterialDao { let mut stmt = conn.prepare(sql)?; let results: Vec = if let Some(cat) = category { - stmt.query_map(params![project_id, cat], |row| Self::map_joined_row(row))? + stmt.query_map(params![project_id, cat], Self::map_joined_row)? .filter_map(|r| r.ok()) .collect() } else { - stmt.query_map([project_id], |row| Self::map_joined_row(row))? + stmt.query_map([project_id], Self::map_joined_row)? .filter_map(|r| r.ok()) .collect() }; @@ -241,11 +241,11 @@ impl PosterMaterialDao { let mut stmt = conn.prepare(sql)?; let results: Vec = if let Some(cat) = category { - stmt.query_map(params![project_id, cat], |row| Self::map_joined_row(row))? + stmt.query_map(params![project_id, cat], Self::map_joined_row)? .filter_map(|r| r.ok()) .collect() } else { - stmt.query_map([project_id], |row| Self::map_joined_row(row))? + stmt.query_map([project_id], Self::map_joined_row)? .filter_map(|r| r.ok()) .collect() }; @@ -286,11 +286,11 @@ impl PosterMaterialDao { let mut stmt = conn.prepare(sql)?; let results: Vec = if let Some(m) = mood { - stmt.query_map(params![project_id, m], |row| Self::map_joined_row(row))? + stmt.query_map(params![project_id, m], Self::map_joined_row)? .filter_map(|r| r.ok()) .collect() } else { - stmt.query_map([project_id], |row| Self::map_joined_row(row))? + stmt.query_map([project_id], Self::map_joined_row)? .filter_map(|r| r.ok()) .collect() }; diff --git a/src-tauri/crates/core/src/database/dao/publish_config_dao.rs b/src-tauri/crates/core/src/database/dao/publish_config_dao.rs index 3a3724286..954ac41b2 100644 --- a/src-tauri/crates/core/src/database/dao/publish_config_dao.rs +++ b/src-tauri/crates/core/src/database/dao/publish_config_dao.rs @@ -163,7 +163,7 @@ impl PublishConfigDao { )?; let configs: Vec = stmt - .query_map([project_id], |row| Self::map_row(row))? + .query_map([project_id], Self::map_row)? .filter_map(|r| r.ok()) .collect(); diff --git a/src-tauri/crates/core/src/database/dao/template_dao.rs b/src-tauri/crates/core/src/database/dao/template_dao.rs index 0c9b99e15..5264130f6 100644 --- a/src-tauri/crates/core/src/database/dao/template_dao.rs +++ b/src-tauri/crates/core/src/database/dao/template_dao.rs @@ -141,7 +141,7 @@ impl TemplateDao { )?; let templates: Vec