Skip to content

feat: add FlowTool, the tool-call card, and its message part - #44

Merged
divyanshub024 merged 3 commits into
mainfrom
dv/flutter-tool-widget-plan-5bad8e
Sep 7, 2026
Merged

feat: add FlowTool, the tool-call card, and its message part#44
divyanshub024 merged 3 commits into
mainfrom
dv/flutter-tool-widget-plan-5bad8e

Conversation

@divyanshub024

@divyanshub024 divyanshub024 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Summary

Adds FlowTool, roadmap item 17: the tool-call card.

  • One 16px mark carries the status, never words: a still muted asterisk while pending, the thinking indicator's turning asterisk beside a shimmering title while running, a check in success once complete, error_outline in error on failure. Nothing new to localize for status.
  • The header row holds the host's title (or the tool name in the code face), the primary argument as a chip, and a chevron at the trailing edge when there is a body. Input and output render as nested FlowCodeBlocks (json and plain by default, wrapping) under host-localized section labels, behind a widget-owned disclosure (initiallyExpanded + onExpandedChanged, the ExpansionTile contract). errorMessage renders under the header, outside the disclosure, as a live region.
  • FlowToolPart joins the sealed part model with FlowToolStatus { pending, running, complete, error }. FlowMessage renders it and keys the card by the provider's call id; FlowThread forwards toolInputLabel and toolOutputLabel. Copy reuses the existing onCodeCopy / copiedCodePart contract through synthesized FlowCodeParts, the markdown-fence precedent.
  • FlowToolStyle joins the component styles with a FlowTheme.toolStyle default. The four accents recolor the mark, never the words.
  • The chrome is the code block's flat card (surfaceContainerLowest, outline firming to outlineVariant on hover), not the confirmation's raised one: a tool call is a record of the runtime's work, the confirmation is the host's gate.
  • Docs page, playground stage (Live run / Complete / Running / Error / In a thread), README row, _redirects line, roadmap rows and changelog entry included.

Reviewer notes:

  • No Figma frame for this card yet. Metrics derive from the code block and confirmation specs (12 radius, 36 header, 16 mark, nested blocks at radius 8) and are flagged as provisional in the changelog and docs.
  • The disclosure state lives in the route's PageStorage, keyed through a PageStorageKey on the part's wrapper, because FlowThread remounts its subtree when a conversation first outgrows the viewport, which opening a card in a short thread triggers. It is stored under a private identifier built from the key chain rather than the framework's computed one: the blocks' SelectableText restores its scroll offset from the same chain and casts it to double?, which a bool there crashes. Found in the playground and fixed before this PR.
  • The body animates with ClipRect + Align(heightFactor:) on one controller shared with the chevron, since AnimatedSize drops the content on the first frame of a collapse.
  • Approval is not a tool state: a call that needs one is a FlowConfirmationPart beside the tool part.
  • Title and chip are both Flexible, so under pressure each gets at most half the row; a priority layout is a possible follow-up. A host-rendered output slot and grouping consecutive calls are out of scope.

Screenshots

New component, so no before column.

Complete, light Complete, dark Running Error In a thread

How this was verified

  • Playground tool stage in Chrome (web-server build): all five variants, light and dark. Expanding a card inside the 420px thread stays open across the viewport flip, collapses without a bounce, and the two cards keep independent state. Copy shows the check on the right block, the running mark turns, and the phone stage ellipsizes the title and chip.
  • Headless screenshots of the embeds (?embed=tool&variant=...&theme=...).
  • flutter analyze clean at the root and in playground/; example/ reports only its pre-existing missing env.g.dart. dart format . applied.
  • Not exercised: reduced motion and keyboard toggling. Both use the same guards as the thinking indicator and the code block.

Checklist

  • flutter analyze lib and flutter analyze in example/ and playground/ are clean
  • dart format . applied
  • Exercised in the playground — with a stage demo added or updated if this is a new component or variant
  • No new entries under dependencies: in pubspec.yaml (Flutter SDK and flutter.dev packages only)
  • Nothing model-facing — no prompts, schemas, or provider/network calls
  • New public API is exported from lib/flow_ui.dart and documented in docs/ and the README table
  • CHANGELOG.md updated for user-facing changes, with breaking changes called out
  • PR title follows conventional commits (feat:, fix:, refactor:, docs:, chore:)

Note

Medium Risk
Expands the sealed FlowMessagePart API (hosts with exhaustive switches must add a case) and changes message part layout/keying for tool cards; behavior is presentation-only with no auth or network logic.

Overview
Ships FlowTool, the tool-call card for agent turns, and wires it through the message model and thread.

The card is host-driven state only: FlowToolStatus (pendingrunningcomplete / error) drives a morphing header mark (still vs turning asterisk, check, error glyph) and optional title shimmer—no built-in status strings. Input and output show as nested, wrapping **FlowCodeBlock**s behind a collapsible header; failures surface via errorMessage outside the disclosure (live region). Copy reuses the existing onCodeCopy / copiedCodePart path via synthesized FlowCodePart instances.

FlowToolPart joins the sealed FlowMessagePart set; FlowMessage renders it and keys wrappers with PageStorageKey(part.id) so expand/collapse survives streaming reshapes and thread viewport remounts (disclosure stored in PageStorage with a private id to avoid colliding with code-block scroll state). FlowThread forwards toolInputLabel and toolOutputLabel. Theming adds FlowToolStyle and FlowTheme.toolStyle.

Also updates 0.4.0 changelog, roadmap/docs/README, a tool docs page and playground demo (live / complete / running / error / thread), and /playground/tool redirect.

Reviewed by Cursor Bugbot for commit c630d35. Bugbot is set up for automated code reviews on this repo. Configure here.

…t-plan-5bad8e

# Conflicts:
#	CHANGELOG.md
#	README.md
#	docs/public/_redirects
#	docs/src/content/docs/theming.mdx
#	lib/flow_ui.dart
#	lib/src/theme/flow_theme.dart
#	playground/lib/src/demo_registry.dart
#	playground/lib/src/playground_item.dart

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 94c026c. Configure here.

Comment thread lib/src/widgets/flow_tool.dart
Comment thread lib/src/widgets/flow_tool.dart
@divyanshub024
divyanshub024 merged commit 1cd15b1 into main Sep 7, 2026
5 checks passed
@divyanshub024
divyanshub024 deleted the dv/flutter-tool-widget-plan-5bad8e branch September 7, 2026 18:55
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