Merge remote-tracking branch 'origin/rhan/escalations-approvals-sandbox' into rhan/approval-source1

# Conflicts:
#	codex-rs/core/src/codex.rs
This commit is contained in:
Roy Han
2026-03-23 12:07:00 -07:00
3 changed files with 82 additions and 87 deletions

View File

@@ -216,7 +216,6 @@ fn formatted_input_preserves_message_metadata_id_when_disabled() {
}],
metadata: Some(ResponseItemMessageMetadata {
user_message_type: Some(UserMessageType::Prompt),
sandbox_policy: None,
metadata_id: "2585a800-7d93-4f52-8648-d9cb39f413d2".to_string(),
}),
end_turn: None,
@@ -252,7 +251,6 @@ fn formatted_input_preserves_existing_message_metadata_id() {
}],
metadata: Some(ResponseItemMessageMetadata {
user_message_type: Some(UserMessageType::Prompt),
sandbox_policy: None,
metadata_id: "2585a800-7d93-4f52-8648-d9cb39f413d2".to_string(),
}),
end_turn: None,

View File

@@ -83,6 +83,11 @@ use codex_protocol::config_types::Settings;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::dynamic_tools::DynamicToolResponse;
use codex_protocol::dynamic_tools::DynamicToolSpec;
use codex_protocol::item_metadata::response_item_tool_call_id;
use codex_protocol::item_metadata::stamp_message_metadata_on_input_item;
use codex_protocol::item_metadata::stamp_tool_metadata_on_response_item;
use codex_protocol::item_metadata::tool_call_metadata_or_default;
use codex_protocol::item_metadata::user_message_metadata_patch;
use codex_protocol::items::PlanItem;
use codex_protocol::items::TurnItem;
use codex_protocol::items::UserMessageItem;
@@ -1007,35 +1012,6 @@ fn local_time_context() -> (String, String) {
}
}
fn stamp_message_metadata_on_input_item(
item: &mut ResponseInputItem,
patch: &ResponseItemMessageMetadata,
) {
let ResponseInputItem::Message { role, metadata, .. } = item else {
return;
};
if role != "user" {
return;
}
match metadata {
Some(existing) => {
if patch.user_message_type.is_some() {
existing.user_message_type = patch.user_message_type.clone();
}
}
None => {
*metadata = Some(patch.clone());
}
}
}
fn user_message_metadata_patch(kind: UserMessageType) -> ResponseItemMessageMetadata {
ResponseItemMessageMetadata {
user_message_type: Some(kind),
..ResponseItemMessageMetadata::new(/*user_message_type*/ None)
}
}
fn approval_source_for_turn(turn_context: &TurnContext) -> ApprovalSourceMetadata {
if routes_approval_to_guardian(turn_context) {
ApprovalSourceMetadata::Guardian
@@ -1043,57 +1019,6 @@ fn approval_source_for_turn(turn_context: &TurnContext) -> ApprovalSourceMetadat
ApprovalSourceMetadata::User
}
}
fn response_item_tool_call_id(item: &ResponseItem) -> Option<&str> {
match item {
ResponseItem::LocalShellCall {
call_id: Some(call_id),
..
} => Some(call_id),
ResponseItem::FunctionCall { call_id, .. } => Some(call_id),
ResponseItem::CustomToolCall { call_id, .. } => Some(call_id),
_ => None,
}
}
fn tool_call_metadata_slot_mut(
item: &mut ResponseItem,
) -> Option<&mut Option<ResponseItemMetadata>> {
match item {
ResponseItem::LocalShellCall { metadata, .. }
| ResponseItem::FunctionCall { metadata, .. }
| ResponseItem::CustomToolCall { metadata, .. } => Some(metadata),
_ => None,
}
}
fn stamp_tool_metadata_on_response_item(
mut item: ResponseItem,
patch: ResponseItemMetadata,
) -> ResponseItem {
if patch.is_empty() {
return item;
}
let Some(metadata_slot) = tool_call_metadata_slot_mut(&mut item) else {
return item;
};
let mut metadata = metadata_slot.take().unwrap_or_default();
metadata.merge_from(patch);
*metadata_slot = (!metadata.is_empty()).then_some(metadata);
item
}
fn tool_call_metadata_or_default(item: &ResponseItem) -> Option<ResponseItemMetadata> {
match item {
ResponseItem::LocalShellCall { metadata, .. }
| ResponseItem::FunctionCall { metadata, .. }
| ResponseItem::CustomToolCall { metadata, .. } => {
Some(metadata.clone().unwrap_or_default())
}
_ => None,
}
}
#[derive(Clone, Debug, Default)]
struct ToolApprovalMetadataSnapshot {
approval_outcomes_by_call_id: HashMap<String, ApprovalOutcomeMetadata>,

View File

@@ -1,17 +1,89 @@
use crate::models::ResponseInputItem;
use crate::models::ResponseItem;
use crate::models::ResponseItemMessageMetadata;
use crate::models::ResponseItemMetadata;
use crate::models::UserMessageType;
pub fn stamp_user_message_type_on_input_item(item: &mut ResponseInputItem, kind: UserMessageType) {
let metadata = user_message_metadata_patch(kind);
stamp_message_metadata_on_input_item(item, &metadata);
}
pub fn stamp_message_metadata_on_input_item(
item: &mut ResponseInputItem,
patch: &ResponseItemMessageMetadata,
) {
let ResponseInputItem::Message { role, metadata, .. } = item else {
return;
};
if role != "user" {
return;
}
let mut metadata_value = metadata
.take()
.unwrap_or_else(|| ResponseItemMessageMetadata::new(/*user_message_type*/ None));
metadata_value.user_message_type = Some(kind);
*metadata = Some(metadata_value);
match metadata {
Some(existing) => {
if patch.user_message_type.is_some() {
existing.user_message_type = patch.user_message_type.clone();
}
}
None => {
*metadata = Some(patch.clone());
}
}
}
pub fn user_message_metadata_patch(kind: UserMessageType) -> ResponseItemMessageMetadata {
ResponseItemMessageMetadata {
user_message_type: Some(kind),
..ResponseItemMessageMetadata::new(/*user_message_type*/ None)
}
}
pub fn response_item_tool_call_id(item: &ResponseItem) -> Option<&str> {
match item {
ResponseItem::LocalShellCall {
call_id: Some(call_id),
..
} => Some(call_id),
ResponseItem::FunctionCall { call_id, .. } => Some(call_id),
ResponseItem::CustomToolCall { call_id, .. } => Some(call_id),
_ => None,
}
}
fn tool_call_metadata_slot_mut(
item: &mut ResponseItem,
) -> Option<&mut Option<ResponseItemMetadata>> {
match item {
ResponseItem::LocalShellCall { metadata, .. }
| ResponseItem::FunctionCall { metadata, .. }
| ResponseItem::CustomToolCall { metadata, .. } => Some(metadata),
_ => None,
}
}
pub fn tool_call_metadata_or_default(item: &ResponseItem) -> Option<ResponseItemMetadata> {
match item {
ResponseItem::LocalShellCall { metadata, .. }
| ResponseItem::FunctionCall { metadata, .. }
| ResponseItem::CustomToolCall { metadata, .. } => {
Some(metadata.clone().unwrap_or_default())
}
_ => None,
}
}
pub fn stamp_tool_metadata_on_response_item(
mut item: ResponseItem,
patch: ResponseItemMetadata,
) -> ResponseItem {
if patch.is_empty() {
return item;
}
let Some(metadata_slot) = tool_call_metadata_slot_mut(&mut item) else {
return item;
};
let mut metadata = metadata_slot.take().unwrap_or_default();
metadata.merge_from(patch);
*metadata_slot = (!metadata.is_empty()).then_some(metadata);
item
}