From 29069b08f74ca38b126ba8885036abce6bc53aa7 Mon Sep 17 00:00:00 2001 From: Simon Klee Date: Mon, 20 Apr 2026 12:33:20 +0200 Subject: [PATCH] tighten question fmt --- .../src/cli/cmd/run/scrollback.writer.tsx | 6 +- packages/opencode/src/cli/cmd/run/tool.ts | 7 +- .../test/cli/run/scrollback.surface.test.ts | 110 ++++++++++++++++++ 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/packages/opencode/src/cli/cmd/run/scrollback.writer.tsx b/packages/opencode/src/cli/cmd/run/scrollback.writer.tsx index bc14c37d8b..2de41c3294 100644 --- a/packages/opencode/src/cli/cmd/run/scrollback.writer.tsx +++ b/packages/opencode/src/cli/cmd/run/scrollback.writer.tsx @@ -278,9 +278,9 @@ export function RunEntryContent(props: { # Questions - - {snap.items.map((item) => ( - + + {snap.items.map((item) => ( + {item.question} diff --git a/packages/opencode/src/cli/cmd/run/tool.ts b/packages/opencode/src/cli/cmd/run/tool.ts index d8258f4785..1467120c60 100644 --- a/packages/opencode/src/cli/cmd/run/tool.ts +++ b/packages/opencode/src/cli/cmd/run/tool.ts @@ -630,7 +630,7 @@ function snapQuestion(p: ToolProps): ToolSnapshot { return { kind: "question", items, - tail: done("questions", span(p.frame.state)), + tail: "", } } @@ -831,9 +831,8 @@ function scrollTodoFinal(p: ToolProps): string { return `${done("todos", span(p.frame.state))} · ${tail.join(" · ")}` } -function scrollQuestionStart(p: ToolProps): string { - const total = list(p.frame.input.questions).length - return `→ Asked ${total} question${total === 1 ? "" : "s"}` +function scrollQuestionStart(_: ToolProps): string { + return "" } function scrollQuestionFinal(p: ToolProps): string { diff --git a/packages/opencode/test/cli/run/scrollback.surface.test.ts b/packages/opencode/test/cli/run/scrollback.surface.test.ts index 094af15ac3..0c5b4f1f78 100644 --- a/packages/opencode/test/cli/run/scrollback.surface.test.ts +++ b/packages/opencode/test/cli/run/scrollback.surface.test.ts @@ -546,6 +546,116 @@ test("renders todos without redundant start or footer lines", async () => { } }) +test("renders questions without redundant start or footer lines", async () => { + const out = await createTestRenderer({ + width: 80, + screenMode: "split-footer", + footerHeight: 6, + externalOutputMode: "capture-stdout", + consoleMode: "disabled", + }) + active.push(out.renderer) + + const scrollback = new RunScrollbackStream(out.renderer, RUN_THEME_FALLBACK, { + wrote: false, + }) + + await scrollback.append({ + kind: "tool", + text: "", + phase: "start", + source: "tool", + partID: "question-1", + messageID: "msg-1", + tool: "question", + toolState: "running", + part: { + id: "question-1", + sessionID: "session-1", + messageID: "msg-1", + type: "tool", + callID: "call-1", + tool: "question", + state: { + status: "running", + input: { + questions: [ + { + question: "What should I work on in the codebase next?", + header: "Next work", + options: [{ label: "bug", description: "Bug fix" }], + multiple: false, + }, + ], + }, + time: { + start: 1, + }, + }, + } as never, + }) + + expect(claimCommits(out.renderer)).toHaveLength(0) + + await scrollback.append({ + kind: "tool", + text: "", + phase: "final", + source: "tool", + partID: "question-1", + messageID: "msg-1", + tool: "question", + toolState: "completed", + part: { + id: "question-1", + sessionID: "session-1", + messageID: "msg-1", + type: "tool", + callID: "call-1", + tool: "question", + state: { + status: "completed", + input: { + questions: [ + { + question: "What should I work on in the codebase next?", + header: "Next work", + options: [{ label: "bug", description: "Bug fix" }], + multiple: false, + }, + ], + }, + metadata: { + answers: [["Bug fix"]], + }, + time: { + start: 1, + end: 2100, + }, + }, + } as never, + }) + + const commits = claimCommits(out.renderer) + try { + expect(commits).toHaveLength(1) + const raw = decoder.decode(commits[0]!.snapshot.getRealCharBytes(true)) + const rows = Array.from({ length: commits[0]!.snapshot.height }, (_, index) => + raw.slice(index * 80, (index + 1) * 80).trimEnd(), + ) + const rendered = rows.join("\n") + expect(rendered).toContain("# Questions") + expect(rendered).toContain("What should I work on in the codebase next?") + expect(rendered).toContain("Bug fix") + expect(rendered).not.toContain("Asked") + expect(rendered).not.toContain("questions completed") + expect(rows).toContain("What should I work on in the codebase next?") + expect(rows).toContain("Bug fix") + } finally { + destroyCommits(commits) + } +}) + test("bodyless starts keep the previous rendered item as separator context", async () => { const out = await createTestRenderer({ width: 80,