fix(background-agent): gracefully handle aborted parent session in notifyParentSession
When the main session is aborted while background tasks are running, notifyParentSession() would attempt to call session.messages() and session.prompt() on the aborted parent session, causing exceptions that could crash the TUI. - Add isAbortedSessionError() helper to detect abort-related errors - Add abort check in session.messages() catch block with early return - Add abort check in session.prompt() catch block with early return - Add test case covering aborted parent session scenario Fixes TUI crash when aborting main session with running background tasks.
This commit is contained in:
@@ -1123,7 +1123,14 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
} catch (error) {
|
||||
if (this.isAbortedSessionError(error)) {
|
||||
log("[background-agent] Parent session aborted, skipping notification:", {
|
||||
taskId: task.id,
|
||||
parentSessionID: task.parentSessionID,
|
||||
})
|
||||
return
|
||||
}
|
||||
const messageDir = getMessageDir(task.parentSessionID)
|
||||
const currentMessage = messageDir ? findNearestMessageWithFields(messageDir) : null
|
||||
agent = currentMessage?.agent ?? task.parentAgent
|
||||
@@ -1154,6 +1161,13 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
||||
noReply: !allComplete,
|
||||
})
|
||||
} catch (error) {
|
||||
if (this.isAbortedSessionError(error)) {
|
||||
log("[background-agent] Parent session aborted, skipping notification:", {
|
||||
taskId: task.id,
|
||||
parentSessionID: task.parentSessionID,
|
||||
})
|
||||
return
|
||||
}
|
||||
log("[background-agent] Failed to send notification:", error)
|
||||
}
|
||||
|
||||
@@ -1192,6 +1206,28 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
||||
return `${seconds}s`
|
||||
}
|
||||
|
||||
private isAbortedSessionError(error: unknown): boolean {
|
||||
const message = this.getErrorText(error)
|
||||
return message.toLowerCase().includes("aborted")
|
||||
}
|
||||
|
||||
private getErrorText(error: unknown): string {
|
||||
if (!error) return ""
|
||||
if (typeof error === "string") return error
|
||||
if (error instanceof Error) {
|
||||
return `${error.name}: ${error.message}`
|
||||
}
|
||||
if (typeof error === "object" && error !== null) {
|
||||
if ("message" in error && typeof error.message === "string") {
|
||||
return error.message
|
||||
}
|
||||
if ("name" in error && typeof error.name === "string") {
|
||||
return error.name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
private hasRunningTasks(): boolean {
|
||||
for (const task of this.tasks.values()) {
|
||||
if (task.status === "running") return true
|
||||
|
||||
Reference in New Issue
Block a user