mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
133 lines
4.1 KiB
Python
133 lines
4.1 KiB
Python
import json
|
|
import os
|
|
import tempfile
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import HTTPException, Query, UploadFile, File
|
|
from fastapi.responses import JSONResponse
|
|
from pydantic import BaseModel
|
|
from typing import Optional
|
|
|
|
from backend.config.Apps import SubApp
|
|
from backend.apps.settings.models import AppSettings, DEFAULT_SYSTEM_PROMPT
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
from backend.config.paths import SETTINGS_DIR as DATA_DIR
|
|
|
|
SETTINGS_FILE = os.path.join(DATA_DIR, "settings.json")
|
|
|
|
|
|
@asynccontextmanager
|
|
async def settings_lifespan():
|
|
os.makedirs(DATA_DIR, exist_ok=True)
|
|
yield
|
|
|
|
|
|
settings = SubApp("settings", settings_lifespan)
|
|
|
|
|
|
def load_settings() -> AppSettings:
|
|
"""Load settings from JSON file, returning defaults if not found."""
|
|
if os.path.exists(SETTINGS_FILE):
|
|
with open(SETTINGS_FILE) as f:
|
|
settings = AppSettings(**json.load(f))
|
|
if settings.default_system_prompt is None:
|
|
settings.default_system_prompt = DEFAULT_SYSTEM_PROMPT
|
|
return settings
|
|
return AppSettings()
|
|
|
|
|
|
def _save_settings(settings_obj: AppSettings):
|
|
"""Persist settings to JSON file."""
|
|
os.makedirs(DATA_DIR, exist_ok=True)
|
|
with open(SETTINGS_FILE, "w") as f:
|
|
json.dump(settings_obj.model_dump(), f, indent=2)
|
|
|
|
|
|
@settings.router.get("")
|
|
async def get_settings():
|
|
return load_settings().model_dump()
|
|
|
|
|
|
@settings.router.put("")
|
|
async def update_settings(body: AppSettings):
|
|
os.makedirs(DATA_DIR, exist_ok=True)
|
|
with open(SETTINGS_FILE, "w") as f:
|
|
json.dump(body.model_dump(), f, indent=2)
|
|
return {"ok": True, "settings": body.model_dump()}
|
|
|
|
|
|
@settings.router.get("/default-system-prompt")
|
|
async def get_default_system_prompt():
|
|
return {"default_system_prompt": DEFAULT_SYSTEM_PROMPT}
|
|
|
|
|
|
@settings.router.post("/reset-system-prompt")
|
|
async def reset_system_prompt():
|
|
current = load_settings()
|
|
current.default_system_prompt = DEFAULT_SYSTEM_PROMPT
|
|
os.makedirs(DATA_DIR, exist_ok=True)
|
|
with open(SETTINGS_FILE, "w") as f:
|
|
json.dump(current.model_dump(), f, indent=2)
|
|
return {"ok": True, "settings": current.model_dump()}
|
|
|
|
|
|
class BrowseResponse(BaseModel):
|
|
current: str
|
|
parent: Optional[str]
|
|
directories: list[str]
|
|
files: list[str]
|
|
|
|
|
|
UPLOAD_DIR = os.path.join(tempfile.gettempdir(), "self-swarm-uploads")
|
|
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
|
|
|
|
|
@settings.router.post("/upload-files")
|
|
async def upload_files(files: list[UploadFile] = File(...)):
|
|
"""Accept dropped files, save them, and return their server-side paths."""
|
|
results = []
|
|
for f in files:
|
|
safe_name = os.path.basename(f.filename or "untitled")
|
|
dest = os.path.join(UPLOAD_DIR, safe_name)
|
|
|
|
counter = 1
|
|
base, ext = os.path.splitext(safe_name)
|
|
while os.path.exists(dest):
|
|
dest = os.path.join(UPLOAD_DIR, f"{base}_{counter}{ext}")
|
|
counter += 1
|
|
|
|
contents = await f.read()
|
|
with open(dest, "wb") as fh:
|
|
fh.write(contents)
|
|
|
|
results.append({"path": dest, "name": safe_name, "size": len(contents)})
|
|
|
|
return JSONResponse({"files": results})
|
|
|
|
|
|
@settings.router.get("/browse-directories")
|
|
async def browse_directories(path: str = Query(default="")) -> BrowseResponse:
|
|
target = path.strip() if path.strip() else os.path.expanduser("~")
|
|
target = os.path.expanduser(target)
|
|
target = os.path.abspath(target)
|
|
|
|
if not os.path.exists(target):
|
|
raise HTTPException(status_code=404, detail=f"Path not found: {target}")
|
|
if not os.path.isdir(target):
|
|
raise HTTPException(status_code=400, detail=f"Not a directory: {target}")
|
|
|
|
try:
|
|
entries = sorted(os.listdir(target))
|
|
except PermissionError:
|
|
raise HTTPException(status_code=403, detail=f"Permission denied: {target}")
|
|
|
|
visible = [e for e in entries if not e.startswith(".")]
|
|
directories = [e for e in visible if os.path.isdir(os.path.join(target, e))]
|
|
files = [e for e in visible if os.path.isfile(os.path.join(target, e))]
|
|
|
|
parent = os.path.dirname(target) if target != "/" else None
|
|
|
|
return BrowseResponse(current=target, parent=parent, directories=directories, files=files)
|