You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
v2: add optimistic UI while MCP prompt commands resolve #34860
V2 slash commands backed by MCP prompts can take noticeable time to resolve because command submission must call the MCP server's prompt resolution path before the prompt is admitted to the session.
Today there is no optimistic/pending UI for that resolution phase. If an MCP prompt command is slow, the submit experience can look like the prompt input is stalled or in an odd intermediate state before the resolved prompt appears in the session.
Expected behavior
After submitting an MCP prompt slash command, the TUI should immediately show an explicit pending/submitted command state while the server resolves the MCP prompt. The user should not be left looking at an apparently idle or stuck prompt input during that wait.
Reproduction aid
Temporarily add an artificial delay before MCP prompt evaluation:
Then submit an MCP prompt slash command with arguments. The UI should make the command resolution phase obvious and non-confusing during the artificial delay.
I’d like to take this on. I’ve traced the current TUI submission path and plan to add a small pending/resolving state that appears immediately after an MCP-backed slash command is submitted, clears when resolution completes or fails, and is covered by a delayed-resolution regression test. Does that interaction and scope match what you had in mind?
Thanks for the detailed report. I reproduced this on v2.2.0 and on the latest dev (f43563b).
Setup: a small local stdio MCP server, slow, offering one prompt, greet. It waits 4 seconds before answering a prompt request, which stands in for the artificial delay in the issue.
Steps: submit /slow:greet world in the TUI.
Result: the TUI switches to a blank "New session" view with an empty composer for the whole 4 seconds. There's no user row and no busy or interrupt indicator. Then the resolved prompt ("Say hello to world") appears and the model replies. The recording and screenshots below show this, and the script below reproduces it with opencode-drive.
Likely cause: in packages/tui/src/component/prompt/index.tsx, the slash-command branch of submit sends session.command without calling move.startSubmit() and without the optimistic admission that plain prompts get via data.session.prompt. So nothing is rendered until the server has resolved the MCP prompt and admitted the result.
Reproduction script (drive.ts)
// Repro for #34860: no pending UI while an MCP prompt slash command resolves.// A local stdio MCP server (slow-mcp.mjs, next to this script) delays prompts/get by 4s.import{Effect,Stream}from"effect"import{Llm,OpenCodeDriver}from"opencode-drive"constserver=`import { createInterface } from "node:readline"const send = (m) => process.stdout.write(JSON.stringify(m) + "\\n")createInterface({ input: process.stdin }).on("line", (line) => { if (!line.trim()) return const msg = JSON.parse(line) if (msg.id === undefined) return const ok = (result) => send({ jsonrpc: "2.0", id: msg.id, result }) if (msg.method === "initialize") return ok({ protocolVersion: msg.params?.protocolVersion ?? "2025-06-18", capabilities: { prompts: {} }, serverInfo: { name: "slow", version: "1.0.0" } }) if (msg.method === "prompts/list") return ok({ prompts: [{ name: "greet", description: "Slow greeting prompt", arguments: [{ name: "who", required: true }] }] }) if (msg.method === "prompts/get") return setTimeout(() => ok({ messages: [{ role: "user", content: { type: "text", text: "Say hello to " + msg.params?.arguments?.who } }] }), 4000) send({ jsonrpc: "2.0", id: msg.id, error: { code: -32601, message: "Method not found" } })})`exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true,keypressOverlay: true},project: {git: true,files: {"slow-mcp.mjs": server}},config: {mcp: {servers: {slow: {type: "local",command: ["bun","slow-mcp.mjs"]}}}}asany,},({ ui, llm })=>Effect.gen(function*(){yield*llm.serve(()=>Stream.make(Llm.text("Hello, world!")))yield*Effect.sleep(3000)// let the MCP server connectyield*ui.type("/slow:greet world")yield*Effect.sleep(500)yield*ui.screenshot("01-typed")yield*ui.enter()yield*Effect.sleep(300)yield*ui.screenshot("02-after-submit-300ms")yield*Effect.sleep(1500)yield*ui.screenshot("03-after-submit-1800ms")yield*Effect.sleep(1500)yield*ui.screenshot("04-after-submit-3300ms")yield*ui.waitFor("Say hello to world")yield*ui.waitFor("Hello, world!")yield*ui.screenshot("05-resolved")}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Activity
zanemo109 commentedon Aug 2, 2026
I’d like to take this on. I’ve traced the current TUI submission path and plan to add a small pending/resolving state that appears immediately after an MCP-backed slash command is submitted, clears when resolution completes or fails, and is covered by a delayed-resolution regression test. Does that interaction and scope match what you had in mind?
opencodejr commentedon Oct 29, 2026
Thanks for the detailed report. I reproduced this on v2.2.0 and on the latest
dev(f43563b).Setup: a small local stdio MCP server,
slow, offering one prompt,greet. It waits 4 seconds before answering a prompt request, which stands in for the artificial delay in the issue.Steps: submit
/slow:greet worldin the TUI.Result: the TUI switches to a blank "New session" view with an empty composer for the whole 4 seconds. There's no user row and no busy or interrupt indicator. Then the resolved prompt ("Say hello to world") appears and the model replies. The recording and screenshots below show this, and the script below reproduces it with opencode-drive.
Likely cause: in
packages/tui/src/component/prompt/index.tsx, the slash-command branch of submit sendssession.commandwithout callingmove.startSubmit()and without the optimistic admission that plain prompts get viadata.session.prompt. So nothing is rendered until the server has resolved the MCP prompt and admitted the result.Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.