Repository navigation
Description
Symptom
The AskUserQuestion option-picker card only ever appears on the claude provider. On grok and kimi the agent asks and the run continues without ever showing the user anything.
Measured root cause (live CLIs, 2026-08-21)
grok has a native ask_user_question tool and does call it — but in headless -p the CLI answers it itself:
tool_result: {"type":"AskUserQuestion","UserAnswered":{"message":
"No user is available to answer questions in this non-interactive session.
Continue with your best judgment; do not wait for clarification."}}
grok -p has no permission/answer channel (no --permission-prompt-tool, no stream-json stdin), same structural cause as #549 / #578. Solenta never sees a prompt. The tool_use block is visible in --output-format streaming-messages-json.
kimi in -p runs in auto mode, which forbids its question tool outright:
"I can't do that right now — auto permission mode is active, and it explicitly forbids me from calling the question tool while it's enabled."
-p cannot be combined with -y/--auto (providers.js already notes this), so there is no flag that re-enables it.
claude is fine and stays untouched: verified live that --model claude-fable-5 under both default and bypassPermissions sends
control_request {"subtype":"can_use_tool","tool_name":"AskUserQuestion","requires_user_interaction":true}.
Two fable threads in the live store (ae6fce5d, a7b7ae47) have answered question cards. No fable-specific defect exists.
Why not a blocking MCP tool
First plan was an ask_user tool on coder-threads that blocks until answered. Two measurements killed the blocking part:
- grok hides every MCP tool behind a
search_tool/use_toolindirection (total_hidden_tools: 38in a live probe), so an MCP question tool is second-class there — the model has to go looking for it, while its native tool is right there. - A blocking tool holds an HTTP request open for however long the user takes, against MCP clients whose request timeout we do not control.
Design: ask -> card -> answer is the next turn
Non-blocking, one card, one answer path. The run ENDS after the question, so the pending question is persisted on the thread (pendingPermissions is ephemeral and dies with the run).
thread.pendingQuestion = { id, questions, askedAt }, normalized in store.js.- grok: runner parses the
ask_user_questiontool_use out of the claude-stream and sets it. - kimi / codex / opencode: new non-blocking
ask_usertool on coder-threads sets it and returns "asked; end your turn, the answer arrives as your next turn". - claude: unchanged. The blocking control_request path is strictly better; keep it.
- Renderer reuses the existing
QuestionPromptcard; answering starts a new run with the chosen labels (sessions resume, so context is kept).
Acceptance
- grok asking a question shows the option picker; clicking an option starts the next turn with that answer.
- kimi calls
ask_userand the same card appears. - claude behaviour is byte-identical to today.
Activity
currentbits commentedon Aug 22, 2026
Landed on main via 90b19c0 (worktree 'The questions modal does not pop up under fable, grok and kimi'): shared electron/questions.js normalizer feeding claude's AskUserQuestion, grok's native
ask_user_questiontool_use (electron/runner.js:2981), the coder-threadsask_userMCP tool and the store load-time heal.