mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
tui: normalize pending steer keys directly
This commit is contained in:
@@ -86,7 +86,6 @@ use codex_protocol::config_types::Settings;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::items::AgentMessageContent;
|
||||
use codex_protocol::items::AgentMessageItem;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::models::MessagePhase;
|
||||
use codex_protocol::models::local_image_label_text;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use super::*;
|
||||
use codex_core::parse_turn_item;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::protocol::ConversationStartParams;
|
||||
use codex_protocol::protocol::RealtimeAudioFrame;
|
||||
use codex_protocol::protocol::RealtimeConversationClosedEvent;
|
||||
@@ -92,14 +90,40 @@ impl ChatWidget {
|
||||
pub(super) fn rendered_user_message_event_from_inputs(
|
||||
items: &[UserInput],
|
||||
) -> RenderedUserMessageEvent {
|
||||
let response_item = ResponseInputItem::from(items.to_vec()).into();
|
||||
let Some(TurnItem::UserMessage(user_message)) = parse_turn_item(&response_item) else {
|
||||
unreachable!("user inputs must round-trip into a user-message turn item");
|
||||
};
|
||||
let EventMsg::UserMessage(event) = user_message.as_legacy_event() else {
|
||||
unreachable!("UserMessageItem::as_legacy_event must return UserMessage");
|
||||
};
|
||||
Self::rendered_user_message_event_from_event(&event)
|
||||
let mut message = String::new();
|
||||
let mut remote_image_urls = Vec::new();
|
||||
let mut local_images = Vec::new();
|
||||
let mut text_elements = Vec::new();
|
||||
|
||||
for item in items {
|
||||
match item {
|
||||
UserInput::Text {
|
||||
text,
|
||||
text_elements: current_text_elements,
|
||||
} => {
|
||||
let offset = message.len();
|
||||
for element in current_text_elements {
|
||||
text_elements.push(TextElement::new(
|
||||
(offset + element.byte_range.start..offset + element.byte_range.end)
|
||||
.into(),
|
||||
element.placeholder(text).map(str::to_string),
|
||||
));
|
||||
}
|
||||
message.push_str(text);
|
||||
}
|
||||
UserInput::Image { image_url } => remote_image_urls.push(image_url.clone()),
|
||||
UserInput::LocalImage { path } => local_images.push(path.clone()),
|
||||
UserInput::Skill { .. } | UserInput::Mention { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Self::rendered_user_message_event_from_parts(
|
||||
message,
|
||||
text_elements,
|
||||
local_images,
|
||||
remote_image_urls,
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn should_render_realtime_user_message_event(
|
||||
|
||||
@@ -3612,6 +3612,48 @@ async fn live_legacy_agent_message_after_item_completed_does_not_duplicate_assis
|
||||
assert!(drain_insert_history(&mut rx).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rendered_user_message_event_from_inputs_matches_flattened_user_message_shape() {
|
||||
let local_image = PathBuf::from("/tmp/local.png");
|
||||
let rendered = ChatWidget::rendered_user_message_event_from_inputs(&[
|
||||
UserInput::Text {
|
||||
text: "hello ".to_string(),
|
||||
text_elements: vec![TextElement::new((0..5).into(), None)],
|
||||
},
|
||||
UserInput::Image {
|
||||
image_url: "https://example.com/remote.png".to_string(),
|
||||
},
|
||||
UserInput::LocalImage {
|
||||
path: local_image.clone(),
|
||||
},
|
||||
UserInput::Skill {
|
||||
name: "demo".to_string(),
|
||||
path: PathBuf::from("/tmp/skill/SKILL.md"),
|
||||
},
|
||||
UserInput::Mention {
|
||||
name: "repo".to_string(),
|
||||
path: "app://repo".to_string(),
|
||||
},
|
||||
UserInput::Text {
|
||||
text: "world".to_string(),
|
||||
text_elements: vec![TextElement::new((0..5).into(), Some("planet".to_string()))],
|
||||
},
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
rendered,
|
||||
ChatWidget::rendered_user_message_event_from_parts(
|
||||
"hello world".to_string(),
|
||||
vec![
|
||||
TextElement::new((0..5).into(), Some("hello".to_string())),
|
||||
TextElement::new((6..11).into(), Some("planet".to_string())),
|
||||
],
|
||||
vec![local_image],
|
||||
vec!["https://example.com/remote.png".to_string()],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn item_completed_only_pops_front_pending_steer() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;
|
||||
|
||||
Reference in New Issue
Block a user