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
+83
View File
@@ -248,3 +248,86 @@ def test_the_switch_posts_at_a_route_that_serves_post(client: TestClient, db, re
interface looks exactly like one that works."""
assert client.get("/api/preferences/sidebar-kind").status_code == 405
assert client.post("/api/preferences/sidebar-kind", data={"kind": "chat"}).status_code == 200
# --- Pinned models ----------------------------------------------------------------
def _pin(db, model_id: str = "test-model") -> None:
model = db.scalar(select(Model).where(Model.model_id == model_id))
model.pinned = True
db.commit()
def test_a_pinned_model_carries_the_side_the_switch_is_on(
client: TestClient, db, registered
):
"""Picking a pinned model on the Agent side used to open an ordinary chat,
which is the fork silently ignoring the one choice already made."""
_add_connection(db)
_enable_agents(db)
_pin(db)
page = client.get("/chat").text
assert 'href="/chat?model=test-model"' in page
client.post("/api/preferences/sidebar-kind", data={"kind": "agent"})
page = client.get("/chat").text
assert 'href="/chat?model=test-model&amp;kind=agent"' in page
def test_the_pinned_links_follow_the_switch_without_a_reload(
client: TestClient, db, registered
):
"""They sit above the tree the switch swaps, so they arrive out of band --
the same shape as the New chat button. Asserted on the *fragment*: a page
load re-renders them anyway, which is how the New chat button went unnoticed.
"""
_add_connection(db)
_enable_agents(db)
_pin(db)
response = client.post("/api/preferences/sidebar-kind", data={"kind": "agent"})
assert 'id="sidebar-pinned"' in response.text
assert "kind=agent" in response.text
response = client.post("/api/preferences/sidebar-kind", data={"kind": "chat"})
assert 'href="/chat?model=test-model"' in response.text
def test_the_pinned_group_is_always_there_to_be_swapped(
client: TestClient, db, registered
):
"""Rendered even with nothing pinned. A block that vanished when the last
model was unpinned would leave the out-of-band fragment with nowhere to
land, and htmx says nothing at all when a target is missing."""
_add_connection(db)
_enable_agents(db)
assert 'id="sidebar-pinned"' in client.get("/chat").text
response = client.post("/api/preferences/sidebar-kind", data={"kind": "agent"})
assert 'id="sidebar-pinned"' in response.text
# And it says nothing when there is nothing to say.
assert "Pinned models" not in response.text
def test_an_empty_pinned_group_takes_no_room():
"""It is in the DOM whether or not it holds anything, so it has to collapse
or every sidebar with nothing pinned gains a gap."""
from pathlib import Path
import lembas
css = (Path(lembas.__file__).parent / "web/static/css/app.css").read_text(encoding="utf-8")
assert ".nav-group--pinned:empty" in css
def test_the_shortcuts_are_on_every_page_that_shows_the_sidebar(
client: TestClient, db, registered
):
"""They came from the chat page's own context, so the library and the
connections pages carried the sidebar without them -- a shortcut that is
there on one page and gone on the next."""
_add_connection(db)
_pin(db)
for path in ("/chat", "/library/knowledge", "/agents", "/settings"):
assert "Pinned models" in client.get(path).text, path