From b4f3c99a7d458d32517077ef77b0e5676020b9a2 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Sun, 28 Jun 2026 17:39:32 +0900 Subject: モデル名によってthinkingトグルがグレーアウトする不具合を修正 モデル名にスラッシュが含まれている場合にStarlette側でエスケープされる問題を回避 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ollama_web/app.py | 7 +++---- tests/test_models.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 tests/test_models.py diff --git a/src/ollama_web/app.py b/src/ollama_web/app.py index 701cc3c..eeb3bae 100644 --- a/src/ollama_web/app.py +++ b/src/ollama_web/app.py @@ -38,6 +38,7 @@ class NoCacheStaticFiles(StaticFiles): response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0" return response + _STATIC_DIR = Path(__file__).resolve().parent / "static" @@ -47,9 +48,7 @@ def create_app() -> Starlette: log_path = Path(settings.data_dir).resolve().parent / "server.log" log_path.parent.mkdir(parents=True, exist_ok=True) handler = logging.FileHandler(str(log_path), encoding="utf-8") - handler.setFormatter( - logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") - ) + handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")) root = logging.getLogger() root.setLevel(logging.INFO) root.addHandler(handler) @@ -63,7 +62,7 @@ def create_app() -> Starlette: Route("/api/chat", chat_route.chat, methods=["POST"], name="chat"), Route("/api/models", models_route.get_models, methods=["GET"], name="models"), Route( - "/api/models/{model}/capabilities", + "/api/models/{model:path}/capabilities", models_route.get_model_capabilities, methods=["GET"], name="model_capabilities", diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..8cc2738 --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,54 @@ +"""Tests for model listing and capability routes.""" + +from __future__ import annotations + +from starlette.testclient import TestClient + +from ollama_web.app import create_app +from ollama_web.config import settings + + +def _login_client(client: TestClient) -> str: + """Authenticate the test client and return the CSRF token.""" + login = client.post("/api/auth/login", json={"pin": str(settings.pin)}) + return str(login.headers["x-csrf-token"]) + + +def test_model_capabilities_route_supports_slash_in_model_name() -> None: + """HuggingFace-style model names contain slashes and must reach the API. + + Starlette's default path converter does not allow ``/`` inside a segment, + so the route uses the ``path`` converter. Encoding ``%2F`` must decode to + the full model name, not split the URL into multiple segments. + """ + with TestClient(create_app()) as client: + csrf = _login_client(client) + + slash_model = "hf.co/hotdogs/gemma-4-E4B-it-ultra-uncensored-heretic-GGUF:Q5_K_M" + encoded = slash_model.replace("/", "%2F").replace(":", "%3A") + response = client.get( + f"/api/models/{encoded}/capabilities", + headers={"X-CSRF-Token": csrf}, + ) + assert response.status_code == 200 + payload = response.json() + assert "capabilities" in payload + assert all( + cap in [c.lower() for c in payload["capabilities"]] + for cap in ("completion", "vision", "tools", "thinking") + ) + + +def test_model_capabilities_route_still_works_without_slashes() -> None: + """Model names without slashes (e.g. cloud aliases) must keep working.""" + with TestClient(create_app()) as client: + csrf = _login_client(client) + + response = client.get( + "/api/models/glm-5.2%3Acloud/capabilities", + headers={"X-CSRF-Token": csrf}, + ) + assert response.status_code == 200 + payload = response.json() + assert "capabilities" in payload + assert "completion" in [c.lower() for c in payload["capabilities"]] -- cgit v1.2.3