未登记资源指引抽到 tool/error.rs,生成与抠图共用同一份文案

- UNREGISTERED_SOURCE_HINT 从 create_or_derive_resource/error.rs 移到公共 tool/error.rs
- remove_background 的 SourceAssetNotRegistered 改为拼接同一常量,去掉逐字复制的副本
- 两个工具的 SourceAssetNotRegistered 文案字面不变(前缀各自保留「生成或派生资源失败:」/「抠图失败:」)
- remove_background/error.rs 一处 format! 收口改动使该 match 触发 rustfmt 重排,随该文件一并 rustfmt(只此一个文件,其余文件未动)

验证:cargo fmt --all --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --check 通过
This commit is contained in:
2026-10-01 16:44:25 +08:00
parent 6a1973b0e3
commit 3c2dc57c57
3 changed files with 30 additions and 28 deletions
@@ -5,13 +5,9 @@
use crate::agent::direct_tool_bridge::DirectResourceGenerationKind;
use crate::agent::tool::error::{
ProjectManifestRejection, ProjectPermissionRejection, ResourceCompletionRejection,
ToolArgumentsRejection, ToolFailure,
ToolArgumentsRejection, ToolFailure, UNREGISTERED_SOURCE_HINT,
};
/// `sourceLocalAssetId` 不在当前项目 manifest 时的完整指引:模型要知道下一步做什么,
/// 只报「不属于已登记资源」会让它原地重试。
const UNREGISTERED_SOURCE_HINT: &str = "先调用 agc_list_registered_assets 选择已有 localAssetId;若目标图片只在项目里,先用 agc_list_project_files 确认它 assetImportable=true,再用 agc_import_account_assets.localPaths 登记后重试。";
/// `agc_create_or_derive_resource` 的每一种失败各占一个变体;文案写在这里,捕获处只调
/// `to_user_msg`。
#[derive(serde::Serialize, Debug)]
@@ -6,6 +6,12 @@
use serde_json::Value;
/// `sourceLocalAssetId` 不在当前项目 manifest 时的完整指引:模型要知道下一步做什么,
/// 只报「不属于已登记资源」会让它原地重试。
///
/// 生成/派生与抠图都会命中这个 case,指引只在这里写一份。
pub(crate) const UNREGISTERED_SOURCE_HINT: &str = "先调用 agc_list_registered_assets 选择已有 localAssetId;若目标图片只在项目里,先用 agc_list_project_files 确认它 assetImportable=true,再用 agc_import_account_assets.localPaths 登记后重试。";
/// 工具失败对用户(以及转述给用户的模型)说的那一句话。
pub(crate) trait ToolFailure: serde::Serialize {
fn to_user_msg(&self) -> String;
@@ -4,7 +4,7 @@
use crate::agent::tool::error::{
ProjectManifestRejection, ProjectPermissionRejection, ResourceCompletionRejection,
ToolArgumentsRejection, ToolFailure,
ToolArgumentsRejection, ToolFailure, UNREGISTERED_SOURCE_HINT,
};
/// `agc_remove_background` 的每一种失败各占一个变体;文案写在这里,捕获处只调
@@ -71,9 +71,7 @@ impl ToolFailure for RemoveBackgroundError {
Self::PermissionDenied(rejection) => rejection.to_user_msg(),
Self::Manifest(rejection) => rejection.to_user_msg(),
Self::Completion(rejection) => rejection.to_user_msg(),
Self::SourceLocalAssetIdEmpty => {
"抠图失败:sourceLocalAssetId 不能为空。".to_string()
}
Self::SourceLocalAssetIdEmpty => "抠图失败:sourceLocalAssetId 不能为空。".to_string(),
Self::SourceLocalAssetIdTooLong {
got_chars,
max_chars,
@@ -83,39 +81,41 @@ impl ToolFailure for RemoveBackgroundError {
Self::SourceLocalAssetIdHasControlCharacters => {
"抠图失败:sourceLocalAssetId 含有控制字符。".to_string()
}
Self::SourceLocalAssetIdNotText { got } => format!(
"抠图失败:sourceLocalAssetId 必须是字符串,当前是「{got}」。"
),
Self::SourceLocalAssetIdNotText { got } => {
format!("抠图失败:sourceLocalAssetId 必须是字符串,当前是「{got}」。")
}
Self::AssetNameEmpty => "抠图失败:assetName 不能为空。".to_string(),
Self::AssetNameTooLong {
got_chars,
max_chars,
} => format!("抠图失败:assetName 有 {got_chars} 个字符,超过上限 {max_chars}。"),
Self::AssetNameHasControlCharacters => {
"抠图失败:assetName 含有控制字符。".to_string()
}
Self::AssetNameHasControlCharacters => "抠图失败:assetName 含有控制字符。".to_string(),
Self::AssetNameNotText { got } => {
format!("抠图失败:assetName 必须是字符串,当前是「{got}」。")
}
Self::BackgroundModeNotText { got } => format!(
"抠图失败:backgroundMode 必须是 complex 或 flat,当前是「{got}」。"
),
Self::BackgroundModeNotText { got } => {
format!("抠图失败:backgroundMode 必须是 complex 或 flat,当前是「{got}」。")
}
Self::BackgroundModeUnsupported { got } => {
format!("抠图失败:backgroundMode「{got}」不受支持,只能是 complex 或 flat。")
}
Self::ScreenColorNotText { got } => format!(
"抠图失败:screenColor 必须是 auto 或 #RRGGBB,当前是「{got}」。"
),
Self::ScreenColorMalformed { got } => format!(
"抠图失败:screenColor「{got}」不是受支持的取值,必须是 auto 或 #RRGGBB。"
),
Self::ScreenColorNotText { got } => {
format!("抠图失败:screenColor 必须是 auto 或 #RRGGBB,当前是「{got}」。")
}
Self::ScreenColorMalformed { got } => {
format!("抠图失败:screenColor「{got}」不是受支持的取值,必须是 auto 或 #RRGGBB。")
}
Self::ScreenColorRequiresFlatMode => {
"抠图失败:complex 模式不能传 screenColor。".to_string()
}
Self::SourceAssetNotRegistered => "抠图失败:sourceLocalAssetId 不是当前项目已登记资源。先调用 agc_list_registered_assets 选择已有 localAssetId;若目标图片只在项目里,先用 agc_list_project_files 确认它 assetImportable=true,再用 agc_import_account_assets.localPaths 登记后重试。".to_string(),
Self::SourceNotImage { media_type } => format!(
"抠图失败:抠图工具只接受当前项目已登记的图片资源,该资源是 {media_type}。"
),
Self::SourceAssetNotRegistered => {
format!(
"抠图失败:sourceLocalAssetId 不是当前项目已登记资源。{UNREGISTERED_SOURCE_HINT}"
)
}
Self::SourceNotImage { media_type } => {
format!("抠图失败:抠图工具只接受当前项目已登记的图片资源,该资源是 {media_type}。")
}
Self::CredentialsUnavailable { cause } => {
format!("抠图失败:无法取得平台凭据,未发起抠图:{cause}")
}