mirror of
https://github.com/openai/codex.git
synced 2026-11-06 20:20:34 +00:00
chore(event_mapping) handle new ide context format
This commit is contained in:
@@ -8,11 +8,17 @@ use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::protocol::ENVIRONMENT_CONTEXT_CLOSE_TAG;
|
||||
use codex_protocol::protocol::ENVIRONMENT_CONTEXT_OPEN_TAG;
|
||||
use codex_protocol::protocol::USER_IDE_CONTEXT_CLOSE_TAG;
|
||||
use codex_protocol::protocol::USER_IDE_CONTEXT_OPEN_TAG;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub(crate) fn is_user_ide_context(text: &str) -> bool {
|
||||
text.starts_with(USER_IDE_CONTEXT_OPEN_TAG) && text.ends_with(USER_IDE_CONTEXT_CLOSE_TAG)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename = "environment_context", rename_all = "snake_case")]
|
||||
pub(crate) struct EnvironmentContext {
|
||||
|
||||
@@ -13,6 +13,7 @@ use codex_protocol::user_input::UserInput;
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::environment_context::is_user_ide_context;
|
||||
use crate::user_instructions::SkillInstructions;
|
||||
use crate::user_instructions::UserInstructions;
|
||||
use crate::user_shell_command::is_user_shell_command_text;
|
||||
@@ -38,6 +39,10 @@ fn parse_user_message(message: &[ContentItem]) -> Option<UserMessageItem> {
|
||||
if is_session_prefix(text) || is_user_shell_command_text(text) {
|
||||
return None;
|
||||
}
|
||||
// user_ide_context is bundled with the user's prompt in its own content item
|
||||
if is_user_ide_context(text) {
|
||||
continue;
|
||||
}
|
||||
content.push(UserInput::Text { text: text.clone() });
|
||||
}
|
||||
ContentItem::InputImage { image_url } => {
|
||||
@@ -49,12 +54,16 @@ fn parse_user_message(message: &[ContentItem]) -> Option<UserMessageItem> {
|
||||
if is_session_prefix(text) {
|
||||
return None;
|
||||
}
|
||||
warn!("Output text in user message: {}", text);
|
||||
warn!("Output text in user message: {text}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(UserMessageItem::new(&content))
|
||||
if content.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(UserMessageItem::new(&content))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_agent_message(id: Option<&String>, message: &[ContentItem]) -> AgentMessageItem {
|
||||
@@ -131,14 +140,26 @@ mod tests {
|
||||
use super::parse_turn_item;
|
||||
use codex_protocol::items::AgentMessageContent;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::items::UserMessageItem;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ReasoningItemContent;
|
||||
use codex_protocol::models::ReasoningItemReasoningSummary;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::models::WebSearchAction;
|
||||
use codex_protocol::protocol::USER_IDE_CONTEXT_CLOSE_TAG;
|
||||
use codex_protocol::protocol::USER_IDE_CONTEXT_OPEN_TAG;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
fn assert_eq_user_message_content(actual: TurnItem, expected_content: &[UserInput]) {
|
||||
match actual {
|
||||
TurnItem::UserMessage(user) => {
|
||||
assert_eq!(user.content, expected_content);
|
||||
}
|
||||
other => panic!("expected TurnItem::UserMessage, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_user_message_with_text_and_two_images() {
|
||||
let img1 = "https://example.com/one.png".to_string();
|
||||
@@ -162,19 +183,14 @@ mod tests {
|
||||
|
||||
let turn_item = parse_turn_item(&item).expect("expected user message turn item");
|
||||
|
||||
match turn_item {
|
||||
TurnItem::UserMessage(user) => {
|
||||
let expected_content = vec![
|
||||
UserInput::Text {
|
||||
text: "Hello world".to_string(),
|
||||
},
|
||||
UserInput::Image { image_url: img1 },
|
||||
UserInput::Image { image_url: img2 },
|
||||
];
|
||||
assert_eq!(user.content, expected_content);
|
||||
}
|
||||
other => panic!("expected TurnItem::UserMessage, got {other:?}"),
|
||||
}
|
||||
let expected_content = vec![
|
||||
UserInput::Text {
|
||||
text: "Hello world".to_string(),
|
||||
},
|
||||
UserInput::Image { image_url: img1 },
|
||||
UserInput::Image { image_url: img2 },
|
||||
];
|
||||
assert_eq_user_message_content(turn_item, &expected_content);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -216,6 +232,13 @@ mod tests {
|
||||
text: "<user_shell_command>echo 42</user_shell_command>".to_string(),
|
||||
}],
|
||||
},
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: "user".to_string(),
|
||||
content: vec![ContentItem::InputText {
|
||||
text: "<user_ide_context>echo 42</user_ide_context>".to_string(),
|
||||
}],
|
||||
},
|
||||
];
|
||||
|
||||
for item in items {
|
||||
@@ -224,6 +247,33 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trims_user_ide_context_item_from_user_message() {
|
||||
let message = ResponseItem::Message {
|
||||
id: Some("user-1".to_string()),
|
||||
role: "user".to_string(),
|
||||
content: vec![
|
||||
ContentItem::InputText {
|
||||
text: format!(
|
||||
"{USER_IDE_CONTEXT_OPEN_TAG}some context{USER_IDE_CONTEXT_CLOSE_TAG}"
|
||||
),
|
||||
},
|
||||
ContentItem::InputText {
|
||||
text: "Hello world".to_string(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let turn_item = parse_turn_item(&message).expect("expected user message turn item");
|
||||
|
||||
assert_eq_user_message_content(
|
||||
turn_item,
|
||||
&[UserInput::Text {
|
||||
text: "Hello world".to_string(),
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_agent_message() {
|
||||
let item = ResponseItem::Message {
|
||||
|
||||
@@ -10,7 +10,7 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
#[serde(tag = "type")]
|
||||
#[ts(tag = "type")]
|
||||
pub enum TurnItem {
|
||||
@@ -20,26 +20,26 @@ pub enum TurnItem {
|
||||
WebSearch(WebSearchItem),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct UserMessageItem {
|
||||
pub id: String,
|
||||
pub content: Vec<UserInput>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
#[serde(tag = "type")]
|
||||
#[ts(tag = "type")]
|
||||
pub enum AgentMessageContent {
|
||||
Text { text: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct AgentMessageItem {
|
||||
pub id: String,
|
||||
pub content: Vec<AgentMessageContent>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct ReasoningItem {
|
||||
pub id: String,
|
||||
pub summary_text: Vec<String>,
|
||||
@@ -47,7 +47,7 @@ pub struct ReasoningItem {
|
||||
pub raw_content: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct WebSearchItem {
|
||||
pub id: String,
|
||||
pub query: String,
|
||||
|
||||
@@ -49,6 +49,8 @@ pub const USER_INSTRUCTIONS_OPEN_TAG: &str = "<user_instructions>";
|
||||
pub const USER_INSTRUCTIONS_CLOSE_TAG: &str = "</user_instructions>";
|
||||
pub const ENVIRONMENT_CONTEXT_OPEN_TAG: &str = "<environment_context>";
|
||||
pub const ENVIRONMENT_CONTEXT_CLOSE_TAG: &str = "</environment_context>";
|
||||
pub const USER_IDE_CONTEXT_OPEN_TAG: &str = "<user_ide_context>";
|
||||
pub const USER_IDE_CONTEXT_CLOSE_TAG: &str = "</user_ide_context>";
|
||||
pub const USER_MESSAGE_BEGIN: &str = "## My request for Codex:";
|
||||
|
||||
/// Submission Queue Entry - requests from user
|
||||
|
||||
Reference in New Issue
Block a user