txcript/harness/
campfire.rs1use std::path::PathBuf;
7
8use crate::error::Result;
9use crate::harness::jsonl;
10use crate::harness::pi::{self, Record};
11use crate::transcript::{Codec, Common, Discovered, Harness, Saved, Store, TextCodec, Transcript};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct Campfire;
16
17impl Harness for Campfire {
18 const NAME: &'static str = "campfire";
19 type Body = Vec<Record>;
20}
21
22impl Codec for Campfire {
23 fn to_common(transcript: &Transcript<Self>) -> Result<Transcript<Common>> {
24 Ok(Transcript::new(
25 transcript.meta.clone(),
26 pi::records_to_messages(&transcript.body, transcript.meta.timestamp),
27 ))
28 }
29
30 fn from_common(transcript: &Transcript<Common>) -> Result<Transcript<Self>> {
31 Ok(Transcript::new(
32 transcript.meta.clone(),
33 pi::messages_to_records(&transcript.meta, &transcript.body),
34 ))
35 }
36}
37
38impl TextCodec for Campfire {
39 fn from_text(text: &str) -> Result<Transcript<Self>> {
40 let records = pi::records_from_text(text);
42 Ok(Transcript::new(pi::meta_from_records(&records), records))
43 }
44
45 fn to_text(transcript: &Transcript<Self>) -> Result<String> {
46 jsonl::render(&transcript.body)
47 }
48}
49
50#[derive(Debug, Clone)]
52pub struct CampfireStore {
53 pub sessions_dir: PathBuf,
54}
55
56impl CampfireStore {
57 pub fn new(sessions_dir: impl Into<PathBuf>) -> Self {
58 Self {
59 sessions_dir: sessions_dir.into(),
60 }
61 }
62
63 pub fn default_root() -> Option<Self> {
65 pi::resolve_sessions_dir(".campfire", "CAMPFIRE").map(Self::new)
66 }
67}
68
69impl Store for CampfireStore {
70 type H = Campfire;
71 type Ref = PathBuf;
72
73 fn discover(&self) -> Result<Vec<Discovered<PathBuf>>> {
74 Ok(pi::discover_format(&self.sessions_dir))
75 }
76
77 fn load(&self, reference: &PathBuf) -> Result<Transcript<Campfire>> {
78 pi::load_session(reference, Campfire::from_text)
79 }
80
81 fn save(&self, transcript: &Transcript<Campfire>) -> Result<Saved<PathBuf>> {
82 pi::write_session(&self.sessions_dir, &transcript.meta, &transcript.body)
83 }
84
85 fn delete(&self, reference: &PathBuf) -> Result<()> {
86 Ok(std::fs::remove_file(reference)?)
87 }
88}