use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use crate::error::{NewtError, Result};
#[cfg(doc)]
use super::BackendConfig;
use super::{resolve_api_key_common, BackendKind, Config};
fn default_summarizer_timeout_secs() -> u64 {
60
}
fn default_summarizer_retries() -> u32 {
1
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub struct SummarizerConfig {
pub endpoint: Option<String>,
pub model: Option<String>,
pub kind: Option<BackendKind>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model_path: Option<String>,
pub api_key_file: Option<String>,
pub api_key_env: Option<String>,
#[serde(default = "default_summarizer_timeout_secs")]
pub timeout_secs: u64,
#[serde(default = "default_summarizer_retries")]
pub retries: u32,
pub fallback_model: Option<String>,
pub keep_alive: Option<String>,
}
impl Default for SummarizerConfig {
fn default() -> Self {
Self {
endpoint: None,
model: None,
kind: None,
model_path: None,
api_key_file: None,
api_key_env: None,
timeout_secs: default_summarizer_timeout_secs(),
retries: default_summarizer_retries(),
fallback_model: None,
keep_alive: None,
}
}
}
impl SummarizerConfig {
pub fn from_toml_str(text: &str) -> Result<Self> {
toml::from_str(text).map_err(|e| NewtError::Config(e.to_string()))
}
pub fn resolve() -> Result<Self> {
for path in Self::candidate_paths() {
if path.is_file() {
let text = std::fs::read_to_string(&path)?;
return Self::from_toml_str(&text);
}
}
Ok(Self::default())
}
fn candidate_paths() -> Vec<PathBuf> {
let mut paths = Vec::new();
if let Ok(p) = std::env::var("NEWT_SUMMARIZER_CONFIG") {
paths.push(PathBuf::from(p));
}
if let Some(dir) = Config::user_config_dir() {
paths.push(dir.join("summarizer.toml"));
}
paths
}
pub fn resolve_api_key(&self) -> Option<String> {
match resolve_api_key_common(self.api_key_env.as_deref(), self.api_key_file.as_deref()) {
Ok(v) => return v,
Err(e) => {
crate::secrets::warn_once(self.api_key_file.as_deref().unwrap_or("summarizer"), &e);
}
}
None
}
}