systemprompt_models/services/
teams.rs1use std::collections::BTreeMap;
16
17use schemars::JsonSchema;
18use serde::{Deserialize, Serialize};
19use systemprompt_identifiers::{AgentName, SecretName, TeamsTenantId};
20
21use crate::errors::ConfigValidationError;
22
23#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
24#[serde(deny_unknown_fields)]
25pub struct TeamsAppConfig {
26 pub tenant_id: TeamsTenantId,
27 pub app_id: String,
28 pub app_password_ref: SecretName,
29 #[serde(default = "default_enabled")]
30 pub enabled: bool,
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub default_agent: Option<AgentName>,
33 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
34 pub routing: BTreeMap<String, AgentName>,
35 #[serde(default)]
36 pub authz: TeamsAuthzConfig,
37}
38
39#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
40#[serde(deny_unknown_fields)]
41pub struct TeamsAuthzConfig {
42 #[serde(default)]
43 pub allowed_roles: Vec<String>,
44}
45
46const fn default_enabled() -> bool {
47 true
48}
49
50impl TeamsAppConfig {
51 #[must_use]
52 pub fn agent_for(&self, key: &str) -> Option<&AgentName> {
53 self.routing.get(key).or(self.default_agent.as_ref())
54 }
55
56 pub fn validate(&self, name: &str) -> Result<(), ConfigValidationError> {
57 if self.tenant_id.as_str().is_empty() {
58 return Err(ConfigValidationError::invalid_field(format!(
59 "teams app '{name}' has an empty tenant_id"
60 )));
61 }
62 if self.app_id.is_empty() {
63 return Err(ConfigValidationError::invalid_field(format!(
64 "teams app '{name}' has an empty app_id"
65 )));
66 }
67 if self.default_agent.is_none() && self.routing.is_empty() {
68 return Err(ConfigValidationError::required(format!(
69 "teams app '{name}' must set default_agent or at least one routing entry"
70 )));
71 }
72 Ok(())
73 }
74}