use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use zeph_common::secret::Secret;
use zeph_tools::ToolsConfig;
use crate::agent::{AgentConfig, FocusConfig, SubAgentConfig};
use crate::channels::{A2aServerConfig, DiscordConfig, McpConfig, SlackConfig, TelegramConfig};
use crate::classifiers::ClassifiersConfig;
use crate::defaults::{default_skill_paths, default_sqlite_path_field};
use crate::experiment::{ExperimentConfig, OrchestrationConfig};
use crate::features::{
CostConfig, DaemonConfig, DebugConfig, GatewayConfig, IndexConfig, ObservabilityConfig,
SchedulerConfig, SkillPromptMode, SkillsConfig, VaultConfig,
};
use crate::learning::LearningConfig;
use crate::logging::LoggingConfig;
use crate::memory::{
CompressionConfig, DocumentConfig, GraphConfig, MemoryConfig, RoutingConfig, SemanticConfig,
SessionsConfig, SidequestConfig, TierConfig, VectorBackend,
};
use crate::providers::{
LlmConfig, get_default_embedding_model, get_default_response_cache_ttl_secs,
get_default_router_ema_alpha, get_default_router_reorder_interval,
};
use crate::security::TrustConfig;
use crate::security::{SecurityConfig, TimeoutConfig};
use crate::ui::{AcpConfig, TuiConfig};
#[cfg(feature = "lsp-context")]
use crate::ui::LspConfig;
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
pub agent: AgentConfig,
pub llm: LlmConfig,
pub skills: SkillsConfig,
pub memory: MemoryConfig,
#[serde(skip_serializing_if = "Option::is_none")]
pub telegram: Option<TelegramConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub discord: Option<DiscordConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub slack: Option<SlackConfig>,
#[serde(default)]
pub tools: ToolsConfig,
#[serde(default)]
pub a2a: A2aServerConfig,
#[serde(default)]
pub mcp: McpConfig,
#[serde(default)]
pub index: IndexConfig,
#[serde(default)]
pub vault: VaultConfig,
#[serde(default)]
pub security: SecurityConfig,
#[serde(default)]
pub timeouts: TimeoutConfig,
#[serde(default)]
pub cost: CostConfig,
#[serde(default)]
pub observability: ObservabilityConfig,
#[serde(default)]
pub gateway: GatewayConfig,
#[serde(default)]
pub daemon: DaemonConfig,
#[serde(default)]
pub scheduler: SchedulerConfig,
#[serde(default)]
pub tui: TuiConfig,
#[serde(default)]
pub acp: AcpConfig,
#[serde(default)]
pub agents: SubAgentConfig,
#[serde(default)]
pub orchestration: OrchestrationConfig,
#[serde(default)]
pub classifiers: ClassifiersConfig,
#[serde(default)]
pub experiments: ExperimentConfig,
#[serde(default)]
pub debug: DebugConfig,
#[serde(default)]
pub logging: LoggingConfig,
#[cfg(feature = "lsp-context")]
#[serde(default)]
pub lsp: LspConfig,
#[serde(skip)]
pub secrets: ResolvedSecrets,
}
#[derive(Debug, Default)]
pub struct ResolvedSecrets {
pub claude_api_key: Option<Secret>,
pub openai_api_key: Option<Secret>,
pub gemini_api_key: Option<Secret>,
pub compatible_api_keys: HashMap<String, Secret>,
pub discord_token: Option<Secret>,
pub slack_bot_token: Option<Secret>,
pub slack_signing_secret: Option<Secret>,
pub custom: HashMap<String, Secret>,
}
impl Default for Config {
#[allow(clippy::too_many_lines)] fn default() -> Self {
Self {
agent: AgentConfig {
name: "Zeph".into(),
max_tool_iterations: 10,
auto_update_check: true,
instruction_files: Vec::new(),
instruction_auto_detect: true,
max_tool_retries: 2,
tool_repeat_threshold: 2,
max_retry_duration_secs: 30,
focus: FocusConfig::default(),
tool_filter: crate::agent::ToolFilterConfig::default(),
},
llm: LlmConfig {
providers: Vec::new(),
routing: crate::providers::LlmRoutingStrategy::None,
routes: std::collections::HashMap::new(),
embedding_model: get_default_embedding_model(),
candle: None,
stt: None,
response_cache_enabled: false,
response_cache_ttl_secs: get_default_response_cache_ttl_secs(),
semantic_cache_enabled: false,
semantic_cache_threshold: 0.95,
semantic_cache_max_candidates: 10,
router_ema_enabled: false,
router_ema_alpha: get_default_router_ema_alpha(),
router_reorder_interval: get_default_router_reorder_interval(),
router: None,
instruction_file: None,
summary_model: None,
summary_provider: None,
complexity_routing: None,
},
skills: SkillsConfig {
paths: default_skill_paths(),
max_active_skills: 5,
disambiguation_threshold: 0.05,
cosine_weight: 0.7,
hybrid_search: true,
learning: LearningConfig::default(),
trust: TrustConfig::default(),
prompt_mode: SkillPromptMode::Auto,
two_stage_matching: false,
confusability_threshold: 0.0,
},
memory: MemoryConfig {
sqlite_path: default_sqlite_path_field(),
history_limit: 50,
qdrant_url: "http://localhost:6334".into(),
semantic: SemanticConfig::default(),
summarization_threshold: 50,
context_budget_tokens: 0,
soft_compaction_threshold: 0.60,
hard_compaction_threshold: 0.90,
compaction_preserve_tail: 6,
compaction_cooldown_turns: 2,
auto_budget: true,
prune_protect_tokens: 40_000,
cross_session_score_threshold: 0.35,
vector_backend: VectorBackend::default(),
token_safety_margin: 1.0,
redact_credentials: true,
autosave_assistant: true,
autosave_min_length: 20,
tool_call_cutoff: 6,
sqlite_pool_size: 5,
sessions: SessionsConfig::default(),
documents: DocumentConfig::default(),
eviction: zeph_memory::EvictionConfig::default(),
compression: CompressionConfig::default(),
sidequest: SidequestConfig::default(),
routing: RoutingConfig::default(),
graph: GraphConfig::default(),
compression_guidelines: zeph_memory::CompressionGuidelinesConfig::default(),
shutdown_summary: true,
shutdown_summary_min_messages: 4,
shutdown_summary_max_messages: 20,
shutdown_summary_timeout_secs: 10,
structured_summaries: false,
tiers: TierConfig::default(),
admission: crate::memory::AdmissionConfig::default(),
digest: crate::memory::DigestConfig::default(),
context_strategy: crate::memory::ContextStrategy::default(),
crossover_turn_threshold: 20,
consolidation: crate::memory::ConsolidationConfig::default(),
database_url: None,
store_routing: crate::memory::StoreRoutingConfig::default(),
},
telegram: None,
discord: None,
slack: None,
tools: ToolsConfig::default(),
a2a: A2aServerConfig::default(),
mcp: McpConfig::default(),
index: IndexConfig::default(),
vault: VaultConfig::default(),
security: SecurityConfig::default(),
timeouts: TimeoutConfig::default(),
cost: CostConfig::default(),
observability: ObservabilityConfig::default(),
gateway: GatewayConfig::default(),
daemon: DaemonConfig::default(),
scheduler: SchedulerConfig::default(),
tui: TuiConfig::default(),
acp: AcpConfig::default(),
agents: SubAgentConfig::default(),
orchestration: OrchestrationConfig::default(),
classifiers: ClassifiersConfig::default(),
experiments: ExperimentConfig::default(),
debug: DebugConfig::default(),
logging: LoggingConfig::default(),
#[cfg(feature = "lsp-context")]
lsp: LspConfig::default(),
secrets: ResolvedSecrets::default(),
}
}
}