Skip to content
Draft
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
30 changes: 13 additions & 17 deletions crates/tui/src/core/engine/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2555,13 +2555,11 @@ async fn yolo_mode_does_not_prompt_for_model_driven_typed_ask_rule() {
Event::ApprovalRequired { .. } => {
panic!("YOLO mode must not prompt for a model-driven typed ask-rule");
}
Event::ToolCallComplete { name, result, .. } => {
if name == "exec_shell" {
saw_complete = true;
let result = result.expect("shell result");
assert!(result.success, "{result:?}");
assert!(result.content.contains("yolo-model-ask-rule"), "{result:?}");
}
Event::ToolCallComplete { name, result, .. } if name == "exec_shell" => {
saw_complete = true;
let result = result.expect("shell result");
assert!(result.success, "{result:?}");
assert!(result.content.contains("yolo-model-ask-rule"), "{result:?}");
}
Event::TurnComplete { status, .. } => {
assert_eq!(status, TurnOutcomeStatus::Completed);
Expand Down Expand Up @@ -2690,16 +2688,14 @@ async fn yolo_mode_does_not_prompt_for_background_shell() {
Event::ApprovalRequired { .. } => {
panic!("YOLO mode must not prompt for a background shell command");
}
Event::ToolCallComplete { name, result, .. } => {
if name == "exec_shell" {
saw_complete = true;
let result = result.expect("shell result");
assert!(result.success, "{result:?}");
assert!(
result.content.contains("Background task started"),
"expected a background start, got: {result:?}"
);
}
Event::ToolCallComplete { name, result, .. } if name == "exec_shell" => {
saw_complete = true;
let result = result.expect("shell result");
assert!(result.success, "{result:?}");
assert!(
result.content.contains("Background task started"),
"expected a background start, got: {result:?}"
);
}
Event::TurnComplete { status, .. } => {
assert_eq!(status, TurnOutcomeStatus::Completed);
Expand Down
12 changes: 10 additions & 2 deletions crates/tui/src/runtime_api/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,10 @@ async fn spawn_test_server_with_root_token_mobile_workspace_subagents_and_config
let _ = rustls::crypto::ring::default_provider().install_default();
fs::create_dir_all(&sessions_dir)?;
fs::create_dir_all(&workspace)?;
let mut config = Config::default();
config.mcp_config_path = Some(root.join("mcp.json").to_string_lossy().to_string());
let config = Config {
mcp_config_path: Some(root.join("mcp.json").to_string_lossy().to_string()),
..Default::default()
};
let manager = TaskManager::start_with_executor(
TaskManagerConfig {
data_dir: root.join("tasks"),
Expand Down Expand Up @@ -3732,6 +3734,9 @@ fn skill_entry_is_bundled_requires_configured_bundle_path() {
#[test]
fn resolve_skills_dir_rejects_symlink_escaping_workspace() {
let tmp = tempfile::tempdir().expect("tempdir");
let _env_lock = crate::test_support::lock_test_env();
let _home = crate::test_support::EnvVarGuard::set("HOME", tmp.path());
let _userprofile = crate::test_support::EnvVarGuard::set("USERPROFILE", tmp.path());
let workspace_root = tmp.path().join("workspace");
let escape_target = tmp.path().join("escape_target");
fs::create_dir_all(&workspace_root).expect("create workspace");
Expand Down Expand Up @@ -3761,6 +3766,9 @@ fn resolve_skills_dir_rejects_symlink_escaping_workspace() {
#[test]
fn resolve_skills_dir_rejects_codewhale_only_symlink_escaping_workspace() {
let tmp = tempfile::tempdir().expect("tempdir");
let _env_lock = crate::test_support::lock_test_env();
let _home = crate::test_support::EnvVarGuard::set("HOME", tmp.path());
let _userprofile = crate::test_support::EnvVarGuard::set("USERPROFILE", tmp.path());
let workspace_root = tmp.path().join("workspace");
let escape_target = tmp.path().join("escape_target");
fs::create_dir_all(&workspace_root).expect("create workspace");
Expand Down
21 changes: 16 additions & 5 deletions crates/tui/src/tui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3524,13 +3524,24 @@ impl App {

#[must_use]
pub fn tool_run_start_for_history_index(&self, index: usize) -> Option<usize> {
if !self.tool_collapse_active() || index >= self.history.len() {
if !self.tool_collapse_active() {
return None;
}
crate::tui::history::detect_tool_runs(&self.history, self.tool_collapse_threshold)
.into_iter()
.find(|run| index >= run.start && index < run.start.saturating_add(run.count))
.map(|run| run.start)
let active_entries = self
.active_cell
.as_ref()
.map_or(&[][..], crate::tui::active_cell::ActiveCell::entries);
if index >= self.history.len().saturating_add(active_entries.len()) {
return None;
}
crate::tui::history::detect_tool_runs_from_slices(
&self.history,
active_entries,
self.tool_collapse_threshold,
)
.into_iter()
.find(|run| index >= run.start && index < run.start.saturating_add(run.count))
.map(|run| run.start)
}

pub fn toggle_tool_run_expansion_at(&mut self, index: usize) -> bool {
Expand Down
30 changes: 30 additions & 0 deletions crates/tui/src/tui/app/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,36 @@ fn tool_run_expansion_toggle_opens_and_closes_run() {
assert!(!app.toggle_tool_run_expansion_at(99));
}

#[test]
fn tool_run_expansion_toggle_handles_active_run() {
let mut app = App::new(test_options(false), &Config::default());
app.tool_collapse_mode = ToolCollapseMode::Compact;
app.tool_collapse_threshold = 3;
app.add_message(HistoryCell::User {
content: "go".to_string(),
});

let active_start = app.history.len();
let active = app.active_cell.get_or_insert_with(ActiveCell::new);
for name in ["read_file", "list_dir", "web_search"] {
active.push_untracked(HistoryCell::Tool(ToolCell::Generic(GenericToolCell {
name: name.to_string(),
status: ToolStatus::Success,
input_summary: None,
output: Some("ok".to_string()),
prompts: None,
spillover_path: None,
output_summary: None,
is_diff: false,
})));
}

assert!(app.toggle_tool_run_expansion_at(active_start));
assert!(app.expanded_tool_runs.contains(&active_start));
assert!(app.toggle_tool_run_expansion_at(active_start + 2));
assert!(!app.expanded_tool_runs.contains(&active_start));
}

#[test]
fn test_scroll_operations() {
let mut app = App::new(test_options(false), &Config::default());
Expand Down
4 changes: 3 additions & 1 deletion crates/tui/src/tui/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ pub use plan::PlanUpdateCell;
use thinking::extract_reasoning_summary;
#[cfg(test)]
use tool_run::ToolRunActivitySummary;
pub use tool_run::{ToolRun, detect_tool_runs, detect_tool_runs_from_slices, tool_run_summary};
#[cfg(test)]
pub use tool_run::detect_tool_runs;
pub use tool_run::{ToolRun, detect_tool_runs_from_slices, tool_run_summary};

#[cfg(test)]
use thinking::{REASONING_CURSOR, REASONING_OPENER, REASONING_RAIL};
Expand Down
1 change: 1 addition & 0 deletions crates/tui/src/tui/history/tool_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ impl ToolRunActivitySummary {
/// cells can join dense runs; `v` / expansion keeps their raw details
/// available without making routine verifier/shell work dominate the default
/// transcript.
#[cfg(test)]
pub fn detect_tool_runs(history: &[HistoryCell], min_size: usize) -> Vec<ToolRun> {
detect_tool_runs_from_slices(history, &[], min_size)
}
Expand Down
8 changes: 8 additions & 0 deletions crates/tui/src/tui/provider_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1949,6 +1949,14 @@ mod tests {

#[test]
fn self_hosted_provider_row_marks_self_hosted_in_hint() {
let _env_lock = crate::test_support::lock_test_env();
let _sglang_key = crate::test_support::EnvVarGuard::remove("SGLANG_API_KEY");
let _sglang_base_url = crate::test_support::EnvVarGuard::remove("SGLANG_BASE_URL");
let _vllm_key = crate::test_support::EnvVarGuard::remove("VLLM_API_KEY");
let _vllm_base_url = crate::test_support::EnvVarGuard::remove("VLLM_BASE_URL");
let _ollama_key = crate::test_support::EnvVarGuard::remove("OLLAMA_API_KEY");
let _ollama_base_url = crate::test_support::EnvVarGuard::remove("OLLAMA_BASE_URL");

let config = Config::default();
let row =
ProviderDashboardRow::from_config(ApiProvider::Ollama, ApiProvider::Ollama, &config);
Expand Down
4 changes: 2 additions & 2 deletions crates/tui/src/working_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1679,8 +1679,8 @@ mod tests {
let tmp = TempDir::new().expect("tempdir");
let src = tmp.path().join("src");
fs::create_dir_all(&src).expect("mkdir");
fs::write(src.join("a.rs"), &"a".repeat(200)).expect("write");
fs::write(src.join("b.rs"), &"b".repeat(200)).expect("write");
fs::write(src.join("a.rs"), "a".repeat(200)).expect("write");
fs::write(src.join("b.rs"), "b".repeat(200)).expect("write");

let mut ws = cache_maximal_ws();
ws.config.max_resident_file_bytes = 200;
Expand Down
Loading