aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-ai/src/permissions/resolver.rs
diff options
context:
space:
mode:
authorMichelle Tilley <michelle@michelletilley.net>2026-04-10 13:24:57 -0700
committerGitHub <noreply@github.com>2026-04-10 20:24:57 +0000
commit09279a428659cf41824737d3e0c97bcc19a8885a (patch)
tree64731502c065df2483e8dd680d46c5559f3094f2 /crates/atuin-ai/src/permissions/resolver.rs
parentfeat: add strip_trailing_whitespace, on by default (#3390) (diff)
downloadatuin-09279a428659cf41824737d3e0c97bcc19a8885a.zip
feat: Client-tool execution + permission system (#3370)
Adds client-side tool execution to Atuin AI, starting with `atuin_history`. The server can request tool calls, which are executed locally with a permission system, and results are sent back to continue the conversation.
Diffstat (limited to 'crates/atuin-ai/src/permissions/resolver.rs')
-rw-r--r--crates/atuin-ai/src/permissions/resolver.rs31
1 files changed, 31 insertions, 0 deletions
diff --git a/crates/atuin-ai/src/permissions/resolver.rs b/crates/atuin-ai/src/permissions/resolver.rs
new file mode 100644
index 00000000..dc4f83bf
--- /dev/null
+++ b/crates/atuin-ai/src/permissions/resolver.rs
@@ -0,0 +1,31 @@
+use std::path::PathBuf;
+
+use eyre::Result;
+
+use crate::permissions::check::{PermissionChecker, PermissionRequest, PermissionResponse};
+use crate::permissions::walker::PermissionWalker;
+use crate::permissions::writer;
+use crate::tools::ClientToolCall;
+
+/// Resolves permissions for client tool calls by walking the filesystem to find permission files,
+pub(crate) struct PermissionResolver {
+ checker: PermissionChecker,
+}
+
+impl PermissionResolver {
+ /// Create a new resolver that walks from `working_dir` to root for project
+ /// permissions, and also checks the global permissions file.
+ pub async fn new(working_dir: PathBuf) -> Result<Self> {
+ let global_file = writer::global_permissions_path();
+ let mut walker = PermissionWalker::new(working_dir, Some(global_file));
+ walker.walk().await?;
+ let checker = PermissionChecker::new(walker.rules().to_owned());
+ Ok(Self { checker })
+ }
+
+ /// Check whether `tool` is allowed, denied, or needs user confirmation.
+ pub async fn check(&self, tool: &ClientToolCall) -> Result<PermissionResponse> {
+ let request = PermissionRequest::new(tool);
+ self.checker.check(&request).await
+ }
+}