perf(background-agent): index tasks by parent session
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -138,6 +138,7 @@ export class BackgroundManager {
|
|||||||
|
|
||||||
|
|
||||||
private tasks: Map<string, BackgroundTask>
|
private tasks: Map<string, BackgroundTask>
|
||||||
|
private tasksByParentSession: Map<string, Set<string>>
|
||||||
private notifications: Map<string, BackgroundTask[]>
|
private notifications: Map<string, BackgroundTask[]>
|
||||||
private pendingNotifications: Map<string, string[]>
|
private pendingNotifications: Map<string, string[]>
|
||||||
private pendingByParent: Map<string, Set<string>> // Track pending tasks per parent for batching
|
private pendingByParent: Map<string, Set<string>> // Track pending tasks per parent for batching
|
||||||
@@ -177,6 +178,7 @@ export class BackgroundManager {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
this.tasks = new Map()
|
this.tasks = new Map()
|
||||||
|
this.tasksByParentSession = new Map()
|
||||||
this.notifications = new Map()
|
this.notifications = new Map()
|
||||||
this.pendingNotifications = new Map()
|
this.pendingNotifications = new Map()
|
||||||
this.pendingByParent = new Map()
|
this.pendingByParent = new Map()
|
||||||
@@ -280,6 +282,50 @@ export class BackgroundManager {
|
|||||||
this.unregisterRootDescendant(task.rootSessionID)
|
this.unregisterRootDescendant(task.rootSessionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private addTask(task: BackgroundTask): void {
|
||||||
|
this.tasks.set(task.id, task)
|
||||||
|
if (!task.parentSessionID) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskIDs = this.tasksByParentSession.get(task.parentSessionID) ?? new Set<string>()
|
||||||
|
taskIDs.add(task.id)
|
||||||
|
this.tasksByParentSession.set(task.parentSessionID, taskIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeTask(task: BackgroundTask): void {
|
||||||
|
this.tasks.delete(task.id)
|
||||||
|
this.removeTaskFromParentIndex(task.id, task.parentSessionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTaskParent(task: BackgroundTask, parentSessionID: string): void {
|
||||||
|
if (task.parentSessionID === parentSessionID) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeTaskFromParentIndex(task.id, task.parentSessionID)
|
||||||
|
task.parentSessionID = parentSessionID
|
||||||
|
const taskIDs = this.tasksByParentSession.get(parentSessionID) ?? new Set<string>()
|
||||||
|
taskIDs.add(task.id)
|
||||||
|
this.tasksByParentSession.set(parentSessionID, taskIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeTaskFromParentIndex(taskID: string, parentSessionID: string | undefined): void {
|
||||||
|
if (!parentSessionID) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskIDs = this.tasksByParentSession.get(parentSessionID)
|
||||||
|
if (!taskIDs) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
taskIDs.delete(taskID)
|
||||||
|
if (taskIDs.size === 0) {
|
||||||
|
this.tasksByParentSession.delete(parentSessionID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async launch(input: LaunchInput): Promise<BackgroundTask> {
|
async launch(input: LaunchInput): Promise<BackgroundTask> {
|
||||||
log("[background-agent] launch() called with:", {
|
log("[background-agent] launch() called with:", {
|
||||||
agent: input.agent,
|
agent: input.agent,
|
||||||
@@ -325,7 +371,7 @@ export class BackgroundManager {
|
|||||||
category: input.category,
|
category: input.category,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tasks.set(task.id, task)
|
this.addTask(task)
|
||||||
this.taskHistory.record(input.parentSessionID, { id: task.id, agent: input.agent, description: input.description, status: "pending", category: input.category })
|
this.taskHistory.record(input.parentSessionID, { id: task.id, agent: input.agent, description: input.description, status: "pending", category: input.category })
|
||||||
|
|
||||||
// Track for batched notifications immediately (pending state)
|
// Track for batched notifications immediately (pending state)
|
||||||
@@ -636,13 +682,25 @@ export class BackgroundManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTasksByParentSession(sessionID: string): BackgroundTask[] {
|
getTasksByParentSession(sessionID: string): BackgroundTask[] {
|
||||||
const result: BackgroundTask[] = []
|
const taskIDs = this.tasksByParentSession.get(sessionID)
|
||||||
for (const task of this.tasks.values()) {
|
if (!taskIDs) {
|
||||||
if (task.parentSessionID === sessionID) {
|
const result: BackgroundTask[] = []
|
||||||
result.push(task)
|
for (const task of this.tasks.values()) {
|
||||||
|
if (task.parentSessionID === sessionID) {
|
||||||
|
result.push(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasks: BackgroundTask[] = []
|
||||||
|
for (const taskID of taskIDs) {
|
||||||
|
const task = this.tasks.get(taskID)
|
||||||
|
if (task) {
|
||||||
|
tasks.push(task)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllDescendantTasks(sessionID: string): BackgroundTask[] {
|
getAllDescendantTasks(sessionID: string): BackgroundTask[] {
|
||||||
@@ -696,7 +754,7 @@ export class BackgroundManager {
|
|||||||
const parentChanged = input.parentSessionID !== existingTask.parentSessionID
|
const parentChanged = input.parentSessionID !== existingTask.parentSessionID
|
||||||
if (parentChanged) {
|
if (parentChanged) {
|
||||||
this.cleanupPendingByParent(existingTask) // Clean from OLD parent
|
this.cleanupPendingByParent(existingTask) // Clean from OLD parent
|
||||||
existingTask.parentSessionID = input.parentSessionID
|
this.updateTaskParent(existingTask, input.parentSessionID)
|
||||||
}
|
}
|
||||||
if (input.parentAgent !== undefined) {
|
if (input.parentAgent !== undefined) {
|
||||||
existingTask.parentAgent = input.parentAgent
|
existingTask.parentAgent = input.parentAgent
|
||||||
@@ -751,7 +809,7 @@ export class BackgroundManager {
|
|||||||
concurrencyGroup,
|
concurrencyGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tasks.set(task.id, task)
|
this.addTask(task)
|
||||||
subagentSessions.add(input.sessionID)
|
subagentSessions.add(input.sessionID)
|
||||||
this.startPolling()
|
this.startPolling()
|
||||||
this.taskHistory.record(input.parentSessionID, { id: task.id, sessionID: input.sessionID, agent: input.agent || "task", description: input.description, status: "running", startedAt: task.startedAt })
|
this.taskHistory.record(input.parentSessionID, { id: task.id, sessionID: input.sessionID, agent: input.agent || "task", description: input.description, status: "running", startedAt: task.startedAt })
|
||||||
@@ -801,7 +859,7 @@ export class BackgroundManager {
|
|||||||
existingTask.status = "running"
|
existingTask.status = "running"
|
||||||
existingTask.completedAt = undefined
|
existingTask.completedAt = undefined
|
||||||
existingTask.error = undefined
|
existingTask.error = undefined
|
||||||
existingTask.parentSessionID = input.parentSessionID
|
this.updateTaskParent(existingTask, input.parentSessionID)
|
||||||
existingTask.parentMessageID = input.parentMessageID
|
existingTask.parentMessageID = input.parentMessageID
|
||||||
existingTask.parentModel = input.parentModel
|
existingTask.parentModel = input.parentModel
|
||||||
existingTask.parentAgent = input.parentAgent
|
existingTask.parentAgent = input.parentAgent
|
||||||
@@ -1493,7 +1551,7 @@ export class BackgroundManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.clearNotificationsForTask(taskId)
|
this.clearNotificationsForTask(taskId)
|
||||||
this.tasks.delete(taskId)
|
this.removeTask(task)
|
||||||
this.clearTaskHistoryWhenParentTasksGone(task.parentSessionID)
|
this.clearTaskHistoryWhenParentTasksGone(task.parentSessionID)
|
||||||
if (task.sessionID) {
|
if (task.sessionID) {
|
||||||
subagentSessions.delete(task.sessionID)
|
subagentSessions.delete(task.sessionID)
|
||||||
@@ -2161,6 +2219,7 @@ export class BackgroundManager {
|
|||||||
|
|
||||||
this.concurrencyManager.clear()
|
this.concurrencyManager.clear()
|
||||||
this.tasks.clear()
|
this.tasks.clear()
|
||||||
|
this.tasksByParentSession.clear()
|
||||||
this.notifications.clear()
|
this.notifications.clear()
|
||||||
this.pendingNotifications.clear()
|
this.pendingNotifications.clear()
|
||||||
this.pendingByParent.clear()
|
this.pendingByParent.clear()
|
||||||
|
|||||||
Reference in New Issue
Block a user