mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Emit image view as core item (#20512)
## Why Image-view results should be represented as a core-produced turn item instead of being reconstructed by app-server. At the same time, existing rollout/history paths still understand the legacy `ViewImageToolCall` event, so this keeps that event as compatibility output generated from the new item lifecycle. ## What changed - Added `TurnItem::ImageView` to `codex-protocol`. - Emitted image-view item start/completion directly from the core `view_image` handler. - Kept `ViewImageToolCall` as a legacy event and generate it from completed `TurnItem::ImageView` items. - Kept `thread_history.rs` on the legacy `ViewImageToolCall` replay path, with `ImageView` item lifecycle events ignored there. - Updated app-server protocol conversion, rollout persistence, and affected exhaustive event matches for the new item plus legacy fan-out shape. ## Verification - `cargo test -p codex-protocol -p codex-app-server-protocol -p codex-rollout -p codex-rollout-trace -p codex-mcp-server -p codex-app-server --lib` - `cargo test -p codex-core --test all view_image_tool_attaches_local_image` - `just fix -p codex-protocol -p codex-core -p codex-app-server-protocol -p codex-app-server -p codex-rollout -p codex-rollout-trace -p codex-mcp-server` - `git diff --check`
This commit is contained in:
committed by
GitHub
Unverified
parent
610eefb86b
commit
aed74e5ee4
@@ -299,12 +299,26 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> {
|
||||
))
|
||||
.await?;
|
||||
|
||||
let mut tool_event = None;
|
||||
let mut item_started = None;
|
||||
let mut item_completed = None;
|
||||
let mut legacy_event = None;
|
||||
wait_for_event_with_timeout(
|
||||
codex,
|
||||
|event| match event {
|
||||
EventMsg::ViewImageToolCall(_) => {
|
||||
tool_event = Some(event.clone());
|
||||
EventMsg::ItemStarted(event) => {
|
||||
if matches!(&event.item, codex_protocol::items::TurnItem::ImageView(_)) {
|
||||
item_started = Some(event.item.clone());
|
||||
}
|
||||
false
|
||||
}
|
||||
EventMsg::ItemCompleted(event) => {
|
||||
if matches!(&event.item, codex_protocol::items::TurnItem::ImageView(_)) {
|
||||
item_completed = Some(event.item.clone());
|
||||
}
|
||||
false
|
||||
}
|
||||
EventMsg::ViewImageToolCall(event) => {
|
||||
legacy_event = Some(event.clone());
|
||||
false
|
||||
}
|
||||
EventMsg::TurnComplete(_) => true,
|
||||
@@ -316,12 +330,23 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> {
|
||||
)
|
||||
.await;
|
||||
|
||||
let tool_event = match tool_event.expect("view image tool event emitted") {
|
||||
EventMsg::ViewImageToolCall(event) => event,
|
||||
_ => unreachable!("stored event must be ViewImageToolCall"),
|
||||
};
|
||||
assert_eq!(tool_event.call_id, call_id);
|
||||
assert_eq!(tool_event.path, abs_path);
|
||||
match item_started.expect("view image item started event emitted") {
|
||||
codex_protocol::items::TurnItem::ImageView(item) => {
|
||||
assert_eq!(item.id, call_id);
|
||||
assert_eq!(item.path, abs_path);
|
||||
}
|
||||
other => panic!("expected ImageView item, got {other:?}"),
|
||||
}
|
||||
match item_completed.expect("view image item completed event emitted") {
|
||||
codex_protocol::items::TurnItem::ImageView(item) => {
|
||||
assert_eq!(item.id, call_id);
|
||||
assert_eq!(item.path, abs_path);
|
||||
}
|
||||
other => panic!("expected ImageView item, got {other:?}"),
|
||||
}
|
||||
let legacy_event = legacy_event.expect("legacy view image event emitted");
|
||||
assert_eq!(legacy_event.call_id, call_id);
|
||||
assert_eq!(legacy_event.path, abs_path);
|
||||
|
||||
let req = mock.single_request();
|
||||
let body = req.body_json();
|
||||
|
||||
Reference in New Issue
Block a user