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
When an agent pauses to ask the user a structured question (currently implemented for Claude's AskUserQuestion tool via the user_input_requested event), the UI renders a single question at a time inside UserInputRequestedBlock in client/src/pages/SessionView.tsx (around line 1855). After the user answers, a separate user_input_response message is appended to the transcript.
Problems with the current UI
One question at a time + "1 / 3" pagination. Multi-question requests (e.g. Claude's AskUserQuestion with multiSelect: true or 2–4 questions in one batch) force the user to click Next/Back through each question. The questions are typically independent and short enough to answer in one view.
Generic "user_input_response" message. When the user submits, a follow-up transcript entry with the raw label user_input_response is appended. It's redundant (the user's selections are already implied by what happens next) and the literal label is confusing — looks like a system token, not the user's answer.
Provider portability is unclear. This was originally wired up for Claude. Codex and Ada may emit the same kind of structured-input events with different shapes (or not at all yet), and the current single-question-at-a-time rendering plus the user_input_response tail message are Claude-specific assumptions we shouldn't carry into other providers.
Proposed solution
Collapse all questions into one scrollable dialog.
Render every question in UserInputRequestedBlock together, each with its header label, question text, and option list.
Drop the activeQuestionIndex state and the 1 / N counter. Keep the Back button only if it's still meaningful (it likely isn't once questions are not paginated — remove it).
The single Continue button submits when every question has a non-empty answer (the existing allAnswered check is already there, just use it as the only gate).
Plan-approval mode (claude_exit_plan_mode / header.toLowerCase().includes("plan")) should keep its own treatment — keep the textarea there but render it inline with its question rather than as a paginated step.
Use a real, human label for the response.
Replace the user_input_response follow-up transcript entry with a label that reads as the user's choice. Default suggestion: Answered agent request (matches the existing submit button copy and the screenshot).
If the question has a clear short summary (e.g. the first option the user picked, or a generated "answered N questions"), use that instead of the generic label.
The label should be derived at submit time, not stored on the event, so we don't have to migrate existing transcript history.
Stop appending the redundant trailing message.
Once fix: persist active session across reloads and allow all vite hosts #2 lands, the trailing user_input_response entry becomes noise. Remove it from the message list in the render path that handles user_input_response events (SessionView.tsx line ~1019–1028 already filters these out for the pending-request detection — extend that filter or collapse the message rendering for the response event itself).
If we keep any visible artifact of the answer, render it as part of the question block (e.g. a small "Your answer: Yes, rename to anita" footnote under each question once submitted), not as a separate transcript entry.
Provider-portability audit.
While making the change, verify the rendering for Codex and Ada's equivalent question events. If they don't emit a structured-question event, this UI simply doesn't render for them today and that's fine — call it out in the PR.
If they do emit something similar but with a different shape, abstract the question list shape so UserInputRequestedBlock only depends on { id, header, question, options } (which is already the shape of UserInputQuestion in client/src/api.ts).
Acceptance criteria
UserInputRequestedBlock renders every question in a multi-question request in a single view, with no Next/Back pagination.
The "1 / N" counter is removed.
The single submit button is disabled until every question has an answer, and uses the existing allAnswered check.
On submit, the transcript no longer shows a separate user_input_response message; the answer is represented inline with each question (or simply omitted if the questions remain in the transcript with the user's choice marked).
Plan-approval (claude_exit_plan_mode) still works and keeps its own textarea, just no longer paginated.
Verified for Claude; documented whether Codex and Ada need additional work to surface their equivalent events.
Existing tests pass; add coverage for: multi-question rendering shows all questions, submit disabled until all answered, user_input_response is filtered out of the transcript.
Files of interest
client/src/pages/SessionView.tsx — UserInputRequestedBlock (around line 1855), the pending-request selectors at line ~1019 and ~1347, and the message-render path that handles user_input_response.
client/src/api.ts — UserInputQuestion type (line 133) and the submit/dismiss helpers around line 535 / 603.
Server side: server/lib/agents/ (or equivalent) — only relevant if Codex/Ada adapters need a parallel event shape.
Out of scope
Changing the question schema or how questions are sent back to the agent.
Redesigning the agent-side AskUserQuestion equivalents.
Mobile layout (a follow-up issue is fine if the desktop fix needs desktop-only treatment).
Context
When an agent pauses to ask the user a structured question (currently implemented for Claude's
AskUserQuestiontool via theuser_input_requestedevent), the UI renders a single question at a time insideUserInputRequestedBlockinclient/src/pages/SessionView.tsx(around line 1855). After the user answers, a separateuser_input_responsemessage is appended to the transcript.Problems with the current UI
AskUserQuestionwithmultiSelect: trueor 2–4 questions in one batch) force the user to click Next/Back through each question. The questions are typically independent and short enough to answer in one view.user_input_responseis appended. It's redundant (the user's selections are already implied by what happens next) and the literal label is confusing — looks like a system token, not the user's answer.user_input_responsetail message are Claude-specific assumptions we shouldn't carry into other providers.Proposed solution
Collapse all questions into one scrollable dialog.
UserInputRequestedBlocktogether, each with itsheaderlabel,questiontext, and option list.activeQuestionIndexstate and the1 / Ncounter. Keep theBackbutton only if it's still meaningful (it likely isn't once questions are not paginated — remove it).Continuebutton submits when every question has a non-empty answer (the existingallAnsweredcheck is already there, just use it as the only gate).claude_exit_plan_mode/header.toLowerCase().includes("plan")) should keep its own treatment — keep the textarea there but render it inline with its question rather than as a paginated step.Use a real, human label for the response.
user_input_responsefollow-up transcript entry with a label that reads as the user's choice. Default suggestion:Answered agent request(matches the existing submit button copy and the screenshot).Stop appending the redundant trailing message.
user_input_responseentry becomes noise. Remove it from the message list in the render path that handlesuser_input_responseevents (SessionView.tsxline ~1019–1028 already filters these out for the pending-request detection — extend that filter or collapse the message rendering for the response event itself).Provider-portability audit.
UserInputRequestedBlockonly depends on{ id, header, question, options }(which is already the shape ofUserInputQuestioninclient/src/api.ts).Acceptance criteria
UserInputRequestedBlockrenders every question in a multi-question request in a single view, with no Next/Back pagination.allAnsweredcheck.user_input_responsemessage; the answer is represented inline with each question (or simply omitted if the questions remain in the transcript with the user's choice marked).claude_exit_plan_mode) still works and keeps its own textarea, just no longer paginated.user_input_responseis filtered out of the transcript.Files of interest
client/src/pages/SessionView.tsx—UserInputRequestedBlock(around line 1855), the pending-request selectors at line ~1019 and ~1347, and the message-render path that handlesuser_input_response.client/src/api.ts—UserInputQuestiontype (line 133) and the submit/dismiss helpers around line 535 / 603.server/lib/agents/(or equivalent) — only relevant if Codex/Ada adapters need a parallel event shape.Out of scope
AskUserQuestionequivalents.