mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: fix UI performance issue during long tasks with incremental message updates
- Add incrementalStateUpdate message type to ExtensionMessage.ts - Implement postIncrementalUpdateToWebview() method in ClineProvider.ts - Update Task.ts to use incremental updates instead of full state posts - Add webview handler for incremental updates in ExtensionStateContext.tsx - Maintain backward compatibility for initial loads and reconnections - Reduces data transfer from O(n²) to O(1) per message update Fixes #6513
This commit is contained in:
parent
5041880da0
commit
a373d6cb04
4 changed files with 84 additions and 3 deletions
|
|
@ -544,7 +544,12 @@ export class Task extends EventEmitter<TaskEvents> {
|
|||
private async addToClineMessages(message: ClineMessage) {
|
||||
this.clineMessages.push(message)
|
||||
const provider = this.providerRef.deref()
|
||||
await provider?.postStateToWebview()
|
||||
|
||||
// Use incremental update instead of posting full state for better performance
|
||||
await provider?.postIncrementalUpdateToWebview({
|
||||
newMessages: [message],
|
||||
})
|
||||
|
||||
this.emit("message", { action: "created", message })
|
||||
await this.saveClineMessages()
|
||||
|
||||
|
|
@ -566,7 +571,12 @@ export class Task extends EventEmitter<TaskEvents> {
|
|||
|
||||
private async updateClineMessage(message: ClineMessage) {
|
||||
const provider = this.providerRef.deref()
|
||||
await provider?.postMessageToWebview({ type: "messageUpdated", clineMessage: message })
|
||||
|
||||
// Use incremental update for message updates as well
|
||||
await provider?.postIncrementalUpdateToWebview({
|
||||
updatedMessages: [message],
|
||||
})
|
||||
|
||||
this.emit("message", { action: "updated", message })
|
||||
|
||||
const shouldCaptureMessage = message.partial !== true && CloudService.isEnabled()
|
||||
|
|
@ -598,7 +608,13 @@ export class Task extends EventEmitter<TaskEvents> {
|
|||
|
||||
this.emit("taskTokenUsageUpdated", this.taskId, tokenUsage)
|
||||
|
||||
await this.providerRef.deref()?.updateTaskHistory(historyItem)
|
||||
const provider = this.providerRef.deref()
|
||||
await provider?.updateTaskHistory(historyItem)
|
||||
|
||||
// Send incremental update for task history
|
||||
await provider?.postIncrementalUpdateToWebview({
|
||||
taskHistoryUpdate: historyItem,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("Failed to save Roo messages:", error)
|
||||
}
|
||||
|
|
@ -926,6 +942,7 @@ export class Task extends EventEmitter<TaskEvents> {
|
|||
// messages from previous session).
|
||||
this.clineMessages = []
|
||||
this.apiConversationHistory = []
|
||||
// Use full state update for initial task start
|
||||
await this.providerRef.deref()?.postStateToWebview()
|
||||
|
||||
await this.say("text", task, images)
|
||||
|
|
|
|||
|
|
@ -1340,6 +1340,22 @@ export class ClineProvider
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts incremental updates to the webview instead of the full state.
|
||||
* This significantly improves performance for long conversations by only
|
||||
* sending new or updated messages instead of the entire conversation history.
|
||||
*/
|
||||
async postIncrementalUpdateToWebview(options: {
|
||||
newMessages?: import("@roo-code/types").ClineMessage[]
|
||||
updatedMessages?: import("@roo-code/types").ClineMessage[]
|
||||
taskHistoryUpdate?: import("@roo-code/types").HistoryItem
|
||||
}) {
|
||||
await this.postMessageToWebview({
|
||||
type: "incrementalStateUpdate",
|
||||
incrementalUpdate: options,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches marketplace data on demand to avoid blocking main state updates
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ export interface ExtensionMessage {
|
|||
type:
|
||||
| "action"
|
||||
| "state"
|
||||
| "incrementalStateUpdate"
|
||||
| "selectedImages"
|
||||
| "theme"
|
||||
| "workspaceUpdated"
|
||||
|
|
@ -135,6 +136,11 @@ export interface ExtensionMessage {
|
|||
| "switchTab"
|
||||
invoke?: "newChat" | "sendMessage" | "primaryButtonClick" | "secondaryButtonClick" | "setChatBoxMessage"
|
||||
state?: ExtensionState
|
||||
incrementalUpdate?: {
|
||||
newMessages?: ClineMessage[]
|
||||
updatedMessages?: ClineMessage[]
|
||||
taskHistoryUpdate?: HistoryItem
|
||||
}
|
||||
images?: string[]
|
||||
filePaths?: string[]
|
||||
openedTabs?: Array<{
|
||||
|
|
|
|||
|
|
@ -312,6 +312,48 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
}
|
||||
break
|
||||
}
|
||||
case "incrementalStateUpdate": {
|
||||
const update = message.incrementalUpdate!
|
||||
setState((prevState) => {
|
||||
let newClineMessages = [...prevState.clineMessages]
|
||||
|
||||
// Add new messages
|
||||
if (update.newMessages) {
|
||||
newClineMessages.push(...update.newMessages)
|
||||
}
|
||||
|
||||
// Update existing messages
|
||||
if (update.updatedMessages) {
|
||||
for (const updatedMessage of update.updatedMessages) {
|
||||
const index = findLastIndex(newClineMessages, (msg) => msg.ts === updatedMessage.ts)
|
||||
if (index !== -1) {
|
||||
newClineMessages[index] = updatedMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update task history if provided
|
||||
let newTaskHistory = prevState.taskHistory
|
||||
if (update.taskHistoryUpdate) {
|
||||
const historyIndex = newTaskHistory.findIndex(
|
||||
(item) => item.id === update.taskHistoryUpdate!.id,
|
||||
)
|
||||
if (historyIndex !== -1) {
|
||||
newTaskHistory = [...newTaskHistory]
|
||||
newTaskHistory[historyIndex] = update.taskHistoryUpdate
|
||||
} else {
|
||||
newTaskHistory = [...newTaskHistory, update.taskHistoryUpdate]
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
clineMessages: newClineMessages,
|
||||
taskHistory: newTaskHistory,
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
case "theme": {
|
||||
if (message.text) {
|
||||
setTheme(convertTextMateToHljs(JSON.parse(message.text)))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue