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
54 changes: 45 additions & 9 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ uninlined_format_args = "allow"
string_slice = "warn"

[workspace.dependencies]
rmcp = { version = "0.12.0", features = ["schemars", "auth"] }
rmcp = { version = "0.13.0", features = ["schemars", "auth"] }
anyhow = "1.0"
futures = "0.3"
regex = "1.12"
Expand Down
15 changes: 15 additions & 0 deletions crates/goose-cli/src/session/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ mod tests {
#[test]
fn test_tool_request_to_markdown_shell() {
let tool_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "ls -la",
Expand All @@ -552,6 +553,7 @@ mod tests {
#[test]
fn test_tool_request_to_markdown_text_editor() {
let tool_call = CallToolRequestParam {
task: None,
name: "developer__text_editor".into(),
arguments: Some(object!({
"path": "/path/to/file.txt",
Expand Down Expand Up @@ -635,6 +637,7 @@ mod tests {
#[test]
fn test_message_to_markdown_with_tool_request() {
let tool_call = CallToolRequestParam {
task: None,
name: "test_tool".into(),
arguments: Some(object!({"param": "value"})),
};
Expand Down Expand Up @@ -694,6 +697,7 @@ mod tests {
#[test]
fn test_shell_tool_with_code_output() {
let tool_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "cat main.py"
Expand Down Expand Up @@ -748,6 +752,7 @@ if __name__ == "__main__":
#[test]
fn test_shell_tool_with_git_commands() {
let git_status_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "git status --porcelain"
Expand Down Expand Up @@ -794,6 +799,7 @@ if __name__ == "__main__":
#[test]
fn test_shell_tool_with_build_output() {
let cargo_build_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "cargo build"
Expand Down Expand Up @@ -846,6 +852,7 @@ warning: unused variable `x`
#[test]
fn test_shell_tool_with_json_api_response() {
let curl_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "curl -s https://api.github.com/repos/microsoft/vscode/releases/latest"
Expand Down Expand Up @@ -900,6 +907,7 @@ warning: unused variable `x`
#[test]
fn test_text_editor_tool_with_code_creation() {
let editor_call = CallToolRequestParam {
task: None,
name: "developer__text_editor".into(),
arguments: Some(object!({
"command": "write",
Expand Down Expand Up @@ -949,6 +957,7 @@ warning: unused variable `x`
#[test]
fn test_text_editor_tool_view_code() {
let editor_call = CallToolRequestParam {
task: None,
name: "developer__text_editor".into(),
arguments: Some(object!({
"command": "view",
Expand Down Expand Up @@ -1007,6 +1016,7 @@ def process_data(data: List[Dict]) -> List[Dict]:
#[test]
fn test_shell_tool_with_error_output() {
let error_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "python nonexistent_script.py"
Expand Down Expand Up @@ -1050,6 +1060,7 @@ Command failed with exit code 2"#;
#[test]
fn test_shell_tool_complex_script_execution() {
let script_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "python -c \"import sys; print(f'Python {sys.version}'); [print(f'{i}^2 = {i**2}') for i in range(1, 6)]\""
Expand Down Expand Up @@ -1104,6 +1115,7 @@ Command failed with exit code 2"#;
#[test]
fn test_shell_tool_with_multi_command() {
let multi_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "cd /tmp && ls -la | head -5 && pwd"
Expand Down Expand Up @@ -1156,6 +1168,7 @@ drwx------ 3 user staff 96 Dec 6 16:20 com.apple.launchd.abc
#[test]
fn test_developer_tool_grep_code_search() {
let grep_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "rg 'async fn' --type rust -n"
Expand Down Expand Up @@ -1207,6 +1220,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
fn test_shell_tool_json_detection_works() {
// This test shows that JSON detection in tool responses DOES work
let tool_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "echo '{\"test\": \"json\"}'"
Expand Down Expand Up @@ -1249,6 +1263,7 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
#[test]
fn test_shell_tool_with_package_management() {
let npm_call = CallToolRequestParam {
task: None,
name: "developer__shell".into(),
arguments: Some(object!({
"command": "npm install express typescript @types/node --save-dev"
Expand Down
1 change: 1 addition & 0 deletions crates/goose-server/src/routes/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,7 @@ async fn call_tool(
};

let tool_call = CallToolRequestParam {
task: None,
name: payload.name.into(),
arguments,
};
Expand Down
1 change: 1 addition & 0 deletions crates/goose/examples/image_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ async fn main() -> Result<()> {
Message::assistant().with_tool_request(
"000",
Ok(CallToolRequestParam {
task: None,
name: "view_image".into(),
arguments: Some(object!({"path": "./test_image.png"})),
}),
Expand Down
1 change: 1 addition & 0 deletions crates/goose/src/agents/chatrecall_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl ChatRecallClient {
let info = InitializeResult {
protocol_version: ProtocolVersion::V_2025_03_26,
capabilities: ServerCapabilities {
tasks: None,
tools: Some(ToolsCapability {
list_changed: Some(false),
}),
Expand Down
2 changes: 2 additions & 0 deletions crates/goose/src/agents/code_execution_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ impl CodeExecutionClient {
let info = InitializeResult {
protocol_version: ProtocolVersion::V_2025_03_26,
capabilities: ServerCapabilities {
tasks: None,
tools: Some(ToolsCapability {
list_changed: Some(false),
}),
Expand Down Expand Up @@ -667,6 +668,7 @@ impl CodeExecutionClient {
let result = match extension_manager.as_ref().and_then(|w| w.upgrade()) {
Some(manager) => {
let tool_call = CallToolRequestParam {
task: None,
name: tool_name.into(),
arguments: serde_json::from_str(&arguments).ok(),
};
Expand Down
9 changes: 9 additions & 0 deletions crates/goose/src/agents/extension_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,7 @@ mod tests {

// verify a normal tool call
let tool_call = CallToolRequestParam {
task: None,
name: "test_client__tool".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1644,6 +1645,7 @@ mod tests {
assert!(result.is_ok());

let tool_call = CallToolRequestParam {
task: None,
name: "test_client__test__tool".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1655,6 +1657,7 @@ mod tests {

// verify a multiple underscores dispatch
let tool_call = CallToolRequestParam {
task: None,
name: "__cli__ent____tool".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1666,6 +1669,7 @@ mod tests {

// Test unicode in tool name, "client 🚀" should become "client_"
let tool_call = CallToolRequestParam {
task: None,
name: "client___tool".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1676,6 +1680,7 @@ mod tests {
assert!(result.is_ok());

let tool_call = CallToolRequestParam {
task: None,
name: "client___test__tool".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1687,6 +1692,7 @@ mod tests {

// this should error out, specifically for an ToolError::ExecutionError
let invalid_tool_call = CallToolRequestParam {
task: None,
name: "client___tools".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1712,6 +1718,7 @@ mod tests {
// this should error out, specifically with an ToolError::NotFound
// this client doesn't exist
let invalid_tool_call = CallToolRequestParam {
task: None,
name: "_client__tools".to_string().into(),
arguments: Some(object!({})),
};
Expand Down Expand Up @@ -1806,6 +1813,7 @@ mod tests {

// Try to call an unavailable tool
let unavailable_tool_call = CallToolRequestParam {
task: None,
name: "test_extension__tool".to_string().into(),
arguments: Some(object!({})),
};
Expand All @@ -1829,6 +1837,7 @@ mod tests {

// Try to call an available tool - should succeed
let available_tool_call = CallToolRequestParam {
task: None,
name: "test_extension__available_tool".to_string().into(),
arguments: Some(object!({})),
};
Expand Down
1 change: 1 addition & 0 deletions crates/goose/src/agents/extension_manager_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl ExtensionManagerClient {
let info = InitializeResult {
protocol_version: ProtocolVersion::V_2025_03_26,
capabilities: ServerCapabilities {
tasks: None,
tools: Some(ToolsCapability {
list_changed: Some(false),
}),
Expand Down
2 changes: 2 additions & 0 deletions crates/goose/src/agents/final_output_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ mod tests {

let mut tool = FinalOutputTool::new(response);
let tool_call = CallToolRequestParam {
task: None,
name: FINAL_OUTPUT_TOOL_NAME.into(),
arguments: Some(object!({
"message": "Hello" // Missing required "count" field
Expand All @@ -255,6 +256,7 @@ mod tests {

let mut tool = FinalOutputTool::new(response);
let tool_call = CallToolRequestParam {
task: None,
name: FINAL_OUTPUT_TOOL_NAME.into(),
arguments: Some(object!({
"user": {
Expand Down
Loading
Loading