use crate::transcript::{Entry, FlatValueEntry};
#[derive(Debug, Default, Clone)]
pub struct SessionInfo {
pub title: Option<String>,
pub permission_mode: Option<String>,
pub mode: Option<String>,
pub last_prompt: Option<String>,
pub queued_ops: u32,
pub file_snapshots: u32,
}
impl SessionInfo {
pub fn apply(&mut self, entry: &Entry) {
match entry {
Entry::AiTitle(e) => {
if let Some(t) = &e.title {
self.title = Some(t.clone());
}
}
Entry::Mode(e) => self.mode = str_field(e, "mode").or(self.mode.take()),
Entry::PermissionMode(e) => {
self.permission_mode =
str_field(e, "permissionMode").or(self.permission_mode.take())
}
Entry::LastPrompt(e) => {
self.last_prompt = str_field(e, "lastPrompt").or(self.last_prompt.take())
}
Entry::QueueOperation(e) => {
if str_field(e, "operation").as_deref() == Some("enqueue") {
self.queued_ops += 1;
}
}
Entry::FileHistorySnapshot(_) => self.file_snapshots += 1,
_ => {}
}
}
}
fn str_field(e: &FlatValueEntry, key: &str) -> Option<String> {
e.fields
.get(key)
.and_then(|v| v.as_str())
.map(str::to_string)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::transcript::parse_line;
#[test]
fn session_info_extracts_metadata_latest_wins() {
let mut info = SessionInfo::default();
let p = |s: &str| parse_line(s).unwrap();
info.apply(&p(r#"{"type":"ai-title","aiTitle":"Build the thing"}"#));
info.apply(&p(r#"{"type":"mode","mode":"normal"}"#));
info.apply(&p(
r#"{"type":"permission-mode","permissionMode":"default"}"#,
));
info.apply(&p(
r#"{"type":"permission-mode","permissionMode":"acceptEdits"}"#,
));
info.apply(&p(r#"{"type":"last-prompt","lastPrompt":"hey"}"#));
info.apply(&p(r#"{"type":"queue-operation","operation":"enqueue"}"#));
info.apply(&p(r#"{"type":"queue-operation","operation":"dequeue"}"#));
info.apply(&p(r#"{"type":"file-history-snapshot","messageId":"x"}"#));
info.apply(&p(r#"{"type":"file-history-snapshot","messageId":"y"}"#));
assert_eq!(info.title.as_deref(), Some("Build the thing"));
assert_eq!(info.mode.as_deref(), Some("normal"));
assert_eq!(info.permission_mode.as_deref(), Some("acceptEdits")); assert_eq!(info.last_prompt.as_deref(), Some("hey"));
assert_eq!(info.queued_ops, 1, "only enqueues counted");
assert_eq!(info.file_snapshots, 2);
}
}