diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/import_account_assets/error.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/import_account_assets/error.rs index 732829122..64e7a2f3b 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/tool/import_account_assets/error.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/tool/import_account_assets/error.rs @@ -112,8 +112,12 @@ impl ToolFailure for ImportAccountAssetsError { Self::NoImportSource => { "登记素材失败:至少提供一个非空的 assetIds 或 localPaths 数组。".to_string() } - Self::ImportFailed { report } => format!("登记素材失败:{report}"), - Self::ImportPartial { report } => format!("登记素材部分成功:{report}"), + Self::ImportFailed { report } => { + format!("登记素材失败:{}", import_report_message(report)) + } + Self::ImportPartial { report } => { + format!("登记素材部分成功:{}", import_report_message(report)) + } } } @@ -124,3 +128,29 @@ impl ToolFailure for ImportAccountAssetsError { } } } + +/// 逐项导入结果写进消息时的字符上限。 +/// +/// 完整 `report` 仍留在 typed 错误里(诊断 sidecar 落的是原文),这里只收口给模型/用户 +/// 看的那一句话。 +const IMPORT_REPORT_MESSAGE_MAX_CHARS: usize = 4_000; + +/// 把逐项导入结果压成一句话:先报成功/失败计数,再附有界 JSON 明细。 +fn import_report_message(report: &Value) -> String { + let imported = report + .get("imported") + .and_then(Value::as_array) + .map_or(0, |items| items.len()); + let failures = report + .get("failures") + .and_then(Value::as_array) + .map_or(0, |items| items.len()); + // TODO(工具设计):这里仍把整份 report 序列化进消息,只是按字符数收口兜底。正确方向是让 + // 工具自己做选择性返回——消息只带计数 + 可操作的失败项;或允许把完整报告重定向到文件/ + // 诊断日志,消息里只留引用,避免几十 KB 的逐项结果挤占模型上下文。 + let detail = crate::agent::redaction::truncate_agent_runtime_text( + &report.to_string(), + IMPORT_REPORT_MESSAGE_MAX_CHARS, + ); + format!("成功 {imported} 项、失败 {failures} 项:{detail}") +}