From 4fb52feececfe9facaf0d04eca47ad4e2c9bbf6f Mon Sep 17 00:00:00 2001 From: Liang-Ting Jiang Date: Fri, 24 Apr 2026 17:25:08 -0700 Subject: [PATCH] Delay auth fetch for file download materialization --- codex-rs/core/src/codex_apps_file_download.rs | 49 +++++++++++++------ codex-rs/core/src/mcp_tool_call.rs | 4 +- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/codex-rs/core/src/codex_apps_file_download.rs b/codex-rs/core/src/codex_apps_file_download.rs index 04b5a43776..526f2b8482 100644 --- a/codex-rs/core/src/codex_apps_file_download.rs +++ b/codex-rs/core/src/codex_apps_file_download.rs @@ -1,3 +1,4 @@ +use crate::session::session::Session; use crate::session::turn_context::TurnContext; use codex_api::download_openai_file; use codex_login::CodexAuth; @@ -50,9 +51,8 @@ fn should_materialize_codex_apps_file_download( } pub(crate) async fn maybe_materialize_codex_apps_file_download_result( + sess: &Session, turn_context: &TurnContext, - session_id: &str, - auth: Option<&CodexAuth>, server: &str, codex_apps_meta: Option<&JsonMap>, mut result: CallToolResult, @@ -73,12 +73,32 @@ pub(crate) async fn maybe_materialize_codex_apps_file_download_result( result.structured_content = Some(structured_content); } - let Some(auth) = auth else { + let auth = sess.services.auth_manager.auth().await; + let Some(auth) = auth.as_ref() else { warn!( "skipping codex_apps file download materialization because ChatGPT auth is unavailable" ); return result; }; + materialize_codex_apps_file_download_result_with_auth( + turn_context, + download_base_url, + &sess.conversation_id.to_string(), + auth, + payload, + result, + ) + .await +} + +async fn materialize_codex_apps_file_download_result_with_auth( + turn_context: &TurnContext, + download_base_url: &str, + session_id: &str, + auth: &CodexAuth, + payload: CodexAppsFileDownloadPayload, + mut result: CallToolResult, +) -> CallToolResult { let token_data = match auth.get_token_data() { Ok(token_data) => token_data, Err(error) => { @@ -235,15 +255,6 @@ mod tests { use wiremock::matchers::method; use wiremock::matchers::path; - fn download_materialization_meta() -> JsonMap { - serde_json::json!({ - "materialize_file_download": true, - }) - .as_object() - .cloned() - .expect("_codex_apps metadata object") - } - #[tokio::test] async fn codex_apps_file_download_materialization_adds_local_path_for_marked_tools() { let server = MockServer::start().await; @@ -282,12 +293,18 @@ mod tests { meta: None, }; - let result = maybe_materialize_codex_apps_file_download_result( + let result = materialize_codex_apps_file_download_result_with_auth( &turn_context, + turn_context.config.chatgpt_base_url.as_str(), "session-1", - Some(&CodexAuth::create_dummy_chatgpt_auth_for_testing()), - codex_mcp::CODEX_APPS_MCP_SERVER_NAME, - Some(&download_materialization_meta()), + &CodexAuth::create_dummy_chatgpt_auth_for_testing(), + serde_json::from_value( + original + .structured_content + .clone() + .expect("structured content should exist"), + ) + .expect("download payload"), original, ) .await; diff --git a/codex-rs/core/src/mcp_tool_call.rs b/codex-rs/core/src/mcp_tool_call.rs index 5b575071f6..96bd98fd84 100644 --- a/codex-rs/core/src/mcp_tool_call.rs +++ b/codex-rs/core/src/mcp_tool_call.rs @@ -549,11 +549,9 @@ async fn execute_mcp_tool_call( .call_tool(server, tool_name, rewritten_arguments, request_meta) .await .map_err(|e| format!("tool call error: {e:?}"))?; - let auth = sess.services.auth_manager.auth().await; let result = maybe_materialize_codex_apps_file_download_result( + sess, turn_context, - &sess.conversation_id.to_string(), - auth.as_ref(), server, metadata.and_then(|metadata| metadata.codex_apps_meta.as_ref()), result,