use super::*;
use crate::tui_internal::chatwidget::tests::make_chatwidget_manual_with_sender;
use lemurclaw_core::models_manager::test_support::construct_model_info_offline_for_tests;
use lemurclaw_core::models_manager::test_support::get_model_offline_for_tests;
pub(super) 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 file_search = FileSearchManager::new(config.cwd.to_path_buf(), app_event_tx.clone());
let model = get_model_offline_for_tests(config.model.as_deref());
let session_telemetry = test_session_telemetry(&config, model.as_str());
App {
model_catalog: chat_widget.model_catalog(),
session_telemetry,
app_event_tx,
chat_widget,
workspace_command_runner: None,
launch_cwd: config.cwd.to_path_buf(),
config,
state_db: None,
cli_kv_overrides: Vec::new(),
harness_overrides: ConfigOverrides::default(),
loader_overrides: LoaderOverrides::without_managed_config_for_tests(),
cloud_config_bundle: CloudConfigBundleLoader::default(),
runtime_approval_policy_override: None,
runtime_permission_profile_override: None,
file_search,
transcript_cells: Vec::new(),
overlay: None,
deferred_history_lines: Vec::new(),
has_emitted_history_lines: false,
transcript_reflow: TranscriptReflowState::default(),
initial_history_replay_buffer: None,
enhanced_keys_supported: false,
keymap: crate::tui_internal::keymap::RuntimeKeymap::defaults(),
commit_anim_running: Arc::new(AtomicBool::new(false)),
status_line_invalid_items_warned: Arc::new(AtomicBool::new(false)),
terminal_title_invalid_items_warned: Arc::new(AtomicBool::new(false)),
skill_load_warnings: SkillLoadWarningState::default(),
backtrack: BacktrackState::default(),
backtrack_render_pending: false,
feedback: lemurclaw_core::feedback::CodexFeedback::new(),
feedback_audience: FeedbackAudience::External,
environment_manager: Arc::new(EnvironmentManager::default_for_tests()),
app_server_target: crate::tui_internal::AppServerTarget::Embedded,
pending_update_action: None,
pending_shutdown_exit_thread_id: None,
windows_sandbox: WindowsSandboxState::default(),
thread_event_channels: HashMap::new(),
thread_event_listener_tasks: HashMap::new(),
agent_navigation: AgentNavigationState::default(),
side_threads: HashMap::new(),
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: PendingAppServerRequests::default(),
pending_startup_thread_start: false,
rate_limit_hard_stop_generation: 0,
pending_plugin_enabled_writes: HashMap::new(),
pending_hook_enabled_writes: HashMap::new(),
}
}
fn test_session_telemetry(config: &Config, model: &str) -> SessionTelemetry {
let model_info =
construct_model_info_offline_for_tests(model, &config.to_models_manager_config());
SessionTelemetry::new(
ThreadId::new(),
model,
model_info.slug.as_str(),
None,
None,
None,
"test_originator".to_string(),
false,
"test".to_string(),
serde_json::from_value(serde_json::json!("cli"))
.expect("cli session source should deserialize"),
)
}
pub(super) fn app_enabled_in_effective_config(config: &Config, app_id: &str) -> Option<bool> {
config
.config_layer_stack
.effective_config()
.as_table()
.and_then(|table| table.get("apps"))
.and_then(TomlValue::as_table)
.and_then(|apps| apps.get(app_id))
.and_then(TomlValue::as_table)
.and_then(|app| app.get("enabled"))
.and_then(TomlValue::as_bool)
}