mirror of
https://github.com/openai/codex.git
synced 2026-11-09 00:39:32 +00:00
Harden Code Mode tool-call completeness tracking (#44472)
## Why Reused call IDs, ambiguous exec/wait associations, and missing history can make tool-call completeness claims unreliable. Truncating one cell's recorded calls should also preserve completeness for unrelated cells. ## What changed - Track observed call and runtime cell IDs with bounded memory, including call IDs from initial history, and withhold completeness when evidence is missing or ambiguous. - Validate exec/wait input-output associations and keep invalidated completeness from returning on retries. Withhold wait completeness after resume or fork, where runtime cell IDs can be reused. - Keep truncation markers and omission counts local to each output, clearing completeness across the affected cell while preserving unrelated cells within the metadata budget. - Refresh recording enablement from runtime configuration without changing execution features, and preserve the live recorder during legacy configuration reloads. ## Testing Add regression coverage for reused IDs, compaction, resumed waits, mismatched wrappers, runtime recording changes, and metadata budgeting that preserves unrelated complete calls. GitOrigin-RevId: 0bc85964bee079879620ec0664eea530a13b61fb
This commit is contained in:
1 parent
b348fc2667
commit
03f014564d
12 files changed
+1792
-658
No files matched your search
@@ -1932,6 +1932,11 @@ impl Session {
|
||||
}
|
||||
|
||||
pub(crate) async fn refresh_runtime_config(&self, next_config: Config) {
|
||||
self.refresh_runtime_config_inner(next_config, /*refresh_recording*/ true)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn refresh_runtime_config_inner(&self, next_config: Config, refresh_recording: bool) {
|
||||
// Refresh only the user layer from the incoming snapshot. Preserve thread-local
|
||||
// layers such as request/session overrides that were present when this session
|
||||
// was created.
|
||||
@@ -1950,6 +1955,13 @@ impl Session {
|
||||
config.mcp_servers = next_config.mcp_servers.clone();
|
||||
config.mcp_optional_startup_grace = next_config.mcp_optional_startup_grace;
|
||||
config.mcp_oauth_credentials_store_mode = next_config.mcp_oauth_credentials_store_mode;
|
||||
// Recording can follow rollout changes without changing the session's
|
||||
// execution features (including Code Mode's dispatch gate).
|
||||
if refresh_recording {
|
||||
self.services
|
||||
.executed_tool_calls
|
||||
.refresh(&next_config.features);
|
||||
}
|
||||
if let Err(err) = config.features.set_enabled(
|
||||
Feature::Mcp20260728,
|
||||
next_config.features.enabled(Feature::Mcp20260728),
|
||||
@@ -2144,7 +2156,10 @@ impl Session {
|
||||
};
|
||||
self.services.skills_service.clear_cache();
|
||||
self.services.plugins_manager.clear_cache();
|
||||
self.refresh_runtime_config(next_config).await;
|
||||
// This legacy snapshot still has the original execution features, not
|
||||
// the host's latest rollout settings. Leave the live recorder alone.
|
||||
self.refresh_runtime_config_inner(next_config, /*refresh_recording*/ false)
|
||||
.await;
|
||||
}
|
||||
|
||||
/// Record a terminal CodexErr before the app-server completion notification is reduced.
|
||||
|
||||
@@ -1478,7 +1478,10 @@ impl Session {
|
||||
}).await;
|
||||
}
|
||||
|
||||
let executed_tool_calls = crate::state::ExecutedToolCalls::new(&config.features);
|
||||
let executed_tool_calls = crate::state::ExecutedToolCalls::new(
|
||||
&config.features,
|
||||
&initial_history,
|
||||
);
|
||||
let services = SessionServices {
|
||||
// Start with an empty connection set. The initialized set is
|
||||
// published after SessionConfigured so MCP events follow it.
|
||||
|
||||
@@ -6592,7 +6592,8 @@ 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 = crate::state::ExecutedToolCalls::new(&config.features);
|
||||
let executed_tool_calls =
|
||||
crate::state::ExecutedToolCalls::new(&config.features, &InitialHistory::Forked(Vec::new()));
|
||||
let (hooks, async_hook_results) = Hooks::new(
|
||||
HooksConfig {
|
||||
legacy_notify_argv: config.notify.clone(),
|
||||
@@ -8764,7 +8765,8 @@ 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 = crate::state::ExecutedToolCalls::new(&config.features);
|
||||
let executed_tool_calls =
|
||||
crate::state::ExecutedToolCalls::new(&config.features, &InitialHistory::Forked(Vec::new()));
|
||||
let (hooks, async_hook_results) = Hooks::new(
|
||||
HooksConfig {
|
||||
legacy_notify_argv: config.notify.clone(),
|
||||
|
||||
Reference in new issue
Block a user