From 4cb8d8679c051663c27827d3c2f15289671f864b Mon Sep 17 00:00:00 2001 From: pmccrary-oai Date: Thu, 27 Aug 2026 06:06:17 +0000 Subject: [PATCH] Forward truncation policies to the history notes backend (#41062) ## What changed - Serialize each history and notes request's output truncation policy into the `x-openai-tool-output-truncation-policy` header. - Forward the invoking tool call's policy for tool requests and use the thread hint byte limit for context-contributor requests. GitOrigin-RevId: 9d4e61480397b325efdb033861893e88c708de3b --- codex-rs/ext/history-notes/src/backend.rs | 11 +++++++++++ codex-rs/ext/history-notes/src/backend_tests.rs | 3 +++ codex-rs/ext/history-notes/src/extension.rs | 2 ++ codex-rs/ext/history-notes/src/tools.rs | 1 + 4 files changed, 17 insertions(+) diff --git a/codex-rs/ext/history-notes/src/backend.rs b/codex-rs/ext/history-notes/src/backend.rs index d874da7d5f..af8653402c 100644 --- a/codex-rs/ext/history-notes/src/backend.rs +++ b/codex-rs/ext/history-notes/src/backend.rs @@ -5,6 +5,7 @@ use codex_client::HttpTransport; use codex_client::RequestBody; use codex_login::default_client::create_client; use codex_model_provider::SharedModelProvider; +use codex_utils_output_truncation::TruncationPolicy; use http::HeaderValue; use http::Method; use serde_json::Value; @@ -12,6 +13,7 @@ use serde_json::json; const HISTORY_NOTES_BACKEND_TIMEOUT: Duration = Duration::from_secs(35); const ENCRYPTED_TOOL_ARGUMENTS_HEADER: &str = "x-openai-encrypted-tool-arguments"; +const TOOL_OUTPUT_TRUNCATION_POLICY_HEADER: &str = "x-openai-tool-output-truncation-policy"; #[derive(Clone)] pub(crate) struct HistoryNotesBackend { @@ -29,6 +31,7 @@ impl HistoryNotesBackend { session_id: &str, current_agent_name: &str, mut arguments: Value, + truncation_policy: TruncationPolicy, ) -> Result { let Some(arguments_object) = arguments.as_object_mut() else { return Err("History tool arguments must be a JSON object".to_string()); @@ -52,6 +55,14 @@ impl HistoryNotesBackend { .map_err(|error| format!("History backend auth could not be resolved: {error}"))?; let mut request = provider.build_request(Method::POST, path); + let encoded_truncation_policy = serde_json::to_string(&truncation_policy) + .map_err(|error| format!("Could not encode tool output truncation policy: {error}"))?; + request.headers.insert( + TOOL_OUTPUT_TRUNCATION_POLICY_HEADER, + HeaderValue::from_str(&encoded_truncation_policy).map_err(|error| { + format!("Invalid tool output truncation policy header: {error}") + })?, + ); if matches!( path, "alpha/history/v2/search_contents" diff --git a/codex-rs/ext/history-notes/src/backend_tests.rs b/codex-rs/ext/history-notes/src/backend_tests.rs index 31da7b7ede..bd9211ad12 100644 --- a/codex-rs/ext/history-notes/src/backend_tests.rs +++ b/codex-rs/ext/history-notes/src/backend_tests.rs @@ -3,6 +3,7 @@ use codex_login::AuthManager; use codex_login::CodexAuth; use codex_model_provider::create_model_provider; use codex_model_provider_info::ModelProviderInfo; +use codex_utils_output_truncation::TruncationPolicy; use http::HeaderMap; use http::HeaderValue; use pretty_assertions::assert_eq; @@ -56,6 +57,7 @@ async fn routes_through_codex_backend_and_injects_trusted_session_agent_context( "current_agent_name": "/root/spoofed", } }), + TruncationPolicy::Bytes(1024), ) .await .expect("History request should succeed"); @@ -129,6 +131,7 @@ async fn marks_encrypted_history_and_notes_arguments_without_changing_the_json_b "session-123", "/root", arguments.clone(), + TruncationPolicy::Bytes(1024), ) .await .expect("encrypted argument request should succeed"); diff --git a/codex-rs/ext/history-notes/src/extension.rs b/codex-rs/ext/history-notes/src/extension.rs index 069e104d9b..4d3e4e24f2 100644 --- a/codex-rs/ext/history-notes/src/extension.rs +++ b/codex-rs/ext/history-notes/src/extension.rs @@ -17,6 +17,7 @@ use codex_extension_api::ToolExecutor; use codex_login::AuthManager; use codex_model_provider::create_model_provider; use codex_protocol::AgentPath; +use codex_utils_output_truncation::TruncationPolicy; use serde_json::json; use crate::backend::HistoryNotesBackend; @@ -110,6 +111,7 @@ impl ContextContributor for HistoryNotesExtension { session_store.level_id(), &identity.agent_name, json!({}), + TruncationPolicy::Bytes(MAX_THREAD_HINT_BYTES), ) .await else { diff --git a/codex-rs/ext/history-notes/src/tools.rs b/codex-rs/ext/history-notes/src/tools.rs index 2c75581586..735269eedb 100644 --- a/codex-rs/ext/history-notes/src/tools.rs +++ b/codex-rs/ext/history-notes/src/tools.rs @@ -278,6 +278,7 @@ impl HistoryNotesTool { &self.session_id, &self.current_agent_name, arguments, + call.truncation_policy, ) .await .map_err(FunctionCallError::RespondToModel)?;