1#[cfg(all(
30 windows,
31 not(all(
32 target_vendor = "pc",
33 target_env = "msvc",
34 any(target_arch = "x86_64", target_arch = "aarch64")
35 ))
36))]
37compile_error!(
38 "Pitboard for Windows is built for x86_64-pc-windows-msvc and aarch64-pc-windows-msvc \
39 alone, the targets it is built and tested on."
40);
41
42#[cfg(not(any(target_os = "macos", target_os = "linux", windows)))]
43compile_error!(
44 "Pitboard runs on macOS, Linux and Windows. Another system needs a host of its own in \
45 `host/`, saying where its stores, processes and scheduler are."
46);
47
48pub(crate) mod api;
49pub mod app;
50pub mod assumptions;
51pub mod audit;
52pub mod context;
53#[cfg(any(test, feature = "test-support"))]
55#[doc(hidden)]
56pub mod desktop_testing;
57pub mod doctor;
58pub mod duty;
59pub mod error;
60pub(crate) mod in_use;
61pub mod label;
62pub mod provider;
63pub mod redact;
64pub mod release;
65pub mod schedule;
66pub mod service;
67pub(crate) mod settings;
68pub mod state;
69pub mod status;
70pub mod statusline;
71pub mod switch;
72pub mod time;
73pub mod usage;
74pub mod words;
75
76pub(crate) mod atomic;
77pub(crate) mod fault;
78pub mod holder;
79pub(crate) mod home;
80pub mod host;
81pub(crate) mod lock;
82pub(crate) mod park;
83pub(crate) mod pending;
84pub(crate) mod proxy;
85pub(crate) mod sessions;
86#[cfg(any(test, feature = "test-support"))]
89#[doc(hidden)]
90pub mod stand_in;
91pub(crate) mod store;
92
93#[cfg(feature = "test-support")]
96#[doc(hidden)]
97pub mod testing {
98 pub use crate::api::scripted::{Answer, Asked, ScriptedApi, Trouble};
99 pub use crate::desktop_testing as desktop;
100 pub use crate::duty::warm::run::{Started, WarmScript};
101 pub use crate::host::Ran;
102 pub use crate::host::fs::testing as fs;
106 pub use crate::host::memory::MemoryHost;
107 pub use crate::provider::claude::api::Renewed;
108 pub use crate::provider::claude::paths::live_service;
109 pub use crate::provider::claude::slot::{LIVE_SERVICE, dir_hash, service_for_dir};
110 pub use crate::stand_in;
113 pub use crate::store::memory::{Fault, MemoryStore};
114 pub use crate::store::vault_read;
115 pub use crate::switch::enroll::{ScriptedSignIn, SignInScript};
116 pub use crate::time::{Clock, FixedClock};
117
118 pub fn variables() -> impl Iterator<Item = &'static str> {
121 crate::context::variables()
122 }
123
124 pub fn lies_in(path: &std::path::Path, place: &std::path::Path) -> bool {
126 crate::host::lies_in(path, place)
127 }
128
129 pub fn real_login_places(
130 started_in: &crate::context::Context,
131 ) -> Result<Vec<std::path::PathBuf>, String> {
132 use crate::host::user;
133 let home = user::accounts_own_home().ok_or("this system names no home for this account")?;
134 let pitboard = user::accounts_own_pitboard_home()
135 .ok_or("this system names no Pitboard folder for this account")?;
136 let own = crate::context::Context::new(home).with_pitboard_home(pitboard);
137 Ok([&own, started_in]
138 .into_iter()
139 .flat_map(|ctx| {
140 [
141 crate::provider::claude::paths::config_dir(ctx),
142 crate::provider::claude::paths::config_file(ctx),
143 crate::provider::codex::paths::home(ctx),
144 ctx.pitboard_home.clone(),
145 ctx.home.join("Library/Application Support/Claude"),
146 ctx.home.join("Library/Application Support/Claude-3p"),
147 std::path::PathBuf::from("/Applications/Claude.app"),
148 ]
149 })
150 .filter(|place| place.is_absolute())
151 .collect())
152 }
153
154 pub fn vault_write(
157 ctx: &crate::context::Context,
158 service: &str,
159 contents: &str,
160 ) -> crate::error::Result<()> {
161 let permit = crate::service::gate(ctx)?;
162 Ok(crate::store::vault_write(ctx, permit, service, contents)?)
163 }
164
165 pub fn vault_delete(ctx: &crate::context::Context, service: &str) -> crate::error::Result<()> {
167 let permit = crate::service::gate(ctx)?;
168 Ok(crate::store::vault_delete(ctx, permit, service)?)
169 }
170
171 pub fn signed_in(
176 ctx: &crate::context::Context,
177 which: crate::provider::ProviderId,
178 document: &str,
179 ) -> crate::error::Result<crate::switch::SignIn> {
180 use crate::provider::LoginKind;
181 let document = serde_json::from_str(document).expect("a login a test wrote as JSON");
182 match crate::provider::of(which) {
183 LoginKind::Document(tool) => {
184 crate::switch::planted(ctx, crate::service::gate(ctx)?, tool, document)
185 }
186 LoginKind::Folder(_) => Err(crate::error::Error::Usage(
187 "a Claude Desktop sign-in is played by testing::desktop".into(),
188 )),
189 }
190 }
191}