use crate::config::acp::CustomAcpAgentConfig;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AssistantInputHistoryMode {
Session,
Persist,
}
impl AssistantInputHistoryMode {
pub const fn all() -> [Self; 2] {
[Self::Session, Self::Persist]
}
pub const fn label(self) -> &'static str {
match self {
Self::Session => "Session only",
Self::Persist => "Persist across restarts",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct AiInspectorConfig {
#[serde(default = "default_ai_inspector_enabled")]
pub ai_inspector_enabled: bool,
#[serde(default = "default_ai_inspector_open_on_startup")]
pub ai_inspector_open_on_startup: bool,
#[serde(default = "default_ai_inspector_width")]
pub ai_inspector_width: f32,
#[serde(default = "default_ai_inspector_default_scope")]
pub ai_inspector_default_scope: String,
#[serde(default = "default_ai_inspector_view_mode")]
pub ai_inspector_view_mode: String,
#[serde(default = "default_ai_inspector_live_update")]
pub ai_inspector_live_update: bool,
#[serde(default = "default_ai_inspector_show_zones")]
pub ai_inspector_show_zones: bool,
#[serde(default = "default_ai_inspector_agent")]
pub ai_inspector_agent: String,
#[serde(default = "default_ai_inspector_auto_launch")]
pub ai_inspector_auto_launch: bool,
#[serde(default = "default_ai_inspector_auto_context")]
pub ai_inspector_auto_context: bool,
#[serde(default = "default_ai_inspector_context_max_lines")]
pub ai_inspector_context_max_lines: usize,
#[serde(default = "default_ai_inspector_auto_approve")]
pub ai_inspector_auto_approve: bool,
#[serde(default = "default_ai_inspector_agent_terminal_access")]
pub ai_inspector_agent_terminal_access: bool,
#[serde(default = "default_ai_inspector_agent_screenshot_access")]
pub ai_inspector_agent_screenshot_access: bool,
#[serde(default = "default_ai_inspector_chat_font_size")]
pub ai_inspector_chat_font_size: f32,
#[serde(default = "default_ai_inspector_input_history_mode")]
pub ai_inspector_input_history_mode: AssistantInputHistoryMode,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub ai_inspector_extra_agent_roots: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub ai_inspector_custom_agents: Vec<CustomAcpAgentConfig>,
}
fn default_ai_inspector_enabled() -> bool {
true
}
fn default_ai_inspector_open_on_startup() -> bool {
false
}
fn default_ai_inspector_width() -> f32 {
300.0
}
fn default_ai_inspector_default_scope() -> String {
"visible".to_string()
}
fn default_ai_inspector_view_mode() -> String {
"tree".to_string()
}
fn default_ai_inspector_live_update() -> bool {
false
}
fn default_ai_inspector_show_zones() -> bool {
true
}
fn default_ai_inspector_agent() -> String {
"claude.com".to_string()
}
fn default_ai_inspector_auto_launch() -> bool {
false
}
fn default_ai_inspector_auto_context() -> bool {
false
}
fn default_ai_inspector_context_max_lines() -> usize {
200
}
fn default_ai_inspector_auto_approve() -> bool {
false
}
fn default_ai_inspector_agent_terminal_access() -> bool {
false
}
fn default_ai_inspector_agent_screenshot_access() -> bool {
true
}
fn default_ai_inspector_chat_font_size() -> f32 {
14.0
}
pub const fn default_ai_inspector_input_history_mode() -> AssistantInputHistoryMode {
AssistantInputHistoryMode::Session
}
impl Default for AiInspectorConfig {
fn default() -> Self {
Self {
ai_inspector_enabled: default_ai_inspector_enabled(),
ai_inspector_open_on_startup: default_ai_inspector_open_on_startup(),
ai_inspector_width: default_ai_inspector_width(),
ai_inspector_default_scope: default_ai_inspector_default_scope(),
ai_inspector_view_mode: default_ai_inspector_view_mode(),
ai_inspector_live_update: default_ai_inspector_live_update(),
ai_inspector_show_zones: default_ai_inspector_show_zones(),
ai_inspector_agent: default_ai_inspector_agent(),
ai_inspector_auto_launch: default_ai_inspector_auto_launch(),
ai_inspector_auto_context: default_ai_inspector_auto_context(),
ai_inspector_context_max_lines: default_ai_inspector_context_max_lines(),
ai_inspector_auto_approve: default_ai_inspector_auto_approve(),
ai_inspector_agent_terminal_access: default_ai_inspector_agent_terminal_access(),
ai_inspector_agent_screenshot_access: default_ai_inspector_agent_screenshot_access(),
ai_inspector_chat_font_size: default_ai_inspector_chat_font_size(),
ai_inspector_input_history_mode: default_ai_inspector_input_history_mode(),
ai_inspector_extra_agent_roots: Vec::new(),
ai_inspector_custom_agents: Vec::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::{AiInspectorConfig, AssistantInputHistoryMode};
#[test]
fn default_extra_agent_roots_is_empty() {
let config = AiInspectorConfig::default();
assert!(config.ai_inspector_extra_agent_roots.is_empty());
}
#[test]
fn deserializes_extra_agent_roots() {
let yaml = r#"
ai_inspector_extra_agent_roots:
- ~/Repos/shared
- /opt/project
"#;
let config: AiInspectorConfig = serde_yaml_ng::from_str(yaml).expect("deserialize");
assert_eq!(
config.ai_inspector_extra_agent_roots,
vec!["~/Repos/shared".to_string(), "/opt/project".to_string()]
);
}
#[test]
fn ai_inspector_input_history_default_mode_is_session() {
let config = AiInspectorConfig::default();
assert_eq!(
config.ai_inspector_input_history_mode,
AssistantInputHistoryMode::Session
);
}
#[test]
fn ai_inspector_input_history_deserializes_persist_mode() {
let yaml = "ai_inspector_input_history_mode: persist\n";
let config: AiInspectorConfig = serde_yaml_ng::from_str(yaml).expect("deserialize");
assert_eq!(
config.ai_inspector_input_history_mode,
AssistantInputHistoryMode::Persist
);
}
}