Skip to main content

systemprompt_models/services/
mod.rs

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