Skip to content

fix: merge HeZeBang's fork fixes + accessibility/i18n audit items (#128) - #149

Merged
ananmouaz merged 4 commits into
mainfrom
fix/fork-merge-and-audit-easy-wins
Aug 24, 2026
Merged

ananmouaz merged 4 commits into
mainfrom
fix/fork-merge-and-audit-easy-wins

Conversation

@ananmouaz

Copy link
Copy Markdown
Owner

What

Two fixes cherry-picked from @HeZeBang's fork, plus the accessibility/i18n items from the 2026-07 audit that were still open.

From the fork (verified locally: flutter analyze clean, 59/59 client tests pass)

  • fix(client) — settle dangling tool calls before submit/regenerate/editMessage. A turn interrupted mid agent-loop (stop(), a maxSteps cutoff, or a transcript rehydrated from storage) leaves a ToolCallPart with no matching ToolResultPart; providers reject that history, so every later submit fails. The controller now inserts a synthesized error result immediately after each affected assistant message — in place, not appended, because the Anthropic mapper emits tool results as the following turn and an end-appended result would not repair a mid-history hole. Two tests cover it, including the buried-mid-history case.
  • fix(elements) — aiLightHaptic compiles on both upstream Flutter and the OHOS fork. The exhaustive TargetPlatform switch can't cover both enums at once (the fork adds TargetPlatform.ohos), so it's an iOS/Android allowlist now.

Only change made on top of the fork's commits: dart format (they were authored under a different formatter version and would have failed --set-exit-if-changed).

Accessibility & i18n (#128)

  • i18n — every string that bypassed AiLocalizations now goes through it: tool-call sections (toolArguments/toolResult/toolError), context meter (contextLabel), source expand/collapse (moreSources(int)/showLess), live-voice statuses, empty-state headline, inline-citation and model-selector semantics labels, attachment remove badge. AiChainOfThought.title, AiContextMeter.label, AiEmptyState.title and AiComposer.hintText are now String? and fall back to the localized value.
  • Touch targets — the attachment remove badge and AiBranch's arrows get 44px InkResponse targets (the badge reserves the room via padding: a hit area that merely overhung the Stack would be clipped by the ancestor's bounds check). AiModelSelector's trigger moves from GestureDetector to InkWell for focus traversal and keyboard activation.
  • Contrast — AiConfirmation derives the filled label color from the fill's brightness (white on the caution amber was ~2.2:1, AA needs 4.5:1) and uses minHeight + padding instead of a fixed 40px height, so labels don't clip at large text scales.
  • RTL — directional alignment for the streaming loader and the "New chat" label; directional padding/border for Markdown blockquotes.
  • demo — gallery section header was ~3:1 on white; darkened. Two affected screenshots regenerated.

Versions

  • flutter_ai_client 0.3.1
  • flutter_ai_elements 0.3.0 — minor, not patch: the four widget fields above widened to String?

Tests

New packages/flutter_ai_elements/test/a11y_i18n_test.dart (10 tests) covers the localization fallbacks and overrides, the 44px labelled remove badge, the caution-tone label color, text-scale growth, and the RTL directional widgets. Full suite: all packages pass (flutter analyze clean repo-wide).

Note on the audit issues

While scoping this I checked every open audit-labelled bug issue against the code. All of these are already fixed on main and can be closed: #109 #110 #111 #112 #113 #114 #115 #116 #117 #118 #119 #120 #121 #122 #123, plus every item in #131 except the "verify claude-opus-4-8 is still served" checkbox (needs a live API call).

Closes #128

🤖 Generated with Claude Code

HeZeBang and others added 4 commits August 21, 2026 21:42
A turn interrupted mid agent-loop (stop, replace, maxSteps, or a dirty
rehydrated transcript) leaves tool calls with no ToolResultPart.
Providers reject such a history — Anthropic 400s with 'tool_use ids
were found without tool_result blocks' — permanently breaking the
conversation. Before re-prompting, scan the transcript and insert a
synthesized error result message directly after each affected assistant
message (in place, since providers require the result in the
immediately-following turn).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The exhaustive TargetPlatform switch in aiLightHaptic can't satisfy
both SDKs — the OHOS fork adds TargetPlatform.ohos, upstream lacks it.
Use an iOS/Android allowlist if instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Localizes the strings that bypassed AiLocalizations, fixes sub-44px touch
targets, the caution-tone contrast failure, and the remaining RTL gaps.

- AiLocalizations gains toolArguments/toolResult/toolError, contextLabel,
  showLess/moreSources(int), removeAttachment, liveConnecting/liveListening/
  liveThinking/liveSpeaking, emptyStateTitle, citation(int) and
  selectModel(String). AiChainOfThought.title, AiContextMeter.label,
  AiEmptyState.title and AiComposer.hintText are now nullable and fall back to
  the localized value.
- The attachment remove badge and AiBranch's arrows get 44px InkResponse
  targets (the badge's padding reserves the room, since a hit area that only
  overhung the Stack would be clipped by the ancestor bounds check).
  AiModelSelector's trigger moves to InkWell for focus traversal.
- AiConfirmation derives the filled label color from the fill's brightness
  (white on the caution amber was ~2.2:1) and uses minHeight + padding instead
  of a fixed 40px height so labels survive large text scales.
- RTL: directional alignment for the streaming loader and the "New chat"
  label, directional padding/border for Markdown blockquotes.
- demo: darken the gallery section header (~3:1 on white) and refresh the two
  affected screenshots.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
client 0.3.1 — dangling tool calls are settled before submit/regenerate/edit.
elements 0.3.0 — OHOS compile fix plus the accessibility/i18n pass; minor
rather than patch because AiChainOfThought.title, AiContextMeter.label,
AiEmptyState.title and AiComposer.hintText widened to String?.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ananmouaz
ananmouaz merged commit c9b5e0d into main Aug 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants