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
This commit is contained in:
pmccrary-oai
2026-08-27 06:06:17 +00:00
committed by copyberry
parent d5caceccb1
commit 4cb8d8679c
4 changed files with 17 additions and 0 deletions

View File

@@ -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<Value, String> {
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"

View File

@@ -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");

View File

@@ -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 {

View File

@@ -278,6 +278,7 @@ impl HistoryNotesTool {
&self.session_id,
&self.current_agent_name,
arguments,
call.truncation_policy,
)
.await
.map_err(FunctionCallError::RespondToModel)?;