diff --git a/apps/ai-game-creator-shell/src-tauri/src/debug.rs b/apps/ai-game-creator-shell/src-tauri/src/debug.rs new file mode 100644 index 000000000..8172834ff --- /dev/null +++ b/apps/ai-game-creator-shell/src-tauri/src/debug.rs @@ -0,0 +1,3 @@ +pub(crate) mod debug_drafts; + +pub(crate) use debug_drafts::*; \ No newline at end of file diff --git a/apps/ai-game-creator-shell/src-tauri/src/debug_drafts.rs b/apps/ai-game-creator-shell/src-tauri/src/debug/debug_drafts.rs similarity index 93% rename from apps/ai-game-creator-shell/src-tauri/src/debug_drafts.rs rename to apps/ai-game-creator-shell/src-tauri/src/debug/debug_drafts.rs index 6a78cd9a3..8e0d606a3 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/debug_drafts.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/debug/debug_drafts.rs @@ -1,10 +1,12 @@ //! 调试落盘:保存 LLM 原始输出 / 失败输入,便于排查截断、空返回等问题。 //! -//! 本模块在 main.rs 用 `#[cfg(all(debug_assertions, not(test)))]` 声明——仅在开发(debug) +//! 本模块用 `#[cfg(all(debug_assertions, not(test)))]` 声明——仅在开发(debug) //! 且非测试构建中编入二进制;生产 release 与 cargo test 下整个模块与其调用处一并被剔除, //! 不会往仓库写任何文件。 -use super::*; +use std::fs; +use std::path::PathBuf; +use crate::unix_millis; // 找到仓库根(包含 apps/ai-game-creator-shell/src-tauri/Cargo.toml 的目录), // 以便把草案落到仓库内而非 tmp 项目目录。 @@ -35,7 +37,7 @@ fn repo_root() -> Option { // 把生成器原始返回(含被截断、解析失败的内容)保存到仓库 .llm-drafts/, // 便于排查 “EOF while parsing a string” 这类输出截断问题。尽力而为,不阻断主流程。 -pub(super) fn persist_snapshot(raw_content: &str) { +pub(crate) fn persist_snapshot(raw_content: &str) { let Some(repo_root) = repo_root() else { eprintln!("llm.draft.snapshot.skip: 未能定位仓库根目录"); return; @@ -64,7 +66,7 @@ pub(super) fn persist_snapshot(raw_content: &str) { // LLM 调用失败(例如返回内容为空)时,把本次发送给模型的输入(system + 完整 user prompt) // 连同错误信息一起落盘到 .llm-drafts/,便于按同样输入复现与定位。尽力而为,不阻断主流程。 -pub(super) fn persist_error_input(system_prompt: &str, user_prompt: &str, error: &str) { +pub(crate) fn persist_error_input(system_prompt: &str, user_prompt: &str, error: &str) { let Some(repo_root) = repo_root() else { eprintln!("llm.draft.error-input.skip: 未能定位仓库根目录"); return; diff --git a/apps/ai-game-creator-shell/src-tauri/src/main.rs b/apps/ai-game-creator-shell/src-tauri/src/main.rs index 360cbbad4..471d7c0df 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/main.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/main.rs @@ -34,6 +34,11 @@ use shared_contracts::game_creation_app::{ use tauri::Emitter; use tauri_plugin_opener::OpenerExt; +// 调试落盘模块(保存 LLM 原始输出 / 失败输入,排查截断、空返回等)放在 debug_drafts.rs。 +// 用 #[cfg] 编译期门控:仅开发(debug)且非测试构建编入;生产 release 与 cargo test 下整体剔除。 +#[cfg(all(debug_assertions, not(test)))] +mod debug; + #[derive(Debug, Eq, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] struct InitLocalProjectResult { @@ -1833,7 +1838,7 @@ async fn request_generator_game_draft_with_client( Err(error) => { // 调用失败(含空返回重试耗尽)时,把本次输入连同错误一并落盘,便于复现定位(仅 debug 构建)。 #[cfg(all(debug_assertions, not(test)))] - debug_drafts::persist_error_input( + debug::persist_error_input( system_prompt, user_prompt.as_str(), &error.to_string(), @@ -1844,7 +1849,7 @@ async fn request_generator_game_draft_with_client( }; // 先把原始返回落盘,再解析;解析失败(如输出截断)时仍能从仓库里拿到完整原文(仅 debug 构建)。 #[cfg(all(debug_assertions, not(test)))] - debug_drafts::persist_snapshot(response.content.as_str()); + debug::persist_snapshot(response.content.as_str()); let content = strip_llm_thinking_blocks(response.content.as_str()); parse_llm_game_draft_response(content.as_str()) } @@ -3749,11 +3754,6 @@ fn parse_llm_game_draft_response(content: &str) -> Result .map_err(|error| format!("解析 LLM 游戏草案失败:{error}")) } -// 调试落盘模块(保存 LLM 原始输出 / 失败输入,排查截断、空返回等)放在 debug_drafts.rs。 -// 用 #[cfg] 编译期门控:仅开发(debug)且非测试构建编入;生产 release 与 cargo test 下整体剔除。 -#[cfg(all(debug_assertions, not(test)))] -mod debug_drafts; - fn strip_llm_thinking_blocks(content: &str) -> String { let mut output = String::new(); let mut rest = content;