use std::sync::OnceLock;
use serde::{Deserialize, Serialize};
use crate::ProviderKind;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum HarnessPostureKind {
#[default]
Standard,
CacheHeavy,
Lean,
Custom,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum HarnessCompactionStrategy {
#[default]
Default,
PrefixCache,
Aggressive,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum HarnessToolSurface {
#[default]
Full,
ReadOnly,
Auto,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "kebab-case")]
pub enum HarnessSafetyPosture {
#[default]
Standard,
Strict,
Permissive,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct HarnessPosture {
#[serde(default)]
pub kind: HarnessPostureKind,
#[serde(default)]
pub max_subagents: usize,
#[serde(default)]
pub prefer_codebase_search: bool,
#[serde(default)]
pub compaction_strategy: HarnessCompactionStrategy,
#[serde(default)]
pub tool_surface: HarnessToolSurface,
#[serde(default)]
pub safety_posture: HarnessSafetyPosture,
}
impl Default for HarnessPosture {
fn default() -> Self {
Self {
kind: HarnessPostureKind::Standard,
max_subagents: 0,
prefer_codebase_search: false,
compaction_strategy: HarnessCompactionStrategy::default(),
tool_surface: HarnessToolSurface::default(),
safety_posture: HarnessSafetyPosture::default(),
}
}
}
impl HarnessPosture {
#[must_use]
pub fn cache_heavy() -> Self {
Self {
kind: HarnessPostureKind::CacheHeavy,
max_subagents: 10,
prefer_codebase_search: false,
compaction_strategy: HarnessCompactionStrategy::PrefixCache,
tool_surface: HarnessToolSurface::Full,
safety_posture: HarnessSafetyPosture::Standard,
}
}
#[must_use]
pub fn lean() -> Self {
Self {
kind: HarnessPostureKind::Lean,
max_subagents: 20,
prefer_codebase_search: true,
compaction_strategy: HarnessCompactionStrategy::Aggressive,
tool_surface: HarnessToolSurface::Full,
safety_posture: HarnessSafetyPosture::Standard,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct HarnessProfile {
pub provider_route: String,
pub model_pattern: String,
#[serde(default)]
pub posture: HarnessPosture,
}
impl HarnessProfile {
#[must_use]
pub fn matches_route(&self, provider_route: &str, model: &str) -> bool {
provider_routes_equal(&self.provider_route, provider_route)
&& wildcard_pattern_matches(&self.model_pattern, model)
}
}
#[must_use]
pub fn built_in_harness_profiles() -> &'static [HarnessProfile] {
static PROFILES: OnceLock<Vec<HarnessProfile>> = OnceLock::new();
PROFILES.get_or_init(|| {
vec![
HarnessProfile {
provider_route: "deepseek".to_string(),
model_pattern: "deepseek-v4*".to_string(),
posture: HarnessPosture::cache_heavy(),
},
HarnessProfile {
provider_route: "xiaomi-mimo".to_string(),
model_pattern: "mimo-v2.5*".to_string(),
posture: HarnessPosture::cache_heavy(),
},
HarnessProfile {
provider_route: "arcee".to_string(),
model_pattern: "trinity-large-thinking".to_string(),
posture: HarnessPosture::cache_heavy(),
},
HarnessProfile {
provider_route: "huggingface".to_string(),
model_pattern: "*".to_string(),
posture: HarnessPosture::lean(),
},
HarnessProfile {
provider_route: "sglang".to_string(),
model_pattern: "*".to_string(),
posture: HarnessPosture::lean(),
},
HarnessProfile {
provider_route: "vllm".to_string(),
model_pattern: "*".to_string(),
posture: HarnessPosture::lean(),
},
HarnessProfile {
provider_route: "ollama".to_string(),
model_pattern: "*".to_string(),
posture: HarnessPosture::lean(),
},
]
})
}
fn provider_routes_equal(expected: &str, actual: &str) -> bool {
match (ProviderKind::parse(expected), ProviderKind::parse(actual)) {
(Some(expected), Some(actual)) => expected == actual,
_ => expected.trim().eq_ignore_ascii_case(actual.trim()),
}
}
fn wildcard_pattern_matches(pattern: &str, value: &str) -> bool {
wildcard_chars_match(
&pattern.chars().collect::<Vec<_>>(),
&value.chars().collect::<Vec<_>>(),
)
}
fn wildcard_chars_match(pattern: &[char], value: &[char]) -> bool {
let (mut pattern_idx, mut value_idx) = (0, 0);
let mut star_idx: Option<usize> = None;
let mut star_value_idx = 0;
while value_idx < value.len() {
if pattern_idx < pattern.len()
&& (pattern[pattern_idx] == '?' || pattern[pattern_idx] == value[value_idx])
{
pattern_idx += 1;
value_idx += 1;
} else if pattern_idx < pattern.len() && pattern[pattern_idx] == '*' {
star_idx = Some(pattern_idx);
pattern_idx += 1;
star_value_idx = value_idx;
} else if let Some(star) = star_idx {
pattern_idx = star + 1;
star_value_idx += 1;
value_idx = star_value_idx;
} else {
return false;
}
}
pattern[pattern_idx..].iter().all(|ch| *ch == '*')
}