diff --git a/packages/opencode/src/cli/cmd/run/footer.question.tsx b/packages/opencode/src/cli/cmd/run/footer.question.tsx
index c48be37d41..5bea73a919 100644
--- a/packages/opencode/src/cli/cmd/run/footer.question.tsx
+++ b/packages/opencode/src/cli/cmd/run/footer.question.tsx
@@ -416,7 +416,7 @@ export function RunQuestionBody(props: {
- {hit() ? "✓" : ""}
+ {hit() ? " ✓" : ""}
@@ -466,7 +466,7 @@ export function RunQuestionBody(props: {
- {picked() ? "✓" : ""}
+ {picked() ? " ✓" : ""}
- {picked() ? "✓" : ""}
+ {picked() ? " ✓" : ""}
@@ -408,7 +408,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
- {customPicked() ? "✓" : ""}
+ {customPicked() ? " ✓" : ""}
diff --git a/packages/opencode/test/cli/run/footer.view.test.tsx b/packages/opencode/test/cli/run/footer.view.test.tsx
index 716554be49..697e64efc8 100644
--- a/packages/opencode/test/cli/run/footer.view.test.tsx
+++ b/packages/opencode/test/cli/run/footer.view.test.tsx
@@ -2,6 +2,7 @@
import { expect, test } from "bun:test"
import { testRender } from "@opentui/solid"
import { createSignal } from "solid-js"
+import type { QuestionRequest } from "@opencode-ai/sdk/v2"
import {
RUN_COMMAND_PANEL_ROWS,
RUN_SUBAGENT_PANEL_ROWS,
@@ -24,6 +25,7 @@ import type {
RunProvider,
StreamCommit,
} from "@/cli/cmd/run/types"
+import { RunQuestionBody } from "@/cli/cmd/run/footer.question"
function bindings(...keys: string[]) {
return keys.map((key) => ({ key }))
@@ -401,6 +403,53 @@ test("direct footer shows subagent indicator while prompt is running", async ()
}
})
+test("direct question body separates single-select checkmark from label", async () => {
+ const request = {
+ id: "question-1",
+ sessionID: "session-1",
+ questions: [
+ {
+ question: "Which categorical concept is often described as a universal way to combine two objects?",
+ header: "Universal Product",
+ options: [
+ { label: "Product", description: "A product comes with projections." },
+ { label: "Equalizer", description: "An equalizer selects morphisms where arrows agree." },
+ ],
+ },
+ ],
+ } satisfies QuestionRequest
+ const replies: unknown[] = []
+
+ const app = await testRender(
+ () => (
+
+ {
+ replies.push(input)
+ }}
+ onReject={() => {}}
+ />
+
+ ),
+ {
+ width: 100,
+ height: 12,
+ },
+ )
+
+ try {
+ app.mockInput.pressEnter()
+ await app.renderOnce()
+
+ expect(replies).toHaveLength(1)
+ expect(app.captureCharFrame()).toContain("Product ✓")
+ } finally {
+ app.renderer.destroy()
+ }
+})
+
test("direct model panel renders current model selector", async () => {
const [providers] = createSignal([provider()])
const [current] = createSignal({ providerID: "opencode", modelID: "gpt-5" })
diff --git a/packages/opencode/test/cli/run/stream.transport.test.ts b/packages/opencode/test/cli/run/stream.transport.test.ts
index d1b145db24..f01519fe7d 100644
--- a/packages/opencode/test/cli/run/stream.transport.test.ts
+++ b/packages/opencode/test/cli/run/stream.transport.test.ts
@@ -171,7 +171,7 @@ function globalSse(stream: GlobalEventStream) {
function wrapGlobalStream(stream: EventStream): GlobalEventStream {
return (async function* (): GlobalEventStream {
for await (const event of stream) {
- yield globalEvent(event)
+ yield globalEvent(event as GlobalEvent["payload"])
}
return StreamClosed
})()
@@ -339,11 +339,11 @@ function child(id: string): SessionChild {
}
}
-function globalEvent(payload: GlobalEvent["payload"]): GlobalEvent {
+function globalEvent(payload: SdkEvent | GlobalEvent["payload"]): GlobalEvent {
return {
directory: "/tmp",
project: "project-1",
- payload,
+ payload: payload as GlobalEvent["payload"],
}
}
diff --git a/packages/opencode/test/cli/tui/use-event.test.tsx b/packages/opencode/test/cli/tui/use-event.test.tsx
index d690cfd6ce..5889eaa7c4 100644
--- a/packages/opencode/test/cli/tui/use-event.test.tsx
+++ b/packages/opencode/test/cli/tui/use-event.test.tsx
@@ -1,7 +1,7 @@
/** @jsxImportSource @opentui/solid */
import { describe, expect, test } from "bun:test"
import { testRender } from "@opentui/solid"
-import type { Event, GlobalEvent } from "@opencode-ai/sdk/v2"
+import type { GlobalEvent } from "@opencode-ai/sdk/v2"
import { onMount } from "solid-js"
import { ProjectProvider, useProject } from "../../../src/cli/cmd/tui/context/project"
import { SDKProvider } from "../../../src/cli/cmd/tui/context/sdk"
@@ -17,7 +17,10 @@ async function wait(fn: () => boolean, timeout = 2000) {
}
}
-function event(payload: Event, input: { directory: string; project?: string; workspace?: string }): GlobalEvent {
+function event(
+ payload: GlobalEvent["payload"],
+ input: { directory: string; project?: string; workspace?: string },
+): GlobalEvent {
return {
directory: input.directory,
project: input.project,
@@ -26,7 +29,7 @@ function event(payload: Event, input: { directory: string; project?: string; wor
}
}
-function vcs(branch: string): Event {
+function vcs(branch: string): GlobalEvent["payload"] {
return {
id: `evt_vcs_${branch}`,
type: "vcs.branch.updated",
@@ -36,7 +39,7 @@ function vcs(branch: string): Event {
}
}
-function update(version: string): Event {
+function update(version: string): GlobalEvent["payload"] {
return {
id: `evt_update_${version}`,
type: "installation.update-available",
@@ -67,7 +70,7 @@ function createSource() {
async function mount() {
const source = createSource()
- const seen: Event[] = []
+ const seen: GlobalEvent["payload"][] = []
const workspaces: Array = []
const fetch = (async (input: RequestInfo | URL) => {
const url = new URL(input instanceof Request ? input.url : String(input))
@@ -102,7 +105,7 @@ async function mount() {
}
function Probe(props: {
- seen: Event[]
+ seen: GlobalEvent["payload"][]
workspaces: Array
onReady: (ctx: { project: ReturnType }) => void
}) {
@@ -111,7 +114,7 @@ function Probe(props: {
onMount(() => {
event.subscribe((evt, { workspace }) => {
- props.seen.push(evt)
+ props.seen.push(evt as GlobalEvent["payload"])
props.workspaces.push(workspace)
})
props.onReady({ project })