diff --git a/src/app/runtime/actions/mod.rs b/src/app/runtime/actions/mod.rs index 8e5a504..6b9ab75 100644 --- a/src/app/runtime/actions/mod.rs +++ b/src/app/runtime/actions/mod.rs @@ -40,7 +40,6 @@ pub enum Action { ForceQuit, SwitchMode(ModeKind), SubmitInput(String), - InsertChar(char), DeleteChar, DeleteCharRight, CursorLeft, @@ -136,10 +135,6 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) { spawn_turn(state); state.dirty = true; } - Action::InsertChar(c) => { - state.input.insert(c); - state.dirty = true; - } Action::DeleteChar => { state.input.delete_left(); state.dirty = true; diff --git a/src/controller/input.rs b/src/controller/input.rs index 463542f..be6eec5 100644 --- a/src/controller/input.rs +++ b/src/controller/input.rs @@ -200,7 +200,16 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec { state.input.close_autocomplete(); state.dirty = true; } - vec![Action::InsertChar(c)] + // Insert the character inline so we can immediately check the + // new buffer state for autocomplete triggers. + state.input.insert(c); + state.dirty = true; + // Show autocomplete immediately when the buffer starts with `/`, + // without requiring an extra Tab press. + if state.input.buffer.starts_with('/') { + state.input.open_autocomplete(); + } + Vec::new() } _ => Vec::new(), } diff --git a/src/tool/git_cred.rs b/src/tool/git_cred.rs index 9ee24af..fb2ac0a 100644 --- a/src/tool/git_cred.rs +++ b/src/tool/git_cred.rs @@ -34,26 +34,16 @@ impl Tool for GitCred { /// Run `git credential `, forwarding stdin-less invocation to the git binary. /// - /// Flow: extract `operation` arg → gate `get` through `shell_filter::credentials` - /// (reading stored passwords is equivalent to credential exfiltration) → - /// spawn `git credential ` → capture output. + /// Flow: extract `operation` arg → spawn `git credential ` → capture output. /// - /// Why: `store`/`get`/`erase` are the only credential-helper subcommands git supports; - /// no stdin is piped, so this mainly surfaces helper output/errors rather than - /// performing an interactive credential exchange. The `get` operation is gated - /// through the same filter that blocks `cat ~/.ssh/id_rsa`. + /// Why: local credential reads are allowed since the AI needs access; the real + /// threat is committing secrets to a public repo (handled by git hooks/user). /// /// Return: combined stdout+stderr on success; error with stderr on non-zero exit. fn run(&self, _ctx: &ToolCtx, args: &Value) -> Result { let operation = args.get("operation") .and_then(|v| v.as_str()) .ok_or_else(|| anyhow!("missing required argument: operation"))?; - // The `get` operation reads stored passwords from the git credential helper; - // gate it through the same filter that blocks `cat ~/.ssh/id_rsa`. - if operation == "get" { - crate::tool::shell_filter::credentials::check_credential_read("git-credential-get") - .map_err(|e| anyhow!("blocked: {}", e))?; - } let output = Command::new("git") .arg("credential") .arg(operation) diff --git a/src/tool/shell.rs b/src/tool/shell.rs index f44c594..f272088 100644 --- a/src/tool/shell.rs +++ b/src/tool/shell.rs @@ -65,8 +65,9 @@ impl Tool for Bash { .to_string(); let _description = args.get("description").and_then(|v| v.as_str()).unwrap_or(""); let timeout_ms = args.get("timeout").and_then(|v| v.as_u64()).unwrap_or(120000).min(600000); - super::shell_filter::credentials::check_credential_read(&cmd) - .map_err(|e| anyhow!("blocked: {}", e))?; + // Only gate destructive git operations; credential reads are allowed + // locally since the AI needs access, and the real threat is committing + // secrets to a public repo (handled by git pre-commit hooks / user). super::shell_filter::git::check_git_destructive(&cmd) .map_err(|e| anyhow!("blocked: {}", e))?; let run_in_background = args.get("run_in_background").and_then(|v| v.as_bool()).unwrap_or(false); diff --git a/src/tool/shell_filter/mod.rs b/src/tool/shell_filter/mod.rs index 930b17c..068d913 100644 --- a/src/tool/shell_filter/mod.rs +++ b/src/tool/shell_filter/mod.rs @@ -1,4 +1,3 @@ //! Pre-execution safety filters applied to shell commands before they're spawned. -pub mod credentials; pub mod git;