use serde::Deserialize; use serde::Serialize; use codex_protocol::models::ContentItem; use codex_protocol::models::ResponseItem; use codex_protocol::protocol::USER_INSTRUCTIONS_CLOSE_TAG; use codex_protocol::protocol::USER_INSTRUCTIONS_OPEN_TAG; /// Wraps user instructions in a tag so the model can classify them easily. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename = "user_instructions", rename_all = "snake_case")] pub(crate) struct UserInstructions { text: String, } impl UserInstructions { pub fn new>(text: T) -> Self { Self { text: text.into() } } /// Serializes the user instructions to an XML-like tagged block that starts /// with so clients can classify it. pub fn serialize_to_xml(self) -> String { format!( "{USER_INSTRUCTIONS_OPEN_TAG}\n\n{}\n\n{USER_INSTRUCTIONS_CLOSE_TAG}", self.text ) } } impl From for ResponseItem { fn from(ui: UserInstructions) -> Self { ResponseItem::Message { id: None, role: "user".to_string(), content: vec![ContentItem::InputText { text: ui.serialize_to_xml(), }], } } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename = "developer_instructions", rename_all = "snake_case")] pub(crate) struct DeveloperInstructions { text: String, } impl DeveloperInstructions { pub fn new>(text: T) -> Self { Self { text: text.into() } } pub fn into_text(self) -> String { self.text } } impl From for ResponseItem { fn from(di: DeveloperInstructions) -> Self { ResponseItem::Message { id: None, role: "developer".to_string(), content: vec![ContentItem::InputText { text: di.into_text(), }], } } }