use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct VoiceProvenance {
#[serde(default)]
pub source_reviewers: Vec<String>,
#[serde(default)]
pub reviewers_count: u32,
#[serde(default)]
pub total_comments_analyzed: u32,
#[serde(default)]
pub notes: String,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct VoiceMeta {
pub name: String,
#[serde(default)]
pub version: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub generated_at: String,
#[serde(default)]
pub pipeline_version: String,
#[serde(default)]
pub corpus_cutoff: String,
#[serde(default)]
pub llm_model: String,
#[serde(default)]
pub provenance: VoiceProvenance,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct VoiceKnobs {
#[serde(default)]
pub tone: String,
#[serde(default)]
pub block_bias: String,
#[serde(default)]
pub comment_length: String,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct VoiceSection {
#[serde(default)]
pub system_addendum: String,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct CustomOverlay {
#[serde(default)]
pub extra_addendum: String,
#[serde(default)]
pub voice: Option<CustomVoiceOverride>,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct CustomVoiceOverride {
#[serde(default)]
pub system_addendum: String,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct VoicePackage {
#[serde(default)]
pub meta: VoiceMeta,
#[serde(default)]
pub voice: VoiceSection,
#[serde(default)]
pub knobs: VoiceKnobs,
#[serde(default)]
pub custom: CustomOverlay,
}
impl VoicePackage {
pub fn effective_addendum(&self) -> String {
let base = if let Some(ref cv) = self.custom.voice {
if !cv.system_addendum.is_empty() {
cv.system_addendum.clone()
} else {
self.voice.system_addendum.clone()
}
} else {
self.voice.system_addendum.clone()
};
if !self.custom.extra_addendum.is_empty() {
format!("{}\n\n{}", base, self.custom.extra_addendum)
} else {
base
}
}
}