use serde::{Deserialize, Serialize};
use super::short_id;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct RequestId(pub String);
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthorKind {
#[default]
User,
Agent,
Plugin(String),
Rig,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Author {
#[serde(default)]
pub kind: AuthorKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub from: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request: Option<RequestId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
}
impl Author {
pub fn user() -> Self {
Self::default()
}
pub fn agent(from: impl Into<String>, request: Option<RequestId>) -> Self {
Self {
kind: AuthorKind::Agent,
from: Some(from.into()),
request,
title: None,
}
}
pub fn plugin(name: impl Into<String>) -> Self {
Self {
kind: AuthorKind::Plugin(name.into()),
..Self::default()
}
}
pub fn rig() -> Self {
Self {
kind: AuthorKind::Rig,
..Self::default()
}
}
#[must_use]
pub fn titled(self, title: impl Into<String>) -> Self {
Self {
title: Some(title.into()),
..self
}
}
pub fn label(&self) -> String {
let who = match &self.kind {
AuthorKind::User => "you".to_owned(),
AuthorKind::Agent => {
format!("agent {}", self.from.as_deref().map_or("?", short_id))
}
AuthorKind::Plugin(name) => format!("plugin {name}"),
AuthorKind::Rig => "rig".to_owned(),
};
match &self.title {
Some(title) => format!("{who} \"{title}\""),
None => who,
}
}
pub fn header(&self) -> Option<String> {
match self.kind {
AuthorKind::User => None,
_ => Some(format!(
"[Output of {}, not the user's words]",
self.label()
)),
}
}
}