mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
fix(tui): order transient token cards after active cells
This commit is contained in:
@@ -1177,6 +1177,7 @@ impl ChatWidget {
|
||||
if let Some(active) = self.transcript.active_cell.take() {
|
||||
self.transcript.needs_final_message_separator = true;
|
||||
self.app_event_tx.send(AppEvent::InsertHistoryCell(active));
|
||||
self.request_completed_token_activity_output_insertion();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1388,6 +1389,7 @@ impl ChatWidget {
|
||||
tool.mark_failed();
|
||||
}
|
||||
self.add_boxed_history(cell);
|
||||
self.request_completed_token_activity_output_insertion();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ impl ChatWidget {
|
||||
}
|
||||
_ => RenderableItem::Owned(Box::new(())),
|
||||
};
|
||||
let mut flex = FlexRenderable::new();
|
||||
flex.push(/*flex*/ 1, active_cell_renderable);
|
||||
flex.push(/*flex*/ 0, active_hook_cell_renderable);
|
||||
let mut content = FlexRenderable::new();
|
||||
content.push(/*flex*/ 0, active_cell_renderable);
|
||||
content.push(/*flex*/ 0, active_hook_cell_renderable);
|
||||
if let Some(cell) = self.pending_token_activity_output() {
|
||||
flex.push(
|
||||
content.push(
|
||||
/*flex*/ 1,
|
||||
RenderableItem::Owned(Box::new(TranscriptAreaRenderable {
|
||||
child: cell,
|
||||
@@ -36,6 +36,8 @@ impl ChatWidget {
|
||||
})),
|
||||
);
|
||||
}
|
||||
let mut flex = FlexRenderable::new();
|
||||
flex.push(/*flex*/ 1, RenderableItem::Owned(Box::new(content)));
|
||||
flex.push(
|
||||
/*flex*/ 0,
|
||||
RenderableItem::Owned(Box::new(BottomPaneComposerReserveRenderable {
|
||||
|
||||
@@ -1298,6 +1298,36 @@ async fn completed_token_activity_refresh_waits_for_active_stream() {
|
||||
assert!(chat.take_completed_token_activity_output().is_some());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn completed_token_activity_refresh_waits_for_active_history_cell() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
set_chatgpt_auth(&mut chat);
|
||||
|
||||
chat.dispatch_command(SlashCommand::Tokens);
|
||||
let request_id = match rx.try_recv() {
|
||||
Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id,
|
||||
other => panic!("expected token activity refresh request, got {other:?}"),
|
||||
};
|
||||
chat.transcript.active_cell = Some(Box::new(PlainHistoryCell::new(vec![Line::from(
|
||||
"active tool",
|
||||
)])));
|
||||
assert!(
|
||||
chat.finish_token_activity_refresh(
|
||||
request_id,
|
||||
Err("token activity unavailable".to_string()),
|
||||
)
|
||||
);
|
||||
assert!(chat.token_activity_history_insertion_blocked());
|
||||
|
||||
chat.flush_active_cell();
|
||||
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::InsertHistoryCell(_)));
|
||||
assert_matches!(
|
||||
rx.try_recv(),
|
||||
Ok(AppEvent::CommitCompletedTokenActivityOutput)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn completed_token_activity_refresh_retries_after_plan_item_completion() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
@@ -1330,6 +1360,40 @@ async fn completed_token_activity_refresh_retries_after_plan_item_completion() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pending_token_activity_refresh_keeps_composer_visible_in_short_viewport() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
set_chatgpt_auth(&mut chat);
|
||||
chat.transcript.active_cell = Some(Box::new(PlainHistoryCell::new(
|
||||
std::iter::repeat_n(Line::from("active output"), /*n*/ 20).collect(),
|
||||
)));
|
||||
|
||||
chat.dispatch_command(SlashCommand::Tokens);
|
||||
assert_matches!(
|
||||
rx.try_recv(),
|
||||
Ok(AppEvent::RefreshTokenActivity { .. }),
|
||||
"expected token activity refresh request"
|
||||
);
|
||||
|
||||
let width: u16 = 80;
|
||||
let height: u16 = 8;
|
||||
let backend = VT100Backend::new(width, height);
|
||||
let mut term = crate::custom_terminal::Terminal::with_options(backend).expect("terminal");
|
||||
term.set_viewport_area(Rect::new(/*x*/ 0, /*y*/ 0, width, height));
|
||||
term.draw(|f| {
|
||||
chat.render(f.area(), f.buffer_mut());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
term.backend()
|
||||
.vt100()
|
||||
.screen()
|
||||
.contents()
|
||||
.contains("Ask Codex to do anything")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn repeated_token_activity_refreshes_keep_only_latest_card() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
@@ -685,7 +685,9 @@ impl ChatWidget {
|
||||
}
|
||||
|
||||
pub(crate) fn token_activity_history_insertion_blocked(&self) -> bool {
|
||||
self.stream_controller.is_some() || self.plan_stream_controller.is_some()
|
||||
self.stream_controller.is_some()
|
||||
|| self.plan_stream_controller.is_some()
|
||||
|| self.transcript.active_cell.is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn take_completed_token_activity_output(&mut self) -> Option<CompositeHistoryCell> {
|
||||
|
||||
Reference in New Issue
Block a user