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
19 changes: 19 additions & 0 deletions crates/goose-mcp/src/developer/rmcp_developer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1765,6 +1765,25 @@ mod tests {
.as_text()
.unwrap();
assert!(user_content.text.contains("Hello, world!"));

// The assistant-audience content must be extractable via as_text()
let assistant_content = view_result
.content
.iter()
.find(|c| {
c.audience()
.is_some_and(|roles| roles.contains(&Role::Assistant))
})
.expect("view should return content with Assistant audience");
assert!(
assistant_content.as_text().is_some(),
"assistant content must be RawContent::Text, not Resource"
);
assert!(assistant_content
.as_text()
.unwrap()
.text
.contains("Hello, world!"));
}

#[tokio::test]
Expand Down
18 changes: 2 additions & 16 deletions crates/goose-mcp/src/developer/text_editor.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
use anyhow::Result;
use indoc::formatdoc;
use mpatch::{apply_patch, parse_diffs, PatchError};
use rmcp::model::{Content, ErrorCode, ErrorData, Role};
use std::{
collections::HashMap,
fs::File,
io::Read,
path::{Path, PathBuf},
};
use url::Url;

use rmcp::model::{Content, ErrorCode, ErrorData, Role};

use super::editor_models::EditorModel;
use super::lang;
Expand Down Expand Up @@ -660,16 +658,6 @@ pub async fn text_editor_view(
// Ensure we never read over that limit even if the file is being concurrently mutated
let mut f = f.take(MAX_FILE_SIZE);

let uri = Url::from_file_path(path)
.map_err(|_| {
ErrorData::new(
ErrorCode::INTERNAL_ERROR,
"Invalid file path".to_string(),
None,
)
})?
.to_string();

let mut content = String::new();
f.read_to_string(&mut content).map_err(|e| {
ErrorData::new(
Expand All @@ -691,10 +679,8 @@ pub async fn text_editor_view(
let (start_idx, end_idx) = calculate_view_range(view_range, total_lines)?;
let formatted = format_file_content(path, &lines, start_idx, end_idx, view_range);

// The LLM gets just a quick update as we expect the file to view in the status
// but we send a low priority message for the human
Ok(vec![
Content::embedded_text(uri, content).with_audience(vec![Role::Assistant]),
Content::text(formatted.clone()).with_audience(vec![Role::Assistant]),
Content::text(formatted)
.with_audience(vec![Role::User])
.with_priority(0.0),
Comment on lines +683 to 686
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

This change fixes model-facing output by switching the assistant-audience payload to Content::text, but there’s no regression test asserting that text_editor view returns non-empty assistant-audience text content (current tests only validate the user-audience output); consider adding a test in crates/goose-mcp/src/developer/rmcp_developer.rs that locates the Role::Assistant item and asserts it contains the viewed lines.

Copilot generated this review using guidance from repository custom instructions.
Expand Down
Loading