fix(tools/background-task): respect block=true even when full_session=true
Move blocking/polling logic before full_session branch so that
block=true waits for task completion regardless of output format.
🤖 Generated with assistance of oh-my-opencode
This commit is contained in:
parent
ebd26b7421
commit
e11c217d15
@ -77,36 +77,13 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client:
|
|||||||
storeToolMetadata(ctx.sessionID, callID, meta)
|
storeToolMetadata(ctx.sessionID, callID, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isActive = task.status === "pending" || task.status === "running"
|
|
||||||
const fullSession = args.full_session ?? true
|
|
||||||
const includeThinking = isActive || (args.include_thinking ?? false)
|
|
||||||
const includeToolResults = isActive || (args.include_tool_results ?? false)
|
|
||||||
|
|
||||||
if (fullSession) {
|
|
||||||
return await formatFullSession(task, client, {
|
|
||||||
includeThinking,
|
|
||||||
messageLimit: args.message_limit,
|
|
||||||
sinceMessageId: args.since_message_id,
|
|
||||||
includeToolResults,
|
|
||||||
thinkingMaxChars: args.thinking_max_chars,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const shouldBlock = args.block === true
|
const shouldBlock = args.block === true
|
||||||
const timeoutMs = Math.min(args.timeout ?? 60000, 600000)
|
const timeoutMs = Math.min(args.timeout ?? 60000, 600000)
|
||||||
|
const fullSession = args.full_session ?? true
|
||||||
|
|
||||||
if (task.status === "completed") {
|
let resolvedTask = task
|
||||||
return await formatTaskResult(task, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task.status === "error" || task.status === "cancelled" || task.status === "interrupt") {
|
|
||||||
return formatTaskStatus(task)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shouldBlock) {
|
|
||||||
return formatTaskStatus(task)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (shouldBlock && (task.status === "pending" || task.status === "running")) {
|
||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
while (Date.now() - startTime < timeoutMs) {
|
while (Date.now() - startTime < timeoutMs) {
|
||||||
await delay(1000)
|
await delay(1000)
|
||||||
@ -116,20 +93,41 @@ export function createBackgroundOutput(manager: BackgroundOutputManager, client:
|
|||||||
return `Task was deleted: ${args.task_id}`
|
return `Task was deleted: ${args.task_id}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTask.status === "completed") {
|
if (currentTask.status !== "pending" && currentTask.status !== "running") {
|
||||||
return await formatTaskResult(currentTask, client)
|
resolvedTask = currentTask
|
||||||
}
|
break
|
||||||
|
|
||||||
if (currentTask.status === "error" || currentTask.status === "cancelled" || currentTask.status === "interrupt") {
|
|
||||||
return formatTaskStatus(currentTask)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalTask = manager.getTask(args.task_id)
|
const finalCheck = manager.getTask(args.task_id)
|
||||||
if (!finalTask) {
|
if (finalCheck) {
|
||||||
return `Task was deleted: ${args.task_id}`
|
resolvedTask = finalCheck
|
||||||
}
|
}
|
||||||
return `Timeout exceeded (${timeoutMs}ms). Task still ${finalTask.status}.\n\n${formatTaskStatus(finalTask)}`
|
}
|
||||||
|
|
||||||
|
const isActive = resolvedTask.status === "pending" || resolvedTask.status === "running"
|
||||||
|
const includeThinking = isActive || (args.include_thinking ?? false)
|
||||||
|
const includeToolResults = isActive || (args.include_tool_results ?? false)
|
||||||
|
|
||||||
|
if (fullSession) {
|
||||||
|
return await formatFullSession(resolvedTask, client, {
|
||||||
|
includeThinking,
|
||||||
|
messageLimit: args.message_limit,
|
||||||
|
sinceMessageId: args.since_message_id,
|
||||||
|
includeToolResults,
|
||||||
|
thinkingMaxChars: args.thinking_max_chars,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolvedTask.status === "completed") {
|
||||||
|
return await formatTaskResult(resolvedTask, client)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resolvedTask.status === "error" || resolvedTask.status === "cancelled" || resolvedTask.status === "interrupt") {
|
||||||
|
return formatTaskStatus(resolvedTask)
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatTaskStatus(resolvedTask)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return `Error getting output: ${error instanceof Error ? error.message : String(error)}`
|
return `Error getting output: ${error instanceof Error ? error.message : String(error)}`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -339,6 +339,48 @@ describe("background_output full_session", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
describe("background_output blocking", () => {
|
||||||
|
test("block=true waits for task completion even with default full_session=true", async () => {
|
||||||
|
// #given a task that transitions running → completed after 2 polls
|
||||||
|
let pollCount = 0
|
||||||
|
const task = createTask({ status: "running" })
|
||||||
|
const manager: BackgroundOutputManager = {
|
||||||
|
getTask: (id: string) => {
|
||||||
|
if (id !== task.id) return undefined
|
||||||
|
pollCount++
|
||||||
|
if (pollCount >= 3) {
|
||||||
|
task.status = "completed"
|
||||||
|
}
|
||||||
|
return task
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const client = createMockClient({
|
||||||
|
"ses-1": [
|
||||||
|
{
|
||||||
|
id: "m1",
|
||||||
|
info: { role: "assistant", time: "2026-01-01T00:00:00Z" },
|
||||||
|
parts: [{ type: "text", text: "completed result" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
const tool = createBackgroundOutput(manager, client)
|
||||||
|
|
||||||
|
// #when block=true, full_session not specified (defaults to true)
|
||||||
|
const output = await tool.execute({
|
||||||
|
task_id: "task-1",
|
||||||
|
block: true,
|
||||||
|
timeout: 10000,
|
||||||
|
}, mockContext)
|
||||||
|
|
||||||
|
// #then should have waited and returned full session output
|
||||||
|
expect(task.status).toBe("completed")
|
||||||
|
expect(pollCount).toBeGreaterThanOrEqual(3)
|
||||||
|
expect(output).toContain("# Full Session Output")
|
||||||
|
expect(output).toContain("completed result")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("background_cancel", () => {
|
describe("background_cancel", () => {
|
||||||
test("cancels a running task via manager", async () => {
|
test("cancels a running task via manager", async () => {
|
||||||
// #given
|
// #given
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user