use std::sync::{Mutex, MutexGuard};
use shuvarie_llm::ToolContext;
use crate::permissions::{Access, DenyCut, PermissionGate, Permissions};
static CWD_LOCK: Mutex<()> = Mutex::new(());
pub(crate) struct CwdGuard {
original: std::path::PathBuf,
#[allow(dead_code)]
lock: MutexGuard<'static, ()>,
}
pub(crate) fn lock_cwd() -> CwdGuard {
let lock = CWD_LOCK.lock().unwrap_or_else(|err| err.into_inner());
let original = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
CwdGuard { original, lock }
}
impl Drop for CwdGuard {
fn drop(&mut self) {
let _ = std::env::set_current_dir(&self.original);
}
}
pub(crate) fn tempdir() -> (tempfile::TempDir, CwdGuard) {
let guard = lock_cwd();
let dir = tempfile::TempDir::new().unwrap();
std::env::set_current_dir(dir.path()).unwrap();
(dir, guard)
}
pub(crate) fn new_ctx() -> ToolContext {
ToolContext::new()
}
pub(crate) fn access() -> Access {
access_for_config(&shuvarie_config::PermissionsConfig::builtin())
}
pub(crate) fn access_for_config(config: &shuvarie_config::PermissionsConfig) -> Access {
let permissions = std::sync::Arc::new(
Permissions::build(
config,
&std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from(".")),
)
.unwrap(),
);
let (tx, _rx) = tokio::sync::mpsc::channel(1);
Access::new(permissions, PermissionGate::new(tx), DenyCut::default())
}
pub(crate) fn access_with_answering_gate(
config: &shuvarie_config::PermissionsConfig,
) -> (
Access,
tokio::sync::mpsc::Receiver<crate::permissions::PermissionRequest>,
) {
let permissions = std::sync::Arc::new(
Permissions::build(
config,
&std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from(".")),
)
.unwrap(),
);
let (tx, rx) = tokio::sync::mpsc::channel(1);
(
Access::new(permissions, PermissionGate::new(tx), DenyCut::default()),
rx,
)
}