fix(background-agent): resolve parent wake agent aliases
This commit is contained in:
@@ -7,7 +7,7 @@ import { getSessionPromptParams, clearSessionPromptParams } from "../../shared/s
|
||||
import { tmpdir } from "node:os"
|
||||
import type { PluginInput } from "@opencode-ai/plugin"
|
||||
import * as sharedModule from "../../shared"
|
||||
import { _resetForTesting as resetClaudeCodeSessionState, subagentSessions } from "../claude-code-session-state"
|
||||
import { _resetForTesting as resetClaudeCodeSessionState, registerAgentName, subagentSessions } from "../claude-code-session-state"
|
||||
import type { BackgroundTask, ResumeInput } from "./types"
|
||||
import { MIN_IDLE_TIME_MS } from "./constants"
|
||||
import { BackgroundManager } from "./manager"
|
||||
@@ -5204,6 +5204,51 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
manager.shutdown()
|
||||
})
|
||||
|
||||
test("pins the registered parent agent alias before dispatching a deferred parent wake", async () => {
|
||||
//#given
|
||||
resetClaudeCodeSessionState()
|
||||
registerAgentName("\u200B\u200B\u200B\u200BAtlas - Plan Executor")
|
||||
const promptCalls: Array<{ path: { id: string }; body: Record<string, unknown> }> = []
|
||||
const client = {
|
||||
session: {
|
||||
status: async () => ({ data: { "parent-session-alias": { type: "idle" } } }),
|
||||
promptAsync: async (args: { path: { id: string }; body: Record<string, unknown> }) => {
|
||||
promptCalls.push(args)
|
||||
return {}
|
||||
},
|
||||
abort: async () => ({}),
|
||||
},
|
||||
}
|
||||
const manager = new BackgroundManager({ pluginContext: createPluginInput(client) })
|
||||
const managerInternals = cast<{
|
||||
queuePendingParentWake: (
|
||||
sessionID: string,
|
||||
notification: string,
|
||||
promptContext: Record<string, unknown>,
|
||||
shouldReply: boolean,
|
||||
delayMs?: number,
|
||||
) => void
|
||||
flushPendingParentWake: (sessionID: string) => Promise<void>
|
||||
}>(manager)
|
||||
|
||||
//#when
|
||||
managerInternals.queuePendingParentWake(
|
||||
"parent-session-alias",
|
||||
"<system-reminder>done</system-reminder>",
|
||||
{ agent: "atlas" },
|
||||
true,
|
||||
0,
|
||||
)
|
||||
await managerInternals.flushPendingParentWake("parent-session-alias")
|
||||
|
||||
//#then
|
||||
expect(promptCalls).toHaveLength(1)
|
||||
expect(promptCalls[0]?.body.agent).toBe("\u200B\u200B\u200B\u200BAtlas - Plan Executor")
|
||||
|
||||
manager.shutdown()
|
||||
resetClaudeCodeSessionState()
|
||||
})
|
||||
|
||||
test("does not requeue dispatched parent wake when session.error arrives before accepted history is visible", async () => {
|
||||
//#given
|
||||
const promptCalls: Array<{ path: { id: string }; body: Record<string, unknown> }> = []
|
||||
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
type QueueItem,
|
||||
} from "./constants"
|
||||
|
||||
import { subagentSessions } from "../claude-code-session-state"
|
||||
import { resolveRegisteredAgentName, subagentSessions } from "../claude-code-session-state"
|
||||
import { getTaskToastManager } from "../task-toast-manager"
|
||||
import { formatDuration } from "./duration-formatter"
|
||||
import {
|
||||
@@ -1385,13 +1385,20 @@ The fallback retry session is now created and can be inspected directly.
|
||||
this.observedOutputSessions.add(sessionID)
|
||||
}
|
||||
|
||||
private cloneParentWake(wake: PendingParentWake): PendingParentWake {
|
||||
private resolveParentWakePromptContext(promptContext: ParentWakePromptContext): ParentWakePromptContext {
|
||||
const resolvedAgent = resolveRegisteredAgentName(promptContext.agent)
|
||||
return {
|
||||
promptContext: {
|
||||
...wake.promptContext,
|
||||
...(wake.promptContext.model ? { model: { ...wake.promptContext.model } } : {}),
|
||||
...(wake.promptContext.tools ? { tools: { ...wake.promptContext.tools } } : {}),
|
||||
},
|
||||
...promptContext,
|
||||
...(resolvedAgent ? { agent: resolvedAgent } : {}),
|
||||
...(promptContext.model ? { model: { ...promptContext.model } } : {}),
|
||||
...(promptContext.tools ? { tools: { ...promptContext.tools } } : {}),
|
||||
}
|
||||
}
|
||||
|
||||
private cloneParentWake(wake: PendingParentWake): PendingParentWake {
|
||||
const promptContext = this.resolveParentWakePromptContext(wake.promptContext)
|
||||
return {
|
||||
promptContext,
|
||||
notifications: [...wake.notifications],
|
||||
shouldReply: wake.shouldReply,
|
||||
...(wake.dispatchedAt !== undefined ? { dispatchedAt: wake.dispatchedAt } : {}),
|
||||
@@ -2692,14 +2699,15 @@ The task was re-queued on a fallback model after a retryable failure.
|
||||
shouldReply: boolean,
|
||||
delayMs?: number,
|
||||
): void {
|
||||
const resolvedPromptContext = this.resolveParentWakePromptContext(promptContext)
|
||||
const pendingWake = this.pendingParentWakes.get(sessionID)
|
||||
if (pendingWake) {
|
||||
pendingWake.notifications.push(notification)
|
||||
pendingWake.promptContext = promptContext
|
||||
pendingWake.promptContext = resolvedPromptContext
|
||||
pendingWake.shouldReply = pendingWake.shouldReply || shouldReply
|
||||
} else {
|
||||
this.pendingParentWakes.set(sessionID, {
|
||||
promptContext,
|
||||
promptContext: resolvedPromptContext,
|
||||
notifications: [notification],
|
||||
shouldReply,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user