Add a test for remote tool use by the agent (#30289)

- Adds a new smoke test for the use of the read_file tool by the agent
in an SSH project
- Fixes the SSH shutdown sequence to use a timer from the app's executor
instead of always using a real timer
- Changes the main executor loop for tests to advance the clock
automatically instead of panicking with `parked with nothing left to
run` when there is a delayed task

Release Notes:

- N/A
This commit is contained in:
Cole Miller 2025-05-08 16:53:04 -04:00 committed by GitHub
parent 660b4cee76
commit 8b764a5477
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 104 additions and 13 deletions

View file

@ -69,6 +69,8 @@ fork.workspace = true
libc.workspace = true
[dev-dependencies]
assistant_tool.workspace = true
assistant_tools.workspace = true
client = { workspace = true, features = ["test-support"] }
clock = { workspace = true, features = ["test-support"] }
dap = { workspace = true, features = ["test-support"] }
@ -79,6 +81,7 @@ language = { workspace = true, features = ["test-support"] }
node_runtime = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
remote = { workspace = true, features = ["test-support"] }
language_model = { workspace = true, features = ["test-support"] }
lsp = { workspace = true, features=["test-support"] }
unindent.workspace = true
serde_json.workspace = true

View file

@ -2,8 +2,11 @@
/// The tests in this file assume that server_cx is running on Windows too.
/// We neead to find a way to test Windows-Non-Windows interactions.
use crate::headless_project::HeadlessProject;
use assistant_tool::Tool as _;
use assistant_tools::{ReadFileTool, ReadFileToolInput};
use client::{Client, UserStore};
use clock::FakeSystemClock;
use language_model::{LanguageModelRequest, fake_provider::FakeLanguageModel};
use extension::ExtensionHostProxy;
use fs::{FakeFs, Fs};
@ -1548,6 +1551,70 @@ async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestA
assert_eq!(server_branch.name(), "totally-new-branch");
}
#[gpui::test]
async fn test_remote_agent_fs_tool_calls(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
let fs = FakeFs::new(server_cx.executor());
fs.insert_tree(
path!("/project"),
json!({
"a.txt": "A",
"b.txt": "B",
}),
)
.await;
let (project, _headless_project) = init_test(&fs, cx, server_cx).await;
project
.update(cx, |project, cx| {
project.find_or_create_worktree(path!("/project"), true, cx)
})
.await
.unwrap();
let action_log = cx.new(|_| assistant_tool::ActionLog::new(project.clone()));
let model = Arc::new(FakeLanguageModel::default());
let request = Arc::new(LanguageModelRequest::default());
let input = ReadFileToolInput {
path: "project/b.txt".into(),
start_line: None,
end_line: None,
};
let exists_result = cx.update(|cx| {
ReadFileTool::run(
Arc::new(ReadFileTool),
serde_json::to_value(input).unwrap(),
request.clone(),
project.clone(),
action_log.clone(),
model.clone(),
None,
cx,
)
});
let output = exists_result.output.await.unwrap().content;
assert_eq!(output, "B");
let input = ReadFileToolInput {
path: "project/c.txt".into(),
start_line: None,
end_line: None,
};
let does_not_exist_result = cx.update(|cx| {
ReadFileTool::run(
Arc::new(ReadFileTool),
serde_json::to_value(input).unwrap(),
request.clone(),
project.clone(),
action_log.clone(),
model.clone(),
None,
cx,
)
});
does_not_exist_result.output.await.unwrap_err();
}
pub async fn init_test(
server_fs: &Arc<FakeFs>,
cx: &mut TestAppContext,