Merge pull request #4350 from Yeachan-Heo/omc-team/you-are-one-of-5-parallel-work/worker-3
fix: TUI subagent session entry stuck spinning + unclickable (#4252)
This commit is contained in:
@@ -94,6 +94,13 @@ export function createBackgroundTask(
|
||||
await delay(WAIT_FOR_SESSION_INTERVAL_MS)
|
||||
}
|
||||
|
||||
// Capture late-arriving sessionId between the wait-loop exit and
|
||||
// metadata publish so the OpenCode TUI subagent entry has a navigable
|
||||
// target (issue #4252).
|
||||
if (!sessionId) {
|
||||
sessionId = manager.getTask(task.id)?.sessionId
|
||||
}
|
||||
|
||||
const bgMeta = {
|
||||
title: args.description,
|
||||
metadata: {
|
||||
|
||||
@@ -160,6 +160,15 @@ export async function executeBackgroundTask(
|
||||
return `Task failed to start (status: ${updatedTask.status}).\n\nTask ID: ${task.id}`
|
||||
}
|
||||
|
||||
// Capture late-arriving sessionId from the race window between wait-loop
|
||||
// exit and metadata publish. Without this, a session that gets created
|
||||
// moments after the wait loop returns leaves metadata.sessionId undefined,
|
||||
// which makes the OpenCode TUI render the subagent entry as a perpetual
|
||||
// spinner with no clickable navigation target (issue #4252).
|
||||
if (!sessionId && updatedTask?.sessionId) {
|
||||
sessionId = updatedTask.sessionId
|
||||
}
|
||||
|
||||
if (sessionId) {
|
||||
registerBackgroundSessionContext({
|
||||
sessionId,
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
const { describe, test, expect } = require("bun:test")
|
||||
|
||||
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
||||
import type { ParentContext } from "./executor-types"
|
||||
import { unsafeTestValue } from "../../../test-support/unsafe-test-value"
|
||||
|
||||
const MODEL = { providerID: "anthropic", modelID: "claude-sonnet-4-6" }
|
||||
|
||||
function makeMockCtx(): ToolContextWithMetadata & { captured: any[] } {
|
||||
const captured: any[] = []
|
||||
return {
|
||||
sessionID: "ses_parent",
|
||||
messageID: "msg_parent",
|
||||
agent: "sisyphus",
|
||||
abort: new AbortController().signal,
|
||||
callID: "call_001",
|
||||
metadata: async (input: any) => { captured.push(input) },
|
||||
captured,
|
||||
}
|
||||
}
|
||||
|
||||
const parentContext: ParentContext = {
|
||||
sessionID: "ses_parent",
|
||||
messageID: "msg_parent",
|
||||
agent: "sisyphus",
|
||||
model: MODEL,
|
||||
}
|
||||
|
||||
describe("background-task late sessionId capture (issue #4252)", () => {
|
||||
test("#given launch returns no sessionId and getTask returns one #when publishing metadata #then sessionId is captured so TUI entry is clickable", async () => {
|
||||
const { executeBackgroundTask } = require("./background-task")
|
||||
const ctx = makeMockCtx()
|
||||
const args: DelegateTaskArgs = {
|
||||
description: "deferred task",
|
||||
prompt: "do it",
|
||||
load_skills: [],
|
||||
run_in_background: true,
|
||||
subagent_type: "explore",
|
||||
}
|
||||
|
||||
// launch returns a pending task with no sessionId; getTask returns the
|
||||
// same task with sessionId populated *after* the wait loop exits. This
|
||||
// simulates the race where the subagent session is created moments after
|
||||
// we stop polling, and is the exact condition that left the OpenCode TUI
|
||||
// session entry stuck spinning with no click target on v4.2.3.
|
||||
await executeBackgroundTask(args, ctx, unsafeTestValue({
|
||||
manager: {
|
||||
launch: async () => ({
|
||||
id: "bg_late",
|
||||
description: "deferred task",
|
||||
agent: "explore",
|
||||
status: "pending",
|
||||
}),
|
||||
getTask: () => ({
|
||||
id: "bg_late",
|
||||
description: "deferred task",
|
||||
agent: "explore",
|
||||
status: "running",
|
||||
sessionId: "ses_late",
|
||||
}),
|
||||
},
|
||||
}), parentContext, "explore", MODEL, undefined)
|
||||
|
||||
const meta = ctx.captured.find((m: any) => m.metadata?.sessionId)
|
||||
expect(meta).toBeDefined()
|
||||
expect(meta.metadata.sessionId).toBe("ses_late")
|
||||
expect(meta.metadata.taskId).toBe("ses_late")
|
||||
expect(meta.metadata.backgroundTaskId).toBe("bg_late")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user