use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum Role {
User,
Assistant,
System,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ToolEvent {
pub kind: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub input: Option<Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output: Option<String>,
#[serde(default)]
pub index: usize,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Message {
pub role: Role,
pub content: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub events: Vec<ToolEvent>,
}
impl Message {
pub fn user(content: impl Into<String>) -> Self {
Self {
role: Role::User,
content: content.into(),
events: Vec::new(),
}
}
pub fn assistant(content: impl Into<String>) -> Self {
Self {
role: Role::Assistant,
content: content.into(),
events: Vec::new(),
}
}
#[must_use]
pub fn with_events(mut self, events: Vec<ToolEvent>) -> Self {
self.events = events;
self
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Transcript {
pub messages: Vec<Message>,
}
impl Transcript {
pub fn from_input(input: impl Into<String>) -> Self {
Self {
messages: vec![Message::user(input)],
}
}
pub fn push(&mut self, message: Message) {
self.messages.push(message);
}
#[must_use]
pub fn assistant_turns(&self) -> usize {
self.messages
.iter()
.filter(|m| m.role == Role::Assistant)
.count()
}
}