重构: DRY截断正典改名收尾

- 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 收口,同名不同义陷阱消除
This commit is contained in:
lxy
2026-10-05 00:35:04 +08:00
parent 6a50193b34
commit 753de25696
7 changed files with 17 additions and 15 deletions
+3 -1
View File
@@ -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 { fn truncate_chars(s: &str, max: usize) -> String {
if s.chars().count() <= max { if s.chars().count() <= max {
return s.to_string(); return s.to_string();
+2 -2
View File
@@ -18,10 +18,10 @@ use super::tools::entity_resolve;
// utils(audit/utils.rs):RiskLevel ↔ 字符串转换 + 字符串安全截断纯 helper。 // utils(audit/utils.rs):RiskLevel ↔ 字符串转换 + 字符串安全截断纯 helper。
// 第五批从本文件抽离,行为零变更。pub(crate) use 保持 finalize / restore 子模块 // 第五批从本文件抽离,行为零变更。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 共用。 // DTO 装配 + record.rs 审计面板 IPC 共用。
mod utils; 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(audit/diff.rs):write_file 审批预览 diff 生成。
// 第五批从本文件抽离,行为零变更。 // 第五批从本文件抽离,行为零变更。
+3 -3
View File
@@ -7,7 +7,7 @@
//! - `ToolExecutionDto`:传给前端的精简审计视图 //! - `ToolExecutionDto`:传给前端的精简审计视图
//! - `list_tool_executions`:审批历史面板查询 IPC //! - `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 serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
@@ -233,8 +233,8 @@ pub async fn list_tool_executions(
// ToolCallId → String(DTO 边界,前端按字符串消费) // ToolCallId → String(DTO 边界,前端按字符串消费)
tool_call_id: r.tool_call_id.into(), tool_call_id: r.tool_call_id.into(),
tool_name: r.tool_name, tool_name: r.tool_name,
arguments_brief: super::truncate_chars(&r.arguments, 120), arguments_brief: super::truncate_chars_ellipsis(&r.arguments, 120),
result_brief: r.result.map(|s| super::truncate_chars(&s, 160)), result_brief: r.result.map(|s| super::truncate_chars_ellipsis(&s, 160)),
status: r.status, status: r.status,
risk_level: r.risk_level, risk_level: r.risk_level,
requested_at: r.requested_at, requested_at: r.requested_at,
+2 -2
View File
@@ -4,7 +4,7 @@
//! - `risk_str` / `risk_from_str`:finalize / restore 通过 `super::` 引用(pub(crate))。 //! - `risk_str` / `risk_from_str`:finalize / restore 通过 `super::` 引用(pub(crate))。
//! - `truncate_chars`:mod.rs 的 process_tool_calls DTO 装配用 + record.rs 审计面板 IPC 用(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_*` 引用不变。 //! 在 audit/mod.rs 内通过 `pub(crate) use` 引入后裸名可用,外部子模块的 `super::risk_*` 引用不变。
use df_ai::ai_tools::RiskLevel; use df_ai::ai_tools::RiskLevel;
@@ -29,7 +29,7 @@ pub(crate) fn risk_from_str(s: &str) -> Option<RiskLevel> {
} }
/// 截断字符串到 max 字符(按 char_indices 边界切,避免切坏中文/emoji) /// 截断字符串到 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 { if s.chars().count() <= max {
return s.to_string(); return s.to_string();
} }
+3 -3
View File
@@ -49,7 +49,7 @@ use df_storage::db::Database;
use df_storage::models::AiProviderRecord; use df_storage::models::AiProviderRecord;
use df_storage::secret::resolve_provider_secret; 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::{ use crate::commands::ai::http::{
build_client, execute_with_redirects, resolve_and_check_host, validate_url, MAX_REDIRECTS, 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() { if !status.is_success() {
// 错误响应读 body 摘要(截断 500 chars,截断时尾部补 …)帮助定位 // 错误响应读 body 摘要(截断 500 chars,截断时尾部补 …)帮助定位
let err_text = resp.text().await.unwrap_or_default(); 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!( anyhow::bail!(
"图像生成端点返回 HTTP {}: {}", "图像生成端点返回 HTTP {}: {}",
status.as_u16(), status.as_u16(),
@@ -459,7 +459,7 @@ async fn write_atomic(output_path: &str, data: &[u8]) -> anyhow::Result<()> {
/// 走 audit truncate_chars 正典(截断时尾部补 …);错误文案无硬长度约束,允许多 1 字符。 /// 走 audit truncate_chars 正典(截断时尾部补 …);错误文案无硬长度约束,允许多 1 字符。
fn body_snippet(v: &Value) -> String { fn body_snippet(v: &Value) -> String {
let s = v.to_string(); let s = v.to_string();
truncate_chars(&s, 500) truncate_chars_ellipsis(&s, 500)
} }
// ============================================================ // ============================================================
@@ -21,7 +21,7 @@ use df_types::types::new_id;
use crate::state::{AppState, ExtractTrigger, LlmConcurrency, log_slow_lock}; 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 crate::commands::err_str;
use super::{AiSession}; use super::{AiSession};
@@ -562,7 +562,7 @@ pub(crate) async fn build_knowledge_context(
let kind = r.kind.clone(); let kind = r.kind.clone();
let title = r.title.clone(); let title = r.title.clone();
// 截断 content 防膨胀(注入侧最多 500 字符;走 audit 正典,截断时尾部补 … 提示有省略) // 截断 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.push_str(&format!("- [{}] {}: {} (复用 {} 次)\n", kind, title, snippet, r.reuse_count));
} }
out out
+2 -2
View File
@@ -30,7 +30,7 @@ use df_storage::db::Database;
use df_storage::models::KnowledgeRecord; use df_storage::models::KnowledgeRecord;
use df_types::types::new_id; 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::ai::knowledge_inject::{extract_query_keywords, spawn_embedding_for_record};
use crate::commands::knowledge_timeline::KnowledgeTimeline; use crate::commands::knowledge_timeline::KnowledgeTimeline;
use crate::commands::now_millis; use crate::commands::now_millis;
@@ -81,7 +81,7 @@ pub fn register(registry: &mut AiToolRegistry, db: &Arc<Database>) {
serde_json::json!({ serde_json::json!({
"title": k.title, "title": k.title,
"kind": k.kind, "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, "status": k.status,
"reuse_count": k.reuse_count, "reuse_count": k.reuse_count,
}) })