fix: propagate variant field in all promptAsync continuation paths (#3081)
All 5 continuation paths now send variant as top-level body field: - boulder-continuation-injector.ts - ralph-loop/continuation-prompt-injector.ts - todo-continuation-enforcer/continuation-injection.ts - unstable-agent-babysitter-hook.ts - session-recovery/resume.ts Plus type/helper updates in atlas, todo-continuation-enforcer, unstable-agent-babysitter, and session-recovery. TDD: 18 regression tests added, all pass. tsc clean.
This commit is contained in:
@@ -121,4 +121,64 @@ describe("injectBoulderContinuation", () => {
|
||||
expect(result).toBe("skipped_agent_unavailable")
|
||||
expect(promptAsyncMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test("#given recent prompt context includes variant #when injecting boulder continuation #then promptAsync receives variant as a top-level field", async () => {
|
||||
// given
|
||||
registerAgentName("atlas")
|
||||
const capturedRequests: Array<{
|
||||
body?: {
|
||||
model?: { providerID: string; modelID: string }
|
||||
variant?: string
|
||||
}
|
||||
}> = []
|
||||
const promptAsyncMock = mock(async (request: unknown) => {
|
||||
capturedRequests.push(request as typeof capturedRequests[number])
|
||||
return undefined
|
||||
})
|
||||
const recentModel = {
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-sonnet-4-20250514",
|
||||
variant: "max",
|
||||
}
|
||||
const messagesMock = mock(async () => ({
|
||||
data: [{
|
||||
id: "msg_1",
|
||||
info: {
|
||||
agent: "atlas",
|
||||
model: recentModel,
|
||||
time: { created: Date.now() },
|
||||
},
|
||||
}],
|
||||
}))
|
||||
|
||||
const ctx = {
|
||||
directory: "/tmp",
|
||||
client: {
|
||||
session: {
|
||||
messages: messagesMock,
|
||||
promptAsync: promptAsyncMock,
|
||||
},
|
||||
},
|
||||
} as unknown as PluginInput
|
||||
|
||||
// when
|
||||
const result = await injectBoulderContinuation({
|
||||
ctx,
|
||||
sessionID: "ses_test_variant",
|
||||
planName: "test-plan",
|
||||
remaining: 1,
|
||||
total: 2,
|
||||
agent: "atlas",
|
||||
sessionState: { promptFailureCount: 0 },
|
||||
})
|
||||
|
||||
// then
|
||||
expect(result).toBe("injected")
|
||||
expect(capturedRequests).toHaveLength(1)
|
||||
expect(capturedRequests[0]?.body?.model).toEqual({
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-sonnet-4-20250514",
|
||||
})
|
||||
expect(capturedRequests[0]?.body?.variant).toBe("max")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -71,12 +71,18 @@ export async function injectBoulderContinuation(input: {
|
||||
const promptContext = await resolveRecentPromptContextForSession(ctx, sessionID)
|
||||
const inheritedTools = resolveInheritedPromptTools(sessionID, promptContext.tools)
|
||||
|
||||
await ctx.client.session.promptAsync({
|
||||
path: { id: sessionID },
|
||||
body: {
|
||||
agent: continuationAgent,
|
||||
...(promptContext.model !== undefined ? { model: promptContext.model } : {}),
|
||||
...(inheritedTools ? { tools: inheritedTools } : {}),
|
||||
const launchModel = promptContext.model
|
||||
? { providerID: promptContext.model.providerID, modelID: promptContext.model.modelID }
|
||||
: undefined
|
||||
const launchVariant = promptContext.model?.variant
|
||||
|
||||
await ctx.client.session.promptAsync({
|
||||
path: { id: sessionID },
|
||||
body: {
|
||||
agent: continuationAgent,
|
||||
...(launchModel ? { model: launchModel } : {}),
|
||||
...(launchVariant ? { variant: launchVariant } : {}),
|
||||
...(inheritedTools ? { tools: inheritedTools } : {}),
|
||||
parts: [createInternalAgentTextPart(prompt)],
|
||||
},
|
||||
query: { directory: ctx.directory },
|
||||
|
||||
@@ -40,7 +40,14 @@ export async function resolveRecentPromptContextForSession(
|
||||
const model = info?.model
|
||||
const tools = normalizePromptTools(info?.tools)
|
||||
if (model?.providerID && model?.modelID) {
|
||||
return { model: { providerID: model.providerID, modelID: model.modelID }, tools }
|
||||
return {
|
||||
model: {
|
||||
providerID: model.providerID,
|
||||
modelID: model.modelID,
|
||||
...(model.variant ? { variant: model.variant } : {}),
|
||||
},
|
||||
tools,
|
||||
}
|
||||
}
|
||||
|
||||
if (info?.providerID && info?.modelID) {
|
||||
@@ -63,7 +70,14 @@ export async function resolveRecentPromptContextForSession(
|
||||
if (!model?.providerID || !model?.modelID) {
|
||||
return { tools }
|
||||
}
|
||||
return { model: { providerID: model.providerID, modelID: model.modelID }, tools }
|
||||
return {
|
||||
model: {
|
||||
providerID: model.providerID,
|
||||
modelID: model.modelID,
|
||||
...(model.variant ? { variant: model.variant } : {}),
|
||||
},
|
||||
tools,
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolveRecentModelForSession(
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { AgentOverrides } from "../../config"
|
||||
import type { BackgroundManager } from "../../features/background-agent"
|
||||
import type { TopLevelTaskRef } from "../../features/boulder-state"
|
||||
|
||||
export type ModelInfo = { providerID: string; modelID: string }
|
||||
export type ModelInfo = { providerID: string; modelID: string; variant?: string }
|
||||
|
||||
export interface AtlasHookOptions {
|
||||
directory: string
|
||||
|
||||
Reference in New Issue
Block a user