mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Preserve executor context for MCP stop hooks (#40012)
## What changed - Scope executor-provided stop-hook calls to the MCP server environment that registered the hook, and reject calls when that environment does not match. - Forward turn metadata with executor stop-hook requests while retaining the hook call's `threadId` metadata. ## Testing - Cover environment matching for MCP tool calls and verify executor stop hooks receive their environment ID and request metadata. GitOrigin-RevId: b544ea3a6ca1f61389fb4597978ed7aac27d529a
This commit is contained in:
committed by
copyberry
parent
8b5beea5c0
commit
ab8768306f
@@ -833,8 +833,8 @@ impl CodexThread {
|
||||
.services
|
||||
.mcp_runtime
|
||||
.latest_call_tool(
|
||||
server, tool, arguments, meta, /*requested_timeout*/ None,
|
||||
/*wait_for_server*/ true,
|
||||
server, tool, /*environment_id*/ None, arguments, meta,
|
||||
/*requested_timeout*/ None, /*wait_for_server*/ true,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -18,13 +18,20 @@ pub(crate) struct CoreHookMcpExecutor {
|
||||
impl HookMcpExecutor for CoreHookMcpExecutor {
|
||||
fn execute(&self, call: HookMcpCall) -> BoxFuture<'_, anyhow::Result<String>> {
|
||||
async move {
|
||||
let mut metadata = call.metadata.unwrap_or_default();
|
||||
metadata.insert(
|
||||
"threadId".to_string(),
|
||||
Value::String(self.thread_id.to_string()),
|
||||
);
|
||||
|
||||
let result = self
|
||||
.runtime
|
||||
.latest_call_tool(
|
||||
&call.server,
|
||||
&call.tool,
|
||||
call.environment_id.as_deref(),
|
||||
Some(Value::Object(call.input)),
|
||||
Some(serde_json::json!({ "threadId": self.thread_id.to_string() })),
|
||||
Some(Value::Object(metadata)),
|
||||
Some(call.timeout),
|
||||
/*wait_for_server*/ false,
|
||||
)
|
||||
|
||||
@@ -57,6 +57,7 @@ use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::sandboxing::PermissionRequestPayload;
|
||||
use crate::turn_metadata::McpTurnMetadataContext;
|
||||
|
||||
pub(crate) struct HookRuntimeOutcome {
|
||||
pub should_stop: bool,
|
||||
@@ -356,6 +357,18 @@ pub(crate) async fn run_turn_stop_hooks(
|
||||
SessionSource::SubAgent(_) => return StopOutcome::default(),
|
||||
_ => (StopHookTarget::Stop, sess.hook_transcript_path().await),
|
||||
};
|
||||
let request_metadata = turn_context
|
||||
.turn_metadata_state
|
||||
.current_meta_value_for_mcp_request(McpTurnMetadataContext {
|
||||
model: step_context.model_info.slug.as_str(),
|
||||
reasoning_effort: step_context.reasoning_effort.clone(),
|
||||
})
|
||||
.map(|turn_metadata| {
|
||||
serde_json::Map::from_iter([(
|
||||
crate::X_CODEX_TURN_METADATA_HEADER.to_string(),
|
||||
turn_metadata,
|
||||
)])
|
||||
});
|
||||
let request = codex_hooks::StopRequest {
|
||||
session_id: sess.session_id().into(),
|
||||
turn_id: turn_context.sub_id.clone(),
|
||||
@@ -364,6 +377,7 @@ pub(crate) async fn run_turn_stop_hooks(
|
||||
transcript_path,
|
||||
model: turn_context.model_info.slug.clone(),
|
||||
permission_mode: hook_permission_mode(turn_context),
|
||||
request_metadata,
|
||||
stop_hook_active,
|
||||
last_assistant_message,
|
||||
target,
|
||||
|
||||
@@ -3635,6 +3635,7 @@ impl Session {
|
||||
.latest_call_tool(
|
||||
"notes",
|
||||
"thread_hint",
|
||||
/*environment_id*/ None,
|
||||
/*arguments*/ None,
|
||||
Some(serde_json::json!({
|
||||
"threadId": self.thread_id().to_string(),
|
||||
|
||||
Reference in New Issue
Block a user