Answer the user in the language they spoke, and point with a moving cursor - #3
Conversation
…ursor
Two things the demo needed: it has to reply in the user's own language, and
the pill has to visibly guide rather than sit still.
## Multilingual
Language detection already reached TTS, but the TEXT stayed English. A Hindi
speaker heard English words requested as hi-IN, which Bulbul rejects outright:
400 "Text must contain at least one character from the allowed languages."
A rejected synthesis is indistinguishable from having nothing to say, so the
app just went quiet. Fixes, in the order the words travel:
- Spoken(text, language) pairs every string with the language it is actually
written in, so the mismatch is now unrepresentable.
- Language.reconcile() trusts the script over the claim before anything is
sent to Bulbul. The rule is presence, not majority, matching Bulbul's own:
if the claimed language's script appears at all, keep it. That is what makes
code-switching work - "amount यहाँ भरिए" stays hi-IN and the English word is
read naturally. A majority count gets this wrong, because Devanagari vowel
signs are combining marks rather than letters, so it scores 6 Latin to 5
Devanagari and calls it English.
- The planner now receives the detected language and the CURRENT step, and
returns instruction in that language plus a `language` code. The prompt rule
"if unclear, stay on the current step" was previously unfollowable - the
model was never told which step that was.
- The task DSL carries per-language wording, so the offline fallback is
multilingual too, and Phrases/PillLabels move the assistant's own words and
the pill's labels off English literals.
- TaskRepository.normalize() stripped with [^a-z0-9 ], which deletes every
Devanagari character. Saaras returns Hindi speech AS Devanagari, so utterance
matching scored zero on the primary demo language and silently matched
nothing. It now strips by character category.
Verified live against Sarvam, not assumed:
- scripts/smoke_languages.ps1 - all ten languages synthesise with speaker
`anand` and Saaras detects each one back correctly.
- scripts/planner_case.ps1 - the real prompt and tool spec return Devanagari
for Hindi, Tamil for Tamil, Bengali for Bengali, each correctly labelled.
## Moving cursor
HighlightView now flies a cursor along an arc to the target, trailing a comet
tail and a tether back to the pill, and the ring only blooms once it arrives so
the two read as cause and effect. The ring alone teleported between fields,
which read as a highlight appearing rather than as something guiding you.
## Stop
onStopTapped() silences speech, invalidates the in-flight turn, flies the
cursor home and clears the ring - while keeping the step position, so the next
mic tap resumes instead of restarting.
## Also
Speech moved to its own thread and now starts in parallel with bounds
resolution, so the visual never queues behind Bulbul's ~1.2s. The planner got a
hard 5s call timeout: the step engine answers instantly and for free, so
waiting longer than that is strictly worse than falling back.
Tested: assembleDebug and testDebugUnitTest green (56 tests, 39 new); installed
and exercised on a real device - cursor flight, ring, tether, Stop button and
the language chip all render, no crashes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Warning Review limit reached
Next review available in: 7 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (26)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Sorry @NITISH-R-G, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.



Two things the demo needed: reply in the user's own language, and make the pill visibly guide rather than sit still.
The multilingual break, and where it was
Language detection already reached TTS —
lastLanguagewas set from Saaras and passed to Bulbul. But the text stayed English. A Hindi speaker heard English words requested ashi-IN, which Bulbul rejects outright:A rejected synthesis is indistinguishable from the assistant having nothing to say, so the app just went quiet. Fixed in the order the words travel:
Spoken(text, language)Language.reconcile()SarvamPlannerinstructionin that language +languagecode outinstructioninstructions, so the offline path is multilingual tooPhrases/PillLabelsTaskRepository.normalize()[^a-z0-9 ]Two of those deserve detail:
reconcileuses presence, not majority — matching Bulbul's own rule. If the claimed language's script appears at all, keep the claim. That is what makes code-switching work:"amount यहाँ भरिए"stayshi-INand Bulbul reads the English word naturally. A majority count gets this wrong, because Devanagari vowel signs (ा,ि) are combining marks rather than letters — it scores 6 Latin to 5 Devanagari and calls it English. A unit test caught this.The utterance matcher was dead in Hindi.
[^a-z0-9 ]deletes every Devanagari character, and Saaras returns Hindi speech as Devanagari. So matching scored zero on the primary demo language and silently matched nothing — masked today only because there is one task and the fallback picks it anyway. It would have broken the moment task #2 landed in M3.Verified live, not assumed
scripts/smoke_languages.ps1— all ten languages synthesise with speakeranand, and Saaras detects each one back correctly.scripts/planner_case.ps1— the real prompt and tool spec, driven through curl:Moving cursor
HighlightViewnow flies a cursor along an arc to the target, trailing a comet tail and a tether back to the pill, and the ring blooms only once it arrives so the two read as cause and effect. The ring alone teleported between fields, which reads as a highlight appearing rather than as something guiding you. Confirmed on device.Stop
onStopTapped()silences speech, invalidates the in-flight turn, flies the cursor home and clears the ring — while keeping the step position, so the next mic tap resumes rather than restarts.Also
Speech moved to its own thread and starts in parallel with bounds resolution, so the visual never queues behind Bulbul's ~1.2 s. The planner got a hard 5 s call timeout — the step engine answers instantly and for free, so waiting longer is strictly worse than falling back.
What was tested
assembleDebug+testDebugUnitTest— 56 tests green (39 new)Still needs verification
PARKING_LOT.md.step: amount. Parked with the fix bucket named; worth doing before the demo if a judge is likely to try it.