diff --git a/CHANGELOG.md b/CHANGELOG.md index 12f5245..d045423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,15 @@ for 1.0.0 have something to be assembled from. ## Unreleased +## 1.9.1 + +- **A temporary chat can be started on any model.** On the new-chat screen, + turning on Temporary switched the model back to the default, and choosing a + model switched Temporary off, so a temporary chat could only ever be started + on the default model. The Temporary button, the model menu and `/temp` now + keep each other's choice, and also keep the folder a chat was started in + ("New chat here") and whether it is an agent chat. + ## 1.9.0 The model menu says which model is loaded, and a new chat now matches the diff --git a/src/lembas/__init__.py b/src/lembas/__init__.py index 74b1c05..e555d9c 100644 --- a/src/lembas/__init__.py +++ b/src/lembas/__init__.py @@ -1,3 +1,3 @@ """LLeMbas - a Middle-earth themed web UI for OpenAI-compatible LLM endpoints.""" -__version__ = "1.9.0" +__version__ = "1.9.1" diff --git a/src/lembas/api/pages.py b/src/lembas/api/pages.py index 100adde..568125a 100644 --- a/src/lembas/api/pages.py +++ b/src/lembas/api/pages.py @@ -2,6 +2,7 @@ from __future__ import annotations +from urllib.parse import urlencode from zoneinfo import available_timezones from fastapi import APIRouter, HTTPException, Request, Response, status @@ -727,6 +728,24 @@ async def chat_index( if preselected is None and context["models"]: preselected = context["models"][0] + # Every preselection lives in the URL, so every link that changes one of + # them has to carry the rest. The temporary toggle used to link to a bare + # `/chat?temporary=1` and the model picker to a bare `/chat?model=`, so + # each undid the other: temporary chats could only ever be started on the + # default model. The model goes last in the picker's URL because ui.js + # appends the chosen id to it. + carried = { + "model": model if model and preselected and preselected.model_id == model else "", + "temporary": "1" if temporary else "", + "kind": kind if kind in KINDS and kind != KIND_CHAT else "", + "folder": starting_folder.id if starting_folder is not None else "", + } + + def new_chat_url(**changes: str) -> str: + query = urlencode({k: v for k, v in {**carried, **changes}.items() if v}) + return f"/chat?{query}" if query else "/chat" + + without_model = new_chat_url(model="") return render( request, "chat/index.html", @@ -749,6 +768,8 @@ async def chat_index( else chat_service.DEFAULT_EFFORTS ), "starting_temporary": temporary, + "temporary_toggle_url": new_chat_url(temporary="" if temporary else "1"), + "model_navigate_url": without_model + ("&" if "?" in without_model else "?") + "model=", "starting_kind": kind if kind in KINDS else KIND_CHAT, "starting_folder": starting_folder, "suggestions": suggestions_service.visible(db), diff --git a/src/lembas/web/static/js/commands.js b/src/lembas/web/static/js/commands.js index 41aee98..71e546e 100644 --- a/src/lembas/web/static/js/commands.js +++ b/src/lembas/web/static/js/commands.js @@ -222,7 +222,16 @@ { name: "temp", summary: "Start a temporary chat, gone after a day", - run: function () { window.location = "/chat?temporary=1"; } + run: function () { + /* On the new-chat screen the model, folder and kind already chosen are + in the query string. Add the flag to them rather than starting over, + or the chat is made on the default model. */ + var query = new URLSearchParams( + window.location.pathname === "/chat" ? window.location.search : "" + ); + query.set("temporary", "1"); + window.location = "/chat?" + query.toString(); + } }, { name: "stop", diff --git a/src/lembas/web/templates/chat/_model_picker.html b/src/lembas/web/templates/chat/_model_picker.html index 2ad6fab..1777427 100644 --- a/src/lembas/web/templates/chat/_model_picker.html +++ b/src/lembas/web/templates/chat/_model_picker.html @@ -91,7 +91,9 @@ {% else %} {# No chat yet: selecting navigates so the whole composer re-renders with the - right vision warning and the right hidden model_id. #} - + right vision warning and the right hidden model_id. The URL carries the + other preselections -- temporary, folder, kind -- and ends in `model=`, + which ui.js completes. #} + {% endif %} diff --git a/src/lembas/web/templates/chat/index.html b/src/lembas/web/templates/chat/index.html index 2e8452d..fd185de 100644 --- a/src/lembas/web/templates/chat/index.html +++ b/src/lembas/web/templates/chat/index.html @@ -65,11 +65,12 @@