Skip to content

Commit cf9ad89

Browse files
committed
Show progress timing for thinking/agents
1 parent 234a1a6 commit cf9ad89

3 files changed

Lines changed: 66 additions & 5 deletions

File tree

packages/frontend/src/pages/SessionPage.tsx

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export function SessionPage() {
5151
const cliToolAbortRef = useRef<AbortController | null>(null);
5252
const [mobileView, setMobileView] = useState<MobileView>('chat');
5353
const [showAllowedDirsDialog, setShowAllowedDirsDialog] = useState(false);
54+
const [now, setNow] = useState(Date.now());
5455

5556
const { usage, addMessage } = useSessionStore();
5657
const { uiProvider } = useProviderStore();
@@ -125,6 +126,13 @@ export function SessionPage() {
125126
const currentSelectedFile = selectedFile[id || ''];
126127
const currentOpenFiles = openFiles[id || ''] || [];
127128
const hasOpenFiles = currentOpenFiles.length > 0;
129+
const isActive = currentActivity.type === 'thinking' || !!currentActiveAgent;
130+
131+
useEffect(() => {
132+
if (!isActive) return;
133+
const intervalId = window.setInterval(() => setNow(Date.now()), 1000);
134+
return () => window.clearInterval(intervalId);
135+
}, [isActive]);
128136

129137
// Combine messages and generated images into a single timeline
130138
// Tool executions are NOT added to timeline - they're shown inline with activity indicator
@@ -198,6 +206,47 @@ export function SessionPage() {
198206
return agentMap[agentType] || agentType;
199207
}, []);
200208

209+
const getAgentDescription = useCallback((agentType: string) => {
210+
const descriptions: Record<string, string> = {
211+
'Explore': 'Exploring project',
212+
'Plan': 'Drafting a plan',
213+
'general-purpose': 'Handling general tasks',
214+
'claude-code-guide': 'Checking docs',
215+
'research-bot': 'Researching',
216+
'frontend-developer': 'Working on UI',
217+
'mobile-developer': 'Working on mobile',
218+
'backend-dev': 'Working on backend',
219+
'fullstack-dev': 'Working across stack',
220+
'api-designer': 'Designing API',
221+
'ui-designer': 'Designing UI',
222+
'devops': 'Handling infra',
223+
'devops-engineer': 'Handling infra',
224+
'database': 'Working on database',
225+
'database-specialist': 'Working on database',
226+
'git-ops': 'Managing git tasks',
227+
'git-operations': 'Managing git tasks',
228+
'debugger': 'Debugging',
229+
'debugging-expert': 'Debugging',
230+
'architect': 'Designing architecture',
231+
'system-architect': 'Designing architecture',
232+
};
233+
return descriptions[agentType] || `Running ${agentType} agent`;
234+
}, []);
235+
236+
const formatElapsed = useCallback((ms: number) => {
237+
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
238+
const hours = Math.floor(totalSeconds / 3600);
239+
const minutes = Math.floor((totalSeconds % 3600) / 60);
240+
const seconds = totalSeconds % 60;
241+
if (hours > 0) {
242+
return `${hours}h ${minutes}m`;
243+
}
244+
if (minutes > 0) {
245+
return `${minutes}m ${seconds}s`;
246+
}
247+
return `${seconds}s`;
248+
}, []);
249+
201250
// Fetch session details
202251
const { data: session, isLoading: sessionLoading } = useQuery({
203252
queryKey: ['session', id],
@@ -830,9 +879,10 @@ export function SessionPage() {
830879
<span className="text-sm font-medium text-purple-600 dark:text-purple-400">
831880
Agent: {getAgentDisplay(currentActiveAgent.agentType)}
832881
</span>
833-
{currentActiveAgent.description && (
834-
<span className="text-xs text-muted-foreground">{currentActiveAgent.description}</span>
835-
)}
882+
<span className="text-xs text-muted-foreground">
883+
{currentActiveAgent.description || getAgentDescription(currentActiveAgent.agentType)}
884+
{currentActiveAgent.startedAt ? ` (${formatElapsed(now - currentActiveAgent.startedAt)})` : ''}
885+
</span>
836886
</div>
837887
</>
838888
) : currentActivity.type === 'thinking' ? (
@@ -841,7 +891,9 @@ export function SessionPage() {
841891
<div className="flex flex-col">
842892
<span className="text-sm font-medium">{providerLabel} is thinking...</span>
843893
<span className="text-xs text-muted-foreground">
844-
{currentActivity.message || 'Analyzing request'}
894+
{currentActivity.message
895+
? `• ${currentActivity.message}${currentActivity.messageStartedAt ? ` (${formatElapsed(now - currentActivity.messageStartedAt)})` : ''}`
896+
: 'Analyzing request'}
845897
</span>
846898
</div>
847899
</>

packages/frontend/src/services/socket.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,13 @@ class SocketService {
8080
if (data.isThinking) {
8181
this.activeSessions.add(data.sessionId);
8282
const existing = activity[data.sessionId];
83+
const now = Date.now();
8384
const message = data.message ?? (existing?.type === 'thinking' ? existing.message : undefined);
84-
setActivity(data.sessionId, { type: 'thinking', message });
85+
const startedAt = existing?.type === 'thinking' ? (existing.startedAt ?? now) : now;
86+
const messageStartedAt = message && message !== existing?.message
87+
? now
88+
: (existing?.messageStartedAt ?? (message ? now : undefined));
89+
setActivity(data.sessionId, { type: 'thinking', message, startedAt, messageStartedAt });
8590
} else {
8691
// Claude stopped thinking - check if task is complete
8792
const wasActive = this.activeSessions.has(data.sessionId);
@@ -144,6 +149,7 @@ class SocketService {
144149
agentType: data.agentType,
145150
description: data.description,
146151
status: data.status,
152+
startedAt: Date.now(),
147153
});
148154
} else {
149155
// Clear agent when completed or error

packages/frontend/src/stores/sessionStore.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ export interface ActivityState {
77
toolName?: string;
88
toolStatus?: 'started' | 'completed' | 'error';
99
message?: string;
10+
startedAt?: number;
11+
messageStartedAt?: number;
1012
}
1113

1214
// Active agent state
1315
export interface AgentState {
1416
agentType: string;
1517
description?: string;
1618
status: 'started' | 'completed' | 'error';
19+
startedAt?: number;
1720
}
1821

1922
// Todo item from Claude's TodoWrite tool

0 commit comments

Comments
 (0)