Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 12 additions & 5 deletions crates/goose-acp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,34 @@ fn create_tool_location(path: &str, line: Option<u32>) -> ToolCallLocation {
loc
}

fn is_developer_file_tool(tool_name: &str) -> bool {
matches!(tool_name, "write" | "edit")
}

fn extract_tool_locations(
tool_request: &goose::conversation::message::ToolRequest,
tool_response: &goose::conversation::message::ToolResponse,
) -> Vec<ToolCallLocation> {
let mut locations = Vec::new();

if let Ok(tool_call) = &tool_request.tool_call {
if tool_call.name != "developer__text_editor" {
if !is_developer_file_tool(tool_call.name.as_ref()) {
return locations;
}

let tool_name = tool_call.name.as_ref();
let path_str = tool_call
.arguments
.as_ref()
.and_then(|args| args.get("path"))
.and_then(|p| p.as_str());

if let Some(path_str) = path_str {
if matches!(tool_name, "write" | "edit") {
locations.push(create_tool_location(path_str, Some(1)));
return locations;
}

Comment on lines +105 to +132
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract_tool_locations() only recognizes unprefixed write|edit, but the codebase still contains/records tool calls with legacy names like developer__text_editor; consider accepting both legacy and new names so ACP can still extract locations from older sessions.

Copilot uses AI. Check for mistakes.
let command = tool_call
.arguments
.as_ref()
Expand Down Expand Up @@ -1432,10 +1442,7 @@ print(\"hello, world\")

#[test]
fn test_format_tool_name_with_extension() {
assert_eq!(
format_tool_name("developer__text_editor"),
"Developer: Text Editor"
);
assert_eq!(format_tool_name("developer__edit"), "Developer: Edit");
assert_eq!(
format_tool_name("platform__manage_extensions"),
"Platform: Manage Extensions"
Expand Down
6 changes: 3 additions & 3 deletions crates/goose-acp/tests/common_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ pub async fn run_prompt_basic<C: Connection>() {
pub async fn run_prompt_codemode<C: Connection>() {
let expected_session_id = ExpectedSessionId::default();
let prompt =
"Search for getCode and textEditor tools. Use them to save the code to /tmp/result.txt.";
"Search for getCode and write tools. Use them to save the code to /tmp/result.txt.";
let mcp = McpFixture::new(Some(expected_session_id.clone())).await;
let openai = OpenAiFixture::new(
vec![
Expand All @@ -326,7 +326,7 @@ pub async fn run_prompt_codemode<C: Connection>() {
include_str!("../test_data/openai_builtin_execute.txt"),
),
(
r#"Successfully wrote to /tmp/result.txt"#.into(),
r#"Created /tmp/result.txt"#.into(),
include_str!("../test_data/openai_builtin_final.txt"),
),
],
Expand All @@ -352,7 +352,7 @@ pub async fn run_prompt_codemode<C: Connection>() {
}

let result = fs::read_to_string("/tmp/result.txt").unwrap_or_default();
assert_eq!(result, format!("{FAKE_CODE}\n"));
assert_eq!(result, FAKE_CODE);
expected_session_id.assert_matches(&session.session_id().0);
}

Expand Down
14 changes: 7 additions & 7 deletions crates/goose-acp/tests/test_data/openai_builtin_execute.txt
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,9 @@ data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.c

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Developer"}}]},"finish_reason":null}],"usage":null,"obfuscation":"G6t"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".text"}}]},"finish_reason":null}],"usage":null,"obfuscation":"OOxdzNJq"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"."}}]},"finish_reason":null}],"usage":null,"obfuscation":"OOxdzNJq"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Editor"}}]},"finish_reason":null}],"usage":null,"obfuscation":"MiMZRWA"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"write"}}]},"finish_reason":null}],"usage":null,"obfuscation":"MiMZRWA"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"({"}}]},"finish_reason":null}],"usage":null,"obfuscation":"7sQdVn1KZH3"}

Expand Down Expand Up @@ -354,7 +354,7 @@ data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.c

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" "}}]},"finish_reason":null}],"usage":null,"obfuscation":"XurvUHlgwc"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" command"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ZsYLy"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" // command"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ZsYLy"}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test data file shows the tool call was changed from developer.textEditor to developer.write, but the comment on line 357 still says // command which doesn't match the new tool's parameter naming. The write tool uses content parameter, not command. This comment should likely be removed or updated to // content.

Suggested change
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" // command"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ZsYLy"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" // content"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ZsYLy"}

Copilot uses AI. Check for mistakes.

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"PFlue8D49Rzx"}

Expand All @@ -370,9 +370,9 @@ data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.c

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" "}}]},"finish_reason":null}],"usage":null,"obfuscation":"xVJI6wFQLA"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" file"}}]},"finish_reason":null}],"usage":null,"obfuscation":"aYkuCMJQ"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" content"}}]},"finish_reason":null}],"usage":null,"obfuscation":"aYkuCMJQ"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_text"}}]},"finish_reason":null}],"usage":null,"obfuscation":"DQ5IKXUC"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":""}}]},"finish_reason":null}],"usage":null,"obfuscation":"DQ5IKXUC"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":":"}}]},"finish_reason":null}],"usage":null,"obfuscation":"YaxTVILdGh6I"}

Expand Down Expand Up @@ -466,9 +466,9 @@ data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.c

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Developer"}}]},"finish_reason":null}],"usage":null,"obfuscation":"jzRU"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":".text"}}]},"finish_reason":null}],"usage":null,"obfuscation":"zeeCDR1q"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"."}}]},"finish_reason":null}],"usage":null,"obfuscation":"zeeCDR1q"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Editor"}}]},"finish_reason":null}],"usage":null,"obfuscation":"8YZ1VtI"}
data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"write"}}]},"finish_reason":null}],"usage":null,"obfuscation":"8YZ1VtI"}

