2024-01-07 22:17:22 +00:00
"""
2024-07-05 14:02:55 +00:00
project : lollms_advanced
file : lollms_advanced . py
2024-01-07 22:17:22 +00:00
author : ParisNeo
description :
2024-07-05 14:02:55 +00:00
This module contains a set of FastAPI routes that provide access to advanced functionalities of lollms . These routes allow users to do advanced stuff like executing code .
2024-01-07 22:17:22 +00:00
"""
2024-12-19 12:48:57 +00:00
import io
2024-01-07 23:22:23 +00:00
import os
import platform
2024-02-14 23:35:04 +00:00
import re
2024-12-19 12:48:57 +00:00
import shutil
import string
import subprocess
from pathlib import Path
2024-02-15 00:01:55 +00:00
from typing import Optional
2024-02-14 23:35:04 +00:00
2024-12-19 12:48:57 +00:00
import tqdm
from ascii_colors import ASCIIColors
from fastapi import ( APIRouter , FastAPI , File , HTTPException , Query , Request ,
UploadFile )
2024-09-12 23:19:22 +00:00
from fastapi . responses import FileResponse , StreamingResponse
2024-12-19 12:48:57 +00:00
from lollms . client_session import Client
from lollms . databases . discussions_database import DiscussionsDB
from lollms . main_config import BaseConfig
from lollms . security import ( check_access , forbid_remote_access , sanitize_path ,
sanitize_svg )
from lollms . types import MSG_OPERATION_TYPE
from lollms . utilities import ( add_period , detect_antiprompt ,
remove_text_from_string , show_yes_no_dialog ,
trace_exception )
from pydantic import BaseModel , Field
from starlette . responses import StreamingResponse
from lollms_webui import LOLLMSWebUI
2024-09-12 23:19:22 +00:00
2024-02-14 23:35:04 +00:00
def validate_file_path ( path ) :
2024-03-28 22:58:51 +00:00
try :
sanitized_path = sanitize_path ( path , allow_absolute_path = False )
return sanitized_path is not None
except Exception as e :
print ( f " Path validation error: { str ( e ) } " )
return False
2024-01-07 22:17:22 +00:00
2024-02-05 22:50:40 +00:00
2024-09-12 23:19:22 +00:00
import os
import shutil
2024-12-19 12:48:57 +00:00
import tempfile
from fastapi import FastAPI , File , UploadFile
from fastapi . responses import JSONResponse
from utilities . execution_engines . graphviz_execution_engine import \
execute_graphviz
from utilities . execution_engines . html_execution_engine import execute_html
from utilities . execution_engines . javascript_execution_engine import \
execute_javascript
from utilities . execution_engines . latex_execution_engine import execute_latex
from utilities . execution_engines . lilypond_execution_engine import \
execute_lilypond
from utilities . execution_engines . mermaid_execution_engine import \
execute_mermaid
from utilities . execution_engines . python_execution_engine import execute_python
from utilities . execution_engines . shell_execution_engine import execute_bash
from utilities . execution_engines . svg_execution_engine import execute_svg
2024-01-07 22:17:22 +00:00
2024-01-09 22:26:41 +00:00
# ----------------------- Defining router and main class ------------------------------
2024-01-07 23:22:23 +00:00
2024-01-07 22:17:22 +00:00
router = APIRouter ( )
2024-12-19 12:48:57 +00:00
lollmsElfServer : LOLLMSWebUI = LOLLMSWebUI . get_instance ( )
2024-05-05 15:28:45 +00:00
class Identification ( BaseModel ) :
2024-12-19 12:48:57 +00:00
client_id : str
2024-02-15 00:31:16 +00:00
2024-02-15 19:31:03 +00:00
class CodeRequest ( BaseModel ) :
2024-12-19 12:48:57 +00:00
client_id : str = Field ( . . . )
2024-02-15 19:31:03 +00:00
code : str = Field ( . . . , description = " Code to be executed " )
discussion_id : int = Field ( . . . , description = " Discussion ID " )
message_id : int = Field ( . . . , description = " Message ID " )
language : str = Field ( . . . , description = " Programming language of the code " )
2024-12-19 12:48:57 +00:00
2024-01-07 22:17:22 +00:00
@router.post ( " /execute_code " )
2024-02-15 19:31:03 +00:00
async def execute_code ( request : CodeRequest ) :
2024-01-07 22:17:22 +00:00
"""
Executes Python code and returns the output .
: param request : The HTTP request object .
: return : A JSON response with the status of the operation .
"""
2024-04-07 01:51:37 +00:00
client = check_access ( lollmsElfServer , request . client_id )
2024-02-14 23:35:04 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Code execution is blocked when in headless mode for obvious security reasons! " ,
}
forbid_remote_access (
lollmsElfServer ,
" Code execution is blocked when the server is exposed outside for very obvious reasons! " ,
)
2024-02-15 00:31:16 +00:00
if not lollmsElfServer . config . turn_on_code_execution :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Code execution is blocked by the configuration! " ,
}
2024-02-15 00:31:16 +00:00
if lollmsElfServer . config . turn_on_code_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the execution of the code? "
) :
return { " status " : False , " error " : " User refused the execution! " }
2024-02-15 00:31:16 +00:00
2024-01-07 22:17:22 +00:00
try :
2024-02-15 19:31:03 +00:00
code = request . code
discussion_id = request . discussion_id
message_id = request . message_id
language = request . language
2024-01-07 22:17:22 +00:00
2024-12-19 12:48:57 +00:00
if language == " function " :
2024-05-13 23:57:07 +00:00
ASCIIColors . info ( " Executing function call: " )
ASCIIColors . yellow ( code )
2024-06-08 23:42:06 +00:00
try :
out = lollmsElfServer . personality . execute_function ( code )
2024-12-19 12:48:57 +00:00
return (
out
if type ( out ) == str
else (
out [ 0 ] if type ( out ) is tuple and type ( out [ 0 ] ) == str else " Done "
)
)
2024-06-08 23:42:06 +00:00
except Exception as ex :
trace_exception ( ex )
return ex
2024-12-19 12:48:57 +00:00
if language == " python " :
2024-02-05 22:50:40 +00:00
ASCIIColors . info ( " Executing python code: " )
ASCIIColors . yellow ( code )
2024-02-28 00:06:59 +00:00
return execute_python ( code , client , message_id )
2024-12-19 12:48:57 +00:00
if language == " svg " :
2024-04-21 15:14:00 +00:00
ASCIIColors . info ( " Executing svg code: " )
ASCIIColors . yellow ( code )
2024-05-19 15:38:45 +00:00
return execute_svg ( sanitize_svg ( code ) , client , message_id )
2024-12-19 12:48:57 +00:00
if language == " lilypond " :
2024-10-31 20:57:29 +00:00
ASCIIColors . info ( " Executing svg code: " )
ASCIIColors . yellow ( code )
return execute_lilypond ( code , client , message_id )
2024-12-19 12:48:57 +00:00
if language == " javascript " :
2024-02-05 22:50:40 +00:00
ASCIIColors . info ( " Executing javascript code: " )
ASCIIColors . yellow ( code )
2024-04-21 00:50:43 +00:00
return execute_javascript ( code , client , message_id )
2024-12-19 12:48:57 +00:00
if language in [ " html " , " html5 " , " svg " ] :
2024-02-05 23:57:00 +00:00
ASCIIColors . info ( " Executing javascript code: " )
ASCIIColors . yellow ( code )
2024-04-21 00:50:43 +00:00
return execute_html ( code , client , message_id )
2024-02-15 19:31:03 +00:00
2024-12-19 12:48:57 +00:00
elif language == " latex " :
2024-02-05 22:50:40 +00:00
ASCIIColors . info ( " Executing latex code: " )
ASCIIColors . yellow ( code )
2024-02-28 21:56:34 +00:00
return execute_latex ( code , client , message_id )
2024-12-19 12:48:57 +00:00
elif language in [ " bash " , " shell " , " cmd " , " powershell " ] :
2024-02-05 22:50:40 +00:00
ASCIIColors . info ( " Executing shell code: " )
ASCIIColors . yellow ( code )
2024-04-28 09:17:22 +00:00
return execute_bash ( code , client , message_id )
2024-02-05 22:50:40 +00:00
elif language in [ " mermaid " ] :
ASCIIColors . info ( " Executing mermaid code: " )
ASCIIColors . yellow ( code )
2024-04-21 00:50:43 +00:00
return execute_mermaid ( code , client , message_id )
2024-12-19 12:48:57 +00:00
elif language in [ " graphviz " , " dot " ] :
2024-02-05 22:50:40 +00:00
ASCIIColors . info ( " Executing graphviz code: " )
ASCIIColors . yellow ( code )
2024-04-21 00:50:43 +00:00
return execute_graphviz ( code , client , message_id )
2024-02-14 23:35:04 +00:00
return { " status " : False , " error " : " Unsupported language " , " execution_time " : 0 }
2024-01-07 23:22:23 +00:00
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : str ( ex ) }
2024-04-21 00:50:43 +00:00
@router.post ( " /execute_code_in_new_tab " )
async def execute_code_in_new_tab ( request : CodeRequest ) :
"""
Executes Python code and returns the output .
: param request : The HTTP request object .
: return : A JSON response with the status of the operation .
"""
client = check_access ( lollmsElfServer , request . client_id )
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Code execution is blocked when in headless mode for obvious security reasons! " ,
}
forbid_remote_access (
lollmsElfServer ,
" Code execution is blocked when the server is exposed outside for very obvious reasons! " ,
)
2024-04-21 00:50:43 +00:00
if not lollmsElfServer . config . turn_on_code_execution :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Code execution is blocked by the configuration! " ,
}
2024-04-21 00:50:43 +00:00
if lollmsElfServer . config . turn_on_code_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the execution of the code? "
) :
return { " status " : False , " error " : " User refused the execution! " }
2024-04-21 00:50:43 +00:00
try :
code = request . code
discussion_id = request . discussion_id
message_id = request . message_id
language = request . language
2024-12-19 12:48:57 +00:00
if language == " python " :
2024-04-21 00:50:43 +00:00
ASCIIColors . info ( " Executing python code: " )
ASCIIColors . yellow ( code )
return execute_python ( code , client , message_id , True )
2024-12-19 12:48:57 +00:00
if language == " javascript " :
2024-04-21 00:50:43 +00:00
ASCIIColors . info ( " Executing javascript code: " )
ASCIIColors . yellow ( code )
return execute_javascript ( code , client , message_id , True )
2024-12-19 12:48:57 +00:00
if language in [ " html " , " html5 " , " svg " ] :
2024-04-21 00:50:43 +00:00
ASCIIColors . info ( " Executing javascript code: " )
ASCIIColors . yellow ( code )
return execute_html ( code , client , message_id , True )
2024-01-07 23:22:23 +00:00
2024-12-19 12:48:57 +00:00
elif language == " latex " :
2024-04-21 00:50:43 +00:00
ASCIIColors . info ( " Executing latex code: " )
ASCIIColors . yellow ( code )
return execute_latex ( code , client , message_id , True )
2024-12-19 12:48:57 +00:00
elif language in [ " bash " , " shell " , " cmd " , " powershell " ] :
2024-04-21 00:50:43 +00:00
ASCIIColors . info ( " Executing shell code: " )
ASCIIColors . yellow ( code )
return execute_bash ( code , client )
elif language in [ " mermaid " ] :
ASCIIColors . info ( " Executing mermaid code: " )
ASCIIColors . yellow ( code )
return execute_mermaid ( code , client , message_id , True )
2024-12-19 12:48:57 +00:00
elif language in [ " graphviz " , " dot " ] :
2024-04-21 00:50:43 +00:00
ASCIIColors . info ( " Executing graphviz code: " )
ASCIIColors . yellow ( code )
return execute_graphviz ( code , client , message_id , True )
return { " status " : False , " error " : " Unsupported language " , " execution_time " : 0 }
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : str ( ex ) }
2024-01-07 23:22:23 +00:00
2024-02-15 00:01:55 +00:00
class FilePath ( BaseModel ) :
2024-10-13 14:38:13 +00:00
client_id : str
2024-02-15 00:01:55 +00:00
path : Optional [ str ] = Field ( None , max_length = 500 )
2024-12-19 12:48:57 +00:00
2024-01-08 00:08:47 +00:00
@router.post ( " /open_file " )
2024-02-15 00:01:55 +00:00
async def open_file ( file_path : FilePath ) :
2024-01-07 23:22:23 +00:00
"""
Opens code in vs code .
2024-02-15 00:01:55 +00:00
: param file_path : The file path object .
2024-01-07 23:22:23 +00:00
: return : A JSON response with the status of the operation .
"""
2024-10-13 14:38:13 +00:00
check_access ( lollmsElfServer , client_id = file_path . client_id )
2024-02-15 20:47:24 +00:00
2024-12-19 12:48:57 +00:00
if lollmsElfServer . config . headless_server_mode :
return {
" status " : False ,
" error " : " Open file is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Open file is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-01-07 23:22:23 +00:00
2024-02-17 01:08:14 +00:00
if lollmsElfServer . config . turn_on_open_file_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the opening of a file? "
) :
return { " status " : False , " error " : " User refused the opeining file! " }
2024-02-17 01:08:14 +00:00
2024-03-24 14:39:42 +00:00
forbid_remote_access ( lollmsElfServer )
2024-04-29 16:52:35 +00:00
# Validate the 'path' parameter
path = sanitize_path ( file_path . path , allow_absolute_path = True )
2024-04-07 01:51:37 +00:00
2024-12-19 12:48:57 +00:00
try :
2024-04-07 01:51:37 +00:00
if Path ( path ) . exists ( ) :
# Use subprocess.Popen to safely open the file
ASCIIColors . yellow ( f " Starting file : { path } " )
2024-12-19 12:48:57 +00:00
if os . name == " nt " : # if the operating system is Windows
subprocess . Popen ( f " start { path } " , shell = True )
else : # for other operating systems
2024-04-07 01:51:37 +00:00
subprocess . Popen ( [ path ] , shell = True )
2024-12-19 12:48:57 +00:00
2024-02-14 23:35:04 +00:00
return { " status " : True , " execution_time " : 0 }
2024-12-19 12:48:57 +00:00
2024-01-07 23:22:23 +00:00
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : str ( ex ) }
2024-03-24 17:09:18 +00:00
@router.post ( " /open_folder " )
async def open_folder ( file_path : FilePath ) :
"""
Opens a folder
: param file_path : The file path object .
: return : A JSON response with the status of the operation .
"""
2024-12-19 12:48:57 +00:00
forbid_remote_access (
lollmsElfServer ,
" Open file is blocked when the server is exposed outside for very obvious reasons! " ,
)
2024-03-29 21:11:21 +00:00
2024-03-24 17:09:18 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Open file is blocked when in headless mode for obvious security reasons! " ,
}
2024-03-24 17:09:18 +00:00
if lollmsElfServer . config . turn_on_open_file_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the opening of a folder? "
) :
return { " status " : False , " error " : " User refused the opening folder! " }
2024-03-24 17:09:18 +00:00
forbid_remote_access ( lollmsElfServer )
try :
# Validate the 'path' parameter
2024-04-07 01:51:37 +00:00
path = sanitize_path ( file_path . path , allow_absolute_path = True )
ASCIIColors . yellow ( f " Opening folder : { path } " )
if Path ( path ) . exists ( ) :
# Use subprocess.Popen to safely open the file
2024-12-19 12:48:57 +00:00
if platform . system ( ) == " Windows " :
path = path . replace ( " / " , " \\ " )
2024-07-22 19:18:19 +00:00
subprocess . Popen ( f ' explorer " { path } " ' )
2024-12-19 12:48:57 +00:00
elif platform . system ( ) == " Linux " :
subprocess . run ( [ " xdg-open " , str ( path ) ] , check = True , shell = True )
elif platform . system ( ) == " Darwin " :
subprocess . run ( [ " open " , str ( path ) ] , check = True , shell = True )
2024-03-24 17:09:18 +00:00
return { " status " : True , " execution_time " : 0 }
2024-12-19 12:48:57 +00:00
2024-03-24 17:09:18 +00:00
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : str ( ex ) }
2024-03-24 17:09:18 +00:00
2024-02-27 16:06:22 +00:00
class OpenCodeFolderInVsCodeRequestModel ( BaseModel ) :
client_id : str = Field ( . . . )
discussion_id : Optional [ int ] = Field ( None , gt = 0 )
message_id : Optional [ int ] = Field ( None , gt = 0 )
code : Optional [ str ]
2024-12-19 12:48:57 +00:00
2024-05-02 22:58:18 +00:00
@router.post ( " /open_discussion_folder_in_vs_code " )
2024-12-19 12:48:57 +00:00
async def open_discussion_folder_in_vs_code (
request : OpenCodeFolderInVsCodeRequestModel ,
) :
2024-02-27 16:06:22 +00:00
2024-04-07 01:51:37 +00:00
client = check_access ( lollmsElfServer , request . client_id )
2024-02-27 16:06:22 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Open code folder in vscode is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Open code folder in vscode is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-02-27 16:06:22 +00:00
if lollmsElfServer . config . turn_on_open_file_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the opening of folder in vscode? "
) :
return { " status " : False , " error " : " User refused the execution! " }
2024-02-27 16:06:22 +00:00
try :
2024-12-19 12:48:57 +00:00
if request . discussion_id :
2024-02-27 16:06:22 +00:00
ASCIIColors . info ( " Opening folder: " )
root_folder = client . discussion . discussion_folder
2024-12-19 12:48:57 +00:00
root_folder . mkdir ( parents = True , exist_ok = True )
tmp_file = root_folder / f " ai_code_ { request . message_id } .py "
with open ( tmp_file , " w " , encoding = " utf-8 " , errors = " ignore " ) as f :
2024-02-27 16:06:22 +00:00
f . write ( request . code )
2024-12-19 12:48:57 +00:00
if os . path . isdir ( root_folder ) :
path = ' " ' + str ( root_folder ) + ' " ' . replace ( " \\ " , " / " )
subprocess . run ( [ " code " , " -n " , path ] , shell = True )
2024-02-27 16:06:22 +00:00
return { " status " : True , " execution_time " : 0 }
except Exception as ex :
trace_exception ( ex )
2024-02-28 01:06:50 +00:00
lollmsElfServer . error ( str ( ex ) )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : " An error occurred during processing. " }
2024-02-15 00:01:55 +00:00
class VSCodeData ( BaseModel ) :
2024-02-27 16:06:22 +00:00
client_id : str = Field ( . . . )
2024-02-15 00:01:55 +00:00
discussion_id : Optional [ int ] = Field ( None , ge = 0 )
message_id : Optional [ int ] = Field ( None , ge = 0 )
code : str = Field ( . . . )
2024-01-07 23:22:23 +00:00
2024-12-19 12:48:57 +00:00
2024-01-08 00:08:47 +00:00
@router.post ( " /open_code_in_vs_code " )
2024-02-15 00:01:55 +00:00
async def open_code_in_vs_code ( vs_code_data : VSCodeData ) :
2024-01-07 23:22:23 +00:00
"""
Opens code in vs code .
2024-02-15 00:01:55 +00:00
: param vs_code_data : The data object .
2024-01-07 23:22:23 +00:00
: return : A JSON response with the status of the operation .
"""
2024-04-07 01:51:37 +00:00
client = check_access ( lollmsElfServer , vs_code_data . client_id )
2024-02-15 20:47:24 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Open code in vs code is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Open code in vs code is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-01-07 23:22:23 +00:00
2024-02-17 01:08:14 +00:00
if lollmsElfServer . config . turn_on_open_file_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the opening of a code in vscode? "
) :
return { " status " : False , " error " : " User refused the opeining file! " }
2024-02-17 01:08:14 +00:00
2024-01-07 23:22:23 +00:00
try :
2024-02-15 00:01:55 +00:00
discussion_id = vs_code_data . discussion_id
message_id = vs_code_data . message_id
code = vs_code_data . code
2024-01-07 23:22:23 +00:00
ASCIIColors . info ( " Opening folder: " )
# Create a temporary file.
2024-02-27 16:06:22 +00:00
root_folder = client . discussion . discussion_folder
2024-12-19 12:48:57 +00:00
root_folder . mkdir ( parents = True , exist_ok = True )
tmp_file = root_folder / f " ai_code_ { message_id } .py "
with open ( tmp_file , " w " , encoding = " utf-8 " , errors = " ignore " ) as f :
2024-01-07 23:22:23 +00:00
f . write ( code )
2024-12-19 12:48:57 +00:00
2024-02-15 00:01:55 +00:00
# Use subprocess.Popen to safely open the file
2024-07-28 23:39:19 +00:00
os . system ( f ' code -n " { tmp_file } " ' )
2024-12-19 12:48:57 +00:00
2024-02-14 23:35:04 +00:00
return { " status " : True , " execution_time " : 0 }
2024-01-07 23:22:23 +00:00
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : str ( ex ) }
2024-05-08 22:08:44 +00:00
class DiscussionFolderRequest ( BaseModel ) :
2024-02-27 16:06:22 +00:00
client_id : str = Field ( . . . )
2024-05-02 22:58:18 +00:00
discussion_id : int = Field ( . . . )
2024-01-07 23:22:23 +00:00
2024-12-19 12:48:57 +00:00
2024-05-02 22:58:18 +00:00
@router.post ( " /open_discussion_folder " )
2024-05-08 22:08:44 +00:00
async def open_discussion_folder ( request : DiscussionFolderRequest ) :
2024-01-07 23:22:23 +00:00
"""
Opens code folder .
: param request : The HTTP request object .
: return : A JSON response with the status of the operation .
"""
2024-04-07 01:51:37 +00:00
client = check_access ( lollmsElfServer , request . client_id )
2024-02-15 20:47:24 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Open code folder is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Open code folder is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-02-15 20:47:24 +00:00
2024-02-17 01:08:14 +00:00
if lollmsElfServer . config . turn_on_open_file_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the opening of a folder? "
) :
return { " status " : False , " error " : " User refused the opeining folder! " }
2024-02-17 01:08:14 +00:00
2024-01-07 23:22:23 +00:00
try :
2024-02-28 00:06:59 +00:00
ASCIIColors . info ( " Opening folder: " )
# Create a temporary file.
root_folder = client . discussion . discussion_folder
root_folder . mkdir ( parents = True , exist_ok = True )
2024-12-19 12:48:57 +00:00
if platform . system ( ) == " Windows " :
2024-03-01 09:57:47 +00:00
subprocess . Popen ( f ' explorer " { root_folder } " ' )
2024-12-19 12:48:57 +00:00
elif platform . system ( ) == " Linux " :
subprocess . run ( [ " xdg-open " , str ( root_folder ) ] , check = True )
elif platform . system ( ) == " Darwin " :
subprocess . run ( [ " open " , str ( root_folder ) ] , check = True )
2024-02-28 00:06:59 +00:00
return { " status " : True , " execution_time " : 0 }
2024-01-07 23:22:23 +00:00
2024-01-07 22:17:22 +00:00
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " An error occurred while processing the request " ,
}
2024-02-03 18:04:43 +00:00
2024-05-08 22:08:44 +00:00
class PersonalityFolderRequest ( BaseModel ) :
client_id : str = Field ( . . . )
2024-05-24 22:36:51 +00:00
personality_folder : str = Field ( . . . )
2024-05-08 22:08:44 +00:00
2024-12-19 12:48:57 +00:00
2024-05-08 22:08:44 +00:00
@router.post ( " /open_personality_folder " )
async def open_personality_folder ( request : PersonalityFolderRequest ) :
"""
Opens code folder .
: param request : The HTTP request object .
: return : A JSON response with the status of the operation .
"""
client = check_access ( lollmsElfServer , request . client_id )
personality_folder = sanitize_path ( request . personality_folder )
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Open code folder is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Open code folder is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-05-08 22:08:44 +00:00
if lollmsElfServer . config . turn_on_open_file_validation :
2024-12-19 12:48:57 +00:00
if not show_yes_no_dialog (
" Validation " , " Do you validate the opening of a folder? "
) :
return { " status " : False , " error " : " User refused the opeining folder! " }
2024-05-08 22:08:44 +00:00
try :
ASCIIColors . info ( " Opening folder: " )
# Create a temporary file.
2024-12-19 12:48:57 +00:00
root_folder = (
lollmsElfServer . lollms_paths . personalities_zoo_path / personality_folder
)
2024-05-08 22:08:44 +00:00
root_folder . mkdir ( parents = True , exist_ok = True )
2024-12-19 12:48:57 +00:00
if platform . system ( ) == " Windows " :
2024-05-08 22:08:44 +00:00
subprocess . Popen ( f ' explorer " { root_folder } " ' )
2024-12-19 12:48:57 +00:00
elif platform . system ( ) == " Linux " :
subprocess . run ( [ " xdg-open " , str ( root_folder ) ] , check = True )
elif platform . system ( ) == " Darwin " :
subprocess . run ( [ " open " , str ( root_folder ) ] , check = True )
2024-05-08 22:08:44 +00:00
return { " status " : True , " execution_time " : 0 }
except Exception as ex :
trace_exception ( ex )
lollmsElfServer . error ( ex )
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " An error occurred while processing the request " ,
}
2024-05-08 22:08:44 +00:00
2024-05-19 12:35:05 +00:00
@router.get ( " /is_rt_on " )
def is_rt_on ( ) :
return { " status " : lollmsElfServer . rt_com is not None }
2024-05-08 22:08:44 +00:00
2024-12-19 12:48:57 +00:00
2024-05-05 15:28:45 +00:00
@router.post ( " /start_recording " )
2024-12-19 12:48:57 +00:00
def start_recording ( data : Identification ) :
2024-05-05 15:28:45 +00:00
client = check_access ( lollmsElfServer , data . client_id )
2024-02-15 20:47:24 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Start recording is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Start recording is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-02-15 20:47:24 +00:00
2024-05-24 21:51:17 +00:00
lollmsElfServer . info ( " Starting audio capture " )
if not lollmsElfServer . tts or not lollmsElfServer . stt :
2024-12-19 12:48:57 +00:00
lollmsElfServer . InfoMessage (
" TTS or STT are not configured. \n Please go to settings and configure them first "
)
return { " status " : False , " error " : " TTS or STT not configured " }
2024-05-24 21:51:17 +00:00
if not lollmsElfServer . tts . ready or not lollmsElfServer . stt . ready :
lollmsElfServer . InfoMessage ( " TTS is not ready yet. \n Please wait " )
2024-12-19 12:48:57 +00:00
return { " status " : False , " error " : " TTS not ready " }
2024-05-24 21:51:17 +00:00
2024-02-03 18:04:43 +00:00
lollmsElfServer . info ( " Starting audio capture " )
try :
2024-05-26 22:36:45 +00:00
from lollms . media import AudioNinja
2024-12-19 12:48:57 +00:00
lollmsElfServer . rec_output_folder = (
lollmsElfServer . lollms_paths . personal_outputs_path / " audio_rec "
)
2024-02-03 18:04:43 +00:00
lollmsElfServer . rec_output_folder . mkdir ( exist_ok = True , parents = True )
lollmsElfServer . summoned = False
2024-05-26 22:36:45 +00:00
lollmsElfServer . audioNinja = AudioNinja (
2024-12-19 12:48:57 +00:00
lollmsElfServer , logs_folder = lollmsElfServer . rec_output_folder
)
2024-05-26 22:36:45 +00:00
lollmsElfServer . audioNinja . start_recording ( )
2024-02-03 18:04:43 +00:00
except :
2024-12-19 12:48:57 +00:00
lollmsElfServer . InfoMessage (
" Couldn ' t load media library. \n You will not be able to perform any of the media linked operations. please verify the logs and install any required installations "
)
2024-02-03 18:04:43 +00:00
2024-05-05 15:28:45 +00:00
@router.post ( " /stop_recording " )
2024-12-19 12:48:57 +00:00
def stop_recording ( data : Identification ) :
2024-05-05 15:28:45 +00:00
client = check_access ( lollmsElfServer , data . client_id )
2024-02-15 20:47:24 +00:00
if lollmsElfServer . config . headless_server_mode :
2024-12-19 12:48:57 +00:00
return {
" status " : False ,
" error " : " Stop recording is blocked when in headless mode for obvious security reasons! " ,
}
if (
lollmsElfServer . config . host != " localhost "
and lollmsElfServer . config . host != " 127.0.0.1 "
) :
return {
" status " : False ,
" error " : " Stop recording is blocked when the server is exposed outside for very obvious reasons! " ,
}
2024-02-15 20:47:24 +00:00
2024-02-03 18:04:43 +00:00
lollmsElfServer . info ( " Stopping audio capture " )
2024-05-26 22:36:45 +00:00
fn = lollmsElfServer . audioNinja . stop_recording ( )
lollmsElfServer . audioNinja = None
2024-09-12 20:23:24 +00:00
if lollmsElfServer . stt and fn :
2024-05-26 22:36:45 +00:00
text = lollmsElfServer . stt . transcribe ( fn )
return text
2024-09-12 20:23:24 +00:00
else :
return " "
2024-02-05 22:50:40 +00:00
2024-09-12 23:19:22 +00:00
@router.post ( " /transcribe " )
async def transcribe_audio ( file : UploadFile = File ( . . . ) ) :
2024-12-19 12:48:57 +00:00
with tempfile . NamedTemporaryFile ( delete = False , suffix = " .wav " ) as temp_file :
2024-09-12 23:19:22 +00:00
# Copy the contents of the uploaded file to the temporary file
shutil . copyfileobj ( file . file , temp_file )
temp_file_path = temp_file . name
try :
2024-12-19 12:48:57 +00:00
if hasattr ( lollmsElfServer , " stt " ) and lollmsElfServer . stt :
2024-09-12 23:19:22 +00:00
text = lollmsElfServer . stt . transcribe ( temp_file_path )
return JSONResponse ( content = { " transcription " : text } )
else :
2024-12-19 12:48:57 +00:00
return JSONResponse (
content = { " error " : " STT service not available " } , status_code = 503
)
2024-09-12 23:19:22 +00:00
finally :
# Clean up the temporary file
os . unlink ( temp_file_path )
class TTSRequest ( BaseModel ) :
text : str
speaker : str = None
language : str = " en "
2024-12-19 12:48:57 +00:00
2024-09-12 23:19:22 +00:00
@router.post ( " /tts/file " )
async def text_to_speech_file ( request : TTSRequest ) :
try :
file_path = lollmsElfServer . tts . tts_file (
text = request . text ,
2024-12-19 12:48:57 +00:00
file_name_or_path = lollmsElfServer . lollms_paths . personal_outputs_path
/ " output.wav " ,
2024-09-12 23:19:22 +00:00
speaker = request . speaker ,
2024-12-19 12:48:57 +00:00
language = request . language ,
2024-09-12 23:19:22 +00:00
)
return FileResponse ( file_path , media_type = " audio/wav " , filename = " speech.wav " )
except Exception as e :
2024-10-06 20:59:17 +00:00
trace_exception ( e )
2024-09-12 23:19:22 +00:00
raise HTTPException ( status_code = 500 , detail = str ( e ) )
2024-12-19 12:48:57 +00:00
2024-09-12 23:19:22 +00:00
@router.post ( " /tts/stream " )
async def text_to_speech_stream ( request : TTSRequest ) :
try :
audio_data = lollmsElfServer . tts . tts_audio (
2024-12-19 12:48:57 +00:00
text = request . text , speaker = request . speaker , language = request . language
2024-09-12 23:19:22 +00:00
)
return StreamingResponse ( io . BytesIO ( audio_data ) , media_type = " audio/wav " )
except Exception as e :
raise HTTPException ( status_code = 500 , detail = str ( e ) )
2024-12-19 12:48:57 +00:00
2024-09-12 23:19:22 +00:00
@router.get ( " /tts/voices " )
async def get_available_voices ( ) :
try :
voices = lollmsElfServer . tts . get_voices ( )
return JSONResponse ( content = { " voices " : voices } )
except Exception as e :
2024-12-19 12:48:57 +00:00
return JSONResponse ( content = { " error " : str ( e ) } , status_code = 500 )