From 6abc33648490faffaa33aaf5ca305c8dac44a797 Mon Sep 17 00:00:00 2001 From: Yingjie He Date: Tue, 11 Mar 2025 20:52:41 -0700 Subject: [PATCH] feat: add write approve mode (#1628) --- crates/goose-cli/src/commands/configure.rs | 11 ++++++++++- crates/goose-cli/src/session/completion.rs | 2 +- crates/goose-cli/src/session/mod.rs | 2 +- crates/goose/src/agents/truncate.rs | 4 ++-- documentation/docs/guides/goose-permissions.md | 4 +++- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/crates/goose-cli/src/commands/configure.rs b/crates/goose-cli/src/commands/configure.rs index 8eb4d94e..25d6b6e5 100644 --- a/crates/goose-cli/src/commands/configure.rs +++ b/crates/goose-cli/src/commands/configure.rs @@ -697,6 +697,11 @@ pub fn configure_goose_mode_dialog() -> Result<(), Box> { .item( "approve", "Approve Mode", + "All tools, extensions and file modificatio will require human approval" + ) + .item( + "write_approve", + "Write Approve Mode", "Editing, creating, deleting files and using extensions will require human approval" ) .item( @@ -713,7 +718,11 @@ pub fn configure_goose_mode_dialog() -> Result<(), Box> { } "approve" => { config.set_param("GOOSE_MODE", Value::String("approve".to_string()))?; - cliclack::outro("Set to Approve Mode - modifications require approval")?; + cliclack::outro("Set to Approve Mode - all tools and modifications require approval")?; + } + "write_approve" => { + config.set_param("GOOSE_MODE", Value::String("write_approve".to_string()))?; + cliclack::outro("Set to Write Approve Mode - modifications require approval")?; } "chat" => { config.set_param("GOOSE_MODE", Value::String("chat".to_string()))?; diff --git a/crates/goose-cli/src/session/completion.rs b/crates/goose-cli/src/session/completion.rs index 9346d499..ad3a0fbe 100644 --- a/crates/goose-cli/src/session/completion.rs +++ b/crates/goose-cli/src/session/completion.rs @@ -77,7 +77,7 @@ impl GooseCompleter { /// Complete flags for the /mode command fn complete_mode_flags(&self, line: &str) -> Result<(usize, Vec)> { - let modes = ["auto", "approve", "chat"]; + let modes = ["auto", "approve", "write_approve", "chat"]; let parts: Vec<&str> = line.split_whitespace().collect(); diff --git a/crates/goose-cli/src/session/mod.rs b/crates/goose-cli/src/session/mod.rs index 1f7a5fd4..694b8f55 100644 --- a/crates/goose-cli/src/session/mod.rs +++ b/crates/goose-cli/src/session/mod.rs @@ -335,7 +335,7 @@ impl Session { let mode = mode.to_lowercase(); // Check if mode is valid - if !["auto", "approve", "chat"].contains(&mode.as_str()) { + if !["auto", "approve", "chat", "write_approve"].contains(&mode.as_str()) { output::render_error(&format!( "Invalid mode '{}'. Mode must be one of: auto, approve, chat", mode diff --git a/crates/goose/src/agents/truncate.rs b/crates/goose/src/agents/truncate.rs index 3e45daed..393ef2b1 100644 --- a/crates/goose/src/agents/truncate.rs +++ b/crates/goose/src/agents/truncate.rs @@ -275,7 +275,7 @@ impl Agent for TruncateAgent { // Clone goose_mode once before the match to avoid move issues let mode = goose_mode.clone(); match mode.as_str() { - "approve" => { + "approve" | "write_approve" => { let mut read_only_tools = Vec::new(); let mut needs_confirmation = Vec::<&ToolRequest>::new(); let mut approved_tools = Vec::new(); @@ -298,7 +298,7 @@ impl Agent for TruncateAgent { } // Only check read-only status for tools needing confirmation - if !needs_confirmation.is_empty() { + if !needs_confirmation.is_empty() && mode == "write_approve" { read_only_tools = detect_read_only_tools(&capabilities, needs_confirmation.clone()).await; } diff --git a/documentation/docs/guides/goose-permissions.md b/documentation/docs/guides/goose-permissions.md index 24d87310..457811d2 100644 --- a/documentation/docs/guides/goose-permissions.md +++ b/documentation/docs/guides/goose-permissions.md @@ -15,7 +15,8 @@ Goose’s permissions determine how much autonomy it has when modifying files, u | Mode | Description | Best For | | ---------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | **Auto Mode** | Goose can modify files, use extensions, and delete files **without requiring approval**. | Users who want **full automation** and seamless integration into their workflow. | -| **Approve Mode** | Goose **asks for confirmation** before modifying, creating, deleting files and before using extensions. | Users who want to **review and approve** changes and extension use before they happen. | +| **Approve Mode** | Goose **asks for confirmation** before all tools and extensions. | Users who want to **review and approve** any changes and extension use before they happen. | +| **Write Approve Mode** | Goose **asks for confirmation** before modifying, creating, deleting files and before using extensions. | Users who want to **review and approve** write or risky changes and extension use before they happen. | | **Chat Mode** | Goose **only engages in chat**, with no extension use or file modifications. | Users who prefer a **conversational AI experience** without automation. | :::warning @@ -82,6 +83,7 @@ Here's how to configure: │ ● Auto Mode // highlight-end | ○ Approve Mode + | ○ Write Approve Mode | ○ Chat Mode | └ Set to Auto Mode - full file modification enabled