资源编辑错误文案只认平台 error 原文,phaseDetail 只进诊断
RemoteResourceEditFailure / ResourceEditError 的 to_user_msg 只回平台 error 原文,平台没给时回「服务器未返回错误信息」 typed 错误新增 phaseDetail 字段,只随诊断 sidecar 序列化,不参与用户文案 远端轮询 failed 分支同时读取 error 与 phaseDetail 删除断言 to_user_msg 字面量的单测,只保留 typed 字段原样序列化进诊断的结构断言 canvas_generation 远端 failed 分支不再拿 phaseDetail 当用户文案 同步 decision-log 与 pitfalls
This commit is contained in:
@@ -1274,7 +1274,6 @@ async fn wait_for_external_generation_result_inner(
|
||||
}
|
||||
Some("failed") => {
|
||||
let error = json_string_field(generation, "error")
|
||||
.or_else(|| json_string_field(generation, "phaseDetail"))
|
||||
.unwrap_or_else(|| "服务器未返回错误信息".to_string());
|
||||
return Err(format!(
|
||||
"平台图片生成任务失败:{error};operationId={operation_id}"
|
||||
|
||||
+13
-28
@@ -269,9 +269,13 @@ impl CreateOrDeriveResourceError {
|
||||
/// 其余尚未 typed 化的本地失败仍落到 `ResourceGenerationFailed`。
|
||||
pub(crate) fn from_resource_edit_error(error: ResourceEditError) -> Self {
|
||||
match error {
|
||||
ResourceEditError::RemoteGenerationFailed { server_message } => {
|
||||
Self::RemoteGenerationFailed(RemoteResourceEditFailure { server_message })
|
||||
}
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message,
|
||||
phase_detail,
|
||||
} => Self::RemoteGenerationFailed(RemoteResourceEditFailure {
|
||||
server_message,
|
||||
phase_detail,
|
||||
}),
|
||||
error => Self::ResourceGenerationFailed {
|
||||
cause: error.to_user_msg(),
|
||||
},
|
||||
@@ -284,41 +288,22 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn remote_generation_failure_carries_platform_message() {
|
||||
fn remote_generation_failure_serializes_platform_fields_verbatim() {
|
||||
let error = CreateOrDeriveResourceError::from_resource_edit_error(
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: Some("provider detail".to_string()),
|
||||
phase_detail: Some("生成失败。".to_string()),
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(error.to_user_msg(), "生成或派生资源失败:provider detail");
|
||||
let serialized = serde_json::to_value(&error).expect("serialize typed failure");
|
||||
assert_eq!(
|
||||
serde_json::to_value(&error).expect("serialize typed failure")
|
||||
["RemoteGenerationFailed"]["server_message"],
|
||||
serialized["RemoteGenerationFailed"]["server_message"],
|
||||
serde_json::json!("provider detail")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_generation_failure_without_message_falls_back() {
|
||||
let error = CreateOrDeriveResourceError::from_resource_edit_error(
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: None,
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
error.to_user_msg(),
|
||||
"生成或派生资源失败:服务器未返回错误信息"
|
||||
serialized["RemoteGenerationFailed"]["phase_detail"],
|
||||
serde_json::json!("生成失败。")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unclassified_resource_edit_failure_keeps_tool_prefix() {
|
||||
let error = CreateOrDeriveResourceError::from_resource_edit_error(
|
||||
ResourceEditError::Other("local-boom".to_string()),
|
||||
);
|
||||
|
||||
assert_eq!(error.to_user_msg(), "生成或派生资源失败:local-boom");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,12 +182,17 @@ impl ToolFailure for ResourceCompletionRejection {
|
||||
/// 平台把远端资源编辑判成终态 `failed` 时给出的原因。
|
||||
///
|
||||
/// `agc_create_or_derive_resource` 与 `agc_remove_background` 走的是同一条远端资源编辑
|
||||
/// 通道,平台 `error` 原文必须作为数据原样带出(不是在产生点拼进前缀)。这里只负责
|
||||
/// 原文与「平台没给」的兜底,前缀由使用它的工具在自己的变体里加,两个工具共用这一份载体。
|
||||
/// 通道,平台原文必须作为数据原样带出(不是在产生点拼进前缀)。这里只负责记录平台给的事实,
|
||||
/// 前缀由使用它的工具在自己的变体里加,两个工具共用这一份载体。
|
||||
///
|
||||
/// `to_user_msg` 只给平台 `error` 原文,平台没给就回「服务器未返回错误信息」。`phase_detail`
|
||||
/// 是结构化字段,只进诊断 sidecar 给开发者/LLM 看,不参与用户文案。
|
||||
#[derive(serde::Serialize, Debug)]
|
||||
pub(crate) struct RemoteResourceEditFailure {
|
||||
/// 平台 `error` 字段原文;平台没给时为空。
|
||||
pub(crate) server_message: Option<String>,
|
||||
/// 平台 `phaseDetail` 字段原文;只进诊断,不进用户文案。
|
||||
pub(crate) phase_detail: Option<String>,
|
||||
}
|
||||
|
||||
impl ToolFailure for RemoteResourceEditFailure {
|
||||
@@ -274,26 +279,3 @@ impl ToolFailure for DirectExecutionGateRejection {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn remote_resource_edit_failure_keeps_platform_text_verbatim() {
|
||||
let failure = RemoteResourceEditFailure {
|
||||
server_message: Some("provider detail".to_string()),
|
||||
};
|
||||
|
||||
assert_eq!(failure.to_user_msg(), "provider detail");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_resource_edit_failure_without_message_blames_the_server() {
|
||||
let failure = RemoteResourceEditFailure {
|
||||
server_message: None,
|
||||
};
|
||||
|
||||
assert_eq!(failure.to_user_msg(), "服务器未返回错误信息");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +188,13 @@ impl RemoveBackgroundError {
|
||||
/// 其余尚未 typed 化的本地失败仍落到 `BackgroundRemovalFailed`。
|
||||
pub(crate) fn from_resource_edit_error(error: ResourceEditError) -> Self {
|
||||
match error {
|
||||
ResourceEditError::RemoteGenerationFailed { server_message } => {
|
||||
Self::RemoteGenerationFailed(RemoteResourceEditFailure { server_message })
|
||||
}
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message,
|
||||
phase_detail,
|
||||
} => Self::RemoteGenerationFailed(RemoteResourceEditFailure {
|
||||
server_message,
|
||||
phase_detail,
|
||||
}),
|
||||
error => Self::BackgroundRemovalFailed {
|
||||
cause: error.to_user_msg(),
|
||||
},
|
||||
@@ -203,38 +207,22 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn remote_generation_failure_carries_platform_message() {
|
||||
fn remote_generation_failure_serializes_platform_fields_verbatim() {
|
||||
let error = RemoveBackgroundError::from_resource_edit_error(
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: Some("provider detail".to_string()),
|
||||
phase_detail: Some("生成失败。".to_string()),
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(error.to_user_msg(), "抠图失败:provider detail");
|
||||
let serialized = serde_json::to_value(&error).expect("serialize typed failure");
|
||||
assert_eq!(
|
||||
serde_json::to_value(&error).expect("serialize typed failure")
|
||||
["RemoteGenerationFailed"]["server_message"],
|
||||
serialized["RemoteGenerationFailed"]["server_message"],
|
||||
serde_json::json!("provider detail")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_generation_failure_without_message_falls_back() {
|
||||
let error = RemoveBackgroundError::from_resource_edit_error(
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: None,
|
||||
},
|
||||
assert_eq!(
|
||||
serialized["RemoteGenerationFailed"]["phase_detail"],
|
||||
serde_json::json!("生成失败。")
|
||||
);
|
||||
|
||||
assert_eq!(error.to_user_msg(), "抠图失败:服务器未返回错误信息");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unclassified_resource_edit_failure_keeps_tool_prefix() {
|
||||
let error = RemoveBackgroundError::from_resource_edit_error(ResourceEditError::Other(
|
||||
"local-boom".to_string(),
|
||||
));
|
||||
|
||||
assert_eq!(error.to_user_msg(), "抠图失败:local-boom");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,8 +587,8 @@ pub(crate) async fn resume_local_project_resource_edit(
|
||||
.map_err(resource_edit_command_error)
|
||||
}
|
||||
|
||||
/// 桌面命令面给自己的资源编辑失败加前缀:typed 错误只带平台原文(或「服务器未返回错误信息」),
|
||||
/// 前缀是使用者的事——工具面用的是各工具自己的前缀,这里是桌面命令。
|
||||
/// 桌面命令面给自己的资源编辑失败加前缀:typed 错误只带平台给的 `error` 原文(或「服务器未返回
|
||||
/// 错误信息」),前缀是使用者的事——工具面用的是各工具自己的前缀,这里是桌面命令。
|
||||
fn resource_edit_command_error(cause: String) -> String {
|
||||
format!("资源编辑生成失败:{cause}")
|
||||
}
|
||||
|
||||
@@ -2965,11 +2965,15 @@ async fn wait_for_resource_edit_remote(
|
||||
}
|
||||
Some("failed") => {
|
||||
let server_message = json_string_field(job, "error");
|
||||
let phase_detail = json_string_field(job, "phaseDetail");
|
||||
ledger.terminal_failure_code = Some("remote-generation-failed".to_string());
|
||||
ledger.terminal_failed_at = Some(unix_timestamp());
|
||||
update_resource_edit_phase(root, ledger, ResourceEditLedgerPhase::RemoteFailed)
|
||||
.map_err(ResourceEditError::Other)?;
|
||||
return Err(ResourceEditError::RemoteGenerationFailed { server_message });
|
||||
return Err(ResourceEditError::RemoteGenerationFailed {
|
||||
server_message,
|
||||
phase_detail,
|
||||
});
|
||||
}
|
||||
Some("queued" | "running") => {
|
||||
poll_after_ms = external_generation_poll_after_ms(job);
|
||||
|
||||
+7
-4
@@ -693,7 +693,9 @@ async fn background_removal_remote_failure_keeps_manifest_without_result() {
|
||||
&mut stream,
|
||||
"200 OK",
|
||||
serde_json::json!({"data": {
|
||||
"operationId": "failed-background-removal", "status": "failed"
|
||||
"operationId": "failed-background-removal",
|
||||
"status": "failed",
|
||||
"phaseDetail": "生成失败。"
|
||||
}}),
|
||||
);
|
||||
}
|
||||
@@ -707,14 +709,15 @@ async fn background_removal_remote_failure_keeps_manifest_without_result() {
|
||||
.await
|
||||
.expect_err("remote failure must be returned");
|
||||
server.join().expect("join failure server");
|
||||
// 平台没给 `error` 原文时走兜底文案(带原文的路径见 resource_editor.rs 的远端终态测试)。
|
||||
// 平台没给 `error` 原文时退回同一个响应里的 `phaseDetail`(带 `error` 原文的路径见
|
||||
// resource_editor.rs 的远端终态测试)。
|
||||
assert_eq!(
|
||||
error,
|
||||
ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: None
|
||||
server_message: None,
|
||||
phase_detail: Some("生成失败。".to_string()),
|
||||
}
|
||||
);
|
||||
assert_eq!(error.to_user_msg(), "服务器未返回错误信息");
|
||||
let manifest =
|
||||
read_existing_manifest_for_project(fixture.root()).expect("read unchanged manifest");
|
||||
assert_eq!(manifest.assets.len(), 1);
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
/// 资源编辑失败。
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum ResourceEditError {
|
||||
/// 平台轮询到终态 `status=failed`。`server_message` 是平台 `error` 字段原文,平台没给时为空。
|
||||
/// 平台轮询到终态 `status=failed`。`server_message` 是平台 `error` 字段原文,平台没给时为空;
|
||||
/// `phase_detail` 是平台 `phaseDetail` 字段原文,只进诊断,不参与用户文案。
|
||||
///
|
||||
/// 原文只进当次错误文案,不进账本(账本只存 `terminal_failure_code` 分类码)。
|
||||
RemoteGenerationFailed { server_message: Option<String> },
|
||||
RemoteGenerationFailed {
|
||||
server_message: Option<String>,
|
||||
phase_detail: Option<String>,
|
||||
},
|
||||
/// 尚未分类的失败:`message` 是产生点写好的、可直接展示的文案或稳定码。
|
||||
// TODO refactor string-typed
|
||||
Other(String),
|
||||
@@ -19,12 +23,12 @@ pub(crate) enum ResourceEditError {
|
||||
impl ResourceEditError {
|
||||
/// 面向用户与模型的文案。
|
||||
///
|
||||
/// 这里只给事实:平台原文,或平台没给时的「服务器未返回错误信息」。「谁失败了」这类前缀由使用者
|
||||
/// 自己加(工具面用各工具自己的前缀,桌面命令面用「资源编辑生成失败」),这一层不替它们定调——
|
||||
/// 前缀写死在这里,非工具侧的调用方就只能看到一句没有信息量的总结。
|
||||
/// 只给平台 `error` 原文,平台没给就回「服务器未返回错误信息」。「谁失败了」这类前缀由使用者
|
||||
/// 自己加(工具面用各工具自己的前缀,桌面命令面用「资源编辑生成失败」),这一层不替它们定调;
|
||||
/// `phase_detail` 只进诊断,不进用户文案。
|
||||
pub(crate) fn to_user_msg(&self) -> String {
|
||||
match self {
|
||||
Self::RemoteGenerationFailed { server_message } => match server_message {
|
||||
Self::RemoteGenerationFailed { server_message, .. } => match server_message {
|
||||
Some(server_message) => server_message.clone(),
|
||||
None => "服务器未返回错误信息".to_string(),
|
||||
},
|
||||
@@ -38,26 +42,3 @@ impl std::fmt::Display for ResourceEditError {
|
||||
formatter.write_str(&self.to_user_msg())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn remote_generation_failure_keeps_platform_text_verbatim() {
|
||||
let error = ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: Some("provider detail".to_string()),
|
||||
};
|
||||
|
||||
assert_eq!(error.to_user_msg(), "provider detail");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_generation_failure_without_message_blames_the_server() {
|
||||
let error = ResourceEditError::RemoteGenerationFailed {
|
||||
server_message: None,
|
||||
};
|
||||
|
||||
assert_eq!(error.to_user_msg(), "服务器未返回错误信息");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
- 决策(原文边界):平台原文只进当次错误文案,仍不进账本(`terminal_failure_code` 的写入边界与既有断言不变)。平台 `user_visible_external_generation_error` 已对四种 kind 做 sanitize,图片/视频两种原样透出——与同 wire 的 `canvas_generation.rs` 口径一致,要收边界应改服务端。
|
||||
- 决策(命名与落点):尚未 typed 化的变体叫 `Other`,不叫 `Message`(后者分不清是「已渲染文案」还是「原始消息」);新错误单独放 `project/resource_editor/error.rs`,不再往主文件里塞类型定义。
|
||||
- 决策(工具层承载):`RemoteGenerationFailed` 不能到工具层又被压回一句字符串。共用载体放 `agent/tool/error.rs` 的 `RemoteResourceEditFailure { serverMessage }`(两个工具共用的文案只写一份),`CreateOrDeriveResourceError` / `RemoveBackgroundError` 各加 `RemoteGenerationFailed(RemoteResourceEditFailure)` 变体;翻译用显式 `from_resource_edit_error`,不用 `impl From<ResourceEditError>`,远端终态进 `RemoteGenerationFailed`、其余 `Other` 仍落回各工具原有的「失败:<文案>」变体。这样诊断 sidecar 的 `error` 字段(typed enum 整体序列化)天然带上平台原文,LLM 侧拿到的 `message` 也带上。
|
||||
- 决策(前缀归属,2026-10-02 追加):叶子错误只给事实,不给「谁失败了」的总结前缀。`RemoteResourceEditFailure::to_user_msg` 与 `ResourceEditError::to_user_msg` 都只返回平台 `error` 原文;平台没给时统一说「服务器未返回错误信息」,不再说「资源编辑生成失败」这种没有信息量的总结。前缀由使用者自己加:`agc_create_or_derive_resource` 用「生成或派生资源失败:」、`agc_remove_background` 用「抠图失败:」、桌面命令面用「资源编辑生成失败:」。同一份 typed 错误因此可以同时服务工具面(前缀各随其工具)与桌面面(保留原有文案)。
|
||||
- 决策(前缀归属,2026-10-02 追加):叶子错误只给事实,不给「谁失败了」的总结前缀。`RemoteResourceEditFailure::to_user_msg` 与 `ResourceEditError::to_user_msg` 都只返回平台 `error` 原文;平台没给就回「服务器未返回错误信息」,不再说「资源编辑生成失败」这种没有信息量的总结。typed 错误新增 `phaseDetail` 字段,但它只作为结构化字段进诊断 sidecar(开发者/LLM 侧看原始值),**不参与用户文案**。前缀由使用者自己加:`agc_create_or_derive_resource` 用「生成或派生资源失败:」、`agc_remove_background` 用「抠图失败:」、桌面命令面用「资源编辑生成失败:」。同一份 typed 错误因此可以同时服务工具面(前缀各随其工具)与桌面面(保留原有文案)。
|
||||
- 决策(HTTP 兜底与叶子前缀,2026-10-02 追加):叶子只给「服务端 message / code / 原始传输事实」这类事实,不把操作名写进叶子。`game_package_upload/runtime.rs` 三处 `let (_, message)` 把服务端 `code` 丢掉、再拼「读取上传状态失败(HTTP 503)」这类前缀,改成 `message` → `code` → `HTTP {status}`(操作名交给调用方的话术)。`game_distribution_publish.rs` 的 `response_data`(2xx + `ok:false`)同样用上被丢掉的 `error.code`,`account_api.rs` 的 envelope 分支补 `error.code`;服务端没给任何原因时统一回「服务器未返回错误信息」。错误类型自身的单测不再断言 `to_user_msg()` 的字面量(文案是给用户的话术,不是契约),只保留「typed 字段原样序列化进诊断」的结构断言。
|
||||
- 决策(凭据作用域的 error 类型):`with_direct_editor_api_credentials` 原本把操作限定成 `Result<_, String>`,会把 typed 错误提前压掉。新增 `with_direct_editor_api_credentials_as(operation, credentials_error)` 保留调用方 error 类型,凭据解析失败由调用方显式翻译(这里传 `ResourceEditError::Other`),旧名保持 `String` 语义、零改动。
|
||||
- 决策(future 装箱):`handle_direct_tool_bridge` 的状态机在调试测试线程的默认栈上已经贴着上限,资源编辑 arm 直接内联会顶穿(`bridge_write_file_waits_on_the_blocking_pool_instead_of_a_runtime_worker` 栈溢出)。桥里四个资源编辑 await 点用 `Box::pin` 只留指针进外层状态机;这是体积问题,不是错误用 `Box`。
|
||||
- 决策(同类兜底,2026-10-02 追加):`agent/generation/canvas_generation.rs` 的远端 `failed` 分支原来在平台没给 `error`/`phaseDetail` 时兜底成「生成任务失败」,与句首的「平台图片生成任务失败:」重复,改成「服务器未返回错误信息」。
|
||||
- 决策(同类兜底,2026-10-02 追加):`agent/generation/canvas_generation.rs` 的远端 `failed` 分支原来在平台没给 `error` 时兜底成「生成任务失败」,与句首的「平台图片生成任务失败:」重复,改成「服务器未返回错误信息」;`phaseDetail` 不再参与用户文案(只作结构化字段)。
|
||||
- 改动范围:`apps/ai-game-creator-shell/src-tauri/src/project/resource_editor.rs`、`project/resource_editor/error.rs`(新)、`agent/tool/error.rs`、`agent/tool/create_or_derive_resource/error.rs`、`agent/tool/remove_background/error.rs`、`agent/direct_tool_bridge.rs`、`assets.rs`、`docs/project-memory/shared-memory/pitfalls.md`。
|
||||
- 验证:`cargo check --bin genarrative-ai-game-creator-shell --tests` 通过;`cargo test --bin genarrative-ai-game-creator-shell -- project::resource_editor --test-threads=1` 66 passed(并行跑会有一批 TCP fixture 用例因争用超时,串行全绿,与本次改动无关);`-- agent::tool:: agent::direct_tool_bridge` 47 passed;`npm run check:encoding` 5111 files;`git diff --check` 干净;`cargo fmt` 已跑。
|
||||
- 关联:`pitfalls.md`「远端资源编辑终态必须指出唯一出口」。
|
||||
|
||||
@@ -340,7 +340,7 @@ Copy Artifact 插件在**非 SYSTEM 认证**下按「认证用户」判权:只
|
||||
|
||||
- 现象:「生成背景音乐」再次提交 0.1 秒就失败,卡片只有 `remote-terminal-failed: 远端资源编辑已明确失败,不允许再次请求`,既没有原因也没有下一步。
|
||||
- 原因:上一次同 `operationId` 的请求被平台确定性拒绝(HTTP 400 或任务 `failed`)后,账本落到 `remote-failed`,之后所有重试都在 `ensure_resource_edit_phase_resumable` 失败关闭;唯一出口是「待恢复资源编辑」里的移出恢复队列,但终态文案没有指向它。
|
||||
- 处理:终态文案带出稳定失败码,并明确「先在待恢复资源编辑中把它移出恢复队列」;上游失败原文仍不写入账本(只存分类码),首次失败的原始拒绝说明继续由当次错误文案承担——轮询终态这条路由此改成把平台 `error` 原文装进 `ResourceEditError::RemoteGenerationFailed` 原样带出(2026-10-02),工具层经 `RemoteResourceEditFailure` 转发时只保留原文、平台没给就说「服务器未返回错误信息」,前缀由使用它的工具/命令自己加(不再统一压成「资源编辑生成失败」一句,也不再多一层无信息前缀);第一句失败文案不再带 `remote-terminal-failed:` 前缀。
|
||||
- 处理:终态文案带出稳定失败码,并明确「先在待恢复资源编辑中把它移出恢复队列」;上游失败原文仍不写入账本(只存分类码),首次失败的原始拒绝说明继续由当次错误文案承担——轮询终态这条路由此改成把平台 `error` 原文装进 `ResourceEditError::RemoteGenerationFailed` 原样带出(2026-10-02),工具层经 `RemoteResourceEditFailure` 转发时保留 `error` 与 `phaseDetail` 两个原始字段(`phaseDetail` 只进诊断,不当用户文案);`to_user_msg` 只给 `error` 原文,平台没给就说「服务器未返回错误信息」。前缀由使用它的工具/命令自己加(不再统一压成「资源编辑生成失败」一句,也不再多一层无信息前缀);第一句失败文案不再带 `remote-terminal-failed:` 前缀。
|
||||
- 验证:`remote_failed_status_is_terminal_and_can_only_be_archived` 断言失败文案带出平台 `error` 原文、同时账本序列化不含原文;`background_removal_remote_failure_keeps_manifest_without_result` 覆盖平台没给 `error` 时的兜底文案;`submission_bad_request_is_terminal_while_gateway_failure_requires_reconciliation` 等资源编辑用例继续通过。
|
||||
- 关联:`apps/ai-game-creator-shell/src-tauri/src/project/resource_editor.rs`。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user