mirror of
https://github.com/openai/codex.git
synced 2026-11-01 19:33:35 +00:00
Include session id in MCP turn metadata
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
co-authored by
Codex
parent
fb816b1322
commit
e84f54294a
@@ -1285,6 +1285,7 @@ impl Session {
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn make_turn_context(
|
||||
conversation_id: ThreadId,
|
||||
auth_manager: Option<Arc<AuthManager>>,
|
||||
session_telemetry: &SessionTelemetry,
|
||||
provider: ModelProviderInfo,
|
||||
@@ -1335,6 +1336,7 @@ impl Session {
|
||||
|
||||
let cwd = session_configuration.cwd.clone();
|
||||
let turn_metadata_state = Arc::new(TurnMetadataState::new(
|
||||
conversation_id.to_string(),
|
||||
sub_id.clone(),
|
||||
cwd.clone(),
|
||||
session_configuration.sandbox_policy.get(),
|
||||
@@ -2391,6 +2393,7 @@ impl Session {
|
||||
.skills_for_config(&per_turn_config),
|
||||
);
|
||||
let mut turn_context: TurnContext = Self::make_turn_context(
|
||||
self.conversation_id,
|
||||
Some(Arc::clone(&self.services.auth_manager)),
|
||||
&self.services.session_telemetry,
|
||||
session_configuration.provider.clone(),
|
||||
@@ -5217,6 +5220,7 @@ async fn spawn_review_thread(
|
||||
let per_turn_config = Arc::new(per_turn_config);
|
||||
let review_turn_id = sub_id.to_string();
|
||||
let turn_metadata_state = Arc::new(TurnMetadataState::new(
|
||||
sess.conversation_id.to_string(),
|
||||
review_turn_id.clone(),
|
||||
parent_turn_context.cwd.clone(),
|
||||
parent_turn_context.sandbox_policy.get(),
|
||||
|
||||
@@ -2513,6 +2513,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
|
||||
let skills_outcome = Arc::new(services.skills_manager.skills_for_config(&per_turn_config));
|
||||
let turn_context = Session::make_turn_context(
|
||||
conversation_id,
|
||||
Some(Arc::clone(&auth_manager)),
|
||||
&session_telemetry,
|
||||
session_configuration.provider.clone(),
|
||||
@@ -3307,6 +3308,7 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx(
|
||||
|
||||
let skills_outcome = Arc::new(services.skills_manager.skills_for_config(&per_turn_config));
|
||||
let turn_context = Arc::new(Session::make_turn_context(
|
||||
conversation_id,
|
||||
Some(Arc::clone(&auth_manager)),
|
||||
&session_telemetry,
|
||||
session_configuration.provider.clone(),
|
||||
|
||||
@@ -441,7 +441,14 @@ fn sanitize_mcp_tool_result_for_model_preserves_image_when_supported() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn mcp_tool_call_request_meta_includes_turn_metadata_for_custom_server() {
|
||||
let (_session, turn_context) = make_session_and_context().await;
|
||||
let (_, turn_context) = make_session_and_context().await;
|
||||
let expected_turn_metadata = serde_json::from_str::<serde_json::Value>(
|
||||
&turn_context
|
||||
.turn_metadata_state
|
||||
.current_header_value()
|
||||
.expect("turn metadata header"),
|
||||
)
|
||||
.expect("turn metadata json");
|
||||
|
||||
let meta =
|
||||
build_mcp_tool_call_request_meta(&turn_context, "custom_server", /*metadata*/ None)
|
||||
@@ -450,17 +457,21 @@ async fn mcp_tool_call_request_meta_includes_turn_metadata_for_custom_server() {
|
||||
assert_eq!(
|
||||
meta,
|
||||
serde_json::json!({
|
||||
crate::X_CODEX_TURN_METADATA_HEADER: {
|
||||
"turn_id": turn_context.sub_id,
|
||||
"sandbox": "workspace-write",
|
||||
},
|
||||
crate::X_CODEX_TURN_METADATA_HEADER: expected_turn_metadata,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn codex_apps_tool_call_request_meta_includes_turn_metadata_and_codex_apps_meta() {
|
||||
let (_session, turn_context) = make_session_and_context().await;
|
||||
let (_, turn_context) = make_session_and_context().await;
|
||||
let expected_turn_metadata = serde_json::from_str::<serde_json::Value>(
|
||||
&turn_context
|
||||
.turn_metadata_state
|
||||
.current_header_value()
|
||||
.expect("turn metadata header"),
|
||||
)
|
||||
.expect("turn metadata json");
|
||||
let metadata = McpToolApprovalMetadata {
|
||||
annotations: None,
|
||||
connector_id: Some("calendar".to_string()),
|
||||
@@ -487,10 +498,7 @@ async fn codex_apps_tool_call_request_meta_includes_turn_metadata_and_codex_apps
|
||||
Some(&metadata),
|
||||
),
|
||||
Some(serde_json::json!({
|
||||
crate::X_CODEX_TURN_METADATA_HEADER: {
|
||||
"turn_id": turn_context.sub_id,
|
||||
"sandbox": "workspace-write",
|
||||
},
|
||||
crate::X_CODEX_TURN_METADATA_HEADER: expected_turn_metadata,
|
||||
MCP_TOOL_CODEX_APPS_META_KEY: {
|
||||
"resource_uri": "connector://calendar/tools/calendar_create_event",
|
||||
"contains_mcp_source": true,
|
||||
|
||||
@@ -53,6 +53,8 @@ impl From<WorkspaceGitMetadata> for TurnMetadataWorkspace {
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Default)]
|
||||
pub(crate) struct TurnMetadataBag {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
session_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
turn_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||
@@ -68,6 +70,7 @@ impl TurnMetadataBag {
|
||||
}
|
||||
|
||||
fn build_turn_metadata_bag(
|
||||
session_id: Option<String>,
|
||||
turn_id: Option<String>,
|
||||
sandbox: Option<String>,
|
||||
repo_root: Option<String>,
|
||||
@@ -81,6 +84,7 @@ fn build_turn_metadata_bag(
|
||||
}
|
||||
|
||||
TurnMetadataBag {
|
||||
session_id,
|
||||
turn_id,
|
||||
workspaces,
|
||||
sandbox,
|
||||
@@ -104,6 +108,7 @@ pub async fn build_turn_metadata_header(cwd: &Path, sandbox: Option<&str>) -> Op
|
||||
}
|
||||
|
||||
build_turn_metadata_bag(
|
||||
/*session_id*/ None,
|
||||
/*turn_id*/ None,
|
||||
sandbox.map(ToString::to_string),
|
||||
repo_root,
|
||||
@@ -128,6 +133,7 @@ pub(crate) struct TurnMetadataState {
|
||||
|
||||
impl TurnMetadataState {
|
||||
pub(crate) fn new(
|
||||
session_id: String,
|
||||
turn_id: String,
|
||||
cwd: PathBuf,
|
||||
sandbox_policy: &SandboxPolicy,
|
||||
@@ -136,6 +142,7 @@ impl TurnMetadataState {
|
||||
let repo_root = get_git_repo_root(&cwd).map(|root| root.to_string_lossy().into_owned());
|
||||
let sandbox = Some(sandbox_tag(sandbox_policy, windows_sandbox_level).to_string());
|
||||
let base_metadata = build_turn_metadata_bag(
|
||||
Some(session_id),
|
||||
Some(turn_id),
|
||||
sandbox,
|
||||
/*repo_root*/ None,
|
||||
@@ -194,6 +201,7 @@ impl TurnMetadataState {
|
||||
};
|
||||
|
||||
let enriched_metadata = build_turn_metadata_bag(
|
||||
state.base_metadata.session_id.clone(),
|
||||
state.base_metadata.turn_id.clone(),
|
||||
state.base_metadata.sandbox.clone(),
|
||||
Some(repo_root),
|
||||
|
||||
@@ -67,6 +67,7 @@ fn turn_metadata_state_uses_platform_sandbox_tag() {
|
||||
let sandbox_policy = SandboxPolicy::new_read_only_policy();
|
||||
|
||||
let state = TurnMetadataState::new(
|
||||
"session-a".to_string(),
|
||||
"turn-a".to_string(),
|
||||
cwd,
|
||||
&sandbox_policy,
|
||||
@@ -76,7 +77,9 @@ fn turn_metadata_state_uses_platform_sandbox_tag() {
|
||||
let header = state.current_header_value().expect("header");
|
||||
let json: Value = serde_json::from_str(&header).expect("json");
|
||||
let sandbox_name = json.get("sandbox").and_then(Value::as_str);
|
||||
let session_id = json.get("session_id").and_then(Value::as_str);
|
||||
|
||||
let expected_sandbox = sandbox_tag(&sandbox_policy, WindowsSandboxLevel::Disabled);
|
||||
assert_eq!(sandbox_name, Some(expected_sandbox));
|
||||
assert_eq!(session_id, Some("session-a"));
|
||||
}
|
||||
|
||||
@@ -446,6 +446,10 @@ async fn tool_search_returns_deferred_tools_without_follow_up_tool_injection() -
|
||||
"connector_id": "calendar",
|
||||
}))
|
||||
);
|
||||
assert_eq!(
|
||||
apps_tool_call.pointer("/params/_meta/x-codex-turn-metadata/session_id"),
|
||||
Some(&json!(test.session_configured.session_id.to_string()))
|
||||
);
|
||||
assert!(
|
||||
apps_tool_call
|
||||
.pointer("/params/_meta/x-codex-turn-metadata/turn_id")
|
||||
|
||||
Reference in New Issue
Block a user