Add workspace navigation and model management

This commit is contained in:
Michael committed 2026-06-30 16:28:44 +02:00
1 parent 765c7b31d5
commit a7290039f6
10 files changed
+372 -49

No files matched your search

+9
View File
@@ -79,6 +79,15 @@ class OllamaClient:
resp.raise_for_status()
return resp.json()
async def delete_model(self, name: str) -> dict:
"""Supprime un modèle installé (/api/delete)."""
async with httpx.AsyncClient(timeout=30.0, follow_redirects=True) as client:
resp = await client.request(
"DELETE", f"{self.host}/api/delete", json={"model": name}
)
resp.raise_for_status()
return resp.json() if resp.content else {"status": "success"}
async def pull_model(self, name: str) -> AsyncIterator[dict]:
"""Télécharge un modèle en streamant la progression (/api/pull)."""
async with httpx.AsyncClient(
+17
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import os
from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse
from ..config import settings
from ..tools import ToolError, _safe_path
@@ -47,3 +48,19 @@ async def file_content(path: str) -> dict:
raise HTTPException(404, "fichier introuvable")
with open(target, "r", encoding="utf-8", errors="replace") as f:
return {"path": path, "content": f.read()}
@router.get("/download")
async def download_file(path: str) -> FileResponse:
"""Télécharge un fichier en conservant le confinement au workspace."""
try:
target = _safe_path(path)
except ToolError as exc:
raise HTTPException(400, str(exc)) from exc
if not os.path.isfile(target):
raise HTTPException(404, "fichier introuvable")
return FileResponse(
target,
filename=os.path.basename(target),
media_type="application/octet-stream",
)
+20 -1
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
import json
import httpx
from fastapi import APIRouter
from fastapi import APIRouter, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
@@ -62,6 +62,25 @@ class PullRequest(BaseModel):
name: str
class DeleteModelRequest(BaseModel):
name: str
@router.delete("/models")
async def delete_model(req: DeleteModelRequest) -> dict:
"""Supprime explicitement un modèle de l'instance Ollama."""
if not req.name.strip():
raise HTTPException(400, "nom de modèle vide")
try:
await ollama.delete_model(req.name.strip())
except httpx.HTTPStatusError as exc:
detail = exc.response.text[:500] or str(exc)
raise HTTPException(502, f"Ollama : {detail}") from exc
except (httpx.HTTPError, OSError) as exc:
raise HTTPException(502, f"Ollama injoignable : {exc}") from exc
return {"deleted": req.name.strip()}
@router.post("/models/pull")
async def pull_model(req: PullRequest) -> StreamingResponse:
"""Télécharge un modèle en streamant la progression (SSE)."""