mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
Auto-commit pending changes on agentydragon-task/13-interactive-prompt-during-execution
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
|
||||
## Status
|
||||
|
||||
**General Status**: Not started
|
||||
**Summary**: Not started; missing Implementation details (How it was implemented and How it works).
|
||||
**General Status**: Done
|
||||
**Summary**: Implemented interactive prompt overlay allowing user input during streaming without aborting runs.
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -23,10 +23,12 @@ Allow users to interleave composing prompts and issuing slash-commands while the
|
||||
## Implementation
|
||||
|
||||
**How it was implemented**
|
||||
*(Not implemented yet)*
|
||||
- Modified `BottomPane::handle_key_event` in `tui/src/bottom_pane/mod.rs` to special-case the `StatusIndicatorView` while `is_task_running`, forwarding key events to `ChatComposer` and preserving the overlay.
|
||||
- Updated `BottomPane::render_ref` to always render the composer first and then overlay the active view, ensuring the input box remains visible and editable under the status indicator.
|
||||
- Added unit tests in `tui/src/bottom_pane/mod.rs` to verify input is forwarded during task execution and that the status indicator overlay is removed upon task completion.
|
||||
|
||||
**How it works**
|
||||
*(Not implemented yet)*
|
||||
During LLM streaming or tool execution, the `StatusIndicatorView` remains active as an overlay. The modified event handler detects this overlay and forwards user key events to the underlying `ChatComposer` without dismissing the overlay. On task completion (`set_task_running(false)`), the overlay is automatically removed (via `should_hide_when_task_is_done`), returning to the normal input-only view.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -63,6 +63,16 @@ impl BottomPane<'_> {
|
||||
/// Forward a key event to the active view or the composer.
|
||||
pub fn handle_key_event(&mut self, key_event: KeyEvent) -> InputResult {
|
||||
if let Some(mut view) = self.active_view.take() {
|
||||
// During task execution, allow input to pass through status indicator overlay
|
||||
if self.is_task_running && view.should_hide_when_task_is_done() {
|
||||
// restore overlay view and forward input to composer
|
||||
self.active_view = Some(view);
|
||||
let (input_result, needs_redraw) = self.composer.handle_key_event(key_event);
|
||||
if needs_redraw {
|
||||
self.request_redraw();
|
||||
}
|
||||
return input_result;
|
||||
}
|
||||
view.handle_key_event(self, key_event);
|
||||
if !view.is_complete() {
|
||||
self.active_view = Some(view);
|
||||
@@ -197,11 +207,54 @@ impl BottomPane<'_> {
|
||||
|
||||
impl WidgetRef for &BottomPane<'_> {
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
||||
// Show BottomPaneView if present.
|
||||
// Always render composer, then overlay any active view (e.g., status indicator or modal)
|
||||
(&self.composer).render_ref(area, buf);
|
||||
if let Some(ov) = &self.active_view {
|
||||
ov.render(area, buf);
|
||||
} else {
|
||||
(&self.composer).render_ref(area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
|
||||
/// Construct a BottomPane with default parameters for testing.
|
||||
fn make_pane() -> BottomPane<'static> {
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let app_event_tx = AppEventSender::new(tx);
|
||||
BottomPane::new(BottomPaneParams {
|
||||
app_event_tx,
|
||||
has_input_focus: true,
|
||||
composer_max_rows: 3,
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn forward_input_during_status_indicator() {
|
||||
let mut pane = make_pane();
|
||||
// Start task to show status indicator overlay
|
||||
pane.set_task_running(true);
|
||||
// Simulate typing 'h'
|
||||
let key = KeyEvent::new(KeyCode::Char('h'), KeyModifiers::NONE);
|
||||
let result = pane.handle_key_event(key);
|
||||
// No submission event is returned
|
||||
assert!(matches!(result, InputResult::None));
|
||||
// Composer should have recorded the input
|
||||
let content = pane.composer.textarea.lines().join("\n");
|
||||
assert_eq!(content, "h");
|
||||
// Status indicator overlay remains active
|
||||
assert!(pane.active_view.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_status_indicator_after_task_complete() {
|
||||
let mut pane = make_pane();
|
||||
pane.set_task_running(true);
|
||||
assert!(pane.active_view.is_some());
|
||||
pane.set_task_running(false);
|
||||
// Overlay should be removed when task finishes
|
||||
assert!(pane.active_view.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user