github Fangyuan025/Chaty v2.1.6

5 hours ago

A click that lands

Driving a real lesson on a real site, question after question,
turned up a failure an agent cannot escape on its own: a click that
reports success without having reached anything. A control still
settling — a popover animating in, a scroll container snapping
back, a banner sitting on top — is somewhere else by the time the
event is sent, and the event lands on whatever now occupies that
spot. Told it worked, the model has no reason to try anything else,
and it clicks the same button until the turn dies. The target is
now armed before the click and asked afterwards whether it fired. A
miss names what is in the way, and a coordinate the hit test
rejects is never clicked at all.

A choice can also be clicked by the words that are actually on
screen. An answer in a list wears a badge the page adds — 1,
2), 3. — so the element carries "2 jolie" while the page reads
"jolie". Asking for what you can read fell through to a substring
match, where the panel wrapping every choice matched too, and won:
the click landed on the panel, well away from any option, and
nothing was selected. Among elements that match, the one carrying
the least text beyond what was asked for now wins — anything
wrapping a control always carries more — and a leading list badge
is ignored on both sides.

The element list says what state a control is in, too. A greyed-out
submit read exactly like a live one, and an answer already chosen
like an untouched one, so a model clicked a dead button over and
over and lost track of what it had picked.

A session that stops dying quietly

Several long-lived things in Chaty could die in a way nothing
noticed and nothing recovered from, leaving a restart as the only
way out. One browser_close used to end browsing for the rest of
the run: the closed browser's actor cleared the cached handle as it
exited, by which time the next browser had already been cached, so
it wiped its successor's. Navigation then reported success while
every read came back blank, because the read happened in a window
that had never been navigated anywhere.

A browser left open by a previous run — after a force quit, or a
crash — held the profile, and Chrome will not start a second
browser on one profile, so the launcher waited out its deadline for
a debugging port that was never coming. That window is now adopted
when it can be reached and asked to quit when it cannot.

Speech that stopped stayed stopped: the output context was replaced
only when it reported closed, and WebKit has another state that a
route change or the machine sleeping reaches. One panic inside a
query poisoned the conversation database's lock, and the app
quietly stopped reading and writing conversations. One panic inside
a synthesis did the same to voice.

Faster, and smoother to listen to

Every drain of the browser's event queue blocked on a read timeout
that was empty nearly every time, and the settle loop paid it on
every poll. Draining what has arrived instead, leaving as soon as
the page goes quiet, and gathering the page digest in one round
trip instead of three: on a real site a click went from 4.1s to
0.47s, a page read from 130ms to 8ms.

Spoken replies are stitched on the audio clock. Each clip used to
be built only after the previous one's end had made its way back to
the main thread — which, during a spoken reply, is streaming
tokens, rendering and driving IPC — so a whole event loop landed at
every sentence boundary, exactly where it is most audible.

Under it

The thinking menu ticks the rung the model will actually use: the
chosen rung is remembered per app while ladders differ in length,
so one picked on a four-rung model could be absent from the
three-rung one you switched to, and the engine was handed nothing
at all. Six engine load failures — the out-of-memory refusal among
them — now speak the reader's language instead of English. Bilibili
links work again: a browser user agent without the cookies a
browser carries is the fingerprint that endpoint screens for.
Finished background jobs stop accumulating for as long as the app
is open. And a model that addresses each span to a recipient no
longer flashes that recipient as answer text at the head of every
reply.

Two fixes that reached v2.1.5 as a rebuild are in here for anyone
who installed that version on release day: code mode lights the
thinking depth you chose again, and a multimodal MLX model arrives
with the processor configuration its vision needs.

Install

Platform File
Windows x64 Chaty_*_x64-setup.exe — per-user installer, no admin
macOS (Apple Silicon) Chaty_*_aarch64.dmg
Linux x64 (beta) Chaty_*_amd64.AppImagechmod +x and run. First Linux release — please report anything odd

⚠️ macOS first launch — "Apple could not verify…" / "damaged"

Chaty is ad-hoc signed but not notarized (no paid Apple Developer
account), so Gatekeeper flags it on first launch. The app is safe —
everything runs locally. Clear the download quarantine once, in Terminal:

xattr -dr com.apple.quarantine /Applications/Chaty.app

Then open Chaty normally. (Alternatively: try to open it once, then go to
System Settings → Privacy & Security → Open Anyway.)


Full Changelog: v2.1.5...v2.1.6

Don't miss a new Chaty release

NewReleases is sending notifications on new releases.