diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-17 01:41:17 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-17 01:41:17 +0300 |
| commit | f7fe0f203e0f349df33819aab239c0aade016f79 (patch) | |
| tree | 51540d4a040a1a2d32ecf73c5c2d9277a7d4efef /src/app | |
| parent | 3ecacfddae86d603bfd0d1a0c01602b1d34b1df3 (diff) | |
fix: polish terminal-core agent semantics
Diffstat (limited to 'src/app')
| -rw-r--r-- | src/app/actions.rs | 14 | ||||
| -rw-r--r-- | src/app/agents.rs | 17 | ||||
| -rw-r--r-- | src/app/creation.rs | 7 | ||||
| -rw-r--r-- | src/app/input/mod.rs | 2 | ||||
| -rw-r--r-- | src/app/input/navigate.rs | 4 | ||||
| -rw-r--r-- | src/app/mod.rs | 17 | ||||
| -rw-r--r-- | src/app/runtime.rs | 5 | ||||
| -rw-r--r-- | src/app/terminal_targets.rs | 6 |
8 files changed, 52 insertions, 20 deletions
diff --git a/src/app/actions.rs b/src/app/actions.rs index 27ca7474..faa5717d 100644 --- a/src/app/actions.rs +++ b/src/app/actions.rs @@ -693,18 +693,23 @@ impl AppState { pub fn apply_workspace_git_statuses(&mut self, results: Vec<WorkspaceGitStatus>) -> bool { let mut changed = false; for result in results { - let Some(ws) = self + let Some(ws_idx) = self .workspaces - .iter_mut() - .find(|ws| ws.id == result.workspace_id) + .iter() + .position(|ws| ws.id == result.workspace_id) else { continue; }; - if ws.resolved_identity_cwd().as_ref() != Some(&result.resolved_identity_cwd) { + if self.workspaces[ws_idx] + .resolved_identity_cwd_from(&self.terminals, &self.terminal_runtimes) + .as_ref() + != Some(&result.resolved_identity_cwd) + { continue; } + let ws = &mut self.workspaces[ws_idx]; if ws.cached_git_branch != result.branch { ws.cached_git_branch = result.branch; changed = true; @@ -1050,6 +1055,7 @@ mod tests { } fn mark_agent(state: &mut AppState, ws_idx: usize, tab_idx: usize, pane_id: PaneId) { + state.ensure_test_terminals(); let terminal_id = state.workspaces[ws_idx].tabs[tab_idx] .panes .get(&pane_id) diff --git a/src/app/agents.rs b/src/app/agents.rs index f9e410f5..15b93674 100644 --- a/src/app/agents.rs +++ b/src/app/agents.rs @@ -17,7 +17,6 @@ impl App { .filter_map(move |pane_id| self.agent_info(ws_idx, pane_id)) }) }) - .filter(|agent| agent.name.is_some() || agent.agent.is_some()) .collect() } @@ -88,8 +87,11 @@ impl App { })); }; match normalized_name { - Some(name) => terminal.set_manual_label(name), - None => terminal.clear_manual_label(), + Some(name) => { + terminal.set_agent_name(name.clone()); + terminal.set_manual_label(name); + } + None => terminal.clear_agent_name(), } self.state.mark_session_dirty(); self.agent_info(resolved.ws_idx, resolved.pane_id) @@ -195,6 +197,7 @@ impl App { let Some(terminal) = self.state.terminals.get_mut(&terminal_id) else { return Err(AgentStartError::SpawnFailed("terminal disappeared".into())); }; + terminal.set_agent_name(name.clone()); terminal.set_manual_label(name); self.state.mark_session_dirty(); @@ -403,10 +406,16 @@ impl App { ws_idx: usize, pane_id: crate::layout::PaneId, ) -> Option<crate::api::schema::AgentInfo> { + let ws = self.state.workspaces.get(ws_idx)?; + let pane_state = ws.pane_state(pane_id)?; + let terminal = self.state.terminals.get(&pane_state.attached_terminal_id)?; + if !terminal.is_agent_terminal() { + return None; + } let pane = self.pane_info(ws_idx, pane_id)?; Some(crate::api::schema::AgentInfo { terminal_id: pane.terminal_id, - name: pane.label, + name: terminal.agent_name.clone(), agent: pane.agent, agent_status: pane.agent_status, workspace_id: pane.workspace_id, diff --git a/src/app/creation.rs b/src/app/creation.rs index 1832e637..f1638e15 100644 --- a/src/app/creation.rs +++ b/src/app/creation.rs @@ -8,7 +8,10 @@ use crate::workspace::Workspace; impl App { pub(super) fn seed_cwd_from_workspace(&self, ws_idx: usize) -> Option<std::path::PathBuf> { - self.state.workspaces.get(ws_idx)?.resolved_identity_cwd() + self.state + .workspaces + .get(ws_idx)? + .resolved_identity_cwd_from(&self.state.terminals, &self.state.terminal_runtimes) } pub(super) fn workspace_creation_source(&self) -> Option<usize> { @@ -294,7 +297,7 @@ impl App { crate::api::schema::WorkspaceInfo { workspace_id: self.public_workspace_id(index), number: index + 1, - label: ws.display_name(), + label: ws.display_name_from(&self.state.terminals, &self.state.terminal_runtimes), focused: self.state.active == Some(index), pane_count: ws.public_pane_numbers.len(), tab_count: ws.tabs.len(), diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs index fea88b55..7823de31 100644 --- a/src/app/input/mod.rs +++ b/src/app/input/mod.rs @@ -216,6 +216,8 @@ impl AppState { self.host_terminal_theme, ) { let new_id = new_pane.pane_id; + self.terminal_runtimes + .insert(new_pane.terminal.id.clone(), new_pane.runtime); self.terminals .insert(new_pane.terminal.id.clone(), new_pane.terminal); ws.layout.focus_pane(new_id); diff --git a/src/app/input/navigate.rs b/src/app/input/navigate.rs index 6445b6ab..798aafa8 100644 --- a/src/app/input/navigate.rs +++ b/src/app/input/navigate.rs @@ -331,6 +331,9 @@ impl App { )?; let new_pane_id = new_pane.pane_id; self.state + .terminal_runtimes + .insert(new_pane.terminal.id.clone(), new_pane.runtime); + self.state .terminals .insert(new_pane.terminal.id.clone(), new_pane.terminal); ws.active_tab_mut() @@ -1122,6 +1125,7 @@ mod tests { .await; assert_eq!(app.state.workspaces[0].tabs[0].layout.pane_count(), 2); + assert_eq!(app.state.terminal_runtimes.len(), 2); assert!(app.state.workspaces[0].tabs[0].zoomed); let _ = wait_for_file(&output_path); diff --git a/src/app/mod.rs b/src/app/mod.rs index c5654db2..1c818a9c 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -412,8 +412,11 @@ impl App { state.terminals = restored_terminals; state.terminal_runtimes = restored_terminal_runtimes; - for ws in &mut state.workspaces { - ws.refresh_git_branch(); + for ws_idx in 0..state.workspaces.len() { + let cwd = state.workspaces[ws_idx] + .resolved_identity_cwd_from(&state.terminals, &state.terminal_runtimes); + state.workspaces[ws_idx].cached_git_branch = + cwd.as_deref().and_then(crate::workspace::git_branch); } // Background auto-update is disabled in monolithic no-session mode @@ -1702,7 +1705,7 @@ mod tests { } #[test] - fn terminal_target_resolves_unique_manual_name() { + fn terminal_target_resolves_unique_agent_name() { let mut app = test_app(); let workspace = Workspace::test_new("terminal-target-name"); let pane = workspace.tabs[0].root_pane; @@ -1718,7 +1721,7 @@ mod tests { .terminals .get_mut(&attached_terminal_id) .unwrap() - .manual_label = Some("reviewer".into()); + .set_agent_name("reviewer".into()); app.state.active = Some(0); app.state.selected = 0; @@ -1746,7 +1749,7 @@ mod tests { } #[test] - fn terminal_target_reports_ambiguous_duplicate_manual_name() { + fn terminal_target_reports_ambiguous_duplicate_agent_name() { let mut app = test_app(); let mut workspace = Workspace::test_new("terminal-target-ambiguous"); let first = workspace.tabs[0].root_pane; @@ -1762,7 +1765,7 @@ mod tests { .terminals .get_mut(&first_terminal_id) .unwrap() - .manual_label = Some("worker".into()); + .set_agent_name("worker".into()); let second_terminal_id = app.state.workspaces[0] .pane_state(second) .unwrap() @@ -1772,7 +1775,7 @@ mod tests { .terminals .get_mut(&second_terminal_id) .unwrap() - .manual_label = Some("worker".into()); + .set_agent_name("worker".into()); app.state.active = Some(0); app.state.selected = 0; diff --git a/src/app/runtime.rs b/src/app/runtime.rs index 98ae4e0e..55c89e73 100644 --- a/src/app/runtime.rs +++ b/src/app/runtime.rs @@ -247,7 +247,10 @@ impl App { .state .workspaces .iter() - .filter_map(|ws| ws.resolved_identity_cwd().map(|cwd| (ws.id.clone(), cwd))) + .filter_map(|ws| { + ws.resolved_identity_cwd_from(&self.state.terminals, &self.state.terminal_runtimes) + .map(|cwd| (ws.id.clone(), cwd)) + }) .collect(); if workspaces.is_empty() { diff --git a/src/app/terminal_targets.rs b/src/app/terminal_targets.rs index 94cf89d0..71ca83bb 100644 --- a/src/app/terminal_targets.rs +++ b/src/app/terminal_targets.rs @@ -65,8 +65,10 @@ impl App { .terminals .values() .find(|terminal| terminal.id.to_string() == candidate.terminal_id) - .and_then(|terminal| terminal.manual_label.as_deref()) - .is_some_and(|label| label == target) + .is_some_and(|terminal| { + terminal.agent_name.as_deref() == Some(target) + || terminal.effective_agent_label() == Some(target) + }) }) .collect(); if let Some(resolved) = self.single_terminal_match(target, name_matches)? { |
