Skip to content

fix(desktop): make model and thinking-level changes instant without success toasts #3745

Description

@Sun-GLiang

Background

Maka Desktop persists active-task model and thinking-level changes asynchronously through Runtime Host. The current UI exposes that implementation detail in two ways:

  • It shows a success toast after every completed change (Task model changed or Thinking level updated).
  • It puts the corresponding control into a pending/loading state while the mutation is in flight.

Dogfooding has exposed three problems with this feedback:

  1. Toasts stack during rapid changes. Switching between several models or thinking levels in a short period creates multiple independent notifications. They obscure the conversation and report intermediate states that are no longer relevant.
  2. The source model can be incorrect. The model-switch toast derives its from value from the latest assistant message rather than the model configured immediately before the switch. For example, switching A → B → C before B produces an assistant message can report A → C.
  3. The loading state makes a lightweight setting change feel slow. The selector shows a spinner or disabled state until the Host round trip completes, even though the user's intent is already known and the control itself can display the new value immediately.

The model and thinking-level controls already communicate the selected state. A separate success surface is redundant, and making users watch the persistence round trip adds visual latency without providing useful information.

Model and thinking-level selections should therefore behave like an optimistic, latest-wins intent: update immediately, settle silently in the background, and only interrupt the user when the latest requested state cannot be committed.

How to reproduce

Stacked success toasts

  1. Open an existing Desktop task.
  2. Change the thinking level several times in quick succession, for example High → Extra high → Low.
  3. Observe that a separate success toast is created for every completed change.
  4. The notifications stack and continue showing obsolete intermediate values.

The same behavior can occur when switching models repeatedly.

Incorrect source model

  1. Open a task whose latest assistant response was generated by model A.
  2. Change the task model from A to B.
  3. Before receiving an assistant response from B, change the model from B to C.
  4. Observe that the second toast can report A → C instead of B → C.

Visible mutation latency

  1. Change the active task's model or thinking level.
  2. Observe that the control enters a loading or disabled state while Desktop waits for Runtime Host.
  3. Repeat the selection quickly and observe that the interaction is gated by the in-flight mutation instead of immediately reflecting the latest choice.

Expected behavior

  • Selecting a model or thinking level updates the control immediately, with no spinner, disabled flicker, or success toast.
  • Runtime Host persistence continues silently in the background.
  • Rapid changes use latest-wins semantics: intermediate pending choices may be coalesced, and the UI continues to represent the newest user intent.
  • If the user sends a message immediately after changing a setting, the send waits for the latest setting to settle before reaching Runtime Host. This wait uses the ordinary processing state rather than exposing a separate settings-loading state.
  • If the latest setting mutation fails, Desktop rolls the control back to the last successfully committed state, shows the existing localized error toast and diagnostic context, and does not send with a stale or unintended setting. The composer draft remains available for retry.

Suggested direction

  • Remove model and thinking-level success-toast calls, copy, label helpers, transcript-derived source-model logic, and dependencies used only by those notifications.
  • Represent model and thinking-level changes as per-session desired state layered over the authoritative session projection used by the controls.
  • Serialize Host mutations per session and coalesce rapid selections so pending work converges on the latest desired target.
  • Keep the optimistic projection scoped to model controls; unrelated session health, conversation state, and execution state should continue to use authoritative data.
  • Before sending from an existing task, silently settle the latest model-setting intent. Abort the send and retain the draft if settlement fails.
  • Persist the composer default only after a model change commits successfully, and continue refreshing sessions after successful mutations.
  • Clear optimistic state when its session is removed or the owning surface unmounts so late completions cannot restore stale UI or emit irrelevant errors.
  • Preserve Runtime Host APIs, pending execution guards, permission-mode feedback, localized failure toasts, diagnostics, and unrelated notifications.
  • Do not replace the removed success toasts with another notification or persisted event.

Acceptance criteria

  • Successfully changing the active task's model updates the selector immediately and does not show a spinner or success toast.
  • Successfully changing the active task's thinking level updates the selector immediately and does not show a spinner or success toast.
  • Rapid model or thinking-level changes converge on the latest selection without stacked notifications or obsolete pending UI.
  • A cross-connection model selection, including two connections exposing the same model ID, displays the projected connection/model target and can be changed again while persistence is pending.
  • The final control state reconciles with the authoritative session projection after refresh.
  • An immediate send waits silently for the latest model and thinking-level intent, then sends with the committed settings.
  • If settings fail to settle, the send is skipped, the ordinary processing indicator is disarmed, and the composer draft is retained.
  • A terminal model or thinking-level failure rolls back to the last committed state and produces the existing localized error toast with session diagnostic context.
  • Superseded or late failures do not overwrite a newer selection or report an error on an unrelated/unmounted surface.
  • Successful model commits continue to update the composer default; failed, uncommitted selections do not.
  • Permission-mode and other unrelated notifications are unaffected.
  • Regression tests cover silent optimistic success, latest-wins coalescing, send settlement, rollback/failure feedback, cross-connection targets, and lifecycle cleanup.

Out of scope

  • Runtime Host, IPC, or persistence-format changes.
  • Toast deduplication or reconstructing a more accurate success-toast source model.
  • A replacement success notification or persisted model-setting event.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions