Codex Handbook
tui/src/chatwidget/ide_context.rs 132 lines
//! Chat-widget wiring for the `/ide` command and IDE context prompt injection.use codex_app_server_protocol::UserInput;use super::ChatWidget;#[derive(Default)]pub(super) struct IdeContextState {    enabled: bool,    prompt_fetch_warned: bool,}impl IdeContextState {    pub(super) fn is_enabled(&self) -> bool {        self.enabled    }    fn enable(&mut self) {        self.enabled = true;        self.prompt_fetch_warned = false;    }    fn disable(&mut self) {        self.enabled = false;        self.prompt_fetch_warned = false;    }    fn mark_available(&mut self) {        self.prompt_fetch_warned = false;    }}impl ChatWidget {    pub(super) fn handle_ide_command(&mut self) {        if self.ide_context.is_enabled() {            self.ide_context.disable();            self.sync_ide_context_status_indicator();            self.add_info_message("IDE context is off.".to_string(), /*hint*/ None);        } else {            self.ide_context.enable();            self.add_ide_context_status_message();        }    }    pub(super) fn handle_ide_command_args(&mut self, args: &str) {        match args.to_ascii_lowercase().as_str() {            "" => self.handle_ide_command(),            "on" => {                self.ide_context.enable();                self.add_ide_context_status_message();            }            "off" => {                self.ide_context.disable();                self.sync_ide_context_status_indicator();                self.add_info_message("IDE context is off.".to_string(), /*hint*/ None);            }            "status" => {                self.add_ide_context_status_message();            }            _ => {                self.add_error_message("Usage: /ide [on|off|status]".to_string());            }        }    }    /// Fetches fresh IDE context for the outgoing user turn and folds it into the prompt.    pub(super) fn maybe_apply_ide_context(&mut self, items: &mut Vec<UserInput>) {        if !self.ide_context.is_enabled() {            return;        }        match crate::ide_context::fetch_ide_context(&self.config.cwd) {            Ok(context) => {                self.ide_context.mark_available();                self.sync_ide_context_status_indicator();                crate::ide_context::apply_ide_context_to_user_input(&context, items);            }            Err(err) => {                self.sync_ide_context_status_indicator();                if !self.ide_context.prompt_fetch_warned {                    self.ide_context.prompt_fetch_warned = true;                    self.add_info_message(                        "IDE context was skipped for this message.".to_string(),                        Some(err.prompt_skip_hint()),                    );                }            }        }    }    fn add_ide_context_status_message(&mut self) {        if !self.ide_context.is_enabled() {            self.sync_ide_context_status_indicator();            self.add_info_message("IDE context is off.".to_string(), /*hint*/ None);            return;        }        match crate::ide_context::fetch_ide_context(&self.config.cwd) {            Ok(context) => {                self.ide_context.mark_available();                self.sync_ide_context_status_indicator();                if crate::ide_context::has_prompt_context(&context) {                    self.add_info_message(                        "IDE context is on.".to_string(),                        Some(                            "Future messages will include your current IDE selection and open tabs."                                .to_string(),                        ),                    );                } else {                    self.add_info_message(                        "IDE context is on.".to_string(),                        Some("Connected to your IDE.".to_string()),                    );                }            }            Err(err) => {                self.ide_context.disable();                self.sync_ide_context_status_indicator();                self.add_info_message(                    "IDE context could not be enabled.".to_string(),                    Some(err.user_facing_hint()),                );            }        }    }    pub(super) fn sync_ide_context_status_indicator(&mut self) {        self.bottom_pane            .set_ide_context_active(self.ide_context.is_enabled());    }}