fix(background-agent): allow disabling parent session reminders
This commit is contained in:
parent
b963571642
commit
5298ff2879
@ -981,6 +981,52 @@ describe("BackgroundManager.notifyParentSession - aborted parent", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("BackgroundManager.notifyParentSession - notifications toggle", () => {
|
||||||
|
test("should skip parent prompt injection when notifications are disabled", async () => {
|
||||||
|
//#given
|
||||||
|
let promptCalled = false
|
||||||
|
const promptMock = async () => {
|
||||||
|
promptCalled = true
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
const client = {
|
||||||
|
session: {
|
||||||
|
prompt: promptMock,
|
||||||
|
promptAsync: promptMock,
|
||||||
|
abort: async () => ({}),
|
||||||
|
messages: async () => ({ data: [] }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const manager = new BackgroundManager(
|
||||||
|
{ client, directory: tmpdir() } as unknown as PluginInput,
|
||||||
|
undefined,
|
||||||
|
{ enableParentSessionNotifications: false },
|
||||||
|
)
|
||||||
|
const task: BackgroundTask = {
|
||||||
|
id: "task-no-parent-notification",
|
||||||
|
sessionID: "session-child",
|
||||||
|
parentSessionID: "session-parent",
|
||||||
|
parentMessageID: "msg-parent",
|
||||||
|
description: "task notifications disabled",
|
||||||
|
prompt: "test",
|
||||||
|
agent: "explore",
|
||||||
|
status: "completed",
|
||||||
|
startedAt: new Date(),
|
||||||
|
completedAt: new Date(),
|
||||||
|
}
|
||||||
|
getPendingByParent(manager).set("session-parent", new Set([task.id]))
|
||||||
|
|
||||||
|
//#when
|
||||||
|
await (manager as unknown as { notifyParentSession: (task: BackgroundTask) => Promise<void> })
|
||||||
|
.notifyParentSession(task)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(promptCalled).toBe(false)
|
||||||
|
|
||||||
|
manager.shutdown()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
function buildNotificationPromptBody(
|
function buildNotificationPromptBody(
|
||||||
task: BackgroundTask,
|
task: BackgroundTask,
|
||||||
currentMessage: CurrentMessage | null
|
currentMessage: CurrentMessage | null
|
||||||
|
|||||||
@ -93,6 +93,7 @@ export class BackgroundManager {
|
|||||||
private completionTimers: Map<string, ReturnType<typeof setTimeout>> = new Map()
|
private completionTimers: Map<string, ReturnType<typeof setTimeout>> = new Map()
|
||||||
private idleDeferralTimers: Map<string, ReturnType<typeof setTimeout>> = new Map()
|
private idleDeferralTimers: Map<string, ReturnType<typeof setTimeout>> = new Map()
|
||||||
private notificationQueueByParent: Map<string, Promise<void>> = new Map()
|
private notificationQueueByParent: Map<string, Promise<void>> = new Map()
|
||||||
|
private enableParentSessionNotifications: boolean
|
||||||
readonly taskHistory = new TaskHistory()
|
readonly taskHistory = new TaskHistory()
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -102,6 +103,7 @@ export class BackgroundManager {
|
|||||||
tmuxConfig?: TmuxConfig
|
tmuxConfig?: TmuxConfig
|
||||||
onSubagentSessionCreated?: OnSubagentSessionCreated
|
onSubagentSessionCreated?: OnSubagentSessionCreated
|
||||||
onShutdown?: () => void
|
onShutdown?: () => void
|
||||||
|
enableParentSessionNotifications?: boolean
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
this.tasks = new Map()
|
this.tasks = new Map()
|
||||||
@ -114,6 +116,7 @@ export class BackgroundManager {
|
|||||||
this.tmuxEnabled = options?.tmuxConfig?.enabled ?? false
|
this.tmuxEnabled = options?.tmuxConfig?.enabled ?? false
|
||||||
this.onSubagentSessionCreated = options?.onSubagentSessionCreated
|
this.onSubagentSessionCreated = options?.onSubagentSessionCreated
|
||||||
this.onShutdown = options?.onShutdown
|
this.onShutdown = options?.onShutdown
|
||||||
|
this.enableParentSessionNotifications = options?.enableParentSessionNotifications ?? true
|
||||||
this.registerProcessCleanup()
|
this.registerProcessCleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,14 +1189,17 @@ export class BackgroundManager {
|
|||||||
allComplete = true
|
allComplete = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const completedTasks = allComplete
|
||||||
|
? Array.from(this.tasks.values())
|
||||||
|
.filter(t => t.parentSessionID === task.parentSessionID && t.status !== "running" && t.status !== "pending")
|
||||||
|
: []
|
||||||
|
|
||||||
|
if (this.enableParentSessionNotifications) {
|
||||||
const statusText = task.status === "completed" ? "COMPLETED" : task.status === "interrupt" ? "INTERRUPTED" : "CANCELLED"
|
const statusText = task.status === "completed" ? "COMPLETED" : task.status === "interrupt" ? "INTERRUPTED" : "CANCELLED"
|
||||||
const errorInfo = task.error ? `\n**Error:** ${task.error}` : ""
|
const errorInfo = task.error ? `\n**Error:** ${task.error}` : ""
|
||||||
|
|
||||||
let notification: string
|
let notification: string
|
||||||
let completedTasks: BackgroundTask[] = []
|
|
||||||
if (allComplete) {
|
if (allComplete) {
|
||||||
completedTasks = Array.from(this.tasks.values())
|
|
||||||
.filter(t => t.parentSessionID === task.parentSessionID && t.status !== "running" && t.status !== "pending")
|
|
||||||
const completedTasksText = completedTasks
|
const completedTasksText = completedTasks
|
||||||
.map(t => `- \`${t.id}\`: ${t.description}`)
|
.map(t => `- \`${t.id}\`: ${t.description}`)
|
||||||
.join("\n")
|
.join("\n")
|
||||||
@ -1285,6 +1291,12 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
|||||||
}
|
}
|
||||||
log("[background-agent] Failed to send notification:", error)
|
log("[background-agent] Failed to send notification:", error)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log("[background-agent] Parent session notifications disabled, skipping prompt injection:", {
|
||||||
|
taskId: task.id,
|
||||||
|
parentSessionID: task.parentSessionID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (allComplete) {
|
if (allComplete) {
|
||||||
for (const completedTask of completedTasks) {
|
for (const completedTask of completedTasks) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user