#[allow(clippy::wildcard_imports)]
use super::*;
pub(super) async fn shell_command_base_dir(
server: &LeanCtxServer,
args: Option<&serde_json::Map<String, serde_json::Value>>,
) -> Option<String> {
if let Some(cwd) = helpers::get_str(args, "cwd").filter(|c| !c.trim().is_empty()) {
return Some(cwd);
}
let session = server.session.read().await;
session
.shell_cwd
.clone()
.or_else(|| session.project_root.clone())
.filter(|c| !c.trim().is_empty())
}
pub(super) fn record_shell_file_effects(command: &str, base: Option<&str>) {
use lean_ctx::core::bounce_tracker::ReadView;
use lean_ctx::core::shell_file_effects::ShellReadKind;
let effects = lean_ctx::core::shell_file_effects::analyze(command);
if effects.reads.is_empty() && effects.edits.is_empty() {
return;
}
let resolve = |path: &str| -> String {
match base {
Some(dir) if !std::path::Path::new(path).is_absolute() && !path.starts_with('~') => {
std::path::Path::new(dir)
.join(path)
.to_string_lossy()
.into_owned()
}
_ => path.to_string(),
}
};
let Ok(mut bt) = lean_ctx::core::bounce_tracker::global().lock() else {
return;
};
bt.next_seq();
for (path, kind) in &effects.reads {
let view = match kind {
ShellReadKind::Full => ReadView::Full,
ShellReadKind::Partial => ReadView::Partial,
};
bt.record_shell_read(&resolve(path), view);
}
for path in &effects.edits {
bt.record_edit(&resolve(path));
}
}