mirror of
https://github.com/openai/codex.git
synced 2026-04-30 09:26:44 +00:00
Persist text elements through TUI input and history (#9393)
Continuation of breaking up this PR https://github.com/openai/codex/pull/9116 ## Summary - Thread user text element ranges through TUI/TUI2 input, submission, queueing, and history so placeholders survive resume/edit flows. - Preserve local image attachments alongside text elements and rehydrate placeholders when restoring drafts. - Keep model-facing content shapes clean by attaching UI metadata only to user input/events (no API content changes). ## Key Changes - TUI/TUI2 composer now captures text element ranges, trims them with text edits, and restores them when submission is suppressed. - User history cells render styled spans for text elements and keep local image paths for future rehydration. - Initial chat widget bootstraps accept empty `initial_text_elements` to keep initialization uniform. - Protocol/core helpers updated to tolerate the new InputText field shape without changing payloads sent to the API.
This commit is contained in:
@@ -28,6 +28,7 @@ use bottom_pane_view::BottomPaneView;
|
||||
use codex_core::features::Features;
|
||||
use codex_core::skills::model::SkillMetadata;
|
||||
use codex_file_search::FileMatch;
|
||||
use codex_protocol::user_input::TextElement;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use ratatui::buffer::Buffer;
|
||||
@@ -39,6 +40,12 @@ mod approval_overlay;
|
||||
pub(crate) use approval_overlay::ApprovalOverlay;
|
||||
pub(crate) use approval_overlay::ApprovalRequest;
|
||||
mod bottom_pane_view;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct LocalImageAttachment {
|
||||
pub(crate) placeholder: String,
|
||||
pub(crate) path: PathBuf,
|
||||
}
|
||||
mod chat_composer;
|
||||
mod chat_composer_history;
|
||||
mod command_popup;
|
||||
@@ -317,8 +324,14 @@ impl BottomPane {
|
||||
}
|
||||
|
||||
/// Replace the composer text with `text`.
|
||||
pub(crate) fn set_composer_text(&mut self, text: String) {
|
||||
self.composer.set_text_content(text);
|
||||
pub(crate) fn set_composer_text(
|
||||
&mut self,
|
||||
text: String,
|
||||
text_elements: Vec<TextElement>,
|
||||
local_image_paths: Vec<PathBuf>,
|
||||
) {
|
||||
self.composer
|
||||
.set_text_content(text, text_elements, local_image_paths);
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
@@ -342,6 +355,19 @@ impl BottomPane {
|
||||
self.composer.current_text()
|
||||
}
|
||||
|
||||
pub(crate) fn composer_text_elements(&self) -> Vec<TextElement> {
|
||||
self.composer.text_elements()
|
||||
}
|
||||
|
||||
pub(crate) fn composer_local_images(&self) -> Vec<LocalImageAttachment> {
|
||||
self.composer.local_images()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn composer_local_image_paths(&self) -> Vec<PathBuf> {
|
||||
self.composer.local_image_paths()
|
||||
}
|
||||
|
||||
pub(crate) fn composer_text_with_pending(&self) -> String {
|
||||
self.composer.current_text_with_pending()
|
||||
}
|
||||
@@ -652,10 +678,18 @@ impl BottomPane {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn take_recent_submission_images(&mut self) -> Vec<PathBuf> {
|
||||
self.composer.take_recent_submission_images()
|
||||
}
|
||||
|
||||
pub(crate) fn take_recent_submission_images_with_placeholders(
|
||||
&mut self,
|
||||
) -> Vec<LocalImageAttachment> {
|
||||
self.composer
|
||||
.take_recent_submission_images_with_placeholders()
|
||||
}
|
||||
|
||||
fn as_renderable(&'_ self) -> RenderableItem<'_> {
|
||||
if let Some(view) = self.active_view() {
|
||||
RenderableItem::Borrowed(view)
|
||||
|
||||
Reference in New Issue
Block a user