Encapsulate executed tool call metadata recording (#44002)

## What changed

Introduce `ExecutedToolCalls` to own optional shared recorder state and centralize feature checks, call recording, and accepted result source lookup. Update session, tool runtime, MCP, and Code Mode callers to use this interface.

Move prompt attachment, retry handling, and metadata budgeting into the `request_metadata` module, preserving existing recording and request behavior.

## Testing

Add coverage for all session and turn feature combinations, lazy result source lookup, and unchanged prompts when recording is disabled. Retain the existing metadata budget and cell completeness tests in the new module.

GitOrigin-RevId: bc19f34317232b6599c7ec71c15db4a80123ff6f
This commit is contained in:
ningyi-oai authored and copyberry committed 2026-09-09 02:33:17 +00:00
1 parent b831057106
commit 0d46c252b3
16 files changed
+450 -299

No files matched your search

+1 -4
View File
@@ -1470,10 +1470,7 @@ impl Session {
}).await;
}
let executed_tool_calls = config
.features
.enabled(Feature::ExecutedToolCallMetadata)
.then(|| Arc::new(crate::state::ExecutedToolCallRecorder::default()));
let executed_tool_calls = crate::state::ExecutedToolCalls::new(&config.features);
let services = SessionServices {
// Start with an empty connection set. The initialized set is
// published after SessionConfigured so MCP events follow it.
+2 -8
View File
@@ -6544,10 +6544,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
));
let network_approval = Arc::new(NetworkApprovalService::default());
let mcp_runtime = Arc::new(codex_mcp::McpRuntime::empty(config.prefix_mcp_tool_names()));
let executed_tool_calls = config
.features
.enabled(Feature::ExecutedToolCallMetadata)
.then(|| Arc::new(crate::state::ExecutedToolCallRecorder::default()));
let executed_tool_calls = crate::state::ExecutedToolCalls::new(&config.features);
let (hooks, async_hook_results) = Hooks::new(
HooksConfig {
legacy_notify_argv: config.notify.clone(),
@@ -8855,10 +8852,7 @@ where
));
let network_approval = Arc::new(NetworkApprovalService::default());
let mcp_runtime = Arc::new(codex_mcp::McpRuntime::empty(config.prefix_mcp_tool_names()));
let executed_tool_calls = config
.features
.enabled(Feature::ExecutedToolCallMetadata)
.then(|| Arc::new(crate::state::ExecutedToolCallRecorder::default()));
let executed_tool_calls = crate::state::ExecutedToolCalls::new(&config.features);
let (hooks, async_hook_results) = Hooks::new(
HooksConfig {
legacy_notify_argv: config.notify.clone(),
+3 -6
View File
@@ -1460,12 +1460,9 @@ async fn run_sampling_request(
.for_prompt(&step_context.settings.model_info.input_modalities)
};
let mut prompt_input = prompt_input;
if let Some(executed_tool_calls) = sess.services.executed_tool_calls.as_ref()
&& executed_tool_calls
.attach_pending_to_prompt(&mut prompt_input, &mut executed_tool_calls_by_output)
{
codex_protocol::models::bound_executed_tool_calls_for_prompt(&mut prompt_input);
}
sess.services
.executed_tool_calls
.attach_to_prompt(&mut prompt_input, &mut executed_tool_calls_by_output);
let prompt = build_prompt(
prompt_input,
step_context.as_ref(),