inference: allow user change chat title
diff --git a/inference/full-dev-setup.sh b/inference/full-dev-setup.sh
index 4a6a10cada..1c73e1de39 100755
--- a/inference/full-dev-setup.sh
+++ b/inference/full-dev-setup.sh
@@ -30,7 +30,7 @@ fi
 
 tmux split-window -h
 tmux send-keys "cd server" C-m
-tmux send-keys "LOGURU_LEVEL=$LOGLEVEL POSTGRES_PORT=5732 REDIS_PORT=6779 DEBUG_API_KEYS='0000,0001' ALLOW_DEBUG_AUTH=True uvicorn main:app" C-m
+tmux send-keys "LOGURU_LEVEL=$LOGLEVEL POSTGRES_PORT=5732 REDIS_PORT=6779 DEBUG_API_KEYS='0000,0001' ALLOW_DEBUG_AUTH=True TRUSTED_CLIENT_KEYS=6969 uvicorn main:app" C-m
 tmux split-window -h
 tmux send-keys "cd text-client" C-m
 tmux send-keys "sleep 5" C-m
diff --git a/inference/server/oasst_inference_server/routes/chats.py b/inference/server/oasst_inference_server/routes/chats.py
index 15b4923e13..d3b96ff567 100644
--- a/inference/server/oasst_inference_server/routes/chats.py
+++ b/inference/server/oasst_inference_server/routes/chats.py
@@ -256,3 +256,17 @@ async def handle_create_report(
     except Exception:
         logger.exception("Error adding report")
         return fastapi.Response(status_code=500)
+
+
+@router.put("/{chat_id}/title")
+async def handle_update_title(
+    chat_id: str,
+    request: chat_schema.ChatUpdateTitleRequest,
+    ucr: deps.UserChatRepository = fastapi.Depends(deps.create_user_chat_repository),
+) -> fastapi.Response:
+    """Allows the client to update a chat title."""
+    try:
+        await ucr.update_title(chat_id=chat_id, title=request.title)
+    except Exception:
+        logger.exception("Error when updating chat title")
+        return fastapi.Response(status_code=500)
diff --git a/inference/server/oasst_inference_server/schemas/chat.py b/inference/server/oasst_inference_server/schemas/chat.py
index 42bbd2f071..ae70bf4b71 100644
--- a/inference/server/oasst_inference_server/schemas/chat.py
+++ b/inference/server/oasst_inference_server/schemas/chat.py
@@ -81,3 +81,7 @@ class MessageTimeoutException(Exception):
     def __init__(self, message: inference.MessageRead):
         super().__init__(f"Message {message.id} timed out")
         self.message = message
+
+
+class ChatUpdateTitleRequest(pydantic.BaseModel):
+    title: pydantic.constr(max_length=100)
diff --git a/inference/server/oasst_inference_server/user_chat_repository.py b/inference/server/oasst_inference_server/user_chat_repository.py
index 8e4bf33e92..6f9df15319 100644
--- a/inference/server/oasst_inference_server/user_chat_repository.py
+++ b/inference/server/oasst_inference_server/user_chat_repository.py
@@ -20,17 +20,16 @@ async def get_chats(self) -> list[models.DbChat]:
         query = query.order_by(models.DbChat.created_at.desc())
         return (await self.session.exec(query)).all()
 
-    async def get_chat_by_id(self, chat_id: str) -> models.DbChat:
-        query = (
-            sqlmodel.select(models.DbChat)
-            .options(
+    async def get_chat_by_id(self, chat_id: str, include_messages: bool = True) -> models.DbChat:
+        query = sqlmodel.select(models.DbChat).where(
+            models.DbChat.id == chat_id,
+            models.DbChat.user_id == self.user_id,
+        )
+        if include_messages:
+            query = query.options(
                 sqlalchemy.orm.selectinload(models.DbChat.messages).selectinload(models.DbMessage.reports),
             )
-            .where(
-                models.DbChat.id == chat_id,
-                models.DbChat.user_id == self.user_id,
-            )
-        )
+
         chat = (await self.session.exec(query)).one()
         return chat
 
@@ -226,3 +225,10 @@ async def add_report(self, message_id: str, reason: str, report_type: inference.
         await self.session.commit()
         await self.session.refresh(report)
         return report
+
+    async def update_title(self, chat_id: str, title: str) -> models.DbChat:
+        logger.info(f"Updating title of chat {chat_id=}: {title=}")
+        chat = await self.get_chat_by_id(chat_id=chat_id, include_messages=False)
+
+        chat.title = title
+        await self.session.commit()
