Merge pull request #2807 from code-yeongyu/fix/b4-manager-model-override-1774351606
fix(background-task): apply model override omission to manager live path
This commit is contained in:
@@ -1668,7 +1668,7 @@ describe("BackgroundManager.resume model persistence", () => {
|
|||||||
// then - model should be passed in prompt body
|
// then - model should be passed in prompt body
|
||||||
expect(promptCalls).toHaveLength(1)
|
expect(promptCalls).toHaveLength(1)
|
||||||
expect(promptCalls[0].body.model).toEqual({ providerID: "anthropic", modelID: "claude-sonnet-4-20250514" })
|
expect(promptCalls[0].body.model).toEqual({ providerID: "anthropic", modelID: "claude-sonnet-4-20250514" })
|
||||||
expect(promptCalls[0].body.agent).toBe("explore")
|
expect("agent" in promptCalls[0].body).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should NOT pass model when task has no model (backward compatibility)", async () => {
|
test("should NOT pass model when task has no model (backward compatibility)", async () => {
|
||||||
@@ -1806,9 +1806,9 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
|
|||||||
expect(task.sessionID).toBeUndefined()
|
expect(task.sessionID).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should return immediately even with concurrency limit", async () => {
|
test("should return immediately even with concurrency limit", async () => {
|
||||||
// given
|
// given
|
||||||
const config = { defaultConcurrency: 1 }
|
const config = { defaultConcurrency: 1 }
|
||||||
manager.shutdown()
|
manager.shutdown()
|
||||||
manager = new BackgroundManager({ client: mockClient, directory: tmpdir() } as unknown as PluginInput, config)
|
manager = new BackgroundManager({ client: mockClient, directory: tmpdir() } as unknown as PluginInput, config)
|
||||||
|
|
||||||
@@ -1828,9 +1828,76 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
expect(endTime - startTime).toBeLessThan(100) // Should be instant
|
expect(endTime - startTime).toBeLessThan(100) // Should be instant
|
||||||
expect(task1.status).toBe("pending")
|
expect(task1.status).toBe("pending")
|
||||||
expect(task2.status).toBe("pending")
|
expect(task2.status).toBe("pending")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should omit agent when launch has model and keep agent without model", async () => {
|
||||||
|
// given
|
||||||
|
const promptBodies: Array<Record<string, unknown>> = []
|
||||||
|
let resolveFirstPromptStarted: (() => void) | undefined
|
||||||
|
let resolveSecondPromptStarted: (() => void) | undefined
|
||||||
|
const firstPromptStarted = new Promise<void>((resolve) => {
|
||||||
|
resolveFirstPromptStarted = resolve
|
||||||
})
|
})
|
||||||
|
const secondPromptStarted = new Promise<void>((resolve) => {
|
||||||
|
resolveSecondPromptStarted = resolve
|
||||||
|
})
|
||||||
|
const customClient = {
|
||||||
|
session: {
|
||||||
|
create: async (_args?: unknown) => ({ data: { id: `ses_${crypto.randomUUID()}` } }),
|
||||||
|
get: async () => ({ data: { directory: "/test/dir" } }),
|
||||||
|
prompt: async () => ({}),
|
||||||
|
promptAsync: async (args: { path: { id: string }; body: Record<string, unknown> }) => {
|
||||||
|
promptBodies.push(args.body)
|
||||||
|
if (promptBodies.length === 1) {
|
||||||
|
resolveFirstPromptStarted?.()
|
||||||
|
}
|
||||||
|
if (promptBodies.length === 2) {
|
||||||
|
resolveSecondPromptStarted?.()
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
messages: async () => ({ data: [] }),
|
||||||
|
todo: async () => ({ data: [] }),
|
||||||
|
status: async () => ({ data: {} }),
|
||||||
|
abort: async () => ({}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
manager.shutdown()
|
||||||
|
manager = new BackgroundManager({ client: customClient, directory: tmpdir() } as unknown as PluginInput)
|
||||||
|
|
||||||
|
const launchInputWithModel = {
|
||||||
|
description: "Test task with model",
|
||||||
|
prompt: "Do something",
|
||||||
|
agent: "test-agent",
|
||||||
|
parentSessionID: "parent-session",
|
||||||
|
parentMessageID: "parent-message",
|
||||||
|
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||||
|
}
|
||||||
|
const launchInputWithoutModel = {
|
||||||
|
description: "Test task without model",
|
||||||
|
prompt: "Do something else",
|
||||||
|
agent: "test-agent",
|
||||||
|
parentSessionID: "parent-session",
|
||||||
|
parentMessageID: "parent-message",
|
||||||
|
}
|
||||||
|
|
||||||
|
// when
|
||||||
|
const taskWithModel = await manager.launch(launchInputWithModel)
|
||||||
|
await firstPromptStarted
|
||||||
|
const taskWithoutModel = await manager.launch(launchInputWithoutModel)
|
||||||
|
await secondPromptStarted
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(taskWithModel.status).toBe("pending")
|
||||||
|
expect(taskWithoutModel.status).toBe("pending")
|
||||||
|
expect(promptBodies).toHaveLength(2)
|
||||||
|
expect(promptBodies[0].model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-6" })
|
||||||
|
expect("agent" in promptBodies[0]).toBe(false)
|
||||||
|
expect(promptBodies[1].agent).toBe("test-agent")
|
||||||
|
expect("model" in promptBodies[1]).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
test("should queue multiple tasks without blocking", async () => {
|
test("should queue multiple tasks without blocking", async () => {
|
||||||
// given
|
// given
|
||||||
|
|||||||
@@ -515,7 +515,9 @@ export class BackgroundManager {
|
|||||||
promptWithModelSuggestionRetry(this.client, {
|
promptWithModelSuggestionRetry(this.client, {
|
||||||
path: { id: sessionID },
|
path: { id: sessionID },
|
||||||
body: {
|
body: {
|
||||||
agent: input.agent,
|
// When a model is explicitly provided, omit the agent name so opencode's
|
||||||
|
// built-in agent fallback chain does not override the user-specified model.
|
||||||
|
...(launchModel ? {} : { agent: input.agent }),
|
||||||
...(launchModel ? { model: launchModel } : {}),
|
...(launchModel ? { model: launchModel } : {}),
|
||||||
...(launchVariant ? { variant: launchVariant } : {}),
|
...(launchVariant ? { variant: launchVariant } : {}),
|
||||||
system: input.skillContent,
|
system: input.skillContent,
|
||||||
@@ -792,7 +794,9 @@ export class BackgroundManager {
|
|||||||
this.client.session.promptAsync({
|
this.client.session.promptAsync({
|
||||||
path: { id: existingTask.sessionID },
|
path: { id: existingTask.sessionID },
|
||||||
body: {
|
body: {
|
||||||
agent: existingTask.agent,
|
// When a model is explicitly provided, omit the agent name so opencode's
|
||||||
|
// built-in agent fallback chain does not override the user-specified model.
|
||||||
|
...(resumeModel ? {} : { agent: existingTask.agent }),
|
||||||
...(resumeModel ? { model: resumeModel } : {}),
|
...(resumeModel ? { model: resumeModel } : {}),
|
||||||
...(resumeVariant ? { variant: resumeVariant } : {}),
|
...(resumeVariant ? { variant: resumeVariant } : {}),
|
||||||
tools: (() => {
|
tools: (() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user