memory cleanup (#4190)

* memory cleaanup

* forgot to run linter
This commit is contained in:
xyOz 2025-06-23 23:45:15 +01:00 committed by GitHub
parent 245c8f3269
commit 976dcfdcef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -8,6 +8,8 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
import useSound from "use-sound"
import { LRUCache } from "lru-cache"
import { useDebounceEffect } from "@src/utils/useDebounceEffect"
import type { ClineAsk, ClineMessage } from "@roo-code/types"
import { ClineSayBrowserAction, ClineSayTool, ExtensionMessage } from "@roo/ExtensionMessage"
@ -154,6 +156,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
ttl: 1000 * 60 * 15, // 15 minutes TTL for long-running tasks
}),
)
const autoApproveTimeoutRef = useRef<NodeJS.Timeout | null>(null)
const clineAskRef = useRef(clineAsk)
useEffect(() => {
@ -408,6 +411,12 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
everVisibleMessagesTsRef.current.clear() // Clear for new task
}, [task?.ts])
useEffect(() => {
if (isHidden) {
everVisibleMessagesTsRef.current.clear()
}
}, [isHidden])
useEffect(() => () => everVisibleMessagesTsRef.current.clear(), [])
useEffect(() => {
@ -714,17 +723,15 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
// NOTE: the VSCode window needs to be focused for this to work.
useMount(() => textAreaRef.current?.focus())
useEffect(() => {
const timer = setTimeout(() => {
useDebounceEffect(
() => {
if (!isHidden && !sendingDisabled && !enableButtons) {
textAreaRef.current?.focus()
}
}, 50)
return () => {
clearTimeout(timer)
}
}, [isHidden, sendingDisabled, enableButtons])
},
50,
[isHidden, sendingDisabled, enableButtons]
)
const visibleMessages = useMemo(() => {
const newVisibleMessages = modifiedMessages.filter((message) => {
@ -1086,6 +1093,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
[],
)
useEffect(() => {
return () => {
if (scrollToBottomSmooth && typeof (scrollToBottomSmooth as any).cancel === 'function') {
(scrollToBottomSmooth as any).cancel()
}
}
}, [scrollToBottomSmooth])
const scrollToBottomAuto = useCallback(() => {
virtuosoRef.current?.scrollTo({
top: Number.MAX_SAFE_INTEGER,
@ -1124,13 +1139,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
)
useEffect(() => {
let timerId: NodeJS.Timeout | undefined
let timer: NodeJS.Timeout | undefined
if (!disableAutoScrollRef.current) {
timerId = setTimeout(() => scrollToBottomSmooth(), 50)
timer = setTimeout(() => scrollToBottomSmooth(), 50)
}
return () => {
if (timerId) {
clearTimeout(timerId)
if (timer) {
clearTimeout(timer)
}
}
}, [groupedMessages.length, scrollToBottomSmooth])
@ -1151,21 +1166,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
// Effect to handle showing the checkpoint warning after a delay
useEffect(() => {
// Only show the warning when there's a task but no visible messages yet
if (task && modifiedMessages.length === 0 && !isStreaming) {
if (task && modifiedMessages.length === 0 && !isStreaming && !isHidden) {
const timer = setTimeout(() => {
setShowCheckpointWarning(true)
}, 5000) // 5 seconds
return () => clearTimeout(timer)
} else {
setShowCheckpointWarning(false)
}
}, [task, modifiedMessages.length, isStreaming])
}, [task, modifiedMessages.length, isStreaming, isHidden])
// Effect to hide the checkpoint warning when messages appear
useEffect(() => {
if (modifiedMessages.length > 0 || isStreaming) {
if (modifiedMessages.length > 0 || isStreaming || isHidden) {
setShowCheckpointWarning(false)
}
}, [modifiedMessages.length, isStreaming])
}, [modifiedMessages.length, isStreaming, isHidden])
const placeholderText = task ? t("chat:typeMessage") : t("chat:typeTask")
@ -1239,31 +1256,26 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
)
useEffect(() => {
// Only proceed if we have an ask and buttons are enabled.
if (autoApproveTimeoutRef.current) {
clearTimeout(autoApproveTimeoutRef.current)
autoApproveTimeoutRef.current = null
}
if (!clineAsk || !enableButtons) {
return
}
const autoApprove = async () => {
if (lastMessage?.ask && isAutoApproved(lastMessage)) {
// Note that `isAutoApproved` can only return true if
// lastMessage is an ask of type "browser_action_launch",
// "use_mcp_server", "command", or "tool".
// Add delay for write operations.
if (lastMessage.ask === "tool" && isWriteToolAction(lastMessage)) {
await new Promise((resolve) => setTimeout(resolve, writeDelayMs))
if (!isMountedRef.current) {
return
}
await new Promise<void>((resolve) => {
autoApproveTimeoutRef.current = setTimeout(resolve, writeDelayMs)
})
}
vscode.postMessage({ type: "askResponse", askResponse: "yesButtonClicked" })
if (autoApproveTimeoutRef.current === null || autoApproveTimeoutRef.current) {
vscode.postMessage({ type: "askResponse", askResponse: "yesButtonClicked" })
// This is copied from `handlePrimaryButtonClick`, which we used
// to call from `autoApprove`. I'm not sure how many of these
// things are actually needed.
if (isMountedRef.current) {
setSendingDisabled(true)
setClineAsk(undefined)
setEnableButtons(false)
@ -1271,6 +1283,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
}
}
autoApprove()
return () => {
if (autoApproveTimeoutRef.current) {
clearTimeout(autoApproveTimeoutRef.current)
autoApproveTimeoutRef.current = null
}
}
}, [
clineAsk,
enableButtons,