diff --git a/apps/backend/internal/worktree/manager.go b/apps/backend/internal/worktree/manager.go index 81965ec90e..6f209b58ae 100644 --- a/apps/backend/internal/worktree/manager.go +++ b/apps/backend/internal/worktree/manager.go @@ -730,10 +730,12 @@ func (m *Manager) pullBaseBranch(repoPath, baseBranch string) string { pullCmd := exec.CommandContext(fetchCtx, "git", "pull", "--ff-only", "origin", baseBranch) pullCmd.Dir = repoPath if output, err := pullCmd.CombinedOutput(); err != nil { - m.logger.Error("git pull failed before worktree creation", + m.logger.Warn("git pull failed before worktree creation, falling back to remote ref", zap.String("branch", baseBranch), + zap.String("remote_ref", remoteRef), zap.String("output", string(output)), zap.Error(err)) + return remoteRef } return baseBranch } diff --git a/apps/web/components/task/chat/messages/agent-status.tsx b/apps/web/components/task/chat/messages/agent-status.tsx index 36f47d421a..646d3da23c 100644 --- a/apps/web/components/task/chat/messages/agent-status.tsx +++ b/apps/web/components/task/chat/messages/agent-status.tsx @@ -72,7 +72,10 @@ function calculateTurnDurationFromMessages(messages: Message[]): string | null { * Uses the turn's started_at timestamp to calculate elapsed time, so it persists across page refreshes. */ function useRunningTimer(isRunning: boolean, turnStartedAt: string | null) { - const [elapsedSeconds, setElapsedSeconds] = useState(0); + const [elapsedSeconds, setElapsedSeconds] = useState(() => { + if (!isRunning || !turnStartedAt) return 0; + return Math.floor((Date.now() - new Date(turnStartedAt).getTime()) / 1000); + }); useEffect(() => { if (!isRunning || !turnStartedAt) { @@ -98,8 +101,8 @@ function useRunningTimer(isRunning: boolean, turnStartedAt: string | null) { }; }, [isRunning, turnStartedAt]); - // Reset to 0 when not running - const displaySeconds = isRunning && turnStartedAt ? elapsedSeconds : 0; + // Keep showing elapsed time while isRunning, even if turnStartedAt was cleared + const displaySeconds = isRunning ? elapsedSeconds : 0; // Format as Xs or XmXs const formatted = useMemo(() => { diff --git a/apps/web/hooks/use-active-turn-timer.ts b/apps/web/hooks/use-active-turn-timer.ts deleted file mode 100644 index dd891a9347..0000000000 --- a/apps/web/hooks/use-active-turn-timer.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { useEffect, useMemo, useState } from 'react'; -import { useAppStore } from '@/components/state-provider'; -import type { Turn } from '@/lib/types/http'; - -/** - * Hook to get a live timer for the active turn of a session. - * Updates every second while there's an active turn. - * - * @param sessionId - The session ID to track - * @returns The formatted duration string (MM:SS or HH:MM:SS) - */ -export function useActiveTurnTimer(sessionId: string | null) { - const turns = useAppStore((state) => sessionId ? state.turns.bySession[sessionId] : undefined); - const activeTurnId = useAppStore((state) => sessionId ? state.turns.activeBySession[sessionId] : null); - - // Find the active turn - const activeTurn = useMemo(() => { - if (!turns || !activeTurnId) return null; - return turns.find((t: Turn) => t.id === activeTurnId) ?? null; - }, [turns, activeTurnId]); - - const [elapsedSeconds, setElapsedSeconds] = useState(() => { - if (!activeTurn?.started_at) return 0; - return Math.floor((Date.now() - new Date(activeTurn.started_at).getTime()) / 1000); - }); - - useEffect(() => { - if (!activeTurn?.started_at) { - return; - } - - const startTime = new Date(activeTurn.started_at).getTime(); - - const calculateElapsed = () => { - return Math.floor((Date.now() - startTime) / 1000); - }; - - const interval = setInterval(() => { - setElapsedSeconds(calculateElapsed()); - }, 1000); - - return () => clearInterval(interval); - }, [activeTurn?.started_at]); - - // Format as MM:SS or HH:MM:SS - const formattedDuration = useMemo(() => { - if (elapsedSeconds <= 0) return '0:00'; - - const hours = Math.floor(elapsedSeconds / 3600); - const minutes = Math.floor((elapsedSeconds % 3600) / 60); - const seconds = elapsedSeconds % 60; - - if (hours > 0) { - return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; - } - return `${minutes}:${seconds.toString().padStart(2, '0')}`; - }, [elapsedSeconds]); - - return { - isActive: !!activeTurn, - elapsedSeconds, - formattedDuration, - }; -} -