Repository navigation
Windows & Linux: eight fixes from daily use, one commit each (idle CPU, the chat's picker and errors, a flaky test) - #365
Open
shakibbinkabir wants to merge 8 commits into
Open
shakibbinkabir wants to merge 8 commits into
shakibbinkabir wants to merge 8 commits into
Conversation
This was referenced Oct 8, 2026
Two cases sleep for a fixed time and then assert that a pending timer has not fired yet, with 150 ms and 100 ms to spare. On a busy macOS runner the sleep runs long, the timer fires first and the precondition traps: line 27 on the windows-catch-up PR, line 54 on mochi-colours, neither of which touches the state machine. Both timers are now a full second out, so the sleeps only have to outlast what they are there to outlast. The test takes about 1.6 s longer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Infinite CSS animations were paused only in views that are not `.on`. The view that is on stays on while the island is compact or hidden, so the ticker's shimmer went on repainting at 60 fps inside an island of zero height. `#content` now carries `.live` while it is visible, and everything under a content that is not live is paused. Nothing visible changes: the content has opacity 0 whenever it is not live. Measured on Windows 11 with the island hidden after a Claude Code session, CPU time of coucou.exe plus its WebView2 processes over 30 s: before 2,297 ms (renderer 1,344 + GPU 797), after 656 ms (GPU ~0). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The model picker is a popover on macOS, with 260 pt for the list. Here it sits inside the island, in whatever the chat leaves: with an empty conversation the island is 240 px tall and the list had room for one model, scrolled with the arrows of a collapsed scrollbar. While the picker is open the island now takes all the height the panel has (312 px), the way the question view already grows for its options, and comes back to the chat's own height when it closes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… in its card A chat error is shown as a note, in a card made for one short line. The cloud providers' errors carried the provider's whole message after our own sentence: Gemini's 404 for a model new accounts can no longer use adds three sentences of advice for developers and a link, and the note filled its card edge to edge. - net::error_detail keeps the provider's first sentence (it already promised a text "cut down for a message", but only cut plain-text bodies). - The note is held to four lines with an ellipsis, with the whole text in its tooltip, so whatever is passed to it stays inside the card. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
After a failed chat turn the note stayed up with nothing to close it: the
only ways out were the tabs or Escape, and the chat it came from was a tab
away from the advice it had just given ("pick another one above the chat box").
- The note gets the finished card's OK button, which goes back to the chat.
- Left alone for ten seconds it folds the island. It does not go back to the
chat by itself: the chat takes the keyboard, and nobody asked for that.
- A note with its own timing (a failed drop, gone after 2.4 s) is unchanged:
no button, no second timer.
Builds on the previous commit.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A provider's list offers models a key cannot use: Gemini lists gemini-2.5-pro to accounts it then answers 404 to. Nothing says so before the model is used, and after the error the list still showed it like any other. The chat now remembers, until the app quits, the models a cloud provider answered 404 for, and the picker shows them greyed with "Not available". They can still be picked, and one that answers again loses the mark. No request is made to find out: only what a real chat turn was answered is remembered. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The models a provider answered 404 for were only remembered until the app quit: after a restart the list offered them again like any other, and the only way to find out was to hit the same error. They are now kept in refused-models.json, next to the log: model names only, nothing leaves the machine, and the uninstaller removes it with the log. A model that answers again loses its mark for good, and the file is only written when a mark is added or removed, never on an ordinary answer. Past 200 marks the oldest go. Builds on the previous commit. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The picker listed every cloud provider, with or without a key, next to the model servers, which only show once connected. It now treats them alike: a cloud provider shows once its key is in the credential store, a model server once it is connected, and the active provider always, so the picker never hides where the chat goes. With nothing set up, the active provider says its key is missing and links to Settings, as before. The store is only asked whether each key is there, when the picker is built and each time it opens, so a key added in Settings shows the next time. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit 2c227d4a2c75feba4fb1cf99c996e2e83bbdd06e)
shakibbinkabir
force-pushed
the
chat-fixes
branch
from
October 8, 2026 22:38
4a2a7a6 to
89d2b70
Compare
This was referenced Oct 8, 2026
PythonTilk
added a commit
to PythonTilk/coucou
that referenced
this pull request
Oct 9, 2026
Taken from upstream PR Louis-CFM#318 by shakibbinkabir (folded into Louis-CFM#365 there): the ticker's shimmer kept repainting while the island was compact or hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Eight things I ran into using Coucou on Windows every day, one commit each. This folds in #318 and #321, which I am closing, so everything is in one place.
Take any subset. Five commits stand alone, and the other three each need only the one before them. I applied every row of the table to
mainseparately and ran the tests on each.df9b63a157f37c4f82cbcf6798e8d92b538bcae11bf5dd75889d2b70They are ordered from "plain fix" to "your call". Commit 1 is first so that this PR's own
Buildcheck stops failing at random.What changes on screen
Shipped views stay as they are. These are the only visible differences, so you can judge them against the no-restyle rule:
Commits 1, 2 and 7 change nothing you can see.
The repo's rules
refused-models.jsonnext to the log, with model names only. The uninstaller removes it with the log.settings.jsongets no new field.The commits
1. Auto-close test no longer races its own timers (was #321)
"Test auto-close timing" fails now and then on PRs that do not touch the state machine: line 27 on #307, line 54 on #320 and on this PR. Two cases sleep for a fixed time and then assert that a pending timer has not fired, with 150 ms and 100 ms to spare. Both timers are now a full second out. What each case checks is unchanged, and the test takes about 1.6 s longer.
On a
macos-latestrunner on my fork, compiled the wayscripts/test-auto-close.shdoes:Plain CPU load did not reproduce it. Freezing the process did, at the two lines CI fails on. The freeze is my model of a stalled runner, not something I observed on the failing runs.
2. A hidden island stops painting (was #318)
style.csspauses infinite animations only in views that are not.on. The view that is on stays on while the island is compact or hidden, so the ticker's shimmer kept repainting at 60 fps inside an island of zero height.#contentnow carries.livewhile it is visible, and the existing rule also covers#content:not(.live) *.CPU time of
coucou.exeplus its WebView2 processes over 30 s, starting 3 s after the window shrinks to the wake strip, after a Claude Code session:About 0.5 s per 30 s remains, and this commit does not address it. It is not the page: a CDP profile of the hidden island shows 0 ms of script, layout and style over 20 s, and the AudioContext is suspended. It sits on Chromium's thread-pool threads and I could not attribute it to app code.
3. Room for the chat's model list
On macOS the picker is a popover with 260 pt for the list. In the port it sits inside the island, in whatever the chat leaves: 23 px for rows 28 px tall. While the picker is open the island now takes all the height the panel has (
PANEL_H - 8), the way the question view already grows for its options.It does not reach the Mac's 260 pt. That needs a taller window, and
PANEL_His also the desktop Mochi's home zone and the Linux geometry, so I left it alone.4. A provider's error is one sentence, and a note stays in its card
A chat error is shown as a note, in a card made for one short line. The cloud providers' errors carried the provider's whole message after our own sentence. Gemini's 404 for a model new accounts can no longer use adds three sentences of developer advice and a link: 341 characters over five lines, filling 100 of the card's 108 px.
net::error_detailkeeps the provider's first sentence. Its comment already said "cut down for a message", but only plain-text bodies were cut.5. A chat error's note can be closed, and closes by itself (needs 4)
After a failed chat turn the note stayed up with nothing to close it, one tab away from the chat its own advice points to ("pick another one above the chat box").
On the real app: OK lands in the chat. With the island's own auto-close set to 120 s, so that only the note's timer could act, the note was still up after 6.5 s and the island was folded after 12 s.
6. The picker marks a model its provider refused
A provider's list offers models a key cannot use. Gemini lists
gemini-2.5-proto accounts it then answers 404 to, and afterwards the list still showed it like any other.The chat now remembers the models a cloud provider answered 404 for, and the picker shows them greyed with "Not available". They can still be picked, and one that answers again loses the mark. Only a 404 marks a model: quota, rate-limit and server errors can pass, so they do not. It covers the providers in
openai_compat.rs; Anthropic and the model servers are untouched.7. A refused model stays marked between launches (needs 6)
With commit 6 alone the marks are gone after a restart. They are now kept in
refused-models.json, next to the log. The file is written only when a mark is added or removed, never on an ordinary answer, and past 200 marks the oldest go.On the real app: three Gemini models that answered 404 were still reported as refused by a fresh launch.
8. The picker shows the providers that are set up
Every cloud provider is listed, key or not, and picking one without a key leads to "No API key". Model servers already only show once connected. This treats cloud providers the same way: one shows once its key is stored, and the active one always shows, so the picker never hides where the chat goes. With nothing set up, the active provider still says its key is missing and links to Settings.
On the Mac,
ModelPickerViewalways shows the cloud providers, so this departs from it. Drop this commit if you want the two alike. If you want it on the Mac too, I can add the same filter there.Tests
mainnpm testtsc --noEmitcargo test --workspace: 200 + 30 pass, run on the full series only.Not tested
🤖 Generated with Claude Code