From 753de2569685a1d753f48da614d3812babbe055d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Mon, 5 Oct 2026 00:35:04 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84:=20DRY=E6=88=AA=E6=96=AD?= =?UTF-8?q?=E6=AD=A3=E5=85=B8=E6=94=B9=E5=90=8D=E6=94=B6=E5=B0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - audit/utils.rs truncate_chars→truncate_chars_ellipsis 正典改名(补…语义),re-export 链同步 - record.rs/generate_image.rs/knowledge_inject.rs/tools/knowledge.rs 调用点全链更新 - df-ai context_helpers.rs 私有版跨 crate 不引依赖保留原名,加正典标注注释 - DRY #11 收口,同名不同义陷阱消除 --- crates/df-ai/src/context_helpers.rs | 4 +++- src-tauri/src/commands/ai/audit/mod.rs | 4 ++-- src-tauri/src/commands/ai/audit/record.rs | 6 +++--- src-tauri/src/commands/ai/audit/utils.rs | 4 ++-- src-tauri/src/commands/ai/generate_image.rs | 6 +++--- src-tauri/src/commands/ai/knowledge_inject.rs | 4 ++-- src-tauri/src/commands/ai/tools/knowledge.rs | 4 ++-- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/crates/df-ai/src/context_helpers.rs b/crates/df-ai/src/context_helpers.rs index 8f4bb1a..973e24e 100644 --- a/crates/df-ai/src/context_helpers.rs +++ b/crates/df-ai/src/context_helpers.rs @@ -923,7 +923,9 @@ impl WorkingContext { } } -/// 按 chars 计数截断文本,越界补省略号(begin_turn / sync_after_compress 共用) +/// 按 chars 计数截断文本,越界补省略号(begin_turn / sync_after_compress 共用)。 +/// 语义与正典(src-tauri audit/utils.rs truncate_chars_ellipsis,DRY #11)一致; +/// 跨 crate 不引入依赖,保持本地同语义实现(有意保留原名,勿误认遗漏)。 fn truncate_chars(s: &str, max: usize) -> String { if s.chars().count() <= max { return s.to_string(); diff --git a/src-tauri/src/commands/ai/audit/mod.rs b/src-tauri/src/commands/ai/audit/mod.rs index 772faff..d7836a2 100644 --- a/src-tauri/src/commands/ai/audit/mod.rs +++ b/src-tauri/src/commands/ai/audit/mod.rs @@ -18,10 +18,10 @@ use super::tools::entity_resolve; // utils(audit/utils.rs):RiskLevel ↔ 字符串转换 + 字符串安全截断纯 helper。 // 第五批从本文件抽离,行为零变更。pub(crate) use 保持 finalize / restore 子模块 -// super::risk_str / super::risk_from_str 引用路径不变;truncate_chars 供本文件 process_tool_calls +// super::risk_str / super::risk_from_str 引用路径不变;truncate_chars_ellipsis 供本文件 process_tool_calls // DTO 装配 + record.rs 审计面板 IPC 共用。 mod utils; -pub(crate) use utils::{risk_from_str, risk_str, truncate_chars}; +pub(crate) use utils::{risk_from_str, risk_str, truncate_chars_ellipsis}; // diff(audit/diff.rs):write_file 审批预览 diff 生成。 // 第五批从本文件抽离,行为零变更。 diff --git a/src-tauri/src/commands/ai/audit/record.rs b/src-tauri/src/commands/ai/audit/record.rs index ff8d336..2cd5035 100644 --- a/src-tauri/src/commands/ai/audit/record.rs +++ b/src-tauri/src/commands/ai/audit/record.rs @@ -7,7 +7,7 @@ //! - `ToolExecutionDto`:传给前端的精简审计视图 //! - `list_tool_executions`:审批历史面板查询 IPC //! -//! 依赖 audit/utils.rs 的 `truncate_chars` 做参数/结果截断,通过 `super::truncate_chars` 引用。 +//! 依赖 audit/utils.rs 的 `truncate_chars_ellipsis` 做参数/结果截断,通过 `super::truncate_chars_ellipsis` 引用。 use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; @@ -233,8 +233,8 @@ pub async fn list_tool_executions( // ToolCallId → String(DTO 边界,前端按字符串消费) tool_call_id: r.tool_call_id.into(), tool_name: r.tool_name, - arguments_brief: super::truncate_chars(&r.arguments, 120), - result_brief: r.result.map(|s| super::truncate_chars(&s, 160)), + arguments_brief: super::truncate_chars_ellipsis(&r.arguments, 120), + result_brief: r.result.map(|s| super::truncate_chars_ellipsis(&s, 160)), status: r.status, risk_level: r.risk_level, requested_at: r.requested_at, diff --git a/src-tauri/src/commands/ai/audit/utils.rs b/src-tauri/src/commands/ai/audit/utils.rs index 48ce22e..484f8c0 100644 --- a/src-tauri/src/commands/ai/audit/utils.rs +++ b/src-tauri/src/commands/ai/audit/utils.rs @@ -4,7 +4,7 @@ //! - `risk_str` / `risk_from_str`:finalize / restore 通过 `super::` 引用(pub(crate))。 //! - `truncate_chars`:mod.rs 的 process_tool_calls DTO 装配用 + record.rs 审计面板 IPC 用(pub(crate))。 //! -//! re-export 维持原路径透明:`super::risk_str` / `super::risk_from_str` / `super::truncate_chars` +//! re-export 维持原路径透明:`super::risk_str` / `super::risk_from_str` / `super::truncate_chars_ellipsis` //! 在 audit/mod.rs 内通过 `pub(crate) use` 引入后裸名可用,外部子模块的 `super::risk_*` 引用不变。 use df_ai::ai_tools::RiskLevel; @@ -29,7 +29,7 @@ pub(crate) fn risk_from_str(s: &str) -> Option { } /// 截断字符串到 max 字符(按 char_indices 边界切,避免切坏中文/emoji) -pub(crate) fn truncate_chars(s: &str, max: usize) -> String { +pub(crate) fn truncate_chars_ellipsis(s: &str, max: usize) -> String { if s.chars().count() <= max { return s.to_string(); } diff --git a/src-tauri/src/commands/ai/generate_image.rs b/src-tauri/src/commands/ai/generate_image.rs index 63dbcea..127b229 100644 --- a/src-tauri/src/commands/ai/generate_image.rs +++ b/src-tauri/src/commands/ai/generate_image.rs @@ -49,7 +49,7 @@ use df_storage::db::Database; use df_storage::models::AiProviderRecord; use df_storage::secret::resolve_provider_secret; -use crate::commands::ai::audit::truncate_chars; +use crate::commands::ai::audit::truncate_chars_ellipsis; use crate::commands::ai::http::{ build_client, execute_with_redirects, resolve_and_check_host, validate_url, MAX_REDIRECTS, }; @@ -184,7 +184,7 @@ pub(crate) async fn execute_generate_image( if !status.is_success() { // 错误响应读 body 摘要(截断 500 chars,截断时尾部补 …)帮助定位 let err_text = resp.text().await.unwrap_or_default(); - let snippet: String = truncate_chars(&err_text, 500); + let snippet: String = truncate_chars_ellipsis(&err_text, 500); anyhow::bail!( "图像生成端点返回 HTTP {}: {}", status.as_u16(), @@ -459,7 +459,7 @@ async fn write_atomic(output_path: &str, data: &[u8]) -> anyhow::Result<()> { /// 走 audit truncate_chars 正典(截断时尾部补 …);错误文案无硬长度约束,允许多 1 字符。 fn body_snippet(v: &Value) -> String { let s = v.to_string(); - truncate_chars(&s, 500) + truncate_chars_ellipsis(&s, 500) } // ============================================================ diff --git a/src-tauri/src/commands/ai/knowledge_inject.rs b/src-tauri/src/commands/ai/knowledge_inject.rs index b37e165..6a7e8d2 100644 --- a/src-tauri/src/commands/ai/knowledge_inject.rs +++ b/src-tauri/src/commands/ai/knowledge_inject.rs @@ -21,7 +21,7 @@ use df_types::types::new_id; use crate::state::{AppState, ExtractTrigger, LlmConcurrency, log_slow_lock}; -use crate::commands::ai::audit::truncate_chars; +use crate::commands::ai::audit::truncate_chars_ellipsis; use crate::commands::err_str; use super::{AiSession}; @@ -562,7 +562,7 @@ pub(crate) async fn build_knowledge_context( let kind = r.kind.clone(); let title = r.title.clone(); // 截断 content 防膨胀(注入侧最多 500 字符;走 audit 正典,截断时尾部补 … 提示有省略) - let snippet: String = truncate_chars(&r.content, 500); + let snippet: String = truncate_chars_ellipsis(&r.content, 500); out.push_str(&format!("- [{}] {}: {} (复用 {} 次)\n", kind, title, snippet, r.reuse_count)); } out diff --git a/src-tauri/src/commands/ai/tools/knowledge.rs b/src-tauri/src/commands/ai/tools/knowledge.rs index 0d5a7b5..2651d30 100644 --- a/src-tauri/src/commands/ai/tools/knowledge.rs +++ b/src-tauri/src/commands/ai/tools/knowledge.rs @@ -30,7 +30,7 @@ use df_storage::db::Database; use df_storage::models::KnowledgeRecord; use df_types::types::new_id; -use crate::commands::ai::audit::truncate_chars; +use crate::commands::ai::audit::truncate_chars_ellipsis; use crate::commands::ai::knowledge_inject::{extract_query_keywords, spawn_embedding_for_record}; use crate::commands::knowledge_timeline::KnowledgeTimeline; use crate::commands::now_millis; @@ -81,7 +81,7 @@ pub fn register(registry: &mut AiToolRegistry, db: &Arc) { serde_json::json!({ "title": k.title, "kind": k.kind, - "content": truncate_chars(&k.content, SEARCH_CONTENT_SNIPPET_LEN), + "content": truncate_chars_ellipsis(&k.content, SEARCH_CONTENT_SNIPPET_LEN), "status": k.status, "reuse_count": k.reuse_count, })