#[cfg(feature = "unstable-llm-providers")]
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use parking_lot::{Mutex, RwLock};
use tokio_util::sync::CancellationToken;
use agent_client_protocol as acp;
use zeph_common::task_supervisor::TaskSupervisor;
use zeph_core::{ContentIsolationConfig, ContentSanitizer};
use zeph_mcp::McpManager;
use zeph_memory::store::SqliteStore;
use crate::lsp::DiagnosticsCache;
use crate::transport::SharedAvailableModels;
use super::{AgentSpawner, ProviderFactory, ZephAcpAgentState};
impl ZephAcpAgentState {
pub fn new(
spawner: AgentSpawner,
max_sessions: usize,
session_idle_timeout_secs: u64,
permission_file: Option<std::path::PathBuf>,
) -> Self {
let lsp_config = zeph_core::config::AcpLspConfig::default();
let max_diag_files = lsp_config.max_diagnostic_files;
let reaper_cancel = CancellationToken::new();
let task_supervisor = TaskSupervisor::new(reaper_cancel.clone());
Self {
spawner,
sessions: Arc::new(Mutex::new(std::collections::HashMap::new())),
agent_name: "zeph".to_owned(),
agent_version: env!("CARGO_PKG_VERSION").to_owned(),
max_sessions,
idle_timeout: std::time::Duration::from_secs(session_idle_timeout_secs),
store: None,
session_data_dir: None,
permission_file,
client_caps: RwLock::new(acp::schema::v1::ClientCapabilities::default()),
provider_factory: None,
available_models: Arc::new(RwLock::new(Vec::new())),
mcp_manager: None,
project_rules: Vec::new(),
title_max_chars: 60,
max_history: 100,
lsp_config,
diagnostics_cache: Arc::new(RwLock::new(DiagnosticsCache::new(max_diag_files))),
reaper_cancel,
task_supervisor,
additional_directories_allow: Vec::new(),
auth_methods_config: vec![zeph_core::config::AcpAuthMethod::Agent],
timeouts: zeph_config::AcpTimeoutsConfig::default(),
model_config: zeph_config::AcpModelConfigConfig::default(),
prompt_injection_detector: ContentSanitizer::new(&ContentIsolationConfig {
spotlight_untrusted: false,
..ContentIsolationConfig::default()
}),
#[cfg(feature = "unstable-elicitation")]
elicitation_supported: std::sync::atomic::AtomicBool::new(false),
#[cfg(feature = "unstable-llm-providers")]
provider_names: Vec::new(),
#[cfg(feature = "unstable-llm-providers")]
global_disabled_providers: Mutex::new(HashSet::new()),
#[cfg(feature = "unstable-llm-providers")]
global_provider_overrides: Mutex::new(HashMap::new()),
owner_key: crate::transport::OWNER_KEY_LOCAL.to_owned(),
}
}
#[must_use]
pub fn with_owner_key(mut self, owner_key: impl Into<String>) -> Self {
self.owner_key = owner_key.into();
self
}
#[must_use]
pub fn with_additional_directories(
mut self,
dirs: Vec<zeph_core::config::AdditionalDir>,
) -> Self {
self.additional_directories_allow = dirs
.into_iter()
.map(|d| d.as_path().to_path_buf())
.collect();
self
}
#[must_use]
pub fn with_auth_methods(mut self, methods: Vec<zeph_core::config::AcpAuthMethod>) -> Self {
self.auth_methods_config = methods;
self
}
#[must_use]
pub fn with_timeouts(mut self, timeouts: zeph_config::AcpTimeoutsConfig) -> Self {
self.timeouts = timeouts;
self
}
#[must_use]
pub fn with_model_config(mut self, model_config: zeph_config::AcpModelConfigConfig) -> Self {
self.model_config = model_config;
self
}
#[must_use]
pub fn with_lsp_config(mut self, config: zeph_core::config::AcpLspConfig) -> Self {
let max_files = config.max_diagnostic_files;
self.lsp_config = config;
self.diagnostics_cache = Arc::new(RwLock::new(DiagnosticsCache::new(max_files)));
self
}
#[must_use]
pub fn with_store(mut self, store: SqliteStore) -> Self {
self.store = Some(store);
self
}
#[must_use]
pub fn with_session_data_dir(mut self, data_dir: std::path::PathBuf) -> Self {
self.session_data_dir = Some(data_dir);
self
}
#[must_use]
pub fn with_agent_info(mut self, name: impl Into<String>, version: impl Into<String>) -> Self {
self.agent_name = name.into();
self.agent_version = version.into();
self
}
#[must_use]
pub fn with_provider_factory(
mut self,
factory: ProviderFactory,
available_models: SharedAvailableModels,
) -> Self {
self.provider_factory = Some(factory);
self.available_models = available_models;
self
}
pub(crate) fn available_models_snapshot(&self) -> Vec<String> {
self.available_models.read().clone()
}
pub(crate) fn initial_model(&self) -> String {
self.available_models_snapshot()
.into_iter()
.next()
.unwrap_or_default()
}
#[must_use]
pub fn with_mcp_manager(mut self, manager: Arc<McpManager>) -> Self {
self.mcp_manager = Some(manager);
self
}
#[must_use]
pub fn with_project_rules(mut self, rules: Vec<std::path::PathBuf>) -> Self {
self.project_rules = rules;
self
}
#[must_use]
pub fn with_title_max_chars(mut self, max_chars: usize) -> Self {
self.title_max_chars = max_chars;
self
}
#[must_use]
pub fn with_max_history(mut self, max_history: usize) -> Self {
self.max_history = max_history;
self
}
}