Skip to content

feat(tui): render forms and route question tool through form service#35189

Closed
rekram1-node wants to merge 21 commits into
v2from
form-tui
Closed

feat(tui): render forms and route question tool through form service#35189
rekram1-node wants to merge 21 commits into
v2from
form-tui

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

Integrates the V2 Form service into the TUI and migrates the question tool onto it. First client consumer of the form surface (#35094/#35099/#35106/#35115).

Core

  • QuestionTool now creates forms via Form.Service.ask instead of QuestionV2.ask. Each question maps positionally to a field (q0..qn): single-select questions become string fields with options + custom, multiple becomes multiselect. Tool input/output schemas and model-facing output are unchanged.
  • Dismissal keeps V1 semantics: a cancelled form dies with QuestionV2.RejectedError, which the runner already detects to halt the drain (verified live: esc → "Provider turn interrupted").
  • Plugin runtime exposes Form.Service (context + Location node dep).

TUI

  • Event-driven form store in data.tsx: subscribes form.created/form.replied/form.cancelled, keyed by owning session; refresh via sdk.api.form.list reconciles on session load (covers restarts). Forms owned by the temporary "global" MCP elicitation sentinel are stored under that key and surfaced in any active session view.
  • New FormPrompt (routes/session/form.tsx), styled after QuestionPrompt:
    • all field types: string with options (+ custom), free text, number/integer (locally validated, defaults prefilled), boolean, multiselect (+ custom)
    • when conditions evaluated live, mirroring core semantics — tabs appear/disappear as answers change
    • tab-per-field + review/confirm tab; single select-style field submits directly
    • url mode: shows title/message/link, enter opens browser, esc cancels
    • server-side validation errors (400 InvalidRequestError) render inline, e.g. "Expected email for form field: email"
  • Composer disabled while a form is pending, same as questions/permissions.

The existing QuestionPrompt path stays intact for compatibility; it no longer triggers from the built-in tool since the tool now emits forms.

Verified with termctrl (PNG evidence captured)

  • complex 5-field form: event-driven render, when-gated tab reveal, defaults, typed answer record ({pm:"bun", features:["ts"], strict:true, port:3000, name:"..."})
  • pending form re-render after TUI restart (refresh path)
  • url form render + cancel; global-sentinel form render + validation error + submit
  • question tool end-to-end: model ask → form UI → answers returned to model; esc dismissal halts the runner

Typechecks: core, tui, cli. Tests: tui 203 pass, core suite green apart from pre-existing watcher readiness flakes under full-suite load (pass in isolation on clean v2 and with this change).

@rekram1-node

Copy link
Copy Markdown
Collaborator Author

Updated for many-field forms (e.g. the everything server's 14-field kitchen-sink elicitation, which previously rendered an unbounded tab row with sentence-length labels):

  • Tab labels truncate at 24 chars; when the tab row still cannot fit the terminal width (measured reactively via useTerminalDimensions), the header switches to a compact stepper: Field 3 of 14 · 2/14 answered. Small forms keep the tab bar.
  • Review labels truncate at 40 chars so 14-field reviews stay one line per field.
  • Added explicit shift+tab bindings for backward navigation (a key: "tab" binding never receives shift+tab in this keymap; text fields commit their content before moving).
  • FormPrompt is now keyed by form identity in the session route, so switching between pending forms (e.g. a session form settling and revealing a queued global elicitation) resets prompt state instead of leaking tab/answer state.

Verified with termctrl against a reproduction of the everything elicitation: stepper render, backward nav, 14-field review, and session→global form handoff with fresh state.

@rekram1-node rekram1-node force-pushed the form-tui branch 2 times, most recently from 5a16cac to fde7080 Compare July 3, 2026 17:24
@rekram1-node

Copy link
Copy Markdown
Collaborator Author

Superseded by the smaller stacked PRs #35421, #35422, and #35423.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant