Skip to content
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6c97adf
First post
Aug 5, 2025
1a938d7
Merge branch 'main' into goose-apps
Aug 7, 2025
7191f75
What
Aug 7, 2025
7a6e6ff
Merge branch 'main' into goose-apps
Aug 17, 2025
a63775c
Make them launchable
Aug 17, 2025
fd93127
At least it compiles
Aug 18, 2025
424b3e8
Merge branch 'main' into goose-apps
Sep 26, 2025
2d34098
Throw
Sep 27, 2025
9266aca
One step
Sep 27, 2025
9922462
Spawn a recipe
Sep 27, 2025
b8c55ee
Extension support -ish
Sep 27, 2025
7af960f
Merge branch 'main' into goose-apps
Nov 1, 2025
5cf680b
Include the clock
Nov 1, 2025
5bfe874
I dont know
Nov 1, 2025
19ac055
WIP
Nov 1, 2025
e2c0269
WIP 3
Nov 1, 2025
b5f5754
WIP 5
Nov 2, 2025
01cda27
Serving
Nov 2, 2025
514593a
Fix image processing
Nov 3, 2025
d1c36dd
Remove print
Nov 4, 2025
e2d242d
Actually save
Nov 5, 2025
2c27388
Merge branch 'main' into goose-apps
Nov 7, 2025
14d12a6
Say more
Nov 7, 2025
aaa3ffa
External clock
Nov 7, 2025
6082aa6
Report errors
Nov 7, 2025
02b040c
Merge branch 'main' into goose-apps
Nov 15, 2025
ef4af72
Merge
Nov 15, 2025
2fea66d
Merge branch 'main' into goose-apps
Dec 5, 2025
ebdcc40
That's a lot
Dec 10, 2025
5941fe5
More
Dec 10, 2025
e64e8bd
Bla
Dec 10, 2025
65744d4
WIP
Dec 11, 2025
4c8b1d4
Merge branch 'main' into tool-reply-meta
Dec 11, 2025
630982a
Revert a bunch
Dec 11, 2025
25828bc
Merge branch 'main' into tool-reply-meta
Dec 11, 2025
4224831
api
Dec 11, 2025
63cbab6
recordings
Dec 11, 2025
634577e
Hmm, what?
Dec 11, 2025
79b3d98
Maybe now?
Dec 11, 2025
43f6d58
Also the other
Dec 11, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl Evaluation for DeveloperImage {
if let MessageContent::ToolResponse(tool_resp) = content {
if let Ok(result) = &tool_resp.tool_result {
// Check each item in the result list
for item in result {
for item in &result.content {
if let Some(image) = item.as_image() {
// Image content already contains mime_type and data
if image.mime_type.starts_with("image/")
Expand Down
11 changes: 6 additions & 5 deletions crates/goose-cli/src/commands/acp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use goose::mcp_utils::ToolResult;
use goose::providers::create;
use goose::session::session_manager::SessionType;
use goose::session::SessionManager;
use rmcp::model::{Content, RawContent, ResourceContents, Role};
use rmcp::model::{CallToolResult, RawContent, ResourceContents, Role};
use std::collections::{HashMap, HashSet};
use std::fs;
use std::sync::Arc;
Expand Down Expand Up @@ -74,8 +74,8 @@ fn extract_tool_locations(
.and_then(|c| c.as_str());

// Extract line numbers from the response content
if let Ok(content_items) = &tool_response.tool_result {
for content in content_items {
if let Ok(result) = &tool_response.tool_result {
for content in &result.content {
if let RawContent::Text(text_content) = &content.raw {
let text = &text_content.text;

Expand Down Expand Up @@ -491,9 +491,10 @@ impl GooseAcpAgent {
}

/// Build tool call content from tool result
fn build_tool_call_content(tool_result: &ToolResult<Vec<Content>>) -> Vec<ToolCallContent> {
fn build_tool_call_content(tool_result: &ToolResult<CallToolResult>) -> Vec<ToolCallContent> {
match tool_result {
Ok(content_items) => content_items
Ok(result) => result
.content
.iter()
.filter_map(|content| match &content.raw {
RawContent::Text(val) => Some(ToolCallContent::Content {
Expand Down
104 changes: 87 additions & 17 deletions crates/goose-cli/src/session/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,12 @@ pub fn tool_response_to_markdown(resp: &ToolResponse, export_all_content: bool)
md.push_str("#### Tool Response:\n");

match &resp.tool_result {
Ok(contents) => {
if contents.is_empty() {
Ok(result) => {
if result.content.is_empty() {
md.push_str("*No textual output from tool.*\n");
}

for content in contents {
for content in &result.content {
if !export_all_content {
if let Some(audience) = content.audience() {
if !audience.contains(&Role::Assistant) {
Expand Down Expand Up @@ -581,7 +581,12 @@ mod tests {
};
let tool_response = ToolResponse {
id: "test-id".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let result = tool_response_to_markdown(&tool_response, true);
Expand All @@ -601,7 +606,12 @@ mod tests {
};
let tool_response = ToolResponse {
id: "test-id".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let result = tool_response_to_markdown(&tool_response, true);
Expand Down Expand Up @@ -707,7 +717,12 @@ if __name__ == "__main__":
};
let tool_response = ToolResponse {
id: "shell-cat".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&tool_request, true);
Expand Down Expand Up @@ -748,7 +763,12 @@ if __name__ == "__main__":
};
let tool_response = ToolResponse {
id: "git-status".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&tool_request, true);
Expand Down Expand Up @@ -797,7 +817,12 @@ warning: unused variable `x`
};
let tool_response = ToolResponse {
id: "cargo-build".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let response_result = tool_response_to_markdown(&tool_response, true);
Expand Down Expand Up @@ -844,7 +869,12 @@ warning: unused variable `x`
};
let tool_response = ToolResponse {
id: "curl-api".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let response_result = tool_response_to_markdown(&tool_response, true);
Expand Down Expand Up @@ -880,7 +910,12 @@ warning: unused variable `x`
};
let tool_response = ToolResponse {
id: "editor-write".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&tool_request, true);
Expand Down Expand Up @@ -937,7 +972,12 @@ def process_data(data: List[Dict]) -> List[Dict]:
};
let tool_response = ToolResponse {
id: "editor-view".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let response_result = tool_response_to_markdown(&tool_response, true);
Expand Down Expand Up @@ -974,7 +1014,12 @@ Command failed with exit code 2"#;
};
let tool_response = ToolResponse {
id: "shell-error".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let response_result = tool_response_to_markdown(&tool_response, true);
Expand Down Expand Up @@ -1014,7 +1059,12 @@ Command failed with exit code 2"#;
};
let tool_response = ToolResponse {
id: "script-exec".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&tool_request, true);
Expand Down Expand Up @@ -1061,7 +1111,12 @@ drwx------ 3 user staff 96 Dec 6 16:20 com.apple.launchd.abc
};
let tool_response = ToolResponse {
id: "multi-cmd".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&_tool_request, true);
Expand Down Expand Up @@ -1104,7 +1159,12 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
};
let tool_response = ToolResponse {
id: "grep-search".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&tool_request, true);
Expand Down Expand Up @@ -1144,7 +1204,12 @@ src/middleware.rs:12:async fn auth_middleware(req: Request, next: Next) -> Resul
};
let tool_response = ToolResponse {
id: "json-test".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let response_result = tool_response_to_markdown(&tool_response, true);
Expand Down Expand Up @@ -1185,7 +1250,12 @@ found 0 vulnerabilities"#;
};
let tool_response = ToolResponse {
id: "npm-install".to_string(),
tool_result: Ok(vec![Content::text(text_content.raw.text)]),
tool_result: Ok(rmcp::model::CallToolResult {
content: vec![Content::text(text_content.raw.text)],
structured_content: None,
is_error: Some(false),
meta: None,
}),
};

let request_result = tool_request_to_markdown(&tool_request, true);
Expand Down
4 changes: 2 additions & 2 deletions crates/goose-cli/src/session/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ fn render_tool_response(resp: &ToolResponse, theme: Theme, debug: bool) {
let config = Config::global();

match &resp.tool_result {
Ok(contents) => {
for content in contents {
Ok(result) => {
for content in &result.content {
if let Some(audience) = content.audience() {
if !audience.contains(&rmcp::model::Role::User) {
continue;
Expand Down
6 changes: 6 additions & 0 deletions crates/goose-server/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ derive_utoipa!(Icon as IconSchema);
super::routes::agent::start_agent,
super::routes::agent::resume_agent,
super::routes::agent::get_tools,
super::routes::agent::read_resource,
super::routes::agent::call_tool,
super::routes::agent::update_from_session,
super::routes::agent::agent_add_extension,
super::routes::agent::agent_remove_extension,
Expand Down Expand Up @@ -514,6 +516,10 @@ derive_utoipa!(Icon as IconSchema);
goose::agents::types::SuccessCheck,
super::routes::agent::UpdateProviderRequest,
super::routes::agent::GetToolsQuery,
super::routes::agent::ReadResourceRequest,
super::routes::agent::ReadResourceResponse,
super::routes::agent::CallToolRequest,
super::routes::agent::CallToolResponse,
super::routes::agent::UpdateRouterToolSelectorRequest,
super::routes::agent::StartAgentRequest,
super::routes::agent::ResumeAgentRequest,
Expand Down
Loading
Loading