1#![doc = include_str!("../README.md")]
2
3pub mod derive;
4pub mod error;
5pub mod io;
6pub mod paths;
7pub mod project;
8pub mod provider;
9pub mod reader;
10pub mod types;
11
12pub use derive::{derive_graph, derive_path, derive_project};
13pub use error::{PiError, Result};
14pub use paths::PathResolver;
15pub use provider::session_to_view;
16pub use reader::{PiSession, SessionMeta};
17pub use toolpath_convo::DeriveConfig;
18pub use types::{
19 AgentMessage, ContentBlock, CostBreakdown, Entry, EntryBase, SessionHeader, Usage,
20};
21
22use toolpath_convo::ConversationView;
23
24#[derive(Debug, Clone, Default)]
26pub struct PiConvo {
27 resolver: PathResolver,
28}
29
30impl PiConvo {
31 pub fn new() -> Self {
33 Self {
34 resolver: PathResolver::new(),
35 }
36 }
37
38 pub fn with_resolver(resolver: PathResolver) -> Self {
40 Self { resolver }
41 }
42
43 pub fn resolver(&self) -> &PathResolver {
45 &self.resolver
46 }
47
48 pub fn exists(&self) -> bool {
50 self.resolver.sessions_dir().exists()
51 }
52
53 pub fn list_projects(&self) -> Result<Vec<String>> {
55 io::list_projects(&self.resolver)
56 }
57
58 pub fn list_sessions(&self, project: &str) -> Result<Vec<SessionMeta>> {
60 io::list_sessions(&self.resolver, project)
61 }
62
63 pub fn read_session(&self, project: &str, session_id: &str) -> Result<PiSession> {
65 reader::read_session(&self.resolver, project, session_id)
66 }
67
68 pub fn most_recent_session(&self, project: &str) -> Result<Option<PiSession>> {
70 let mut metas = self.list_sessions(project)?;
71 if let Some(meta) = metas.drain(..).next() {
72 let session = self.read_session(project, &meta.id)?;
73 Ok(Some(session))
74 } else {
75 Ok(None)
76 }
77 }
78
79 pub fn to_view(&self, session: &PiSession) -> ConversationView {
81 provider::session_to_view(session)
82 }
83
84 pub fn read_all_sessions(&self, project: &str) -> Result<Vec<PiSession>> {
86 let metas = self.list_sessions(project)?;
87 let mut sessions = Vec::new();
88 for meta in metas {
89 match self.read_session(project, &meta.id) {
90 Ok(s) => sessions.push(s),
91 Err(e) => {
92 eprintln!("Warning: failed to read Pi session {}: {}", meta.id, e);
93 }
94 }
95 }
96 Ok(sessions)
97 }
98}