lollms-webui/endpoints/lollms_apps.py

672 lines
24 KiB
Python
Raw Normal View History

2024-12-19 12:48:57 +00:00
import os
import platform
2024-07-27 23:19:18 +00:00
import shutil
2024-12-19 12:48:57 +00:00
import subprocess
import sys
2024-07-27 23:19:18 +00:00
import uuid
2024-12-19 12:48:57 +00:00
from pathlib import Path
import pipmaster as pm
2024-07-27 23:19:18 +00:00
import requests
import yaml
2024-08-02 07:46:55 +00:00
from ascii_colors import ASCIIColors, trace_exception
2024-12-19 12:48:57 +00:00
from fastapi import (APIRouter, FastAPI, File, HTTPException, Response,
UploadFile)
from fastapi.responses import (FileResponse, JSONResponse, PlainTextResponse,
StreamingResponse)
from lollms.security import check_access, sanitize_path
from packaging import version
from pydantic import BaseModel, Field
from lollms_webui import LOLLMSWebUI
2024-08-11 21:42:58 +00:00
2024-08-05 10:10:12 +00:00
if not pm.is_installed("httpx"):
pm.install("httpx")
import httpx
2024-08-11 18:11:14 +00:00
from lollms.utilities import PackageManager
2024-12-19 12:48:57 +00:00
2024-08-11 18:11:14 +00:00
# Pull the repository if it already exists
def check_lollms_models_zoo():
if not PackageManager.check_package_installed("zipfile"):
PackageManager.install_or_update("zipfile36")
2024-12-19 12:48:57 +00:00
ASCIIColors.execute_with_animation("Checking zip library.", check_lollms_models_zoo)
2024-08-05 10:10:12 +00:00
2024-08-11 19:55:00 +00:00
2024-12-19 12:48:57 +00:00
import io
2024-08-11 19:55:00 +00:00
import shutil
2024-12-19 12:48:57 +00:00
import zipfile
from pathlib import Path
2024-08-11 19:55:00 +00:00
2024-12-19 12:48:57 +00:00
from pydantic import BaseModel
2024-08-11 19:55:00 +00:00
2024-07-27 23:19:18 +00:00
router = APIRouter()
lollmsElfServer: LOLLMSWebUI = LOLLMSWebUI.get_instance()
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
class AuthRequest(BaseModel):
client_id: str
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
class AppInfo:
2024-08-11 19:55:00 +00:00
def __init__(
2024-12-19 12:48:57 +00:00
self,
uid: str,
name: str,
folder_name: str,
icon: str,
category: str,
description: str,
author: str,
version: str,
creation_date: str,
last_update_date: str,
model_name: str,
disclaimer: str,
has_server: bool,
has_readme: bool,
is_public: bool,
has_update: bool,
installed: bool,
):
2024-07-27 23:19:18 +00:00
self.uid = uid
self.name = name
2024-07-29 23:12:54 +00:00
self.folder_name = folder_name
2024-07-27 23:19:18 +00:00
self.icon = icon
2024-07-29 22:02:24 +00:00
self.category = category
2024-07-27 23:19:18 +00:00
self.description = description
self.author = author
self.version = version
2024-08-19 12:51:13 +00:00
self.creation_date = creation_date
self.last_update_date = last_update_date
2024-07-27 23:19:18 +00:00
self.model_name = model_name
self.disclaimer = disclaimer
2024-08-11 19:55:00 +00:00
self.has_server = has_server
2024-09-23 23:11:09 +00:00
self.has_readme = has_readme
2024-08-11 19:55:00 +00:00
self.has_update = has_update
self.is_public = is_public
2024-07-29 23:12:54 +00:00
self.installed = installed
2024-07-27 23:19:18 +00:00
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
@router.get("/apps")
async def list_apps():
apps = []
2024-08-02 07:46:55 +00:00
apps_zoo_path = lollmsElfServer.lollms_paths.apps_zoo_path
2024-12-19 12:48:57 +00:00
REPO_DIR = lollmsElfServer.lollms_paths.personal_path / "apps_zoo_repo"
2024-08-11 19:55:00 +00:00
if REPO_DIR.exists():
remote_apps = [a.stem for a in REPO_DIR.iterdir()]
else:
remote_apps = []
2024-08-02 07:46:55 +00:00
for app_name in apps_zoo_path.iterdir():
2024-09-19 06:41:41 +00:00
try:
if app_name.is_dir():
icon_path = app_name / "icon.png"
description_path = app_name / "description.yaml"
description = ""
author = ""
current_version = ""
model_name = ""
disclaimer = ""
has_server = False
2024-09-23 23:11:09 +00:00
has_readme = False
2024-09-19 06:41:41 +00:00
is_public = app_name.stem in remote_apps
2024-12-19 12:48:57 +00:00
2024-09-19 06:41:41 +00:00
if description_path.exists():
2024-12-19 12:48:57 +00:00
with open(description_path, "r") as file:
2024-09-19 06:41:41 +00:00
data = yaml.safe_load(file)
2024-12-19 12:48:57 +00:00
application_name = data.get("name", app_name.name)
category = data.get("category", "generic")
description = data.get("description", "")
author = data.get("author", "")
current_version = data.get("version", "")
creation_date = data.get("creation_date", "unknown")
last_update_date = data.get("last_update_date", "")
current_version = data.get("version", "")
model_name = data.get("model_name", "")
disclaimer = data.get("disclaimer", "No disclaimer provided.")
has_server = data.get(
"has_server", (Path(app_name) / "server.py").exists()
)
has_readme = data.get(
"has_readme", (Path(app_name) / "README.md").exists()
)
2024-09-19 06:41:41 +00:00
installed = True
else:
installed = False
if is_public:
try:
2024-12-19 12:48:57 +00:00
with (REPO_DIR / app_name.stem / "description.yaml").open(
"r"
) as file:
2024-09-19 06:41:41 +00:00
# Parse the YAML content
yaml_content = yaml.safe_load(file)
repo_version = yaml_content.get("version", "0")
2024-12-19 12:48:57 +00:00
2024-09-19 06:41:41 +00:00
# Compare versions using packaging.version
2024-12-19 12:48:57 +00:00
has_update = version.parse(
str(repo_version)
) > version.parse(str(current_version))
2024-09-19 06:41:41 +00:00
except (yaml.YAMLError, FileNotFoundError) as e:
print(f"Error reading or parsing YAML file: {e}")
has_update = False
else:
2024-08-11 19:55:00 +00:00
has_update = False
2024-09-19 06:41:41 +00:00
if icon_path.exists():
uid = str(uuid.uuid4())
2024-12-19 12:48:57 +00:00
apps.append(
AppInfo(
uid=uid,
name=application_name,
folder_name=app_name.name,
icon=f"/apps/{app_name.name}/icon.png",
category=category,
description=description,
author=author,
version=current_version,
creation_date=creation_date,
last_update_date=last_update_date,
model_name=model_name,
disclaimer=disclaimer,
has_server=has_server,
has_readme=has_readme,
is_public=is_public,
has_update=has_update,
installed=installed,
)
)
2024-09-19 06:41:41 +00:00
except Exception as ex:
trace_exception(ex)
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
return apps
2024-07-29 22:49:52 +00:00
class ShowAppsFolderRequest(BaseModel):
client_id: str = Field(...)
2024-12-19 12:48:57 +00:00
2024-07-29 22:49:52 +00:00
@router.post("/show_apps_folder")
async def open_folder_in_vscode(request: ShowAppsFolderRequest):
check_access(lollmsElfServer, request.client_id)
# Get the current operating system
current_os = platform.system()
try:
if current_os == "Windows":
# For Windows
2024-12-19 12:48:57 +00:00
subprocess.run(["explorer", lollmsElfServer.lollms_paths.apps_zoo_path])
2024-07-29 22:49:52 +00:00
elif current_os == "Darwin":
# For macOS
2024-12-19 12:48:57 +00:00
subprocess.run(["open", lollmsElfServer.lollms_paths.apps_zoo_path])
2024-07-29 22:49:52 +00:00
elif current_os == "Linux":
# For Linux
2024-12-19 12:48:57 +00:00
subprocess.run(["xdg-open", lollmsElfServer.lollms_paths.apps_zoo_path])
2024-07-29 22:49:52 +00:00
else:
print("Unsupported operating system.")
except Exception as e:
print(f"An error occurred: {e}")
2024-12-19 12:48:57 +00:00
2024-07-28 23:39:19 +00:00
class OpenFolderRequest(BaseModel):
client_id: str = Field(...)
app_name: str = Field(...)
2024-12-19 12:48:57 +00:00
2024-07-28 23:39:19 +00:00
@router.post("/open_app_in_vscode")
async def open_folder_in_vscode(request: OpenFolderRequest):
check_access(lollmsElfServer, request.client_id)
sanitize_path(request.app_name)
# Construct the folder path
2024-12-19 12:48:57 +00:00
folder_path = lollmsElfServer.lollms_paths.apps_zoo_path / request.app_name
2024-07-28 23:39:19 +00:00
# Check if the folder exists
if not folder_path.exists():
raise HTTPException(status_code=404, detail="Folder not found")
# Open the folder in VSCode
try:
os.system(f'code -n "{folder_path}"') # This assumes 'code' is in the PATH
return {"message": f"Opened {folder_path} in VSCode."}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to open folder: {str(e)}")
2024-07-27 23:19:18 +00:00
2024-07-30 23:08:35 +00:00
@router.get("/apps/{app_name}/{file}")
async def get_app_file(app_name: str, file: str):
2024-12-19 12:48:57 +00:00
app_name = sanitize_path(app_name)
file = sanitize_path(file)
2024-07-30 23:08:35 +00:00
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name / file
if not app_path.exists():
raise HTTPException(status_code=404, detail="App file not found")
return FileResponse(app_path)
2024-12-19 12:48:57 +00:00
2024-10-01 21:21:12 +00:00
@router.get("/apps/{app_name}/{subfolder}/{file}")
async def get_app_file(app_name: str, subfolder: str, file: str):
2024-12-19 12:48:57 +00:00
app_name = sanitize_path(app_name)
subfolder = sanitize_path(subfolder)
file = sanitize_path(file)
2024-10-01 21:21:12 +00:00
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name / subfolder / file
if not app_path.exists():
raise HTTPException(status_code=404, detail="App file not found")
return FileResponse(app_path)
2024-08-11 18:11:14 +00:00
class AppNameInput(BaseModel):
client_id: str
app_name: str
2024-12-19 12:48:57 +00:00
import os
2024-08-17 20:11:00 +00:00
import tempfile
2024-12-19 12:48:57 +00:00
import zipfile
from io import BytesIO
2024-08-17 20:11:00 +00:00
2024-12-19 12:48:57 +00:00
from fastapi.responses import FileResponse, Response
2024-08-17 20:11:00 +00:00
2024-08-11 18:11:14 +00:00
@router.post("/download_app")
async def download_app(input_data: AppNameInput):
check_access(lollmsElfServer, input_data.client_id)
app_name = sanitize_path(input_data.app_name)
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name
if not app_path.exists():
raise HTTPException(status_code=404, detail="App not found")
2024-08-17 20:11:00 +00:00
# Create a BytesIO object to store the zip file in memory
zip_buffer = BytesIO()
2024-08-11 18:11:14 +00:00
2024-08-17 20:11:00 +00:00
try:
2024-12-19 12:48:57 +00:00
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for file in app_path.rglob("*"):
if file.is_file() and ".git" not in file.parts:
2024-08-17 20:11:00 +00:00
relative_path = file.relative_to(app_path)
zip_file.write(file, arcname=str(relative_path))
# Move the cursor to the beginning of the BytesIO object
zip_buffer.seek(0)
# Create a Response with the zip content
return Response(
content=zip_buffer.getvalue(),
media_type="application/zip",
headers={
"Content-Disposition": f"attachment; filename={app_name}.zip",
"Cache-Control": "no-cache",
"Pragma": "no-cache",
2024-12-19 12:48:57 +00:00
"Expires": "0",
},
2024-08-17 20:11:00 +00:00
)
except Exception as e:
2024-12-19 12:48:57 +00:00
raise HTTPException(
status_code=500, detail=f"Error creating ZIP file: {str(e)}"
)
2024-08-11 18:11:14 +00:00
@router.post("/upload_app")
async def upload_app(client_id: str, file: UploadFile = File(...)):
check_access(lollmsElfServer, client_id)
sanitize_path(file.filename)
2024-12-19 12:48:57 +00:00
2024-08-11 18:11:14 +00:00
# Create a temporary directory to extract the zip file
temp_dir = lollmsElfServer.lollms_paths.personal_path / "temp"
os.makedirs(temp_dir, exist_ok=True)
try:
# Save the uploaded file temporarily
temp_file = temp_dir / file.filename
with open(temp_file, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
# Extract the zip file
2024-12-19 12:48:57 +00:00
with zipfile.ZipFile(temp_file, "r") as zip_ref:
2024-08-11 18:11:14 +00:00
zip_ref.extractall(temp_dir)
# Check for required files
2024-12-19 12:48:57 +00:00
required_files = ["index.html", "description.yaml", "icon.png"]
2024-08-11 18:11:14 +00:00
for required_file in required_files:
if not os.path.exists(os.path.join(temp_dir, required_file)):
2024-12-19 12:48:57 +00:00
raise HTTPException(
status_code=400, detail=f"Missing required file: {required_file}"
)
2024-08-11 18:11:14 +00:00
# Read the description.yaml file
2024-12-19 12:48:57 +00:00
with open(os.path.join(temp_dir, "description.yaml"), "r") as yaml_file:
2024-08-11 18:11:14 +00:00
description = yaml.safe_load(yaml_file)
# Get the app name from the description
2024-12-19 12:48:57 +00:00
app_name = description.get("name")
2024-08-11 18:11:14 +00:00
if not app_name:
2024-12-19 12:48:57 +00:00
raise HTTPException(
status_code=400, detail="App name not found in description.yaml"
)
2024-08-11 18:11:14 +00:00
# Create the app directory
app_dir = lollmsElfServer.lollms_paths.apps_zoo_path / app_name
if os.path.exists(app_dir):
2024-12-19 12:48:57 +00:00
raise HTTPException(
status_code=400, detail="An app with this name already exists"
)
2024-08-11 18:11:14 +00:00
# Move the extracted files to the app directory
shutil.move(temp_dir, app_dir)
2024-12-19 12:48:57 +00:00
return JSONResponse(
content={"message": f"App '{app_name}' uploaded successfully"},
status_code=200,
)
2024-08-11 18:11:14 +00:00
except zipfile.BadZipFile:
raise HTTPException(status_code=400, detail="Invalid zip file")
except yaml.YAMLError:
raise HTTPException(status_code=400, detail="Invalid YAML in description.yaml")
finally:
# Clean up temporary files
if os.path.exists(temp_file):
os.remove(temp_file)
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)
2024-07-27 23:19:18 +00:00
2024-12-19 12:48:57 +00:00
import json
2024-08-11 21:42:58 +00:00
import shutil
from pathlib import Path
2024-09-14 23:37:41 +00:00
2024-08-11 21:42:58 +00:00
2024-07-27 23:19:18 +00:00
@router.post("/install/{app_name}")
async def install_app(app_name: str, auth: AuthRequest):
2024-07-28 00:49:10 +00:00
check_access(lollmsElfServer, auth.client_id)
2024-12-19 12:48:57 +00:00
app_name = sanitize_path(app_name)
REPO_DIR = lollmsElfServer.lollms_paths.personal_path / "apps_zoo_repo"
2024-09-15 20:23:22 +00:00
2024-07-27 23:19:18 +00:00
# Create the app directory
2024-12-19 12:48:57 +00:00
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name
2024-07-27 23:19:18 +00:00
os.makedirs(app_path, exist_ok=True)
2024-12-19 12:48:57 +00:00
source_dir = REPO_DIR / app_name
2024-08-11 21:42:58 +00:00
if not source_dir.exists():
2024-12-19 12:48:57 +00:00
raise HTTPException(
status_code=404, detail=f"App {app_name} not found in the local repository"
)
2024-07-27 23:19:18 +00:00
2024-08-11 21:42:58 +00:00
# Define directories to exclude
2024-12-19 12:48:57 +00:00
exclude_dirs = {".vscode", ".git"}
2024-08-11 21:42:58 +00:00
# Copy all files and directories, excluding the ones in exclude_dirs
2024-12-19 12:48:57 +00:00
for item in source_dir.glob("*"):
2024-08-11 21:42:58 +00:00
if item.is_dir():
if item.name not in exclude_dirs:
2024-12-19 12:48:57 +00:00
shutil.copytree(item, app_path / item.name, dirs_exist_ok=True)
2024-07-27 23:19:18 +00:00
else:
2024-08-11 21:42:58 +00:00
shutil.copy2(item, app_path)
2024-07-27 23:19:18 +00:00
2024-09-14 23:37:41 +00:00
try:
2024-12-19 12:48:57 +00:00
description_path = app_path / "description.yaml"
requirements = app_path / "requirements.txt"
2024-09-14 23:37:41 +00:00
if description_path.exists() and requirements.exists():
2024-12-19 12:48:57 +00:00
with open(description_path, "r") as file:
2024-09-14 23:37:41 +00:00
description_data = yaml.safe_load(file)
2024-12-19 12:48:57 +00:00
if description_data.get(
"has_server", (Path(app_path) / "server.py").exists()
):
pass
2024-09-14 23:37:41 +00:00
except Exception as ex:
trace_exception(ex)
2024-07-27 23:19:18 +00:00
return {"message": f"App {app_name} installed successfully."}
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
@router.post("/uninstall/{app_name}")
async def uninstall_app(app_name: str, auth: AuthRequest):
2024-10-13 13:06:28 +00:00
check_access(lollmsElfServer, auth.client_id)
2024-12-19 12:48:57 +00:00
app_name = sanitize_path(app_name)
2024-07-27 23:19:18 +00:00
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name
if app_path.exists():
shutil.rmtree(app_path)
return {"message": f"App {app_name} uninstalled successfully."}
else:
raise HTTPException(status_code=404, detail="App not found")
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
2024-07-28 00:49:10 +00:00
REPO_URL = "https://github.com/ParisNeo/lollms_apps_zoo.git"
2024-12-19 12:48:57 +00:00
2024-08-05 10:10:12 +00:00
class ProxyRequest(BaseModel):
url: str
2024-07-28 00:49:10 +00:00
2024-12-19 12:48:57 +00:00
2024-08-05 10:10:12 +00:00
@router.post("/api/proxy")
async def proxy(request: ProxyRequest):
try:
async with httpx.AsyncClient() as client:
response = await client.get(request.url)
return {"content": response.text}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
2024-12-19 12:48:57 +00:00
2024-07-28 00:49:10 +00:00
def clone_repo():
REPO_DIR = Path(lollmsElfServer.lollms_paths.personal_path) / "apps_zoo_repo"
2024-12-19 12:48:57 +00:00
2024-07-28 00:49:10 +00:00
# Check if the directory exists and if it is empty
if REPO_DIR.exists():
if any(REPO_DIR.iterdir()): # Check if the directory is not empty
print(f"Directory {REPO_DIR} is not empty. Aborting clone.")
return
else:
2024-12-19 12:48:57 +00:00
REPO_DIR.mkdir(
parents=True, exist_ok=True
) # Create the directory if it doesn't exist
2024-07-28 00:49:10 +00:00
# Clone the repository
subprocess.run(["git", "clone", REPO_URL, str(REPO_DIR)], check=True)
print(f"Repository cloned into {REPO_DIR}")
2024-12-19 12:48:57 +00:00
2024-07-28 00:49:10 +00:00
def pull_repo():
2024-12-19 12:48:57 +00:00
REPO_DIR = lollmsElfServer.lollms_paths.personal_path / "apps_zoo_repo"
2024-07-28 00:49:10 +00:00
subprocess.run(["git", "-C", str(REPO_DIR), "pull"], check=True)
2024-12-19 12:48:57 +00:00
2024-07-28 00:49:10 +00:00
def load_apps_data():
apps = []
2024-12-19 12:48:57 +00:00
REPO_DIR = lollmsElfServer.lollms_paths.personal_path / "apps_zoo_repo"
2024-07-28 00:49:10 +00:00
for item in os.listdir(REPO_DIR):
item_path = os.path.join(REPO_DIR, item)
if os.path.isdir(item_path):
description_path = os.path.join(item_path, "description.yaml")
icon_url = f"https://github.com/ParisNeo/lollms_apps_zoo/blob/main/{item}/icon.png?raw=true"
2024-12-19 12:48:57 +00:00
2024-07-28 00:49:10 +00:00
if os.path.exists(description_path):
2024-12-19 12:48:57 +00:00
with open(description_path, "r") as file:
2024-07-28 00:49:10 +00:00
description_data = yaml.safe_load(file)
2024-12-19 12:48:57 +00:00
apps.append(
AppInfo(
uid=str(uuid.uuid4()),
name=description_data.get("name", item),
folder_name=item,
icon=icon_url,
category=description_data.get("category", "generic"),
description=description_data.get("description", ""),
author=description_data.get("author", ""),
version=description_data.get("version", ""),
creation_date=description_data.get(
"creation_date", "unknown"
),
last_update_date=description_data.get(
"last_update_date", "unknown"
),
model_name=description_data.get("model_name", ""),
disclaimer=description_data.get(
"disclaimer", "No disclaimer provided."
),
has_server=description_data.get(
"has_server", (Path(item_path) / "server.py").exists()
),
has_readme=description_data.get(
"has_readme", (Path(item_path) / "README.md").exists()
),
is_public=True,
has_update=False,
installed=True,
)
)
2024-07-28 00:49:10 +00:00
return apps
2024-08-11 23:35:27 +00:00
@router.get("/lollms_assets/{asset_type}/{file_name}")
2024-08-11 18:11:14 +00:00
async def lollms_assets(asset_type: str, file_name: str):
2024-09-15 20:23:22 +00:00
asset_type = sanitize_path(asset_type)
file_name = sanitize_path(file_name)
2024-08-11 18:11:14 +00:00
# Define the base path
base_path = Path(__file__).parent
2024-08-11 23:35:27 +00:00
# Determine the correct directory and file extension based on asset_type
2024-08-11 18:11:14 +00:00
if asset_type == "js":
directory = base_path / "libraries"
file_extension = ".js"
2024-08-11 23:35:27 +00:00
content_type = "application/javascript"
2024-08-11 18:11:14 +00:00
elif asset_type == "css":
directory = base_path / "styles"
file_extension = ".css"
2024-08-11 23:35:27 +00:00
content_type = "text/css"
2024-08-11 18:11:14 +00:00
else:
raise HTTPException(status_code=400, detail="Invalid asset type")
# Sanitize the file name to prevent path traversal
safe_file_name = sanitize_path(file_name)
# Construct the full file path
file_path = directory / f"{safe_file_name}{file_extension}"
2024-08-27 19:05:20 +00:00
file_path_with_entension = directory / f"{safe_file_name}"
2024-12-19 12:48:57 +00:00
if file_path_with_entension.is_file() and file_path_with_entension.is_relative_to(
directory
):
2024-08-27 19:05:20 +00:00
file_path = file_path_with_entension
2024-08-11 18:11:14 +00:00
# Check if the file exists and is within the allowed directory
if not file_path.is_file() or not file_path.is_relative_to(directory):
raise HTTPException(status_code=404, detail="File not found")
2024-08-11 23:35:27 +00:00
# Read and return the file content with the appropriate content type
2024-08-11 18:11:14 +00:00
try:
2024-12-19 12:48:57 +00:00
with file_path.open("r") as file:
2024-08-11 18:11:14 +00:00
content = file.read()
2024-08-11 23:35:27 +00:00
return Response(content=content, media_type=content_type)
2024-08-11 18:11:14 +00:00
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error reading file: {str(e)}")
2024-12-19 12:48:57 +00:00
2024-07-29 22:02:24 +00:00
@router.get("/template")
async def lollms_js():
return {
"start_header_id_template": lollmsElfServer.config.start_header_id_template,
"end_header_id_template": lollmsElfServer.config.end_header_id_template,
"separator_template": lollmsElfServer.config.separator_template,
"start_user_header_id_template": lollmsElfServer.config.start_user_header_id_template,
"end_user_header_id_template": lollmsElfServer.config.end_user_header_id_template,
"end_user_message_id_template": lollmsElfServer.config.end_user_message_id_template,
"start_ai_header_id_template": lollmsElfServer.config.start_ai_header_id_template,
"end_ai_header_id_template": lollmsElfServer.config.end_ai_header_id_template,
"end_ai_message_id_template": lollmsElfServer.config.end_ai_message_id_template,
2024-12-19 12:48:57 +00:00
"system_message_template": lollmsElfServer.config.system_message_template,
2024-07-29 22:02:24 +00:00
}
2024-07-28 00:49:10 +00:00
2024-12-19 12:48:57 +00:00
2024-07-27 23:19:18 +00:00
@router.get("/github/apps")
async def fetch_github_apps():
2024-07-28 00:49:10 +00:00
try:
clone_repo()
pull_repo()
2024-08-02 07:46:55 +00:00
except:
ASCIIColors.error("Couldn't interact with ")
2024-12-19 12:48:57 +00:00
lollmsElfServer.error(
"Couldn't interact with github.\nPlease verify your internet connection"
)
2024-08-02 07:46:55 +00:00
apps = load_apps_data()
return {"apps": apps}
2024-07-27 23:19:18 +00:00
2024-08-11 21:42:58 +00:00
def install_requirements(app_path: Path):
requirements_file = app_path / "requirements.txt"
if requirements_file.exists():
try:
2024-12-19 12:48:57 +00:00
subprocess.check_call(
[sys.executable, "-m", "pip", "install", "-r", str(requirements_file)]
)
2024-08-11 21:42:58 +00:00
print("Requirements installed successfully.")
except subprocess.CalledProcessError as e:
print(f"Error installing requirements: {e}")
raise
2024-12-19 12:48:57 +00:00
def run_server(app_path: Path):
2024-08-11 19:55:00 +00:00
server_script = app_path / "server.py"
if server_script.exists():
2024-08-11 21:42:58 +00:00
try:
# Install requirements if they exist
install_requirements(app_path)
# Determine the platform and open a terminal to execute the Python code.
system = platform.system()
if system == "Windows":
2024-12-19 12:48:57 +00:00
process = subprocess.Popen(
f"""start cmd /k "cd /d "{app_path}" && python "{server_script}" && pause" """,
shell=True,
)
2024-08-11 21:42:58 +00:00
elif system == "Darwin": # macOS
2024-12-19 12:48:57 +00:00
process = subprocess.Popen(
[
"open",
"-a",
"Terminal",
f'cd "{app_path}" && python "{server_script}"',
],
shell=True,
)
2024-08-11 21:42:58 +00:00
elif system == "Linux":
2024-12-19 12:48:57 +00:00
process = subprocess.Popen(
[
"x-terminal-emulator",
"-e",
f'bash -c "cd \\"{app_path}\\" && python \\"{server_script}\\"; exec bash"',
],
shell=True,
)
2024-08-11 21:42:58 +00:00
else:
raise Exception(f"Unsupported platform: {system}")
except Exception as ex:
# Stop the timer.
ASCIIColors.error(f"Error executing Python code: {ex}")
2024-08-11 19:55:00 +00:00
else:
2024-08-11 21:42:58 +00:00
ASCIIColors.error(f"Server script not found for app: {app_path.name}")
2024-08-11 19:55:00 +00:00
2024-12-19 12:48:57 +00:00
2024-08-11 19:55:00 +00:00
@router.post("/apps/start_server")
async def start_app_server(request: OpenFolderRequest):
check_access(lollmsElfServer, request.client_id)
app_name = sanitize_path(request.app_name)
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name
2024-12-19 12:48:57 +00:00
2024-08-11 19:55:00 +00:00
if not app_path.exists():
raise HTTPException(status_code=404, detail="App not found")
2024-12-19 12:48:57 +00:00
2024-08-11 19:55:00 +00:00
server_script = app_path / "server.py"
if not server_script.exists():
2024-12-19 12:48:57 +00:00
raise HTTPException(
status_code=404, detail="Server script not found for this app"
)
2024-08-11 19:55:00 +00:00
# Start the server in the background
2024-08-11 21:42:58 +00:00
run_server(app_path)
2024-12-19 12:48:57 +00:00
2024-08-11 21:42:58 +00:00
return {"status": "success", "message": f"Server for {app_path} is starting"}