Pinned models that know which side you are on

Reported: a pinned model always opened an ordinary chat, even with Agents
selected in the sidebar. They now carry `&kind=agent` with the switch -- a
preselection like `?model=` itself, so the new-chat screen still decides and
nothing is fixed until the first message is sent.

They sit above the tree the switch swaps, so this is the same shape as the New
chat button a few commits ago and gets the same treatment: their own partial,
arriving out of band. The group is rendered even when nothing is pinned,
because a block that vanished when the last model was unpinned would leave that
fragment with nowhere to land -- and htmx says nothing at all when a target is
missing, which is the silent failure this codebase keeps cataloguing.
`.nav-group--pinned:empty` stops the empty one taking room.

Chasing it turned up something else. The shortcuts came from `_chat_context`,
which only the chat pages build -- so the library, connections, settings and
folder pages carried the sidebar without them. A shortcut that is there on one
page and gone on the next. They come from `sidebar_context` now, where they
belong: it is sidebar content, and it is what the fragment route has.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-08-04 12:53:47 +02:00
parent 5984d90fb0
commit 9db4e03795
6 changed files with 127 additions and 17 deletions
+8 -3
View File
@@ -38,9 +38,6 @@ def _chat_context(db: DBSession, user: User, chat: Chat | None) -> dict:
current = next((m for m in models if m.model_id == chat.model_id), None) if chat else None
return {
"models": models,
# For the sidebar shortcuts only. The picker lists `models` in the
# administrator's order, pinned or not.
"pinned_models": [m for m in models if m.pinned],
"current_model": current,
# Assistant bubbles show the avatar of the model that wrote them, which
# may not be the model the chat is set to now. Keyed by model_id, the
@@ -279,6 +276,14 @@ def sidebar_context(db: DBSession, user: User) -> dict:
return {
"folders": folders,
"unfiled_chats": unfiled,
# The shortcuts at the top of the sidebar. Here rather than in
# `_chat_context`, where they used to be, for two reasons: they are
# sidebar content and the fragment route that re-renders the sidebar has
# only this, and the library and connections pages carry the sidebar
# without ever calling `_chat_context` -- so the shortcuts simply were
# not there on any of them. The picker lists every model in the
# administrator's order, pinned or not; pinning is not ordering.
"pinned_models": [m for m in chat_service.available_models(db, user) if m.pinned],
"sidebar_kind": kind,
# Whether the switch is worth showing at all. A two-way switch with one
# useful side is worse than no switch: it offers a view that is empty by