Skip to content

feat(expert): grouped clarifying questions UI + render robustness (#407)#7556

Open
andypalmi wants to merge 7 commits into
mainfrom
feat/407-expert-quick-replies
Open

feat(expert): grouped clarifying questions UI + render robustness (#407)#7556
andypalmi wants to merge 7 commits into
mainfrom
feat/407-expert-quick-replies

Conversation

@andypalmi

@andypalmi andypalmi commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Frontend for the Expert "ask before acting" clarifying-questions UX (FlowFuse/product#407), plus a couple of robustness fixes in the answer rendering.

Grouped clarifying questions: the Expert can ask 1-4 questions in a single turn, each rendered as its own option group (single- or multi-select), and all answers are collected before the turn is submitted. Answered questions can be edited and resubmitted; the card is disabled once a newer message arrives so a stale turn can't be answered. The options are built on the existing form components (ff-radio-group for single-select, ff-checkbox for multi-select) so they look and behave like the rest of the app.

Cadence control: a follow-up-questions setting in the composer menu (all at once vs one at a time), shipped to the agent via the expert context.

Composer auto-size: the chat input grows with its content (typed text, or an edited question loaded back in) using CSS field-sizing: content capped by a max-height, and only pins to a fixed height once the user drag-resizes it.

Resource card robustness: guarded the optional streamable chains in StandardResourceCard and FlowResourceCard that could throw on a null/malformed value and blank the whole message. They now degrade to "nothing to show" for that field instead, and the streaming list still advances.

Testing

npm run lint, npm run build and npm run test:unit:frontend (570 tests) all pass.

Manual: grouped questions render and collect answers; a single missing value renders as a single question; cadence setting persists; composer grows with loaded/edited content.

Relates to FlowFuse/product#407

@codecov

codecov Bot commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.47%. Comparing base (c12f0c5) to head (33ae0a1).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7556   +/-   ##
=======================================
  Coverage   76.47%   76.47%           
=======================================
  Files         413      413           
  Lines       21775    21775           
  Branches     5736     5736           
=======================================
  Hits        16652    16652           
  Misses       5123     5123           
Flag Coverage Δ
backend 76.47% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

andypalmi added 2 commits June 29, 2026 19:41
…crash

Add an ErrorBoundary and wrap each answer item in it, so a failure in one
section degrades only that section instead of blanking the whole message.
Also guard the optional streamable chain in StandardResourceCard that could
throw on a null value and take down the message.
)

The Expert can ask 1-4 clarifying questions in a single turn, each rendered as
its own single- or multi-select option card; all answers are collected before
the turn is submitted. Answered cards can be edited and resubmitted, and a card
from a past turn is disabled once a newer message arrives.

Adds a follow-up-questions cadence setting (all at once vs one at a time) in the
composer settings menu, shipped to the agent via the expert context.
@andypalmi andypalmi force-pushed the feat/407-expert-quick-replies branch from 7ee8af7 to 213b352 Compare June 29, 2026 17:42
@andypalmi andypalmi changed the title feat(expert): grouped clarifying questions UI + render robustness feat(expert): grouped clarifying questions UI + render robustness (#407) Jun 29, 2026
Comment thread frontend/src/components/expert/components/messages/components/ErrorBoundary.vue Outdated
Comment thread frontend/src/components/expert/components/ExpertChatInput.vue Outdated

@cstns cstns left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid observations

Comment thread frontend/src/components/expert/components/messages/components/ErrorBoundary.vue Outdated
Comment thread frontend/src/components/expert/components/ExpertChatInput.vue Outdated
- Guard the optional streamable chain in FlowResourceCard directly instead
  of relying on a render boundary to mask the throw. Reduce ErrorBoundary to
  a single last-resort backstop per answer item in AiMessage; drop the
  per-section boundary wrappers in AnswerWrapper.
- Rewrite QuestionsList on top of the existing ff-radio-group (single-select)
  and ff-checkbox (multi-select) components so options look like standard,
  clickable form controls and stay consistent with the rest of the app.
- Replace the imperative growComposerToContent DOM measuring with CSS
  field-sizing on the textarea; drop the manual reflows and the auto-grown
  flag. The composer auto-sizes to content and pins to an explicit height
  only after a drag-resize.
Per review: the local-catch pattern was the only one in the frontend; the
rest of the app leans on the global app.config.errorHandler. The real throws
are now guarded at their source (the optional streamable chains in the
resource cards), so the boundary was redundant. Remove it entirely and let
genuinely unexpected render errors surface through the global handler like
everywhere else.
@andypalmi

Copy link
Copy Markdown
Contributor Author

Thanks, all three addressed in the latest commits. @cstns @n-lark

Replace the composer kebab menu with a settings gear that opens an
ff-dialog. The follow-up-questions cadence control now lives in the
dialog as an ff-radio-group, with a FormHeading per section so the
panel can grow as more settings are added.
@andypalmi

Copy link
Copy Markdown
Contributor Author

I've also changed to modal to be a ff-dialog in preparation of the MCP Tool Permissions Views

I've:

Replaced the composer kebab menu with a settings gear that opens an ff-dialog. The follow-up-questions cadence control now lives in the dialog as an ff-radio-group, with a FormHeading per section so the panel can grow as more settings are added.

Screenshot 2026-06-30 at 15 08 40

@n-lark

n-lark commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Hey so while testing this - I am running into an issue where once I submit my answers, the chat just times out. This is on https://7556.flowfuse.dev/. I get no console errors. Example messages, I've been able to recreate this multiple times - https://gist.github.com/n-lark/87be54af4c32064ff7223190a8545056

Screenshot 2026-06-30 at 6 35 35 AM

@andypalmi

andypalmi commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@n-lark Unfortunately that's an issue with the Posthog feature flags to have the staging environment point to the dev agent and unrelated to this branch

EDIT: actually, let me look a bit more into this because I also got the AIMessage back but it did not render

handleMessageResponse lived in the composer's send handler, so a reply to a
query sent from the questions card was fetched but never rendered over HTTP
(without comms-beta the reply only renders via the MQTT push handler). Fold
the response handling into handleQuery so every entry point (composer and the
question/plan cards) renders the reply without re-implementing it.
@andypalmi

Copy link
Copy Markdown
Contributor Author

@n-lark this should now be fixed.

Root cause: rendering the reply lived in the composer's send handler, so a reply to a query submitted from the clarifying-questions card was fetched but never rendered when comms-beta (MQTT) is off and the chat falls back to HTTP. The response handling now lives in the shared handleQuery action, so every entry point (composer and the question/plan cards) renders the reply. It only surfaced where the MQTT push path is unavailable, which is why staging is hitting it right now.

I will test this myself once it lands in the staging environment, and you are welcome to give it another go too. Let me know if you still see it.

@andypalmi

Copy link
Copy Markdown
Contributor Author

@n-lark I can confirm it's working over HTTP now.

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.

3 participants