Skip to content

Commit 1be489b

Browse files
committed
refactor: simplify ReasoningBlock by removing timer persistence
- Remove unnecessary persistence logic for timer state - Remove updateMessageReasoningMeta handler from webviewMessageHandler - Remove ReasoningMeta type and related fields from WebviewMessage - Keep simple ephemeral timer that runs while reasoning is active - Only show timer when elapsed time is greater than 0
1 parent a34f392 commit 1be489b

File tree

3 files changed

+22
-118
lines changed

3 files changed

+22
-118
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2865,35 +2865,6 @@ export const webviewMessageHandler = async (
28652865
}
28662866
break
28672867
}
2868-
case "updateMessageReasoningMeta": {
2869-
// Persist reasoning timer metadata on a specific message (by ts)
2870-
try {
2871-
const currentCline = provider.getCurrentTask()
2872-
if (!currentCline || !message.messageTs) {
2873-
break
2874-
}
2875-
const { messageIndex } = findMessageIndices(message.messageTs, currentCline)
2876-
if (messageIndex === -1) {
2877-
break
2878-
}
2879-
const msg = currentCline.clineMessages[messageIndex] as { metadata?: { reasoning?: { startedAt?: number; elapsedMs?: number } } }
2880-
const existingMeta = msg.metadata || {}
2881-
const existingReasoning = existingMeta.reasoning || {}
2882-
msg.metadata = {
2883-
...existingMeta,
2884-
reasoning: { ...existingReasoning, ...(message.reasoningMeta || {}) },
2885-
}
2886-
2887-
await saveTaskMessages({
2888-
messages: currentCline.clineMessages,
2889-
taskId: currentCline.taskId,
2890-
globalStoragePath: provider.contextProxy.globalStorageUri.fsPath,
2891-
})
2892-
} catch (error) {
2893-
console.error("[updateMessageReasoningMeta] Failed to persist reasoning metadata:", error)
2894-
}
2895-
break
2896-
}
28972868
case "showMdmAuthRequiredNotification": {
28982869
// Show notification that organization requires authentication
28992870
vscode.window.showWarningMessage(t("common:mdm.info.organization_requires_auth"))

src/shared/WebviewMessage.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ export interface UpdateTodoListPayload {
2323
todos: any[]
2424
}
2525

26-
export interface ReasoningMeta {
27-
startedAt?: number
28-
elapsedMs?: number
29-
}
30-
3126
export type EditQueuedMessagePayload = Pick<QueuedMessage, "id" | "text" | "images">
3227

3328
export interface WebviewMessage {
@@ -226,7 +221,6 @@ export interface WebviewMessage {
226221
| "queueMessage"
227222
| "removeQueuedMessage"
228223
| "editQueuedMessage"
229-
| "updateMessageReasoningMeta"
230224
text?: string
231225
editedMessageContent?: string
232226
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"
@@ -262,7 +256,6 @@ export interface WebviewMessage {
262256
terminalOperation?: "continue" | "abort"
263257
messageTs?: number
264258
restoreCheckpoint?: boolean
265-
reasoningMeta?: ReasoningMeta
266259
historyPreviewCollapsed?: boolean
267260
filters?: { type?: string; search?: string; tags?: string[] }
268261
settings?: any

webview-ui/src/components/chat/ReasoningBlock.tsx

Lines changed: 22 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,54 @@
1-
import React, { useEffect, useMemo, useRef, useState } from "react"
1+
import React, { useEffect, useRef, useState } from "react"
22
import { useTranslation } from "react-i18next"
33

44
import MarkdownBlock from "../common/MarkdownBlock"
5-
import { vscode } from "@src/utils/vscode"
6-
7-
interface ReasoningMeta {
8-
startedAt?: number
9-
elapsedMs?: number
10-
}
5+
import { Clock, Lightbulb } from "lucide-react"
116

127
interface ReasoningBlockProps {
138
content: string
149
ts: number
1510
isStreaming: boolean
1611
isLast: boolean
17-
metadata?: { reasoning?: ReasoningMeta } | Record<string, any>
12+
metadata?: any
1813
}
1914

2015
/**
21-
* Render reasoning with a heading and a persistent timer.
16+
* Render reasoning with a heading and a simple timer.
2217
* - Heading uses i18n key chat:reasoning.thinking
23-
* - Timer shown beside the heading and persists via message.metadata.reasoning { startedAt, elapsedMs }
18+
* - Timer runs while reasoning is active (no persistence)
2419
*/
25-
export const ReasoningBlock = ({ content, ts, isStreaming, isLast, metadata }: ReasoningBlockProps) => {
20+
export const ReasoningBlock = ({ content, isStreaming, isLast }: ReasoningBlockProps) => {
2621
const { t } = useTranslation()
2722

28-
const persisted: ReasoningMeta = (metadata?.reasoning as ReasoningMeta) || {}
29-
const startedAtRef = useRef<number>(persisted.startedAt ?? Date.now())
30-
const [elapsed, setElapsed] = useState<number>(persisted.elapsedMs ?? 0)
31-
const postedRef = useRef<boolean>(false)
32-
const intervalRef = useRef<number | null>(null)
23+
const startTimeRef = useRef<number>(Date.now())
24+
const [elapsed, setElapsed] = useState<number>(0)
3325

34-
// Initialize startedAt on first mount if missing (persist to task) - guard with postedRef
26+
// Simple timer that runs while streaming
3527
useEffect(() => {
36-
if (!persisted.startedAt && isLast && !postedRef.current) {
37-
postedRef.current = true
38-
vscode.postMessage({
39-
type: "updateMessageReasoningMeta",
40-
messageTs: ts,
41-
reasoningMeta: { startedAt: startedAtRef.current },
42-
})
43-
}
44-
}, [ts, isLast, persisted.startedAt])
45-
46-
// Tick while active (last row and streaming)
47-
useEffect(() => {
48-
const active = isLast && isStreaming
49-
if (!active) return
50-
51-
const tick = () => setElapsed(Date.now() - startedAtRef.current)
52-
tick()
53-
// ensure no duplicate intervals
54-
if (intervalRef.current) {
55-
clearInterval(intervalRef.current)
56-
intervalRef.current = null
57-
}
58-
intervalRef.current = window.setInterval(tick, 1000)
59-
return () => {
60-
if (intervalRef.current) {
61-
clearInterval(intervalRef.current)
62-
intervalRef.current = null
63-
}
28+
if (isLast && isStreaming) {
29+
const tick = () => setElapsed(Date.now() - startTimeRef.current)
30+
tick()
31+
const id = setInterval(tick, 1000)
32+
return () => clearInterval(id)
6433
}
6534
}, [isLast, isStreaming])
6635

67-
// Cleanup on unmount (safety net)
68-
useEffect(() => {
69-
return () => {
70-
if (intervalRef.current) {
71-
clearInterval(intervalRef.current)
72-
intervalRef.current = null
73-
}
74-
}
75-
}, [])
76-
77-
// Persist final elapsed when streaming stops
78-
const wasActiveRef = useRef<boolean>(false)
79-
useEffect(() => {
80-
const active = isLast && isStreaming
81-
if (wasActiveRef.current && !active) {
82-
const finalMs = Date.now() - startedAtRef.current
83-
setElapsed(finalMs)
84-
vscode.postMessage({
85-
type: "updateMessageReasoningMeta",
86-
messageTs: ts,
87-
reasoningMeta: { startedAt: startedAtRef.current, elapsedMs: finalMs },
88-
})
89-
}
90-
wasActiveRef.current = active
91-
}, [isLast, isStreaming, ts])
92-
93-
const displayMs = useMemo(() => {
94-
if (isLast && isStreaming) return elapsed
95-
return persisted.elapsedMs ?? elapsed
96-
}, [elapsed, isLast, isStreaming, persisted.elapsedMs])
97-
98-
const seconds = Math.max(0, Math.floor((displayMs || 0) / 1000))
36+
const seconds = Math.floor(elapsed / 1000)
9937
const secondsLabel = t("chat:reasoning.seconds", { count: seconds })
10038

10139
return (
10240
<div className="py-1">
10341
<div className="flex items-center justify-between mb-2.5">
10442
<div className="flex items-center gap-2">
105-
<span className="codicon codicon-light-bulb text-vscode-charts-yellow" />
43+
<Lightbulb className="w-4" />
10644
<span className="font-bold text-vscode-foreground">{t("chat:reasoning.thinking")}</span>
10745
</div>
108-
<span className="text-vscode-foreground tabular-nums flex items-center gap-1">
109-
<span className="codicon codicon-clock text-base" />
110-
{secondsLabel}
111-
</span>
46+
{elapsed > 0 && (
47+
<span className="text-vscode-foreground tabular-nums flex items-center gap-1">
48+
<Clock className="w-4" />
49+
{secondsLabel}
50+
</span>
51+
)}
11252
</div>
11353
{(content?.trim()?.length ?? 0) > 0 && (
11454
<div className="px-3 italic text-vscode-descriptionForeground">

0 commit comments

Comments
 (0)