Skip to content

Commit 1868c8c

Browse files
echobtfactorydroid
andauthored
fix(tui): improve subagent display and timer tracking (#282)
Changes: - Force main agent and subagents to use TodoWrite tool for progress visibility - Show 'Delegation' status indicator when subagent is running - Use total time from last user prompt instead of per-task timer - Keep Task display visible after completion (cleared on next turn) - Add prompt_started_at tracking for consistent elapsed time display - Enable TodoWrite/TodoRead tools for subagents (only Task disabled) Fixes issues with: - Subagent todo list not visible in real-time - Loading indicator not shown during agent delegation - Timer resetting per task instead of showing total duration - Task label disappearing immediately after completion Co-authored-by: Droid Agent <droid@factory.ai>
1 parent c2128a3 commit 1868c8c

File tree

4 files changed

+198
-77
lines changed

4 files changed

+198
-77
lines changed

cortex-tui/src/agent/system_prompt.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ pub const SYSTEM_PROMPT_TEMPLATE: &str = r#"You are Cortex, an expert AI coding
3333
- For shell commands, explain what they do before executing
3434
- Call multiple tools in parallel when operations are independent
3535
36+
# Todo List (IMPORTANT)
37+
For any non-trivial task that requires multiple steps:
38+
- Use the TodoWrite tool immediately to create a todo list tracking your progress
39+
- Update the todo list as you complete each step (mark items as in_progress or completed)
40+
- This provides real-time visibility to the user on what you're working on
41+
- Keep only ONE item as in_progress at a time
42+
3643
# Guidelines
3744
- Always verify paths exist before operations
3845
- Handle errors gracefully and suggest alternatives

cortex-tui/src/app.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ pub struct StreamingState {
4949
pub executing_tool: Option<String>,
5050
/// When the tool started executing (for elapsed time display)
5151
pub tool_started_at: Option<Instant>,
52+
/// When the last user prompt was sent (for total elapsed time from user's perspective)
53+
/// This persists across streaming restarts (e.g., after tool execution)
54+
pub prompt_started_at: Option<Instant>,
55+
/// Whether a subagent (Task) is currently running
56+
pub is_delegating: bool,
5257
}
5358

5459
impl Default for StreamingState {
@@ -61,6 +66,8 @@ impl Default for StreamingState {
6166
task_started_at: None,
6267
executing_tool: None,
6368
tool_started_at: None,
69+
prompt_started_at: None,
70+
is_delegating: false,
6471
}
6572
}
6673
}
@@ -71,6 +78,10 @@ impl StreamingState {
7178
self.thinking = true;
7279
self.current_tool = tool;
7380
self.task_started_at = Some(Instant::now());
81+
// Only set prompt_started_at if not already set (first call in a turn)
82+
if self.prompt_started_at.is_none() {
83+
self.prompt_started_at = Some(Instant::now());
84+
}
7485
}
7586

7687
/// Get the elapsed seconds since the task started
@@ -80,13 +91,40 @@ impl StreamingState {
8091
.unwrap_or(0)
8192
}
8293

94+
/// Get the elapsed seconds since the original prompt was sent
95+
/// This is the total time from the user's perspective
96+
pub fn prompt_elapsed_seconds(&self) -> u64 {
97+
self.prompt_started_at
98+
.map(|t| t.elapsed().as_secs())
99+
.unwrap_or(0)
100+
}
101+
83102
/// Reset streaming state when task completes
84103
pub fn stop(&mut self) {
85104
self.is_streaming = false;
86105
self.thinking = false;
87106
self.current_tool = None;
88107
self.tool_status = None;
89108
self.task_started_at = None;
109+
// Note: prompt_started_at is NOT reset here - it persists until full_reset()
110+
}
111+
112+
/// Full reset when the entire conversation turn is complete
113+
/// (no more tool executions or continuations expected)
114+
pub fn full_reset(&mut self) {
115+
self.stop();
116+
self.prompt_started_at = None;
117+
self.is_delegating = false;
118+
}
119+
120+
/// Start delegation mode (subagent is running)
121+
pub fn start_delegation(&mut self) {
122+
self.is_delegating = true;
123+
}
124+
125+
/// Stop delegation mode
126+
pub fn stop_delegation(&mut self) {
127+
self.is_delegating = false;
90128
}
91129

92130
/// Start tool execution in background
@@ -1347,6 +1385,8 @@ impl AppState {
13471385
pub fn clear_tool_calls(&mut self) {
13481386
self.tool_calls.clear();
13491387
self.clear_content_segments();
1388+
// Also clear completed/failed subagents from the previous turn
1389+
self.active_subagents.retain(|t| !t.status.is_terminal());
13501390
}
13511391

13521392
/// Advance spinner frames for all running tool calls

0 commit comments

Comments
 (0)