Skip to content

Commit a84d41b

Browse files
committed
refactor(chat): reasoning UI tidy — utility classes, mb-2.5, safer effect guard; add ReasoningMeta typing; reduce any casts
1 parent ea322fd commit a84d41b

File tree

3 files changed

+26
-18
lines changed

3 files changed

+26
-18
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,8 +2876,8 @@ export const webviewMessageHandler = async (
28762876
if (messageIndex === -1) {
28772877
break
28782878
}
2879-
const msg = currentCline.clineMessages[messageIndex] as any
2880-
const existingMeta = (msg.metadata as any) || {}
2879+
const msg = currentCline.clineMessages[messageIndex] as { metadata?: { reasoning?: { startedAt?: number; elapsedMs?: number } } }
2880+
const existingMeta = msg.metadata || {}
28812881
const existingReasoning = existingMeta.reasoning || {}
28822882
msg.metadata = {
28832883
...existingMeta,

src/shared/WebviewMessage.ts

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

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

2833
export interface WebviewMessage {
@@ -257,10 +262,7 @@ export interface WebviewMessage {
257262
terminalOperation?: "continue" | "abort"
258263
messageTs?: number
259264
restoreCheckpoint?: boolean
260-
reasoningMeta?: {
261-
startedAt?: number
262-
elapsedMs?: number
263-
}
265+
reasoningMeta?: ReasoningMeta
264266
historyPreviewCollapsed?: boolean
265267
filters?: { type?: string; search?: string; tags?: string[] }
266268
settings?: any

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,43 @@ import { useTranslation } from "react-i18next"
44
import MarkdownBlock from "../common/MarkdownBlock"
55
import { vscode } from "@src/utils/vscode"
66

7+
interface ReasoningMeta {
8+
startedAt?: number
9+
elapsedMs?: number
10+
}
11+
712
interface ReasoningBlockProps {
813
content: string
914
ts: number
1015
isStreaming: boolean
1116
isLast: boolean
12-
metadata?: Record<string, any>
17+
metadata?: { reasoning?: ReasoningMeta } | Record<string, any>
1318
}
1419

1520
/**
1621
* Render reasoning with a heading and a persistent timer.
1722
* - Heading uses i18n key chat:reasoning.thinking
18-
* - Timer shown as "(⟲ 24s)" beside the heading and persists via message.metadata.reasoning { startedAt, elapsedMs }
23+
* - Timer shown beside the heading and persists via message.metadata.reasoning { startedAt, elapsedMs }
1924
*/
2025
export const ReasoningBlock = ({ content, ts, isStreaming, isLast, metadata }: ReasoningBlockProps) => {
2126
const { t } = useTranslation()
2227

23-
const persisted = (metadata?.reasoning as { startedAt?: number; elapsedMs?: number } | undefined) || {}
28+
const persisted: ReasoningMeta = (metadata?.reasoning as ReasoningMeta) || {}
2429
const startedAtRef = useRef<number>(persisted.startedAt ?? Date.now())
2530
const [elapsed, setElapsed] = useState<number>(persisted.elapsedMs ?? 0)
31+
const postedRef = useRef<boolean>(false)
2632

27-
// Initialize startedAt on first mount if missing (persist to task)
33+
// Initialize startedAt on first mount if missing (persist to task) - guard with postedRef
2834
useEffect(() => {
29-
if (!persisted.startedAt && isLast) {
35+
if (!persisted.startedAt && isLast && !postedRef.current) {
36+
postedRef.current = true
3037
vscode.postMessage({
3138
type: "updateMessageReasoningMeta",
3239
messageTs: ts,
3340
reasoningMeta: { startedAt: startedAtRef.current },
34-
} as any)
41+
})
3542
}
36-
// eslint-disable-next-line react-hooks/exhaustive-deps
37-
}, [ts])
43+
}, [ts, isLast, persisted.startedAt])
3844

3945
// Tick while active (last row and streaming)
4046
useEffect(() => {
@@ -58,7 +64,7 @@ export const ReasoningBlock = ({ content, ts, isStreaming, isLast, metadata }: R
5864
type: "updateMessageReasoningMeta",
5965
messageTs: ts,
6066
reasoningMeta: { startedAt: startedAtRef.current, elapsedMs: finalMs },
61-
} as any)
67+
})
6268
}
6369
wasActiveRef.current = active
6470
}, [isLast, isStreaming, ts])
@@ -73,13 +79,13 @@ export const ReasoningBlock = ({ content, ts, isStreaming, isLast, metadata }: R
7379

7480
return (
7581
<div className="py-1">
76-
<div className="flex items-center justify-between mb-[10px]">
82+
<div className="flex items-center justify-between mb-2.5">
7783
<div className="flex items-center gap-2">
78-
<span className="codicon codicon-light-bulb" style={{ color: "var(--vscode-charts-yellow)" }} />
84+
<span className="codicon codicon-light-bulb text-vscode-charts-yellow" />
7985
<span className="font-bold text-vscode-foreground">{t("chat:reasoning.thinking")}</span>
8086
</div>
8187
<span className="text-vscode-foreground tabular-nums flex items-center gap-1">
82-
<span className="codicon codicon-clock" style={{ fontSize: "inherit" }} />
88+
<span className="codicon codicon-clock text-base" />
8389
{secondsLabel}
8490
</span>
8591
</div>

0 commit comments

Comments
 (0)