summaryrefslogtreecommitdiff
path: root/src/ollama_web/routes/sessions.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/ollama_web/routes/sessions.py')
-rw-r--r--src/ollama_web/routes/sessions.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/ollama_web/routes/sessions.py b/src/ollama_web/routes/sessions.py
new file mode 100644
index 0000000..8980960
--- /dev/null
+++ b/src/ollama_web/routes/sessions.py
@@ -0,0 +1,120 @@
+"""Session management API routes."""
+
+from __future__ import annotations
+
+import logging
+from typing import Any
+
+from starlette.requests import Request
+from starlette.responses import JSONResponse
+
+from ..sessions import SessionStore
+from ..tools.pdf import extract_pdf_text
+
+logger = logging.getLogger("ollama_web.sessions")
+
+
+def _get_store(request: Request) -> SessionStore:
+ return request.app.state.session_store
+
+
+async def list_sessions(request: Request) -> JSONResponse:
+ store = _get_store(request)
+ return JSONResponse({"sessions": store.list_sessions()})
+
+
+async def create_session(request: Request) -> JSONResponse:
+ store = _get_store(request)
+ body = await request.json() if await request.body() else {}
+ title = body.get("title")
+ session = store.create(title=title)
+ return JSONResponse(session)
+
+
+async def get_session(request: Request) -> JSONResponse:
+ store = _get_store(request)
+ session_id = request.path_params["session_id"]
+ session = store.get(session_id)
+ if session is None:
+ return JSONResponse({"error": "Session not found"}, status_code=404)
+ return JSONResponse(session)
+
+
+async def delete_session(request: Request) -> JSONResponse:
+ store = _get_store(request)
+ session_id = request.path_params["session_id"]
+ ok = store.delete(session_id)
+ if not ok:
+ return JSONResponse({"error": "Session not found"}, status_code=404)
+ return JSONResponse({"deleted": True})
+
+
+async def upload_file(request: Request) -> JSONResponse:
+ store = _get_store(request)
+ session_id = request.path_params["session_id"]
+ session = store.get(session_id)
+ if session is None:
+ return JSONResponse({"error": "Session not found"}, status_code=404)
+
+ max_size = request.app.state.settings.max_upload_mb * 1024 * 1024
+ try:
+ form = await request.form()
+ except Exception as exc: # noqa: BLE001
+ logger.error("failed to parse multipart form: %s", exc)
+ return JSONResponse({"error": f"Invalid form data: {exc}"}, status_code=400)
+
+ files = form.getlist("files") if hasattr(form, "getlist") else [form.get("files")]
+ results: list[dict[str, Any]] = []
+ for upload in files:
+ if upload is None:
+ continue
+ try:
+ data = await upload.read()
+ except Exception as exc: # noqa: BLE001
+ results.append({"name": getattr(upload, "filename", "unknown"), "error": str(exc)})
+ continue
+ if len(data) > max_size:
+ results.append(
+ {
+ "name": getattr(upload, "filename", "unknown"),
+ "error": f"File exceeds {request.app.state.settings.max_upload_mb} MB limit",
+ }
+ )
+ continue
+
+ name = getattr(upload, "filename", "uploaded-file") or "uploaded-file"
+ content_type = getattr(upload, "content_type", None) or "application/octet-stream"
+ text = ""
+ if content_type == "application/pdf" or name.lower().endswith(".pdf"):
+ text = extract_pdf_text(data)
+ else:
+ # Try decode as text for text-like uploads.
+ try:
+ text = data.decode("utf-8")
+ except UnicodeDecodeError:
+ try:
+ text = data.decode("cp932")
+ except UnicodeDecodeError:
+ text = data.decode("utf-8", errors="replace")
+
+ chat_file = store.add_file(
+ session_id=session_id,
+ name=name,
+ data=data,
+ mime=content_type,
+ text=text,
+ source="upload",
+ )
+ results.append(chat_file.to_dict())
+
+ return JSONResponse({"files": results})
+
+
+async def delete_file(request: Request) -> JSONResponse:
+ store = _get_store(request)
+ session_id = request.path_params["session_id"]
+ file_id = request.path_params["file_id"]
+ ok = store.remove_file(session_id, file_id)
+ if not ok:
+ return JSONResponse({"error": "File not found"}, status_code=404)
+ return JSONResponse({"deleted": True}) \ No newline at end of file