From 599c9a4471013e8003b684162c9ee5f15ed627ba Mon Sep 17 00:00:00 2001 From: Robert Queenin <2177841+ecalifornica@users.noreply.github.com> Date: Fri, 14 Aug 2026 09:44:36 -0400 Subject: [PATCH] refactor(pi): PathResolver::new takes a required home argument (#185) toolpath-pi reads no environment variable. The caller supplies the home directory. The crate keeps the layout below it: Pi session logs are in /.pi/agent/sessions. - PathResolver::new(home) takes the home directory as a required argument. PiConvo::new(home) takes the same argument. - Deleted: the Default impls on PathResolver and PiConvo, PathResolver::with_home, and the $HOME read. - with_sessions_dir stays as the full override. It beats the home argument. - The resolver does not consult the current working directory. The ./.pi/agent/sessions fallback is gone. path-cli: - providers::pi_resolver returns Option. None means the configuration carries no home directory. - harness_bundle omits the Pi manager when the resolver is None. - providers::require_pi_resolver turns None into an error. The 5 commands that target Pi use it. --- CHANGELOG.md | 21 +++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- crates/path-cli/src/cmd_export.rs | 4 +- crates/path-cli/src/cmd_import.rs | 2 +- crates/path-cli/src/cmd_list.rs | 10 +++- crates/path-cli/src/cmd_show.rs | 6 +- crates/path-cli/src/derive.rs | 2 +- crates/path-cli/src/providers.rs | 52 ++++++++--------- crates/toolpath-pi/Cargo.toml | 2 +- crates/toolpath-pi/README.md | 4 +- crates/toolpath-pi/src/io.rs | 2 +- crates/toolpath-pi/src/lib.rs | 9 +-- crates/toolpath-pi/src/paths.rs | 81 +++++++------------------- crates/toolpath-pi/src/provider.rs | 8 +-- crates/toolpath-pi/src/reader.rs | 6 +- crates/toolpath-pi/tests/end_to_end.rs | 2 +- site/_data/crates.json | 2 +- 18 files changed, 103 insertions(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a33d8f32..30f97a5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,27 @@ cache the same queries run ~4.7× faster (e.g. `length` 966 ms → drivers so the zero-file rule lives once. - The emscripten (playground) build keeps the sequential engine — no threads there. +## `toolpath-pi`: the caller supplies the home directory — 2026-08-14 + +- **`toolpath-pi`** (0.7.0): breaking. `PathResolver::new(home)` takes + the home directory as a required argument. The crate reads no + environment variable; it keeps the layout knowledge + (`/.pi/agent/sessions`) and the caller owns "what is home". + `PiConvo::new(home)` takes the same argument. + + Removed: the `Default` impls on `PathResolver` and `PiConvo`; + `PathResolver::with_home`. `with_sessions_dir` stays as the full + override, and it beats the home argument. + + Behavior change: the resolver does not consult the current working + directory. It resolves the sessions directory from the home argument, + or from `with_sessions_dir`. The `./.pi/agent/sessions` fallback is + deleted. +- **`path-cli`** (unreleased): `providers::pi_resolver` returns + `Option`. `None` means the configuration carries no home + directory, so Pi is out of reach: the harness bundle omits it, and a + command that targets Pi reports "cannot determine the home + directory". ## `toolpath-cursor`: the caller supplies the home directory — 2026-08-14 - **`toolpath-cursor`** (0.3.0): breaking. `PathResolver::new(home)` diff --git a/Cargo.lock b/Cargo.lock index 60797d21..fd7bf1a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4372,7 +4372,7 @@ dependencies = [ [[package]] name = "toolpath-pi" -version = "0.6.1" +version = "0.7.0" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index e2dd5462..f9716b44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ toolpath-cursor = { version = "0.3.0", path = "crates/toolpath-cursor" } toolpath-github = { version = "0.6.0", path = "crates/toolpath-github" } toolpath-dot = { version = "0.5.0", path = "crates/toolpath-dot" } toolpath-md = { version = "0.7.0", path = "crates/toolpath-md" } -toolpath-pi = { version = "0.6.1", path = "crates/toolpath-pi" } +toolpath-pi = { version = "0.7.0", path = "crates/toolpath-pi" } path-cli = { version = "0.17.0", path = "crates/path-cli" } pathbase-client = { version = "0.2.0", path = "crates/pathbase-client" } diff --git a/crates/path-cli/src/cmd_export.rs b/crates/path-cli/src/cmd_export.rs index b2d3d8a7..909c4753 100644 --- a/crates/path-cli/src/cmd_export.rs +++ b/crates/path-cli/src/cmd_export.rs @@ -1064,7 +1064,7 @@ fn write_into_pi_project( cwd: &str, config: &Config, ) -> Result<()> { - let resolver = providers::pi_resolver(config); + let resolver = providers::require_pi_resolver(config)?; let project_dir = resolver.project_dir(cwd); std::fs::create_dir_all(&project_dir) .with_context(|| format!("create {}", project_dir.display()))?; @@ -2588,7 +2588,7 @@ mod tests { .expect("export pi"); let canon_project = std::fs::canonicalize(&project_dir).unwrap(); - let resolver = PathResolver::new().with_home(&fake_home); + let resolver = PathResolver::new(&fake_home); let project_dir_path = resolver.project_dir(canon_project.to_str().unwrap()); let expected = project_dir_path.join(format!("{}.jsonl", session_uuid)); assert!(expected.exists(), "expected JSONL at {:?}", expected); diff --git a/crates/path-cli/src/cmd_import.rs b/crates/path-cli/src/cmd_import.rs index 9ca0a135..18e771c8 100644 --- a/crates/path-cli/src/cmd_import.rs +++ b/crates/path-cli/src/cmd_import.rs @@ -1310,7 +1310,7 @@ fn derive_pi( base: Option, config: &Config, ) -> Result> { - let mut resolver = providers::pi_resolver(config); + let mut resolver = providers::require_pi_resolver(config)?; if let Some(path) = base { resolver = resolver.with_sessions_dir(&path); } diff --git a/crates/path-cli/src/cmd_list.rs b/crates/path-cli/src/cmd_list.rs index 49648cb5..71e252b1 100644 --- a/crates/path-cli/src/cmd_list.rs +++ b/crates/path-cli/src/cmd_list.rs @@ -999,7 +999,11 @@ fn run_pi( fmt: ListFormat, config: &Config, ) -> Result<()> { - let manager = providers::pi_convo(config, base.as_deref()); + let mut resolver = providers::require_pi_resolver(config)?; + if let Some(path) = base { + resolver = resolver.with_sessions_dir(&path); + } + let manager = toolpath_pi::PiConvo::with_resolver(resolver); match (project, fmt) { (None, ListFormat::Tsv) => list_pi_sessions_all(&manager, ListFormat::Tsv), @@ -1416,7 +1420,7 @@ mod tests { ) .unwrap(); - let resolver = toolpath_pi::PathResolver::new().with_sessions_dir(&sessions_dir); + let resolver = toolpath_pi::PathResolver::new(temp.path()); let manager = toolpath_pi::PiConvo::with_resolver(resolver); (temp, manager) } @@ -1441,7 +1445,7 @@ mod tests { let sessions_dir = temp.path().join(".pi/agent/sessions"); std::fs::create_dir_all(&sessions_dir).unwrap(); - let resolver = toolpath_pi::PathResolver::new().with_sessions_dir(&sessions_dir); + let resolver = toolpath_pi::PathResolver::new(temp.path()); let manager = toolpath_pi::PiConvo::with_resolver(resolver); let result = list_pi_projects(&manager, ListFormat::Pretty); diff --git a/crates/path-cli/src/cmd_show.rs b/crates/path-cli/src/cmd_show.rs index 0dab4b37..17cce08c 100644 --- a/crates/path-cli/src/cmd_show.rs +++ b/crates/path-cli/src/cmd_show.rs @@ -199,7 +199,11 @@ fn derive_one(source: ShowSource, config: &Config) -> Result session, base, } => { - let manager = providers::pi_convo(config, base.as_deref()); + let mut resolver = providers::require_pi_resolver(config)?; + if let Some(p) = base { + resolver = resolver.with_sessions_dir(&p); + } + let manager = toolpath_pi::PiConvo::with_resolver(resolver); let s = manager .read_session(&project, &session) .map_err(|e| anyhow::anyhow!("{}", e))?; diff --git a/crates/path-cli/src/derive.rs b/crates/path-cli/src/derive.rs index 9541d049..ef37c1af 100644 --- a/crates/path-cli/src/derive.rs +++ b/crates/path-cli/src/derive.rs @@ -341,7 +341,7 @@ pub(crate) fn derive_pi_session( session: &str, base: Option, ) -> Result { - let mut resolver = providers::pi_resolver(config); + let mut resolver = providers::require_pi_resolver(config)?; if let Some(path) = base { resolver = resolver.with_sessions_dir(&path); } diff --git a/crates/path-cli/src/providers.rs b/crates/path-cli/src/providers.rs index 6dad3b46..d090911d 100644 --- a/crates/path-cli/src/providers.rs +++ b/crates/path-cli/src/providers.rs @@ -24,7 +24,6 @@ use crate::config::Config; #[cfg(not(target_os = "emscripten"))] use crate::harness::HarnessBundle; -use std::path::Path; use anyhow::{Result, anyhow}; @@ -132,17 +131,13 @@ pub(crate) fn require_cursor_resolver(config: &Config) -> Result) -> toolpath_pi::PiConvo { - let mut resolver = toolpath_pi::PathResolver::new(); - if let Some(home) = config.home_dir() { - resolver = resolver.with_home(home); - } - if let Some(dir) = base { - resolver = resolver.with_sessions_dir(dir); - } - toolpath_pi::PiConvo::with_resolver(resolver) +pub(crate) fn pi_resolver(config: &Config) -> Option { + config.home_dir().map(toolpath_pi::PathResolver::new) +} + +/// [`pi_resolver`] for a command that targets Pi. +pub(crate) fn require_pi_resolver(config: &Config) -> Result { + pi_resolver(config).ok_or_else(|| missing_home("Pi")) } /// The production [`HarnessBundle`], every provider built from @@ -165,7 +160,7 @@ pub(crate) fn harness_bundle(config: &Config) -> HarnessBundle { }), opencode: opencode_resolver(config).map(toolpath_opencode::OpencodeConvo::with_resolver), cursor: cursor_resolver(config).map(toolpath_cursor::CursorConvo::with_resolver), - pi: Some(pi_convo(config, None)), + pi: pi_resolver(config).map(toolpath_pi::PiConvo::with_resolver), } } @@ -361,21 +356,6 @@ mod tests { ); } - #[test] - fn pi_convo_roots_at_config_home() { - let manager = pi_convo(&config_with_home(), None); - assert_eq!( - manager.resolver().sessions_dir(), - PathBuf::from("/home/jailed/.pi/agent/sessions") - ); - } - - #[test] - fn pi_convo_base_replaces_the_sessions_dir() { - let manager = pi_convo(&config_with_home(), Some(Path::new("/pi/base"))); - assert_eq!(manager.resolver().sessions_dir(), PathBuf::from("/pi/base")); - } - #[test] fn harness_bundle_roots_providers_at_config_home() { let bundle = harness_bundle(&config_with_home()); @@ -388,4 +368,20 @@ mod tests { PathBuf::from("/home/jailed/.pi/agent/sessions") ); } + + #[test] + fn pi_resolver_roots_at_config_home() { + let resolver = pi_resolver(&config_with_home()).unwrap(); + assert_eq!( + resolver.sessions_dir(), + PathBuf::from("/home/jailed/.pi/agent/sessions") + ); + } + + #[test] + fn pi_resolver_is_none_without_a_home() { + assert!(pi_resolver(&Config::default()).is_none()); + let err = require_pi_resolver(&Config::default()).unwrap_err(); + assert!(err.to_string().contains("home directory")); + } } diff --git a/crates/toolpath-pi/Cargo.toml b/crates/toolpath-pi/Cargo.toml index 72b1e236..f8ff6209 100644 --- a/crates/toolpath-pi/Cargo.toml +++ b/crates/toolpath-pi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "toolpath-pi" -version = "0.6.1" +version = "0.7.0" edition.workspace = true license.workspace = true repository = "https://github.com/empathic/toolpath" diff --git a/crates/toolpath-pi/README.md b/crates/toolpath-pi/README.md index d27a4c4b..dc061473 100644 --- a/crates/toolpath-pi/README.md +++ b/crates/toolpath-pi/README.md @@ -18,7 +18,7 @@ the shared derivation in [`toolpath_convo::derive_path`]. ```rust,no_run use toolpath_pi::PiConvo; -let manager = PiConvo::new(); +let manager = PiConvo::new("/Users/alex"); let session = manager .most_recent_session("/Users/alex/project") .unwrap() @@ -36,7 +36,7 @@ user-prompt text). The last field is what makes the listing useful for ```rust,no_run use toolpath_pi::PiConvo; -let manager = PiConvo::new(); +let manager = PiConvo::new("/Users/alex"); for meta in manager.list_sessions("/Users/alex/project").unwrap() { println!( "{}: {}", diff --git a/crates/toolpath-pi/src/io.rs b/crates/toolpath-pi/src/io.rs index 16c619b0..9254498d 100644 --- a/crates/toolpath-pi/src/io.rs +++ b/crates/toolpath-pi/src/io.rs @@ -255,7 +255,7 @@ mod tests { use tempfile::TempDir; fn resolver_with(sessions_dir: &Path) -> PathResolver { - PathResolver::new().with_sessions_dir(sessions_dir) + PathResolver::new("/tmp/fake-home").with_sessions_dir(sessions_dir) } #[test] diff --git a/crates/toolpath-pi/src/lib.rs b/crates/toolpath-pi/src/lib.rs index 4ef66ba3..cb08d68d 100644 --- a/crates/toolpath-pi/src/lib.rs +++ b/crates/toolpath-pi/src/lib.rs @@ -22,16 +22,17 @@ pub use types::{ use toolpath_convo::ConversationView; /// High-level interface for reading Pi sessions. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub struct PiConvo { resolver: PathResolver, } impl PiConvo { - /// Build a manager with the default resolver (`~/.pi/agent/sessions/`). - pub fn new() -> Self { + /// Build a manager for `/.pi/agent/sessions/`. The caller + /// supplies the home directory. + pub fn new(home: impl AsRef) -> Self { Self { - resolver: PathResolver::new(), + resolver: PathResolver::new(home), } } diff --git a/crates/toolpath-pi/src/paths.rs b/crates/toolpath-pi/src/paths.rs index 6d64d80a..42964058 100644 --- a/crates/toolpath-pi/src/paths.rs +++ b/crates/toolpath-pi/src/paths.rs @@ -3,7 +3,7 @@ //! Pi stores session logs at: //! //! ```text -//! $HOME/.pi/agent/sessions/----/_.jsonl +//! /.pi/agent/sessions/----/_.jsonl //! ``` //! //! The project directory name encodes the cwd: the leading slash is dropped, @@ -16,47 +16,21 @@ use std::path::{Path, PathBuf}; /// Resolves the Pi sessions directory and its project subdirectories. #[derive(Debug, Clone)] pub struct PathResolver { - home_dir: Option, - sessions_dir_override: Option, - /// Cached effective sessions_dir. Recomputed on `with_home`. sessions_dir: PathBuf, } -impl Default for PathResolver { - fn default() -> Self { - Self::new() - } -} - impl PathResolver { - /// Default resolver: `$HOME/.pi/agent/sessions/`, falling back to - /// `./.pi/agent/sessions` when no home directory is available. - pub fn new() -> Self { - let home_dir = std::env::var_os("HOME").map(PathBuf::from); - let sessions_dir = compute_sessions_dir(home_dir.as_deref(), None); + /// Resolver for `/.pi/agent/sessions/`. The caller supplies the + /// home directory. + pub fn new(home: impl AsRef) -> Self { Self { - home_dir, - sessions_dir_override: None, - sessions_dir, + sessions_dir: home.as_ref().join(".pi").join("agent").join("sessions"), } } - /// Override the home directory (useful for tests). Recomputes sessions_dir - /// unless an explicit sessions-dir override is in effect. - pub fn with_home(mut self, home: impl AsRef) -> Self { - self.home_dir = Some(home.as_ref().to_path_buf()); - self.sessions_dir = compute_sessions_dir( - self.home_dir.as_deref(), - self.sessions_dir_override.as_deref(), - ); - self - } - /// Override the sessions base directory directly. pub fn with_sessions_dir(mut self, dir: impl AsRef) -> Self { - let p = dir.as_ref().to_path_buf(); - self.sessions_dir_override = Some(p.clone()); - self.sessions_dir = p; + self.sessions_dir = dir.as_ref().to_path_buf(); self } @@ -108,16 +82,6 @@ impl PathResolver { } } -fn compute_sessions_dir(home: Option<&Path>, override_dir: Option<&Path>) -> PathBuf { - if let Some(o) = override_dir { - return o.to_path_buf(); - } - let base = home - .map(Path::to_path_buf) - .unwrap_or_else(|| PathBuf::from(".")); - base.join(".pi").join("agent").join("sessions") -} - /// Encode a cwd path into a Pi project directory name. /// /// ``` @@ -157,9 +121,9 @@ mod tests { use tempfile::TempDir; #[test] - fn test_default_sessions_dir_uses_home() { + fn test_sessions_dir_sits_under_the_home_argument() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_home(temp.path()); + let resolver = PathResolver::new(temp.path()); assert_eq!( resolver.sessions_dir(), temp.path().join(".pi/agent/sessions") @@ -169,16 +133,14 @@ mod tests { #[test] fn test_with_sessions_dir_override() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path()); assert_eq!(resolver.sessions_dir(), temp.path()); } #[test] - fn test_with_sessions_dir_override_survives_with_home() { + fn test_with_sessions_dir_override_beats_the_home_argument() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new() - .with_sessions_dir(temp.path()) - .with_home("/some/other/home"); + let resolver = PathResolver::new("/some/other/home").with_sessions_dir(temp.path()); assert_eq!(resolver.sessions_dir(), temp.path()); } @@ -224,7 +186,7 @@ mod tests { #[test] fn test_project_dir_combines_sessions_and_encoded_cwd() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path()); let pd = resolver.project_dir("/Users/alex/proj"); assert_eq!(pd, temp.path().join("--Users-alex-proj--")); } @@ -232,7 +194,7 @@ mod tests { #[test] fn test_list_projects_empty_dir() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path()); let projects = resolver.list_projects().unwrap(); assert!(projects.is_empty()); } @@ -241,7 +203,7 @@ mod tests { fn test_list_projects_nonexistent_dir() { let temp = TempDir::new().unwrap(); let missing = temp.path().join("does-not-exist"); - let resolver = PathResolver::new().with_sessions_dir(&missing); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&missing); let projects = resolver.list_projects().unwrap(); assert!(projects.is_empty()); } @@ -252,7 +214,7 @@ mod tests { fs::create_dir(temp.path().join("--Users-alex-proj--")).unwrap(); fs::write(temp.path().join("stray-file.txt"), "hi").unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path()); let projects = resolver.list_projects().unwrap(); assert_eq!(projects, vec!["/Users/alex/proj".to_string()]); } @@ -263,7 +225,7 @@ mod tests { fs::create_dir(temp.path().join("--Users-alex-proj--")).unwrap(); fs::create_dir(temp.path().join("--home-bob-repo--")).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path()); let projects = resolver.list_projects().unwrap(); assert_eq!( projects, @@ -274,34 +236,35 @@ mod tests { #[test] fn test_exists_returns_false_for_missing_dir() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path().join("nope")); + let resolver = + PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path().join("nope")); assert!(!resolver.exists()); } #[test] fn test_exists_returns_true_for_created_dir() { let temp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_sessions_dir(temp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(temp.path()); assert!(resolver.exists()); } #[test] fn test_debug_impl_doesnt_panic() { - let resolver = PathResolver::new().with_home("/tmp/fake-home"); + let resolver = PathResolver::new("/tmp/fake-home"); let s = format!("{resolver:?}"); assert!(!s.is_empty()); } #[test] fn test_clone_produces_equal_resolver() { - let resolver = PathResolver::new().with_home("/tmp/fake-home"); + let resolver = PathResolver::new("/tmp/fake-home"); let cloned = resolver.clone(); assert_eq!(resolver.sessions_dir(), cloned.sessions_dir()); } #[test] fn test_encode_cwd_and_decode_project_dir_methods() { - let resolver = PathResolver::new(); + let resolver = PathResolver::new("/tmp/fake-home"); assert_eq!(resolver.encode_cwd("/a/b"), "--a-b--"); assert_eq!(resolver.decode_project_dir("--a-b--"), "/a/b"); } diff --git a/crates/toolpath-pi/src/provider.rs b/crates/toolpath-pi/src/provider.rs index f536b952..4623adb6 100644 --- a/crates/toolpath-pi/src/provider.rs +++ b/crates/toolpath-pi/src/provider.rs @@ -1180,7 +1180,7 @@ mod tests { let tmp = tempfile::TempDir::new().unwrap(); let sessions = tmp.path().join("sessions"); std::fs::create_dir_all(&sessions).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions); let proj = resolver.project_dir("/tmp/p"); std::fs::create_dir_all(&proj).unwrap(); write_session_file(&proj, "s1", "2026-04-16T00:00:00Z"); @@ -1195,7 +1195,7 @@ mod tests { let tmp = tempfile::TempDir::new().unwrap(); let sessions = tmp.path().join("sessions"); std::fs::create_dir_all(&sessions).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions); let proj = resolver.project_dir("/tmp/p"); std::fs::create_dir_all(&proj).unwrap(); write_session_file(&proj, "s1", "2026-04-16T00:00:00Z"); @@ -1212,7 +1212,7 @@ mod tests { let tmp = tempfile::TempDir::new().unwrap(); let sessions = tmp.path().join("sessions"); std::fs::create_dir_all(&sessions).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions); let proj = resolver.project_dir("/tmp/p"); std::fs::create_dir_all(&proj).unwrap(); let path = write_session_file(&proj, "s1", "2026-04-16T00:00:00Z"); @@ -1229,7 +1229,7 @@ mod tests { let tmp = tempfile::TempDir::new().unwrap(); let sessions = tmp.path().join("sessions"); std::fs::create_dir_all(&sessions).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions); let proj = resolver.project_dir("/tmp/p"); std::fs::create_dir_all(&proj).unwrap(); write_session_file(&proj, "older", "2026-04-16T00:00:00Z"); diff --git a/crates/toolpath-pi/src/reader.rs b/crates/toolpath-pi/src/reader.rs index 3f6b0595..8ce156b7 100644 --- a/crates/toolpath-pi/src/reader.rs +++ b/crates/toolpath-pi/src/reader.rs @@ -604,7 +604,7 @@ mod tests { fn resolver_with_project(tmp: &TempDir, cwd: &str) -> (PathResolver, PathBuf) { let sessions = tmp.path().join("sessions"); fs::create_dir_all(&sessions).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions); let proj_dir = resolver.project_dir(cwd); fs::create_dir_all(&proj_dir).unwrap(); (resolver, proj_dir) @@ -648,7 +648,7 @@ mod tests { let tmp = TempDir::new().unwrap(); let sessions = tmp.path().join("sessions"); fs::create_dir_all(&sessions).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions); let err = read_session(&resolver, "/nonexistent-proj", "x").unwrap_err(); assert!(matches!(err, PiError::ProjectNotFound(_))); } @@ -710,7 +710,7 @@ mod tests { #[test] fn test_list_session_files_nonexistent_project() { let tmp = TempDir::new().unwrap(); - let resolver = PathResolver::new().with_sessions_dir(tmp.path()); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(tmp.path()); let files = list_session_files(&resolver, "/missing").unwrap(); assert!(files.is_empty()); } diff --git a/crates/toolpath-pi/tests/end_to_end.rs b/crates/toolpath-pi/tests/end_to_end.rs index 0ed9b444..80c5219d 100644 --- a/crates/toolpath-pi/tests/end_to_end.rs +++ b/crates/toolpath-pi/tests/end_to_end.rs @@ -33,7 +33,7 @@ fn write_fixture(sessions_dir: &Path) { fn manager_for(temp: &TempDir) -> PiConvo { let sessions_dir = temp.path().join(".pi/agent/sessions"); fs::create_dir_all(&sessions_dir).unwrap(); - let resolver = PathResolver::new().with_sessions_dir(&sessions_dir); + let resolver = PathResolver::new("/tmp/fake-home").with_sessions_dir(&sessions_dir); PiConvo::with_resolver(resolver) } diff --git a/site/_data/crates.json b/site/_data/crates.json index 088c8b96..4f43706a 100644 --- a/site/_data/crates.json +++ b/site/_data/crates.json @@ -73,7 +73,7 @@ }, { "name": "toolpath-pi", - "version": "0.6.1", + "version": "0.7.0", "description": "Derive Toolpath provenance documents from Pi (pi.dev) agent session logs", "docs": "https://docs.rs/toolpath-pi", "crate": "https://crates.io/crates/toolpath-pi",