data: {"id":"chatcmpl-D64NZp69RkEyXdUoDaCBj7fSYll8J","object":"chat.completion.chunk","created":1770339173,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\",\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"R15EQTSl"}

Expand Down
6 changes: 3 additions & 3 deletions crates/goose-acp/tests/test_data/openai_builtin_search.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.c

data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"evelop"}}]},"finish_reason":null}],"obfuscation":"YdjzlvJ"}

data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"er.t"}}]},"finish_reason":null}],"obfuscation":"Kv1vRc0to"}
data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"er.w"}}]},"finish_reason":null}],"obfuscation":"Kv1vRc0to"}

data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"extEd"}}]},"finish_reason":null}],"obfuscation":"4sRF9L7t"}
data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"rite"}}]},"finish_reason":null}],"obfuscation":"4sRF9L7t"}

data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"itor\"]"}}]},"finish_reason":null}],"obfuscation":"SmXF9J"}
data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"]"}}]},"finish_reason":null}],"obfuscation":"SmXF9J"}

data: {"id":"chatcmpl-D64NHpAses8hYgIt8xQfDCmg3PoHQ","object":"chat.completion.chunk","created":1770339155,"model":"gpt-5-nano-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"finish_reason":null}],"obfuscation":"kO5yFNBeMAXW"}

Expand Down
5 changes: 1 addition & 4 deletions crates/goose-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use goose::config::Config;
use goose::posthog::get_telemetry_choice;
use goose::recipe::Recipe;
use goose_mcp::mcp_server_runner::{serve, McpCommand};
use goose_mcp::{
AutoVisualiserRouter, ComputerControllerServer, DeveloperServer, MemoryServer, TutorialServer,
};
use goose_mcp::{AutoVisualiserRouter, ComputerControllerServer, MemoryServer, TutorialServer};

use crate::commands::configure::{configure_telemetry_consent_dialog, handle_configure};
use crate::commands::info::handle_info;
Expand Down Expand Up @@ -1018,7 +1016,6 @@ async fn handle_mcp_command(server: McpCommand) -> Result<()> {
McpCommand::ComputerController => serve(ComputerControllerServer::new()).await?,
McpCommand::Memory => serve(MemoryServer::new()).await?,
McpCommand::Tutorial => serve(TutorialServer::new()).await?,
McpCommand::Developer => serve(DeveloperServer::new()).await?,
}
Ok(())
}
Expand Down
35 changes: 22 additions & 13 deletions crates/goose-cli/src/commands/configure.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::recipes::github_recipe::GOOSE_RECIPE_GITHUB_REPO_CONFIG_KEY;
use cliclack::spinner;
use console::style;
use goose::agents::extension::ToolInfo;
use goose::agents::extension::{ToolInfo, PLATFORM_EXTENSIONS};
use goose::agents::extension_manager::get_parameter_names;
use goose::agents::Agent;
use goose::agents::{extension::Envs, ExtensionConfig};
Expand Down Expand Up @@ -983,24 +983,35 @@ fn configure_builtin_extension() -> anyhow::Result<()> {
select = select.item(id, name, desc);
}
let extension = select.interact()?.to_string();
let timeout = prompt_extension_timeout()?;

let (display_name, description) = extensions
.iter()
.find(|(id, _, _)| id == &extension)
.map(|(_, name, desc)| (name.to_string(), desc.to_string()))
.unwrap_or_else(|| (extension.clone(), extension.clone()));

set_extension(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Builtin {
let config = if PLATFORM_EXTENSIONS.contains_key(extension.as_str()) {
ExtensionConfig::Platform {
name: extension.clone(),
description,
display_name: Some(display_name),
bundled: Some(true),
available_tools: Vec::new(),
}
} else {
let timeout = prompt_extension_timeout()?;
ExtensionConfig::Builtin {
name: extension.clone(),
display_name: Some(display_name),
timeout: Some(timeout),
bundled: Some(true),
description,
available_tools: Vec::new(),
},
}
};

set_extension(ExtensionEntry {
enabled: true,
config,
});

cliclack::outro(format!("Enabled {} extension", style(extension).green()))?;
Expand Down Expand Up @@ -1741,12 +1752,11 @@ pub async fn handle_openrouter_auth() -> anyhow::Result<()> {
if !has_developer {
set_extension(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Builtin {
config: ExtensionConfig::Platform {
name: "developer".to_string(),
description: "Developer extension".to_string(),
display_name: Some(goose::config::DEFAULT_DISPLAY_NAME.to_string()),
timeout: Some(goose::config::DEFAULT_EXTENSION_TIMEOUT),
bundled: Some(true),
description: "Developer extension".to_string(),
available_tools: Vec::new(),
},
});
Expand Down Expand Up @@ -1811,12 +1821,11 @@ pub async fn handle_tetrate_auth() -> anyhow::Result<()> {
if !has_developer {
set_extension(ExtensionEntry {
enabled: true,
config: ExtensionConfig::Builtin {
config: ExtensionConfig::Platform {
name: "developer".to_string(),
description: "Developer extension".to_string(),
display_name: Some(goose::config::DEFAULT_DISPLAY_NAME.to_string()),
timeout: Some(goose::config::DEFAULT_EXTENSION_TIMEOUT),
bundled: Some(true),
description: "Developer extension".to_string(),
available_tools: Vec::new(),
},
});
Expand Down
Loading