mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Preserve user input when MCP startup is interrupted (#34839)
## Why Interrupting a turn while MCP tools were still starting could abort before the submitted user input was recorded in conversation history. ## What changed - Build and retain the MCP tool list and tool router as part of each step snapshot, using the turn cancellation token during tool discovery. - Record turn hooks and submitted input when cancellation occurs during startup prewarming, pre-sampling compaction, or first-step capture. - Reuse the captured router for sampling, compaction, and prompt debugging so advertised and executable tools share the same request-scoped view. ## Testing Add coverage that interrupts each affected MCP startup phase and verifies that the user prompt remains in history before the turn-aborted marker. GitOrigin-RevId: 6e96c6814357a55545d69b580e28f35933cfadf7
This commit is contained in:
1 parent
bd5b55e403
commit
d7e8f4c3dc
21 files changed
+359
-174
No files matched your search
@@ -4,13 +4,12 @@ use crate::agents_md::LoadedAgentsMd;
|
||||
use crate::environment_selection::TurnEnvironmentSnapshot;
|
||||
use crate::session::McpRuntimeSnapshot;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::router::ToolRouter;
|
||||
use codex_exec_server::ExecutorCapabilityDiscoverySnapshot;
|
||||
use codex_exec_server::ResolvedSelectedCapabilityRoot;
|
||||
use codex_mcp::ToolInfo;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
/// Request-scoped state that may change between model sampling requests.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct StepContext {
|
||||
pub(crate) turn: Arc<TurnContext>,
|
||||
pub(crate) environments: TurnEnvironmentSnapshot,
|
||||
@@ -21,34 +20,9 @@ pub(crate) struct StepContext {
|
||||
/// The exact MCP config and manager used to advertise and execute tools for this step.
|
||||
pub(crate) mcp: Arc<McpRuntimeSnapshot>,
|
||||
/// The fixed MCP tool list used for this exact sampling request.
|
||||
mcp_tool_snapshot: OnceCell<Vec<ToolInfo>>,
|
||||
pub(crate) mcp_tools: Vec<ToolInfo>,
|
||||
/// The finalized tool plan advertised and executed for this exact sampling request.
|
||||
pub(crate) tool_router: Arc<ToolRouter>,
|
||||
/// The canonical AGENTS.md value observed with this environment snapshot.
|
||||
pub(crate) loaded_agents_md: Option<Arc<LoadedAgentsMd>>,
|
||||
}
|
||||
|
||||
impl StepContext {
|
||||
pub(crate) fn new(
|
||||
turn: Arc<TurnContext>,
|
||||
environments: TurnEnvironmentSnapshot,
|
||||
selected_capability_roots: Vec<ResolvedSelectedCapabilityRoot>,
|
||||
executor_capability_discovery: Option<Arc<ExecutorCapabilityDiscoverySnapshot>>,
|
||||
mcp: Arc<McpRuntimeSnapshot>,
|
||||
loaded_agents_md: Option<Arc<LoadedAgentsMd>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
turn,
|
||||
environments,
|
||||
selected_capability_roots,
|
||||
executor_capability_discovery,
|
||||
mcp,
|
||||
mcp_tool_snapshot: OnceCell::new(),
|
||||
loaded_agents_md,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn mcp_tools(&self) -> &[ToolInfo] {
|
||||
self.mcp_tool_snapshot
|
||||
.get_or_init(|| self.mcp.manager().list_all_tools())
|
||||
.await
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user