From da7c4dc71c2cf4cabb532436ead0c7302759a41b Mon Sep 17 00:00:00 2001 From: kdletters Date: Wed, 12 Aug 2026 22:24:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3Agent=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E5=9B=9E=E5=BD=92=E8=AF=AD=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将流式连接中断断言为 Runtime 失败 禁止 transport 错误提交 planning fallback 冒充成功 保留安全失败消息与 final-reply-failed 审计验证 --- .../src-tauri/src/tests/response_stream.rs | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/tests/response_stream.rs b/apps/ai-game-creator-shell/src-tauri/src/tests/response_stream.rs index b9d345fde..0dd733f80 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/tests/response_stream.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/tests/response_stream.rs @@ -617,7 +617,8 @@ async fn response_stream_private_process_output_is_never_published_or_committed_ } #[tokio::test] -async fn response_stream_final_failure_with_retry_disabled_commits_planning_fallback() { +async fn response_stream_final_disconnect_with_retry_disabled_fails_without_committing_planning_fallback( +) { let root = unique_project_path(); init_local_game_project_at( &root, @@ -686,32 +687,28 @@ async fn response_stream_final_failure_with_retry_disabled_commits_planning_fall ); drop(finalization_lock); - let completed = wait_for_agent_runtime_idle(&root, "design-director"); - assert_eq!(completed.phase, "completed"); - assert_eq!(completed.last_response.as_deref(), Some(planning_fallback)); - let committed = wait_for_response_stream_status( - &root, - "design-director", - run_id, - "committed", - ready.sequence.saturating_add(1), - ); - assert_eq!(committed.accumulated_text, planning_fallback); + let failed = wait_for_agent_runtime_phase(&root, "design-director", "failed"); + assert_eq!(failed.status, "failed"); + assert!(failed + .error + .as_deref() + .is_some_and(|error| error.contains("kind=transport"))); + assert_eq!(failed.last_response, None); let conversation = read_local_conversation_for_session_at( &root, Some("design-director"), Some(&started.state.session_id), ) - .expect("read committed fallback conversation"); - assert_eq!( - conversation - .messages - .iter() - .filter(|message| message.role == "assistant") - .map(|message| message.content.as_str()) - .collect::>(), - vec![planning_fallback] - ); + .expect("read failed final stream conversation"); + let assistant_messages = conversation + .messages + .iter() + .filter(|message| message.role == "assistant") + .map(|message| message.content.as_str()) + .collect::>(); + assert_eq!(assistant_messages.len(), 1); + assert_ne!(assistant_messages[0], planning_fallback); + assert!(assistant_messages[0].contains("失败")); let requests = mock.stop_and_collect(); assert_eq!( @@ -760,12 +757,11 @@ async fn response_stream_final_failure_with_retry_disabled_commits_planning_fall final_lifecycle[0]["requestSlot"], final_lifecycle[1]["requestSlot"] ); - assert_response_stream_completion_event_details( - &root, - "design-director", - run_id, - planning_fallback, - ); + assert!(read_agent_db_records_for_test(&root).iter().any(|record| { + record["recordType"] == "agent.runtime.background_task.failed" + && record["runId"] == run_id + && record["failureKind"] == "final-reply-failed" + })); assert_response_stream_public_surfaces_exclude(&root, "design-director", &[planning_fallback]); fs::remove_dir_all(root).ok();