mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
Fix fork popup mouse support
This commit is contained in:
+10
-6
@@ -153,19 +153,18 @@ use uuid::Uuid;
|
||||
mod agent_navigation;
|
||||
mod app_server_adapter;
|
||||
mod app_server_requests;
|
||||
mod loaded_threads;
|
||||
mod fork_session_overlay;
|
||||
mod fork_session_overlay_mouse;
|
||||
mod fork_session_overlay_stack;
|
||||
mod fork_session_terminal;
|
||||
mod loaded_threads;
|
||||
mod pending_interactive_replay;
|
||||
|
||||
use self::agent_navigation::AgentNavigationDirection;
|
||||
use self::agent_navigation::AgentNavigationState;
|
||||
use self::app_server_requests::PendingAppServerRequests;
|
||||
use self::loaded_threads::find_loaded_subagent_threads_for_primary;
|
||||
use self::fork_session_overlay::ForkSessionOverlayState;
|
||||
use self::fork_session_overlay_stack::ForkSessionOverlayStack;
|
||||
use self::loaded_threads::find_loaded_subagent_threads_for_primary;
|
||||
use self::pending_interactive_replay::PendingInteractiveReplayState;
|
||||
|
||||
const EXTERNAL_EDITOR_HINT: &str = "Save and close external editor to continue.";
|
||||
@@ -3905,7 +3904,7 @@ impl App {
|
||||
if self.overlay.is_some() {
|
||||
let _ = self.handle_backtrack_overlay_event(tui, event).await?;
|
||||
} else if self.fork_session_overlay.is_some() {
|
||||
self.handle_fork_session_overlay_tui_event(tui, event)
|
||||
self.handle_fork_session_overlay_tui_event(tui, app_server, event)
|
||||
.await?;
|
||||
} else {
|
||||
match event {
|
||||
@@ -3974,7 +3973,7 @@ impl App {
|
||||
.await;
|
||||
}
|
||||
AppEvent::ClearUi => {
|
||||
self.clear_terminal_ui(tui, false)?;
|
||||
self.clear_terminal_ui(tui, /*redraw_header*/ false)?;
|
||||
self.reset_app_ui_state_after_clear();
|
||||
|
||||
self.start_fresh_session_with_summary_hint(tui, app_server)
|
||||
@@ -4125,7 +4124,12 @@ impl App {
|
||||
// Fresh threads expose a precomputed path, but the file is
|
||||
// materialized lazily on first user message.
|
||||
if path.exists() {
|
||||
match crate::resolve_session_thread_id(path.as_path(), None).await {
|
||||
match crate::resolve_session_thread_id(
|
||||
path.as_path(),
|
||||
/*id_str_if_uuid*/ None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Some(thread_id) => {
|
||||
if let Err(err) =
|
||||
self.open_fork_session_overlay(tui, thread_id).await
|
||||
|
||||
@@ -18,6 +18,7 @@ use ratatui::widgets::Clear;
|
||||
use ratatui::widgets::Widget;
|
||||
|
||||
use crate::app::App;
|
||||
use crate::app_server_session::AppServerSession;
|
||||
use crate::chatwidget::ExternalEditorState;
|
||||
use crate::custom_terminal::Frame;
|
||||
use crate::insert_history::insert_history_lines;
|
||||
@@ -281,7 +282,7 @@ fn popup_block(
|
||||
|
||||
fn popup_terminal_size(popup: Rect) -> codex_utils_pty::TerminalSize {
|
||||
let inner = popup_block(
|
||||
None,
|
||||
/*exit_code*/ None,
|
||||
OverlayCommandState::PassThrough,
|
||||
OverlayFocusedPane::Popup,
|
||||
)
|
||||
@@ -382,7 +383,7 @@ impl App {
|
||||
stack.push_popup(popup_state);
|
||||
} else {
|
||||
self.fork_session_overlay = Some(ForkSessionOverlayStack::new(popup_state));
|
||||
tui.set_mouse_capture_enabled(true)?;
|
||||
tui.set_mouse_capture_enabled(/*enabled*/ true)?;
|
||||
}
|
||||
tui.frame_requester().schedule_frame();
|
||||
Ok(())
|
||||
@@ -393,7 +394,7 @@ impl App {
|
||||
let _ = stack.close_active_popup();
|
||||
if stack.is_empty() {
|
||||
self.fork_session_overlay = None;
|
||||
tui.set_mouse_capture_enabled(false)?;
|
||||
tui.set_mouse_capture_enabled(/*enabled*/ false)?;
|
||||
self.restore_inline_view_after_fork_overlay_close(tui)?;
|
||||
}
|
||||
}
|
||||
@@ -404,6 +405,7 @@ impl App {
|
||||
pub(crate) async fn handle_fork_session_overlay_tui_event(
|
||||
&mut self,
|
||||
tui: &mut tui::Tui,
|
||||
app_server: &mut AppServerSession,
|
||||
event: TuiEvent,
|
||||
) -> Result<()> {
|
||||
match event {
|
||||
@@ -438,7 +440,7 @@ impl App {
|
||||
} else {
|
||||
match stack.focused_pane() {
|
||||
OverlayFocusedPane::Background => {
|
||||
self.handle_key_event(tui, key_event).await;
|
||||
self.handle_key_event(tui, app_server, key_event).await;
|
||||
}
|
||||
OverlayFocusedPane::Popup => {
|
||||
forward_key = Some(key_event);
|
||||
@@ -637,61 +639,92 @@ impl App {
|
||||
}
|
||||
KeyCode::Char('h') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_left_edge(area, popup.popup, -1);
|
||||
popup.popup = resize_left_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ -1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('H') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_left_edge(area, popup.popup, 1);
|
||||
popup.popup = resize_left_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('j') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_bottom_edge(area, popup.popup, 1);
|
||||
popup.popup = resize_bottom_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('J') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_bottom_edge(area, popup.popup, -1);
|
||||
popup.popup = resize_bottom_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ -1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('k') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_top_edge(area, popup.popup, -1);
|
||||
popup.popup = resize_top_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ -1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('K') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup = resize_top_edge(area, popup.popup, 1);
|
||||
popup.popup = resize_top_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('l') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_right_edge(area, popup.popup, 1);
|
||||
popup.popup = resize_right_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('L') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_right_edge(area, popup.popup, -1);
|
||||
popup.popup = resize_right_edge(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ -1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('=') | KeyCode::Char('+') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_all_edges(area, popup.popup, 1);
|
||||
popup.popup = resize_all_edges(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Char('-') => {
|
||||
if let Some(popup) = stack.active_popup_mut() {
|
||||
popup.popup =
|
||||
resize_all_edges(area, popup.popup, -1);
|
||||
popup.popup = resize_all_edges(
|
||||
area,
|
||||
popup.popup,
|
||||
/*delta*/ -1,
|
||||
);
|
||||
}
|
||||
}
|
||||
KeyCode::Esc | KeyCode::Enter => {
|
||||
@@ -778,7 +811,7 @@ impl App {
|
||||
};
|
||||
if close_all_overlays {
|
||||
self.fork_session_overlay = None;
|
||||
tui.set_mouse_capture_enabled(false)?;
|
||||
tui.set_mouse_capture_enabled(/*enabled*/ false)?;
|
||||
self.restore_inline_view_after_fork_overlay_close(tui)?;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -987,8 +1020,9 @@ mod tests {
|
||||
use crate::app_backtrack::BacktrackState;
|
||||
use crate::chatwidget::tests::make_chatwidget_manual_with_sender;
|
||||
use crate::file_search::FileSearchManager;
|
||||
use codex_core::CodexAuth;
|
||||
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_otel::SessionTelemetry;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
@@ -1022,42 +1056,38 @@ mod tests {
|
||||
async fn make_test_app() -> App {
|
||||
let (chat_widget, app_event_tx, _rx, _op_rx) = make_chatwidget_manual_with_sender().await;
|
||||
let config = chat_widget.config_ref().clone();
|
||||
let server = Arc::new(
|
||||
let _server = Arc::new(
|
||||
codex_core::test_support::thread_manager_with_models_provider(
|
||||
CodexAuth::from_api_key("Test API Key"),
|
||||
config.model_provider.clone(),
|
||||
),
|
||||
);
|
||||
let auth_manager = codex_core::test_support::auth_manager_from_auth(
|
||||
let _auth_manager = codex_core::test_support::auth_manager_from_auth(
|
||||
CodexAuth::from_api_key("Test API Key"),
|
||||
);
|
||||
let file_search = FileSearchManager::new(config.cwd.clone(), app_event_tx.clone());
|
||||
let file_search = FileSearchManager::new(config.cwd.to_path_buf(), app_event_tx.clone());
|
||||
let model = codex_core::test_support::get_model_offline(config.model.as_deref());
|
||||
let session_telemetry = SessionTelemetry::new(
|
||||
ThreadId::new(),
|
||||
model.as_str(),
|
||||
model.as_str(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
/*account_id*/ None,
|
||||
/*account_email*/ None,
|
||||
/*auth_mode*/ None,
|
||||
"test_originator".to_string(),
|
||||
false,
|
||||
/*log_user_prompts*/ false,
|
||||
"test".to_string(),
|
||||
SessionSource::Cli,
|
||||
);
|
||||
|
||||
App {
|
||||
server,
|
||||
model_catalog: chat_widget.model_catalog(),
|
||||
session_telemetry,
|
||||
app_event_tx,
|
||||
chat_widget,
|
||||
auth_manager,
|
||||
config,
|
||||
active_profile: None,
|
||||
cli_kv_overrides: Vec::new(),
|
||||
arg0_paths: codex_arg0::Arg0DispatchPaths::default(),
|
||||
loader_overrides: codex_core::config_loader::LoaderOverrides::default(),
|
||||
cloud_requirements: codex_core::config_loader::CloudRequirementsLoader::default(),
|
||||
harness_overrides: ConfigOverrides::default(),
|
||||
runtime_approval_policy_override: None,
|
||||
runtime_sandbox_policy_override: None,
|
||||
@@ -1075,8 +1105,9 @@ mod tests {
|
||||
backtrack_render_pending: false,
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
feedback_audience: FeedbackAudience::External,
|
||||
remote_app_server_url: None,
|
||||
remote_app_server_auth_token: None,
|
||||
pending_update_action: None,
|
||||
suppress_shutdown_complete: false,
|
||||
pending_shutdown_exit_thread_id: None,
|
||||
windows_sandbox: WindowsSandboxState::default(),
|
||||
thread_event_channels: HashMap::new(),
|
||||
@@ -1085,8 +1116,10 @@ mod tests {
|
||||
active_thread_id: None,
|
||||
active_thread_rx: None,
|
||||
primary_thread_id: None,
|
||||
last_subagent_backfill_attempt: None,
|
||||
primary_session_configured: None,
|
||||
pending_primary_events: VecDeque::new(),
|
||||
pending_app_server_requests: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1095,7 +1128,10 @@ mod tests {
|
||||
let temp_dir = tempdir().expect("tempdir");
|
||||
let mut app = make_test_app().await;
|
||||
app.active_profile = Some("dev".to_string());
|
||||
app.config.cwd = temp_dir.path().join("project");
|
||||
app.config.cwd = codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(
|
||||
temp_dir.path().join("project"),
|
||||
)
|
||||
.unwrap();
|
||||
app.chat_widget.set_model("gpt-5.4");
|
||||
app.on_update_reasoning_effort(Some(codex_protocol::openai_models::ReasoningEffort::High));
|
||||
app.runtime_approval_policy_override =
|
||||
@@ -1157,7 +1193,7 @@ mod tests {
|
||||
let area = Rect::new(0, 0, 100, 28);
|
||||
let popup = default_popup_rect(area);
|
||||
|
||||
let moved = move_popup_rect(area, popup, -100, 100);
|
||||
let moved = move_popup_rect(area, popup, /*dx*/ -100, /*dy*/ 100);
|
||||
|
||||
assert_eq!(moved, Rect::new(0, 13, 64, 15));
|
||||
}
|
||||
@@ -1207,7 +1243,7 @@ mod tests {
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
app.transcript_history_lines(80),
|
||||
app.transcript_history_lines(/*width*/ 80),
|
||||
vec![Line::from("first"), Line::from(""), Line::from("second")]
|
||||
);
|
||||
}
|
||||
@@ -1217,8 +1253,8 @@ mod tests {
|
||||
let area = Rect::new(0, 0, 100, 28);
|
||||
let popup = default_popup_rect(area);
|
||||
|
||||
let shrunk = resize_all_edges(area, popup, -100);
|
||||
let grown = resize_all_edges(area, popup, 100);
|
||||
let shrunk = resize_all_edges(area, popup, /*delta*/ -100);
|
||||
let grown = resize_all_edges(area, popup, /*delta*/ 100);
|
||||
|
||||
assert_eq!(shrunk, Rect::new(38, 11, 44, 10));
|
||||
assert_eq!(grown, Rect::new(0, 0, 96, 26));
|
||||
@@ -1229,7 +1265,7 @@ mod tests {
|
||||
let area = Rect::new(0, 0, 140, 40);
|
||||
let popup = default_popup_rect(area);
|
||||
|
||||
let grown = resize_all_edges(area, popup, 100);
|
||||
let grown = resize_all_edges(area, popup, /*delta*/ 100);
|
||||
|
||||
assert_eq!(grown, Rect::new(0, 0, 136, 38));
|
||||
}
|
||||
@@ -1260,7 +1296,7 @@ mod tests {
|
||||
ready for a fresh turn\r\n",
|
||||
);
|
||||
app.fork_session_overlay = Some(ForkSessionOverlayStack::new(ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(parser, None),
|
||||
terminal: ForkSessionTerminal::for_test(parser, /*exit_code*/ None),
|
||||
popup: default_popup_rect(Rect::new(0, 0, 100, 28)),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
@@ -1305,13 +1341,13 @@ ready for a fresh turn\r\n",
|
||||
);
|
||||
|
||||
let mut stack = ForkSessionOverlayStack::new(ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(first_popup, None),
|
||||
terminal: ForkSessionTerminal::for_test(first_popup, /*exit_code*/ None),
|
||||
popup: Rect::new(14, 7, 52, 12),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
});
|
||||
stack.push_popup(ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(second_popup, None),
|
||||
terminal: ForkSessionTerminal::for_test(second_popup, /*exit_code*/ None),
|
||||
popup: Rect::new(28, 11, 52, 12),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
@@ -1354,7 +1390,7 @@ ready for a fresh turn\r\n",
|
||||
ready for a fresh turn\r\n",
|
||||
);
|
||||
let mut stack = ForkSessionOverlayStack::new(ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(parser, None),
|
||||
terminal: ForkSessionTerminal::for_test(parser, /*exit_code*/ None),
|
||||
popup: default_popup_rect(Rect::new(0, 0, 100, 28)),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
@@ -1399,7 +1435,10 @@ ready for a fresh turn\r\n",
|
||||
Vec::new(),
|
||||
);
|
||||
let mut stack = ForkSessionOverlayStack::new(ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(vt100::Parser::new(1, 1, 0), None),
|
||||
terminal: ForkSessionTerminal::for_test(
|
||||
vt100::Parser::new(1, 1, 0),
|
||||
/*exit_code*/ None,
|
||||
),
|
||||
popup: default_popup_rect(Rect::new(0, 0, 80, 18)),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
|
||||
@@ -104,7 +104,7 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
overlay_mouse_action(area, &popups, None, mouse_event),
|
||||
overlay_mouse_action(area, &popups, /*drag_state*/ None, mouse_event),
|
||||
OverlayMouseAction::FocusBackground
|
||||
);
|
||||
}
|
||||
@@ -121,7 +121,7 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
overlay_mouse_action(area, &popups, None, mouse_event),
|
||||
overlay_mouse_action(area, &popups, /*drag_state*/ None, mouse_event),
|
||||
OverlayMouseAction::FocusPopup {
|
||||
popup_index: 0,
|
||||
drag_state: PopupDragState {
|
||||
@@ -165,7 +165,7 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
overlay_mouse_action(area, &popups, None, mouse_event),
|
||||
overlay_mouse_action(area, &popups, /*drag_state*/ None, mouse_event),
|
||||
OverlayMouseAction::EndDrag
|
||||
);
|
||||
}
|
||||
@@ -182,7 +182,7 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
overlay_mouse_action(area, &popups, None, mouse_event),
|
||||
overlay_mouse_action(area, &popups, /*drag_state*/ None, mouse_event),
|
||||
OverlayMouseAction::FocusPopup {
|
||||
popup_index: 1,
|
||||
drag_state: PopupDragState {
|
||||
|
||||
@@ -128,8 +128,11 @@ mod tests {
|
||||
|
||||
fn popup(x: u16, y: u16) -> ForkSessionOverlayState {
|
||||
ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(vt100::Parser::new(1, 1, 0), None),
|
||||
popup: Rect::new(x, y, 40, 16),
|
||||
terminal: ForkSessionTerminal::for_test(
|
||||
vt100::Parser::new(1, 1, 0),
|
||||
/*exit_code*/ None,
|
||||
),
|
||||
popup: Rect::new(/*x*/ x, /*y*/ y, 40, 16),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
}
|
||||
@@ -142,7 +145,7 @@ mod tests {
|
||||
stack.push_popup(popup(30, 30));
|
||||
|
||||
let active = stack
|
||||
.bring_popup_to_front(0)
|
||||
.bring_popup_to_front(/*index*/ 0)
|
||||
.expect("bring first popup to front");
|
||||
|
||||
assert_eq!(active.popup, Rect::new(10, 10, 40, 16));
|
||||
|
||||
@@ -10,8 +10,9 @@ use crate::file_search::FileSearchManager;
|
||||
use crate::history_cell;
|
||||
use crate::history_cell::PlainHistoryCell;
|
||||
use crate::test_backend::VT100Backend;
|
||||
use codex_core::CodexAuth;
|
||||
use codex_config::types::ApprovalsReviewer;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_otel::SessionTelemetry;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
@@ -35,41 +36,37 @@ use tempfile::NamedTempFile;
|
||||
async fn make_test_app() -> App {
|
||||
let (chat_widget, app_event_tx, _rx, _op_rx) = make_chatwidget_manual_with_sender().await;
|
||||
let config = chat_widget.config_ref().clone();
|
||||
let server = Arc::new(
|
||||
let _server = Arc::new(
|
||||
codex_core::test_support::thread_manager_with_models_provider(
|
||||
CodexAuth::from_api_key("Test API Key"),
|
||||
config.model_provider.clone(),
|
||||
),
|
||||
);
|
||||
let auth_manager =
|
||||
let _auth_manager =
|
||||
codex_core::test_support::auth_manager_from_auth(CodexAuth::from_api_key("Test API Key"));
|
||||
let file_search = FileSearchManager::new(config.cwd.clone(), app_event_tx.clone());
|
||||
let file_search = FileSearchManager::new(config.cwd.to_path_buf(), app_event_tx.clone());
|
||||
let model = codex_core::test_support::get_model_offline(config.model.as_deref());
|
||||
let session_telemetry = SessionTelemetry::new(
|
||||
ThreadId::new(),
|
||||
model.as_str(),
|
||||
model.as_str(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
/*account_id*/ None,
|
||||
/*account_email*/ None,
|
||||
/*auth_mode*/ None,
|
||||
"test_originator".to_string(),
|
||||
false,
|
||||
/*log_user_prompts*/ false,
|
||||
"test".to_string(),
|
||||
SessionSource::Cli,
|
||||
);
|
||||
|
||||
App {
|
||||
server,
|
||||
model_catalog: chat_widget.model_catalog(),
|
||||
session_telemetry,
|
||||
app_event_tx,
|
||||
chat_widget,
|
||||
auth_manager,
|
||||
config,
|
||||
active_profile: None,
|
||||
cli_kv_overrides: Vec::new(),
|
||||
arg0_paths: codex_arg0::Arg0DispatchPaths::default(),
|
||||
loader_overrides: codex_core::config_loader::LoaderOverrides::default(),
|
||||
cloud_requirements: codex_core::config_loader::CloudRequirementsLoader::default(),
|
||||
harness_overrides: ConfigOverrides::default(),
|
||||
runtime_approval_policy_override: None,
|
||||
runtime_sandbox_policy_override: None,
|
||||
@@ -87,8 +84,9 @@ async fn make_test_app() -> App {
|
||||
backtrack_render_pending: false,
|
||||
feedback: codex_feedback::CodexFeedback::new(),
|
||||
feedback_audience: FeedbackAudience::External,
|
||||
remote_app_server_url: None,
|
||||
remote_app_server_auth_token: None,
|
||||
pending_update_action: None,
|
||||
suppress_shutdown_complete: false,
|
||||
pending_shutdown_exit_thread_id: None,
|
||||
windows_sandbox: WindowsSandboxState::default(),
|
||||
thread_event_channels: HashMap::new(),
|
||||
@@ -97,14 +95,16 @@ async fn make_test_app() -> App {
|
||||
active_thread_id: None,
|
||||
active_thread_rx: None,
|
||||
primary_thread_id: None,
|
||||
last_subagent_backfill_attempt: None,
|
||||
primary_session_configured: None,
|
||||
pending_primary_events: VecDeque::new(),
|
||||
pending_app_server_requests: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_chat_widget(app: &mut App) {
|
||||
let rollout_file = NamedTempFile::new().expect("rollout file");
|
||||
app.handle_codex_event_now(Event {
|
||||
app.chat_widget.handle_codex_event(Event {
|
||||
id: "configured".to_string(),
|
||||
msg: EventMsg::SessionConfigured(SessionConfiguredEvent {
|
||||
session_id: ThreadId::new(),
|
||||
@@ -114,7 +114,7 @@ fn configure_chat_widget(app: &mut App) {
|
||||
model_provider_id: "test-provider".to_string(),
|
||||
service_tier: None,
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: codex_core::config::types::ApprovalsReviewer::User,
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
cwd: PathBuf::from("/tmp/worktree"),
|
||||
reasoning_effort: Some(ReasoningEffortConfig::XHigh),
|
||||
@@ -216,7 +216,7 @@ async fn fork_session_overlay_open_from_inline_viewport_snapshot() {
|
||||
terminal.set_viewport_area(Rect::new(0, height - 7, width, 7));
|
||||
|
||||
app.fork_session_overlay = Some(ForkSessionOverlayStack::new(ForkSessionOverlayState {
|
||||
terminal: ForkSessionTerminal::for_test(child, None),
|
||||
terminal: ForkSessionTerminal::for_test(child, /*exit_code*/ None),
|
||||
popup: default_popup_rect(Rect::new(0, 0, width, height)),
|
||||
command_state: OverlayCommandState::PassThrough,
|
||||
drag_state: None,
|
||||
|
||||
@@ -423,7 +423,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
encode_key_event(
|
||||
KeyEvent::new(KeyCode::Char('c'), KeyModifiers::CONTROL),
|
||||
false
|
||||
/*application_cursor*/ false
|
||||
),
|
||||
Some(vec![0x03])
|
||||
);
|
||||
@@ -432,7 +432,10 @@ mod tests {
|
||||
#[test]
|
||||
fn alt_left_uses_word_motion_fallback() {
|
||||
assert_eq!(
|
||||
encode_key_event(KeyEvent::new(KeyCode::Left, KeyModifiers::ALT), false),
|
||||
encode_key_event(
|
||||
KeyEvent::new(KeyCode::Left, KeyModifiers::ALT),
|
||||
/*application_cursor*/ false,
|
||||
),
|
||||
Some(b"\x1bb".to_vec())
|
||||
);
|
||||
}
|
||||
@@ -440,7 +443,7 @@ mod tests {
|
||||
#[test]
|
||||
fn bracketed_paste_wraps_contents() {
|
||||
assert_eq!(
|
||||
encode_paste(true, "hello"),
|
||||
encode_paste(/*bracketed_paste*/ true, "hello"),
|
||||
b"\x1b[200~hello\x1b[201~".to_vec()
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ >_ OpenAI Codex (v0.0.0) │
|
||||
│ │
|
||||
│ model: gpt-5.3-codex /model to change │
|
||||
│ directory: ~/code/codex/codex-rs/tui │
|
||||
│ directory: /tmp/project │
|
||||
╰─────────────────────────────────────────────╯
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@ expression: snapshot_buffer(&buf)
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
? for shortcuts 100% context left
|
||||
gpt-5.3-codex default · 100% left · /tmp/project
|
||||
|
||||
+2
-2
@@ -6,10 +6,10 @@ expression: snapshot_buffer(&buf)
|
||||
│ >_ OpenAI Codex (v0.0.0) │
|
||||
│ │
|
||||
│ model: gpt-5.3-codex /model to change │
|
||||
│ directory: ~/code/codex/codex-rs/tui │
|
||||
│ directory: /tmp/project │
|
||||
╰─────────────────────────────────────────────╯
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
? for shortcuts 100% context left
|
||||
gpt-5.3-codex default · 100% left · /tmp/project
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ >_ OpenAI Codex (v0.0.0) │
|
||||
│ │
|
||||
│ model: gpt-5.3-codex /model to change │
|
||||
│ directory: ~/code/codex/codex-rs/tui │
|
||||
│ directory: /tmp/project │
|
||||
╰─────────────────────────────────────────────╯
|
||||
|
||||
╭ fork session running ctrl+] prefix───────────────╮
|
||||
@@ -16,7 +16,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ ╭ fork session running ctrl+] prefix───────────────╮
|
||||
› Ask Codex to│ │Second fork session │
|
||||
│ │ │
|
||||
? for shortc│ │> /tmp/second │ 100% context left
|
||||
gpt-5.3-code│ │> /tmp/second │
|
||||
│ │ │
|
||||
│ │ │
|
||||
│ │ │
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ >_ OpenAI Codex (v0.0.0) │
|
||||
│ │
|
||||
│ model: gpt-5.3-codex /model to change │
|
||||
│ directory: ~/code/codex/codex-rs/tui │
|
||||
│ directory: /tmp/project │
|
||||
╰─────────────────────────────────────────────╯
|
||||
╭ fork session running ctrl+] prefix───────────────────────────╮
|
||||
│Independent Codex session │
|
||||
@@ -16,7 +16,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ready for a fresh turn │
|
||||
› Ask Codex to do │ │
|
||||
│ │
|
||||
? for shortcuts │ │00% context left
|
||||
gpt-5.3-codex de│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ >_ OpenAI Codex (v0.0.0) │
|
||||
│ │
|
||||
│ model: gpt-5.3-codex /model to change │
|
||||
│ directory: ~/code/codex/codex-rs/tui │
|
||||
│ directory: /tmp/project │
|
||||
╰─────────────────────────────────────────────╯
|
||||
╭ fork session running ctrl+] prefix───────────────────────────╮
|
||||
│Independent Codex session │
|
||||
@@ -16,7 +16,7 @@ expression: snapshot_buffer(&buf)
|
||||
│ready for a fresh turn │
|
||||
› Ask Codex to do │ │
|
||||
│ │
|
||||
? for shortcuts │ │00% context left
|
||||
gpt-5.3-codex de│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
|
||||
@@ -155,10 +155,10 @@ mod updates;
|
||||
mod version;
|
||||
#[cfg(all(not(target_os = "linux"), feature = "voice-input"))]
|
||||
mod voice;
|
||||
mod vt100_backend;
|
||||
mod vt100_render;
|
||||
#[cfg(all(not(target_os = "linux"), not(feature = "voice-input")))]
|
||||
mod voice;
|
||||
mod vt100_backend;
|
||||
mod vt100_render;
|
||||
#[cfg(target_os = "linux")]
|
||||
#[allow(dead_code)]
|
||||
mod voice {
|
||||
|
||||
@@ -497,18 +497,18 @@ pub const XTERM_COLORS: [(u8, u8, u8); 256] = [
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::parse_bg_rgb_env;
|
||||
use super::parse_rgb_env;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn parse_bg_rgb_env_accepts_rgb_triplet() {
|
||||
assert_eq!(parse_bg_rgb_env("12,34,56"), Some((12, 34, 56)));
|
||||
fn parse_rgb_env_accepts_rgb_triplet() {
|
||||
assert_eq!(parse_rgb_env("12,34,56"), Some((12, 34, 56)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_bg_rgb_env_rejects_invalid_values() {
|
||||
assert_eq!(parse_bg_rgb_env("12,34"), None);
|
||||
assert_eq!(parse_bg_rgb_env("12,34,56,78"), None);
|
||||
assert_eq!(parse_bg_rgb_env("12,nope,56"), None);
|
||||
fn parse_rgb_env_rejects_invalid_values() {
|
||||
assert_eq!(parse_rgb_env("12,34"), None);
|
||||
assert_eq!(parse_rgb_env("12,34,56,78"), None);
|
||||
assert_eq!(parse_rgb_env("12,nope,56"), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user