Fix: stop repeating the cloud subscription notice on model switches - #75
Merged
Merged
Conversation
Selecting a cloud model announced that cloud models need an ollama.com subscription. It was guarded to fire once, but the guard was an instance field on ChatController and there is one controller per agent tab — so the fact being stated was app-wide while the memory of having stated it was per-tab, and every agent the user switched announced it again. A second defect ran the other way: the flag was set before the DeferModelAnnouncement check, so a tab restored onto a cloud model marked the notice as shown while displaying nothing, then suppressed it for the rest of that session. Removed rather than repaired. The notice was pre-emptive — fired on selection in case a 403 arrived later — but the model chip already carries "cloud", and ResponseStreamer already reports the actionable version when a request actually fails. It told the user something they could not act on, before anything had gone wrong. ModelNoticeReplay keeps recognising it, and now covers the 0.14.x wording too. Nothing emits it any more, so replay is the only thing keeping it off screen for anyone whose journal already holds one. That older wording contains an apostrophe and is journaled HTML-encoded, so the filter now decodes before matching — comparing the encoded text against a raw literal fails silently, which is exactly how it would have come back on restore. The setup wizard's cloud messaging is untouched: it explains cloud versus local while the user is choosing, and only mentions the subscription when a sign-in check has actually failed. Both are conditional and actionable.
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.
Summary
Picking a cloud model announced that cloud models need an ollama.com subscription, and kept
announcing it. The notice is removed — the model chip already says
cloud, and the only messagethat was ever actionable already appears when a cloud request actually fails.
What was happening
The notice was supposed to appear once. Two separate defects meant it appeared far more often than
that for some people, and never at all for others.
The guard was per-agent, not app-wide. The "already said this" flag was an instance field on
ChatController, and there is one controller per agent tab. The fact being stated is app-wide —cloud needs a subscription — but the memory of having stated it lived in a single tab. Four agents
open meant four announcements.
The flag was burned without showing anything. It was set before the check that suppresses
announcements during restore, so a tab restored onto a cloud model marked the notice as shown while
displaying nothing — and then suppressed it for the rest of that session. So the behaviour was not
merely chatty, it was inconsistent in both directions.
What changed
arrived later. But the model chip already marks a cloud model, and
ResponseStreameralreadyreports the useful version if a request actually fails — that the account is signed in but has no
active subscription. The removed notice told the user something they could not act on, before
anything had gone wrong.
which means journal replay is now the only thing keeping it off screen for anyone whose journal
already holds one. The 0.14.x wording contains an apostrophe and is journaled HTML-encoded, so the
filter now decodes before matching — comparing encoded text against a raw literal fails silently,
which is precisely how it would have reappeared on restore.
model, and mentions the subscription only when a sign-in check has actually failed, immediately
before offering to sign you in. Both are conditional and actionable, unlike the removed one.
Scope and risk
Low. One notice deleted, one field deleted, and the replay filter widened. No behaviour changes
beyond what is displayed.
The judgement worth reviewing is whether losing the pre-emptive warning matters. The argument for
removing it: a user who picks a cloud model without a subscription now learns at their first
message instead of at selection — one step later, but with a message that names the actual problem
and is tied to a real failure rather than a hypothetical one. If you would rather keep a warning at
selection time, the alternative was a once-ever flag persisted to
ui-settings.json; happy to buildthat instead.
Verification
dotnet build src/MandoCode.Desktop— succeeded, 0 warnings, 0 errors.dotnet test src/MandoCode.Desktop.Tests— 490 passed, 0 failed.HTML-encoded 0.14.x one — that test fails without the decode, so it pins the actual bug rather
than restating the code.
must survive replay, since it is part of a walkthrough the user went through. The filter
matches the exact retired notices rather than anything containing the word "cloud".
Not covered: no runtime check that a real cloud switch is now silent, or that a real 403 still
produces the actionable message — the 403 path is unchanged by this PR but is the thing a user now
depends on. Worth switching to a cloud model in a build of this branch and confirming you get the
chip and nothing else.