Skip to content

Commit 5bbb1dc

Browse files
authored
fix: Fixed generating indictator not keeping time correctly (#588)
1 parent 50e3256 commit 5bbb1dc

6 files changed

Lines changed: 32 additions & 7 deletions

File tree

apps/twig/src/renderer/features/sessions/components/ConversationView.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type ConversationItem = Turn | UserShellExecute;
5252
interface ConversationViewProps {
5353
events: AcpMessage[];
5454
isPromptPending: boolean;
55+
promptStartedAt?: number | null;
5556
repoPath?: string | null;
5657
isCloud?: boolean;
5758
taskId?: string;
@@ -63,6 +64,7 @@ const SHOW_BUTTON_THRESHOLD = 300;
6364
export function ConversationView({
6465
events,
6566
isPromptPending,
67+
promptStartedAt,
6668
repoPath,
6769
isCloud = false,
6870
taskId,
@@ -141,6 +143,7 @@ export function ConversationView({
141143
</div>
142144
<SessionFooter
143145
isPromptPending={isPromptPending}
146+
promptStartedAt={promptStartedAt}
144147
lastGenerationDuration={
145148
lastTurn?.isComplete ? lastTurn.durationMs : null
146149
}

apps/twig/src/renderer/features/sessions/components/GeneratingIndicator.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,22 @@ export function formatDuration(ms: number): string {
1616
return `${secs}.${centiseconds.toString().padStart(2, "0")}s`;
1717
}
1818

19-
export function GeneratingIndicator() {
19+
interface GeneratingIndicatorProps {
20+
startedAt?: number | null;
21+
}
22+
23+
export function GeneratingIndicator({ startedAt }: GeneratingIndicatorProps) {
2024
const [elapsed, setElapsed] = useState(0);
2125
const [activityIndex, setActivityIndex] = useState(0);
2226

2327
useEffect(() => {
24-
const startTime = Date.now();
28+
const startTime = startedAt ?? Date.now();
2529
const interval = setInterval(() => {
2630
setElapsed(Date.now() - startTime);
2731
}, 50);
2832

2933
return () => clearInterval(interval);
30-
}, []);
34+
}, [startedAt]);
3135

3236
useEffect(() => {
3337
const interval = setInterval(() => {

apps/twig/src/renderer/features/sessions/components/SessionFooter.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ import { formatDuration, GeneratingIndicator } from "./GeneratingIndicator";
44

55
interface SessionFooterProps {
66
isPromptPending: boolean;
7+
promptStartedAt?: number | null;
78
lastGenerationDuration: number | null;
89
lastStopReason?: string;
910
}
1011

1112
export function SessionFooter({
1213
isPromptPending,
14+
promptStartedAt,
1315
lastGenerationDuration,
1416
lastStopReason,
1517
}: SessionFooterProps) {
1618
if (isPromptPending) {
1719
return (
1820
<Box className="pt-3 pb-1">
19-
<GeneratingIndicator />
21+
<GeneratingIndicator startedAt={promptStartedAt} />
2022
</Box>
2123
);
2224
}

apps/twig/src/renderer/features/sessions/components/SessionView.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ interface SessionViewProps {
4242
taskId?: string;
4343
isRunning: boolean;
4444
isPromptPending?: boolean;
45+
promptStartedAt?: number | null;
4546
onSendPrompt: (text: string) => void;
4647
onBashCommand?: (command: string) => void;
4748
onCancelPrompt: () => void;
@@ -61,6 +62,7 @@ export function SessionView({
6162
taskId,
6263
isRunning,
6364
isPromptPending = false,
65+
promptStartedAt,
6466
onSendPrompt,
6567
onBashCommand,
6668
onCancelPrompt,
@@ -301,6 +303,7 @@ export function SessionView({
301303
<ConversationView
302304
events={events}
303305
isPromptPending={isPromptPending}
306+
promptStartedAt={promptStartedAt}
304307
repoPath={repoPath}
305308
isCloud={isCloud}
306309
taskId={taskId}

apps/twig/src/renderer/features/sessions/stores/sessionStore.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export interface AgentSession {
4949
status: "connecting" | "connected" | "disconnected" | "error";
5050
errorMessage?: string;
5151
isPromptPending: boolean;
52+
promptStartedAt: number | null;
5253
isCloud: boolean;
5354
logUrl?: string;
5455
processedLineCount?: number;
@@ -133,9 +134,11 @@ function subscribeToChannel(taskRunId: string) {
133134
session.events.push(payload as AcpMessage);
134135

135136
// Track isPromptPending from ACP events (handles backend-initiated prompts)
136-
const msg = (payload as AcpMessage).message;
137+
const acpMsg = payload as AcpMessage;
138+
const msg = acpMsg.message;
137139
if (isJsonRpcRequest(msg) && msg.method === "session/prompt") {
138140
session.isPromptPending = true;
141+
session.promptStartedAt = acpMsg.ts;
139142
}
140143
if (
141144
"id" in msg &&
@@ -146,6 +149,7 @@ function subscribeToChannel(taskRunId: string) {
146149
) {
147150
// This is a prompt response
148151
session.isPromptPending = false;
152+
session.promptStartedAt = null;
149153
}
150154

151155
// Handle session/update notifications
@@ -462,6 +466,7 @@ function createBaseSession(
462466
startedAt: Date.now(),
463467
status: "connecting",
464468
isPromptPending: false,
469+
promptStartedAt: null,
465470
isCloud,
466471
currentMode: executionMode ?? "default",
467472
pendingPermissions: new Map(),
@@ -772,15 +777,21 @@ const useStore = create<SessionStore>()(
772777
session: AgentSession,
773778
blocks: ContentBlock[],
774779
): Promise<{ stopReason: string }> => {
775-
updateSession(session.taskRunId, { isPromptPending: true });
780+
updateSession(session.taskRunId, {
781+
isPromptPending: true,
782+
promptStartedAt: Date.now(),
783+
});
776784

777785
try {
778786
return await trpcVanilla.agent.prompt.mutate({
779787
sessionId: session.taskRunId,
780788
prompt: blocks,
781789
});
782790
} finally {
783-
updateSession(session.taskRunId, { isPromptPending: false });
791+
updateSession(session.taskRunId, {
792+
isPromptPending: false,
793+
promptStartedAt: null,
794+
});
784795
}
785796
};
786797

apps/twig/src/renderer/features/task-detail/components/TaskLogsPanel.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export function TaskLogsPanel({ taskId, task }: TaskLogsPanelProps) {
4747

4848
const events = session?.events ?? [];
4949
const isPromptPending = session?.isPromptPending ?? false;
50+
const promptStartedAt = session?.promptStartedAt;
5051

5152
const isConnecting = useRef(false);
5253

@@ -177,6 +178,7 @@ export function TaskLogsPanel({ taskId, task }: TaskLogsPanelProps) {
177178
taskId={taskId}
178179
isRunning={isRunning}
179180
isPromptPending={isPromptPending}
181+
promptStartedAt={promptStartedAt}
180182
onSendPrompt={handleSendPrompt}
181183
onBashCommand={handleBashCommand}
182184
onCancelPrompt={handleCancelPrompt}

0 commit comments

Comments
 (0)