Skip to main content

systemprompt_models/services/
mod.rs

1//! `services` module — see crate-level docs for context.
2
3pub mod agent_config;
4pub mod ai;
5pub mod external_agent;
6pub mod frontmatter;
7pub mod hooks;
8mod includable;
9pub mod marketplace;
10pub mod mcp;
11pub mod plugin;
12pub mod runtime;
13pub mod scheduler;
14pub mod settings;
15pub mod skills;
16pub mod system_admin;
17mod validation;
18
19pub use includable::IncludableString;
20
21pub use agent_config::{
22    AGENT_CONFIG_FILENAME, AgentCardConfig, AgentConfig, AgentMetadataConfig, AgentProviderInfo,
23    AgentSkillConfig, AgentSummary, CapabilitiesConfig, DEFAULT_AGENT_SYSTEM_PROMPT_FILE,
24    DiskAgentConfig, OAuthConfig,
25};
26pub use ai::{
27    AiConfig, AiProviderConfig, HistoryConfig, McpConfig, ModelCapabilities, ModelDefinition,
28    ModelLimits, ModelPricing, ResilienceSettings, SamplingConfig,
29};
30pub use external_agent::{ExternalAgentConfig, ExternalAgentKind};
31pub use frontmatter::{Frontmatter, split_frontmatter, strip_frontmatter};
32pub use hooks::{
33    DiskHookConfig, HOOK_CONFIG_FILENAME, HookAction, HookCategory, HookEvent, HookEventsConfig,
34    HookMatcher, HookType,
35};
36pub use marketplace::{
37    MarketplaceAccess, MarketplaceConfig, MarketplaceConfigFile, MarketplaceVisibility,
38};
39pub use mcp::McpServerSummary;
40pub use plugin::{
41    ComponentFilter, ComponentSource, PluginAuthor, PluginComponentRef, PluginConfig,
42    PluginConfigFile, PluginScript, PluginSummary, PluginVariableDef,
43};
44pub use runtime::{RuntimeStatus, ServiceType};
45pub use scheduler::*;
46pub use settings::*;
47pub use skills::{
48    DEFAULT_SKILL_CONTENT_FILE, DiskSkillConfig, SKILL_CONFIG_FILENAME, SkillConfig, SkillDetail,
49    SkillSummary, SkillsConfig,
50};
51pub use system_admin::{SystemAdmin, SystemAdminConfig};
52pub use systemprompt_provider_contracts::{BrandingConfig, WebConfig};
53
54use crate::errors::ConfigValidationError;
55use crate::mcp::Deployment;
56use serde::{Deserialize, Serialize};
57use std::collections::HashMap;
58use systemprompt_identifiers::{ExternalAgentId, MarketplaceId};
59
60/// The single canonical shape of a services config file.
61///
62/// A root config file and an include file deserialize into the same struct.
63/// `settings` is meaningful only at the root; the loader rejects an include
64/// that sets it (`ConfigLoadError::IncludeMustNotSetGlobalSettings`) rather
65/// than silently ignoring the value.
66#[derive(Debug, Clone, Default, Serialize, Deserialize)]
67#[serde(deny_unknown_fields)]
68pub struct ServicesConfig {
69    #[serde(default)]
70    pub includes: Vec<String>,
71    #[serde(default)]
72    pub settings: Settings,
73    #[serde(default)]
74    pub agents: HashMap<String, AgentConfig>,
75    #[serde(default)]
76    pub mcp_servers: HashMap<String, Deployment>,
77    #[serde(default)]
78    pub scheduler: Option<SchedulerConfig>,
79    #[serde(default)]
80    pub ai: AiConfig,
81    #[serde(default)]
82    pub web: Option<WebConfig>,
83    #[serde(default)]
84    pub plugins: HashMap<String, PluginConfig>,
85    #[serde(default)]
86    pub marketplaces: HashMap<MarketplaceId, MarketplaceConfig>,
87    #[serde(default)]
88    pub skills: SkillsConfig,
89    #[serde(default)]
90    pub external_agents: HashMap<ExternalAgentId, ExternalAgentConfig>,
91}
92
93impl ServicesConfig {
94    pub fn validate(&self) -> Result<(), ConfigValidationError> {
95        self.validate_ports()?;
96        self.validate_single_default_agent()?;
97
98        for (name, agent) in &self.agents {
99            agent.validate(name)?;
100        }
101
102        for (name, mcp) in &self.mcp_servers {
103            mcp.validate(name)?;
104        }
105
106        for (name, plugin) in &self.plugins {
107            plugin.validate(name)?;
108            self.validate_plugin_bindings(name, plugin)?;
109        }
110
111        for (id, marketplace) in &self.marketplaces {
112            marketplace.validate(id.as_str())?;
113            self.validate_marketplace_bindings(id.as_str(), marketplace)?;
114        }
115
116        self.validate_default_marketplace_selector()?;
117
118        Ok(())
119    }
120}