diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs index bb509ec4d..670ecc567 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs @@ -2149,11 +2149,6 @@ impl CodexAppServerConnection { .await .map_err(platform_llm::LlmError::Transport)?; } - append_direct_project_history_item_at( - history_root, - &direct_project_user_message_item(current_prompt), - ) - .map_err(platform_llm::LlmError::InvalidRequest)?; } let prompt = if self.inner.workspace_mode.uses_direct_conversation() { direct_codex_user_prompt(&request) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_project_history.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_project_history.rs index edad7c9c8..e51c425ae 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_project_history.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_project_history.rs @@ -9,6 +9,28 @@ use std::io::{BufRead, BufReader, Read, Seek, SeekFrom}; use std::path::{Path, PathBuf}; const DIRECT_PROJECT_HISTORY_RECORD_TYPE: &str = "response_item"; +const DIRECT_PROJECT_INTERNAL_CONTEXT_KINDS: &[&str] = &[ + "host_skills.instructions", + "permissions.instructions", + "environments.environment_context", +]; + +pub(crate) fn is_direct_project_internal_context_item(item: &Value) -> bool { + if matches!( + item.get("role").and_then(Value::as_str), + Some("developer" | "system") + ) { + return true; + } + item.pointer("/internal_chat_message_metadata_passthrough/content_item_kinds") + .and_then(Value::as_array) + .is_some_and(|kinds| { + kinds + .iter() + .filter_map(Value::as_str) + .any(|kind| DIRECT_PROJECT_INTERNAL_CONTEXT_KINDS.contains(&kind)) + }) +} fn history_path(root: &Path) -> PathBuf { root.join(".agent/conversations/project.jsonl") @@ -113,6 +135,9 @@ pub(crate) fn append_direct_project_history_item_at( item: &Value, ) -> Result<(), String> { enforce_project_permission_policy(root, "conversation.write")?; + if is_direct_project_internal_context_item(item) { + return Ok(()); + } let _project_lock = crate::project::acquire_project_write_lock(root, "conversation.write")?; let path = history_path(root); prepare_game_creator_private_path_for_read(&path, false, "DirectProject 历史")?; @@ -154,14 +179,6 @@ pub(crate) fn direct_project_local_message_item( Ok(item) } -pub(crate) fn direct_project_user_message_item(prompt: &str) -> Value { - serde_json::json!({ - "type": "message", - "role": "user", - "content": [{"type": "input_text", "text": prompt}], - }) -} - pub(crate) fn read_direct_project_history_items_at(root: &Path) -> Result, String> { let path = history_path(root); if !prepare_game_creator_private_path_for_read(&path, false, "DirectProject 历史")? { @@ -204,6 +221,9 @@ pub(crate) fn read_direct_project_history_items_at(root: &Path) -> Result"}] + }))); + assert!(is_direct_project_internal_context_item(&json!({ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": ""}], + "internal_chat_message_metadata_passthrough": { + "content_item_kinds": ["environments.environment_context"] + } + }))); + assert!(!is_direct_project_internal_context_item(&json!({ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "ls ui"}], + "internal_chat_message_metadata_passthrough": { + "content_item_kinds": ["user.text"] + } + }))); + } +}