systemprompt_models/profile/gateway/
override_rule.rs1use serde::{Deserialize, Serialize};
15use systemprompt_identifiers::ProviderId;
16
17use super::error::{GatewayProfileError, GatewayResult};
18use super::route::match_pattern;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
21#[serde(rename_all = "snake_case")]
22pub enum OverrideRuleAction {
23 Replace,
24 Strip,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
28#[serde(deny_unknown_fields)]
29pub struct SystemPromptRule {
30 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub provider: Option<ProviderId>,
32 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub model_pattern: Option<String>,
34 pub action: OverrideRuleAction,
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub prompt: Option<String>,
37}
38
39impl SystemPromptRule {
40 #[must_use]
41 pub fn matches(&self, provider: &ProviderId, model: &str) -> bool {
42 let provider_ok = self
43 .provider
44 .as_ref()
45 .is_none_or(|p| p.as_str() == provider.as_str());
46 let model_ok = self
47 .model_pattern
48 .as_deref()
49 .is_none_or(|pat| match_pattern(pat, model));
50 provider_ok && model_ok
51 }
52
53 pub const fn validate(&self) -> GatewayResult<()> {
54 match self.action {
55 OverrideRuleAction::Replace if self.prompt.is_none() => {
56 Err(GatewayProfileError::OverrideReplaceMissingPrompt)
57 },
58 OverrideRuleAction::Strip if self.prompt.is_some() => {
59 Err(GatewayProfileError::OverrideStripWithPrompt)
60 },
61 _ => Ok(()),
62 }
63 }
64}