From 2dbbf7245008ae264e4e392ed7b89cc6a75fdd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sat, 3 Oct 2026 10:59:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=A4=B1=E8=B4=A5=E6=94=B9=E6=8C=89=20typed?= =?UTF-8?q?=20kind=20=E5=88=A4=E5=AE=9A=E9=80=9A=E9=81=93=E6=96=AD?= =?UTF-8?q?=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - direct_codex_error_code 原来对 ModelCallFailed 一律按宿主原文子串分类,ModelCallKind::TransportBroken 只有在原文恰好含 transport closed / 连接已关闭 时才会标成 transport-closed - 改为先看 payload.kind:TransportBroken 直接给 transport-closed,其余 kind 仍按原文兜底(TODO 文本判据) - 补用例 model_call_transport_broken_is_classified_from_the_typed_kind:原文不含任何分类标记,也只可能由 typed kind 得出该 code --- .../src-tauri/src/agent/direct_runtime/mod.rs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime/mod.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime/mod.rs index b915c5ece..92d4a2c47 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime/mod.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_runtime/mod.rs @@ -2012,11 +2012,17 @@ fn direct_codex_error_code(failure: &TurnError) -> &'static str { Deadline::TurnHardLimit => "turn-hard-timeout", }, TurnError::TransportClosed(_) => "transport-closed", + // typed 分类优先于文本判据:通道断开的原文不一定带 "transport closed", + // 不能让分类结果取决于宿主换了哪句 Display。 + TurnError::ModelCallFailed(payload) => match payload.kind { + ModelCallKind::TransportBroken => "transport-closed", + // 其余 kind 还没有专属 code,仍按宿主原文兜底(TODO(文本判据))。 + _ => classify_direct_codex_error(&payload.detail), + }, // 产生层还没有 typed 出口:按宿主原文分类(TODO(文本判据))。 TurnError::ProjectRootUnanchored(_) | TurnError::EnvironmentNotReady(_) | TurnError::HostStateUnavailable(_) - | TurnError::ModelCallFailed(_) | TurnError::TurnInterrupted(_) | TurnError::ReviewRequired { .. } | TurnError::RepairRequired { .. } => { @@ -7417,6 +7423,22 @@ mod tests { assert!(!diagnostic.contains("provider.example")); } + /// typed 分类优先于文本判据:`ModelCallKind::TransportBroken` 的原文里没有 + /// `transport closed` / `连接已关闭`,也要标成 `transport-closed`。 + #[test] + fn model_call_transport_broken_is_classified_from_the_typed_kind() { + let parent = tempfile::tempdir().expect("temp dir"); + let root = parent.path().join("project"); + init_local_game_project_at(&root, "direct-diagnostic", "直连诊断").expect("init project"); + let error = TurnError::from_model_call(&LlmError::Transport( + "宿主自己写的收场说明,不含分类标记".to_string(), + )); + + let text = record_direct_codex_failure(&root, &error, None); + + assert!(text.contains("code=transport-closed"), "{text}"); + } + #[test] fn direct_failure_diagnostic_marks_project_history_shape_failure_as_not_retryable() { let parent = tempfile::tempdir().expect("temp dir");