use crate::error::CliError;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::path::Path;
pub mod parser;
#[cfg(test)]
mod tests;
pub use parser::{parse_modelfile, parse_modelfile_str, ModelfileError};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ModelfileConfig {
pub from: String,
#[serde(default)]
pub parameters: BTreeMap<String, serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub template: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub system: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub messages: Vec<MessageEntry>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub adapter: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct MessageEntry {
pub role: String,
pub content: String,
}
pub fn run_parse(file: &Path, format: &str) -> Result<(), CliError> {
let raw = std::fs::read_to_string(file).map_err(|e| {
CliError::ValidationFailed(format!("failed to read {}: {e}", file.display()))
})?;
let config = parse_modelfile_str(&raw, file).map_err(|e| {
CliError::ValidationFailed(e.to_string())
})?;
match format {
"json" => {
let pretty = serde_json::to_string_pretty(&config)
.map_err(|e| CliError::ValidationFailed(format!("JSON serialize failed: {e}")))?;
println!("{pretty}");
}
"human" | "" => {
println!("FROM: {}", config.from);
for (k, v) in &config.parameters {
println!("PARAMETER {k}: {v}");
}
if let Some(t) = &config.template {
println!("TEMPLATE:\n{t}");
}
if let Some(s) = &config.system {
println!("SYSTEM:\n{s}");
}
if let Some(l) = &config.license {
println!("LICENSE: {l}");
}
for m in &config.messages {
println!("MESSAGE {} {}", m.role, m.content);
}
if let Some(a) = &config.adapter {
println!("ADAPTER: {a}");
}
}
other => {
return Err(CliError::ValidationFailed(format!(
"unknown --format {other}; expected `json` or `human`"
)));
}
}
Ok(())
}