69 lines
3.0 KiB
TypeScript
69 lines
3.0 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { fileURLToPath } from "node:url"
|
|
import type { Message, Part, ToolPart } from "@opencode-ai/sdk/v2"
|
|
import { createDebugFrameTransport } from "../../../src/cli/cmd/tui/debug/frame"
|
|
|
|
const fixture = fileURLToPath(
|
|
new URL("../../../src/cli/cmd/tui/debug/fixtures/subagent-lifecycle.json", import.meta.url),
|
|
)
|
|
|
|
describe("TUI debug frames", () => {
|
|
test("compiles completed direct and child-tool subagents into distinct sessions", async () => {
|
|
const transport = await createDebugFrameTransport({ file: fixture, frame: "completed", directory: "/tmp/project" })
|
|
const transcript = (await (
|
|
await transport.fetch(`http://opencode.debug/session/${transport.sessionID}/message`)
|
|
).json()) as Array<{ info: Message; parts: Part[] }>
|
|
const tasks = transcript[1]!.parts.filter((part): part is ToolPart => part.type === "tool" && part.tool === "task")
|
|
const directID = completedMetadata(tasks[1]!).sessionId as string
|
|
const readID = completedMetadata(tasks[2]!).sessionId as string
|
|
const direct = (await (
|
|
await transport.fetch(`http://opencode.debug/session/${directID}/message`)
|
|
).json()) as Array<{ info: Message; parts: Part[] }>
|
|
const read = (await (await transport.fetch(`http://opencode.debug/session/${readID}/message`)).json()) as Array<{
|
|
info: Message
|
|
parts: Part[]
|
|
}>
|
|
|
|
expect(directID).not.toBe(readID)
|
|
expect(direct[1]!.parts).toHaveLength(0)
|
|
expect(read[1]!.parts.filter((part) => part.type === "tool")).toHaveLength(1)
|
|
if (direct[1]!.info.role !== "assistant" || direct[1]!.info.time.completed === undefined) {
|
|
throw new Error("Expected completed child response")
|
|
}
|
|
expect(direct[1]!.info.time.completed - direct[0]!.info.time.created).toBe(501)
|
|
})
|
|
|
|
test("marks only active background children busy", async () => {
|
|
const transport = await createDebugFrameTransport({
|
|
file: fixture,
|
|
frame: "active-background",
|
|
directory: "/tmp/project",
|
|
})
|
|
const status = (await (await transport.fetch("http://opencode.debug/session/status")).json()) as Record<
|
|
string,
|
|
{ type: string }
|
|
>
|
|
|
|
expect(Object.values(status)).toEqual([{ type: "busy" }])
|
|
})
|
|
|
|
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")
|
|
})
|
|
|
|
test("rejects mutations against static debug frames", async () => {
|
|
const transport = await createDebugFrameTransport({ file: fixture, frame: "completed", directory: "/tmp/project" })
|
|
|
|
await expect(
|
|
transport.fetch(`http://opencode.debug/session/${transport.sessionID}/message`, { method: "POST" }),
|
|
).rejects.toThrow("Unexpected debug frame request: POST")
|
|
})
|
|
})
|
|
|
|
function completedMetadata(part: ToolPart) {
|
|
if (part.state.status !== "completed") throw new Error("Expected completed task")
|
|
return part.state.metadata
|
|
}
|