pub trait Render {
fn render(&self, args: crate::Args) -> String;
}
#[derive(Debug, Copy, Clone, Default)]
pub enum OutputFormat {
#[default]
Markdown,
Json,
Debug,
}
impl std::fmt::Display for OutputFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OutputFormat::Markdown => write!(f, "markdown"),
OutputFormat::Json => write!(f, "json"),
OutputFormat::Debug => write!(f, "debug"),
}
}
}
impl std::str::FromStr for OutputFormat {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"markdown" => Ok(OutputFormat::Markdown),
"json" => Ok(OutputFormat::Json),
"debug" => Ok(OutputFormat::Debug),
_ => Err(format!("Unknown output format '{s}'")),
}
}
}
impl Render for kagi_api::v0::fastgpt::Answer {
fn render(&self, args: crate::Args) -> String {
match args.format {
OutputFormat::Markdown => {
if args.compact {
let mut markdown = self.data.output.replace('\n', " ").trim().to_string();
if let Some(references) = self.data.references.as_ref() {
if let Some(first_reference) = references.get(0) {
markdown.push(' ');
markdown.push_str(&first_reference.url);
}
}
markdown
} else {
let mut markdown = self.data.output.clone();
if let Some(references) = self.data.references.as_ref() {
markdown.push_str("\n\n");
for (n, reference) in references.iter().enumerate() {
let reference_str = format!("\n- {} [{}]\n", reference.snippet, n + 1);
markdown.push_str(&reference_str);
}
for (n, reference) in references.iter().enumerate() {
let reference_str = format!("[{}]: {}\n", n + 1, reference.url);
markdown.push_str(&reference_str);
}
}
markdown
}
}
OutputFormat::Json => {
if args.compact {
serde_json::to_string(&self).unwrap()
} else {
serde_json::to_string_pretty(&self).unwrap()
}
}
OutputFormat::Debug => {
if args.compact {
format!("{:?}", self)
} else {
format!("{:#?}", self)
}
}
}
}
}