Codex Handbook
tui/src/chatwidget/constructor.rs 279 lines
//! Construction and initial wiring for `ChatWidget`.use super::*;impl ChatWidget {    pub(crate) fn new_with_app_event(common: ChatWidgetInit) -> Self {        Self::new_with_op_target(common, CodexOpTarget::AppEvent)    }    pub(super) fn new_with_op_target(        common: ChatWidgetInit,        codex_op_target: CodexOpTarget,    ) -> Self {        let ChatWidgetInit {            config,            frame_requester,            app_event_tx,            workspace_command_runner,            initial_user_message,            enhanced_keys_supported,            has_chatgpt_account,            has_codex_backend_auth,            model_catalog,            feedback,            is_first_run,            status_account_display,            runtime_model_provider_base_url,            initial_plan_type,            model,            startup_tooltip_override,            status_line_invalid_items_warned,            terminal_title_invalid_items_warned,            session_telemetry,        } = common;        let model = model.filter(|m| !m.trim().is_empty());        let mut config = config;        config.model = model.clone();        let prevent_idle_sleep = config.features.enabled(Feature::PreventIdleSleep);        let mut rng = rand::rng();        let placeholder = PLACEHOLDERS[rng.random_range(0..PLACEHOLDERS.len())].to_string();        let side_placeholder =            SIDE_PLACEHOLDERS[rng.random_range(0..SIDE_PLACEHOLDERS.len())].to_string();        let model_override = model.as_deref();        let model_for_header = model            .clone()            .unwrap_or_else(|| DEFAULT_MODEL_DISPLAY_NAME.to_string());        let active_collaboration_mask =            Self::initial_collaboration_mask(&config, model_catalog.as_ref(), model_override);        let header_model = active_collaboration_mask            .as_ref()            .and_then(|mask| mask.model.clone())            .unwrap_or_else(|| model_for_header.clone());        let fallback_default = Settings {            model: header_model.clone(),            reasoning_effort: None,            developer_instructions: None,        };        // Collaboration modes start in Default mode.        let current_collaboration_mode = CollaborationMode {            mode: ModeKind::Default,            settings: fallback_default,        };        let active_cell = Some(Self::placeholder_session_header_cell(&config));        let current_cwd = Some(config.cwd.to_path_buf());        let effective_service_tier = crate::service_tier_resolution::effective_service_tier(            &config,            &header_model,            &model_catalog.try_list_models().unwrap_or_default(),        );        let current_terminal_info = terminal_info();        let runtime_keymap = RuntimeKeymap::from_config(&config.tui_keymap).ok();        let default_keymap = RuntimeKeymap::defaults();        let copy_last_response_binding = runtime_keymap            .as_ref()            .map(|keymap| keymap.app.copy.clone())            .unwrap_or_else(|| default_keymap.app.copy.clone());        let chat_keymap = runtime_keymap            .as_ref()            .map(|keymap| keymap.chat.clone())            .unwrap_or_else(|| default_keymap.chat.clone());        let queued_message_edit_hint_binding = queued_message_edit_hint_binding(            &chat_keymap.edit_queued_message,            current_terminal_info,        );        pets::start_configured_pet_load_if_needed(            &config,            /*ambient_pet_missing*/ true,            frame_requester.clone(),            app_event_tx.clone(),        );        let mut widget = Self {            app_event_tx: app_event_tx.clone(),            frame_requester: frame_requester.clone(),            codex_op_target,            bottom_pane: BottomPane::new(BottomPaneParams {                frame_requester,                app_event_tx,                has_input_focus: true,                enhanced_keys_supported,                placeholder_text: placeholder.clone(),                disable_paste_burst: config.disable_paste_burst,                animations_enabled: config.animations,                skills: None,            }),            transcript: TranscriptState::new(active_cell),            raw_output_mode: config.tui_raw_output_mode,            config,            effective_service_tier,            skills_all: Vec::new(),            skills_initial_state: None,            current_collaboration_mode,            active_collaboration_mask,            has_chatgpt_account,            has_codex_backend_auth,            model_catalog,            session_telemetry,            session_header: SessionHeader::new(header_model),            initial_user_message,            status_account_display,            runtime_model_provider_base_url,            remote_connection: None,            token_info: None,            rate_limit_snapshots_by_limit_id: BTreeMap::new(),            refreshing_status_outputs: Vec::new(),            next_status_refresh_request_id: 0,            refreshing_token_activity_output: None,            completed_token_activity_output: None,            next_token_activity_request_id: 0,            pending_rate_limit_reset_request_id: None,            pending_rate_limit_reset_hint_request_id: None,            pending_rate_limit_reset_hint: None,            available_rate_limit_reset_credits: None,            next_rate_limit_reset_request_id: 0,            plan_type: initial_plan_type,            codex_rate_limit_reached_type: None,            rate_limit_warnings: RateLimitWarningState::default(),            warning_display_state: WarningDisplayState::default(),            rate_limit_switch_prompt: RateLimitSwitchPromptState::default(),            add_credits_nudge_email_in_flight: None,            adaptive_chunking: AdaptiveChunkingPolicy::default(),            stream_controller: None,            plan_stream_controller: None,            pending_stream_consolidations: 0,            clipboard_lease: None,            copy_last_response_binding,            running_commands: HashMap::new(),            collab_agent_metadata: HashMap::new(),            pending_collab_spawn_requests: HashMap::new(),            suppressed_exec_calls: HashSet::new(),            last_unified_wait: None,            unified_exec_wait_streak: None,            turn_lifecycle: TurnLifecycleState::new(prevent_idle_sleep),            task_complete_pending: false,            unified_exec_processes: Vec::new(),            mcp_startup_status: None,            mcp_startup_expected_servers: None,            mcp_startup_ignore_updates_until_next_start: false,            mcp_startup_allow_terminal_only_next_round: false,            mcp_startup_pending_next_round: HashMap::new(),            mcp_startup_pending_next_round_saw_starting: false,            connectors: ConnectorsState::default(),            ide_context: IdeContextState::default(),            plugins_cache: PluginsCacheState::default(),            plugins_fetch_state: PluginListFetchState::default(),            plugin_remote_sections_loading: false,            plugin_remote_sections_loaded: false,            plugin_remote_section_errors: Vec::new(),            plugin_install_apps_needing_auth: Vec::new(),            plugin_install_auth_flow: None,            plugins_active_tab_id: None,            newly_installed_marketplace_tab_id: None,            interrupts: InterruptManager::new(),            reasoning_buffer: String::new(),            full_reasoning_buffer: String::new(),            status_state: StatusState::default(),            review: ReviewState::default(),            active_hook_cell: None,            ambient_pet: None,            pet_picker_preview_state: crate::pets::PetPickerPreviewState::default(),            pet_picker_preview_pet: None,            pet_picker_preview_request_id: 0,            pet_picker_preview_image_visible: std::cell::Cell::new(/*value*/ false),            pet_selection_load_request_id: 0,            #[cfg(test)]            pet_image_support_override: None,            thread_id: None,            dismissed_plan_mode_nudge_scopes: HashSet::new(),            thread_name: None,            thread_rename_block_message: None,            active_side_conversation: false,            normal_placeholder_text: placeholder,            side_placeholder_text: side_placeholder,            forked_from: None,            interrupted_turn_notice_mode: InterruptedTurnNoticeMode::Default,            input_queue: InputQueueState::default(),            cancel_edit: CancelEditState::default(),            chat_keymap,            queued_message_edit_hint_binding,            show_welcome_banner: is_first_run,            startup_tooltip_override,            suppress_session_configured_redraw: false,            suppress_initial_user_message_submit: false,            pending_notification: None,            quit_shortcut_expires_at: None,            quit_shortcut_key: None,            turn_runtime_metrics: RuntimeMetricsSummary::default(),            last_rendered_width: std::cell::Cell::new(None),            feedback,            current_rollout_path: None,            current_cwd,            workspace_command_runner,            instruction_source_paths: Vec::new(),            session_network_proxy: None,            status_line_invalid_items_warned,            terminal_title_invalid_items_warned,            last_terminal_title: None,            last_terminal_title_requires_action: false,            terminal_title_setup_original_items: None,            terminal_title_animation_origin: Instant::now(),            status_line_project_root_name_cache: None,            status_line_branch: None,            status_line_branch_cwd: None,            status_line_branch_pending: false,            status_line_branch_lookup_complete: false,            status_line_git_summary: None,            status_line_git_summary_cwd: None,            status_line_git_summary_pending: false,            status_line_git_summary_lookup_complete: false,            current_goal_status_indicator: None,            current_goal_status: None,            external_editor_state: ExternalEditorState::Closed,            last_rendered_user_message_display: None,            last_non_retry_error: None,        };        widget.prefetch_rate_limits();        if let Some(keymap) = runtime_keymap {            widget.bottom_pane.set_keymap_bindings(&keymap);        }        widget            .bottom_pane            .set_vim_enabled(widget.config.tui_vim_mode_default);        widget            .bottom_pane            .set_status_line_enabled(!widget.configured_status_line_items().is_empty());        widget            .bottom_pane            .set_collaboration_modes_enabled(/*enabled*/ true);        widget.sync_service_tier_commands();        widget.sync_personality_command_enabled();        widget.sync_plugins_command_enabled();        widget.sync_goal_command_enabled();        widget.sync_mentions_v2_enabled();        widget            .bottom_pane            .set_queued_message_edit_binding(widget.queued_message_edit_hint_binding);        #[cfg(target_os = "windows")]        widget            .bottom_pane            .set_windows_degraded_sandbox_active(matches!(                crate::windows_sandbox::level_from_config(&widget.config),                WindowsSandboxLevel::RestrictedToken            ));        widget.update_collaboration_mode_indicator();        widget            .bottom_pane            .set_connectors_enabled(widget.connectors_enabled());        widget            .bottom_pane            .set_token_activity_command_enabled(widget.has_codex_backend_auth);        widget.refresh_status_surfaces();        widget    }}