feat(tui): add retry and failure debug frames

This commit is contained in:
Kit Langton
2026-06-01 15:03:34 -04:00
parent 360a49980e
commit 6f340cd701
3 changed files with 87 additions and 10 deletions
@@ -47,10 +47,35 @@ describe("TUI debug frames", () => {
expect(Object.values(status)).toEqual([{ type: "busy" }])
})
test("compiles retrying and failed subagent states", async () => {
const retrying = await createDebugFrameTransport({ file: fixture, frame: "retrying", directory: "/tmp/project" })
const retryTranscript = (await (
await retrying.fetch(`http://opencode.debug/session/${retrying.sessionID}/message`)
).json()) as Array<{ parts: Part[] }>
const retryTask = retryTranscript[1]!.parts.find(
(part): part is ToolPart => part.type === "tool" && part.tool === "task",
)!
const retryID = runningMetadata(retryTask).sessionId as string
const status = (await (await retrying.fetch("http://opencode.debug/session/status")).json()) as Record<
string,
{ type: string; attempt?: number }
>
const failed = await createDebugFrameTransport({ file: fixture, frame: "failed", directory: "/tmp/project" })
const failedTranscript = (await (
await failed.fetch(`http://opencode.debug/session/${failed.sessionID}/message`)
).json()) as Array<{ parts: Part[] }>
const failedTask = failedTranscript[1]!.parts.find(
(part): part is ToolPart => part.type === "tool" && part.tool === "task",
)!
expect(status[retryID]).toMatchObject({ type: "retry", attempt: 2 })
expect(failedTask.state.status).toBe("error")
})
test("reports available frames for unknown selection", async () => {
await expect(
createDebugFrameTransport({ file: fixture, frame: "missing", directory: "/tmp/project" }),
).rejects.toThrow("Available frames: running, active-background, completed")
).rejects.toThrow("Available frames: running, active-background, retrying, failed, completed")
})
test("rejects mutations against static debug frames", async () => {
@@ -66,3 +91,8 @@ function completedMetadata(part: ToolPart) {
if (part.state.status !== "completed") throw new Error("Expected completed task")
return part.state.metadata
}
function runningMetadata(part: ToolPart) {
if (part.state.status !== "running") throw new Error("Expected running task")
return part.state.metadata ?? {}
}