mirror of
https://github.com/openai/codex.git
synced 2026-10-27 18:48:37 +00:00
## What changed - Define `SleepItem` in `codex-extension-items` and carry `clock.sleep` events through `TurnItem::Extension`. - Preserve sleep persistence, thread-history reconstruction, and the app-server's `type: "sleep"` schema while reusing the extension-owned type. ## Testing - Add serialization coverage for the `clock.sleep` extension wire shape and its protocol wrapper. - Update sleep lifecycle and thread-history tests to exercise the extension-owned item. GitOrigin-RevId: 34bb33ed9b90a09bf4744aafdb56e019c717a168
130 lines
3.4 KiB
Rust
130 lines
3.4 KiB
Rust
use pretty_assertions::assert_eq;
|
|
use serde_json::json;
|
|
|
|
use super::ExtensionItem;
|
|
use super::image_generation::ImageGenerationItem;
|
|
use super::sleep::SleepItem;
|
|
use super::web_search::WebSearchAction;
|
|
use super::web_search::WebSearchItem;
|
|
|
|
fn completed_image_generation_item() -> ExtensionItem {
|
|
ExtensionItem::ImageGeneration(ImageGenerationItem {
|
|
id: "image-1".to_string(),
|
|
status: "completed".to_string(),
|
|
revised_prompt: Some("A blue square".to_string()),
|
|
result: "cG5n".to_string(),
|
|
saved_path: None,
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn image_generation_item_preserves_stable_wire_shape() {
|
|
let item = completed_image_generation_item();
|
|
let value = serde_json::to_value(&item).expect("serialize extension item");
|
|
|
|
assert_eq!(
|
|
value,
|
|
json!({
|
|
"kind": "image_gen.generation",
|
|
"id": "image-1",
|
|
"status": "completed",
|
|
"revisedPrompt": "A blue square",
|
|
"result": "cG5n",
|
|
})
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_value::<ExtensionItem>(value).expect("deserialize extension item"),
|
|
item
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn web_search_item_preserves_stable_wire_shape() {
|
|
let item = ExtensionItem::WebSearch(WebSearchItem {
|
|
id: "search-1".to_string(),
|
|
query: "docs".to_string(),
|
|
action: Some(WebSearchAction::Search {
|
|
query: Some("docs".to_string()),
|
|
queries: None,
|
|
}),
|
|
results: None,
|
|
});
|
|
let value = serde_json::to_value(&item).expect("serialize extension item");
|
|
|
|
assert_eq!(
|
|
value,
|
|
json!({
|
|
"kind": "web.search",
|
|
"id": "search-1",
|
|
"query": "docs",
|
|
"action": {
|
|
"type": "search",
|
|
"query": "docs",
|
|
"queries": null,
|
|
},
|
|
"results": null,
|
|
})
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_value::<ExtensionItem>(value).expect("deserialize extension item"),
|
|
item
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_value::<ExtensionItem>(json!({
|
|
"kind": "web.search",
|
|
"id": "search-1",
|
|
"query": "docs",
|
|
"action": {
|
|
"type": "search",
|
|
"query": "docs",
|
|
"queries": null,
|
|
},
|
|
}))
|
|
.expect("deserialize legacy extension item without results"),
|
|
item
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn sleep_item_preserves_stable_wire_shape() {
|
|
let item = ExtensionItem::Sleep(SleepItem {
|
|
id: "sleep-1".to_string(),
|
|
duration_ms: 1_000,
|
|
});
|
|
let value = serde_json::to_value(&item).expect("serialize extension item");
|
|
|
|
assert_eq!(
|
|
value,
|
|
json!({
|
|
"kind": "clock.sleep",
|
|
"id": "sleep-1",
|
|
"durationMs": 1_000,
|
|
})
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_value::<ExtensionItem>(value).expect("deserialize extension item"),
|
|
item
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn unknown_extension_kind_is_rejected() {
|
|
let value = json!({
|
|
"kind": "image_gen.unknown",
|
|
"id": "image-1",
|
|
});
|
|
|
|
assert!(serde_json::from_value::<ExtensionItem>(value).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn malformed_known_extension_payload_is_rejected() {
|
|
let value = json!({
|
|
"kind": "image_gen.generation",
|
|
"id": "image-1",
|
|
"status": "completed",
|
|
});
|
|
|
|
assert!(serde_json::from_value::<ExtensionItem>(value).is_err());
|
|
}
|