mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: persist parent-child task relationships across extension reloads
- 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
This commit is contained in:
parent
82a007a211
commit
1bc2eefdf4
4 changed files with 67 additions and 2 deletions
|
|
@ -17,6 +17,9 @@ export const historyItemSchema = z.object({
|
|||
size: z.number().optional(),
|
||||
workspace: z.string().optional(),
|
||||
mode: z.string().optional(),
|
||||
parentTaskId: z.string().optional(),
|
||||
rootTaskId: z.string().optional(),
|
||||
taskHierarchy: z.array(z.string()).optional(),
|
||||
})
|
||||
|
||||
export type HistoryItem = z.infer<typeof historyItemSchema>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ export type TaskMetadataOptions = {
|
|||
globalStoragePath: string
|
||||
workspace: string
|
||||
mode?: string
|
||||
parentTaskId?: string
|
||||
rootTaskId?: string
|
||||
taskHierarchy?: string[]
|
||||
}
|
||||
|
||||
export async function taskMetadata({
|
||||
|
|
@ -28,6 +31,9 @@ export async function taskMetadata({
|
|||
globalStoragePath,
|
||||
workspace,
|
||||
mode,
|
||||
parentTaskId,
|
||||
rootTaskId,
|
||||
taskHierarchy,
|
||||
}: TaskMetadataOptions) {
|
||||
const taskDir = await getTaskDirectoryPath(globalStoragePath, taskId)
|
||||
|
||||
|
|
@ -95,6 +101,9 @@ export async function taskMetadata({
|
|||
size: taskDirSize,
|
||||
workspace,
|
||||
mode,
|
||||
parentTaskId,
|
||||
rootTaskId,
|
||||
taskHierarchy,
|
||||
}
|
||||
|
||||
return { historyItem, tokenUsage }
|
||||
|
|
|
|||
|
|
@ -129,6 +129,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
readonly taskNumber: number
|
||||
readonly workspacePath: string
|
||||
|
||||
// Store task IDs for persistence
|
||||
readonly rootTaskId: string | undefined = undefined
|
||||
readonly parentTaskId: string | undefined = undefined
|
||||
|
||||
/**
|
||||
* The mode associated with this task. Persisted across sessions
|
||||
* to maintain user context when reopening tasks from history.
|
||||
|
|
@ -307,6 +311,10 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
this.parentTask = parentTask
|
||||
this.taskNumber = taskNumber
|
||||
|
||||
// Store task IDs for persistence
|
||||
this.rootTaskId = rootTask?.taskId
|
||||
this.parentTaskId = parentTask?.taskId
|
||||
|
||||
// Store the task's mode when it's created.
|
||||
// For history items, use the stored mode; for new tasks, we'll set it
|
||||
// after getting state.
|
||||
|
|
@ -582,6 +590,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
globalStoragePath: this.globalStoragePath,
|
||||
workspace: this.cwd,
|
||||
mode: this._taskMode || defaultModeSlug, // Use the task's own mode, not the current provider mode
|
||||
parentTaskId: this.parentTaskId,
|
||||
rootTaskId: this.rootTaskId,
|
||||
taskHierarchy: this.getTaskHierarchy(),
|
||||
})
|
||||
|
||||
this.emit(RooCodeEventName.TaskTokenUsageUpdated, this.taskId, tokenUsage)
|
||||
|
|
@ -2152,4 +2163,17 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
public get cwd() {
|
||||
return this.workspacePath
|
||||
}
|
||||
|
||||
// Get task hierarchy for persistence
|
||||
public getTaskHierarchy(): string[] {
|
||||
const hierarchy: string[] = []
|
||||
let currentTask: Task | undefined = this.parentTask
|
||||
|
||||
while (currentTask) {
|
||||
hierarchy.unshift(currentTask.taskId)
|
||||
currentTask = currentTask.parentTask
|
||||
}
|
||||
|
||||
return hierarchy
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -740,6 +740,18 @@ export class ClineProvider
|
|||
experiments,
|
||||
} = await this.getState()
|
||||
|
||||
// Restore parent and root tasks if their IDs are stored in the history item
|
||||
let rootTask: Task | undefined = historyItem.rootTask
|
||||
let parentTask: Task | undefined = historyItem.parentTask
|
||||
|
||||
// If we don't have the actual task objects but have their IDs, try to find them in the stack
|
||||
if (!rootTask && historyItem.rootTaskId) {
|
||||
rootTask = this.clineStack.find((task) => task.taskId === historyItem.rootTaskId)
|
||||
}
|
||||
if (!parentTask && historyItem.parentTaskId) {
|
||||
parentTask = this.clineStack.find((task) => task.taskId === historyItem.parentTaskId)
|
||||
}
|
||||
|
||||
const task = new Task({
|
||||
provider: this,
|
||||
apiConfiguration,
|
||||
|
|
@ -749,8 +761,8 @@ export class ClineProvider
|
|||
consecutiveMistakeLimit: apiConfiguration.consecutiveMistakeLimit,
|
||||
historyItem,
|
||||
experiments,
|
||||
rootTask: historyItem.rootTask,
|
||||
parentTask: historyItem.parentTask,
|
||||
rootTask,
|
||||
parentTask,
|
||||
taskNumber: historyItem.number,
|
||||
onCreated: (instance) => this.emit(RooCodeEventName.TaskCreated, instance),
|
||||
})
|
||||
|
|
@ -1344,6 +1356,23 @@ export class ClineProvider
|
|||
if (id !== this.getCurrentCline()?.taskId) {
|
||||
// Non-current task.
|
||||
const { historyItem } = await this.getTaskWithId(id)
|
||||
|
||||
// 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
|
||||
const taskHistory = this.getGlobalState("taskHistory") ?? []
|
||||
|
||||
// First, restore all parent tasks in the hierarchy
|
||||
for (const taskId of historyItem.taskHierarchy) {
|
||||
const parentHistoryItem = taskHistory.find((item: HistoryItem) => item.id === taskId)
|
||||
if (parentHistoryItem && !this.clineStack.find((task) => task.taskId === taskId)) {
|
||||
// This parent task is not in the stack, so restore it
|
||||
await this.initClineWithHistoryItem(parentHistoryItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now restore the requested task
|
||||
await this.initClineWithHistoryItem(historyItem) // Clears existing task.
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue