|
|
@@ -2,7 +2,7 @@ import uuid
|
|
|
from pathlib import Path
|
|
|
|
|
|
import litellm
|
|
|
-from fastapi import Depends, FastAPI, WebSocket, status
|
|
|
+from fastapi import Depends, FastAPI, WebSocket, HTTPException, Query, status
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
@@ -116,6 +116,24 @@ def refresh_files():
|
|
|
return structure.to_dict()
|
|
|
|
|
|
|
|
|
+@app.get('/api/list-files')
|
|
|
+def list_files(relpath: str = Query(None, description='Relative path from workspace base')):
|
|
|
+ """Refreshes and returns the files and directories from a specified subdirectory or the base directory if no subdirectory is specified, limited to one level deep."""
|
|
|
+ base_path = Path(config.get('WORKSPACE_BASE')).resolve()
|
|
|
+ full_path = (base_path / relpath).resolve() if relpath is not None else base_path
|
|
|
+
|
|
|
+ logger.debug(f'Listing files at {full_path}')
|
|
|
+
|
|
|
+ # Ensure path exists, is a directory,
|
|
|
+ # And is within the workspace base directory - to prevent directory traversal attacks
|
|
|
+ # https://owasp.org/www-community/attacks/Path_Traversal
|
|
|
+ if not full_path.exists() or not full_path.is_dir() or not str(full_path).startswith(str(base_path)):
|
|
|
+ raise HTTPException(status_code=400, detail='Invalid path provided.')
|
|
|
+
|
|
|
+ structure = files.get_single_level_folder_structure(base_path, full_path)
|
|
|
+ return {'files': structure}
|
|
|
+
|
|
|
+
|
|
|
@app.get('/api/select-file')
|
|
|
def select_file(file: str):
|
|
|
try:
|