mirror of
https://github.com/openai/codex.git
synced 2026-11-03 08:22:30 +00:00
Include originating item IDs in MCP request metadata (#40866)
## What changed - Add the originating Responses item ID to MCP tool request metadata as `_meta.itemId`. - Preserve the initiating `exec` item ID across code-mode cells so nested MCP calls carry the same origin. ## Testing - Cover metadata generation for direct and code-mode MCP tool calls. GitOrigin-RevId: 1161cac64f1cc3a6d4dac4368e63804bd9d2c417
This commit is contained in:
1 parent
74772623db
commit
f5420174da
9 files changed
+175
-49
No files matched your search
@@ -7,6 +7,7 @@ use codex_code_mode::CodeModeNestedToolCall;
|
||||
use codex_code_mode::CodeModeSessionDelegate;
|
||||
use codex_code_mode::NotificationFuture;
|
||||
use codex_code_mode::ToolInvocationFuture;
|
||||
use codex_protocol::ResponseItemId;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use serde_json::Value as JsonValue;
|
||||
@@ -24,7 +25,13 @@ use crate::tools::parallel::ToolCallRuntime;
|
||||
pub(super) struct CodeModeDispatchBroker {
|
||||
dispatch_tx: async_channel::Sender<DispatchMessage>,
|
||||
dispatch_rx: async_channel::Receiver<DispatchMessage>,
|
||||
dispatch_gates: Arc<Mutex<HashMap<CellId, watch::Sender<bool>>>>,
|
||||
dispatch_gates: Arc<Mutex<HashMap<CellId, CellDispatchGate>>>,
|
||||
}
|
||||
|
||||
struct CellDispatchGate {
|
||||
ready: watch::Sender<bool>,
|
||||
// Keep the original exec item when later waits resume this cell.
|
||||
originating_item_id: Option<ResponseItemId>,
|
||||
}
|
||||
|
||||
impl CodeModeDispatchBroker {
|
||||
@@ -37,8 +44,34 @@ impl CodeModeDispatchBroker {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn mark_cell_ready_for_dispatch(&self, cell_id: &CellId) {
|
||||
dispatch_gate(&self.dispatch_gates, cell_id).send_replace(true);
|
||||
pub(super) fn mark_cell_ready_for_dispatch(
|
||||
&self,
|
||||
cell_id: &CellId,
|
||||
originating_item_id: Option<ResponseItemId>,
|
||||
) {
|
||||
let ready = {
|
||||
let mut dispatch_gates = self
|
||||
.dispatch_gates
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let gate = dispatch_gates
|
||||
.entry(cell_id.clone())
|
||||
.or_insert_with(|| CellDispatchGate {
|
||||
ready: watch::channel(false).0,
|
||||
originating_item_id: None,
|
||||
});
|
||||
gate.originating_item_id = originating_item_id;
|
||||
gate.ready.clone()
|
||||
};
|
||||
ready.send_replace(true);
|
||||
}
|
||||
|
||||
pub(super) fn cell_originating_item_id(&self, cell_id: &CellId) -> Option<ResponseItemId> {
|
||||
self.dispatch_gates
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.get(cell_id)
|
||||
.and_then(|gate| gate.originating_item_id.clone())
|
||||
}
|
||||
|
||||
pub(super) fn close_cell(&self, cell_id: &CellId) {
|
||||
@@ -135,7 +168,7 @@ impl CodeModeDispatchBroker {
|
||||
}
|
||||
|
||||
fn dispatch_gate(
|
||||
dispatch_gates: &Mutex<HashMap<CellId, watch::Sender<bool>>>,
|
||||
dispatch_gates: &Mutex<HashMap<CellId, CellDispatchGate>>,
|
||||
cell_id: &CellId,
|
||||
) -> watch::Sender<bool> {
|
||||
let mut dispatch_gates = match dispatch_gates.lock() {
|
||||
@@ -144,12 +177,16 @@ fn dispatch_gate(
|
||||
};
|
||||
dispatch_gates
|
||||
.entry(cell_id.clone())
|
||||
.or_insert_with(|| watch::channel(false).0)
|
||||
.or_insert_with(|| CellDispatchGate {
|
||||
ready: watch::channel(false).0,
|
||||
originating_item_id: None,
|
||||
})
|
||||
.ready
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn remove_dispatch_gate(
|
||||
dispatch_gates: &Mutex<HashMap<CellId, watch::Sender<bool>>>,
|
||||
dispatch_gates: &Mutex<HashMap<CellId, CellDispatchGate>>,
|
||||
cell_id: &CellId,
|
||||
) {
|
||||
let mut dispatch_gates = match dispatch_gates.lock() {
|
||||
@@ -160,7 +197,7 @@ fn remove_dispatch_gate(
|
||||
}
|
||||
|
||||
async fn wait_until_cell_ready_for_dispatch(
|
||||
dispatch_gates: &Mutex<HashMap<CellId, watch::Sender<bool>>>,
|
||||
dispatch_gates: &Mutex<HashMap<CellId, CellDispatchGate>>,
|
||||
cell_id: &CellId,
|
||||
cancellation_token: &CancellationToken,
|
||||
) -> bool {
|
||||
|
||||
@@ -35,6 +35,7 @@ impl CodeModeExecuteHandler {
|
||||
session: std::sync::Arc<crate::session::session::Session>,
|
||||
turn: std::sync::Arc<crate::session::turn_context::TurnContext>,
|
||||
call_id: String,
|
||||
originating_item_id: Option<codex_protocol::ResponseItemId>,
|
||||
code: String,
|
||||
telemetry: &mut CodeModeToolCallGuard,
|
||||
) -> Result<FunctionToolOutput, FunctionCallError> {
|
||||
@@ -103,7 +104,7 @@ impl CodeModeExecuteHandler {
|
||||
exec.session
|
||||
.services
|
||||
.code_mode_service
|
||||
.mark_cell_ready_for_dispatch(&cell_id);
|
||||
.mark_cell_ready_for_dispatch(&cell_id, originating_item_id);
|
||||
let response = started_cell
|
||||
.initial_response()
|
||||
.await
|
||||
@@ -155,6 +156,7 @@ impl CodeModeExecuteHandler {
|
||||
&self,
|
||||
invocation: ToolInvocation,
|
||||
) -> Result<Box<dyn crate::tools::context::ToolOutput>, FunctionCallError> {
|
||||
let originating_item_id = invocation.originating_item_id().await;
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
@@ -174,7 +176,14 @@ impl CodeModeExecuteHandler {
|
||||
);
|
||||
let result = match payload {
|
||||
ToolPayload::Custom { input } if is_exec_tool_name(&tool_name) => self
|
||||
.execute(session, turn, call_id, input, &mut telemetry)
|
||||
.execute(
|
||||
session,
|
||||
turn,
|
||||
call_id,
|
||||
originating_item_id,
|
||||
input,
|
||||
&mut telemetry,
|
||||
)
|
||||
.await
|
||||
.map(boxed_tool_output),
|
||||
_ => Err(FunctionCallError::RespondToModel(format!(
|
||||
|
||||
@@ -176,8 +176,20 @@ impl CodeModeService {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mark_cell_ready_for_dispatch(&self, cell_id: &codex_code_mode::CellId) {
|
||||
self.dispatch_broker.mark_cell_ready_for_dispatch(cell_id);
|
||||
pub(crate) fn mark_cell_ready_for_dispatch(
|
||||
&self,
|
||||
cell_id: &codex_code_mode::CellId,
|
||||
originating_item_id: Option<codex_protocol::ResponseItemId>,
|
||||
) {
|
||||
self.dispatch_broker
|
||||
.mark_cell_ready_for_dispatch(cell_id, originating_item_id);
|
||||
}
|
||||
|
||||
pub(crate) fn cell_originating_item_id(
|
||||
&self,
|
||||
cell_id: &codex_code_mode::CellId,
|
||||
) -> Option<codex_protocol::ResponseItemId> {
|
||||
self.dispatch_broker.cell_originating_item_id(cell_id)
|
||||
}
|
||||
|
||||
pub(crate) fn finish_cell_dispatch(&self, cell_id: &CellId) {
|
||||
|
||||
Reference in new issue
Block a user