-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix: persist parent-child task relationships across extension reloads #6625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add parentTaskId, rootTaskId, and taskHierarchy fields to HistoryItem schema - Store task IDs alongside object references in Task class - Update taskMetadata to save parent-child relationship data - Modify ClineProvider to restore task hierarchy when loading from history - Implement getTaskHierarchy() method to build hierarchy array Fixes #6624
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote this code 10 minutes ago and already found 6 ways it could break.
| } | ||
|
|
||
| // Get task hierarchy for persistence | ||
| public getTaskHierarchy(): string[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method could cause an infinite loop if task data becomes corrupted and creates circular references. Consider:
| public getTaskHierarchy(): string[] { | |
| public getTaskHierarchy(): string[] { | |
| const hierarchy: string[] = [] | |
| const visited = new Set<string>() | |
| let currentTask: Task | undefined = this.parentTask | |
| while (currentTask && !visited.has(currentTask.taskId)) { | |
| visited.add(currentTask.taskId) | |
| hierarchy.unshift(currentTask.taskId) | |
| currentTask = currentTask.parentTask | |
| } | |
| return hierarchy | |
| } |
| const taskHistory = this.getGlobalState("taskHistory") ?? [] | ||
|
|
||
| // First, restore all parent tasks in the hierarchy | ||
| for (const taskId of historyItem.taskHierarchy) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling here. If a parent task fails to restore, the entire hierarchy restoration could fail. Consider wrapping this in a try-catch:
| for (const taskId of historyItem.taskHierarchy) { | |
| for (const taskId of historyItem.taskHierarchy) { | |
| try { | |
| const parentHistoryItem = taskHistory.find((item: HistoryItem) => item.id === taskId) | |
| if (parentHistoryItem && !this.clineStack.find((task) => task.taskId === taskId)) { | |
| await this.initClineWithHistoryItem(parentHistoryItem) | |
| } | |
| } catch (error) { | |
| console.error(`Failed to restore parent task ${taskId}:`, error) | |
| // Continue with other tasks in hierarchy | |
| } | |
| } |
| const hierarchy: string[] = [] | ||
| let currentTask: Task | undefined = this.parentTask | ||
|
|
||
| while (currentTask) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a maximum depth limit to prevent performance issues with excessively deep task hierarchies. You could add a MAX_HIERARCHY_DEPTH constant and check against it in the while loop.
| size: z.number().optional(), | ||
| workspace: z.string().optional(), | ||
| mode: z.string().optional(), | ||
| parentTaskId: z.string().optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be helpful to add JSDoc comments explaining these new fields:
| parentTaskId: z.string().optional(), | |
| /** ID of the parent task if this is a subtask */ | |
| parentTaskId: z.string().optional(), | |
| /** ID of the root task in the hierarchy */ | |
| rootTaskId: z.string().optional(), | |
| /** Array of task IDs representing the full hierarchy from root to parent */ | |
| taskHierarchy: z.array(z.string()).optional(), |
|
|
||
| // Check if this task has parent/child relationships that need to be restored | ||
| if (historyItem.taskHierarchy && historyItem.taskHierarchy.length > 0) { | ||
| // Restore the entire task hierarchy from root to this task |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding debug logging here to help troubleshoot hierarchy restoration issues in production:
| // Restore the entire task hierarchy from root to this task | |
| // Restore the entire task hierarchy from root to this task | |
| console.log(`[showTaskWithId] Restoring task hierarchy for task ${id} with ${historyItem.taskHierarchy.length} parent tasks`) | |
| const taskHistory = this.getGlobalState("taskHistory") ?? [] |
|
Doesn't work but I'm not sure why, the issue probably needs scoping |
Summary
This PR fixes issue #6624 by implementing persistence for parent-child task relationships that were previously lost when the VS Code extension reloaded.
Problem
When the RooCode extension reloaded (e.g., during VS Code restart, extension update, or window reload), parent-child task relationships were lost because they were only stored as object references in memory. This broke task hierarchy and workflow continuity for users working with nested tasks.
Solution
The solution adds persistent storage for task relationships by:
parentTaskId,rootTaskId, andtaskHierarchyfields to the HistoryItem schema to store relationship dataChanges
getTaskHierarchy()methodinitClineWithHistoryItemandshowTaskWithIdTesting
Impact
This change ensures that users can maintain their task workflows even when the extension reloads, providing a more stable and reliable experience when working with complex, nested tasks.
Fixes #6624
Important
Persist parent-child task relationships across extension reloads by updating
HistoryItemschema and enhancing task restoration logic.parentTaskId,rootTaskId, andtaskHierarchytoHistoryItemschema inhistory.ts.Taskclass inTask.tsto store task IDs and implementgetTaskHierarchy()for hierarchy retrieval.taskMetadata()intaskMetadata.tsto handle new relationship fields.ClineProviderinClineProvider.tsto restore task hierarchy usinginitClineWithHistoryItemandshowTaskWithId.Task.spec.tsandClineProvider.spec.ts.This description was created by
for 1bc2eef. You can customize this summary. It will automatically update as commits are pushed.