codex_protocol/
compacted_item.rs1use crate::models::ResponseItem;
2use crate::protocol::CompactedItem;
3use serde::Deserialize;
4
5impl<'de> Deserialize<'de> for CompactedItem {
8 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
9 where
10 D: serde::Deserializer<'de>,
11 {
12 let serialized = SerializedCompactedItem::deserialize(deserializer)?;
13 let mut window_number = serialized.window_number;
14 let window_id = match serialized.window_id {
15 Some(SerializedWindowId::Id(window_id)) => Some(window_id),
16 Some(SerializedWindowId::LegacyWindowNumber(legacy_window_number)) => {
17 window_number.get_or_insert(legacy_window_number);
18 None
19 }
20 None => None,
21 };
22 Ok(Self {
23 message: serialized.message,
24 replacement_history: serialized.replacement_history,
25 window_number,
26 first_window_id: serialized.first_window_id,
27 previous_window_id: serialized.previous_window_id,
28 window_id,
29 })
30 }
31}
32
33#[derive(Deserialize)]
34struct SerializedCompactedItem {
35 message: String,
36 #[serde(default)]
37 replacement_history: Option<Vec<ResponseItem>>,
38 #[serde(default)]
39 window_number: Option<u64>,
40 #[serde(default)]
41 first_window_id: Option<String>,
42 #[serde(default)]
43 previous_window_id: Option<String>,
44 #[serde(default)]
45 window_id: Option<SerializedWindowId>,
46}
47
48#[derive(Deserialize)]
49#[serde(untagged)]
50enum SerializedWindowId {
51 Id(String),
52 LegacyWindowNumber(u64),
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use anyhow::Result;
59 use pretty_assertions::assert_eq;
60 use serde_json::json;
61
62 #[test]
63 fn serializes_window_number_and_id() -> Result<()> {
64 let item = CompactedItem {
65 message: "summary".to_string(),
66 replacement_history: None,
67 window_number: Some(3),
68 first_window_id: Some("019b3f6e-0000-7000-8000-000000000001".to_string()),
69 previous_window_id: Some("019b3f6e-0000-7000-8000-000000000002".to_string()),
70 window_id: Some("019b3f6e-7a10-7cc3-8b6e-1d09e2f7a001".to_string()),
71 };
72
73 assert_eq!(
74 serde_json::to_value(item)?,
75 json!({
76 "message": "summary",
77 "window_number": 3,
78 "first_window_id": "019b3f6e-0000-7000-8000-000000000001",
79 "previous_window_id": "019b3f6e-0000-7000-8000-000000000002",
80 "window_id": "019b3f6e-7a10-7cc3-8b6e-1d09e2f7a001",
81 })
82 );
83 Ok(())
84 }
85
86 #[test]
87 fn migrates_legacy_numeric_window_id() -> Result<()> {
88 let item = serde_json::from_value::<CompactedItem>(json!({
89 "message": "summary",
90 "window_id": 3,
91 }))?;
92
93 assert_eq!(
94 item,
95 CompactedItem {
96 message: "summary".to_string(),
97 replacement_history: None,
98 window_number: Some(3),
99 first_window_id: None,
100 previous_window_id: None,
101 window_id: None,
102 }
103 );
104 Ok(())
105 }
106}