feat: AI based permission checks
This commit is contained in:
45
src/app.rs
45
src/app.rs
@@ -16,7 +16,7 @@ use preferences::{parse_optional_gib, parse_streaming_cache};
|
||||
|
||||
use crate::config::{
|
||||
Config, DevBrainConfig, EndpointConfig, GitConfig, GitDiffAlgorithm, GitDiffLayout,
|
||||
GitDiffWhitespace,
|
||||
GitDiffWhitespace, PermissionMode,
|
||||
};
|
||||
use crate::database::{Database, ProjectWithSessions, SessionState, StoredMessage};
|
||||
#[cfg(any(target_os = "macos", test))]
|
||||
@@ -76,6 +76,7 @@ pub(crate) struct App {
|
||||
restore_dev_brain_confirmation: bool,
|
||||
selected_project: Option<i32>,
|
||||
selected_session: Option<i32>,
|
||||
pub(super) permission_mode: PermissionMode,
|
||||
/// Unsaved sessions, keyed by project. A draft only becomes a `sessions` row
|
||||
/// when its first chat turn is stored, so empty ones vanish on restart.
|
||||
drafts: HashMap<i32, String>,
|
||||
@@ -178,6 +179,7 @@ pub(crate) struct App {
|
||||
struct ChatSnapshot {
|
||||
selected_project: Option<i32>,
|
||||
selected_session: Option<i32>,
|
||||
permission_mode: PermissionMode,
|
||||
composer: text_editor::Content,
|
||||
queued_inputs: VecDeque<String>,
|
||||
conversation: Vec<ChatMessage>,
|
||||
@@ -349,6 +351,7 @@ pub(crate) enum Message {
|
||||
FocusNext,
|
||||
FocusPrevious,
|
||||
PreferenceModelChanged(ModelChoice),
|
||||
PreferencePermissionModeChanged(PermissionMode),
|
||||
PreferenceLegacyMtpChanged(bool),
|
||||
PreferenceDsparkChanged(bool),
|
||||
PreferenceTimeoutChanged(String),
|
||||
@@ -446,6 +449,7 @@ pub(crate) enum Message {
|
||||
CreateSession(i32),
|
||||
DraftProjectChanged(i32),
|
||||
SwitchGitBranch(String),
|
||||
PermissionModeChanged(PermissionMode),
|
||||
ToggleGitFile(PathBuf),
|
||||
OpenGitDiff(PathBuf),
|
||||
SetGitDiffLayout(GitDiffLayout),
|
||||
@@ -502,6 +506,7 @@ impl App {
|
||||
#[cfg(target_os = "macos")]
|
||||
crate::engine::sweep_transient_cache(&transient_cache_path());
|
||||
let context_limit = config.generation.context_tokens.max(0) as u32;
|
||||
let default_permission_mode = config.default_permission_mode;
|
||||
// Reopen on the project we left, with a fresh draft chat.
|
||||
let last_project = config
|
||||
.interface
|
||||
@@ -538,6 +543,7 @@ impl App {
|
||||
restore_dev_brain_confirmation: false,
|
||||
selected_project: last_project,
|
||||
selected_session: None,
|
||||
permission_mode: default_permission_mode,
|
||||
drafts,
|
||||
git_states: HashMap::new(),
|
||||
git_worktrees: HashMap::new(),
|
||||
@@ -653,6 +659,7 @@ impl App {
|
||||
let config = Config::default();
|
||||
let preference_draft = PreferenceDraft::from_saved(&config);
|
||||
let context_limit = config.generation.context_tokens.max(0) as u32;
|
||||
let default_permission_mode = config.default_permission_mode;
|
||||
let metrics = Arc::new(Metrics::new(&application_support_path().join("kv-cache")));
|
||||
let metrics_snapshot = metrics.snapshot();
|
||||
let git_diff_layout = config.git.diff_layout;
|
||||
@@ -683,6 +690,7 @@ impl App {
|
||||
restore_dev_brain_confirmation: false,
|
||||
selected_project: None,
|
||||
selected_session: None,
|
||||
permission_mode: default_permission_mode,
|
||||
drafts: HashMap::new(),
|
||||
git_states: HashMap::new(),
|
||||
git_worktrees: HashMap::new(),
|
||||
@@ -780,6 +788,7 @@ impl App {
|
||||
ChatSnapshot {
|
||||
selected_project: self.selected_project.take(),
|
||||
selected_session: self.selected_session.take(),
|
||||
permission_mode: self.permission_mode,
|
||||
composer: std::mem::take(&mut self.composer),
|
||||
queued_inputs: std::mem::take(&mut self.queued_inputs),
|
||||
conversation: std::mem::take(&mut self.conversation),
|
||||
@@ -828,6 +837,7 @@ impl App {
|
||||
fn restore_chat_snapshot(&mut self, snapshot: ChatSnapshot) {
|
||||
self.selected_project = snapshot.selected_project;
|
||||
self.selected_session = snapshot.selected_session;
|
||||
self.permission_mode = snapshot.permission_mode;
|
||||
self.composer = snapshot.composer;
|
||||
self.queued_inputs = snapshot.queued_inputs;
|
||||
self.conversation = snapshot.conversation;
|
||||
@@ -1512,6 +1522,34 @@ impl App {
|
||||
}
|
||||
Message::DraftProjectChanged(project_id) => self.move_draft_to_project(project_id),
|
||||
Message::SwitchGitBranch(branch) => self.switch_git_branch(&branch),
|
||||
Message::PermissionModeChanged(mode) => {
|
||||
#[cfg(target_os = "macos")]
|
||||
if self.active_tools.is_some() {
|
||||
self.error = Some(
|
||||
"Wait for the current tool batch before changing permission mode.".into(),
|
||||
);
|
||||
return Task::none();
|
||||
}
|
||||
if let Some(session_id) = self.selected_session {
|
||||
let Some(database) = &mut self.database else {
|
||||
self.error = Some("The project database is unavailable.".into());
|
||||
return Task::none();
|
||||
};
|
||||
match database.set_session_permission_mode(session_id, mode) {
|
||||
Ok(()) => {
|
||||
self.permission_mode = mode;
|
||||
self.error = None;
|
||||
self.reload_projects();
|
||||
}
|
||||
Err(error) => {
|
||||
self.error = Some(format!("Could not save permission mode: {error}"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.permission_mode = mode;
|
||||
self.error = None;
|
||||
}
|
||||
}
|
||||
Message::ToggleGitFile(path) => self.toggle_git_file(path),
|
||||
Message::OpenGitDiff(path) => self.open_git_diff(&path),
|
||||
Message::SetGitDiffLayout(layout) => self.git_diff_layout = layout,
|
||||
@@ -1681,6 +1719,7 @@ impl App {
|
||||
session.context_used,
|
||||
session.context_limit,
|
||||
session.last_tokens_per_second,
|
||||
session.permission_mode(),
|
||||
)
|
||||
});
|
||||
let Some(database) = &mut self.database else {
|
||||
@@ -1722,7 +1761,8 @@ impl App {
|
||||
self.selected_session = Some(session_id);
|
||||
self.system_prompt_seen_at = 0;
|
||||
self.queued_inputs.clear();
|
||||
let (used, limit, tokens_per_second) = saved_context.unwrap_or_default();
|
||||
let (used, limit, tokens_per_second, permission_mode) =
|
||||
saved_context.unwrap_or((0, 0, None, PermissionMode::default()));
|
||||
self.context_used = used.max(0) as u32;
|
||||
self.context_limit = if limit > 0 {
|
||||
limit as u32
|
||||
@@ -1730,6 +1770,7 @@ impl App {
|
||||
self.config.generation.context_tokens.max(0) as u32
|
||||
};
|
||||
self.tokens_per_second = tokens_per_second;
|
||||
self.permission_mode = permission_mode;
|
||||
self.error = restore_error;
|
||||
self.reload_projects();
|
||||
return Task::batch([scroll_chat_to_end(), self.load_next_a2ui_image()]);
|
||||
|
||||
Reference in New Issue
Block a user